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_inexact ((uintmax_t) ST_NBLOCKS (*stat_buf
),
567 case 'c': /* ctime in `ctime' format */
568 fprintf (fp
, segment
->text
, ctime_format (stat_buf
->st_ctime
));
570 case 'd': /* depth in search tree */
571 fprintf (fp
, segment
->text
, curdepth
);
573 case 'f': /* basename of path */
574 fprintf (fp
, segment
->text
, base_name (pathname
));
576 case 'F': /* filesystem type */
577 fprintf (fp
, segment
->text
,
578 filesystem_type (pathname
, rel_pathname
, stat_buf
));
580 case 'g': /* group name */
584 g
= getgrgid (stat_buf
->st_gid
);
587 segment
->text
[segment
->text_len
] = 's';
588 fprintf (fp
, segment
->text
, g
->gr_name
);
593 case 'G': /* GID number */
594 fprintf (fp
, segment
->text
,
595 human_readable_inexact ((uintmax_t) stat_buf
->st_gid
, hbuf
,
596 1, 1, human_ceiling
));
598 case 'h': /* leading directories part of path */
602 cp
= strrchr (pathname
, '/');
603 if (cp
== NULL
) /* No leading directories. */
607 fprintf (fp
, segment
->text
, pathname
);
611 case 'H': /* ARGV element file was found under */
613 char cc
= pathname
[path_length
];
615 pathname
[path_length
] = '\0';
616 fprintf (fp
, segment
->text
, pathname
);
617 pathname
[path_length
] = cc
;
620 case 'i': /* inode number */
621 fprintf (fp
, segment
->text
,
622 human_readable_inexact ((uintmax_t) stat_buf
->st_ino
, hbuf
,
626 case 'k': /* size in 1K blocks */
627 fprintf (fp
, segment
->text
,
628 human_readable_inexact ((uintmax_t) ST_NBLOCKS (*stat_buf
),
633 case 'l': /* object of symlink */
638 if (S_ISLNK (stat_buf
->st_mode
))
640 linkname
= get_link_name (pathname
, rel_pathname
);
646 fprintf (fp
, segment
->text
, linkname
);
650 fprintf (fp
, segment
->text
, "");
654 case 'm': /* mode as octal number (perms only) */
656 /* Output the mode portably using the traditional numbers,
657 even if the host unwisely uses some other numbering
658 scheme. But help the compiler in the common case where
659 the host uses the traditional numbering scheme. */
660 mode_t m
= stat_buf
->st_mode
;
661 boolean traditional_numbering_scheme
=
662 (S_ISUID
== 04000 && S_ISGID
== 02000 && S_ISVTX
== 01000
663 && S_IRUSR
== 00400 && S_IWUSR
== 00200 && S_IXUSR
== 00100
664 && S_IRGRP
== 00040 && S_IWGRP
== 00020 && S_IXGRP
== 00010
665 && S_IROTH
== 00004 && S_IWOTH
== 00002 && S_IXOTH
== 00001);
666 fprintf (fp
, segment
->text
,
667 (traditional_numbering_scheme
669 : ((m
& S_ISUID
? 04000 : 0)
670 | (m
& S_ISGID
? 02000 : 0)
671 | (m
& S_ISVTX
? 01000 : 0)
672 | (m
& S_IRUSR
? 00400 : 0)
673 | (m
& S_IWUSR
? 00200 : 0)
674 | (m
& S_IXUSR
? 00100 : 0)
675 | (m
& S_IRGRP
? 00040 : 0)
676 | (m
& S_IWGRP
? 00020 : 0)
677 | (m
& S_IXGRP
? 00010 : 0)
678 | (m
& S_IROTH
? 00004 : 0)
679 | (m
& S_IWOTH
? 00002 : 0)
680 | (m
& S_IXOTH
? 00001 : 0))));
683 case 'n': /* number of links */
684 fprintf (fp
, segment
->text
,
685 human_readable_inexact ((uintmax_t) stat_buf
->st_nlink
,
690 case 'p': /* pathname */
691 fprintf (fp
, segment
->text
, pathname
);
693 case 'P': /* pathname with ARGV element stripped */
696 cp
= pathname
+ path_length
;
698 /* Move past the slash between the ARGV element
699 and the rest of the pathname. But if the ARGV element
700 ends in a slash, we didn't add another, so we've
701 already skipped past it. */
706 fprintf (fp
, segment
->text
, cp
);
708 case 's': /* size in bytes */
709 fprintf (fp
, segment
->text
,
710 human_readable_inexact ((uintmax_t) stat_buf
->st_size
,
711 hbuf
, 1, 1, human_ceiling
));
713 case 't': /* mtime in `ctime' format */
714 fprintf (fp
, segment
->text
, ctime_format (stat_buf
->st_mtime
));
716 case 'u': /* user name */
720 p
= getpwuid (stat_buf
->st_uid
);
723 segment
->text
[segment
->text_len
] = 's';
724 fprintf (fp
, segment
->text
, p
->pw_name
);
729 case 'U': /* UID number */
730 fprintf (fp
, segment
->text
,
731 human_readable_inexact ((uintmax_t) stat_buf
->st_uid
, hbuf
,
732 1, 1, human_ceiling
));
740 pred_fstype (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
742 if (strcmp (filesystem_type (pathname
, rel_pathname
, stat_buf
),
743 pred_ptr
->args
.str
) == 0)
749 pred_gid (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
751 switch (pred_ptr
->args
.info
.kind
)
754 if (stat_buf
->st_gid
> pred_ptr
->args
.info
.l_val
)
758 if (stat_buf
->st_gid
< pred_ptr
->args
.info
.l_val
)
762 if (stat_buf
->st_gid
== pred_ptr
->args
.info
.l_val
)
770 pred_group (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
772 if (pred_ptr
->args
.gid
== stat_buf
->st_gid
)
779 pred_ilname (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
781 return insert_lname (pathname
, stat_buf
, pred_ptr
, true);
785 pred_iname (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
789 base
= base_name (pathname
);
790 if (fnmatch (pred_ptr
->args
.str
, base
, FNM_PERIOD
| FNM_CASEFOLD
) == 0)
796 pred_inum (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
798 switch (pred_ptr
->args
.info
.kind
)
801 if (stat_buf
->st_ino
> pred_ptr
->args
.info
.l_val
)
805 if (stat_buf
->st_ino
< pred_ptr
->args
.info
.l_val
)
809 if (stat_buf
->st_ino
== pred_ptr
->args
.info
.l_val
)
817 pred_ipath (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
819 if (fnmatch (pred_ptr
->args
.str
, pathname
, FNM_CASEFOLD
) == 0)
825 pred_links (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
827 switch (pred_ptr
->args
.info
.kind
)
830 if (stat_buf
->st_nlink
> pred_ptr
->args
.info
.l_val
)
834 if (stat_buf
->st_nlink
< pred_ptr
->args
.info
.l_val
)
838 if (stat_buf
->st_nlink
== pred_ptr
->args
.info
.l_val
)
846 pred_lname (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
848 return insert_lname (pathname
, stat_buf
, pred_ptr
, false);
852 insert_lname (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
, boolean ignore_case
)
856 if (S_ISLNK (stat_buf
->st_mode
))
858 char *linkname
= get_link_name (pathname
, rel_pathname
);
861 if (fnmatch (pred_ptr
->args
.str
, linkname
,
862 ignore_case
? FNM_CASEFOLD
: 0) == 0)
872 pred_ls (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
874 list_file (pathname
, rel_pathname
, stat_buf
, start_time
,
875 output_block_size
, stdout
);
880 pred_mmin (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
882 switch (pred_ptr
->args
.info
.kind
)
885 if (stat_buf
->st_mtime
> (time_t) pred_ptr
->args
.info
.l_val
)
889 if (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
)
893 if ((stat_buf
->st_mtime
>= (time_t) pred_ptr
->args
.info
.l_val
)
894 && (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
+ 60))
902 pred_mtime (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
904 switch (pred_ptr
->args
.info
.kind
)
907 if (stat_buf
->st_mtime
> (time_t) pred_ptr
->args
.info
.l_val
)
911 if (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
)
915 if ((stat_buf
->st_mtime
>= (time_t) pred_ptr
->args
.info
.l_val
)
916 && (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
925 pred_name (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
929 base
= base_name (pathname
);
930 if (fnmatch (pred_ptr
->args
.str
, base
, FNM_PERIOD
) == 0)
936 pred_negate (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
938 /* Check whether we need a stat here. */
939 if (pred_ptr
->need_stat
)
941 if (!have_stat
&& (*xstat
) (rel_pathname
, stat_buf
) != 0)
943 error (0, errno
, "%s", pathname
);
949 return (!(*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
950 pred_ptr
->pred_right
));
954 pred_newer (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
956 if (stat_buf
->st_mtime
> pred_ptr
->args
.time
)
962 pred_nogroup (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
965 extern char *gid_unused
;
967 return gid_unused
[(unsigned) stat_buf
->st_gid
];
969 return getgrgid (stat_buf
->st_gid
) == NULL
;
974 pred_nouser (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
977 extern char *uid_unused
;
979 return uid_unused
[(unsigned) stat_buf
->st_uid
];
981 return getpwuid (stat_buf
->st_uid
) == NULL
;
986 pred_ok (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
989 /* The draft open standard requires that, in the POSIX locale,
990 the last non-blank character of this prompt be '?'.
991 The exact format is not specified.
992 This standard does not have requirements for locales other than POSIX
994 fprintf (stderr
, _("< %s ... %s > ? "),
995 pred_ptr
->args
.exec_vec
.vec
[0], pathname
);
998 return pred_exec (pathname
, stat_buf
, pred_ptr
);
1004 pred_open (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1010 pred_or (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1012 if (pred_ptr
->pred_left
== NULL
1013 || !(*pred_ptr
->pred_left
->pred_func
) (pathname
, stat_buf
,
1014 pred_ptr
->pred_left
))
1016 /* Check whether we need a stat here. */
1017 if (pred_ptr
->need_stat
)
1019 if (!have_stat
&& (*xstat
) (rel_pathname
, stat_buf
) != 0)
1021 error (0, errno
, "%s", pathname
);
1027 return ((*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
1028 pred_ptr
->pred_right
));
1035 pred_path (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1037 if (fnmatch (pred_ptr
->args
.str
, pathname
, 0) == 0)
1043 pred_perm (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1045 switch (pred_ptr
->args
.perm
.kind
)
1048 return (stat_buf
->st_mode
& pred_ptr
->args
.perm
.val
) == pred_ptr
->args
.perm
.val
;
1052 return (stat_buf
->st_mode
& pred_ptr
->args
.perm
.val
) != 0;
1056 return (stat_buf
->st_mode
& MODE_ALL
) == pred_ptr
->args
.perm
.val
;
1066 pred_print (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1073 pred_print0 (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1075 fputs (pathname
, stdout
);
1081 pred_prune (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1083 stop_at_current_level
= true;
1084 return (do_dir_first
); /* This is what SunOS find seems to do. */
1088 pred_regex (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1090 int len
= strlen (pathname
);
1091 if (re_match (pred_ptr
->args
.regex
, pathname
, len
, 0,
1092 (struct re_registers
*) NULL
) == len
)
1098 pred_size (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1102 f_val
= ((stat_buf
->st_size
/ pred_ptr
->args
.size
.blocksize
)
1103 + (stat_buf
->st_size
% pred_ptr
->args
.size
.blocksize
!= 0));
1104 switch (pred_ptr
->args
.size
.kind
)
1107 if (f_val
> pred_ptr
->args
.size
.size
)
1111 if (f_val
< pred_ptr
->args
.size
.size
)
1115 if (f_val
== pred_ptr
->args
.size
.size
)
1123 pred_true (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1129 pred_type (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1131 mode_t mode
= stat_buf
->st_mode
;
1132 mode_t type
= pred_ptr
->args
.type
;
1135 /* POSIX system; check `mode' the slow way. */
1136 if ((S_ISBLK (mode
) && type
== S_IFBLK
)
1137 || (S_ISCHR (mode
) && type
== S_IFCHR
)
1138 || (S_ISDIR (mode
) && type
== S_IFDIR
)
1139 || (S_ISREG (mode
) && type
== S_IFREG
)
1141 || (S_ISLNK (mode
) && type
== S_IFLNK
)
1144 || (S_ISFIFO (mode
) && type
== S_IFIFO
)
1147 || (S_ISSOCK (mode
) && type
== S_IFSOCK
)
1150 || (S_ISDOOR (mode
) && type
== S_IFDOOR
)
1154 /* Unix system; check `mode' the fast way. */
1155 if ((mode
& S_IFMT
) == type
)
1163 pred_uid (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1165 switch (pred_ptr
->args
.info
.kind
)
1168 if (stat_buf
->st_uid
> pred_ptr
->args
.info
.l_val
)
1172 if (stat_buf
->st_uid
< pred_ptr
->args
.info
.l_val
)
1176 if (stat_buf
->st_uid
== pred_ptr
->args
.info
.l_val
)
1184 pred_used (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1188 delta
= stat_buf
->st_atime
- stat_buf
->st_ctime
; /* Use difftime? */
1189 switch (pred_ptr
->args
.info
.kind
)
1192 if (delta
> (time_t) pred_ptr
->args
.info
.l_val
)
1196 if (delta
< (time_t) pred_ptr
->args
.info
.l_val
)
1200 if ((delta
>= (time_t) pred_ptr
->args
.info
.l_val
)
1201 && (delta
< (time_t) pred_ptr
->args
.info
.l_val
+ DAYSECS
))
1209 pred_user (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1211 if (pred_ptr
->args
.uid
== stat_buf
->st_uid
)
1218 pred_xtype (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1223 ystat
= xstat
== lstat
? stat
: lstat
;
1224 if ((*ystat
) (rel_pathname
, &sbuf
) != 0)
1226 if (ystat
== stat
&& errno
== ENOENT
)
1227 /* Mimic behavior of ls -lL. */
1228 return (pred_type (pathname
, stat_buf
, pred_ptr
));
1229 error (0, errno
, "%s", pathname
);
1233 return (pred_type (pathname
, &sbuf
, pred_ptr
));
1236 /* 1) fork to get a child; parent remembers the child pid
1237 2) child execs the command requested
1238 3) parent waits for child; checks for proper pid of child
1242 ret errno status(h) status(l)
1244 pid x signal# 0177 stopped
1245 pid x exit arg 0 term by _exit
1246 pid x 0 signal # term by signal
1247 -1 EINTR parent got signal
1248 -1 other some other kind of error
1250 Return true only if the pid matches, status(l) is
1251 zero, and the exit arg (status high) is 0.
1252 Otherwise return false, possibly printing an error message. */
1255 launch (struct predicate
*pred_ptr
)
1259 struct exec_val
*execp
; /* Pointer for efficiency. */
1260 static int first_time
= 1;
1262 execp
= &pred_ptr
->args
.exec_vec
;
1264 /* Make sure output of command doesn't get mixed with find output. */
1268 /* Make sure to listen for the kids. */
1272 signal (SIGCHLD
, SIG_DFL
);
1275 child_pid
= fork ();
1276 if (child_pid
== -1)
1277 error (1, errno
, _("cannot fork"));
1280 /* We be the child. */
1281 if (starting_desc
< 0
1282 ? chdir (starting_dir
) != 0
1283 : fchdir (starting_desc
) != 0)
1285 error (0, errno
, "%s", starting_dir
);
1288 execvp (execp
->vec
[0], execp
->vec
);
1289 error (0, errno
, "%s", execp
->vec
[0]);
1294 while (waitpid (child_pid
, &status
, 0) == (pid_t
) -1)
1297 error (0, errno
, _("error waiting for %s"), execp
->vec
[0]);
1301 if (WIFSIGNALED (status
))
1303 error (0, 0, _("%s terminated by signal %d"),
1304 execp
->vec
[0], WTERMSIG (status
));
1308 return (!WEXITSTATUS (status
));
1311 /* Return a static string formatting the time WHEN according to the
1312 strftime format character KIND. */
1315 format_date (time_t when
, int kind
)
1317 static char buf
[MAX (LONGEST_HUMAN_READABLE
+ 2, 64)];
1326 && (tm
= localtime (&when
))
1327 && strftime (buf
, sizeof buf
, fmt
, tm
))
1332 char *p
= human_readable_inexact (when
< 0 ? -w
: w
, buf
+ 1,
1333 1, 1, human_ceiling
);
1344 char *r
= ctime (&when
);
1347 /* The time cannot be represented as a struct tm.
1348 Output it as an integer. */
1349 return format_date (when
, '@');
1353 /* Remove the trailing newline from the ctime output,
1354 being careful not to assume that the output is fixed-width. */
1355 *strchr (r
, '\n') = '\0';
1361 /* Return a pointer to the string representation of
1362 the predicate function PRED_FUNC. */
1365 find_pred_name (pred_func
)
1370 for (i
= 0; pred_table
[i
].pred_func
!= 0; i
++)
1371 if (pred_table
[i
].pred_func
== pred_func
)
1373 return (pred_table
[i
].pred_name
);
1382 for (i
= 0; type_table
[i
].type
!= (short) -1; i
++)
1383 if (type_table
[i
].type
== type
)
1385 return (type_table
[i
].type_name
);
1394 for (i
= 0; prec_table
[i
].prec
!= (short) -1; i
++)
1395 if (prec_table
[i
].prec
== prec
)
1397 return (prec_table
[i
].prec_name
);
1400 /* Walk the expression tree NODE to stdout.
1401 INDENT is the number of levels to indent the left margin. */
1404 print_tree (node
, indent
)
1405 struct predicate
*node
;
1412 for (i
= 0; i
< indent
; i
++)
1414 printf ("pred = %s type = %s prec = %s addr = %x\n",
1415 find_pred_name (node
->pred_func
),
1416 type_name (node
->p_type
), prec_name (node
->p_prec
), node
);
1417 for (i
= 0; i
< indent
; i
++)
1419 printf (_("left:\n"));
1420 print_tree (node
->pred_left
, indent
+ 1);
1421 for (i
= 0; i
< indent
; i
++)
1423 printf (_("right:\n"));
1424 print_tree (node
->pred_right
, indent
+ 1);
1427 /* Copy STR into BUF and trim blanks from the end of BUF.
1431 blank_rtrim (str
, buf
)
1440 i
= strlen (buf
) - 1;
1441 while ((i
>= 0) && ((buf
[i
] == ' ') || buf
[i
] == '\t'))
1447 /* Print out the predicate list starting at NODE. */
1451 struct predicate
*node
;
1453 struct predicate
*cur
;
1459 printf ("%s ", blank_rtrim (find_pred_name (cur
->pred_func
), name
));
1460 cur
= cur
->pred_next
;