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