!494 linux: Do not skip d_ino == 0 entries in readdir, readdir64 (bug 12165)
From: @superhugepan Reviewed-by: @liqingqing_1229 Signed-off-by: @liqingqing_1229
This commit is contained in:
commit
34bd2843f4
243
Linux-Do-not-skip-d_ino-0-entries-in-readdir-readdir.patch
Normal file
243
Linux-Do-not-skip-d_ino-0-entries-in-readdir-readdir.patch
Normal file
@ -0,0 +1,243 @@
|
||||
From 766b73768b290b303f5b56268c6c0d588d5a9267 Mon Sep 17 00:00:00 2001
|
||||
From: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon, 19 Sep 2022 08:10:41 +0200
|
||||
Subject: [PATCH] Linux: Do not skip d_ino == 0 entries in readdir, readdir64
|
||||
(bug 12165)
|
||||
|
||||
POSIX does not say this value is special. For example, old XFS file
|
||||
systems may still use inode number zero.
|
||||
|
||||
Also update the comment regarding ENOENT. Linux may return ENOENT
|
||||
for some file systems.
|
||||
---
|
||||
sysdeps/unix/sysv/linux/readdir.c | 57 +++++--------
|
||||
sysdeps/unix/sysv/linux/readdir64.c | 120 +++++++++++-----------------
|
||||
2 files changed, 69 insertions(+), 108 deletions(-)
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/readdir.c b/sysdeps/unix/sysv/linux/readdir.c
|
||||
index c31f349639..c9a04dc160 100644
|
||||
--- a/sysdeps/unix/sysv/linux/readdir.c
|
||||
+++ b/sysdeps/unix/sysv/linux/readdir.c
|
||||
@@ -28,48 +28,33 @@ __readdir_unlocked (DIR *dirp)
|
||||
struct dirent *dp;
|
||||
int saved_errno = errno;
|
||||
|
||||
- do
|
||||
+ if (dirp->offset >= dirp->size)
|
||||
{
|
||||
- size_t reclen;
|
||||
+ /* We've emptied out our buffer. Refill it. */
|
||||
|
||||
- if (dirp->offset >= dirp->size)
|
||||
+ size_t maxread = dirp->allocation;
|
||||
+ ssize_t bytes;
|
||||
+
|
||||
+ bytes = __getdents (dirp->fd, dirp->data, maxread);
|
||||
+ if (bytes <= 0)
|
||||
{
|
||||
- /* We've emptied out our buffer. Refill it. */
|
||||
-
|
||||
- size_t maxread = dirp->allocation;
|
||||
- ssize_t bytes;
|
||||
-
|
||||
- bytes = __getdents (dirp->fd, dirp->data, maxread);
|
||||
- if (bytes <= 0)
|
||||
- {
|
||||
- /* On some systems getdents fails with ENOENT when the
|
||||
- open directory has been rmdir'd already. POSIX.1
|
||||
- requires that we treat this condition like normal EOF. */
|
||||
- if (bytes < 0 && errno == ENOENT)
|
||||
- bytes = 0;
|
||||
-
|
||||
- /* Don't modifiy errno when reaching EOF. */
|
||||
- if (bytes == 0)
|
||||
- __set_errno (saved_errno);
|
||||
- dp = NULL;
|
||||
- break;
|
||||
- }
|
||||
- dirp->size = (size_t) bytes;
|
||||
-
|
||||
- /* Reset the offset into the buffer. */
|
||||
- dirp->offset = 0;
|
||||
+ /* Linux may fail with ENOENT on some file systems if the
|
||||
+ directory inode is marked as dead (deleted). POSIX
|
||||
+ treats this as a regular end-of-directory condition, so
|
||||
+ do not set errno in that case, to indicate success. */
|
||||
+ if (bytes == 0 || errno == ENOENT)
|
||||
+ __set_errno (saved_errno);
|
||||
+ return NULL;
|
||||
}
|
||||
+ dirp->size = (size_t) bytes;
|
||||
|
||||
- dp = (struct dirent *) &dirp->data[dirp->offset];
|
||||
-
|
||||
- reclen = dp->d_reclen;
|
||||
-
|
||||
- dirp->offset += reclen;
|
||||
-
|
||||
- dirp->filepos = dp->d_off;
|
||||
+ /* Reset the offset into the buffer. */
|
||||
+ dirp->offset = 0;
|
||||
+ }
|
||||
|
||||
- /* Skip deleted files. */
|
||||
- } while (dp->d_ino == 0);
|
||||
+ dp = (struct dirent *) &dirp->data[dirp->offset];
|
||||
+ dirp->offset += dp->d_reclen;
|
||||
+ dirp->filepos = dp->d_off;
|
||||
|
||||
return dp;
|
||||
}
|
||||
diff --git a/sysdeps/unix/sysv/linux/readdir64.c b/sysdeps/unix/sysv/linux/readdir64.c
|
||||
index e876d84b02..7952da5c27 100644
|
||||
--- a/sysdeps/unix/sysv/linux/readdir64.c
|
||||
+++ b/sysdeps/unix/sysv/linux/readdir64.c
|
||||
@@ -37,48 +37,36 @@ __readdir64 (DIR *dirp)
|
||||
__libc_lock_lock (dirp->lock);
|
||||
#endif
|
||||
|
||||
- do
|
||||
+ if (dirp->offset >= dirp->size)
|
||||
{
|
||||
- size_t reclen;
|
||||
+ /* We've emptied out our buffer. Refill it. */
|
||||
|
||||
- if (dirp->offset >= dirp->size)
|
||||
+ size_t maxread = dirp->allocation;
|
||||
+ ssize_t bytes;
|
||||
+
|
||||
+ bytes = __getdents64 (dirp->fd, dirp->data, maxread);
|
||||
+ if (bytes <= 0)
|
||||
{
|
||||
- /* We've emptied out our buffer. Refill it. */
|
||||
-
|
||||
- size_t maxread = dirp->allocation;
|
||||
- ssize_t bytes;
|
||||
-
|
||||
- bytes = __getdents64 (dirp->fd, dirp->data, maxread);
|
||||
- if (bytes <= 0)
|
||||
- {
|
||||
- /* On some systems getdents fails with ENOENT when the
|
||||
- open directory has been rmdir'd already. POSIX.1
|
||||
- requires that we treat this condition like normal EOF. */
|
||||
- if (bytes < 0 && errno == ENOENT)
|
||||
- bytes = 0;
|
||||
-
|
||||
- /* Don't modifiy errno when reaching EOF. */
|
||||
- if (bytes == 0)
|
||||
- __set_errno (saved_errno);
|
||||
- dp = NULL;
|
||||
- break;
|
||||
- }
|
||||
- dirp->size = (size_t) bytes;
|
||||
-
|
||||
- /* Reset the offset into the buffer. */
|
||||
- dirp->offset = 0;
|
||||
+ /* Linux may fail with ENOENT on some file systems if the
|
||||
+ directory inode is marked as dead (deleted). POSIX
|
||||
+ treats this as a regular end-of-directory condition, so
|
||||
+ do not set errno in that case, to indicate success. */
|
||||
+ if (bytes == 0 || errno == ENOENT)
|
||||
+ __set_errno (saved_errno);
|
||||
+#if IS_IN (libc)
|
||||
+ __libc_lock_unlock (dirp->lock);
|
||||
+#endif
|
||||
+ return NULL;
|
||||
}
|
||||
+ dirp->size = (size_t) bytes;
|
||||
|
||||
- dp = (struct dirent64 *) &dirp->data[dirp->offset];
|
||||
-
|
||||
- reclen = dp->d_reclen;
|
||||
-
|
||||
- dirp->offset += reclen;
|
||||
-
|
||||
- dirp->filepos = dp->d_off;
|
||||
+ /* Reset the offset into the buffer. */
|
||||
+ dirp->offset = 0;
|
||||
+ }
|
||||
|
||||
- /* Skip deleted files. */
|
||||
- } while (dp->d_ino == 0);
|
||||
+ dp = (struct dirent64 *) &dirp->data[dirp->offset];
|
||||
+ dirp->offset += dp->d_reclen;
|
||||
+ dirp->filepos = dp->d_off;
|
||||
|
||||
#if IS_IN (libc)
|
||||
__libc_lock_unlock (dirp->lock);
|
||||
@@ -115,48 +103,36 @@ __old_readdir64 (DIR *dirp)
|
||||
__libc_lock_lock (dirp->lock);
|
||||
#endif
|
||||
|
||||
- do
|
||||
+ if (dirp->offset >= dirp->size)
|
||||
{
|
||||
- size_t reclen;
|
||||
+ /* We've emptied out our buffer. Refill it. */
|
||||
|
||||
- if (dirp->offset >= dirp->size)
|
||||
+ size_t maxread = dirp->allocation;
|
||||
+ ssize_t bytes;
|
||||
+
|
||||
+ bytes = __old_getdents64 (dirp->fd, dirp->data, maxread);
|
||||
+ if (bytes <= 0)
|
||||
{
|
||||
- /* We've emptied out our buffer. Refill it. */
|
||||
-
|
||||
- size_t maxread = dirp->allocation;
|
||||
- ssize_t bytes;
|
||||
-
|
||||
- bytes = __old_getdents64 (dirp->fd, dirp->data, maxread);
|
||||
- if (bytes <= 0)
|
||||
- {
|
||||
- /* On some systems getdents fails with ENOENT when the
|
||||
- open directory has been rmdir'd already. POSIX.1
|
||||
- requires that we treat this condition like normal EOF. */
|
||||
- if (bytes < 0 && errno == ENOENT)
|
||||
- bytes = 0;
|
||||
-
|
||||
- /* Don't modifiy errno when reaching EOF. */
|
||||
- if (bytes == 0)
|
||||
- __set_errno (saved_errno);
|
||||
- dp = NULL;
|
||||
- break;
|
||||
- }
|
||||
- dirp->size = (size_t) bytes;
|
||||
-
|
||||
- /* Reset the offset into the buffer. */
|
||||
- dirp->offset = 0;
|
||||
+ /* Linux may fail with ENOENT on some file systems if the
|
||||
+ directory inode is marked as dead (deleted). POSIX
|
||||
+ treats this as a regular end-of-directory condition, so
|
||||
+ do not set errno in that case, to indicate success. */
|
||||
+ if (bytes == 0 || errno == ENOENT)
|
||||
+ __set_errno (saved_errno);
|
||||
+#if IS_IN (libc)
|
||||
+ __libc_lock_unlock (dirp->lock);
|
||||
+#endif
|
||||
+ return NULL;
|
||||
}
|
||||
+ dirp->size = (size_t) bytes;
|
||||
|
||||
- dp = (struct __old_dirent64 *) &dirp->data[dirp->offset];
|
||||
-
|
||||
- reclen = dp->d_reclen;
|
||||
-
|
||||
- dirp->offset += reclen;
|
||||
-
|
||||
- dirp->filepos = dp->d_off;
|
||||
+ /* Reset the offset into the buffer. */
|
||||
+ dirp->offset = 0;
|
||||
+ }
|
||||
|
||||
- /* Skip deleted files. */
|
||||
- } while (dp->d_ino == 0);
|
||||
+ dp = (struct __old_dirent64 *) &dirp->data[dirp->offset];
|
||||
+ dirp->offset += dp->d_reclen;
|
||||
+ dirp->filepos = dp->d_off;
|
||||
|
||||
#if IS_IN (libc)
|
||||
__libc_lock_unlock (dirp->lock);
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -65,7 +65,7 @@
|
||||
##############################################################################
|
||||
Name: glibc
|
||||
Version: 2.36
|
||||
Release: 7
|
||||
Release: 8
|
||||
Summary: The GNU libc libraries
|
||||
License: %{all_license}
|
||||
URL: http://www.gnu.org/software/glibc/
|
||||
@ -88,6 +88,7 @@ Patch1: linux-Mimic-kernel-defition-for-BLOCK_SIZE.patch
|
||||
Patch2: linux-Fix-sys-mount.h-usage-with-kernel-headers.patch
|
||||
Patch3: Linux-Fix-enum-fsconfig_command-detection-in-sys-mou.patch
|
||||
Patch4: syslog-Fix-large-messages-BZ-29536.patch
|
||||
Patch5: Linux-Do-not-skip-d_ino-0-entries-in-readdir-readdir.patch
|
||||
|
||||
Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch
|
||||
Patch9001: locale-delete-no-hard-link-to-avoid-all_language-pac.patch
|
||||
@ -1263,6 +1264,9 @@ fi
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Tue Sep 20 2022 SuperHugePan <zhangpan26@huawei.com> - 2.36-8
|
||||
- linux: Do not skip d_ino==0 entries in readdir, readdir64(bug 12165)
|
||||
|
||||
* Thu Sep 8 2022 Qingqing Li <liqingqing3@huawei.com> - 2.36-7
|
||||
- add requires between glibc-info and glibc
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user