public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
From: "Andreas K. Hüttel" <dilfridge@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/toolchain/glibc-patches:master commit in: 9999/
Date: Thu, 11 Jan 2024 23:27:37 +0000 (UTC)	[thread overview]
Message-ID: <1705015630.d53894fd2ecb4fe3ae4242b36d314d95f8222a3e.dilfridge@gentoo> (raw)

commit:     d53894fd2ecb4fe3ae4242b36d314d95f8222a3e
Author:     Andreas K. Hüttel <dilfridge <AT> gentoo <DOT> org>
AuthorDate: Thu Jan 11 23:27:10 2024 +0000
Commit:     Andreas K. Hüttel <dilfridge <AT> gentoo <DOT> org>
CommitDate: Thu Jan 11 23:27:10 2024 +0000
URL:        https://gitweb.gentoo.org/proj/toolchain/glibc-patches.git/commit/?id=d53894fd

Update qemu patch series from azanella/bz23960-dirent

Signed-off-by: Andreas K. Hüttel <dilfridge <AT> gentoo.org>

 ...4-linux-Use-getdents64-on-non-LFS-readdir.patch | 179 ++++++---------
 9999/0005-support-Add-xreallocarray.patch          |  76 ++++++
 9999/0006-linux-Add-__readdir64_unlocked.patch     | 182 ---------------
 ...ternal-DIR-filepos-as-off64_t-BZ-23960-B.patch} | 254 ++++++++++++---------
 9999/0007-linux-Add-__old_readdir64_unlocked.patch | 194 ----------------
 ...etdents64-on-readdir64-compat-implementat.patch | 250 --------------------
 6 files changed, 290 insertions(+), 845 deletions(-)

diff --git a/9999/0004-linux-Use-getdents64-on-non-LFS-readdir.patch b/9999/0004-linux-Use-getdents64-on-non-LFS-readdir.patch
index a451fd6..ddb3660 100644
--- a/9999/0004-linux-Use-getdents64-on-non-LFS-readdir.patch
+++ b/9999/0004-linux-Use-getdents64-on-non-LFS-readdir.patch
@@ -1,114 +1,29 @@
-From 782410070379ffbf54cb8abe71cc13fd24cfaea5 Mon Sep 17 00:00:00 2001
+From 3fac92713621f894d33a9f499bacb5b20f0d8ec3 Mon Sep 17 00:00:00 2001
 From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
-Date: Fri, 27 Jan 2023 14:28:30 -0300
-Subject: [PATCH 4/9] linux: Use getdents64 on non-LFS readdir
+Date: Tue, 20 Oct 2020 13:37:15 -0300
+Subject: [PATCH 1/3] linux: Use getdents64 on non-LFS readdir
 
-The non-LFS opendir reserves a translation entry to be used to return
-the entry and the 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.
+It is similar to what non-LFS getdents do (including overflow check).
 
 Checked on x86_64-linux-gnu and i686-linux-gnu.
 ---
- dirent/tst-scandir.c                |  6 ++-
- include/dirent.h                    |  2 +-
- sysdeps/unix/sysv/linux/dirstream.h |  5 ++
- sysdeps/unix/sysv/linux/readdir.c   | 83 +++++++++++++++++++----------
- 4 files changed, 67 insertions(+), 29 deletions(-)
+ sysdeps/unix/sysv/linux/readdir.c | 97 +++++++++++++++++++++++--------
+ 1 file changed, 73 insertions(+), 24 deletions(-)
 
-diff --git a/dirent/tst-scandir.c b/dirent/tst-scandir.c
-index 8d87d4dd74..7bc666449e 100644
---- a/dirent/tst-scandir.c
-+++ b/dirent/tst-scandir.c
-@@ -155,8 +155,12 @@ do_test (void)
-     }
-   if (n != 6)
-     {
-+      /* Non-lfs opendir skips entries that can not be represented (for
-+	 instance if d_off is not an offset but rather an internal filesystem
-+	 representation.  For this case there is no point in continue the
-+	 testcase.  */
-       printf ("scandir returned %d entries instead of 6\n", n);
--      return 1;
-+      return EXIT_UNSUPPORTED;
-     }
- 
-   struct
-diff --git a/include/dirent.h b/include/dirent.h
-index d7567f5e86..17827176ba 100644
---- a/include/dirent.h
-+++ b/include/dirent.h
-@@ -1,8 +1,8 @@
- #ifndef _DIRENT_H
-+# include <dirent/dirent.h>
- # ifndef _ISOMAC
- #  include <dirstream.h>
- # endif
--# include <dirent/dirent.h>
- # ifndef _ISOMAC
- # include <sys/stat.h>
- # include <stdbool.h>
-diff --git a/sysdeps/unix/sysv/linux/dirstream.h b/sysdeps/unix/sysv/linux/dirstream.h
-index 3cb313b410..adcf8234f1 100644
---- a/sysdeps/unix/sysv/linux/dirstream.h
-+++ b/sysdeps/unix/sysv/linux/dirstream.h
-@@ -18,6 +18,7 @@
- #ifndef	_DIRSTREAM_H
- #define	_DIRSTREAM_H	1
- 
-+#include <dirent.h>
- #include <sys/types.h>
- 
- #include <libc-lock.h>
-@@ -41,6 +42,10 @@ struct __dirstream
- 
-     int errcode;		/* Delayed error code.  */
- 
-+#if !defined __OFF_T_MATCHES_OFF64_T || !defined __INO_T_MATCHES_INO64_T
-+    struct dirent tdp;
-+#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/readdir.c b/sysdeps/unix/sysv/linux/readdir.c
-index 4a4c00ea07..cd0ccaf33a 100644
+index 33bae4b57d..4e2214f21e 100644
 --- a/sysdeps/unix/sysv/linux/readdir.c
 +++ b/sysdeps/unix/sysv/linux/readdir.c
-@@ -21,42 +21,71 @@
+@@ -20,43 +20,92 @@
+ 
  #if !_DIRENT_MATCHES_DIRENT64
  #include <dirstream.h>
- 
-+/* Translate the DP64 entry to the non-LFS one in the translation entry
-+   at dirstream DS.  Return true is the translation was possible or
-+   false if either an internal field can not be represented in the non-LFS
-+   entry or if the name is too long.  */
-+static bool
-+dirstream_entry (struct __dirstream *ds, const struct dirent64 *dp64)
-+{
-+  /* Check for overflow.  */
-+  if (!in_off_t_range (dp64->d_off) || !in_ino_t_range (dp64->d_ino))
-+    return false;
-+
-+  /* And if name is too large.  */
-+  if (dp64->d_reclen - offsetof (struct dirent64, d_name) > NAME_MAX)
-+    return false;
-+
-+  ds->filepos = dp64->d_off;
-+
-+  ds->tdp.d_off = dp64->d_off;
-+  ds->tdp.d_ino = dp64->d_ino;
-+  ds->tdp.d_reclen = sizeof (struct dirent)
-+    + dp64->d_reclen - offsetof (struct dirent64, d_name);
-+  ds->tdp.d_type = dp64->d_type;
-+  memcpy (ds->tdp.d_name, dp64->d_name,
-+	  dp64->d_reclen - offsetof (struct dirent64, d_name));
-+
-+  return true;
-+}
++#include <unistd.h>
 +
++# ifndef DIRENT_SET_DP_INO
++#  define DIRENT_SET_DP_INO(dp, value) (dp)->d_ino = (value)
++# endif
+ 
  /* Read a directory entry from DIRP.  */
  struct dirent *
  __readdir_unlocked (DIR *dirp)
@@ -134,13 +49,6 @@ index 4a4c00ea07..cd0ccaf33a 100644
 -	     do not set errno in that case, to indicate success.  */
 -	  if (bytes == 0 || errno == ENOENT)
 -	    __set_errno (saved_errno);
--	  return NULL;
--	}
--      dirp->size = (size_t) bytes;
--
--      /* Reset the offset into the buffer.  */
--      dirp->offset = 0;
-+	  /* We've emptied out our buffer.  Refill it.  */
 +	  ssize_t bytes = __getdents64 (dirp->fd, dirp->data,
 +					dirp->allocation);
 +	  if (bytes <= 0)
@@ -159,13 +67,60 @@ index 4a4c00ea07..cd0ccaf33a 100644
 +	  dirp->offset = 0;
 + 	}
 +
-+      struct dirent64 *dp64 = (struct dirent64 *) &dirp->data[dirp->offset];
-+      dirp->offset += dp64->d_reclen;
++    /* These two pointers might alias the same memory buffer.  Standard C
++       requires that we always use the same type for them, so we must use the
++       union type.  */
++      union
++      {
++	struct dirent64 dp64;
++	struct dirent dp;
++	char *b;
++      } *inp, *outp;
++      inp = (void*) &dirp->data[dirp->offset];
++      outp = (void*) &dirp->data[dirp->offset];
++
++      const size_t size_diff = offsetof (struct dirent64, d_name)
++	- offsetof (struct dirent, d_name);
++
++      /* Since inp->dp64.d_reclen is already aligned for the kernel structure
++	 this may compute a value that is bigger than necessary.  */
++      size_t old_reclen = inp->dp64.d_reclen;
++      size_t new_reclen = ALIGN_UP (old_reclen - size_diff,
++				    _Alignof (struct dirent));
++
++      if (!in_ino_t_range (inp->dp64.d_ino)
++	  || !in_off_t_range (inp->dp64.d_off))
++	{
++	  /* Overflow.  If there was at least one entry before this one,
++	     return them without error, otherwise signal overflow.  */
++	  if (dirp->offset != 0)
++	    {
++	      __lseek64 (dirp->fd, dirp->offset, SEEK_SET);
++	      outp = (void*)(outp->b - dirp->data);
++	      return &outp->dp;
++	    }
++	  __set_errno (EOVERFLOW);
+ 	  return NULL;
+ 	}
+-      dirp->size = (size_t) bytes;
+ 
+-      /* Reset the offset into the buffer.  */
+-      dirp->offset = 0;
++      /* Copy the data from INP and access only OUTP.  */
++      const uint64_t d_ino = inp->dp64.d_ino;
++      const int64_t d_off = inp->dp64.d_off;
++      const uint8_t d_type = inp->dp64.d_type;
++      outp->dp.d_ino = d_ino;
++      outp->dp.d_off = d_off;
++      outp->dp.d_reclen = new_reclen;
++      outp->dp.d_type = d_type;
++      memmove (outp->dp.d_name, inp->dp64.d_name,
++	       old_reclen - offsetof (struct dirent64, d_name));
++
++      dirp->filepos = d_off;
++      dirp->offset += old_reclen;
 +
-+      /* Skip entries which might overflow d_off/d_ino or if the translation
-+	 buffer can not be resized.  */
-+      if (dirstream_entry (dirp, dp64))
-+	return &dirp->tdp;
++      return &outp->dp;
      }
 -
 -  dp = (struct dirent *) &dirp->data[dirp->offset];

diff --git a/9999/0005-support-Add-xreallocarray.patch b/9999/0005-support-Add-xreallocarray.patch
new file mode 100644
index 0000000..dbfae4d
--- /dev/null
+++ b/9999/0005-support-Add-xreallocarray.patch
@@ -0,0 +1,76 @@
+From 7d0638e792ebe528af3f6d8e353eff68157d7105 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Wed, 1 Mar 2023 14:41:23 -0300
+Subject: [PATCH 2/3] support: Add xreallocarray
+
+As a wrapper over reallocarray.
+---
+ support/Makefile        |  1 +
+ support/support.h       |  2 ++
+ support/xreallocarray.c | 29 +++++++++++++++++++++++++++++
+ 3 files changed, 32 insertions(+)
+ create mode 100644 support/xreallocarray.c
+
+diff --git a/support/Makefile b/support/Makefile
+index 362a51f882..d056563c15 100644
+--- a/support/Makefile
++++ b/support/Makefile
+@@ -201,6 +201,7 @@ libsupport-routines = \
+   xread \
+   xreadlink \
+   xrealloc \
++  xreallocarray \
+   xrecvfrom \
+   xsendto \
+   xsetlocale \
+diff --git a/support/support.h b/support/support.h
+index ba21ec9b5a..b4e31e4483 100644
+--- a/support/support.h
++++ b/support/support.h
+@@ -107,6 +107,8 @@ extern void *xcalloc (size_t n, size_t s)
+   __returns_nonnull;
+ extern void *xrealloc (void *o, size_t n)
+   __attribute_malloc__ __attribute_alloc_size__ ((2)) __attr_dealloc_free;
++extern void *xreallocarray (void *p, size_t n, size_t s)
++  __attribute_alloc_size__ ((2, 3)) __attr_dealloc_free;
+ extern char *xstrdup (const char *) __attribute_malloc__ __attr_dealloc_free
+   __returns_nonnull;
+ void *xposix_memalign (size_t alignment, size_t n)
+diff --git a/support/xreallocarray.c b/support/xreallocarray.c
+new file mode 100644
+index 0000000000..74fdaa421b
+--- /dev/null
++++ b/support/xreallocarray.c
+@@ -0,0 +1,29 @@
++/* Error-checking wrapper for reallocarray
++   Copyright (C) 2016-2023 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
++   <https://www.gnu.org/licenses/>.  */
++
++#include <stdlib.h>
++#include <support/support.h>
++
++void *
++xreallocarray (void *p, size_t n, size_t s)
++{
++  void *r = reallocarray (p, n, s);
++  if (r == NULL && (p == NULL || (n != 0 && s != 0)))
++    oom_error ("reallocarray", n);
++  return r;
++}
+-- 
+2.41.0
+

diff --git a/9999/0006-linux-Add-__readdir64_unlocked.patch b/9999/0006-linux-Add-__readdir64_unlocked.patch
deleted file mode 100644
index 3510868..0000000
--- a/9999/0006-linux-Add-__readdir64_unlocked.patch
+++ /dev/null
@@ -1,182 +0,0 @@
-From a2a34383be6e082561a09f37c5747215a70e2439 Mon Sep 17 00:00:00 2001
-From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
-Date: Fri, 27 Jan 2023 14:28:32 -0300
-Subject: [PATCH 6/9] 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 17827176ba..f391476298 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 db1c6214d8..2327511736 100644
---- a/sysdeps/unix/sysv/linux/readdir64.c
-+++ b/sysdeps/unix/sysv/linux/readdir64.c
-@@ -28,15 +28,11 @@
- 
- /* Read a directory entry from DIRP.  */
- struct dirent64 *
--__readdir64 (DIR *dirp)
-+__readdir64_unlocked (DIR *dirp)
- {
-   struct dirent64 *dp;
-   int saved_errno = errno;
- 
--#if IS_IN (libc)
--  __libc_lock_lock (dirp->lock);
--#endif
--
-   if (dirp->offset >= dirp->size)
-     {
-       /* We've emptied out our buffer.  Refill it.  */
-@@ -68,6 +64,20 @@ __readdir64 (DIR *dirp)
-   dirp->offset += dp->d_reclen;
-   dirp->filepos = dp->d_off;
- 
-+  return dp;
-+}
-+
-+struct dirent64 *
-+__readdir64 (DIR *dirp)
-+{
-+  struct dirent64 *dp;
-+
-+#if IS_IN (libc)
-+  __libc_lock_lock (dirp->lock);
-+#endif
-+
-+  dp = __readdir64_unlocked (dirp);
-+
- #if IS_IN (libc)
-   __libc_lock_unlock (dirp->lock);
- #endif
-diff --git a/sysdeps/unix/sysv/linux/readdir64_r.c b/sysdeps/unix/sysv/linux/readdir64_r.c
-index 285dc99509..5ae099bde7 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.41.0
-

diff --git a/9999/0005-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch b/9999/0006-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch
similarity index 70%
rename from 9999/0005-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch
rename to 9999/0006-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch
index 9b566a2..6450910 100644
--- a/9999/0005-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch
+++ b/9999/0006-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch
@@ -1,7 +1,7 @@
-From 8b628a35f0ce66d74be6557e74e28a49a58d749a Mon Sep 17 00:00:00 2001
+From 6d5975652503acffae0566500cc15f8efc89e30a Mon Sep 17 00:00:00 2001
 From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
-Date: Fri, 27 Jan 2023 14:28:31 -0300
-Subject: [PATCH 5/9] linux: Set internal DIR filepos as off64_t (BZ #23960, BZ
+Date: Mon, 13 Apr 2020 18:09:20 -0300
+Subject: [PATCH 3/3] linux: Set internal DIR filepos as off64_t (BZ #23960, BZ
  #24050)
 
 It allows to obtain the expected entry offset on telldir and set
@@ -24,56 +24,55 @@ telldir (BZ #24050).
 Checked on x86_64-linux-gnu, i686-linux-gnu, powerpc-linux-gnu,
 and arm-linux-gnueabihf.
 ---
- dirent/tst-seekdir.c                        |   8 ++
- sysdeps/unix/sysv/linux/Makefile            |   1 +
+ include/dirent.h                            |   2 +-
+ sysdeps/unix/sysv/linux/Makefile            |   2 +
  sysdeps/unix/sysv/linux/alpha/bits/dirent.h |   3 +
  sysdeps/unix/sysv/linux/bits/dirent.h       |   4 +
  sysdeps/unix/sysv/linux/closedir.c          |   4 +
- sysdeps/unix/sysv/linux/dirstream.h         |   6 +-
+ sysdeps/unix/sysv/linux/dirstream.h         |   9 +-
  sysdeps/unix/sysv/linux/opendir.c           |   3 +
- sysdeps/unix/sysv/linux/readdir.c           |  11 +-
+ sysdeps/unix/sysv/linux/readdir.c           |  21 ++-
+ sysdeps/unix/sysv/linux/readdir64.c         |  11 ++
  sysdeps/unix/sysv/linux/rewinddir.c         |   5 +
- sysdeps/unix/sysv/linux/seekdir.c           |  35 ++++-
- sysdeps/unix/sysv/linux/telldir.c           |  35 +++++
- sysdeps/unix/sysv/linux/telldir.h           |  65 +++++++++
- sysdeps/unix/sysv/linux/tst-opendir-nolfs.c | 146 ++++++++++++++++++++
- 13 files changed, 319 insertions(+), 7 deletions(-)
+ sysdeps/unix/sysv/linux/seekdir.c           |  30 +++-
+ sysdeps/unix/sysv/linux/telldir.c           |  36 +++++
+ sysdeps/unix/sysv/linux/telldir.h           |  70 ++++++++++
+ sysdeps/unix/sysv/linux/tst-opendir-lfs.c   |   2 +
+ sysdeps/unix/sysv/linux/tst-opendir.c       | 145 ++++++++++++++++++++
+ 15 files changed, 329 insertions(+), 18 deletions(-)
  create mode 100644 sysdeps/unix/sysv/linux/telldir.h
- create mode 100644 sysdeps/unix/sysv/linux/tst-opendir-nolfs.c
+ create mode 100644 sysdeps/unix/sysv/linux/tst-opendir-lfs.c
+ create mode 100644 sysdeps/unix/sysv/linux/tst-opendir.c
 
-diff --git a/dirent/tst-seekdir.c b/dirent/tst-seekdir.c
-index dcdd699b09..187eda7584 100644
---- a/dirent/tst-seekdir.c
-+++ b/dirent/tst-seekdir.c
-@@ -41,6 +41,14 @@ do_test (void)
-       if (i == 400)
- 	break;
-     }
-+  if (i < 3)
-+    {
-+      /* Non-lfs opendir skips entries that can not be represented (for
-+	 instance if d_off is not an offset but rather an internal filesystem
-+	 representation.  For this case there is no point in continue the
-+	 testcase.  */
-+      return 77;
-+    }
- 
-   printf ("going back past 4-th entry...\n");
- 
+diff --git a/include/dirent.h b/include/dirent.h
+index d7567f5e86..17827176ba 100644
+--- a/include/dirent.h
++++ b/include/dirent.h
+@@ -1,8 +1,8 @@
+ #ifndef _DIRENT_H
++# include <dirent/dirent.h>
+ # ifndef _ISOMAC
+ #  include <dirstream.h>
+ # endif
+-# include <dirent/dirent.h>
+ # ifndef _ISOMAC
+ # include <sys/stat.h>
+ # include <stdbool.h>
 diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
-index 415aa1f14d..dc204883db 100644
+index 415aa1f14d..d5b6e26e76 100644
 --- a/sysdeps/unix/sysv/linux/Makefile
 +++ b/sysdeps/unix/sysv/linux/Makefile
-@@ -574,6 +574,7 @@ sysdep_routines += \
+@@ -574,6 +574,8 @@ sysdep_routines += \
  
  tests += \
    tst-getdents64 \
-+  tst-opendir-nolfs \
++  tst-opendir \
++  tst-opendir-lfs \
    tst-readdir64-compat \
    # tests
  endif # $(subdir) == dirent
 diff --git a/sysdeps/unix/sysv/linux/alpha/bits/dirent.h b/sysdeps/unix/sysv/linux/alpha/bits/dirent.h
-index c8a0cfe93f..586d75586a 100644
+index b604576188..4e511e7654 100644
 --- a/sysdeps/unix/sysv/linux/alpha/bits/dirent.h
 +++ b/sysdeps/unix/sysv/linux/alpha/bits/dirent.h
 @@ -54,4 +54,7 @@ struct dirent64
@@ -85,7 +84,7 @@ index c8a0cfe93f..586d75586a 100644
 +
  #endif /* bits/dirent.h */
 diff --git a/sysdeps/unix/sysv/linux/bits/dirent.h b/sysdeps/unix/sysv/linux/bits/dirent.h
-index ab34d986ff..bb02dcb70a 100644
+index 8bf38f8188..7c5f3419cd 100644
 --- a/sysdeps/unix/sysv/linux/bits/dirent.h
 +++ b/sysdeps/unix/sysv/linux/bits/dirent.h
 @@ -57,3 +57,7 @@ struct dirent64
@@ -97,7 +96,7 @@ index ab34d986ff..bb02dcb70a 100644
 +   store off64_t values.  In this case, translation is required.  */
 +#define _DIRENT_OFFSET_TRANSLATION (LONG_WIDTH < 64)
 diff --git a/sysdeps/unix/sysv/linux/closedir.c b/sysdeps/unix/sysv/linux/closedir.c
-index f1c2608642..9585a6ca3a 100644
+index b86f79f133..3a4eba03f1 100644
 --- a/sysdeps/unix/sysv/linux/closedir.c
 +++ b/sysdeps/unix/sysv/linux/closedir.c
 @@ -47,6 +47,10 @@ __closedir (DIR *dirp)
@@ -112,10 +111,10 @@ index f1c2608642..9585a6ca3a 100644
  
    return __close_nocancel (fd);
 diff --git a/sysdeps/unix/sysv/linux/dirstream.h b/sysdeps/unix/sysv/linux/dirstream.h
-index adcf8234f1..8f58a1c3a6 100644
+index 3d3643733a..fc2586566a 100644
 --- a/sysdeps/unix/sysv/linux/dirstream.h
 +++ b/sysdeps/unix/sysv/linux/dirstream.h
-@@ -22,6 +22,7 @@
+@@ -21,6 +21,7 @@
  #include <sys/types.h>
  
  #include <libc-lock.h>
@@ -123,7 +122,7 @@ index adcf8234f1..8f58a1c3a6 100644
  
  /* Directory stream type.
  
-@@ -38,13 +39,16 @@ struct __dirstream
+@@ -37,10 +38,16 @@ struct __dirstream
      size_t size;		/* Total valid data in the block.  */
      size_t offset;		/* Current offset into the block.  */
  
@@ -132,17 +131,17 @@ index adcf8234f1..8f58a1c3a6 100644
  
      int errcode;		/* Delayed error code.  */
  
- #if !defined __OFF_T_MATCHES_OFF64_T || !defined __INO_T_MATCHES_INO64_T
-     struct dirent tdp;
- #endif
 +#if _DIRENT_OFFSET_TRANSLATION
-+    struct dirstream_loc_t locs; /* off64_t to long int map for telldir.  */
++    /* The array is used to map long to off_64 for telldir/seekdir for ABIs
++       where long can not fully represend a LFS off_t value.  */
++    struct dirstream_loc_t locs;
 +#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 4336196a4d..3e2caabb9d 100644
+index b5218138ec..fda2c5f9fe 100644
 --- a/sysdeps/unix/sysv/linux/opendir.c
 +++ b/sysdeps/unix/sysv/linux/opendir.c
 @@ -129,6 +129,9 @@ __alloc_dir (int fd, bool close_fd, int flags,
@@ -156,36 +155,68 @@ index 4336196a4d..3e2caabb9d 100644
    return dirp;
  }
 diff --git a/sysdeps/unix/sysv/linux/readdir.c b/sysdeps/unix/sysv/linux/readdir.c
-index cd0ccaf33a..7a7f484c36 100644
+index 4e2214f21e..d474f70a8d 100644
 --- a/sysdeps/unix/sysv/linux/readdir.c
 +++ b/sysdeps/unix/sysv/linux/readdir.c
-@@ -36,6 +36,15 @@ dirstream_entry (struct __dirstream *ds, const struct dirent64 *dp64)
-   if (dp64->d_reclen - offsetof (struct dirent64, d_name) > NAME_MAX)
-     return false;
+@@ -75,25 +75,22 @@ __readdir_unlocked (DIR *dirp)
+       size_t new_reclen = ALIGN_UP (old_reclen - size_diff,
+ 				    _Alignof (struct dirent));
+ 
+-      if (!in_ino_t_range (inp->dp64.d_ino)
+-	  || !in_off_t_range (inp->dp64.d_off))
++      /* telldir can not return an error, so preallocate a map entry if
++	 d_off can not be used directly.  */
++      if (telldir_need_dirstream (inp->dp64.d_off))
+ 	{
+-	  /* Overflow.  If there was at least one entry before this one,
+-	     return them without error, otherwise signal overflow.  */
+-	  if (dirp->offset != 0)
+-	    {
+-	      __lseek64 (dirp->fd, dirp->offset, SEEK_SET);
+-	      outp = (void*)(outp->b - dirp->data);
+-	      return &outp->dp;
+-	    }
+-	  __set_errno (EOVERFLOW);
+-	  return NULL;
++	  dirstream_loc_add (&dirp->locs, inp->dp64.d_off);
++	  if (dirstream_loc_has_failed (&dirp->locs))
++	    return NULL;
+ 	}
+ 
+       /* Copy the data from INP and access only OUTP.  */
+       const uint64_t d_ino = inp->dp64.d_ino;
+       const int64_t d_off = inp->dp64.d_off;
+       const uint8_t d_type = inp->dp64.d_type;
++      /* This will clamp both d_off and d_ino values, which is required to
++	 avoid return EOVERFLOW.  The lelldir/seekdir uses the 'locs' value
++	 if the value overflows.  */
+       outp->dp.d_ino = d_ino;
+       outp->dp.d_off = d_off;
+       outp->dp.d_reclen = new_reclen;
+diff --git a/sysdeps/unix/sysv/linux/readdir64.c b/sysdeps/unix/sysv/linux/readdir64.c
+index e6f5108c0a..d61c5e6e26 100644
+--- a/sysdeps/unix/sysv/linux/readdir64.c
++++ b/sysdeps/unix/sysv/linux/readdir64.c
+@@ -68,6 +68,17 @@ __readdir64 (DIR *dirp)
+   dirp->offset += dp->d_reclen;
+   dirp->filepos = dp->d_off;
  
-+  /* telldir can not return an error, so preallocate the map if the entry can
-+     not be packed directly.  */
-+  if (telldir_need_dirstream (dp64->d_off))
++#if _DIRENT_OFFSET_TRANSLATION
++  /* telldir can not return an error, so preallocate a map entry if
++     d_off can not be used directly.  */
++  if (telldir_need_dirstream (dp->d_off))
 +    {
-+      dirstream_loc_add (&ds->locs, dp64->d_off);
-+      if (dirstream_loc_has_failed (&ds->locs))
-+	return false;
++      dirstream_loc_add (&dirp->locs, dp->d_off);
++      if (dirstream_loc_has_failed (&dirp->locs))
++	dp = NULL;
 +    }
++#endif
 +
-   ds->filepos = dp64->d_off;
- 
-   ds->tdp.d_off = dp64->d_off;
-@@ -76,7 +85,7 @@ __readdir_unlocked (DIR *dirp)
- 
-  	  /* Reset the offset into the buffer.  */
- 	  dirp->offset = 0;
-- 	}
-+	}
- 
-       struct dirent64 *dp64 = (struct dirent64 *) &dirp->data[dirp->offset];
-       dirp->offset += dp64->d_reclen;
+ #if IS_IN (libc)
+   __libc_lock_unlock (dirp->lock);
+ #endif
 diff --git a/sysdeps/unix/sysv/linux/rewinddir.c b/sysdeps/unix/sysv/linux/rewinddir.c
-index c0fb7aa765..1b158a584f 100644
+index af85000a28..4936be5c6a 100644
 --- a/sysdeps/unix/sysv/linux/rewinddir.c
 +++ b/sysdeps/unix/sysv/linux/rewinddir.c
 @@ -33,6 +33,11 @@ __rewinddir (DIR *dirp)
@@ -201,10 +232,10 @@ index c0fb7aa765..1b158a584f 100644
    __libc_lock_unlock (dirp->lock);
  #endif
 diff --git a/sysdeps/unix/sysv/linux/seekdir.c b/sysdeps/unix/sysv/linux/seekdir.c
-index 939ccc4447..30cce691a4 100644
+index 52005878fc..cd49676750 100644
 --- a/sysdeps/unix/sysv/linux/seekdir.c
 +++ b/sysdeps/unix/sysv/linux/seekdir.c
-@@ -22,14 +22,39 @@
+@@ -22,14 +22,36 @@
  #include <dirstream.h>
  
  /* Seek to position POS in DIRP.  */
@@ -217,8 +248,6 @@ index 939ccc4447..30cce691a4 100644
    __libc_lock_lock (dirp->lock);
 -  (void) __lseek (dirp->fd, pos, SEEK_SET);
 -  dirp->size = 0;
--  dirp->offset = 0;
--  dirp->filepos = pos;
 +
 +#if _DIRENT_OFFSET_TRANSLATION
 +  union dirstream_packed dsp = { .l = pos };
@@ -239,24 +268,23 @@ index 939ccc4447..30cce691a4 100644
 +  filepos = pos;
 +#endif
 +
-+  if (dirp->filepos != filepos)
-+    {
-+      __lseek64 (dirp->fd, filepos, SEEK_SET);
-+      dirp->filepos = filepos;
-+      dirp->offset = 0;
-+      dirp->size = 0;
-+    }
++  __lseek64 (dirp->fd, filepos, SEEK_SET);
++  dirp->filepos = filepos;
+   dirp->offset = 0;
+-  dirp->filepos = pos;
++  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 1e5c129e9f..c3ef14f3da 100644
+index c8dff30719..8d9e2c9db2 100644
 --- a/sysdeps/unix/sysv/linux/telldir.c
 +++ b/sysdeps/unix/sysv/linux/telldir.c
-@@ -15,9 +15,11 @@
+@@ -15,9 +15,12 @@
     License along with the GNU C Library; if not, see
     <https://www.gnu.org/licenses/>.  */
  
++#include <stdio.h>
 +#include <assert.h>
  #include <dirent.h>
  
@@ -265,7 +293,7 @@ index 1e5c129e9f..c3ef14f3da 100644
  
  /* Return the current position of DIRP.  */
  long int
-@@ -26,7 +28,40 @@ telldir (DIR *dirp)
+@@ -26,7 +29,40 @@ telldir (DIR *dirp)
    long int ret;
  
    __libc_lock_lock (dirp->lock);
@@ -287,15 +315,15 @@ index 1e5c129e9f..c3ef14f3da 100644
 +      dsp.l = -1;
 +
 +      size_t i;
-+      for (i = 0; i < dirstream_loc_size (&dirp->locs); i++)
-+	if (*dirstream_loc_at (&dirp->locs, i) == dirp->filepos)
-+	  break;
-+      /* It should be pre-allocated on readdir.  */
-+      assert (i != dirstream_loc_size (&dirp->locs));
++      for (i = 0; ;i++)
++	{
++	  /* It should be pre-allocated on readdir.  */
++	  assert (i < dirstream_loc_size (&dirp->locs));
++	  if (*dirstream_loc_at (&dirp->locs, i) == dirp->filepos)
++	    break;
++	}
 +
 +      dsp.p.is_packed = 0;
-+      /* This assignment might overflow, however most likely ENOME would
-+	 happen long before.  */
 +      dsp.p.info = i;
 +    }
 +
@@ -308,10 +336,10 @@ index 1e5c129e9f..c3ef14f3da 100644
    return ret;
 diff --git a/sysdeps/unix/sysv/linux/telldir.h b/sysdeps/unix/sysv/linux/telldir.h
 new file mode 100644
-index 0000000000..758bcb0eb3
+index 0000000000..7772129db0
 --- /dev/null
 +++ b/sysdeps/unix/sysv/linux/telldir.h
-@@ -0,0 +1,65 @@
+@@ -0,0 +1,70 @@
 +/* Linux internal telldir definitions.
 +   Copyright (C) 2023 Free Software Foundation, Inc.
 +   This file is part of the GNU C Library.
@@ -333,7 +361,15 @@ index 0000000000..758bcb0eb3
 +#ifndef _TELLDIR_H
 +#define _TELLDIR_H 1
 +
++#include <dirent.h>
++
 +#if _DIRENT_OFFSET_TRANSLATION
++
++_Static_assert (sizeof (long int) < sizeof (__off64_t),
++		"sizeof (long int) >= sizeof (__off64_t)");
++
++# include <intprops.h>
++
 +/* 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
@@ -352,9 +388,6 @@ index 0000000000..758bcb0eb3
 +  } p;
 +};
 +
-+_Static_assert (sizeof (long int) == sizeof (union dirstream_packed),
-+		"sizeof (long int) != sizeof (union dirstream_packed)");
-+
 +/* telldir maintains a list of offsets that describe the obtained diretory
 +   position if it can fit this information in the returned 'dirstream_packed'
 +   struct.  */
@@ -367,7 +400,7 @@ index 0000000000..758bcb0eb3
 +static __always_inline bool
 +telldir_need_dirstream (__off64_t d_off)
 +{
-+  return d_off >= 1UL << 31;
++  return ! (TYPE_MINIMUM (off_t) <= d_off && d_off <= TYPE_MAXIMUM (off_t));
 +}
 +#else
 +
@@ -377,12 +410,20 @@ index 0000000000..758bcb0eb3
 +#endif /* __LP64__  */
 +
 +#endif /* _TELLDIR_H  */
-diff --git a/sysdeps/unix/sysv/linux/tst-opendir-nolfs.c b/sysdeps/unix/sysv/linux/tst-opendir-nolfs.c
+diff --git a/sysdeps/unix/sysv/linux/tst-opendir-lfs.c b/sysdeps/unix/sysv/linux/tst-opendir-lfs.c
 new file mode 100644
-index 0000000000..52e18171a7
+index 0000000000..1de1891fb4
 --- /dev/null
-+++ b/sysdeps/unix/sysv/linux/tst-opendir-nolfs.c
-@@ -0,0 +1,146 @@
++++ b/sysdeps/unix/sysv/linux/tst-opendir-lfs.c
+@@ -0,0 +1,2 @@
++#define _FILE_OFFSET_BITS 64
++#include "tst-opendir.c"
+diff --git a/sysdeps/unix/sysv/linux/tst-opendir.c b/sysdeps/unix/sysv/linux/tst-opendir.c
+new file mode 100644
+index 0000000000..216ecf123f
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/tst-opendir.c
+@@ -0,0 +1,145 @@
 +/* Check multiple telldir and seekdir.
 +   Copyright (C) 2023 Free Software Foundation, Inc.
 +   This file is part of the GNU C Library.
@@ -455,17 +496,18 @@ index 0000000000..52e18171a7
 +  DIR *dirp = opendir (dirname);
 +  TEST_VERIFY_EXIT (dirp != NULL);
 +
-+  long int *tdirp = xmalloc (nfiles * sizeof (long int));
-+  struct dirent **ddirp = xmalloc (nfiles * sizeof (struct dirent *));
++  long int *tdirp = xreallocarray (NULL, nfiles, sizeof (long int));
++  struct dirent **ddirp = xreallocarray (NULL, nfiles,
++					 sizeof (struct dirent *));
 +
 +  /* For non-LFS, the entry is skipped if it can not be converted.  */
 +  int count = 0;
 +  for (; count < nfiles; count++)
 +    {
-+      tdirp[count] = telldir (dirp);
 +      struct dirent *dp = readdir (dirp);
 +      if (dp == NULL)
 +	break;
++      tdirp[count] = telldir (dirp);
 +      ddirp[count] = xmalloc (dp->d_reclen);
 +      memcpy (ddirp[count], dp, dp->d_reclen);
 +    }
@@ -499,11 +541,10 @@ index 0000000000..52e18171a7
 +          entry.d_name[sizeof (entry.d_name) - 1] = '\0';
 +          TEST_VERIFY (strlen (entry.d_name) < sizeof (entry.d_name) - 1);
 +
-+	  if (in_ino_t_range (entry.d_ino) && in_off_t_range (entry.d_off))
++	  if (in_ino_t_range (entry.d_ino))
 +	    {
 +	      TEST_COMPARE_STRING (entry.d_name, ddirp[i]->d_name);
 +	      TEST_COMPARE (entry.d_ino, ddirp[i]->d_ino);
-+	      TEST_COMPARE (entry.d_off, ddirp[i]->d_off);
 +	      TEST_COMPARE (entry.d_type, ddirp[i]->d_type);
 +
 +	      /* Offset zero is reserved for the first entry.  */
@@ -517,7 +558,6 @@ index 0000000000..52e18171a7
 +	}
 +    }
 +
-+  /* direntries_read has been called more than once.  */
 +  TEST_COMPARE (count, i);
 +
 +  free (tdirp);

diff --git a/9999/0007-linux-Add-__old_readdir64_unlocked.patch b/9999/0007-linux-Add-__old_readdir64_unlocked.patch
deleted file mode 100644
index 2b99897..0000000
--- a/9999/0007-linux-Add-__old_readdir64_unlocked.patch
+++ /dev/null
@@ -1,194 +0,0 @@
-From f1d798104d5adfdec9aff9390dd7b62014d888eb Mon Sep 17 00:00:00 2001
-From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
-Date: Fri, 27 Jan 2023 14:28:33 -0300
-Subject: [PATCH 7/9] linux: Add __old_readdir64_unlocked
-
-And use it __old_readdir64_r.
-
-Checked on i686-linux-gnu.
----
- sysdeps/unix/sysv/linux/olddirent.h   |  2 +
- sysdeps/unix/sysv/linux/readdir64.c   | 24 +++++---
- sysdeps/unix/sysv/linux/readdir64_r.c | 79 ++++++---------------------
- 3 files changed, 35 insertions(+), 70 deletions(-)
-
-diff --git a/sysdeps/unix/sysv/linux/olddirent.h b/sysdeps/unix/sysv/linux/olddirent.h
-index 9789ffae07..cde95e192e 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 2327511736..b901071aa7 100644
---- a/sysdeps/unix/sysv/linux/readdir64.c
-+++ b/sysdeps/unix/sysv/linux/readdir64.c
-@@ -104,15 +104,11 @@ versioned_symbol (libc, __readdir64, readdir64, GLIBC_2_2);
- 
- attribute_compat_text_section
- struct __old_dirent64 *
--__old_readdir64 (DIR *dirp)
-+__old_readdir64_unlocked (DIR *dirp)
- {
-   struct __old_dirent64 *dp;
-   int saved_errno = errno;
- 
--#if IS_IN (libc)
--  __libc_lock_lock (dirp->lock);
--#endif
--
-   if (dirp->offset >= dirp->size)
-     {
-       /* We've emptied out our buffer.  Refill it.  */
-@@ -129,9 +125,6 @@ __old_readdir64 (DIR *dirp)
- 	     do not set errno in that case, to indicate success.  */
- 	  if (bytes == 0 || errno == ENOENT)
- 	    __set_errno (saved_errno);
--#if IS_IN (libc)
--	  __libc_lock_unlock (dirp->lock);
--#endif
- 	  return NULL;
- 	}
-       dirp->size = (size_t) bytes;
-@@ -144,6 +137,21 @@ __old_readdir64 (DIR *dirp)
-   dirp->offset += dp->d_reclen;
-   dirp->filepos = dp->d_off;
- 
-+  return dp;
-+}
-+
-+attribute_compat_text_section
-+struct __old_dirent64 *
-+__old_readdir64 (DIR *dirp)
-+{
-+  struct __old_dirent64 *dp;
-+
-+#if IS_IN (libc)
-+  __libc_lock_lock (dirp->lock);
-+#endif
-+
-+  dp = __old_readdir64_unlocked (dirp);
-+
- #if IS_IN (libc)
-   __libc_lock_unlock (dirp->lock);
- #endif
-diff --git a/sysdeps/unix/sysv/linux/readdir64_r.c b/sysdeps/unix/sysv/linux/readdir64_r.c
-index 5ae099bde7..b499388de7 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.41.0
-

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


             reply	other threads:[~2024-01-11 23:27 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-11 23:27 Andreas K. Hüttel [this message]
  -- strict thread matches above, loose matches on Subject: below --
2025-01-24 11:27 [gentoo-commits] proj/toolchain/glibc-patches:master commit in: 9999/ Sam James
2025-01-24  1:28 Sam James
2024-12-22  6:28 Sam James
2024-08-26 16:38 Sam James
2024-02-19  0:52 Andreas K. Hüttel
2024-01-11 23:28 Andreas K. Hüttel
2023-12-25 20:15 Andreas K. Hüttel
2023-12-25 20:11 Andreas K. Hüttel
2023-12-23 21:58 Andreas K. Hüttel
2023-10-04 19:13 Andreas K. Hüttel
2023-09-11 17:21 Andreas K. Hüttel
2023-07-17 20:40 Andreas K. Hüttel
2023-02-01 19:47 Andreas K. Hüttel
2023-01-01 18:42 Andreas K. Hüttel
2022-09-20 17:56 Andreas K. Hüttel
2022-09-19 21:26 Andreas K. Hüttel
2022-08-08 21:22 Andreas K. Hüttel
2022-07-29 12:20 WANG Xuerui
2022-07-05  4:02 Andreas K. Hüttel
2022-04-16 11:54 Andreas K. Hüttel
2022-04-16 11:54 Andreas K. Hüttel
2022-04-16 11:54 Andreas K. Hüttel
2022-03-27 16:12 Andreas K. Hüttel
2022-03-07  1:04 Andreas K. Hüttel
2022-02-21 21:42 Andreas K. Hüttel
2022-02-12 18:45 Andreas K. Hüttel
2022-01-06 15:13 Andreas K. Hüttel
2022-01-05 21:19 Andreas K. Hüttel
2022-01-04 11:00 Andreas K. Hüttel
2021-12-01 16:30 Andreas K. Hüttel
2021-12-01 16:17 Andreas K. Hüttel
2021-08-02 22:42 Andreas K. Hüttel
2021-08-02 22:41 Andreas K. Hüttel
2021-07-22 23:17 Andreas K. Hüttel
2021-05-25 20:30 Andreas K. Hüttel
2021-04-10 15:34 Andreas K. Hüttel
2021-02-27 19:18 Andreas K. Hüttel
2020-07-23 23:20 Andreas K. Hüttel
2020-07-18 16:23 Andreas K. Hüttel
2020-05-13  8:52 Andreas K. Hüttel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1705015630.d53894fd2ecb4fe3ae4242b36d314d95f8222a3e.dilfridge@gentoo \
    --to=dilfridge@gentoo.org \
    --cc=gentoo-commits@lists.gentoo.org \
    --cc=gentoo-dev@lists.gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox