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
;
32 if ((flags
& FTW_PHYS
) ? lstat(path
, &st
) : stat(path
, &st
) < 0) {
33 if (!(flags
& FTW_PHYS
) && errno
==ENOENT
&& !lstat(path
, &st
))
35 else if (errno
!= EACCES
) return -1;
37 } else if (S_ISDIR(st
.st_mode
)) {
38 if (access(path
, R_OK
) < 0) type
= FTW_DNR
;
39 else if (flags
& FTW_DEPTH
) type
= FTW_DP
;
41 } else if (S_ISLNK(st
.st_mode
)) {
42 if (flags
& FTW_PHYS
) type
= FTW_SL
;
48 if ((flags
& FTW_MOUNT
) && h
&& st
.st_dev
!= h
->dev
)
54 new.level
= h
? h
->level
+1 : 0;
57 lev
.level
= new.level
;
62 for (k
=j
; k
&& path
[k
]=='/'; k
--);
63 for (; k
&& path
[k
-1]!='/'; k
--);
67 if (!(flags
& FTW_DEPTH
) && (r
=fn(path
, &st
, type
, &lev
)))
70 for (; h
; h
= h
->chain
)
71 if (h
->dev
== st
.st_dev
&& h
->ino
== st
.st_ino
)
74 if ((type
== FTW_D
|| type
== FTW_DP
) && fd_limit
) {
75 DIR *d
= opendir(path
);
78 while ((de
= readdir(d
))) {
79 if (de
->d_name
[0] == '.'
81 || (de
->d_name
[1]=='.'
82 && !de
->d_name
[2]))) continue;
83 if (strlen(de
->d_name
) >= PATH_MAX
-l
) {
89 strcpy(path
+j
+1, de
->d_name
);
90 if ((r
=do_nftw(path
, fn
, fd_limit
-1, flags
, &new))) {
96 } else if (errno
!= EACCES
) {
102 if ((flags
& FTW_DEPTH
) && (r
=fn(path
, &st
, type
, &lev
)))
108 int nftw(const char *path
, int (*fn
)(const char *, const struct stat
*, int, struct FTW
*), int fd_limit
, int flags
)
112 char pathbuf
[PATH_MAX
+1];
114 if (fd_limit
<= 0) return 0;
118 errno
= ENAMETOOLONG
;
121 memcpy(pathbuf
, path
, l
+1);
123 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, &cs
);
124 r
= do_nftw(pathbuf
, fn
, fd_limit
, flags
, NULL
);
125 pthread_setcancelstate(cs
, 0);