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)
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,
34 # define _(Text) gettext (Text)
39 # define N_(String) gettext_noop (String)
41 # define N_(String) (String)
44 #if !defined(SIGCHLD) && defined(SIGCLD)
45 #define SIGCHLD SIGCLD
50 # define NAMLEN(dirent) strlen((dirent)->d_name)
52 # define dirent direct
53 # define NAMLEN(dirent) (dirent)->d_namlen
55 # include <sys/ndir.h>
66 /* Fake a return value. */
67 #define CLOSEDIR(d) (closedir (d), 0)
69 #define CLOSEDIR(d) closedir (d)
75 /* Get or fake the disk device blocksize.
76 Usually defined by sys/param.h (if at all). */
79 # define DEV_BSIZE BSIZE
81 # define DEV_BSIZE 4096
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
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 */
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)
121 # endif /* not AIX PS/2 */
123 #endif /* HAVE_STRUCT_STAT_ST_BLOCKS */
126 # define ST_NBLOCKS(statbuf) \
127 (S_ISREG ((statbuf).st_mode) \
128 || S_ISDIR ((statbuf).st_mode) \
129 ? (statbuf).st_blocks : 0)
132 #ifndef ST_NBLOCKSIZE
133 # define ST_NBLOCKSIZE 512
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
));
151 struct pred_assoc pred_table
[] =
153 {pred_amin
, "amin "},
155 {pred_anewer
, "anewer "},
156 {pred_atime
, "atime "},
158 {pred_amin
, "cmin "},
159 {pred_cnewer
, "cnewer "},
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 "},
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 "},
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 "},
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 "},
198 {pred_used
, "used "},
199 {pred_user
, "user "},
200 {pred_xtype
, "xtype "},
210 struct op_assoc type_table
[] =
213 {PRIMARY_TYPE
, "primary "},
216 {OPEN_PAREN
, "open_paren "},
217 {CLOSE_PAREN
, "close_paren "},
227 struct prec_assoc prec_table
[] =
230 {COMMA_PREC
, "comma "},
233 {NEGATE_PREC
, "negate "},
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. */
248 pred_amin (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
250 switch (pred_ptr
->args
.info
.kind
)
253 if (stat_buf
->st_atime
> (time_t) pred_ptr
->args
.info
.l_val
)
257 if (stat_buf
->st_atime
< (time_t) pred_ptr
->args
.info
.l_val
)
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))
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
);
287 return ((*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
288 pred_ptr
->pred_right
));
295 pred_anewer (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
297 if (stat_buf
->st_atime
> pred_ptr
->args
.time
)
303 pred_atime (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
305 switch (pred_ptr
->args
.info
.kind
)
308 if (stat_buf
->st_atime
> (time_t) pred_ptr
->args
.info
.l_val
)
312 if (stat_buf
->st_atime
< (time_t) pred_ptr
->args
.info
.l_val
)
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
326 pred_close (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
332 pred_cmin (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
334 switch (pred_ptr
->args
.info
.kind
)
337 if (stat_buf
->st_ctime
> (time_t) pred_ptr
->args
.info
.l_val
)
341 if (stat_buf
->st_ctime
< (time_t) pred_ptr
->args
.info
.l_val
)
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))
354 pred_cnewer (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
356 if (stat_buf
->st_ctime
> pred_ptr
->args
.time
)
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
);
378 return ((*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
379 pred_ptr
->pred_right
));
383 pred_ctime (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
385 switch (pred_ptr
->args
.info
.kind
)
388 if (stat_buf
->st_ctime
> (time_t) pred_ptr
->args
.info
.l_val
)
392 if (stat_buf
->st_ctime
< (time_t) pred_ptr
->args
.info
.l_val
)
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
406 pred_empty (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
408 if (S_ISDIR (stat_buf
->st_mode
))
412 boolean empty
= true;
415 d
= opendir (rel_pathname
);
418 error (0, errno
, "%s", pathname
);
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')))
434 error (0, errno
, "%s", pathname
);
440 else if (S_ISREG (stat_buf
->st_mode
))
441 return (stat_buf
->st_size
== 0);
447 pred_exec (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
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
;
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
);
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
]);
485 pred_false (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
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
);
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
);
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
);
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
;
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. */
529 switch (segment
->kind
& 0xff)
532 t
= stat_buf
->st_atime
;
535 t
= stat_buf
->st_ctime
;
538 t
= stat_buf
->st_mtime
;
543 fprintf (fp
, segment
->text
,
544 format_date (t
, (segment
->kind
>> 8) & 0xff));
548 switch (segment
->kind
)
550 case KIND_PLAIN
: /* Plain text string (no % conversion). */
551 fwrite (segment
->text
, 1, segment
->text_len
, fp
);
553 case KIND_STOP
: /* Terminate argument and flush output. */
554 fwrite (segment
->text
, 1, segment
->text_len
, fp
);
557 case 'a': /* atime in `ctime' format. */
558 fprintf (fp
, segment
->text
, ctime_format (stat_buf
->st_atime
));
560 case 'b': /* size in 512-byte blocks */
561 fprintf (fp
, segment
->text
,
562 human_readable ((uintmax_t) ST_NBLOCKS (*stat_buf
),
564 ST_NBLOCKSIZE
, 512));
566 case 'c': /* ctime in `ctime' format */
567 fprintf (fp
, segment
->text
, ctime_format (stat_buf
->st_ctime
));
569 case 'd': /* depth in search tree */
570 fprintf (fp
, segment
->text
, curdepth
);
572 case 'f': /* basename of path */
573 fprintf (fp
, segment
->text
, base_name (pathname
));
575 case 'F': /* filesystem type */
576 fprintf (fp
, segment
->text
,
577 filesystem_type (pathname
, rel_pathname
, stat_buf
));
579 case 'g': /* group name */
583 g
= getgrgid (stat_buf
->st_gid
);
586 segment
->text
[segment
->text_len
] = 's';
587 fprintf (fp
, segment
->text
, g
->gr_name
);
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));
597 case 'h': /* leading directories part of path */
601 cp
= strrchr (pathname
, '/');
602 if (cp
== NULL
) /* No leading directories. */
606 fprintf (fp
, segment
->text
, pathname
);
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
;
619 case 'i': /* inode number */
620 fprintf (fp
, segment
->text
,
621 human_readable ((uintmax_t) stat_buf
->st_ino
, hbuf
,
625 case 'k': /* size in 1K blocks */
626 fprintf (fp
, segment
->text
,
627 human_readable ((uintmax_t) ST_NBLOCKS (*stat_buf
),
629 ST_NBLOCKSIZE
, 1024, human_ceiling
));
631 case 'l': /* object of symlink */
636 if (S_ISLNK (stat_buf
->st_mode
))
638 linkname
= get_link_name (pathname
, rel_pathname
);
644 fprintf (fp
, segment
->text
, linkname
);
648 fprintf (fp
, segment
->text
, "");
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
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))));
681 case 'n': /* number of links */
682 fprintf (fp
, segment
->text
,
683 human_readable ((uintmax_t) stat_buf
->st_nlink
,
688 case 'p': /* pathname */
689 fprintf (fp
, segment
->text
, pathname
);
691 case 'P': /* pathname with ARGV element stripped */
694 cp
= pathname
+ path_length
;
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. */
704 fprintf (fp
, segment
->text
, cp
);
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));
711 case 't': /* mtime in `ctime' format */
712 fprintf (fp
, segment
->text
, ctime_format (stat_buf
->st_mtime
));
714 case 'u': /* user name */
718 p
= getpwuid (stat_buf
->st_uid
);
721 segment
->text
[segment
->text_len
] = 's';
722 fprintf (fp
, segment
->text
, p
->pw_name
);
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));
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)
747 pred_gid (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
749 switch (pred_ptr
->args
.info
.kind
)
752 if (stat_buf
->st_gid
> pred_ptr
->args
.info
.l_val
)
756 if (stat_buf
->st_gid
< pred_ptr
->args
.info
.l_val
)
760 if (stat_buf
->st_gid
== pred_ptr
->args
.info
.l_val
)
768 pred_group (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
770 if (pred_ptr
->args
.gid
== stat_buf
->st_gid
)
777 pred_ilname (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
779 return insert_lname (pathname
, stat_buf
, pred_ptr
, true);
783 pred_iname (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
787 base
= base_name (pathname
);
788 if (fnmatch (pred_ptr
->args
.str
, base
, FNM_PERIOD
| FNM_CASEFOLD
) == 0)
794 pred_inum (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
796 switch (pred_ptr
->args
.info
.kind
)
799 if (stat_buf
->st_ino
> pred_ptr
->args
.info
.l_val
)
803 if (stat_buf
->st_ino
< pred_ptr
->args
.info
.l_val
)
807 if (stat_buf
->st_ino
== pred_ptr
->args
.info
.l_val
)
815 pred_ipath (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
817 if (fnmatch (pred_ptr
->args
.str
, pathname
, FNM_CASEFOLD
) == 0)
823 pred_links (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
825 switch (pred_ptr
->args
.info
.kind
)
828 if (stat_buf
->st_nlink
> pred_ptr
->args
.info
.l_val
)
832 if (stat_buf
->st_nlink
< pred_ptr
->args
.info
.l_val
)
836 if (stat_buf
->st_nlink
== pred_ptr
->args
.info
.l_val
)
844 pred_lname (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
846 return insert_lname (pathname
, stat_buf
, pred_ptr
, false);
850 insert_lname (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
, boolean ignore_case
)
854 if (S_ISLNK (stat_buf
->st_mode
))
856 char *linkname
= get_link_name (pathname
, rel_pathname
);
859 if (fnmatch (pred_ptr
->args
.str
, linkname
,
860 ignore_case
? FNM_CASEFOLD
: 0) == 0)
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
);
878 pred_mmin (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
880 switch (pred_ptr
->args
.info
.kind
)
883 if (stat_buf
->st_mtime
> (time_t) pred_ptr
->args
.info
.l_val
)
887 if (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
)
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))
900 pred_mtime (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
902 switch (pred_ptr
->args
.info
.kind
)
905 if (stat_buf
->st_mtime
> (time_t) pred_ptr
->args
.info
.l_val
)
909 if (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
)
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
923 pred_name (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
927 base
= base_name (pathname
);
928 if (fnmatch (pred_ptr
->args
.str
, base
, FNM_PERIOD
) == 0)
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
);
947 return (!(*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
948 pred_ptr
->pred_right
));
952 pred_newer (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
954 if (stat_buf
->st_mtime
> pred_ptr
->args
.time
)
960 pred_nogroup (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
963 extern char *gid_unused
;
965 return gid_unused
[(unsigned) stat_buf
->st_gid
];
967 return getgrgid (stat_buf
->st_gid
) == NULL
;
972 pred_nouser (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
975 extern char *uid_unused
;
977 return uid_unused
[(unsigned) stat_buf
->st_uid
];
979 return getpwuid (stat_buf
->st_uid
) == NULL
;
984 pred_ok (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
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
);
996 return pred_exec (pathname
, stat_buf
, pred_ptr
);
1002 pred_open (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
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
);
1025 return ((*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
1026 pred_ptr
->pred_right
));
1033 pred_path (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1035 if (fnmatch (pred_ptr
->args
.str
, pathname
, 0) == 0)
1041 pred_perm (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1043 switch (pred_ptr
->args
.perm
.kind
)
1046 return (stat_buf
->st_mode
& pred_ptr
->args
.perm
.val
) == pred_ptr
->args
.perm
.val
;
1050 return (stat_buf
->st_mode
& pred_ptr
->args
.perm
.val
) != 0;
1054 return (stat_buf
->st_mode
& MODE_ALL
) == pred_ptr
->args
.perm
.val
;
1064 pred_print (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1071 pred_print0 (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1073 fputs (pathname
, stdout
);
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. */
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
)
1096 pred_size (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
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
)
1105 if (f_val
> pred_ptr
->args
.size
.size
)
1109 if (f_val
< pred_ptr
->args
.size
.size
)
1113 if (f_val
== pred_ptr
->args
.size
.size
)
1121 pred_true (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
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
;
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
)
1139 || (S_ISLNK (mode
) && type
== S_IFLNK
)
1142 || (S_ISFIFO (mode
) && type
== S_IFIFO
)
1145 || (S_ISSOCK (mode
) && type
== S_IFSOCK
)
1148 || (S_ISDOOR (mode
) && type
== S_IFDOOR
)
1152 /* Unix system; check `mode' the fast way. */
1153 if ((mode
& S_IFMT
) == type
)
1161 pred_uid (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1163 switch (pred_ptr
->args
.info
.kind
)
1166 if (stat_buf
->st_uid
> pred_ptr
->args
.info
.l_val
)
1170 if (stat_buf
->st_uid
< pred_ptr
->args
.info
.l_val
)
1174 if (stat_buf
->st_uid
== pred_ptr
->args
.info
.l_val
)
1182 pred_used (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1186 delta
= stat_buf
->st_atime
- stat_buf
->st_ctime
; /* Use difftime? */
1187 switch (pred_ptr
->args
.info
.kind
)
1190 if (delta
> (time_t) pred_ptr
->args
.info
.l_val
)
1194 if (delta
< (time_t) pred_ptr
->args
.info
.l_val
)
1198 if ((delta
>= (time_t) pred_ptr
->args
.info
.l_val
)
1199 && (delta
< (time_t) pred_ptr
->args
.info
.l_val
+ DAYSECS
))
1207 pred_user (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1209 if (pred_ptr
->args
.uid
== stat_buf
->st_uid
)
1216 pred_xtype (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
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
);
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
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. */
1253 launch (struct predicate
*pred_ptr
)
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. */
1266 /* Make sure to listen for the kids. */
1270 signal (SIGCHLD
, SIG_DFL
);
1273 child_pid
= fork ();
1274 if (child_pid
== -1)
1275 error (1, errno
, _("cannot fork"));
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
);
1286 execvp (execp
->vec
[0], execp
->vec
);
1287 error (0, errno
, "%s", execp
->vec
[0]);
1292 while (waitpid (child_pid
, &status
, 0) == (pid_t
) -1)
1295 error (0, errno
, _("error waiting for %s"), execp
->vec
[0]);
1299 if (WIFSIGNALED (status
))
1301 error (0, 0, _("%s terminated by signal %d"),
1302 execp
->vec
[0], WTERMSIG (status
));
1306 return (!WEXITSTATUS (status
));
1309 /* Return a static string formatting the time WHEN according to the
1310 strftime format character KIND. */
1313 format_date (time_t when
, int kind
)
1315 static char buf
[MAX (LONGEST_HUMAN_READABLE
+ 2, 64)];
1324 && (tm
= localtime (&when
))
1325 && strftime (buf
, sizeof buf
, fmt
, tm
))
1330 char *p
= human_readable (when
< 0 ? -w
: w
, buf
+ 1,
1331 human_ceiling
, 1, 1);
1342 char *r
= ctime (&when
);
1345 /* The time cannot be represented as a struct tm.
1346 Output it as an integer. */
1347 return format_date (when
, '@');
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';
1359 /* Return a pointer to the string representation of
1360 the predicate function PRED_FUNC. */
1363 find_pred_name (pred_func
)
1368 for (i
= 0; pred_table
[i
].pred_func
!= 0; i
++)
1369 if (pred_table
[i
].pred_func
== pred_func
)
1371 return (pred_table
[i
].pred_name
);
1380 for (i
= 0; type_table
[i
].type
!= (short) -1; i
++)
1381 if (type_table
[i
].type
== type
)
1383 return (type_table
[i
].type_name
);
1392 for (i
= 0; prec_table
[i
].prec
!= (short) -1; i
++)
1393 if (prec_table
[i
].prec
== prec
)
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. */
1402 print_tree (node
, indent
)
1403 struct predicate
*node
;
1410 for (i
= 0; i
< indent
; i
++)
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
++)
1417 printf (_("left:\n"));
1418 print_tree (node
->pred_left
, indent
+ 1);
1419 for (i
= 0; i
< indent
; i
++)
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.
1429 blank_rtrim (str
, buf
)
1438 i
= strlen (buf
) - 1;
1439 while ((i
>= 0) && ((buf
[i
] == ' ') || buf
[i
] == '\t'))
1445 /* Print out the predicate list starting at NODE. */
1449 struct predicate
*node
;
1451 struct predicate
*cur
;
1457 printf ("%s ", blank_rtrim (find_pred_name (cur
->pred_func
), name
));
1458 cur
= cur
->pred_next
;