Main Page   Modules   Compound List   File List   Compound Members   File Members   Related Pages  

build/myftw.c

Go to the documentation of this file.
00001 
00006 /* Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
00007 This file is part of the GNU C Library.
00008 Contributed by Ian Lance Taylor (ian@airs.com).
00009 
00010 The GNU C Library is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU Library General Public License as
00012 published by the Free Software Foundation; either version 2 of the
00013 License, or (at your option) any later version.
00014 
00015 The GNU C Library is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 Library General Public License for more details.
00019 
00020 You should have received a copy of the GNU Library General Public
00021 License along with the GNU C Library; see the file COPYING.LIB.  If
00022 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
00023 Cambridge, MA 02139, USA.  */
00024 
00025 #include "system.h"
00026 
00027 #include <rpmio.h>
00028 
00029 #ifndef NAMLEN
00030 #define NAMLEN(a) strlen((a)->d_name)
00031 #endif
00032 
00033 #ifndef PATH_MAX
00034 #ifdef _POSIX_VERSION
00035 #define PATH_MAX _POSIX_PATH_MAX
00036 #else
00037 #ifdef MAXPATHLEN
00038 #define PATH_MAX MAXPATHLEN
00039 #else
00040 #define PATH_MAX 1024
00041 #endif
00042 #endif
00043 #endif
00044 
00045 #include "myftw.h"
00046 #include "debug.h"
00047 
00048 /* Traverse one level of a directory tree.  */
00049 
00052 static int
00053 myftw_dir (DIR **dirs, int level, int descriptors,
00054            char *dir, size_t len, 
00055            myftwFunc func,
00056            void *fl)
00057 {
00058   int got;
00059   struct dirent *entry;
00060   int d_namlen;
00061 
00062   got = 0;
00063 
00064   errno = 0;
00065 
00066   while ((entry = Readdir (dirs[level])) != NULL)
00067     {
00068       struct stat s;
00069       int flag, retval, newlev = 0;
00070 
00071       ++got;
00072 
00073       if (entry->d_name[0] == '.'
00074           && (entry->d_name [1] == '\0' ||
00075               (entry->d_name [2] == '\0' && entry->d_name[1] == '.')))
00076         {
00077           errno = 0;
00078           continue;
00079         }
00080 
00081       d_namlen = NAMLEN(entry) + 1;
00082       if (d_namlen + len > PATH_MAX)
00083         {
00084 #ifdef ENAMETOOLONG
00085           errno = ENAMETOOLONG;
00086 #else
00087           errno = ENOMEM;
00088 #endif
00089           return -1;
00090         }
00091 
00092       dir[len] = '/';
00093       memcpy ((void *) (dir + len + 1), (void *) entry->d_name, d_namlen);
00094 
00095       if (Lstat (dir, &s) < 0)
00096         {
00097           /* Following POSIX.1 2.4 ENOENT is returned if the file cannot
00098            * be stat'ed.  This can happen for a file returned by Readdir
00099            * if it's an unresolved symbolic link.  This should be regarded
00100            * as an forgivable error.  -- Uli.  */
00101           if (errno != EACCES && errno != ENOENT)
00102             return -1;
00103           flag = MYFTW_NS;
00104         }
00105       else if (S_ISDIR (s.st_mode))
00106         {
00107           newlev = (level + 1) % descriptors;
00108 
00109           if (dirs[newlev] != NULL)
00110             Closedir (dirs[newlev]);
00111 
00112           dirs[newlev] = Opendir (dir);
00113           if (dirs[newlev] != NULL)
00114             flag = MYFTW_D;
00115           else
00116             {
00117               if (errno != EACCES)
00118                 return -1;
00119               flag = MYFTW_DNR;
00120             }
00121         }
00122       else
00123         flag = MYFTW_F;
00124 
00125       retval = (*func) (fl, dir, &s);
00126 
00127       if (flag == MYFTW_D)
00128         {
00129           if (retval == 0)
00130             retval = myftw_dir (dirs, newlev, descriptors, dir,
00131                                 d_namlen + len, func, fl);
00132           if (dirs[newlev] != NULL)
00133             {
00134               int save;
00135 
00136               save = errno;
00137               Closedir (dirs[newlev]);
00138               errno = save;
00139               dirs[newlev] = NULL;
00140             }
00141         }
00142 
00143       if (retval != 0)
00144         return retval;
00145 
00146       if (dirs[level] == NULL)
00147         {
00148           int skip;
00149 
00150           dir[len] = '\0';
00151           dirs[level] = Opendir (dir);
00152           if (dirs[level] == NULL)
00153             return -1;
00154           skip = got;
00155           while (skip-- != 0)
00156             {
00157               errno = 0;
00158               if (Readdir (dirs[level]) == NULL)
00159                 return errno == 0 ? 0 : -1;
00160             }
00161         }
00162 
00163       errno = 0;
00164     }
00165 
00166   return errno == 0 ? 0 : -1;
00167 }
00168 
00169 /* Call a function on every element in a directory tree.  */
00170 
00171 int myftw (const char *dir,
00172            int descriptors,
00173            myftwFunc func,
00174            void *fl)
00175 {
00176   DIR **dirs;
00177   size_t len;
00178   char buf[PATH_MAX + 1];
00179   struct stat s;
00180   int flag, retval;
00181   int i;
00182 
00183   if (descriptors <= 0)
00184     descriptors = 1;
00185 
00186   /*@access DIR@*/
00187   dirs = (DIR **) alloca (descriptors * sizeof (DIR *));
00188   i = descriptors;
00189   while (i-- > 0)
00190     dirs[i] = NULL;
00191 
00192   if (Lstat (dir, &s) < 0)
00193     {
00194       /* Following POSIX.1 2.4 ENOENT is returned if the file cannot
00195        * be stat'ed.  This can happen for a file returned by Readdir
00196        * if it's an unresolved symbolic link.  This should be regarded
00197        * as an forgivable error.  -- Uli.  */
00198       if (errno != EACCES && errno != ENOENT)
00199         return -1;
00200       flag = MYFTW_NS;
00201     }
00202   else if (S_ISDIR (s.st_mode))
00203     {
00204       dirs[0] = Opendir (dir);
00205       if (dirs[0] != NULL)
00206         flag = MYFTW_D;
00207       else
00208         {
00209           if (errno != EACCES)
00210             return -1;
00211           flag = MYFTW_DNR;
00212         }
00213     }
00214   else
00215     flag = MYFTW_F;
00216 
00217   len = strlen (dir);
00218   memcpy ((void *) buf, (void *) dir, len + 1);
00219 
00220   retval = (*func) (fl, buf, &s);
00221 
00222   if (flag == MYFTW_D)
00223     {
00224       if (retval == 0)
00225         retval = myftw_dir (dirs, 0, descriptors, buf, len, func, fl);
00226       if (dirs[0] != NULL)
00227         {
00228           int save;
00229 
00230           save = errno;
00231           Closedir (dirs[0]);
00232           errno = save;
00233         }
00234     }
00235 
00236   return retval;
00237 }

Generated at Sun Apr 8 18:42:58 2001 for rpm by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000