This is mostly to document the bug.
If these old platforms were still common I suppose we should
change the readdir module to work around it.  However, I’m not
sure it’s worth the hassle at this point.
* doc/posix-functions/readdir.texi, doc/posix-functions/readdir_r.texi:
Document the bug.
* lib/fts.c (fts_build):
* lib/savedir.c (streamsavedir):
Work around it.
---
 ChangeLog                          | 13 +++++++++++++
 doc/posix-functions/readdir.texi   |  5 +++++
 doc/posix-functions/readdir_r.texi |  5 +++++
 lib/fts.c                          |  7 +++++++
 lib/savedir.c                      | 10 +++++++++-
 5 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/ChangeLog b/ChangeLog
index bf54cbd836..d4e849e8a8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2025-01-13  Paul Eggert  <egg...@cs.ucla.edu>
+
+       fts, savedir: avoid glibc 2.2 readdir ENOENT bug
+       This is mostly to document the bug.
+       If these old platforms were still common I suppose we should
+       change the readdir module to work around it.  However, I’m not
+       sure it’s worth the hassle at this point.
+       * doc/posix-functions/readdir.texi, doc/posix-functions/readdir_r.texi:
+       Document the bug.
+       * lib/fts.c (fts_build):
+       * lib/savedir.c (streamsavedir):
+       Work around it.
+
 2025-01-13  Bruno Haible  <br...@clisp.org>
 
        stdlib-h: Define WCOREDUMP, as required by POSIX:2024.
diff --git a/doc/posix-functions/readdir.texi b/doc/posix-functions/readdir.texi
index 97d83ce946..3e28b35bde 100644
--- a/doc/posix-functions/readdir.texi
+++ b/doc/posix-functions/readdir.texi
@@ -30,4 +30,9 @@ readdir
 misbehavior on standard systems and so Gnulib does not attempt to
 cater to them any more.  If you know of any problems caused by this,
 please send a bug report.
+@item
+When reading a directory that has been removed,
+this function sets @code{errno} to @code{ENOENT}
+instead of leaving @code{errno} alone to indicate EOF:
+glibc 2.2.5.
 @end itemize
diff --git a/doc/posix-functions/readdir_r.texi 
b/doc/posix-functions/readdir_r.texi
index 76904314d7..c1e8aaad09 100644
--- a/doc/posix-functions/readdir_r.texi
+++ b/doc/posix-functions/readdir_r.texi
@@ -28,4 +28,9 @@ readdir_r
 @item
 This function is missing on some platforms:
 Minix 3.1.8, mingw, MSVC 14.
+@item
+When reading a directory that has been removed,
+this function sets @code{errno} to @code{ENOENT}
+instead of leaving @code{errno} alone to indicate EOF:
+glibc 2.2.5.
 @end itemize
diff --git a/lib/fts.c b/lib/fts.c
index d31443902b..b611e997d4 100644
--- a/lib/fts.c
+++ b/lib/fts.c
@@ -1443,6 +1443,13 @@ fts_build (register FTS *sp, int type)
                 __set_errno (0);
                 struct dirent *dp = readdir(cur->fts_dirp);
                 if (dp == NULL) {
+                        /* Some readdir()s do not absorb ENOENT (dir
+                           deleted but open).  This bug was fixed in
+                           glibc 2.3 (2002).  */
+#if ! (2 < __GLIBC__ + (3 <= __GLIBC_MINOR__))
+                        if (errno == ENOENT)
+                          errno = 0;
+#endif
                         if (errno) {
                                 cur->fts_errno = errno;
                                 /* If we've not read any items yet, treat
diff --git a/lib/savedir.c b/lib/savedir.c
index 93c2c36f7d..40e3b8cebc 100644
--- a/lib/savedir.c
+++ b/lib/savedir.c
@@ -123,7 +123,15 @@ streamsavedir (DIR *dirp, enum savedir_option option)
       errno = 0;
       dp = readdir (dirp);
       if (! dp)
-        break;
+        {
+          /* Some readdir()s do not absorb ENOENT (dir deleted but open).
+             This bug was fixed in glibc 2.3 (2002).  */
+#if ! (2 < __GLIBC__ + (3 <= __GLIBC_MINOR__))
+          if (errno == ENOENT)
+            errno = 0;
+#endif
+          break;
+        }
 
       /* Skip "", ".", and "..".  "" is returned by at least one buggy
          implementation: Solaris 2.4 readdir on NFS file systems.  */
-- 
2.47.1


Reply via email to