From 825c8462d8704328bf7c1e1c4416c9a191f85b6a Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Sat, 16 Apr 2022 15:28:10 +0800 Subject: Rebase all MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: WANG Xuerui Signed-off-by: Andreas K. Hüttel --- 9999/0001-Disable-ldconfig-during-install.patch | 4 +- ...eps-posix-getaddrinfo.c-gaih_inet-Only-us.patch | 43 +- ...Adapt-to-Gentoo-specific-etc-mail-aliases.patch | 4 +- ...O0-in-conform-tests-to-survive-CC-changes.patch | 65 +++ .../0005-Fix-miscompilation-on-ia64-s-gcc-10.patch | 32 ++ ...O0-in-conform-tests-to-survive-CC-changes.patch | 65 --- .../0006-Fix-miscompilation-on-ia64-s-gcc-10.patch | 32 -- ...t-skip-entries-with-zero-d_ino-values-BZ-.patch | 182 ++++++++ ...7-linux-Use-getdents64-on-non-LFS-readdir.patch | 204 +++++++++ ...nternal-DIR-filepos-as-off64_t-BZ-23960-B.patch | 494 +++++++++++++++++++++ 9999/0009-linux-Add-__readdir64_unlocked.patch | 181 ++++++++ 9999/0010-linux-Add-__old_readdir64_unlocked.patch | 184 ++++++++ ...etdents64-on-readdir64-compat-implementat.patch | 298 +++++++++++++ 9999/0012-dirent-Deprecate-getdirentries.patch | 103 +++++ ...ault-in-getpwuid-when-stat-fails-BZ-28752.patch | 38 ++ ...0014-Drop-glibc-lock-when-returning-early.patch | 36 ++ ...t-skip-entries-with-zero-d_ino-values-BZ-.patch | 182 -------- ...2-linux-Use-getdents64-on-non-LFS-readdir.patch | 204 --------- ...nternal-DIR-filepos-as-off64_t-BZ-23960-B.patch | 494 --------------------- 9999/0204-linux-Add-__readdir64_unlocked.patch | 181 -------- 9999/0205-linux-Add-__old_readdir64_unlocked.patch | 184 -------- ...etdents64-on-readdir64-compat-implementat.patch | 298 ------------- 9999/0207-dirent-Deprecate-getdirentries.patch | 103 ----- ...ault-in-getpwuid-when-stat-fails-BZ-28752.patch | 38 -- ...0302-Drop-glibc-lock-when-returning-early.patch | 36 -- 25 files changed, 1842 insertions(+), 1843 deletions(-) create mode 100644 9999/0004-Force-O0-in-conform-tests-to-survive-CC-changes.patch create mode 100644 9999/0005-Fix-miscompilation-on-ia64-s-gcc-10.patch delete mode 100644 9999/0005-Force-O0-in-conform-tests-to-survive-CC-changes.patch delete mode 100644 9999/0006-Fix-miscompilation-on-ia64-s-gcc-10.patch create mode 100644 9999/0006-linux-Do-not-skip-entries-with-zero-d_ino-values-BZ-.patch create mode 100644 9999/0007-linux-Use-getdents64-on-non-LFS-readdir.patch create mode 100644 9999/0008-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch create mode 100644 9999/0009-linux-Add-__readdir64_unlocked.patch create mode 100644 9999/0010-linux-Add-__old_readdir64_unlocked.patch create mode 100644 9999/0011-linux-Use-getdents64-on-readdir64-compat-implementat.patch create mode 100644 9999/0012-dirent-Deprecate-getdirentries.patch create mode 100644 9999/0013-Fix-segfault-in-getpwuid-when-stat-fails-BZ-28752.patch create mode 100644 9999/0014-Drop-glibc-lock-when-returning-early.patch delete mode 100644 9999/0201-linux-Do-not-skip-entries-with-zero-d_ino-values-BZ-.patch delete mode 100644 9999/0202-linux-Use-getdents64-on-non-LFS-readdir.patch delete mode 100644 9999/0203-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch delete mode 100644 9999/0204-linux-Add-__readdir64_unlocked.patch delete mode 100644 9999/0205-linux-Add-__old_readdir64_unlocked.patch delete mode 100644 9999/0206-linux-Use-getdents64-on-readdir64-compat-implementat.patch delete mode 100644 9999/0207-dirent-Deprecate-getdirentries.patch delete mode 100644 9999/0301-Fix-segfault-in-getpwuid-when-stat-fails-BZ-28752.patch delete mode 100644 9999/0302-Drop-glibc-lock-when-returning-early.patch diff --git a/9999/0001-Disable-ldconfig-during-install.patch b/9999/0001-Disable-ldconfig-during-install.patch index fde0cbb..65e2357 100644 --- a/9999/0001-Disable-ldconfig-during-install.patch +++ b/9999/0001-Disable-ldconfig-during-install.patch @@ -1,4 +1,4 @@ -From 77b6eec2fbc116152cdc0362448e89a22ea1ae83 Mon Sep 17 00:00:00 2001 +From 4ec3b3446cac3917499fba2c3067dc39bb24bf83 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 3 Aug 2021 00:34:59 +0200 Subject: [PATCH 01/14] Disable ldconfig during install @@ -27,5 +27,5 @@ index b1454882bd..73c3ef1e76 100644 $(elf-objpfx)ldconfig $(addprefix -r ,$(install_root)) \ $(slibdir) $(libdir) -- -2.34.1 +2.35.1 diff --git a/9999/0002-Revert-sysdeps-posix-getaddrinfo.c-gaih_inet-Only-us.patch b/9999/0002-Revert-sysdeps-posix-getaddrinfo.c-gaih_inet-Only-us.patch index d6cd1b3..59c2b86 100644 --- a/9999/0002-Revert-sysdeps-posix-getaddrinfo.c-gaih_inet-Only-us.patch +++ b/9999/0002-Revert-sysdeps-posix-getaddrinfo.c-gaih_inet-Only-us.patch @@ -1,4 +1,4 @@ -From 93e05c56a80d3145e3552ea611f2bd8c755d5887 Mon Sep 17 00:00:00 2001 +From afd71f4f5c995d68a00f0d34210d80eaf08dbed8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20K=2E=20H=C3=BCttel?= Date: Tue, 29 Aug 2017 22:58:50 +0200 Subject: [PATCH 02/14] Revert " * sysdeps/posix/getaddrinfo.c (gaih_inet): @@ -13,14 +13,14 @@ See for the background This makes tst-nss-files-hosts-multi fail. Disable it. --- nss/Makefile | 1 - - sysdeps/posix/getaddrinfo.c | 9 ++------- - 2 files changed, 2 insertions(+), 8 deletions(-) + sysdeps/posix/getaddrinfo.c | 8 ++------ + 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/nss/Makefile b/nss/Makefile -index 552e5d03e1..35ec106e0c 100644 +index d8b06b44fb..e3639f78ec 100644 --- a/nss/Makefile +++ b/nss/Makefile -@@ -74,7 +74,6 @@ tests-container = \ +@@ -85,7 +85,6 @@ tests-container := \ # Tests which need libdl ifeq (yes,$(build-shared)) tests += tst-nss-files-hosts-erange @@ -29,25 +29,24 @@ index 552e5d03e1..35ec106e0c 100644 tests += tst-nss-files-alias-leak tests += tst-nss-files-alias-truncated diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c -index 18dccd5924..2cca006f3d 100644 +index bcff909b2f..09954dee22 100644 --- a/sysdeps/posix/getaddrinfo.c +++ b/sysdeps/posix/getaddrinfo.c -@@ -733,13 +733,8 @@ gaih_inet (const char *name, const struct gaih_service *service, - while (!no_more) - { - no_data = 0; -- nss_gethostbyname4_r *fct4 = NULL; +@@ -623,12 +623,8 @@ get_nss_addresses (const char *name, const struct addrinfo *req, + } + + no_data = 0; +- nss_gethostbyname4_r *fct4 = NULL; - -- /* gethostbyname4_r sends out parallel A and AAAA queries and -- is thus only suitable for PF_UNSPEC. */ -- if (req->ai_family == PF_UNSPEC) -- fct4 = __nss_lookup_function (nip, "gethostbyname4_r"); -- -+ nss_gethostbyname4_r *fct4 -+ = __nss_lookup_function (nip, "gethostbyname4_r"); - if (fct4 != NULL) - { - while (1) +- /* gethostbyname4_r sends out parallel A and AAAA queries and +- is thus only suitable for PF_UNSPEC. */ +- if (req->ai_family == PF_UNSPEC) +- fct4 = __nss_lookup_function (nip, "gethostbyname4_r"); ++ nss_gethostbyname4_r *fct4 ++ = __nss_lookup_function (nip, "gethostbyname4_r"); + + if (fct4 != NULL) + { -- -2.34.1 +2.35.1 diff --git a/9999/0003-Adapt-to-Gentoo-specific-etc-mail-aliases.patch b/9999/0003-Adapt-to-Gentoo-specific-etc-mail-aliases.patch index 32c5e4a..a9d0605 100644 --- a/9999/0003-Adapt-to-Gentoo-specific-etc-mail-aliases.patch +++ b/9999/0003-Adapt-to-Gentoo-specific-etc-mail-aliases.patch @@ -1,4 +1,4 @@ -From 6e27ad8827f67f742aa53b72c141002085e7e1a8 Mon Sep 17 00:00:00 2001 +From 4a1235321c3749726d4f0b3ed0f0769a40d714f9 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 03/14] Adapt to Gentoo-specific /etc/mail/aliases @@ -104,5 +104,5 @@ index 4bf6fe0834..1548eba2ad 100644 /* valgrind needs a temporary directory in the chroot. */ { -- -2.34.1 +2.35.1 diff --git a/9999/0004-Force-O0-in-conform-tests-to-survive-CC-changes.patch b/9999/0004-Force-O0-in-conform-tests-to-survive-CC-changes.patch new file mode 100644 index 0000000..ce101ab --- /dev/null +++ b/9999/0004-Force-O0-in-conform-tests-to-survive-CC-changes.patch @@ -0,0 +1,65 @@ +From 6f332b192b1e0a502d904c608630e3392dd69d15 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 04/14] Force -O0 in conform tests to survive $CC changes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In bug #659030 Gentoo started passing user's CFLAGS via $CC variable. +conform tests should but are not ready to handle -O1/-O2 yet. +Tests fail to validate headers due to inlining of weak symbol aliases +and other problems. Let's force it back to -O0 until it's fixed upstream. + +Original patch by Sergei, ported to the new python test framework by Andreas + +Bug: https://bugs.gentoo.org/659030 +Signed-off-by: Sergei Trofimovich +Signed-off-by: Andreas K. Hüttel +--- + conform/conformtest.py | 6 ++++-- + conform/linknamespace.py | 4 +++- + 2 files changed, 7 insertions(+), 3 deletions(-) + +diff --git a/conform/conformtest.py b/conform/conformtest.py +index 94a7ee110f..90c81ac88e 100644 +--- a/conform/conformtest.py ++++ b/conform/conformtest.py +@@ -566,7 +566,7 @@ class HeaderTests(object): + o_file = os.path.join(self.temp_dir, 'test.o') + with open(c_file, 'w') as c_file_out: + c_file_out.write('#include <%s>\n%s' % (self.header, text)) +- cmd = ('%s %s -c %s -o %s' % (self.cc, self.cflags, c_file, o_file)) ++ cmd = ('%s %s -O0 -c %s -o %s' % (self.cc, self.cflags, c_file, o_file)) + try: + subprocess.check_call(cmd, shell=True) + except subprocess.CalledProcessError: +@@ -620,7 +620,9 @@ class HeaderTests(object): + out_file = os.path.join(self.temp_dir, 'namespace-out') + with open(c_file, 'w') as c_file_out: + c_file_out.write('#include <%s>\n' % self.header) +- cmd = ('%s %s -E %s -P -Wp,-dN > %s' ++ # -O0 to negate effect of possible -O passed to $CC ++ # See https://bugs.gentoo.org/659030#c6 ++ cmd = ('%s -O0 %s -E %s -P -Wp,-dN > %s' + % (self.cc, self.cflags_namespace, c_file, out_file)) + subprocess.check_call(cmd, shell=True) + bad_tokens = set() +diff --git a/conform/linknamespace.py b/conform/linknamespace.py +index f7fe3a7a0a..ad87fd2a6d 100644 +--- a/conform/linknamespace.py ++++ b/conform/linknamespace.py +@@ -157,7 +157,9 @@ def main(): + files_seen = set() + all_undef = {} + current_undef = {} +- compiler = '%s %s' % (args.cc, args.flags) ++ # -O0 avoid failures like ++ # '[initial] ptsname_r -> [libc.a(ptsname.o)] ptsname' ++ compiler = '%s %s -O0' % (args.cc, args.flags) + c_syms = glibcconform.list_exported_functions(compiler, args.standard, + args.header) + with tempfile.TemporaryDirectory() as temp_dir: +-- +2.35.1 + diff --git a/9999/0005-Fix-miscompilation-on-ia64-s-gcc-10.patch b/9999/0005-Fix-miscompilation-on-ia64-s-gcc-10.patch new file mode 100644 index 0000000..9024676 --- /dev/null +++ b/9999/0005-Fix-miscompilation-on-ia64-s-gcc-10.patch @@ -0,0 +1,32 @@ +From da8126c1493016b2c9aed0c34b240619b7aee075 Mon Sep 17 00:00:00 2001 +From: Sergei Trofimovich +Date: Sat, 11 Jul 2020 20:06:51 +0300 +Subject: [PATCH 05/14] Fix miscompilation on ia64's gcc-10 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Bug: https://bugs.gentoo.org/723268 +Signed-off-by: Andreas K. Hüttel +--- + sysdeps/unix/sysv/linux/ia64/dl-sysdep.h | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h b/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h +index 0d2a1d093a..b50694d6f3 100644 +--- a/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h ++++ b/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h +@@ -32,7 +32,9 @@ + #ifndef __ASSEMBLER__ + /* Don't declare this as a function---we want it's entry-point, not + it's function descriptor... */ +-extern int _dl_sysinfo_break attribute_hidden; ++/* Use section ".text" to force far GPREL64 relocation instead of ++ GPREL22 . */ ++extern int _dl_sysinfo_break attribute_hidden __attribute__((section(".text"))); + # define DL_SYSINFO_DEFAULT ((uintptr_t) &_dl_sysinfo_break) + # define DL_SYSINFO_IMPLEMENTATION \ + asm (".text\n\t" \ +-- +2.35.1 + diff --git a/9999/0005-Force-O0-in-conform-tests-to-survive-CC-changes.patch b/9999/0005-Force-O0-in-conform-tests-to-survive-CC-changes.patch deleted file mode 100644 index d39eb5d..0000000 --- a/9999/0005-Force-O0-in-conform-tests-to-survive-CC-changes.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 16337b6a4a14c8eb7ae57341aa04d7d571f00783 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 04/14] Force -O0 in conform tests to survive $CC changes -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -In bug #659030 Gentoo started passing user's CFLAGS via $CC variable. -conform tests should but are not ready to handle -O1/-O2 yet. -Tests fail to validate headers due to inlining of weak symbol aliases -and other problems. Let's force it back to -O0 until it's fixed upstream. - -Original patch by Sergei, ported to the new python test framework by Andreas - -Bug: https://bugs.gentoo.org/659030 -Signed-off-by: Sergei Trofimovich -Signed-off-by: Andreas K. Hüttel ---- - conform/conformtest.py | 6 ++++-- - conform/linknamespace.py | 4 +++- - 2 files changed, 7 insertions(+), 3 deletions(-) - -diff --git a/conform/conformtest.py b/conform/conformtest.py -index 94a7ee110f..90c81ac88e 100644 ---- a/conform/conformtest.py -+++ b/conform/conformtest.py -@@ -566,7 +566,7 @@ class HeaderTests(object): - o_file = os.path.join(self.temp_dir, 'test.o') - with open(c_file, 'w') as c_file_out: - c_file_out.write('#include <%s>\n%s' % (self.header, text)) -- cmd = ('%s %s -c %s -o %s' % (self.cc, self.cflags, c_file, o_file)) -+ cmd = ('%s %s -O0 -c %s -o %s' % (self.cc, self.cflags, c_file, o_file)) - try: - subprocess.check_call(cmd, shell=True) - except subprocess.CalledProcessError: -@@ -620,7 +620,9 @@ class HeaderTests(object): - out_file = os.path.join(self.temp_dir, 'namespace-out') - with open(c_file, 'w') as c_file_out: - c_file_out.write('#include <%s>\n' % self.header) -- cmd = ('%s %s -E %s -P -Wp,-dN > %s' -+ # -O0 to negate effect of possible -O passed to $CC -+ # See https://bugs.gentoo.org/659030#c6 -+ cmd = ('%s -O0 %s -E %s -P -Wp,-dN > %s' - % (self.cc, self.cflags_namespace, c_file, out_file)) - subprocess.check_call(cmd, shell=True) - bad_tokens = set() -diff --git a/conform/linknamespace.py b/conform/linknamespace.py -index f7fe3a7a0a..ad87fd2a6d 100644 ---- a/conform/linknamespace.py -+++ b/conform/linknamespace.py -@@ -157,7 +157,9 @@ def main(): - files_seen = set() - all_undef = {} - current_undef = {} -- compiler = '%s %s' % (args.cc, args.flags) -+ # -O0 avoid failures like -+ # '[initial] ptsname_r -> [libc.a(ptsname.o)] ptsname' -+ compiler = '%s %s -O0' % (args.cc, args.flags) - c_syms = glibcconform.list_exported_functions(compiler, args.standard, - args.header) - with tempfile.TemporaryDirectory() as temp_dir: --- -2.34.1 - diff --git a/9999/0006-Fix-miscompilation-on-ia64-s-gcc-10.patch b/9999/0006-Fix-miscompilation-on-ia64-s-gcc-10.patch deleted file mode 100644 index 6fb25e1..0000000 --- a/9999/0006-Fix-miscompilation-on-ia64-s-gcc-10.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 7fedf8c50534b2930caf2fad55cd98b9eed36e82 Mon Sep 17 00:00:00 2001 -From: Sergei Trofimovich -Date: Sat, 11 Jul 2020 20:06:51 +0300 -Subject: [PATCH 05/14] Fix miscompilation on ia64's gcc-10 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Bug: https://bugs.gentoo.org/723268 -Signed-off-by: Andreas K. Hüttel ---- - sysdeps/unix/sysv/linux/ia64/dl-sysdep.h | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h b/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h -index 0d2a1d093a..b50694d6f3 100644 ---- a/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h -+++ b/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h -@@ -32,7 +32,9 @@ - #ifndef __ASSEMBLER__ - /* Don't declare this as a function---we want it's entry-point, not - it's function descriptor... */ --extern int _dl_sysinfo_break attribute_hidden; -+/* Use section ".text" to force far GPREL64 relocation instead of -+ GPREL22 . */ -+extern int _dl_sysinfo_break attribute_hidden __attribute__((section(".text"))); - # define DL_SYSINFO_DEFAULT ((uintptr_t) &_dl_sysinfo_break) - # define DL_SYSINFO_IMPLEMENTATION \ - asm (".text\n\t" \ --- -2.34.1 - diff --git a/9999/0006-linux-Do-not-skip-entries-with-zero-d_ino-values-BZ-.patch b/9999/0006-linux-Do-not-skip-entries-with-zero-d_ino-values-BZ-.patch new file mode 100644 index 0000000..eae612d --- /dev/null +++ b/9999/0006-linux-Do-not-skip-entries-with-zero-d_ino-values-BZ-.patch @@ -0,0 +1,182 @@ +From 2a131fefbe72a749fe28b426a37b499bf7255cdf Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Tue, 20 Oct 2020 12:18:56 -0300 +Subject: [PATCH 06/14] 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/0007-linux-Use-getdents64-on-non-LFS-readdir.patch b/9999/0007-linux-Use-getdents64-on-non-LFS-readdir.patch new file mode 100644 index 0000000..6f8081f --- /dev/null +++ b/9999/0007-linux-Use-getdents64-on-non-LFS-readdir.patch @@ -0,0 +1,204 @@ +From bda59ff47746fdec69cf4a695d6aeaa4aae2acf8 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Tue, 20 Oct 2020 13:37:15 -0300 +Subject: [PATCH 07/14] 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/0008-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch b/9999/0008-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch new file mode 100644 index 0000000..68d9ce0 --- /dev/null +++ b/9999/0008-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch @@ -0,0 +1,494 @@ +From 90aa2d426422b6acc0e7f2b9d8afa2718098601b Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Mon, 13 Apr 2020 18:09:20 -0300 +Subject: [PATCH 08/14] 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/0009-linux-Add-__readdir64_unlocked.patch b/9999/0009-linux-Add-__readdir64_unlocked.patch new file mode 100644 index 0000000..2453183 --- /dev/null +++ b/9999/0009-linux-Add-__readdir64_unlocked.patch @@ -0,0 +1,181 @@ +From 91dd23b0cf7a3aa11fae6cd3e71e9d49409f17b0 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Mon, 13 Apr 2020 08:35:40 -0300 +Subject: [PATCH 09/14] 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/0010-linux-Add-__old_readdir64_unlocked.patch b/9999/0010-linux-Add-__old_readdir64_unlocked.patch new file mode 100644 index 0000000..d795095 --- /dev/null +++ b/9999/0010-linux-Add-__old_readdir64_unlocked.patch @@ -0,0 +1,184 @@ +From fa48dff4045e66ef9c65b33e80dbfb1390500b6b Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Tue, 14 Apr 2020 11:14:22 -0300 +Subject: [PATCH 10/14] 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/0011-linux-Use-getdents64-on-readdir64-compat-implementat.patch b/9999/0011-linux-Use-getdents64-on-readdir64-compat-implementat.patch new file mode 100644 index 0000000..616e44d --- /dev/null +++ b/9999/0011-linux-Use-getdents64-on-readdir64-compat-implementat.patch @@ -0,0 +1,298 @@ +From 201d65ca12185f171be7b532b16bc315af7d45c3 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Tue, 20 Oct 2020 16:00:43 -0300 +Subject: [PATCH 11/14] 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/0012-dirent-Deprecate-getdirentries.patch b/9999/0012-dirent-Deprecate-getdirentries.patch new file mode 100644 index 0000000..8be7591 --- /dev/null +++ b/9999/0012-dirent-Deprecate-getdirentries.patch @@ -0,0 +1,103 @@ +From 40ec9c0d2bdeee4192885f7781167afdeeee899d Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Fri, 17 Apr 2020 09:59:51 -0300 +Subject: [PATCH 12/14] 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 4b6d9de2b5..b00c803a1c 100644 +--- a/NEWS ++++ b/NEWS +@@ -25,6 +25,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 ca953804d0..26794e4fef 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -341,6 +341,10 @@ tests += tst-getdents64 + ifeq ($(have-GLIBC_2.1.3)$(build-shared),yesyes) + tests += tst-readdir64-compat + endif ++ ++# 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 + diff --git a/9999/0013-Fix-segfault-in-getpwuid-when-stat-fails-BZ-28752.patch b/9999/0013-Fix-segfault-in-getpwuid-when-stat-fails-BZ-28752.patch new file mode 100644 index 0000000..32fd8a6 --- /dev/null +++ b/9999/0013-Fix-segfault-in-getpwuid-when-stat-fails-BZ-28752.patch @@ -0,0 +1,38 @@ +From ce54d71af85a735b3ddf29bde1f6ee6e0844d352 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Sat, 12 Feb 2022 19:40:58 +0100 +Subject: [PATCH 13/14] Fix segfault in getpwuid when stat fails (BZ #28752) + +[azanella proposed this patch to sam when discussing the issue, + but it's not anywhere upstream yet- dilfridge] + +Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28752 +Bug: https://bugs.gentoo.org/828070 +(cherry picked from commit 1bcdcd4fec9bfe2f1d3fef67a43825903f6a5f2b) +--- + nss/nss_database.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/nss/nss_database.c b/nss/nss_database.c +index d56c5b798d..133682b858 100644 +--- a/nss/nss_database.c ++++ b/nss/nss_database.c +@@ -424,10 +424,11 @@ nss_database_check_reload_and_get (struct nss_database_state *local, + errors here are very unlikely, but the chance that we're entering + a container is also very unlikely, so we err on the side of both + very unlikely things not happening at the same time. */ +- if (__stat64_time64 ("/", &str) != 0 +- || (local->root_ino != 0 +- && (str.st_ino != local->root_ino +- || str.st_dev != local->root_dev))) ++ if (__stat64_time64 ("/", &str) != 0) ++ return false; ++ ++ if (local->root_ino != 0 && (str.st_ino != local->root_ino ++ || str.st_dev != local->root_dev)) + { + /* Change detected; disable reloading and return current state. */ + atomic_store_release (&local->data.reload_disabled, 1); +-- +2.35.1 + diff --git a/9999/0014-Drop-glibc-lock-when-returning-early.patch b/9999/0014-Drop-glibc-lock-when-returning-early.patch new file mode 100644 index 0000000..ccb544e --- /dev/null +++ b/9999/0014-Drop-glibc-lock-when-returning-early.patch @@ -0,0 +1,36 @@ +From f0967c21f82d9b6db6faa41315f668f56e38562f Mon Sep 17 00:00:00 2001 +From: Sam James +Date: Mon, 7 Mar 2022 01:59:53 +0100 +Subject: [PATCH 14/14] Drop glibc lock when returning early +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fixes 1bcdcd4fec9bfe2f1d3fef67a43825903f6a5f2b + +Bug: https://bugs.gentoo.org/828070 +Signed-off-by: Andreas K. Hüttel +(cherry picked from commit 81f6a812264e375a695e5b00e2906da8102cc9b6) +--- + nss/nss_database.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/nss/nss_database.c b/nss/nss_database.c +index 133682b858..5f58baf34b 100644 +--- a/nss/nss_database.c ++++ b/nss/nss_database.c +@@ -424,8 +424,10 @@ nss_database_check_reload_and_get (struct nss_database_state *local, + errors here are very unlikely, but the chance that we're entering + a container is also very unlikely, so we err on the side of both + very unlikely things not happening at the same time. */ +- if (__stat64_time64 ("/", &str) != 0) ++ if (__stat64_time64 ("/", &str) != 0) { ++ __libc_lock_unlock (local->lock); + return false; ++ } + + if (local->root_ino != 0 && (str.st_ino != local->root_ino + || str.st_dev != local->root_dev)) +-- +2.35.1 + diff --git a/9999/0201-linux-Do-not-skip-entries-with-zero-d_ino-values-BZ-.patch b/9999/0201-linux-Do-not-skip-entries-with-zero-d_ino-values-BZ-.patch deleted file mode 100644 index 221dbd6..0000000 --- a/9999/0201-linux-Do-not-skip-entries-with-zero-d_ino-values-BZ-.patch +++ /dev/null @@ -1,182 +0,0 @@ -From 58b842de801f64de1d323ecceaf24b7cd30cbb87 Mon Sep 17 00:00:00 2001 -From: Adhemerval Zanella -Date: Tue, 20 Oct 2020 12:18:56 -0300 -Subject: [PATCH 07/14] 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.34.1 - diff --git a/9999/0202-linux-Use-getdents64-on-non-LFS-readdir.patch b/9999/0202-linux-Use-getdents64-on-non-LFS-readdir.patch deleted file mode 100644 index 762a943..0000000 --- a/9999/0202-linux-Use-getdents64-on-non-LFS-readdir.patch +++ /dev/null @@ -1,204 +0,0 @@ -From 057920ea715c979638045d2966d6a7c616f3cbc2 Mon Sep 17 00:00:00 2001 -From: Adhemerval Zanella -Date: Tue, 20 Oct 2020 13:37:15 -0300 -Subject: [PATCH 08/14] 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.34.1 - diff --git a/9999/0203-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch b/9999/0203-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch deleted file mode 100644 index bde1527..0000000 --- a/9999/0203-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch +++ /dev/null @@ -1,494 +0,0 @@ -From 0afb8fa52cded9c332c31c7a1e62b9f2b04acdf8 Mon Sep 17 00:00:00 2001 -From: Adhemerval Zanella -Date: Mon, 13 Apr 2020 18:09:20 -0300 -Subject: [PATCH 09/14] 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.34.1 - diff --git a/9999/0204-linux-Add-__readdir64_unlocked.patch b/9999/0204-linux-Add-__readdir64_unlocked.patch deleted file mode 100644 index 839b18d..0000000 --- a/9999/0204-linux-Add-__readdir64_unlocked.patch +++ /dev/null @@ -1,181 +0,0 @@ -From 333f932faec29e5c9238d3d1f8584acc25d986c0 Mon Sep 17 00:00:00 2001 -From: Adhemerval Zanella -Date: Mon, 13 Apr 2020 08:35:40 -0300 -Subject: [PATCH 10/14] 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.34.1 - diff --git a/9999/0205-linux-Add-__old_readdir64_unlocked.patch b/9999/0205-linux-Add-__old_readdir64_unlocked.patch deleted file mode 100644 index 42c9d1d..0000000 --- a/9999/0205-linux-Add-__old_readdir64_unlocked.patch +++ /dev/null @@ -1,184 +0,0 @@ -From b69d95b17a828f5f39b577c00ff0d02e4c0a5da6 Mon Sep 17 00:00:00 2001 -From: Adhemerval Zanella -Date: Tue, 14 Apr 2020 11:14:22 -0300 -Subject: [PATCH 11/14] 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.34.1 - diff --git a/9999/0206-linux-Use-getdents64-on-readdir64-compat-implementat.patch b/9999/0206-linux-Use-getdents64-on-readdir64-compat-implementat.patch deleted file mode 100644 index 889266d..0000000 --- a/9999/0206-linux-Use-getdents64-on-readdir64-compat-implementat.patch +++ /dev/null @@ -1,298 +0,0 @@ -From a5aee8e0e844f9f9cf8df0a41e67cddf8de7540f Mon Sep 17 00:00:00 2001 -From: Adhemerval Zanella -Date: Tue, 20 Oct 2020 16:00:43 -0300 -Subject: [PATCH 12/14] 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.34.1 - diff --git a/9999/0207-dirent-Deprecate-getdirentries.patch b/9999/0207-dirent-Deprecate-getdirentries.patch deleted file mode 100644 index 42e3002..0000000 --- a/9999/0207-dirent-Deprecate-getdirentries.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 96f2c068b5aa972b23cfe25d3c8042fed1056607 Mon Sep 17 00:00:00 2001 -From: Adhemerval Zanella -Date: Fri, 17 Apr 2020 09:59:51 -0300 -Subject: [PATCH 13/14] 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 626eeabf5d..ed5b7b641f 100644 ---- a/NEWS -+++ b/NEWS -@@ -25,6 +25,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 218f1ed44b..b2737bc53b 100644 ---- a/dirent/dirent.h -+++ b/dirent/dirent.h -@@ -348,29 +348,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 7122f55975..c9b43898b2 100644 ---- a/sysdeps/unix/sysv/linux/Makefile -+++ b/sysdeps/unix/sysv/linux/Makefile -@@ -338,6 +338,10 @@ tests += tst-getdents64 - ifeq ($(have-GLIBC_2.1.3)$(build-shared),yesyes) - tests += tst-readdir64-compat - endif -+ -+# 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.34.1 - diff --git a/9999/0301-Fix-segfault-in-getpwuid-when-stat-fails-BZ-28752.patch b/9999/0301-Fix-segfault-in-getpwuid-when-stat-fails-BZ-28752.patch deleted file mode 100644 index 48036b3..0000000 --- a/9999/0301-Fix-segfault-in-getpwuid-when-stat-fails-BZ-28752.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 7032e8bf35b229ff759286435f1f51b5588b56ed Mon Sep 17 00:00:00 2001 -From: Adhemerval Zanella -Date: Sat, 12 Feb 2022 19:40:58 +0100 -Subject: [PATCH 14/14] Fix segfault in getpwuid when stat fails (BZ #28752) - -[azanella proposed this patch to sam when discussing the issue, - but it's not anywhere upstream yet- dilfridge] - -Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28752 -Bug: https://bugs.gentoo.org/828070 -(cherry picked from commit 1bcdcd4fec9bfe2f1d3fef67a43825903f6a5f2b) ---- - nss/nss_database.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - -diff --git a/nss/nss_database.c b/nss/nss_database.c -index d56c5b798d..133682b858 100644 ---- a/nss/nss_database.c -+++ b/nss/nss_database.c -@@ -424,10 +424,11 @@ nss_database_check_reload_and_get (struct nss_database_state *local, - errors here are very unlikely, but the chance that we're entering - a container is also very unlikely, so we err on the side of both - very unlikely things not happening at the same time. */ -- if (__stat64_time64 ("/", &str) != 0 -- || (local->root_ino != 0 -- && (str.st_ino != local->root_ino -- || str.st_dev != local->root_dev))) -+ if (__stat64_time64 ("/", &str) != 0) -+ return false; -+ -+ if (local->root_ino != 0 && (str.st_ino != local->root_ino -+ || str.st_dev != local->root_dev)) - { - /* Change detected; disable reloading and return current state. */ - atomic_store_release (&local->data.reload_disabled, 1); --- -2.34.1 - diff --git a/9999/0302-Drop-glibc-lock-when-returning-early.patch b/9999/0302-Drop-glibc-lock-when-returning-early.patch deleted file mode 100644 index 4eab4ea..0000000 --- a/9999/0302-Drop-glibc-lock-when-returning-early.patch +++ /dev/null @@ -1,36 +0,0 @@ -From fd939e8740a97b3ffc5816cebb7be947c7b560af Mon Sep 17 00:00:00 2001 -From: Sam James -Date: Mon, 7 Mar 2022 01:59:53 +0100 -Subject: [PATCH] Drop glibc lock when returning early -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Fixes 1bcdcd4fec9bfe2f1d3fef67a43825903f6a5f2b - -Bug: https://bugs.gentoo.org/828070 -Signed-off-by: Andreas K. Hüttel -(cherry picked from commit 81f6a812264e375a695e5b00e2906da8102cc9b6) ---- - nss/nss_database.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/nss/nss_database.c b/nss/nss_database.c -index 133682b858..5f58baf34b 100644 ---- a/nss/nss_database.c -+++ b/nss/nss_database.c -@@ -424,8 +424,10 @@ nss_database_check_reload_and_get (struct nss_database_state *local, - errors here are very unlikely, but the chance that we're entering - a container is also very unlikely, so we err on the side of both - very unlikely things not happening at the same time. */ -- if (__stat64_time64 ("/", &str) != 0) -+ if (__stat64_time64 ("/", &str) != 0) { -+ __libc_lock_unlock (local->lock); - return false; -+ } - - if (local->root_ino != 0 && (str.st_ino != local->root_ino - || str.st_dev != local->root_dev)) --- -2.34.1 - -- cgit v1.2.3-65-gdbad