1 /* pred.c -- execute the expression tree.
2 Copyright (C) 1990, 1991, 1992, 1993, 1994, 2000, 2003, 2004, 2005,
3 2006, 2007, 2008, 2009, 2010, 2011 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 3 of the License, or
8 (at your option) 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, see <http://www.gnu.org/licenses/>.
19 /* config.h always comes first. */
32 #include <selinux/selinux.h>
35 #include <sys/types.h>
37 #include <unistd.h> /* for unlinkat() */
40 #include "areadlink.h"
45 #include "stat-size.h"
46 #include "stat-time.h"
51 #include "dircallback.h"
53 #include "printquoted.h"
59 # define _(Text) gettext (Text)
64 # define N_(String) gettext_noop (String)
66 /* See locate.c for explanation as to why not use (String) */
67 # define N_(String) String
71 /* Fake a return value. */
72 #define CLOSEDIR(d) (closedir (d), 0)
74 #define CLOSEDIR(d) closedir (d)
77 static bool match_lname (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr, bool ignore_case);
86 struct pred_assoc pred_table[] =
90 {pred_anewer, "anewer "},
91 {pred_atime, "atime "},
92 {pred_closeparen, ") "},
94 {pred_cnewer, "cnewer "},
96 {pred_ctime, "ctime "},
97 {pred_delete, "delete "},
98 {pred_empty, "empty "},
100 {pred_execdir, "execdir "},
101 {pred_executable, "executable "},
102 {pred_false, "false "},
103 {pred_fprint, "fprint "},
104 {pred_fprint0, "fprint0 "},
105 {pred_fprintf, "fprintf "},
106 {pred_fstype, "fstype "},
108 {pred_group, "group "},
109 {pred_ilname, "ilname "},
110 {pred_iname, "iname "},
111 {pred_inum, "inum "},
112 {pred_ipath, "ipath "},
113 {pred_links, "links "},
114 {pred_lname, "lname "},
116 {pred_mmin, "mmin "},
117 {pred_mtime, "mtime "},
118 {pred_name, "name "},
119 {pred_negate, "not "},
120 {pred_newer, "newer "},
121 {pred_newerXY, "newerXY "},
122 {pred_nogroup, "nogroup "},
123 {pred_nouser, "nouser "},
125 {pred_okdir, "okdir "},
126 {pred_openparen, "( "},
128 {pred_path, "path "},
129 {pred_perm, "perm "},
130 {pred_print, "print "},
131 {pred_print0, "print0 "},
132 {pred_prune, "prune "},
133 {pred_quit, "quit "},
134 {pred_readable, "readable "},
135 {pred_regex, "regex "},
136 {pred_samefile,"samefile "},
137 {pred_size, "size "},
138 {pred_true, "true "},
139 {pred_type, "type "},
141 {pred_used, "used "},
142 {pred_user, "user "},
143 {pred_writable, "writable "},
144 {pred_xtype, "xtype "},
145 {pred_context, "context"},
150 /* Returns ts1 - ts2 */
151 static double ts_difference (struct timespec ts1,
154 double d = difftime (ts1.tv_sec, ts2.tv_sec)
155 + (1.0e-9 * (ts1.tv_nsec - ts2.tv_nsec));
161 compare_ts (struct timespec ts1,
164 if ((ts1.tv_sec == ts2.tv_sec) &&
165 (ts1.tv_nsec == ts2.tv_nsec))
171 double diff = ts_difference (ts1, ts2);
172 return diff < 0.0 ? -1 : +1;
176 /* Predicate processing routines.
178 PATHNAME is the full pathname of the file being checked.
179 *STAT_BUF contains information about PATHNAME.
180 *PRED_PTR contains information for applying the predicate.
182 Return true if the file passes this predicate, false if not. */
187 * Returns true if THE_TIME is
188 * COMP_GT: after the specified time
189 * COMP_LT: before the specified time
190 * COMP_EQ: after the specified time but by not more than WINDOW seconds.
193 pred_timewindow (struct timespec ts, struct predicate const *pred_ptr, int window)
195 switch (pred_ptr->args.reftime.kind)
198 return compare_ts (ts, pred_ptr->args.reftime.ts) > 0;
201 return compare_ts (ts, pred_ptr->args.reftime.ts) < 0;
205 /* consider "find . -mtime 0".
207 * Here, the origin is exactly 86400 seconds before the start
208 * of the program (since -daystart was not specified). This
209 * function will be called with window=86400 and
210 * pred_ptr->args.reftime.ts as the origin. Hence a file
211 * created the instant the program starts will show a time
212 * difference (value of delta) of 86400. Similarly, a file
213 * created exactly 24h ago would be the newest file which was
214 * _not_ created today. So, if delta is 0.0, the file
215 * was not created today. If the delta is 86400, the file
216 * was created this instant.
218 double delta = ts_difference (ts, pred_ptr->args.reftime.ts);
219 return (delta > 0.0 && delta <= window);
228 pred_amin (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
231 return pred_timewindow (get_stat_atime(stat_buf), pred_ptr, 60);
235 pred_and (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
237 if (pred_ptr->pred_left == NULL
238 || apply_predicate (pathname, stat_buf, pred_ptr->pred_left))
240 return apply_predicate (pathname, stat_buf, pred_ptr->pred_right);
247 pred_anewer (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
250 assert (COMP_GT == pred_ptr->args.reftime.kind);
251 return compare_ts (get_stat_atime(stat_buf), pred_ptr->args.reftime.ts) > 0;
255 pred_atime (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
258 return pred_timewindow (get_stat_atime(stat_buf), pred_ptr, DAYSECS);
262 pred_closeparen (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
272 pred_cmin (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
275 return pred_timewindow (get_stat_ctime(stat_buf), pred_ptr, 60);
279 pred_cnewer (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
283 assert (COMP_GT == pred_ptr->args.reftime.kind);
284 return compare_ts (get_stat_ctime(stat_buf), pred_ptr->args.reftime.ts) > 0;
288 pred_comma (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
290 if (pred_ptr->pred_left != NULL)
292 apply_predicate (pathname, stat_buf,pred_ptr->pred_left);
294 return apply_predicate (pathname, stat_buf, pred_ptr->pred_right);
298 pred_ctime (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
301 return pred_timewindow (get_stat_ctime(stat_buf), pred_ptr, DAYSECS);
305 perform_delete (int flags)
307 return 0 == unlinkat (state.cwd_dir_fd, state.rel_pathname, flags);
312 pred_delete (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
316 if (strcmp (state.rel_pathname, "."))
319 if (state.have_stat && S_ISDIR(stat_buf->st_mode))
320 flags |= AT_REMOVEDIR;
321 if (perform_delete (flags))
329 if ((flags & AT_REMOVEDIR) == 0)
331 /* unlink() operation failed because we should have done rmdir(). */
332 flags |= AT_REMOVEDIR;
333 if (perform_delete (flags))
338 error (0, errno, _("cannot delete %s"),
339 safely_quote_err_filename (0, pathname));
340 /* Previously I had believed that having the -delete action
341 * return false provided the user with control over whether an
342 * error message is issued. While this is true, the policy of
343 * not affecting the exit status is contrary to the POSIX
344 * requirement that diagnostic messages are accompanied by a
345 * nonzero exit status. While -delete is not a POSIX option and
346 * we can therefore opt not to follow POSIX in this case, that
347 * seems somewhat arbitrary and confusing. So, as of
348 * findutils-4.3.11, we also set the exit status in this case.
350 state.exit_status = 1;
361 pred_empty (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
366 if (S_ISDIR (stat_buf->st_mode))
374 if ((fd = openat (state.cwd_dir_fd, state.rel_pathname, O_RDONLY
375 #if defined O_LARGEFILE
380 error (0, errno, "%s", safely_quote_err_filename (0, pathname));
381 state.exit_status = 1;
387 error (0, errno, "%s", safely_quote_err_filename (0, pathname));
388 state.exit_status = 1;
391 for (dp = readdir (d); dp; dp = readdir (d))
393 if (dp->d_name[0] != '.'
394 || (dp->d_name[1] != '\0'
395 && (dp->d_name[1] != '.' || dp->d_name[2] != '\0')))
403 error (0, errno, "%s", safely_quote_err_filename (0, pathname));
404 state.exit_status = 1;
409 else if (S_ISREG (stat_buf->st_mode))
410 return (stat_buf->st_size == 0);
417 pred_exec (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
419 return impl_pred_exec (pathname, stat_buf, pred_ptr);
423 pred_execdir (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
426 return impl_pred_exec (state.rel_pathname, stat_buf, pred_ptr);
430 pred_false (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
441 pred_fls (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
443 FILE * stream = pred_ptr->args.printf_vec.stream;
444 list_file (pathname, state.cwd_dir_fd, state.rel_pathname, stat_buf,
445 options.start_time.tv_sec,
446 options.output_block_size,
447 pred_ptr->literal_control_chars, stream);
452 pred_fprint (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
457 print_quoted (pred_ptr->args.printf_vec.stream,
458 pred_ptr->args.printf_vec.quote_opts,
459 pred_ptr->args.printf_vec.dest_is_tty,
466 pred_fprint0 (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
468 FILE * fp = pred_ptr->args.printf_vec.stream;
472 fputs (pathname, fp);
480 pred_fstype (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
484 if (strcmp (filesystem_type (stat_buf, pathname), pred_ptr->args.str) == 0)
491 pred_gid (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
495 switch (pred_ptr->args.numinfo.kind)
498 if (stat_buf->st_gid > pred_ptr->args.numinfo.l_val)
502 if (stat_buf->st_gid < pred_ptr->args.numinfo.l_val)
506 if (stat_buf->st_gid == pred_ptr->args.numinfo.l_val)
514 pred_group (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
518 if (pred_ptr->args.gid == stat_buf->st_gid)
525 pred_ilname (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
527 return match_lname (pathname, stat_buf, pred_ptr, true);
530 /* Common code between -name, -iname. PATHNAME is being visited, STR
531 is name to compare basename against, and FLAGS are passed to
532 fnmatch. Recall that 'find / -name /' is one of the few times where a '/'
533 in the -name must actually find something. */
535 pred_name_common (const char *pathname, const char *str, int flags)
538 /* We used to use last_component() here, but that would not allow us to modify the
539 * input string, which is const. We could optimise by duplicating the string only
540 * if we need to modify it, and I'll do that if there is a measurable
541 * performance difference on a machine built after 1990...
543 char *base = base_name (pathname);
544 /* remove trailing slashes, but leave "/" or "//foo" unchanged. */
545 strip_trailing_slashes (base);
547 /* FNM_PERIOD is not used here because POSIX requires that it not be.
548 * See http://standards.ieee.org/reading/ieee/interp/1003-2-92_int/pasc-1003.2-126.html
550 b = fnmatch (str, base, flags) == 0;
556 pred_iname (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
559 return pred_name_common (pathname, pred_ptr->args.str, FNM_CASEFOLD);
563 pred_inum (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
567 assert (stat_buf->st_ino != 0);
569 switch (pred_ptr->args.numinfo.kind)
572 if (stat_buf->st_ino > pred_ptr->args.numinfo.l_val)
576 if (stat_buf->st_ino < pred_ptr->args.numinfo.l_val)
580 if (stat_buf->st_ino == pred_ptr->args.numinfo.l_val)
588 pred_ipath (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
592 if (fnmatch (pred_ptr->args.str, pathname, FNM_CASEFOLD) == 0)
598 pred_links (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
602 switch (pred_ptr->args.numinfo.kind)
605 if (stat_buf->st_nlink > pred_ptr->args.numinfo.l_val)
609 if (stat_buf->st_nlink < pred_ptr->args.numinfo.l_val)
613 if (stat_buf->st_nlink == pred_ptr->args.numinfo.l_val)
621 pred_lname (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
623 return match_lname (pathname, stat_buf, pred_ptr, false);
627 match_lname (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr, bool ignore_case)
631 if (S_ISLNK (stat_buf->st_mode))
633 char *linkname = areadlinkat (state.cwd_dir_fd, state.rel_pathname);
636 if (fnmatch (pred_ptr->args.str, linkname,
637 ignore_case ? FNM_CASEFOLD : 0) == 0)
642 nonfatal_target_file_error (errno, pathname);
643 state.exit_status = 1;
652 pred_ls (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
654 return pred_fls (pathname, stat_buf, pred_ptr);
658 pred_mmin (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
661 return pred_timewindow (get_stat_mtime(stat_buf), pred_ptr, 60);
665 pred_mtime (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
668 return pred_timewindow (get_stat_mtime(stat_buf), pred_ptr, DAYSECS);
672 pred_name (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
675 return pred_name_common (pathname, pred_ptr->args.str, 0);
679 pred_negate (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
681 return !apply_predicate (pathname, stat_buf, pred_ptr->pred_right);
685 pred_newer (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
689 assert (COMP_GT == pred_ptr->args.reftime.kind);
690 return compare_ts (get_stat_mtime(stat_buf), pred_ptr->args.reftime.ts) > 0;
694 pred_newerXY (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
697 bool collected = false;
699 assert (COMP_GT == pred_ptr->args.reftime.kind);
701 switch (pred_ptr->args.reftime.xval)
704 assert (pred_ptr->args.reftime.xval != XVAL_TIME);
708 ts = get_stat_atime (stat_buf);
713 ts = get_stat_birthtime (stat_buf);
717 /* XXX: Cannot determine birth time. Warn once. */
718 error (0, 0, _("WARNING: cannot determine birth time of file %s"),
719 safely_quote_err_filename (0, pathname));
725 ts = get_stat_ctime (stat_buf);
730 ts = get_stat_mtime (stat_buf);
736 return compare_ts (ts, pred_ptr->args.reftime.ts) > 0;
740 pred_nogroup (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
746 extern char *gid_unused;
748 return gid_unused[(unsigned) stat_buf->st_gid];
750 return getgrgid (stat_buf->st_gid) == NULL;
755 pred_nouser (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
758 extern char *uid_unused;
765 return uid_unused[(unsigned) stat_buf->st_uid];
767 return getpwuid (stat_buf->st_uid) == NULL;
773 is_ok (const char *program, const char *arg)
776 /* The draft open standard requires that, in the POSIX locale,
777 the last non-blank character of this prompt be '?'.
778 The exact format is not specified.
779 This standard does not have requirements for locales other than POSIX
781 /* XXX: printing UNTRUSTED data here. */
782 if (fprintf (stderr, _("< %s ... %s > ? "), program, arg) < 0)
784 error (EXIT_FAILURE, errno, _("Failed to write prompt for -ok"));
791 pred_ok (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
793 if (is_ok (pred_ptr->args.exec_vec.replace_vec[0], pathname))
794 return impl_pred_exec (pathname, stat_buf, pred_ptr);
800 pred_okdir (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
802 if (is_ok (pred_ptr->args.exec_vec.replace_vec[0], pathname))
803 return impl_pred_exec (state.rel_pathname, stat_buf, pred_ptr);
809 pred_openparen (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
818 pred_or (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
820 if (pred_ptr->pred_left == NULL
821 || !apply_predicate (pathname, stat_buf, pred_ptr->pred_left))
823 return apply_predicate (pathname, stat_buf, pred_ptr->pred_right);
830 pred_path (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
833 if (fnmatch (pred_ptr->args.str, pathname, 0) == 0)
839 pred_perm (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
841 mode_t mode = stat_buf->st_mode;
842 mode_t perm_val = pred_ptr->args.perm.val[S_ISDIR (mode) != 0];
844 switch (pred_ptr->args.perm.kind)
847 return (mode & perm_val) == perm_val;
851 /* True if any of the bits set in the mask are also set in the file's mode.
854 * Otherwise, if onum is prefixed by a hyphen, the primary shall
855 * evaluate as true if at least all of the bits specified in
856 * onum that are also set in the octal mask 07777 are set.
858 * Eric Blake's interpretation is that the mode argument is zero,
862 return true; /* Savannah bug 14748; we used to return false */
864 return (mode & perm_val) != 0;
868 return (mode & MODE_ALL) == perm_val;
879 pred_executable (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
885 /* As for access, the check is performed with the real user id. */
886 return 0 == faccessat (state.cwd_dir_fd, state.rel_pathname, X_OK, 0);
890 pred_readable (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
896 /* As for access, the check is performed with the real user id. */
897 return 0 == faccessat (state.cwd_dir_fd, state.rel_pathname, R_OK, 0);
901 pred_writable (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
907 /* As for access, the check is performed with the real user id. */
908 return 0 == faccessat (state.cwd_dir_fd, state.rel_pathname, W_OK, 0);
912 pred_print (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
917 print_quoted (pred_ptr->args.printf_vec.stream,
918 pred_ptr->args.printf_vec.quote_opts,
919 pred_ptr->args.printf_vec.dest_is_tty,
925 pred_print0 (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
927 return pred_fprint0(pathname, stat_buf, pred_ptr);
931 pred_prune (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
936 if (options.do_dir_first == true) { /* no effect with -depth */
937 assert (state.have_stat);
938 if (stat_buf != NULL &&
939 S_ISDIR(stat_buf->st_mode))
940 state.stop_at_current_level = true;
943 /* findutils used to return options.do_dir_first here, so that -prune
944 * returns true only if -depth is not in effect. But POSIX requires
945 * that -prune always evaluate as true.
951 pred_quit (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
957 /* Run any cleanups. This includes executing any command lines
958 * we have partly built but not executed.
962 /* Since -exec and friends don't leave child processes running in the
963 * background, there is no need to wait for them here.
965 exit (state.exit_status); /* 0 for success, etc. */
969 pred_regex (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
971 int len = strlen (pathname);
973 if (re_match (pred_ptr->args.regex, pathname, len, 0,
974 (struct re_registers *) NULL) == len)
980 pred_size (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
985 f_val = ((stat_buf->st_size / pred_ptr->args.size.blocksize)
986 + (stat_buf->st_size % pred_ptr->args.size.blocksize != 0));
987 switch (pred_ptr->args.size.kind)
990 if (f_val > pred_ptr->args.size.size)
994 if (f_val < pred_ptr->args.size.size)
998 if (f_val == pred_ptr->args.size.size)
1006 pred_samefile (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1008 /* Potential optimisation: because of the loop protection, we always
1009 * know the device of the current directory, hence the device number
1010 * of the file we're currently considering. If -L is not in effect,
1011 * and the device number of the file we're looking for is not the
1012 * same as the device number of the current directory, this
1013 * predicate cannot return true. Hence there would be no need to
1014 * stat the file we're looking at.
1016 * For the moment, we simply compare inode numbers, which should cut
1017 * down greatly on the number of calls to stat. Some of the
1018 * remainder will be unnecessary, but the additional complexity
1019 * probably isn't worthwhile.
1023 /* We will often still have an fd open on the file under consideration,
1024 * but that's just to ensure inode number stability by maintaining
1025 * a reference to it; we don't need the file for anything else.
1027 if (stat_buf->st_ino)
1029 if (stat_buf->st_ino != pred_ptr->args.samefileid.ino)
1032 /* Now stat the file to check the device number. */
1033 if (0 == get_statinfo (pathname, state.rel_pathname, stat_buf))
1035 /* the repeated test here is necessary in case stat_buf.st_ino had been zero. */
1036 return stat_buf->st_ino == pred_ptr->args.samefileid.ino
1037 && stat_buf->st_dev == pred_ptr->args.samefileid.dev;
1041 /* get_statinfo will already have emitted an error message. */
1047 pred_true (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1056 pred_type (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1059 mode_t type = pred_ptr->args.type;
1061 assert (state.have_type);
1063 if (0 == state.type)
1065 /* This can sometimes happen with broken NFS servers.
1066 * See Savannah bug #16378.
1073 if (state.have_stat)
1074 mode = stat_buf->st_mode;
1079 /* POSIX system; check `mode' the slow way. */
1080 if ((S_ISBLK (mode) && type == S_IFBLK)
1081 || (S_ISCHR (mode) && type == S_IFCHR)
1082 || (S_ISDIR (mode) && type == S_IFDIR)
1083 || (S_ISREG (mode) && type == S_IFREG)
1085 || (S_ISLNK (mode) && type == S_IFLNK)
1088 || (S_ISFIFO (mode) && type == S_IFIFO)
1091 || (S_ISSOCK (mode) && type == S_IFSOCK)
1094 || (S_ISDOOR (mode) && type == S_IFDOOR)
1098 /* Unix system; check `mode' the fast way. */
1099 if ((mode & S_IFMT) == type)
1107 pred_uid (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1110 switch (pred_ptr->args.numinfo.kind)
1113 if (stat_buf->st_uid > pred_ptr->args.numinfo.l_val)
1117 if (stat_buf->st_uid < pred_ptr->args.numinfo.l_val)
1121 if (stat_buf->st_uid == pred_ptr->args.numinfo.l_val)
1129 pred_used (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1131 struct timespec delta, at, ct;
1135 /* TODO: this needs to be retested carefully (manually, if necessary) */
1136 at = get_stat_atime (stat_buf);
1137 ct = get_stat_ctime (stat_buf);
1138 delta.tv_sec = at.tv_sec - ct.tv_sec;
1139 delta.tv_nsec = at.tv_nsec - ct.tv_nsec;
1140 if (delta.tv_nsec < 0)
1142 delta.tv_nsec += 1000000000;
1145 return pred_timewindow (delta, pred_ptr, DAYSECS);
1149 pred_user (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1152 if (pred_ptr->args.uid == stat_buf->st_uid)
1159 pred_xtype (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1161 struct stat sbuf; /* local copy, not stat_buf because we're using a different stat method */
1162 int (*ystat) (const char*, struct stat *p);
1164 /* If we would normally stat the link itself, stat the target instead.
1165 * If we would normally follow the link, stat the link itself instead.
1167 if (following_links ())
1168 ystat = optionp_stat;
1170 ystat = optionl_stat;
1172 set_stat_placeholders (&sbuf);
1173 if ((*ystat) (state.rel_pathname, &sbuf) != 0)
1175 if (following_links () && errno == ENOENT)
1177 /* If we failed to follow the symlink,
1178 * fall back on looking at the symlink itself.
1180 /* Mimic behavior of ls -lL. */
1181 return (pred_type (pathname, stat_buf, pred_ptr));
1185 error (0, errno, "%s", safely_quote_err_filename (0, pathname));
1186 state.exit_status = 1;
1190 /* Now that we have our stat() information, query it in the same
1191 * way that -type does.
1193 return (pred_type (pathname, &sbuf, pred_ptr));
1198 pred_context (const char *pathname, struct stat *stat_buf,
1199 struct predicate *pred_ptr)
1201 security_context_t scontext;
1202 int rv = (*options.x_getfilecon) (state.cwd_dir_fd, state.rel_pathname,
1208 error (0, errno, _("getfilecon failed: %s"),
1209 safely_quote_err_filename (0, pathname));
1213 rv = (fnmatch (pred_ptr->args.scontext, scontext, 0) == 0);
1218 /* Copy STR into BUF and trim blanks from the end of BUF.
1222 blank_rtrim (const char *str, char *buf)
1229 i = strlen (buf) - 1;
1230 while ((i >= 0) && ((buf[i] == ' ') || buf[i] == '\t'))
1236 /* Print out the predicate list starting at NODE. */
1238 print_list (FILE *fp, struct predicate *node)
1240 struct predicate *cur;
1246 fprintf (fp, "[%s] ", blank_rtrim (cur->p_name, name));
1247 cur = cur->pred_next;
1252 /* Print out the predicate list starting at NODE. */
1254 print_parenthesised (FILE *fp, struct predicate *node)
1260 if ((pred_is (node, pred_or) || pred_is (node, pred_and))
1261 && node->pred_left == NULL)
1263 /* We print "<nothing> or X" as just "X"
1264 * We print "<nothing> and X" as just "X"
1266 print_parenthesised(fp, node->pred_right);
1270 if (node->pred_left || node->pred_right)
1274 fprintf (fp, "%s", " ( ");
1275 print_optlist (fp, node);
1277 fprintf (fp, "%s", " ) ");
1283 print_optlist (FILE *fp, const struct predicate *p)
1287 print_parenthesised (fp, p->pred_left);
1290 p->need_stat ? "[call stat] " : "",
1291 p->need_type ? "[need type] " : "",
1292 p->need_inum ? "[need inum] " : "");
1293 print_predicate (fp, p);
1294 fprintf (fp, " [%g] ", p->est_success_rate);
1295 if (options.debug_options & DebugSuccessRates)
1297 fprintf (fp, "[%ld/%ld", p->perf.successes, p->perf.visits);
1300 double real_rate = (double)p->perf.successes / (double)p->perf.visits;
1301 fprintf (fp, "=%g] ", real_rate);
1305 fprintf (fp, "=_] ");
1308 print_parenthesised (fp, p->pred_right);
1312 void show_success_rates (const struct predicate *p)
1314 if (options.debug_options & DebugSuccessRates)
1316 fprintf (stderr, "Predicate success rates after completion:\n");
1317 print_optlist (stderr, p);
1318 fprintf (stderr, "\n");
1326 /* If _NDEBUG is defined, the assertions will do nothing. Hence
1327 * there is no point in having a function body for pred_sanity_check()
1328 * if that preprocessor macro is defined.
1331 pred_sanity_check (const struct predicate *predicates)
1333 /* Do nothing, since assert is a no-op with _NDEBUG set */
1338 pred_sanity_check (const struct predicate *predicates)
1340 const struct predicate *p;
1342 for (p=predicates; p != NULL; p=p->pred_next)
1344 /* All predicates must do something. */
1345 assert (p->pred_func != NULL);
1347 /* All predicates must have a parser table entry. */
1348 assert (p->parser_entry != NULL);
1350 /* If the parser table tells us that just one predicate function is
1351 * possible, verify that that is still the one that is in effect.
1352 * If the parser has NULL for the predicate function, that means that
1353 * the parse_xxx function fills it in, so we can't check it.
1355 if (p->parser_entry->pred_func)
1357 assert (p->parser_entry->pred_func == p->pred_func);
1360 switch (p->parser_entry->type)
1362 /* Options all take effect during parsing, so there should
1363 * be no predicate entries corresponding to them. Hence we
1364 * should not see any ARG_OPTION or ARG_POSITIONAL_OPTION
1367 * This is a silly way of coding this test, but it prevents
1368 * a compiler warning (i.e. otherwise it would think that
1369 * there would be case statements missing).
1372 case ARG_POSITIONAL_OPTION:
1373 assert (p->parser_entry->type != ARG_OPTION);
1374 assert (p->parser_entry->type != ARG_POSITIONAL_OPTION);
1378 assert (p->side_effects); /* actions have side effects. */
1379 if (!pred_is (p, pred_prune) && !pred_is(p, pred_quit))
1381 /* actions other than -prune and -quit should
1382 * inhibit the default -print
1384 assert (p->no_default_print);
1388 /* We happen to know that the only user of ARG_SPECIAL_PARSE
1389 * is a test, so handle it like ARG_TEST.
1391 case ARG_SPECIAL_PARSE:
1393 case ARG_PUNCTUATION:
1395 /* Punctuation and tests should have no side
1396 * effects and not inhibit default print.
1398 assert (!p->no_default_print);
1399 assert (!p->side_effects);