1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
/*
* Written by Jesper Juhl <jj@dif.dk> - released under the terms of the GPL
*
* Credit should be given to :
* R. Stevens author of "Advanced Programming in the UNIX Environment"
* since I have made heavy use of some of his example code.
*
*/
/* To compile the test code: gcc -DTEST_FTW ftw.c */
#include "ftw.h"
static int depth;
static char *path;
static int trawl(char *path, ftw_func *f, int d) {
int retval;
struct stat sb;
struct dirent *dir;
DIR *dp;
char *p;
if (depth == d)
return(0);
if (lstat(path, &sb) == -1)
return(f(path, &sb, FTW_NS));
if (!S_ISDIR(sb.st_mode))
return(f(path, &sb, FTW_F));
if ((retval = f(path, &sb, FTW_D)) != 0)
return(retval);
p = path + strlen(path);
*p++ = '/';
*p = '\0';
if ((dp = opendir(path)) == NULL)
return(f(path, &sb, FTW_DNR));
while ((dir = readdir(dp)) != NULL) {
if ((strncmp(dir->d_name, ".", 1) == 0) ||
(strncmp(dir->d_name, "..", 2) == 0))
continue;
strcpy(p, dir->d_name);
depth++;
if ((retval = trawl(path, f, d)) != 0)
break;
depth--;
}
p[-1] = '\0';
closedir(dp);
return(retval);
}
int ftw(const char *directory, ftw_func *f, int d) {
int retval;
if ((path = (char *)malloc(sysconf(_PC_PATH_MAX)+1)) == NULL)
return(-1);
strcpy(path, directory);
depth = 0;
retval = trawl(path, f, d);
free(path);
return(retval);
}
#ifdef TEST_FTW
int foo(const char *file, struct stat *sb, int flag) {
switch (flag) {
case FTW_F :
if (S_ISREG(sb->st_mode)) printf("%s is a regular file\n\n", file);
else if (S_ISBLK(sb->st_mode)) printf("%s is a block dev\n\n", file);
else if (S_ISCHR(sb->st_mode)) printf("%s is a char dev\n\n", file);
else if (S_ISFIFO(sb->st_mode)) printf("%s is a fifo\n\n", file);
else if (S_ISLNK(sb->st_mode)) printf("%s is a link\n\n", file);
break;
case FTW_D :
printf("%s is a directory\n\n", file);
break;
case FTW_NS :
printf("stat failed on %s\n\n", file);
break;
case FTW_DNR :
printf("%s is a directory which can't be read\n\n", file);
break;
default :
printf("%s is unknown\n\n", file);
break;
}
return(0);
}
int main(int argc, char *argv[]) {
if (argc == 2) {
ftw(argv[1], foo, 1);
exit(0);
} else if (argc > 2) {
ftw(argv[1], foo, atoi(argv[2]));
exit(0);
} else {
printf("usage %s <dirname> [depth]\n", argv[0]);
exit(1);
}
}
#endif
|