Guard against multiple inclusion
[findutils.git] / find / pred.c
blob81c51e5293b4df00e6d843b007ee577e055557be
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17 USA.
20 #include "defs.h"
22 #include <fnmatch.h>
23 #include <signal.h>
24 #include <pwd.h>
25 #include <grp.h>
26 #include "../gnulib/lib/dirname.h"
27 #include "../gnulib/lib/human.h"
28 #include "modetype.h"
29 #include "filemode.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 /* See locate.c for explanation as to why not use (String) */
42 # define N_(String) String
43 #endif
45 #if !defined(SIGCHLD) && defined(SIGCLD)
46 #define SIGCHLD SIGCLD
47 #endif
49 #if HAVE_DIRENT_H
50 # include <dirent.h>
51 # define NAMLEN(dirent) strlen((dirent)->d_name)
52 #else
53 # define dirent direct
54 # define NAMLEN(dirent) (dirent)->d_namlen
55 # if HAVE_SYS_NDIR_H
56 # include <sys/ndir.h>
57 # endif
58 # if HAVE_SYS_DIR_H
59 # include <sys/dir.h>
60 # endif
61 # if HAVE_NDIR_H
62 # include <ndir.h>
63 # endif
64 #endif
66 #ifdef CLOSEDIR_VOID
67 /* Fake a return value. */
68 #define CLOSEDIR(d) (closedir (d), 0)
69 #else
70 #define CLOSEDIR(d) closedir (d)
71 #endif
73 extern int yesno ();
76 /* Get or fake the disk device blocksize.
77 Usually defined by sys/param.h (if at all). */
78 #ifndef DEV_BSIZE
79 # ifdef BSIZE
80 # define DEV_BSIZE BSIZE
81 # else /* !BSIZE */
82 # define DEV_BSIZE 4096
83 # endif /* !BSIZE */
84 #endif /* !DEV_BSIZE */
86 /* Extract or fake data from a `struct stat'.
87 ST_BLKSIZE: Preferred I/O blocksize for the file, in bytes.
88 ST_NBLOCKS: Number of blocks in the file, including indirect blocks.
89 ST_NBLOCKSIZE: Size of blocks used when calculating ST_NBLOCKS. */
90 #ifndef HAVE_STRUCT_STAT_ST_BLOCKS
91 # define ST_BLKSIZE(statbuf) DEV_BSIZE
92 # if defined(_POSIX_SOURCE) || !defined(BSIZE) /* fileblocks.c uses BSIZE. */
93 # define ST_NBLOCKS(statbuf) \
94 (S_ISREG ((statbuf).st_mode) \
95 || S_ISDIR ((statbuf).st_mode) \
96 ? (statbuf).st_size / ST_NBLOCKSIZE + ((statbuf).st_size % ST_NBLOCKSIZE != 0) : 0)
97 # else /* !_POSIX_SOURCE && BSIZE */
98 # define ST_NBLOCKS(statbuf) \
99 (S_ISREG ((statbuf).st_mode) \
100 || S_ISDIR ((statbuf).st_mode) \
101 ? st_blocks ((statbuf).st_size) : 0)
102 # endif /* !_POSIX_SOURCE && BSIZE */
103 #else /* HAVE_STRUCT_STAT_ST_BLOCKS */
104 /* Some systems, like Sequents, return st_blksize of 0 on pipes. */
105 # define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \
106 ? (statbuf).st_blksize : DEV_BSIZE)
107 # if defined(hpux) || defined(__hpux__) || defined(__hpux)
108 /* HP-UX counts st_blocks in 1024-byte units.
109 This loses when mixing HP-UX and BSD filesystems with NFS. */
110 # define ST_NBLOCKSIZE 1024
111 # else /* !hpux */
112 # if defined(_AIX) && defined(_I386)
113 /* AIX PS/2 counts st_blocks in 4K units. */
114 # define ST_NBLOCKSIZE (4 * 1024)
115 # else /* not AIX PS/2 */
116 # if defined(_CRAY)
117 # define ST_NBLOCKS(statbuf) \
118 (S_ISREG ((statbuf).st_mode) \
119 || S_ISDIR ((statbuf).st_mode) \
120 ? (statbuf).st_blocks * ST_BLKSIZE(statbuf)/ST_NBLOCKSIZE : 0)
121 # endif /* _CRAY */
122 # endif /* not AIX PS/2 */
123 # endif /* !hpux */
124 #endif /* HAVE_STRUCT_STAT_ST_BLOCKS */
126 #ifndef ST_NBLOCKS
127 # define ST_NBLOCKS(statbuf) \
128 (S_ISREG ((statbuf).st_mode) \
129 || S_ISDIR ((statbuf).st_mode) \
130 ? (statbuf).st_blocks : 0)
131 #endif
133 #ifndef ST_NBLOCKSIZE
134 # define ST_NBLOCKSIZE 512
135 #endif
137 #undef MAX
138 #define MAX(a, b) ((a) > (b) ? (a) : (b))
140 static boolean insert_lname PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr, boolean ignore_case));
141 static boolean launch PARAMS((struct predicate *pred_ptr));
142 static char *format_date PARAMS((time_t when, int kind));
143 static char *ctime_format PARAMS((time_t when));
145 #ifdef DEBUG
146 struct pred_assoc
148 PFB pred_func;
149 char *pred_name;
152 struct pred_assoc pred_table[] =
154 {pred_amin, "amin "},
155 {pred_and, "and "},
156 {pred_anewer, "anewer "},
157 {pred_atime, "atime "},
158 {pred_close, ") "},
159 {pred_amin, "cmin "},
160 {pred_cnewer, "cnewer "},
161 {pred_comma, ", "},
162 {pred_ctime, "ctime "},
163 {pred_delete, "delete "},
164 {pred_empty, "empty "},
165 {pred_exec, "exec "},
166 {pred_false, "false "},
167 {pred_fprint, "fprint "},
168 {pred_fprint0, "fprint0 "},
169 {pred_fprintf, "fprintf "},
170 {pred_fstype, "fstype "},
171 {pred_gid, "gid "},
172 {pred_group, "group "},
173 {pred_ilname, "ilname "},
174 {pred_iname, "iname "},
175 {pred_inum, "inum "},
176 {pred_ipath, "ipath "},
177 {pred_links, "links "},
178 {pred_lname, "lname "},
179 {pred_ls, "ls "},
180 {pred_amin, "mmin "},
181 {pred_mtime, "mtime "},
182 {pred_name, "name "},
183 {pred_negate, "not "},
184 {pred_newer, "newer "},
185 {pred_nogroup, "nogroup "},
186 {pred_nouser, "nouser "},
187 {pred_ok, "ok "},
188 {pred_open, "( "},
189 {pred_or, "or "},
190 {pred_path, "path "},
191 {pred_perm, "perm "},
192 {pred_print, "print "},
193 {pred_print0, "print0 "},
194 {pred_prune, "prune "},
195 {pred_regex, "regex "},
196 {pred_size, "size "},
197 {pred_true, "true "},
198 {pred_type, "type "},
199 {pred_uid, "uid "},
200 {pred_used, "used "},
201 {pred_user, "user "},
202 {pred_xtype, "xtype "},
203 {0, "none "}
206 struct op_assoc
208 short type;
209 char *type_name;
212 struct op_assoc type_table[] =
214 {NO_TYPE, "no "},
215 {PRIMARY_TYPE, "primary "},
216 {UNI_OP, "uni_op "},
217 {BI_OP, "bi_op "},
218 {OPEN_PAREN, "open_paren "},
219 {CLOSE_PAREN, "close_paren "},
220 {-1, "unknown "}
223 struct prec_assoc
225 short prec;
226 char *prec_name;
229 struct prec_assoc prec_table[] =
231 {NO_PREC, "no "},
232 {COMMA_PREC, "comma "},
233 {OR_PREC, "or "},
234 {AND_PREC, "and "},
235 {NEGATE_PREC, "negate "},
236 {MAX_PREC, "max "},
237 {-1, "unknown "}
239 #endif /* DEBUG */
241 /* Predicate processing routines.
243 PATHNAME is the full pathname of the file being checked.
244 *STAT_BUF contains information about PATHNAME.
245 *PRED_PTR contains information for applying the predicate.
247 Return true if the file passes this predicate, false if not. */
250 /* pred_timewindow
252 * Returns true if THE_TIME is
253 * COMP_GT: after the specified time
254 * COMP_LT: before the specified time
255 * COMP_EQ: less than WINDOW seconds after the specified time.
257 static boolean
258 pred_timewindow(time_t the_time, struct predicate const *pred_ptr, int window)
260 switch (pred_ptr->args.info.kind)
262 case COMP_GT:
263 if (the_time > (time_t) pred_ptr->args.info.l_val)
264 return true;
265 break;
266 case COMP_LT:
267 if (the_time < (time_t) pred_ptr->args.info.l_val)
268 return true;
269 break;
270 case COMP_EQ:
271 if ((the_time >= (time_t) pred_ptr->args.info.l_val)
272 && (the_time < (time_t) pred_ptr->args.info.l_val + window))
273 return true;
274 break;
276 return false;
280 boolean
281 pred_amin (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
283 (void) &pathname;
284 return pred_timewindow(stat_buf->st_atime, pred_ptr, 60);
287 boolean
288 pred_and (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
290 if (pred_ptr->pred_left == NULL
291 || (*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
292 pred_ptr->pred_left))
294 /* Check whether we need a stat here. */
295 if (pred_ptr->need_stat)
297 if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
299 error (0, errno, "%s", pathname);
300 exit_status = 1;
301 return (false);
303 have_stat = true;
305 return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
306 pred_ptr->pred_right));
308 else
309 return (false);
312 boolean
313 pred_anewer (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
315 (void) &pathname;
317 if (stat_buf->st_atime > pred_ptr->args.time)
318 return (true);
319 return (false);
322 boolean
323 pred_atime (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
325 (void) &pathname;
326 return pred_timewindow(stat_buf->st_atime, pred_ptr, DAYSECS);
329 boolean
330 pred_close (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
332 (void) &pathname;
333 (void) &stat_buf;
334 (void) &pred_ptr;
336 return true;
339 boolean
340 pred_cmin (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
342 (void) pathname;
343 return pred_timewindow(stat_buf->st_ctime, pred_ptr, 60);
346 boolean
347 pred_cnewer (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
349 (void) pathname;
351 if (stat_buf->st_ctime > pred_ptr->args.time)
352 return true;
353 else
354 return false;
357 boolean
358 pred_comma (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
360 if (pred_ptr->pred_left != NULL)
361 (*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
362 pred_ptr->pred_left);
363 /* Check whether we need a stat here. */
364 if (pred_ptr->need_stat)
366 if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
368 error (0, errno, "%s", pathname);
369 exit_status = 1;
370 return (false);
372 have_stat = true;
374 return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
375 pred_ptr->pred_right));
378 boolean
379 pred_ctime (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
381 (void) &pathname;
382 return pred_timewindow(stat_buf->st_ctime, pred_ptr, DAYSECS);
385 boolean
386 pred_delete (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
388 (void) pred_ptr;
389 (void) stat_buf;
390 if (strcmp (rel_pathname, "."))
392 if (0 != remove (rel_pathname))
394 error (0, errno, "cannot delete %s", pathname);
395 return false;
397 else
399 return true;
403 /* nothing to do. */
404 return true;
407 boolean
408 pred_empty (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
410 (void) pathname;
411 (void) pred_ptr;
413 if (S_ISDIR (stat_buf->st_mode))
415 DIR *d;
416 struct dirent *dp;
417 boolean empty = true;
419 errno = 0;
420 d = opendir (rel_pathname);
421 if (d == NULL)
423 error (0, errno, "%s", pathname);
424 exit_status = 1;
425 return (false);
427 for (dp = readdir (d); dp; dp = readdir (d))
429 if (dp->d_name[0] != '.'
430 || (dp->d_name[1] != '\0'
431 && (dp->d_name[1] != '.' || dp->d_name[2] != '\0')))
433 empty = false;
434 break;
437 if (CLOSEDIR (d))
439 error (0, errno, "%s", pathname);
440 exit_status = 1;
441 return (false);
443 return (empty);
445 else if (S_ISREG (stat_buf->st_mode))
446 return (stat_buf->st_size == 0);
447 else
448 return (false);
451 boolean
452 pred_exec (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
454 int i;
455 int path_pos;
456 struct exec_val *execp; /* Pointer for efficiency. */
458 (void) pathname;
459 (void) stat_buf;
461 execp = &pred_ptr->args.exec_vec;
463 /* Replace "{}" with the real path in each affected arg. */
464 for (path_pos = 0; execp->paths[path_pos].offset >= 0; path_pos++)
466 register char *from, *to;
468 i = execp->paths[path_pos].offset;
469 execp->vec[i] =
470 xmalloc (strlen (execp->paths[path_pos].origarg) + 1
471 + (strlen (pathname) - 2) * execp->paths[path_pos].count);
472 for (from = execp->paths[path_pos].origarg, to = execp->vec[i]; *from; )
473 if (from[0] == '{' && from[1] == '}')
475 to = stpcpy (to, pathname);
476 from += 2;
478 else
479 *to++ = *from++;
480 *to = *from; /* Copy null. */
483 i = launch (pred_ptr);
485 /* Free the temporary args. */
486 for (path_pos = 0; execp->paths[path_pos].offset >= 0; path_pos++)
487 free (execp->vec[execp->paths[path_pos].offset]);
489 return (i);
492 boolean
493 pred_false (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
495 (void) &pathname;
496 (void) &stat_buf;
497 (void) &pred_ptr;
500 return (false);
503 boolean
504 pred_fls (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
506 list_file (pathname, rel_pathname, stat_buf, start_time,
507 output_block_size, pred_ptr->args.stream);
508 return (true);
511 boolean
512 pred_fprint (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
514 (void) &pathname;
515 (void) &stat_buf;
517 fputs (pathname, pred_ptr->args.stream);
518 putc ('\n', pred_ptr->args.stream);
519 return (true);
522 boolean
523 pred_fprint0 (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
525 (void) &pathname;
526 (void) &stat_buf;
528 fputs (pathname, pred_ptr->args.stream);
529 putc (0, pred_ptr->args.stream);
530 return (true);
533 boolean
534 pred_fprintf (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
536 FILE *fp = pred_ptr->args.printf_vec.stream;
537 struct segment *segment;
538 char *cp;
539 char hbuf[LONGEST_HUMAN_READABLE + 1];
541 for (segment = pred_ptr->args.printf_vec.segment; segment;
542 segment = segment->next)
544 if (segment->kind & 0xff00) /* Component of date. */
546 time_t t;
548 switch (segment->kind & 0xff)
550 case 'A':
551 t = stat_buf->st_atime;
552 break;
553 case 'C':
554 t = stat_buf->st_ctime;
555 break;
556 case 'T':
557 t = stat_buf->st_mtime;
558 break;
559 default:
560 abort ();
562 fprintf (fp, segment->text,
563 format_date (t, (segment->kind >> 8) & 0xff));
564 continue;
567 switch (segment->kind)
569 case KIND_PLAIN: /* Plain text string (no % conversion). */
570 fwrite (segment->text, 1, segment->text_len, fp);
571 break;
572 case KIND_STOP: /* Terminate argument and flush output. */
573 fwrite (segment->text, 1, segment->text_len, fp);
574 fflush (fp);
575 return (true);
576 case 'a': /* atime in `ctime' format. */
577 fprintf (fp, segment->text, ctime_format (stat_buf->st_atime));
578 break;
579 case 'b': /* size in 512-byte blocks */
580 fprintf (fp, segment->text,
581 human_readable ((uintmax_t) ST_NBLOCKS (*stat_buf),
582 hbuf, human_ceiling,
583 ST_NBLOCKSIZE, 512));
584 break;
585 case 'c': /* ctime in `ctime' format */
586 fprintf (fp, segment->text, ctime_format (stat_buf->st_ctime));
587 break;
588 case 'd': /* depth in search tree */
589 fprintf (fp, segment->text, curdepth);
590 break;
591 case 'D': /* Device on which file exists (stat.st_dev) */
592 fprintf (fp, segment->text,
593 human_readable ((uintmax_t) stat_buf->st_dev, hbuf,
594 human_ceiling, 1, 1));
595 break;
596 case 'f': /* basename of path */
597 fprintf (fp, segment->text, base_name (pathname));
598 break;
599 case 'F': /* filesystem type */
600 fprintf (fp, segment->text,
601 filesystem_type (pathname, rel_pathname, stat_buf));
602 break;
603 case 'g': /* group name */
605 struct group *g;
607 g = getgrgid (stat_buf->st_gid);
608 if (g)
610 segment->text[segment->text_len] = 's';
611 fprintf (fp, segment->text, g->gr_name);
612 break;
614 /* else fallthru */
616 case 'G': /* GID number */
617 fprintf (fp, segment->text,
618 human_readable ((uintmax_t) stat_buf->st_gid, hbuf,
619 human_ceiling, 1, 1));
620 break;
621 case 'h': /* leading directories part of path */
623 char cc;
625 cp = strrchr (pathname, '/');
626 if (cp == NULL) /* No leading directories. */
627 break;
628 cc = *cp;
629 *cp = '\0';
630 fprintf (fp, segment->text, pathname);
631 *cp = cc;
632 break;
634 case 'H': /* ARGV element file was found under */
636 char cc = pathname[path_length];
638 pathname[path_length] = '\0';
639 fprintf (fp, segment->text, pathname);
640 pathname[path_length] = cc;
641 break;
643 case 'i': /* inode number */
644 fprintf (fp, segment->text,
645 human_readable ((uintmax_t) stat_buf->st_ino, hbuf,
646 human_ceiling,
647 1, 1));
648 break;
649 case 'k': /* size in 1K blocks */
650 fprintf (fp, segment->text,
651 human_readable ((uintmax_t) ST_NBLOCKS (*stat_buf),
652 hbuf, human_ceiling,
653 ST_NBLOCKSIZE, 1024));
654 break;
655 case 'l': /* object of symlink */
656 #ifdef S_ISLNK
658 char *linkname = 0;
660 if (S_ISLNK (stat_buf->st_mode))
662 linkname = get_link_name (pathname, rel_pathname);
663 if (linkname == 0)
664 exit_status = 1;
666 if (linkname)
668 fprintf (fp, segment->text, linkname);
669 free (linkname);
671 else
672 fprintf (fp, segment->text, "");
674 #endif /* S_ISLNK */
675 break;
677 case 'M': /* mode as 10 chars (eg., "-rwxr-x--x" */
679 char modestring[16] ;
680 mode_string (stat_buf->st_mode, modestring);
681 modestring[10] = '\0';
682 fprintf (fp, segment->text, modestring);
684 break;
686 case 'm': /* mode as octal number (perms only) */
688 /* Output the mode portably using the traditional numbers,
689 even if the host unwisely uses some other numbering
690 scheme. But help the compiler in the common case where
691 the host uses the traditional numbering scheme. */
692 mode_t m = stat_buf->st_mode;
693 boolean traditional_numbering_scheme =
694 (S_ISUID == 04000 && S_ISGID == 02000 && S_ISVTX == 01000
695 && S_IRUSR == 00400 && S_IWUSR == 00200 && S_IXUSR == 00100
696 && S_IRGRP == 00040 && S_IWGRP == 00020 && S_IXGRP == 00010
697 && S_IROTH == 00004 && S_IWOTH == 00002 && S_IXOTH == 00001);
698 fprintf (fp, segment->text,
699 (traditional_numbering_scheme
700 ? m & MODE_ALL
701 : ((m & S_ISUID ? 04000 : 0)
702 | (m & S_ISGID ? 02000 : 0)
703 | (m & S_ISVTX ? 01000 : 0)
704 | (m & S_IRUSR ? 00400 : 0)
705 | (m & S_IWUSR ? 00200 : 0)
706 | (m & S_IXUSR ? 00100 : 0)
707 | (m & S_IRGRP ? 00040 : 0)
708 | (m & S_IWGRP ? 00020 : 0)
709 | (m & S_IXGRP ? 00010 : 0)
710 | (m & S_IROTH ? 00004 : 0)
711 | (m & S_IWOTH ? 00002 : 0)
712 | (m & S_IXOTH ? 00001 : 0))));
714 break;
716 case 'n': /* number of links */
717 fprintf (fp, segment->text,
718 human_readable ((uintmax_t) stat_buf->st_nlink,
719 hbuf,
720 human_ceiling,
721 1, 1));
722 break;
723 case 'p': /* pathname */
724 fprintf (fp, segment->text, pathname);
725 break;
726 case 'P': /* pathname with ARGV element stripped */
727 if (curdepth)
729 cp = pathname + path_length;
730 if (*cp == '/')
731 /* Move past the slash between the ARGV element
732 and the rest of the pathname. But if the ARGV element
733 ends in a slash, we didn't add another, so we've
734 already skipped past it. */
735 cp++;
737 else
738 cp = "";
739 fprintf (fp, segment->text, cp);
740 break;
741 case 's': /* size in bytes */
742 fprintf (fp, segment->text,
743 human_readable ((uintmax_t) stat_buf->st_size,
744 hbuf, human_ceiling, 1, 1));
745 break;
746 case 't': /* mtime in `ctime' format */
747 fprintf (fp, segment->text, ctime_format (stat_buf->st_mtime));
748 break;
749 case 'u': /* user name */
751 struct passwd *p;
753 p = getpwuid (stat_buf->st_uid);
754 if (p)
756 segment->text[segment->text_len] = 's';
757 fprintf (fp, segment->text, p->pw_name);
758 break;
760 /* else fallthru */
763 case 'U': /* UID number */
764 fprintf (fp, segment->text,
765 human_readable ((uintmax_t) stat_buf->st_uid, hbuf,
766 human_ceiling, 1, 1));
767 break;
769 /* type of filesystem entry like `ls -l`: (d,-,l,s,p,b,c,n) n=nonexistent(symlink) */
770 case 'Y': /* in case of symlink */
772 #ifdef S_ISLNK
773 if (S_ISLNK (stat_buf->st_mode))
775 struct stat sbuf;
776 int (*ystat) ();
777 ystat = xstat == lstat ? stat : lstat;
778 if ((*ystat) (rel_pathname, &sbuf) != 0)
780 if ( errno == ENOENT ) {
781 fprintf (fp, segment->text, "N");
782 break;
784 if ( errno == ELOOP ) {
785 fprintf (fp, segment->text, "L");
786 break;
788 error (0, errno, "", pathname);
789 /* exit_status = 1;
790 return (false); */
792 stat_buf->st_mode = sbuf.st_mode;
794 #endif /* S_ISLNK */
796 /* FALLTHROUGH */
797 case 'y':
799 mode_t m = stat_buf->st_mode & S_IFMT;
801 fprintf (fp, segment->text,
802 ( m == S_IFSOCK ? "s" :
803 m == S_IFLNK ? "l" :
804 m == S_IFREG ? "f" :
805 m == S_IFBLK ? "b" :
806 m == S_IFDIR ? "d" :
807 m == S_IFCHR ? "c" :
808 #ifdef S_IFDOOR
809 m == S_IFDOOR ? "D" :
810 #endif
811 m == S_IFIFO ? "p" : "U" ) );
814 break;
817 return (true);
820 boolean
821 pred_fstype (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
823 if (strcmp (filesystem_type (pathname, rel_pathname, stat_buf),
824 pred_ptr->args.str) == 0)
825 return (true);
826 return (false);
829 boolean
830 pred_gid (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
832 (void) pathname;
834 switch (pred_ptr->args.info.kind)
836 case COMP_GT:
837 if (stat_buf->st_gid > pred_ptr->args.info.l_val)
838 return (true);
839 break;
840 case COMP_LT:
841 if (stat_buf->st_gid < pred_ptr->args.info.l_val)
842 return (true);
843 break;
844 case COMP_EQ:
845 if (stat_buf->st_gid == pred_ptr->args.info.l_val)
846 return (true);
847 break;
849 return (false);
852 boolean
853 pred_group (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
855 (void) pathname;
857 if (pred_ptr->args.gid == stat_buf->st_gid)
858 return (true);
859 else
860 return (false);
863 boolean
864 pred_ilname (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
866 return insert_lname (pathname, stat_buf, pred_ptr, true);
869 boolean
870 pred_iname (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
872 const char *base;
874 (void) stat_buf;
876 /* FNM_PERIOD is not used here because POSIX requires that it not be.
877 * See http://standards.ieee.org/reading/ieee/interp/1003-2-92_int/pasc-1003.2-126.html
879 base = base_name (pathname);
880 if (fnmatch (pred_ptr->args.str, base, FNM_CASEFOLD) == 0)
881 return (true);
882 return (false);
885 boolean
886 pred_inum (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
888 (void) pathname;
890 switch (pred_ptr->args.info.kind)
892 case COMP_GT:
893 if (stat_buf->st_ino > pred_ptr->args.info.l_val)
894 return (true);
895 break;
896 case COMP_LT:
897 if (stat_buf->st_ino < pred_ptr->args.info.l_val)
898 return (true);
899 break;
900 case COMP_EQ:
901 if (stat_buf->st_ino == pred_ptr->args.info.l_val)
902 return (true);
903 break;
905 return (false);
908 boolean
909 pred_ipath (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
911 (void) stat_buf;
913 if (fnmatch (pred_ptr->args.str, pathname, FNM_CASEFOLD) == 0)
914 return (true);
915 return (false);
918 boolean
919 pred_links (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
921 (void) pathname;
923 switch (pred_ptr->args.info.kind)
925 case COMP_GT:
926 if (stat_buf->st_nlink > pred_ptr->args.info.l_val)
927 return (true);
928 break;
929 case COMP_LT:
930 if (stat_buf->st_nlink < pred_ptr->args.info.l_val)
931 return (true);
932 break;
933 case COMP_EQ:
934 if (stat_buf->st_nlink == pred_ptr->args.info.l_val)
935 return (true);
936 break;
938 return (false);
941 boolean
942 pred_lname (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
944 return insert_lname (pathname, stat_buf, pred_ptr, false);
947 static boolean
948 insert_lname (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr, boolean ignore_case)
950 boolean ret = false;
951 #ifdef S_ISLNK
952 if (S_ISLNK (stat_buf->st_mode))
954 char *linkname = get_link_name (pathname, rel_pathname);
955 if (linkname)
957 if (fnmatch (pred_ptr->args.str, linkname,
958 ignore_case ? FNM_CASEFOLD : 0) == 0)
959 ret = true;
960 free (linkname);
963 #endif /* S_ISLNK */
964 return (ret);
967 boolean
968 pred_ls (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
970 (void) pred_ptr;
972 list_file (pathname, rel_pathname, stat_buf, start_time,
973 output_block_size, stdout);
974 return (true);
977 boolean
978 pred_mmin (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
980 (void) &pathname;
981 return pred_timewindow(stat_buf->st_mtime, pred_ptr, 60);
984 boolean
985 pred_mtime (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
987 (void) pathname;
988 return pred_timewindow(stat_buf->st_mtime, pred_ptr, DAYSECS);
991 boolean
992 pred_name (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
994 const char *base;
996 (void) stat_buf;
997 base = base_name (pathname);
999 /* FNM_PERIOD is not used here because POSIX requires that it not be.
1000 * See http://standards.ieee.org/reading/ieee/interp/1003-2-92_int/pasc-1003.2-126.html
1002 if (fnmatch (pred_ptr->args.str, base, 0) == 0)
1003 return (true);
1004 return (false);
1007 boolean
1008 pred_negate (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1010 /* Check whether we need a stat here. */
1011 if (pred_ptr->need_stat)
1013 if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
1015 error (0, errno, "%s", pathname);
1016 exit_status = 1;
1017 return (false);
1019 have_stat = true;
1021 return (!(*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
1022 pred_ptr->pred_right));
1025 boolean
1026 pred_newer (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1028 (void) pathname;
1030 if (stat_buf->st_mtime > pred_ptr->args.time)
1031 return (true);
1032 return (false);
1035 boolean
1036 pred_nogroup (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1038 (void) pathname;
1039 (void) pred_ptr;
1041 #ifdef CACHE_IDS
1042 extern char *gid_unused;
1044 return gid_unused[(unsigned) stat_buf->st_gid];
1045 #else
1046 return getgrgid (stat_buf->st_gid) == NULL;
1047 #endif
1050 boolean
1051 pred_nouser (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1053 #ifdef CACHE_IDS
1054 extern char *uid_unused;
1055 #endif
1057 (void) pathname;
1058 (void) pred_ptr;
1060 #ifdef CACHE_IDS
1061 return uid_unused[(unsigned) stat_buf->st_uid];
1062 #else
1063 return getpwuid (stat_buf->st_uid) == NULL;
1064 #endif
1067 boolean
1068 pred_ok (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1070 fflush (stdout);
1071 /* The draft open standard requires that, in the POSIX locale,
1072 the last non-blank character of this prompt be '?'.
1073 The exact format is not specified.
1074 This standard does not have requirements for locales other than POSIX
1076 fprintf (stderr, _("< %s ... %s > ? "),
1077 pred_ptr->args.exec_vec.vec[0], pathname);
1078 fflush (stderr);
1079 if (yesno ())
1080 return pred_exec (pathname, stat_buf, pred_ptr);
1081 else
1082 return (false);
1085 boolean
1086 pred_open (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1088 (void) pathname;
1089 (void) stat_buf;
1090 (void) pred_ptr;
1091 return true;
1094 boolean
1095 pred_or (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1097 if (pred_ptr->pred_left == NULL
1098 || !(*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
1099 pred_ptr->pred_left))
1101 /* Check whether we need a stat here. */
1102 if (pred_ptr->need_stat)
1104 if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
1106 error (0, errno, "%s", pathname);
1107 exit_status = 1;
1108 return (false);
1110 have_stat = true;
1112 return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
1113 pred_ptr->pred_right));
1115 else
1116 return (true);
1119 boolean
1120 pred_path (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1122 (void) stat_buf;
1123 if (fnmatch (pred_ptr->args.str, pathname, 0) == 0)
1124 return (true);
1125 return (false);
1128 boolean
1129 pred_perm (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1131 (void) pathname;
1132 switch (pred_ptr->args.perm.kind)
1134 case PERM_AT_LEAST:
1135 return (stat_buf->st_mode & pred_ptr->args.perm.val) == pred_ptr->args.perm.val;
1136 break;
1138 case PERM_ANY:
1139 return (stat_buf->st_mode & pred_ptr->args.perm.val) != 0;
1140 break;
1142 case PERM_EXACT:
1143 return (stat_buf->st_mode & MODE_ALL) == pred_ptr->args.perm.val;
1144 break;
1146 default:
1147 abort ();
1148 break;
1152 boolean
1153 pred_print (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1155 (void) stat_buf;
1156 (void) pred_ptr;
1157 puts (pathname);
1158 return true;
1161 boolean
1162 pred_print0 (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1164 (void) stat_buf;
1165 (void) pred_ptr;
1166 fputs (pathname, stdout);
1167 putc (0, stdout);
1168 return (true);
1171 boolean
1172 pred_prune (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1174 (void) pathname;
1175 (void) stat_buf;
1176 (void) pred_ptr;
1177 stop_at_current_level = true;
1178 return (do_dir_first); /* This is what SunOS find seems to do. */
1181 boolean
1182 pred_quit (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1184 (void) pathname;
1185 (void) stat_buf;
1186 (void) pred_ptr;
1187 exit(0);
1190 boolean
1191 pred_regex (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1193 int len = strlen (pathname);
1194 (void) stat_buf;
1195 if (re_match (pred_ptr->args.regex, pathname, len, 0,
1196 (struct re_registers *) NULL) == len)
1197 return (true);
1198 return (false);
1201 boolean
1202 pred_size (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1204 uintmax_t f_val;
1206 (void) pathname;
1207 f_val = ((stat_buf->st_size / pred_ptr->args.size.blocksize)
1208 + (stat_buf->st_size % pred_ptr->args.size.blocksize != 0));
1209 switch (pred_ptr->args.size.kind)
1211 case COMP_GT:
1212 if (f_val > pred_ptr->args.size.size)
1213 return (true);
1214 break;
1215 case COMP_LT:
1216 if (f_val < pred_ptr->args.size.size)
1217 return (true);
1218 break;
1219 case COMP_EQ:
1220 if (f_val == pred_ptr->args.size.size)
1221 return (true);
1222 break;
1224 return (false);
1227 boolean
1228 pred_true (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1230 (void) pathname;
1231 (void) stat_buf;
1232 (void) pred_ptr;
1233 return true;
1236 boolean
1237 pred_type (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1239 mode_t mode = stat_buf->st_mode;
1240 mode_t type = pred_ptr->args.type;
1242 (void) pathname;
1244 #ifndef S_IFMT
1245 /* POSIX system; check `mode' the slow way. */
1246 if ((S_ISBLK (mode) && type == S_IFBLK)
1247 || (S_ISCHR (mode) && type == S_IFCHR)
1248 || (S_ISDIR (mode) && type == S_IFDIR)
1249 || (S_ISREG (mode) && type == S_IFREG)
1250 #ifdef S_IFLNK
1251 || (S_ISLNK (mode) && type == S_IFLNK)
1252 #endif
1253 #ifdef S_IFIFO
1254 || (S_ISFIFO (mode) && type == S_IFIFO)
1255 #endif
1256 #ifdef S_IFSOCK
1257 || (S_ISSOCK (mode) && type == S_IFSOCK)
1258 #endif
1259 #ifdef S_IFDOOR
1260 || (S_ISDOOR (mode) && type == S_IFDOOR)
1261 #endif
1263 #else /* S_IFMT */
1264 /* Unix system; check `mode' the fast way. */
1265 if ((mode & S_IFMT) == type)
1266 #endif /* S_IFMT */
1267 return (true);
1268 else
1269 return (false);
1272 boolean
1273 pred_uid (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1275 (void) pathname;
1276 switch (pred_ptr->args.info.kind)
1278 case COMP_GT:
1279 if (stat_buf->st_uid > pred_ptr->args.info.l_val)
1280 return (true);
1281 break;
1282 case COMP_LT:
1283 if (stat_buf->st_uid < pred_ptr->args.info.l_val)
1284 return (true);
1285 break;
1286 case COMP_EQ:
1287 if (stat_buf->st_uid == pred_ptr->args.info.l_val)
1288 return (true);
1289 break;
1291 return (false);
1294 boolean
1295 pred_used (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1297 time_t delta;
1299 (void) pathname;
1300 delta = stat_buf->st_atime - stat_buf->st_ctime; /* Use difftime? */
1301 return pred_timewindow(delta, pred_ptr, DAYSECS);
1304 boolean
1305 pred_user (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1307 (void) pathname;
1308 if (pred_ptr->args.uid == stat_buf->st_uid)
1309 return (true);
1310 else
1311 return (false);
1314 boolean
1315 pred_xtype (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1317 struct stat sbuf; /* local copy, not stat_buf because we're using a different stat method */
1318 int (*ystat) (const char*, struct stat *p);
1320 switch (symlink_handling)
1322 case SYMLINK_ALWAYS_DEREF:
1323 ystat = optionl_stat;
1324 case SYMLINK_DEREF_ARGSONLY:
1325 case SYMLINK_NEVER_DEREF:
1326 ystat = optionp_stat;
1329 if ((*ystat) (rel_pathname, &sbuf) != 0)
1331 if (ystat == optionl_stat && errno == ENOENT)
1333 /* If we failed to follow the symlink,
1334 * fall back on looking at the symlink itself.
1336 /* Mimic behavior of ls -lL. */
1337 return (pred_type (pathname, stat_buf, pred_ptr));
1339 else
1341 error (0, errno, "%s", pathname);
1342 exit_status = 1;
1344 return false;
1346 /* Now that we have our stat() information, query it in the same
1347 * way that -type does.
1349 return (pred_type (pathname, &sbuf, pred_ptr));
1352 /* 1) fork to get a child; parent remembers the child pid
1353 2) child execs the command requested
1354 3) parent waits for child; checks for proper pid of child
1356 Possible returns:
1358 ret errno status(h) status(l)
1360 pid x signal# 0177 stopped
1361 pid x exit arg 0 term by _exit
1362 pid x 0 signal # term by signal
1363 -1 EINTR parent got signal
1364 -1 other some other kind of error
1366 Return true only if the pid matches, status(l) is
1367 zero, and the exit arg (status high) is 0.
1368 Otherwise return false, possibly printing an error message. */
1370 static boolean
1371 launch (struct predicate *pred_ptr)
1373 int status;
1374 pid_t child_pid;
1375 struct exec_val *execp; /* Pointer for efficiency. */
1376 static int first_time = 1;
1378 execp = &pred_ptr->args.exec_vec;
1380 /* Make sure output of command doesn't get mixed with find output. */
1381 fflush (stdout);
1382 fflush (stderr);
1384 /* Make sure to listen for the kids. */
1385 if (first_time)
1387 first_time = 0;
1388 signal (SIGCHLD, SIG_DFL);
1391 child_pid = fork ();
1392 if (child_pid == -1)
1393 error (1, errno, _("cannot fork"));
1394 if (child_pid == 0)
1396 /* We be the child. */
1397 if (starting_desc < 0
1398 ? chdir (starting_dir) != 0
1399 : fchdir (starting_desc) != 0)
1401 error (0, errno, "%s", starting_dir);
1402 _exit (1);
1404 execvp (execp->vec[0], execp->vec);
1405 error (0, errno, "%s", execp->vec[0]);
1406 _exit (1);
1410 while (waitpid (child_pid, &status, 0) == (pid_t) -1)
1411 if (errno != EINTR)
1413 error (0, errno, _("error waiting for %s"), execp->vec[0]);
1414 exit_status = 1;
1415 return false;
1417 if (WIFSIGNALED (status))
1419 error (0, 0, _("%s terminated by signal %d"),
1420 execp->vec[0], WTERMSIG (status));
1421 exit_status = 1;
1422 return (false);
1424 return (!WEXITSTATUS (status));
1427 /* Return a static string formatting the time WHEN according to the
1428 strftime format character KIND. */
1430 static char *
1431 format_date (time_t when, int kind)
1433 static char buf[MAX (LONGEST_HUMAN_READABLE + 2, 64)];
1434 struct tm *tm;
1435 char fmt[6];
1437 fmt[0] = '%';
1438 fmt[1] = kind;
1439 fmt[2] = '\0';
1440 if (kind == '+')
1441 strcpy (fmt, "%F+%T");
1443 if (kind != '@'
1444 && (tm = localtime (&when))
1445 && strftime (buf, sizeof buf, fmt, tm))
1446 return buf;
1447 else
1449 uintmax_t w = when;
1450 char *p = human_readable (when < 0 ? -w : w, buf + 1,
1451 human_ceiling, 1, 1);
1452 if (when < 0)
1453 *--p = '-';
1454 return p;
1458 static char *
1459 ctime_format (when)
1460 time_t when;
1462 char *r = ctime (&when);
1463 if (!r)
1465 /* The time cannot be represented as a struct tm.
1466 Output it as an integer. */
1467 return format_date (when, '@');
1469 else
1471 /* Remove the trailing newline from the ctime output,
1472 being careful not to assume that the output is fixed-width. */
1473 *strchr (r, '\n') = '\0';
1474 return r;
1478 #ifdef DEBUG
1479 /* Return a pointer to the string representation of
1480 the predicate function PRED_FUNC. */
1482 char *
1483 find_pred_name (pred_func)
1484 PFB pred_func;
1486 int i;
1488 for (i = 0; pred_table[i].pred_func != 0; i++)
1489 if (pred_table[i].pred_func == pred_func)
1490 break;
1491 return (pred_table[i].pred_name);
1494 static char *
1495 type_name (type)
1496 short type;
1498 int i;
1500 for (i = 0; type_table[i].type != (short) -1; i++)
1501 if (type_table[i].type == type)
1502 break;
1503 return (type_table[i].type_name);
1506 static char *
1507 prec_name (prec)
1508 short prec;
1510 int i;
1512 for (i = 0; prec_table[i].prec != (short) -1; i++)
1513 if (prec_table[i].prec == prec)
1514 break;
1515 return (prec_table[i].prec_name);
1518 /* Walk the expression tree NODE to stdout.
1519 INDENT is the number of levels to indent the left margin. */
1521 void
1522 print_tree (node, indent)
1523 struct predicate *node;
1524 int indent;
1526 int i;
1528 if (node == NULL)
1529 return;
1530 for (i = 0; i < indent; i++)
1531 printf (" ");
1532 printf ("pred = %s type = %s prec = %s addr = %x\n",
1533 find_pred_name (node->pred_func),
1534 type_name (node->p_type), prec_name (node->p_prec), node);
1535 for (i = 0; i < indent; i++)
1536 printf (" ");
1537 printf (_("left:\n"));
1538 print_tree (node->pred_left, indent + 1);
1539 for (i = 0; i < indent; i++)
1540 printf (" ");
1541 printf (_("right:\n"));
1542 print_tree (node->pred_right, indent + 1);
1545 /* Copy STR into BUF and trim blanks from the end of BUF.
1546 Return BUF. */
1548 static char *
1549 blank_rtrim (str, buf)
1550 char *str;
1551 char *buf;
1553 int i;
1555 if (str == NULL)
1556 return (NULL);
1557 strcpy (buf, str);
1558 i = strlen (buf) - 1;
1559 while ((i >= 0) && ((buf[i] == ' ') || buf[i] == '\t'))
1560 i--;
1561 buf[++i] = '\0';
1562 return (buf);
1565 /* Print out the predicate list starting at NODE. */
1567 void
1568 print_list (node)
1569 struct predicate *node;
1571 struct predicate *cur;
1572 char name[256];
1574 cur = node;
1575 while (cur != NULL)
1577 printf ("%s ", blank_rtrim (find_pred_name (cur->pred_func), name));
1578 cur = cur->pred_next;
1580 printf ("\n");
1582 #endif /* DEBUG */