49 lines
1.4 KiB
Diff
49 lines
1.4 KiB
Diff
commit 61f2c2e1d1287a791c22d86c943b44bcf66bb8ad
|
|
Author: Florian Weimer <fweimer@redhat.com>
|
|
Date: Fri Aug 30 21:52:23 2024 +0200
|
|
|
|
Linux: readdir_r needs to report getdents failures (bug 32124)
|
|
|
|
Upon error, return the errno value set by the __getdents call
|
|
in __readdir_unlocked. Previously, kernel-reported errors
|
|
were ignored.
|
|
|
|
Reviewed-by: DJ Delorie <dj@redhat.com>
|
|
|
|
diff --git a/sysdeps/unix/sysv/linux/readdir_r.c b/sysdeps/unix/sysv/linux/readdir_r.c
|
|
index 4792d730eb2c1fa1..2a2491e5e3786746 100644
|
|
--- a/sysdeps/unix/sysv/linux/readdir_r.c
|
|
+++ b/sysdeps/unix/sysv/linux/readdir_r.c
|
|
@@ -25,14 +25,22 @@ __readdir_r (DIR *dirp, struct dirent *entry, struct dirent **result)
|
|
{
|
|
struct dirent *dp;
|
|
size_t reclen;
|
|
+ int saved_errno = errno;
|
|
|
|
__libc_lock_lock (dirp->lock);
|
|
|
|
while (1)
|
|
{
|
|
+ /* If errno is changed from 0, the NULL return value indicates
|
|
+ an actual error. It overrides a pending ENAMETOOLONG error. */
|
|
+ __set_errno (0);
|
|
dp = __readdir_unlocked (dirp);
|
|
if (dp == NULL)
|
|
- break;
|
|
+ {
|
|
+ if (errno != 0)
|
|
+ dirp->errcode = errno;
|
|
+ break;
|
|
+ }
|
|
|
|
reclen = dp->d_reclen;
|
|
if (reclen <= offsetof (struct dirent, d_name) + NAME_MAX + 1)
|
|
@@ -61,6 +69,7 @@ __readdir_r (DIR *dirp, struct dirent *entry, struct dirent **result)
|
|
|
|
__libc_lock_unlock (dirp->lock);
|
|
|
|
+ __set_errno (saved_errno);
|
|
return dp != NULL ? 0 : dirp->errcode;
|
|
}
|
|
|