linux: Do not skip d_ino==0 entries in readdir, readdir64(bug 12165)
This commit is contained in:
parent
2e5d102f55
commit
80e03554ca
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
|
Name: glibc
|
||||||
Version: 2.36
|
Version: 2.36
|
||||||
Release: 7
|
Release: 8
|
||||||
Summary: The GNU libc libraries
|
Summary: The GNU libc libraries
|
||||||
License: %{all_license}
|
License: %{all_license}
|
||||||
URL: http://www.gnu.org/software/glibc/
|
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
|
Patch2: linux-Fix-sys-mount.h-usage-with-kernel-headers.patch
|
||||||
Patch3: Linux-Fix-enum-fsconfig_command-detection-in-sys-mou.patch
|
Patch3: Linux-Fix-enum-fsconfig_command-detection-in-sys-mou.patch
|
||||||
Patch4: syslog-Fix-large-messages-BZ-29536.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
|
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
|
Patch9001: locale-delete-no-hard-link-to-avoid-all_language-pac.patch
|
||||||
@ -1263,6 +1264,9 @@ fi
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
%changelog
|
%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
|
* Thu Sep 8 2022 Qingqing Li <liqingqing3@huawei.com> - 2.36-7
|
||||||
- add requires between glibc-info and glibc
|
- add requires between glibc-info and glibc
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user