home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Source / GNU / uucp / Uucp.framework / unix.subproj / ftw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-09  |  4.7 KB  |  255 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., 59 Temple Place -
  18. Suite 330, Boston, MA 02111-1307, USA.
  19.  
  20. Modified by Ian Lance Taylor for Taylor UUCP, June 1992, and October 1993.  */
  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, 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 = 0;
  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, 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.     {
  238.       if (len == 1 && *buf == '/')
  239.         len = 0;
  240.       ret = ftw_dir (dirs, 0, descriptors, buf, len, func);
  241.     }
  242.       if (dirs[0] != NULL)
  243.     {
  244.       int save;
  245.  
  246.       save = errno;
  247.       closedir (dirs[0]);
  248.       errno = save;
  249.     }
  250.     }
  251.  
  252.   free ((pointer) dirs);
  253.   return ret;
  254. }
  255.