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@*/