On 17/11/14(Mon) 17:00, enh wrote: > Sony sent us (Android) a patch to use fstatat instead of lstat in fts. > Sadly our copy of fts.c is already a little diverged from yours > (because we have to use strlen to get the length of the d_name, not > having a d_namlen field) but i thought i'd forward this your way > anyway to reduce the need for further divergence... > > https://android-review.googlesource.com/#/c/113415/
Here's the diff inline to facilitate review: Index: gen/fts.c =================================================================== RCS file: /home/ncvs/src/lib/libc/gen/fts.c,v retrieving revision 1.47 diff -u -p -r1.47 fts.c --- gen/fts.c 8 Oct 2014 04:36:23 -0000 1.47 +++ gen/fts.c 18 Nov 2014 14:17:07 -0000 @@ -49,7 +49,7 @@ static size_t fts_maxarglen(char * cons static void fts_padjust(FTS *, FTSENT *); static int fts_palloc(FTS *, size_t); static FTSENT *fts_sort(FTS *, FTSENT *, int); -static u_short fts_stat(FTS *, FTSENT *, int); +static u_short fts_stat(FTS *, FTSENT *, int, DIR *); static int fts_safe_changedir(FTS *, FTSENT *, int, char *); #define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2]))) @@ -116,7 +116,7 @@ fts_open(char * const *argv, int options p->fts_level = FTS_ROOTLEVEL; p->fts_parent = parent; p->fts_accpath = p->fts_name; - p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW)); + p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW), NULL); /* Command-line "." and ".." are real directories. */ if (p->fts_info == FTS_DOT) @@ -270,7 +270,7 @@ fts_read(FTS *sp) /* Any type of file may be re-visited; re-stat and re-turn. */ if (instr == FTS_AGAIN) { - p->fts_info = fts_stat(sp, p, 0); + p->fts_info = fts_stat(sp, p, 0, NULL); return (p); } @@ -282,7 +282,7 @@ fts_read(FTS *sp) */ if (instr == FTS_FOLLOW && (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) { - p->fts_info = fts_stat(sp, p, 1); + p->fts_info = fts_stat(sp, p, 1, NULL); if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) { p->fts_errno = errno; @@ -371,7 +371,7 @@ next: tmp = p; if (p->fts_instr == FTS_SKIP) goto next; if (p->fts_instr == FTS_FOLLOW) { - p->fts_info = fts_stat(sp, p, 1); + p->fts_info = fts_stat(sp, p, 1, NULL); if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) { @@ -719,7 +719,7 @@ mem1: saved_errno = errno; } else p->fts_accpath = p->fts_name; /* Stat it. */ - p->fts_info = fts_stat(sp, p, 0); + p->fts_info = fts_stat(sp, p, 0, dirp); /* Decrement link count if applicable. */ if (nlinks > 0 && (p->fts_info == FTS_D || @@ -786,7 +786,7 @@ mem1: saved_errno = errno; } static u_short -fts_stat(FTS *sp, FTSENT *p, int follow) +fts_stat(FTS *sp, FTSENT *p, int follow, DIR *dirp) { FTSENT *t; dev_t dev; @@ -810,6 +810,11 @@ fts_stat(FTS *sp, FTSENT *p, int follow) return (FTS_SLNONE); } p->fts_errno = saved_errno; + goto err; + } + } else if (dirp) { + if (fstatat(dirfd(dirp), p->fts_name, sbp, AT_SYMLINK_NOFOLLOW)) { + p->fts_errno = errno; goto err; } } else if (lstat(p->fts_accpath, sbp)) {