chcon, chgrp, chmod and chown now diagnose a directory cycle
authorJim Meyering <meyering@redhat.com>
Sat, 7 Nov 2009 07:09:12 +0000 (08:09 +0100)
committerJim Meyering <meyering@redhat.com>
Sat, 7 Nov 2009 07:43:00 +0000 (08:43 +0100)
* lib/xfts.c (cycle_warning_required): New function.
* lib/xfts.h: Declare it.
* src/chown-core.c (change_file_owner): Diagnose a cycle.
* src/chmod.c (process_file): Likewise.
* src/chcon.c (process_file): Likewise.
* NEWS (Bug fixes): Mention this.

NEWS
lib/xfts.c
lib/xfts.h
src/chcon.c
src/chmod.c
src/chown-core.c

diff --git a/NEWS b/NEWS
index 24b2afa..b13a5f2 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -8,8 +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."
+  chcon, chgrp, chmod, chown and du now diagnose an ostensible directory cycle
+  and arrange to exit nonzero.  Before, they 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
index 5994a5f..9c46f6a 100644 (file)
@@ -61,3 +61,22 @@ xfts_open (char * const *argv, int options,
 
   return fts;
 }
+
+/* When fts_read returns FTS_DC to indicate a directory cycle,
+   it may or may not indicate a real problem.  When a program like
+   chgrp performs a recursive traversal that requires traversing
+   symbolic links, it is *not* a problem.  However, when invoked
+   with "-P -R", it deserves a warning.  The fts_options member
+   records the options that control this aspect of fts's behavior,
+   so test that.  */
+bool
+cycle_warning_required (FTS const *fts, FTSENT const *ent)
+{
+#define ISSET(Fts,Opt) ((Fts)->fts_options & (Opt))
+  /* 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. */
+  return ((ISSET (fts, FTS_PHYSICAL) && !ISSET (fts, FTS_COMFOLLOW))
+          || (ISSET (fts, FTS_PHYSICAL) && ISSET (fts, FTS_COMFOLLOW)
+              && ent->fts_level != FTS_ROOTLEVEL));
+}
index 27ddb5d..fc3ba90 100644 (file)
@@ -1,5 +1,9 @@
+#include <stdbool.h>
 #include "fts_.h"
 
 FTS *
 xfts_open (char * const *, int options,
            int (*) (const FTSENT **, const FTSENT **));
+
+bool
+cycle_warning_required (FTS const *fts, FTSENT const *ent);
index 2badefb..5e58cac 100644 (file)
@@ -267,6 +267,14 @@ process_file (FTS *fts, FTSENT *ent)
       ok = false;
       break;
 
+    case FTS_DC:               /* directory that causes cycles */
+      if (cycle_warning_required (fts, ent))
+        {
+          emit_cycle_warning (file_full_name);
+          return false;
+        }
+      break;
+
     default:
       break;
     }
index da35003..1a0dafa 100644 (file)
@@ -228,6 +228,15 @@ process_file (FTS *fts, FTSENT *ent)
         error (0, 0, _("cannot operate on dangling symlink %s"),
                quote (file_full_name));
       ok = false;
+      break;
+
+    case FTS_DC:               /* directory that causes cycles */
+      if (cycle_warning_required (fts, ent))
+        {
+          emit_cycle_warning (file_full_name);
+          return false;
+        }
+      break;
 
     default:
       break;
index e7dacf6..eaebe60 100644 (file)
@@ -316,6 +316,14 @@ change_file_owner (FTS *fts, FTSENT *ent,
       ok = false;
       break;
 
+    case FTS_DC:               /* directory that causes cycles */
+      if (cycle_warning_required (fts, ent))
+        {
+          emit_cycle_warning (file_full_name);
+          return false;
+        }
+      break;
+
     default:
       break;
     }