summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2000-04-27 12:23:59 +0000
committerJim Meyering <jim@meyering.net>2000-04-27 12:23:59 +0000
commit4954d34c147a80932b3befe5ef5d922ee534f6ff (patch)
tree2f92b57788d7bbf89c10e80c640a645d8e06ad22 /src
parente9c9e0f9e5c93e9f6af1ce99da661a81bb17d492 (diff)
downloadcoreutils-4954d34c147a80932b3befe5ef5d922ee534f6ff.tar.xz
(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.
Diffstat (limited to 'src')
-rw-r--r--src/du.c39
1 files changed, 24 insertions, 15 deletions
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)