summaryrefslogtreecommitdiff
path: root/src/du.c
diff options
context:
space:
mode:
authorJim Meyering <meyering@redhat.com>2011-01-08 17:44:55 +0100
committerJim Meyering <meyering@redhat.com>2011-01-10 07:49:55 +0100
commit1c5987d2effdfae93362fcc4575c8ca4057740fc (patch)
tree370a04cf2fbf018b89cf1e02d81ed2bcf37e6759 /src/du.c
parentd5d283dbc9ae8d727470975bc8fdd3371468cbdf (diff)
downloadcoreutils-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.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/src/du.c b/src/du.c
index 77deb0c52..671cac784 100644
--- a/src/du.c
+++ b/src/du.c
@@ -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);