diff options
author | Jim Meyering <meyering@redhat.com> | 2011-01-08 17:44:55 +0100 |
---|---|---|
committer | Jim Meyering <meyering@redhat.com> | 2011-01-10 07:49:55 +0100 |
commit | 1c5987d2effdfae93362fcc4575c8ca4057740fc (patch) | |
tree | 370a04cf2fbf018b89cf1e02d81ed2bcf37e6759 /src/du.c | |
parent | d5d283dbc9ae8d727470975bc8fdd3371468cbdf (diff) | |
download | coreutils-1c5987d2effdfae93362fcc4575c8ca4057740fc.tar.xz |
du: don't abort when a subdir is renamed during traversal
* NEWS (Bug fixes): Mention it.
* src/du.c (prev_level): Move declaration "up" to file-scope global.
(du_files): Reset prev_level to 0 upon abnormal fts_read termination.
Reported by Johathan Nieder in http://bugs.debian.org/609049
Also, improve a diagnostic.
* tests/du/move-dir-while-traversing: Test for the above.
* tests/Makefile.am (TESTS): Add it.
Diffstat (limited to 'src/du.c')
-rw-r--r-- | src/du.c | 15 |
1 files changed, 11 insertions, 4 deletions
@@ -63,8 +63,11 @@ extern bool fts_debug; /* A set of dev/ino pairs. */ static struct di_set *di_set; -/* Define a class for collecting directory information. */ +/* Keep track of the preceding "level" (depth in hierarchy) + from one call of process_file to the next. */ +static size_t prev_level; +/* Define a class for collecting directory information. */ struct duinfo { /* Size of files in directory. */ @@ -399,7 +402,6 @@ process_file (FTS *fts, FTSENT *ent) struct duinfo dui; struct duinfo dui_to_print; size_t level; - static size_t prev_level; static size_t n_alloc; /* First element of the structure contains: The sum of the st_size values of all entries in the single directory @@ -582,10 +584,15 @@ du_files (char **files, int bit_flags) { if (errno != 0) { - /* FIXME: try to give a better message */ - error (0, errno, _("fts_read failed")); + error (0, errno, _("fts_read failed: %s"), + quotearg_colon (fts->fts_path)); ok = false; } + + /* When exiting this loop early, be careful to reset the + global, prev_level, used in process_file. Otherwise, its + (level == prev_level - 1) assertion could fail. */ + prev_level = 0; break; } FTS_CROSS_CHECK (fts); |