115
115
int (*call_back)(const char* filepath, int type, void* data),
116
116
int options, int max_depth, void* call_back_data)
118
dir_entry *dirs_stack = NULL; /* root of the dir_list */
122
struct rsh_stat_struct st;
124
if(max_depth < 0 || max_depth >= MAX_DIRS_DEPTH) {
125
max_depth = MAX_DIRS_DEPTH;
127
/* skip the directory if max_depth == 0 */
132
/* check that start_dir is a drectory */
133
if(rsh_stat(start_dir, &st) < 0) {
134
return -1; /* errno is already set by stat */
136
if( !S_ISDIR(st.st_mode) ) {
142
const char* cur_dirpath;
143
if( options&FIND_CHDIR ) {
144
cur_dirpath = getcwd(NULL, 2);
148
if( options&FIND_CHDIR ) {
153
/* check if we should descend into the root directory */
154
if( !(options&FIND_WALK_DEPTH_FIRST)
155
&& !call_back(start_dir, FIND_IFDIR | FIND_IFFIRST, call_back_data)) {
159
it = (dir_iterator*)malloc(MAX_DIRS_DEPTH*sizeof(dir_iterator));
162
/* push root directory into dirs_stack */
164
it[0].prev_dir = rsh_strdup(start_dir);
165
it[1].prev_dir = NULL;
166
if(!it[0].prev_dir) {
170
entry = dir_entry_insert(&dirs_stack, NULL, 0);
172
free(it[0].prev_dir);
179
dir_entry *dir, **insert_at;
185
while((--level) >= 0 && it[level].left <= 0) free(it[level+1].prev_dir);
187
assert(dirs_stack != NULL);
188
/* on the first cycle: level == 0, stack[0] == 0; */
190
dir = dirs_stack; /* take last dir from the list */
191
dirs_stack = dirs_stack->next; /* remove last dir from the list */
194
dir_path = (!dir->filename ? rsh_strdup(it[level].prev_dir) :
195
make_path(it[level].prev_dir, dir->filename) );
197
if(!dir_path) continue;
201
it[level].prev_dir = dir_path;
203
if( options&FIND_WALK_DEPTH_FIRST ) {
204
/* check if we should skip the directory */
205
if( !call_back(dir_path, FIND_IFDIR, call_back_data) )
210
dp = opendir(dir_path);
211
if(dp == NULL) continue;
213
insert_at = &dirs_stack;
215
while((de = readdir(dp)) != NULL) {
218
/* skip "." and ".." dirs */
219
if(de->d_name[0] == '.' && (de->d_name[1] == 0 ||
220
(de->d_name[1] == '.' && de->d_name[2] == 0 )))
223
if( !(path = make_path(dir_path, de->d_name)) ) continue;
118
dir_entry *dirs_stack = NULL; /* root of the dir_list */
122
struct rsh_stat_struct st;
124
if(max_depth < 0 || max_depth >= MAX_DIRS_DEPTH) {
125
max_depth = MAX_DIRS_DEPTH;
127
/* skip the directory if max_depth == 0 */
132
/* check that start_dir is a drectory */
133
if(rsh_stat(start_dir, &st) < 0) {
134
return -1; /* errno is already set by stat */
136
if( !S_ISDIR(st.st_mode) ) {
141
/* check if we should descend into the root directory */
142
if( !(options&FIND_WALK_DEPTH_FIRST)
143
&& !call_back(start_dir, FIND_IFDIR | FIND_IFFIRST, call_back_data)) {
147
it = (dir_iterator*)malloc(MAX_DIRS_DEPTH*sizeof(dir_iterator));
150
/* push root directory into dirs_stack */
152
it[0].prev_dir = rsh_strdup(start_dir);
153
it[1].prev_dir = NULL;
154
if(!it[0].prev_dir) {
158
entry = dir_entry_insert(&dirs_stack, NULL, 0);
160
free(it[0].prev_dir);
167
dir_entry *dir, **insert_at;
173
while((--level) >= 0 && it[level].left <= 0) free(it[level+1].prev_dir);
175
assert(dirs_stack != NULL);
176
/* on the first cycle: level == 0, stack[0] == 0; */
178
dir = dirs_stack; /* take last dir from the list */
179
dirs_stack = dirs_stack->next; /* remove last dir from the list */
182
dir_path = (!dir->filename ? rsh_strdup(it[level].prev_dir) :
183
make_path(it[level].prev_dir, dir->filename) );
185
if(!dir_path) continue;
189
it[level].prev_dir = dir_path;
191
if( options&FIND_WALK_DEPTH_FIRST ) {
192
/* check if we should skip the directory */
193
if( !call_back(dir_path, FIND_IFDIR, call_back_data) )
198
dp = opendir(dir_path);
199
if(dp == NULL) continue;
201
insert_at = &dirs_stack;
203
while((de = readdir(dp)) != NULL) {
206
/* skip "." and ".." dirs */
207
if(de->d_name[0] == '.' && (de->d_name[1] == 0 ||
208
(de->d_name[1] == '.' && de->d_name[2] == 0 )))
211
if( !(path = make_path(dir_path, de->d_name)) ) continue;
225
213
#ifndef USE_LSTAT_FOR_SYMLINKS
226
if(rsh_stat(path, &st) < 0) {
214
if(rsh_stat(path, &st) < 0) {
231
res = (options & FIND_FOLLOW_LINKS ? rsh_stat(path, &st) : lstat(path, &st));
232
/*if((st.st_mode&S_IFMT) == S_IFLNK) type |= FIND_IFLNK;*/
233
if(res < 0 || (!(options & FIND_FOLLOW_LINKS) && S_ISLNK(st.st_mode)) ) {
219
res = (options & FIND_FOLLOW_LINKS ? rsh_stat(path, &st) : lstat(path, &st));
220
/*if((st.st_mode&S_IFMT) == S_IFLNK) type |= FIND_IFLNK;*/
221
if(res < 0 || (!(options & FIND_FOLLOW_LINKS) && S_ISLNK(st.st_mode)) ) {
239
227
/* check bits (the check fails for gcc -ansi) */
241
229
# error wrong bits for S_IFMT and S_IFDIR
244
/*type |= (S_ISDIR(st.st_mode) ? FIND_IFDIR : 0);*/
245
type |= ((st.st_mode >> 12) & 0x0f);
247
if((type & FIND_IFDIR) && (options & FIND_WALK_DEPTH_FIRST)) res = 1;
249
/* handle file by callback function */
250
res = call_back(path, type, call_back_data);
254
/* if file is a directory and we need to walk it */
255
if((type & FIND_IFDIR) && res && level < max_depth) {
256
/* don't go deeper if max_depth reached */
258
/* add directory to dirs_stack */
259
if( dir_entry_insert(insert_at, de->d_name, type) ) {
260
/* if really added */
261
insert_at = &((*insert_at)->next);
265
type = 0; /* clear FIND_IFFIRST flag */
269
if(it[level].left > 0) level++;
271
assert(dirs_stack == NULL);
232
/*type |= (S_ISDIR(st.st_mode) ? FIND_IFDIR : 0);*/
233
type |= ((st.st_mode >> 12) & 0x0f);
235
if((type & FIND_IFDIR) && (options & FIND_WALK_DEPTH_FIRST)) res = 1;
237
/* handle file by callback function */
238
res = call_back(path, type, call_back_data);
242
/* if file is a directory and we need to walk it */
243
if((type & FIND_IFDIR) && res && level < max_depth) {
244
/* don't go deeper if max_depth reached */
246
/* add directory to dirs_stack */
247
if( dir_entry_insert(insert_at, de->d_name, type) ) {
248
/* if really added */
249
insert_at = &((*insert_at)->next);
253
type = 0; /* clear FIND_IFFIRST flag */
257
if(it[level].left > 0) level++;
259
assert(dirs_stack == NULL);