[Top][All Lists]
[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"
- added support for "chmod -r -w file", plus test cases,
Paul Eggert <=