Resolves Savannah bug 4380, that updatedb generates an empty database if one of the...
[findutils.git] / find / pred.c
blob4b120541e3c0200734d99fd30620138c597e8081
1 /* pred.c -- execute the expression tree.
2 Copyright (C) 1990, 91, 92, 93, 94, 2000, 2003 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 9 Temple Place - Suite 330, Boston, MA 02111-1307,
17 USA.
20 #define _GNU_SOURCE
21 #include "defs.h"
23 #include <fnmatch.h>
24 #include <signal.h>
25 #include <pwd.h>
26 #include <grp.h>
27 #include "dirname.h"
28 #include "human.h"
29 #include "modetype.h"
30 #include "wait.h"
32 #if ENABLE_NLS
33 # include <libintl.h>
34 # define _(Text) gettext (Text)
35 #else
36 # define _(Text) Text
37 #endif
38 #ifdef gettext_noop
39 # define N_(String) gettext_noop (String)
40 #else
41 # define N_(String) (String)
42 #endif
44 #if !defined(SIGCHLD) && defined(SIGCLD)
45 #define SIGCHLD SIGCLD
46 #endif
48 #if HAVE_DIRENT_H
49 # include <dirent.h>
50 # define NAMLEN(dirent) strlen((dirent)->d_name)
51 #else
52 # define dirent direct
53 # define NAMLEN(dirent) (dirent)->d_namlen
54 # if HAVE_SYS_NDIR_H
55 # include <sys/ndir.h>
56 # endif
57 # if HAVE_SYS_DIR_H
58 # include <sys/dir.h>
59 # endif
60 # if HAVE_NDIR_H
61 # include <ndir.h>
62 # endif
63 #endif
65 #ifdef CLOSEDIR_VOID
66 /* Fake a return value. */
67 #define CLOSEDIR(d) (closedir (d), 0)
68 #else
69 #define CLOSEDIR(d) closedir (d)
70 #endif
72 extern int yesno ();
75 /* Get or fake the disk device blocksize.
76 Usually defined by sys/param.h (if at all). */
77 #ifndef DEV_BSIZE
78 # ifdef BSIZE
79 # define DEV_BSIZE BSIZE
80 # else /* !BSIZE */
81 # define DEV_BSIZE 4096
82 # endif /* !BSIZE */
83 #endif /* !DEV_BSIZE */
85 /* Extract or fake data from a `struct stat'.
86 ST_BLKSIZE: Preferred I/O blocksize for the file, in bytes.
87 ST_NBLOCKS: Number of blocks in the file, including indirect blocks.
88 ST_NBLOCKSIZE: Size of blocks used when calculating ST_NBLOCKS. */
89 #ifndef HAVE_STRUCT_STAT_ST_BLOCKS
90 # define ST_BLKSIZE(statbuf) DEV_BSIZE
91 # if defined(_POSIX_SOURCE) || !defined(BSIZE) /* fileblocks.c uses BSIZE. */
92 # define ST_NBLOCKS(statbuf) \
93 (S_ISREG ((statbuf).st_mode) \
94 || S_ISDIR ((statbuf).st_mode) \
95 ? (statbuf).st_size / ST_NBLOCKSIZE + ((statbuf).st_size % ST_NBLOCKSIZE != 0) : 0)
96 # else /* !_POSIX_SOURCE && BSIZE */
97 # define ST_NBLOCKS(statbuf) \
98 (S_ISREG ((statbuf).st_mode) \
99 || S_ISDIR ((statbuf).st_mode) \
100 ? st_blocks ((statbuf).st_size) : 0)
101 # endif /* !_POSIX_SOURCE && BSIZE */
102 #else /* HAVE_STRUCT_STAT_ST_BLOCKS */
103 /* Some systems, like Sequents, return st_blksize of 0 on pipes. */
104 # define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \
105 ? (statbuf).st_blksize : DEV_BSIZE)
106 # if defined(hpux) || defined(__hpux__) || defined(__hpux)
107 /* HP-UX counts st_blocks in 1024-byte units.
108 This loses when mixing HP-UX and BSD filesystems with NFS. */
109 # define ST_NBLOCKSIZE 1024
110 # else /* !hpux */
111 # if defined(_AIX) && defined(_I386)
112 /* AIX PS/2 counts st_blocks in 4K units. */
113 # define ST_NBLOCKSIZE (4 * 1024)
114 # else /* not AIX PS/2 */
115 # if defined(_CRAY)
116 # define ST_NBLOCKS(statbuf) \
117 (S_ISREG ((statbuf).st_mode) \
118 || S_ISDIR ((statbuf).st_mode) \
119 ? (statbuf).st_blocks * ST_BLKSIZE(statbuf)/ST_NBLOCKSIZE : 0)
120 # endif /* _CRAY */
121 # endif /* not AIX PS/2 */
122 # endif /* !hpux */
123 #endif /* HAVE_STRUCT_STAT_ST_BLOCKS */
125 #ifndef ST_NBLOCKS
126 # define ST_NBLOCKS(statbuf) \
127 (S_ISREG ((statbuf).st_mode) \
128 || S_ISDIR ((statbuf).st_mode) \
129 ? (statbuf).st_blocks : 0)
130 #endif
132 #ifndef ST_NBLOCKSIZE
133 # define ST_NBLOCKSIZE 512
134 #endif
136 #undef MAX
137 #define MAX(a, b) ((a) > (b) ? (a) : (b))
139 static boolean insert_lname PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr, boolean ignore_case));
140 static boolean launch PARAMS((struct predicate *pred_ptr));
141 static char *format_date PARAMS((time_t when, int kind));
142 static char *ctime_format PARAMS((time_t when));
144 #ifdef DEBUG
145 struct pred_assoc
147 PFB pred_func;
148 char *pred_name;
151 struct pred_assoc pred_table[] =
153 {pred_amin, "amin "},
154 {pred_and, "and "},
155 {pred_anewer, "anewer "},
156 {pred_atime, "atime "},
157 {pred_close, ") "},
158 {pred_amin, "cmin "},
159 {pred_cnewer, "cnewer "},
160 {pred_comma, ", "},
161 {pred_ctime, "ctime "},
162 {pred_empty, "empty "},
163 {pred_exec, "exec "},
164 {pred_false, "false "},
165 {pred_fprint, "fprint "},
166 {pred_fprint0, "fprint0 "},
167 {pred_fprintf, "fprintf "},
168 {pred_fstype, "fstype "},
169 {pred_gid, "gid "},
170 {pred_group, "group "},
171 {pred_ilname, "ilname "},
172 {pred_iname, "iname "},
173 {pred_inum, "inum "},
174 {pred_ipath, "ipath "},
175 {pred_links, "links "},
176 {pred_lname, "lname "},
177 {pred_ls, "ls "},
178 {pred_amin, "mmin "},
179 {pred_mtime, "mtime "},
180 {pred_name, "name "},
181 {pred_negate, "not "},
182 {pred_newer, "newer "},
183 {pred_nogroup, "nogroup "},
184 {pred_nouser, "nouser "},
185 {pred_ok, "ok "},
186 {pred_open, "( "},
187 {pred_or, "or "},
188 {pred_path, "path "},
189 {pred_perm, "perm "},
190 {pred_print, "print "},
191 {pred_print0, "print0 "},
192 {pred_prune, "prune "},
193 {pred_regex, "regex "},
194 {pred_size, "size "},
195 {pred_true, "true "},
196 {pred_type, "type "},
197 {pred_uid, "uid "},
198 {pred_used, "used "},
199 {pred_user, "user "},
200 {pred_xtype, "xtype "},
201 {0, "none "}
204 struct op_assoc
206 short type;
207 char *type_name;
210 struct op_assoc type_table[] =
212 {NO_TYPE, "no "},
213 {PRIMARY_TYPE, "primary "},
214 {UNI_OP, "uni_op "},
215 {BI_OP, "bi_op "},
216 {OPEN_PAREN, "open_paren "},
217 {CLOSE_PAREN, "close_paren "},
218 {-1, "unknown "}
221 struct prec_assoc
223 short prec;
224 char *prec_name;
227 struct prec_assoc prec_table[] =
229 {NO_PREC, "no "},
230 {COMMA_PREC, "comma "},
231 {OR_PREC, "or "},
232 {AND_PREC, "and "},
233 {NEGATE_PREC, "negate "},
234 {MAX_PREC, "max "},
235 {-1, "unknown "}
237 #endif /* DEBUG */
239 /* Predicate processing routines.
241 PATHNAME is the full pathname of the file being checked.
242 *STAT_BUF contains information about PATHNAME.
243 *PRED_PTR contains information for applying the predicate.
245 Return true if the file passes this predicate, false if not. */
247 boolean
248 pred_amin (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
250 switch (pred_ptr->args.info.kind)
252 case COMP_GT:
253 if (stat_buf->st_atime > (time_t) pred_ptr->args.info.l_val)
254 return (true);
255 break;
256 case COMP_LT:
257 if (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val)
258 return (true);
259 break;
260 case COMP_EQ:
261 if ((stat_buf->st_atime >= (time_t) pred_ptr->args.info.l_val)
262 && (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val + 60))
263 return (true);
264 break;
266 return (false);
269 boolean
270 pred_and (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
272 if (pred_ptr->pred_left == NULL
273 || (*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
274 pred_ptr->pred_left))
276 /* Check whether we need a stat here. */
277 if (pred_ptr->need_stat)
279 if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
281 error (0, errno, "%s", pathname);
282 exit_status = 1;
283 return (false);
285 have_stat = true;
287 return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
288 pred_ptr->pred_right));
290 else
291 return (false);
294 boolean
295 pred_anewer (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
297 if (stat_buf->st_atime > pred_ptr->args.time)
298 return (true);
299 return (false);
302 boolean
303 pred_atime (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
305 switch (pred_ptr->args.info.kind)
307 case COMP_GT:
308 if (stat_buf->st_atime > (time_t) pred_ptr->args.info.l_val)
309 return (true);
310 break;
311 case COMP_LT:
312 if (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val)
313 return (true);
314 break;
315 case COMP_EQ:
316 if ((stat_buf->st_atime >= (time_t) pred_ptr->args.info.l_val)
317 && (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val
318 + DAYSECS))
319 return (true);
320 break;
322 return (false);
325 boolean
326 pred_close (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
328 return (true);
331 boolean
332 pred_cmin (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
334 switch (pred_ptr->args.info.kind)
336 case COMP_GT:
337 if (stat_buf->st_ctime > (time_t) pred_ptr->args.info.l_val)
338 return (true);
339 break;
340 case COMP_LT:
341 if (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val)
342 return (true);
343 break;
344 case COMP_EQ:
345 if ((stat_buf->st_ctime >= (time_t) pred_ptr->args.info.l_val)
346 && (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val + 60))
347 return (true);
348 break;
350 return (false);
353 boolean
354 pred_cnewer (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
356 if (stat_buf->st_ctime > pred_ptr->args.time)
357 return (true);
358 return (false);
361 boolean
362 pred_comma (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
364 if (pred_ptr->pred_left != NULL)
365 (*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
366 pred_ptr->pred_left);
367 /* Check whether we need a stat here. */
368 if (pred_ptr->need_stat)
370 if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
372 error (0, errno, "%s", pathname);
373 exit_status = 1;
374 return (false);
376 have_stat = true;
378 return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
379 pred_ptr->pred_right));
382 boolean
383 pred_ctime (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
385 switch (pred_ptr->args.info.kind)
387 case COMP_GT:
388 if (stat_buf->st_ctime > (time_t) pred_ptr->args.info.l_val)
389 return (true);
390 break;
391 case COMP_LT:
392 if (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val)
393 return (true);
394 break;
395 case COMP_EQ:
396 if ((stat_buf->st_ctime >= (time_t) pred_ptr->args.info.l_val)
397 && (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val
398 + DAYSECS))
399 return (true);
400 break;
402 return (false);
405 boolean
406 pred_empty (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
408 if (S_ISDIR (stat_buf->st_mode))
410 DIR *d;
411 struct dirent *dp;
412 boolean empty = true;
414 errno = 0;
415 d = opendir (rel_pathname);
416 if (d == NULL)
418 error (0, errno, "%s", pathname);
419 exit_status = 1;
420 return (false);
422 for (dp = readdir (d); dp; dp = readdir (d))
424 if (dp->d_name[0] != '.'
425 || (dp->d_name[1] != '\0'
426 && (dp->d_name[1] != '.' || dp->d_name[2] != '\0')))
428 empty = false;
429 break;
432 if (CLOSEDIR (d))
434 error (0, errno, "%s", pathname);
435 exit_status = 1;
436 return (false);
438 return (empty);
440 else if (S_ISREG (stat_buf->st_mode))
441 return (stat_buf->st_size == 0);
442 else
443 return (false);
446 boolean
447 pred_exec (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
449 int i;
450 int path_pos;
451 struct exec_val *execp; /* Pointer for efficiency. */
453 execp = &pred_ptr->args.exec_vec;
455 /* Replace "{}" with the real path in each affected arg. */
456 for (path_pos = 0; execp->paths[path_pos].offset >= 0; path_pos++)
458 register char *from, *to;
460 i = execp->paths[path_pos].offset;
461 execp->vec[i] =
462 xmalloc (strlen (execp->paths[path_pos].origarg) + 1
463 + (strlen (pathname) - 2) * execp->paths[path_pos].count);
464 for (from = execp->paths[path_pos].origarg, to = execp->vec[i]; *from; )
465 if (from[0] == '{' && from[1] == '}')
467 to = stpcpy (to, pathname);
468 from += 2;
470 else
471 *to++ = *from++;
472 *to = *from; /* Copy null. */
475 i = launch (pred_ptr);
477 /* Free the temporary args. */
478 for (path_pos = 0; execp->paths[path_pos].offset >= 0; path_pos++)
479 free (execp->vec[execp->paths[path_pos].offset]);
481 return (i);
484 boolean
485 pred_false (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
487 return (false);
490 boolean
491 pred_fls (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
493 list_file (pathname, rel_pathname, stat_buf, start_time,
494 output_block_size, pred_ptr->args.stream);
495 return (true);
498 boolean
499 pred_fprint (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
501 fputs (pathname, pred_ptr->args.stream);
502 putc ('\n', pred_ptr->args.stream);
503 return (true);
506 boolean
507 pred_fprint0 (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
509 fputs (pathname, pred_ptr->args.stream);
510 putc (0, pred_ptr->args.stream);
511 return (true);
514 boolean
515 pred_fprintf (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
517 FILE *fp = pred_ptr->args.printf_vec.stream;
518 struct segment *segment;
519 char *cp;
520 char hbuf[LONGEST_HUMAN_READABLE + 1];
522 for (segment = pred_ptr->args.printf_vec.segment; segment;
523 segment = segment->next)
525 if (segment->kind & 0xff00) /* Component of date. */
527 time_t t;
529 switch (segment->kind & 0xff)
531 case 'A':
532 t = stat_buf->st_atime;
533 break;
534 case 'C':
535 t = stat_buf->st_ctime;
536 break;
537 case 'T':
538 t = stat_buf->st_mtime;
539 break;
540 default:
541 abort ();
543 fprintf (fp, segment->text,
544 format_date (t, (segment->kind >> 8) & 0xff));
545 continue;
548 switch (segment->kind)
550 case KIND_PLAIN: /* Plain text string (no % conversion). */
551 fwrite (segment->text, 1, segment->text_len, fp);
552 break;
553 case KIND_STOP: /* Terminate argument and flush output. */
554 fwrite (segment->text, 1, segment->text_len, fp);
555 fflush (fp);
556 return (true);
557 case 'a': /* atime in `ctime' format. */
558 fprintf (fp, segment->text, ctime_format (stat_buf->st_atime));
559 break;
560 case 'b': /* size in 512-byte blocks */
561 fprintf (fp, segment->text,
562 human_readable ((uintmax_t) ST_NBLOCKS (*stat_buf),
563 hbuf, human_ceiling,
564 ST_NBLOCKSIZE, 512));
565 break;
566 case 'c': /* ctime in `ctime' format */
567 fprintf (fp, segment->text, ctime_format (stat_buf->st_ctime));
568 break;
569 case 'd': /* depth in search tree */
570 fprintf (fp, segment->text, curdepth);
571 break;
572 case 'f': /* basename of path */
573 fprintf (fp, segment->text, base_name (pathname));
574 break;
575 case 'F': /* filesystem type */
576 fprintf (fp, segment->text,
577 filesystem_type (pathname, rel_pathname, stat_buf));
578 break;
579 case 'g': /* group name */
581 struct group *g;
583 g = getgrgid (stat_buf->st_gid);
584 if (g)
586 segment->text[segment->text_len] = 's';
587 fprintf (fp, segment->text, g->gr_name);
588 break;
590 /* else fallthru */
592 case 'G': /* GID number */
593 fprintf (fp, segment->text,
594 human_readable ((uintmax_t) stat_buf->st_gid, hbuf,
595 human_ceiling, 1, 1));
596 break;
597 case 'h': /* leading directories part of path */
599 char cc;
601 cp = strrchr (pathname, '/');
602 if (cp == NULL) /* No leading directories. */
603 break;
604 cc = *cp;
605 *cp = '\0';
606 fprintf (fp, segment->text, pathname);
607 *cp = cc;
608 break;
610 case 'H': /* ARGV element file was found under */
612 char cc = pathname[path_length];
614 pathname[path_length] = '\0';
615 fprintf (fp, segment->text, pathname);
616 pathname[path_length] = cc;
617 break;
619 case 'i': /* inode number */
620 fprintf (fp, segment->text,
621 human_readable ((uintmax_t) stat_buf->st_ino, hbuf,
622 human_ceiling,
623 1, 1));
624 break;
625 case 'k': /* size in 1K blocks */
626 fprintf (fp, segment->text,
627 human_readable ((uintmax_t) ST_NBLOCKS (*stat_buf),
628 hbuf,
629 ST_NBLOCKSIZE, 1024, human_ceiling));
630 break;
631 case 'l': /* object of symlink */
632 #ifdef S_ISLNK
634 char *linkname = 0;
636 if (S_ISLNK (stat_buf->st_mode))
638 linkname = get_link_name (pathname, rel_pathname);
639 if (linkname == 0)
640 exit_status = 1;
642 if (linkname)
644 fprintf (fp, segment->text, linkname);
645 free (linkname);
647 else
648 fprintf (fp, segment->text, "");
650 #endif /* S_ISLNK */
651 break;
652 case 'm': /* mode as octal number (perms only) */
654 /* Output the mode portably using the traditional numbers,
655 even if the host unwisely uses some other numbering
656 scheme. But help the compiler in the common case where
657 the host uses the traditional numbering scheme. */
658 mode_t m = stat_buf->st_mode;
659 boolean traditional_numbering_scheme =
660 (S_ISUID == 04000 && S_ISGID == 02000 && S_ISVTX == 01000
661 && S_IRUSR == 00400 && S_IWUSR == 00200 && S_IXUSR == 00100
662 && S_IRGRP == 00040 && S_IWGRP == 00020 && S_IXGRP == 00010
663 && S_IROTH == 00004 && S_IWOTH == 00002 && S_IXOTH == 00001);
664 fprintf (fp, segment->text,
665 (traditional_numbering_scheme
666 ? m & MODE_ALL
667 : ((m & S_ISUID ? 04000 : 0)
668 | (m & S_ISGID ? 02000 : 0)
669 | (m & S_ISVTX ? 01000 : 0)
670 | (m & S_IRUSR ? 00400 : 0)
671 | (m & S_IWUSR ? 00200 : 0)
672 | (m & S_IXUSR ? 00100 : 0)
673 | (m & S_IRGRP ? 00040 : 0)
674 | (m & S_IWGRP ? 00020 : 0)
675 | (m & S_IXGRP ? 00010 : 0)
676 | (m & S_IROTH ? 00004 : 0)
677 | (m & S_IWOTH ? 00002 : 0)
678 | (m & S_IXOTH ? 00001 : 0))));
680 break;
681 case 'n': /* number of links */
682 fprintf (fp, segment->text,
683 human_readable ((uintmax_t) stat_buf->st_nlink,
684 hbuf,
685 human_ceiling,
686 1, 1));
687 break;
688 case 'p': /* pathname */
689 fprintf (fp, segment->text, pathname);
690 break;
691 case 'P': /* pathname with ARGV element stripped */
692 if (curdepth)
694 cp = pathname + path_length;
695 if (*cp == '/')
696 /* Move past the slash between the ARGV element
697 and the rest of the pathname. But if the ARGV element
698 ends in a slash, we didn't add another, so we've
699 already skipped past it. */
700 cp++;
702 else
703 cp = "";
704 fprintf (fp, segment->text, cp);
705 break;
706 case 's': /* size in bytes */
707 fprintf (fp, segment->text,
708 human_readable ((uintmax_t) stat_buf->st_size,
709 hbuf, human_ceiling, 1, 1));
710 break;
711 case 't': /* mtime in `ctime' format */
712 fprintf (fp, segment->text, ctime_format (stat_buf->st_mtime));
713 break;
714 case 'u': /* user name */
716 struct passwd *p;
718 p = getpwuid (stat_buf->st_uid);
719 if (p)
721 segment->text[segment->text_len] = 's';
722 fprintf (fp, segment->text, p->pw_name);
723 break;
725 /* else fallthru */
727 case 'U': /* UID number */
728 fprintf (fp, segment->text,
729 human_readable ((uintmax_t) stat_buf->st_uid, hbuf,
730 human_ceiling, 1, 1));
731 break;
734 return (true);
737 boolean
738 pred_fstype (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
740 if (strcmp (filesystem_type (pathname, rel_pathname, stat_buf),
741 pred_ptr->args.str) == 0)
742 return (true);
743 return (false);
746 boolean
747 pred_gid (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
749 switch (pred_ptr->args.info.kind)
751 case COMP_GT:
752 if (stat_buf->st_gid > pred_ptr->args.info.l_val)
753 return (true);
754 break;
755 case COMP_LT:
756 if (stat_buf->st_gid < pred_ptr->args.info.l_val)
757 return (true);
758 break;
759 case COMP_EQ:
760 if (stat_buf->st_gid == pred_ptr->args.info.l_val)
761 return (true);
762 break;
764 return (false);
767 boolean
768 pred_group (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
770 if (pred_ptr->args.gid == stat_buf->st_gid)
771 return (true);
772 else
773 return (false);
776 boolean
777 pred_ilname (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
779 return insert_lname (pathname, stat_buf, pred_ptr, true);
782 boolean
783 pred_iname (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
785 const char *base;
787 base = base_name (pathname);
788 if (fnmatch (pred_ptr->args.str, base, FNM_PERIOD | FNM_CASEFOLD) == 0)
789 return (true);
790 return (false);
793 boolean
794 pred_inum (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
796 switch (pred_ptr->args.info.kind)
798 case COMP_GT:
799 if (stat_buf->st_ino > pred_ptr->args.info.l_val)
800 return (true);
801 break;
802 case COMP_LT:
803 if (stat_buf->st_ino < pred_ptr->args.info.l_val)
804 return (true);
805 break;
806 case COMP_EQ:
807 if (stat_buf->st_ino == pred_ptr->args.info.l_val)
808 return (true);
809 break;
811 return (false);
814 boolean
815 pred_ipath (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
817 if (fnmatch (pred_ptr->args.str, pathname, FNM_CASEFOLD) == 0)
818 return (true);
819 return (false);
822 boolean
823 pred_links (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
825 switch (pred_ptr->args.info.kind)
827 case COMP_GT:
828 if (stat_buf->st_nlink > pred_ptr->args.info.l_val)
829 return (true);
830 break;
831 case COMP_LT:
832 if (stat_buf->st_nlink < pred_ptr->args.info.l_val)
833 return (true);
834 break;
835 case COMP_EQ:
836 if (stat_buf->st_nlink == pred_ptr->args.info.l_val)
837 return (true);
838 break;
840 return (false);
843 boolean
844 pred_lname (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
846 return insert_lname (pathname, stat_buf, pred_ptr, false);
849 static boolean
850 insert_lname (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr, boolean ignore_case)
852 boolean ret = false;
853 #ifdef S_ISLNK
854 if (S_ISLNK (stat_buf->st_mode))
856 char *linkname = get_link_name (pathname, rel_pathname);
857 if (linkname)
859 if (fnmatch (pred_ptr->args.str, linkname,
860 ignore_case ? FNM_CASEFOLD : 0) == 0)
861 ret = true;
862 free (linkname);
865 #endif /* S_ISLNK */
866 return (ret);
869 boolean
870 pred_ls (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
872 list_file (pathname, rel_pathname, stat_buf, start_time,
873 output_block_size, stdout);
874 return (true);
877 boolean
878 pred_mmin (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
880 switch (pred_ptr->args.info.kind)
882 case COMP_GT:
883 if (stat_buf->st_mtime > (time_t) pred_ptr->args.info.l_val)
884 return (true);
885 break;
886 case COMP_LT:
887 if (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val)
888 return (true);
889 break;
890 case COMP_EQ:
891 if ((stat_buf->st_mtime >= (time_t) pred_ptr->args.info.l_val)
892 && (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val + 60))
893 return (true);
894 break;
896 return (false);
899 boolean
900 pred_mtime (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
902 switch (pred_ptr->args.info.kind)
904 case COMP_GT:
905 if (stat_buf->st_mtime > (time_t) pred_ptr->args.info.l_val)
906 return (true);
907 break;
908 case COMP_LT:
909 if (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val)
910 return (true);
911 break;
912 case COMP_EQ:
913 if ((stat_buf->st_mtime >= (time_t) pred_ptr->args.info.l_val)
914 && (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val
915 + DAYSECS))
916 return (true);
917 break;
919 return (false);
922 boolean
923 pred_name (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
925 const char *base;
927 base = base_name (pathname);
928 if (fnmatch (pred_ptr->args.str, base, FNM_PERIOD) == 0)
929 return (true);
930 return (false);
933 boolean
934 pred_negate (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
936 /* Check whether we need a stat here. */
937 if (pred_ptr->need_stat)
939 if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
941 error (0, errno, "%s", pathname);
942 exit_status = 1;
943 return (false);
945 have_stat = true;
947 return (!(*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
948 pred_ptr->pred_right));
951 boolean
952 pred_newer (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
954 if (stat_buf->st_mtime > pred_ptr->args.time)
955 return (true);
956 return (false);
959 boolean
960 pred_nogroup (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
962 #ifdef CACHE_IDS
963 extern char *gid_unused;
965 return gid_unused[(unsigned) stat_buf->st_gid];
966 #else
967 return getgrgid (stat_buf->st_gid) == NULL;
968 #endif
971 boolean
972 pred_nouser (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
974 #ifdef CACHE_IDS
975 extern char *uid_unused;
977 return uid_unused[(unsigned) stat_buf->st_uid];
978 #else
979 return getpwuid (stat_buf->st_uid) == NULL;
980 #endif
983 boolean
984 pred_ok (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
986 fflush (stdout);
987 /* The draft open standard requires that, in the POSIX locale,
988 the last non-blank character of this prompt be '?'.
989 The exact format is not specified.
990 This standard does not have requirements for locales other than POSIX
992 fprintf (stderr, _("< %s ... %s > ? "),
993 pred_ptr->args.exec_vec.vec[0], pathname);
994 fflush (stderr);
995 if (yesno ())
996 return pred_exec (pathname, stat_buf, pred_ptr);
997 else
998 return (false);
1001 boolean
1002 pred_open (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1004 return (true);
1007 boolean
1008 pred_or (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1010 if (pred_ptr->pred_left == NULL
1011 || !(*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
1012 pred_ptr->pred_left))
1014 /* Check whether we need a stat here. */
1015 if (pred_ptr->need_stat)
1017 if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
1019 error (0, errno, "%s", pathname);
1020 exit_status = 1;
1021 return (false);
1023 have_stat = true;
1025 return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
1026 pred_ptr->pred_right));
1028 else
1029 return (true);
1032 boolean
1033 pred_path (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1035 if (fnmatch (pred_ptr->args.str, pathname, 0) == 0)
1036 return (true);
1037 return (false);
1040 boolean
1041 pred_perm (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1043 switch (pred_ptr->args.perm.kind)
1045 case PERM_AT_LEAST:
1046 return (stat_buf->st_mode & pred_ptr->args.perm.val) == pred_ptr->args.perm.val;
1047 break;
1049 case PERM_ANY:
1050 return (stat_buf->st_mode & pred_ptr->args.perm.val) != 0;
1051 break;
1053 case PERM_EXACT:
1054 return (stat_buf->st_mode & MODE_ALL) == pred_ptr->args.perm.val;
1055 break;
1057 default:
1058 abort ();
1059 break;
1063 boolean
1064 pred_print (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1066 puts (pathname);
1067 return (true);
1070 boolean
1071 pred_print0 (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1073 fputs (pathname, stdout);
1074 putc (0, stdout);
1075 return (true);
1078 boolean
1079 pred_prune (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1081 stop_at_current_level = true;
1082 return (do_dir_first); /* This is what SunOS find seems to do. */
1085 boolean
1086 pred_regex (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1088 int len = strlen (pathname);
1089 if (re_match (pred_ptr->args.regex, pathname, len, 0,
1090 (struct re_registers *) NULL) == len)
1091 return (true);
1092 return (false);
1095 boolean
1096 pred_size (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1098 uintmax_t f_val;
1100 f_val = ((stat_buf->st_size / pred_ptr->args.size.blocksize)
1101 + (stat_buf->st_size % pred_ptr->args.size.blocksize != 0));
1102 switch (pred_ptr->args.size.kind)
1104 case COMP_GT:
1105 if (f_val > pred_ptr->args.size.size)
1106 return (true);
1107 break;
1108 case COMP_LT:
1109 if (f_val < pred_ptr->args.size.size)
1110 return (true);
1111 break;
1112 case COMP_EQ:
1113 if (f_val == pred_ptr->args.size.size)
1114 return (true);
1115 break;
1117 return (false);
1120 boolean
1121 pred_true (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1123 return (true);
1126 boolean
1127 pred_type (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1129 mode_t mode = stat_buf->st_mode;
1130 mode_t type = pred_ptr->args.type;
1132 #ifndef S_IFMT
1133 /* POSIX system; check `mode' the slow way. */
1134 if ((S_ISBLK (mode) && type == S_IFBLK)
1135 || (S_ISCHR (mode) && type == S_IFCHR)
1136 || (S_ISDIR (mode) && type == S_IFDIR)
1137 || (S_ISREG (mode) && type == S_IFREG)
1138 #ifdef S_IFLNK
1139 || (S_ISLNK (mode) && type == S_IFLNK)
1140 #endif
1141 #ifdef S_IFIFO
1142 || (S_ISFIFO (mode) && type == S_IFIFO)
1143 #endif
1144 #ifdef S_IFSOCK
1145 || (S_ISSOCK (mode) && type == S_IFSOCK)
1146 #endif
1147 #ifdef S_IFDOOR
1148 || (S_ISDOOR (mode) && type == S_IFDOOR)
1149 #endif
1151 #else /* S_IFMT */
1152 /* Unix system; check `mode' the fast way. */
1153 if ((mode & S_IFMT) == type)
1154 #endif /* S_IFMT */
1155 return (true);
1156 else
1157 return (false);
1160 boolean
1161 pred_uid (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1163 switch (pred_ptr->args.info.kind)
1165 case COMP_GT:
1166 if (stat_buf->st_uid > pred_ptr->args.info.l_val)
1167 return (true);
1168 break;
1169 case COMP_LT:
1170 if (stat_buf->st_uid < pred_ptr->args.info.l_val)
1171 return (true);
1172 break;
1173 case COMP_EQ:
1174 if (stat_buf->st_uid == pred_ptr->args.info.l_val)
1175 return (true);
1176 break;
1178 return (false);
1181 boolean
1182 pred_used (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1184 time_t delta;
1186 delta = stat_buf->st_atime - stat_buf->st_ctime; /* Use difftime? */
1187 switch (pred_ptr->args.info.kind)
1189 case COMP_GT:
1190 if (delta > (time_t) pred_ptr->args.info.l_val)
1191 return (true);
1192 break;
1193 case COMP_LT:
1194 if (delta < (time_t) pred_ptr->args.info.l_val)
1195 return (true);
1196 break;
1197 case COMP_EQ:
1198 if ((delta >= (time_t) pred_ptr->args.info.l_val)
1199 && (delta < (time_t) pred_ptr->args.info.l_val + DAYSECS))
1200 return (true);
1201 break;
1203 return (false);
1206 boolean
1207 pred_user (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1209 if (pred_ptr->args.uid == stat_buf->st_uid)
1210 return (true);
1211 else
1212 return (false);
1215 boolean
1216 pred_xtype (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1218 struct stat sbuf;
1219 int (*ystat) ();
1221 ystat = xstat == lstat ? stat : lstat;
1222 if ((*ystat) (rel_pathname, &sbuf) != 0)
1224 if (ystat == stat && errno == ENOENT)
1225 /* Mimic behavior of ls -lL. */
1226 return (pred_type (pathname, stat_buf, pred_ptr));
1227 error (0, errno, "%s", pathname);
1228 exit_status = 1;
1229 return (false);
1231 return (pred_type (pathname, &sbuf, pred_ptr));
1234 /* 1) fork to get a child; parent remembers the child pid
1235 2) child execs the command requested
1236 3) parent waits for child; checks for proper pid of child
1238 Possible returns:
1240 ret errno status(h) status(l)
1242 pid x signal# 0177 stopped
1243 pid x exit arg 0 term by _exit
1244 pid x 0 signal # term by signal
1245 -1 EINTR parent got signal
1246 -1 other some other kind of error
1248 Return true only if the pid matches, status(l) is
1249 zero, and the exit arg (status high) is 0.
1250 Otherwise return false, possibly printing an error message. */
1252 static boolean
1253 launch (struct predicate *pred_ptr)
1255 int status;
1256 pid_t child_pid;
1257 struct exec_val *execp; /* Pointer for efficiency. */
1258 static int first_time = 1;
1260 execp = &pred_ptr->args.exec_vec;
1262 /* Make sure output of command doesn't get mixed with find output. */
1263 fflush (stdout);
1264 fflush (stderr);
1266 /* Make sure to listen for the kids. */
1267 if (first_time)
1269 first_time = 0;
1270 signal (SIGCHLD, SIG_DFL);
1273 child_pid = fork ();
1274 if (child_pid == -1)
1275 error (1, errno, _("cannot fork"));
1276 if (child_pid == 0)
1278 /* We be the child. */
1279 if (starting_desc < 0
1280 ? chdir (starting_dir) != 0
1281 : fchdir (starting_desc) != 0)
1283 error (0, errno, "%s", starting_dir);
1284 _exit (1);
1286 execvp (execp->vec[0], execp->vec);
1287 error (0, errno, "%s", execp->vec[0]);
1288 _exit (1);
1292 while (waitpid (child_pid, &status, 0) == (pid_t) -1)
1293 if (errno != EINTR)
1295 error (0, errno, _("error waiting for %s"), execp->vec[0]);
1296 exit_status = 1;
1297 return false;
1299 if (WIFSIGNALED (status))
1301 error (0, 0, _("%s terminated by signal %d"),
1302 execp->vec[0], WTERMSIG (status));
1303 exit_status = 1;
1304 return (false);
1306 return (!WEXITSTATUS (status));
1309 /* Return a static string formatting the time WHEN according to the
1310 strftime format character KIND. */
1312 static char *
1313 format_date (time_t when, int kind)
1315 static char buf[MAX (LONGEST_HUMAN_READABLE + 2, 64)];
1316 struct tm *tm;
1317 char fmt[3];
1319 fmt[0] = '%';
1320 fmt[1] = kind;
1321 fmt[2] = '\0';
1323 if (kind != '@'
1324 && (tm = localtime (&when))
1325 && strftime (buf, sizeof buf, fmt, tm))
1326 return buf;
1327 else
1329 uintmax_t w = when;
1330 char *p = human_readable (when < 0 ? -w : w, buf + 1,
1331 human_ceiling, 1, 1);
1332 if (when < 0)
1333 *--p = '-';
1334 return p;
1338 static char *
1339 ctime_format (when)
1340 time_t when;
1342 char *r = ctime (&when);
1343 if (!r)
1345 /* The time cannot be represented as a struct tm.
1346 Output it as an integer. */
1347 return format_date (when, '@');
1349 else
1351 /* Remove the trailing newline from the ctime output,
1352 being careful not to assume that the output is fixed-width. */
1353 *strchr (r, '\n') = '\0';
1354 return r;
1358 #ifdef DEBUG
1359 /* Return a pointer to the string representation of
1360 the predicate function PRED_FUNC. */
1362 char *
1363 find_pred_name (pred_func)
1364 PFB pred_func;
1366 int i;
1368 for (i = 0; pred_table[i].pred_func != 0; i++)
1369 if (pred_table[i].pred_func == pred_func)
1370 break;
1371 return (pred_table[i].pred_name);
1374 static char *
1375 type_name (type)
1376 short type;
1378 int i;
1380 for (i = 0; type_table[i].type != (short) -1; i++)
1381 if (type_table[i].type == type)
1382 break;
1383 return (type_table[i].type_name);
1386 static char *
1387 prec_name (prec)
1388 short prec;
1390 int i;
1392 for (i = 0; prec_table[i].prec != (short) -1; i++)
1393 if (prec_table[i].prec == prec)
1394 break;
1395 return (prec_table[i].prec_name);
1398 /* Walk the expression tree NODE to stdout.
1399 INDENT is the number of levels to indent the left margin. */
1401 void
1402 print_tree (node, indent)
1403 struct predicate *node;
1404 int indent;
1406 int i;
1408 if (node == NULL)
1409 return;
1410 for (i = 0; i < indent; i++)
1411 printf (" ");
1412 printf ("pred = %s type = %s prec = %s addr = %x\n",
1413 find_pred_name (node->pred_func),
1414 type_name (node->p_type), prec_name (node->p_prec), node);
1415 for (i = 0; i < indent; i++)
1416 printf (" ");
1417 printf (_("left:\n"));
1418 print_tree (node->pred_left, indent + 1);
1419 for (i = 0; i < indent; i++)
1420 printf (" ");
1421 printf (_("right:\n"));
1422 print_tree (node->pred_right, indent + 1);
1425 /* Copy STR into BUF and trim blanks from the end of BUF.
1426 Return BUF. */
1428 static char *
1429 blank_rtrim (str, buf)
1430 char *str;
1431 char *buf;
1433 int i;
1435 if (str == NULL)
1436 return (NULL);
1437 strcpy (buf, str);
1438 i = strlen (buf) - 1;
1439 while ((i >= 0) && ((buf[i] == ' ') || buf[i] == '\t'))
1440 i--;
1441 buf[++i] = '\0';
1442 return (buf);
1445 /* Print out the predicate list starting at NODE. */
1447 void
1448 print_list (node)
1449 struct predicate *node;
1451 struct predicate *cur;
1452 char name[256];
1454 cur = node;
1455 while (cur != NULL)
1457 printf ("%s ", blank_rtrim (find_pred_name (cur->pred_func), name));
1458 cur = cur->pred_next;
1460 printf ("\n");
1462 #endif /* DEBUG */