diff options
author | Andreas Gruenbacher <agruen@suse.de> | 2006-01-21 23:45:37 +0000 |
---|---|---|
committer | Andreas Gruenbacher <agruen@suse.de> | 2006-01-21 23:45:37 +0000 |
commit | 91a883abd8138ea0c864cc34b46a7359d4505a21 (patch) | |
tree | c964a64ce76dba87a1d1010feef0b60a788055dc /lib/ftw.c | |
parent | 7650e642f6405339620b850ec12fd53238fc55d4 (diff) | |
download | quilt-91a883abd8138ea0c864cc34b46a7359d4505a21.tar.gz |
- Add fallback ftw implementation for systems that don't have it.
Diffstat (limited to 'lib/ftw.c')
-rw-r--r-- | lib/ftw.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/lib/ftw.c b/lib/ftw.c new file mode 100644 index 0000000..8762194 --- /dev/null +++ b/lib/ftw.c @@ -0,0 +1,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 + |