]> git.saurik.com Git - apple/libc.git/blob - tests/fts_find.c
1c0bc31ae0126f4fb2cf76e22baf2a9119e4c247
[apple/libc.git] / tests / fts_find.c
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