]> Savannah Git Hosting - gnulib.git/commitdiff
fts: handle readdir() errors
authorPádraig Brady <P@draigBrady.com>
Wed, 22 Jun 2016 12:49:53 +0000 (13:49 +0100)
committerPádraig Brady <P@draigBrady.com>
Sun, 26 Jun 2016 18:24:58 +0000 (19:24 +0100)
* 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
lib/fts.c

index bb343daa4173bb43b4da9cab3e1ce27745250444..34b651f24286bde6b0a2933bd2a80eba4cb3f960 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2016-06-26  Pádraig Brady  <P@draigBrady.com>
+
+       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  <eggert@cs.ucla.edu>
 
        intprops: port better to GCC 7
index bcdcff9bb7f8aced6c4d0f00a40a0a5ec7f4353e..331d23bf88c67a31ae5b47e9045a3d3fd188776c 100644 (file)
--- 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);