home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2181 / ftw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-28  |  2.4 KB  |  107 lines

  1. /*
  2. **  FTW
  3. **  Walk a directory hierarchy from a given point, calling a user-supplied
  4. **  function at each thing we find.  If we go below a specified depth,
  5. **  recycle file descriptors.
  6. */
  7.  
  8. #include <stdio.h>
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include <sys/dir.h>
  12. #include <ftw.h>
  13.  
  14. #ifdef    RCSID
  15. static char RCS[] = "$Header: ftw.c,v 1.1 87/12/29 21:38:52 rsalz Exp $";
  16. #endif    /* RCSID */
  17.  
  18. #define EQ(a, b)    (strcmp((a), (b)) == 0)
  19.  
  20. extern char        *malloc();
  21. extern char        *strcpy();
  22.  
  23. int
  24. ftw(directory, funcptr, depth)
  25.     char         *directory;
  26.     int            (*funcptr)();
  27.     int              depth;
  28. {
  29.     register DIR     *dirp;
  30.     struct direct     *entp;
  31.     struct stat          stats;
  32.     register char     *p;
  33.     register int      i;
  34.     long          seekpoint;
  35.     char         *fullpath;
  36.  
  37.     /* If can't stat, tell the user so. */
  38.     if (stat(directory, &stats) < 0)
  39.     return (*funcptr)(directory, &stats, FTW_NS);
  40.  
  41.     /* If it's not a directory, call the user's function. */
  42.     if ((stats.st_mode & S_IFMT) != S_IFDIR)
  43.     /* Saying "FTW_F" here is lying; what if this is a symlink? */
  44.     return (*funcptr)(directory, &stats, FTW_F);
  45.  
  46.     /* Open directory; if we can't, tell the user so. */
  47.     dirp = opendir(directory);
  48.     if (dirp == NULL)
  49.     return (*funcptr)(directory, &stats, FTW_DNR);
  50.  
  51.     /* See if user wants to go further. */
  52.     i = (*funcptr)(directory, &stats, FTW_D);
  53.     if (i) {
  54.     closedir(dirp);
  55.     return i;
  56.     }
  57.  
  58.     /* Get ready to hold the full paths. */
  59.     i = strlen(directory);
  60.     fullpath = malloc(i + 1 + MAXNAMLEN + 1);
  61.     if (fullpath == NULL) {
  62.     closedir(dirp);
  63.     return -1;
  64.     }
  65.     (void)strcpy(fullpath, directory);
  66.     p = &fullpath[i];
  67.     if (i && p[-1] != '/')
  68.     *p++ = '/';
  69.  
  70.     /* Read all entries in the directory.. */
  71.     while (entp = readdir(dirp))
  72.     if (!EQ(entp->d_name, ".") && !EQ(entp->d_name, "..")) {
  73.         if (depth <= 1) {
  74.         /* Going too deep; checkpoint and close this directory. */
  75.         seekpoint = telldir(dirp);
  76.         closedir(dirp);
  77.         dirp = NULL;
  78.         }
  79.  
  80.         /* Process the file. */
  81.         (void)strcpy(p, entp->d_name);
  82.         i = ftw(fullpath, funcptr, depth - 1);
  83.         if (i) {
  84.         /* User's finished; clean up. */
  85.         free(fullpath);
  86.         if (dirp)
  87.             closedir(dirp);
  88.         return i;
  89.         }
  90.  
  91.         /* Reopen the directory if necessary. */
  92.         if (dirp == NULL) {
  93.         dirp = opendir(directory);
  94.         if (dirp == NULL) {
  95.             free(fullpath);
  96.             return -1;
  97.         }
  98.         seekdir(dirp, seekpoint);
  99.         }
  100.     }
  101.  
  102.     /* Clean up. */
  103.     free(fullpath);
  104.     closedir(dirp);
  105.     return 0;
  106. }
  107.