00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
00046
00047 #include "myftw.h"
00048 #include "debug.h"
00049
00050
00051
00054
00055 static int
00056 myftw_dir (DIR **dirs, int level, int descriptors,
00057 char *dir, size_t len,
00058 myftwFunc func,
00059 void *fl)
00060
00061
00062 {
00063 int got;
00064 struct dirent *entry;
00065 int d_namlen;
00066
00067 got = 0;
00068
00069 errno = 0;
00070
00071 while ((entry = Readdir (dirs[level])) != NULL)
00072 {
00073 struct stat s;
00074 int flag, retval, newlev = 0;
00075
00076 ++got;
00077
00078 if (entry->d_name[0] == '.'
00079 && (entry->d_name [1] == '\0' ||
00080 (entry->d_name [2] == '\0' && entry->d_name[1] == '.')))
00081 {
00082 errno = 0;
00083 continue;
00084 }
00085
00086 d_namlen = NAMLEN(entry) + 1;
00087 if (d_namlen + len > PATH_MAX)
00088 {
00089 #ifdef ENAMETOOLONG
00090 errno = ENAMETOOLONG;
00091 #else
00092 errno = ENOMEM;
00093 #endif
00094 return -1;
00095 }
00096
00097 dir[len] = '/';
00098 memcpy ((void *) (dir + len + 1), (void *) entry->d_name, d_namlen);
00099
00100 if (Lstat (dir, &s) < 0)
00101 {
00102
00103
00104
00105
00106 if (errno != EACCES && errno != ENOENT)
00107 return -1;
00108 flag = MYFTW_NS;
00109 }
00110 else if (S_ISDIR (s.st_mode))
00111 {
00112 newlev = (level + 1) % descriptors;
00113
00114
00115 if (dirs[newlev] != NULL)
00116 (void) Closedir (dirs[newlev]);
00117
00118
00119 dirs[newlev] = Opendir (dir);
00120 if (dirs[newlev] != NULL)
00121 flag = MYFTW_D;
00122 else
00123 {
00124 if (errno != EACCES)
00125 return -1;
00126 flag = MYFTW_DNR;
00127 }
00128 }
00129 else
00130 flag = MYFTW_F;
00131
00132 retval = (*func) (fl, dir, &s);
00133
00134 if (flag == MYFTW_D)
00135 {
00136 if (retval == 0)
00137 retval = myftw_dir (dirs, newlev, descriptors, dir,
00138 d_namlen + len, func, fl);
00139 if (dirs[newlev] != NULL)
00140 {
00141 int save;
00142
00143 save = errno;
00144 (void) Closedir (dirs[newlev]);
00145 errno = save;
00146 dirs[newlev] = NULL;
00147 }
00148 }
00149
00150 if (retval != 0)
00151 return retval;
00152
00153 if (dirs[level] == NULL)
00154 {
00155 int skip;
00156
00157 dir[len] = '\0';
00158 dirs[level] = Opendir (dir);
00159 if (dirs[level] == NULL)
00160 return -1;
00161 skip = got;
00162 while (skip-- != 0)
00163 {
00164 errno = 0;
00165 if (Readdir (dirs[level]) == NULL)
00166 return errno == 0 ? 0 : -1;
00167 }
00168 }
00169
00170 errno = 0;
00171 }
00172
00173 return errno == 0 ? 0 : -1;
00174 }
00175
00176
00177
00178
00179 int myftw (const char *dir,
00180 int descriptors,
00181 myftwFunc func,
00182 void *fl)
00183 {
00184 DIR **dirs;
00185 size_t len;
00186 char buf[PATH_MAX + 1];
00187 struct stat s;
00188 int flag, retval;
00189 int i;
00190
00191 if (descriptors <= 0)
00192 descriptors = 1;
00193
00194
00195 dirs = (DIR **) alloca (descriptors * sizeof (*dirs));
00196 i = descriptors;
00197 while (i-- > 0)
00198 dirs[i] = NULL;
00199
00200 if (Lstat (dir, &s) < 0)
00201 {
00202
00203
00204
00205
00206 if (errno != EACCES && errno != ENOENT)
00207 return -1;
00208 flag = MYFTW_NS;
00209 }
00210 else if (S_ISDIR (s.st_mode))
00211 {
00212 dirs[0] = Opendir (dir);
00213 if (dirs[0] != NULL)
00214 flag = MYFTW_D;
00215 else
00216 {
00217 if (errno != EACCES)
00218 return -1;
00219 flag = MYFTW_DNR;
00220 }
00221 }
00222 else
00223 flag = MYFTW_F;
00224
00225 len = strlen (dir);
00226 memcpy ((void *) buf, (void *) dir, len + 1);
00227
00228 retval = (*func) (fl, buf, &s);
00229
00230 if (flag == MYFTW_D)
00231 {
00232 if (retval == 0)
00233 retval = myftw_dir (dirs, 0, descriptors, buf, len, func, fl);
00234 if (dirs[0] != NULL)
00235 {
00236 int save;
00237
00238 save = errno;
00239 (void) Closedir (dirs[0]);
00240
00241 errno = save;
00242
00243 }
00244 }
00245
00246 return retval;
00247 }