From 6835fc458f30b94f15d69c35a79cbc2dfabe2d06 Mon Sep 17 00:00:00 2001 From: =?utf8?q?P=C3=A1draig=20Brady?= Date: Wed, 22 Jun 2016 13:49:53 +0100 Subject: [PATCH] fts: handle readdir() errors * lib/fts.c (fts_build): readdir(3) returns NULL when finished, but also upon error when it will also set errno. Therefore flag the error case from readdir(). We treat the case where no items are read the same as if the dir can't be accessed, i.e. by setting fts_errno to FTS_DNR. The bug was initially reported by Peter Benie http://bugzilla.opensuse.org/show_bug.cgi?id=984910 where it was mentioned that readdir() may fail when an NFS server has a poor readdir cookie implementation. --- ChangeLog | 9 +++++++++ lib/fts.c | 14 ++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index bb343daa41..34b651f242 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2016-06-26 Pádraig Brady + + fts: handle readdir() errors + * lib/fts.c (fts_build): readdir(3) returns NULL when finished, + but also upon error when it will also set errno. Therefore + flag the error case from readdir(). We treat the case where + no items are read the same as if the dir can't be accessed, + i.e. by setting fts_errno to FTS_DNR. + 2016-06-24 Paul Eggert intprops: port better to GCC 7 diff --git a/lib/fts.c b/lib/fts.c index bcdcff9bb7..331d23bf88 100644 --- a/lib/fts.c +++ b/lib/fts.c @@ -1461,9 +1461,18 @@ fts_build (register FTS *sp, int type) while (cur->fts_dirp) { bool is_dir; size_t d_namelen; + __set_errno (0); struct dirent *dp = readdir(cur->fts_dirp); - if (dp == NULL) + if (dp == NULL) { + if (errno) { + cur->fts_errno = errno; + /* If we've not read any items yet, treat + the error as if we can't access the dir. */ + cur->fts_info = (continue_readdir || nitems) + ? FTS_ERR : FTS_DNR; + } break; + } if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name)) continue; @@ -1622,7 +1631,8 @@ mem1: saved_errno = errno; /* If didn't find anything, return NULL. */ if (!nitems) { - if (type == BREAD) + if (type == BREAD + && cur->fts_info != FTS_DNR && cur->fts_info != FTS_ERR) cur->fts_info = FTS_DP; fts_lfree(head); return (NULL); -- 2.39.5