home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / uucp-1.04 / unix / ftw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-13  |  4.6 KB  |  251 lines

  1. /* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. Contributed by Ian Lance Taylor (ian@airs.com).
  4.  
  5. The GNU C Library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Library General Public License as
  7. published by the Free Software Foundation; either version 2 of the
  8. License, or (at your option) any later version.
  9.  
  10. The GNU C Library is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13. Library General Public License for more details.
  14.  
  15. You should have received a copy of the GNU Library General Public
  16. License along with the GNU C Library; see the file COPYING.LIB.  If
  17. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  18. Cambridge, MA 02139, USA.
  19.  
  20. Modified by Ian Lanc Taylor for Taylor UUCP, June 1992.  */
  21.  
  22. #include "uucp.h"
  23.  
  24. #include "sysdep.h"
  25.  
  26. #include <errno.h>
  27.  
  28. #if HAVE_LIMITS_H
  29. #include <limits.h>
  30. #endif
  31.  
  32. #if HAVE_SYS_PARAM_H
  33. #include <sys/param.h>
  34. #endif
  35.  
  36. #if HAVE_OPENDIR
  37. #if HAVE_DIRENT_H
  38. #include <dirent.h>
  39. #else /* ! HAVE_DIRENT_H */
  40. #include <sys/dir.h>
  41. #define dirent direct
  42. #endif /* ! HAVE_DIRENT_H */
  43. #endif /* HAVE_OPENDIR */
  44.  
  45. #if HAVE_FTW_H
  46. #include <ftw.h>
  47. #endif
  48.  
  49. #ifndef PATH_MAX
  50. #ifdef MAXPATHLEN
  51. #define PATH_MAX MAXPATHLEN
  52. #else
  53. #define PATH_MAX 1024
  54. #endif
  55. #endif
  56.  
  57. /* Traverse one level of a directory tree.  */
  58.  
  59. static int
  60. ftw_dir (dirs, level, descriptors, dir, len, func)
  61.      DIR **dirs;
  62.      int level;
  63.      int descriptors;
  64.      char *dir;
  65.      size_t len;
  66.      int (*func) P((const char *file, const struct stat *status, int flag));
  67. {
  68.   int got;
  69.   struct dirent *entry;
  70.  
  71.   got = 0;
  72.  
  73.   errno = 0;
  74.  
  75.   while ((entry = readdir (dirs[level])) != NULL)
  76.     {
  77.       size_t namlen;
  78.       struct stat s;
  79.       int flag, ret, newlev;
  80.  
  81.       ++got;
  82.  
  83.       namlen = strlen (entry->d_name);
  84.       if (entry->d_name[0] == '.'
  85.       && (namlen == 1 ||
  86.           (namlen == 2 && entry->d_name[1] == '.')))
  87.     {
  88.       errno = 0;
  89.       continue;
  90.     }
  91.  
  92.       if (namlen + len + 1 > PATH_MAX)
  93.     {
  94. #ifdef ENAMETOOLONG
  95.       errno = ENAMETOOLONG;
  96. #else
  97.       errno = ENOMEM;
  98. #endif
  99.       return -1;
  100.     }
  101.  
  102.       dir[len] = '/';
  103.       memcpy ((dir + len + 1), entry->d_name, namlen + 1);
  104.  
  105.       if (stat (dir, &s) < 0)
  106.     {
  107.       if (errno != EACCES)
  108.         return -1;
  109.       flag = FTW_NS;
  110.     }
  111.       else if (S_ISDIR (s.st_mode))
  112.     {
  113.       newlev = (level + 1) % descriptors;
  114.  
  115.       if (dirs[newlev] != NULL)
  116.         closedir (dirs[newlev]);
  117.  
  118.       dirs[newlev] = opendir (dir);
  119.       if (dirs[newlev] != NULL)
  120.         flag = FTW_D;
  121.       else
  122.         {
  123.           if (errno != EACCES)
  124.         return -1;
  125.           flag = FTW_DNR;
  126.         }
  127.     }
  128.       else
  129.     flag = FTW_F;
  130.  
  131.       ret = (*func) (dir, &s, flag);
  132.  
  133.       if (flag == FTW_D)
  134.     {
  135.       if (ret == 0)
  136.         ret = ftw_dir (dirs, newlev, descriptors, dir,
  137.                namlen + len + 1, func);
  138.       if (dirs[newlev] != NULL)
  139.         {
  140.           int save;
  141.  
  142.           save = errno;
  143.           closedir (dirs[newlev]);
  144.           errno = save;
  145.           dirs[newlev] = NULL;
  146.         }
  147.     }
  148.  
  149.       if (ret != 0)
  150.     return ret;
  151.  
  152.       if (dirs[level] == NULL)
  153.     {
  154.       int skip;
  155.  
  156.       dir[len] = '\0';
  157.       dirs[level] = opendir (dir);
  158.       if (dirs[level] == NULL)
  159.         return -1;
  160.       skip = got;
  161.       while (skip-- != 0)
  162.         {
  163.           errno = 0;
  164.           if (readdir (dirs[level]) == NULL)
  165.         return errno == 0 ? 0 : -1;
  166.         }
  167.     }
  168.  
  169.       errno = 0;
  170.     }
  171.  
  172.   return errno == 0 ? 0 : -1;
  173. }
  174.  
  175. /* Call a function on every element in a directory tree.  */
  176.  
  177. int
  178. ftw (dir, func, descriptors)
  179.      const char *dir;
  180.      int (*func) P((const char *file, const struct stat *status, int flag));
  181.      int descriptors;
  182. {
  183.   DIR **dirs;
  184.   int c;
  185.   DIR **p;
  186.   size_t len;
  187.   char buf[PATH_MAX + 1];
  188.   struct stat s;
  189.   int flag, ret;
  190.  
  191.   if (descriptors <= 0)
  192.     descriptors = 1;
  193.  
  194.   dirs = (DIR **) malloc (descriptors * sizeof (DIR *));
  195.   if (dirs == NULL)
  196.     return -1;
  197.   c = descriptors;
  198.   p = dirs;
  199.   while (c-- != 0)
  200.     *p++ = NULL;
  201.  
  202.   len = strlen (dir);
  203.   memcpy (buf, dir, len + 1);
  204.  
  205.   if (stat (dir, &s) < 0)
  206.     {
  207.       if (errno != EACCES)
  208.     {
  209.       free ((pointer) dirs);
  210.       return -1;
  211.     }
  212.       flag = FTW_NS;
  213.     }
  214.   else if (S_ISDIR (s.st_mode))
  215.     {
  216.       dirs[0] = opendir (dir);
  217.       if (dirs[0] != NULL)
  218.     flag = FTW_D;
  219.       else
  220.     {
  221.       if (errno != EACCES)
  222.         {
  223.           free ((pointer) dirs);
  224.           return -1;
  225.         }
  226.       flag = FTW_DNR;
  227.     }
  228.     }
  229.   else
  230.     flag = FTW_F;
  231.  
  232.   ret = (*func) (buf, &s, flag);
  233.  
  234.   if (flag == FTW_D)
  235.     {
  236.       if (ret == 0)
  237.     ret = ftw_dir (dirs, 0, descriptors, buf, len, func);
  238.       if (dirs[0] != NULL)
  239.     {
  240.       int save;
  241.  
  242.       save = errno;
  243.       closedir (dirs[0]);
  244.       errno = save;
  245.     }
  246.     }
  247.  
  248.   free ((pointer) dirs);
  249.   return ret;
  250. }
  251.