From 82af9273c46fe3f6227d0bf0e9198a11f8a82156 Mon Sep 17 00:00:00 2001 From: "Andreas K. Hüttel" Date: Sun, 1 Jan 2023 19:29:39 +0100 Subject: Update dirent-related patchset from azanella/bz23960-dirent git branch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas K. Hüttel --- 9999/0001-Disable-ldconfig-during-install.patch | 10 +- ...Adapt-to-Gentoo-specific-etc-mail-aliases.patch | 7 +- ...O0-in-conform-tests-to-survive-CC-changes.patch | 6 +- .../0004-Fix-miscompilation-on-ia64-s-gcc-10.patch | 6 +- ...t-skip-entries-with-zero-d_ino-values-BZ-.patch | 182 -------- ...5-linux-Use-getdents64-on-non-LFS-readdir.patch | 201 +++++++++ ...nternal-DIR-filepos-as-off64_t-BZ-23960-B.patch | 494 +++++++++++++++++++++ ...6-linux-Use-getdents64-on-non-LFS-readdir.patch | 204 --------- 9999/0007-linux-Add-__readdir64_unlocked.patch | 182 ++++++++ ...nternal-DIR-filepos-as-off64_t-BZ-23960-B.patch | 494 --------------------- 9999/0008-linux-Add-__old_readdir64_unlocked.patch | 194 ++++++++ 9999/0008-linux-Add-__readdir64_unlocked.patch | 181 -------- 9999/0009-linux-Add-__old_readdir64_unlocked.patch | 184 -------- ...etdents64-on-readdir64-compat-implementat.patch | 265 +++++++++++ 9999/0010-dirent-Deprecate-getdirentries.patch | 100 +++++ ...etdents64-on-readdir64-compat-implementat.patch | 298 ------------- 9999/0011-dirent-Deprecate-getdirentries.patch | 103 ----- 17 files changed, 1453 insertions(+), 1658 deletions(-) delete mode 100644 9999/0005-linux-Do-not-skip-entries-with-zero-d_ino-values-BZ-.patch create mode 100644 9999/0005-linux-Use-getdents64-on-non-LFS-readdir.patch create mode 100644 9999/0006-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch delete mode 100644 9999/0006-linux-Use-getdents64-on-non-LFS-readdir.patch create mode 100644 9999/0007-linux-Add-__readdir64_unlocked.patch delete mode 100644 9999/0007-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch create mode 100644 9999/0008-linux-Add-__old_readdir64_unlocked.patch delete mode 100644 9999/0008-linux-Add-__readdir64_unlocked.patch delete mode 100644 9999/0009-linux-Add-__old_readdir64_unlocked.patch create mode 100644 9999/0009-linux-Use-getdents64-on-readdir64-compat-implementat.patch create mode 100644 9999/0010-dirent-Deprecate-getdirentries.patch delete mode 100644 9999/0010-linux-Use-getdents64-on-readdir64-compat-implementat.patch delete mode 100644 9999/0011-dirent-Deprecate-getdirentries.patch diff --git a/9999/0001-Disable-ldconfig-during-install.patch b/9999/0001-Disable-ldconfig-during-install.patch index 7bc6628..4a8c771 100644 --- a/9999/0001-Disable-ldconfig-during-install.patch +++ b/9999/0001-Disable-ldconfig-during-install.patch @@ -1,7 +1,10 @@ -From 4917be423cb1a70a66e90e39a73e986b011d7687 Mon Sep 17 00:00:00 2001 +From 5349895a928bff28939b228824c8265d20d9fa60 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 3 Aug 2021 00:34:59 +0200 -Subject: [PATCH 01/12] Disable ldconfig during install +Subject: [PATCH 01/10] Disable ldconfig during install +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Do not bother running ldconfig on DESTDIR. It's a waste of time as we won't use the result (portage will rebuild the cache after install). @@ -10,6 +13,7 @@ we end up (incorrectly) flagging it as a violation as a write to /etc. http://sourceware.org/ml/libc-alpha/2012-08/msg00118.html https://bugs.gentoo.org/431038 +Signed-off-by: Andreas K. Hüttel --- Makefile | 1 + 1 file changed, 1 insertion(+) @@ -27,5 +31,5 @@ index 179dd478ff..763d6a084a 100644 $(elf-objpfx)ldconfig $(addprefix -r ,$(install_root)) \ $(slibdir) $(libdir) -- -2.35.1 +2.38.2 diff --git a/9999/0002-Adapt-to-Gentoo-specific-etc-mail-aliases.patch b/9999/0002-Adapt-to-Gentoo-specific-etc-mail-aliases.patch index 56b9db3..559e736 100644 --- a/9999/0002-Adapt-to-Gentoo-specific-etc-mail-aliases.patch +++ b/9999/0002-Adapt-to-Gentoo-specific-etc-mail-aliases.patch @@ -1,7 +1,7 @@ -From a66ccda34dd319ce19255a029b746362d5773d31 Mon Sep 17 00:00:00 2001 +From ab1ca71990a972e375709711f5fa268010505324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20K=2E=20H=C3=BCttel?= Date: Mon, 22 Oct 2018 22:34:13 +0200 -Subject: [PATCH 02/12] Adapt to Gentoo-specific /etc/mail/aliases +Subject: [PATCH 02/10] Adapt to Gentoo-specific /etc/mail/aliases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -10,6 +10,7 @@ Patch by pacho2 Signed-off-by: Andreas K. Hüttel (cherry picked from commit 4e616cda056f471b799beba2b1cedc787ad4ecc0) +Signed-off-by: Andreas K. Hüttel --- nss/nss_files/files-alias.c | 2 +- nss/tst-nss-files-alias-leak.c | 18 +++++++++--------- @@ -104,5 +105,5 @@ index 4bf6fe0834..1548eba2ad 100644 /* valgrind needs a temporary directory in the chroot. */ { -- -2.35.1 +2.38.2 diff --git a/9999/0003-Force-O0-in-conform-tests-to-survive-CC-changes.patch b/9999/0003-Force-O0-in-conform-tests-to-survive-CC-changes.patch index 95fc2c5..f662cda 100644 --- a/9999/0003-Force-O0-in-conform-tests-to-survive-CC-changes.patch +++ b/9999/0003-Force-O0-in-conform-tests-to-survive-CC-changes.patch @@ -1,7 +1,7 @@ -From 68476d32783ea64c21bbd6d166a69fa881a3f22b Mon Sep 17 00:00:00 2001 +From f44c6c3768c2a3ef274782a2e308fb6b8fe84499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20K=2E=20H=C3=BCttel?= Date: Fri, 14 Dec 2018 20:43:04 +0100 -Subject: [PATCH 03/12] Force -O0 in conform tests to survive $CC changes +Subject: [PATCH 03/10] Force -O0 in conform tests to survive $CC changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -61,5 +61,5 @@ index f7fe3a7a0a..ad87fd2a6d 100644 args.header) with tempfile.TemporaryDirectory() as temp_dir: -- -2.35.1 +2.38.2 diff --git a/9999/0004-Fix-miscompilation-on-ia64-s-gcc-10.patch b/9999/0004-Fix-miscompilation-on-ia64-s-gcc-10.patch index b742135..2d9c8f7 100644 --- a/9999/0004-Fix-miscompilation-on-ia64-s-gcc-10.patch +++ b/9999/0004-Fix-miscompilation-on-ia64-s-gcc-10.patch @@ -1,7 +1,7 @@ -From 88e7fe55212b0110dca46b5d3a4b7be8db404598 Mon Sep 17 00:00:00 2001 +From 4aafe3fae7777fec09e2dd3915a8fd33642bba94 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Sat, 11 Jul 2020 20:06:51 +0300 -Subject: [PATCH 04/12] Fix miscompilation on ia64's gcc-10 +Subject: [PATCH 04/10] Fix miscompilation on ia64's gcc-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -28,5 +28,5 @@ index aa1de6b361..f6472f1942 100644 # define DL_SYSINFO_IMPLEMENTATION \ asm (".text\n\t" \ -- -2.35.1 +2.38.2 diff --git a/9999/0005-linux-Do-not-skip-entries-with-zero-d_ino-values-BZ-.patch b/9999/0005-linux-Do-not-skip-entries-with-zero-d_ino-values-BZ-.patch deleted file mode 100644 index 33f9869..0000000 --- a/9999/0005-linux-Do-not-skip-entries-with-zero-d_ino-values-BZ-.patch +++ /dev/null @@ -1,182 +0,0 @@ -From ad50ce9ae10cdd50bd620ae6ef67fe3b11896913 Mon Sep 17 00:00:00 2001 -From: Adhemerval Zanella -Date: Tue, 20 Oct 2020 12:18:56 -0300 -Subject: [PATCH 05/12] linux: Do not skip entries with zero d_ino values [BZ - #12165] - -According to Linux commit 2adc376c55194 (vfs: avoid creation of inode -number 0 in get_next_ino) Linux did not treat d_ino == 0 as a special -case (it is a valid inode number). - -This patch fixes readdir{64} by not ignoring entried with d_ino being -0. - -Checked on x86_64-linux-gnu and i686-linux-gnu. ---- - sysdeps/unix/sysv/linux/readdir.c | 59 +++++++++++------------------ - sysdeps/unix/sysv/linux/readdir64.c | 59 +++++++++++------------------ - 2 files changed, 44 insertions(+), 74 deletions(-) - -diff --git a/sysdeps/unix/sysv/linux/readdir.c b/sysdeps/unix/sysv/linux/readdir.c -index c31f349639..7743f50071 100644 ---- a/sysdeps/unix/sysv/linux/readdir.c -+++ b/sysdeps/unix/sysv/linux/readdir.c -@@ -25,51 +25,36 @@ - struct dirent * - __readdir_unlocked (DIR *dirp) - { -- struct dirent *dp; -- int saved_errno = errno; -+ const int saved_errno = errno; - -- do -+ if (dirp->offset >= dirp->size) - { -- size_t reclen; -- -- if (dirp->offset >= dirp->size) -+ /* We've emptied out our buffer. Refill it. */ -+ ssize_t bytes = __getdents (dirp->fd, dirp->data, dirp->allocation); -+ 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; -+ /* 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); -+ return NULL; - } -+ dirp->size = bytes; - -- dp = (struct dirent *) &dirp->data[dirp->offset]; -- -- reclen = dp->d_reclen; -+ /* Reset the offset into the buffer. */ -+ dirp->offset = 0; -+ } - -- dirp->offset += reclen; -+ struct dirent *dp = (struct dirent *) &dirp->data[dirp->offset]; - -- dirp->filepos = dp->d_off; -+ dirp->offset += dp->d_reclen; - -- /* Skip deleted files. */ -- } while (dp->d_ino == 0); -+ 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..d990a36e4e 100644 ---- a/sysdeps/unix/sysv/linux/readdir64.c -+++ b/sysdeps/unix/sysv/linux/readdir64.c -@@ -30,55 +30,40 @@ - struct dirent64 * - __readdir64 (DIR *dirp) - { -- struct dirent64 *dp; -- int saved_errno = errno; -+ const int saved_errno = errno; - - #if IS_IN (libc) - __libc_lock_lock (dirp->lock); - #endif - -- do -+ if (dirp->offset >= dirp->size) - { -- size_t reclen; -- -- if (dirp->offset >= dirp->size) -+ /* We've emptied out our buffer. Refill it. */ -+ ssize_t bytes = __getdents64 (dirp->fd, dirp->data, dirp->allocation); -+ 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; -+ /* 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); -+ return NULL; - } -+ dirp->size = bytes; - -- dp = (struct dirent64 *) &dirp->data[dirp->offset]; -- -- reclen = dp->d_reclen; -+ /* Reset the offset into the buffer. */ -+ dirp->offset = 0; -+ } - -- dirp->offset += reclen; -+ struct dirent64 *dp = (struct dirent64 *) &dirp->data[dirp->offset]; - -- dirp->filepos = dp->d_off; -+ dirp->offset += dp->d_reclen; - -- /* Skip deleted files. */ -- } while (dp->d_ino == 0); -+ dirp->filepos = dp->d_off; - - #if IS_IN (libc) - __libc_lock_unlock (dirp->lock); --- -2.35.1 - diff --git a/9999/0005-linux-Use-getdents64-on-non-LFS-readdir.patch b/9999/0005-linux-Use-getdents64-on-non-LFS-readdir.patch new file mode 100644 index 0000000..4e1dc0d --- /dev/null +++ b/9999/0005-linux-Use-getdents64-on-non-LFS-readdir.patch @@ -0,0 +1,201 @@ +From 0718c1ca37fe6407bd4bad15dfae873719eabb6e Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Tue, 20 Oct 2020 13:37:15 -0300 +Subject: [PATCH 05/10] linux: Use getdents64 on non-LFS readdir + +The opendir allocates a translation buffer to be used to return the +non-LFS readdir entry. The obtained dirent64 struct is translated +to the temporary buffer on each readdir call. + +Entries that overflow d_off/d_ino and the buffer reallocation failure +(in case of large d_name) are ignored. + +Checked on x86_64-linux-gnu and i686-linux-gnu. +--- + sysdeps/unix/sysv/linux/closedir.c | 4 ++ + sysdeps/unix/sysv/linux/dirstream.h | 5 ++ + sysdeps/unix/sysv/linux/opendir.c | 21 +++++++ + sysdeps/unix/sysv/linux/readdir.c | 94 +++++++++++++++++++++-------- + 4 files changed, 98 insertions(+), 26 deletions(-) + +diff --git a/sysdeps/unix/sysv/linux/closedir.c b/sysdeps/unix/sysv/linux/closedir.c +index eee0193fc4..d876d49d78 100644 +--- a/sysdeps/unix/sysv/linux/closedir.c ++++ b/sysdeps/unix/sysv/linux/closedir.c +@@ -47,6 +47,10 @@ __closedir (DIR *dirp) + __libc_lock_fini (dirp->lock); + #endif + ++#if !_DIRENT_MATCHES_DIRENT64 ++ free (dirp->tbuffer); ++#endif ++ + free ((void *) dirp); + + return __close_nocancel (fd); +diff --git a/sysdeps/unix/sysv/linux/dirstream.h b/sysdeps/unix/sysv/linux/dirstream.h +index a0d8acf08d..064273cc31 100644 +--- a/sysdeps/unix/sysv/linux/dirstream.h ++++ b/sysdeps/unix/sysv/linux/dirstream.h +@@ -41,6 +41,11 @@ struct __dirstream + + int errcode; /* Delayed error code. */ + ++#if !defined __OFF_T_MATCHES_OFF64_T || !defined __INO_T_MATCHES_INO64_T ++ char *tbuffer; /* Translation buffer for non-LFS calls. */ ++ size_t tbuffer_size; /* Size of translation buffer. */ ++#endif ++ + /* Directory block. We must make sure that this block starts + at an address that is aligned adequately enough to store + dirent entries. Using the alignment of "void *" is not +diff --git a/sysdeps/unix/sysv/linux/opendir.c b/sysdeps/unix/sysv/linux/opendir.c +index 9e81d00630..bfd2f382a6 100644 +--- a/sysdeps/unix/sysv/linux/opendir.c ++++ b/sysdeps/unix/sysv/linux/opendir.c +@@ -120,6 +120,27 @@ __alloc_dir (int fd, bool close_fd, int flags, + return NULL; + } + ++#if !_DIRENT_MATCHES_DIRENT64 ++ /* Allocates a translation buffer to use as the returned 'struct direct' ++ for non-LFS 'readdir' calls. ++ ++ The initial NAME_MAX size should handle most cases, while readdir might ++ expand the buffer if required. */ ++ enum ++ { ++ tbuffer_size = sizeof (struct dirent) + NAME_MAX + 1 ++ }; ++ dirp->tbuffer = malloc (tbuffer_size); ++ if (dirp->tbuffer == NULL) ++ { ++ free (dirp); ++ if (close_fd) ++ __close_nocancel_nostatus (fd); ++ return NULL; ++ } ++ dirp->tbuffer_size = tbuffer_size; ++#endif ++ + dirp->fd = fd; + #if IS_IN (libc) + __libc_lock_init (dirp->lock); +diff --git a/sysdeps/unix/sysv/linux/readdir.c b/sysdeps/unix/sysv/linux/readdir.c +index c9a04dc160..c078146d7d 100644 +--- a/sysdeps/unix/sysv/linux/readdir.c ++++ b/sysdeps/unix/sysv/linux/readdir.c +@@ -21,42 +21,84 @@ + #if !_DIRENT_MATCHES_DIRENT64 + #include + ++/* Translate the DP64 entry to the non-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_entry (struct __dirstream *ds, const struct dirent64 *dp64) ++{ ++ off_t d_off = dp64->d_off; ++ if (d_off != dp64->d_off) ++ return false; ++ ino_t d_ino = dp64->d_ino; ++ if (d_ino != dp64->d_ino) ++ return false; ++ ++ /* Expand the translation buffer to hold the new name size. */ ++ size_t new_reclen = sizeof (struct dirent) ++ + dp64->d_reclen - offsetof (struct dirent64, d_name); ++ if (new_reclen > ds->tbuffer_size) ++ { ++ char *newbuffer = realloc (ds->tbuffer, new_reclen); ++ if (newbuffer == NULL) ++ return false; ++ ds->tbuffer = newbuffer; ++ ds->tbuffer_size = new_reclen; ++ } ++ ++ struct dirent *dp = (struct dirent *) ds->tbuffer; ++ ++ dp->d_off = d_off; ++ dp->d_ino = d_ino; ++ dp->d_reclen = new_reclen; ++ dp->d_type = dp64->d_type; ++ memcpy (dp->d_name, dp64->d_name, ++ dp64->d_reclen - offsetof (struct dirent64, d_name)); ++ ++ return true; ++} ++ + /* Read a directory entry from DIRP. */ + struct dirent * + __readdir_unlocked (DIR *dirp) + { +- struct dirent *dp; + int saved_errno = errno; + +- if (dirp->offset >= dirp->size) ++ while (1) + { +- /* 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) ++ if (dirp->offset >= dirp->size) ++ { ++ /* We've emptied out our buffer. Refill it. */ ++ ssize_t bytes = __getdents64 (dirp->fd, dirp->data, ++ dirp->allocation); ++ if (bytes <= 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 = bytes; ++ ++ /* Reset the offset into the buffer. */ ++ dirp->offset = 0; ++ } ++ ++ struct dirent64 *dp64 = (struct dirent64 *) &dirp->data[dirp->offset]; ++ dirp->offset += dp64->d_reclen; ++ ++ /* Skip entries which might overflow d_off/d_ino or if the translation ++ buffer can't be resized. */ ++ if (dirstream_entry (dirp, dp64)) + { +- /* 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->filepos = dp64->d_off; ++ return (struct dirent *) dirp->tbuffer; + } +- dirp->size = (size_t) bytes; +- +- /* Reset the offset into the buffer. */ +- dirp->offset = 0; + } +- +- dp = (struct dirent *) &dirp->data[dirp->offset]; +- dirp->offset += dp->d_reclen; +- dirp->filepos = dp->d_off; +- +- return dp; + } + + struct dirent * +-- +2.38.2 + diff --git a/9999/0006-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch b/9999/0006-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch new file mode 100644 index 0000000..38acaf8 --- /dev/null +++ b/9999/0006-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch @@ -0,0 +1,494 @@ +From 36f553f67b8268341b7879640637fac5ea806017 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Mon, 13 Apr 2020 18:09:20 -0300 +Subject: [PATCH 06/10] linux: Set internal DIR filepos as off64_t [BZ #23960, + BZ #24050] + +It allows to obtain the expected entry offset on telldir and set +it correctly on seekdir on platforms where long int is smaller +than off64_t. + +On such cases telldir will mantain an internal list that maps the +DIR object off64_t offsets to the returned long int (the function +return value). The seekdir will then set the correct offset from +the internal list using the telldir as the list key. + +It also removes the overflow check on readdir and the returned value +will be truncated by the non-LFS off_t size. As Joseph has noted +in BZ #23960 comment #22, d_off is an opaque value and since +telldir/seekdir works regardless of the returned dirent d_off value. + +Finally it removed the requirement to check for overflow values on +telldir (BZ #24050). + +Checked on x86_64-linux-gnu, i686-linux-gnu, powerpc-linux-gnu, +and arm-linux-gnueabihf. +--- + dirent/Makefile | 2 +- + dirent/tst-seekdir2.c | 158 ++++++++++++++++++++++++++++ + sysdeps/unix/sysv/linux/closedir.c | 4 + + sysdeps/unix/sysv/linux/dirstream.h | 6 +- + sysdeps/unix/sysv/linux/opendir.c | 3 + + sysdeps/unix/sysv/linux/readdir.c | 1 + + sysdeps/unix/sysv/linux/rewinddir.c | 5 + + sysdeps/unix/sysv/linux/seekdir.c | 36 ++++++- + sysdeps/unix/sysv/linux/telldir.c | 47 ++++++++- + sysdeps/unix/sysv/linux/telldir.h | 64 +++++++++++ + 10 files changed, 317 insertions(+), 9 deletions(-) + create mode 100644 dirent/tst-seekdir2.c + create mode 100644 sysdeps/unix/sysv/linux/telldir.h + +diff --git a/dirent/Makefile b/dirent/Makefile +index cfa61826ed..9a9d91b8a5 100644 +--- a/dirent/Makefile ++++ b/dirent/Makefile +@@ -31,7 +31,7 @@ routines := opendir closedir readdir readdir_r rewinddir \ + scandir-cancel scandir-tail scandir64-tail + + tests := list tst-seekdir opendir-tst1 bug-readdir1 tst-fdopendir \ +- tst-fdopendir2 tst-scandir tst-scandir64 ++ tst-fdopendir2 tst-scandir tst-scandir64 tst-seekdir2 + + CFLAGS-scandir.c += $(uses-callbacks) + CFLAGS-scandir64.c += $(uses-callbacks) +diff --git a/dirent/tst-seekdir2.c b/dirent/tst-seekdir2.c +new file mode 100644 +index 0000000000..3e01b361e5 +--- /dev/null ++++ b/dirent/tst-seekdir2.c +@@ -0,0 +1,158 @@ ++/* Check multiple telldir and seekdir. ++ Copyright (C) 2020 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++/* Some filesystems returns a arbitrary value for d_off direnty entry (ext4 ++ for instance, where the value is an internal hash key). The idea of ++ create a large number of file is to try trigger a overflow d_off value ++ in a entry to check if telldir/seekdir does work corretly in such ++ case. */ ++static const char *dirname; ++static const size_t nfiles = 10240; ++ ++static void ++do_prepare (int argc, char *argv[]) ++{ ++ dirname = support_create_temp_directory ("tst-seekdir2-"); ++ ++ for (size_t i = 0; i < nfiles; i++) ++ { ++ int fd = create_temp_file_in_dir ("tempfile.", dirname, NULL); ++ TEST_VERIFY_EXIT (fd > 0); ++ close (fd); ++ } ++} ++#define PREPARE do_prepare ++ ++/* Check for old non Large File Support (LFS). */ ++static int ++do_test_not_lfs (void) ++{ ++ DIR *dirp = opendir (dirname); ++ TEST_VERIFY_EXIT (dirp != NULL); ++ ++ size_t dirp_count = 0; ++ for (struct dirent *dp = readdir (dirp); ++ dp != NULL; ++ dp = readdir (dirp)) ++ dirp_count++; ++ ++ /* The 2 extra files are '.' and '..'. */ ++ TEST_COMPARE (dirp_count, nfiles + 2); ++ ++ rewinddir (dirp); ++ ++ long *tdirp = xmalloc (dirp_count * sizeof (long)); ++ struct dirent **ddirp = xmalloc (dirp_count * sizeof (struct dirent *)); ++ ++ size_t i = 0; ++ do ++ { ++ tdirp[i] = telldir (dirp); ++ struct dirent *dp = readdir (dirp); ++ TEST_VERIFY_EXIT (dp != NULL); ++ ddirp[i] = xmalloc (dp->d_reclen); ++ memcpy (ddirp[i], dp, dp->d_reclen); ++ } while (++i < dirp_count); ++ ++ for (i = 0; i < dirp_count - 1; i++) ++ { ++ seekdir (dirp, tdirp[i]); ++ struct dirent *dp = readdir (dirp); ++ TEST_COMPARE (strcmp (dp->d_name, ddirp[i]->d_name), 0); ++ TEST_COMPARE (dp->d_ino, ddirp[i]->d_ino); ++ TEST_COMPARE (dp->d_off, ddirp[i]->d_off); ++ } ++ ++ closedir (dirp); ++ free (tdirp); ++ for (i = 0; i < dirp_count; i++) ++ free (ddirp[i]); ++ free (ddirp); ++ ++ return 0; ++} ++ ++/* Same as before but with LFS support. */ ++static int ++do_test_lfs (void) ++{ ++ DIR *dirp = opendir (dirname); ++ TEST_VERIFY_EXIT (dirp != NULL); ++ ++ size_t dirp_count = 0; ++ for (struct dirent64 * dp = readdir64 (dirp); ++ dp != NULL; ++ dp = readdir64 (dirp)) ++ dirp_count++; ++ ++ /* The 2 extra files are '.' and '..'. */ ++ TEST_COMPARE (dirp_count, nfiles + 2); ++ ++ rewinddir (dirp); ++ ++ long *tdirp = xmalloc (dirp_count * sizeof (long)); ++ struct dirent64 **ddirp = xmalloc (dirp_count * sizeof (struct dirent64 *)); ++ ++ size_t i = 0; ++ do ++ { ++ tdirp[i] = telldir (dirp); ++ struct dirent64 *dp = readdir64 (dirp); ++ TEST_VERIFY_EXIT (dp != NULL); ++ ddirp[i] = xmalloc (dp->d_reclen); ++ memcpy (ddirp[i], dp, dp->d_reclen); ++ } while (++i < dirp_count); ++ ++ for (i = 0; i < dirp_count - 1; i++) ++ { ++ seekdir (dirp, tdirp[i]); ++ struct dirent64 *dp = readdir64 (dirp); ++ TEST_COMPARE (strcmp (dp->d_name, ddirp[i]->d_name), 0); ++ TEST_COMPARE (dp->d_ino, ddirp[i]->d_ino); ++ TEST_COMPARE (dp->d_off, ddirp[i]->d_off); ++ } ++ ++ closedir (dirp); ++ free (tdirp); ++ for (i = 0; i < dirp_count; i++) ++ free (ddirp[i]); ++ free (ddirp); ++ ++ return 0; ++} ++ ++static int ++do_test (void) ++{ ++ do_test_not_lfs (); ++ do_test_lfs (); ++ ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/unix/sysv/linux/closedir.c b/sysdeps/unix/sysv/linux/closedir.c +index d876d49d78..8e5669963c 100644 +--- a/sysdeps/unix/sysv/linux/closedir.c ++++ b/sysdeps/unix/sysv/linux/closedir.c +@@ -43,6 +43,10 @@ __closedir (DIR *dirp) + + fd = dirp->fd; + ++#ifndef __LP64__ ++ dirstream_loc_clear (&dirp->locs); ++#endif ++ + #if IS_IN (libc) + __libc_lock_fini (dirp->lock); + #endif +diff --git a/sysdeps/unix/sysv/linux/dirstream.h b/sysdeps/unix/sysv/linux/dirstream.h +index 064273cc31..a284292cb2 100644 +--- a/sysdeps/unix/sysv/linux/dirstream.h ++++ b/sysdeps/unix/sysv/linux/dirstream.h +@@ -21,6 +21,7 @@ + #include + + #include ++#include + + /* Directory stream type. + +@@ -37,7 +38,7 @@ struct __dirstream + size_t size; /* Total valid data in the block. */ + size_t offset; /* Current offset into the block. */ + +- off_t filepos; /* Position of next entry to read. */ ++ off64_t filepos; /* Position of next entry to read. */ + + int errcode; /* Delayed error code. */ + +@@ -45,6 +46,9 @@ struct __dirstream + char *tbuffer; /* Translation buffer for non-LFS calls. */ + size_t tbuffer_size; /* Size of translation buffer. */ + #endif ++#ifndef __LP64__ ++ struct dirstream_loc_t locs; /* off64_t to long int map for telldir. */ ++#endif + + /* Directory block. We must make sure that this block starts + at an address that is aligned adequately enough to store +diff --git a/sysdeps/unix/sysv/linux/opendir.c b/sysdeps/unix/sysv/linux/opendir.c +index bfd2f382a6..9a0b7ab4c4 100644 +--- a/sysdeps/unix/sysv/linux/opendir.c ++++ b/sysdeps/unix/sysv/linux/opendir.c +@@ -150,6 +150,9 @@ __alloc_dir (int fd, bool close_fd, int flags, + dirp->offset = 0; + dirp->filepos = 0; + dirp->errcode = 0; ++#ifndef __LP64__ ++ dirstream_loc_init (&dirp->locs); ++#endif + + return dirp; + } +diff --git a/sysdeps/unix/sysv/linux/readdir.c b/sysdeps/unix/sysv/linux/readdir.c +index c078146d7d..f377e5f268 100644 +--- a/sysdeps/unix/sysv/linux/readdir.c ++++ b/sysdeps/unix/sysv/linux/readdir.c +@@ -17,6 +17,7 @@ + . */ + + #include ++#include + + #if !_DIRENT_MATCHES_DIRENT64 + #include +diff --git a/sysdeps/unix/sysv/linux/rewinddir.c b/sysdeps/unix/sysv/linux/rewinddir.c +index b1e8259703..0194d29e38 100644 +--- a/sysdeps/unix/sysv/linux/rewinddir.c ++++ b/sysdeps/unix/sysv/linux/rewinddir.c +@@ -33,6 +33,11 @@ __rewinddir (DIR *dirp) + dirp->offset = 0; + dirp->size = 0; + dirp->errcode = 0; ++ ++#ifndef __LP64__ ++ dirstream_loc_clear (&dirp->locs); ++#endif ++ + #if IS_IN (libc) + __libc_lock_unlock (dirp->lock); + #endif +diff --git a/sysdeps/unix/sysv/linux/seekdir.c b/sysdeps/unix/sysv/linux/seekdir.c +index f4e1a9f8e0..0c3e58a2ed 100644 +--- a/sysdeps/unix/sysv/linux/seekdir.c ++++ b/sysdeps/unix/sysv/linux/seekdir.c +@@ -22,14 +22,40 @@ + #include + + /* Seek to position POS in DIRP. */ +-/* XXX should be __seekdir ? */ + void + seekdir (DIR *dirp, long int pos) + { ++ off64_t filepos; ++ + __libc_lock_lock (dirp->lock); +- (void) __lseek (dirp->fd, pos, SEEK_SET); +- dirp->size = 0; +- dirp->offset = 0; +- dirp->filepos = pos; ++ ++#ifndef __LP64__ ++ union dirstream_packed dsp; ++ ++ dsp.l = pos; ++ ++ if (dsp.p.is_packed == 1) ++ filepos = dsp.p.info; ++ else ++ { ++ size_t index = dsp.p.info; ++ ++ if (index >= dirstream_loc_size (&dirp->locs)) ++ return; ++ struct dirstream_loc *loc = dirstream_loc_at (&dirp->locs, index); ++ filepos = loc->filepos; ++ } ++#else ++ filepos = pos; ++#endif ++ ++ if (dirp->filepos != filepos) ++ { ++ __lseek64 (dirp->fd, filepos, SEEK_SET); ++ dirp->filepos = filepos; ++ dirp->offset = 0; ++ dirp->size = 0; ++ } ++ + __libc_lock_unlock (dirp->lock); + } +diff --git a/sysdeps/unix/sysv/linux/telldir.c b/sysdeps/unix/sysv/linux/telldir.c +index b60b231e48..874905489f 100644 +--- a/sysdeps/unix/sysv/linux/telldir.c ++++ b/sysdeps/unix/sysv/linux/telldir.c +@@ -18,16 +18,59 @@ + #include + + #include ++#include + + /* Return the current position of DIRP. */ + long int + telldir (DIR *dirp) + { +- long int ret; ++#ifndef __LP64__ ++ /* If the directory position fits in the packet structure returns it. ++ Otherwise, check if the position is already been recorded in the ++ dynamic array. If not, add the new record. */ ++ ++ union dirstream_packed dsp; ++ size_t i; + + __libc_lock_lock (dirp->lock); +- ret = dirp->filepos; ++ ++ if (dirp->filepos < (1U << 31)) ++ { ++ dsp.p.is_packed = 1; ++ dsp.p.info = dirp->filepos; ++ goto out; ++ } ++ ++ dsp.l = -1; ++ ++ for (i = 0; i < dirstream_loc_size (&dirp->locs); i++) ++ { ++ struct dirstream_loc *loc = dirstream_loc_at (&dirp->locs, i); ++ if (loc->filepos == dirp->filepos) ++ break; ++ } ++ if (i == dirstream_loc_size (&dirp->locs)) ++ { ++ dirstream_loc_add (&dirp->locs, ++ (struct dirstream_loc) { dirp->filepos }); ++ if (dirstream_loc_has_failed (&dirp->locs)) ++ goto out; ++ } ++ ++ dsp.p.is_packed = 0; ++ /* This assignment might overflow, however most likely ENOMEM would happen ++ long before. */ ++ dsp.p.info = i; ++ ++out: + __libc_lock_unlock (dirp->lock); + ++ return dsp.l; ++#else ++ long int ret; ++ __libc_lock_lock (dirp->lock); ++ ret = dirp->filepos; ++ __libc_lock_unlock (dirp->lock); + return ret; ++#endif + } +diff --git a/sysdeps/unix/sysv/linux/telldir.h b/sysdeps/unix/sysv/linux/telldir.h +new file mode 100644 +index 0000000000..7c45886341 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/telldir.h +@@ -0,0 +1,64 @@ ++/* Linux internal telldir definitions. ++ Copyright (C) 2020 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _TELLDIR_H ++#define _TELLDIR_H 1 ++ ++#ifndef __LP64__ ++ ++/* On platforms where long int is smaller than off64_t this is how the ++ returned value is encoded and returned by 'telldir'. If the directory ++ offset can be enconded in 31 bits it is returned in the 'info' member ++ with 'is_packed' set to 1. ++ ++ Otherwise, the 'info' member describes an index in a dynamic array at ++ 'DIR' structure. */ ++ ++union dirstream_packed ++{ ++ long int l; ++ struct ++ { ++ unsigned long is_packed:1; ++ unsigned long info:31; ++ } p; ++}; ++ ++_Static_assert (sizeof (long int) == sizeof (union dirstream_packed), ++ "sizeof (long int) != sizeof (union dirstream_packed)"); ++ ++/* telldir will mantain a list of offsets that describe the obtained diretory ++ position if it can fit this information in the returned 'dirstream_packed' ++ struct. */ ++ ++struct dirstream_loc ++{ ++ off64_t filepos; ++}; ++ ++# define DYNARRAY_STRUCT dirstream_loc_t ++# define DYNARRAY_ELEMENT struct dirstream_loc ++# define DYNARRAY_PREFIX dirstream_loc_ ++# include ++#else ++ ++_Static_assert (sizeof (long int) == sizeof (off64_t), ++ "sizeof (long int) != sizeof (off64_t)"); ++#endif /* __LP64__ */ ++ ++#endif /* _TELLDIR_H */ +-- +2.38.2 + diff --git a/9999/0006-linux-Use-getdents64-on-non-LFS-readdir.patch b/9999/0006-linux-Use-getdents64-on-non-LFS-readdir.patch deleted file mode 100644 index b588195..0000000 --- a/9999/0006-linux-Use-getdents64-on-non-LFS-readdir.patch +++ /dev/null @@ -1,204 +0,0 @@ -From 5e92232132d809ca1a4dde473e3b9d061754db90 Mon Sep 17 00:00:00 2001 -From: Adhemerval Zanella -Date: Tue, 20 Oct 2020 13:37:15 -0300 -Subject: [PATCH 06/12] linux: Use getdents64 on non-LFS readdir - -The opendir allocates a translation buffer to be used to return the -non-LFS readdir entry. The obtained dirent64 struct is translated -to the temporary buffer on each readdir call. - -Entries that overflow d_off/d_ino and the buffer reallocation failure -(in case of large d_name) are ignored. - -Checked on x86_64-linux-gnu and i686-linux-gnu. ---- - sysdeps/unix/sysv/linux/closedir.c | 4 ++ - sysdeps/unix/sysv/linux/dirstream.h | 5 ++ - sysdeps/unix/sysv/linux/opendir.c | 21 +++++++ - sysdeps/unix/sysv/linux/readdir.c | 97 +++++++++++++++++++++-------- - 4 files changed, 101 insertions(+), 26 deletions(-) - -diff --git a/sysdeps/unix/sysv/linux/closedir.c b/sysdeps/unix/sysv/linux/closedir.c -index eee0193fc4..d876d49d78 100644 ---- a/sysdeps/unix/sysv/linux/closedir.c -+++ b/sysdeps/unix/sysv/linux/closedir.c -@@ -47,6 +47,10 @@ __closedir (DIR *dirp) - __libc_lock_fini (dirp->lock); - #endif - -+#if !_DIRENT_MATCHES_DIRENT64 -+ free (dirp->tbuffer); -+#endif -+ - free ((void *) dirp); - - return __close_nocancel (fd); -diff --git a/sysdeps/unix/sysv/linux/dirstream.h b/sysdeps/unix/sysv/linux/dirstream.h -index a0d8acf08d..064273cc31 100644 ---- a/sysdeps/unix/sysv/linux/dirstream.h -+++ b/sysdeps/unix/sysv/linux/dirstream.h -@@ -41,6 +41,11 @@ struct __dirstream - - int errcode; /* Delayed error code. */ - -+#if !defined __OFF_T_MATCHES_OFF64_T || !defined __INO_T_MATCHES_INO64_T -+ char *tbuffer; /* Translation buffer for non-LFS calls. */ -+ size_t tbuffer_size; /* Size of translation buffer. */ -+#endif -+ - /* Directory block. We must make sure that this block starts - at an address that is aligned adequately enough to store - dirent entries. Using the alignment of "void *" is not -diff --git a/sysdeps/unix/sysv/linux/opendir.c b/sysdeps/unix/sysv/linux/opendir.c -index 9e81d00630..bfd2f382a6 100644 ---- a/sysdeps/unix/sysv/linux/opendir.c -+++ b/sysdeps/unix/sysv/linux/opendir.c -@@ -120,6 +120,27 @@ __alloc_dir (int fd, bool close_fd, int flags, - return NULL; - } - -+#if !_DIRENT_MATCHES_DIRENT64 -+ /* Allocates a translation buffer to use as the returned 'struct direct' -+ for non-LFS 'readdir' calls. -+ -+ The initial NAME_MAX size should handle most cases, while readdir might -+ expand the buffer if required. */ -+ enum -+ { -+ tbuffer_size = sizeof (struct dirent) + NAME_MAX + 1 -+ }; -+ dirp->tbuffer = malloc (tbuffer_size); -+ if (dirp->tbuffer == NULL) -+ { -+ free (dirp); -+ if (close_fd) -+ __close_nocancel_nostatus (fd); -+ return NULL; -+ } -+ dirp->tbuffer_size = tbuffer_size; -+#endif -+ - dirp->fd = fd; - #if IS_IN (libc) - __libc_lock_init (dirp->lock); -diff --git a/sysdeps/unix/sysv/linux/readdir.c b/sysdeps/unix/sysv/linux/readdir.c -index 7743f50071..7b4571839e 100644 ---- a/sysdeps/unix/sysv/linux/readdir.c -+++ b/sysdeps/unix/sysv/linux/readdir.c -@@ -21,42 +21,87 @@ - #if !_DIRENT_MATCHES_DIRENT64 - #include - -+/* Translate the DP64 entry to the non-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_entry (struct __dirstream *ds, const struct dirent64 *dp64) -+{ -+ off_t d_off = dp64->d_off; -+ if (d_off != dp64->d_off) -+ return false; -+ ino_t d_ino = dp64->d_ino; -+ if (d_ino != dp64->d_ino) -+ return false; -+ -+ /* Expand the translation buffer to hold the new name size. */ -+ size_t new_reclen = sizeof (struct dirent) -+ + dp64->d_reclen - offsetof (struct dirent64, d_name); -+ if (new_reclen > ds->tbuffer_size) -+ { -+ char *newbuffer = realloc (ds->tbuffer, new_reclen); -+ if (newbuffer == NULL) -+ return false; -+ ds->tbuffer = newbuffer; -+ ds->tbuffer_size = new_reclen; -+ } -+ -+ struct dirent *dp = (struct dirent *) ds->tbuffer; -+ -+ dp->d_off = d_off; -+ dp->d_ino = d_ino; -+ dp->d_reclen = new_reclen; -+ dp->d_type = dp64->d_type; -+ memcpy (dp->d_name, dp64->d_name, -+ dp64->d_reclen - offsetof (struct dirent64, d_name)); -+ -+ return true; -+} -+ - /* Read a directory entry from DIRP. */ - struct dirent * - __readdir_unlocked (DIR *dirp) - { - const int saved_errno = errno; - -- if (dirp->offset >= dirp->size) -+ while (1) - { -- /* We've emptied out our buffer. Refill it. */ -- ssize_t bytes = __getdents (dirp->fd, dirp->data, dirp->allocation); -- if (bytes <= 0) -+ if (dirp->offset >= dirp->size) - { -- /* 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); -- return NULL; -+ /* We've emptied out our buffer. Refill it. */ -+ ssize_t bytes = __getdents64 (dirp->fd, dirp->data, -+ dirp->allocation); -+ 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); -+ return NULL; -+ } -+ dirp->size = bytes; -+ -+ /* Reset the offset into the buffer. */ -+ dirp->offset = 0; -+ } -+ -+ struct dirent64 *dp64 = (struct dirent64 *) &dirp->data[dirp->offset]; -+ dirp->offset += dp64->d_reclen; -+ -+ /* Skip entries which might overflow d_off/d_ino or if the translation -+ buffer can't be resized. */ -+ if (dirstream_entry (dirp, dp64)) -+ { -+ dirp->filepos = dp64->d_off; -+ return (struct dirent *) dirp->tbuffer; - } -- dirp->size = bytes; -- -- /* Reset the offset into the buffer. */ -- dirp->offset = 0; - } -- -- struct dirent *dp = (struct dirent *) &dirp->data[dirp->offset]; -- -- dirp->offset += dp->d_reclen; -- -- dirp->filepos = dp->d_off; -- -- return dp; - } - - struct dirent * --- -2.35.1 - diff --git a/9999/0007-linux-Add-__readdir64_unlocked.patch b/9999/0007-linux-Add-__readdir64_unlocked.patch new file mode 100644 index 0000000..631550c --- /dev/null +++ b/9999/0007-linux-Add-__readdir64_unlocked.patch @@ -0,0 +1,182 @@ +From 4cca67d0d2d615918e05db864c236e33c0fda8f3 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Mon, 13 Apr 2020 08:35:40 -0300 +Subject: [PATCH 07/10] linux: Add __readdir64_unlocked + +And use it on readdir_r implementation. + +Checked on i686-linux-gnu. +--- + include/dirent.h | 1 + + sysdeps/unix/sysv/linux/readdir64.c | 20 +++++-- + sysdeps/unix/sysv/linux/readdir64_r.c | 80 ++++++--------------------- + 3 files changed, 33 insertions(+), 68 deletions(-) + +diff --git a/include/dirent.h b/include/dirent.h +index d7567f5e86..0c6715d0e4 100644 +--- a/include/dirent.h ++++ b/include/dirent.h +@@ -21,6 +21,7 @@ extern DIR *__fdopendir (int __fd) attribute_hidden; + extern int __closedir (DIR *__dirp) attribute_hidden; + extern struct dirent *__readdir (DIR *__dirp) attribute_hidden; + extern struct dirent *__readdir_unlocked (DIR *__dirp) attribute_hidden; ++extern struct dirent64 *__readdir64_unlocked (DIR *__dirp) attribute_hidden; + extern struct dirent64 *__readdir64 (DIR *__dirp); + libc_hidden_proto (__readdir64) + extern int __readdir_r (DIR *__dirp, struct dirent *__entry, +diff --git a/sysdeps/unix/sysv/linux/readdir64.c b/sysdeps/unix/sysv/linux/readdir64.c +index 7952da5c27..9d82054182 100644 +--- a/sysdeps/unix/sysv/linux/readdir64.c ++++ b/sysdeps/unix/sysv/linux/readdir64.c +@@ -28,15 +28,11 @@ + + /* Read a directory entry from DIRP. */ + struct dirent64 * +-__readdir64 (DIR *dirp) ++__readdir64_unlocked (DIR *dirp) + { + struct dirent64 *dp; + int saved_errno = errno; + +-#if IS_IN (libc) +- __libc_lock_lock (dirp->lock); +-#endif +- + if (dirp->offset >= dirp->size) + { + /* We've emptied out our buffer. Refill it. */ +@@ -68,6 +64,20 @@ __readdir64 (DIR *dirp) + dirp->offset += dp->d_reclen; + dirp->filepos = dp->d_off; + ++ return dp; ++} ++ ++struct dirent64 * ++__readdir64 (DIR *dirp) ++{ ++ struct dirent64 *dp; ++ ++#if IS_IN (libc) ++ __libc_lock_lock (dirp->lock); ++#endif ++ ++ dp = __readdir64_unlocked (dirp); ++ + #if IS_IN (libc) + __libc_lock_unlock (dirp->lock); + #endif +diff --git a/sysdeps/unix/sysv/linux/readdir64_r.c b/sysdeps/unix/sysv/linux/readdir64_r.c +index afd7f9af0f..32962a176a 100644 +--- a/sysdeps/unix/sysv/linux/readdir64_r.c ++++ b/sysdeps/unix/sysv/linux/readdir64_r.c +@@ -32,89 +32,43 @@ __readdir64_r (DIR *dirp, struct dirent64 *entry, struct dirent64 **result) + { + struct dirent64 *dp; + size_t reclen; +- const int saved_errno = errno; +- int ret; + + __libc_lock_lock (dirp->lock); +- +- do ++ while (1) + { +- if (dirp->offset >= dirp->size) +- { +- /* We've emptied out our buffer. Refill it. */ +- +- size_t maxread = dirp->allocation; +- ssize_t bytes; +- +- maxread = dirp->allocation; +- +- 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; +- __set_errno (saved_errno); +- } +- if (bytes < 0) +- dirp->errcode = errno; +- +- dp = NULL; +- break; +- } +- dirp->size = (size_t) bytes; +- +- /* Reset the offset into the buffer. */ +- dirp->offset = 0; +- } +- +- dp = (struct dirent64 *) &dirp->data[dirp->offset]; ++ dp = __readdir64_unlocked (dirp); ++ if (dp == NULL) ++ break; + + reclen = dp->d_reclen; ++ if (reclen <= offsetof (struct dirent64, d_name) + NAME_MAX + 1) ++ break; + +- dirp->offset += reclen; +- +- dirp->filepos = dp->d_off; +- +- if (reclen > offsetof (struct dirent64, d_name) + NAME_MAX + 1) ++ /* The record is very long. It could still fit into the caller-supplied ++ buffer if we can skip padding at the end. */ ++ size_t namelen = _D_EXACT_NAMLEN (dp); ++ if (namelen <= NAME_MAX) + { +- /* The record is very long. It could still fit into the +- caller-supplied buffer if we can skip padding at the +- end. */ +- size_t namelen = _D_EXACT_NAMLEN (dp); +- if (namelen <= NAME_MAX) +- reclen = offsetof (struct dirent64, d_name) + namelen + 1; +- else +- { +- /* The name is too long. Ignore this file. */ +- dirp->errcode = ENAMETOOLONG; +- dp->d_ino = 0; +- continue; +- } ++ reclen = offsetof (struct dirent64, d_name) + namelen + 1; ++ break; + } + +- /* Skip deleted and ignored files. */ ++ /* The name is too long. Ignore this file. */ ++ dirp->errcode = ENAMETOOLONG; ++ dp->d_ino = 0; + } +- while (dp->d_ino == 0); + + if (dp != NULL) + { + *result = memcpy (entry, dp, reclen); + entry->d_reclen = reclen; +- ret = 0; + } + else +- { +- *result = NULL; +- ret = dirp->errcode; +- } ++ *result = NULL; + + __libc_lock_unlock (dirp->lock); + +- return ret; ++ return dp != NULL ? 0 : dirp->errcode; + } + + +-- +2.38.2 + diff --git a/9999/0007-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch b/9999/0007-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch deleted file mode 100644 index a239bbc..0000000 --- a/9999/0007-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch +++ /dev/null @@ -1,494 +0,0 @@ -From a9813305234d6163d86aa78c062017f05b7a79d6 Mon Sep 17 00:00:00 2001 -From: Adhemerval Zanella -Date: Mon, 13 Apr 2020 18:09:20 -0300 -Subject: [PATCH 07/12] linux: Set internal DIR filepos as off64_t [BZ #23960, - BZ #24050] - -It allows to obtain the expected entry offset on telldir and set -it correctly on seekdir on platforms where long int is smaller -than off64_t. - -On such cases telldir will mantain an internal list that maps the -DIR object off64_t offsets to the returned long int (the function -return value). The seekdir will then set the correct offset from -the internal list using the telldir as the list key. - -It also removes the overflow check on readdir and the returned value -will be truncated by the non-LFS off_t size. As Joseph has noted -in BZ #23960 comment #22, d_off is an opaque value and since -telldir/seekdir works regardless of the returned dirent d_off value. - -Finally it removed the requirement to check for overflow values on -telldir (BZ #24050). - -Checked on x86_64-linux-gnu, i686-linux-gnu, powerpc-linux-gnu, -and arm-linux-gnueabihf. ---- - dirent/Makefile | 2 +- - dirent/tst-seekdir2.c | 158 ++++++++++++++++++++++++++++ - sysdeps/unix/sysv/linux/closedir.c | 4 + - sysdeps/unix/sysv/linux/dirstream.h | 6 +- - sysdeps/unix/sysv/linux/opendir.c | 3 + - sysdeps/unix/sysv/linux/readdir.c | 1 + - sysdeps/unix/sysv/linux/rewinddir.c | 5 + - sysdeps/unix/sysv/linux/seekdir.c | 36 ++++++- - sysdeps/unix/sysv/linux/telldir.c | 47 ++++++++- - sysdeps/unix/sysv/linux/telldir.h | 64 +++++++++++ - 10 files changed, 317 insertions(+), 9 deletions(-) - create mode 100644 dirent/tst-seekdir2.c - create mode 100644 sysdeps/unix/sysv/linux/telldir.h - -diff --git a/dirent/Makefile b/dirent/Makefile -index b80f6a73ea..65119db578 100644 ---- a/dirent/Makefile -+++ b/dirent/Makefile -@@ -31,7 +31,7 @@ routines := opendir closedir readdir readdir_r rewinddir \ - scandir-cancel scandir-tail scandir64-tail - - tests := list tst-seekdir opendir-tst1 bug-readdir1 tst-fdopendir \ -- tst-fdopendir2 tst-scandir tst-scandir64 -+ tst-fdopendir2 tst-scandir tst-scandir64 tst-seekdir2 - - CFLAGS-scandir.c += $(uses-callbacks) - CFLAGS-scandir64.c += $(uses-callbacks) -diff --git a/dirent/tst-seekdir2.c b/dirent/tst-seekdir2.c -new file mode 100644 -index 0000000000..3e01b361e5 ---- /dev/null -+++ b/dirent/tst-seekdir2.c -@@ -0,0 +1,158 @@ -+/* Check multiple telldir and seekdir. -+ Copyright (C) 2020 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+/* Some filesystems returns a arbitrary value for d_off direnty entry (ext4 -+ for instance, where the value is an internal hash key). The idea of -+ create a large number of file is to try trigger a overflow d_off value -+ in a entry to check if telldir/seekdir does work corretly in such -+ case. */ -+static const char *dirname; -+static const size_t nfiles = 10240; -+ -+static void -+do_prepare (int argc, char *argv[]) -+{ -+ dirname = support_create_temp_directory ("tst-seekdir2-"); -+ -+ for (size_t i = 0; i < nfiles; i++) -+ { -+ int fd = create_temp_file_in_dir ("tempfile.", dirname, NULL); -+ TEST_VERIFY_EXIT (fd > 0); -+ close (fd); -+ } -+} -+#define PREPARE do_prepare -+ -+/* Check for old non Large File Support (LFS). */ -+static int -+do_test_not_lfs (void) -+{ -+ DIR *dirp = opendir (dirname); -+ TEST_VERIFY_EXIT (dirp != NULL); -+ -+ size_t dirp_count = 0; -+ for (struct dirent *dp = readdir (dirp); -+ dp != NULL; -+ dp = readdir (dirp)) -+ dirp_count++; -+ -+ /* The 2 extra files are '.' and '..'. */ -+ TEST_COMPARE (dirp_count, nfiles + 2); -+ -+ rewinddir (dirp); -+ -+ long *tdirp = xmalloc (dirp_count * sizeof (long)); -+ struct dirent **ddirp = xmalloc (dirp_count * sizeof (struct dirent *)); -+ -+ size_t i = 0; -+ do -+ { -+ tdirp[i] = telldir (dirp); -+ struct dirent *dp = readdir (dirp); -+ TEST_VERIFY_EXIT (dp != NULL); -+ ddirp[i] = xmalloc (dp->d_reclen); -+ memcpy (ddirp[i], dp, dp->d_reclen); -+ } while (++i < dirp_count); -+ -+ for (i = 0; i < dirp_count - 1; i++) -+ { -+ seekdir (dirp, tdirp[i]); -+ struct dirent *dp = readdir (dirp); -+ TEST_COMPARE (strcmp (dp->d_name, ddirp[i]->d_name), 0); -+ TEST_COMPARE (dp->d_ino, ddirp[i]->d_ino); -+ TEST_COMPARE (dp->d_off, ddirp[i]->d_off); -+ } -+ -+ closedir (dirp); -+ free (tdirp); -+ for (i = 0; i < dirp_count; i++) -+ free (ddirp[i]); -+ free (ddirp); -+ -+ return 0; -+} -+ -+/* Same as before but with LFS support. */ -+static int -+do_test_lfs (void) -+{ -+ DIR *dirp = opendir (dirname); -+ TEST_VERIFY_EXIT (dirp != NULL); -+ -+ size_t dirp_count = 0; -+ for (struct dirent64 * dp = readdir64 (dirp); -+ dp != NULL; -+ dp = readdir64 (dirp)) -+ dirp_count++; -+ -+ /* The 2 extra files are '.' and '..'. */ -+ TEST_COMPARE (dirp_count, nfiles + 2); -+ -+ rewinddir (dirp); -+ -+ long *tdirp = xmalloc (dirp_count * sizeof (long)); -+ struct dirent64 **ddirp = xmalloc (dirp_count * sizeof (struct dirent64 *)); -+ -+ size_t i = 0; -+ do -+ { -+ tdirp[i] = telldir (dirp); -+ struct dirent64 *dp = readdir64 (dirp); -+ TEST_VERIFY_EXIT (dp != NULL); -+ ddirp[i] = xmalloc (dp->d_reclen); -+ memcpy (ddirp[i], dp, dp->d_reclen); -+ } while (++i < dirp_count); -+ -+ for (i = 0; i < dirp_count - 1; i++) -+ { -+ seekdir (dirp, tdirp[i]); -+ struct dirent64 *dp = readdir64 (dirp); -+ TEST_COMPARE (strcmp (dp->d_name, ddirp[i]->d_name), 0); -+ TEST_COMPARE (dp->d_ino, ddirp[i]->d_ino); -+ TEST_COMPARE (dp->d_off, ddirp[i]->d_off); -+ } -+ -+ closedir (dirp); -+ free (tdirp); -+ for (i = 0; i < dirp_count; i++) -+ free (ddirp[i]); -+ free (ddirp); -+ -+ return 0; -+} -+ -+static int -+do_test (void) -+{ -+ do_test_not_lfs (); -+ do_test_lfs (); -+ -+ return 0; -+} -+ -+#include -diff --git a/sysdeps/unix/sysv/linux/closedir.c b/sysdeps/unix/sysv/linux/closedir.c -index d876d49d78..8e5669963c 100644 ---- a/sysdeps/unix/sysv/linux/closedir.c -+++ b/sysdeps/unix/sysv/linux/closedir.c -@@ -43,6 +43,10 @@ __closedir (DIR *dirp) - - fd = dirp->fd; - -+#ifndef __LP64__ -+ dirstream_loc_clear (&dirp->locs); -+#endif -+ - #if IS_IN (libc) - __libc_lock_fini (dirp->lock); - #endif -diff --git a/sysdeps/unix/sysv/linux/dirstream.h b/sysdeps/unix/sysv/linux/dirstream.h -index 064273cc31..a284292cb2 100644 ---- a/sysdeps/unix/sysv/linux/dirstream.h -+++ b/sysdeps/unix/sysv/linux/dirstream.h -@@ -21,6 +21,7 @@ - #include - - #include -+#include - - /* Directory stream type. - -@@ -37,7 +38,7 @@ struct __dirstream - size_t size; /* Total valid data in the block. */ - size_t offset; /* Current offset into the block. */ - -- off_t filepos; /* Position of next entry to read. */ -+ off64_t filepos; /* Position of next entry to read. */ - - int errcode; /* Delayed error code. */ - -@@ -45,6 +46,9 @@ struct __dirstream - char *tbuffer; /* Translation buffer for non-LFS calls. */ - size_t tbuffer_size; /* Size of translation buffer. */ - #endif -+#ifndef __LP64__ -+ struct dirstream_loc_t locs; /* off64_t to long int map for telldir. */ -+#endif - - /* Directory block. We must make sure that this block starts - at an address that is aligned adequately enough to store -diff --git a/sysdeps/unix/sysv/linux/opendir.c b/sysdeps/unix/sysv/linux/opendir.c -index bfd2f382a6..9a0b7ab4c4 100644 ---- a/sysdeps/unix/sysv/linux/opendir.c -+++ b/sysdeps/unix/sysv/linux/opendir.c -@@ -150,6 +150,9 @@ __alloc_dir (int fd, bool close_fd, int flags, - dirp->offset = 0; - dirp->filepos = 0; - dirp->errcode = 0; -+#ifndef __LP64__ -+ dirstream_loc_init (&dirp->locs); -+#endif - - return dirp; - } -diff --git a/sysdeps/unix/sysv/linux/readdir.c b/sysdeps/unix/sysv/linux/readdir.c -index 7b4571839e..94ac4cbae7 100644 ---- a/sysdeps/unix/sysv/linux/readdir.c -+++ b/sysdeps/unix/sysv/linux/readdir.c -@@ -17,6 +17,7 @@ - . */ - - #include -+#include - - #if !_DIRENT_MATCHES_DIRENT64 - #include -diff --git a/sysdeps/unix/sysv/linux/rewinddir.c b/sysdeps/unix/sysv/linux/rewinddir.c -index b1e8259703..0194d29e38 100644 ---- a/sysdeps/unix/sysv/linux/rewinddir.c -+++ b/sysdeps/unix/sysv/linux/rewinddir.c -@@ -33,6 +33,11 @@ __rewinddir (DIR *dirp) - dirp->offset = 0; - dirp->size = 0; - dirp->errcode = 0; -+ -+#ifndef __LP64__ -+ dirstream_loc_clear (&dirp->locs); -+#endif -+ - #if IS_IN (libc) - __libc_lock_unlock (dirp->lock); - #endif -diff --git a/sysdeps/unix/sysv/linux/seekdir.c b/sysdeps/unix/sysv/linux/seekdir.c -index f4e1a9f8e0..0c3e58a2ed 100644 ---- a/sysdeps/unix/sysv/linux/seekdir.c -+++ b/sysdeps/unix/sysv/linux/seekdir.c -@@ -22,14 +22,40 @@ - #include - - /* Seek to position POS in DIRP. */ --/* XXX should be __seekdir ? */ - void - seekdir (DIR *dirp, long int pos) - { -+ off64_t filepos; -+ - __libc_lock_lock (dirp->lock); -- (void) __lseek (dirp->fd, pos, SEEK_SET); -- dirp->size = 0; -- dirp->offset = 0; -- dirp->filepos = pos; -+ -+#ifndef __LP64__ -+ union dirstream_packed dsp; -+ -+ dsp.l = pos; -+ -+ if (dsp.p.is_packed == 1) -+ filepos = dsp.p.info; -+ else -+ { -+ size_t index = dsp.p.info; -+ -+ if (index >= dirstream_loc_size (&dirp->locs)) -+ return; -+ struct dirstream_loc *loc = dirstream_loc_at (&dirp->locs, index); -+ filepos = loc->filepos; -+ } -+#else -+ filepos = pos; -+#endif -+ -+ if (dirp->filepos != filepos) -+ { -+ __lseek64 (dirp->fd, filepos, SEEK_SET); -+ dirp->filepos = filepos; -+ dirp->offset = 0; -+ dirp->size = 0; -+ } -+ - __libc_lock_unlock (dirp->lock); - } -diff --git a/sysdeps/unix/sysv/linux/telldir.c b/sysdeps/unix/sysv/linux/telldir.c -index b60b231e48..874905489f 100644 ---- a/sysdeps/unix/sysv/linux/telldir.c -+++ b/sysdeps/unix/sysv/linux/telldir.c -@@ -18,16 +18,59 @@ - #include - - #include -+#include - - /* Return the current position of DIRP. */ - long int - telldir (DIR *dirp) - { -- long int ret; -+#ifndef __LP64__ -+ /* If the directory position fits in the packet structure returns it. -+ Otherwise, check if the position is already been recorded in the -+ dynamic array. If not, add the new record. */ -+ -+ union dirstream_packed dsp; -+ size_t i; - - __libc_lock_lock (dirp->lock); -- ret = dirp->filepos; -+ -+ if (dirp->filepos < (1U << 31)) -+ { -+ dsp.p.is_packed = 1; -+ dsp.p.info = dirp->filepos; -+ goto out; -+ } -+ -+ dsp.l = -1; -+ -+ for (i = 0; i < dirstream_loc_size (&dirp->locs); i++) -+ { -+ struct dirstream_loc *loc = dirstream_loc_at (&dirp->locs, i); -+ if (loc->filepos == dirp->filepos) -+ break; -+ } -+ if (i == dirstream_loc_size (&dirp->locs)) -+ { -+ dirstream_loc_add (&dirp->locs, -+ (struct dirstream_loc) { dirp->filepos }); -+ if (dirstream_loc_has_failed (&dirp->locs)) -+ goto out; -+ } -+ -+ dsp.p.is_packed = 0; -+ /* This assignment might overflow, however most likely ENOMEM would happen -+ long before. */ -+ dsp.p.info = i; -+ -+out: - __libc_lock_unlock (dirp->lock); - -+ return dsp.l; -+#else -+ long int ret; -+ __libc_lock_lock (dirp->lock); -+ ret = dirp->filepos; -+ __libc_lock_unlock (dirp->lock); - return ret; -+#endif - } -diff --git a/sysdeps/unix/sysv/linux/telldir.h b/sysdeps/unix/sysv/linux/telldir.h -new file mode 100644 -index 0000000000..7c45886341 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/telldir.h -@@ -0,0 +1,64 @@ -+/* Linux internal telldir definitions. -+ Copyright (C) 2020 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#ifndef _TELLDIR_H -+#define _TELLDIR_H 1 -+ -+#ifndef __LP64__ -+ -+/* On platforms where long int is smaller than off64_t this is how the -+ returned value is encoded and returned by 'telldir'. If the directory -+ offset can be enconded in 31 bits it is returned in the 'info' member -+ with 'is_packed' set to 1. -+ -+ Otherwise, the 'info' member describes an index in a dynamic array at -+ 'DIR' structure. */ -+ -+union dirstream_packed -+{ -+ long int l; -+ struct -+ { -+ unsigned long is_packed:1; -+ unsigned long info:31; -+ } p; -+}; -+ -+_Static_assert (sizeof (long int) == sizeof (union dirstream_packed), -+ "sizeof (long int) != sizeof (union dirstream_packed)"); -+ -+/* telldir will mantain a list of offsets that describe the obtained diretory -+ position if it can fit this information in the returned 'dirstream_packed' -+ struct. */ -+ -+struct dirstream_loc -+{ -+ off64_t filepos; -+}; -+ -+# define DYNARRAY_STRUCT dirstream_loc_t -+# define DYNARRAY_ELEMENT struct dirstream_loc -+# define DYNARRAY_PREFIX dirstream_loc_ -+# include -+#else -+ -+_Static_assert (sizeof (long int) == sizeof (off64_t), -+ "sizeof (long int) != sizeof (off64_t)"); -+#endif /* __LP64__ */ -+ -+#endif /* _TELLDIR_H */ --- -2.35.1 - diff --git a/9999/0008-linux-Add-__old_readdir64_unlocked.patch b/9999/0008-linux-Add-__old_readdir64_unlocked.patch new file mode 100644 index 0000000..3cd2923 --- /dev/null +++ b/9999/0008-linux-Add-__old_readdir64_unlocked.patch @@ -0,0 +1,194 @@ +From cd6d96ae0a09c1bff40f19d54e2910d7d4e74864 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Tue, 14 Apr 2020 11:14:22 -0300 +Subject: [PATCH 08/10] linux: Add __old_readdir64_unlocked + +And use it __old_readdir64_r. + +Checked on i686-linux-gnu. +--- + sysdeps/unix/sysv/linux/olddirent.h | 2 + + sysdeps/unix/sysv/linux/readdir64.c | 24 +++++--- + sysdeps/unix/sysv/linux/readdir64_r.c | 79 ++++++--------------------- + 3 files changed, 35 insertions(+), 70 deletions(-) + +diff --git a/sysdeps/unix/sysv/linux/olddirent.h b/sysdeps/unix/sysv/linux/olddirent.h +index 9a22609177..00c84b9521 100644 +--- a/sysdeps/unix/sysv/linux/olddirent.h ++++ b/sysdeps/unix/sysv/linux/olddirent.h +@@ -32,6 +32,8 @@ struct __old_dirent64 + /* Now define the internal interfaces. */ + extern struct __old_dirent64 *__old_readdir64 (DIR *__dirp); + libc_hidden_proto (__old_readdir64); ++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) +diff --git a/sysdeps/unix/sysv/linux/readdir64.c b/sysdeps/unix/sysv/linux/readdir64.c +index 9d82054182..bbe247f95d 100644 +--- a/sysdeps/unix/sysv/linux/readdir64.c ++++ b/sysdeps/unix/sysv/linux/readdir64.c +@@ -104,15 +104,11 @@ versioned_symbol (libc, __readdir64, readdir64, GLIBC_2_2); + + attribute_compat_text_section + struct __old_dirent64 * +-__old_readdir64 (DIR *dirp) ++__old_readdir64_unlocked (DIR *dirp) + { + struct __old_dirent64 *dp; + int saved_errno = errno; + +-#if IS_IN (libc) +- __libc_lock_lock (dirp->lock); +-#endif +- + if (dirp->offset >= dirp->size) + { + /* We've emptied out our buffer. Refill it. */ +@@ -129,9 +125,6 @@ __old_readdir64 (DIR *dirp) + 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; +@@ -144,6 +137,21 @@ __old_readdir64 (DIR *dirp) + dirp->offset += dp->d_reclen; + dirp->filepos = dp->d_off; + ++ return dp; ++} ++ ++attribute_compat_text_section ++struct __old_dirent64 * ++__old_readdir64 (DIR *dirp) ++{ ++ struct __old_dirent64 *dp; ++ ++#if IS_IN (libc) ++ __libc_lock_lock (dirp->lock); ++#endif ++ ++ dp = __old_readdir64_unlocked (dirp); ++ + #if IS_IN (libc) + __libc_lock_unlock (dirp->lock); + #endif +diff --git a/sysdeps/unix/sysv/linux/readdir64_r.c b/sysdeps/unix/sysv/linux/readdir64_r.c +index 32962a176a..699d120b76 100644 +--- a/sysdeps/unix/sysv/linux/readdir64_r.c ++++ b/sysdeps/unix/sysv/linux/readdir64_r.c +@@ -91,89 +91,44 @@ __old_readdir64_r (DIR *dirp, struct __old_dirent64 *entry, + { + struct __old_dirent64 *dp; + size_t reclen; +- const int saved_errno = errno; +- int ret; + + __libc_lock_lock (dirp->lock); + +- do ++ while (1) + { +- if (dirp->offset >= dirp->size) +- { +- /* We've emptied out our buffer. Refill it. */ +- +- size_t maxread = dirp->allocation; +- ssize_t bytes; +- +- maxread = dirp->allocation; +- +- 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; +- __set_errno (saved_errno); +- } +- if (bytes < 0) +- dirp->errcode = errno; +- +- dp = NULL; +- break; +- } +- dirp->size = (size_t) bytes; +- +- /* Reset the offset into the buffer. */ +- dirp->offset = 0; +- } +- +- dp = (struct __old_dirent64 *) &dirp->data[dirp->offset]; ++ dp = __old_readdir64_unlocked (dirp); ++ if (dp == NULL) ++ break; + + reclen = dp->d_reclen; ++ if (reclen <= offsetof (struct __old_dirent64, d_name) + NAME_MAX + 1) ++ break; + +- dirp->offset += reclen; +- +- dirp->filepos = dp->d_off; +- +- if (reclen > offsetof (struct __old_dirent64, d_name) + NAME_MAX + 1) ++ /* The record is very long. It could still fit into the caller-supplied ++ buffer if we can skip padding at the end. */ ++ size_t namelen = _D_EXACT_NAMLEN (dp); ++ if (namelen <= NAME_MAX) + { +- /* The record is very long. It could still fit into the +- caller-supplied buffer if we can skip padding at the +- end. */ +- size_t namelen = _D_EXACT_NAMLEN (dp); +- if (namelen <= NAME_MAX) +- reclen = offsetof (struct __old_dirent64, d_name) + namelen + 1; +- else +- { +- /* The name is too long. Ignore this file. */ +- dirp->errcode = ENAMETOOLONG; +- dp->d_ino = 0; +- continue; +- } ++ reclen = offsetof (struct dirent64, d_name) + namelen + 1; ++ break; + } + +- /* Skip deleted and ignored files. */ ++ /* The name is too long. Ignore this file. */ ++ dirp->errcode = ENAMETOOLONG; ++ dp->d_ino = 0; + } +- while (dp->d_ino == 0); + + if (dp != NULL) + { + *result = memcpy (entry, dp, reclen); + entry->d_reclen = reclen; +- ret = 0; + } + else +- { +- *result = NULL; +- ret = dirp->errcode; +- } ++ *result = NULL; + + __libc_lock_unlock (dirp->lock); + +- return ret; ++ return dp != NULL ? 0 : dirp->errcode; + } + + compat_symbol (libc, __old_readdir64_r, readdir64_r, GLIBC_2_1); +-- +2.38.2 + diff --git a/9999/0008-linux-Add-__readdir64_unlocked.patch b/9999/0008-linux-Add-__readdir64_unlocked.patch deleted file mode 100644 index 540ddf7..0000000 --- a/9999/0008-linux-Add-__readdir64_unlocked.patch +++ /dev/null @@ -1,181 +0,0 @@ -From 81cdcf158a683bb9c999967de2e332e5c5881bc9 Mon Sep 17 00:00:00 2001 -From: Adhemerval Zanella -Date: Mon, 13 Apr 2020 08:35:40 -0300 -Subject: [PATCH 08/12] linux: Add __readdir64_unlocked - -And use it on readdir_r implementation. - -Checked on i686-linux-gnu. ---- - include/dirent.h | 1 + - sysdeps/unix/sysv/linux/readdir64.c | 20 +++++-- - sysdeps/unix/sysv/linux/readdir64_r.c | 80 ++++++--------------------- - 3 files changed, 33 insertions(+), 68 deletions(-) - -diff --git a/include/dirent.h b/include/dirent.h -index d7567f5e86..0c6715d0e4 100644 ---- a/include/dirent.h -+++ b/include/dirent.h -@@ -21,6 +21,7 @@ extern DIR *__fdopendir (int __fd) attribute_hidden; - extern int __closedir (DIR *__dirp) attribute_hidden; - extern struct dirent *__readdir (DIR *__dirp) attribute_hidden; - extern struct dirent *__readdir_unlocked (DIR *__dirp) attribute_hidden; -+extern struct dirent64 *__readdir64_unlocked (DIR *__dirp) attribute_hidden; - extern struct dirent64 *__readdir64 (DIR *__dirp); - libc_hidden_proto (__readdir64) - extern int __readdir_r (DIR *__dirp, struct dirent *__entry, -diff --git a/sysdeps/unix/sysv/linux/readdir64.c b/sysdeps/unix/sysv/linux/readdir64.c -index d990a36e4e..c4539f6d96 100644 ---- a/sysdeps/unix/sysv/linux/readdir64.c -+++ b/sysdeps/unix/sysv/linux/readdir64.c -@@ -28,14 +28,10 @@ - - /* Read a directory entry from DIRP. */ - struct dirent64 * --__readdir64 (DIR *dirp) -+__readdir64_unlocked (DIR *dirp) - { - const int saved_errno = errno; - --#if IS_IN (libc) -- __libc_lock_lock (dirp->lock); --#endif -- - if (dirp->offset >= dirp->size) - { - /* We've emptied out our buffer. Refill it. */ -@@ -65,6 +61,20 @@ __readdir64 (DIR *dirp) - - dirp->filepos = dp->d_off; - -+ return dp; -+} -+ -+struct dirent64 * -+__readdir64 (DIR *dirp) -+{ -+ struct dirent64 *dp; -+ -+#if IS_IN (libc) -+ __libc_lock_lock (dirp->lock); -+#endif -+ -+ dp = __readdir64_unlocked (dirp); -+ - #if IS_IN (libc) - __libc_lock_unlock (dirp->lock); - #endif -diff --git a/sysdeps/unix/sysv/linux/readdir64_r.c b/sysdeps/unix/sysv/linux/readdir64_r.c -index afd7f9af0f..32962a176a 100644 ---- a/sysdeps/unix/sysv/linux/readdir64_r.c -+++ b/sysdeps/unix/sysv/linux/readdir64_r.c -@@ -32,89 +32,43 @@ __readdir64_r (DIR *dirp, struct dirent64 *entry, struct dirent64 **result) - { - struct dirent64 *dp; - size_t reclen; -- const int saved_errno = errno; -- int ret; - - __libc_lock_lock (dirp->lock); -- -- do -+ while (1) - { -- if (dirp->offset >= dirp->size) -- { -- /* We've emptied out our buffer. Refill it. */ -- -- size_t maxread = dirp->allocation; -- ssize_t bytes; -- -- maxread = dirp->allocation; -- -- 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; -- __set_errno (saved_errno); -- } -- if (bytes < 0) -- dirp->errcode = errno; -- -- dp = NULL; -- break; -- } -- dirp->size = (size_t) bytes; -- -- /* Reset the offset into the buffer. */ -- dirp->offset = 0; -- } -- -- dp = (struct dirent64 *) &dirp->data[dirp->offset]; -+ dp = __readdir64_unlocked (dirp); -+ if (dp == NULL) -+ break; - - reclen = dp->d_reclen; -+ if (reclen <= offsetof (struct dirent64, d_name) + NAME_MAX + 1) -+ break; - -- dirp->offset += reclen; -- -- dirp->filepos = dp->d_off; -- -- if (reclen > offsetof (struct dirent64, d_name) + NAME_MAX + 1) -+ /* The record is very long. It could still fit into the caller-supplied -+ buffer if we can skip padding at the end. */ -+ size_t namelen = _D_EXACT_NAMLEN (dp); -+ if (namelen <= NAME_MAX) - { -- /* The record is very long. It could still fit into the -- caller-supplied buffer if we can skip padding at the -- end. */ -- size_t namelen = _D_EXACT_NAMLEN (dp); -- if (namelen <= NAME_MAX) -- reclen = offsetof (struct dirent64, d_name) + namelen + 1; -- else -- { -- /* The name is too long. Ignore this file. */ -- dirp->errcode = ENAMETOOLONG; -- dp->d_ino = 0; -- continue; -- } -+ reclen = offsetof (struct dirent64, d_name) + namelen + 1; -+ break; - } - -- /* Skip deleted and ignored files. */ -+ /* The name is too long. Ignore this file. */ -+ dirp->errcode = ENAMETOOLONG; -+ dp->d_ino = 0; - } -- while (dp->d_ino == 0); - - if (dp != NULL) - { - *result = memcpy (entry, dp, reclen); - entry->d_reclen = reclen; -- ret = 0; - } - else -- { -- *result = NULL; -- ret = dirp->errcode; -- } -+ *result = NULL; - - __libc_lock_unlock (dirp->lock); - -- return ret; -+ return dp != NULL ? 0 : dirp->errcode; - } - - --- -2.35.1 - diff --git a/9999/0009-linux-Add-__old_readdir64_unlocked.patch b/9999/0009-linux-Add-__old_readdir64_unlocked.patch deleted file mode 100644 index 52af81a..0000000 --- a/9999/0009-linux-Add-__old_readdir64_unlocked.patch +++ /dev/null @@ -1,184 +0,0 @@ -From 82605e1450880ac7d40f1b5d12eecbf2f0815535 Mon Sep 17 00:00:00 2001 -From: Adhemerval Zanella -Date: Tue, 14 Apr 2020 11:14:22 -0300 -Subject: [PATCH 09/12] linux: Add __old_readdir64_unlocked - -And use it __old_readdir64_r. - -Checked on i686-linux-gnu. ---- - sysdeps/unix/sysv/linux/olddirent.h | 2 + - sysdeps/unix/sysv/linux/readdir64.c | 21 +++++-- - sysdeps/unix/sysv/linux/readdir64_r.c | 79 ++++++--------------------- - 3 files changed, 35 insertions(+), 67 deletions(-) - -diff --git a/sysdeps/unix/sysv/linux/olddirent.h b/sysdeps/unix/sysv/linux/olddirent.h -index 9a22609177..00c84b9521 100644 ---- a/sysdeps/unix/sysv/linux/olddirent.h -+++ b/sysdeps/unix/sysv/linux/olddirent.h -@@ -32,6 +32,8 @@ struct __old_dirent64 - /* Now define the internal interfaces. */ - extern struct __old_dirent64 *__old_readdir64 (DIR *__dirp); - libc_hidden_proto (__old_readdir64); -+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) -diff --git a/sysdeps/unix/sysv/linux/readdir64.c b/sysdeps/unix/sysv/linux/readdir64.c -index c4539f6d96..dbf6a8c54d 100644 ---- a/sysdeps/unix/sysv/linux/readdir64.c -+++ b/sysdeps/unix/sysv/linux/readdir64.c -@@ -101,15 +101,11 @@ versioned_symbol (libc, __readdir64, readdir64, GLIBC_2_2); - - attribute_compat_text_section - struct __old_dirent64 * --__old_readdir64 (DIR *dirp) -+__old_readdir64_unlocked (DIR *dirp) - { - struct __old_dirent64 *dp; - int saved_errno = errno; - --#if IS_IN (libc) -- __libc_lock_lock (dirp->lock); --#endif -- - do - { - size_t reclen; -@@ -153,6 +149,21 @@ __old_readdir64 (DIR *dirp) - /* Skip deleted files. */ - } while (dp->d_ino == 0); - -+ return dp; -+} -+ -+attribute_compat_text_section -+struct __old_dirent64 * -+__old_readdir64 (DIR *dirp) -+{ -+ struct __old_dirent64 *dp; -+ -+#if IS_IN (libc) -+ __libc_lock_lock (dirp->lock); -+#endif -+ -+ dp = __old_readdir64_unlocked (dirp); -+ - #if IS_IN (libc) - __libc_lock_unlock (dirp->lock); - #endif -diff --git a/sysdeps/unix/sysv/linux/readdir64_r.c b/sysdeps/unix/sysv/linux/readdir64_r.c -index 32962a176a..699d120b76 100644 ---- a/sysdeps/unix/sysv/linux/readdir64_r.c -+++ b/sysdeps/unix/sysv/linux/readdir64_r.c -@@ -91,89 +91,44 @@ __old_readdir64_r (DIR *dirp, struct __old_dirent64 *entry, - { - struct __old_dirent64 *dp; - size_t reclen; -- const int saved_errno = errno; -- int ret; - - __libc_lock_lock (dirp->lock); - -- do -+ while (1) - { -- if (dirp->offset >= dirp->size) -- { -- /* We've emptied out our buffer. Refill it. */ -- -- size_t maxread = dirp->allocation; -- ssize_t bytes; -- -- maxread = dirp->allocation; -- -- 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; -- __set_errno (saved_errno); -- } -- if (bytes < 0) -- dirp->errcode = errno; -- -- dp = NULL; -- break; -- } -- dirp->size = (size_t) bytes; -- -- /* Reset the offset into the buffer. */ -- dirp->offset = 0; -- } -- -- dp = (struct __old_dirent64 *) &dirp->data[dirp->offset]; -+ dp = __old_readdir64_unlocked (dirp); -+ if (dp == NULL) -+ break; - - reclen = dp->d_reclen; -+ if (reclen <= offsetof (struct __old_dirent64, d_name) + NAME_MAX + 1) -+ break; - -- dirp->offset += reclen; -- -- dirp->filepos = dp->d_off; -- -- if (reclen > offsetof (struct __old_dirent64, d_name) + NAME_MAX + 1) -+ /* The record is very long. It could still fit into the caller-supplied -+ buffer if we can skip padding at the end. */ -+ size_t namelen = _D_EXACT_NAMLEN (dp); -+ if (namelen <= NAME_MAX) - { -- /* The record is very long. It could still fit into the -- caller-supplied buffer if we can skip padding at the -- end. */ -- size_t namelen = _D_EXACT_NAMLEN (dp); -- if (namelen <= NAME_MAX) -- reclen = offsetof (struct __old_dirent64, d_name) + namelen + 1; -- else -- { -- /* The name is too long. Ignore this file. */ -- dirp->errcode = ENAMETOOLONG; -- dp->d_ino = 0; -- continue; -- } -+ reclen = offsetof (struct dirent64, d_name) + namelen + 1; -+ break; - } - -- /* Skip deleted and ignored files. */ -+ /* The name is too long. Ignore this file. */ -+ dirp->errcode = ENAMETOOLONG; -+ dp->d_ino = 0; - } -- while (dp->d_ino == 0); - - if (dp != NULL) - { - *result = memcpy (entry, dp, reclen); - entry->d_reclen = reclen; -- ret = 0; - } - else -- { -- *result = NULL; -- ret = dirp->errcode; -- } -+ *result = NULL; - - __libc_lock_unlock (dirp->lock); - -- return ret; -+ return dp != NULL ? 0 : dirp->errcode; - } - - compat_symbol (libc, __old_readdir64_r, readdir64_r, GLIBC_2_1); --- -2.35.1 - diff --git a/9999/0009-linux-Use-getdents64-on-readdir64-compat-implementat.patch b/9999/0009-linux-Use-getdents64-on-readdir64-compat-implementat.patch new file mode 100644 index 0000000..7a9c5a3 --- /dev/null +++ b/9999/0009-linux-Use-getdents64-on-readdir64-compat-implementat.patch @@ -0,0 +1,265 @@ +From c71a60022adc7c9b7e37a813e2abad0d0724245a Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Tue, 20 Oct 2020 16:00:43 -0300 +Subject: [PATCH 09/10] 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/getdents64.c | 93 ---------------------------- + sysdeps/unix/sysv/linux/olddirent.h | 2 - + sysdeps/unix/sysv/linux/opendir.c | 15 ++++- + sysdeps/unix/sysv/linux/readdir64.c | 62 +++++++++++++++---- + 4 files changed, 64 insertions(+), 108 deletions(-) + +diff --git a/sysdeps/unix/sysv/linux/getdents64.c b/sysdeps/unix/sysv/linux/getdents64.c +index 510a586859..92481526c5 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 +- +-# if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2) +-# include +-# include +- +-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 00c84b9521..68aafd7c02 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/opendir.c b/sysdeps/unix/sysv/linux/opendir.c +index 9a0b7ab4c4..df40b0a64e 100644 +--- a/sysdeps/unix/sysv/linux/opendir.c ++++ b/sysdeps/unix/sysv/linux/opendir.c +@@ -23,6 +23,11 @@ + + #include + ++#include ++#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2) ++# include ++#endif ++ + enum { + opendir_oflags = O_RDONLY|O_NDELAY|O_DIRECTORY|O_LARGEFILE|O_CLOEXEC + }; +@@ -128,7 +133,15 @@ __alloc_dir (int fd, bool close_fd, int flags, + expand the buffer if required. */ + enum + { +- tbuffer_size = sizeof (struct dirent) + NAME_MAX + 1 ++ tbuffer_size = ++# if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2) ++ /* This is used on compat readdir64. */ ++ MAX (sizeof (struct dirent), ++ sizeof (struct __old_dirent64)) ++# else ++ sizeof (struct dirent) ++# endif ++ + NAME_MAX + 1 + }; + dirp->tbuffer = malloc (tbuffer_size); + if (dirp->tbuffer == NULL) +diff --git a/sysdeps/unix/sysv/linux/readdir64.c b/sysdeps/unix/sysv/linux/readdir64.c +index bbe247f95d..01e834e238 100644 +--- a/sysdeps/unix/sysv/linux/readdir64.c ++++ b/sysdeps/unix/sysv/linux/readdir64.c +@@ -102,21 +102,52 @@ versioned_symbol (libc, __readdir64, readdir64, GLIBC_2_2); + # if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2) + # include + ++/* 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. */ ++ ino_t d_ino = dp64->d_ino; ++ if (d_ino != dp64->d_ino) ++ return false; ++ ++ /* Expand the translation buffer to hold the new namesize. */ ++ size_t d_reclen = sizeof (struct __old_dirent64) ++ + dp64->d_reclen - offsetof (struct dirent64, d_name); ++ if (d_reclen > ds->tbuffer_size) ++ { ++ char *newbuffer = realloc (ds->tbuffer, d_reclen); ++ if (newbuffer == NULL) ++ return false; ++ ds->tbuffer = newbuffer; ++ ds->tbuffer_size = d_reclen; ++ } ++ ++ struct __old_dirent64 *olddp64 = (struct __old_dirent64 *) ds->tbuffer; ++ ++ olddp64->d_off = dp64->d_off; ++ olddp64->d_ino = dp64->d_ino; ++ olddp64->d_reclen = dp64->d_reclen; ++ olddp64->d_type = dp64->d_type; ++ memcpy (olddp64->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 +158,24 @@ __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)) ++ { ++ dirp->filepos = dp64->d_off; ++ return (struct __old_dirent64 *) dirp->tbuffer; ++ } ++ ++ return NULL; + } + + attribute_compat_text_section +-- +2.38.2 + diff --git a/9999/0010-dirent-Deprecate-getdirentries.patch b/9999/0010-dirent-Deprecate-getdirentries.patch new file mode 100644 index 0000000..28f744a --- /dev/null +++ b/9999/0010-dirent-Deprecate-getdirentries.patch @@ -0,0 +1,100 @@ +From 2f0668caf22acf6493dce8dcfd670e4b35fb6892 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Fri, 17 Apr 2020 09:59:51 -0300 +Subject: [PATCH 10/10] dirent: Deprecate getdirentries + +The interface has some issues: + + 1. It is build on top getdents on Linux and requires handling + non-LFS call using LFS getdents. + + 2. It is not wildly used and the non-LFS support is as problematic + as non-LFS readdir. glibc only exports the LFS getdents. + + 3. It is not a direct replacement over BSD since on some plataform + its signature has changed (FreeBSD 11, for instance, used to + set the offset as a 'long' and changed to 'off_t' on version 12). + +The idea is to eventually move the symbols to compat ones. +--- + NEWS | 3 +++ + dirent/dirent.h | 14 ++++++++++---- + sysdeps/unix/sysv/linux/Makefile | 4 ++++ + 3 files changed, 17 insertions(+), 4 deletions(-) + +diff --git a/NEWS b/NEWS +index a10bb08fb0..2b4ed6bbc1 100644 +--- a/NEWS ++++ b/NEWS +@@ -21,6 +21,9 @@ Deprecated and removed features, and other changes affecting compatibility: + corresponds to the AT_PLATFORM system name, or employs the legacy AT_HWCAP + search mechanism, which was deprecated in version 2.33. + ++* The function getdirentries is now deprecated, applications should use ++ either getdents64, readdir64 or readdir. ++ + Changes to build and runtime requirements: + + [Add changes to build and runtime requirements here] +diff --git a/dirent/dirent.h b/dirent/dirent.h +index c47d3273b2..1c299e5be8 100644 +--- a/dirent/dirent.h ++++ b/dirent/dirent.h +@@ -350,29 +350,35 @@ extern int alphasort64 (const struct dirent64 **__e1, + /* Read directory entries from FD into BUF, reading at most NBYTES. + Reading starts at offset *BASEP, and *BASEP is updated with the new + position after reading. Returns the number of bytes read; zero when at +- end of directory; or -1 for errors. */ ++ end of directory; or -1 for errors. ++ This is deprecated and getdents64 or readdir should be used instead. */ + # ifndef __USE_FILE_OFFSET64 + extern __ssize_t getdirentries (int __fd, char *__restrict __buf, + size_t __nbytes, + __off_t *__restrict __basep) +- __THROW __nonnull ((2, 4)); ++ __THROW __nonnull ((2, 4)) ++ __attribute_deprecated_msg__ ("Use getdents64 instead"); + # else + # ifdef __REDIRECT + extern __ssize_t __REDIRECT_NTH (getdirentries, + (int __fd, char *__restrict __buf, + size_t __nbytes, + __off64_t *__restrict __basep), +- getdirentries64) __nonnull ((2, 4)); ++ getdirentries64) ++ __nonnull ((2, 4)) ++ __attribute_deprecated_msg__ ("Use getdents64 instead"); + # else + # define getdirentries getdirentries64 + # endif + # endif + + # ifdef __USE_LARGEFILE64 ++/* This is deprecated and getdents64 or readdir64 should be used instead. */ + extern __ssize_t getdirentries64 (int __fd, char *__restrict __buf, + size_t __nbytes, + __off64_t *__restrict __basep) +- __THROW __nonnull ((2, 4)); ++ __THROW __nonnull ((2, 4)) ++ __attribute_deprecated_msg__ ("Use getdents64 instead"); + # endif + #endif /* Use misc. */ + +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index f298878e8f..41e5341450 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -467,6 +467,10 @@ tests += \ + tst-getdents64 \ + tst-readdir64-compat \ + # tests ++ ++# Avoid the warning for the weak_alias for _DIRENT_MATCHES_DIRENT64 ++CFLAGS-getdirentries64.o = -Wno-deprecated-declarations ++CFLAGS-getdirentries64.os = -Wno-deprecated-declarations + endif # $(subdir) == dirent + + ifeq ($(subdir),nis) +-- +2.38.2 + diff --git a/9999/0010-linux-Use-getdents64-on-readdir64-compat-implementat.patch b/9999/0010-linux-Use-getdents64-on-readdir64-compat-implementat.patch deleted file mode 100644 index 5bbea04..0000000 --- a/9999/0010-linux-Use-getdents64-on-readdir64-compat-implementat.patch +++ /dev/null @@ -1,298 +0,0 @@ -From 7a72e18a7b710feea5375578450e11a106336102 Mon Sep 17 00:00:00 2001 -From: Adhemerval Zanella -Date: Tue, 20 Oct 2020 16:00:43 -0300 -Subject: [PATCH 10/12] 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/getdents64.c | 93 ------------------------ - sysdeps/unix/sysv/linux/olddirent.h | 2 - - sysdeps/unix/sysv/linux/opendir.c | 15 +++- - sysdeps/unix/sysv/linux/readdir64.c | 104 +++++++++++++++++---------- - 4 files changed, 79 insertions(+), 135 deletions(-) - -diff --git a/sysdeps/unix/sysv/linux/getdents64.c b/sysdeps/unix/sysv/linux/getdents64.c -index 510a586859..92481526c5 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 -- --# if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2) --# include --# include -- --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 00c84b9521..68aafd7c02 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/opendir.c b/sysdeps/unix/sysv/linux/opendir.c -index 9a0b7ab4c4..df40b0a64e 100644 ---- a/sysdeps/unix/sysv/linux/opendir.c -+++ b/sysdeps/unix/sysv/linux/opendir.c -@@ -23,6 +23,11 @@ - - #include - -+#include -+#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2) -+# include -+#endif -+ - enum { - opendir_oflags = O_RDONLY|O_NDELAY|O_DIRECTORY|O_LARGEFILE|O_CLOEXEC - }; -@@ -128,7 +133,15 @@ __alloc_dir (int fd, bool close_fd, int flags, - expand the buffer if required. */ - enum - { -- tbuffer_size = sizeof (struct dirent) + NAME_MAX + 1 -+ tbuffer_size = -+# if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2) -+ /* This is used on compat readdir64. */ -+ MAX (sizeof (struct dirent), -+ sizeof (struct __old_dirent64)) -+# else -+ sizeof (struct dirent) -+# endif -+ + NAME_MAX + 1 - }; - dirp->tbuffer = malloc (tbuffer_size); - if (dirp->tbuffer == NULL) -diff --git a/sysdeps/unix/sysv/linux/readdir64.c b/sysdeps/unix/sysv/linux/readdir64.c -index dbf6a8c54d..4b41299c6c 100644 ---- a/sysdeps/unix/sysv/linux/readdir64.c -+++ b/sysdeps/unix/sysv/linux/readdir64.c -@@ -99,57 +99,83 @@ versioned_symbol (libc, __readdir64, readdir64, GLIBC_2_2); - # if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2) - # include - -+/* 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. */ -+ ino_t d_ino = dp64->d_ino; -+ if (d_ino != dp64->d_ino) -+ return false; -+ -+ /* Expand the translation buffer to hold the new namesize. */ -+ size_t d_reclen = sizeof (struct __old_dirent64) -+ + dp64->d_reclen - offsetof (struct dirent64, d_name); -+ if (d_reclen > ds->tbuffer_size) -+ { -+ char *newbuffer = realloc (ds->tbuffer, d_reclen); -+ if (newbuffer == NULL) -+ return false; -+ ds->tbuffer = newbuffer; -+ ds->tbuffer_size = d_reclen; -+ } -+ -+ struct __old_dirent64 *olddp64 = (struct __old_dirent64 *) ds->tbuffer; -+ -+ olddp64->d_off = dp64->d_off; -+ olddp64->d_ino = dp64->d_ino; -+ olddp64->d_reclen = dp64->d_reclen; -+ olddp64->d_type = dp64->d_type; -+ memcpy (olddp64->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; - -- do -+ if (dirp->offset >= dirp->size) - { -- size_t reclen; -- -- if (dirp->offset >= dirp->size) -+ /* We've emptied out our buffer. Refill it. */ -+ ssize_t bytes = __getdents64 (dirp->fd, dirp->data, dirp->allocation); -+ 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; -- } -- -- dp = (struct __old_dirent64 *) &dirp->data[dirp->offset]; -+ /* 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; - -- reclen = dp->d_reclen; -+ /* Don't modifiy errno when reaching EOF. */ -+ if (bytes == 0) -+ __set_errno (saved_errno); -+ return NULL; -+ } -+ dirp->size = bytes; - -- dirp->offset += reclen; -+ /* Reset the offset into the buffer. */ -+ dirp->offset = 0; -+ } - -- dirp->filepos = dp->d_off; -+ struct dirent64 *dp64 = (struct dirent64 *) &dirp->data[dirp->offset]; -+ dirp->offset += dp64->d_reclen; - -- /* Skip deleted files. */ -- } while (dp->d_ino == 0); -+ /* Skip entries which might overflow d_ino or for memory allocation failure -+ in case of large file names. */ -+ if (dirstream_old_entry (dirp, dp64)) -+ { -+ dirp->filepos = dp64->d_off; -+ return (struct __old_dirent64 *) dirp->tbuffer; -+ } - -- return dp; -+ return NULL; - } - - attribute_compat_text_section --- -2.35.1 - diff --git a/9999/0011-dirent-Deprecate-getdirentries.patch b/9999/0011-dirent-Deprecate-getdirentries.patch deleted file mode 100644 index c7abd61..0000000 --- a/9999/0011-dirent-Deprecate-getdirentries.patch +++ /dev/null @@ -1,103 +0,0 @@ -From fe14184069e952f57e74f1e599816d0403205ac0 Mon Sep 17 00:00:00 2001 -From: Adhemerval Zanella -Date: Fri, 17 Apr 2020 09:59:51 -0300 -Subject: [PATCH 11/12] dirent: Deprecate getdirentries - -The interface has some issues: - - 1. It is build on top getdents on Linux and requires handling - non-LFS call using LFS getdents. - - 2. It is not wildly used and the non-LFS support is as problematic - as non-LFS readdir. glibc only exports the LFS getdents. - - 3. It is not a direct replacement over BSD since on some plataform - its signature has changed (FreeBSD 11, for instance, used to - set the offset as a 'long' and changed to 'off_t' on version 12). - -The idea is to eventually move the symbols to compat ones. ---- - NEWS | 6 ++++++ - dirent/dirent.h | 14 ++++++++++---- - sysdeps/unix/sysv/linux/Makefile | 4 ++++ - 3 files changed, 20 insertions(+), 4 deletions(-) - -diff --git a/NEWS b/NEWS -index bc1aac1270..56c4d3ed7e 100644 ---- a/NEWS -+++ b/NEWS -@@ -93,6 +93,12 @@ Security related changes: - - [Add security related changes here] - -+Deprecated and removed features, and other changes affecting compatibility: -+ -+* The function getdirentries is now deprecated, applications should use -+ either getdents64, readdir64 or readdir. -+ -+ - The following bugs are resolved with this release: - - [The release manager will add the list generated by -diff --git a/dirent/dirent.h b/dirent/dirent.h -index c47d3273b2..1c299e5be8 100644 ---- a/dirent/dirent.h -+++ b/dirent/dirent.h -@@ -350,29 +350,35 @@ extern int alphasort64 (const struct dirent64 **__e1, - /* Read directory entries from FD into BUF, reading at most NBYTES. - Reading starts at offset *BASEP, and *BASEP is updated with the new - position after reading. Returns the number of bytes read; zero when at -- end of directory; or -1 for errors. */ -+ end of directory; or -1 for errors. -+ This is deprecated and getdents64 or readdir should be used instead. */ - # ifndef __USE_FILE_OFFSET64 - extern __ssize_t getdirentries (int __fd, char *__restrict __buf, - size_t __nbytes, - __off_t *__restrict __basep) -- __THROW __nonnull ((2, 4)); -+ __THROW __nonnull ((2, 4)) -+ __attribute_deprecated_msg__ ("Use getdents64 instead"); - # else - # ifdef __REDIRECT - extern __ssize_t __REDIRECT_NTH (getdirentries, - (int __fd, char *__restrict __buf, - size_t __nbytes, - __off64_t *__restrict __basep), -- getdirentries64) __nonnull ((2, 4)); -+ getdirentries64) -+ __nonnull ((2, 4)) -+ __attribute_deprecated_msg__ ("Use getdents64 instead"); - # else - # define getdirentries getdirentries64 - # endif - # endif - - # ifdef __USE_LARGEFILE64 -+/* This is deprecated and getdents64 or readdir64 should be used instead. */ - extern __ssize_t getdirentries64 (int __fd, char *__restrict __buf, - size_t __nbytes, - __off64_t *__restrict __basep) -- __THROW __nonnull ((2, 4)); -+ __THROW __nonnull ((2, 4)) -+ __attribute_deprecated_msg__ ("Use getdents64 instead"); - # endif - #endif /* Use misc. */ - -diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile -index a139a16532..237b8ca80a 100644 ---- a/sysdeps/unix/sysv/linux/Makefile -+++ b/sysdeps/unix/sysv/linux/Makefile -@@ -365,6 +365,10 @@ tests += \ - tst-getdents64 \ - tst-readdir64-compat \ - # tests -+ -+# Avoid the warning for the weak_alias for _DIRENT_MATCHES_DIRENT64 -+CFLAGS-getdirentries64.o = -Wno-deprecated-declarations -+CFLAGS-getdirentries64.os = -Wno-deprecated-declarations - endif # $(subdir) == dirent - - ifeq ($(subdir),nis) --- -2.35.1 - -- cgit v1.2.3-65-gdbad