From 90f0c5d24153ad3327edd6f2249fc95a5cfb72e0 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Sun, 21 Apr 2013 00:14:18 -0700
Subject: [PATCH] Remove support for obsolete -perm +MODE syntax.
To: findutils-patches@gnu.org

Also, do not reject -perm /MODE merely because of POSIXLY_CORRECT.
Problem reported in <https://savannah.gnu.org/bugs/?38474>.
* NEWS:
* doc/find.texi (Mode Bits): Document this.
(Environment Variables): POSIXLY_CORRECT does not affect -perm.
* find/parser.c (parse_help): Mention /MODE, not +MODE.
(non_posix_mode): Remove.
(parse_perm): Remove support for -perm +MODE.
Do not reject -perm /MODE merely because POSIXLY_CORRECT is set;
POSIXLY_CORRECT is not supposed to be for pedantic checking.
---
 ChangeLog     |   17 +++++++++++++++
 NEWS          |   13 ++++++++++-
 doc/find.texi |   11 +--------
 find/find.1   |   38 ++++++++++++---------------------
 find/parser.c |   63 ++++++++++----------------------------------------------
 5 files changed, 57 insertions(+), 85 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index baf91cd..582ca05 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2013-04-21  Paul Eggert  <eggert@cs.ucla.edu>
+
+	Remove support for obsolete -perm +MODE syntax.
+	Also, do not reject -perm /MODE merely because of POSIXLY_CORRECT.
+	Problem reported in <https://savannah.gnu.org/bugs/?38474>.
+	* NEWS:
+	* doc/find.texi (Mode Bits): Document this.
+	(Environment Variables): POSIXLY_CORRECT does not affect -perm.
+	* find/parser.c (parse_help): Mention /MODE, not +MODE.
+	(non_posix_mode): Remove.
+	(parse_perm): Remove support for -perm +MODE.
+	Do not reject -perm /MODE merely because POSIXLY_CORRECT is set;
+	POSIXLY_CORRECT is not supposed to be for pedantic checking.
+	* find/find.1 (-perm): describe this change.
+	(HISTORY): update the existing statement about the deprecation of
+	+MODE to explain that support has now been removed.
+
 2013-04-22  James Youngman  <jay@gnu.org>
 
 	Fix documentation typo.
diff --git a/NEWS b/NEWS
index 8dfc2fb..4349a21 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,15 @@ GNU findutils NEWS - User visible changes.      -*- outline -*- (allout)
 
 * Major changes in release 4.5.12-git, YYYY-MM-DD
 
+** Functional Changes to find
+
+The GNU extension "find ... -perm /MODE" is no longer disabled when
+the POSIXLY_CORRECT environment variable is set.
+
+The obsolete GNU extension "find ... -perm +MODE", which was withdrawn
+in release 4.2.21 in 2005 due to compatibility problems, has been
+completely removed.  Use "find ... -perm /MODE" instead.
+
 ** Documentation Changes
 
 If you use -type or -xtype with a type letter corresponding to a file
@@ -18,7 +27,7 @@ The documentation for xargs now warns about parallel processes (xargs
 
 ** Bug Fixes
 
-Some bugs in 4.5.11 were fixed without addinng them to the bug
+Some bugs in 4.5.11 were fixed without adding them to the bug
 database, though they are in the ChangeLog:
 
 *** Use of [[ ... ]] in find/testsuite/sv-bug-32043.sh
@@ -28,6 +37,8 @@ database, though they are in the ChangeLog:
 These following fixed bugs are recorded at
 https://savannah.gnu.org/bugs/?group=findutils:
 
+#38474: Unintended (?) behaviour change of -perm +mode predicate
+
 #38583: errno-buffer read failed in xargs_do_exec
 
 #36652: Better document that -0/-d turns off the effect of -E.
diff --git a/doc/find.texi b/doc/find.texi
index 263faea..94d4c5c 100644
--- a/doc/find.texi
+++ b/doc/find.texi
@@ -1182,11 +1182,8 @@ optionally prefixed by @samp{-} or @samp{/}.
 
 A @var{pmode} that starts with neither @samp{-} nor @samp{/} matches
 if @var{mode} exactly matches the file mode bits.
-
-A @var{pmode} that starts with @samp{+} but which is not valid (for
-example @samp{+a+x}) is an error if the @code{POSIXLY_CORRECT} environment
-variable is set.  Otherwise this is treated as if the initial
-@samp{+} were a @samp{/}, for backward compatibility.
+(To avoid confusion with an obsolete GNU extension, @var{mode}
+must not start with a @samp{+} immediately followed by an octal digit.)
 
 A @var{pmode} that starts with @samp{-} matches if
 @emph{all} the file mode bits set in @var{mode} are set for the file;
@@ -3982,10 +3979,6 @@ Setting this variable also turns off warning messages (that is, implies
 the output for @samp{-ok}, all messages printed on stderr are
 diagnostics and must result in a non-zero exit status.
 
-Arguments to @samp{-perm} beginning with @samp{+} are treated
-differently when @code{POSIXLY_CORRECT} is set.
-@xref{Mode Bits,-perm,File Mode Bits}.
-
 When @code{POSIXLY_CORRECT} is set, the response to the prompt made by the
 @code{-ok} action is interpreted according to the system's message
 catalogue, as opposed to according to @code{find}'s own message
diff --git a/find/find.1 b/find/find.1
index d4f824f..472d85e 100644
--- a/find/find.1
+++ b/find/find.1
@@ -801,25 +801,9 @@ with the behaviour of
 .BR \-000 ).
 
 .IP "\-perm +\fImode\fR"
-Deprecated, old way of searching for files with any of the permission
-bits in \fImode\fR set.  You should use
-.B \-perm \fI/mode\fR
-instead. Trying to use the `+' syntax with symbolic modes will yield
-surprising results.  For example, `+u+x' is a valid symbolic mode
-(equivalent to +u,+x, i.e. 0111) and will therefore not be evaluated
-as
-.B \-perm +\fImode\fR
-but instead as the exact mode specifier
-.B \-perm \fImode\fR
-and so it matches files with exact permissions 0111 instead of files with any
-execute bit set.  If you found this paragraph confusing, you're not
-alone - just use
-.B \-perm /\fImode\fR.
-This form of the
-.B \-perm
-test is deprecated because the POSIX specification requires the
-interpretation of a leading `+' as being part of a symbolic mode, and
-so we switched to using `/' instead.
+This is no longer supported (and has been deprecated since 2005).  Use
+.B "\-perm /\fImode\fR"
+instead.
 
 .IP \-readable
 Matches files which are readable.  This takes into account access
@@ -2046,11 +2030,6 @@ As of findutils-4.2.2, shell metacharacters (`*', `?' or `[]' for
 example) used in filename patterns will match a leading `.', because
 IEEE POSIX interpretation 126 requires this.
 .P
-The syntax
-\.B \-perm +MODE
-was deprecated in findutils-4.2.21, in favour of
-\.B \-perm
-.BR /MODE .
 As of findutils-4.3.3,
 .B \-perm /000
 now matches all files instead of none.
@@ -2098,6 +2077,17 @@ Feature	Added in	Also occurs in
 \-ipath	3.8
 \-iregex	3.8
 .TE
+.P
+The syntax
+\.B \-perm +MODE
+was removed in findutils-4.5.12, in favour of
+\.B \-perm
+.BR /MODE .
+The
+.B +MODE
+syntax had been deprecated since findutils-4.2.21
+which was released in 2005.
+.P
 .SH "NON-BUGS"
 .nf
 .B $ find . \-name *.c \-print
diff --git a/find/parser.c b/find/parser.c
index 18173fb..6d9005c 100644
--- a/find/parser.c
+++ b/find/parser.c
@@ -1237,7 +1237,7 @@ tests (N can be +N or -N or N): -amin N -anewer FILE -atime N -cmin N\n\
       -ilname PATTERN -iname PATTERN -inum N -iwholename PATTERN -iregex PATTERN\n\
       -links N -lname PATTERN -mmin N -mtime N -name PATTERN -newer FILE"));
   puts (_("\
-      -nouser -nogroup -path PATTERN -perm [+-]MODE -regex PATTERN\n\
+      -nouser -nogroup -path PATTERN -perm [-/]MODE -regex PATTERN\n\
       -readable -writable -executable\n\
       -wholename PATTERN -size N[bcwkMG] -true -type [bcdpflsD] -uid N\n\
       -used N -user NAME -xtype [bcdpfls]"));
@@ -1942,17 +1942,6 @@ parse_iwholename (const struct parser_table* entry, char **argv, int *arg_ptr)
   return insert_path_check (entry, argv, arg_ptr, "iwholename", pred_ipath);
 }
 
-static void
-non_posix_mode (const char *mode)
-{
-  if (options.posixly_correct)
-    {
-      error (EXIT_FAILURE, 0,
-	     _("Mode %s is not valid when POSIXLY_CORRECT is on."),
-	     quotearg_n_style (0, options.err_quoting_style, mode));
-    }
-}
-
 
 static bool
 parse_perm (const struct parser_table* entry, char **argv, int *arg_ptr)
@@ -1962,7 +1951,7 @@ parse_perm (const struct parser_table* entry, char **argv, int *arg_ptr)
   int mode_start = 0;
   bool havekind = false;
   enum permissions_type kind = PERM_EXACT;
-  struct mode_change *change = NULL;
+  struct mode_change *change;
   struct predicate *our_pred;
   const char *perm_expr;
 
@@ -1978,38 +1967,7 @@ parse_perm (const struct parser_table* entry, char **argv, int *arg_ptr)
       rate = 0.2;
       break;
 
-     case '+':
-       change = mode_compile (perm_expr);
-       if (NULL == change)
-	 {
-	   /* Most likely the caller 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.
-	    *
-	    * Example: POSIXLY_CORRECT=y find -perm +a+x
-	    */
-	   non_posix_mode (perm_expr);
-
-	   /* support the previous behaviour. */
-	   mode_start = 1;
-	   kind = PERM_ANY;
-	   rate = 0.3;
-	 }
-       else
-	 {
-	   /* This is a POSIX-compatible usage */
-	   mode_start = 0;
-	   kind = PERM_EXACT;
-	   rate = 0.1;
-	 }
-       havekind = true;
-       break;
-
     case '/':			/* GNU extension */
-      non_posix_mode (perm_expr);
       mode_start = 1;
       kind = PERM_ANY;
       havekind = true;
@@ -2027,13 +1985,16 @@ parse_perm (const struct parser_table* entry, char **argv, int *arg_ptr)
       break;
     }
 
-  if (NULL == change)
-    {
-      change = mode_compile (perm_expr + mode_start);
-      if (NULL == change)
-	error (EXIT_FAILURE, 0, _("invalid mode %s"),
-	       quotearg_n_style (0, options.err_quoting_style, perm_expr));
-    }
+  change = mode_compile (perm_expr + mode_start);
+
+  /* Reject invalid modes, or modes of the form +NUMERICMODE.
+     The latter were formerly accepted as a GNU extension, but that
+     extension was incompatible with how GNU 'chmod' treats these modes now,
+     and it would be confusing if 'find' continued to support it.  */
+  if (NULL == change
+      || (perm_expr[0] == '+' && '0' <= perm_expr[1] && perm_expr[1] < '8'))
+    error (EXIT_FAILURE, 0, _("invalid mode %s"),
+	   quotearg_n_style (0, options.err_quoting_style, perm_expr));
   perm_val[0] = mode_adjust (0, false, 0, change, NULL);
   perm_val[1] = mode_adjust (0, true, 0, change, NULL);
   free (change);
-- 
1.7.2.5

