diff options
author | Florian Weimer <fweimer@redhat.com> | 2024-08-30 21:52:23 +0200 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2024-09-05 12:05:32 +0200 |
commit | 61f2c2e1d1287a791c22d86c943b44bcf66bb8ad (patch) | |
tree | 91468df783dd54e8f9fc817ba79e6a4d68f4f046 | |
parent | 3b1d32177635023e37bec7fbfd77c3cfb2659eb1 (diff) | |
download | glibc-61f2c2e1d1287a791c22d86c943b44bcf66bb8ad.zip glibc-61f2c2e1d1287a791c22d86c943b44bcf66bb8ad.tar.gz glibc-61f2c2e1d1287a791c22d86c943b44bcf66bb8ad.tar.bz2 |
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>
-rw-r--r-- | sysdeps/unix/sysv/linux/readdir_r.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/sysdeps/unix/sysv/linux/readdir_r.c b/sysdeps/unix/sysv/linux/readdir_r.c index ffd5262..1d59568 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; } |