Definition in file new_ftw.c.
#include <dirent.h>
#include <errno.h>
#include "new_ftw.h"
#include <limits.h>
#include <search.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <assert.h>
#include <stdio.h>
Go to the source code of this file.
Classes | |
| struct | dir_data |
| struct | known_object |
| struct | new_ftw_data |
Defines | |
| #define | dirent direct |
| #define | NAMLEN(dirent) (dirent)->d_namlen |
| #define | NAMLEN(dirent) strlen ((dirent)->d_name) |
| #define | mempcpy(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N))) |
| #define | __chdir chdir |
| #define | __closedir closedir |
| #define | __fchdir fchdir |
| #define | __getcwd(P, N) xgetcwd () |
| #define | __mempcpy mempcpy |
| #define | __opendir opendir |
| #define | __readdir64 readdir |
| #define | __stpcpy stpcpy |
| #define | __tdestroy tdestroy |
| #define | __tfind tfind |
| #define | __tsearch tsearch |
| #define | internal_function |
| #define | dirent64 dirent |
| #define | MAX(a, b) ((a) > (b) ? (a) : (b)) |
| #define | lstat(Name, Stat_buf) rpl_lstat(Name, Stat_buf) |
| #define | __set_errno(Val) errno = (Val) |
| #define | NEW_FTW_NAME new_ftw |
| #define | NEW_NFTW_NAME new_nftw |
| #define | NEW_NFTW_OLD_NAME __new_old_nftw |
| #define | NEW_NFTW_NEW_NAME __new_new_nftw |
| #define | INO_T ino_t |
| #define | STAT stat |
| #define | LXSTAT(V, f, sb) lstat (f,sb) |
| #define | XSTAT(V, f, sb) stat (f,sb) |
| #define | NEW_FTW_FUNC_T __new_ftw_func_t |
| #define | NEW_NFTW_FUNC_T __new_nftw_func_t |
| #define | PATH_MAX 1024 |
Functions | |
| char * | alloca () |
| char * | stpcpy () |
| char * | xgetcwd (void) |
| int | rpl_lstat (const char *, struct stat *) |
| int | ftw_dir (struct new_ftw_data *data, struct STAT *st, struct dir_data *old_dir) internal_function |
| int | object_compare (const void *p1, const void *p2) |
| int | add_object (struct new_ftw_data *data, struct STAT *st) |
| int | find_object (struct new_ftw_data *data, struct STAT *st) |
| int | __attribute ((always_inline)) |
| int internal_function | process_entry (struct new_ftw_data *data, struct dir_data *dir, const char *name, size_t namlen) |
| int | __attribute ((noinline)) |
| int | NEW_FTW_NAME (char *path, NEW_FTW_FUNC_T func, int descriptors, void *data) const |
| int | NEW_NFTW_NAME (char *path, NEW_NFTW_FUNC_T func, int descriptors, int flags, void *data) const |
| int | rpl_lstat (char *file, struct stat *sbuf) const |
Variables | |
| const int | nftw_arr [] |
| const int | ftw_arr [] |
|
|
|
|
|
Definition at line 69 of file new_ftw.c. Referenced by __attribute(). |
|
|
|
|
|
|
|
|
Definition at line 101 of file new_ftw.c. Referenced by __attribute(). |
|
|
Definition at line 103 of file new_ftw.c. Referenced by __attribute(). |
|
|
Definition at line 105 of file new_ftw.c. Referenced by __attribute(). |
|
|
|
|
|
Definition at line 110 of file new_ftw.c. Referenced by __attribute(), and process_entry(). |
|
|
Definition at line 112 of file new_ftw.c. Referenced by __attribute(). |
|
|
Definition at line 114 of file new_ftw.c. Referenced by __attribute(). |
|
|
|
|
|
|
|
|
Definition at line 120 of file new_ftw.c. Referenced by find_object(). |
|
|
Definition at line 122 of file new_ftw.c. Referenced by add_object(). |
|
|
Definition at line 124 of file new_ftw.c. Referenced by process_entry(). |
|
|
Definition at line 126 of file new_ftw.c. Referenced by __attribute(). |
|
|
Definition at line 128 of file new_ftw.c. Referenced by __attribute(). |
|
|
Definition at line 137 of file new_ftw.c. Referenced by rpl_lstat(). |
|
|
Definition at line 141 of file new_ftw.c. Referenced by __attribute(). |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Definition at line 151 of file new_ftw.c. Referenced by process_entry(). |
|
|
Definition at line 156 of file new_ftw.c. Referenced by process_entry(). |
|
|
Definition at line 157 of file new_ftw.c. Referenced by process_entry(). |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Definition at line 741 of file new_ftw.c. 00742 {
00743 char *cwd = getcwd(NULL, 0);
00744 if (!cwd && errno == ENOMEM) {
00745 fprintf(stderr, "out of memory\n");
00746 exit(1);
00747 }
00748 return cwd;
00749 }
|
|
||||||||||||
|
|
|
||||||||||||||||
|
Referenced by process_entry(). |
|
||||||||||||
|
Definition at line 231 of file new_ftw.c. References known_object::dev, and known_object::ino. Referenced by add_object(), and find_object(). 00232 {
00233 /* We don't need a sophisticated and useful comparison. We are only
00234 interested in equality. However, we must be careful not to
00235 accidentally compare `holes' in the structure. */
00236 const struct known_object *kp1 = p1, *kp2 = p2;
00237 int cmp1;
00238 cmp1 = (kp1->ino > kp2->ino) - (kp1->ino < kp2->ino);
00239 if (cmp1 != 0)
00240 return cmp1;
00241 return (kp1->dev > kp2->dev) - (kp1->dev < kp2->dev);
00242 }
|
|
||||||||||||
|
Definition at line 244 of file new_ftw.c. References __tsearch, known_object::dev, known_object::ino, new_ftw_data::known_objects, and object_compare(). Referenced by process_entry(). 00245 {
00246 struct known_object *newp = malloc(sizeof(struct known_object));
00247 if (newp == NULL)
00248 return -1;
00249 newp->dev = st->st_dev;
00250 newp->ino = st->st_ino;
00251 return __tsearch(newp, &data->known_objects, object_compare) ? 0 : -1;
00252 }
|
|
||||||||||||
|
Definition at line 254 of file new_ftw.c. References __tfind, known_object::dev, known_object::ino, new_ftw_data::known_objects, and object_compare(). Referenced by process_entry(). 00255 {
00256 struct known_object obj;
00257 obj.dev = st->st_dev;
00258 obj.ino = st->st_ino;
00259 return __tfind(&obj, &data->known_objects, object_compare) != NULL;
00260 }
|
|
|
Definition at line 262 of file new_ftw.c. References __closedir, __mempcpy, __opendir, __readdir64, __set_errno, dirent64, MAX, and NAMLEN. 00263 {
00264 int result = 0;
00265
00266 if (data->dirstreams[data->actdir] != NULL) {
00267 /* Oh, oh. We must close this stream. Get all remaining
00268 entries and store them as a list in the `content' member of
00269 the `struct dir_data' variable. */
00270 size_t bufsize = 1024;
00271 char *buf = malloc(bufsize);
00272
00273 if (buf == NULL)
00274 result = -1;
00275 else {
00276 DIR *st = data->dirstreams[data->actdir]->stream;
00277 struct dirent64 *d;
00278 size_t actsize = 0;
00279
00280 while ((d = __readdir64(st)) != NULL) {
00281 size_t this_len = NAMLEN(d);
00282 if (actsize + this_len + 2 >= bufsize) {
00283 char *newp;
00284 bufsize += MAX(1024, 2 * this_len);
00285 newp = (char *)realloc(buf, bufsize);
00286 if (newp == NULL) {
00287 /* No more memory. */
00288 int save_err = errno;
00289 free(buf);
00290 __set_errno(save_err);
00291 result = -1;
00292 break;
00293 }
00294 buf = newp;
00295 }
00296
00297 *((char *)__mempcpy(buf + actsize, d->d_name, this_len))
00298 = '\0';
00299 actsize += this_len + 1;
00300 }
00301
00302 /* Terminate the list with an additional NUL byte. */
00303 buf[actsize++] = '\0';
00304
00305 /* Shrink the buffer to what we actually need. */
00306 data->dirstreams[data->actdir]->content = realloc(buf, actsize);
00307 if (data->dirstreams[data->actdir]->content == NULL) {
00308 int save_err = errno;
00309 free(buf);
00310 __set_errno(save_err);
00311 result = -1;
00312 } else {
00313 __closedir(st);
00314 data->dirstreams[data->actdir]->stream = NULL;
00315 data->dirstreams[data->actdir] = NULL;
00316 }
00317 }
00318 }
00319
00320 /* Open the new stream. */
00321 if (result == 0) {
00322 const char *name = ((data->flags & FTW_CHDIR)
00323 ? data->dirbuf + data->ftw.base : data->dirbuf);
00324 assert(data->dirstreams[data->actdir] == NULL);
00325
00326 dirp->stream = __opendir(name);
00327 if (dirp->stream == NULL)
00328 result = -1;
00329 else {
00330 dirp->content = NULL;
00331 data->dirstreams[data->actdir] = dirp;
00332
00333 if (++data->actdir == data->maxdir)
00334 data->actdir = 0;
00335 }
00336 }
00337
00338 return result;
00339 }
|
|
||||||||||||||||||||
|
Definition at line 341 of file new_ftw.c. References __mempcpy, add_object(), new_ftw_data::cvt_arr, new_ftw_data::data, new_ftw_data::dev, new_ftw_data::dirbuf, new_ftw_data::dirbufsize, find_object(), new_ftw_data::flags, new_ftw_data::ftw, ftw_dir(), FTW_NS, new_ftw_data::func, internal_function, LXSTAT, STAT, and XSTAT. Referenced by __attribute(). 00342 {
00343 struct STAT st;
00344 int result = 0;
00345 int flag = 0;
00346 size_t new_buflen;
00347
00348 if (name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
00349 /* Don't process the "." and ".." entries. */
00350 return 0;
00351
00352 new_buflen = data->ftw.base + namlen + 2;
00353 if (data->dirbufsize < new_buflen) {
00354 /* Enlarge the buffer. */
00355 char *newp;
00356
00357 data->dirbufsize = 2 * new_buflen;
00358 newp = (char *)realloc(data->dirbuf, data->dirbufsize);
00359 if (newp == NULL)
00360 return -1;
00361 data->dirbuf = newp;
00362 }
00363
00364 *((char *)__mempcpy(data->dirbuf + data->ftw.base, name, namlen)) = '\0';
00365
00366 if ((data->flags & FTW_CHDIR) == 0)
00367 name = data->dirbuf;
00368
00369 if (((data->flags & FTW_PHYS)
00370 ? LXSTAT(_STAT_VER, name, &st)
00371 : XSTAT(_STAT_VER, name, &st)) < 0) {
00372 if (errno != EACCES && errno != ENOENT)
00373 result = -1;
00374 else if (!(data->flags & FTW_PHYS)
00375 && LXSTAT(_STAT_VER, name, &st) == 0 && S_ISLNK(st.st_mode))
00376 flag = FTW_SLN;
00377 else
00378 flag = FTW_NS;
00379 } else {
00380 if (S_ISDIR(st.st_mode))
00381 flag = FTW_D;
00382 else if (S_ISLNK(st.st_mode))
00383 flag = FTW_SL;
00384 else
00385 flag = FTW_F;
00386 }
00387
00388 if (result == 0 && (flag == FTW_NS || !(data->flags & FTW_MOUNT) || st.st_dev == data->dev)) {
00389 if (flag == FTW_D) {
00390 if ((data->flags & FTW_PHYS)
00391 || (!find_object(data, &st)
00392 /* Remember the object. */
00393 && (result = add_object(data, &st)) == 0))
00394 result = ftw_dir(data, &st, dir);
00395 } else
00396 result = (*data->func) (data->dirbuf, &st, data->cvt_arr[flag], &data->ftw, data->data);
00397 }
00398
00399 if ((data->flags & FTW_ACTIONRETVAL) && result == FTW_SKIP_SUBTREE)
00400 result = 0;
00401
00402 return result;
00403 }
|
|
|
Definition at line 405 of file new_ftw.c. References __chdir, __closedir, __fchdir, __readdir64, __set_errno, dir_data::content, dirent64, NAMLEN, process_entry(), and dir_data::stream. 00407 {
00408 struct dir_data dir;
00409 struct dirent64 *d;
00410 int previous_base = data->ftw.base;
00411 int result;
00412 char *startp;
00413
00414 /* Open the stream for this directory. This might require that
00415 another stream has to be closed. */
00416 result = open_dir_stream(data, &dir);
00417 if (result != 0) {
00418 if (errno == EACCES)
00419 /* We cannot read the directory. Signal this with a special flag. */
00420 result = (*data->func) (data->dirbuf, st, FTW_DNR, &data->ftw, data->data);
00421
00422 return result;
00423 }
00424
00425 /* First, report the directory (if not depth-first). */
00426 if (!(data->flags & FTW_DEPTH)) {
00427 result = (*data->func) (data->dirbuf, st, FTW_D, &data->ftw, data->data);
00428 if (result != 0) {
00429 int save_err;
00430 fail:
00431 save_err = errno;
00432 __closedir(dir.stream);
00433 __set_errno(save_err);
00434
00435 if (data->actdir-- == 0)
00436 data->actdir = data->maxdir - 1;
00437 data->dirstreams[data->actdir] = NULL;
00438 return result;
00439 }
00440 }
00441
00442 /* If necessary, change to this directory. */
00443 if (data->flags & FTW_CHDIR) {
00444 if (__fchdir(dirfd(dir.stream)) < 0) {
00445 result = -1;
00446 goto fail;
00447 }
00448 }
00449
00450 /* Next, update the `struct FTW' information. */
00451 ++data->ftw.level;
00452 startp = strchr(data->dirbuf, '\0');
00453 /* There always must be a directory name. */
00454 assert(startp != data->dirbuf);
00455 if (startp[-1] != '/')
00456 *startp++ = '/';
00457 data->ftw.base = startp - data->dirbuf;
00458
00459 while (dir.stream != NULL && (d = __readdir64(dir.stream)) != NULL) {
00460 result = process_entry(data, &dir, d->d_name, NAMLEN(d));
00461 if (result != 0)
00462 break;
00463 }
00464
00465 if (dir.stream != NULL) {
00466 /* The stream is still open. I.e., we did not need more
00467 descriptors. Simply close the stream now. */
00468 int save_err = errno;
00469
00470 assert(dir.content == NULL);
00471
00472 __closedir(dir.stream);
00473 __set_errno(save_err);
00474
00475 if (data->actdir-- == 0)
00476 data->actdir = data->maxdir - 1;
00477 data->dirstreams[data->actdir] = NULL;
00478 } else {
00479 int save_err;
00480 char *runp = dir.content;
00481
00482 while (result == 0 && *runp != '\0') {
00483 char *endp = strchr(runp, '\0');
00484
00485 result = process_entry(data, &dir, runp, endp - runp);
00486
00487 runp = endp + 1;
00488 }
00489
00490 save_err = errno;
00491 free(dir.content);
00492 __set_errno(save_err);
00493 }
00494
00495 if ((data->flags & FTW_ACTIONRETVAL) && result == FTW_SKIP_SIBLINGS)
00496 result = 0;
00497
00498 /* Prepare the return, revert the `struct FTW' information. */
00499 data->dirbuf[data->ftw.base - 1] = '\0';
00500 --data->ftw.level;
00501 data->ftw.base = previous_base;
00502
00503 /* Finally, if we process depth-first report the directory. */
00504 if (result == 0 && (data->flags & FTW_DEPTH))
00505 result = (*data->func) (data->dirbuf, st, FTW_DP, &data->ftw, data->data);
00506
00507 if (old_dir && (data->flags & FTW_CHDIR)
00508 && (result == 0 || ((data->flags & FTW_ACTIONRETVAL)
00509 && (result != -1 && result != FTW_STOP)))) {
00510 /* Change back to the parent directory. */
00511 int done = 0;
00512 if (old_dir->stream != NULL)
00513 if (__fchdir(dirfd(old_dir->stream)) == 0)
00514 done = 1;
00515
00516 if (!done) {
00517 if (data->ftw.base == 1) {
00518 if (__chdir("/") < 0)
00519 result = -1;
00520 } else if (__chdir("..") < 0)
00521 result = -1;
00522 }
00523 }
00524
00525 return result;
00526 }
|
|
||||||||||||||||||||
|
Definition at line 665 of file new_ftw.c. 00670 {
00671 return new_ftw_startup(path, 0, func, descriptors, 0, data);
00672 }
|
|
||||||||||||||||||||||||
|
Definition at line 675 of file new_ftw.c. 00681 {
00682 return new_ftw_startup(path, 1, func, descriptors, flags, data);
00683 }
|
|
||||||||||||
|
Definition at line 727 of file new_ftw.c. References lstat. 00730 {
00731 if (file && *file == 0) {
00732 errno = EINVAL;
00733 return -1;
00734 }
00735
00736 return lstat(file, sbuf);
00737 }
|
|
|
Initial value: {
FTW_F, FTW_D, FTW_DNR, FTW_NS, FTW_SL, FTW_DP, FTW_SLN
}
|
|
|
Initial value: {
FTW_F, FTW_D, FTW_DNR, FTW_NS, FTW_F, FTW_D, FTW_NS
}
|