summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '9999/0008-linux-Use-getdents64-on-readdir64-compat-implementat.patch')
-rw-r--r--9999/0008-linux-Use-getdents64-on-readdir64-compat-implementat.patch250
1 files changed, 0 insertions, 250 deletions
diff --git a/9999/0008-linux-Use-getdents64-on-readdir64-compat-implementat.patch b/9999/0008-linux-Use-getdents64-on-readdir64-compat-implementat.patch
deleted file mode 100644
index bf2981e..0000000
--- a/9999/0008-linux-Use-getdents64-on-readdir64-compat-implementat.patch
+++ /dev/null
@@ -1,250 +0,0 @@
-From 43e064d5764246f49561def52f9fd592d58b7ac2 Mon Sep 17 00:00:00 2001
-From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
-Date: Fri, 27 Jan 2023 14:28:34 -0300
-Subject: [PATCH 8/9] linux: Use getdents64 on readdir64 compat implementation
-
-It uses a similar strategy from the non-LFS readdir that also
-uses getdents64 internally and uses a translation buffer to return
-the compat readdir64 entry.
-
-It allows to remove __old_getdents64.
-
-Checked on i686-linux-gnu.
----
- sysdeps/unix/sysv/linux/dirstream.h | 13 +++-
- sysdeps/unix/sysv/linux/getdents64.c | 93 ----------------------------
- sysdeps/unix/sysv/linux/olddirent.h | 2 -
- sysdeps/unix/sysv/linux/readdir64.c | 50 +++++++++++----
- 4 files changed, 50 insertions(+), 108 deletions(-)
-
-diff --git a/sysdeps/unix/sysv/linux/dirstream.h b/sysdeps/unix/sysv/linux/dirstream.h
-index 8f58a1c3a6..b03ece4590 100644
---- a/sysdeps/unix/sysv/linux/dirstream.h
-+++ b/sysdeps/unix/sysv/linux/dirstream.h
-@@ -24,6 +24,11 @@
- #include <libc-lock.h>
- #include <telldir.h>
-
-+#include <shlib-compat.h>
-+#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-+# include <olddirent.h>
-+#endif
-+
- /* Directory stream type.
-
- The miscellaneous Unix `readdir' implementations read directory data
-@@ -44,7 +49,13 @@ struct __dirstream
- int errcode; /* Delayed error code. */
-
- #if !defined __OFF_T_MATCHES_OFF64_T || !defined __INO_T_MATCHES_INO64_T
-- struct dirent tdp;
-+ union
-+ {
-+ struct dirent tdp;
-+#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-+ struct __old_dirent64 tdp64;
-+# endif
-+ };
- #endif
- #if _DIRENT_OFFSET_TRANSLATION
- struct dirstream_loc_t locs; /* off64_t to long int map for telldir. */
-diff --git a/sysdeps/unix/sysv/linux/getdents64.c b/sysdeps/unix/sysv/linux/getdents64.c
-index 01c3517deb..db299864ed 100644
---- a/sysdeps/unix/sysv/linux/getdents64.c
-+++ b/sysdeps/unix/sysv/linux/getdents64.c
-@@ -36,97 +36,4 @@ weak_alias (__getdents64, getdents64)
-
- #if _DIRENT_MATCHES_DIRENT64
- strong_alias (__getdents64, __getdents)
--#else
--# include <shlib-compat.h>
--
--# if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
--# include <olddirent.h>
--# include <unistd.h>
--
--static ssize_t
--handle_overflow (int fd, __off64_t offset, ssize_t count)
--{
-- /* If this is the first entry in the buffer, we can report the
-- error. */
-- if (offset == 0)
-- {
-- __set_errno (EOVERFLOW);
-- return -1;
-- }
--
-- /* Otherwise, seek to the overflowing entry, so that the next call
-- will report the error, and return the data read so far. */
-- if (__lseek64 (fd, offset, SEEK_SET) != 0)
-- return -1;
-- return count;
--}
--
--ssize_t
--__old_getdents64 (int fd, char *buf, size_t nbytes)
--{
-- /* We do not move the individual directory entries. This is only
-- possible if the target type (struct __old_dirent64) is smaller
-- than the source type. */
-- _Static_assert (offsetof (struct __old_dirent64, d_name)
-- <= offsetof (struct dirent64, d_name),
-- "__old_dirent64 is larger than dirent64");
-- _Static_assert (__alignof__ (struct __old_dirent64)
-- <= __alignof__ (struct dirent64),
-- "alignment of __old_dirent64 is larger than dirent64");
--
-- ssize_t retval = INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes);
-- if (retval > 0)
-- {
-- /* This is the marker for the first entry. Offset 0 is reserved
-- for the first entry (see rewinddir). Here, we use it as a
-- marker for the first entry in the buffer. We never actually
-- seek to offset 0 because handle_overflow reports the error
-- directly, so it does not matter that the offset is incorrect
-- if entries have been read from the descriptor before (so that
-- the descriptor is not actually at offset 0). */
-- __off64_t previous_offset = 0;
--
-- char *p = buf;
-- char *end = buf + retval;
-- while (p < end)
-- {
-- struct dirent64 *source = (struct dirent64 *) p;
--
-- /* Copy out the fixed-size data. */
-- __ino_t ino = source->d_ino;
-- __off64_t offset = source->d_off;
-- unsigned int reclen = source->d_reclen;
-- unsigned char type = source->d_type;
--
-- /* Check for ino_t overflow. */
-- if (__glibc_unlikely (ino != source->d_ino))
-- return handle_overflow (fd, previous_offset, p - buf);
--
-- /* Convert to the target layout. Use a separate struct and
-- memcpy to side-step aliasing issues. */
-- struct __old_dirent64 result;
-- result.d_ino = ino;
-- result.d_off = offset;
-- result.d_reclen = reclen;
-- result.d_type = type;
--
-- /* Write the fixed-sized part of the result to the
-- buffer. */
-- size_t result_name_offset = offsetof (struct __old_dirent64, d_name);
-- memcpy (p, &result, result_name_offset);
--
-- /* Adjust the position of the name if necessary. Copy
-- everything until the end of the record, including the
-- terminating NUL byte. */
-- if (result_name_offset != offsetof (struct dirent64, d_name))
-- memmove (p + result_name_offset, source->d_name,
-- reclen - offsetof (struct dirent64, d_name));
--
-- p += reclen;
-- previous_offset = offset;
-- }
-- }
-- return retval;
--}
--# endif /* SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2) */
- #endif /* _DIRENT_MATCHES_DIRENT64 */
-diff --git a/sysdeps/unix/sysv/linux/olddirent.h b/sysdeps/unix/sysv/linux/olddirent.h
-index cde95e192e..2d682a6919 100644
---- a/sysdeps/unix/sysv/linux/olddirent.h
-+++ b/sysdeps/unix/sysv/linux/olddirent.h
-@@ -36,8 +36,6 @@ extern struct __old_dirent64 *__old_readdir64_unlocked (DIR *__dirp)
- attribute_hidden;
- extern int __old_readdir64_r (DIR *__dirp, struct __old_dirent64 *__entry,
- struct __old_dirent64 **__result);
--extern __ssize_t __old_getdents64 (int __fd, char *__buf, size_t __nbytes)
-- attribute_hidden;
- int __old_scandir64 (const char * __dir,
- struct __old_dirent64 *** __namelist,
- int (*__selector) (const struct __old_dirent64 *),
-diff --git a/sysdeps/unix/sysv/linux/readdir64.c b/sysdeps/unix/sysv/linux/readdir64.c
-index b901071aa7..88e42c5e90 100644
---- a/sysdeps/unix/sysv/linux/readdir64.c
-+++ b/sysdeps/unix/sysv/linux/readdir64.c
-@@ -102,21 +102,43 @@ versioned_symbol (libc, __readdir64, readdir64, GLIBC_2_2);
- # if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
- # include <olddirent.h>
-
-+/* Translate the DP64 entry to the old LFS one in the translation buffer
-+ at dirstream DS. Return true is the translation was possible or
-+ false if either an internal fields can be represented in the non-LFS
-+ entry or if the translation can not be resized. */
-+static bool
-+dirstream_old_entry (struct __dirstream *ds, const struct dirent64 *dp64)
-+{
-+ /* Check for overflow. */
-+ if (!in_ino_t_range (dp64->d_ino))
-+ return false;
-+
-+ /* And if name is too large. */
-+ if (dp64->d_reclen - offsetof (struct dirent64, d_name) > NAME_MAX)
-+ return false;
-+
-+ ds->filepos = dp64->d_off;
-+
-+ ds->tdp64.d_off = dp64->d_off;
-+ ds->tdp64.d_ino = dp64->d_ino;
-+ ds->tdp64.d_reclen = dp64->d_reclen;
-+ ds->tdp64.d_type = dp64->d_type;
-+ memcpy (ds->tdp64.d_name, dp64->d_name,
-+ dp64->d_reclen - offsetof (struct dirent64, d_name));
-+
-+ return true;
-+}
-+
- attribute_compat_text_section
- struct __old_dirent64 *
- __old_readdir64_unlocked (DIR *dirp)
- {
-- struct __old_dirent64 *dp;
-- int saved_errno = errno;
-+ const int saved_errno = errno;
-
- if (dirp->offset >= dirp->size)
- {
- /* We've emptied out our buffer. Refill it. */
--
-- size_t maxread = dirp->allocation;
-- ssize_t bytes;
--
-- bytes = __old_getdents64 (dirp->fd, dirp->data, maxread);
-+ ssize_t bytes = __getdents64 (dirp->fd, dirp->data, dirp->allocation);
- if (bytes <= 0)
- {
- /* Linux may fail with ENOENT on some file systems if the
-@@ -127,17 +149,21 @@ __old_readdir64_unlocked (DIR *dirp)
- __set_errno (saved_errno);
- return NULL;
- }
-- dirp->size = (size_t) bytes;
-+ dirp->size = bytes;
-
- /* Reset the offset into the buffer. */
- dirp->offset = 0;
- }
-
-- dp = (struct __old_dirent64 *) &dirp->data[dirp->offset];
-- dirp->offset += dp->d_reclen;
-- dirp->filepos = dp->d_off;
-+ struct dirent64 *dp64 = (struct dirent64 *) &dirp->data[dirp->offset];
-+ dirp->offset += dp64->d_reclen;
-
-- return dp;
-+ /* Skip entries which might overflow d_ino or for memory allocation failure
-+ in case of large file names. */
-+ if (dirstream_old_entry (dirp, dp64))
-+ return &dirp->tdp64;
-+
-+ return NULL;
- }
-
- attribute_compat_text_section
---
-2.41.0
-