diff options
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.patch | 250 |
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 - |