From 77fc5549115e40abb5c4bfa8cdc5a9deff483fb8 Mon Sep 17 00:00:00 2001 From: jay Date: Thu, 22 Nov 2007 09:16:34 +0000 Subject: [PATCH] POSIXLY_CORRECT should turn off warnings. When it is set, also diagnose some noncompliant arguments to -perm. Fixes Savannah bug #21039. --- ChangeLog | 29 ++++++++++ NEWS | 9 ++++ doc/find.texi | 24 +++++++-- find/defs.h | 6 +++ find/find.1 | 76 ++++++++++++++++++--------- find/find.c | 3 ++ find/parser.c | 73 +++++++++++++++---------- find/testsuite/Makefile.am | 1 + find/testsuite/find.gnu/posix-perminvalid.exp | 17 ++++++ find/util.c | 12 ++++- 10 files changed, 192 insertions(+), 58 deletions(-) create mode 100644 find/testsuite/find.gnu/posix-perminvalid.exp diff --git a/ChangeLog b/ChangeLog index 96b2a27..63fe8e8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,34 @@ 2007-11-22 James Youngman + POSIXLY_CORRECT turns off warnings. + * find/defs.h (struct options): Added member posixly_correct. + This is set when the POSIXLY_CORRECT environment variable is set. + * find/util.c (set_option_defaults): Set options.posixly_correct + if the POSIXLY_CORRECT environment variable is set. + (set_option_defaults): Turn off warnings when POSIXLY_CORRECT is + in force. + * find/find.1: Document this. + (Environment Variables): Likewise. + (Warning Messages): Likewise. + + Non-POSIX compliant arguments to -perm generate an error when + POSIXLY_CORRECT is set. + * find/parser.c (parse_table): Indicate which primaries are + defined by POSIX. + (non_posix_mode): New function; issues an error message when a + non-POSIX-compliant argument to -perm is used (and POSIXLY_CORRECT + is in force). + (parse_perm): Call non_posix_mode when a non-POSIX-compliant mode + argument is seen. + * find/testsuite/find.gnu/posix-perminvalid.exp: New file; tests + invalid arguments to -perm. + * find/testsuite/Makefile.am (EXTRA_DIST_EXP): Add + posix-perminvalid.exp. + * find/find.1: Document this. + * doc/find.texi (Mode Bits): Likewise + (Environment Variables): Likewise + + * xargs/xargs.1: Options should be bold, not italic; filenames should also be italic. OPTIONS should be a section, not a subsection. In the description of --max-lines, "max-args" was diff --git a/NEWS b/NEWS index 4a1d853..0f1ba0c 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,15 @@ GNU findutils NEWS - User visible changes. -*- outline -*- (allout) * Major changes in release 4.3.11-CVS +** Bug Fixes + +#21039: Setting the POSIXLY_CORRECT environment variable now turns off +warnings by default, because POSIX requires that only diagnostic +messages (and -ok prompts) are printed on STDERR, and diagnostic +messages must also result in a nonzero exit status. Some +non-compliant arguments to -perm (for example -perm +a+x) also result +in an error when POSIXLY_CORRECT is set. + ** Documentation Fixes #21270: Formatting fixes to the xargs.1 manual page, including making diff --git a/doc/find.texi b/doc/find.texi index c3525af..c54c49c 100644 --- a/doc/find.texi +++ b/doc/find.texi @@ -1164,7 +1164,12 @@ either a symbolic or numeric @var{mode} (@pxref{File Permissions}) 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. +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 POSIXLY_CORRECT environment +variable it set. Otherwise this is treated as if the initial +@samp{+} were a @samp{/}, for backward compatibility. A @var{pmode} that starts with @samp{-} matches if @emph{all} the file mode bits set in @var{mode} are set for the file; @@ -2991,9 +2996,11 @@ symbolic links are handled. If there is an error on the @code{find} command line, an error message is normally issued. However, there are some usages that are inadvisable but which @code{find} should still accept. Under these -circumstances, @code{find} may issue a warning message. By default, -warnings are enabled only if @code{find} is being run interactively -(specifically, if the standard input is a terminal). Warning messages +circumstances, @code{find} may issue a warning message. + +By default, warnings are enabled only if @code{find} is being run +interactively (specifically, if the standard input is a terminal) and +the POSIXLY_CORRECT environment variable is not set. Warning messages can be controlled explicitly by the use of options on the command line: @@ -3583,6 +3590,15 @@ Determines the block size used by @samp{-ls} and @samp{-fls}. If @var{POSIXLY_CORRECT} is set, blocks are units of 512 bytes. Otherwise they are units of 1024 bytes. +Setting this variable also turns off warning messages (that is, implies +@samp{-nowarn}) by default, because POSIX requires that apart from +the output for @samp{-ok}, all messages printed on stderr are +diagnositcs and must result in a non-zero exit status. + +Arguments to @samp{-perm} beginning with @samp{+} are treated +differently when POSIXLY_CORRECT is set. See +@ref{Mode Bits,-perm,File Mode Bits}. + @item TZ Affects the time zone used for some of the time-related format directives of @samp{-printf} and @samp{-fprintf}. diff --git a/find/defs.h b/find/defs.h index bf67687..d886fa2 100644 --- a/find/defs.h +++ b/find/defs.h @@ -558,6 +558,12 @@ struct options */ boolean warnings; + /* If true, avoid POSIX-incompatible behaviours + * (this functionality is currently incomplete + * and at the moment affects mainly warning messages). + */ + boolean posixly_correct; + struct timespec start_time; /* Time at start of execution. */ /* Seconds between 00:00 1/1/70 and either one day before now diff --git a/find/find.1 b/find/find.1 index c3dcee0..de3dda5 100644 --- a/find/find.1 +++ b/find/find.1 @@ -1230,16 +1230,17 @@ different output files. .SH "STANDARDS CONFORMANCE" -The following options are specified in the POSIX standard -(IEEE Std 1003.1, 2003 Edition): +For closest compliance to the POSIX standard, you should set the +POSIXLY_CORRECT environment variable. The following options are +specified in the POSIX standard (IEEE Std 1003.1, 2003 Edition): -.IP "\-H" +.IP \fB\-H\fR This option is supported. -.IP "\-L" +.IP \fB\-L\fR This option is supported. -.IP "\-name" +.IP \fB\-name\fR This option is supported, but POSIX conformance depends on the POSIX conformance of the system's .BR fnmatch (3) @@ -1248,36 +1249,41 @@ library function. As of findutils-4.2.2, shell metacharacters IEEE PASC interpretation 126 requires this. This is a change from previous versions of findutils. -.IP "\-type" +.IP \fB\-type\fR Supported. POSIX specifies `b', `c', `d', `l', `p', `f' and `s'. GNU find also supports `D', representing a Door, where the OS provides these. -.IP "\-ok" +.IP \fB\-ok\fR Supported. Interpretation of the response is not locale-dependent (see ENVIRONMENT VARIABLES). -.IP "\-newer" +.IP \fB\-newer\fR Supported. If the file specified is a symbolic link, it is always dereferenced. This is a change from previous behaviour, which used to take the relevant time from the symbolic link; see the HISTORY section below. +.IP \fB\-perm\fR +Supported. If the POSIXLY_CORRECT environment variable is not set, +some mode arguments (for example +a+x) which are not valid in POSIX +are supported for backward-compatibility. + .IP "Other predicates" The predicates -`\-atime', -`\-ctime', -`\-depth', -`\-group', -`\-links', -`\-mtime', -`\-nogroup', -`\-nouser', -`\-perm', -`\-print', -`\-prune', -`\-size', -`\-user' and -`\-xdev', +.BR \-atime , +.BR \-ctime , +.BR \-depth , +.BR \-group , +.BR \-links , +.BR \-mtime , +.BR \-nogroup , +.BR \-nouser , +.BR \-print , +.BR \-prune , +.BR \-size , +.BR \-user +and +.B \-xdev are all supported. .P @@ -1373,11 +1379,33 @@ Affects the directories which are searched to find the executables invoked by `\-exec', `\-execdir', `\-ok' and `\-okdir'. .IP POSIXLY_CORRECT -Determines the block size used by `\-ls' and `\-fls'. +Determines the block size used by +.B \-ls +and +.BR \-fls . If .B POSIXLY_CORRECT is set, blocks are units of 512 bytes. Otherwise -they are units of 1024 bytes. +they are units of 1024 bytes. +.IP +Setting this variable also turns off +warning messages (that is, implies +.BR \-nowarn ) +by default, because POSIX requires that apart from +the output for +.BR \-ok , +all messages printed on stderr are diagnositcs and must result in a +non-zero exit status. +.IP +When POSIXLY_CORRECT is not set, +.B \-perm ++zzz +is treated just like +.B \-perm +/zzz +if ++zzz is not a valid symbolic mode. When POSIXLY_CORRECT is set, such +constructs are treated as an error. .IP TZ Affects the time zone used for some of the time-related format diff --git a/find/find.c b/find/find.c index b1178fb..bc6f8e9 100644 --- a/find/find.c +++ b/find/find.c @@ -1088,6 +1088,9 @@ issue_loop_warning(const char *name, const char *pathname, int level) error(0, 0, _("Symbolic link %s is part of a loop in the directory hierarchy; we have already visited the directory to which it points."), safely_quote_err_filename(0, pathname)); + /* XXX: POSIX appears to require that the exit status be non-zero if a + * diagnostic is issued. + */ } else { diff --git a/find/parser.c b/find/parser.c index d46127f..18d26cc 100644 --- a/find/parser.c +++ b/find/parser.c @@ -239,23 +239,23 @@ static struct parser_table const parse_entry_newerXY = static struct parser_table const parse_table[] = { - PARSE_PUNCTUATION("!", negate), + PARSE_PUNCTUATION("!", negate), /* POSIX */ PARSE_PUNCTUATION("not", negate), /* GNU */ - PARSE_PUNCTUATION("(", openparen), - PARSE_PUNCTUATION(")", closeparen), + PARSE_PUNCTUATION("(", openparen), /* POSIX */ + PARSE_PUNCTUATION(")", closeparen), /* POSIX */ PARSE_PUNCTUATION(",", comma), /* GNU */ - PARSE_PUNCTUATION("a", and), + PARSE_PUNCTUATION("a", and), /* POSIX */ PARSE_TEST ("amin", amin), /* GNU */ PARSE_PUNCTUATION("and", and), /* GNU */ PARSE_TEST ("anewer", anewer), /* GNU */ - {ARG_TEST, "atime", parse_time, pred_atime}, + {ARG_TEST, "atime", parse_time, pred_atime}, /* POSIX */ PARSE_TEST ("cmin", cmin), /* GNU */ PARSE_TEST ("cnewer", cnewer), /* GNU */ - {ARG_TEST, "ctime", parse_time, pred_ctime}, + {ARG_TEST, "ctime", parse_time, pred_ctime}, /* POSIX */ PARSE_POSOPT ("daystart", daystart), /* GNU */ PARSE_ACTION ("delete", delete), /* GNU, Mac OS, FreeBSD */ PARSE_OPTION ("d", d), /* Mac OS X, FreeBSD, NetBSD, OpenBSD, but deprecated in favour of -depth */ - PARSE_OPTION ("depth", depth), + PARSE_OPTION ("depth", depth), /* POSIX */ PARSE_TEST ("empty", empty), /* GNU */ {ARG_ACTION, "exec", parse_exec, pred_exec}, /* POSIX */ {ARG_TEST, "executable", parse_accesscheck, pred_executable}, /* GNU, 4.3.0+ */ @@ -267,7 +267,7 @@ static struct parser_table const parse_table[] = {ARG_ACTION, "fprintf", parse_fprintf, pred_fprintf}, /* GNU */ PARSE_TEST ("fstype", fstype), /* GNU, Unix */ PARSE_TEST ("gid", gid), /* GNU */ - PARSE_TEST ("group", group), + PARSE_TEST ("group", group), /* POSIX */ PARSE_OPTION ("ignore_readdir_race", ignore_race), /* GNU */ PARSE_TEST ("ilname", ilname), /* GNU */ PARSE_TEST ("iname", iname), /* GNU */ @@ -275,35 +275,35 @@ static struct parser_table const parse_table[] = PARSE_TEST ("ipath", ipath), /* GNU, deprecated in favour of iwholename */ PARSE_TEST_NP ("iregex", iregex), /* GNU */ PARSE_TEST_NP ("iwholename", iwholename), /* GNU */ - PARSE_TEST ("links", links), + PARSE_TEST ("links", links), /* POSIX */ PARSE_TEST ("lname", lname), /* GNU */ PARSE_ACTION ("ls", ls), /* GNU, Unix */ PARSE_OPTION ("maxdepth", maxdepth), /* GNU */ PARSE_OPTION ("mindepth", mindepth), /* GNU */ PARSE_TEST ("mmin", mmin), /* GNU */ PARSE_OPTION ("mount", xdev), /* Unix */ - {ARG_TEST, "mtime", parse_time, pred_mtime}, + {ARG_TEST, "mtime", parse_time, pred_mtime}, /* POSIX */ PARSE_TEST ("name", name), #ifdef UNIMPLEMENTED_UNIX PARSE(ARG_UNIMPLEMENTED, "ncpio", ncpio), /* Unix */ #endif - PARSE_TEST ("newer", newer), - {ARG_TEST, "atime", parse_time, pred_atime}, + PARSE_TEST ("newer", newer), /* POSIX */ + {ARG_TEST, "atime", parse_time, pred_atime}, /* POSIX */ PARSE_OPTION ("noleaf", noleaf), /* GNU */ - PARSE_TEST ("nogroup", nogroup), - PARSE_TEST ("nouser", nouser), + PARSE_TEST ("nogroup", nogroup), /* POSIX */ + PARSE_TEST ("nouser", nouser), /* POSIX */ PARSE_OPTION ("noignore_readdir_race", noignore_race), /* GNU */ PARSE_POSOPT ("nowarn", nowarn), /* GNU */ - PARSE_PUNCTUATION("o", or), + PARSE_PUNCTUATION("o", or), /* POSIX */ PARSE_PUNCTUATION("or", or), /* GNU */ - PARSE_ACTION ("ok", ok), + PARSE_ACTION ("ok", ok), /* POSIX */ PARSE_ACTION ("okdir", okdir), /* GNU (-execdir is BSD) */ PARSE_TEST ("path", path), /* GNU, HP-UX, RMS prefers wholename, but anyway soon POSIX */ - PARSE_TEST ("perm", perm), - PARSE_ACTION ("print", print), + PARSE_TEST ("perm", perm), /* POSIX */ + PARSE_ACTION ("print", print), /* POSIX */ PARSE_ACTION ("print0", print0), /* GNU */ {ARG_ACTION, "printf", parse_printf, NULL}, /* GNU */ - PARSE_ACTION ("prune", prune), + PARSE_ACTION ("prune", prune), /* POSIX */ PARSE_ACTION ("quit", quit), /* GNU */ {ARG_TEST, "readable", parse_accesscheck, pred_readable}, /* GNU, 4.3.0+ */ PARSE_TEST ("regex", regex), /* GNU */ @@ -312,15 +312,15 @@ static struct parser_table const parse_table[] = #if 0 PARSE_OPTION ("show-control-chars", show_control_chars), /* GNU, 4.3.0+ */ #endif - PARSE_TEST ("size", size), - PARSE_TEST ("type", type), + PARSE_TEST ("size", size), /* POSIX */ + PARSE_TEST ("type", type), /* POSIX */ PARSE_TEST ("uid", uid), /* GNU */ PARSE_TEST ("used", used), /* GNU */ - PARSE_TEST ("user", user), + PARSE_TEST ("user", user), /* POSIX */ PARSE_OPTION ("warn", warn), /* GNU */ PARSE_TEST_NP ("wholename", wholename), /* GNU, replaced -path, but anyway -path will soon be in POSIX */ {ARG_TEST, "writable", parse_accesscheck, pred_writable}, /* GNU, 4.3.0+ */ - PARSE_OPTION ("xdev", xdev), + PARSE_OPTION ("xdev", xdev), /* POSIX */ PARSE_TEST ("xtype", xtype), /* GNU */ #ifdef UNIMPLEMENTED_UNIX /* It's pretty ugly for find to know about archive formats. @@ -1714,6 +1714,17 @@ parse_wholename (const struct parser_table* entry, char **argv, int *arg_ptr) return parse_path (entry, argv, arg_ptr); } +static void +non_posix_mode(const char *mode) +{ + if (options.posixly_correct) + { + error (1, 0, _("Mode %s is not valid when POSIXLY_CORRECT is on."), + quotearg_n_style(0, options.err_quoting_style, mode)); + } +} + + static boolean parse_perm (const struct parser_table* entry, char **argv, int *arg_ptr) { @@ -1748,7 +1759,12 @@ parse_perm (const struct parser_table* entry, char **argv, int *arg_ptr) * 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; @@ -1764,11 +1780,12 @@ parse_perm (const struct parser_table* entry, char **argv, int *arg_ptr) break; case '/': /* GNU extension */ - mode_start = 1; - kind = PERM_ANY; - havekind = true; - rate = 0.3; - break; + non_posix_mode(perm_expr); + mode_start = 1; + kind = PERM_ANY; + havekind = true; + rate = 0.3; + break; default: /* For example, '-perm 0644', which is valid and matches diff --git a/find/testsuite/Makefile.am b/find/testsuite/Makefile.am index c1033d4..089820e 100644 --- a/find/testsuite/Makefile.am +++ b/find/testsuite/Makefile.am @@ -145,6 +145,7 @@ find.gnu/perm-slash.exp \ find.gnu/posix-dflt.exp \ find.gnu/posix-h.exp \ find.gnu/posix-l.exp \ +find.gnu/posix-perminvalid.exp \ find.gnu/printfHdfl.exp \ find.gnu/printf.exp \ find.gnu/printf.exp \ diff --git a/find/testsuite/find.gnu/posix-perminvalid.exp b/find/testsuite/find.gnu/posix-perminvalid.exp new file mode 100644 index 0000000..7463a4a --- /dev/null +++ b/find/testsuite/find.gnu/posix-perminvalid.exp @@ -0,0 +1,17 @@ +# tests for non-POSIX-compliant argument to -perm +# Remember any previous value of POSIXLY_CORRECT (if there was one) +if [info exists env(POSIXLY_CORRECT)] { + set oldval env(POSIXLY_CORRECT) +} + +# Set POSIXLY_CORRECT and perform the test +set env(POSIXLY_CORRECT) 1 +find_start f {. -perm +a+x} + +# Set POSIXLY_CORRECT to its previous value +if [info exists oldval] { + set env(POSIXLY_CORRECT) $oldval +} else { + unset env(POSIXLY_CORRECT) +} + diff --git a/find/util.c b/find/util.c index 8cd7ef9..388f9fc 100644 --- a/find/util.c +++ b/find/util.c @@ -888,6 +888,11 @@ now(void) void set_option_defaults(struct options *p) { + if (getenv("POSIXLY_CORRECT")) + p->posixly_correct = true; + else + p->posixly_correct = false; + /* We call check_nofollow() before setlocale() because the numbers * for which we check (in the results of uname) definitiely have "." * as the decimal point indicator even under locales for which that @@ -912,7 +917,10 @@ set_option_defaults(struct options *p) p->warnings = false; p->literal_control_chars = false; /* may change */ } - + if (p->posixly_correct) + { + p->warnings = false; + } p->do_dir_first = true; p->maxdepth = p->mindepth = -1; @@ -922,7 +930,7 @@ set_option_defaults(struct options *p) p->stay_on_filesystem = false; p->ignore_readdir_race = false; - if (getenv("POSIXLY_CORRECT")) + if (p->posixly_correct) p->output_block_size = 512; else p->output_block_size = 1024; -- 2.11.4.GIT