Main Page   Modules   Data Structures   File List   Data Fields   Globals   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 #if !defined(__LCLINT__)
00034 #ifndef PATH_MAX
00035 #ifdef _POSIX_VERSION
00036 #define PATH_MAX _POSIX_PATH_MAX
00037 #else
00038 #ifdef MAXPATHLEN
00039 #define PATH_MAX MAXPATHLEN
00040 #else
00041 #define PATH_MAX 1024
00042 #endif
00043 #endif
00044 #endif
00045 #endif  /* !__LCLINT */
00046 
00047 #include "myftw.h"
00048 #include "debug.h"
00049 
00050 /* Traverse one level of a directory tree.  */
00051 
00054 /*@-boundswrite@*/
00055 /*@-nullstate@*/
00056 static int
00057 myftw_dir (DIR **dirs, int level, int descriptors,
00058            char *dir, size_t len, 
00059            myftwFunc func,
00060            void *fl)
00061         /*@globals errno, fileSystem, internalState @*/
00062         /*@modifies *dirs, *dir, errno, fileSystem, internalState @*/
00063 {
00064   int got;
00065   struct dirent *entry;
00066   int d_namlen;
00067 
00068   got = 0;
00069 
00070   errno = 0;
00071 
00072   while ((entry = Readdir (dirs[level])) != NULL)
00073     {
00074       struct stat s;
00075       int flag, retval, newlev = 0;
00076 
00077       ++got;
00078 
00079       if (entry->d_name[0] == '.'
00080           && (entry->d_name [1] == '\0' ||
00081               (entry->d_name [2] == '\0' && entry->d_name[1] == '.')))
00082         {
00083           errno = 0;
00084           continue;
00085         }
00086 
00087       d_namlen = NAMLEN(entry) + 1;
00088       if (d_namlen + len > PATH_MAX)
00089         {
00090 #ifdef ENAMETOOLONG
00091           errno = ENAMETOOLONG;
00092 #else
00093           errno = ENOMEM;
00094 #endif
00095           return -1;
00096         }
00097 
00098       dir[len] = '/';
00099       memcpy ((void *) (dir + len + 1), (void *) entry->d_name, d_namlen);
00100 
00101       if (Lstat (dir, &s) < 0)
00102         {
00103           /* Following POSIX.1 2.4 ENOENT is returned if the file cannot
00104            * be stat'ed.  This can happen for a file returned by Readdir
00105            * if it's an unresolved symbolic link.  This should be regarded
00106            * as an forgivable error.  -- Uli.  */
00107           if (errno != EACCES && errno != ENOENT)
00108             return -1;
00109           flag = MYFTW_NS;
00110         }
00111       else if (S_ISDIR (s.st_mode))
00112         {
00113           newlev = (level + 1) % descriptors;
00114 
00115           /*@-unqualifiedtrans@*/
00116           if (dirs[newlev] != NULL)
00117             (void) Closedir (dirs[newlev]);
00118           /*@=unqualifiedtrans@*/
00119 
00120           dirs[newlev] = Opendir (dir);
00121           if (dirs[newlev] != NULL)
00122             flag = MYFTW_D;
00123           else
00124             {
00125               if (errno != EACCES)
00126                 return -1;
00127               flag = MYFTW_DNR;
00128             }
00129         }
00130       else
00131         flag = MYFTW_F;
00132 
00133       retval = (*func) (fl, dir, &s);
00134 
00135       if (flag == MYFTW_D)
00136         {
00137           if (retval == 0)
00138             retval = myftw_dir (dirs, newlev, descriptors, dir,
00139                                 d_namlen + len, func, fl);
00140           if (dirs[newlev] != NULL)
00141             {
00142               int save;
00143 
00144               save = errno;
00145               (void) Closedir (dirs[newlev]);
00146               errno = save;
00147               dirs[newlev] = NULL;
00148             }
00149         }
00150 
00151       if (retval != 0)
00152         return retval;
00153 
00154       if (dirs[level] == NULL)
00155         {
00156           int skip;
00157 
00158           dir[len] = '\0';
00159           dirs[level] = Opendir (dir);
00160           if (dirs[level] == NULL)
00161             return -1;
00162           skip = got;
00163           while (skip-- != 0)
00164             {
00165               errno = 0;
00166               if (Readdir (dirs[level]) == NULL)
00167                 return errno == 0 ? 0 : -1;
00168             }
00169         }
00170 
00171       errno = 0;
00172     }
00173 
00174   return errno == 0 ? 0 : -1;
00175 }
00176 /*@=nullstate@*/
00177 /*@=boundswrite@*/
00178 
00179 /* Call a function on every element in a directory tree.  */
00180 
00181 /*@-bounds@*/
00182 int myftw (const char *dir,
00183            int descriptors,
00184            myftwFunc func,
00185            void *fl)
00186 {
00187   DIR **dirs;
00188   size_t len;
00189   char buf[PATH_MAX + 1];
00190   struct stat s;
00191   int flag, retval;
00192   int i;
00193 
00194   if (descriptors <= 0)
00195     descriptors = 1;
00196 
00197   /*@access DIR@*/
00198   dirs = (DIR **) alloca (descriptors * sizeof (*dirs));
00199   i = descriptors;
00200   while (i-- > 0)
00201     dirs[i] = NULL;
00202 
00203   if (Lstat (dir, &s) < 0)
00204     {
00205       /* Following POSIX.1 2.4 ENOENT is returned if the file cannot
00206        * be stat'ed.  This can happen for a file returned by Readdir
00207        * if it's an unresolved symbolic link.  This should be regarded
00208        * as an forgivable error.  -- Uli.  */
00209       if (errno != EACCES && errno != ENOENT)
00210         return -1;
00211       flag = MYFTW_NS;
00212     }
00213   else if (S_ISDIR (s.st_mode))
00214     {
00215       dirs[0] = Opendir (dir);
00216       if (dirs[0] != NULL)
00217         flag = MYFTW_D;
00218       else
00219         {
00220           if (errno != EACCES)
00221             return -1;
00222           flag = MYFTW_DNR;
00223         }
00224     }
00225   else
00226     flag = MYFTW_F;
00227 
00228   len = strlen (dir);
00229   memcpy ((void *) buf, (void *) dir, len + 1);
00230 
00231   retval = (*func) (fl, buf, &s);
00232 
00233   if (flag == MYFTW_D)
00234     {
00235 /*@-compdef@*/ /* FIX: *dirs not defined */
00236       if (retval == 0)
00237         retval = myftw_dir (dirs, 0, descriptors, buf, len, func, fl);
00238       if (dirs[0] != NULL)
00239         {
00240           int save;
00241 
00242           save = errno;
00243           (void) Closedir (dirs[0]);
00244           /*@-mods@*/
00245           errno = save;
00246           /*@=mods@*/
00247         }
00248 /*@=compdef@*/
00249     }
00250 
00251   return retval;
00252 }
00253 /*@=bounds@*/

Generated on Tue Sep 17 15:56:38 2002 for rpm by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002