]>
Commit | Line | Data |
---|---|---|
974e3884 A |
1 | #include <err.h> |
2 | #include <stdbool.h> | |
3 | #include <stdio.h> | |
4 | #include <stdlib.h> | |
5 | #include <string.h> | |
6 | #include <sysexits.h> | |
7 | #include <unistd.h> | |
8 | #include <fts.h> | |
9 | #include <sys/types.h> | |
10 | #include <sys/stat.h> | |
11 | ||
12 | // Can ASan fts by uncommenting below | |
13 | //#include "../gen/fts.c" | |
14 | ||
15 | #ifndef DARWINTEST | |
16 | #define fts_find_main main | |
17 | #else | |
18 | #include <darwintest.h> | |
19 | #endif | |
20 | ||
21 | int fts_find_main(int argc, char *argv[]); | |
22 | ||
23 | static char * | |
24 | stat_str(struct stat *st) | |
25 | { | |
26 | static char charbuf[256]; | |
27 | snprintf(charbuf, sizeof(charbuf), "dev: %d, mode: %x, nlink: %d, ino: %lld, " | |
28 | "owner: %d/%d, rdev: %d, mtime: %ld, ctime: %ld, btime: %ld, " | |
29 | "size: %lld, blocks: %lld, blksize: %d, flags: %d, gen: %d", | |
30 | st->st_dev, st->st_mode, st->st_nlink, st->st_ino, st->st_uid, | |
31 | st->st_gid, st->st_rdev, st->st_mtimespec.tv_sec, | |
32 | st->st_ctimespec.tv_sec, st->st_birthtimespec.tv_sec, st->st_size, | |
33 | st->st_blocks, st->st_blksize, st->st_flags, st->st_gen); | |
34 | return charbuf; | |
35 | } | |
36 | ||
37 | int | |
38 | fts_find_main(int argc, char *argv[]) | |
39 | { | |
40 | FTS *fts; | |
41 | FTSENT *ftse; | |
42 | ||
43 | bool print_children = false; | |
44 | int fts_options = FTS_COMFOLLOW | FTS_XDEV; | |
45 | ||
46 | int ch; | |
47 | while ((ch = getopt(argc, argv, "lpcdsS")) != -1){ | |
48 | switch (ch){ | |
49 | case 'l': | |
50 | fts_options |= FTS_LOGICAL; | |
51 | break; | |
52 | case 'p': | |
53 | fts_options |= FTS_PHYSICAL; | |
54 | break; | |
55 | case 'c': | |
56 | print_children = true; | |
57 | break; | |
58 | case 'd': | |
59 | fts_options |= FTS_NOCHDIR; | |
60 | break; | |
61 | case 's': | |
62 | fts_options |= FTS_NOSTAT; | |
63 | break; | |
64 | case 'S': | |
65 | fts_options |= FTS_NOSTAT_TYPE; | |
66 | break; | |
67 | case '?': | |
68 | fprintf(stderr, "Usage: %s (-l|-p) [-c] [-d] [-s|-S] <path> ...\n", argv[0]); | |
69 | exit(EX_USAGE); | |
70 | } | |
71 | } | |
72 | ||
73 | if ((fts_options & (FTS_LOGICAL|FTS_PHYSICAL)) == 0){ | |
74 | fprintf(stderr, "Usage: %s (-l|-p) [-c] [-s|-S] <path> ...\n", argv[0]); | |
75 | exit(EX_USAGE); | |
76 | } | |
77 | ||
78 | argc -= optind; | |
79 | argv += optind; | |
80 | ||
81 | char **args = alloca((size_t)(argc + 1)*sizeof(char*)); | |
82 | for (int i = 0; i < argc; i++){ | |
83 | args[i] = argv[i]; | |
84 | } | |
85 | args[argc] = NULL; | |
86 | fts = fts_open_b(args, fts_options, ^(const FTSENT **a, const FTSENT **b){ | |
87 | return strcmp((*a)->fts_name, (*b)->fts_name); | |
88 | }); | |
89 | if (!fts) err(EX_DATAERR, "fts_open_b"); | |
90 | ||
91 | while ((ftse = fts_read(fts)) != NULL) { | |
92 | #ifndef DARWINTEST | |
93 | if (!print_children || (ftse->fts_info & FTS_D)){ | |
94 | printf("%s (%s): 0x%x\n", ftse->fts_path, ftse->fts_name, ftse->fts_info); | |
95 | if (!(fts_options & (FTS_NOSTAT|FTS_NOSTAT_TYPE))) printf("\t\t%s\n", stat_str(ftse->fts_statp)); | |
96 | } | |
97 | #endif | |
98 | if (print_children){ | |
99 | FTSENT *child = fts_children(fts, 0); | |
100 | while (child){ | |
101 | #ifndef DARWINTEST | |
102 | if (child->fts_info & FTS_F){ | |
103 | printf("\t%s (%s): 0x%x\n", child->fts_path, child->fts_name, child->fts_info); | |
104 | if (!(fts_options & (FTS_NOSTAT|FTS_NOSTAT_TYPE))) printf("\t\t%s\n", stat_str(child->fts_statp)); | |
105 | } | |
106 | #endif | |
107 | child = child->fts_link; | |
108 | } | |
109 | } | |
110 | } | |
111 | ||
112 | (void)fts_close(fts); | |
113 | return 0; | |
114 | } | |
115 | ||
116 | #ifdef DARWINTEST | |
117 | T_DECL(fts_find, "A find(1) example in fts"){ | |
118 | int fts_argc = 3; | |
119 | char *fts_argv[] = {"fts_find", "-lc", "/System", NULL}; | |
120 | if (fts_find_main(fts_argc, fts_argv) == 0){ | |
121 | T_PASS("fts_find() completed successfully"); | |
122 | } else { | |
123 | T_FAIL("fts_find() exited with error"); | |
124 | } | |
125 | } | |
126 | #endif |