1 /* See LICENSE file for copyright and license details. */
14 #define FLAG(x) (flag[(x)-'a'])
16 static void test(const char *, const char *);
17 static void usage(void);
21 static struct stat old
, new;
24 test(const char *path
, const char *name
)
28 if ((!stat(path
, &st
) && (FLAG('a') || name
[0] != '.') /* hidden files */
29 && (!FLAG('b') || S_ISBLK(st
.st_mode
)) /* block special */
30 && (!FLAG('c') || S_ISCHR(st
.st_mode
)) /* character special */
31 && (!FLAG('d') || S_ISDIR(st
.st_mode
)) /* directory */
32 && (!FLAG('e') || access(path
, F_OK
) == 0) /* exists */
33 && (!FLAG('f') || S_ISREG(st
.st_mode
)) /* regular file */
34 && (!FLAG('g') || st
.st_mode
& S_ISGID
) /* set-group-id flag */
35 && (!FLAG('h') || (!lstat(path
, &ln
) && S_ISLNK(ln
.st_mode
))) /* symbolic link */
36 && (!FLAG('n') || st
.st_mtime
> new.st_mtime
) /* newer than file */
37 && (!FLAG('o') || st
.st_mtime
< old
.st_mtime
) /* older than file */
38 && (!FLAG('p') || S_ISFIFO(st
.st_mode
)) /* named pipe */
39 && (!FLAG('r') || access(path
, R_OK
) == 0) /* readable */
40 && (!FLAG('s') || st
.st_size
> 0) /* not empty */
41 && (!FLAG('u') || st
.st_mode
& S_ISUID
) /* set-user-id flag */
42 && (!FLAG('w') || access(path
, W_OK
) == 0) /* writable */
43 && (!FLAG('x') || access(path
, X_OK
) == 0)) != FLAG('v')) { /* executable */
54 fprintf(stderr
, "usage: %s [-abcdefghlpqrsuvwx] "
55 "[-n file] [-o file] [file...]\n", argv0
);
56 exit(2); /* like test(1) return > 1 on error */
60 main(int argc
, char *argv
[])
63 char path
[PATH_MAX
], *line
= NULL
, *file
;
70 case 'n': /* newer than file */
71 case 'o': /* older than file */
72 file
= EARGF(usage());
73 if (!(FLAG(ARGC()) = !stat(file
, (ARGC() == 'n' ? &new : &old
))))
77 /* miscellaneous operators */
78 if (strchr("abcdefghlpqrsuvwx", ARGC()))
81 usage(); /* unknown flag */
85 /* read list from stdin */
86 while ((n
= getline(&line
, &linesiz
, stdin
)) > 0) {
87 if (line
[n
- 1] == '\n')
93 for (; argc
; argc
--, argv
++) {
94 if (FLAG('l') && (dir
= opendir(*argv
))) {
95 /* test directory contents */
96 while ((d
= readdir(dir
))) {
97 r
= snprintf(path
, sizeof path
, "%s/%s",
99 if (r
>= 0 && (size_t)r
< sizeof path
)
100 test(path
, d
->d_name
);
108 return match
? 0 : 1;