X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Fmisc%2Fnftw.c;h=fcd25a7354630c2b0bd7b1a3b832456ed15de45e;hb=1d5750b95c06913a1f18a995481276d698d20fae;hp=efb2b89524747397b0ccf3e5bbfb5438fd9ecd87;hpb=73871ee3f21b13b88f2f20a39a1d9bc751bcc1df;p=musl diff --git a/src/misc/nftw.c b/src/misc/nftw.c index efb2b895..fcd25a73 100644 --- a/src/misc/nftw.c +++ b/src/misc/nftw.c @@ -1,12 +1,12 @@ #include #include +#include #include #include #include #include #include #include -#include "libc.h" struct history { @@ -27,8 +27,9 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, struct history new; int type; int r; + int dfd; + int err; struct FTW lev; - char *name; if ((flags & FTW_PHYS) ? lstat(path, &st) : stat(path, &st) < 0) { if (!(flags & FTW_PHYS) && errno==ENOENT && !lstat(path, &st)) @@ -36,8 +37,7 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, else if (errno != EACCES) return -1; else type = FTW_NS; } else if (S_ISDIR(st.st_mode)) { - if (access(path, R_OK) < 0) type = FTW_DNR; - else if (flags & FTW_DEPTH) type = FTW_DP; + if (flags & FTW_DEPTH) type = FTW_DP; else type = FTW_D; } else if (S_ISLNK(st.st_mode)) { if (flags & FTW_PHYS) type = FTW_SL; @@ -53,10 +53,24 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, new.dev = st.st_dev; new.ino = st.st_ino; new.level = h ? h->level+1 : 0; - new.base = l+1; + new.base = j+1; lev.level = new.level; - lev.base = h ? h->base : (name=strrchr(path, '/')) ? name-path : 0; + if (h) { + lev.base = h->base; + } else { + size_t k; + for (k=j; k && path[k]=='/'; k--); + for (; k && path[k-1]!='/'; k--); + lev.base = k; + } + + if (type == FTW_D || type == FTW_DP) { + dfd = open(path, O_RDONLY); + err = errno; + if (dfd < 0 && err == EACCES) type = FTW_DNR; + if (!fd_limit) close(dfd); + } if (!(flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev))) return r; @@ -66,7 +80,11 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, return 0; if ((type == FTW_D || type == FTW_DP) && fd_limit) { - DIR *d = opendir(path); + if (dfd < 0) { + errno = err; + return -1; + } + DIR *d = fdopendir(dfd); if (d) { struct dirent *de; while ((de = readdir(d))) { @@ -87,7 +105,8 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, } } closedir(d); - } else if (errno != EACCES) { + } else { + close(dfd); return -1; } } @@ -119,5 +138,3 @@ int nftw(const char *path, int (*fn)(const char *, const struct stat *, int, str pthread_setcancelstate(cs, 0); return r; } - -LFS64(nftw);