Imported Upstream version 4.5.14
[platform/upstream/findutils.git] / find / parser.c
1 /* parser.c -- convert the command line args into an expression tree.
2    Copyright (C) 1990, 1991, 1992, 1993, 1994, 2000, 2001, 2003, 2004,
3    2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
4    Inc.
5
6    This program is free software: you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation, either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 /* config.h must always come first. */
21 #include <config.h>
22
23 /* system headers. */
24 #include <assert.h>
25 #include <ctype.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <grp.h>
29 #include <math.h>
30 #include <pwd.h>
31 #include <regex.h>
32 #include <sys/stat.h>
33 #include <unistd.h>
34
35
36 /* gnulib headers. */
37 #include "error.h"
38 #include "fnmatch.h"
39 #include "fts_.h"
40 #include "gettext.h"
41 #include "modechange.h"
42 #include "mountlist.h"
43 #include "parse-datetime.h"
44 #include "print.h"
45 #include "quotearg.h"
46 #include "regextype.h"
47 #include "safe-atoi.h"
48 #include "selinux-at.h"
49 #include "splitstring.h"
50 #include "stat-time.h"
51 #include "xalloc.h"
52 #include "xstrtod.h"
53 #include "xstrtol.h"
54
55 /* find headers. */
56 #include "buildcmd.h"
57 #include "defs.h"
58 #include "fdleak.h"
59 #include "findutils-version.h"
60
61
62
63
64 #if ENABLE_NLS
65 # include <libintl.h>
66 # define _(Text) gettext (Text)
67 #else
68 # define _(Text) Text
69 #endif
70 #ifdef gettext_noop
71 # define N_(String) gettext_noop (String)
72 #else
73 /* See locate.c for explanation as to why not use (String) */
74 # define N_(String) String
75 #endif
76
77 #ifndef HAVE_ENDGRENT
78 #define endgrent ()
79 #endif
80 #ifndef HAVE_ENDPWENT
81 #define endpwent ()
82 #endif
83
84 static bool parse_accesscheck   (const struct parser_table*, char *argv[], int *arg_ptr);
85 static bool parse_amin          (const struct parser_table*, char *argv[], int *arg_ptr);
86 static bool parse_and           (const struct parser_table*, char *argv[], int *arg_ptr);
87 static bool parse_anewer        (const struct parser_table*, char *argv[], int *arg_ptr);
88 static bool parse_cmin          (const struct parser_table*, char *argv[], int *arg_ptr);
89 static bool parse_cnewer        (const struct parser_table*, char *argv[], int *arg_ptr);
90 static bool parse_comma         (const struct parser_table*, char *argv[], int *arg_ptr);
91 static bool parse_daystart      (const struct parser_table*, char *argv[], int *arg_ptr);
92 static bool parse_delete        (const struct parser_table*, char *argv[], int *arg_ptr);
93 static bool parse_d             (const struct parser_table*, char *argv[], int *arg_ptr);
94 static bool parse_depth         (const struct parser_table*, char *argv[], int *arg_ptr);
95 static bool parse_empty         (const struct parser_table*, char *argv[], int *arg_ptr);
96 static bool parse_exec          (const struct parser_table*, char *argv[], int *arg_ptr);
97 static bool parse_execdir       (const struct parser_table*, char *argv[], int *arg_ptr);
98 static bool parse_false         (const struct parser_table*, char *argv[], int *arg_ptr);
99 static bool parse_fls           (const struct parser_table*, char *argv[], int *arg_ptr);
100 static bool parse_fprintf       (const struct parser_table*, char *argv[], int *arg_ptr);
101 static bool parse_follow        (const struct parser_table*, char *argv[], int *arg_ptr);
102 static bool parse_fprint        (const struct parser_table*, char *argv[], int *arg_ptr);
103 static bool parse_fprint0       (const struct parser_table*, char *argv[], int *arg_ptr);
104 static bool parse_fstype        (const struct parser_table*, char *argv[], int *arg_ptr);
105 static bool parse_gid           (const struct parser_table*, char *argv[], int *arg_ptr);
106 static bool parse_group         (const struct parser_table*, char *argv[], int *arg_ptr);
107 static bool parse_help          (const struct parser_table*, char *argv[], int *arg_ptr);
108 static bool parse_ilname        (const struct parser_table*, char *argv[], int *arg_ptr);
109 static bool parse_iname         (const struct parser_table*, char *argv[], int *arg_ptr);
110 static bool parse_inum          (const struct parser_table*, char *argv[], int *arg_ptr);
111 static bool parse_ipath         (const struct parser_table*, char *argv[], int *arg_ptr);
112 static bool parse_iregex        (const struct parser_table*, char *argv[], int *arg_ptr);
113 static bool parse_iwholename    (const struct parser_table*, char *argv[], int *arg_ptr);
114 static bool parse_links         (const struct parser_table*, char *argv[], int *arg_ptr);
115 static bool parse_lname         (const struct parser_table*, char *argv[], int *arg_ptr);
116 static bool parse_ls            (const struct parser_table*, char *argv[], int *arg_ptr);
117 static bool parse_maxdepth      (const struct parser_table*, char *argv[], int *arg_ptr);
118 static bool parse_mindepth      (const struct parser_table*, char *argv[], int *arg_ptr);
119 static bool parse_mmin          (const struct parser_table*, char *argv[], int *arg_ptr);
120 static bool parse_name          (const struct parser_table*, char *argv[], int *arg_ptr);
121 static bool parse_negate        (const struct parser_table*, char *argv[], int *arg_ptr);
122 static bool parse_newer         (const struct parser_table*, char *argv[], int *arg_ptr);
123 static bool parse_newerXY       (const struct parser_table*, char *argv[], int *arg_ptr);
124 static bool parse_noleaf        (const struct parser_table*, char *argv[], int *arg_ptr);
125 static bool parse_nogroup       (const struct parser_table*, char *argv[], int *arg_ptr);
126 static bool parse_nouser        (const struct parser_table*, char *argv[], int *arg_ptr);
127 static bool parse_nowarn        (const struct parser_table*, char *argv[], int *arg_ptr);
128 static bool parse_ok            (const struct parser_table*, char *argv[], int *arg_ptr);
129 static bool parse_okdir         (const struct parser_table*, char *argv[], int *arg_ptr);
130 static bool parse_or            (const struct parser_table*, char *argv[], int *arg_ptr);
131 static bool parse_path          (const struct parser_table*, char *argv[], int *arg_ptr);
132 static bool parse_perm          (const struct parser_table*, char *argv[], int *arg_ptr);
133 static bool parse_print0        (const struct parser_table*, char *argv[], int *arg_ptr);
134 static bool parse_printf        (const struct parser_table*, char *argv[], int *arg_ptr);
135 static bool parse_prune         (const struct parser_table*, char *argv[], int *arg_ptr);
136 static bool parse_regex         (const struct parser_table*, char *argv[], int *arg_ptr);
137 static bool parse_regextype     (const struct parser_table*, char *argv[], int *arg_ptr);
138 static bool parse_samefile      (const struct parser_table*, char *argv[], int *arg_ptr);
139 static bool parse_size          (const struct parser_table*, char *argv[], int *arg_ptr);
140 static bool parse_time          (const struct parser_table*, char *argv[], int *arg_ptr);
141 static bool parse_true          (const struct parser_table*, char *argv[], int *arg_ptr);
142 static bool parse_type          (const struct parser_table*, char *argv[], int *arg_ptr);
143 static bool parse_uid           (const struct parser_table*, char *argv[], int *arg_ptr);
144 static bool parse_used          (const struct parser_table*, char *argv[], int *arg_ptr);
145 static bool parse_user          (const struct parser_table*, char *argv[], int *arg_ptr);
146 static bool parse_version       (const struct parser_table*, char *argv[], int *arg_ptr);
147 static bool parse_wholename     (const struct parser_table*, char *argv[], int *arg_ptr);
148 static bool parse_xdev          (const struct parser_table*, char *argv[], int *arg_ptr);
149 static bool parse_ignore_race   (const struct parser_table*, char *argv[], int *arg_ptr);
150 static bool parse_noignore_race (const struct parser_table*, char *argv[], int *arg_ptr);
151 static bool parse_warn          (const struct parser_table*, char *argv[], int *arg_ptr);
152 static bool parse_xtype         (const struct parser_table*, char *argv[], int *arg_ptr);
153 static bool parse_quit          (const struct parser_table*, char *argv[], int *arg_ptr);
154 static bool parse_context       (const struct parser_table*, char *argv[], int *arg_ptr);
155 #if 0
156 static bool parse_show_control_chars (const struct parser_table*, char *argv[], int *arg_ptr);
157 #endif
158
159
160
161 static bool insert_type (char **argv, int *arg_ptr,
162                          const struct parser_table *entry,
163                          PRED_FUNC which_pred);
164 static bool insert_regex (char *argv[], int *arg_ptr,
165                           const struct parser_table *entry,
166                           int regex_options);
167 static bool insert_exec_ok (const char *action,
168                             const struct parser_table *entry,
169                             char *argv[],
170                             int *arg_ptr);
171 static bool get_comp_type (const char **str,
172                            enum comparison_type *comp_type);
173 static bool get_relative_timestamp (const char *str,
174                                     struct time_val *tval,
175                                     struct timespec origin,
176                                     double sec_per_unit,
177                                     const char *overflowmessage);
178 static bool get_num (const char *str,
179                      uintmax_t *num,
180                      enum comparison_type *comp_type);
181 static struct predicate* insert_num (char *argv[], int *arg_ptr,
182                                      const struct parser_table *entry);
183 static void open_output_file (const char *path, struct format_val *p);
184 static void open_stdout (struct format_val *p);
185 static bool stream_is_tty(FILE *fp);
186 static bool parse_noop (const struct parser_table* entry,
187                         char **argv, int *arg_ptr);
188
189 #define PASTE(x,y) x##y
190
191
192 #define PARSE_OPTION(what,suffix) \
193   { (ARG_OPTION), (what), PASTE(parse_,suffix), NULL }
194
195 #define PARSE_POSOPT(what,suffix) \
196   { (ARG_POSITIONAL_OPTION), (what), PASTE(parse_,suffix), NULL }
197
198 #define PARSE_TEST(what,suffix) \
199   { (ARG_TEST), (what), PASTE(parse_,suffix), PASTE(pred_,suffix) }
200
201 #define PARSE_TEST_NP(what,suffix) \
202   { (ARG_TEST), (what), PASTE(parse_,suffix), NULL }
203
204 #define PARSE_ACTION(what,suffix) \
205   { (ARG_ACTION), (what), PASTE(parse_,suffix), PASTE(pred_,suffix) }
206
207 #define PARSE_PUNCTUATION(what,suffix) \
208   { (ARG_PUNCTUATION), (what), PASTE(parse_,suffix), PASTE(pred_,suffix) }
209
210
211 /* Predicates we cannot handle in the usual way.  If you add an entry
212  * to this table, double-check the switch statement in
213  * pred_sanity_check() to make sure that the new case is being
214  * correctly handled.
215  */
216 static struct parser_table const parse_entry_newerXY =
217   {
218     ARG_SPECIAL_PARSE, "newerXY",            parse_newerXY, pred_newerXY /* BSD  */
219   };
220
221 /* GNU find predicates that are not mentioned in POSIX.2 are marked `GNU'.
222    If they are in some Unix versions of find, they are marked `Unix'. */
223
224 static struct parser_table const parse_table[] =
225 {
226   PARSE_PUNCTUATION("!",                     negate), /* POSIX */
227   PARSE_PUNCTUATION("not",                   negate),        /* GNU */
228   PARSE_PUNCTUATION("(",                     openparen), /* POSIX */
229   PARSE_PUNCTUATION(")",                     closeparen), /* POSIX */
230   PARSE_PUNCTUATION(",",                     comma),         /* GNU */
231   PARSE_PUNCTUATION("a",                     and), /* POSIX */
232   PARSE_TEST       ("amin",                  amin),          /* GNU */
233   PARSE_PUNCTUATION("and",                   and),              /* GNU */
234   PARSE_TEST       ("anewer",                anewer),        /* GNU */
235   {ARG_TEST,       "atime",                  parse_time, pred_atime}, /* POSIX */
236   PARSE_TEST       ("cmin",                  cmin),          /* GNU */
237   PARSE_TEST       ("cnewer",                cnewer),        /* GNU */
238   {ARG_TEST,       "ctime",                  parse_time, pred_ctime}, /* POSIX */
239   PARSE_TEST       ("context",               context),      /* GNU */
240   PARSE_POSOPT     ("daystart",              daystart),      /* GNU */
241   PARSE_ACTION     ("delete",                delete), /* GNU, Mac OS, FreeBSD */
242   PARSE_OPTION     ("d",                     d), /* Mac OS X, FreeBSD, NetBSD, OpenBSD, but deprecated  in favour of -depth */
243   PARSE_OPTION     ("depth",                 depth), /* POSIX */
244   PARSE_TEST       ("empty",                 empty),         /* GNU */
245   {ARG_ACTION,      "exec",    parse_exec, pred_exec}, /* POSIX */
246   {ARG_TEST,        "executable",            parse_accesscheck, pred_executable}, /* GNU, 4.3.0+ */
247   PARSE_ACTION     ("execdir",               execdir), /* *BSD, GNU */
248   PARSE_ACTION     ("fls",                   fls),           /* GNU */
249   PARSE_POSOPT     ("follow",                follow),  /* GNU, Unix */
250   PARSE_ACTION     ("fprint",                fprint),        /* GNU */
251   PARSE_ACTION     ("fprint0",               fprint0),       /* GNU */
252   {ARG_ACTION,      "fprintf", parse_fprintf, pred_fprintf}, /* GNU */
253   PARSE_TEST       ("fstype",                fstype),  /* GNU, Unix */
254   PARSE_TEST       ("gid",                   gid),           /* GNU */
255   PARSE_TEST       ("group",                 group), /* POSIX */
256   PARSE_OPTION     ("ignore_readdir_race",   ignore_race),   /* GNU */
257   PARSE_TEST       ("ilname",                ilname),        /* GNU */
258   PARSE_TEST       ("iname",                 iname),         /* GNU */
259   PARSE_TEST       ("inum",                  inum),    /* GNU, Unix */
260   PARSE_TEST       ("ipath",                 ipath), /* GNU, deprecated in favour of iwholename */
261   PARSE_TEST_NP    ("iregex",                iregex),        /* GNU */
262   PARSE_TEST_NP    ("iwholename",            iwholename),    /* GNU */
263   PARSE_TEST       ("links",                 links), /* POSIX */
264   PARSE_TEST       ("lname",                 lname),         /* GNU */
265   PARSE_ACTION     ("ls",                    ls),      /* GNU, Unix */
266   PARSE_OPTION     ("maxdepth",              maxdepth),      /* GNU */
267   PARSE_OPTION     ("mindepth",              mindepth),      /* GNU */
268   PARSE_TEST       ("mmin",                  mmin),          /* GNU */
269   PARSE_OPTION     ("mount",                 xdev),         /* Unix */
270   {ARG_TEST,       "mtime",                  parse_time, pred_mtime}, /* POSIX */
271   PARSE_TEST       ("name",                  name),
272 #ifdef UNIMPLEMENTED_UNIX
273   PARSE(ARG_UNIMPLEMENTED, "ncpio",          ncpio),        /* Unix */
274 #endif
275   PARSE_TEST       ("newer",                 newer), /* POSIX */
276   {ARG_TEST,       "atime",                  parse_time, pred_atime}, /* POSIX */
277   PARSE_OPTION     ("noleaf",                noleaf),        /* GNU */
278   PARSE_TEST       ("nogroup",               nogroup), /* POSIX */
279   PARSE_TEST       ("nouser",                nouser), /* POSIX */
280   PARSE_OPTION     ("noignore_readdir_race", noignore_race), /* GNU */
281   PARSE_POSOPT     ("nowarn",                nowarn),        /* GNU */
282   PARSE_PUNCTUATION("o",                     or), /* POSIX */
283   PARSE_PUNCTUATION("or",                    or),            /* GNU */
284   PARSE_ACTION     ("ok",                    ok), /* POSIX */
285   PARSE_ACTION     ("okdir",                 okdir), /* GNU (-execdir is BSD) */
286   PARSE_TEST       ("path",                  path), /* GNU, HP-UX, RMS prefers wholename, but anyway soon POSIX */
287   PARSE_TEST       ("perm",                  perm), /* POSIX */
288   PARSE_ACTION     ("print",                 print), /* POSIX */
289   PARSE_ACTION     ("print0",                print0),        /* GNU */
290   {ARG_ACTION,      "printf",   parse_printf, NULL},         /* GNU */
291   PARSE_ACTION     ("prune",                 prune), /* POSIX */
292   PARSE_ACTION     ("quit",                  quit),          /* GNU */
293   {ARG_TEST,       "readable",            parse_accesscheck, pred_readable}, /* GNU, 4.3.0+ */
294   PARSE_TEST       ("regex",                 regex),         /* GNU */
295   PARSE_POSOPT     ("regextype",             regextype),     /* GNU */
296   PARSE_TEST       ("samefile",              samefile),      /* GNU */
297 #if 0
298   PARSE_OPTION     ("show-control-chars",    show_control_chars), /* GNU, 4.3.0+ */
299 #endif
300   PARSE_TEST       ("size",                  size), /* POSIX */
301   PARSE_TEST       ("type",                  type), /* POSIX */
302   PARSE_TEST       ("uid",                   uid),           /* GNU */
303   PARSE_TEST       ("used",                  used),          /* GNU */
304   PARSE_TEST       ("user",                  user), /* POSIX */
305   PARSE_OPTION     ("warn",                  warn),          /* GNU */
306   PARSE_TEST_NP    ("wholename",             wholename), /* GNU, replaced -path, but anyway -path will soon be in POSIX */
307   {ARG_TEST,       "writable",               parse_accesscheck, pred_writable}, /* GNU, 4.3.0+ */
308   PARSE_OPTION     ("xdev",                  xdev), /* POSIX */
309   PARSE_TEST       ("xtype",                 xtype),         /* GNU */
310 #ifdef UNIMPLEMENTED_UNIX
311   /* It's pretty ugly for find to know about archive formats.
312      Plus what it could do with cpio archives is very limited.
313      Better to leave it out.  */
314   PARSE(ARG_UNIMPLEMENTED,      "cpio",                  cpio), /* Unix */
315 #endif
316   /* gnulib's stdbool.h might have made true and false into macros,
317    * so we can't leave named 'true' and 'false' tokens, so we have
318    * to expeant the relevant entries longhand.
319    */
320   {ARG_TEST, "false",                 parse_false,   pred_false}, /* GNU */
321   {ARG_TEST, "true",                  parse_true,    pred_true }, /* GNU */
322   {ARG_NOOP, "noop",                  NULL,          pred_true }, /* GNU, internal use only */
323
324   /* Various other cases that don't fit neatly into our macro scheme. */
325   {ARG_TEST, "help",                  parse_help,    NULL},       /* GNU */
326   {ARG_TEST, "-help",                 parse_help,    NULL},       /* GNU */
327   {ARG_TEST, "version",               parse_version, NULL},       /* GNU */
328   {ARG_TEST, "-version",              parse_version, NULL},       /* GNU */
329   {0, 0, 0, 0}
330 };
331
332
333 static const char *first_nonoption_arg = NULL;
334 static const struct parser_table *noop = NULL;
335
336 static int
337 fallback_getfilecon (int fd, const char *name, security_context_t *p,
338                      int prev_rv)
339 {
340   /* Our original getfilecon () call failed.  Perhaps we can't follow a
341    * symbolic link.  If that might be the problem, lgetfilecon () the link.
342    * Otherwise, admit defeat. */
343   switch (errno)
344     {
345       case ENOENT:
346       case ENOTDIR:
347 #ifdef DEBUG_STAT
348         fprintf (stderr, "fallback_getfilecon(): getfilecon(%s) failed; falling "
349                         "back on lgetfilecon()\n", name);
350 #endif
351         return lgetfileconat (fd, name, p);
352
353       case EACCES:
354       case EIO:
355       case ELOOP:
356       case ENAMETOOLONG:
357 #ifdef EOVERFLOW
358       case EOVERFLOW:        /* EOVERFLOW is not #defined on UNICOS. */
359 #endif
360       default:
361         return prev_rv;
362     }
363 }
364
365 /* optionh_getfilecon () implements the getfilecon operation when the
366  * -H option is in effect.
367  *
368  * If the item to be examined is a command-line argument, we follow
369  * symbolic links.  If the getfilecon () call fails on the command-line
370  * item, we fall back on the properties of the symbolic link.
371  *
372  * If the item to be examined is not a command-line argument, we
373  * examine the link itself. */
374 static int
375 optionh_getfilecon (int fd, const char *name, security_context_t *p)
376 {
377   int rv;
378   if (0 == state.curdepth)
379     {
380       /* This file is from the command line; dereference the link (if it is
381          a link). */
382       rv = getfileconat (fd, name, p);
383       if (0 == rv)
384         return 0;               /* success */
385       else
386         return fallback_getfilecon (fd, name, p, rv);
387     }
388   else
389     {
390       /* Not a file on the command line; do not dereference the link. */
391       return lgetfileconat (fd, name, p);
392     }
393 }
394
395 /* optionl_getfilecon () implements the getfilecon operation when the
396  * -L option is in effect.  That option makes us examine the thing the
397  * symbolic link points to, not the symbolic link itself. */
398 static int
399 optionl_getfilecon (int fd, const char *name, security_context_t *p)
400 {
401   int rv = getfileconat (fd, name, p);
402   if (0 == rv)
403     return 0;                  /* normal case. */
404   else
405     return fallback_getfilecon (fd, name, p, rv);
406 }
407
408 /* optionp_getfilecon () implements the stat operation when the -P
409  * option is in effect (this is also the default).  That option makes
410  * us examine the symbolic link itself, not the thing it points to. */
411 static int
412 optionp_getfilecon (int fd, const char *name, security_context_t *p)
413 {
414   return lgetfileconat (fd, name, p);
415 }
416
417 void
418 check_option_combinations (const struct predicate *p)
419 {
420   enum { seen_delete=1u, seen_prune=2u };
421   unsigned int predicates = 0u;
422
423   while (p)
424     {
425       if (p->pred_func == pred_delete)
426         predicates |= seen_delete;
427       else if (p->pred_func == pred_prune)
428         predicates |= seen_prune;
429       p = p->pred_next;
430     }
431
432   if ((predicates & seen_prune) && (predicates & seen_delete))
433     {
434       /* The user specified both -delete and -prune.  One might test
435        * this by first doing
436        *    find dirs   .... -prune ..... -print
437        * to fnd out what's going to get deleted, and then switch to
438        *    find dirs   .... -prune ..... -delete
439        * once we are happy.  Unfortunately, the -delete action also
440        * implicitly turns on -depth, which will affect the behaviour
441        * of -prune (in fact, it makes it a no-op).  In this case we
442        * would like to prevent unfortunate accidents, so we require
443        * the user to have explicitly used -depth.
444        *
445        * We only get away with this because the -delete predicate is not
446        * in POSIX.   If it was, we couldn't issue a fatal error here.
447        */
448       if (!options.explicit_depth)
449         {
450           /* This fixes Savannah bug #20865. */
451           error (EXIT_FAILURE, 0,
452                  _("The -delete action automatically turns on -depth, "
453                    "but -prune does nothing when -depth is in effect.  "
454                    "If you want to carry on anyway, just explicitly use "
455                    "the -depth option."));
456         }
457     }
458 }
459
460
461 static const struct parser_table*
462 get_noop (void)
463 {
464   int i;
465   if (NULL == noop)
466     {
467       for (i = 0; parse_table[i].parser_name != 0; i++)
468         {
469           if (ARG_NOOP ==parse_table[i].type)
470             {
471               noop = &(parse_table[i]);
472               break;
473             }
474         }
475     }
476   return noop;
477 }
478
479 static int
480 get_stat_Ytime (const struct stat *p,
481                 char what,
482                 struct timespec *ret)
483 {
484   switch (what)
485     {
486     case 'a':
487       *ret = get_stat_atime (p);
488       return 1;
489     case 'B':
490       *ret = get_stat_birthtime (p);
491       return (ret->tv_nsec >= 0);
492     case 'c':
493       *ret = get_stat_ctime (p);
494       return 1;
495     case 'm':
496       *ret = get_stat_mtime (p);
497       return 1;
498     default:
499       assert (0);
500       abort ();
501     }
502 }
503
504 void
505 set_follow_state (enum SymlinkOption opt)
506 {
507   if (options.debug_options & DebugStat)
508     {
509       /* For DebugStat, the choice is made at runtime within debug_stat()
510        * by checking the contents of the symlink_handling variable.
511        */
512       options.xstat = debug_stat;
513     }
514   else
515     {
516       switch (opt)
517         {
518         case SYMLINK_ALWAYS_DEREF:  /* -L */
519           options.xstat = optionl_stat;
520           options.x_getfilecon = optionl_getfilecon;
521           options.no_leaf_check = true;
522           break;
523
524         case SYMLINK_NEVER_DEREF:       /* -P (default) */
525           options.xstat = optionp_stat;
526           options.x_getfilecon = optionp_getfilecon;
527           /* Can't turn no_leaf_check off because the user might have specified
528            * -noleaf anyway
529            */
530           break;
531
532         case SYMLINK_DEREF_ARGSONLY: /* -H */
533           options.xstat = optionh_stat;
534           options.x_getfilecon = optionh_getfilecon;
535           options.no_leaf_check = true;
536         }
537     }
538   options.symlink_handling = opt;
539 }
540
541
542 void
543 parse_begin_user_args (char **args, int argno,
544                        const struct predicate *last,
545                        const struct predicate *predicates)
546 {
547   (void) args;
548   (void) argno;
549   (void) last;
550   (void) predicates;
551   first_nonoption_arg = NULL;
552 }
553
554 void
555 parse_end_user_args (char **args, int argno,
556                      const struct predicate *last,
557                      const struct predicate *predicates)
558 {
559   /* does nothing */
560   (void) args;
561   (void) argno;
562   (void) last;
563   (void) predicates;
564 }
565
566
567 /* Check that it is legal to fid the given primary in its
568  * position and return it.
569  */
570 static const struct parser_table*
571 found_parser (const char *original_arg, const struct parser_table *entry)
572 {
573   /* If this is an option, but we have already had a
574    * non-option argument, the user may be under the
575    * impression that the behaviour of the option
576    * argument is conditional on some preceding
577    * tests.  This might typically be the case with,
578    * for example, -maxdepth.
579    *
580    * The options -daystart and -follow are exempt
581    * from this treatment, since their positioning
582    * in the command line does have an effect on
583    * subsequent tests but not previous ones.  That
584    * might be intentional on the part of the user.
585    */
586   if (entry->type != ARG_POSITIONAL_OPTION)
587     {
588       /* Something other than -follow/-daystart.
589        * If this is an option, check if it followed
590        * a non-option and if so, issue a warning.
591        */
592       if (entry->type == ARG_OPTION)
593         {
594           if ((first_nonoption_arg != NULL)
595               && options.warnings )
596             {
597               /* option which follows a non-option */
598               error (0, 0,
599                      _("warning: you have specified the %s "
600                        "option after a non-option argument %s, "
601                        "but options are not positional (%s affects "
602                        "tests specified before it as well as those "
603                        "specified after it).  Please specify options "
604                        "before other arguments.\n"),
605                      original_arg,
606                      first_nonoption_arg,
607                      original_arg);
608             }
609         }
610       else
611         {
612           /* Not an option or a positional option,
613            * so remember we've seen it in order to
614            * use it in a possible future warning message.
615            */
616           if (first_nonoption_arg == NULL)
617             {
618               first_nonoption_arg = original_arg;
619             }
620         }
621     }
622
623   return entry;
624 }
625
626
627 /* Return a pointer to the parser function to invoke for predicate
628    SEARCH_NAME.
629    Return NULL if SEARCH_NAME is not a valid predicate name. */
630
631 const struct parser_table*
632 find_parser (const char *search_name)
633 {
634   int i;
635   const char *original_arg = search_name;
636
637   /* Ugh.  Special case -newerXY. */
638   if (0 == strncmp ("-newer", search_name, 6)
639       && (8 == strlen (search_name)))
640     {
641       return found_parser (original_arg, &parse_entry_newerXY);
642     }
643
644   if (*search_name == '-')
645     search_name++;
646
647   for (i = 0; parse_table[i].parser_name != 0; i++)
648     {
649       if (strcmp (parse_table[i].parser_name, search_name) == 0)
650         {
651           return found_parser (original_arg, &parse_table[i]);
652         }
653     }
654   return NULL;
655 }
656
657 static float
658 estimate_file_age_success_rate (float num_days)
659 {
660   if (num_days < 0.1)
661     {
662       /* Assume 1% of files have timestamps in the future */
663       return 0.01f;
664     }
665   else if (num_days < 1)
666     {
667       /* Assume 30% of files have timestamps today */
668       return 0.3f;
669     }
670   else if (num_days > 100)
671     {
672       /* Assume 30% of files are very old */
673       return 0.3f;
674     }
675   else
676     {
677       /* Assume 39% of files are between 1 and 100 days old. */
678       return 0.39f;
679     }
680 }
681
682 static float
683 estimate_timestamp_success_rate (time_t when)
684 {
685   /* This calculation ignores the nanoseconds field of the
686    * origin, but I don't think that makes much difference
687    * to our estimate.
688    */
689   int num_days = (options.cur_day_start.tv_sec - when) / 86400;
690   return estimate_file_age_success_rate (num_days);
691 }
692
693 /* Collect an argument from the argument list, or
694  * return false.
695  */
696 static bool
697 collect_arg_nonconst (char **argv, int *arg_ptr, char **collected_arg)
698 {
699   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
700     {
701       *collected_arg = NULL;
702       return false;
703     }
704   else
705     {
706       *collected_arg = argv[*arg_ptr];
707       (*arg_ptr)++;
708       return true;
709     }
710 }
711
712 static bool
713 collect_arg (char **argv, int *arg_ptr, const char **collected_arg)
714 {
715   char *arg;
716   const bool result = collect_arg_nonconst (argv, arg_ptr, &arg);
717   *collected_arg = arg;
718   return result;
719 }
720
721
722
723 static bool
724 collect_arg_stat_info (char **argv, int *arg_ptr, struct stat *p,
725                        const char **argument)
726 {
727   const char *filename;
728   if (collect_arg (argv, arg_ptr, &filename))
729     {
730       *argument = filename;
731       if (0 == (options.xstat)(filename, p))
732         {
733           return true;
734         }
735       else
736         {
737           fatal_target_file_error (errno, filename);
738         }
739     }
740   else
741     {
742       *argument = NULL;
743       return false;
744     }
745 }
746
747 /* The parsers are responsible to continue scanning ARGV for
748    their arguments.  Each parser knows what is and isn't
749    allowed for itself.
750
751    ARGV is the argument array.
752    *ARG_PTR is the index to start at in ARGV,
753    updated to point beyond the last element consumed.
754
755    The predicate structure is updated with the new information. */
756
757
758 static bool
759 parse_and (const struct parser_table* entry, char **argv, int *arg_ptr)
760 {
761   struct predicate *our_pred;
762
763   (void) argv;
764   (void) arg_ptr;
765
766   our_pred = get_new_pred_noarg (entry);
767   our_pred->pred_func = pred_and;
768   our_pred->p_type = BI_OP;
769   our_pred->p_prec = AND_PREC;
770   our_pred->need_stat = our_pred->need_type = false;
771   return true;
772 }
773
774 static bool
775 parse_anewer (const struct parser_table* entry, char **argv, int *arg_ptr)
776 {
777   struct stat stat_newer;
778   const char *arg;
779
780   set_stat_placeholders (&stat_newer);
781   if (collect_arg_stat_info (argv, arg_ptr, &stat_newer, &arg))
782     {
783       struct predicate *our_pred = insert_primary (entry, arg);
784       our_pred->args.reftime.xval = XVAL_ATIME;
785       our_pred->args.reftime.ts = get_stat_mtime (&stat_newer);
786       our_pred->args.reftime.kind = COMP_GT;
787       our_pred->est_success_rate = estimate_timestamp_success_rate (stat_newer.st_mtime);
788       return true;
789     }
790   return false;
791 }
792
793 bool
794 parse_closeparen (const struct parser_table* entry, char **argv, int *arg_ptr)
795 {
796   struct predicate *our_pred;
797
798   (void) argv;
799   (void) arg_ptr;
800
801   our_pred = get_new_pred_noarg (entry);
802   our_pred->pred_func = pred_closeparen;
803   our_pred->p_type = CLOSE_PAREN;
804   our_pred->p_prec = NO_PREC;
805   our_pred->need_stat = our_pred->need_type = false;
806   return true;
807 }
808
809 static bool
810 parse_cnewer (const struct parser_table* entry, char **argv, int *arg_ptr)
811 {
812   struct stat stat_newer;
813   const char *arg;
814
815   set_stat_placeholders (&stat_newer);
816   if (collect_arg_stat_info (argv, arg_ptr, &stat_newer, &arg))
817     {
818       struct predicate *our_pred = insert_primary (entry, arg);
819       our_pred->args.reftime.xval = XVAL_CTIME; /* like -newercm */
820       our_pred->args.reftime.ts = get_stat_mtime (&stat_newer);
821       our_pred->args.reftime.kind = COMP_GT;
822       our_pred->est_success_rate = estimate_timestamp_success_rate (stat_newer.st_mtime);
823       return true;
824     }
825   return false;
826 }
827
828 static bool
829 parse_comma (const struct parser_table* entry, char **argv, int *arg_ptr)
830 {
831   struct predicate *our_pred;
832
833   (void) argv;
834   (void) arg_ptr;
835
836   our_pred = get_new_pred_noarg (entry);
837   our_pred->pred_func = pred_comma;
838   our_pred->p_type = BI_OP;
839   our_pred->p_prec = COMMA_PREC;
840   our_pred->need_stat = our_pred->need_type = false;
841   our_pred->est_success_rate = 1.0f;
842   return true;
843 }
844
845 static bool
846 parse_daystart (const struct parser_table* entry, char **argv, int *arg_ptr)
847 {
848   struct tm *local;
849
850   (void) entry;
851   (void) argv;
852   (void) arg_ptr;
853
854   if (options.full_days == false)
855     {
856       options.cur_day_start.tv_sec += DAYSECS;
857       options.cur_day_start.tv_nsec = 0;
858       local = localtime (&options.cur_day_start.tv_sec);
859       options.cur_day_start.tv_sec -= (local
860                                        ? (local->tm_sec + local->tm_min * 60
861                                           + local->tm_hour * 3600)
862                                        : options.cur_day_start.tv_sec % DAYSECS);
863       options.full_days = true;
864     }
865   return true;
866 }
867
868 static bool
869 parse_delete (const struct parser_table* entry, char *argv[], int *arg_ptr)
870 {
871   struct predicate *our_pred;
872   (void) argv;
873   (void) arg_ptr;
874
875   our_pred = insert_primary_noarg (entry);
876   our_pred->side_effects = our_pred->no_default_print = true;
877   /* -delete implies -depth */
878   options.do_dir_first = false;
879
880   /* We do not need stat information because we check for the case
881    * (errno==EISDIR) in pred_delete.
882    */
883   our_pred->need_stat = our_pred->need_type = false;
884
885   our_pred->est_success_rate = 1.0f;
886   return true;
887 }
888
889 static bool
890 parse_depth (const struct parser_table* entry, char **argv, int *arg_ptr)
891 {
892   (void) entry;
893   (void) argv;
894
895   options.do_dir_first = false;
896   options.explicit_depth = true;
897   return parse_noop (entry, argv, arg_ptr);
898 }
899
900 static bool
901 parse_d (const struct parser_table* entry, char **argv, int *arg_ptr)
902 {
903   if (options.warnings)
904     {
905       error (0, 0,
906              _("warning: the -d option is deprecated; please use "
907                "-depth instead, because the latter is a "
908                "POSIX-compliant feature."));
909     }
910   return parse_depth (entry, argv, arg_ptr);
911 }
912
913 static bool
914 parse_empty (const struct parser_table* entry, char **argv, int *arg_ptr)
915 {
916   struct predicate *our_pred;
917   (void) argv;
918   (void) arg_ptr;
919
920   our_pred = insert_primary_noarg (entry);
921   our_pred->est_success_rate = 0.01f; /* assume 1% of files are empty. */
922   return true;
923 }
924
925 static bool
926 parse_exec (const struct parser_table* entry, char **argv, int *arg_ptr)
927 {
928   return insert_exec_ok ("-exec", entry, argv, arg_ptr);
929 }
930
931 static bool
932 parse_execdir (const struct parser_table* entry, char **argv, int *arg_ptr)
933 {
934   return insert_exec_ok ("-execdir", entry, argv, arg_ptr);
935 }
936
937 static bool
938 insert_false(void)
939 {
940   struct predicate *our_pred;
941   const struct parser_table *entry_false;
942
943   entry_false = find_parser("false");
944   our_pred = insert_primary_noarg (entry_false);
945   our_pred->need_stat = our_pred->need_type = false;
946   our_pred->side_effects = our_pred->no_default_print = false;
947   our_pred->est_success_rate = 0.0f;
948   return true;
949 }
950
951
952 static bool
953 parse_false (const struct parser_table* entry, char **argv, int *arg_ptr)
954 {
955   (void) entry;
956   (void) argv;
957   (void) arg_ptr;
958   return insert_false ();
959 }
960
961 static bool
962 insert_fls (const struct parser_table* entry, const char *filename)
963 {
964   struct predicate *our_pred = insert_primary_noarg (entry);
965   if (filename)
966     open_output_file (filename, &our_pred->args.printf_vec);
967   else
968     open_stdout (&our_pred->args.printf_vec);
969   our_pred->side_effects = our_pred->no_default_print = true;
970   our_pred->est_success_rate = 1.0f;
971   return true;
972 }
973
974
975 static bool
976 parse_fls (const struct parser_table* entry, char **argv, int *arg_ptr)
977 {
978   const char *filename;
979   if (collect_arg (argv, arg_ptr, &filename))
980     {
981       if (insert_fls (entry, filename))
982         return true;
983       else
984         --*arg_ptr;             /* don't consume the invalid arg. */
985     }
986   return false;
987 }
988
989 static bool
990 parse_follow (const struct parser_table* entry, char **argv, int *arg_ptr)
991 {
992   set_follow_state (SYMLINK_ALWAYS_DEREF);
993   return parse_noop (entry, argv, arg_ptr);
994 }
995
996 static bool
997 parse_fprint (const struct parser_table* entry, char **argv, int *arg_ptr)
998 {
999   struct predicate *our_pred;
1000   const char *filename;
1001   if (collect_arg (argv, arg_ptr, &filename))
1002     {
1003       our_pred = insert_primary (entry, filename);
1004       open_output_file (filename, &our_pred->args.printf_vec);
1005       our_pred->side_effects = our_pred->no_default_print = true;
1006       our_pred->need_stat = our_pred->need_type = false;
1007       our_pred->est_success_rate = 1.0f;
1008       return true;
1009     }
1010   else
1011     {
1012       return false;
1013     }
1014 }
1015
1016 static bool
1017 insert_fprint (const struct parser_table* entry, const char *filename)
1018 {
1019   struct predicate *our_pred = insert_primary (entry, filename);
1020   if (filename)
1021     open_output_file (filename, &our_pred->args.printf_vec);
1022   else
1023     open_stdout (&our_pred->args.printf_vec);
1024   our_pred->side_effects = our_pred->no_default_print = true;
1025   our_pred->need_stat = our_pred->need_type = false;
1026   our_pred->est_success_rate = 1.0f;
1027   return true;
1028 }
1029
1030
1031 static bool
1032 parse_fprint0 (const struct parser_table* entry, char **argv, int *arg_ptr)
1033 {
1034   const char *filename;
1035   if (collect_arg (argv, arg_ptr, &filename))
1036     {
1037       if (insert_fprint (entry, filename))
1038         return true;
1039       else
1040         --*arg_ptr;             /* don't consume the bad arg. */
1041     }
1042   return false;
1043 }
1044
1045 static float estimate_fstype_success_rate (const char *fsname)
1046 {
1047   struct stat dir_stat;
1048   const char *the_root_dir = "/";
1049   if (0 == stat (the_root_dir, &dir_stat)) /* it's an absolute path anyway */
1050     {
1051       const char *fstype = filesystem_type (&dir_stat, the_root_dir);
1052       /* Assume most files are on the same file system type as the root fs. */
1053       if (0 == strcmp (fsname, fstype))
1054           return 0.7f;
1055       else
1056         return 0.3f;
1057     }
1058   return 1.0f;
1059 }
1060
1061
1062
1063 static bool
1064 is_used_fs_type(const char *name)
1065 {
1066   if (0 == strcmp("afs", name))
1067     {
1068       /* I guess AFS may not appear in /etc/mtab (or equivalent) but still be in use,
1069          so assume we always need to check for AFS.  */
1070       return true;
1071     }
1072   else
1073     {
1074       const struct mount_entry *entries = read_file_system_list(false);
1075       if (entries)
1076         {
1077           const struct mount_entry *entry;
1078           for (entry = entries; entry; entry = entry->me_next)
1079             {
1080               if (0 == strcmp(name, entry->me_type))
1081                 return true;
1082             }
1083         }
1084       else
1085         {
1086           return true;
1087         }
1088     }
1089   return false;
1090 }
1091
1092
1093 static bool
1094 parse_fstype (const struct parser_table* entry, char **argv, int *arg_ptr)
1095 {
1096   const char *typename;
1097   if (collect_arg (argv, arg_ptr, &typename))
1098     {
1099       if (options.optimisation_level < 2 || is_used_fs_type (typename))
1100         {
1101           struct predicate *our_pred = insert_primary (entry, typename);
1102           our_pred->args.str = typename;
1103
1104           /* This is an expensive operation, so although there are
1105            * circumstances where it is selective, we ignore this fact
1106            * because we probably don't want to promote this test to the
1107            * front anyway.
1108            */
1109           our_pred->est_success_rate = estimate_fstype_success_rate (typename);
1110           return true;
1111         }
1112       else
1113         {
1114           /* This filesystem type is not listed in the mount table.
1115            * Hence this predicate will always return false (with this argument).
1116            * Substitute a predicate with the same effect as -false.
1117            */
1118           if (options.debug_options & DebugTreeOpt)
1119             {
1120               fprintf (stderr,
1121                        "-fstype %s can never succeed, substituting -false\n",
1122                        typename);
1123             }
1124           return insert_false ();
1125         }
1126     }
1127   else
1128     {
1129       return false;
1130     }
1131 }
1132
1133 static bool
1134 parse_gid (const struct parser_table* entry, char **argv, int *arg_ptr)
1135 {
1136   struct predicate *p = insert_num (argv, arg_ptr, entry);
1137   if (p)
1138     {
1139       p->est_success_rate = (p->args.numinfo.l_val < 100) ? 0.99 : 0.2;
1140       return true;
1141     }
1142   else
1143     {
1144       --*arg_ptr;               /* don't consume the invalid argument. */
1145       return false;
1146     }
1147 }
1148
1149
1150 static bool
1151 parse_group (const struct parser_table* entry, char **argv, int *arg_ptr)
1152 {
1153   const char *groupname;
1154   const int saved_argc = *arg_ptr;
1155
1156   if (collect_arg (argv, arg_ptr, &groupname))
1157     {
1158       gid_t gid;
1159       struct predicate *our_pred;
1160       struct group *cur_gr = getgrnam (groupname);
1161       endgrent ();
1162       if (cur_gr)
1163         {
1164           gid = cur_gr->gr_gid;
1165         }
1166       else
1167         {
1168           const int gid_len = strspn (groupname, "0123456789");
1169           if (gid_len)
1170             {
1171               if (groupname[gid_len] == 0)
1172                 {
1173                   gid = safe_atoi (groupname, options.err_quoting_style);
1174                 }
1175               else
1176                 {
1177                   /* XXX: no test in test suite for this */
1178                   error (EXIT_FAILURE, 0,
1179                          _("%s is not the name of an existing group and"
1180                            " it does not look like a numeric group ID "
1181                            "because it has the unexpected suffix %s"),
1182                          quotearg_n_style (0, options.err_quoting_style, groupname),
1183                          quotearg_n_style (1, options.err_quoting_style, groupname+gid_len));
1184                   *arg_ptr = saved_argc; /* don't consume the invalid argument. */
1185                   return false;
1186                 }
1187             }
1188           else
1189             {
1190               if (*groupname)
1191                 {
1192                   /* XXX: no test in test suite for this */
1193                   error (EXIT_FAILURE, 0,
1194                          _("%s is not the name of an existing group"),
1195                          quotearg_n_style (0, options.err_quoting_style, groupname));
1196                 }
1197               else
1198                 {
1199                   error (EXIT_FAILURE, 0,
1200                          _("argument to -group is empty, but should be a group name"));
1201                 }
1202               *arg_ptr = saved_argc; /* don't consume the invalid argument. */
1203               return false;
1204             }
1205         }
1206       our_pred = insert_primary (entry, groupname);
1207       our_pred->args.gid = gid;
1208       our_pred->est_success_rate = (our_pred->args.numinfo.l_val < 100) ? 0.99 : 0.2;
1209       return true;
1210     }
1211   return false;
1212 }
1213
1214 static bool
1215 parse_help (const struct parser_table* entry, char **argv, int *arg_ptr)
1216 {
1217   (void) entry;
1218   (void) argv;
1219   (void) arg_ptr;
1220
1221   usage (stdout, 0, NULL);
1222   puts (_("\n\
1223 default path is the current directory; default expression is -print\n\
1224 expression may consist of: operators, options, tests, and actions:\n"));
1225   puts (_("\
1226 operators (decreasing precedence; -and is implicit where no others are given):\n\
1227       ( EXPR )   ! EXPR   -not EXPR   EXPR1 -a EXPR2   EXPR1 -and EXPR2\n\
1228       EXPR1 -o EXPR2   EXPR1 -or EXPR2   EXPR1 , EXPR2\n"));
1229   puts (_("\
1230 positional options (always true): -daystart -follow -regextype\n\n\
1231 normal options (always true, specified before other expressions):\n\
1232       -depth --help -maxdepth LEVELS -mindepth LEVELS -mount -noleaf\n\
1233       --version -xdev -ignore_readdir_race -noignore_readdir_race\n"));
1234   puts (_("\
1235 tests (N can be +N or -N or N): -amin N -anewer FILE -atime N -cmin N\n\
1236       -cnewer FILE -ctime N -empty -false -fstype TYPE -gid N -group NAME\n\
1237       -ilname PATTERN -iname PATTERN -inum N -iwholename PATTERN -iregex PATTERN\n\
1238       -links N -lname PATTERN -mmin N -mtime N -name PATTERN -newer FILE"));
1239   puts (_("\
1240       -nouser -nogroup -path PATTERN -perm [-/]MODE -regex PATTERN\n\
1241       -readable -writable -executable\n\
1242       -wholename PATTERN -size N[bcwkMG] -true -type [bcdpflsD] -uid N\n\
1243       -used N -user NAME -xtype [bcdpfls]"));
1244   puts (_("\
1245       -context CONTEXT\n"));
1246   puts (_("\n\
1247 actions: -delete -print0 -printf FORMAT -fprintf FILE FORMAT -print \n\
1248       -fprint0 FILE -fprint FILE -ls -fls FILE -prune -quit\n\
1249       -exec COMMAND ; -exec COMMAND {} + -ok COMMAND ;\n\
1250       -execdir COMMAND ; -execdir COMMAND {} + -okdir COMMAND ;\n\
1251 "));
1252   puts (_("Report (and track progress on fixing) bugs via the findutils bug-reporting\n\
1253 page at http://savannah.gnu.org/ or, if you have no web access, by sending\n\
1254 email to <bug-findutils@gnu.org>."));
1255   exit (EXIT_SUCCESS);
1256 }
1257
1258 static float
1259 estimate_pattern_match_rate (const char *pattern, int is_regex)
1260 {
1261   if (strpbrk (pattern, "*?[") || (is_regex && strpbrk(pattern, ".")))
1262     {
1263       /* A wildcard; assume the pattern matches most files. */
1264       return 0.8f;
1265     }
1266   else
1267     {
1268       return 0.1f;
1269     }
1270 }
1271
1272 static bool
1273 parse_ilname (const struct parser_table* entry, char **argv, int *arg_ptr)
1274 {
1275   const char *name;
1276   if (collect_arg (argv, arg_ptr, &name))
1277     {
1278       struct predicate *our_pred = insert_primary (entry, name);
1279       our_pred->args.str = name;
1280       /* Use the generic glob pattern estimator to figure out how many
1281        * links will match, but bear in mind that most files won't be links.
1282        */
1283       our_pred->est_success_rate = 0.1 * estimate_pattern_match_rate (name, 0);
1284       return true;
1285     }
1286   else
1287     {
1288       return false;
1289     }
1290 }
1291
1292
1293 /* sanity check the fnmatch() function to make sure that case folding
1294  * is supported (as opposed to just having the flag ignored).
1295  */
1296 static bool
1297 fnmatch_sanitycheck (void)
1298 {
1299   static bool checked = false;
1300   if (!checked)
1301     {
1302       if (0 != fnmatch ("foo", "foo", 0)
1303           || 0 == fnmatch ("Foo", "foo", 0)
1304           || 0 != fnmatch ("Foo", "foo", FNM_CASEFOLD))
1305         {
1306           error (EXIT_FAILURE, 0,
1307                  _("sanity check of the fnmatch() library function failed."));
1308           return false;
1309         }
1310       checked = true;
1311     }
1312   return checked;
1313 }
1314
1315
1316 static bool
1317 check_name_arg (const char *pred, const char *arg)
1318 {
1319   if (options.warnings && strchr (arg, '/'))
1320     {
1321       error (0, 0,_("warning: Unix filenames usually don't contain slashes "
1322                     "(though pathnames do).  That means that '%s %s' will "
1323                     "probably evaluate to false all the time on this system.  "
1324                     "You might find the '-wholename' test more useful, or "
1325                     "perhaps '-samefile'.  Alternatively, if you are using "
1326                     "GNU grep, you could "
1327                     "use 'find ... -print0 | grep -FzZ %s'."),
1328             pred,
1329             safely_quote_err_filename (0, arg),
1330             safely_quote_err_filename (1, arg));
1331     }
1332   return true;                  /* allow it anyway */
1333 }
1334
1335
1336
1337 static bool
1338 parse_iname (const struct parser_table* entry, char **argv, int *arg_ptr)
1339 {
1340   const char *name;
1341   fnmatch_sanitycheck ();
1342   if (collect_arg (argv, arg_ptr, &name))
1343     {
1344       if (check_name_arg ("-iname", name))
1345         {
1346           struct predicate *our_pred = insert_primary (entry, name);
1347           our_pred->need_stat = our_pred->need_type = false;
1348           our_pred->args.str = name;
1349           our_pred->est_success_rate = estimate_pattern_match_rate (name, 0);
1350           return true;
1351         }
1352     }
1353   return false;
1354 }
1355
1356 static bool
1357 parse_inum (const struct parser_table* entry, char **argv, int *arg_ptr)
1358 {
1359   struct predicate *p =  insert_num (argv, arg_ptr, entry);
1360   if (p)
1361     {
1362       /* inode number is exact match only, so very low proportions of
1363        * files match
1364        */
1365       p->est_success_rate = 1e-6;
1366       p->need_inum = true;
1367       p->need_stat = false;
1368       p->need_type = false;
1369       return true;
1370     }
1371   else
1372     {
1373       --*arg_ptr;               /* don't consume the invalid argument. */
1374       return false;
1375     }
1376 }
1377
1378 static bool
1379 parse_iregex (const struct parser_table* entry, char **argv, int *arg_ptr)
1380 {
1381   return insert_regex (argv, arg_ptr, entry, RE_ICASE|options.regex_options);
1382 }
1383
1384 static bool
1385 parse_links (const struct parser_table* entry, char **argv, int *arg_ptr)
1386 {
1387   struct predicate *p = insert_num (argv, arg_ptr, entry);
1388   if (p)
1389     {
1390       if (p->args.numinfo.l_val == 1)
1391         p->est_success_rate = 0.99;
1392       else if (p->args.numinfo.l_val == 2)
1393         p->est_success_rate = 0.01;
1394       else
1395         p->est_success_rate = 1e-3;
1396       return true;
1397     }
1398   else
1399     {
1400       --*arg_ptr;               /* don't consume the invalid argument. */
1401       return false;
1402     }
1403 }
1404
1405 static bool
1406 parse_lname (const struct parser_table* entry, char **argv, int *arg_ptr)
1407 {
1408   const char *name;
1409   fnmatch_sanitycheck ();
1410   if (collect_arg (argv, arg_ptr, &name))
1411     {
1412       struct predicate *our_pred = insert_primary (entry, name);
1413       our_pred->args.str = name;
1414       our_pred->est_success_rate = 0.1 * estimate_pattern_match_rate (name, 0);
1415       return true;
1416     }
1417   return false;
1418 }
1419
1420 static bool
1421 parse_ls (const struct parser_table* entry, char **argv, int *arg_ptr)
1422 {
1423   (void) &argv;
1424   (void) &arg_ptr;
1425   return insert_fls (entry, NULL);
1426 }
1427
1428 static bool
1429 insert_depthspec (const struct parser_table* entry, char **argv, int *arg_ptr,
1430                   int *limitptr)
1431 {
1432   const char *depthstr;
1433   int depth_len;
1434   const char *predicate = argv[(*arg_ptr)-1];
1435   if (collect_arg (argv, arg_ptr, &depthstr))
1436     {
1437       depth_len = strspn (depthstr, "0123456789");
1438       if ((depth_len > 0) && (depthstr[depth_len] == 0))
1439         {
1440           (*limitptr) = safe_atoi (depthstr, options.err_quoting_style);
1441           if (*limitptr >= 0)
1442             {
1443               return parse_noop (entry, argv, arg_ptr);
1444             }
1445         }
1446       error (EXIT_FAILURE, 0,
1447              _("Expected a positive decimal integer argument to %s, but got %s"),
1448              predicate,
1449              quotearg_n_style (0, options.err_quoting_style, depthstr));
1450       /* NOTREACHED */
1451       return false;
1452     }
1453   /* missing argument */
1454   return false;
1455 }
1456
1457
1458 static bool
1459 parse_maxdepth (const struct parser_table* entry, char **argv, int *arg_ptr)
1460 {
1461   return insert_depthspec (entry, argv, arg_ptr, &options.maxdepth);
1462 }
1463
1464 static bool
1465 parse_mindepth (const struct parser_table* entry, char **argv, int *arg_ptr)
1466 {
1467   return insert_depthspec (entry, argv, arg_ptr, &options.mindepth);
1468 }
1469
1470
1471 static bool
1472 do_parse_xmin (const struct parser_table* entry,
1473                char **argv,
1474                int *arg_ptr,
1475                enum xval xv)
1476 {
1477   const char *minutes;
1478   const int saved_argc = *arg_ptr;
1479
1480   if (collect_arg (argv, arg_ptr, &minutes))
1481     {
1482       struct time_val tval;
1483       struct timespec origin = options.cur_day_start;
1484       tval.xval = xv;
1485       origin.tv_sec += DAYSECS;
1486       if (get_relative_timestamp (minutes, &tval, origin, 60,
1487                                   "arithmetic overflow while converting %s "
1488                                   "minutes to a number of seconds"))
1489         {
1490           struct predicate *our_pred = insert_primary (entry, minutes);
1491           our_pred->args.reftime = tval;
1492           our_pred->est_success_rate = estimate_timestamp_success_rate (tval.ts.tv_sec);
1493           return true;
1494         }
1495       else
1496         {
1497           /* Don't consume the invalid argument. */
1498           *arg_ptr = saved_argc;
1499         }
1500     }
1501   return false;
1502 }
1503 static bool
1504 parse_amin (const struct parser_table* entry, char **argv, int *arg_ptr)
1505 {
1506   return do_parse_xmin (entry, argv, arg_ptr, XVAL_ATIME);
1507 }
1508
1509 static bool
1510 parse_cmin (const struct parser_table* entry, char **argv, int *arg_ptr)
1511 {
1512   return do_parse_xmin (entry, argv, arg_ptr, XVAL_CTIME);
1513 }
1514
1515
1516 static bool
1517 parse_mmin (const struct parser_table* entry, char **argv, int *arg_ptr)
1518 {
1519   return do_parse_xmin (entry, argv, arg_ptr, XVAL_MTIME);
1520 }
1521
1522 static bool
1523 parse_name (const struct parser_table* entry, char **argv, int *arg_ptr)
1524 {
1525   const char *name;
1526   const int saved_argc = *arg_ptr;
1527
1528   if (collect_arg (argv, arg_ptr, &name))
1529     {
1530       fnmatch_sanitycheck ();
1531       if (check_name_arg ("-name", name))
1532         {
1533           struct predicate *our_pred = insert_primary (entry, name);
1534           our_pred->need_stat = our_pred->need_type = false;
1535           our_pred->args.str = name;
1536           our_pred->est_success_rate = estimate_pattern_match_rate (name, 0);
1537           return true;
1538         }
1539       else
1540         {
1541           *arg_ptr = saved_argc; /* don't consume the invalid argument. */
1542         }
1543     }
1544   return false;
1545 }
1546
1547 static bool
1548 parse_negate (const struct parser_table* entry, char **argv, int *arg_ptr)
1549 {
1550   struct predicate *our_pred;
1551
1552   (void) &argv;
1553   (void) &arg_ptr;
1554
1555   our_pred = get_new_pred_chk_op (entry, NULL);
1556   our_pred->pred_func = pred_negate;
1557   our_pred->p_type = UNI_OP;
1558   our_pred->p_prec = NEGATE_PREC;
1559   our_pred->need_stat = our_pred->need_type = false;
1560   return true;
1561 }
1562
1563 static bool
1564 parse_newer (const struct parser_table* entry, char **argv, int *arg_ptr)
1565 {
1566   struct predicate *our_pred;
1567   struct stat stat_newer;
1568   const char *arg;
1569
1570   set_stat_placeholders (&stat_newer);
1571   if (collect_arg_stat_info (argv, arg_ptr, &stat_newer, &arg))
1572     {
1573       our_pred = insert_primary (entry, arg);
1574       our_pred->args.reftime.ts = get_stat_mtime (&stat_newer);
1575       our_pred->args.reftime.xval = XVAL_MTIME;
1576       our_pred->args.reftime.kind = COMP_GT;
1577       our_pred->est_success_rate = estimate_timestamp_success_rate (stat_newer.st_mtime);
1578       return true;
1579     }
1580   return false;
1581 }
1582
1583
1584 static bool
1585 parse_newerXY (const struct parser_table* entry, char **argv, int *arg_ptr)
1586 {
1587   (void) argv;
1588   (void) arg_ptr;
1589
1590   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
1591     {
1592       return false;
1593     }
1594   else if (8u != strlen (argv[*arg_ptr]))
1595     {
1596       return false;
1597     }
1598   else
1599     {
1600       char x, y;
1601       const char validchars[] = "aBcmt";
1602
1603       assert (0 == strncmp ("-newer", argv[*arg_ptr], 6));
1604       x = argv[*arg_ptr][6];
1605       y = argv[*arg_ptr][7];
1606
1607
1608 #if !defined HAVE_STRUCT_STAT_ST_BIRTHTIME && !defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC && !defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC && !defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC
1609       if ('B' == x || 'B' == y)
1610         {
1611           error (0, 0,
1612                  _("This system does not provide a way to find the birth time of a file."));
1613           return false;
1614         }
1615 #endif
1616
1617       /* -newertY (for any Y) is invalid. */
1618       if (x == 't'
1619           || (NULL == strchr (validchars, x))
1620           || (NULL == strchr ( validchars, y)))
1621         {
1622           return false;
1623         }
1624       else
1625         {
1626           struct predicate *our_pred;
1627
1628           /* Because this item is ARG_SPECIAL_PARSE, we have to advance arg_ptr
1629            * past the test name (for most other tests, this is already done)
1630            */
1631           if (argv[1+*arg_ptr] == NULL)
1632             {
1633               error (EXIT_FAILURE, 0, _("The %s test needs an argument"),
1634                      quotearg_n_style (0, options.err_quoting_style, argv[*arg_ptr]));
1635             }
1636           else
1637             {
1638               (*arg_ptr)++;
1639             }
1640
1641           our_pred = insert_primary (entry, argv[*arg_ptr]);
1642
1643
1644           switch (x)
1645             {
1646             case 'a':
1647               our_pred->args.reftime.xval = XVAL_ATIME;
1648               break;
1649             case 'B':
1650               our_pred->args.reftime.xval = XVAL_BIRTHTIME;
1651               break;
1652             case 'c':
1653               our_pred->args.reftime.xval = XVAL_CTIME;
1654               break;
1655             case 'm':
1656               our_pred->args.reftime.xval = XVAL_MTIME;
1657               break;
1658             default:
1659               assert (strchr (validchars, x));
1660               assert (0);
1661             }
1662
1663           if ('t' == y)
1664             {
1665               if (!parse_datetime (&our_pred->args.reftime.ts,
1666                                    argv[*arg_ptr],
1667                                    &options.start_time))
1668                 {
1669                   error (EXIT_FAILURE, 0,
1670                          _("I cannot figure out how to interpret %s as a date or time"),
1671                          quotearg_n_style (0, options.err_quoting_style, argv[*arg_ptr]));
1672                 }
1673             }
1674           else
1675             {
1676               struct stat stat_newer;
1677
1678               /* Stat the named file. */
1679               set_stat_placeholders (&stat_newer);
1680               if ((*options.xstat) (argv[*arg_ptr], &stat_newer))
1681                 fatal_target_file_error (errno, argv[*arg_ptr]);
1682
1683               if (!get_stat_Ytime (&stat_newer, y, &our_pred->args.reftime.ts))
1684                 {
1685                   /* We cannot extract a timestamp from the struct stat. */
1686                   error (EXIT_FAILURE, 0,
1687                          _("Cannot obtain birth time of file %s"),
1688                          safely_quote_err_filename (0, argv[*arg_ptr]));
1689                 }
1690             }
1691           our_pred->args.reftime.kind = COMP_GT;
1692           our_pred->est_success_rate = estimate_timestamp_success_rate (our_pred->args.reftime.ts.tv_sec);
1693           (*arg_ptr)++;
1694
1695           assert (our_pred->pred_func != NULL);
1696           assert (our_pred->pred_func == pred_newerXY);
1697           assert (our_pred->need_stat);
1698           return true;
1699         }
1700     }
1701 }
1702
1703
1704 static bool
1705 parse_noleaf (const struct parser_table* entry, char **argv, int *arg_ptr)
1706 {
1707   options.no_leaf_check = true;
1708   return parse_noop (entry, argv, arg_ptr);
1709 }
1710
1711 #ifdef CACHE_IDS
1712 /* Arbitrary amount by which to increase size
1713    of `uid_unused' and `gid_unused'. */
1714 #define ALLOC_STEP 2048
1715
1716 /* Boolean: if uid_unused[n] is nonzero, then UID n has no passwd entry. */
1717 char *uid_unused = NULL;
1718
1719 /* Number of elements in `uid_unused'. */
1720 unsigned uid_allocated;
1721
1722 /* Similar for GIDs and group entries. */
1723 char *gid_unused = NULL;
1724 unsigned gid_allocated;
1725 #endif
1726
1727 static bool
1728 parse_nogroup (const struct parser_table* entry, char **argv, int *arg_ptr)
1729 {
1730   struct predicate *our_pred;
1731
1732   (void) &argv;
1733   (void) &arg_ptr;
1734
1735   our_pred = insert_primary (entry, NULL);
1736   our_pred->est_success_rate = 1e-4;
1737 #ifdef CACHE_IDS
1738   if (gid_unused == NULL)
1739     {
1740       struct group *gr;
1741
1742       gid_allocated = ALLOC_STEP;
1743       gid_unused = xmalloc (gid_allocated);
1744       memset (gid_unused, 1, gid_allocated);
1745       setgrent ();
1746       while ((gr = getgrent ()) != NULL)
1747         {
1748           if ((unsigned) gr->gr_gid >= gid_allocated)
1749             {
1750               unsigned new_allocated = (unsigned) gr->gr_gid + ALLOC_STEP;
1751               gid_unused = xrealloc (gid_unused, new_allocated);
1752               memset (gid_unused + gid_allocated, 1,
1753                       new_allocated - gid_allocated);
1754               gid_allocated = new_allocated;
1755             }
1756           gid_unused[(unsigned) gr->gr_gid] = 0;
1757         }
1758       endgrent ();
1759     }
1760 #endif
1761   return true;
1762 }
1763
1764 static bool
1765 parse_nouser (const struct parser_table* entry, char **argv, int *arg_ptr)
1766 {
1767   struct predicate *our_pred;
1768   (void) argv;
1769   (void) arg_ptr;
1770
1771
1772   our_pred = insert_primary_noarg (entry);
1773   our_pred->est_success_rate = 1e-3;
1774 #ifdef CACHE_IDS
1775   if (uid_unused == NULL)
1776     {
1777       struct passwd *pw;
1778
1779       uid_allocated = ALLOC_STEP;
1780       uid_unused = xmalloc (uid_allocated);
1781       memset (uid_unused, 1, uid_allocated);
1782       setpwent ();
1783       while ((pw = getpwent ()) != NULL)
1784         {
1785           if ((unsigned) pw->pw_uid >= uid_allocated)
1786             {
1787               unsigned new_allocated = (unsigned) pw->pw_uid + ALLOC_STEP;
1788               uid_unused = xrealloc (uid_unused, new_allocated);
1789               memset (uid_unused + uid_allocated, 1,
1790                       new_allocated - uid_allocated);
1791               uid_allocated = new_allocated;
1792             }
1793           uid_unused[(unsigned) pw->pw_uid] = 0;
1794         }
1795       endpwent ();
1796     }
1797 #endif
1798   return true;
1799 }
1800
1801 static bool
1802 parse_nowarn (const struct parser_table* entry, char **argv, int *arg_ptr)
1803 {
1804   options.warnings = false;
1805   return parse_noop (entry, argv, arg_ptr);
1806 }
1807
1808 static bool
1809 parse_ok (const struct parser_table* entry, char **argv, int *arg_ptr)
1810 {
1811   return insert_exec_ok ("-ok", entry, argv, arg_ptr);
1812 }
1813
1814 static bool
1815 parse_okdir (const struct parser_table* entry, char **argv, int *arg_ptr)
1816 {
1817   return insert_exec_ok ("-okdir", entry, argv, arg_ptr);
1818 }
1819
1820 bool
1821 parse_openparen (const struct parser_table* entry, char **argv, int *arg_ptr)
1822 {
1823   struct predicate *our_pred;
1824
1825   (void) argv;
1826   (void) arg_ptr;
1827
1828   our_pred = get_new_pred_chk_op (entry, NULL);
1829   our_pred->pred_func = pred_openparen;
1830   our_pred->p_type = OPEN_PAREN;
1831   our_pred->p_prec = NO_PREC;
1832   our_pred->need_stat = our_pred->need_type = false;
1833   return true;
1834 }
1835
1836 static bool
1837 parse_or (const struct parser_table* entry, char **argv, int *arg_ptr)
1838 {
1839   struct predicate *our_pred;
1840
1841   (void) argv;
1842   (void) arg_ptr;
1843
1844   our_pred = get_new_pred_noarg (entry);
1845   our_pred->pred_func = pred_or;
1846   our_pred->p_type = BI_OP;
1847   our_pred->p_prec = OR_PREC;
1848   our_pred->need_stat = our_pred->need_type = false;
1849   return true;
1850 }
1851
1852 static bool
1853 is_feasible_path_argument (const char *arg, bool foldcase)
1854 {
1855   const char *last = strrchr (arg, '/');
1856   if (last && !last[1])
1857     {
1858       /* The name ends with "/". */
1859       if (matches_start_point (arg, foldcase))
1860         {
1861           /* "-path foo/" can succeed if one of the start points is "foo/". */
1862           return true;
1863         }
1864       else
1865         {
1866           return false;
1867         }
1868     }
1869   return true;
1870 }
1871
1872
1873 static bool
1874 insert_path_check (const struct parser_table* entry, char **argv, int *arg_ptr,
1875                    const char *predicate_name, PREDICATEFUNCTION pred)
1876 {
1877   const char *name;
1878   bool foldcase = false;
1879
1880   if (pred == pred_ipath)
1881     foldcase = true;
1882
1883   fnmatch_sanitycheck ();
1884
1885   if (collect_arg (argv, arg_ptr, &name))
1886     {
1887       struct predicate *our_pred = insert_primary_withpred (entry, pred, name);
1888       our_pred->need_stat = our_pred->need_type = false;
1889       our_pred->args.str = name;
1890       our_pred->est_success_rate = estimate_pattern_match_rate (name, 0);
1891
1892       if (!options.posixly_correct
1893           && !is_feasible_path_argument (name, foldcase))
1894         {
1895           error (0, 0, _("warning: -%s %s will not match anything "
1896                          "because it ends with /."),
1897                  predicate_name, name);
1898           our_pred->est_success_rate = 1.0e-8;
1899         }
1900       return true;
1901     }
1902   return false;
1903 }
1904
1905 /* For some time, -path was deprecated (at RMS's request) in favour of
1906  * -iwholename.  See the node "GNU Manuals" in standards.texi for the
1907  * rationale for this (basically, GNU prefers the use of the phrase
1908  * "file name" to "path name".
1909  *
1910  * We do not issue a warning that this usage is deprecated
1911  * since
1912  * (a) HPUX find supports this predicate also and
1913  * (b) it will soon be in POSIX anyway.
1914  */
1915 static bool
1916 parse_path (const struct parser_table* entry, char **argv, int *arg_ptr)
1917 {
1918   return insert_path_check (entry, argv, arg_ptr, "path", pred_path);
1919 }
1920
1921 static bool
1922 parse_wholename (const struct parser_table* entry, char **argv, int *arg_ptr)
1923 {
1924   return insert_path_check (entry, argv, arg_ptr, "wholename", pred_path);
1925 }
1926
1927 /* -ipath was deprecated (at RMS's request) in favour of
1928  * -iwholename.   See the node "GNU Manuals" in standards.texi
1929  * for the rationale for this (basically, GNU prefers the use
1930  * of the phrase "file name" to "path name".
1931  * However, -path is now standardised so I un-deprecated -ipath.
1932  */
1933 static bool
1934 parse_ipath (const struct parser_table* entry, char **argv, int *arg_ptr)
1935 {
1936   return insert_path_check (entry, argv, arg_ptr, "ipath", pred_ipath);
1937 }
1938
1939 static bool
1940 parse_iwholename (const struct parser_table* entry, char **argv, int *arg_ptr)
1941 {
1942   return insert_path_check (entry, argv, arg_ptr, "iwholename", pred_ipath);
1943 }
1944
1945
1946 static bool
1947 parse_perm (const struct parser_table* entry, char **argv, int *arg_ptr)
1948 {
1949   mode_t perm_val[2];
1950   float rate;
1951   int mode_start = 0;
1952   enum permissions_type kind = PERM_EXACT;
1953   struct mode_change *change;
1954   struct predicate *our_pred;
1955   const char *perm_expr;
1956
1957   if (!collect_arg (argv, arg_ptr, &perm_expr))
1958     return false;
1959
1960   switch (perm_expr[0])
1961     {
1962     case '-':
1963       mode_start = 1;
1964       kind = PERM_AT_LEAST;
1965       rate = 0.2;
1966       break;
1967
1968     case '/':                   /* GNU extension */
1969       mode_start = 1;
1970       kind = PERM_ANY;
1971       rate = 0.3;
1972       break;
1973
1974     default:
1975       /* For example, '-perm 0644', which is valid and matches
1976        * only files whose mode is exactly 0644.
1977        */
1978       mode_start = 0;
1979       kind = PERM_EXACT;
1980       rate = 0.01;
1981       break;
1982     }
1983
1984   change = mode_compile (perm_expr + mode_start);
1985
1986   /* Reject invalid modes, or modes of the form +NUMERICMODE.
1987      The latter were formerly accepted as a GNU extension, but that
1988      extension was incompatible with how GNU 'chmod' treats these modes now,
1989      and it would be confusing if 'find' continued to support it.  */
1990   if (NULL == change
1991       || (perm_expr[0] == '+' && '0' <= perm_expr[1] && perm_expr[1] < '8'))
1992     error (EXIT_FAILURE, 0, _("invalid mode %s"),
1993            quotearg_n_style (0, options.err_quoting_style, perm_expr));
1994   perm_val[0] = mode_adjust (0, false, 0, change, NULL);
1995   perm_val[1] = mode_adjust (0, true, 0, change, NULL);
1996   free (change);
1997
1998   if (('/' == perm_expr[0]) && (0 == perm_val[0]) && (0 == perm_val[1]))
1999     {
2000       /* The meaning of -perm /000 will change in the future.  It
2001        * currently matches no files, but like -perm -000 it should
2002        * match all files.
2003        *
2004        * Starting in 2005, we used to issue a warning message
2005        * informing the user that the behaviour would change in the
2006        * future.  We have now changed the behaviour and issue a
2007        * warning message that the behaviour recently changed.
2008        */
2009       error (0, 0,
2010              _("warning: you have specified a mode pattern %s (which is "
2011                "equivalent to /000). The meaning of -perm /000 has now been "
2012                "changed to be consistent with -perm -000; that is, while it "
2013                "used to match no files, it now matches all files."),
2014              perm_expr);
2015
2016       kind = PERM_AT_LEAST;
2017
2018       /* The "magic" number below is just the fraction of files on my
2019        * own system that "-type l -xtype l" fails for (i.e. unbroken symlinks).
2020        * Actual totals are 1472 and 1073833.
2021        */
2022       rate = 0.9986; /* probably matches anything but a broken symlink */
2023     }
2024
2025   our_pred = insert_primary (entry, perm_expr);
2026   our_pred->est_success_rate = rate;
2027   our_pred->args.perm.kind = kind;
2028   memcpy (our_pred->args.perm.val, perm_val, sizeof perm_val);
2029   return true;
2030 }
2031
2032 bool
2033 parse_print (const struct parser_table* entry, char **argv, int *arg_ptr)
2034 {
2035   struct predicate *our_pred;
2036
2037   (void) argv;
2038   (void) arg_ptr;
2039
2040   our_pred = insert_primary_noarg (entry);
2041   /* -print has the side effect of printing.  This prevents us
2042      from doing undesired multiple printing when the user has
2043      already specified -print. */
2044   our_pred->side_effects = our_pred->no_default_print = true;
2045   our_pred->need_stat = our_pred->need_type = false;
2046   open_stdout (&our_pred->args.printf_vec);
2047   return true;
2048 }
2049
2050 static bool
2051 parse_print0 (const struct parser_table* entry, char **argv, int *arg_ptr)
2052 {
2053   (void) entry;
2054   (void) argv;
2055   (void) arg_ptr;
2056   return insert_fprint (entry, NULL);
2057 }
2058
2059 static bool
2060 parse_printf (const struct parser_table* entry, char **argv, int *arg_ptr)
2061 {
2062   char *format;
2063   const int saved_argc = *arg_ptr;
2064
2065   if (collect_arg_nonconst (argv, arg_ptr, &format))
2066     {
2067       struct format_val fmt;
2068       open_stdout (&fmt);
2069       if (insert_fprintf (&fmt, entry, format))
2070         {
2071           return true;
2072         }
2073       else
2074         {
2075           *arg_ptr = saved_argc; /* don't consume the invalid argument. */
2076           return false;
2077         }
2078     }
2079   return false;
2080 }
2081
2082 static bool
2083 parse_fprintf (const struct parser_table* entry, char **argv, int *arg_ptr)
2084 {
2085   const char *filename;
2086   char *format;
2087   int saved_argc = *arg_ptr;
2088
2089   if (collect_arg (argv, arg_ptr, &filename))
2090     {
2091       if (collect_arg_nonconst (argv, arg_ptr, &format))
2092         {
2093           struct format_val fmt;
2094           open_output_file (filename, &fmt);
2095           saved_argc = *arg_ptr;
2096
2097           if (insert_fprintf (&fmt, entry, format))
2098             return true;
2099         }
2100     }
2101   *arg_ptr = saved_argc; /* don't consume the invalid argument. */
2102   return false;
2103 }
2104
2105 static bool
2106 parse_prune (const struct parser_table* entry, char **argv, int *arg_ptr)
2107 {
2108   struct predicate *our_pred;
2109
2110   (void) argv;
2111   (void) arg_ptr;
2112
2113   our_pred = insert_primary_noarg (entry);
2114   if (options.do_dir_first == false)
2115     our_pred->need_stat = our_pred->need_type = false;
2116   /* -prune has a side effect that it does not descend into
2117      the current directory. */
2118   our_pred->side_effects = true;
2119   our_pred->no_default_print = false;
2120   return true;
2121 }
2122
2123 static bool
2124 parse_quit  (const struct parser_table* entry, char **argv, int *arg_ptr)
2125 {
2126   struct predicate *our_pred = insert_primary_noarg (entry);
2127   (void) argv;
2128   (void) arg_ptr;
2129   our_pred->need_stat = our_pred->need_type = false;
2130   our_pred->side_effects = true; /* Exiting is a side effect... */
2131   our_pred->no_default_print = false; /* Don't inhibit the default print, though. */
2132   our_pred->est_success_rate = 1.0f;
2133   return true;
2134 }
2135
2136
2137 static bool
2138 parse_regextype (const struct parser_table* entry, char **argv, int *arg_ptr)
2139 {
2140   const char *type_name;
2141   if (collect_arg (argv, arg_ptr, &type_name))
2142     {
2143       /* collect the regex type name */
2144       options.regex_options = get_regex_type (type_name);
2145       return parse_noop (entry, argv, arg_ptr);
2146     }
2147   return false;
2148 }
2149
2150
2151 static bool
2152 parse_regex (const struct parser_table* entry, char **argv, int *arg_ptr)
2153 {
2154   return insert_regex (argv, arg_ptr, entry, options.regex_options);
2155 }
2156
2157 static bool
2158 insert_regex (char **argv,
2159               int *arg_ptr,
2160               const struct parser_table *entry,
2161               int regex_options)
2162 {
2163   const char *rx;
2164   if (collect_arg (argv, arg_ptr, &rx))
2165     {
2166       struct re_pattern_buffer *re;
2167       const char *error_message;
2168       struct predicate *our_pred = insert_primary_withpred (entry, pred_regex, rx);
2169       our_pred->need_stat = our_pred->need_type = false;
2170       re = xmalloc (sizeof (struct re_pattern_buffer));
2171       our_pred->args.regex = re;
2172       re->allocated = 100;
2173       re->buffer = xmalloc (re->allocated);
2174       re->fastmap = NULL;
2175
2176       re_set_syntax (regex_options);
2177       re->syntax = regex_options;
2178       re->translate = NULL;
2179
2180       error_message = re_compile_pattern (rx, strlen (rx), re);
2181       if (error_message)
2182         error (EXIT_FAILURE, 0, "%s", error_message);
2183       our_pred->est_success_rate = estimate_pattern_match_rate (rx, 1);
2184       return true;
2185     }
2186   return false;
2187 }
2188
2189 static bool
2190 parse_size (const struct parser_table* entry, char **argv, int *arg_ptr)
2191 {
2192   struct predicate *our_pred;
2193   char *arg;
2194   uintmax_t num;
2195   char suffix;
2196   enum comparison_type c_type;
2197
2198   int blksize = 512;
2199   int len;
2200
2201   /* XXX: cannot (yet) convert to ue collect_arg() as this
2202    * function modifies the args in-place.
2203    */
2204   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
2205     return false;
2206   arg = argv[*arg_ptr];
2207
2208   len = strlen (arg);
2209   if (len == 0)
2210     error (EXIT_FAILURE, 0, _("invalid null argument to -size"));
2211
2212   suffix = arg[len - 1];
2213   switch (suffix)
2214     {
2215     case 'b':
2216       blksize = 512;
2217       arg[len - 1] = '\0';
2218       break;
2219
2220     case 'c':
2221       blksize = 1;
2222       arg[len - 1] = '\0';
2223       break;
2224
2225     case 'k':
2226       blksize = 1024;
2227       arg[len - 1] = '\0';
2228       break;
2229
2230     case 'M':                   /* Megabytes */
2231       blksize = 1024*1024;
2232       arg[len - 1] = '\0';
2233       break;
2234
2235     case 'G':                   /* Gigabytes */
2236       blksize = 1024*1024*1024;
2237       arg[len - 1] = '\0';
2238       break;
2239
2240     case 'w':
2241       blksize = 2;
2242       arg[len - 1] = '\0';
2243       break;
2244
2245     case '0':
2246     case '1':
2247     case '2':
2248     case '3':
2249     case '4':
2250     case '5':
2251     case '6':
2252     case '7':
2253     case '8':
2254     case '9':
2255       suffix = 0;
2256       break;
2257
2258     default:
2259       error (EXIT_FAILURE, 0,
2260              _("invalid -size type `%c'"), argv[*arg_ptr][len - 1]);
2261     }
2262   /* TODO: accept fractional megabytes etc. ? */
2263   if (!get_num (arg, &num, &c_type))
2264     {
2265       char tail[2];
2266       tail[0] = suffix;
2267       tail[1] = 0;
2268
2269       error (EXIT_FAILURE, 0,
2270              _("Invalid argument `%s%s' to -size"),
2271              arg, tail);
2272       return false;
2273     }
2274   our_pred = insert_primary (entry, arg);
2275   our_pred->args.size.kind = c_type;
2276   our_pred->args.size.blocksize = blksize;
2277   our_pred->args.size.size = num;
2278   our_pred->need_stat = true;
2279   our_pred->need_type = false;
2280
2281   if (COMP_GT == c_type)
2282     our_pred->est_success_rate = (num*blksize > 20480) ? 0.1 : 0.9;
2283   else if (COMP_LT == c_type)
2284     our_pred->est_success_rate = (num*blksize > 20480) ? 0.9 : 0.1;
2285   else
2286     our_pred->est_success_rate = 0.01;
2287
2288   (*arg_ptr)++;
2289   return true;
2290 }
2291
2292
2293 static bool
2294 parse_samefile (const struct parser_table* entry, char **argv, int *arg_ptr)
2295 {
2296   /* General idea: stat the file, remember device and inode numbers.
2297    * If a candidate file matches those, it's the same file.
2298    */
2299   struct predicate *our_pred;
2300   struct stat st, fst;
2301   int fd, openflags;
2302   const char *filename;
2303
2304   set_stat_placeholders (&st);
2305   if (!collect_arg_stat_info (argv, arg_ptr, &st, &filename))
2306     return false;
2307
2308   set_stat_placeholders (&fst);
2309   /* POSIX systems are free to re-use the inode number of a deleted
2310    * file.  To ensure that we are not fooled by inode reuse, we hold
2311    * the file open if we can.  This would prevent the system reusing
2312    * the file.
2313    */
2314   fd = -3;                      /* -3 means uninitialized */
2315   openflags = O_RDONLY;
2316
2317   if (options.symlink_handling == SYMLINK_NEVER_DEREF)
2318     {
2319       if (options.open_nofollow_available)
2320         {
2321           assert (O_NOFOLLOW != 0);
2322           openflags |= O_NOFOLLOW;
2323           fd = -1;              /* safe to open it. */
2324         }
2325       else
2326         {
2327           if (S_ISLNK(st.st_mode))
2328             {
2329               /* no way to ensure that a symlink will not be followed
2330                * by open(2), so fall back on using lstat().  Accept
2331                * the risk that the named file will be deleted and
2332                * replaced with another having the same inode.
2333                *
2334                * Avoid opening the file.
2335                */
2336               fd = -2;          /* Do not open it */
2337             }
2338           else
2339             {
2340               fd = -1;
2341               /* Race condition here: the file might become a symlink here. */
2342             }
2343         }
2344     }
2345   else
2346     {
2347       /* We want to dereference the symlink anyway */
2348       fd = -1;                  /* safe to open it without O_NOFOLLOW */
2349     }
2350
2351   assert (fd != -3);            /* check we made a decision */
2352   if (fd == -1)
2353     {
2354       /* Race condition here.  The file might become a
2355        * symbolic link in between our call to stat and
2356        * the call to open_cloexec.
2357        */
2358       fd = open_cloexec (filename, openflags);
2359
2360       if (fd >= 0)
2361         {
2362           /* We stat the file again here to prevent a race condition
2363            * between the first stat and the call to open(2).
2364            */
2365           if (0 != fstat (fd, &fst))
2366             {
2367               fatal_target_file_error (errno, filename);
2368             }
2369           else
2370             {
2371               /* Worry about the race condition.  If the file became a
2372                * symlink after our first stat and before our call to
2373                * open, fst may contain the stat information for the
2374                * destination of the link, not the link itself.
2375                */
2376               if ((*options.xstat) (filename, &st))
2377                 fatal_target_file_error (errno, filename);
2378
2379               if ((options.symlink_handling == SYMLINK_NEVER_DEREF)
2380                   && (!options.open_nofollow_available))
2381                 {
2382                   if (S_ISLNK(st.st_mode))
2383                     {
2384                       /* We lost the race.  Leave the data in st.  The
2385                        * file descriptor points to the wrong thing.
2386                        */
2387                       close (fd);
2388                       fd = -1;
2389                     }
2390                   else
2391                     {
2392                       /* Several possibilities here:
2393                        * 1. There was no race
2394                        * 2. The file changed into a symlink after the stat and
2395                        *    before the open, and then back into a non-symlink
2396                        *    before the second stat.
2397                        *
2398                        * In case (1) there is no problem.  In case (2),
2399                        * the stat() and fstat() calls will have returned
2400                        * different data.  O_NOFOLLOW was not available,
2401                        * so the open() call may have followed a symlink
2402                        * even if the -P option is in effect.
2403                        */
2404                       if ((st.st_dev == fst.st_dev)
2405                           && (st.st_ino == fst.st_ino))
2406                         {
2407                           /* No race.  No need to copy fst to st,
2408                            * since they should be identical (modulo
2409                            * differences in padding bytes).
2410                            */
2411                         }
2412                       else
2413                         {
2414                           /* We lost the race.  Leave the data in st.  The
2415                            * file descriptor points to the wrong thing.
2416                            */
2417                           close (fd);
2418                           fd = -1;
2419                         }
2420                     }
2421                 }
2422               else
2423                 {
2424                   st = fst;
2425                 }
2426             }
2427         }
2428     }
2429
2430   our_pred = insert_primary (entry, filename);
2431   our_pred->args.samefileid.ino = st.st_ino;
2432   our_pred->args.samefileid.dev = st.st_dev;
2433   our_pred->args.samefileid.fd  = fd;
2434   our_pred->need_type = false;
2435   /* smarter way: compare type and inode number first. */
2436   /* TODO: maybe optimise this away by being optimistic */
2437   our_pred->need_stat = true;
2438   our_pred->est_success_rate = 0.01f;
2439   return true;
2440 }
2441
2442 #if 0
2443 /* This function is commented out partly because support for it is
2444  * uneven.
2445  */
2446 static bool
2447 parse_show_control_chars (const struct parser_table* entry,
2448                           char **argv,
2449                           int *arg_ptr)
2450 {
2451   const char *arg;
2452   const char *errmsg = _("The -show-control-chars option takes "
2453                          "a single argument which "
2454                          "must be 'literal' or 'safe'");
2455
2456   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
2457     {
2458       error (EXIT_FAILURE, errno, "%s", errmsg);
2459       return false;
2460     }
2461   else
2462     {
2463       arg = argv[*arg_ptr];
2464
2465       if (0 == strcmp ("literal", arg))
2466         {
2467           options.literal_control_chars = true;
2468         }
2469       else if (0 == strcmp ("safe", arg))
2470         {
2471           options.literal_control_chars = false;
2472         }
2473       else
2474         {
2475           error (EXIT_FAILURE, errno, "%s", errmsg);
2476           return false;
2477         }
2478       (*arg_ptr)++;             /* consume the argument. */
2479       return true;
2480     }
2481 }
2482 #endif
2483
2484
2485 static bool
2486 parse_true (const struct parser_table* entry, char **argv, int *arg_ptr)
2487 {
2488   struct predicate *our_pred;
2489
2490   (void) argv;
2491   (void) arg_ptr;
2492
2493   our_pred = insert_primary_noarg (entry);
2494   our_pred->need_stat = our_pred->need_type = false;
2495   our_pred->est_success_rate = 1.0f;
2496   return true;
2497 }
2498
2499 static bool
2500 parse_noop (const struct parser_table* entry, char **argv, int *arg_ptr)
2501 {
2502   (void) entry;
2503   return parse_true (get_noop (), argv, arg_ptr);
2504 }
2505
2506 static bool
2507 parse_accesscheck (const struct parser_table* entry, char **argv, int *arg_ptr)
2508 {
2509   struct predicate *our_pred;
2510   (void) argv;
2511   (void) arg_ptr;
2512   our_pred = insert_primary_noarg (entry);
2513   our_pred->need_stat = our_pred->need_type = false;
2514   our_pred->side_effects = our_pred->no_default_print = false;
2515   if (pred_is(our_pred, pred_executable))
2516     our_pred->est_success_rate = 0.2;
2517   else
2518     our_pred->est_success_rate = 0.9;
2519   return true;
2520 }
2521
2522 static bool
2523 parse_type (const struct parser_table* entry, char **argv, int *arg_ptr)
2524 {
2525   return insert_type (argv, arg_ptr, entry, pred_type);
2526 }
2527
2528 static bool
2529 parse_uid (const struct parser_table* entry, char **argv, int *arg_ptr)
2530 {
2531   struct predicate *p = insert_num (argv, arg_ptr, entry);
2532   if (p)
2533     {
2534       p->est_success_rate = (p->args.numinfo.l_val < 100) ? 0.99 : 0.2;
2535       return true;
2536     }
2537   else
2538     {
2539       --*arg_ptr;               /* don't consume the invalid argument. */
2540       return false;
2541     }
2542 }
2543
2544 static bool
2545 parse_used (const struct parser_table* entry, char **argv, int *arg_ptr)
2546 {
2547   struct predicate *our_pred;
2548   struct time_val tval;
2549   const char *offset_str;
2550   const char *errmsg = "arithmetic overflow while converting %s days to a number of seconds";
2551
2552   if (collect_arg (argv, arg_ptr, &offset_str))
2553     {
2554       /* The timespec is actually a delta value, so we use an origin of 0. */
2555       struct timespec zero = {0,0};
2556       if (get_relative_timestamp (offset_str, &tval, zero, DAYSECS, errmsg))
2557         {
2558           our_pred = insert_primary (entry, offset_str);
2559           our_pred->args.reftime = tval;
2560           our_pred->est_success_rate = estimate_file_age_success_rate (tval.ts.tv_sec / DAYSECS);
2561           return true;
2562         }
2563       else
2564         {
2565           error (EXIT_FAILURE, 0,
2566                  _("Invalid argument %s to -used"), offset_str);
2567           /*NOTREACHED*/
2568           return false;
2569         }
2570     }
2571   else
2572     {
2573       return false;             /* missing argument */
2574     }
2575 }
2576
2577 static bool
2578 parse_user (const struct parser_table* entry, char **argv, int *arg_ptr)
2579 {
2580   const char *username;
2581
2582   if (collect_arg (argv, arg_ptr, &username))
2583     {
2584       struct predicate *our_pred;
2585       uid_t uid;
2586       struct passwd *cur_pwd = getpwnam (username);
2587       endpwent ();
2588       if (cur_pwd != NULL)
2589         {
2590           uid = cur_pwd->pw_uid;
2591         }
2592       else
2593         {
2594           const size_t uid_len = strspn (username, "0123456789");
2595           if (uid_len && (username[uid_len]==0))
2596             {
2597               uid = safe_atoi (username, options.err_quoting_style);
2598             }
2599           else
2600             {
2601               /* This is a fatal error (if we just return false, the caller
2602                * will say "invalid argument `username' to -user", which is
2603                * not as helpful). */
2604               if (username[0])
2605                 {
2606                   error (EXIT_FAILURE, 0,
2607                          _("%s is not the name of a known user"),
2608                          quotearg_n_style (0, options.err_quoting_style,
2609                                            username));
2610                 }
2611               else
2612                 {
2613                   error (EXIT_FAILURE, 0,
2614                          _("The argument to -user should not be empty"));
2615                 }
2616               /*NOTREACHED*/
2617               return false;
2618             }
2619         }
2620       our_pred = insert_primary (entry, username);
2621       our_pred->args.uid = uid;
2622       our_pred->est_success_rate = (our_pred->args.uid < 100) ? 0.99 : 0.2;
2623       return true;
2624     }
2625   return false;
2626 }
2627
2628 static bool
2629 parse_version (const struct parser_table* entry, char **argv, int *arg_ptr)
2630 {
2631   bool has_features = false;
2632   int flags;
2633
2634   (void) argv;
2635   (void) arg_ptr;
2636   (void) entry;
2637
2638   display_findutils_version ("find");
2639   printf (_("Features enabled: "));
2640
2641 #if CACHE_IDS
2642   printf ("CACHE_IDS ");
2643   has_features = true;
2644 #endif
2645 #if DEBUG
2646   printf ("DEBUG ");
2647   has_features = true;
2648 #endif
2649 #if DEBUG_STAT
2650   printf ("DEBUG_STAT ");
2651   has_features = true;
2652 #endif
2653 #if defined HAVE_STRUCT_DIRENT_D_TYPE
2654   printf ("D_TYPE ");
2655   has_features = true;
2656 #endif
2657 #if defined O_NOFOLLOW
2658   printf ("O_NOFOLLOW(%s) ",
2659           (options.open_nofollow_available ? "enabled" : "disabled"));
2660   has_features = true;
2661 #endif
2662 #if defined LEAF_OPTIMISATION
2663   printf ("LEAF_OPTIMISATION ");
2664   has_features = true;
2665 #endif
2666   if (0 < is_selinux_enabled ())
2667     {
2668       printf ("SELINUX ");
2669       has_features = true;
2670     }
2671
2672   flags = 0;
2673   if (is_fts_enabled (&flags))
2674     {
2675       int nflags = 0;
2676       printf ("FTS(");
2677       has_features = true;
2678
2679       if (flags & FTS_CWDFD)
2680         {
2681           if (nflags)
2682             {
2683               printf (",");
2684             }
2685           printf ("FTS_CWDFD");
2686           has_features = true;
2687         }
2688       printf (") ");
2689     }
2690
2691   printf ("CBO(level=%d) ", (int)(options.optimisation_level));
2692   has_features = true;
2693
2694   if (!has_features)
2695     {
2696       /* For the moment, leave this as English in case someone wants
2697          to parse these strings. */
2698       printf ("none");
2699     }
2700   printf ("\n");
2701
2702   exit (EXIT_SUCCESS);
2703 }
2704
2705 static bool
2706 parse_context (const struct parser_table* entry, char **argv, int *arg_ptr)
2707 {
2708   struct predicate *our_pred;
2709
2710   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
2711     return false;
2712
2713   if (is_selinux_enabled () <= 0)
2714     {
2715       error (EXIT_FAILURE, 0,
2716              _("invalid predicate -context: SELinux is not enabled."));
2717       return false;
2718     }
2719   our_pred = insert_primary (entry, NULL);
2720   our_pred->est_success_rate = 0.01f;
2721   our_pred->need_stat = false;
2722 #ifdef DEBUG
2723   our_pred->p_name = find_pred_name (pred_context);
2724 #endif /*DEBUG*/
2725   our_pred->args.scontext = argv[*arg_ptr];
2726
2727   (*arg_ptr)++;
2728   return true;
2729 }
2730
2731 static bool
2732 parse_xdev (const struct parser_table* entry, char **argv, int *arg_ptr)
2733 {
2734   options.stay_on_filesystem = true;
2735   return parse_noop (entry, argv, arg_ptr);
2736 }
2737
2738 static bool
2739 parse_ignore_race (const struct parser_table* entry, char **argv, int *arg_ptr)
2740 {
2741   options.ignore_readdir_race = true;
2742   return parse_noop (entry, argv, arg_ptr);
2743 }
2744
2745 static bool
2746 parse_noignore_race (const struct parser_table* entry, char **argv, int *arg_ptr)
2747 {
2748   options.ignore_readdir_race = false;
2749   return parse_noop (entry, argv, arg_ptr);
2750 }
2751
2752 static bool
2753 parse_warn (const struct parser_table* entry, char **argv, int *arg_ptr)
2754 {
2755   options.warnings = true;
2756   return parse_noop (entry, argv, arg_ptr);
2757 }
2758
2759 static bool
2760 parse_xtype (const struct parser_table* entry, char **argv, int *arg_ptr)
2761 {
2762   return insert_type (argv, arg_ptr, entry, pred_xtype);
2763 }
2764
2765 static bool
2766 insert_type (char **argv, int *arg_ptr,
2767              const struct parser_table *entry,
2768              PRED_FUNC which_pred)
2769 {
2770   mode_t type_cell;
2771   struct predicate *our_pred;
2772   float rate = 0.5;
2773   const char *typeletter;
2774
2775   if (collect_arg (argv, arg_ptr, &typeletter))
2776     {
2777       if (strlen (typeletter) != 1u)
2778         {
2779           error (EXIT_FAILURE, 0,
2780                  _("Arguments to -type should contain only one letter"));
2781           /*NOTREACHED*/
2782           return false;
2783         }
2784
2785       switch (typeletter[0])
2786         {
2787         case 'b':                       /* block special */
2788           type_cell = S_IFBLK;
2789           rate = 0.01f;
2790           break;
2791         case 'c':                       /* character special */
2792           type_cell = S_IFCHR;
2793           rate = 0.01f;
2794           break;
2795         case 'd':                       /* directory */
2796           type_cell = S_IFDIR;
2797           rate = 0.4f;
2798           break;
2799         case 'f':                       /* regular file */
2800           type_cell = S_IFREG;
2801           rate = 0.95f;
2802           break;
2803         case 'l':                       /* symbolic link */
2804 #ifdef S_IFLNK
2805           type_cell = S_IFLNK;
2806           rate = 0.1f;
2807 #else
2808           error (EXIT_FAILURE, 0,
2809                  _("-type %c is not supported because symbolic links "
2810                    "are not supported on the platform find was compiled on."),
2811                  (*typeletter));
2812 #endif
2813           break;
2814         case 'p':                       /* pipe */
2815 #ifdef S_IFIFO
2816           type_cell = S_IFIFO;
2817           rate = 0.01f;
2818 #else
2819           error (EXIT_FAILURE, 0,
2820                  _("-type %c is not supported because FIFOs "
2821                    "are not supported on the platform find was compiled on."),
2822                  (*typeletter));
2823 #endif
2824           break;
2825         case 's':                       /* socket */
2826 #ifdef S_IFSOCK
2827           type_cell = S_IFSOCK;
2828           rate = 0.01f;
2829 #else
2830           error (EXIT_FAILURE, 0,
2831                  _("-type %c is not supported because named sockets "
2832                    "are not supported on the platform find was compiled on."),
2833                  (*typeletter));
2834 #endif
2835           break;
2836         case 'D':                       /* Solaris door */
2837 #ifdef S_IFDOOR
2838           type_cell = S_IFDOOR;
2839           rate = 0.01f;
2840 #else
2841           error (EXIT_FAILURE, 0,
2842                  _("-type %c is not supported because Solaris doors "
2843                    "are not supported on the platform find was compiled on."),
2844                  (*typeletter));
2845 #endif
2846           break;
2847         default:                        /* None of the above ... nuke 'em. */
2848           error (EXIT_FAILURE, 0,
2849                  _("Unknown argument to -type: %c"), (*typeletter));
2850           /*NOTREACHED*/
2851           return false;
2852         }
2853       our_pred = insert_primary_withpred (entry, which_pred, typeletter);
2854       our_pred->est_success_rate = rate;
2855
2856       /* Figure out if we will need to stat the file, because if we don't
2857        * need to follow symlinks, we can avoid a stat call by using
2858        * struct dirent.d_type.
2859        */
2860       if (which_pred == pred_xtype)
2861         {
2862           our_pred->need_stat = true;
2863           our_pred->need_type = false;
2864         }
2865       else
2866         {
2867           our_pred->need_stat = false; /* struct dirent is enough */
2868           our_pred->need_type = true;
2869         }
2870       our_pred->args.type = type_cell;
2871       return true;
2872     }
2873   return false;
2874 }
2875
2876
2877 /* Return true if the file accessed via FP is a terminal.
2878  */
2879 static bool
2880 stream_is_tty (FILE *fp)
2881 {
2882   int fd = fileno (fp);
2883   if (-1 == fd)
2884     {
2885       return false; /* not a valid stream */
2886     }
2887   else
2888     {
2889       return isatty (fd) ? true : false;
2890     }
2891
2892 }
2893
2894
2895
2896
2897
2898
2899 static void
2900 check_path_safety (const char *action)
2901 {
2902   const char *path = getenv ("PATH");
2903   const char *path_separators = ":";
2904   size_t pos, len;
2905
2906   if (NULL == path)
2907     {
2908       /* $PATH is not set.  Assume the OS default is safe.
2909        * That may not be true on Windows, but I'm not aware
2910        * of a way to get Windows to avoid searching the
2911        * current directory anyway.
2912        */
2913       return;
2914     }
2915
2916   splitstring (path, path_separators, true, &pos, &len);
2917   do
2918     {
2919       if (0 == len || (1 == len && path[pos] == '.'))
2920         {
2921           /* empty field signifies . */
2922           error (EXIT_FAILURE, 0,
2923                  _("The current directory is included in the PATH "
2924                    "environment variable, which is insecure in "
2925                    "combination with the %s action of find.  "
2926                    "Please remove the current directory from your "
2927                    "$PATH (that is, remove \".\", doubled colons, "
2928                    "or leading or trailing colons)"),
2929                  action);
2930         }
2931       else if (path[pos] != '/')
2932         {
2933           char *relpath = strndup (&path[pos], len);
2934           error (EXIT_FAILURE, 0,
2935                  _("The relative path %s is included in the PATH "
2936                    "environment variable, which is insecure in "
2937                    "combination with the %s action of find.  "
2938                    "Please remove that entry from $PATH"),
2939                  safely_quote_err_filename (0, relpath ? relpath : &path[pos]),
2940                  action);
2941           /*NOTREACHED*/
2942           free (relpath);
2943         }
2944     } while (splitstring (path, path_separators, false, &pos, &len));
2945 }
2946
2947
2948 /* handles both exec and ok predicate */
2949 static bool
2950 insert_exec_ok (const char *action,
2951                 const struct parser_table *entry,
2952                 char **argv,
2953                 int *arg_ptr)
2954 {
2955   int start, end;               /* Indexes in ARGV of start & end of cmd. */
2956   int i;                        /* Index into cmd args */
2957   int saw_braces;               /* True if previous arg was '{}'. */
2958   bool allow_plus;              /* True if + is a valid terminator */
2959   int brace_count;              /* Number of instances of {}. */
2960   const char *brace_arg;        /* Which arg did {} appear in? */
2961   PRED_FUNC func = entry->pred_func;
2962   enum BC_INIT_STATUS bcstatus;
2963
2964   struct predicate *our_pred;
2965   struct exec_val *execp;       /* Pointer for efficiency. */
2966
2967   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
2968     return false;
2969
2970   our_pred = insert_primary_withpred (entry, func, "(some -exec* arguments)");
2971   our_pred->side_effects = our_pred->no_default_print = true;
2972   our_pred->need_type = our_pred->need_stat = false;
2973
2974   execp = &our_pred->args.exec_vec;
2975   execp->wd_for_exec = NULL;
2976
2977   if ((func != pred_okdir) && (func != pred_ok))
2978     {
2979       allow_plus = true;
2980       execp->close_stdin = false;
2981     }
2982   else
2983     {
2984       allow_plus = false;
2985       /* If find reads stdin (i.e. for -ok and similar), close stdin
2986        * in the child to prevent some script from consiming the output
2987        * intended for find.
2988        */
2989       execp->close_stdin = true;
2990     }
2991
2992
2993   if ((func == pred_execdir) || (func == pred_okdir))
2994     {
2995       execp->wd_for_exec = NULL;
2996       options.ignore_readdir_race = false;
2997       check_path_safety (action);
2998     }
2999   else
3000     {
3001       assert (NULL != initial_wd);
3002       execp->wd_for_exec = initial_wd;
3003     }
3004
3005   our_pred->args.exec_vec.multiple = 0;
3006
3007   /* Count the number of args with path replacements, up until the ';'.
3008    * Also figure out if the command is terminated by ";" or by "+".
3009    */
3010   start = *arg_ptr;
3011   for (end = start, saw_braces=0, brace_count=0, brace_arg=NULL;
3012        (argv[end] != NULL)
3013        && ((argv[end][0] != ';') || (argv[end][1] != '\0'));
3014        end++)
3015     {
3016       /* For -exec and -execdir, "{} +" can terminate the command. */
3017       if ( allow_plus
3018            && argv[end][0] == '+' && argv[end][1] == 0
3019            && saw_braces)
3020         {
3021           our_pred->args.exec_vec.multiple = 1;
3022           break;
3023         }
3024
3025       saw_braces = 0;
3026       if (mbsstr (argv[end], "{}"))
3027         {
3028           saw_braces = 1;
3029           brace_arg = argv[end];
3030           ++brace_count;
3031
3032           if (0 == end && (func == pred_execdir || func == pred_okdir))
3033             {
3034               /* The POSIX standard says that {} replacement should
3035                * occur even in the utility name.  This is insecure
3036                * since it means we will be executing a command whose
3037                * name is chosen according to whatever find finds in
3038                * the file system.  That can be influenced by an
3039                * attacker.  Hence for -execdir and -okdir this is not
3040                * allowed.  We can specify this as those options are
3041                * not defined by POSIX.
3042                */
3043               error (EXIT_FAILURE, 0,
3044                      _("You may not use {} within the utility name for "
3045                        "-execdir and -okdir, because this is a potential "
3046                        "security problem."));
3047             }
3048         }
3049     }
3050
3051   /* Fail if no command given or no semicolon found. */
3052   if ((end == start) || (argv[end] == NULL))
3053     {
3054       *arg_ptr = end;
3055       free (our_pred);
3056       return false;
3057     }
3058
3059   if (our_pred->args.exec_vec.multiple)
3060     {
3061       const char *suffix;
3062       if (func == pred_execdir)
3063         suffix = "dir";
3064       else
3065         suffix = "";
3066
3067       if (brace_count > 1)
3068         {
3069           error (EXIT_FAILURE, 0,
3070                  _("Only one instance of {} is supported with -exec%s ... +"),
3071                  suffix);
3072         }
3073       else if (strlen (brace_arg) != 2u)
3074         {
3075           enum { MsgBufSize = 19 };
3076           char buf[MsgBufSize];
3077           const size_t needed = snprintf (buf, MsgBufSize, "-exec%s ... {} +", suffix);
3078           assert (needed <= MsgBufSize);  /* If this assertion fails, correct the value of MsgBufSize. */
3079           error (EXIT_FAILURE, 0,
3080                  _("In %s the %s must appear by itself, but you specified %s"),
3081                  quotearg_n_style (0, options.err_quoting_style, buf),
3082                  quotearg_n_style (1, options.err_quoting_style, "{}"),
3083                  quotearg_n_style (2, options.err_quoting_style, brace_arg));
3084         }
3085     }
3086
3087   /* We use a switch statement here so that the compiler warns us when
3088    * we forget to handle a newly invented enum value.
3089    *
3090    * Like xargs, we allow 2KiB of headroom for the launched utility to
3091    * export its own environment variables before calling something
3092    * else.
3093    */
3094   bcstatus = bc_init_controlinfo (&execp->ctl, 2048u);
3095   switch (bcstatus)
3096     {
3097     case BC_INIT_ENV_TOO_BIG:
3098     case BC_INIT_CANNOT_ACCOMODATE_HEADROOM:
3099       error (EXIT_FAILURE, 0,
3100              _("The environment is too large for exec()."));
3101       break;
3102     case BC_INIT_OK:
3103       /* Good news.  Carry on. */
3104       break;
3105     }
3106   bc_use_sensible_arg_max (&execp->ctl);
3107
3108
3109   execp->ctl.exec_callback = launch;
3110
3111   if (our_pred->args.exec_vec.multiple)
3112     {
3113       /* "+" terminator, so we can just append our arguments after the
3114        * command and initial arguments.
3115        */
3116       execp->replace_vec = NULL;
3117       execp->ctl.replace_pat = NULL;
3118       execp->ctl.rplen = 0;
3119       execp->ctl.lines_per_exec = 0; /* no limit */
3120       execp->ctl.args_per_exec = 0; /* no limit */
3121
3122       /* remember how many arguments there are */
3123       execp->ctl.initial_argc = (end-start) - 1;
3124
3125       /* execp->state = xmalloc(sizeof struct buildcmd_state); */
3126       bc_init_state (&execp->ctl, &execp->state, execp);
3127
3128       /* Gather the initial arguments.  Skip the {}. */
3129       for (i=start; i<end-1; ++i)
3130         {
3131           bc_push_arg (&execp->ctl, &execp->state,
3132                        argv[i], strlen (argv[i])+1,
3133                        NULL, 0,
3134                        1);
3135         }
3136     }
3137   else
3138     {
3139       /* Semicolon terminator - more than one {} is supported, so we
3140        * have to do brace-replacement.
3141        */
3142       execp->num_args = end - start;
3143
3144       execp->ctl.replace_pat = "{}";
3145       execp->ctl.rplen = strlen (execp->ctl.replace_pat);
3146       execp->ctl.lines_per_exec = 0; /* no limit */
3147       execp->ctl.args_per_exec = 0; /* no limit */
3148       execp->replace_vec = xmalloc (sizeof(char*)*execp->num_args);
3149
3150
3151       /* execp->state = xmalloc(sizeof(*(execp->state))); */
3152       bc_init_state (&execp->ctl, &execp->state, execp);
3153
3154       /* Remember the (pre-replacement) arguments for later. */
3155       for (i=0; i<execp->num_args; ++i)
3156         {
3157           execp->replace_vec[i] = argv[i+start];
3158         }
3159     }
3160
3161   if (argv[end] == NULL)
3162     *arg_ptr = end;
3163   else
3164     *arg_ptr = end + 1;
3165
3166   return true;
3167 }
3168
3169
3170
3171 /* Get a timestamp and comparison type.
3172
3173    STR is the ASCII representation.
3174    Set *NUM_DAYS to the number of days/minutes/whatever, taken as being
3175    relative to ORIGIN (usually the current moment or midnight).
3176    Thus the sense of the comparison type appears to be reversed.
3177    Set *COMP_TYPE to the kind of comparison that is requested.
3178    Issue OVERFLOWMESSAGE if overflow occurs.
3179    Return true if all okay, false if input error.
3180
3181    Used by -atime, -ctime and -mtime (parsers) to
3182    get the appropriate information for a time predicate processor. */
3183
3184 static bool
3185 get_relative_timestamp (const char *str,
3186                         struct time_val *result,
3187                         struct timespec origin,
3188                         double sec_per_unit,
3189                         const char *overflowmessage)
3190 {
3191   double offset, seconds, nanosec;
3192   static const long nanosec_per_sec = 1000000000;
3193
3194   if (get_comp_type (&str, &result->kind))
3195     {
3196       /* Invert the sense of the comparison */
3197       switch (result->kind)
3198         {
3199         case COMP_LT: result->kind = COMP_GT; break;
3200         case COMP_GT: result->kind = COMP_LT; break;
3201         case COMP_EQ:
3202           break; /* inversion leaves it unchanged */
3203         }
3204
3205       /* Convert the ASCII number into floating-point. */
3206       if (xstrtod (str, NULL, &offset, strtod))
3207         {
3208           /* Separate the floating point number the user specified
3209            * (which is a number of days, or minutes, etc) into an
3210            * integral number of seconds (SECONDS) and a fraction (NANOSEC).
3211            */
3212           nanosec = modf (offset * sec_per_unit, &seconds);
3213           nanosec *= 1.0e9;     /* convert from fractional seconds to ns. */
3214           assert (nanosec < nanosec_per_sec);
3215
3216           /* Perform the subtraction, and then check for overflow.
3217            * On systems where signed aritmetic overflow does not
3218            * wrap, this check may be unreliable.   The C standard
3219            * does not require this approach to work, but I am aware
3220            * of no platforms where it fails.
3221            */
3222           result->ts.tv_sec  = origin.tv_sec - seconds;
3223           if ((origin.tv_sec < result->ts.tv_sec) != (seconds < 0))
3224             {
3225               /* an overflow has occurred. */
3226               error (EXIT_FAILURE, 0, overflowmessage, str);
3227             }
3228
3229           result->ts.tv_nsec = origin.tv_nsec - nanosec;
3230           if (origin.tv_nsec < nanosec)
3231             {
3232               /* Perform a carry operation */
3233               result->ts.tv_nsec += nanosec_per_sec;
3234               result->ts.tv_sec  -= 1;
3235             }
3236           return true;
3237         }
3238       else
3239         {
3240           /* Conversion from ASCII to double failed. */
3241           return false;
3242         }
3243     }
3244   else
3245     {
3246       return false;
3247     }
3248 }
3249
3250 /* Insert a time predicate based on the information in ENTRY.
3251    ARGV is a pointer to the argument array.
3252    ARG_PTR is a pointer to an index into the array, incremented if
3253    all went well.
3254
3255    Return true if input is valid, false if not.
3256
3257    A new predicate node is assigned, along with an argument node
3258    obtained with malloc.
3259
3260    Used by -atime, -ctime, and -mtime parsers. */
3261
3262 static bool
3263 parse_time (const struct parser_table* entry, char *argv[], int *arg_ptr)
3264 {
3265   struct predicate *our_pred;
3266   struct time_val tval;
3267   enum comparison_type comp;
3268   const char *timearg, *orig_timearg;
3269   const char *errmsg = _("arithmetic overflow while converting %s "
3270                          "days to a number of seconds");
3271   struct timespec origin;
3272   const int saved_argc = *arg_ptr;
3273
3274   if (!collect_arg (argv, arg_ptr, &timearg))
3275     return false;
3276   orig_timearg = timearg;
3277
3278   /* Decide the origin by previewing the comparison type. */
3279   origin = options.cur_day_start;
3280
3281   if (get_comp_type (&timearg, &comp))
3282     {
3283       /* Remember, we invert the sense of the comparison, so this tests
3284        * against COMP_LT instead of COMP_GT...
3285        */
3286       if (COMP_LT == comp)
3287         {
3288           uintmax_t expected = origin.tv_sec + (DAYSECS-1);
3289           origin.tv_sec += (DAYSECS-1);
3290           if (origin.tv_sec != expected)
3291             {
3292               error (EXIT_FAILURE, 0,
3293                      _("arithmetic overflow when trying to calculate the end of today"));
3294             }
3295         }
3296     }
3297   /* We discard the value of comp here, as get_relative_timestamp
3298    * will set tval.kind.  For that to work, we have to restore
3299    * timearg so that it points to the +/- prefix, if any.  get_comp_type()
3300    * will have advanced timearg, so we restore it.
3301    */
3302   timearg = orig_timearg;
3303
3304   if (!get_relative_timestamp (timearg, &tval, origin, DAYSECS, errmsg))
3305     {
3306       *arg_ptr = saved_argc;    /* don't consume the invalid argument */
3307       return false;
3308     }
3309
3310   our_pred = insert_primary (entry, orig_timearg);
3311   our_pred->args.reftime = tval;
3312   our_pred->est_success_rate = estimate_timestamp_success_rate (tval.ts.tv_sec);
3313
3314   if (options.debug_options & DebugExpressionTree)
3315     {
3316       time_t t;
3317
3318       fprintf (stderr, "inserting %s\n", our_pred->p_name);
3319       fprintf (stderr, "    type: %s    %s  ",
3320                (tval.kind == COMP_GT) ? "gt" :
3321                ((tval.kind == COMP_LT) ? "lt" : ((tval.kind == COMP_EQ) ? "eq" : "?")),
3322                (tval.kind == COMP_GT) ? " >" :
3323                ((tval.kind == COMP_LT) ? " <" : ((tval.kind == COMP_EQ) ? ">=" : " ?")));
3324       t = our_pred->args.reftime.ts.tv_sec;
3325       fprintf (stderr, "%ju %s",
3326                (uintmax_t) our_pred->args.reftime.ts.tv_sec,
3327                ctime (&t));
3328       if (tval.kind == COMP_EQ)
3329         {
3330           t = our_pred->args.reftime.ts.tv_sec + DAYSECS;
3331           fprintf (stderr, "                 <  %ju %s",
3332                    (uintmax_t) t, ctime (&t));
3333         }
3334     }
3335
3336   return true;
3337 }
3338
3339 /* Get the comparison type prefix (if any) from a number argument.
3340    The prefix is at *STR.
3341    Set *COMP_TYPE to the kind of comparison that is requested.
3342    Advance *STR beyond any initial comparison prefix.
3343
3344    Return true if all okay, false if input error.  */
3345 static bool
3346 get_comp_type (const char **str, enum comparison_type *comp_type)
3347 {
3348   switch (**str)
3349     {
3350     case '+':
3351       *comp_type = COMP_GT;
3352       (*str)++;
3353       break;
3354     case '-':
3355       *comp_type = COMP_LT;
3356       (*str)++;
3357       break;
3358     default:
3359       *comp_type = COMP_EQ;
3360       break;
3361     }
3362   return true;
3363 }
3364
3365
3366
3367
3368
3369 /* Get a number with comparison information.
3370    The sense of the comparison information is 'normal'; that is,
3371    '+' looks for a count > than the number and '-' less than.
3372
3373    STR is the ASCII representation of the number.
3374    Set *NUM to the number.
3375    Set *COMP_TYPE to the kind of comparison that is requested.
3376
3377    Return true if all okay, false if input error.  */
3378
3379 static bool
3380 get_num (const char *str,
3381          uintmax_t *num,
3382          enum comparison_type *comp_type)
3383 {
3384   char *pend;
3385
3386   if (str == NULL)
3387     return false;
3388
3389   /* Figure out the comparison type if the caller accepts one. */
3390   if (comp_type)
3391     {
3392       if (!get_comp_type (&str, comp_type))
3393         return false;
3394     }
3395
3396   return xstrtoumax (str, &pend, 10, num, "") == LONGINT_OK;
3397 }
3398
3399 /* Insert a number predicate.
3400    ARGV is a pointer to the argument array.
3401    *ARG_PTR is an index into ARGV, incremented if all went well.
3402    *PRED is the predicate processor to insert.
3403
3404    Return true if input is valid, false if error.
3405
3406    A new predicate node is assigned, along with an argument node
3407    obtained with malloc.
3408
3409    Used by -inum and -links parsers. */
3410
3411 static struct predicate *
3412 insert_num (char **argv, int *arg_ptr, const struct parser_table *entry)
3413 {
3414   const char *numstr;
3415
3416   if (collect_arg (argv, arg_ptr, &numstr))
3417   {
3418     uintmax_t num;
3419     enum comparison_type c_type;
3420
3421     if (get_num (numstr, &num, &c_type))
3422       {
3423         struct predicate *our_pred = insert_primary (entry, numstr);
3424         our_pred->args.numinfo.kind = c_type;
3425         our_pred->args.numinfo.l_val = num;
3426
3427         if (options.debug_options & DebugExpressionTree)
3428           {
3429             fprintf (stderr, "inserting %s\n", our_pred->p_name);
3430             fprintf (stderr, "    type: %s    %s  ",
3431                      (c_type == COMP_GT) ? "gt" :
3432                      ((c_type == COMP_LT) ? "lt" : ((c_type == COMP_EQ) ? "eq" : "?")),
3433                      (c_type == COMP_GT) ? " >" :
3434                      ((c_type == COMP_LT) ? " <" : ((c_type == COMP_EQ) ? " =" : " ?")));
3435             fprintf (stderr, "%ju\n", our_pred->args.numinfo.l_val);
3436           }
3437         return our_pred;
3438       }
3439   }
3440   return NULL;
3441 }
3442
3443 static void
3444 open_output_file (const char *path, struct format_val *p)
3445 {
3446   p->segment = NULL;
3447   p->quote_opts = clone_quoting_options (NULL);
3448
3449   if (!strcmp (path, "/dev/stderr"))
3450     {
3451       p->stream = stderr;
3452       p->filename = _("standard error");
3453     }
3454   else if (!strcmp (path, "/dev/stdout"))
3455     {
3456       p->stream = stdout;
3457       p->filename = _("standard output");
3458     }
3459   else
3460     {
3461       p->stream = sharefile_fopen (state.shared_files, path);
3462       p->filename = path;
3463
3464       if (p->stream == NULL)
3465         {
3466           fatal_nontarget_file_error (errno, path);
3467         }
3468     }
3469
3470   p->dest_is_tty = stream_is_tty (p->stream);
3471 }
3472
3473 static void
3474 open_stdout (struct format_val *p)
3475 {
3476   open_output_file ("/dev/stdout", p);
3477 }