1 /* pred.c -- execute the expression tree.
2 Copyright (C) 1990, 91, 92, 93, 94, 2000 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
32 # define _(Text) gettext (Text)
37 # define N_(String) gettext_noop (String)
39 # define N_(String) (String)
42 #if !defined(SIGCHLD) && defined(SIGCLD)
43 #define SIGCHLD SIGCLD
48 # define NAMLEN(dirent) strlen((dirent)->d_name)
50 # define dirent direct
51 # define NAMLEN(dirent) (dirent)->d_namlen
53 # include <sys/ndir.h>
64 /* Fake a return value. */
65 #define CLOSEDIR(d) (closedir (d), 0)
67 #define CLOSEDIR(d) closedir (d)
73 /* Get or fake the disk device blocksize.
74 Usually defined by sys/param.h (if at all). */
77 # define DEV_BSIZE BSIZE
79 # define DEV_BSIZE 4096
81 #endif /* !DEV_BSIZE */
83 /* Extract or fake data from a `struct stat'.
84 ST_BLKSIZE: Preferred I/O blocksize for the file, in bytes.
85 ST_NBLOCKS: Number of blocks in the file, including indirect blocks.
86 ST_NBLOCKSIZE: Size of blocks used when calculating ST_NBLOCKS. */
87 #ifndef HAVE_STRUCT_STAT_ST_BLOCKS
88 # define ST_BLKSIZE(statbuf) DEV_BSIZE
89 # if defined(_POSIX_SOURCE) || !defined(BSIZE) /* fileblocks.c uses BSIZE. */
90 # define ST_NBLOCKS(statbuf) \
91 (S_ISREG ((statbuf).st_mode) \
92 || S_ISDIR ((statbuf).st_mode) \
93 ? (statbuf).st_size / ST_NBLOCKSIZE + ((statbuf).st_size % ST_NBLOCKSIZE != 0) : 0)
94 # else /* !_POSIX_SOURCE && BSIZE */
95 # define ST_NBLOCKS(statbuf) \
96 (S_ISREG ((statbuf).st_mode) \
97 || S_ISDIR ((statbuf).st_mode) \
98 ? st_blocks ((statbuf).st_size) : 0)
99 # endif /* !_POSIX_SOURCE && BSIZE */
100 #else /* HAVE_STRUCT_STAT_ST_BLOCKS */
101 /* Some systems, like Sequents, return st_blksize of 0 on pipes. */
102 # define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \
103 ? (statbuf).st_blksize : DEV_BSIZE)
104 # if defined(hpux) || defined(__hpux__) || defined(__hpux)
105 /* HP-UX counts st_blocks in 1024-byte units.
106 This loses when mixing HP-UX and BSD filesystems with NFS. */
107 # define ST_NBLOCKSIZE 1024
109 # if defined(_AIX) && defined(_I386)
110 /* AIX PS/2 counts st_blocks in 4K units. */
111 # define ST_NBLOCKSIZE (4 * 1024)
112 # else /* not AIX PS/2 */
114 # define ST_NBLOCKS(statbuf) \
115 (S_ISREG ((statbuf).st_mode) \
116 || S_ISDIR ((statbuf).st_mode) \
117 ? (statbuf).st_blocks * ST_BLKSIZE(statbuf)/ST_NBLOCKSIZE : 0)
119 # endif /* not AIX PS/2 */
121 #endif /* HAVE_STRUCT_STAT_ST_BLOCKS */
124 # define ST_NBLOCKS(statbuf) \
125 (S_ISREG ((statbuf).st_mode) \
126 || S_ISDIR ((statbuf).st_mode) \
127 ? (statbuf).st_blocks : 0)
130 #ifndef ST_NBLOCKSIZE
131 # define ST_NBLOCKSIZE 512
135 #define MAX(a, b) ((a) > (b) ? (a) : (b))
137 static boolean insert_lname
PARAMS((char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
, boolean ignore_case
));
138 static boolean launch
PARAMS((struct predicate
*pred_ptr
));
139 static char *format_date
PARAMS((time_t when
, int kind
));
140 static char *ctime_format
PARAMS((time_t when
));
149 struct pred_assoc pred_table
[] =
151 {pred_amin
, "amin "},
153 {pred_anewer
, "anewer "},
154 {pred_atime
, "atime "},
156 {pred_amin
, "cmin "},
157 {pred_cnewer
, "cnewer "},
159 {pred_ctime
, "ctime "},
160 {pred_empty
, "empty "},
161 {pred_exec
, "exec "},
162 {pred_false
, "false "},
163 {pred_fprint
, "fprint "},
164 {pred_fprint0
, "fprint0 "},
165 {pred_fprintf
, "fprintf "},
166 {pred_fstype
, "fstype "},
168 {pred_group
, "group "},
169 {pred_ilname
, "ilname "},
170 {pred_iname
, "iname "},
171 {pred_inum
, "inum "},
172 {pred_ipath
, "ipath "},
173 {pred_links
, "links "},
174 {pred_lname
, "lname "},
176 {pred_amin
, "mmin "},
177 {pred_mtime
, "mtime "},
178 {pred_name
, "name "},
179 {pred_negate
, "not "},
180 {pred_newer
, "newer "},
181 {pred_nogroup
, "nogroup "},
182 {pred_nouser
, "nouser "},
186 {pred_path
, "path "},
187 {pred_perm
, "perm "},
188 {pred_print
, "print "},
189 {pred_print0
, "print0 "},
190 {pred_prune
, "prune "},
191 {pred_regex
, "regex "},
192 {pred_size
, "size "},
193 {pred_true
, "true "},
194 {pred_type
, "type "},
196 {pred_used
, "used "},
197 {pred_user
, "user "},
198 {pred_xtype
, "xtype "},
208 struct op_assoc type_table
[] =
211 {PRIMARY_TYPE
, "primary "},
214 {OPEN_PAREN
, "open_paren "},
215 {CLOSE_PAREN
, "close_paren "},
225 struct prec_assoc prec_table
[] =
228 {COMMA_PREC
, "comma "},
231 {NEGATE_PREC
, "negate "},
237 /* Predicate processing routines.
239 PATHNAME is the full pathname of the file being checked.
240 *STAT_BUF contains information about PATHNAME.
241 *PRED_PTR contains information for applying the predicate.
243 Return true if the file passes this predicate, false if not. */
246 pred_amin (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
248 switch (pred_ptr
->args
.info
.kind
)
251 if (stat_buf
->st_atime
> (time_t) pred_ptr
->args
.info
.l_val
)
255 if (stat_buf
->st_atime
< (time_t) pred_ptr
->args
.info
.l_val
)
259 if ((stat_buf
->st_atime
>= (time_t) pred_ptr
->args
.info
.l_val
)
260 && (stat_buf
->st_atime
< (time_t) pred_ptr
->args
.info
.l_val
+ 60))
268 pred_and (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
270 if (pred_ptr
->pred_left
== NULL
271 || (*pred_ptr
->pred_left
->pred_func
) (pathname
, stat_buf
,
272 pred_ptr
->pred_left
))
274 /* Check whether we need a stat here. */
275 if (pred_ptr
->need_stat
)
277 if (!have_stat
&& (*xstat
) (rel_pathname
, stat_buf
) != 0)
279 error (0, errno
, "%s", pathname
);
285 return ((*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
286 pred_ptr
->pred_right
));
293 pred_anewer (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
295 if (stat_buf
->st_atime
> pred_ptr
->args
.time
)
301 pred_atime (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
303 switch (pred_ptr
->args
.info
.kind
)
306 if (stat_buf
->st_atime
> (time_t) pred_ptr
->args
.info
.l_val
)
310 if (stat_buf
->st_atime
< (time_t) pred_ptr
->args
.info
.l_val
)
314 if ((stat_buf
->st_atime
>= (time_t) pred_ptr
->args
.info
.l_val
)
315 && (stat_buf
->st_atime
< (time_t) pred_ptr
->args
.info
.l_val
324 pred_close (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
330 pred_cmin (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
332 switch (pred_ptr
->args
.info
.kind
)
335 if (stat_buf
->st_ctime
> (time_t) pred_ptr
->args
.info
.l_val
)
339 if (stat_buf
->st_ctime
< (time_t) pred_ptr
->args
.info
.l_val
)
343 if ((stat_buf
->st_ctime
>= (time_t) pred_ptr
->args
.info
.l_val
)
344 && (stat_buf
->st_ctime
< (time_t) pred_ptr
->args
.info
.l_val
+ 60))
352 pred_cnewer (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
354 if (stat_buf
->st_ctime
> pred_ptr
->args
.time
)
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 (!have_stat
&& (*xstat
) (rel_pathname
, stat_buf
) != 0)
370 error (0, errno
, "%s", pathname
);
376 return ((*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
377 pred_ptr
->pred_right
));
381 pred_ctime (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
383 switch (pred_ptr
->args
.info
.kind
)
386 if (stat_buf
->st_ctime
> (time_t) pred_ptr
->args
.info
.l_val
)
390 if (stat_buf
->st_ctime
< (time_t) pred_ptr
->args
.info
.l_val
)
394 if ((stat_buf
->st_ctime
>= (time_t) pred_ptr
->args
.info
.l_val
)
395 && (stat_buf
->st_ctime
< (time_t) pred_ptr
->args
.info
.l_val
404 pred_empty (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
406 if (S_ISDIR (stat_buf
->st_mode
))
410 boolean empty
= true;
413 d
= opendir (rel_pathname
);
416 error (0, errno
, "%s", pathname
);
420 for (dp
= readdir (d
); dp
; dp
= readdir (d
))
422 if (dp
->d_name
[0] != '.'
423 || (dp
->d_name
[1] != '\0'
424 && (dp
->d_name
[1] != '.' || dp
->d_name
[2] != '\0')))
432 error (0, errno
, "%s", pathname
);
438 else if (S_ISREG (stat_buf
->st_mode
))
439 return (stat_buf
->st_size
== 0);
445 pred_exec (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
449 struct exec_val
*execp
; /* Pointer for efficiency. */
451 execp
= &pred_ptr
->args
.exec_vec
;
453 /* Replace "{}" with the real path in each affected arg. */
454 for (path_pos
= 0; execp
->paths
[path_pos
].offset
>= 0; path_pos
++)
456 register char *from
, *to
;
458 i
= execp
->paths
[path_pos
].offset
;
460 xmalloc (strlen (execp
->paths
[path_pos
].origarg
) + 1
461 + (strlen (pathname
) - 2) * execp
->paths
[path_pos
].count
);
462 for (from
= execp
->paths
[path_pos
].origarg
, to
= execp
->vec
[i
]; *from
; )
463 if (from
[0] == '{' && from
[1] == '}')
465 to
= stpcpy (to
, pathname
);
470 *to
= *from
; /* Copy null. */
473 i
= launch (pred_ptr
);
475 /* Free the temporary args. */
476 for (path_pos
= 0; execp
->paths
[path_pos
].offset
>= 0; path_pos
++)
477 free (execp
->vec
[execp
->paths
[path_pos
].offset
]);
483 pred_false (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
489 pred_fls (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
491 list_file (pathname
, rel_pathname
, stat_buf
, start_time
,
492 output_block_size
, pred_ptr
->args
.stream
);
497 pred_fprint (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
499 fputs (pathname
, pred_ptr
->args
.stream
);
500 putc ('\n', pred_ptr
->args
.stream
);
505 pred_fprint0 (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
507 fputs (pathname
, pred_ptr
->args
.stream
);
508 putc (0, pred_ptr
->args
.stream
);
513 pred_fprintf (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
515 FILE *fp
= pred_ptr
->args
.printf_vec
.stream
;
516 struct segment
*segment
;
518 char hbuf
[LONGEST_HUMAN_READABLE
+ 1];
520 for (segment
= pred_ptr
->args
.printf_vec
.segment
; segment
;
521 segment
= segment
->next
)
523 if (segment
->kind
& 0xff00) /* Component of date. */
527 switch (segment
->kind
& 0xff)
530 t
= stat_buf
->st_atime
;
533 t
= stat_buf
->st_ctime
;
536 t
= stat_buf
->st_mtime
;
541 fprintf (fp
, segment
->text
,
542 format_date (t
, (segment
->kind
>> 8) & 0xff));
546 switch (segment
->kind
)
548 case KIND_PLAIN
: /* Plain text string (no % conversion). */
549 fwrite (segment
->text
, 1, segment
->text_len
, fp
);
551 case KIND_STOP
: /* Terminate argument and flush output. */
552 fwrite (segment
->text
, 1, segment
->text_len
, fp
);
555 case 'a': /* atime in `ctime' format. */
556 fprintf (fp
, segment
->text
, ctime_format (stat_buf
->st_atime
));
558 case 'b': /* size in 512-byte blocks */
559 fprintf (fp
, segment
->text
,
560 human_readable ((uintmax_t) ST_NBLOCKS (*stat_buf
),
561 hbuf
, ST_NBLOCKSIZE
, 512));
563 case 'c': /* ctime in `ctime' format */
564 fprintf (fp
, segment
->text
, ctime_format (stat_buf
->st_ctime
));
566 case 'd': /* depth in search tree */
567 fprintf (fp
, segment
->text
, curdepth
);
569 case 'f': /* basename of path */
570 fprintf (fp
, segment
->text
, base_name (pathname
));
572 case 'F': /* filesystem type */
573 fprintf (fp
, segment
->text
,
574 filesystem_type (pathname
, rel_pathname
, stat_buf
));
576 case 'g': /* group name */
580 g
= getgrgid (stat_buf
->st_gid
);
583 segment
->text
[segment
->text_len
] = 's';
584 fprintf (fp
, segment
->text
, g
->gr_name
);
589 case 'G': /* GID number */
590 fprintf (fp
, segment
->text
,
591 human_readable ((uintmax_t) stat_buf
->st_gid
, hbuf
, 1, 1));
593 case 'h': /* leading directories part of path */
597 cp
= strrchr (pathname
, '/');
598 if (cp
== NULL
) /* No leading directories. */
602 fprintf (fp
, segment
->text
, pathname
);
606 case 'H': /* ARGV element file was found under */
608 char cc
= pathname
[path_length
];
610 pathname
[path_length
] = '\0';
611 fprintf (fp
, segment
->text
, pathname
);
612 pathname
[path_length
] = cc
;
615 case 'i': /* inode number */
616 fprintf (fp
, segment
->text
,
617 human_readable ((uintmax_t) stat_buf
->st_ino
, hbuf
, 1, 1));
619 case 'k': /* size in 1K blocks */
620 fprintf (fp
, segment
->text
,
621 human_readable ((uintmax_t) ST_NBLOCKS (*stat_buf
),
622 hbuf
, ST_NBLOCKSIZE
, 1024));
624 case 'l': /* object of symlink */
629 if (S_ISLNK (stat_buf
->st_mode
))
631 linkname
= get_link_name (pathname
, rel_pathname
);
637 fprintf (fp
, segment
->text
, linkname
);
641 fprintf (fp
, segment
->text
, "");
645 case 'm': /* mode as octal number (perms only) */
647 /* Output the mode portably using the traditional numbers,
648 even if the host unwisely uses some other numbering
649 scheme. But help the compiler in the common case where
650 the host uses the traditional numbering scheme. */
651 mode_t m
= stat_buf
->st_mode
;
652 boolean traditional_numbering_scheme
=
653 (S_ISUID
== 04000 && S_ISGID
== 02000 && S_ISVTX
== 01000
654 && S_IRUSR
== 00400 && S_IWUSR
== 00200 && S_IXUSR
== 00100
655 && S_IRGRP
== 00040 && S_IWGRP
== 00020 && S_IXGRP
== 00010
656 && S_IROTH
== 00004 && S_IWOTH
== 00002 && S_IXOTH
== 00001);
657 fprintf (fp
, segment
->text
,
658 (traditional_numbering_scheme
660 : ((m
& S_ISUID
? 04000 : 0)
661 | (m
& S_ISGID
? 02000 : 0)
662 | (m
& S_ISVTX
? 01000 : 0)
663 | (m
& S_IRUSR
? 00400 : 0)
664 | (m
& S_IWUSR
? 00200 : 0)
665 | (m
& S_IXUSR
? 00100 : 0)
666 | (m
& S_IRGRP
? 00040 : 0)
667 | (m
& S_IWGRP
? 00020 : 0)
668 | (m
& S_IXGRP
? 00010 : 0)
669 | (m
& S_IROTH
? 00004 : 0)
670 | (m
& S_IWOTH
? 00002 : 0)
671 | (m
& S_IXOTH
? 00001 : 0))));
674 case 'n': /* number of links */
675 fprintf (fp
, segment
->text
,
676 human_readable ((uintmax_t) stat_buf
->st_nlink
,
679 case 'p': /* pathname */
680 fprintf (fp
, segment
->text
, pathname
);
682 case 'P': /* pathname with ARGV element stripped */
685 cp
= pathname
+ path_length
;
687 /* Move past the slash between the ARGV element
688 and the rest of the pathname. But if the ARGV element
689 ends in a slash, we didn't add another, so we've
690 already skipped past it. */
695 fprintf (fp
, segment
->text
, cp
);
697 case 's': /* size in bytes */
698 fprintf (fp
, segment
->text
,
699 human_readable ((uintmax_t) stat_buf
->st_size
,
702 case 't': /* mtime in `ctime' format */
703 fprintf (fp
, segment
->text
, ctime_format (stat_buf
->st_mtime
));
705 case 'u': /* user name */
709 p
= getpwuid (stat_buf
->st_uid
);
712 segment
->text
[segment
->text_len
] = 's';
713 fprintf (fp
, segment
->text
, p
->pw_name
);
718 case 'U': /* UID number */
719 fprintf (fp
, segment
->text
,
720 human_readable ((uintmax_t) stat_buf
->st_uid
, hbuf
, 1, 1));
728 pred_fstype (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
730 if (strcmp (filesystem_type (pathname
, rel_pathname
, stat_buf
),
731 pred_ptr
->args
.str
) == 0)
737 pred_gid (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
739 switch (pred_ptr
->args
.info
.kind
)
742 if (stat_buf
->st_gid
> pred_ptr
->args
.info
.l_val
)
746 if (stat_buf
->st_gid
< pred_ptr
->args
.info
.l_val
)
750 if (stat_buf
->st_gid
== pred_ptr
->args
.info
.l_val
)
758 pred_group (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
760 if (pred_ptr
->args
.gid
== stat_buf
->st_gid
)
767 pred_ilname (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
769 return insert_lname (pathname
, stat_buf
, pred_ptr
, true);
773 pred_iname (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
777 base
= base_name (pathname
);
778 if (fnmatch (pred_ptr
->args
.str
, base
, FNM_PERIOD
| FNM_CASEFOLD
) == 0)
784 pred_inum (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
786 switch (pred_ptr
->args
.info
.kind
)
789 if (stat_buf
->st_ino
> pred_ptr
->args
.info
.l_val
)
793 if (stat_buf
->st_ino
< pred_ptr
->args
.info
.l_val
)
797 if (stat_buf
->st_ino
== pred_ptr
->args
.info
.l_val
)
805 pred_ipath (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
807 if (fnmatch (pred_ptr
->args
.str
, pathname
, FNM_CASEFOLD
) == 0)
813 pred_links (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
815 switch (pred_ptr
->args
.info
.kind
)
818 if (stat_buf
->st_nlink
> pred_ptr
->args
.info
.l_val
)
822 if (stat_buf
->st_nlink
< pred_ptr
->args
.info
.l_val
)
826 if (stat_buf
->st_nlink
== pred_ptr
->args
.info
.l_val
)
834 pred_lname (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
836 return insert_lname (pathname
, stat_buf
, pred_ptr
, false);
840 insert_lname (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
, boolean ignore_case
)
844 if (S_ISLNK (stat_buf
->st_mode
))
846 char *linkname
= get_link_name (pathname
, rel_pathname
);
849 if (fnmatch (pred_ptr
->args
.str
, linkname
,
850 ignore_case
? FNM_CASEFOLD
: 0) == 0)
860 pred_ls (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
862 list_file (pathname
, rel_pathname
, stat_buf
, start_time
,
863 output_block_size
, stdout
);
868 pred_mmin (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
870 switch (pred_ptr
->args
.info
.kind
)
873 if (stat_buf
->st_mtime
> (time_t) pred_ptr
->args
.info
.l_val
)
877 if (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
)
881 if ((stat_buf
->st_mtime
>= (time_t) pred_ptr
->args
.info
.l_val
)
882 && (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
+ 60))
890 pred_mtime (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
892 switch (pred_ptr
->args
.info
.kind
)
895 if (stat_buf
->st_mtime
> (time_t) pred_ptr
->args
.info
.l_val
)
899 if (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
)
903 if ((stat_buf
->st_mtime
>= (time_t) pred_ptr
->args
.info
.l_val
)
904 && (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
913 pred_name (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
917 base
= base_name (pathname
);
918 if (fnmatch (pred_ptr
->args
.str
, base
, FNM_PERIOD
) == 0)
924 pred_negate (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
926 /* Check whether we need a stat here. */
927 if (pred_ptr
->need_stat
)
929 if (!have_stat
&& (*xstat
) (rel_pathname
, stat_buf
) != 0)
931 error (0, errno
, "%s", pathname
);
937 return (!(*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
938 pred_ptr
->pred_right
));
942 pred_newer (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
944 if (stat_buf
->st_mtime
> pred_ptr
->args
.time
)
950 pred_nogroup (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
953 extern char *gid_unused
;
955 return gid_unused
[(unsigned) stat_buf
->st_gid
];
957 return getgrgid (stat_buf
->st_gid
) == NULL
;
962 pred_nouser (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
965 extern char *uid_unused
;
967 return uid_unused
[(unsigned) stat_buf
->st_uid
];
969 return getpwuid (stat_buf
->st_uid
) == NULL
;
974 pred_ok (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
977 /* The draft open standard requires that, in the POSIX locale,
978 the last non-blank character of this prompt be '?'.
979 The exact format is not specified.
980 This standard does not have requirements for locales other than POSIX
982 fprintf (stderr
, _("< %s ... %s > ? "),
983 pred_ptr
->args
.exec_vec
.vec
[0], pathname
);
986 return pred_exec (pathname
, stat_buf
, pred_ptr
);
992 pred_open (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
998 pred_or (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1000 if (pred_ptr
->pred_left
== NULL
1001 || !(*pred_ptr
->pred_left
->pred_func
) (pathname
, stat_buf
,
1002 pred_ptr
->pred_left
))
1004 /* Check whether we need a stat here. */
1005 if (pred_ptr
->need_stat
)
1007 if (!have_stat
&& (*xstat
) (rel_pathname
, stat_buf
) != 0)
1009 error (0, errno
, "%s", pathname
);
1015 return ((*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
1016 pred_ptr
->pred_right
));
1023 pred_path (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1025 if (fnmatch (pred_ptr
->args
.str
, pathname
, 0) == 0)
1031 pred_perm (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1033 switch (pred_ptr
->args
.perm
.kind
)
1036 return (stat_buf
->st_mode
& pred_ptr
->args
.perm
.val
) == pred_ptr
->args
.perm
.val
;
1040 return (stat_buf
->st_mode
& pred_ptr
->args
.perm
.val
) != 0;
1044 return (stat_buf
->st_mode
& MODE_ALL
) == pred_ptr
->args
.perm
.val
;
1054 pred_print (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1061 pred_print0 (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1063 fputs (pathname
, stdout
);
1069 pred_prune (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1071 stop_at_current_level
= true;
1072 return (do_dir_first
); /* This is what SunOS find seems to do. */
1076 pred_regex (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1078 int len
= strlen (pathname
);
1079 if (re_match (pred_ptr
->args
.regex
, pathname
, len
, 0,
1080 (struct re_registers
*) NULL
) == len
)
1086 pred_size (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1090 f_val
= ((stat_buf
->st_size
/ pred_ptr
->args
.size
.blocksize
)
1091 + (stat_buf
->st_size
% pred_ptr
->args
.size
.blocksize
!= 0));
1092 switch (pred_ptr
->args
.size
.kind
)
1095 if (f_val
> pred_ptr
->args
.size
.size
)
1099 if (f_val
< pred_ptr
->args
.size
.size
)
1103 if (f_val
== pred_ptr
->args
.size
.size
)
1111 pred_true (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1117 pred_type (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1119 mode_t mode
= stat_buf
->st_mode
;
1120 mode_t type
= pred_ptr
->args
.type
;
1123 /* POSIX system; check `mode' the slow way. */
1124 if ((S_ISBLK (mode
) && type
== S_IFBLK
)
1125 || (S_ISCHR (mode
) && type
== S_IFCHR
)
1126 || (S_ISDIR (mode
) && type
== S_IFDIR
)
1127 || (S_ISREG (mode
) && type
== S_IFREG
)
1129 || (S_ISLNK (mode
) && type
== S_IFLNK
)
1132 || (S_ISFIFO (mode
) && type
== S_IFIFO
)
1135 || (S_ISSOCK (mode
) && type
== S_IFSOCK
)
1138 || (S_ISDOOR (mode
) && type
== S_IFDOOR
)
1142 /* Unix system; check `mode' the fast way. */
1143 if ((mode
& S_IFMT
) == type
)
1151 pred_uid (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1153 switch (pred_ptr
->args
.info
.kind
)
1156 if (stat_buf
->st_uid
> pred_ptr
->args
.info
.l_val
)
1160 if (stat_buf
->st_uid
< pred_ptr
->args
.info
.l_val
)
1164 if (stat_buf
->st_uid
== pred_ptr
->args
.info
.l_val
)
1172 pred_used (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1176 delta
= stat_buf
->st_atime
- stat_buf
->st_ctime
; /* Use difftime? */
1177 switch (pred_ptr
->args
.info
.kind
)
1180 if (delta
> (time_t) pred_ptr
->args
.info
.l_val
)
1184 if (delta
< (time_t) pred_ptr
->args
.info
.l_val
)
1188 if ((delta
>= (time_t) pred_ptr
->args
.info
.l_val
)
1189 && (delta
< (time_t) pred_ptr
->args
.info
.l_val
+ DAYSECS
))
1197 pred_user (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1199 if (pred_ptr
->args
.uid
== stat_buf
->st_uid
)
1206 pred_xtype (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1211 ystat
= xstat
== lstat
? stat
: lstat
;
1212 if ((*ystat
) (rel_pathname
, &sbuf
) != 0)
1214 if (ystat
== stat
&& errno
== ENOENT
)
1215 /* Mimic behavior of ls -lL. */
1216 return (pred_type (pathname
, stat_buf
, pred_ptr
));
1217 error (0, errno
, "%s", pathname
);
1221 return (pred_type (pathname
, &sbuf
, pred_ptr
));
1224 /* 1) fork to get a child; parent remembers the child pid
1225 2) child execs the command requested
1226 3) parent waits for child; checks for proper pid of child
1230 ret errno status(h) status(l)
1232 pid x signal# 0177 stopped
1233 pid x exit arg 0 term by _exit
1234 pid x 0 signal # term by signal
1235 -1 EINTR parent got signal
1236 -1 other some other kind of error
1238 Return true only if the pid matches, status(l) is
1239 zero, and the exit arg (status high) is 0.
1240 Otherwise return false, possibly printing an error message. */
1243 launch (struct predicate
*pred_ptr
)
1247 struct exec_val
*execp
; /* Pointer for efficiency. */
1248 static int first_time
= 1;
1250 execp
= &pred_ptr
->args
.exec_vec
;
1252 /* Make sure output of command doesn't get mixed with find output. */
1256 /* Make sure to listen for the kids. */
1260 signal (SIGCHLD
, SIG_DFL
);
1263 child_pid
= fork ();
1264 if (child_pid
== -1)
1265 error (1, errno
, _("cannot fork"));
1268 /* We be the child. */
1269 if (starting_desc
< 0
1270 ? chdir (starting_dir
) != 0
1271 : fchdir (starting_desc
) != 0)
1273 error (0, errno
, "%s", starting_dir
);
1276 execvp (execp
->vec
[0], execp
->vec
);
1277 error (0, errno
, "%s", execp
->vec
[0]);
1282 while (waitpid (child_pid
, &status
, 0) == (pid_t
) -1)
1285 error (0, errno
, _("error waiting for %s"), execp
->vec
[0]);
1289 if (WIFSIGNALED (status
))
1291 error (0, 0, _("%s terminated by signal %d"),
1292 execp
->vec
[0], WTERMSIG (status
));
1296 return (!WEXITSTATUS (status
));
1299 /* Return a static string formatting the time WHEN according to the
1300 strftime format character KIND. */
1303 format_date (time_t when
, int kind
)
1305 static char buf
[MAX (LONGEST_HUMAN_READABLE
+ 2, 64)];
1314 && (tm
= localtime (&when
))
1315 && strftime (buf
, sizeof buf
, fmt
, tm
))
1320 char *p
= human_readable (when
< 0 ? -w
: w
, buf
+ 1, 1, 1);
1331 char *r
= ctime (&when
);
1334 /* The time cannot be represented as a struct tm.
1335 Output it as an integer. */
1336 return format_date (when
, '@');
1340 /* Remove the trailing newline from the ctime output,
1341 being careful not to assume that the output is fixed-width. */
1342 *strchr (r
, '\n') = '\0';
1348 /* Return a pointer to the string representation of
1349 the predicate function PRED_FUNC. */
1352 find_pred_name (pred_func
)
1357 for (i
= 0; pred_table
[i
].pred_func
!= 0; i
++)
1358 if (pred_table
[i
].pred_func
== pred_func
)
1360 return (pred_table
[i
].pred_name
);
1369 for (i
= 0; type_table
[i
].type
!= (short) -1; i
++)
1370 if (type_table
[i
].type
== type
)
1372 return (type_table
[i
].type_name
);
1381 for (i
= 0; prec_table
[i
].prec
!= (short) -1; i
++)
1382 if (prec_table
[i
].prec
== prec
)
1384 return (prec_table
[i
].prec_name
);
1387 /* Walk the expression tree NODE to stdout.
1388 INDENT is the number of levels to indent the left margin. */
1391 print_tree (node
, indent
)
1392 struct predicate
*node
;
1399 for (i
= 0; i
< indent
; i
++)
1401 printf ("pred = %s type = %s prec = %s addr = %x\n",
1402 find_pred_name (node
->pred_func
),
1403 type_name (node
->p_type
), prec_name (node
->p_prec
), node
);
1404 for (i
= 0; i
< indent
; i
++)
1406 printf (_("left:\n"));
1407 print_tree (node
->pred_left
, indent
+ 1);
1408 for (i
= 0; i
< indent
; i
++)
1410 printf (_("right:\n"));
1411 print_tree (node
->pred_right
, indent
+ 1);
1414 /* Copy STR into BUF and trim blanks from the end of BUF.
1418 blank_rtrim (str
, buf
)
1427 i
= strlen (buf
) - 1;
1428 while ((i
>= 0) && ((buf
[i
] == ' ') || buf
[i
] == '\t'))
1434 /* Print out the predicate list starting at NODE. */
1438 struct predicate
*node
;
1440 struct predicate
*cur
;
1446 printf ("%s ", blank_rtrim (find_pred_name (cur
->pred_func
), name
));
1447 cur
= cur
->pred_next
;