bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

added support for "chmod -r -w file", plus test cases


From: Paul Eggert
Subject: added support for "chmod -r -w file", plus test cases
Date: Fri, 24 Sep 2004 16:42:13 -0700
User-agent: Gnus/5.1006 (Gnus v5.10.6) Emacs/21.3 (gnu/linux)

In adding chmod test cases inspired by a recent Open Group email from
Glenn Fowler, I noticed that chmod had some bogus behavior for cases
like "chmod -r -w file":

  $ chmod -r -w file
  chmod: invalid character `w' in mode string `-w'

chmod need not support -r -w, but it should behave better when people
use it.  I installed this patch.

2004-09-24  Paul Eggert  <address@hidden>

        * NEWS: Mention that "chmod -r -w x" now works as expected.
        * doc/coreutils.texi (chmod invocation): Warn about "chmod -w file".
        * src/chmod.c (main): Revamp option processing to support this.
        * tests/chmod/Makefile.am (TESTS): Add 'usage'.
        * tests/chmod/usage: New set of tests for usage like that.

Index: NEWS
===================================================================
RCS file: /fetish/cu/NEWS,v
retrieving revision 1.237
diff -p -u -r1.237 NEWS
--- NEWS        23 Sep 2004 20:24:52 -0000      1.237
+++ NEWS        24 Sep 2004 23:29:04 -0000
@@ -32,6 +32,8 @@ GNU coreutils NEWS                      
     recursively-encountered symbolic link cannot be updated because
     the file system does not support it.
 
+  chmod now accepts multiple mode-like options, e.g., "chmod -r -w f".
+
   cut's --output-delimiter=D option works with abutting byte ranges.
 
   echo now conforms to POSIX better.  It supports the \0ooo syntax for
Index: doc/coreutils.texi
===================================================================
RCS file: /fetish/cu/doc/coreutils.texi,v
retrieving revision 1.214
diff -p -u -r1.214 coreutils.texi
--- doc/coreutils.texi  23 Sep 2004 20:26:31 -0000      1.214
+++ doc/coreutils.texi  24 Sep 2004 23:29:05 -0000
@@ -8303,6 +8303,9 @@ recursive directory traversals.
 
 If used, @var{mode} specifies the new permissions.
 For details, see the section on @ref{File permissions}.
+In the extremely rare cases where @var{mode} has leading @samp{-}, a
+portable script should use @option{--} first, e.g., @samp{chmod -- -w
+file}.  Typically, though, @samp{chmod a-w file} is preferable.
 
 The program accepts the following options.  Also see @ref{Common options}.
 
Index: src/chmod.c
===================================================================
RCS file: /fetish/cu/src/chmod.c,v
retrieving revision 1.106
diff -p -u -r1.106 chmod.c
--- src/chmod.c 21 Sep 2004 22:26:42 -0000      1.106
+++ src/chmod.c 24 Sep 2004 23:29:05 -0000
@@ -339,9 +339,10 @@ int
 main (int argc, char **argv)
 {
   struct mode_change *changes;
+  char *mode = NULL;
+  size_t mode_len = 0;
+  size_t mode_alloc = 0;
   bool ok;
-  int modeind = 0;             /* Index of the mode argument in `argv'. */
-  int thisind;
   bool preserve_root = false;
   int c;
 
@@ -355,14 +356,11 @@ main (int argc, char **argv)
 
   recurse = force_silent = false;
 
-  while (1)
+  while ((c = getopt_long (argc, argv,
+                          "Rcfvr::w::x::X::s::t::u::g::o::a::,::+::-::=::",
+                          long_options, NULL))
+        != -1)
     {
-      thisind = optind ? optind : 1;
-
-      c = getopt_long (argc, argv, "RcfvrwxXstugoa,+-=", long_options, NULL);
-      if (c == -1)
-       break;
-
       switch (c)
        {
        case 'r':
@@ -379,15 +377,25 @@ main (int argc, char **argv)
        case '+':
        case '-':
        case '=':
-         if (modeind != 0 && modeind != thisind)
-           {
-             static char char_string[2] = {0, 0};
-             char_string[0] = c;
-             error (EXIT_FAILURE, 0,
-                    _("invalid character %s in mode string %s"),
-                    quote_n (0, char_string), quote_n (1, argv[thisind]));
-           }
-         modeind = thisind;
+         {
+           /* Allocate a mode string (e.g., "-rwx") by concatenating
+              the argument containing this option.  If a previous mode
+              string was given, concatenate the previous string, a
+              comma, and the new string (e.g., "-s,-rwx").  */
+
+           char const *arg = argv[optind - 1];
+           size_t arg_len = strlen (arg);
+           size_t mode_comma_len = mode_len + !!mode_len;
+           size_t new_mode_len = mode_comma_len + arg_len;
+           if (mode_alloc <= new_mode_len)
+             {
+               mode_alloc = new_mode_len + 1;
+               mode = x2realloc (mode, &mode_alloc);
+             }
+           mode[mode_len] = ',';
+           strcpy (mode + mode_comma_len, arg);
+           mode_len = new_mode_len;
+         }
          break;
        case NO_PRESERVE_ROOT:
          preserve_root = false;
@@ -417,12 +425,21 @@ main (int argc, char **argv)
        }
     }
 
-  if (modeind == 0 && reference_file == NULL)
-    modeind = optind++;
+  if (reference_file)
+    {
+      if (mode)
+       error (EXIT_FAILURE, 0,
+              _("cannot combine mode and --reference options"));
+    }
+  else
+    {
+      if (!mode)
+       mode = argv[optind++];
+    }
 
   if (optind >= argc)
     {
-      if (modeind == 0 || modeind != argc - 1)
+      if (!mode || mode != argv[optind - 1])
        error (0, 0, _("missing operand"));
       else
        error (0, 0, _("missing operand after %s"), quote (argv[argc - 1]));
@@ -430,11 +447,10 @@ main (int argc, char **argv)
     }
 
   changes = (reference_file ? mode_create_from_ref (reference_file)
-            : mode_compile (argv[modeind], MODE_MASK_ALL));
+            : mode_compile (mode, MODE_MASK_ALL));
 
   if (changes == MODE_INVALID)
-    error (EXIT_FAILURE, 0,
-          _("invalid mode string: %s"), quote (argv[modeind]));
+    error (EXIT_FAILURE, 0, _("invalid mode: %s"), quote (mode));
   else if (changes == MODE_MEMORY_EXHAUSTED)
     xalloc_die ();
   else if (changes == MODE_BAD_REFERENCE)
Index: tests/chmod/Makefile.am
===================================================================
RCS file: /fetish/cu/tests/chmod/Makefile.am,v
retrieving revision 1.7
diff -p -u -r1.7 Makefile.am
--- tests/chmod/Makefile.am     17 Oct 2003 13:29:01 -0000      1.7
+++ tests/chmod/Makefile.am     24 Sep 2004 23:29:05 -0000
@@ -1,7 +1,7 @@
 ## Process this file with automake to produce Makefile.in -*-Makefile-*-.
 AUTOMAKE_OPTIONS = 1.4 gnits
 
-TESTS = no-x equals equal-x c-option setgid
+TESTS = no-x equals equal-x c-option setgid usage
 EXTRA_DIST = $(TESTS)
 TESTS_ENVIRONMENT = \
   PATH="`pwd`/../../src$(PATH_SEPARATOR)$$PATH"




reply via email to

[Prev in Thread] Current Thread [Next in Thread]