- patch from Denis Vlasenko to add and use bb_xchdir()
diff --git a/archival/dpkg_deb.c b/archival/dpkg_deb.c
index fa89e44..fc8b922 100644
--- a/archival/dpkg_deb.c
+++ b/archival/dpkg_deb.c
@@ -1,18 +1,8 @@
+/* vi: set sw=4 ts=4: */
 /*
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
+ * dpkg-deb packs, unpacks and provides information about Debian archives.
  *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU Library General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
  */
 #include <fcntl.h>
 #include <stdlib.h>
@@ -100,7 +90,7 @@
 	}
 	if (extract_dir) {
 		mkdir(extract_dir, 0777);
-		chdir(extract_dir);
+		chdir(extract_dir); /* error check? */
 	}
 	unpack_ar_archive(ar_archive);
 
diff --git a/archival/tar.c b/archival/tar.c
index 9d0a7c5..dcc2f16 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -19,9 +19,8 @@
  *
  * Based in part on the tar implementation from busybox-0.28
  *  Copyright (C) 1995 Bruce Perens
- *  This is free software under the GNU General Public License.
  *
- * Licensed under GPL v2 (or later), see file LICENSE in this tarball.
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
  */
 
 #include <fcntl.h>
@@ -834,8 +833,8 @@
 		}
 	}
 
-	if ((base_dir) && (chdir(base_dir)))
-		bb_perror_msg_and_die("Couldnt chdir to %s", base_dir);
+	if (base_dir)
+		bb_xchdir(base_dir);
 
 	/* create an archive */
 	if (ENABLE_FEATURE_TAR_CREATE && (opt & CTX_CREATE)) {
diff --git a/archival/unzip.c b/archival/unzip.c
index bb7197d..b9dff19 100644
--- a/archival/unzip.c
+++ b/archival/unzip.c
@@ -236,9 +236,8 @@
 	}
 
 	/* Change dir if necessary */
-	if (base_dir && chdir(base_dir)) {
-		bb_perror_msg_and_die("Cannot chdir");
-	}
+	if (base_dir)
+		bb_xchdir(base_dir);
 
 	if (verbosity != v_silent)
 		printf("Archive:  %s\n", src_fn);
diff --git a/coreutils/chroot.c b/coreutils/chroot.c
index 6225702..8ad680c 100644
--- a/coreutils/chroot.c
+++ b/coreutils/chroot.c
@@ -4,20 +4,7 @@
  *
  * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
  */
 
 /* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
@@ -35,9 +22,10 @@
 	}
 
 	++argv;
-	if (chroot(*argv) || (chdir("/"))) {
+	if (chroot(*argv)) {
 		bb_perror_msg_and_die("cannot change root directory to %s", *argv);
 	}
+	bb_xchdir("/");
 
 	++argv;
 	if (argc == 2) {
diff --git a/include/libbb.h b/include/libbb.h
index d70c71c..e1ac912 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -149,6 +149,7 @@
 extern void bb_xdaemon(int nochdir, int noclose);
 extern void bb_xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
 extern void bb_xlisten(int s, int backlog);
+extern void bb_xchdir(const char *path);
 
 #define BB_GETOPT_ERROR 0x80000000UL
 extern const char *bb_opt_complementally;
diff --git a/libbb/Makefile.in b/libbb/Makefile.in
index f05bf80..eac14c6 100644
--- a/libbb/Makefile.in
+++ b/libbb/Makefile.in
@@ -30,7 +30,7 @@
 	trim.c u_signal_names.c vdprintf.c verror_msg.c \
 	vherror_msg.c vperror_msg.c wfopen.c xconnect.c xgetcwd.c xstat.c \
 	xgethostbyname.c xgethostbyname2.c xreadlink.c xregcomp.c xgetlarg.c \
-	bb_xsocket.c bb_xdaemon.c bb_xbind.c bb_xlisten.c \
+	bb_xsocket.c bb_xdaemon.c bb_xbind.c bb_xlisten.c bb_xchdir.c \
 	get_terminal_width_height.c fclose_nonstdin.c fflush_stdout_and_exit.c \
 	getopt_ulflags.c default_error_retval.c wfopen_input.c speed_table.c \
 	perror_nomsg_and_die.c perror_nomsg.c skip_whitespace.c bb_askpass.c \
diff --git a/libbb/bb_xchdir.c b/libbb/bb_xchdir.c
new file mode 100644
index 0000000..65b0153
--- /dev/null
+++ b/libbb/bb_xchdir.c
@@ -0,0 +1,17 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * bb_xchdir.c - a chdir() which dies on failure with error message
+ *
+ * Copyright (C) 2006 Denis Vlasenko
+ *
+ * Licensed under LGPL, see file docs/lesser.txt in this tarball for details.
+ */
+#include <unistd.h>
+#include "libbb.h"
+
+void bb_xchdir(const char *path)
+{
+	if (chdir(path))
+		bb_perror_msg_and_die("chdir(%s)", path);
+}
+
diff --git a/miscutils/crond.c b/miscutils/crond.c
index 06b8769..4d479bc 100644
--- a/miscutils/crond.c
+++ b/miscutils/crond.c
@@ -197,9 +197,7 @@
 	 * change directory
 	 */
 
-	if (chdir(CDir) != 0) {
-		bb_perror_msg_and_die("%s", CDir);
-	}
+	bb_xchdir(CDir);
 	signal(SIGHUP, SIG_IGN);	/* hmm.. but, if kill -HUP original
 								 * version - his died. ;(
 								 */
diff --git a/miscutils/crontab.c b/miscutils/crontab.c
index df94c85..703d01e 100644
--- a/miscutils/crontab.c
+++ b/miscutils/crontab.c
@@ -1,3 +1,4 @@
+/* vi: set sw=4 ts=4: */
 /*
  * CRONTAB
  *
@@ -148,8 +149,7 @@
      * Change directory to our crontab directory
      */
 
-    if (chdir(CDir) < 0)
-	bb_perror_msg_and_die("cannot change dir to %s", CDir);
+    bb_xchdir(CDir);
 
     /*
      * Handle options as appropriate
@@ -358,10 +358,7 @@
     if (dochdir) {
 	if (chdir(pas->pw_dir) < 0) {
 	    bb_perror_msg("chdir failed: %s %s", user, pas->pw_dir);
-	    if (chdir(TMPDIR) < 0) {
-		bb_perror_msg_and_die("chdir failed: %s %s", user, TMPDIR);
-		return(-1);
-	    }
+	    bb_xchdir(TMPDIR);
 	}
     }
     return(pas->pw_uid);
diff --git a/miscutils/makedevs.c b/miscutils/makedevs.c
index 999b993..24d07eb 100644
--- a/miscutils/makedevs.c
+++ b/miscutils/makedevs.c
@@ -1,4 +1,11 @@
 /* vi: set sw=4 ts=4: */
+/*
+ * public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com>
+ *
+ * makedevs
+ * Make ranges of device files quickly.
+ * known bugs: can't deal with alpha ranges
+ */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -12,13 +19,6 @@
 #include "busybox.h"
 
 #ifdef CONFIG_FEATURE_MAKEDEVS_LEAF
-/*
- * public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com>
- *
- * makedevs
- * Make ranges of device files quickly.
- * known bugs: can't deal with alpha ranges
- */
 int makedevs_main(int argc, char **argv)
 {
 	mode_t mode;
@@ -94,9 +94,7 @@
 		bb_error_msg_and_die("root directory not specified");
 	}
 
-	if (chdir(rootdir) != 0) {
-		bb_perror_msg_and_die("could not chdir to %s", rootdir);
-	}
+	bb_xchdir(rootdir);
 
 	umask(0);
 
diff --git a/networking/httpd.c b/networking/httpd.c
index 0f61741..df280cc 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -2077,9 +2077,7 @@
 #endif
 #endif
 
-  if(chdir(home_httpd)) {
-    bb_perror_msg_and_die("can`t chdir to %s", home_httpd);
-  }
+  bb_xchdir(home_httpd);
 #ifndef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY
   server = openServer();
 # ifdef CONFIG_FEATURE_HTTPD_SETUID
diff --git a/procps/top.c b/procps/top.c
index afd419b..d140924 100644
--- a/procps/top.c
+++ b/procps/top.c
@@ -1,3 +1,4 @@
+/* vi: set sw=4 ts=4: */
 /*
  * A tiny 'top' utility.
  *
@@ -468,9 +469,7 @@
 	col = 35;
 #endif
 	/* change to /proc */
-	if (chdir("/proc") < 0) {
-		bb_perror_msg_and_die("chdir('/proc')");
-	}
+	bb_xchdir("/proc");
 #ifdef CONFIG_FEATURE_USE_TERMIOS
 	tcgetattr(0, (void *) &initial_settings);
 	memcpy(&new_settings, &initial_settings, sizeof(struct termios));