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 int got;
00062 struct dirent *entry;
00063 int d_namlen;
00064
00065 got = 0;
00066
00067 errno = 0;
00068
00069 while ((entry = Readdir (dirs[level])) != NULL)
00070 {
00071 struct stat s;
00072 int flag, retval, newlev = 0;
00073
00074 ++got;
00075
00076 if (entry->d_name[0] == '.'
00077 && (entry->d_name [1] == '\0' ||
00078 (entry->d_name [2] == '\0' && entry->d_name[1] == '.')))
00079 {
00080 errno = 0;
00081 continue;
00082 }
00083
00084 d_namlen = NAMLEN(entry) + 1;
00085 if (d_namlen + len > PATH_MAX)
00086 {
00087 #ifdef ENAMETOOLONG
00088 errno = ENAMETOOLONG;
00089 #else
00090 errno = ENOMEM;
00091 #endif
00092 return -1;
00093 }
00094
00095 dir[len] = '/';
00096 memcpy ((void *) (dir + len + 1), (void *) entry->d_name, d_namlen);
00097
00098 if (Lstat (dir, &s) < 0)
00099 {
00100
00101
00102
00103
00104 if (errno != EACCES && errno != ENOENT)
00105 return -1;
00106 flag = MYFTW_NS;
00107 }
00108 else if (S_ISDIR (s.st_mode))
00109 {
00110 newlev = (level + 1) % descriptors;
00111
00112
00113 if (dirs[newlev] != NULL)
00114 (void) Closedir (dirs[newlev]);
00115
00116
00117 dirs[newlev] = Opendir (dir);
00118 if (dirs[newlev] != NULL)
00119 flag = MYFTW_D;
00120 else
00121 {
00122 if (errno != EACCES)
00123 return -1;
00124 flag = MYFTW_DNR;
00125 }
00126 }
00127 else
00128 flag = MYFTW_F;
00129
00130
00131 retval = (*func) (fl, dir, &s);
00132
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 (DIR *));
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
00229 retval = (*func) (fl, buf, &s);
00230
00231
00232 if (flag == MYFTW_D)
00233 {
00234 if (retval == 0)
00235 retval = myftw_dir (dirs, 0, descriptors, buf, len, func, fl);
00236 if (dirs[0] != NULL)
00237 {
00238 int save;
00239
00240 save = errno;
00241 (void) Closedir (dirs[0]);
00242 errno = save;
00243 }
00244 }
00245
00246 return retval;
00247 }