This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 7e67d2d906d libs/libc/dirent: preserve errno on readdir() 
end-of-directory
7e67d2d906d is described below

commit 7e67d2d906d82da4621c3f3f6674e87c05c78399
Author: yushuailong <[email protected]>
AuthorDate: Tue Jun 2 14:34:04 2026 +0800

    libs/libc/dirent: preserve errno on readdir() end-of-directory
    
    readdir() returned NULL at end-of-directory without ensuring errno was
    clean.  POSIX requires errno to be unchanged at EOF, but the underlying
    read() path may leave a stale errno value.  Callers that follow the
    POSIX idiom (set errno to 0 before the call, test it after a NULL
    return), such as readdir_r() and scandir(), then misread this as a
    readdir() failure.
    
    Save errno on entry and restore it on the end-of-directory return so
    that EOF no longer reports a spurious error, while genuine errors
    (read() returning a negative value) still propagate.
    
    Signed-off-by: yushuailong <[email protected]>
---
 libs/libc/dirent/lib_readdir.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/libs/libc/dirent/lib_readdir.c b/libs/libc/dirent/lib_readdir.c
index 80c587ea8d6..3b2136bca70 100644
--- a/libs/libc/dirent/lib_readdir.c
+++ b/libs/libc/dirent/lib_readdir.c
@@ -59,6 +59,7 @@
 
 FAR struct dirent *readdir(DIR *dirp)
 {
+  int errcode;
   int ret;
 
   if (!dirp)
@@ -67,11 +68,22 @@ FAR struct dirent *readdir(DIR *dirp)
       return NULL;
     }
 
+  /* Save errno so it can be restored on end-of-directory.  POSIX requires
+   * errno to be unchanged at EOF, but the read() path may not preserve it.
+   */
+
+  errcode = get_errno();
+
   ret = read(dirp->fd, &dirp->entry, sizeof(struct dirent));
-  if (ret <= 0)
+  if (ret == 0)
     {
+      set_errno(errcode);  /* EOF: restore errno (not an error) */
       return NULL;
     }
+  else if (ret < 0)
+    {
+      return NULL;         /* error: read() already set errno */
+    }
 
   return &dirp->entry;
 }

Reply via email to