Document addition of %S.
[findutils.git] / find / parser.c
blob4ace53bc9951a8e9357814eafdfe806eefd598b6
1 /* parser.c -- convert the command line args into an expression tree.
2 Copyright (C) 1990, 1991, 1992, 1993, 1994, 2000, 2001, 2003,
3 2004, 2005, 2006 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
18 USA.
22 #include "defs.h"
23 #include <ctype.h>
24 #include <assert.h>
25 #include <pwd.h>
26 #include <grp.h>
27 #include <fnmatch.h>
28 #include "modechange.h"
29 #include "modetype.h"
30 #include "xstrtol.h"
31 #include "xalloc.h"
32 #include "quote.h"
33 #include "quotearg.h"
34 #include "buildcmd.h"
35 #include "nextelem.h"
36 #include "stdio-safer.h"
37 #include "regextype.h"
39 #ifdef HAVE_FCNTL_H
40 #include <fcntl.h>
41 #else
42 #include <sys/file.h>
43 #endif
45 /* The presence of unistd.h is assumed by gnulib these days, so we
46 * might as well assume it too.
48 /* We need <unistd.h> for isatty(). */
49 #include <unistd.h>
51 #if ENABLE_NLS
52 # include <libintl.h>
53 # define _(Text) gettext (Text)
54 #else
55 # define _(Text) Text
56 #endif
57 #ifdef gettext_noop
58 # define N_(String) gettext_noop (String)
59 #else
60 /* See locate.c for explanation as to why not use (String) */
61 # define N_(String) String
62 #endif
64 #if !defined (isascii) || defined (STDC_HEADERS)
65 #ifdef isascii
66 #undef isascii
67 #endif
68 #define isascii(c) 1
69 #endif
71 #define ISDIGIT(c) (isascii ((unsigned char)c) && isdigit ((unsigned char)c))
72 #define ISUPPER(c) (isascii ((unsigned char)c) && isupper ((unsigned char)c))
74 #ifndef HAVE_ENDGRENT
75 #define endgrent()
76 #endif
77 #ifndef HAVE_ENDPWENT
78 #define endpwent()
79 #endif
81 static boolean parse_accesscheck PARAMS((const struct parser_table* entry, char **argv, int *arg_ptr));
82 static boolean parse_amin PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
83 static boolean parse_and PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
84 static boolean parse_anewer PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
85 static boolean parse_cmin PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
86 static boolean parse_cnewer PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
87 static boolean parse_comma PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
88 static boolean parse_daystart PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
89 static boolean parse_delete PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
90 static boolean parse_d PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
91 static boolean parse_depth PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
92 static boolean parse_empty PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
93 static boolean parse_exec PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
94 static boolean parse_execdir PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
95 static boolean parse_false PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
96 static boolean parse_fls PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
97 static boolean parse_fprintf PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
98 static boolean parse_follow PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
99 static boolean parse_fprint PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
100 static boolean parse_fprint0 PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
101 static boolean parse_fstype PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
102 static boolean parse_gid PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
103 static boolean parse_group PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
104 static boolean parse_help PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
105 static boolean parse_ilname PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
106 static boolean parse_iname PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
107 static boolean parse_inum PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
108 static boolean parse_ipath PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
109 static boolean parse_iregex PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
110 static boolean parse_iwholename PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
111 static boolean parse_links PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
112 static boolean parse_lname PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
113 static boolean parse_ls PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
114 static boolean parse_maxdepth PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
115 static boolean parse_mindepth PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
116 static boolean parse_mmin PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
117 static boolean parse_name PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
118 static boolean parse_negate PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
119 static boolean parse_newer PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
120 static boolean parse_noleaf PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
121 static boolean parse_nogroup PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
122 static boolean parse_nouser PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
123 static boolean parse_nowarn PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
124 static boolean parse_ok PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
125 static boolean parse_okdir PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
126 static boolean parse_or PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
127 static boolean parse_path PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
128 static boolean parse_perm PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
129 static boolean parse_print0 PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
130 static boolean parse_printf PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
131 static boolean parse_prune PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
132 static boolean parse_regex PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
133 static boolean parse_regextype PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
134 static boolean parse_samefile PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
135 #if 0
136 static boolean parse_show_control_chars PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
137 #endif
138 static boolean parse_size PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
139 static boolean parse_time PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
140 static boolean parse_true PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
141 static boolean parse_type PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
142 static boolean parse_uid PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
143 static boolean parse_used PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
144 static boolean parse_user PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
145 static boolean parse_version PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
146 static boolean parse_wholename PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
147 static boolean parse_xdev PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
148 static boolean parse_ignore_race PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
149 static boolean parse_noignore_race PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
150 static boolean parse_warn PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
151 static boolean parse_xtype PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
152 static boolean parse_quit PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
154 boolean parse_print PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
157 static boolean insert_type PARAMS((char **argv, int *arg_ptr, const struct parser_table *entry, PRED_FUNC which_pred));
158 static boolean insert_regex PARAMS((char *argv[], int *arg_ptr, const struct parser_table *entry, int regex_options));
159 static boolean insert_fprintf PARAMS((FILE *fp, const struct parser_table *entry, PRED_FUNC func, char *argv[], int *arg_ptr));
161 static struct segment **make_segment PARAMS((struct segment **segment, char *format, int len,
162 int kind, char format_char, char aux_format_char,
163 struct predicate *pred));
164 static boolean insert_exec_ok PARAMS((const char *action, const struct parser_table *entry, char *argv[], int *arg_ptr));
165 static boolean get_num_days PARAMS((char *str, uintmax_t *num_days, enum comparison_type *comp_type));
166 static boolean get_num PARAMS((char *str, uintmax_t *num, enum comparison_type *comp_type));
167 static struct predicate* insert_num PARAMS((char *argv[], int *arg_ptr, const struct parser_table *entry));
168 static FILE *open_output_file PARAMS((char *path));
169 static boolean stream_is_tty(FILE *fp);
170 static boolean parse_noop PARAMS((const struct parser_table* entry, char **argv, int *arg_ptr));
172 #define PASTE(x,y) x##y
173 #define STRINGIFY(s) #s
175 #define PARSE_OPTION(what,suffix) \
176 { (ARG_OPTION), (what), PASTE(parse_,suffix), NULL }
178 #define PARSE_POSOPT(what,suffix) \
179 { (ARG_POSITIONAL_OPTION), (what), PASTE(parse_,suffix), NULL }
181 #define PARSE_TEST(what,suffix) \
182 { (ARG_TEST), (what), PASTE(parse_,suffix), PASTE(pred_,suffix) }
184 #define PARSE_TEST_NP(what,suffix) \
185 { (ARG_TEST), (what), PASTE(parse_,suffix), NULL }
187 #define PARSE_ACTION(what,suffix) \
188 { (ARG_ACTION), (what), PASTE(parse_,suffix), PASTE(pred_,suffix) }
190 #define PARSE_ACTION_NP(what,suffix) \
191 { (ARG_ACTION), (what), PASTE(parse_,suffix), NULL }
193 #define PARSE_PUNCTUATION(what,suffix) \
194 { (ARG_PUNCTUATION), (what), PASTE(parse_,suffix), PASTE(pred_,suffix) }
197 /* GNU find predicates that are not mentioned in POSIX.2 are marked `GNU'.
198 If they are in some Unix versions of find, they are marked `Unix'. */
200 static struct parser_table const parse_table[] =
202 PARSE_PUNCTUATION("!", negate),
203 PARSE_PUNCTUATION("not", negate), /* GNU */
204 PARSE_PUNCTUATION("(", open),
205 PARSE_PUNCTUATION(")", close),
206 PARSE_PUNCTUATION(",", comma), /* GNU */
207 PARSE_PUNCTUATION("a", and),
208 PARSE_TEST ("amin", amin), /* GNU */
209 PARSE_PUNCTUATION("and", and), /* GNU */
210 PARSE_TEST ("anewer", anewer), /* GNU */
211 {ARG_TEST, "atime", parse_time, pred_atime},
212 PARSE_TEST ("cmin", cmin), /* GNU */
213 PARSE_TEST ("cnewer", cnewer), /* GNU */
214 {ARG_TEST, "ctime", parse_time, pred_ctime},
215 PARSE_POSOPT ("daystart", daystart), /* GNU */
216 PARSE_ACTION ("delete", delete), /* GNU, Mac OS, FreeBSD */
217 PARSE_OPTION ("d", d), /* Mac OS X, FreeBSD, NetBSD, OpenBSD, but deprecated in favour of -depth */
218 PARSE_OPTION ("depth", depth),
219 PARSE_TEST ("empty", empty), /* GNU */
220 {ARG_ACTION, "exec", parse_exec, pred_exec}, /* POSIX */
221 {ARG_TEST, "executable", parse_accesscheck, pred_executable}, /* GNU, 4.3.0+ */
222 PARSE_ACTION ("execdir", execdir), /* *BSD, GNU */
223 PARSE_ACTION ("fls", fls), /* GNU */
224 PARSE_POSOPT ("follow", follow), /* GNU, Unix */
225 PARSE_ACTION ("fprint", fprint), /* GNU */
226 PARSE_ACTION ("fprint0", fprint0), /* GNU */
227 {ARG_ACTION, "fprintf", parse_fprintf, pred_fprintf}, /* GNU */
228 PARSE_TEST ("fstype", fstype), /* GNU, Unix */
229 PARSE_TEST ("gid", gid), /* GNU */
230 PARSE_TEST ("group", group),
231 PARSE_OPTION ("ignore_readdir_race", ignore_race), /* GNU */
232 PARSE_TEST ("ilname", ilname), /* GNU */
233 PARSE_TEST ("iname", iname), /* GNU */
234 PARSE_TEST ("inum", inum), /* GNU, Unix */
235 PARSE_TEST ("ipath", ipath), /* GNU, deprecated in favour of iwholename */
236 PARSE_TEST_NP ("iregex", iregex), /* GNU */
237 PARSE_TEST_NP ("iwholename", iwholename), /* GNU */
238 PARSE_TEST ("links", links),
239 PARSE_TEST ("lname", lname), /* GNU */
240 PARSE_ACTION ("ls", ls), /* GNU, Unix */
241 PARSE_OPTION ("maxdepth", maxdepth), /* GNU */
242 PARSE_OPTION ("mindepth", mindepth), /* GNU */
243 PARSE_TEST ("mmin", mmin), /* GNU */
244 PARSE_OPTION ("mount", xdev), /* Unix */
245 {ARG_TEST, "mtime", parse_time, pred_mtime},
246 PARSE_TEST ("name", name),
247 #ifdef UNIMPLEMENTED_UNIX
248 PARSE(ARG_UNIMPLEMENTED, "ncpio", ncpio), /* Unix */
249 #endif
250 PARSE_TEST ("newer", newer),
251 PARSE_OPTION ("noleaf", noleaf), /* GNU */
252 PARSE_TEST ("nogroup", nogroup),
253 PARSE_TEST ("nouser", nouser),
254 PARSE_OPTION ("noignore_readdir_race", noignore_race), /* GNU */
255 PARSE_POSOPT ("nowarn", nowarn), /* GNU */
256 PARSE_PUNCTUATION("o", or),
257 PARSE_PUNCTUATION("or", or), /* GNU */
258 PARSE_ACTION ("ok", ok),
259 PARSE_ACTION ("okdir", okdir), /* GNU (-execdir is BSD) */
260 PARSE_TEST ("path", path), /* GNU, HP-UX, GNU prefers wholename */
261 PARSE_TEST ("perm", perm),
262 PARSE_ACTION ("print", print),
263 PARSE_ACTION ("print0", print0), /* GNU */
264 {ARG_ACTION, "printf", parse_printf, NULL}, /* GNU */
265 PARSE_ACTION ("prune", prune),
266 PARSE_ACTION ("quit", quit), /* GNU */
267 {ARG_TEST, "readable", parse_accesscheck, pred_readable}, /* GNU, 4.3.0+ */
268 PARSE_TEST ("regex", regex), /* GNU */
269 PARSE_OPTION ("regextype", regextype), /* GNU */
270 PARSE_TEST ("samefile", samefile), /* GNU */
271 #if 0
272 PARSE_OPTION ("show-control-chars", show_control_chars), /* GNU, 4.3.0+ */
273 #endif
274 PARSE_TEST ("size", size),
275 PARSE_TEST ("type", type),
276 PARSE_TEST ("uid", uid), /* GNU */
277 PARSE_TEST ("used", used), /* GNU */
278 PARSE_TEST ("user", user),
279 PARSE_OPTION ("warn", warn), /* GNU */
280 PARSE_TEST_NP ("wholename", wholename), /* GNU, replaces -path */
281 {ARG_TEST, "writable", parse_accesscheck, pred_writable}, /* GNU, 4.3.0+ */
282 PARSE_OPTION ("xdev", xdev),
283 PARSE_TEST ("xtype", xtype), /* GNU */
284 #ifdef UNIMPLEMENTED_UNIX
285 /* It's pretty ugly for find to know about archive formats.
286 Plus what it could do with cpio archives is very limited.
287 Better to leave it out. */
288 PARSE(ARG_UNIMPLEMENTED, "cpio", cpio), /* Unix */
289 #endif
290 /* gnulib's stdbool.h might have made true and false into macros,
291 * so we can't leave named 'true' and 'false' tokens, so we have
292 * to expeant the relevant entries longhand.
294 {ARG_TEST, "false", parse_false, pred_false}, /* GNU */
295 {ARG_TEST, "true", parse_true, pred_true }, /* GNU */
296 {ARG_NOOP, "noop", NULL, pred_true }, /* GNU, internal use only */
298 /* Various other cases that don't fit neatly into our macro scheme. */
299 {ARG_TEST, "help", parse_help, NULL}, /* GNU */
300 {ARG_TEST, "-help", parse_help, NULL}, /* GNU */
301 {ARG_TEST, "version", parse_version, NULL}, /* GNU */
302 {ARG_TEST, "-version", parse_version, NULL}, /* GNU */
303 {0, 0, 0, 0}
307 static const char *first_nonoption_arg = NULL;
308 static const struct parser_table *noop = NULL;
312 static const struct parser_table*
313 get_noop(void)
315 int i;
316 if (NULL == noop)
318 for (i = 0; parse_table[i].parser_name != 0; i++)
320 if (ARG_NOOP ==parse_table[i].type)
322 noop = &(parse_table[i]);
323 break;
327 return noop;
332 void
333 set_follow_state(enum SymlinkOption opt)
335 if (options.debug_options & DebugStat)
337 /* For DebugStat, the choice is made at runtime within debug_stat()
338 * by checking the contents of the symlink_handling variable.
340 options.xstat = debug_stat;
342 else
344 switch (opt)
346 case SYMLINK_ALWAYS_DEREF: /* -L */
347 options.xstat = optionl_stat;
348 options.no_leaf_check = true;
349 break;
351 case SYMLINK_NEVER_DEREF: /* -P (default) */
352 options.xstat = optionp_stat;
353 /* Can't turn no_leaf_check off because the user might have specified
354 * -noleaf anyway
356 break;
358 case SYMLINK_DEREF_ARGSONLY: /* -H */
359 options.xstat = optionh_stat;
360 options.no_leaf_check = true;
363 options.symlink_handling = opt;
367 void
368 parse_begin_user_args (char **args, int argno, const struct predicate *last, const struct predicate *predicates)
370 (void) args;
371 (void) argno;
372 (void) last;
373 (void) predicates;
374 first_nonoption_arg = NULL;
377 void
378 parse_end_user_args (char **args, int argno, const struct predicate *last, const struct predicate *predicates)
380 /* does nothing */
381 (void) args;
382 (void) argno;
383 (void) last;
384 (void) predicates;
390 /* Return a pointer to the parser function to invoke for predicate
391 SEARCH_NAME.
392 Return NULL if SEARCH_NAME is not a valid predicate name. */
394 const struct parser_table*
395 find_parser (char *search_name)
397 int i;
398 const char *original_arg = search_name;
400 if (*search_name == '-')
401 search_name++;
402 for (i = 0; parse_table[i].parser_name != 0; i++)
404 if (strcmp (parse_table[i].parser_name, search_name) == 0)
406 /* If this is an option, but we have already had a
407 * non-option argument, the user may be under the
408 * impression that the behaviour of the option
409 * argument is conditional on some preceding
410 * tests. This might typically be the case with,
411 * for example, -maxdepth.
413 * The options -daystart and -follow are exempt
414 * from this treatment, since their positioning
415 * in the command line does have an effect on
416 * subsequent tests but not previous ones. That
417 * might be intentional on the part of the user.
419 if (parse_table[i].type != ARG_POSITIONAL_OPTION)
421 /* Something other than -follow/-daystart.
422 * If this is an option, check if it followed
423 * a non-option and if so, issue a warning.
425 if (parse_table[i].type == ARG_OPTION)
427 if ((first_nonoption_arg != NULL)
428 && options.warnings )
430 /* option which follows a non-option */
431 error (0, 0,
432 _("warning: you have specified the %s "
433 "option after a non-option argument %s, "
434 "but options are not positional (%s affects "
435 "tests specified before it as well as those "
436 "specified after it). Please specify options "
437 "before other arguments.\n"),
438 original_arg,
439 first_nonoption_arg,
440 original_arg);
443 else
445 /* Not an option or a positional option,
446 * so remember we've seen it in order to
447 * use it in a possible future warning message.
449 if (first_nonoption_arg == NULL)
451 first_nonoption_arg = original_arg;
456 return &parse_table[i];
459 return NULL;
462 static float
463 estimate_file_age_success_rate(float num_days)
465 if (num_days < 0.1)
467 /* Assume 1% of files have timestamps in the future */
468 return 0.01f;
470 else if (num_days < 1)
472 /* Assume 30% of files have timestamps today */
473 return 0.3f;
475 else if (num_days > 100)
477 /* Assume 30% of files are very old */
478 return 0.3f;
480 else
482 /* Assume 39% of files are between 1 and 100 days old. */
483 return 0.39f;
487 static float
488 estimate_timestamp_success_rate(time_t when)
490 int num_days = (when - options.cur_day_start) / 86400;
491 return estimate_file_age_success_rate(num_days);
495 /* The parsers are responsible to continue scanning ARGV for
496 their arguments. Each parser knows what is and isn't
497 allowed for itself.
499 ARGV is the argument array.
500 *ARG_PTR is the index to start at in ARGV,
501 updated to point beyond the last element consumed.
503 The predicate structure is updated with the new information. */
505 static boolean
506 parse_amin (const struct parser_table* entry, char **argv, int *arg_ptr)
508 struct predicate *our_pred;
509 uintmax_t num;
510 enum comparison_type c_type;
511 time_t t;
513 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
514 return false;
515 if (!get_num_days (argv[*arg_ptr], &num, &c_type))
516 return false;
517 t = options.cur_day_start + DAYSECS - num * 60;
518 our_pred = insert_primary (entry);
519 our_pred->args.info.kind = c_type;
520 our_pred->args.info.negative = t < 0;
521 our_pred->args.info.l_val = t;
522 our_pred->est_success_rate = estimate_file_age_success_rate(num);
523 (*arg_ptr)++;
524 return true;
527 static boolean
528 parse_and (const struct parser_table* entry, char **argv, int *arg_ptr)
530 struct predicate *our_pred;
532 (void) argv;
533 (void) arg_ptr;
535 our_pred = get_new_pred (entry);
536 our_pred->pred_func = pred_and;
537 our_pred->p_type = BI_OP;
538 our_pred->p_prec = AND_PREC;
539 our_pred->need_stat = our_pred->need_type = false;
540 return true;
543 static boolean
544 parse_anewer (const struct parser_table* entry, char **argv, int *arg_ptr)
546 struct predicate *our_pred;
547 struct stat stat_newer;
549 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
550 return false;
551 if ((*options.xstat) (argv[*arg_ptr], &stat_newer))
552 error (1, errno, "%s", argv[*arg_ptr]);
553 our_pred = insert_primary (entry);
554 our_pred->args.time = stat_newer.st_mtime;
555 our_pred->est_success_rate = estimate_timestamp_success_rate(stat_newer.st_mtime);
556 (*arg_ptr)++;
557 return true;
560 boolean
561 parse_close (const struct parser_table* entry, char **argv, int *arg_ptr)
563 struct predicate *our_pred;
565 (void) argv;
566 (void) arg_ptr;
568 our_pred = get_new_pred (entry);
569 our_pred->pred_func = pred_close;
570 our_pred->p_type = CLOSE_PAREN;
571 our_pred->p_prec = NO_PREC;
572 our_pred->need_stat = our_pred->need_type = false;
573 return true;
576 static boolean
577 parse_cmin (const struct parser_table* entry, char **argv, int *arg_ptr)
579 struct predicate *our_pred;
580 uintmax_t num;
581 enum comparison_type c_type;
582 time_t t;
584 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
585 return false;
586 if (!get_num_days (argv[*arg_ptr], &num, &c_type))
587 return false;
588 t = options.cur_day_start + DAYSECS - num * 60;
589 our_pred = insert_primary (entry);
590 our_pred->args.info.kind = c_type;
591 our_pred->args.info.negative = t < 0;
592 our_pred->args.info.l_val = t;
593 our_pred->est_success_rate = estimate_file_age_success_rate(num);
594 (*arg_ptr)++;
595 return true;
598 static boolean
599 parse_cnewer (const struct parser_table* entry, char **argv, int *arg_ptr)
601 struct predicate *our_pred;
602 struct stat stat_newer;
604 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
605 return false;
606 if ((*options.xstat) (argv[*arg_ptr], &stat_newer))
607 error (1, errno, "%s", argv[*arg_ptr]);
608 our_pred = insert_primary (entry);
609 our_pred->args.time = stat_newer.st_mtime;
610 our_pred->est_success_rate = estimate_timestamp_success_rate(stat_newer.st_mtime);
611 (*arg_ptr)++;
612 return true;
615 static boolean
616 parse_comma (const struct parser_table* entry, char **argv, int *arg_ptr)
618 struct predicate *our_pred;
620 (void) argv;
621 (void) arg_ptr;
623 our_pred = get_new_pred (entry);
624 our_pred->pred_func = pred_comma;
625 our_pred->p_type = BI_OP;
626 our_pred->p_prec = COMMA_PREC;
627 our_pred->need_stat = our_pred->need_type = false;
628 our_pred->est_success_rate = 1.0f;
629 return true;
632 static boolean
633 parse_daystart (const struct parser_table* entry, char **argv, int *arg_ptr)
635 struct tm *local;
637 (void) entry;
638 (void) argv;
639 (void) arg_ptr;
641 if (options.full_days == false)
643 options.cur_day_start += DAYSECS;
644 local = localtime (&options.cur_day_start);
645 options.cur_day_start -= (local
646 ? (local->tm_sec + local->tm_min * 60
647 + local->tm_hour * 3600)
648 : options.cur_day_start % DAYSECS);
649 options.full_days = true;
651 return true;
654 static boolean
655 parse_delete (const struct parser_table* entry, char *argv[], int *arg_ptr)
657 struct predicate *our_pred;
658 (void) argv;
659 (void) arg_ptr;
661 our_pred = insert_primary (entry);
662 our_pred->side_effects = our_pred->no_default_print = true;
663 /* -delete implies -depth */
664 options.do_dir_first = false;
665 our_pred->est_success_rate = 1.0f;
666 return true;
669 static boolean
670 parse_depth (const struct parser_table* entry, char **argv, int *arg_ptr)
672 (void) entry;
673 (void) argv;
674 (void) arg_ptr;
676 options.do_dir_first = false;
677 return parse_noop(entry, argv, arg_ptr);
680 static boolean
681 parse_d (const struct parser_table* entry, char **argv, int *arg_ptr)
683 (void) argv;
684 (void) arg_ptr;
686 if (options.warnings)
688 error (0, 0,
689 _("warning: the -d option is deprecated; please use -depth instead, because the latter is a POSIX-compliant feature."));
691 return parse_depth(entry, argv, arg_ptr);
694 static boolean
695 parse_empty (const struct parser_table* entry, char **argv, int *arg_ptr)
697 struct predicate *our_pred;
698 (void) argv;
699 (void) arg_ptr;
701 our_pred = insert_primary (entry);
702 our_pred->est_success_rate = 0.01f; /* assume 1% of files are empty. */
703 return true;
706 static boolean
707 parse_exec (const struct parser_table* entry, char **argv, int *arg_ptr)
709 return insert_exec_ok ("-exec", entry, argv, arg_ptr);
712 static boolean
713 parse_execdir (const struct parser_table* entry, char **argv, int *arg_ptr)
715 return insert_exec_ok ("-execdir", entry, argv, arg_ptr);
718 static boolean
719 parse_false (const struct parser_table* entry, char **argv, int *arg_ptr)
721 struct predicate *our_pred;
723 (void) argv;
724 (void) arg_ptr;
726 our_pred = insert_primary (entry);
727 our_pred->need_stat = our_pred->need_type = false;
728 our_pred->side_effects = our_pred->no_default_print = false;
729 our_pred->est_success_rate = 0.0f;
730 return true;
733 static boolean
734 parse_fls (const struct parser_table* entry, char **argv, int *arg_ptr)
736 struct predicate *our_pred;
738 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
739 return false;
740 our_pred = insert_primary (entry);
741 our_pred->args.stream = open_output_file (argv[*arg_ptr]);
742 our_pred->side_effects = our_pred->no_default_print = true;
743 our_pred->est_success_rate = 1.0f;
744 (*arg_ptr)++;
745 return true;
748 static boolean
749 parse_fprintf (const struct parser_table* entry, char **argv, int *arg_ptr)
751 FILE *fp;
753 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
754 return false;
755 if (argv[*arg_ptr + 1] == NULL)
757 /* Ensure we get "missing arg" message, not "invalid arg". */
758 (*arg_ptr)++;
759 return false;
761 fp = open_output_file (argv[*arg_ptr]);
762 (*arg_ptr)++;
763 return insert_fprintf (fp, entry, pred_fprintf, argv, arg_ptr);
766 static boolean
767 parse_follow (const struct parser_table* entry, char **argv, int *arg_ptr)
769 (void) entry;
770 (void) argv;
771 (void) arg_ptr;
773 set_follow_state(SYMLINK_ALWAYS_DEREF);
774 return parse_noop(entry, argv, arg_ptr);
777 static boolean
778 parse_fprint (const struct parser_table* entry, char **argv, int *arg_ptr)
780 struct predicate *our_pred;
782 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
783 return false;
784 our_pred = insert_primary (entry);
785 our_pred->args.printf_vec.segment = NULL;
786 our_pred->args.printf_vec.stream = open_output_file (argv[*arg_ptr]);
787 our_pred->args.printf_vec.dest_is_tty = stream_is_tty(our_pred->args.printf_vec.stream);
788 our_pred->args.printf_vec.quote_opts = clone_quoting_options (NULL);
789 our_pred->side_effects = our_pred->no_default_print = true;
790 our_pred->need_stat = our_pred->need_type = false;
791 our_pred->est_success_rate = 1.0f;
792 (*arg_ptr)++;
793 return true;
796 static boolean
797 parse_fprint0 (const struct parser_table* entry, char **argv, int *arg_ptr)
799 struct predicate *our_pred;
801 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
802 return false;
803 our_pred = insert_primary (entry);
804 our_pred->args.stream = open_output_file (argv[*arg_ptr]);
805 our_pred->side_effects = our_pred->no_default_print = true;
806 our_pred->need_stat = our_pred->need_type = false;
807 our_pred->est_success_rate = 1.0f;
808 (*arg_ptr)++;
809 return true;
812 static float estimate_fstype_success_rate(const char *fsname)
814 struct stat dir_stat;
815 const char *dir = "/";
816 if (0 == stat(dir, &dir_stat))
818 const char *fstype = filesystem_type(&dir_stat, dir);
819 /* Assume most files are on the same filesystem type as the root fs. */
820 if (0 == strcmp(fsname, fstype))
821 return 0.7f;
822 else
823 return 0.3f;
825 return 1.0f;
829 static boolean
830 parse_fstype (const struct parser_table* entry, char **argv, int *arg_ptr)
832 struct predicate *our_pred;
834 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
835 return false;
836 our_pred = insert_primary (entry);
837 our_pred->args.str = argv[*arg_ptr];
839 /* This is an expensive operation, so although there are
840 * circumstances where it is selective, we ignore this fact because
841 * we probably don't want to promote this test to the front anyway.
843 our_pred->est_success_rate = estimate_fstype_success_rate(argv[*arg_ptr]);
844 (*arg_ptr)++;
845 return true;
848 static boolean
849 parse_gid (const struct parser_table* entry, char **argv, int *arg_ptr)
851 struct predicate *p = insert_num (argv, arg_ptr, entry);
852 p->est_success_rate = (p->args.info.l_val < 100) ? 0.99 : 0.2;
853 return p;
856 static boolean
857 parse_group (const struct parser_table* entry, char **argv, int *arg_ptr)
859 struct group *cur_gr;
860 struct predicate *our_pred;
861 gid_t gid;
862 int gid_len;
864 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
865 return false;
866 cur_gr = getgrnam (argv[*arg_ptr]);
867 endgrent ();
868 if (cur_gr != NULL)
869 gid = cur_gr->gr_gid;
870 else
872 gid_len = strspn (argv[*arg_ptr], "0123456789");
873 if ((gid_len == 0) || (argv[*arg_ptr][gid_len] != '\0'))
874 return false;
875 gid = atoi (argv[*arg_ptr]);
877 our_pred = insert_primary (entry);
878 our_pred->args.gid = gid;
879 our_pred->est_success_rate = (our_pred->args.info.l_val < 100) ? 0.99 : 0.2;
880 (*arg_ptr)++;
881 return true;
884 static boolean
885 parse_help (const struct parser_table* entry, char **argv, int *arg_ptr)
887 (void) entry;
888 (void) argv;
889 (void) arg_ptr;
891 usage(stdout, 0, NULL);
892 puts (_("\n\
893 default path is the current directory; default expression is -print\n\
894 expression may consist of: operators, options, tests, and actions:\n"));
895 puts (_("\
896 operators (decreasing precedence; -and is implicit where no others are given):\n\
897 ( EXPR ) ! EXPR -not EXPR EXPR1 -a EXPR2 EXPR1 -and EXPR2\n\
898 EXPR1 -o EXPR2 EXPR1 -or EXPR2 EXPR1 , EXPR2\n"));
899 puts (_("\
900 positional options (always true): -daystart -follow -regextype\n\n\
901 normal options (always true, specified before other expressions):\n\
902 -depth --help -maxdepth LEVELS -mindepth LEVELS -mount -noleaf\n\
903 --version -xdev -ignore_readdir_race -noignore_readdir_race\n"));
904 puts (_("\
905 tests (N can be +N or -N or N): -amin N -anewer FILE -atime N -cmin N\n\
906 -cnewer FILE -ctime N -empty -false -fstype TYPE -gid N -group NAME\n\
907 -ilname PATTERN -iname PATTERN -inum N -iwholename PATTERN -iregex PATTERN\n\
908 -links N -lname PATTERN -mmin N -mtime N -name PATTERN -newer FILE"));
909 puts (_("\
910 -nouser -nogroup -path PATTERN -perm [+-]MODE -regex PATTERN\n\
911 -readable -writable -executable\n\
912 -wholename PATTERN -size N[bcwkMG] -true -type [bcdpflsD] -uid N\n\
913 -used N -user NAME -xtype [bcdpfls]\n"));
914 puts (_("\
915 actions: -delete -print0 -printf FORMAT -fprintf FILE FORMAT -print \n\
916 -fprint0 FILE -fprint FILE -ls -fls FILE -prune -quit\n\
917 -exec COMMAND ; -exec COMMAND {} + -ok COMMAND ;\n\
918 -execdir COMMAND ; -execdir COMMAND {} + -okdir COMMAND ;\n\
919 "));
920 puts (_("Report (and track progress on fixing) bugs via the findutils bug-reporting\n\
921 page at http://savannah.gnu.org/ or, if you have no web access, by sending\n\
922 email to <bug-findutils@gnu.org>."));
923 exit (0);
926 static float estimate_pattern_match_rate(const char *pattern, int is_regex)
928 if (strpbrk(pattern, "*?[") || (is_regex && strpbrk(pattern, ".")))
930 /* A wildcard; assume the pattern matches most files. */
931 return 0.8f;
933 else
935 return 0.1f;
939 static boolean
940 parse_ilname (const struct parser_table* entry, char **argv, int *arg_ptr)
942 struct predicate *our_pred;
944 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
945 return false;
946 our_pred = insert_primary (entry);
947 our_pred->args.str = argv[*arg_ptr];
948 /* Use the generic glob pattern estimator to figure out how many
949 * links will match, but bear in mind that most files won't be links.
951 our_pred->est_success_rate = 0.1 * estimate_pattern_match_rate(our_pred->args.str, 0);
952 (*arg_ptr)++;
953 return true;
957 /* sanity check the fnmatch() function to make sure
958 * it really is the GNU version.
960 static boolean
961 fnmatch_sanitycheck(void)
963 /* fprintf(stderr, "Performing find sanity check..."); */
964 if (0 != fnmatch("foo", "foo", 0)
965 || 0 == fnmatch("Foo", "foo", 0)
966 || 0 != fnmatch("Foo", "foo", FNM_CASEFOLD))
968 error (1, 0, _("sanity check of the fnmatch() library function failed."));
969 /* fprintf(stderr, "FAILED\n"); */
970 return false;
973 /* fprintf(stderr, "OK\n"); */
974 return true;
978 static boolean
979 check_name_arg(const char *pred, const char *arg)
981 if (strchr(arg, '/'))
983 error(0, 0,_("warning: Unix filenames usually don't contain slashes (though pathnames do). That means that '%s %s' will probably evaluate to false all the time on this system. You might find the '-wholename' test more useful, or perhaps '-samefile'. Alternatively, if you are using GNU grep, you could use 'find ... -print0 | grep -FzZ %s'."),
984 pred, arg, arg);
986 return true; /* allow it anyway */
991 static boolean
992 parse_iname (const struct parser_table* entry, char **argv, int *arg_ptr)
994 struct predicate *our_pred;
996 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
997 return false;
998 if (!check_name_arg("-iname", argv[*arg_ptr]))
999 return false;
1001 fnmatch_sanitycheck();
1003 our_pred = insert_primary (entry);
1004 our_pred->need_stat = our_pred->need_type = false;
1005 our_pred->args.str = argv[*arg_ptr];
1006 our_pred->est_success_rate = estimate_pattern_match_rate(our_pred->args.str, 0);
1007 (*arg_ptr)++;
1008 return true;
1011 static boolean
1012 parse_inum (const struct parser_table* entry, char **argv, int *arg_ptr)
1014 struct predicate *p = insert_num (argv, arg_ptr, entry);
1015 /* inode number is exact match only, so very low proportions of files match */
1016 p->est_success_rate = 1e-6;
1017 return p;
1020 /* -ipath is deprecated (at RMS's request) in favour of
1021 * -iwholename. See the node "GNU Manuals" in standards.texi
1022 * for the rationale for this (basically, GNU prefers the use
1023 * of the phrase "file name" to "path name"
1025 static boolean
1026 parse_ipath (const struct parser_table* entry, char **argv, int *arg_ptr)
1028 error (0, 0,
1029 _("warning: the predicate -ipath is deprecated; please use -iwholename instead."));
1031 return parse_iwholename(entry, argv, arg_ptr);
1034 static boolean
1035 parse_iwholename (const struct parser_table* entry, char **argv, int *arg_ptr)
1037 struct predicate *our_pred;
1039 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
1040 return false;
1042 fnmatch_sanitycheck();
1044 our_pred = insert_primary_withpred (entry, pred_ipath);
1045 our_pred->need_stat = our_pred->need_type = false;
1046 our_pred->args.str = argv[*arg_ptr];
1047 our_pred->est_success_rate = estimate_pattern_match_rate(our_pred->args.str, 0);
1048 (*arg_ptr)++;
1049 return true;
1052 static boolean
1053 parse_iregex (const struct parser_table* entry, char **argv, int *arg_ptr)
1055 return insert_regex (argv, arg_ptr, entry, RE_ICASE|options.regex_options);
1058 static boolean
1059 parse_links (const struct parser_table* entry, char **argv, int *arg_ptr)
1061 struct predicate *p = insert_num (argv, arg_ptr, entry);
1062 if (p->args.info.l_val == 1)
1063 p->est_success_rate = 0.99;
1064 else if (p->args.info.l_val == 2)
1065 p->est_success_rate = 0.01;
1066 else
1067 p->est_success_rate = 1e-3;
1068 return p;
1071 static boolean
1072 parse_lname (const struct parser_table* entry, char **argv, int *arg_ptr)
1074 struct predicate *our_pred;
1076 (void) argv;
1077 (void) arg_ptr;
1079 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
1080 return false;
1082 fnmatch_sanitycheck();
1084 our_pred = insert_primary (entry);
1085 our_pred->args.str = argv[*arg_ptr];
1086 our_pred->est_success_rate = 0.1 * estimate_pattern_match_rate(our_pred->args.str, 0);
1087 (*arg_ptr)++;
1088 return true;
1091 static boolean
1092 parse_ls (const struct parser_table* entry, char **argv, int *arg_ptr)
1094 struct predicate *our_pred;
1096 (void) &argv;
1097 (void) &arg_ptr;
1099 our_pred = insert_primary (entry);
1100 our_pred->side_effects = our_pred->no_default_print = true;
1101 return true;
1104 static boolean
1105 parse_maxdepth (const struct parser_table* entry, char **argv, int *arg_ptr)
1107 int depth_len;
1108 (void) entry;
1110 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
1111 return false;
1112 depth_len = strspn (argv[*arg_ptr], "0123456789");
1113 if ((depth_len == 0) || (argv[*arg_ptr][depth_len] != '\0'))
1114 return false;
1115 options.maxdepth = atoi (argv[*arg_ptr]);
1116 if (options.maxdepth < 0)
1117 return false;
1118 (*arg_ptr)++;
1119 return parse_noop(entry, argv, arg_ptr);
1122 static boolean
1123 parse_mindepth (const struct parser_table* entry, char **argv, int *arg_ptr)
1125 int depth_len;
1126 (void) entry;
1128 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
1129 return false;
1130 depth_len = strspn (argv[*arg_ptr], "0123456789");
1131 if ((depth_len == 0) || (argv[*arg_ptr][depth_len] != '\0'))
1132 return false;
1133 options.mindepth = atoi (argv[*arg_ptr]);
1134 if (options.mindepth < 0)
1135 return false;
1136 (*arg_ptr)++;
1137 return parse_noop(entry, argv, arg_ptr);
1140 static boolean
1141 parse_mmin (const struct parser_table* entry, char **argv, int *arg_ptr)
1143 struct predicate *our_pred;
1144 uintmax_t num;
1145 enum comparison_type c_type;
1146 time_t t;
1148 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
1149 return false;
1150 if (!get_num_days (argv[*arg_ptr], &num, &c_type))
1151 return false;
1152 t = options.cur_day_start + DAYSECS - num * 60;
1153 our_pred = insert_primary (entry);
1154 our_pred->args.info.kind = c_type;
1155 our_pred->args.info.negative = t < 0;
1156 our_pred->args.info.l_val = t;
1157 our_pred->est_success_rate = estimate_file_age_success_rate(num);
1158 (*arg_ptr)++;
1159 return true;
1162 static boolean
1163 parse_name (const struct parser_table* entry, char **argv, int *arg_ptr)
1165 struct predicate *our_pred;
1167 (void) argv;
1168 (void) arg_ptr;
1170 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
1171 return false;
1172 if (!check_name_arg("-name", argv[*arg_ptr]))
1173 return false;
1174 fnmatch_sanitycheck();
1176 our_pred = insert_primary (entry);
1177 our_pred->need_stat = our_pred->need_type = false;
1178 our_pred->args.str = argv[*arg_ptr];
1179 our_pred->est_success_rate = estimate_pattern_match_rate(our_pred->args.str, 0);
1180 (*arg_ptr)++;
1181 return true;
1184 static boolean
1185 parse_negate (const struct parser_table* entry, char **argv, int *arg_ptr)
1187 struct predicate *our_pred;
1189 (void) &argv;
1190 (void) &arg_ptr;
1192 our_pred = get_new_pred_chk_op (entry);
1193 our_pred->pred_func = pred_negate;
1194 our_pred->p_type = UNI_OP;
1195 our_pred->p_prec = NEGATE_PREC;
1196 our_pred->need_stat = our_pred->need_type = false;
1197 return true;
1200 static boolean
1201 parse_newer (const struct parser_table* entry, char **argv, int *arg_ptr)
1203 struct predicate *our_pred;
1204 struct stat stat_newer;
1206 (void) argv;
1207 (void) arg_ptr;
1209 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
1210 return false;
1211 if ((*options.xstat) (argv[*arg_ptr], &stat_newer))
1212 error (1, errno, "%s", argv[*arg_ptr]);
1213 our_pred = insert_primary (entry);
1214 our_pred->args.time = stat_newer.st_mtime;
1215 our_pred->est_success_rate = estimate_timestamp_success_rate(stat_newer.st_mtime);
1216 (*arg_ptr)++;
1217 return true;
1220 static boolean
1221 parse_noleaf (const struct parser_table* entry, char **argv, int *arg_ptr)
1223 (void) &argv;
1224 (void) &arg_ptr;
1225 (void) entry;
1227 options.no_leaf_check = true;
1228 return parse_noop(entry, argv, arg_ptr);
1231 #ifdef CACHE_IDS
1232 /* Arbitrary amount by which to increase size
1233 of `uid_unused' and `gid_unused'. */
1234 #define ALLOC_STEP 2048
1236 /* Boolean: if uid_unused[n] is nonzero, then UID n has no passwd entry. */
1237 char *uid_unused = NULL;
1239 /* Number of elements in `uid_unused'. */
1240 unsigned uid_allocated;
1242 /* Similar for GIDs and group entries. */
1243 char *gid_unused = NULL;
1244 unsigned gid_allocated;
1245 #endif
1247 static boolean
1248 parse_nogroup (const struct parser_table* entry, char **argv, int *arg_ptr)
1250 struct predicate *our_pred;
1252 (void) &argv;
1253 (void) &arg_ptr;
1255 our_pred = insert_primary (entry);
1256 our_pred->est_success_rate = 1e-4;
1257 #ifdef CACHE_IDS
1258 if (gid_unused == NULL)
1260 struct group *gr;
1262 gid_allocated = ALLOC_STEP;
1263 gid_unused = xmalloc (gid_allocated);
1264 memset (gid_unused, 1, gid_allocated);
1265 setgrent ();
1266 while ((gr = getgrent ()) != NULL)
1268 if ((unsigned) gr->gr_gid >= gid_allocated)
1270 unsigned new_allocated = (unsigned) gr->gr_gid + ALLOC_STEP;
1271 gid_unused = xrealloc (gid_unused, new_allocated);
1272 memset (gid_unused + gid_allocated, 1,
1273 new_allocated - gid_allocated);
1274 gid_allocated = new_allocated;
1276 gid_unused[(unsigned) gr->gr_gid] = 0;
1278 endgrent ();
1280 #endif
1281 return true;
1284 static boolean
1285 parse_nouser (const struct parser_table* entry, char **argv, int *arg_ptr)
1287 struct predicate *our_pred;
1288 (void) argv;
1289 (void) arg_ptr;
1292 our_pred = insert_primary (entry);
1293 our_pred->est_success_rate = 1e-3;
1294 #ifdef CACHE_IDS
1295 if (uid_unused == NULL)
1297 struct passwd *pw;
1299 uid_allocated = ALLOC_STEP;
1300 uid_unused = xmalloc (uid_allocated);
1301 memset (uid_unused, 1, uid_allocated);
1302 setpwent ();
1303 while ((pw = getpwent ()) != NULL)
1305 if ((unsigned) pw->pw_uid >= uid_allocated)
1307 unsigned new_allocated = (unsigned) pw->pw_uid + ALLOC_STEP;
1308 uid_unused = xrealloc (uid_unused, new_allocated);
1309 memset (uid_unused + uid_allocated, 1,
1310 new_allocated - uid_allocated);
1311 uid_allocated = new_allocated;
1313 uid_unused[(unsigned) pw->pw_uid] = 0;
1315 endpwent ();
1317 #endif
1318 return true;
1321 static boolean
1322 parse_nowarn (const struct parser_table* entry, char **argv, int *arg_ptr)
1324 (void) argv;
1325 (void) arg_ptr;
1326 (void) entry;
1328 options.warnings = false;
1329 return parse_noop(entry, argv, arg_ptr);
1332 static boolean
1333 parse_ok (const struct parser_table* entry, char **argv, int *arg_ptr)
1335 return insert_exec_ok ("-ok", entry, argv, arg_ptr);
1338 static boolean
1339 parse_okdir (const struct parser_table* entry, char **argv, int *arg_ptr)
1341 return insert_exec_ok ("-okdir", entry, argv, arg_ptr);
1344 boolean
1345 parse_open (const struct parser_table* entry, char **argv, int *arg_ptr)
1347 struct predicate *our_pred;
1349 (void) argv;
1350 (void) arg_ptr;
1352 our_pred = get_new_pred_chk_op (entry);
1353 our_pred->pred_func = pred_open;
1354 our_pred->p_type = OPEN_PAREN;
1355 our_pred->p_prec = NO_PREC;
1356 our_pred->need_stat = our_pred->need_type = false;
1357 return true;
1360 static boolean
1361 parse_or (const struct parser_table* entry, char **argv, int *arg_ptr)
1363 struct predicate *our_pred;
1365 (void) argv;
1366 (void) arg_ptr;
1368 our_pred = get_new_pred (entry);
1369 our_pred->pred_func = pred_or;
1370 our_pred->p_type = BI_OP;
1371 our_pred->p_prec = OR_PREC;
1372 our_pred->need_stat = our_pred->need_type = false;
1373 return true;
1376 /* -path is deprecated (at RMS's request) in favour of
1377 * -iwholename. See the node "GNU Manuals" in standards.texi
1378 * for the rationale for this (basically, GNU prefers the use
1379 * of the phrase "file name" to "path name".
1381 * We do not issue a warning that this usage is deprecated
1382 * since HPUX find supports this predicate also.
1384 static boolean
1385 parse_path (const struct parser_table* entry, char **argv, int *arg_ptr)
1387 return parse_wholename(entry, argv, arg_ptr);
1390 static boolean
1391 parse_wholename (const struct parser_table* entry, char **argv, int *arg_ptr)
1393 struct predicate *our_pred;
1395 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
1396 return false;
1397 our_pred = insert_primary_withpred (entry, pred_path);
1398 our_pred->need_stat = our_pred->need_type = false;
1399 our_pred->args.str = argv[*arg_ptr];
1400 our_pred->est_success_rate = estimate_pattern_match_rate(our_pred->args.str, 0);
1401 (*arg_ptr)++;
1402 return true;
1405 static boolean
1406 parse_perm (const struct parser_table* entry, char **argv, int *arg_ptr)
1408 mode_t perm_val[2];
1409 float rate;
1410 int mode_start = 0;
1411 boolean havekind = false;
1412 enum permissions_type kind = PERM_EXACT;
1413 struct mode_change *change = NULL;
1414 struct predicate *our_pred;
1416 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
1417 return false;
1419 switch (argv[*arg_ptr][0])
1421 case '-':
1422 mode_start = 1;
1423 kind = PERM_AT_LEAST;
1424 havekind = true;
1425 rate = 0.2;
1426 break;
1428 case '+':
1429 change = mode_compile (argv[*arg_ptr]);
1430 if (NULL == change)
1432 /* Most likely the caller is an old script that is still
1433 * using the obsolete GNU syntax '-perm +MODE'. This old
1434 * syntax was withdrawn in favor of '-perm /MODE' because
1435 * it is incompatible with POSIX in some cases, but we
1436 * still support uses of it that are not incompatible with
1437 * POSIX.
1439 mode_start = 1;
1440 kind = PERM_ANY;
1441 rate = 0.3;
1443 else
1445 /* This is a POSIX-compatible usage */
1446 mode_start = 0;
1447 kind = PERM_EXACT;
1448 rate = 0.1;
1450 havekind = true;
1451 break;
1453 case '/': /* GNU extension */
1454 mode_start = 1;
1455 kind = PERM_ANY;
1456 havekind = true;
1457 rate = 0.3;
1458 break;
1460 default:
1461 /* For example, '-perm 0644', which is valid and matches
1462 * only files whose mode is exactly 0644.
1464 * We do nothing here, because mode_start and kind are already
1465 * correctly set.
1467 rate = 0.01;
1468 break;
1471 if (NULL == change)
1473 change = mode_compile (argv[*arg_ptr] + mode_start);
1474 if (NULL == change)
1475 error (1, 0, _("invalid mode `%s'"), argv[*arg_ptr]);
1477 perm_val[0] = mode_adjust (0, false, 0, change, NULL);
1478 perm_val[1] = mode_adjust (0, true, 0, change, NULL);
1479 free (change);
1481 our_pred = insert_primary (entry);
1482 our_pred->est_success_rate = rate;
1483 if (havekind)
1485 our_pred->args.perm.kind = kind;
1487 else
1490 switch (argv[*arg_ptr][0])
1492 case '-':
1493 our_pred->args.perm.kind = PERM_AT_LEAST;
1494 break;
1495 case '+':
1496 our_pred->args.perm.kind = PERM_ANY;
1497 break;
1498 default:
1499 our_pred->args.perm.kind = PERM_EXACT;
1500 break;
1503 if (('/' == argv[*arg_ptr][0]) && (0 == perm_val[0]) && (0 == perm_val[1]))
1505 /* The meaning of -perm /000 will change in the future.
1506 * It currently matches no files, but like -perm -000 it
1507 * should match all files.
1509 error (0, 0,
1510 _("warning: you have specified a mode pattern %s which is "
1511 "equivalent to 000. The meaning of -perm /000 will soon be "
1512 "changed to be consistent with -perm -000; that is, at the "
1513 "moment it matches no files but it will soon be changed to "
1514 "match all files."),
1515 argv[*arg_ptr]);
1518 memcpy (our_pred->args.perm.val, perm_val, sizeof perm_val);
1519 (*arg_ptr)++;
1520 return true;
1523 boolean
1524 parse_print (const struct parser_table* entry, char **argv, int *arg_ptr)
1526 struct predicate *our_pred;
1528 (void) argv;
1529 (void) arg_ptr;
1531 our_pred = insert_primary (entry);
1532 /* -print has the side effect of printing. This prevents us
1533 from doing undesired multiple printing when the user has
1534 already specified -print. */
1535 our_pred->side_effects = our_pred->no_default_print = true;
1536 our_pred->need_stat = our_pred->need_type = false;
1537 our_pred->args.printf_vec.segment = NULL;
1538 our_pred->args.printf_vec.stream = stdout;
1539 our_pred->args.printf_vec.dest_is_tty = stream_is_tty(stdout);
1540 our_pred->args.printf_vec.quote_opts = clone_quoting_options (NULL);
1542 return true;
1545 static boolean
1546 parse_print0 (const struct parser_table* entry, char **argv, int *arg_ptr)
1548 struct predicate *our_pred;
1550 (void) argv;
1551 (void) arg_ptr;
1553 our_pred = insert_primary (entry);
1554 /* -print0 has the side effect of printing. This prevents us
1555 from doing undesired multiple printing when the user has
1556 already specified -print0. */
1557 our_pred->side_effects = our_pred->no_default_print = true;
1558 our_pred->need_stat = our_pred->need_type = false;
1559 return true;
1562 static boolean
1563 parse_printf (const struct parser_table* entry, char **argv, int *arg_ptr)
1565 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
1566 return false;
1567 return insert_fprintf (stdout, entry, pred_fprintf, argv, arg_ptr);
1570 static boolean
1571 parse_prune (const struct parser_table* entry, char **argv, int *arg_ptr)
1573 struct predicate *our_pred;
1575 (void) argv;
1576 (void) arg_ptr;
1578 our_pred = insert_primary (entry);
1579 our_pred->need_stat = our_pred->need_type = false;
1580 /* -prune has a side effect that it does not descend into
1581 the current directory. */
1582 our_pred->side_effects = true;
1583 our_pred->no_default_print = false;
1584 return true;
1587 static boolean
1588 parse_quit (const struct parser_table* entry, char **argv, int *arg_ptr)
1590 struct predicate *our_pred = insert_primary (entry);
1591 (void) argv;
1592 (void) arg_ptr;
1593 our_pred->need_stat = our_pred->need_type = false;
1594 our_pred->side_effects = true; /* Exiting is a side effect... */
1595 our_pred->no_default_print = false; /* Don't inhibit the default print, though. */
1596 our_pred->est_success_rate = 1e-6;
1597 return true;
1601 static boolean
1602 parse_regextype (const struct parser_table* entry, char **argv, int *arg_ptr)
1604 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
1605 return false;
1607 /* collect the regex type name */
1608 options.regex_options = get_regex_type(argv[*arg_ptr]);
1609 (*arg_ptr)++;
1611 return parse_noop(entry, argv, arg_ptr);
1615 static boolean
1616 parse_regex (const struct parser_table* entry, char **argv, int *arg_ptr)
1618 return insert_regex (argv, arg_ptr, entry, options.regex_options);
1621 static boolean
1622 insert_regex (char **argv, int *arg_ptr, const struct parser_table *entry, int regex_options)
1624 struct predicate *our_pred;
1625 struct re_pattern_buffer *re;
1626 const char *error_message;
1628 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
1629 return false;
1630 our_pred = insert_primary_withpred (entry, pred_regex);
1631 our_pred->need_stat = our_pred->need_type = false;
1632 re = (struct re_pattern_buffer *)
1633 xmalloc (sizeof (struct re_pattern_buffer));
1634 our_pred->args.regex = re;
1635 re->allocated = 100;
1636 re->buffer = (unsigned char *) xmalloc (re->allocated);
1637 re->fastmap = NULL;
1639 re_set_syntax(regex_options);
1640 re->syntax = regex_options;
1641 re->translate = NULL;
1643 error_message = re_compile_pattern (argv[*arg_ptr], strlen (argv[*arg_ptr]),
1644 re);
1645 if (error_message)
1646 error (1, 0, "%s", error_message);
1647 our_pred->est_success_rate = estimate_pattern_match_rate(argv[*arg_ptr], 1);
1648 (*arg_ptr)++;
1649 return true;
1652 static boolean
1653 parse_size (const struct parser_table* entry, char **argv, int *arg_ptr)
1655 struct predicate *our_pred;
1656 uintmax_t num;
1657 enum comparison_type c_type;
1658 int blksize = 512;
1659 int len;
1660 float rate = 1.0;
1662 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
1663 return false;
1664 len = strlen (argv[*arg_ptr]);
1665 if (len == 0)
1666 error (1, 0, _("invalid null argument to -size"));
1667 switch (argv[*arg_ptr][len - 1])
1669 case 'b':
1670 blksize = 512;
1671 argv[*arg_ptr][len - 1] = '\0';
1672 break;
1674 case 'c':
1675 blksize = 1;
1676 argv[*arg_ptr][len - 1] = '\0';
1677 break;
1679 case 'k':
1680 blksize = 1024;
1681 argv[*arg_ptr][len - 1] = '\0';
1682 break;
1684 case 'M': /* Megabytes */
1685 blksize = 1024*1024;
1686 argv[*arg_ptr][len - 1] = '\0';
1687 break;
1689 case 'G': /* Gigabytes */
1690 blksize = 1024*1024*1024;
1691 argv[*arg_ptr][len - 1] = '\0';
1692 break;
1694 case 'w':
1695 blksize = 2;
1696 argv[*arg_ptr][len - 1] = '\0';
1697 break;
1699 case '0':
1700 case '1':
1701 case '2':
1702 case '3':
1703 case '4':
1704 case '5':
1705 case '6':
1706 case '7':
1707 case '8':
1708 case '9':
1709 break;
1711 default:
1712 error (1, 0, _("invalid -size type `%c'"), argv[*arg_ptr][len - 1]);
1714 if (!get_num (argv[*arg_ptr], &num, &c_type))
1715 return false;
1716 our_pred = insert_primary (entry);
1717 our_pred->args.size.kind = c_type;
1718 our_pred->args.size.blocksize = blksize;
1719 our_pred->args.size.size = num;
1720 our_pred->need_stat = true;
1721 our_pred->need_type = false;
1723 if (COMP_GT == c_type)
1724 our_pred->est_success_rate = (num*blksize > 20480) ? 0.1 : 0.9;
1725 else if (COMP_LT == c_type)
1726 our_pred->est_success_rate = (num*blksize > 20480) ? 0.9 : 0.1;
1727 else
1728 our_pred->est_success_rate = 0.01;
1730 (*arg_ptr)++;
1731 return true;
1735 static boolean
1736 parse_samefile (const struct parser_table* entry, char **argv, int *arg_ptr)
1738 struct predicate *our_pred;
1739 struct stat st;
1741 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
1742 return false;
1743 if ((*options.xstat) (argv[*arg_ptr], &st))
1744 error (1, errno, "%s", argv[*arg_ptr]);
1746 our_pred = insert_primary (entry);
1747 our_pred->args.fileid.ino = st.st_ino;
1748 our_pred->args.fileid.dev = st.st_dev;
1749 our_pred->need_type = false;
1750 our_pred->need_stat = true;
1751 our_pred->est_success_rate = 0.01f;
1752 (*arg_ptr)++;
1753 return true;
1756 #if 0
1757 static boolean
1758 parse_show_control_chars (const struct parser_table* entry, char **argv, int *arg_ptr)
1760 const char *arg;
1761 const char *errmsg = _("The -show-control-chars option takes a single argument which "
1762 "must be 'literal' or 'safe'");
1764 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
1766 error (1, errno, "%s", errmsg);
1767 return false;
1769 else
1771 arg = argv[*arg_ptr];
1773 if (0 == strcmp("literal", arg))
1775 options.literal_control_chars = true;
1777 else if (0 == strcmp("safe", arg))
1779 options.literal_control_chars = false;
1781 else
1783 error (1, errno, "%s", errmsg);
1784 return false;
1786 (*arg_ptr)++; /* consume the argument. */
1787 return true;
1790 #endif
1793 static boolean
1794 parse_true (const struct parser_table* entry, char **argv, int *arg_ptr)
1796 struct predicate *our_pred;
1798 (void) argv;
1799 (void) arg_ptr;
1801 our_pred = insert_primary (entry);
1802 our_pred->need_stat = our_pred->need_type = false;
1803 our_pred->est_success_rate = 1.0f;
1804 return true;
1807 static boolean
1808 parse_noop (const struct parser_table* entry, char **argv, int *arg_ptr)
1810 (void) entry;
1811 return parse_true(get_noop(), argv, arg_ptr);
1814 static boolean
1815 parse_accesscheck (const struct parser_table* entry, char **argv, int *arg_ptr)
1817 struct predicate *our_pred;
1818 (void) argv;
1819 (void) arg_ptr;
1820 our_pred = insert_primary (entry);
1821 our_pred->need_stat = our_pred->need_type = false;
1822 our_pred->side_effects = our_pred->no_default_print = false;
1823 if (our_pred->pred_func == pred_executable)
1824 our_pred->est_success_rate = 0.2;
1825 else
1826 our_pred->est_success_rate = 0.9;
1827 return true;
1830 static boolean
1831 parse_type (const struct parser_table* entry, char **argv, int *arg_ptr)
1833 return insert_type (argv, arg_ptr, entry, pred_type);
1836 static boolean
1837 parse_uid (const struct parser_table* entry, char **argv, int *arg_ptr)
1839 struct predicate *p = insert_num (argv, arg_ptr, entry);
1840 p->est_success_rate = (p->args.info.l_val < 100) ? 0.99 : 0.2;
1841 return p;
1844 static boolean
1845 parse_used (const struct parser_table* entry, char **argv, int *arg_ptr)
1847 struct predicate *our_pred;
1848 uintmax_t num_days;
1849 enum comparison_type c_type;
1850 time_t t;
1852 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
1853 return false;
1854 if (!get_num (argv[*arg_ptr], &num_days, &c_type))
1855 return false;
1856 t = num_days * DAYSECS;
1857 our_pred = insert_primary (entry);
1858 our_pred->args.info.kind = c_type;
1859 our_pred->args.info.negative = t < 0;
1860 our_pred->args.info.l_val = t;
1861 our_pred->est_success_rate = estimate_file_age_success_rate(num_days);
1862 (*arg_ptr)++;
1863 return true;
1866 static boolean
1867 parse_user (const struct parser_table* entry, char **argv, int *arg_ptr)
1869 struct passwd *cur_pwd;
1870 struct predicate *our_pred;
1871 uid_t uid;
1872 int uid_len;
1874 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
1875 return false;
1876 cur_pwd = getpwnam (argv[*arg_ptr]);
1877 endpwent ();
1878 if (cur_pwd != NULL)
1879 uid = cur_pwd->pw_uid;
1880 else
1882 uid_len = strspn (argv[*arg_ptr], "0123456789");
1883 if ((uid_len == 0) || (argv[*arg_ptr][uid_len] != '\0'))
1884 return false;
1885 uid = atoi (argv[*arg_ptr]);
1887 our_pred = insert_primary (entry);
1888 our_pred->args.uid = uid;
1889 our_pred->est_success_rate = (our_pred->args.uid < 100) ? 0.99 : 0.2;
1890 (*arg_ptr)++;
1891 return true;
1894 static boolean
1895 parse_version (const struct parser_table* entry, char **argv, int *arg_ptr)
1897 extern char *version_string;
1898 int features = 0;
1900 (void) argv;
1901 (void) arg_ptr;
1902 (void) entry;
1904 fflush (stderr);
1905 printf (_("GNU find version %s\n"), version_string);
1906 printf (_("Features enabled: "));
1908 #if CACHE_IDS
1909 printf("CACHE_IDS ");
1910 ++features;
1911 #endif
1912 #if DEBUG
1913 printf("DEBUG ");
1914 ++features;
1915 #endif
1916 #if DEBUG_STAT
1917 printf("DEBUG_STAT ");
1918 ++features;
1919 #endif
1920 #if defined(USE_STRUCT_DIRENT_D_TYPE) && defined(HAVE_STRUCT_DIRENT_D_TYPE)
1921 printf("D_TYPE ");
1922 ++features;
1923 #endif
1924 #if defined(O_NOFOLLOW)
1925 printf("O_NOFOLLOW(%s) ",
1926 (options.open_nofollow_available ? "enabled" : "disabled"));
1927 ++features;
1928 #endif
1929 #if defined(LEAF_OPTIMISATION)
1930 printf("LEAF_OPTIMISATION ");
1931 ++features;
1932 #endif
1934 if (is_fts_enabled())
1936 printf("FTS ");
1937 ++features;
1940 printf("CBO(level=%d) ", (int)(options.optimisation_level));
1941 ++features;
1943 if (0 == features)
1945 /* For the moment, leave this as English in case someone wants
1946 to parse these strings. */
1947 printf("none");
1949 printf("\n");
1951 exit (0);
1954 static boolean
1955 parse_xdev (const struct parser_table* entry, char **argv, int *arg_ptr)
1957 (void) argv;
1958 (void) arg_ptr;
1959 (void) entry;
1960 options.stay_on_filesystem = true;
1961 return parse_noop(entry, argv, arg_ptr);
1964 static boolean
1965 parse_ignore_race (const struct parser_table* entry, char **argv, int *arg_ptr)
1967 (void) argv;
1968 (void) arg_ptr;
1969 (void) entry;
1970 options.ignore_readdir_race = true;
1971 return parse_noop(entry, argv, arg_ptr);
1974 static boolean
1975 parse_noignore_race (const struct parser_table* entry, char **argv, int *arg_ptr)
1977 (void) argv;
1978 (void) arg_ptr;
1979 (void) entry;
1980 options.ignore_readdir_race = false;
1981 return parse_noop(entry, argv, arg_ptr);
1984 static boolean
1985 parse_warn (const struct parser_table* entry, char **argv, int *arg_ptr)
1987 (void) argv;
1988 (void) arg_ptr;
1989 (void) entry;
1990 options.warnings = true;
1991 return parse_noop(entry, argv, arg_ptr);
1994 static boolean
1995 parse_xtype (const struct parser_table* entry, char **argv, int *arg_ptr)
1997 (void) argv;
1998 (void) arg_ptr;
1999 return insert_type (argv, arg_ptr, entry, pred_xtype);
2002 static boolean
2003 insert_type (char **argv, int *arg_ptr, const struct parser_table *entry, PRED_FUNC which_pred)
2005 mode_t type_cell;
2006 struct predicate *our_pred;
2007 float rate = 0.5;
2009 if ((argv == NULL) || (argv[*arg_ptr] == NULL)
2010 || (strlen (argv[*arg_ptr]) != 1))
2011 return false;
2012 switch (argv[*arg_ptr][0])
2014 case 'b': /* block special */
2015 type_cell = S_IFBLK;
2016 rate = 0.01f;
2017 break;
2018 case 'c': /* character special */
2019 type_cell = S_IFCHR;
2020 rate = 0.01f;
2021 break;
2022 case 'd': /* directory */
2023 type_cell = S_IFDIR;
2024 rate = 0.4f;
2025 break;
2026 case 'f': /* regular file */
2027 type_cell = S_IFREG;
2028 rate = 0.95f;
2029 break;
2030 #ifdef S_IFLNK
2031 case 'l': /* symbolic link */
2032 type_cell = S_IFLNK;
2033 rate = 0.1f;
2034 break;
2035 #endif
2036 #ifdef S_IFIFO
2037 case 'p': /* pipe */
2038 type_cell = S_IFIFO;
2039 rate = 0.01f;
2040 break;
2041 #endif
2042 #ifdef S_IFSOCK
2043 case 's': /* socket */
2044 type_cell = S_IFSOCK;
2045 rate = 0.01f;
2046 break;
2047 #endif
2048 #ifdef S_IFDOOR
2049 case 'D': /* Solaris door */
2050 type_cell = S_IFDOOR;
2051 rate = 0.01f;
2052 break;
2053 #endif
2054 default: /* None of the above ... nuke 'em. */
2055 return false;
2057 our_pred = insert_primary_withpred (entry, which_pred);
2058 our_pred->est_success_rate = rate;
2060 /* Figure out if we will need to stat the file, because if we don't
2061 * need to follow symlinks, we can avoid a stat call by using
2062 * struct dirent.d_type.
2064 if (which_pred == pred_xtype)
2066 our_pred->need_stat = true;
2067 our_pred->need_type = false;
2069 else
2071 our_pred->need_stat = false; /* struct dirent is enough */
2072 our_pred->need_type = true;
2074 our_pred->args.type = type_cell;
2075 (*arg_ptr)++; /* Move on to next argument. */
2076 return true;
2080 /* Return true if the file accessed via FP is a terminal.
2082 static boolean
2083 stream_is_tty(FILE *fp)
2085 int fd = fileno(fp);
2086 if (-1 == fd)
2088 return false; /* not a valid stream */
2090 else
2092 return isatty(fd) ? true : false;
2100 /* XXX: do we need to pass FUNC to this function? */
2101 static boolean
2102 insert_fprintf (FILE *fp, const struct parser_table *entry, PRED_FUNC func, char **argv, int *arg_ptr)
2104 char *format; /* Beginning of unprocessed format string. */
2105 register char *scan; /* Current address in scanning `format'. */
2106 register char *scan2; /* Address inside of element being scanned. */
2107 struct segment **segmentp; /* Address of current segment. */
2108 struct predicate *our_pred;
2110 format = argv[(*arg_ptr)++];
2112 our_pred = insert_primary_withpred (entry, func);
2113 our_pred->side_effects = our_pred->no_default_print = true;
2114 our_pred->args.printf_vec.stream = fp;
2115 our_pred->args.printf_vec.dest_is_tty = stream_is_tty(fp);
2116 our_pred->args.printf_vec.quote_opts = clone_quoting_options (NULL);
2117 our_pred->need_type = false;
2118 our_pred->need_stat = false;
2120 segmentp = &our_pred->args.printf_vec.segment;
2121 *segmentp = NULL;
2123 for (scan = format; *scan; scan++)
2125 if (*scan == '\\')
2127 scan2 = scan + 1;
2128 if (*scan2 >= '0' && *scan2 <= '7')
2130 register int n, i;
2132 for (i = n = 0; i < 3 && (*scan2 >= '0' && *scan2 <= '7');
2133 i++, scan2++)
2134 n = 8 * n + *scan2 - '0';
2135 scan2--;
2136 *scan = n;
2138 else
2140 switch (*scan2)
2142 case 'a':
2143 *scan = 7;
2144 break;
2145 case 'b':
2146 *scan = '\b';
2147 break;
2148 case 'c':
2149 make_segment (segmentp, format, scan - format,
2150 KIND_STOP, 0, 0,
2151 our_pred);
2152 if (our_pred->need_stat && (our_pred->p_cost < NeedsStatInfo))
2153 our_pred->p_cost = NeedsStatInfo;
2154 return true;
2155 case 'f':
2156 *scan = '\f';
2157 break;
2158 case 'n':
2159 *scan = '\n';
2160 break;
2161 case 'r':
2162 *scan = '\r';
2163 break;
2164 case 't':
2165 *scan = '\t';
2166 break;
2167 case 'v':
2168 *scan = '\v';
2169 break;
2170 case '\\':
2171 /* *scan = '\\'; * it already is */
2172 break;
2173 default:
2174 error (0, 0,
2175 _("warning: unrecognized escape `\\%c'"), *scan2);
2176 scan++;
2177 continue;
2180 segmentp = make_segment (segmentp, format, scan - format + 1,
2181 KIND_PLAIN, 0, 0,
2182 our_pred);
2183 format = scan2 + 1; /* Move past the escape. */
2184 scan = scan2; /* Incremented immediately by `for'. */
2186 else if (*scan == '%')
2188 if (scan[1] == 0)
2190 /* Trailing %. We don't like those. */
2191 error (1, 0, _("error: %s at end of format string"), scan);
2193 else if (scan[1] == '%')
2195 segmentp = make_segment (segmentp, format, scan - format + 1,
2196 KIND_PLAIN, 0, 0,
2197 our_pred);
2198 scan++;
2199 format = scan + 1;
2200 continue;
2202 /* Scan past flags, width and precision, to verify kind. */
2203 for (scan2 = scan; *++scan2 && strchr ("-+ #", *scan2);)
2204 /* Do nothing. */ ;
2205 while (ISDIGIT (*scan2))
2206 scan2++;
2207 if (*scan2 == '.')
2208 for (scan2++; ISDIGIT (*scan2); scan2++)
2209 /* Do nothing. */ ;
2210 if (strchr ("abcdDfFgGhHiklmMnpPsStuUyY", *scan2))
2212 segmentp = make_segment (segmentp, format, scan2 - format,
2213 KIND_FORMAT, *scan2, 0,
2214 our_pred);
2215 scan = scan2;
2216 format = scan + 1;
2218 else if (strchr ("ACT", *scan2) && scan2[1])
2220 segmentp = make_segment (segmentp, format, scan2 - format,
2221 KIND_FORMAT, scan2[0], scan2[1],
2222 our_pred);
2223 scan = scan2 + 1;
2224 format = scan + 1;
2225 continue;
2227 else
2229 /* An unrecognized % escape. Print the char after the %. */
2230 error (0, 0, _("warning: unrecognized format directive `%%%c'"),
2231 *scan2);
2232 segmentp = make_segment (segmentp, format, scan - format,
2233 KIND_PLAIN, 0, 0,
2234 our_pred);
2235 format = scan + 1;
2236 continue;
2241 if (scan > format)
2242 make_segment (segmentp, format, scan - format, KIND_PLAIN, 0, 0,
2243 our_pred);
2244 return true;
2247 /* Create a new fprintf segment in *SEGMENT, with type KIND,
2248 from the text in FORMAT, which has length LEN.
2249 Return the address of the `next' pointer of the new segment. */
2251 static struct segment **
2252 make_segment (struct segment **segment,
2253 char *format,
2254 int len,
2255 int kind,
2256 char format_char,
2257 char aux_format_char,
2258 struct predicate *pred)
2260 enum EvaluationCost mycost = NeedsNothing;
2261 char *fmt;
2263 *segment = (struct segment *) xmalloc (sizeof (struct segment));
2265 (*segment)->segkind = kind;
2266 (*segment)->format_char[0] = format_char;
2267 (*segment)->format_char[1] = aux_format_char;
2268 (*segment)->next = NULL;
2269 (*segment)->text_len = len;
2271 fmt = (*segment)->text = xmalloc (len + sizeof "d");
2272 strncpy (fmt, format, len);
2273 fmt += len;
2275 switch (kind)
2277 case KIND_PLAIN: /* Plain text string, no % conversion. */
2278 case KIND_STOP: /* Terminate argument, no newline. */
2279 assert(0 == format_char);
2280 assert(0 == aux_format_char);
2281 *fmt = '\0';
2282 if (mycost > pred->p_cost)
2283 pred->p_cost = NeedsNothing;
2284 return &(*segment)->next;
2285 break;
2288 assert(kind == KIND_FORMAT);
2289 switch (format_char)
2291 case 'l': /* object of symlink */
2292 pred->need_stat = true;
2293 mycost = NeedsLinkName;
2294 *fmt++ = 's';
2295 break;
2297 case 'y': /* file type */
2298 pred->need_type = true;
2299 mycost = NeedsType;
2300 *fmt++ = 's';
2301 break;
2303 case 'a': /* atime in `ctime' format */
2304 case 'A': /* atime in user-specified strftime format */
2305 case 'c': /* ctime in `ctime' format */
2306 case 'C': /* ctime in user-specified strftime format */
2307 case 'F': /* filesystem type */
2308 case 'g': /* group name */
2309 case 'i': /* inode number */
2310 case 'M': /* mode in `ls -l' format (eg., "drwxr-xr-x") */
2311 case 's': /* size in bytes */
2312 case 't': /* mtime in `ctime' format */
2313 case 'T': /* mtime in user-specified strftime format */
2314 case 'u': /* user name */
2315 pred->need_stat = true;
2316 mycost = NeedsStatInfo;
2317 *fmt++ = 's';
2318 break;
2320 case 'S': /* sparseness */
2321 pred->need_stat = true;
2322 mycost = NeedsStatInfo;
2323 *fmt++ = 'g';
2324 break;
2326 case 'Y': /* symlink pointed file type */
2327 pred->need_stat = true;
2328 mycost = NeedsType; /* true for amortised effect */
2329 *fmt++ = 's';
2330 break;
2332 case 'f': /* basename of path */
2333 case 'h': /* leading directories part of path */
2334 case 'p': /* pathname */
2335 case 'P': /* pathname with ARGV element stripped */
2336 *fmt++ = 's';
2337 break;
2339 case 'H': /* ARGV element file was found under */
2340 *fmt++ = 's';
2341 break;
2343 /* Numeric items that one might expect to honour
2344 * #, 0, + flags but which do not.
2346 case 'G': /* GID number */
2347 case 'U': /* UID number */
2348 case 'b': /* size in 512-byte blocks */
2349 case 'D': /* Filesystem device on which the file exits */
2350 case 'k': /* size in 1K blocks */
2351 case 'n': /* number of links */
2352 pred->need_stat = true;
2353 mycost = NeedsStatInfo;
2354 *fmt++ = 's';
2355 break;
2357 /* Numeric items that DO honour #, 0, + flags.
2359 case 'd': /* depth in search tree (0 = ARGV element) */
2360 *fmt++ = 'd';
2361 break;
2363 case 'm': /* mode as octal number (perms only) */
2364 *fmt++ = 'o';
2365 pred->need_stat = true;
2366 mycost = NeedsStatInfo;
2367 break;
2369 case '{':
2370 case '[':
2371 case '(':
2372 error (1, 0,
2373 _("error: the format directive `%%%c' is reserved for future use"),
2374 (int)kind);
2375 /*NOTREACHED*/
2376 break;
2378 *fmt = '\0';
2380 if (mycost > pred->p_cost)
2381 pred->p_cost = mycost;
2382 return &(*segment)->next;
2385 static void
2386 check_path_safety(const char *action)
2388 const char *path = getenv("PATH");
2389 char *s;
2390 s = next_element(path, 1);
2391 while ((s = next_element ((char *) NULL, 1)) != NULL)
2393 if (0 == strcmp(s, "."))
2395 error(1, 0, _("The current directory is included in the PATH environment variable, which is insecure in combination with the %s action of find. Please remove the current directory from your $PATH (that is, remove \".\" or leading or trailing colons)"),
2396 action);
2402 /* handles both exec and ok predicate */
2403 #if defined(NEW_EXEC)
2404 /* handles both exec and ok predicate */
2405 static boolean
2406 new_insert_exec_ok (const char *action,
2407 const struct parser_table *entry,
2408 char **argv,
2409 int *arg_ptr)
2411 int start, end; /* Indexes in ARGV of start & end of cmd. */
2412 int i; /* Index into cmd args */
2413 int saw_braces; /* True if previous arg was '{}'. */
2414 boolean allow_plus; /* True if + is a valid terminator */
2415 int brace_count; /* Number of instances of {}. */
2416 PRED_FUNC func = entry->pred_func;
2417 enum BC_INIT_STATUS bcstatus;
2419 struct predicate *our_pred;
2420 struct exec_val *execp; /* Pointer for efficiency. */
2422 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
2423 return false;
2425 our_pred = insert_primary_withpred (entry, func);
2426 our_pred->side_effects = our_pred->no_default_print = true;
2427 our_pred->need_type = our_pred->need_stat = false;
2429 execp = &our_pred->args.exec_vec;
2431 if ((func != pred_okdir) && (func != pred_ok))
2433 allow_plus = true;
2434 execp->close_stdin = false;
2436 else
2438 allow_plus = false;
2439 /* If find reads stdin (i.e. for -ok and similar), close stdin
2440 * in the child to prevent some script from consiming the output
2441 * intended for find.
2443 execp->close_stdin = true;
2447 if ((func == pred_execdir) || (func == pred_okdir))
2449 options.ignore_readdir_race = false;
2450 check_path_safety(action);
2451 execp->use_current_dir = true;
2453 else
2455 execp->use_current_dir = false;
2458 our_pred->args.exec_vec.multiple = 0;
2460 /* Count the number of args with path replacements, up until the ';'.
2461 * Also figure out if the command is terminated by ";" or by "+".
2463 start = *arg_ptr;
2464 for (end = start, saw_braces=0, brace_count=0;
2465 (argv[end] != NULL)
2466 && ((argv[end][0] != ';') || (argv[end][1] != '\0'));
2467 end++)
2469 /* For -exec and -execdir, "{} +" can terminate the command. */
2470 if ( allow_plus
2471 && argv[end][0] == '+' && argv[end][1] == 0
2472 && saw_braces)
2474 our_pred->args.exec_vec.multiple = 1;
2475 break;
2478 saw_braces = 0;
2479 if (strstr (argv[end], "{}"))
2481 saw_braces = 1;
2482 ++brace_count;
2484 if (0 == end && (func == pred_execdir || func == pred_okdir))
2486 /* The POSIX standard says that {} replacement should
2487 * occur even in the utility name. This is insecure
2488 * since it means we will be executing a command whose
2489 * name is chosen according to whatever find finds in
2490 * the filesystem. That can be influenced by an
2491 * attacker. Hence for -execdir and -okdir this is not
2492 * allowed. We can specify this as those options are
2493 * not defined by POSIX.
2495 error(1, 0, _("You may not use {} within the utility name for -execdir and -okdir, because this is a potential security problem."));
2500 /* Fail if no command given or no semicolon found. */
2501 if ((end == start) || (argv[end] == NULL))
2503 *arg_ptr = end;
2504 free(our_pred);
2505 return false;
2508 if (our_pred->args.exec_vec.multiple && brace_count > 1)
2511 const char *suffix;
2512 if (func == pred_execdir)
2513 suffix = "dir";
2514 else
2515 suffix = "";
2517 error(1, 0,
2518 _("Only one instance of {} is supported with -exec%s ... +"),
2519 suffix);
2522 /* We use a switch statement here so that
2523 * the compiler warns us when we forget to handle a
2524 * newly invented enum value.
2526 bcstatus = bc_init_controlinfo(&execp->ctl);
2527 switch (bcstatus)
2529 case BC_INIT_ENV_TOO_BIG:
2530 error(1, 0,
2531 _("The environment is too large for exec()."));
2532 break;
2533 case BC_INIT_OK:
2534 /* Good news. Carry on. */
2535 break;
2537 bc_use_sensible_arg_max(&execp->ctl);
2540 execp->ctl.exec_callback = launch;
2542 if (our_pred->args.exec_vec.multiple)
2544 /* "+" terminator, so we can just append our arguments after the
2545 * command and initial arguments.
2547 execp->replace_vec = NULL;
2548 execp->ctl.replace_pat = NULL;
2549 execp->ctl.rplen = 0;
2550 execp->ctl.lines_per_exec = 0; /* no limit */
2551 execp->ctl.args_per_exec = 0; /* no limit */
2553 /* remember how many arguments there are */
2554 execp->ctl.initial_argc = (end-start) - 1;
2556 /* execp->state = xmalloc(sizeof struct buildcmd_state); */
2557 bc_init_state(&execp->ctl, &execp->state, execp);
2559 /* Gather the initial arguments. Skip the {}. */
2560 for (i=start; i<end-1; ++i)
2562 bc_push_arg(&execp->ctl, &execp->state,
2563 argv[i], strlen(argv[i])+1,
2564 NULL, 0,
2568 else
2570 /* Semicolon terminator - more than one {} is supported, so we
2571 * have to do brace-replacement.
2573 execp->num_args = end - start;
2575 execp->ctl.replace_pat = "{}";
2576 execp->ctl.rplen = strlen(execp->ctl.replace_pat);
2577 execp->ctl.lines_per_exec = 0; /* no limit */
2578 execp->ctl.args_per_exec = 0; /* no limit */
2579 execp->replace_vec = xmalloc(sizeof(char*)*execp->num_args);
2582 /* execp->state = xmalloc(sizeof(*(execp->state))); */
2583 bc_init_state(&execp->ctl, &execp->state, execp);
2585 /* Remember the (pre-replacement) arguments for later. */
2586 for (i=0; i<execp->num_args; ++i)
2588 execp->replace_vec[i] = argv[i+start];
2592 if (argv[end] == NULL)
2593 *arg_ptr = end;
2594 else
2595 *arg_ptr = end + 1;
2597 return true;
2599 #else
2600 /* handles both exec and ok predicate */
2601 static boolean
2602 old_insert_exec_ok (boolean (*func) (/* ??? */), char **argv, int *arg_ptr)
2604 int start, end; /* Indexes in ARGV of start & end of cmd. */
2605 int num_paths; /* Number of args with path replacements. */
2606 int path_pos; /* Index in array of path replacements. */
2607 int vec_pos; /* Index in array of args. */
2608 struct predicate *our_pred;
2609 struct exec_val *execp; /* Pointer for efficiency. */
2611 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
2612 return false;
2614 /* Count the number of args with path replacements, up until the ';'. */
2615 start = *arg_ptr;
2616 for (end = start, num_paths = 0;
2617 (argv[end] != NULL)
2618 && ((argv[end][0] != ';') || (argv[end][1] != '\0'));
2619 end++)
2620 if (strstr (argv[end], "{}"))
2621 num_paths++;
2622 /* Fail if no command given or no semicolon found. */
2623 if ((end == start) || (argv[end] == NULL))
2625 *arg_ptr = end;
2626 return false;
2629 our_pred = insert_primary (func);
2630 our_pred->side_effects = our_pred->no_default_print = true;
2631 execp = &our_pred->args.exec_vec;
2632 execp->usercontext = our_pred;
2633 execp->use_current_dir = false;
2634 execp->paths =
2635 (struct path_arg *) xmalloc (sizeof (struct path_arg) * (num_paths + 1));
2636 execp->vec = (char **) xmalloc (sizeof (char *) * (end - start + 1));
2637 /* Record the positions of all args, and the args with path replacements. */
2638 for (end = start, path_pos = vec_pos = 0;
2639 (argv[end] != NULL)
2640 && ((argv[end][0] != ';') || (argv[end][1] != '\0'));
2641 end++)
2643 register char *p;
2645 execp->paths[path_pos].count = 0;
2646 for (p = argv[end]; *p; ++p)
2647 if (p[0] == '{' && p[1] == '}')
2649 execp->paths[path_pos].count++;
2650 ++p;
2652 if (execp->paths[path_pos].count)
2654 execp->paths[path_pos].offset = vec_pos;
2655 execp->paths[path_pos].origarg = argv[end];
2656 path_pos++;
2658 execp->vec[vec_pos++] = argv[end];
2660 execp->paths[path_pos].offset = -1;
2661 execp->vec[vec_pos] = NULL;
2663 if (argv[end] == NULL)
2664 *arg_ptr = end;
2665 else
2666 *arg_ptr = end + 1;
2667 return true;
2669 #endif
2673 static boolean
2674 insert_exec_ok (const char *action, const struct parser_table *entry, char **argv, int *arg_ptr)
2676 #if defined(NEW_EXEC)
2677 return new_insert_exec_ok(action, entry, argv, arg_ptr);
2678 #else
2679 return old_insert_exec_ok(func, argv, arg_ptr);
2680 #endif
2685 /* Get a number of days and comparison type.
2686 STR is the ASCII representation.
2687 Set *NUM_DAYS to the number of days, taken as being from
2688 the current moment (or possibly midnight). Thus the sense of the
2689 comparison type appears to be reversed.
2690 Set *COMP_TYPE to the kind of comparison that is requested.
2692 Return true if all okay, false if input error.
2694 Used by -atime, -ctime and -mtime (parsers) to
2695 get the appropriate information for a time predicate processor. */
2697 static boolean
2698 get_num_days (char *str, uintmax_t *num_days, enum comparison_type *comp_type)
2700 boolean r = get_num (str, num_days, comp_type);
2701 if (r)
2702 switch (*comp_type)
2704 case COMP_LT: *comp_type = COMP_GT; break;
2705 case COMP_GT: *comp_type = COMP_LT; break;
2706 default: break;
2708 return r;
2711 /* Insert a time predicate PRED.
2712 ARGV is a pointer to the argument array.
2713 ARG_PTR is a pointer to an index into the array, incremented if
2714 all went well.
2716 Return true if input is valid, false if not.
2718 A new predicate node is assigned, along with an argument node
2719 obtained with malloc.
2721 Used by -atime, -ctime, and -mtime parsers. */
2723 static boolean
2724 parse_time (const struct parser_table* entry, char *argv[], int *arg_ptr)
2726 struct predicate *our_pred;
2727 uintmax_t num_days;
2728 enum comparison_type c_type;
2729 time_t t;
2731 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
2732 return false;
2733 if (!get_num_days (argv[*arg_ptr], &num_days, &c_type))
2734 return false;
2736 /* Figure out the timestamp value we are looking for. */
2737 t = ( options.cur_day_start - num_days * DAYSECS
2738 + ((c_type == COMP_GT) ? DAYSECS - 1 : 0));
2740 if (1)
2742 /* We introduce a scope in which 'val' can be declared, for the
2743 * benefit of compilers that are really C89 compilers
2744 * which support intmax_t because config.h #defines it
2746 intmax_t val = ( (intmax_t)options.cur_day_start - num_days * DAYSECS
2747 + ((c_type == COMP_GT) ? DAYSECS - 1 : 0));
2748 t = val;
2750 /* Check for possibility of an overflow */
2751 if ( (intmax_t)t != val )
2753 error (1, 0, "arithmetic overflow while converting %s days to a number of seconds", argv[*arg_ptr]);
2757 our_pred = insert_primary (entry);
2758 our_pred->args.info.kind = c_type;
2759 our_pred->args.info.negative = t < 0;
2760 our_pred->args.info.l_val = t;
2761 our_pred->est_success_rate = estimate_file_age_success_rate(num_days);
2762 (*arg_ptr)++;
2764 if (options.debug_options & DebugExpressionTree)
2766 fprintf (stderr, "inserting %s\n", our_pred->p_name);
2767 fprintf (stderr, " type: %s %s ",
2768 (c_type == COMP_GT) ? "gt" :
2769 ((c_type == COMP_LT) ? "lt" : ((c_type == COMP_EQ) ? "eq" : "?")),
2770 (c_type == COMP_GT) ? " >" :
2771 ((c_type == COMP_LT) ? " <" : ((c_type == COMP_EQ) ? ">=" : " ?")));
2772 t = our_pred->args.info.l_val;
2773 fprintf (stderr, "%ju %s", (uintmax_t) our_pred->args.info.l_val, ctime (&t));
2774 if (c_type == COMP_EQ)
2776 t = our_pred->args.info.l_val += DAYSECS;
2777 fprintf (stderr, " < %ju %s",
2778 (uintmax_t) our_pred->args.info.l_val, ctime (&t));
2779 our_pred->args.info.l_val -= DAYSECS;
2783 return true;
2786 /* Get a number with comparison information.
2787 The sense of the comparison information is 'normal'; that is,
2788 '+' looks for a count > than the number and '-' less than.
2790 STR is the ASCII representation of the number.
2791 Set *NUM to the number.
2792 Set *COMP_TYPE to the kind of comparison that is requested.
2794 Return true if all okay, false if input error. */
2796 static boolean
2797 get_num (char *str, uintmax_t *num, enum comparison_type *comp_type)
2799 if (str == NULL)
2800 return false;
2801 switch (str[0])
2803 case '+':
2804 *comp_type = COMP_GT;
2805 str++;
2806 break;
2807 case '-':
2808 *comp_type = COMP_LT;
2809 str++;
2810 break;
2811 default:
2812 *comp_type = COMP_EQ;
2813 break;
2816 return xstrtoumax (str, NULL, 10, num, "") == LONGINT_OK;
2819 /* Insert a number predicate.
2820 ARGV is a pointer to the argument array.
2821 *ARG_PTR is an index into ARGV, incremented if all went well.
2822 *PRED is the predicate processor to insert.
2824 Return true if input is valid, false if error.
2826 A new predicate node is assigned, along with an argument node
2827 obtained with malloc.
2829 Used by -inum and -links parsers. */
2831 static struct predicate *
2832 insert_num (char **argv, int *arg_ptr, const struct parser_table *entry)
2834 struct predicate *our_pred;
2835 uintmax_t num;
2836 enum comparison_type c_type;
2838 if ((argv == NULL) || (argv[*arg_ptr] == NULL))
2839 return NULL;
2840 if (!get_num (argv[*arg_ptr], &num, &c_type))
2841 return NULL;
2842 our_pred = insert_primary (entry);
2843 our_pred->args.info.kind = c_type;
2844 our_pred->args.info.l_val = num;
2845 (*arg_ptr)++;
2847 if (options.debug_options & DebugExpressionTree)
2849 fprintf (stderr, "inserting %s\n", our_pred->p_name);
2850 fprintf (stderr, " type: %s %s ",
2851 (c_type == COMP_GT) ? "gt" :
2852 ((c_type == COMP_LT) ? "lt" : ((c_type == COMP_EQ) ? "eq" : "?")),
2853 (c_type == COMP_GT) ? " >" :
2854 ((c_type == COMP_LT) ? " <" : ((c_type == COMP_EQ) ? " =" : " ?")));
2855 fprintf (stderr, "%ju\n", our_pred->args.info.l_val);
2857 return our_pred;
2860 static FILE *
2861 open_output_file (char *path)
2863 FILE *f;
2865 if (!strcmp (path, "/dev/stderr"))
2866 return stderr;
2867 else if (!strcmp (path, "/dev/stdout"))
2868 return stdout;
2869 f = fopen_safer (path, "w");
2870 if (f == NULL)
2871 error (1, errno, "%s", path);
2872 return f;