bug-findutils
[Top][All Lists]
Advanced

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

findutils POSIX incompatiblity with "find . -perm ++w -print"


From: Paul Eggert
Subject: findutils POSIX incompatiblity with "find . -perm ++w -print"
Date: Mon, 23 May 2005 13:04:24 -0700
User-agent: Gnus/5.1006 (Gnus v5.10.6) Emacs/21.4 (gnu/linux)

This is a followup to my bug report of yesterday about findutils and
recent gnulib versions.  The import-gnulib.sh patch of yesterday's
message is still valid, but the patch proposed below supersedes the
parser.c change.

GNU find has an extension "-perm +MODE" that is true if any of the
bits of MODE are set for a file.  Unfortunately, this extension is
incompatible with POSIX
<http://www.opengroup.org/onlinepubs/009695399/utilities/find.html>.
For example, POSIX says that the command

umask 0
find . -perm ++r -print

must print only files with mode 444, but GNU find prints any file
that is readable to anybody.

The incompatibilities occur only for fairly obscure cases, so I
suggest the following fix.

First, GNU find can continue to support "-perm +MODE" under its
current interpretation, when that does not disagree with POSIX.  This
will support common uses of "-perm +MODE", for backwards compatiblity.

Second, GNU find can support and promote a different syntax that
doesn't have this obscure problem.  I suggest "-perm /MODE"; this does
not conflict with POSIX.  I chose "/" because it isn't a shell
metacharacter and it looks a bit like the "or" symbol.

Here is a patch.

2005-05-23  Paul Eggert  <address@hidden>

        * NEWS: Mention the new "find ... -perm /MODE" syntax, which replaces
        the "find ... -perm +MODE" syntax (which was incompatible with POSIX
        in a few obscure cases).
        * doc/find.texi (Permissions): Document "-perm /MODE" rather than
        "-perm +MODE".
        * find/parser.c (parse_perm): Support "-perm /MODE".  Use the
        POSIX interpretation of "-perm +MODE" but only when that disagrees
        with the old GNU interpretation.  Adjust to the new gnulib API
        for mode strings.

Index: NEWS
===================================================================
RCS file: /cvsroot/findutils/findutils/NEWS,v
retrieving revision 1.71
diff -p -u -b -w -r1.71 NEWS
--- NEWS        6 Apr 2005 08:23:45 -0000       1.71
+++ NEWS        23 May 2005 19:59:38 -0000
@@ -1,5 +1,10 @@
 GNU findutils NEWS - User visible changes.     -*- outline -*- (allout)
 * Major changes in release 4.2.21-CVS
+** The GNU extension "find ... -perm +MODE" has been withdrawn because it
+   is incompatible with POSIX in obscure cases like "find ... -perm ++r".
+   Use the new syntax "find ... -perm /MODE" instead.  Old usages will
+   still continue to work, so long as they don't conflict with POSIX.
+
 ** Bug Fixes
    find /blah/blah/blah -depth -empty now works once again.
 
Index: doc/find.texi
===================================================================
RCS file: /cvsroot/findutils/findutils/doc/find.texi,v
retrieving revision 1.78
diff -p -u -b -w -r1.78 find.texi
--- doc/find.texi       18 Apr 2005 09:03:43 -0000      1.78
+++ doc/find.texi       23 May 2005 19:59:38 -0000
@@ -907,16 +907,17 @@ numeric or symbolic).
 If @var{mode} starts with @samp{-}, true if
 @emph{all} of the permissions set in @var{mode} are set for the file;
 permissions not set in @var{mode} are ignored.
-If @var{mode} starts with @samp{+}, true if
+
+If @var{mode} starts with @samp{/}, true if
 @emph{any} of the permissions set in @var{mode} are set for the file;
 permissions not set in @var{mode} are ignored.
+This is a GNU extension.
 
-
-If you don't use the @samp{+} or @samp{-} form with a symbolic mode
+If you don't use the @samp{/} or @samp{-} form with a symbolic mode
 string, you may have to specify a rather complex mode string.  For
 example @samp{-perm g=w} will only match files which have mode 0020
 (that is, ones for which group write permission is the only permission
-set).  It is more likely that you will want to use the @samp{+} or
+set).  It is more likely that you will want to use the @samp{/} or
 @samp{-} forms, for example @samp{-perm -g=w}, which matches any file
 with group write permission.
 
@@ -935,19 +936,19 @@ without regard to the presence of any ex
 example the executable bit).  This will match a file which has mode
 0777, for example.
 
address@hidden -perm +222
address@hidden -perm /222
 Match files which are writeable by somebody (their owner, or
 their group, or anybody else).
 
address@hidden -perm +022
address@hidden -perm /022
 Match files which are writeable by either their owner or their
 group.  The files don't have to be writeable by both the owner and
 group to be matched; either will do.
 
address@hidden -perm +g+w,o+w
address@hidden -perm /g+w,o+w
 As above.
 
address@hidden -perm +g=w,o=w
address@hidden -perm /g=w,o=w
 As above
 
 @item -perm -022
@@ -1994,7 +1995,7 @@ running @code{file} on files that are no
 executable.
 
 @example
-find /usr/local -type f -perm +a=x | xargs file | 
+find /usr/local -type f -perm /a=x | xargs file |
   grep 'not stripped' | cut -d: -f1
 @end example
 
@@ -2037,7 +2038,7 @@ scripts) in the file @file{sbins} and th
 @file{ubins}.
 
 @example
-find /usr/local -type f -perm +a=x \
+find /usr/local -type f -perm /a=x \
   \( -execdir unstripped '@address@hidden' \; -fprint ubins -o -fprint sbins \)
 @end example
 
Index: find/parser.c
===================================================================
RCS file: /cvsroot/findutils/findutils/find/parser.c,v
retrieving revision 1.64
diff -p -u -b -w -r1.64 parser.c
--- find/parser.c       16 May 2005 21:14:46 -0000      1.64
+++ find/parser.c       23 May 2005 19:59:38 -0000
@@ -1,5 +1,5 @@
 /* parser.c -- convert the command line args into an expression tree.
-   Copyright (C) 1990, 91, 92, 93, 94, 2000, 2001, 2003, 2004 Free Software 
Foundation, Inc.
+   Copyright (C) 1990, 91, 92, 93, 94, 2000, 2001, 2003, 2004, 2005 Free 
Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -1214,7 +1214,8 @@ parse_perm (char **argv, int *arg_ptr)
 {
   mode_t perm_val;
   int mode_start = 0;
-  struct mode_change *change;
+  enum permissions_type kind = PERM_EXACT;
+  struct mode_change *change = NULL;
   struct predicate *our_pred;
 
   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
@@ -1223,36 +1224,39 @@ parse_perm (char **argv, int *arg_ptr)
   switch (argv[*arg_ptr][0])
     {
     case '-':
+      mode_start = 1;
+      kind = PERM_AT_LEAST;
+      break;
     case '+':
+      if (argv[*arg_ptr][0] == '+' && (change = mode_compile (argv[*arg_ptr])))
+       break;
+      /* Most likely this is an old script that is still using the obsolete
+        GNU syntax "-perm +MODE".  This old syntax was withdrawn in favor of
+        "-perm /MODE" because it is incompatible with POSIX in some cases,
+        but we still support uses of it that are not incompatible with
+        POSIX.  */
+      /* Fall through.  */
+    case '/':
       mode_start = 1;
+      kind = PERM_ANY;
       break;
     default:
       /* empty */
       break;
     }
 
-  change = mode_compile (argv[*arg_ptr] + mode_start, MODE_MASK_PLUS);
-  if (change == MODE_INVALID)
+  if (! change)
+    {
+      change = mode_compile (argv[*arg_ptr] + mode_start);
+      if (! change)
     error (1, 0, _("invalid mode `%s'"), argv[*arg_ptr]);
-  else if (change == MODE_MEMORY_EXHAUSTED)
-    error (1, 0, _("virtual memory exhausted"));
-  perm_val = mode_adjust (0, change);
-  mode_free (change);
+    }
 
-  our_pred = insert_primary (pred_perm);
+  perm_val = mode_adjust (0, change, 0);
+  free (change);
 
-  switch (argv[*arg_ptr][0])
-    {
-    case '-':
-      our_pred->args.perm.kind = PERM_AT_LEAST;
-      break;
-    case '+':
-      our_pred->args.perm.kind = PERM_ANY;
-      break;
-    default:
-      our_pred->args.perm.kind = PERM_EXACT;
-      break;
-    }
+  our_pred = insert_primary (pred_perm);
+  our_pred->args.perm.kind = kind;
   our_pred->args.perm.val = perm_val & MODE_ALL;
   (*arg_ptr)++;
   return (true);





reply via email to

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