On Sat, Jul 16, 2005 at 07:14:13PM -0700, Paul Eggert wrote: > I assume you're talking about the -H, -h, -L, -P options. You're > right, these would be nice to add to coreutils.
Please find enclosed a patch which adds the -H, -L and -P options (with no long form). This was actually pretty easy since fts() provides all the required functionality. I also enclose an entry for the test suite for these three options (and the default). I've tested the test suite entry by backing out the change and seeing the new tests fail. Apologies for any formatting errors in the ChangeLog entry. Adding the -h option is essentially orthogonal as this would be a change to process_file(); if S_ISLNK(file_stats->st_mode), we would need to use lchmod(2) (for which a test would need to be introduced into configure.ac) on the symbolic link. I haven't implemented this yet. Dave, could you define for us (i.e. the mailing list) how the "-h" and "-L" options of chmod interact, both when -R is given and when it is not? Thanks. Regards, James.
Index: src/chmod.c =================================================================== RCS file: /cvsroot/coreutils/coreutils/src/chmod.c,v retrieving revision 1.113 diff -u -r1.113 chmod.c --- src/chmod.c 29 Jun 2005 16:27:37 -0000 1.113 +++ src/chmod.c 17 Jul 2005 11:01:33 -0000 @@ -235,6 +235,21 @@ ok = false; } } + else + { +#if HAVE_LCHMOD + if (lchmod (file, new_mode) == 0) + chmod_succeeded = true; + else + { + if (! force_silent) + error (0, errno, _("changing permissions of symbolic link %s"), + quote (file_full_name)); + ok = false; + } +#endif + } + } if (verbosity != V_off) @@ -343,6 +358,9 @@ -v, --verbose output a diagnostic for every file processed\n\ --reference=RFILE use RFILE's mode instead of MODE values\n\ -R, --recursive change files and directories recursively\n\ + -P with -R, do not follow symblic links (default)\n\ + -L with -R, follow all symbolic links\n\ + -H with -R, follow links only for named files\n\ "), stdout); fputs (HELP_OPTION_DESCRIPTION, stdout); fputs (VERSION_OPTION_DESCRIPTION, stdout); @@ -368,7 +386,8 @@ bool preserve_root = false; char const *reference_file = NULL; int c; - + int symlink_options = FTS_PHYSICAL; + initialize_main (&argc, &argv); program_name = argv[0]; setlocale (LC_ALL, ""); @@ -378,9 +397,9 @@ atexit (close_stdout); recurse = force_silent = diagnose_surprises = false; - + while ((c = getopt_long (argc, argv, - "Rcfvr::w::x::X::s::t::u::g::o::a::,::+::=::", + "HLPRcfvr::w::x::X::s::t::u::g::o::a::,::+::=::", long_options, NULL)) != -1) { @@ -434,6 +453,15 @@ case REFERENCE_FILE_OPTION: reference_file = optarg; break; + case 'H': + symlink_options = FTS_COMFOLLOW; + break; + case 'L': + symlink_options = FTS_LOGICAL; + break; + case 'P': /* default if -R, ignored otherwise */ + symlink_options = FTS_PHYSICAL; + break; case 'R': recurse = true; break; @@ -507,7 +535,11 @@ root_dev_ino = NULL; } - ok = process_files (argv + optind, FTS_COMFOLLOW); + /* Options -H, -L and -P are ignored in the absence of -R. */ + if (!recurse) + symlink_options = FTS_COMFOLLOW; + + ok = process_files (argv + optind, symlink_options); exit (ok ? EXIT_SUCCESS : EXIT_FAILURE); }
--- /dev/null 2005-04-10 23:52:41.000000000 +0100 +++ tests/chmod/symlinks 2005-07-17 11:57:29.974020711 +0100 @@ -0,0 +1,99 @@ +#!/bin/sh +# Make sure chmod options -H, -L, -P work as designed. +# This is a feature from BSD's chmod. + +if test "$VERBOSE" = yes; then + set -x + chmod --version +fi + +pwd=`pwd` +tmp=equals.$$ +trap 'status=$?; cd $pwd; rm -rf A B C && exit $status' 0 +trap '(exit $?); exit' 1 2 13 15 + +framework_failure=0 + +if test $framework_failure = 1; then + echo "$0: failure in testing framework" 1>&2 + (exit 1); exit 1 +fi + +fail=0 + +# prepare our files. +mkdir A B +ln -s B C +( cd B ; ln -s ../A b ) +touch A/xyzzy B/xyzzy +chmod 555 A/xyzzy B/xyzzy + +expected_yes=-r-xr-x--- +expected_no=-r-xr-xr-x + +if test $fail -eq 0; then + : 1 + # Test -P (the default). + # B should be unaffected since c->B should not be followed. + chmod -R -P o= A C || fail=1 + + # -P: A should be affected. B should be unaffected + set _ `ls -l A/xyzzy`; shift; actual_perms=$1 + test "$actual_perms" = "$expected_yes" || fail=1 + set _ `ls -l B/xyzzy`; shift; actual_perms=$1 + test "$actual_perms" = "$expected_no" || fail=1 +fi + +if test $fail -eq 0; then + : 2 + # reset to initial conditions. + chmod -R 555 */xyzzy + + # -L: Both A and B should be affected, because + # chmod should follow the link B/b -> ../A + chmod -R -L o= B || fail=1 + set _ `ls -l A/xyzzy`; shift; actual_perms=$1 + test "$actual_perms" = "$expected_yes" || fail=1 + set _ `ls -l B/xyzzy`; shift; actual_perms=$1 + test "$actual_perms" = "$expected_yes" || fail=1 +fi + +if test $fail -eq 0; then + : 3a + # reset to initial conditions. + chmod -R 555 */xyzzy + + # -H: Only links named on the command line should + # be followed. + chmod -R -H o= C || fail=1 + # B/xyzzy should be affected since C is a symlink to A. + set _ `ls -l B/xyzzy`; shift; actual_perms=$1 + test "$actual_perms" = "$expected_yes" || fail=1 +fi + +if test $fail -eq 0; then + : 3b + # reset to initial conditions. + chmod -R 555 */xyzzy + chmod -R -H o= B || fail=1 + # A/xyzzy should NOT be affected since the B/b symlink + # should not be affected. + set _ `ls -l A/xyzzy`; shift; actual_perms=$1 + test "$actual_perms" = "$expected_no" || fail=1 +fi + +if test $fail -eq 0; then + : 4 + # Check that the default behaviour is consistent with -P. + # reset to initial conditions. + chmod -R 555 */xyzzy + chmod -R -P o= A C || fail=1 + + # -P: A should be affected. B should be unaffected + set _ `ls -l A/xyzzy`; shift; actual_perms=$1 + test "$actual_perms" = "$expected_yes" || fail=1 + set _ `ls -l B/xyzzy`; shift; actual_perms=$1 + test "$actual_perms" = "$expected_no" || fail=1 +fi + +(exit $fail); exit $fail
2005-07-17 James Youngman <[EMAIL PROTECTED]> * src/chmod.c (main): Implemented options -H, -L and -P. * tests/chmod/symlinks: tests for chmod options -H, -L and -P.
_______________________________________________ Bug-coreutils mailing list Bug-coreutils@gnu.org http://lists.gnu.org/mailman/listinfo/bug-coreutils