home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume1 / 8712 / 15 / ftw.c < prev    next >
C/C++ Source or Header  |  1990-07-13  |  2KB  |  104 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. #include <stdio.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <sys/dir.h>
  11. #include <ftw.h>
  12. #ifdef    RCSID
  13. static char RCS[] = "$Header: ftw.c,v 1.1 87/12/29 21:38:52 rsalz Exp $";
  14. #endif    /* RCSID */
  15.  
  16. /* Handy shorthand. */
  17. #define EQ(a, b)    (strcmp((a), (b)) == 0)
  18.  
  19. /* Linked in later. */
  20. extern char        *malloc();
  21. extern char        *strcpy();
  22.  
  23.  
  24. int
  25. ftw(directory, funcptr, depth)
  26.     char         *directory;
  27.     int            (*funcptr)();
  28.     int              depth;
  29. {
  30.     register DIR     *Dp;
  31.     register char     *p;
  32.     register int      i;
  33.     struct direct     *E;
  34.     struct stat          Sb;
  35.     long          seekpoint;
  36.     char         *fullpath;
  37.  
  38.     /* If can't stat, tell the user so. */
  39.     if (stat(directory, &Sb) < 0)
  40.     return((*funcptr)(directory, &Sb, FTW_NS));
  41.  
  42.     /* If it's not a directory, call the user's function. */
  43.     if ((Sb.st_mode & S_IFMT) != S_IFDIR)
  44.     /* Saying "FTW_F" here is lying, what if this is a symlink? */
  45.     return((*funcptr)(directory, &Sb, FTW_F));
  46.  
  47.     /* Open directory; and if we can't tell the user so. */
  48.     if ((Dp = opendir(directory)) == NULL)
  49.     return((*funcptr)(directory, &Sb, FTW_DNR));
  50.  
  51.     /* See if user wants to go further. */
  52.     if (i = (*funcptr)(directory, &Sb, FTW_D)) {
  53.     closedir(Dp);
  54.     return(i);
  55.     }
  56.  
  57.     /* Get ready to hold the full paths. */
  58.     i = strlen(directory);
  59.     if ((fullpath = malloc(i + 1 + MAXNAMLEN + 1)) == NULL) {
  60.     closedir(Dp);
  61.     return(-1);
  62.     }
  63.     (void)strcpy(fullpath, directory);
  64.     p = &fullpath[i];
  65.     if (i && p[-1] != '/')
  66.     *p++ = '/';
  67.  
  68.     /* Read all entries in the directory.. */
  69.     while (E = readdir(Dp))
  70.     if (!EQ(E->d_name, ".") && !EQ(E->d_name, "..")) {
  71.         if (depth <= 1) {
  72.         /* Going too deep; checkpoint and close this directory. */
  73.         seekpoint = telldir(Dp);
  74.         closedir(Dp);
  75.         Dp = NULL;
  76.         }
  77.  
  78.         /* Process the file. */
  79.         (void)strcpy(p, E->d_name);
  80.         if (i = ftw(fullpath, funcptr, depth - 1)) {
  81.         /* User's finished; clean up. */
  82.         free(fullpath);
  83.         if (Dp)
  84.             closedir(Dp);
  85.         return(i);
  86.         }
  87.  
  88.         /* Reopen the directory if necessary. */
  89.         if (Dp == NULL) {
  90.         if ((Dp = opendir(directory)) == NULL) {
  91.             /* WTF? */
  92.             free(fullpath);
  93.             return(-1);
  94.         }
  95.         seekdir(Dp, seekpoint);
  96.         }
  97.     }
  98.  
  99.     /* Clean up. */
  100.     free(fullpath);
  101.     closedir(Dp);
  102.     return(0);
  103. }
  104.