13 struct history
*chain
;
21 #define dirfd(d) (*(int *)d)
23 static int do_nftw(char *path
, int (*fn
)(const char *, const struct stat
*, int, struct FTW
*), int fd_limit
, int flags
, struct history
*h
)
25 size_t l
= strlen(path
), j
= l
&& path
[l
-1]=='/' ? l
-1 : l
;
33 if ((flags
& FTW_PHYS
) ? lstat(path
, &st
) : stat(path
, &st
) < 0) {
34 if (!(flags
& FTW_PHYS
) && errno
==ENOENT
&& !lstat(path
, &st
))
36 else if (errno
!= EACCES
) return -1;
38 } else if (S_ISDIR(st
.st_mode
)) {
39 if (access(path
, R_OK
) < 0) type
= FTW_DNR
;
40 else if (flags
& FTW_DEPTH
) type
= FTW_DP
;
42 } else if (S_ISLNK(st
.st_mode
)) {
43 if (flags
& FTW_PHYS
) type
= FTW_SL
;
49 if ((flags
& FTW_MOUNT
) && h
&& st
.st_dev
!= h
->dev
)
55 new.level
= h
? h
->level
+1 : 0;
58 lev
.level
= new.level
;
59 lev
.base
= h
? h
->base
: (name
=strrchr(path
, '/')) ? name
-path
: 0;
61 if (!(flags
& FTW_DEPTH
) && (r
=fn(path
, &st
, type
, &lev
)))
64 for (; h
; h
= h
->chain
)
65 if (h
->dev
== st
.st_dev
&& h
->ino
== st
.st_ino
)
68 if ((type
== FTW_D
|| type
== FTW_DP
) && fd_limit
) {
69 DIR *d
= opendir(path
);
72 while ((de
= readdir(d
))) {
73 if (de
->d_name
[0] == '.'
75 || (de
->d_name
[1]=='.'
76 && !de
->d_name
[2]))) continue;
77 if (strlen(de
->d_name
) >= PATH_MAX
-l
) {
83 strcpy(path
+j
+1, de
->d_name
);
84 if ((r
=do_nftw(path
, fn
, fd_limit
-1, flags
, &new))) {
90 } else if (errno
!= EACCES
) {
96 if ((flags
& FTW_DEPTH
) && (r
=fn(path
, &st
, type
, &lev
)))
102 int nftw(const char *path
, int (*fn
)(const char *, const struct stat
*, int, struct FTW
*), int fd_limit
, int flags
)
106 char pathbuf
[PATH_MAX
+1];
108 if (fd_limit
<= 0) return 0;
112 errno
= ENAMETOOLONG
;
115 memcpy(pathbuf
, path
, l
+1);
117 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, &cs
);
118 r
= do_nftw(pathbuf
, fn
, fd_limit
, flags
, NULL
);
119 pthread_setcancelstate(cs
, 0);