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
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
00062
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
00104
00105
00106
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
00116 if (dirs[newlev] != NULL)
00117 (void) Closedir (dirs[newlev]);
00118
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
00177
00178
00179
00180
00181
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
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
00206
00207
00208
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
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
00245 errno = save;
00246
00247 }
00248
00249 }
00250
00251 return retval;
00252 }
00253