home *** CD-ROM | disk | FTP | other *** search
- /*
- ** FTW
- ** Walk a directory hierarchy from a given point, calling a user-supplied
- ** function at each thing we find. If we go below a specified depth,
- ** recycle file descriptors.
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/dir.h>
- #include <ftw.h>
-
- #define EQ(a, b) (strcmp((a), (b)) == 0)
-
- int
- ftw(directory, funcptr, depth)
- char *directory;
- int (*funcptr)();
- int depth;
- {
- register DIR *dirp;
- struct direct *entp;
- struct stat stats;
- register char *p;
- register int i;
- #ifndef __MINT__
- long seekpoint;
- #endif
- char *fullpath;
-
- #ifndef __MINT__
- seekpoint = 0; /* avoid spurious warning from gcc -Wall */
- #endif
-
- /* If can't stat, tell the user so. */
- if (stat(directory, &stats) < 0)
- return (*funcptr)(directory, &stats, FTW_NS);
-
- /* If it's not a directory, call the user's function. */
- if ((stats.st_mode & S_IFMT) != S_IFDIR)
- /* Saying "FTW_F" here is lying; what if this is a symlink? */
- return (*funcptr)(directory, &stats, FTW_F);
-
- /* Open directory; if we can't, tell the user so. */
- dirp = opendir(directory);
- if (dirp == NULL)
- return (*funcptr)(directory, &stats, FTW_DNR);
-
- /* See if user wants to go further. */
- i = (*funcptr)(directory, &stats, FTW_D);
- if (i) {
- closedir(dirp);
- return i;
- }
-
- /* Get ready to hold the full paths. */
- i = strlen(directory);
- fullpath = malloc(i + 1 + MAXNAMLEN + 1);
- if (fullpath == NULL) {
- closedir(dirp);
- return -1;
- }
- (void)strcpy(fullpath, directory);
- p = &fullpath[i];
- if (i && p[-1] != '/')
- *p++ = '/';
-
- /* Read all entries in the directory.. */
- while (entp = readdir(dirp))
- if (!EQ(entp->d_name, ".") && !EQ(entp->d_name, "..")) {
- #ifndef __MINT__
- if (depth <= 1) {
- /* Going too deep; checkpoint and close this directory. */
- seekpoint = telldir(dirp);
- closedir(dirp);
- dirp = NULL;
- }
- #endif
- /* Process the file. */
- (void)strcpy(p, entp->d_name);
- i = ftw(fullpath, funcptr, depth - 1);
- if (i) {
- /* User's finished; clean up. */
- free(fullpath);
- if (dirp)
- closedir(dirp);
- return i;
- }
-
- #ifndef __MINT__
- /* Reopen the directory if necessary. */
- if (dirp == NULL) {
- dirp = opendir(directory);
- if (dirp == NULL) {
- free(fullpath);
- return -1;
- }
- seekdir(dirp, seekpoint);
- }
- #endif
- }
-
- /* Clean up. */
- free(fullpath);
- closedir(dirp);
- return 0;
- }
-