From 8ba5d1a70cc88fce33fabf488f382140d4c5c101 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Wed, 4 Nov 2009 22:01:52 +0100 Subject: [PATCH] du now diagnoses cycles, rather than ignoring them * src/du.c (symlink_deref_bits): New global, decl moved from ... (main): ...here. (process_file): When fts detects a directory cycle that can't be due to symlinks, report it and arrange to exit nonzero. * NEWS (Bug fixes): Mention it. --- NEWS | 3 +++ src/du.c | 23 ++++++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 03ed83ff3f..ffecd86bee 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,9 @@ GNU coreutils NEWS -*- outline -*- Even then, chcon may still be useful. [bug introduced in coreutils-8.0] + du now diagnoses an ostensible directory cycle and arranges to exit nonzero. + Before, it would silently ignore the offending directory and all "contents." + env -u A=B now fails, rather than silently adding A to the environment. Likewise, printenv A=B silently ignores the invalid name. [the bugs date back to the initial implementation] diff --git a/src/du.c b/src/du.c index 9831a17883..7ef0306e88 100644 --- a/src/du.c +++ b/src/du.c @@ -65,9 +65,12 @@ extern bool fts_debug; /* Initial size of the hash table. */ #define INITIAL_TABLE_SIZE 103 +/* Select one of the three FTS_ options that control if/when + to follow a symlink. */ +static int symlink_deref_bits = FTS_PHYSICAL; + /* Hash structure for inode and device numbers. The separate entry structure makes it easier to rehash "in place". */ - struct entry { ino_t st_ino; @@ -495,6 +498,20 @@ process_file (FTS *fts, FTSENT *ent) ok = false; break; + case FTS_DC: /* directory that causes cycles */ + /* When dereferencing no symlinks, or when dereferencing only + those listed on the command line and we're not processing + a command-line argument, then a cycle is a serious problem. */ + if (symlink_deref_bits == FTS_PHYSICAL + || (symlink_deref_bits == (FTS_COMFOLLOW | FTS_PHYSICAL) + && ent->fts_level != FTS_ROOTLEVEL)) + { + emit_cycle_warning (ent->fts_path); + return false; + } + ok = true; + break; + default: ok = true; break; @@ -661,10 +678,6 @@ main (int argc, char **argv) /* Bit flags that control how fts works. */ int bit_flags = FTS_TIGHT_CYCLE_CHECK | FTS_DEFER_STAT; - /* Select one of the three FTS_ options that control if/when - to follow a symlink. */ - int symlink_deref_bits = FTS_PHYSICAL; - /* If true, display only a total for each argument. */ bool opt_summarize_only = false; -- 2.39.5