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 <[EMAIL PROTECTED]> * 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. [EMAIL PROTECTED] -perm +222 [EMAIL PROTECTED] -perm /222 Match files which are writeable by somebody (their owner, or their group, or anybody else). [EMAIL PROTECTED] -perm +022 [EMAIL PROTECTED] -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. [EMAIL PROTECTED] -perm +g+w,o+w [EMAIL PROTECTED] -perm /g+w,o+w As above. [EMAIL PROTECTED] -perm +g=w,o=w [EMAIL PROTECTED] -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 '@[EMAIL PROTECTED]' \; -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); _______________________________________________ Bug-findutils mailing list Bug-findutils@gnu.org http://lists.gnu.org/mailman/listinfo/bug-findutils