* 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.
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
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));
+}
+#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);
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;
}
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;
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;
}