Removed incorrect comment about -H, -P and -follow in HISTORY.
[findutils.git] / find / pred.c
blob254f16a57c0f07a13acf51c612edd04fb216e0d9
1 /* pred.c -- execute the expression tree.
2 Copyright (C) 1990, 91, 92, 93, 94, 2000, 2003, 2004 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/xalloc.h"
27 #include "../gnulib/lib/dirname.h"
28 #include "../gnulib/lib/human.h"
29 #include "modetype.h"
30 #include "filemode.h"
31 #include "wait.h"
33 #if ENABLE_NLS
34 # include <libintl.h>
35 # define _(Text) gettext (Text)
36 #else
37 # define _(Text) Text
38 #endif
39 #ifdef gettext_noop
40 # define N_(String) gettext_noop (String)
41 #else
42 /* See locate.c for explanation as to why not use (String) */
43 # define N_(String) String
44 #endif
46 #if !defined(SIGCHLD) && defined(SIGCLD)
47 #define SIGCHLD SIGCLD
48 #endif
50 #if HAVE_DIRENT_H
51 # include <dirent.h>
52 # define NAMLEN(dirent) strlen((dirent)->d_name)
53 #else
54 # define dirent direct
55 # define NAMLEN(dirent) (dirent)->d_namlen
56 # if HAVE_SYS_NDIR_H
57 # include <sys/ndir.h>
58 # endif
59 # if HAVE_SYS_DIR_H
60 # include <sys/dir.h>
61 # endif
62 # if HAVE_NDIR_H
63 # include <ndir.h>
64 # endif
65 #endif
67 #ifdef CLOSEDIR_VOID
68 /* Fake a return value. */
69 #define CLOSEDIR(d) (closedir (d), 0)
70 #else
71 #define CLOSEDIR(d) closedir (d)
72 #endif
74 extern int yesno ();
77 /* Get or fake the disk device blocksize.
78 Usually defined by sys/param.h (if at all). */
79 #ifndef DEV_BSIZE
80 # ifdef BSIZE
81 # define DEV_BSIZE BSIZE
82 # else /* !BSIZE */
83 # define DEV_BSIZE 4096
84 # endif /* !BSIZE */
85 #endif /* !DEV_BSIZE */
87 /* Extract or fake data from a `struct stat'.
88 ST_BLKSIZE: Preferred I/O blocksize for the file, in bytes.
89 ST_NBLOCKS: Number of blocks in the file, including indirect blocks.
90 ST_NBLOCKSIZE: Size of blocks used when calculating ST_NBLOCKS. */
91 #ifndef HAVE_STRUCT_STAT_ST_BLOCKS
92 # define ST_BLKSIZE(statbuf) DEV_BSIZE
93 # if defined(_POSIX_SOURCE) || !defined(BSIZE) /* fileblocks.c uses BSIZE. */
94 # define ST_NBLOCKS(statbuf) \
95 (S_ISREG ((statbuf).st_mode) \
96 || S_ISDIR ((statbuf).st_mode) \
97 ? (statbuf).st_size / ST_NBLOCKSIZE + ((statbuf).st_size % ST_NBLOCKSIZE != 0) : 0)
98 # else /* !_POSIX_SOURCE && BSIZE */
99 # define ST_NBLOCKS(statbuf) \
100 (S_ISREG ((statbuf).st_mode) \
101 || S_ISDIR ((statbuf).st_mode) \
102 ? st_blocks ((statbuf).st_size) : 0)
103 # endif /* !_POSIX_SOURCE && BSIZE */
104 #else /* HAVE_STRUCT_STAT_ST_BLOCKS */
105 /* Some systems, like Sequents, return st_blksize of 0 on pipes. */
106 # define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \
107 ? (statbuf).st_blksize : DEV_BSIZE)
108 # if defined(hpux) || defined(__hpux__) || defined(__hpux)
109 /* HP-UX counts st_blocks in 1024-byte units.
110 This loses when mixing HP-UX and BSD filesystems with NFS. */
111 # define ST_NBLOCKSIZE 1024
112 # else /* !hpux */
113 # if defined(_AIX) && defined(_I386)
114 /* AIX PS/2 counts st_blocks in 4K units. */
115 # define ST_NBLOCKSIZE (4 * 1024)
116 # else /* not AIX PS/2 */
117 # if defined(_CRAY)
118 # define ST_NBLOCKS(statbuf) \
119 (S_ISREG ((statbuf).st_mode) \
120 || S_ISDIR ((statbuf).st_mode) \
121 ? (statbuf).st_blocks * ST_BLKSIZE(statbuf)/ST_NBLOCKSIZE : 0)
122 # endif /* _CRAY */
123 # endif /* not AIX PS/2 */
124 # endif /* !hpux */
125 #endif /* HAVE_STRUCT_STAT_ST_BLOCKS */
127 #ifndef ST_NBLOCKS
128 # define ST_NBLOCKS(statbuf) \
129 (S_ISREG ((statbuf).st_mode) \
130 || S_ISDIR ((statbuf).st_mode) \
131 ? (statbuf).st_blocks : 0)
132 #endif
134 #ifndef ST_NBLOCKSIZE
135 # define ST_NBLOCKSIZE 512
136 #endif
138 #undef MAX
139 #define MAX(a, b) ((a) > (b) ? (a) : (b))
141 static boolean insert_lname PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr, boolean ignore_case));
142 static boolean launch PARAMS((struct predicate *pred_ptr));
143 static char *format_date PARAMS((time_t when, int kind));
144 static char *ctime_format PARAMS((time_t when));
146 #ifdef DEBUG
147 struct pred_assoc
149 PFB pred_func;
150 char *pred_name;
153 struct pred_assoc pred_table[] =
155 {pred_amin, "amin "},
156 {pred_and, "and "},
157 {pred_anewer, "anewer "},
158 {pred_atime, "atime "},
159 {pred_close, ") "},
160 {pred_amin, "cmin "},
161 {pred_cnewer, "cnewer "},
162 {pred_comma, ", "},
163 {pred_ctime, "ctime "},
164 {pred_delete, "delete "},
165 {pred_empty, "empty "},
166 {pred_exec, "exec "},
167 {pred_false, "false "},
168 {pred_fprint, "fprint "},
169 {pred_fprint0, "fprint0 "},
170 {pred_fprintf, "fprintf "},
171 {pred_fstype, "fstype "},
172 {pred_gid, "gid "},
173 {pred_group, "group "},
174 {pred_ilname, "ilname "},
175 {pred_iname, "iname "},
176 {pred_inum, "inum "},
177 {pred_ipath, "ipath "},
178 {pred_links, "links "},
179 {pred_lname, "lname "},
180 {pred_ls, "ls "},
181 {pred_amin, "mmin "},
182 {pred_mtime, "mtime "},
183 {pred_name, "name "},
184 {pred_negate, "not "},
185 {pred_newer, "newer "},
186 {pred_nogroup, "nogroup "},
187 {pred_nouser, "nouser "},
188 {pred_ok, "ok "},
189 {pred_open, "( "},
190 {pred_or, "or "},
191 {pred_path, "path "},
192 {pred_perm, "perm "},
193 {pred_print, "print "},
194 {pred_print0, "print0 "},
195 {pred_prune, "prune "},
196 {pred_regex, "regex "},
197 {pred_samefile,"samefile "},
198 {pred_size, "size "},
199 {pred_true, "true "},
200 {pred_type, "type "},
201 {pred_uid, "uid "},
202 {pred_used, "used "},
203 {pred_user, "user "},
204 {pred_xtype, "xtype "},
205 {0, "none "}
208 struct op_assoc
210 short type;
211 char *type_name;
214 struct op_assoc type_table[] =
216 {NO_TYPE, "no "},
217 {PRIMARY_TYPE, "primary "},
218 {UNI_OP, "uni_op "},
219 {BI_OP, "bi_op "},
220 {OPEN_PAREN, "open_paren "},
221 {CLOSE_PAREN, "close_paren "},
222 {-1, "unknown "}
225 struct prec_assoc
227 short prec;
228 char *prec_name;
231 struct prec_assoc prec_table[] =
233 {NO_PREC, "no "},
234 {COMMA_PREC, "comma "},
235 {OR_PREC, "or "},
236 {AND_PREC, "and "},
237 {NEGATE_PREC, "negate "},
238 {MAX_PREC, "max "},
239 {-1, "unknown "}
241 #endif /* DEBUG */
243 /* Predicate processing routines.
245 PATHNAME is the full pathname of the file being checked.
246 *STAT_BUF contains information about PATHNAME.
247 *PRED_PTR contains information for applying the predicate.
249 Return true if the file passes this predicate, false if not. */
252 /* pred_timewindow
254 * Returns true if THE_TIME is
255 * COMP_GT: after the specified time
256 * COMP_LT: before the specified time
257 * COMP_EQ: less than WINDOW seconds after the specified time.
259 static boolean
260 pred_timewindow(time_t the_time, struct predicate const *pred_ptr, int window)
262 switch (pred_ptr->args.info.kind)
264 case COMP_GT:
265 if (the_time > (time_t) pred_ptr->args.info.l_val)
266 return true;
267 break;
268 case COMP_LT:
269 if (the_time < (time_t) pred_ptr->args.info.l_val)
270 return true;
271 break;
272 case COMP_EQ:
273 if ((the_time >= (time_t) pred_ptr->args.info.l_val)
274 && (the_time < (time_t) pred_ptr->args.info.l_val + window))
275 return true;
276 break;
278 return false;
282 boolean
283 pred_amin (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
285 (void) &pathname;
286 return pred_timewindow(stat_buf->st_atime, pred_ptr, 60);
289 boolean
290 pred_and (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
292 if (pred_ptr->pred_left == NULL
293 || (*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
294 pred_ptr->pred_left))
296 /* Check whether we need a stat here. */
297 if (pred_ptr->need_stat)
299 if (!state.have_stat && (*options.xstat) (state.rel_pathname, stat_buf) != 0)
301 error (0, errno, "%s", pathname);
302 state.exit_status = 1;
303 return (false);
305 state.have_stat = true;
307 return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
308 pred_ptr->pred_right));
310 else
311 return (false);
314 boolean
315 pred_anewer (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
317 (void) &pathname;
319 if (stat_buf->st_atime > pred_ptr->args.time)
320 return (true);
321 return (false);
324 boolean
325 pred_atime (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
327 (void) &pathname;
328 return pred_timewindow(stat_buf->st_atime, pred_ptr, DAYSECS);
331 boolean
332 pred_close (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
334 (void) &pathname;
335 (void) &stat_buf;
336 (void) &pred_ptr;
338 return true;
341 boolean
342 pred_cmin (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
344 (void) pathname;
345 return pred_timewindow(stat_buf->st_ctime, pred_ptr, 60);
348 boolean
349 pred_cnewer (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
351 (void) pathname;
353 if (stat_buf->st_ctime > pred_ptr->args.time)
354 return true;
355 else
356 return false;
359 boolean
360 pred_comma (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
362 if (pred_ptr->pred_left != NULL)
363 (*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
364 pred_ptr->pred_left);
365 /* Check whether we need a stat here. */
366 if (pred_ptr->need_stat)
368 if (!state.have_stat && (*options.xstat) (state.rel_pathname, stat_buf) != 0)
370 error (0, errno, "%s", pathname);
371 state.exit_status = 1;
372 return (false);
374 state.have_stat = true;
376 return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
377 pred_ptr->pred_right));
380 boolean
381 pred_ctime (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
383 (void) &pathname;
384 return pred_timewindow(stat_buf->st_ctime, pred_ptr, DAYSECS);
387 boolean
388 pred_delete (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
390 (void) pred_ptr;
391 (void) stat_buf;
392 if (strcmp (state.rel_pathname, "."))
394 if (0 != remove (state.rel_pathname))
396 error (0, errno, "cannot delete %s", pathname);
397 return false;
399 else
401 return true;
405 /* nothing to do. */
406 return true;
409 boolean
410 pred_empty (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
412 (void) pathname;
413 (void) pred_ptr;
415 if (S_ISDIR (stat_buf->st_mode))
417 DIR *d;
418 struct dirent *dp;
419 boolean empty = true;
421 errno = 0;
422 d = opendir (state.rel_pathname);
423 if (d == NULL)
425 error (0, errno, "%s", pathname);
426 state.exit_status = 1;
427 return false;
429 for (dp = readdir (d); dp; dp = readdir (d))
431 if (dp->d_name[0] != '.'
432 || (dp->d_name[1] != '\0'
433 && (dp->d_name[1] != '.' || dp->d_name[2] != '\0')))
435 empty = false;
436 break;
439 if (CLOSEDIR (d))
441 error (0, errno, "%s", pathname);
442 state.exit_status = 1;
443 return false;
445 return (empty);
447 else if (S_ISREG (stat_buf->st_mode))
448 return (stat_buf->st_size == 0);
449 else
450 return (false);
453 boolean
454 pred_exec (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
456 int i;
457 int path_pos;
458 struct exec_val *execp; /* Pointer for efficiency. */
460 (void) pathname;
461 (void) stat_buf;
463 execp = &pred_ptr->args.exec_vec;
465 /* Replace "{}" with the real path in each affected arg. */
466 for (path_pos = 0; execp->paths[path_pos].offset >= 0; path_pos++)
468 register char *from, *to;
470 i = execp->paths[path_pos].offset;
471 execp->vec[i] =
472 xmalloc (strlen (execp->paths[path_pos].origarg) + 1
473 + (strlen (pathname) - 2) * execp->paths[path_pos].count);
474 for (from = execp->paths[path_pos].origarg, to = execp->vec[i]; *from; )
475 if (from[0] == '{' && from[1] == '}')
477 to = stpcpy (to, pathname);
478 from += 2;
480 else
481 *to++ = *from++;
482 *to = *from; /* Copy null. */
485 i = launch (pred_ptr);
487 /* Free the temporary args. */
488 for (path_pos = 0; execp->paths[path_pos].offset >= 0; path_pos++)
489 free (execp->vec[execp->paths[path_pos].offset]);
491 return (i);
494 boolean
495 pred_false (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
497 (void) &pathname;
498 (void) &stat_buf;
499 (void) &pred_ptr;
502 return (false);
505 boolean
506 pred_fls (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
508 list_file (pathname, state.rel_pathname, stat_buf, options.start_time,
509 options.output_block_size, pred_ptr->args.stream);
510 return (true);
513 boolean
514 pred_fprint (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
516 (void) &pathname;
517 (void) &stat_buf;
519 fputs (pathname, pred_ptr->args.stream);
520 putc ('\n', pred_ptr->args.stream);
521 return (true);
524 boolean
525 pred_fprint0 (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
527 (void) &pathname;
528 (void) &stat_buf;
530 fputs (pathname, pred_ptr->args.stream);
531 putc (0, pred_ptr->args.stream);
532 return (true);
535 boolean
536 pred_fprintf (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
538 FILE *fp = pred_ptr->args.printf_vec.stream;
539 struct segment *segment;
540 char *cp;
541 char hbuf[LONGEST_HUMAN_READABLE + 1];
543 for (segment = pred_ptr->args.printf_vec.segment; segment;
544 segment = segment->next)
546 if (segment->kind & 0xff00) /* Component of date. */
548 time_t t;
550 switch (segment->kind & 0xff)
552 case 'A':
553 t = stat_buf->st_atime;
554 break;
555 case 'C':
556 t = stat_buf->st_ctime;
557 break;
558 case 'T':
559 t = stat_buf->st_mtime;
560 break;
561 default:
562 abort ();
564 fprintf (fp, segment->text,
565 format_date (t, (segment->kind >> 8) & 0xff));
566 continue;
569 switch (segment->kind)
571 case KIND_PLAIN: /* Plain text string (no % conversion). */
572 fwrite (segment->text, 1, segment->text_len, fp);
573 break;
574 case KIND_STOP: /* Terminate argument and flush output. */
575 fwrite (segment->text, 1, segment->text_len, fp);
576 fflush (fp);
577 return (true);
578 case 'a': /* atime in `ctime' format. */
579 fprintf (fp, segment->text, ctime_format (stat_buf->st_atime));
580 break;
581 case 'b': /* size in 512-byte blocks */
582 fprintf (fp, segment->text,
583 human_readable ((uintmax_t) ST_NBLOCKS (*stat_buf),
584 hbuf, human_ceiling,
585 ST_NBLOCKSIZE, 512));
586 break;
587 case 'c': /* ctime in `ctime' format */
588 fprintf (fp, segment->text, ctime_format (stat_buf->st_ctime));
589 break;
590 case 'd': /* depth in search tree */
591 fprintf (fp, segment->text, state.curdepth);
592 break;
593 case 'D': /* Device on which file exists (stat.st_dev) */
594 fprintf (fp, segment->text,
595 human_readable ((uintmax_t) stat_buf->st_dev, hbuf,
596 human_ceiling, 1, 1));
597 break;
598 case 'f': /* basename of path */
599 fprintf (fp, segment->text, base_name (pathname));
600 break;
601 case 'F': /* filesystem type */
602 fprintf (fp, segment->text, filesystem_type (stat_buf));
603 break;
604 case 'g': /* group name */
606 struct group *g;
608 g = getgrgid (stat_buf->st_gid);
609 if (g)
611 segment->text[segment->text_len] = 's';
612 fprintf (fp, segment->text, g->gr_name);
613 break;
615 /* else fallthru */
617 case 'G': /* GID number */
618 fprintf (fp, segment->text,
619 human_readable ((uintmax_t) stat_buf->st_gid, hbuf,
620 human_ceiling, 1, 1));
621 break;
622 case 'h': /* leading directories part of path */
624 char cc;
626 cp = strrchr (pathname, '/');
627 if (cp == NULL) /* No leading directories. */
628 break;
629 cc = *cp;
630 *cp = '\0';
631 fprintf (fp, segment->text, pathname);
632 *cp = cc;
633 break;
635 case 'H': /* ARGV element file was found under */
637 char cc = pathname[state.path_length];
639 pathname[state.path_length] = '\0';
640 fprintf (fp, segment->text, pathname);
641 pathname[state.path_length] = cc;
642 break;
644 case 'i': /* inode number */
645 fprintf (fp, segment->text,
646 human_readable ((uintmax_t) stat_buf->st_ino, hbuf,
647 human_ceiling,
648 1, 1));
649 break;
650 case 'k': /* size in 1K blocks */
651 fprintf (fp, segment->text,
652 human_readable ((uintmax_t) ST_NBLOCKS (*stat_buf),
653 hbuf, human_ceiling,
654 ST_NBLOCKSIZE, 1024));
655 break;
656 case 'l': /* object of symlink */
657 #ifdef S_ISLNK
659 char *linkname = 0;
661 if (S_ISLNK (stat_buf->st_mode))
663 linkname = get_link_name (pathname, state.rel_pathname);
664 if (linkname == 0)
665 state.exit_status = 1;
667 if (linkname)
669 fprintf (fp, segment->text, linkname);
670 free (linkname);
672 else
673 fprintf (fp, segment->text, "");
675 #endif /* S_ISLNK */
676 break;
678 case 'M': /* mode as 10 chars (eg., "-rwxr-x--x" */
680 char modestring[16] ;
681 mode_string (stat_buf->st_mode, modestring);
682 modestring[10] = '\0';
683 fprintf (fp, segment->text, modestring);
685 break;
687 case 'm': /* mode as octal number (perms only) */
689 /* Output the mode portably using the traditional numbers,
690 even if the host unwisely uses some other numbering
691 scheme. But help the compiler in the common case where
692 the host uses the traditional numbering scheme. */
693 mode_t m = stat_buf->st_mode;
694 boolean traditional_numbering_scheme =
695 (S_ISUID == 04000 && S_ISGID == 02000 && S_ISVTX == 01000
696 && S_IRUSR == 00400 && S_IWUSR == 00200 && S_IXUSR == 00100
697 && S_IRGRP == 00040 && S_IWGRP == 00020 && S_IXGRP == 00010
698 && S_IROTH == 00004 && S_IWOTH == 00002 && S_IXOTH == 00001);
699 fprintf (fp, segment->text,
700 (traditional_numbering_scheme
701 ? m & MODE_ALL
702 : ((m & S_ISUID ? 04000 : 0)
703 | (m & S_ISGID ? 02000 : 0)
704 | (m & S_ISVTX ? 01000 : 0)
705 | (m & S_IRUSR ? 00400 : 0)
706 | (m & S_IWUSR ? 00200 : 0)
707 | (m & S_IXUSR ? 00100 : 0)
708 | (m & S_IRGRP ? 00040 : 0)
709 | (m & S_IWGRP ? 00020 : 0)
710 | (m & S_IXGRP ? 00010 : 0)
711 | (m & S_IROTH ? 00004 : 0)
712 | (m & S_IWOTH ? 00002 : 0)
713 | (m & S_IXOTH ? 00001 : 0))));
715 break;
717 case 'n': /* number of links */
718 fprintf (fp, segment->text,
719 human_readable ((uintmax_t) stat_buf->st_nlink,
720 hbuf,
721 human_ceiling,
722 1, 1));
723 break;
724 case 'p': /* pathname */
725 fprintf (fp, segment->text, pathname);
726 break;
727 case 'P': /* pathname with ARGV element stripped */
728 if (state.curdepth > 0)
730 cp = pathname + state.path_length;
731 if (*cp == '/')
732 /* Move past the slash between the ARGV element
733 and the rest of the pathname. But if the ARGV element
734 ends in a slash, we didn't add another, so we've
735 already skipped past it. */
736 cp++;
738 else
739 cp = "";
740 fprintf (fp, segment->text, cp);
741 break;
742 case 's': /* size in bytes */
743 fprintf (fp, segment->text,
744 human_readable ((uintmax_t) stat_buf->st_size,
745 hbuf, human_ceiling, 1, 1));
746 break;
747 case 't': /* mtime in `ctime' format */
748 fprintf (fp, segment->text, ctime_format (stat_buf->st_mtime));
749 break;
750 case 'u': /* user name */
752 struct passwd *p;
754 p = getpwuid (stat_buf->st_uid);
755 if (p)
757 segment->text[segment->text_len] = 's';
758 fprintf (fp, segment->text, p->pw_name);
759 break;
761 /* else fallthru */
764 case 'U': /* UID number */
765 fprintf (fp, segment->text,
766 human_readable ((uintmax_t) stat_buf->st_uid, hbuf,
767 human_ceiling, 1, 1));
768 break;
770 /* type of filesystem entry like `ls -l`: (d,-,l,s,p,b,c,n) n=nonexistent(symlink) */
771 case 'Y': /* in case of symlink */
773 #ifdef S_ISLNK
774 if (S_ISLNK (stat_buf->st_mode))
776 struct stat sbuf;
777 int (*ystat) ();
778 ystat = options.xstat == lstat ? stat : lstat;
779 if ((*ystat) (state.rel_pathname, &sbuf) != 0)
781 if ( errno == ENOENT ) {
782 fprintf (fp, segment->text, "N");
783 break;
785 if ( errno == ELOOP ) {
786 fprintf (fp, segment->text, "L");
787 break;
789 error (0, errno, "%s", pathname);
790 /* exit_status = 1;
791 return (false); */
793 stat_buf->st_mode = sbuf.st_mode;
795 #endif /* S_ISLNK */
797 /* FALLTHROUGH */
798 case 'y':
800 mode_t m = stat_buf->st_mode & S_IFMT;
802 fprintf (fp, segment->text,
803 ( m == S_IFSOCK ? "s" :
804 m == S_IFLNK ? "l" :
805 m == S_IFREG ? "f" :
806 m == S_IFBLK ? "b" :
807 m == S_IFDIR ? "d" :
808 m == S_IFCHR ? "c" :
809 #ifdef S_IFDOOR
810 m == S_IFDOOR ? "D" :
811 #endif
812 m == S_IFIFO ? "p" : "U" ) );
815 break;
818 return (true);
821 boolean
822 pred_fstype (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
824 (void) pathname;
826 if (strcmp (filesystem_type (stat_buf), pred_ptr->args.str) == 0)
827 return true;
828 else
829 return false;
832 boolean
833 pred_gid (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
835 (void) pathname;
837 switch (pred_ptr->args.info.kind)
839 case COMP_GT:
840 if (stat_buf->st_gid > pred_ptr->args.info.l_val)
841 return (true);
842 break;
843 case COMP_LT:
844 if (stat_buf->st_gid < pred_ptr->args.info.l_val)
845 return (true);
846 break;
847 case COMP_EQ:
848 if (stat_buf->st_gid == pred_ptr->args.info.l_val)
849 return (true);
850 break;
852 return (false);
855 boolean
856 pred_group (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
858 (void) pathname;
860 if (pred_ptr->args.gid == stat_buf->st_gid)
861 return (true);
862 else
863 return (false);
866 boolean
867 pred_ilname (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
869 return insert_lname (pathname, stat_buf, pred_ptr, true);
872 boolean
873 pred_iname (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
875 const char *base;
877 (void) stat_buf;
879 /* FNM_PERIOD is not used here because POSIX requires that it not be.
880 * See http://standards.ieee.org/reading/ieee/interp/1003-2-92_int/pasc-1003.2-126.html
882 base = base_name (pathname);
883 if (fnmatch (pred_ptr->args.str, base, FNM_CASEFOLD) == 0)
884 return (true);
885 return (false);
888 boolean
889 pred_inum (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
891 (void) pathname;
893 switch (pred_ptr->args.info.kind)
895 case COMP_GT:
896 if (stat_buf->st_ino > pred_ptr->args.info.l_val)
897 return (true);
898 break;
899 case COMP_LT:
900 if (stat_buf->st_ino < pred_ptr->args.info.l_val)
901 return (true);
902 break;
903 case COMP_EQ:
904 if (stat_buf->st_ino == pred_ptr->args.info.l_val)
905 return (true);
906 break;
908 return (false);
911 boolean
912 pred_ipath (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
914 (void) stat_buf;
916 if (fnmatch (pred_ptr->args.str, pathname, FNM_CASEFOLD) == 0)
917 return (true);
918 return (false);
921 boolean
922 pred_links (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
924 (void) pathname;
926 switch (pred_ptr->args.info.kind)
928 case COMP_GT:
929 if (stat_buf->st_nlink > pred_ptr->args.info.l_val)
930 return (true);
931 break;
932 case COMP_LT:
933 if (stat_buf->st_nlink < pred_ptr->args.info.l_val)
934 return (true);
935 break;
936 case COMP_EQ:
937 if (stat_buf->st_nlink == pred_ptr->args.info.l_val)
938 return (true);
939 break;
941 return (false);
944 boolean
945 pred_lname (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
947 return insert_lname (pathname, stat_buf, pred_ptr, false);
950 static boolean
951 insert_lname (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr, boolean ignore_case)
953 boolean ret = false;
954 #ifdef S_ISLNK
955 if (S_ISLNK (stat_buf->st_mode))
957 char *linkname = get_link_name (pathname, state.rel_pathname);
958 if (linkname)
960 if (fnmatch (pred_ptr->args.str, linkname,
961 ignore_case ? FNM_CASEFOLD : 0) == 0)
962 ret = true;
963 free (linkname);
966 #endif /* S_ISLNK */
967 return (ret);
970 boolean
971 pred_ls (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
973 (void) pred_ptr;
975 list_file (pathname, state.rel_pathname, stat_buf, options.start_time,
976 options.output_block_size, stdout);
977 return (true);
980 boolean
981 pred_mmin (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
983 (void) &pathname;
984 return pred_timewindow(stat_buf->st_mtime, pred_ptr, 60);
987 boolean
988 pred_mtime (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
990 (void) pathname;
991 return pred_timewindow(stat_buf->st_mtime, pred_ptr, DAYSECS);
994 boolean
995 pred_name (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
997 const char *base;
999 (void) stat_buf;
1000 base = base_name (pathname);
1002 /* FNM_PERIOD is not used here because POSIX requires that it not be.
1003 * See http://standards.ieee.org/reading/ieee/interp/1003-2-92_int/pasc-1003.2-126.html
1005 if (fnmatch (pred_ptr->args.str, base, 0) == 0)
1006 return (true);
1007 return (false);
1010 boolean
1011 pred_negate (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1013 /* Check whether we need a stat here. */
1014 if (pred_ptr->need_stat)
1016 if (!state.have_stat && (*options.xstat) (state.rel_pathname, stat_buf) != 0)
1018 error (0, errno, "%s", pathname);
1019 state.exit_status = 1;
1020 return false;
1022 state.have_stat = true;
1024 return (!(*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
1025 pred_ptr->pred_right));
1028 boolean
1029 pred_newer (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1031 (void) pathname;
1033 if (stat_buf->st_mtime > pred_ptr->args.time)
1034 return (true);
1035 return (false);
1038 boolean
1039 pred_nogroup (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1041 (void) pathname;
1042 (void) pred_ptr;
1044 #ifdef CACHE_IDS
1045 extern char *gid_unused;
1047 return gid_unused[(unsigned) stat_buf->st_gid];
1048 #else
1049 return getgrgid (stat_buf->st_gid) == NULL;
1050 #endif
1053 boolean
1054 pred_nouser (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1056 #ifdef CACHE_IDS
1057 extern char *uid_unused;
1058 #endif
1060 (void) pathname;
1061 (void) pred_ptr;
1063 #ifdef CACHE_IDS
1064 return uid_unused[(unsigned) stat_buf->st_uid];
1065 #else
1066 return getpwuid (stat_buf->st_uid) == NULL;
1067 #endif
1070 boolean
1071 pred_ok (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1073 fflush (stdout);
1074 /* The draft open standard requires that, in the POSIX locale,
1075 the last non-blank character of this prompt be '?'.
1076 The exact format is not specified.
1077 This standard does not have requirements for locales other than POSIX
1079 fprintf (stderr, _("< %s ... %s > ? "),
1080 pred_ptr->args.exec_vec.vec[0], pathname);
1081 fflush (stderr);
1082 if (yesno ())
1083 return pred_exec (pathname, stat_buf, pred_ptr);
1084 else
1085 return (false);
1088 boolean
1089 pred_open (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1091 (void) pathname;
1092 (void) stat_buf;
1093 (void) pred_ptr;
1094 return true;
1097 boolean
1098 pred_or (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1100 if (pred_ptr->pred_left == NULL
1101 || !(*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
1102 pred_ptr->pred_left))
1104 /* Check whether we need a stat here. */
1105 if (pred_ptr->need_stat)
1107 if (!state.have_stat && (*options.xstat) (state.rel_pathname, stat_buf) != 0)
1109 error (0, errno, "%s", pathname);
1110 state.exit_status = 1;
1111 return false;
1113 state.have_stat = true;
1115 return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
1116 pred_ptr->pred_right));
1118 else
1119 return true;
1122 boolean
1123 pred_path (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1125 (void) stat_buf;
1126 if (fnmatch (pred_ptr->args.str, pathname, 0) == 0)
1127 return (true);
1128 return (false);
1131 boolean
1132 pred_perm (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1134 (void) pathname;
1135 switch (pred_ptr->args.perm.kind)
1137 case PERM_AT_LEAST:
1138 return (stat_buf->st_mode & pred_ptr->args.perm.val) == pred_ptr->args.perm.val;
1139 break;
1141 case PERM_ANY:
1142 return (stat_buf->st_mode & pred_ptr->args.perm.val) != 0;
1143 break;
1145 case PERM_EXACT:
1146 return (stat_buf->st_mode & MODE_ALL) == pred_ptr->args.perm.val;
1147 break;
1149 default:
1150 abort ();
1151 break;
1155 boolean
1156 pred_print (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1158 (void) stat_buf;
1159 (void) pred_ptr;
1160 puts (pathname);
1161 return true;
1164 boolean
1165 pred_print0 (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1167 (void) stat_buf;
1168 (void) pred_ptr;
1169 fputs (pathname, stdout);
1170 putc (0, stdout);
1171 return (true);
1174 boolean
1175 pred_prune (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1177 (void) pathname;
1178 (void) stat_buf;
1179 (void) pred_ptr;
1180 state.stop_at_current_level = true;
1181 return (options.do_dir_first); /* This is what SunOS find seems to do. */
1184 boolean
1185 pred_quit (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1187 (void) pathname;
1188 (void) stat_buf;
1189 (void) pred_ptr;
1190 exit(0);
1193 boolean
1194 pred_regex (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1196 int len = strlen (pathname);
1197 (void) stat_buf;
1198 if (re_match (pred_ptr->args.regex, pathname, len, 0,
1199 (struct re_registers *) NULL) == len)
1200 return (true);
1201 return (false);
1204 boolean
1205 pred_size (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1207 uintmax_t f_val;
1209 (void) pathname;
1210 f_val = ((stat_buf->st_size / pred_ptr->args.size.blocksize)
1211 + (stat_buf->st_size % pred_ptr->args.size.blocksize != 0));
1212 switch (pred_ptr->args.size.kind)
1214 case COMP_GT:
1215 if (f_val > pred_ptr->args.size.size)
1216 return (true);
1217 break;
1218 case COMP_LT:
1219 if (f_val < pred_ptr->args.size.size)
1220 return (true);
1221 break;
1222 case COMP_EQ:
1223 if (f_val == pred_ptr->args.size.size)
1224 return (true);
1225 break;
1227 return (false);
1230 boolean
1231 pred_samefile (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1233 /* Potential optimisation: because of the loop protection, we
1234 * always know the device of the current directory, hence the
1235 * device number of the current filesystem. If -L is not in
1236 * effect, and the device number of the file we're looking for
1237 * is not the same as the device number of the current directory,
1238 * this predicate cannot return true. Hence there would be no
1239 * need to stat the file.
1241 return stat_buf->st_ino == pred_ptr->args.fileid.ino
1242 && stat_buf->st_dev == pred_ptr->args.fileid.dev;
1245 boolean
1246 pred_true (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1248 (void) pathname;
1249 (void) stat_buf;
1250 (void) pred_ptr;
1251 return true;
1254 boolean
1255 pred_type (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1257 mode_t mode = stat_buf->st_mode;
1258 mode_t type = pred_ptr->args.type;
1260 (void) pathname;
1262 #ifndef S_IFMT
1263 /* POSIX system; check `mode' the slow way. */
1264 if ((S_ISBLK (mode) && type == S_IFBLK)
1265 || (S_ISCHR (mode) && type == S_IFCHR)
1266 || (S_ISDIR (mode) && type == S_IFDIR)
1267 || (S_ISREG (mode) && type == S_IFREG)
1268 #ifdef S_IFLNK
1269 || (S_ISLNK (mode) && type == S_IFLNK)
1270 #endif
1271 #ifdef S_IFIFO
1272 || (S_ISFIFO (mode) && type == S_IFIFO)
1273 #endif
1274 #ifdef S_IFSOCK
1275 || (S_ISSOCK (mode) && type == S_IFSOCK)
1276 #endif
1277 #ifdef S_IFDOOR
1278 || (S_ISDOOR (mode) && type == S_IFDOOR)
1279 #endif
1281 #else /* S_IFMT */
1282 /* Unix system; check `mode' the fast way. */
1283 if ((mode & S_IFMT) == type)
1284 #endif /* S_IFMT */
1285 return (true);
1286 else
1287 return (false);
1290 boolean
1291 pred_uid (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1293 (void) pathname;
1294 switch (pred_ptr->args.info.kind)
1296 case COMP_GT:
1297 if (stat_buf->st_uid > pred_ptr->args.info.l_val)
1298 return (true);
1299 break;
1300 case COMP_LT:
1301 if (stat_buf->st_uid < pred_ptr->args.info.l_val)
1302 return (true);
1303 break;
1304 case COMP_EQ:
1305 if (stat_buf->st_uid == pred_ptr->args.info.l_val)
1306 return (true);
1307 break;
1309 return (false);
1312 boolean
1313 pred_used (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1315 time_t delta;
1317 (void) pathname;
1318 delta = stat_buf->st_atime - stat_buf->st_ctime; /* Use difftime? */
1319 return pred_timewindow(delta, pred_ptr, DAYSECS);
1322 boolean
1323 pred_user (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1325 (void) pathname;
1326 if (pred_ptr->args.uid == stat_buf->st_uid)
1327 return (true);
1328 else
1329 return (false);
1332 boolean
1333 pred_xtype (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1335 struct stat sbuf; /* local copy, not stat_buf because we're using a different stat method */
1336 int (*ystat) (const char*, struct stat *p);
1338 switch (options.symlink_handling)
1340 case SYMLINK_ALWAYS_DEREF:
1341 ystat = optionl_stat;
1342 case SYMLINK_DEREF_ARGSONLY:
1343 case SYMLINK_NEVER_DEREF:
1344 ystat = optionp_stat;
1347 if ((*ystat) (state.rel_pathname, &sbuf) != 0)
1349 if (ystat == optionl_stat && errno == ENOENT)
1351 /* If we failed to follow the symlink,
1352 * fall back on looking at the symlink itself.
1354 /* Mimic behavior of ls -lL. */
1355 return (pred_type (pathname, stat_buf, pred_ptr));
1357 else
1359 error (0, errno, "%s", pathname);
1360 state.exit_status = 1;
1362 return false;
1364 /* Now that we have our stat() information, query it in the same
1365 * way that -type does.
1367 return (pred_type (pathname, &sbuf, pred_ptr));
1370 /* 1) fork to get a child; parent remembers the child pid
1371 2) child execs the command requested
1372 3) parent waits for child; checks for proper pid of child
1374 Possible returns:
1376 ret errno status(h) status(l)
1378 pid x signal# 0177 stopped
1379 pid x exit arg 0 term by _exit
1380 pid x 0 signal # term by signal
1381 -1 EINTR parent got signal
1382 -1 other some other kind of error
1384 Return true only if the pid matches, status(l) is
1385 zero, and the exit arg (status high) is 0.
1386 Otherwise return false, possibly printing an error message. */
1388 static boolean
1389 launch (struct predicate *pred_ptr)
1391 int status;
1392 pid_t child_pid;
1393 struct exec_val *execp; /* Pointer for efficiency. */
1394 static int first_time = 1;
1396 execp = &pred_ptr->args.exec_vec;
1398 /* Make sure output of command doesn't get mixed with find output. */
1399 fflush (stdout);
1400 fflush (stderr);
1402 /* Make sure to listen for the kids. */
1403 if (first_time)
1405 first_time = 0;
1406 signal (SIGCHLD, SIG_DFL);
1409 child_pid = fork ();
1410 if (child_pid == -1)
1411 error (1, errno, _("cannot fork"));
1412 if (child_pid == 0)
1414 /* We be the child. */
1415 if (starting_desc < 0
1416 ? chdir (starting_dir) != 0
1417 : fchdir (starting_desc) != 0)
1419 error (0, errno, "%s", starting_dir);
1420 _exit (1);
1422 execvp (execp->vec[0], execp->vec);
1423 error (0, errno, "%s", execp->vec[0]);
1424 _exit (1);
1428 while (waitpid (child_pid, &status, 0) == (pid_t) -1)
1429 if (errno != EINTR)
1431 error (0, errno, _("error waiting for %s"), execp->vec[0]);
1432 state.exit_status = 1;
1433 return false;
1435 if (WIFSIGNALED (status))
1437 error (0, 0, _("%s terminated by signal %d"),
1438 execp->vec[0], WTERMSIG (status));
1439 state.exit_status = 1;
1440 return (false);
1442 return (!WEXITSTATUS (status));
1445 /* Return a static string formatting the time WHEN according to the
1446 strftime format character KIND. */
1448 static char *
1449 format_date (time_t when, int kind)
1451 static char buf[MAX (LONGEST_HUMAN_READABLE + 2, 64)];
1452 struct tm *tm;
1453 char fmt[6];
1455 fmt[0] = '%';
1456 fmt[1] = kind;
1457 fmt[2] = '\0';
1458 if (kind == '+')
1459 strcpy (fmt, "%F+%T");
1461 if (kind != '@'
1462 && (tm = localtime (&when))
1463 && strftime (buf, sizeof buf, fmt, tm))
1464 return buf;
1465 else
1467 uintmax_t w = when;
1468 char *p = human_readable (when < 0 ? -w : w, buf + 1,
1469 human_ceiling, 1, 1);
1470 if (when < 0)
1471 *--p = '-';
1472 return p;
1476 static char *
1477 ctime_format (when)
1478 time_t when;
1480 char *r = ctime (&when);
1481 if (!r)
1483 /* The time cannot be represented as a struct tm.
1484 Output it as an integer. */
1485 return format_date (when, '@');
1487 else
1489 /* Remove the trailing newline from the ctime output,
1490 being careful not to assume that the output is fixed-width. */
1491 *strchr (r, '\n') = '\0';
1492 return r;
1496 #ifdef DEBUG
1497 /* Return a pointer to the string representation of
1498 the predicate function PRED_FUNC. */
1500 char *
1501 find_pred_name (pred_func)
1502 PFB pred_func;
1504 int i;
1506 for (i = 0; pred_table[i].pred_func != 0; i++)
1507 if (pred_table[i].pred_func == pred_func)
1508 break;
1509 return (pred_table[i].pred_name);
1512 static char *
1513 type_name (type)
1514 short type;
1516 int i;
1518 for (i = 0; type_table[i].type != (short) -1; i++)
1519 if (type_table[i].type == type)
1520 break;
1521 return (type_table[i].type_name);
1524 static char *
1525 prec_name (prec)
1526 short prec;
1528 int i;
1530 for (i = 0; prec_table[i].prec != (short) -1; i++)
1531 if (prec_table[i].prec == prec)
1532 break;
1533 return (prec_table[i].prec_name);
1536 /* Walk the expression tree NODE to stdout.
1537 INDENT is the number of levels to indent the left margin. */
1539 void
1540 print_tree (FILE *fp, struct predicate *node, int indent)
1542 int i;
1544 if (node == NULL)
1545 return;
1546 for (i = 0; i < indent; i++)
1547 fprintf (fp, " ");
1548 fprintf (fp, "pred = %s type = %s prec = %s addr = %p\n",
1549 find_pred_name (node->pred_func),
1550 type_name (node->p_type), prec_name (node->p_prec), node);
1551 for (i = 0; i < indent; i++)
1552 fprintf (fp, " ");
1553 fprintf (fp, _("left:\n"));
1554 print_tree (fp, node->pred_left, indent + 1);
1555 for (i = 0; i < indent; i++)
1556 fprintf (fp, " ");
1557 fprintf (fp, _("right:\n"));
1558 print_tree (fp, node->pred_right, indent + 1);
1561 /* Copy STR into BUF and trim blanks from the end of BUF.
1562 Return BUF. */
1564 static char *
1565 blank_rtrim (str, buf)
1566 char *str;
1567 char *buf;
1569 int i;
1571 if (str == NULL)
1572 return (NULL);
1573 strcpy (buf, str);
1574 i = strlen (buf) - 1;
1575 while ((i >= 0) && ((buf[i] == ' ') || buf[i] == '\t'))
1576 i--;
1577 buf[++i] = '\0';
1578 return (buf);
1581 /* Print out the predicate list starting at NODE. */
1583 void
1584 print_list (FILE *fp, struct predicate *node)
1586 struct predicate *cur;
1587 char name[256];
1589 cur = node;
1590 while (cur != NULL)
1592 fprintf (fp, "%s ", blank_rtrim (find_pred_name (cur->pred_func), name));
1593 cur = cur->pred_next;
1595 fprintf (fp, "\n");
1599 /* Print out the predicate list starting at NODE. */
1602 static void
1603 print_parenthesised(FILE *fp, struct predicate *node)
1605 int parens = 0;
1607 if (node)
1609 if ( ( (node->pred_func == pred_or)
1610 || (node->pred_func == pred_and) )
1611 && node->pred_left == NULL)
1613 /* We print "<nothing> or X" as just "X"
1614 * We print "<nothing> and X" as just "X"
1616 print_parenthesised(fp, node->pred_right);
1618 else
1620 if (node->pred_left || node->pred_right)
1621 parens = 1;
1623 if (parens)
1624 fprintf(fp, "%s", " ( ");
1625 print_optlist(fp, node);
1626 if (parens)
1627 fprintf(fp, "%s", " ) ");
1632 void
1633 print_optlist (FILE *fp, struct predicate *p)
1635 char name[256];
1637 if (p)
1639 print_parenthesised(fp, p->pred_left);
1640 fprintf (fp,
1641 "%s%s ",
1642 p->need_stat ? _("[stat called here] ") : "",
1643 blank_rtrim (find_pred_name (p->pred_func), name));
1644 print_parenthesised(fp, p->pred_right);
1648 #endif /* DEBUG */