From 4954d34c147a80932b3befe5ef5d922ee534f6ff Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 27 Apr 2000 12:23:59 +0000 Subject: (pop_dir): Remove through_symlink arg; use null cwd for that purpose instead. (count_entry): Also save the directory if we're saving more than one level. Fix file descriptor and memory leak when chdir fails. --- src/du.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/du.c b/src/du.c index dee148219..5729e9424 100644 --- a/src/du.c +++ b/src/du.c @@ -455,14 +455,14 @@ hash_insert (ino_t ino, dev_t dev) } /* Restore the previous working directory or exit. - If THROUGH_SYMLINK is non-zero, simply call `chdir ("..")'. Otherwise, + If CWD is null, simply call `chdir ("..")'. Otherwise, use CWD and free it. CURR_DIR_NAME is the name of the current directory and is used solely in failure diagnostics. */ static void -pop_dir (int through_symlink, struct saved_cwd *cwd, const char *curr_dir_name) +pop_dir (struct saved_cwd *cwd, const char *curr_dir_name) { - if (through_symlink) + if (cwd) { if (restore_cwd (cwd, "..", curr_dir_name)) exit (1); @@ -513,8 +513,8 @@ count_entry (const char *ent, int top, dev_t last_dev, int depth) dev_t dir_dev; char *name_space; char *namep; - struct saved_cwd cwd; - int through_symlink; + struct saved_cwd *cwd; + struct saved_cwd cwd_buf; struct stat e_buf; dir_dev = stat_buf.st_dev; @@ -525,18 +525,27 @@ count_entry (const char *ent, int top, dev_t last_dev, int depth) #ifndef S_ISLNK # define S_ISLNK(s) 0 #endif - /* If we're dereferencing symlinks and we're about to chdir through - a symlink, remember the current directory so we can return to it - later. In other cases, chdir ("..") works fine. */ - through_symlink = (xstat == stat - && lstat (ent, &e_buf) == 0 - && S_ISLNK (e_buf.st_mode)); - if (through_symlink && save_cwd (&cwd)) - exit (1); + /* If we're traversing more than one level, or if we're + dereferencing symlinks and we're about to chdir through a + symlink, remember the current directory so we can return to + it later. In other cases, chdir ("..") works fine. */ + if (strchr (ent, '/') + || (xstat == stat + && lstat (ent, &e_buf) == 0 + && S_ISLNK (e_buf.st_mode))) + { + if (save_cwd (&cwd_buf)) + exit (1); + cwd = &cwd_buf; + } + else + cwd = NULL; if (chdir (ent) < 0) { error (0, errno, _("cannot change to directory %s"), path->text); + if (cwd) + free_cwd (cwd); exit_status = 1; return 0; } @@ -548,7 +557,7 @@ count_entry (const char *ent, int top, dev_t last_dev, int depth) if (errno) { error (0, errno, "%s", path->text); - pop_dir (through_symlink, &cwd, path->text); + pop_dir (cwd, path->text); exit_status = 1; return 0; } @@ -572,7 +581,7 @@ count_entry (const char *ent, int top, dev_t last_dev, int depth) } free (name_space); - pop_dir (through_symlink, &cwd, path->text); + pop_dir (cwd, path->text); str_trunc (path, pathlen - 1); /* Remove the "/" we added. */ if (depth <= max_depth || top) -- cgit v1.2.3-70-g09d2