]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
du now diagnoses cycles, rather than ignoring them
authorJim Meyering <meyering@redhat.com>
Wed, 4 Nov 2009 21:01:52 +0000 (22:01 +0100)
committerJim Meyering <meyering@redhat.com>
Thu, 5 Nov 2009 07:32:31 +0000 (08:32 +0100)
* 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
src/du.c

diff --git a/NEWS b/NEWS
index 03ed83ff3f1d8dac4c50a0fc37e2e7a7232356de..ffecd86bee997a96289807f211d607ca222778ec 100644 (file)
--- 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]
index 9831a1788356ed1284a02a8029f2142e011c564f..7ef0306e8864d9a27b3ad0c4d07d0f7efaea9de4 100644 (file)
--- 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;