public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 5/7] Consolidate scandir{at}{64} implementation
  2018-03-02 18:59 [PATCH 1/7] Assume O_DIRECTORY for opendir Adhemerval Zanella
                   ` (4 preceding siblings ...)
  2018-03-02 18:59 ` [PATCH 7/7] Consolidate getdirentries{64} implementation Adhemerval Zanella
@ 2018-03-02 18:59 ` Adhemerval Zanella
  2018-04-20 13:50   ` Adhemerval Zanella
  2018-04-20 15:30   ` Florian Weimer
  2018-04-02 13:59 ` [PATCH 1/7] Assume O_DIRECTORY for opendir Adhemerval Zanella
  6 siblings, 2 replies; 21+ messages in thread
From: Adhemerval Zanella @ 2018-03-02 18:59 UTC (permalink / raw)
  To: libc-alpha

This patch consolidates scandir{at}{64} implementation on just
the default dirent/scandir{at}{64}{_r}.c ones.  It changes the logic
to follow the conventions used on other code consolidation:

  * scandir{at} is only built for _DIRENT_MATCHES_DIRENT64 being 0.

  * scandir{at}{64} is always built and aliased to getdents for ABIs
    that define _DIRENT_MATCHES_DIRENT64 to 1.

Also on Linux the compat symbol for old non-LFS dirent64 definition
requires a platform-specific scandir64.c.

Checked on aarch64-linux-gnu, x86_64-linux-gnu, i686-linux-gnu,
sparcv9-linux-gnu, sparc64-linux-gnu, powerpc-linux-gnu, and
powerpc64le-linux-gnu.

	* dirent/scandir-tail-common.c: New file.
	* dirent/scandir-tail.c: Use scandir-tail-common.c.
	(__scandir_tail): Build iff _DIRENT_MATCHES_DIRENT64 is not defined.
	* dirent/scandir.c: Use scandir-tail-common.c.
	* dirent/scandirat.c: Likewise.
	* dirent/scandir64-tail.c: Use scandir-tail-common.c.
	* dirent/scandir64.c (scandir64): Always build and alias to scandir
	if _DIRENT_MATCHES_DIRENT64 is defined.
	* dirent/scandirat64.c (scandirat64): Likewise.
	* include/dirent.h (__scandir_tail): Only define iff
	_DIRENT_MATCHES_DIRENT64 is not defined.
	(__scandir64_tail): Define regardless.
	(__scandirat, scandirat64): Remove libc_hidden_proto.
	* sysdeps/unix/sysv/linux/arm/scandir64.c: Remove file.
	* sysdeps/unix/sysv/linux/m68k/scandir64.c: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/scandir64.c: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/scandir64.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/scandir64.c: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/scandir64.c: Likewise.
	* sysdeps/unix/sysv/linux/scandir64.c: New file.
---
 ChangeLog                                          |  21 +++++
 dirent/scandir-tail-common.c                       | 103 +++++++++++++++++++++
 dirent/scandir-tail.c                              |  95 ++-----------------
 dirent/scandir.c                                   |  27 +-----
 dirent/scandir64-tail.c                            |  10 +-
 dirent/scandir64.c                                 |  23 +++--
 dirent/scandirat.c                                 |  30 +-----
 dirent/scandirat64.c                               |  23 +++--
 include/dirent.h                                   |  18 ++--
 sysdeps/unix/sysv/linux/arm/scandir64.c            |   1 -
 sysdeps/unix/sysv/linux/m68k/scandir64.c           |   1 -
 .../unix/sysv/linux/powerpc/powerpc32/scandir64.c  |   1 -
 sysdeps/unix/sysv/linux/s390/s390-32/scandir64.c   |   1 -
 sysdeps/unix/sysv/linux/{i386 => }/scandir64.c     |  37 ++++----
 sysdeps/unix/sysv/linux/sparc/sparc32/scandir64.c  |   1 -
 15 files changed, 198 insertions(+), 194 deletions(-)
 create mode 100644 dirent/scandir-tail-common.c
 delete mode 100644 sysdeps/unix/sysv/linux/arm/scandir64.c
 delete mode 100644 sysdeps/unix/sysv/linux/m68k/scandir64.c
 delete mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/scandir64.c
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/scandir64.c
 rename sysdeps/unix/sysv/linux/{i386 => }/scandir64.c (81%)
 delete mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/scandir64.c

diff --git a/dirent/scandir-tail-common.c b/dirent/scandir-tail-common.c
new file mode 100644
index 0000000..f89cf77
--- /dev/null
+++ b/dirent/scandir-tail-common.c
@@ -0,0 +1,103 @@
+/* Common implementation for scandir{at}.
+   Copyright (C) 2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <errno.h>
+
+int
+SCANDIR_TAIL (DIR *dp,
+              DIRENT_TYPE ***namelist,
+              int (*select) (const DIRENT_TYPE *),
+              int (*cmp) (const DIRENT_TYPE **, const DIRENT_TYPE **))
+{
+  if (dp == NULL)
+    return -1;
+
+  int save = errno;
+  __set_errno (0);
+
+  int result;
+  struct scandir_cancel_struct c = { .dp = dp };
+  __libc_cleanup_push (&__scandir_cancel_handler, &c);
+
+  DIRENT_TYPE **v = NULL;
+  size_t vsize = 0;
+  DIRENT_TYPE *d;
+  while ((d = READDIR (dp)) != NULL)
+    {
+      if (select != NULL)
+        {
+          int selected = (*select) (d);
+
+	  /* The SELECT function might have set errno to non-zero on
+	     success.  It was zero before and it needs to be again to
+	     make the later tests work.  */
+	  __set_errno (0);
+
+          if (!selected)
+            continue;
+        }
+
+      if (__glibc_unlikely (c.cnt == vsize))
+        {
+          if (vsize == 0)
+            vsize = 10;
+          else
+            vsize *= 2;
+          DIRENT_TYPE **new = realloc (v, vsize * sizeof *v);
+          if (new == NULL)
+            break;
+          c.v = v = new;
+        }
+
+      size_t dsize = &d->d_name[_D_ALLOC_NAMLEN (d)] - (char *) d;
+      DIRENT_TYPE *vnew = malloc (dsize);
+      if (vnew == NULL)
+        break;
+      v[c.cnt++] = (DIRENT_TYPE *) memcpy (vnew, d, dsize);
+
+      /* Ignore errors from readdir, malloc or realloc.  These functions
+	 might have set errno to non-zero on success.  It was zero before
+	 and it needs to be again to make the latter tests work.  */
+      __set_errno (0);
+    }
+
+  if (__glibc_likely (errno == 0))
+    {
+      __closedir (dp);
+
+      /* Sort the list if we have a comparison function to sort with.  */
+      if (cmp != NULL)
+	qsort (v, c.cnt, sizeof *v, (__compar_fn_t) cmp);
+
+      *namelist = v;
+      result = c.cnt;
+    }
+  else
+    {
+      /* This frees everything and calls closedir.  */
+      __scandir_cancel_handler (&c);
+      result = -1;
+    }
+
+  __libc_cleanup_pop (0);
+
+  if (result >= 0)
+    __set_errno (save);
+  return result;
+}
diff --git a/dirent/scandir-tail.c b/dirent/scandir-tail.c
index 67c9c92..7395dc4 100644
--- a/dirent/scandir-tail.c
+++ b/dirent/scandir-tail.c
@@ -17,96 +17,13 @@
    <http://www.gnu.org/licenses/>.  */
 
 #include <dirent.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <libc-lock.h>
 
-#ifndef SCANDIR_TAIL
-# define SCANDIR_TAIL	__scandir_tail
-# define READDIR	__readdir
-# define DIRENT_TYPE	struct dirent
-#endif
-
-int
-SCANDIR_TAIL (DIR *dp,
-              DIRENT_TYPE ***namelist,
-              int (*select) (const DIRENT_TYPE *),
-              int (*cmp) (const DIRENT_TYPE **, const DIRENT_TYPE **))
-{
-  if (dp == NULL)
-    return -1;
-
-  int save = errno;
-  __set_errno (0);
-
-  int result;
-  struct scandir_cancel_struct c = { .dp = dp };
-  __libc_cleanup_push (&__scandir_cancel_handler, &c);
-
-  DIRENT_TYPE **v = NULL;
-  size_t vsize = 0;
-  DIRENT_TYPE *d;
-  while ((d = READDIR (dp)) != NULL)
-    {
-      if (select != NULL)
-        {
-          int selected = (*select) (d);
-
-	  /* The SELECT function might have set errno to non-zero on
-	     success.  It was zero before and it needs to be again to
-	     make the later tests work.  */
-	  __set_errno (0);
-
-          if (!selected)
-            continue;
-        }
+#if !_DIRENT_MATCHES_DIRENT64
 
-      if (__glibc_unlikely (c.cnt == vsize))
-        {
-          if (vsize == 0)
-            vsize = 10;
-          else
-            vsize *= 2;
-          DIRENT_TYPE **new = realloc (v, vsize * sizeof *v);
-          if (new == NULL)
-            break;
-          c.v = v = new;
-        }
+# define SCANDIR_TAIL  __scandir_tail
+# define READDIR       __readdir
+# define DIRENT_TYPE   struct dirent
 
-      size_t dsize = &d->d_name[_D_ALLOC_NAMLEN (d)] - (char *) d;
-      DIRENT_TYPE *vnew = malloc (dsize);
-      if (vnew == NULL)
-        break;
-      v[c.cnt++] = (DIRENT_TYPE *) memcpy (vnew, d, dsize);
+# include <dirent/scandir-tail-common.c>
 
-      /* Ignore errors from readdir, malloc or realloc.  These functions
-	 might have set errno to non-zero on success.  It was zero before
-	 and it needs to be again to make the latter tests work.  */
-      __set_errno (0);
-    }
-
-  if (__glibc_likely (errno == 0))
-    {
-      __closedir (dp);
-
-      /* Sort the list if we have a comparison function to sort with.  */
-      if (cmp != NULL)
-	qsort (v, c.cnt, sizeof *v, (__compar_fn_t) cmp);
-
-      *namelist = v;
-      result = c.cnt;
-    }
-  else
-    {
-      /* This frees everything and calls closedir.  */
-      __scandir_cancel_handler (&c);
-      result = -1;
-    }
-
-  __libc_cleanup_pop (0);
-
-  if (result >= 0)
-    __set_errno (save);
-  return result;
-}
+#endif
diff --git a/dirent/scandir.c b/dirent/scandir.c
index b24e157..6d8352d 100644
--- a/dirent/scandir.c
+++ b/dirent/scandir.c
@@ -15,31 +15,14 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-/* We need to avoid the header declaration of scandir64, because
-   the types don't match scandir and then the compiler will
-   complain about the mismatch when we do the alias below.  */
-#define scandir64       __renamed_scandir64
-
 #include <dirent.h>
 
-#undef  scandir64
-
-#ifndef SCANDIR
-# define SCANDIR        scandir
-# define SCANDIR_TAIL   __scandir_tail
-# define DIRENT_TYPE    struct dirent
-#endif
-
-
+#if !_DIRENT_MATCHES_DIRENT64
 int
-SCANDIR (const char *dir,
-	 DIRENT_TYPE ***namelist,
-	 int (*select) (const DIRENT_TYPE *),
-	 int (*cmp) (const DIRENT_TYPE **, const DIRENT_TYPE **))
+scandir (const char *dir, struct dirent ***namelist,
+	 int (*select) (const struct dirent *),
+	 int (*cmp) (const struct dirent **, const struct dirent **))
 {
-  return SCANDIR_TAIL (__opendir (dir), namelist, select, cmp);
+  return __scandir_tail (__opendir (dir), namelist, select, cmp);
 }
-
-#if _DIRENT_MATCHES_DIRENT64
-weak_alias (scandir, scandir64)
 #endif
diff --git a/dirent/scandir64-tail.c b/dirent/scandir64-tail.c
index 8d5cc07..4e873d4 100644
--- a/dirent/scandir64-tail.c
+++ b/dirent/scandir64-tail.c
@@ -18,9 +18,7 @@
 
 #include <dirent.h>
 
-#if !_DIRENT_MATCHES_DIRENT64
-# define SCANDIR_TAIL   __scandir64_tail
-# define READDIR        __readdir64
-# define DIRENT_TYPE    struct dirent64
-# include <scandir-tail.c>
-#endif
+#define SCANDIR_TAIL   __scandir64_tail
+#define READDIR        __readdir64
+#define DIRENT_TYPE    struct dirent64
+#include <scandir-tail-common.c>
diff --git a/dirent/scandir64.c b/dirent/scandir64.c
index 0c63fa9..6bdd462 100644
--- a/dirent/scandir64.c
+++ b/dirent/scandir64.c
@@ -15,15 +15,18 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#define scandir __no_scandir_decl
 #include <dirent.h>
-
-/* scandir.c defines scandir64 as an alias if _DIRENT_MATCHES_DIRENT64.  */
-#if !_DIRENT_MATCHES_DIRENT64
-
-# define SCANDIR        scandir64
-# define SCANDIR_TAIL   __scandir64_tail
-# define DIRENT_TYPE    struct dirent64
-
-# include <dirent/scandir.c>
-
+#undef scandir
+
+int
+scandir64 (const char *dir, struct dirent64 ***namelist,
+	   int (*select) (const struct dirent64 *),
+	   int (*cmp) (const struct dirent64 **, const struct dirent64 **))
+{
+  return __scandir64_tail (__opendir (dir), namelist, select, cmp);
+}
+
+#if _DIRENT_MATCHES_DIRENT64
+weak_alias (scandir64, scandir)
 #endif
diff --git a/dirent/scandirat.c b/dirent/scandirat.c
index 96a1b0e..8dad1e8 100644
--- a/dirent/scandirat.c
+++ b/dirent/scandirat.c
@@ -15,35 +15,15 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-/* We need to avoid the header declaration of scandir64, because
-   the types don't match scandir and then the compiler will
-   complain about the mismatch when we do the alias below.  */
-#define scandirat64       __renamed_scandirat64
-
 #include <dirent.h>
 
-#undef  scandirat64
-
-#ifndef SCANDIRAT
-# define SCANDIRAT	__scandirat
-# define SCANDIR_TAIL	__scandir_tail
-# define DIRENT_TYPE	struct dirent
-# define SCANDIRAT_WEAK_ALIAS
-#endif
-
+#if !_DIRENT_MATCHES_DIRENT64
 int
-SCANDIRAT (int dfd, const char *dir,
-	   DIRENT_TYPE ***namelist,
-	   int (*select) (const DIRENT_TYPE *),
-	   int (*cmp) (const DIRENT_TYPE **, const DIRENT_TYPE **))
+__scandirat (int dfd, const char *dir, struct dirent ***namelist,
+	     int (*select) (const struct dirent *),
+	     int (*cmp) (const struct dirent **, const struct dirent **))
 {
-  return SCANDIR_TAIL (__opendirat (dfd, dir), namelist, select, cmp);
+  return __scandir_tail (__opendirat (dfd, dir), namelist, select, cmp);
 }
-libc_hidden_def (SCANDIRAT)
-#ifdef SCANDIRAT_WEAK_ALIAS
 weak_alias (__scandirat, scandirat)
 #endif
-
-#if _DIRENT_MATCHES_DIRENT64
-weak_alias (scandirat, scandirat64)
-#endif
diff --git a/dirent/scandirat64.c b/dirent/scandirat64.c
index 520ae7c..7e5e209 100644
--- a/dirent/scandirat64.c
+++ b/dirent/scandirat64.c
@@ -15,15 +15,18 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#define scandirat __no_scandirat_decl
 #include <dirent.h>
-
-/* scandirat.c defines scandirat64 as an alias if _DIRENT_MATCHES_DIRENT64.  */
-#if !_DIRENT_MATCHES_DIRENT64
-
-# define SCANDIRAT      scandirat64
-# define SCANDIR_TAIL   __scandir64_tail
-# define DIRENT_TYPE    struct dirent64
-
-# include <scandirat.c>
-
+#undef scandirat
+
+int
+scandirat64 (int dfd, const char *dir, struct dirent64 ***namelist,
+	     int (*select) (const struct dirent64 *),
+	     int (*cmp) (const struct dirent64 **, const struct dirent64 **))
+{
+  return __scandir64_tail (__opendirat (dfd, dir), namelist, select, cmp);
+}
+
+#if _DIRENT_MATCHES_DIRENT64
+weak_alias (scandirat64, scandirat)
 #endif
diff --git a/include/dirent.h b/include/dirent.h
index cc8f189..f8f1942 100644
--- a/include/dirent.h
+++ b/include/dirent.h
@@ -57,25 +57,23 @@ extern int __scandir_tail (DIR *dp,
 			   int (*cmp) (const struct dirent **,
 				       const struct dirent **))
   attribute_hidden;
-#  if _DIRENT_MATCHES_DIRENT64
-#   define __scandir64_tail (dp, namelist, select, cmp)         \
-  __scandir_tail (dp, (struct dirent ***) (namelist),           \
-		  (int (*) (const struct dirent *)) (select),   \
-		  (int (*) (const struct dirent **,             \
-			    const struct dirent **)) (cmp))
-#  else
+#  if !_DIRENT_MATCHES_DIRENT64
+extern int __scandir_tail (DIR *dp,
+			   struct dirent ***namelist,
+			   int (*select) (const struct dirent *),
+			   int (*cmp) (const struct dirent **,
+					 const struct dirent **))
+  attribute_hidden;
+#  endif
 extern int __scandir64_tail (DIR *dp,
 			     struct dirent64 ***namelist,
 			     int (*select) (const struct dirent64 *),
 			     int (*cmp) (const struct dirent64 **,
 					 const struct dirent64 **))
   attribute_hidden;
-#  endif
 
 libc_hidden_proto (__rewinddir)
 extern __typeof (scandirat) __scandirat;
-libc_hidden_proto (__scandirat)
-libc_hidden_proto (scandirat64)
 
 #  if IS_IN (rtld) && !defined NO_RTLD_HIDDEN
 extern __typeof (__rewinddir) __rewinddir attribute_hidden;
diff --git a/sysdeps/unix/sysv/linux/arm/scandir64.c b/sysdeps/unix/sysv/linux/arm/scandir64.c
deleted file mode 100644
index 506fd88..0000000
--- a/sysdeps/unix/sysv/linux/arm/scandir64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/scandir64.c>
diff --git a/sysdeps/unix/sysv/linux/m68k/scandir64.c b/sysdeps/unix/sysv/linux/m68k/scandir64.c
deleted file mode 100644
index 506fd88..0000000
--- a/sysdeps/unix/sysv/linux/m68k/scandir64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/scandir64.c>
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/scandir64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc32/scandir64.c
deleted file mode 100644
index 506fd88..0000000
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/scandir64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/scandir64.c>
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/scandir64.c b/sysdeps/unix/sysv/linux/s390/s390-32/scandir64.c
deleted file mode 100644
index 506fd88..0000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/scandir64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/scandir64.c>
diff --git a/sysdeps/unix/sysv/linux/i386/scandir64.c b/sysdeps/unix/sysv/linux/scandir64.c
similarity index 81%
rename from sysdeps/unix/sysv/linux/i386/scandir64.c
rename to sysdeps/unix/sysv/linux/scandir64.c
index 50590c3..efb502f 100644
--- a/sysdeps/unix/sysv/linux/i386/scandir64.c
+++ b/sysdeps/unix/sysv/linux/scandir64.c
@@ -15,26 +15,28 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#define scandir __no_scandir_decl
 #include <dirent.h>
+#undef scandir
 
-#define SCANDIR		__scandir64
-#define SCANDIR_TAIL	__scandir64_tail
-#define DIRENT_TYPE	struct dirent64
-
-#include <dirent/scandir.c>
-
-#undef	SCANDIR
-#undef	SCANDIR_TAIL
-#undef	DIRENT_TYPE
-
-#include <shlib-compat.h>
+int
+__scandir64 (const char *dir, struct dirent64 ***namelist,
+	   int (*select) (const struct dirent64 *),
+	   int (*cmp) (const struct dirent64 **, const struct dirent64 **))
+{
+  return __scandir64_tail (__opendir (dir), namelist, select, cmp);
+}
 
+#if _DIRENT_MATCHES_DIRENT64
+weak_alias (__scandir64, scandir64)
+weak_alias (__scandir64, scandir)
+#else
+# include <shlib-compat.h>
 versioned_symbol (libc, __scandir64, scandir64, GLIBC_2_2);
-
-#if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_2)
-# include <string.h>
-# include <errno.h>
-# include "olddirent.h"
+# if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_2)
+#  include <string.h>
+#  include <errno.h>
+#  include "olddirent.h"
 
 int
 __old_scandir64 (const char *dir, struct __old_dirent64 ***namelist,
@@ -133,4 +135,5 @@ __old_scandir64 (const char *dir, struct __old_dirent64 ***namelist,
 }
 compat_symbol (libc, __old_scandir64, scandir64, GLIBC_2_1);
 
-#endif
+# endif /* SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_2)  */
+#endif /* _DIRENT_MATCHES_DIRENT64  */
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/scandir64.c b/sysdeps/unix/sysv/linux/sparc/sparc32/scandir64.c
deleted file mode 100644
index 506fd88..0000000
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/scandir64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/scandir64.c>
-- 
2.7.4

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 7/7] Consolidate getdirentries{64} implementation
  2018-03-02 18:59 [PATCH 1/7] Assume O_DIRECTORY for opendir Adhemerval Zanella
                   ` (3 preceding siblings ...)
  2018-03-02 18:59 ` [PATCH 4/7] Consolidate Linux getdents{64} implementation Adhemerval Zanella
@ 2018-03-02 18:59 ` Adhemerval Zanella
  2018-04-25 19:49   ` Adhemerval Zanella
  2018-03-02 18:59 ` [PATCH 5/7] Consolidate scandir{at}{64} implementation Adhemerval Zanella
  2018-04-02 13:59 ` [PATCH 1/7] Assume O_DIRECTORY for opendir Adhemerval Zanella
  6 siblings, 1 reply; 21+ messages in thread
From: Adhemerval Zanella @ 2018-03-02 18:59 UTC (permalink / raw)
  To: libc-alpha

This patch consolidates Linux getdirentries{64} implementation on just
the default sysdeps/unix/sysv/linux/getdirentries{64} ones.  The default
implementation handles the Linux requirements:

  * getdirentries is only built for _DIRENT_MATCHES_DIRENT64 being 0.

  * getdirentries64 is always built and aliased to getdents for ABIs
    that define _DIRENT_MATCHES_DIRENT64 to 1.

Checked on aarch64-linux-gnu, x86_64-linux-gnu, i686-linux-gnu,
sparcv9-linux-gnu, sparc64-linux-gnu, powerpc-linux-gnu, and
powerpc64le-linux-gnu.

	* sysdeps/unix/sysv/linux/getdirentries.c (getdirentries): Build iff
	_DIRENT_MATCHES_DIRENT64 is not defined.
	* sysdeps/unix/sysv/linux/getdirentries64.c (getdirentries64): Open
	implementation and alias to getdirentries if _DIRENT_MATCHES_DIRENT64
	is defined.
	* sysdeps/unix/sysv/linux/wordsize-64/getdirentries.c: Remove file.
	* sysdeps/unix/sysv/linux/wordsize-64/getdirentries64.c: Remove file.
---
 ChangeLog                                          |  8 +++++
 sysdeps/unix/sysv/linux/getdirentries.c            | 21 +++++------
 sysdeps/unix/sysv/linux/getdirentries64.c          | 41 ++++++++++++++++++++--
 .../unix/sysv/linux/wordsize-64/getdirentries.c    |  3 --
 .../unix/sysv/linux/wordsize-64/getdirentries64.c  |  1 -
 5 files changed, 54 insertions(+), 20 deletions(-)
 delete mode 100644 sysdeps/unix/sysv/linux/wordsize-64/getdirentries.c
 delete mode 100644 sysdeps/unix/sysv/linux/wordsize-64/getdirentries64.c

diff --git a/sysdeps/unix/sysv/linux/getdirentries.c b/sysdeps/unix/sysv/linux/getdirentries.c
index bc40292..23f626b 100644
--- a/sysdeps/unix/sysv/linux/getdirentries.c
+++ b/sysdeps/unix/sysv/linux/getdirentries.c
@@ -16,26 +16,21 @@
    <http://www.gnu.org/licenses/>.  */
 
 #include <dirent.h>
-#include <unistd.h>
-
-#ifndef GETDIRENTRIES
-# define GETDIRENTRIES getdirentries
-# define __GETDENTS __getdents
-#else
-# define off_t off64_t
-# define __lseek __lseek64
-#endif
+
+#if !_DIRENT_MATCHES_DIRENT64
+# include <unistd.h>
 
 ssize_t
-GETDIRENTRIES (int fd, char *buf, size_t nbytes, off_t *basep)
+getdirentries (int fd, char *buf, size_t nbytes, off_t *basep)
 {
-  off_t base = __lseek (fd, (off_t) 0, SEEK_CUR);
-  ssize_t result;
+  off_t base = __lseek (fd, 0, SEEK_CUR);
 
-  result = __GETDENTS (fd, buf, nbytes);
+  ssize_t result = __getdents (fd, buf, nbytes);
 
   if (result != -1)
     *basep = base;
 
   return result;
 }
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/getdirentries64.c b/sysdeps/unix/sysv/linux/getdirentries64.c
index e486a36..c1a23a7 100644
--- a/sysdeps/unix/sysv/linux/getdirentries64.c
+++ b/sysdeps/unix/sysv/linux/getdirentries64.c
@@ -1,3 +1,38 @@
-#define GETDIRENTRIES getdirentries64
-#define __GETDENTS __getdents64
-#include "getdirentries.c"
+/* Copyright (C) 1993-2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#define getdirentries __no_getdirentries_decl
+#include <dirent.h>
+#undef getdirentries
+#include <unistd.h>
+
+ssize_t
+getdirentries64 (int fd, char *buf, size_t nbytes, off64_t *basep)
+{
+  off64_t base = __lseek64 (fd, (off_t) 0, SEEK_CUR);
+
+  ssize_t result = __getdents64 (fd, buf, nbytes);
+
+  if (result != -1)
+    *basep = base;
+
+  return result;
+}
+
+#if _DIRENT_MATCHES_DIRENT64
+weak_alias (getdirentries64, getdirentries)
+#endif
diff --git a/sysdeps/unix/sysv/linux/wordsize-64/getdirentries.c b/sysdeps/unix/sysv/linux/wordsize-64/getdirentries.c
deleted file mode 100644
index 298d1e9..0000000
--- a/sysdeps/unix/sysv/linux/wordsize-64/getdirentries.c
+++ /dev/null
@@ -1,3 +0,0 @@
-#include "../getdirentries.c"
-
-weak_alias (getdirentries, getdirentries64)
diff --git a/sysdeps/unix/sysv/linux/wordsize-64/getdirentries64.c b/sysdeps/unix/sysv/linux/wordsize-64/getdirentries64.c
deleted file mode 100644
index 622baf0..0000000
--- a/sysdeps/unix/sysv/linux/wordsize-64/getdirentries64.c
+++ /dev/null
@@ -1 +0,0 @@
-/* Defined in getdirentries.c.  */
-- 
2.7.4

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 6/7] Consolidate alphasort{64} and versionsort{64} implementation
  2018-03-02 18:59 [PATCH 1/7] Assume O_DIRECTORY for opendir Adhemerval Zanella
  2018-03-02 18:59 ` [PATCH 2/7] Define _DIRENT_MATCHES_DIRENT64 regardless Adhemerval Zanella
  2018-03-02 18:59 ` [PATCH 3/7] Consolidate Linux readdir{64}{_r} implementation Adhemerval Zanella
@ 2018-03-02 18:59 ` Adhemerval Zanella
  2018-03-02 20:33   ` Joseph Myers
  2018-04-23 18:01   ` Adhemerval Zanella
  2018-03-02 18:59 ` [PATCH 4/7] Consolidate Linux getdents{64} implementation Adhemerval Zanella
                   ` (3 subsequent siblings)
  6 siblings, 2 replies; 21+ messages in thread
From: Adhemerval Zanella @ 2018-03-02 18:59 UTC (permalink / raw)
  To: libc-alpha

This patch consolidates both alphasort{64} and versionsort{64}
implementation on just the default dirent/alphasort{64}c and
dirent/versionsort{64} respectively.  It changes the logic
to follow the conventions used on other code consolidation:

  * the non-LFS variant is only built for _DIRENT_MATCHES_DIRENT64 being 0.

  * the LFS variant is always built and aliased to getdents for ABIs
    that define _DIRENT_MATCHES_DIRENT64 to 1.

Also on Linux the compat symbol for old non-LFS dirent64 definition
requires a platform-specific scandir64.c.  For powerpc32 and sparcv9
it requires to add specific arch-implementation to override the
generic Linux one because neither ABI exports an compat symbol for
non-LFS alphasort64 and versionsort64 variant.  Considering both
architectures do export other compat symbols for other dirent.h
functions I think this is a bug (I need confirmation).

Checked on aarch64-linux-gnu, x86_64-linux-gnu, i686-linux-gnu,
sparcv9-linux-gnu, sparc64-linux-gnu, powerpc-linux-gnu, and
powerpc64le-linux-gnu.

	* dirent/alphasort.c (alphasort): Build iff _DIRENT_MATCHES_DIRENT64 is
	defined.
	* dirent/versionsort.c (versionsort): Likewise.
	* dirent/alphasort64.c (alphasort64): Build regardless and alias to
	alphasort if _DIRENT_MATCHES_DIRENT64 is defined.
	* dirent/versionsort64.c (versionsort64): Likewise.
	* sysdeps/unix/sysv/linux/i386/alphasort64.c: Remove file.
	* sysdeps/unix/sysv/linux/arm/alphasort64.c: Likewise.
	* sysdeps/unix/sysv/linux/arm/versionsort64.c: Likewise.
	* sysdeps/unix/sysv/linux/m68k/alphasort64.c: Likewise.
	* sysdeps/unix/sysv/linux/m68k/versionsort64.c: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/alphasort64.c: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/versionsort64.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/versionsort64.c: Likewise.
	* sysdeps/unix/sysv/linux/alphasort64.c: New file.
	* sysdeps/unix/sysv/linux/versionsort64.c: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/alphasort64.c: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/versionsort64.c: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/alphasort64.c: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/versionsort64.c: Likewise.
---
 ChangeLog                                          | 21 +++++++++++++++++++++
 dirent/alphasort.c                                 | 13 ++-----------
 dirent/alphasort64.c                               |  7 ++++---
 dirent/versionsort.c                               | 12 ++----------
 dirent/versionsort64.c                             |  7 ++++---
 sysdeps/unix/sysv/linux/{i386 => }/alphasort64.c   | 22 +++++++++++-----------
 sysdeps/unix/sysv/linux/arm/alphasort64.c          |  1 -
 sysdeps/unix/sysv/linux/arm/versionsort64.c        |  1 -
 sysdeps/unix/sysv/linux/m68k/alphasort64.c         |  1 -
 sysdeps/unix/sysv/linux/m68k/versionsort64.c       |  1 -
 .../sysv/linux/powerpc/powerpc32/alphasort64.c     |  3 +++
 .../sysv/linux/powerpc/powerpc32/versionsort64.c   |  3 +++
 sysdeps/unix/sysv/linux/s390/s390-32/alphasort64.c |  1 -
 .../unix/sysv/linux/s390/s390-32/versionsort64.c   |  1 -
 .../unix/sysv/linux/sparc/sparc32/alphasort64.c    |  3 +++
 .../unix/sysv/linux/sparc/sparc32/versionsort64.c  |  3 +++
 sysdeps/unix/sysv/linux/{i386 => }/versionsort64.c | 22 +++++++++++-----------
 17 files changed, 67 insertions(+), 55 deletions(-)
 rename sysdeps/unix/sysv/linux/{i386 => }/alphasort64.c (77%)
 delete mode 100644 sysdeps/unix/sysv/linux/arm/alphasort64.c
 delete mode 100644 sysdeps/unix/sysv/linux/arm/versionsort64.c
 delete mode 100644 sysdeps/unix/sysv/linux/m68k/alphasort64.c
 delete mode 100644 sysdeps/unix/sysv/linux/m68k/versionsort64.c
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/alphasort64.c
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/versionsort64.c
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/alphasort64.c
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/versionsort64.c
 create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/alphasort64.c
 create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/versionsort64.c
 rename sysdeps/unix/sysv/linux/{i386 => }/versionsort64.c (77%)

diff --git a/dirent/alphasort.c b/dirent/alphasort.c
index a6cd151..6b2a707 100644
--- a/dirent/alphasort.c
+++ b/dirent/alphasort.c
@@ -15,23 +15,14 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-/* We need to avoid the header declaration of alphasort64, because
-   the types don't match alphasort and then the compiler will
-   complain about the mismatch when we do the alias below.  */
-#define alphasort64     __renamed_alphasort64
-
 #include <dirent.h>
 
-#undef  alphasort64
-
-#include <string.h>
+#if !_DIRENT_MATCHES_DIRENT64
+# include <string.h>
 
 int
 alphasort (const struct dirent **a, const struct dirent **b)
 {
   return strcoll ((*a)->d_name, (*b)->d_name);
 }
-
-#if _DIRENT_MATCHES_DIRENT64
-weak_alias (alphasort, alphasort64)
 #endif
diff --git a/dirent/alphasort64.c b/dirent/alphasort64.c
index 3a47a97..b822333 100644
--- a/dirent/alphasort64.c
+++ b/dirent/alphasort64.c
@@ -15,16 +15,17 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#define alphasort __no_alphasort_decl
 #include <dirent.h>
+#undef alphasort
 #include <string.h>
 
-/* alphasort.c defines alphasort64 as an alias if _DIRENT_MATCHES_DIRENT64.  */
-#if !_DIRENT_MATCHES_DIRENT64
-
 int
 alphasort64 (const struct dirent64 **a, const struct dirent64 **b)
 {
   return strcoll ((*a)->d_name, (*b)->d_name);
 }
 
+#if _DIRENT_MATCHES_DIRENT64
+weak_alias (alphasort64, alphasort)
 #endif
diff --git a/dirent/versionsort.c b/dirent/versionsort.c
index 5ec15e8..ca38c2d 100644
--- a/dirent/versionsort.c
+++ b/dirent/versionsort.c
@@ -15,16 +15,10 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-/* We need to avoid the header declaration of versionsort64, because
-   the types don't match versionsort and then the compiler will
-   complain about the mismatch when we do the alias below.  */
-#define versionsort64     __renamed_versionsort64
-
 #include <dirent.h>
 
-#undef  versionsort64
-
-#include <string.h>
+#if !_DIRENT_MATCHES_DIRENT64
+# include <string.h>
 
 int
 versionsort (const struct dirent **a, const struct dirent **b)
@@ -32,6 +26,4 @@ versionsort (const struct dirent **a, const struct dirent **b)
   return __strverscmp ((*a)->d_name, (*b)->d_name);
 }
 
-#if _DIRENT_MATCHES_DIRENT64
-weak_alias (versionsort, versionsort64)
 #endif
diff --git a/dirent/versionsort64.c b/dirent/versionsort64.c
index 7689c26..8f47e60 100644
--- a/dirent/versionsort64.c
+++ b/dirent/versionsort64.c
@@ -15,16 +15,17 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#define versionsort __no_versionsort_decl
 #include <dirent.h>
+#undef versionsort
 #include <string.h>
 
-/* versionsort.c defines a versionsort64 alias if _DIRENT_MATCHES_DIRENT64.  */
-#if !_DIRENT_MATCHES_DIRENT64
-
 int
 versionsort64 (const struct dirent64 **a, const struct dirent64 **b)
 {
   return __strverscmp ((*a)->d_name, (*b)->d_name);
 }
 
+#if !_DIRENT_MATCHES_DIRENT64
+weak_alias (versionsort64, versionsort)
 #endif
diff --git a/sysdeps/unix/sysv/linux/i386/alphasort64.c b/sysdeps/unix/sysv/linux/alphasort64.c
similarity index 77%
rename from sysdeps/unix/sysv/linux/i386/alphasort64.c
rename to sysdeps/unix/sysv/linux/alphasort64.c
index ee3b00b..7eee9d0 100644
--- a/sysdeps/unix/sysv/linux/i386/alphasort64.c
+++ b/sysdeps/unix/sysv/linux/alphasort64.c
@@ -15,7 +15,9 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#define alphasort __no_alphasort_decl
 #include <dirent.h>
+#undef alphasort
 #include <string.h>
 
 int
@@ -24,17 +26,14 @@ __alphasort64 (const struct dirent64 **a, const struct dirent64 **b)
   return strcoll ((*a)->d_name, (*b)->d_name);
 }
 
-#include <shlib-compat.h>
-
+#ifdef _DIRENT_MATCHES_DIRENT64
+weak_alias (__alphasort64, alphasort64)
+weak_alias (__alphasort64, alphasort)
+#else
+# include <shlib-compat.h>
 versioned_symbol (libc, __alphasort64, alphasort64, GLIBC_2_2);
-
-#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-
-#include <olddirent.h>
-
-int
-__old_alphasort64 (const struct __old_dirent64 **a,
-		   const struct __old_dirent64 **b);
+# if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
+#  include <olddirent.h>
 
 int
 attribute_compat_text_section
@@ -45,4 +44,5 @@ __old_alphasort64 (const struct __old_dirent64 **a,
 }
 
 compat_symbol (libc, __old_alphasort64, alphasort64, GLIBC_2_1);
-#endif
+# endif /* SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)  */
+#endif /* _DIRENT_MATCHES_DIRENT64  */
diff --git a/sysdeps/unix/sysv/linux/arm/alphasort64.c b/sysdeps/unix/sysv/linux/arm/alphasort64.c
deleted file mode 100644
index 0b5ae47..0000000
--- a/sysdeps/unix/sysv/linux/arm/alphasort64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/alphasort64.c>
diff --git a/sysdeps/unix/sysv/linux/arm/versionsort64.c b/sysdeps/unix/sysv/linux/arm/versionsort64.c
deleted file mode 100644
index 144b691..0000000
--- a/sysdeps/unix/sysv/linux/arm/versionsort64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/versionsort64.c>
diff --git a/sysdeps/unix/sysv/linux/m68k/alphasort64.c b/sysdeps/unix/sysv/linux/m68k/alphasort64.c
deleted file mode 100644
index 0b5ae47..0000000
--- a/sysdeps/unix/sysv/linux/m68k/alphasort64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/alphasort64.c>
diff --git a/sysdeps/unix/sysv/linux/m68k/versionsort64.c b/sysdeps/unix/sysv/linux/m68k/versionsort64.c
deleted file mode 100644
index 144b691..0000000
--- a/sysdeps/unix/sysv/linux/m68k/versionsort64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/versionsort64.c>
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/alphasort64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc32/alphasort64.c
new file mode 100644
index 0000000..c7de3a7
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/alphasort64.c
@@ -0,0 +1,3 @@
+/* Although powerpc32 define _DIRENT_MATCHES_DIRENT64=0 and have compat
+   mode for 2.1, it does have a compat symbol for alphasort64.  */
+#include <dirent/alphasort64.c>
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/versionsort64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc32/versionsort64.c
new file mode 100644
index 0000000..ee0e866
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/versionsort64.c
@@ -0,0 +1,3 @@
+/* Although powerpc32 define _DIRENT_MATCHES_DIRENT64=0 and have compat
+   mode for 2.1, it does have a compat symbol for alphasort64.  */
+#include <dirent/versionsort64.c>
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/alphasort64.c b/sysdeps/unix/sysv/linux/s390/s390-32/alphasort64.c
deleted file mode 100644
index 0b5ae47..0000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/alphasort64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/alphasort64.c>
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/versionsort64.c b/sysdeps/unix/sysv/linux/s390/s390-32/versionsort64.c
deleted file mode 100644
index 144b691..0000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/versionsort64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/versionsort64.c>
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/alphasort64.c b/sysdeps/unix/sysv/linux/sparc/sparc32/alphasort64.c
new file mode 100644
index 0000000..3970086
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/alphasort64.c
@@ -0,0 +1,3 @@
+/* Although sparc32 define _DIRENT_MATCHES_DIRENT64=0 and have compat
+   mode for 2.1, it does have a compat symbol for alphasort64.  */
+#include <dirent/alphasort64.c>
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/versionsort64.c b/sysdeps/unix/sysv/linux/sparc/sparc32/versionsort64.c
new file mode 100644
index 0000000..b195442
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/versionsort64.c
@@ -0,0 +1,3 @@
+/* Although sparc32 define _DIRENT_MATCHES_DIRENT64=0 and have compat
+   mode for 2.1, it does have a compat symbol for alphasort64.  */
+#include <dirent/versionsort64.c>
diff --git a/sysdeps/unix/sysv/linux/i386/versionsort64.c b/sysdeps/unix/sysv/linux/versionsort64.c
similarity index 77%
rename from sysdeps/unix/sysv/linux/i386/versionsort64.c
rename to sysdeps/unix/sysv/linux/versionsort64.c
index 1777eb2..a3a3a66 100644
--- a/sysdeps/unix/sysv/linux/i386/versionsort64.c
+++ b/sysdeps/unix/sysv/linux/versionsort64.c
@@ -15,7 +15,9 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#define versionsort __no_versionsort_decl
 #include <dirent.h>
+#undef versionsort
 #include <string.h>
 
 int
@@ -24,17 +26,14 @@ __versionsort64 (const struct dirent64 **a, const struct dirent64 **b)
   return __strverscmp ((*a)->d_name, (*b)->d_name);
 }
 
-#include <shlib-compat.h>
-
+#if _DIRENT_MATCHES_DIRENT64
+weak_alias (__versionsort64, versionsort64)
+weak_alias (__versionsort64, versionsort)
+#else
+# include <shlib-compat.h>
 versioned_symbol (libc, __versionsort64, versionsort64, GLIBC_2_2);
-
-#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-
-#include <olddirent.h>
-
-int
-__old_versionsort64 (const struct __old_dirent64 **a,
-		     const struct __old_dirent64 **b);
+# if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
+#  include <olddirent.h>
 
 int
 attribute_compat_text_section
@@ -45,4 +44,5 @@ __old_versionsort64 (const struct __old_dirent64 **a,
 }
 
 compat_symbol (libc, __old_versionsort64, versionsort64, GLIBC_2_1);
-#endif
+# endif /* SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)  */
+#endif /* _DIRENT_MATCHES_DIRENT64  */
-- 
2.7.4

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 3/7] Consolidate Linux readdir{64}{_r} implementation
  2018-03-02 18:59 [PATCH 1/7] Assume O_DIRECTORY for opendir Adhemerval Zanella
  2018-03-02 18:59 ` [PATCH 2/7] Define _DIRENT_MATCHES_DIRENT64 regardless Adhemerval Zanella
@ 2018-03-02 18:59 ` Adhemerval Zanella
  2018-04-06 19:49   ` Adhemerval Zanella
  2018-03-02 18:59 ` [PATCH 6/7] Consolidate alphasort{64} and versionsort{64} implementation Adhemerval Zanella
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 21+ messages in thread
From: Adhemerval Zanella @ 2018-03-02 18:59 UTC (permalink / raw)
  To: libc-alpha

This patch consolidates Linux readdir{64}{_r} implementation on just
the default sysdeps/unix/sysv/linux/readdir{64}{_r}.c ones.  The
default implementation handle the Linux requirements:

  * readdir{_r} is only built for _DIRENT_MATCHES_DIRENT64 being 0.

  * readdir64{_r} is always built and aliased to readdir{_r} for
    ABI that define _DIRENT_MATCHES_DIRENT64.

  * A compat symbol is added for readdir64{_r} for ABI that used to
    export the old non-LFS version.

Checked on aarch64-linux-gnu, x86_64-linux-gnu, i686-linux-gnu,
sparcv9-linux-gnu, sparc64-linux-gnu, powerpc-linux-gnu, and
powerpc64le-linux-gnu.

	* sysdeps/posix/readdir.c (__READDIR, __GETDENTS, DIRENTY_TYPE,
	__READDIR_ALIAS): Undefine after usage.
	* sysdeps/posix/readdir_r.c (__READDIR_R, __GETDENTS, DIRENT_TYPE,
	__READDIR_R_ALIAS): Likewise.
	* sysdeps/unix/sysv/linux/arm/readdir64.c: Remove file.
	* sysdeps/unix/sysv/linux/arm/readdir64_r.c: Likewise.
	* sysdeps/unix/sysv/linux/m68k/readdir64.c: Likewise.
	* sysdeps/unix/sysv/linux/m68k/readdir64_r.c: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/readdir64.c: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/readdir64_r.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/readdir64.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/readdir64_r.c: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/readdir64.c: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/readdir64_r.c: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/readdir64.c: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/readdir64_r.c: Likewise.
	* sysdeps/unix/sysv/linux/wordsize-64/readdir.c: Likewise.
	* sysdeps/unix/sysv/linux/wordsize-64/readdir64.c: Likewise.
	* sysdeps/unix/sysv/linux/wordsize-64/readdir64_r.c: Likewise.
	* sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c: Likewise.
	* sysdeps/unix/sysv/linux/readdir.c: New file.
	* sysdeps/unix/sysv/linux/readdir_r.c: Likewise.
	* sysdeps/unix/sysv/linux/readdir64.c: Add compat symbol if required.
	* sysdeps/unix/sysv/linux/readdir64_r.c: Likewise.
---
 ChangeLog                                          | 25 +++++++++++
 sysdeps/posix/readdir.c                            |  5 +++
 sysdeps/posix/readdir_r.c                          |  5 +++
 sysdeps/unix/sysv/linux/arm/readdir64.c            |  1 -
 sysdeps/unix/sysv/linux/arm/readdir64_r.c          |  1 -
 sysdeps/unix/sysv/linux/m68k/readdir64.c           |  1 -
 sysdeps/unix/sysv/linux/m68k/readdir64_r.c         |  1 -
 sysdeps/unix/sysv/linux/powerpc/readdir64.c        |  1 -
 sysdeps/unix/sysv/linux/powerpc/readdir64_r.c      |  1 -
 .../sysv/linux/{i386/readdir64_r.c => readdir.c}   | 30 +++----------
 sysdeps/unix/sysv/linux/readdir64.c                | 51 +++++++++++++++++++++-
 sysdeps/unix/sysv/linux/readdir64_r.c              | 48 +++++++++++++++++++-
 .../sysv/linux/{i386/readdir64.c => readdir_r.c}   | 33 +++-----------
 sysdeps/unix/sysv/linux/s390/s390-32/readdir64.c   |  1 -
 sysdeps/unix/sysv/linux/s390/s390-32/readdir64_r.c |  1 -
 sysdeps/unix/sysv/linux/sparc/sparc32/readdir64.c  |  1 -
 .../unix/sysv/linux/sparc/sparc32/readdir64_r.c    |  1 -
 sysdeps/unix/sysv/linux/wordsize-64/readdir.c      |  8 ----
 sysdeps/unix/sysv/linux/wordsize-64/readdir64.c    |  1 -
 sysdeps/unix/sysv/linux/wordsize-64/readdir64_r.c  |  1 -
 sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c    |  4 --
 21 files changed, 141 insertions(+), 80 deletions(-)
 delete mode 100644 sysdeps/unix/sysv/linux/arm/readdir64.c
 delete mode 100644 sysdeps/unix/sysv/linux/arm/readdir64_r.c
 delete mode 100644 sysdeps/unix/sysv/linux/m68k/readdir64.c
 delete mode 100644 sysdeps/unix/sysv/linux/m68k/readdir64_r.c
 delete mode 100644 sysdeps/unix/sysv/linux/powerpc/readdir64.c
 delete mode 100644 sysdeps/unix/sysv/linux/powerpc/readdir64_r.c
 rename sysdeps/unix/sysv/linux/{i386/readdir64_r.c => readdir.c} (52%)
 rename sysdeps/unix/sysv/linux/{i386/readdir64.c => readdir_r.c} (51%)
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/readdir64.c
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/readdir64_r.c
 delete mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/readdir64.c
 delete mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/readdir64_r.c
 delete mode 100644 sysdeps/unix/sysv/linux/wordsize-64/readdir.c
 delete mode 100644 sysdeps/unix/sysv/linux/wordsize-64/readdir64.c
 delete mode 100644 sysdeps/unix/sysv/linux/wordsize-64/readdir64_r.c
 delete mode 100644 sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c

diff --git a/sysdeps/posix/readdir.c b/sysdeps/posix/readdir.c
index fcd3853..a6ecc0f 100644
--- a/sysdeps/posix/readdir.c
+++ b/sysdeps/posix/readdir.c
@@ -120,3 +120,8 @@ __READDIR (DIR *dirp)
 #ifdef __READDIR_ALIAS
 weak_alias (__readdir, readdir)
 #endif
+
+#undef __READDIR
+#undef __GETDENTS
+#undef DIRENT_TYPE
+#undef __READDIR_ALIAS
diff --git a/sysdeps/posix/readdir_r.c b/sysdeps/posix/readdir_r.c
index 79030ab..2d691e7 100644
--- a/sysdeps/posix/readdir_r.c
+++ b/sysdeps/posix/readdir_r.c
@@ -152,3 +152,8 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
 #ifdef __READDIR_R_ALIAS
 weak_alias (__readdir_r, readdir_r)
 #endif
+
+#undef __READDIR_R
+#undef __GETDENTS
+#undef DIRENT_TYPE
+#undef __READDIR_R_ALIAS
diff --git a/sysdeps/unix/sysv/linux/arm/readdir64.c b/sysdeps/unix/sysv/linux/arm/readdir64.c
deleted file mode 100644
index 2ea26dd..0000000
--- a/sysdeps/unix/sysv/linux/arm/readdir64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/readdir64.c>
diff --git a/sysdeps/unix/sysv/linux/arm/readdir64_r.c b/sysdeps/unix/sysv/linux/arm/readdir64_r.c
deleted file mode 100644
index 9f54f89..0000000
--- a/sysdeps/unix/sysv/linux/arm/readdir64_r.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/readdir64_r.c>
diff --git a/sysdeps/unix/sysv/linux/m68k/readdir64.c b/sysdeps/unix/sysv/linux/m68k/readdir64.c
deleted file mode 100644
index 2ea26dd..0000000
--- a/sysdeps/unix/sysv/linux/m68k/readdir64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/readdir64.c>
diff --git a/sysdeps/unix/sysv/linux/m68k/readdir64_r.c b/sysdeps/unix/sysv/linux/m68k/readdir64_r.c
deleted file mode 100644
index 9f54f89..0000000
--- a/sysdeps/unix/sysv/linux/m68k/readdir64_r.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/readdir64_r.c>
diff --git a/sysdeps/unix/sysv/linux/powerpc/readdir64.c b/sysdeps/unix/sysv/linux/powerpc/readdir64.c
deleted file mode 100644
index 2ea26dd..0000000
--- a/sysdeps/unix/sysv/linux/powerpc/readdir64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/readdir64.c>
diff --git a/sysdeps/unix/sysv/linux/powerpc/readdir64_r.c b/sysdeps/unix/sysv/linux/powerpc/readdir64_r.c
deleted file mode 100644
index 9f54f89..0000000
--- a/sysdeps/unix/sysv/linux/powerpc/readdir64_r.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/readdir64_r.c>
diff --git a/sysdeps/unix/sysv/linux/i386/readdir64_r.c b/sysdeps/unix/sysv/linux/readdir.c
similarity index 52%
rename from sysdeps/unix/sysv/linux/i386/readdir64_r.c
rename to sysdeps/unix/sysv/linux/readdir.c
index 31862a0..b99bc96 100644
--- a/sysdeps/unix/sysv/linux/i386/readdir64_r.c
+++ b/sysdeps/unix/sysv/linux/readdir.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
+/* Read a directory.  Linux no-LFS version.
+   Copyright (C) 2018 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
@@ -15,29 +16,8 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#define __READDIR_R __readdir64_r
-#define __GETDENTS __getdents64
-#define DIRENT_TYPE struct dirent64
+#include <dirent.h>
 
-#include <sysdeps/posix/readdir_r.c>
-
-#undef __READDIR_R
-#undef __GETDENTS
-#undef DIRENT_TYPE
-
-#include <shlib-compat.h>
-
-versioned_symbol (libc, __readdir64_r, readdir64_r, GLIBC_2_2);
-
-#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-
-#include <olddirent.h>
-
-#define __READDIR_R attribute_compat_text_section __old_readdir64_r
-#define __GETDENTS __old_getdents64
-#define DIRENT_TYPE struct __old_dirent64
-
-#include <sysdeps/posix/readdir_r.c>
-
-compat_symbol (libc, __old_readdir64_r, readdir64_r, GLIBC_2_1);
+#if !_DIRENT_MATCHES_DIRENT64
+# include <sysdeps/posix/readdir.c>
 #endif
diff --git a/sysdeps/unix/sysv/linux/readdir64.c b/sysdeps/unix/sysv/linux/readdir64.c
index 6d154fe..054e4ff 100644
--- a/sysdeps/unix/sysv/linux/readdir64.c
+++ b/sysdeps/unix/sysv/linux/readdir64.c
@@ -1,8 +1,55 @@
-#define __READDIR __readdir64
-#define __GETDENTS __getdents64
+/* Read a directory.  Linux LFS version.
+   Copyright (C) 2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+/* When _DIRENT_MATCHES_DIRENT64 is defined we can alias 'readdir64' to
+   'readdir'.  However the function signatures are not equal due
+   different return types, so we need to suppress {__}readdir so weak
+   and strong alias do not throw conflicting types errors.  */
+#define readdir __no_readdir_decl
+#define __readdir __no___readdir_decl
+#include <dirent.h>
+
+#define __READDIR   __readdir64
+#define __GETDENTS  __getdents64
 #define DIRENT_TYPE struct dirent64
 
 #include <sysdeps/posix/readdir.c>
 
+#undef __readdir
+#undef readdir
+
 libc_hidden_def (__readdir64)
+#if _DIRENT_MATCHES_DIRENT64
+strong_alias (__readdir64, __readdir)
 weak_alias (__readdir64, readdir64)
+weak_alias (__readdir64, readdir)
+#else
+/* The compat code expects the 'struct direct' with d_ino being a __ino_t
+   instead of __ino64_t.  */
+# include <shlib-compat.h>
+versioned_symbol (libc, __readdir64, readdir64, GLIBC_2_2);
+# if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
+#  include <olddirent.h>
+#  define __READDIR   attribute_compat_text_section __old_readdir64
+#  define __GETDENTS  __old_getdents64
+#  define DIRENT_TYPE struct __old_dirent64
+#  include <sysdeps/posix/readdir.c>
+libc_hidden_def (__old_readdir64)
+compat_symbol (libc, __old_readdir64, readdir64, GLIBC_2_1);
+# endif /* SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)  */
+#endif /* _DIRENT_MATCHES_DIRENT64  */
diff --git a/sysdeps/unix/sysv/linux/readdir64_r.c b/sysdeps/unix/sysv/linux/readdir64_r.c
index 3dfbf4f..22b23d5 100644
--- a/sysdeps/unix/sysv/linux/readdir64_r.c
+++ b/sysdeps/unix/sysv/linux/readdir64_r.c
@@ -1,7 +1,53 @@
+/* Read a directory in reentrant mode.  Linux LFS version.
+   Copyright (C) 2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+/* When _DIRENT_MATCHES_DIRENT64 is defined we can alias 'readdir64' to
+   'readdir'.  However the function signatures are not equal due
+   different return types, so we need to suppress {__}readdir so weak
+   and strong alias do not throw conflicting types errors.  */
+#define readdir_r   __no_readdir_r_decl
+#define __readdir_r __no___readdir_r_decl
+#include <dirent.h>
+
 #define __READDIR_R __readdir64_r
-#define __GETDENTS __getdents64
+#define __GETDENTS  __getdents64
 #define DIRENT_TYPE struct dirent64
 
 #include <sysdeps/posix/readdir_r.c>
 
+#undef __readdir_r
+#undef readdir_r
+
+#if _DIRENT_MATCHES_DIRENT64
+strong_alias (__readdir64_r, __readdir_r)
+weak_alias (__readdir64_r, readdir_r)
 weak_alias (__readdir64_r, readdir64_r)
+#else
+/* The compat code expects the 'struct direct' with d_ino being a __ino_t
+   instead of __ino64_t.  */
+# include <shlib-compat.h>
+versioned_symbol (libc, __readdir64_r, readdir64_r, GLIBC_2_2);
+# if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
+#  include <olddirent.h>
+#  define __READDIR_R attribute_compat_text_section __old_readdir64_r
+#  define __GETDENTS  __old_getdents64
+#  define DIRENT_TYPE struct __old_dirent64
+#  include <sysdeps/posix/readdir_r.c>
+compat_symbol (libc, __old_readdir64_r, readdir64_r, GLIBC_2_1);
+# endif /* SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)  */
+#endif /* _DIRENT_MATCHES_DIRENT64  */
diff --git a/sysdeps/unix/sysv/linux/i386/readdir64.c b/sysdeps/unix/sysv/linux/readdir_r.c
similarity index 51%
rename from sysdeps/unix/sysv/linux/i386/readdir64.c
rename to sysdeps/unix/sysv/linux/readdir_r.c
index 42b7302..7ca9e8e 100644
--- a/sysdeps/unix/sysv/linux/i386/readdir64.c
+++ b/sysdeps/unix/sysv/linux/readdir_r.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
+/* Read a directory in reentrant mode.  Linux no-LFS version.
+   Copyright (C) 2018 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
@@ -15,32 +16,8 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#define __READDIR __readdir64
-#define __GETDENTS __getdents64
-#define DIRENT_TYPE struct dirent64
+#include <dirent.h>
 
-#include <sysdeps/posix/readdir.c>
-
-#include <shlib-compat.h>
-
-#undef __READDIR
-#undef __GETDENTS
-#undef DIRENT_TYPE
-
-libc_hidden_def (__readdir64)
-versioned_symbol (libc, __readdir64, readdir64, GLIBC_2_2);
-
-#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-
-#include <olddirent.h>
-
-#define __READDIR attribute_compat_text_section __old_readdir64
-#define __GETDENTS __old_getdents64
-#define DIRENT_TYPE struct __old_dirent64
-
-#include <sysdeps/posix/readdir.c>
-
-libc_hidden_def (__old_readdir64)
-
-compat_symbol (libc, __old_readdir64, readdir64, GLIBC_2_1);
+#if !_DIRENT_MATCHES_DIRENT64
+# include <sysdeps/posix/readdir_r.c>
 #endif
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/readdir64.c b/sysdeps/unix/sysv/linux/s390/s390-32/readdir64.c
deleted file mode 100644
index 2ea26dd..0000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/readdir64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/readdir64.c>
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/readdir64_r.c b/sysdeps/unix/sysv/linux/s390/s390-32/readdir64_r.c
deleted file mode 100644
index 9f54f89..0000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/readdir64_r.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/readdir64_r.c>
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/readdir64.c b/sysdeps/unix/sysv/linux/sparc/sparc32/readdir64.c
deleted file mode 100644
index 2ea26dd..0000000
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/readdir64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/readdir64.c>
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/readdir64_r.c b/sysdeps/unix/sysv/linux/sparc/sparc32/readdir64_r.c
deleted file mode 100644
index 9f54f89..0000000
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/readdir64_r.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/readdir64_r.c>
diff --git a/sysdeps/unix/sysv/linux/wordsize-64/readdir.c b/sysdeps/unix/sysv/linux/wordsize-64/readdir.c
deleted file mode 100644
index 0d57988..0000000
--- a/sysdeps/unix/sysv/linux/wordsize-64/readdir.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#define readdir64 __no_readdir64_decl
-#define __readdir64 __no___readdir64_decl
-#include <sysdeps/posix/readdir.c>
-#undef __readdir64
-strong_alias (__readdir, __readdir64)
-strong_alias (__readdir, __GI___readdir64)
-#undef readdir64
-weak_alias (__readdir, readdir64)
diff --git a/sysdeps/unix/sysv/linux/wordsize-64/readdir64.c b/sysdeps/unix/sysv/linux/wordsize-64/readdir64.c
deleted file mode 100644
index 9796431..0000000
--- a/sysdeps/unix/sysv/linux/wordsize-64/readdir64.c
+++ /dev/null
@@ -1 +0,0 @@
-/* readdir64 is in readdir.c */
diff --git a/sysdeps/unix/sysv/linux/wordsize-64/readdir64_r.c b/sysdeps/unix/sysv/linux/wordsize-64/readdir64_r.c
deleted file mode 100644
index b8fe9a3..0000000
--- a/sysdeps/unix/sysv/linux/wordsize-64/readdir64_r.c
+++ /dev/null
@@ -1 +0,0 @@
-/* readdir64_r is in readdir_r.c */
diff --git a/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c b/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c
deleted file mode 100644
index 290f2c8..0000000
--- a/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c
+++ /dev/null
@@ -1,4 +0,0 @@
-#define readdir64_r __no_readdir64_r_decl
-#include <sysdeps/posix/readdir_r.c>
-#undef readdir64_r
-weak_alias (__readdir_r, readdir64_r)
-- 
2.7.4

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 1/7] Assume O_DIRECTORY for opendir
@ 2018-03-02 18:59 Adhemerval Zanella
  2018-03-02 18:59 ` [PATCH 2/7] Define _DIRENT_MATCHES_DIRENT64 regardless Adhemerval Zanella
                   ` (6 more replies)
  0 siblings, 7 replies; 21+ messages in thread
From: Adhemerval Zanella @ 2018-03-02 18:59 UTC (permalink / raw)
  To: libc-alpha

This patch assumes O_DIRECTORY works as defined by POSIX on opendir
implementation (aligning with other glibc code, for instance pwd).  This
allows remove both the fallback code to handle system with missing or
broken O_DIRECTORY along with the Linux specific opendir.c which just
advertise the working flag.

Checked on aarch64-linux-gnu, x86_64-linux-gnu, i686-linux-gnu,
sparcv9-linux-gnu, sparc64-linux-gnu, powerpc-linux-gnu, and
powerpc64le-linux-gnu.

	* sysdeps/posix/opendir.c (o_directory_works, tryopen_o_directory):
	Remove definitions.
	(opendir_oflags): Use O_DIRECTORY regardless.
	(__opendir, __opendirat): Remove need_isdir_precheck usage.
	* sysdeps/unix/sysv/linux/opendir.c: Remove file.
---
 ChangeLog                         |   8 +++
 sysdeps/posix/opendir.c           | 108 ++------------------------------------
 sysdeps/unix/sysv/linux/opendir.c |  20 -------
 3 files changed, 13 insertions(+), 123 deletions(-)
 delete mode 100644 sysdeps/unix/sysv/linux/opendir.c

diff --git a/sysdeps/posix/opendir.c b/sysdeps/posix/opendir.c
index d925804..dea23b2 100644
--- a/sysdeps/posix/opendir.c
+++ b/sysdeps/posix/opendir.c
@@ -15,24 +15,13 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <assert.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdlib.h>
 #include <dirent.h>
 #include <fcntl.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <dirstream.h>
+#include <errno.h>
+#include <stdio.h>	/* For BUFSIZ.  */
+#include <sys/param.h>	/* For MIN and MAX.  */
+
 #include <not-cancel.h>
-#include <kernel-features.h>
 
 /* The st_blksize value of the directory is used as a hint for the
    size of the buffer which receives struct dirent values from the
@@ -40,49 +29,8 @@
    file system provides a bogus value.  */
 #define MAX_DIR_BUFFER_SIZE 1048576U
 
-/* opendir() must not accidentally open something other than a directory.
-   Some OS's have kernel support for that, some don't.  In the worst
-   case we have to stat() before the open() AND fstat() after.
-
-   We have to test at runtime for kernel support since libc may have
-   been compiled with different headers to the kernel it's running on.
-   This test can't be done reliably in the general case.  We'll use
-   /dev/null, which if it's not a device lots of stuff will break, as
-   a guinea pig.  It may be missing in chroot environments, so we
-   make sure to fail safe. */
-#ifdef O_DIRECTORY
-# ifdef O_DIRECTORY_WORKS
-#  define o_directory_works 1
-#  define tryopen_o_directory() while (1) /* This must not be called.  */
-# else
-static int o_directory_works;
-
-static void
-tryopen_o_directory (void)
-{
-  int serrno = errno;
-  int x = __open_nocancel ("/dev/null", O_RDONLY|O_NDELAY|O_DIRECTORY);
-
-  if (x >= 0)
-    {
-      __close_nocancel_nostatus (x);
-      o_directory_works = -1;
-    }
-  else if (errno != ENOTDIR)
-    o_directory_works = -1;
-  else
-    o_directory_works = 1;
-
-  __set_errno (serrno);
-}
-# endif
-# define EXTRA_FLAGS O_DIRECTORY
-#else
-# define EXTRA_FLAGS 0
-#endif
-
 enum {
-  opendir_oflags = O_RDONLY|O_NDELAY|EXTRA_FLAGS|O_LARGEFILE|O_CLOEXEC
+  opendir_oflags = O_RDONLY|O_NDELAY|O_DIRECTORY|O_LARGEFILE|O_CLOEXEC
 };
 
 static bool
@@ -98,21 +46,6 @@ invalid_name (const char *name)
   return false;
 }
 
-
-static bool
-need_isdir_precheck (void)
-{
-#ifdef O_DIRECTORY
-  /* Test whether O_DIRECTORY works.  */
-  if (o_directory_works == 0)
-    tryopen_o_directory ();
-
-  /* We can skip the expensive `stat' call if O_DIRECTORY works.  */
-  return o_directory_works < 0;
-#endif
-  return true;
-}
-
 static DIR *
 opendir_tail (int fd)
 {
@@ -144,22 +77,6 @@ __opendirat (int dfd, const char *name)
   if (__glibc_unlikely (invalid_name (name)))
     return NULL;
 
-  if (need_isdir_precheck ())
-    {
-      /* We first have to check whether the name is for a directory.  We
-	 cannot do this after the open() call since the open/close operation
-	 performed on, say, a tape device might have undesirable effects.  */
-      struct stat64 statbuf;
-      if (__glibc_unlikely (__fxstatat64 (_STAT_VER, dfd, name,
-					  &statbuf, 0) < 0))
-	return NULL;
-      if (__glibc_unlikely (! S_ISDIR (statbuf.st_mode)))
-	{
-	  __set_errno (ENOTDIR);
-	  return NULL;
-	}
-    }
-
   return opendir_tail (__openat_nocancel (dfd, name, opendir_oflags));
 }
 #endif
@@ -172,21 +89,6 @@ __opendir (const char *name)
   if (__glibc_unlikely (invalid_name (name)))
     return NULL;
 
-  if (need_isdir_precheck ())
-    {
-      /* We first have to check whether the name is for a directory.  We
-	 cannot do this after the open() call since the open/close operation
-	 performed on, say, a tape device might have undesirable effects.  */
-      struct stat64 statbuf;
-      if (__glibc_unlikely (__xstat64 (_STAT_VER, name, &statbuf) < 0))
-	return NULL;
-      if (__glibc_unlikely (! S_ISDIR (statbuf.st_mode)))
-	{
-	  __set_errno (ENOTDIR);
-	  return NULL;
-	}
-    }
-
   return opendir_tail (__open_nocancel (name, opendir_oflags));
 }
 weak_alias (__opendir, opendir)
diff --git a/sysdeps/unix/sysv/linux/opendir.c b/sysdeps/unix/sysv/linux/opendir.c
deleted file mode 100644
index 2677253..0000000
--- a/sysdeps/unix/sysv/linux/opendir.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Copyright (C) 2000-2018 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
-   <http://www.gnu.org/licenses/>.  */
-
-#define O_DIRECTORY_WORKS	1
-
-#include <sysdeps/posix/opendir.c>
-- 
2.7.4

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 4/7] Consolidate Linux getdents{64} implementation
  2018-03-02 18:59 [PATCH 1/7] Assume O_DIRECTORY for opendir Adhemerval Zanella
                   ` (2 preceding siblings ...)
  2018-03-02 18:59 ` [PATCH 6/7] Consolidate alphasort{64} and versionsort{64} implementation Adhemerval Zanella
@ 2018-03-02 18:59 ` Adhemerval Zanella
  2018-03-09 18:10   ` Adhemerval Zanella
  2018-03-02 18:59 ` [PATCH 7/7] Consolidate getdirentries{64} implementation Adhemerval Zanella
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 21+ messages in thread
From: Adhemerval Zanella @ 2018-03-02 18:59 UTC (permalink / raw)
  To: libc-alpha

This patch consolidates Linux getdents{64} implementation on just
the default sysdeps/unix/sysv/linux/getdents{64}{_r}.c ones.

Although this symbol is used only internally, the non-LFS version
still need to be build due the non-LFS getdirentries which requires
its semantic.

The non-LFS default implementation now uses the wordsize-32 as base
which uses getdents64 syscall plus adjustment for overflow (it allows
to use the same code for architectures that does not support non-LFS
getdents syscall).  It has two main differences to wordsize-32 one:

  - DIRENT_SET_DP_INO is added to handle alpha requirement to zero
    the padding.

  - alloca is removed by allocating a bounded temporary buffer (it
    increases stack usage by roughly 276 bytes).

The default implementation handle the Linux requirements:

  * getdents is only built for _DIRENT_MATCHES_DIRENT64 being 0.

  * getdents64 is always built and aliased to getdents for ABIs
    that define _DIRENT_MATCHES_DIRENT64 to 1.

  * A compat symbol is added for getdents64 for ABI that used to
    export the old non-LFS version.

Checked on aarch64-linux-gnu, x86_64-linux-gnu, i686-linux-gnu,
sparcv9-linux-gnu, sparc64-linux-gnu, powerpc-linux-gnu, and
powerpc64le-linux-gnu.

	* sysdeps/unix/sysv/linux/alpha/getdents.c: Add comments with alpha
	requirements.
	 (_DIRENT_MATCHES_DIRENT64): Undef
	* sysdeps/unix/sysv/linux/alpha/getdents64.c: Likewise.
	* sysdeps/unix/sysv/linux/arm/getdents64.c: Remove file.
	* sysdeps/unix/sysv/linux/generic/getdents.c: Likewise.
	* sysdeps/unix/sysv/linux/generic/getdents64.c: Likewise.
	* sysdeps/unix/sysv/linux/generic/wordsize-32/getdents.c: Likewise.
	* sysdeps/unix/sysv/linux/getdents.c: Simplify implementation by
	use getdents64 syscalls as base.
	* sysdeps/unix/sysv/linux/getdents64.c: Likewise and add compatibility
	symbol if required.
	* sysdeps/unix/sysv/linux/hppa/getdents64.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/getdents64.c: Likewise.
	* sysdeps/unix/sysv/linux/m68k/getdents64.c: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/getdents64.c: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/getdents64.c: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/getdents64.c: Likewise.
	* sysdeps/unix/sysv/linux/wordsize-64/getdents.c: Likewise.
	* sysdeps/unix/sysv/linux/wordsize-64/getdents64.c: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c
---
 ChangeLog                                          |  22 ++
 sysdeps/unix/sysv/linux/alpha/getdents.c           |   8 +
 sysdeps/unix/sysv/linux/alpha/getdents64.c         |   9 +
 sysdeps/unix/sysv/linux/arm/getdents64.c           |   1 -
 sysdeps/unix/sysv/linux/generic/getdents.c         |   1 -
 sysdeps/unix/sysv/linux/generic/getdents64.c       |  37 ---
 .../unix/sysv/linux/generic/wordsize-32/getdents.c | 115 --------
 sysdeps/unix/sysv/linux/getdents.c                 | 323 ++++++---------------
 sysdeps/unix/sysv/linux/getdents64.c               |  80 ++++-
 sysdeps/unix/sysv/linux/hppa/getdents64.c          |   1 -
 sysdeps/unix/sysv/linux/i386/getdents64.c          |  39 ---
 sysdeps/unix/sysv/linux/m68k/getdents64.c          |   1 -
 sysdeps/unix/sysv/linux/powerpc/getdents64.c       |   1 -
 sysdeps/unix/sysv/linux/s390/s390-32/getdents64.c  |   1 -
 sysdeps/unix/sysv/linux/sparc/sparc32/getdents64.c |   1 -
 .../unix/sysv/linux/sparc/sparc64/get_clockfreq.c  |   8 +-
 sysdeps/unix/sysv/linux/wordsize-64/getdents.c     |   4 -
 sysdeps/unix/sysv/linux/wordsize-64/getdents64.c   |   1 -
 18 files changed, 203 insertions(+), 450 deletions(-)
 delete mode 100644 sysdeps/unix/sysv/linux/arm/getdents64.c
 delete mode 100644 sysdeps/unix/sysv/linux/generic/getdents.c
 delete mode 100644 sysdeps/unix/sysv/linux/generic/getdents64.c
 delete mode 100644 sysdeps/unix/sysv/linux/generic/wordsize-32/getdents.c
 delete mode 100644 sysdeps/unix/sysv/linux/hppa/getdents64.c
 delete mode 100644 sysdeps/unix/sysv/linux/i386/getdents64.c
 delete mode 100644 sysdeps/unix/sysv/linux/m68k/getdents64.c
 delete mode 100644 sysdeps/unix/sysv/linux/powerpc/getdents64.c
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/getdents64.c
 delete mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/getdents64.c
 delete mode 100644 sysdeps/unix/sysv/linux/wordsize-64/getdents.c
 delete mode 100644 sysdeps/unix/sysv/linux/wordsize-64/getdents64.c

diff --git a/sysdeps/unix/sysv/linux/alpha/getdents.c b/sysdeps/unix/sysv/linux/alpha/getdents.c
index dfecfef..64ccf86 100644
--- a/sysdeps/unix/sysv/linux/alpha/getdents.c
+++ b/sysdeps/unix/sysv/linux/alpha/getdents.c
@@ -1,3 +1,11 @@
+/* Although Alpha defines _DIRENT_MATCHES_DIRENT64, 'struct dirent' and
+   'struct dirent64' have slight different internal layout with d_ino
+   being a __ino_t on non-LFS version with an extra __pad field which should
+   be zeroed.  */
+
+#include <dirent.h>
+#undef _DIRENT_MATCHES_DIRENT64
+#define _DIRENT_MATCHES_DIRENT64 0
 #define DIRENT_SET_DP_INO(dp, value) \
   do { (dp)->d_ino = (value); (dp)->__pad = 0; } while (0)
 #include <sysdeps/unix/sysv/linux/getdents.c>
diff --git a/sysdeps/unix/sysv/linux/alpha/getdents64.c b/sysdeps/unix/sysv/linux/alpha/getdents64.c
index 50f1368..53cf93c 100644
--- a/sysdeps/unix/sysv/linux/alpha/getdents64.c
+++ b/sysdeps/unix/sysv/linux/alpha/getdents64.c
@@ -1 +1,10 @@
+/* Although Alpha defines _DIRENT_MATCHES_DIRENT64, 'struct dirent' and
+   'struct dirent64' have slight different internal layout with d_ino
+   being a __ino_t on non-LFS version with an extra __pad field which should
+   be zeroed.  */
+
+#include <dirent.h>
+/* It suppress the __getdents64 to __getdents alias.  */
+#undef _DIRENT_MATCHES_DIRENT64
+#define _DIRENT_MATCHES_DIRENT64 0
 #include <sysdeps/unix/sysv/linux/getdents64.c>
diff --git a/sysdeps/unix/sysv/linux/arm/getdents64.c b/sysdeps/unix/sysv/linux/arm/getdents64.c
deleted file mode 100644
index 0c75fb5..0000000
--- a/sysdeps/unix/sysv/linux/arm/getdents64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/getdents64.c>
diff --git a/sysdeps/unix/sysv/linux/generic/getdents.c b/sysdeps/unix/sysv/linux/generic/getdents.c
deleted file mode 100644
index 14dbbc7..0000000
--- a/sysdeps/unix/sysv/linux/generic/getdents.c
+++ /dev/null
@@ -1 +0,0 @@
-/* Defined in getdents64.c */
diff --git a/sysdeps/unix/sysv/linux/generic/getdents64.c b/sysdeps/unix/sysv/linux/generic/getdents64.c
deleted file mode 100644
index 0f876b8..0000000
--- a/sysdeps/unix/sysv/linux/generic/getdents64.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Copyright (C) 2011-2018 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
-
-   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
-   <http://www.gnu.org/licenses/>.  */
-
-#include <stddef.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <bits/wordsize.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-
-/* The kernel struct linux_dirent64 matches the 'struct getdents64' type.  */
-ssize_t
-__getdents64 (int fd, char *buf, size_t nbytes)
-{
-  return INLINE_SYSCALL (getdents64, 3, fd, buf, nbytes);
-}
-
-#if __WORDSIZE == 64
-strong_alias (__getdents64, __getdents)
-#endif
diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/getdents.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/getdents.c
deleted file mode 100644
index 7158fd1..0000000
--- a/sysdeps/unix/sysv/linux/generic/wordsize-32/getdents.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/* Copyright (C) 1993-2018 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Simplified from sysdeps/unix/sysv/linux/getdents.c.
-
-   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
-   <http://www.gnu.org/licenses/>.  */
-
-#include <alloca.h>
-#include <assert.h>
-#include <errno.h>
-#include <dirent.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <sys/types.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-
-/* Pack the dirent64 struct down into 32-bit offset/inode fields, and
-   ensure that no overflow occurs.  */
-ssize_t
-__getdents (int fd, char *buf, size_t nbytes)
-{
-  union
-  {
-    struct dirent64 k;  /* Kernel structure.  */
-    struct dirent u;
-    char b[1];
-  } *kbuf = (void *) buf, *outp, *inp;
-  size_t kbytes = nbytes;
-  off64_t last_offset = -1;
-  ssize_t retval;
-
-  const size_t size_diff = (offsetof (struct dirent64, d_name)
-                            - offsetof (struct dirent, d_name));
-  if (nbytes <= sizeof (struct dirent))
-    {
-      kbytes = nbytes + offsetof (struct dirent64, d_name)
-        - offsetof (struct dirent, d_name);
-      kbuf = __alloca(kbytes);
-    }
-
-  retval = INLINE_SYSCALL (getdents64, 3, fd, kbuf, kbytes);
-  if (retval == -1)
-    return -1;
-
-  /* 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.  */
-  inp = kbuf;
-  outp = (void *) buf;
-
-  while (&inp->b < &kbuf->b + retval)
-    {
-      const size_t alignment = __alignof__ (struct dirent);
-      /* Since inp->k.d_reclen is already aligned for the kernel
-         structure this may compute a value that is bigger
-         than necessary.  */
-      size_t old_reclen = inp->k.d_reclen;
-      size_t new_reclen = ((old_reclen - size_diff + alignment - 1)
-                           & ~(alignment - 1));
-
-      /* Copy the data out of the old structure into temporary space.
-         Then copy the name, which may overlap if BUF == KBUF.  */
-      const uint64_t d_ino = inp->k.d_ino;
-      const int64_t d_off = inp->k.d_off;
-      const uint8_t d_type = inp->k.d_type;
-
-      memmove (outp->u.d_name, inp->k.d_name,
-               old_reclen - offsetof (struct dirent64, d_name));
-
-      /* Now we have copied the data from INP and access only OUTP.  */
-
-      outp->u.d_ino = d_ino;
-      outp->u.d_off = d_off;
-      if ((sizeof (outp->u.d_ino) != sizeof (inp->k.d_ino)
-           && outp->u.d_ino != d_ino)
-          || (sizeof (outp->u.d_off) != sizeof (inp->k.d_off)
-              && outp->u.d_off != d_off))
-        {
-          /* Overflow.  If there was at least one entry before this one,
-             return them without error, otherwise signal overflow.  */
-          if (last_offset != -1)
-            {
-              __lseek64 (fd, last_offset, SEEK_SET);
-              return outp->b - buf;
-            }
-          __set_errno (EOVERFLOW);
-          return -1;
-        }
-
-      last_offset = d_off;
-      outp->u.d_reclen = new_reclen;
-      outp->u.d_type = d_type;
-
-      inp = (void *) inp + old_reclen;
-      outp = (void *) outp + new_reclen;
-    }
-
-  return outp->b - buf;
-}
diff --git a/sysdeps/unix/sysv/linux/getdents.c b/sysdeps/unix/sysv/linux/getdents.c
index 591ce67..4e52729 100644
--- a/sysdeps/unix/sysv/linux/getdents.c
+++ b/sysdeps/unix/sysv/linux/getdents.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1993-2018 Free Software Foundation, Inc.
+/* Get directory entries.  Linux no-LFS version.
+   Copyright (C) 1993-2018 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
@@ -12,260 +13,102 @@
    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
+   License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <alloca.h>
-#include <assert.h>
-#include <errno.h>
 #include <dirent.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <sys/types.h>
 
-#include <sysdep.h>
-#include <sys/syscall.h>
+#if !_DIRENT_MATCHES_DIRENT64
 
-#include <linux/posix_types.h>
+# include <unistd.h>
+# include <string.h>
+# include <errno.h>
 
-#include <kernel-features.h>
+# ifndef DIRENT_SET_DP_INO
+#  define DIRENT_SET_DP_INO(dp, value) (dp)->d_ino = (value)
+# endif
 
-/* For Linux we need a special version of this file since the
-   definition of `struct dirent' is not the same for the kernel and
-   the libc.  There is one additional field which might be introduced
-   in the kernel structure in the future.
-
-   Here is the kernel definition of `struct dirent' as of 2.1.20:  */
-
-struct kernel_dirent
-  {
-    long int d_ino;
-    __kernel_off_t d_off;
-    unsigned short int d_reclen;
-    char d_name[256];
-  };
-
-struct kernel_dirent64
-  {
-    uint64_t		d_ino;
-    int64_t		d_off;
-    unsigned short int	d_reclen;
-    unsigned char	d_type;
-    char		d_name[256];
-  };
-
-#ifndef __GETDENTS
-# define __GETDENTS __getdents
-#endif
-#ifndef DIRENT_TYPE
-# define DIRENT_TYPE struct dirent
-#endif
-#ifndef DIRENT_SET_DP_INO
-# define DIRENT_SET_DP_INO(dp, value) (dp)->d_ino = (value)
-#endif
-
-/* The problem here is that we cannot simply read the next NBYTES
-   bytes.  We need to take the additional field into account.  We use
-   some heuristic.  Assuming the directory contains names with 14
-   characters on average we can compute an estimated number of entries
-   which fit in the buffer.  Taking this number allows us to specify a
-   reasonable number of bytes to read.  If we should be wrong, we can
-   reset the file descriptor.  In practice the kernel is limiting the
-   amount of data returned much more then the reduced buffer size.  */
+/* Pack the dirent64 struct down into 32-bit offset/inode fields, and
+   ensure that no overflow occurs.  */
 ssize_t
-__GETDENTS (int fd, char *buf, size_t nbytes)
+__getdents (int fd, char *buf, size_t nbytes)
 {
+  union
+  {
+    struct dirent64 k;  /* Kernel structure.  */
+    struct dirent u;
+    char b[1];
+  } *kbuf = (void *) buf, *outp, *inp;
+  size_t kbytes = nbytes;
+  off64_t last_offset = -1;
   ssize_t retval;
 
-  /* The d_ino and d_off fields in kernel_dirent and dirent must have
-     the same sizes and alignments.  */
-  if (sizeof (DIRENT_TYPE) == sizeof (struct dirent)
-      && (sizeof (((struct kernel_dirent *) 0)->d_ino)
-	  == sizeof (((struct dirent *) 0)->d_ino))
-      && (sizeof (((struct kernel_dirent *) 0)->d_off)
-	  == sizeof (((struct dirent *) 0)->d_off))
-      && (offsetof (struct kernel_dirent, d_off)
-	  == offsetof (struct dirent, d_off))
-      && (offsetof (struct kernel_dirent, d_reclen)
-	  == offsetof (struct dirent, d_reclen)))
-    {
-      retval = INLINE_SYSCALL (getdents, 3, fd, buf, nbytes);
+# define size_diff (offsetof (struct dirent64, d_name) \
+		    - offsetof (struct dirent, d_name))
+  char kbuftmp[sizeof (struct dirent) + size_diff];
+  if (nbytes <= sizeof (struct dirent))
+    kbuf = (void*) kbuftmp;
 
-      /* The kernel added the d_type value after the name.  Change
-	 this now.  */
-      if (retval != -1)
-	{
-	  union
-	  {
-	    struct kernel_dirent k;
-	    struct dirent u;
-	  } *kbuf = (void *) buf;
+  retval = INLINE_SYSCALL_CALL (getdents64, fd, kbuf, kbytes);
+  if (retval == -1)
+    return -1;
 
-	  while ((char *) kbuf < buf + retval)
-	    {
-	      char d_type = *((char *) kbuf + kbuf->k.d_reclen - 1);
-	      memmove (kbuf->u.d_name, kbuf->k.d_name,
-		       strlen (kbuf->k.d_name) + 1);
-	      kbuf->u.d_type = d_type;
+  /* 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.  */
+  inp = kbuf;
+  outp = (void *) buf;
 
-	      kbuf = (void *) ((char *) kbuf + kbuf->k.d_reclen);
-	    }
-	}
-
-      return retval;
-    }
-
-  off64_t last_offset = -1;
-
-#ifdef __NR_getdents64
-  {
-    union
+  while (&inp->b < &kbuf->b + retval)
     {
-      struct kernel_dirent64 k;
-      DIRENT_TYPE u;
-      char b[1];
-    } *kbuf = (void *) buf, *outp, *inp;
-    size_t kbytes = nbytes;
-    if (offsetof (DIRENT_TYPE, d_name)
-	< offsetof (struct kernel_dirent64, d_name)
-	&& nbytes <= sizeof (DIRENT_TYPE))
-      {
-	kbytes = (nbytes + offsetof (struct kernel_dirent64, d_name)
-		  - offsetof (DIRENT_TYPE, d_name));
-	kbuf = __alloca(kbytes);
-      }
-    retval = INLINE_SYSCALL (getdents64, 3, fd, kbuf, kbytes);
-    const size_t size_diff = (offsetof (struct kernel_dirent64, d_name)
-			      - offsetof (DIRENT_TYPE, d_name));
-
-    /* Return the error if encountered.  */
-    if (retval == -1)
-      return -1;
-
-    /* If the structure returned by the kernel is identical to what we
-       need, don't do any conversions.  */
-    if (offsetof (DIRENT_TYPE, d_name)
-	== offsetof (struct kernel_dirent64, d_name)
-	&& sizeof (outp->u.d_ino) == sizeof (inp->k.d_ino)
-	&& sizeof (outp->u.d_off) == sizeof (inp->k.d_off))
-      return retval;
-
-    /* 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.  */
-    inp = kbuf;
-    outp = (void *) buf;
-
-    while (&inp->b < &kbuf->b + retval)
-      {
-	const size_t alignment = __alignof__ (DIRENT_TYPE);
-	/* Since inp->k.d_reclen is already aligned for the kernel
-	   structure this may compute a value that is bigger
-	   than necessary.  */
-	size_t old_reclen = inp->k.d_reclen;
-	size_t new_reclen = ((old_reclen - size_diff + alignment - 1)
-			     & ~(alignment - 1));
-
-	/* Copy the data out of the old structure into temporary space.
-	   Then copy the name, which may overlap if BUF == KBUF.  */
-	const uint64_t d_ino = inp->k.d_ino;
-	const int64_t d_off = inp->k.d_off;
-	const uint8_t d_type = inp->k.d_type;
-
-	memmove (outp->u.d_name, inp->k.d_name,
-		 old_reclen - offsetof (struct kernel_dirent64, d_name));
-
-	/* Now we have copied the data from INP and access only OUTP.  */
-
-	DIRENT_SET_DP_INO (&outp->u, d_ino);
-	outp->u.d_off = d_off;
-	if ((sizeof (outp->u.d_ino) != sizeof (inp->k.d_ino)
-	     && outp->u.d_ino != d_ino)
-	    || (sizeof (outp->u.d_off) != sizeof (inp->k.d_off)
-		&& outp->u.d_off != d_off))
-	  {
-	    /* Overflow.  If there was at least one entry
-	       before this one, return them without error,
-	       otherwise signal overflow.  */
-	    if (last_offset != -1)
-	      {
-		__lseek64 (fd, last_offset, SEEK_SET);
-		return outp->b - buf;
-	      }
-	    __set_errno (EOVERFLOW);
-	    return -1;
-	  }
-
-	last_offset = d_off;
-	outp->u.d_reclen = new_reclen;
-	outp->u.d_type = d_type;
-
-	inp = (void *) inp + old_reclen;
-	outp = (void *) outp + new_reclen;
-      }
-
-    return outp->b - buf;
-  }
-#endif
-  {
-    size_t red_nbytes;
-    struct kernel_dirent *skdp, *kdp;
-    const size_t size_diff = (offsetof (DIRENT_TYPE, d_name)
-			      - offsetof (struct kernel_dirent, d_name));
-
-    red_nbytes = MIN (nbytes
-		      - ((nbytes / (offsetof (DIRENT_TYPE, d_name) + 14))
-			 * size_diff),
-		      nbytes - size_diff);
-
-    skdp = kdp = __alloca (red_nbytes);
-
-    retval = INLINE_SYSCALL (getdents, 3, fd, (char *) kdp, red_nbytes);
-
-    if (retval == -1)
-      return -1;
-
-    DIRENT_TYPE *dp = (DIRENT_TYPE *) buf;
-    while ((char *) kdp < (char *) skdp + retval)
-      {
-	const size_t alignment = __alignof__ (DIRENT_TYPE);
-	/* Since kdp->d_reclen is already aligned for the kernel structure
-	   this may compute a value that is bigger than necessary.  */
-	size_t new_reclen = ((kdp->d_reclen + size_diff + alignment - 1)
-			     & ~(alignment - 1));
-	if ((char *) dp + new_reclen > buf + nbytes)
-	  {
-	    /* Our heuristic failed.  We read too many entries.  Reset
-	       the stream.  */
-	    assert (last_offset != -1);
-	    __lseek64 (fd, last_offset, SEEK_SET);
-
-	    if ((char *) dp == buf)
-	      {
-		/* The buffer the user passed in is too small to hold even
-		   one entry.  */
-		__set_errno (EINVAL);
-		return -1;
-	      }
-
-	    break;
-	  }
+      const size_t alignment = __alignof__ (struct dirent);
+      /* Since inp->k.d_reclen is already aligned for the kernel
+         structure this may compute a value that is bigger
+         than necessary.  */
+      size_t old_reclen = inp->k.d_reclen;
+      size_t new_reclen = ((old_reclen - size_diff + alignment - 1)
+                           & ~(alignment - 1));
+
+      /* Copy the data out of the old structure into temporary space.
+         Then copy the name, which may overlap if BUF == KBUF.  */
+      const uint64_t d_ino = inp->k.d_ino;
+      const int64_t d_off = inp->k.d_off;
+      const uint8_t d_type = inp->k.d_type;
+
+      memmove (outp->u.d_name, inp->k.d_name,
+               old_reclen - offsetof (struct dirent64, d_name));
+
+      /* Now we have copied the data from INP and access only OUTP.  */
+
+      DIRENT_SET_DP_INO (&outp->u, d_ino);
+      outp->u.d_off = d_off;
+      if ((sizeof (outp->u.d_ino) != sizeof (inp->k.d_ino)
+           && outp->u.d_ino != d_ino)
+          || (sizeof (outp->u.d_off) != sizeof (inp->k.d_off)
+              && outp->u.d_off != d_off))
+        {
+          /* Overflow.  If there was at least one entry before this one,
+             return them without error, otherwise signal overflow.  */
+          if (last_offset != -1)
+            {
+              __lseek64 (fd, last_offset, SEEK_SET);
+              return outp->b - buf;
+            }
+          __set_errno (EOVERFLOW);
+          return -1;
+        }
+
+      last_offset = d_off;
+      outp->u.d_reclen = new_reclen;
+      outp->u.d_type = d_type;
+
+      inp = (void *) inp + old_reclen;
+      outp = (void *) outp + new_reclen;
+    }
 
-	last_offset = kdp->d_off;
-	DIRENT_SET_DP_INO(dp, kdp->d_ino);
-	dp->d_off = kdp->d_off;
-	dp->d_reclen = new_reclen;
-	dp->d_type = *((char *) kdp + kdp->d_reclen - 1);
-	memcpy (dp->d_name, kdp->d_name,
-		kdp->d_reclen - offsetof (struct kernel_dirent, d_name));
+  return outp->b - buf;
+}
 
-	dp = (DIRENT_TYPE *) ((char *) dp + new_reclen);
-	kdp = (struct kernel_dirent *) (((char *) kdp) + kdp->d_reclen);
-      }
+# undef DIRENT_SET_DP_INO
 
-    return (char *) dp - buf;
-  }
-}
+#endif /* _DIRENT_MATCHES_DIRENT64  */
diff --git a/sysdeps/unix/sysv/linux/getdents64.c b/sysdeps/unix/sysv/linux/getdents64.c
index 805917e..f37fe15 100644
--- a/sysdeps/unix/sysv/linux/getdents64.c
+++ b/sysdeps/unix/sysv/linux/getdents64.c
@@ -1,3 +1,77 @@
-#define __GETDENTS __getdents64
-#define DIRENT_TYPE struct dirent64
-#include <sysdeps/unix/sysv/linux/getdents.c>
+/* Get directory entries.  Linux LFS version.
+   Copyright (C) 1997-2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+
+/* The kernel struct linux_dirent64 matches the 'struct getdents64' type.  */
+ssize_t
+__getdents64 (int fd, char *buf, size_t nbytes)
+{
+  return INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes);
+}
+
+#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>
+
+/* kernel definition of as of 3.2.  */
+struct compat_linux_dirent
+{
+  /* Both d_ino and d_off are compat_ulong_t which are defined in all
+     architectures as 'u32'.  */
+  uint32_t        d_ino;
+  uint32_t        d_off;
+  unsigned short  d_reclen;
+  char            d_name[1];
+};
+
+ssize_t
+__old_getdents64 (int fd, char *buf, size_t nbytes)
+{
+  ssize_t retval = INLINE_SYSCALL_CALL (getdents, fd, buf, nbytes);
+
+  /* The kernel added the d_type value after the name.  Change this now.  */
+  if (retval != -1)
+    {
+      union
+      {
+	struct compat_linux_dirent k;
+	struct dirent u;
+      } *kbuf = (void *) buf;
+
+      while ((char *) kbuf < buf + retval)
+	{
+	  char d_type = *((char *) kbuf + kbuf->k.d_reclen - 1);
+	  memmove (kbuf->u.d_name, kbuf->k.d_name,
+		   strlen (kbuf->k.d_name) + 1);
+	  kbuf->u.d_type = d_type;
+
+	  kbuf = (void *) ((char *) kbuf + kbuf->k.d_reclen);
+	}
+     }
+  return retval;
+}
+# endif /* SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)  */
+#endif /* _DIRENT_MATCHES_DIRENT64  */
diff --git a/sysdeps/unix/sysv/linux/hppa/getdents64.c b/sysdeps/unix/sysv/linux/hppa/getdents64.c
deleted file mode 100644
index 0c75fb5..0000000
--- a/sysdeps/unix/sysv/linux/hppa/getdents64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/getdents64.c>
diff --git a/sysdeps/unix/sysv/linux/i386/getdents64.c b/sysdeps/unix/sysv/linux/i386/getdents64.c
deleted file mode 100644
index 0a2c194..0000000
--- a/sysdeps/unix/sysv/linux/i386/getdents64.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Copyright (C) 2000-2018 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
-   <http://www.gnu.org/licenses/>.  */
-
-#define __GETDENTS __getdents64
-#define DIRENT_TYPE struct dirent64
-
-#include <sysdeps/unix/sysv/linux/getdents.c>
-
-#include <shlib-compat.h>
-
-#undef __READDIR
-#undef __GETDENTS
-#undef DIRENT_TYPE
-
-#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-
-#include <olddirent.h>
-
-#define __GETDENTS __old_getdents64
-#define DIRENT_TYPE struct __old_dirent64
-#define kernel_dirent old_kernel_dirent
-#define kernel_dirent64 old_kernel_dirent64
-
-#include <sysdeps/unix/sysv/linux/getdents.c>
-#endif
diff --git a/sysdeps/unix/sysv/linux/m68k/getdents64.c b/sysdeps/unix/sysv/linux/m68k/getdents64.c
deleted file mode 100644
index 0c75fb5..0000000
--- a/sysdeps/unix/sysv/linux/m68k/getdents64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/getdents64.c>
diff --git a/sysdeps/unix/sysv/linux/powerpc/getdents64.c b/sysdeps/unix/sysv/linux/powerpc/getdents64.c
deleted file mode 100644
index 0c75fb5..0000000
--- a/sysdeps/unix/sysv/linux/powerpc/getdents64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/getdents64.c>
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/getdents64.c b/sysdeps/unix/sysv/linux/s390/s390-32/getdents64.c
deleted file mode 100644
index 0c75fb5..0000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getdents64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/getdents64.c>
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/getdents64.c b/sysdeps/unix/sysv/linux/sparc/sparc32/getdents64.c
deleted file mode 100644
index 0c75fb5..0000000
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/getdents64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/getdents64.c>
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c b/sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c
index c54d301..6838a77 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c
@@ -90,12 +90,12 @@ __get_clockfreq_via_proc_openprom (void)
   if (obp_fd != -1)
     {
       unsigned long int buf[4096 / sizeof (unsigned long int)];
-      struct dirent *dirp = (struct dirent *) buf;
+      struct dirent64 *dirp = (struct dirent64 *) buf;
       ssize_t len;
 
-      while ((len = __getdents (obp_fd, (char *) dirp, sizeof (buf))) > 0)
+      while ((len = __getdents64 (obp_fd, (char *) dirp, sizeof (buf))) > 0)
 	{
-	  struct dirent *this_dirp = dirp;
+	  struct dirent64 *this_dirp = dirp;
 
 	  while (len > 0)
 	    {
@@ -140,7 +140,7 @@ __get_clockfreq_via_proc_openprom (void)
 		break;
 
 	      len -= this_dirp->d_reclen;
-	      this_dirp = (struct dirent *)
+	      this_dirp = (struct dirent64 *)
 		((char *) this_dirp + this_dirp->d_reclen);
 	    }
 	  if (result != 0)
diff --git a/sysdeps/unix/sysv/linux/wordsize-64/getdents.c b/sysdeps/unix/sysv/linux/wordsize-64/getdents.c
deleted file mode 100644
index 5ea4c57..0000000
--- a/sysdeps/unix/sysv/linux/wordsize-64/getdents.c
+++ /dev/null
@@ -1,4 +0,0 @@
-#define __getdents64 __no___getdents64_decl
-#include <sysdeps/unix/sysv/linux/getdents.c>
-#undef __getdents64
-weak_alias (__getdents, __getdents64);
diff --git a/sysdeps/unix/sysv/linux/wordsize-64/getdents64.c b/sysdeps/unix/sysv/linux/wordsize-64/getdents64.c
deleted file mode 100644
index 0df2c8f..0000000
--- a/sysdeps/unix/sysv/linux/wordsize-64/getdents64.c
+++ /dev/null
@@ -1 +0,0 @@
-/* getdents64 is in getdents.c */
-- 
2.7.4

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 2/7] Define _DIRENT_MATCHES_DIRENT64 regardless
  2018-03-02 18:59 [PATCH 1/7] Assume O_DIRECTORY for opendir Adhemerval Zanella
@ 2018-03-02 18:59 ` Adhemerval Zanella
  2018-03-02 19:30   ` Andreas Schwab
  2018-03-02 18:59 ` [PATCH 3/7] Consolidate Linux readdir{64}{_r} implementation Adhemerval Zanella
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 21+ messages in thread
From: Adhemerval Zanella @ 2018-03-02 18:59 UTC (permalink / raw)
  To: libc-alpha

This patch defines _DIRENT_MATCHES_DIRENT64 to either 0 or 1 and adjust its
usage from checking its definition to its value.

Checked on a build for major Linux abis.

	* bits/dirent.h (__INO_T_MATCHES_INO64_T): Define regardless whether
	__INO_T_MATCHES_INO64_T is defined.
	* sysdeps/unix/sysv/linux/bits/dirent.h: Likewise.
	* dirent/alphasort.c: Check _DIRENT_MATCHES_DIRENT64 value instead
	of definition.
	* dirent/alphasort64.c: Likewise.
	* dirent/scandir.c: Likewise.
	* dirent/scandir64-tail.c: Likewise.
	* dirent/scandir64.c: Likewise.
	* dirent/scandirat.c: Likewise.
	* dirent/scandirat64.c: Likewise.
	* dirent/versionsort.c: Likewise.
	* dirent/versionsort64.c: Likewise.
	* include/dirent.h: Likewise.
---
 ChangeLog                             | 15 +++++++++++++++
 bits/dirent.h                         |  2 ++
 dirent/alphasort.c                    |  2 +-
 dirent/alphasort64.c                  |  2 +-
 dirent/scandir.c                      |  2 +-
 dirent/scandir64-tail.c               |  2 +-
 dirent/scandir64.c                    |  2 +-
 dirent/scandirat.c                    |  2 +-
 dirent/scandirat64.c                  |  2 +-
 dirent/versionsort.c                  |  2 +-
 dirent/versionsort64.c                |  2 +-
 include/dirent.h                      |  2 +-
 sysdeps/unix/sysv/linux/bits/dirent.h |  2 ++
 13 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/bits/dirent.h b/bits/dirent.h
index 8c38b8c..d775540 100644
--- a/bits/dirent.h
+++ b/bits/dirent.h
@@ -56,4 +56,6 @@ struct dirent64
 #ifdef __INO_T_MATCHES_INO64_T
 /* Inform libc code that these two types are effectively identical.  */
 # define _DIRENT_MATCHES_DIRENT64	1
+#else
+# define _DIRENT_MATCHES_DIRENT64	0
 #endif
diff --git a/dirent/alphasort.c b/dirent/alphasort.c
index 8d3b939..a6cd151 100644
--- a/dirent/alphasort.c
+++ b/dirent/alphasort.c
@@ -32,6 +32,6 @@ alphasort (const struct dirent **a, const struct dirent **b)
   return strcoll ((*a)->d_name, (*b)->d_name);
 }
 
-#ifdef _DIRENT_MATCHES_DIRENT64
+#if _DIRENT_MATCHES_DIRENT64
 weak_alias (alphasort, alphasort64)
 #endif
diff --git a/dirent/alphasort64.c b/dirent/alphasort64.c
index deb1921..3a47a97 100644
--- a/dirent/alphasort64.c
+++ b/dirent/alphasort64.c
@@ -19,7 +19,7 @@
 #include <string.h>
 
 /* alphasort.c defines alphasort64 as an alias if _DIRENT_MATCHES_DIRENT64.  */
-#ifndef _DIRENT_MATCHES_DIRENT64
+#if !_DIRENT_MATCHES_DIRENT64
 
 int
 alphasort64 (const struct dirent64 **a, const struct dirent64 **b)
diff --git a/dirent/scandir.c b/dirent/scandir.c
index 977d645..b24e157 100644
--- a/dirent/scandir.c
+++ b/dirent/scandir.c
@@ -40,6 +40,6 @@ SCANDIR (const char *dir,
   return SCANDIR_TAIL (__opendir (dir), namelist, select, cmp);
 }
 
-#ifdef _DIRENT_MATCHES_DIRENT64
+#if _DIRENT_MATCHES_DIRENT64
 weak_alias (scandir, scandir64)
 #endif
diff --git a/dirent/scandir64-tail.c b/dirent/scandir64-tail.c
index 684088c..8d5cc07 100644
--- a/dirent/scandir64-tail.c
+++ b/dirent/scandir64-tail.c
@@ -18,7 +18,7 @@
 
 #include <dirent.h>
 
-#ifndef _DIRENT_MATCHES_DIRENT64
+#if !_DIRENT_MATCHES_DIRENT64
 # define SCANDIR_TAIL   __scandir64_tail
 # define READDIR        __readdir64
 # define DIRENT_TYPE    struct dirent64
diff --git a/dirent/scandir64.c b/dirent/scandir64.c
index 7e666b0..0c63fa9 100644
--- a/dirent/scandir64.c
+++ b/dirent/scandir64.c
@@ -18,7 +18,7 @@
 #include <dirent.h>
 
 /* scandir.c defines scandir64 as an alias if _DIRENT_MATCHES_DIRENT64.  */
-#ifndef _DIRENT_MATCHES_DIRENT64
+#if !_DIRENT_MATCHES_DIRENT64
 
 # define SCANDIR        scandir64
 # define SCANDIR_TAIL   __scandir64_tail
diff --git a/dirent/scandirat.c b/dirent/scandirat.c
index 3f63f4d..96a1b0e 100644
--- a/dirent/scandirat.c
+++ b/dirent/scandirat.c
@@ -44,6 +44,6 @@ libc_hidden_def (SCANDIRAT)
 weak_alias (__scandirat, scandirat)
 #endif
 
-#ifdef _DIRENT_MATCHES_DIRENT64
+#if _DIRENT_MATCHES_DIRENT64
 weak_alias (scandirat, scandirat64)
 #endif
diff --git a/dirent/scandirat64.c b/dirent/scandirat64.c
index 6d682ff..520ae7c 100644
--- a/dirent/scandirat64.c
+++ b/dirent/scandirat64.c
@@ -18,7 +18,7 @@
 #include <dirent.h>
 
 /* scandirat.c defines scandirat64 as an alias if _DIRENT_MATCHES_DIRENT64.  */
-#ifndef _DIRENT_MATCHES_DIRENT64
+#if !_DIRENT_MATCHES_DIRENT64
 
 # define SCANDIRAT      scandirat64
 # define SCANDIR_TAIL   __scandir64_tail
diff --git a/dirent/versionsort.c b/dirent/versionsort.c
index 0130138..5ec15e8 100644
--- a/dirent/versionsort.c
+++ b/dirent/versionsort.c
@@ -32,6 +32,6 @@ versionsort (const struct dirent **a, const struct dirent **b)
   return __strverscmp ((*a)->d_name, (*b)->d_name);
 }
 
-#ifdef _DIRENT_MATCHES_DIRENT64
+#if _DIRENT_MATCHES_DIRENT64
 weak_alias (versionsort, versionsort64)
 #endif
diff --git a/dirent/versionsort64.c b/dirent/versionsort64.c
index bfb0cbb..7689c26 100644
--- a/dirent/versionsort64.c
+++ b/dirent/versionsort64.c
@@ -19,7 +19,7 @@
 #include <string.h>
 
 /* versionsort.c defines a versionsort64 alias if _DIRENT_MATCHES_DIRENT64.  */
-#ifndef _DIRENT_MATCHES_DIRENT64
+#if !_DIRENT_MATCHES_DIRENT64
 
 int
 versionsort64 (const struct dirent64 **a, const struct dirent64 **b)
diff --git a/include/dirent.h b/include/dirent.h
index caaeb0b..cc8f189 100644
--- a/include/dirent.h
+++ b/include/dirent.h
@@ -57,7 +57,7 @@ extern int __scandir_tail (DIR *dp,
 			   int (*cmp) (const struct dirent **,
 				       const struct dirent **))
   attribute_hidden;
-#  ifdef _DIRENT_MATCHES_DIRENT64
+#  if _DIRENT_MATCHES_DIRENT64
 #   define __scandir64_tail (dp, namelist, select, cmp)         \
   __scandir_tail (dp, (struct dirent ***) (namelist),           \
 		  (int (*) (const struct dirent *)) (select),   \
diff --git a/sysdeps/unix/sysv/linux/bits/dirent.h b/sysdeps/unix/sysv/linux/bits/dirent.h
index 2ed7919..f312720 100644
--- a/sysdeps/unix/sysv/linux/bits/dirent.h
+++ b/sysdeps/unix/sysv/linux/bits/dirent.h
@@ -54,4 +54,6 @@ struct dirent64
 #if defined __OFF_T_MATCHES_OFF64_T && defined __INO_T_MATCHES_INO64_T
 /* Inform libc code that these two types are effectively identical.  */
 # define _DIRENT_MATCHES_DIRENT64	1
+#else
+# define _DIRENT_MATCHES_DIRENT64	0
 #endif
-- 
2.7.4

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 2/7] Define _DIRENT_MATCHES_DIRENT64 regardless
  2018-03-02 18:59 ` [PATCH 2/7] Define _DIRENT_MATCHES_DIRENT64 regardless Adhemerval Zanella
@ 2018-03-02 19:30   ` Andreas Schwab
  0 siblings, 0 replies; 21+ messages in thread
From: Andreas Schwab @ 2018-03-02 19:30 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

On Mär 02 2018, Adhemerval Zanella <adhemerval.zanella@linaro.org> wrote:

> 	* bits/dirent.h (__INO_T_MATCHES_INO64_T): Define regardless whether
> 	__INO_T_MATCHES_INO64_T is defined.
> 	* sysdeps/unix/sysv/linux/bits/dirent.h: Likewise.
> 	* dirent/alphasort.c: Check _DIRENT_MATCHES_DIRENT64 value instead
> 	of definition.
> 	* dirent/alphasort64.c: Likewise.
> 	* dirent/scandir.c: Likewise.
> 	* dirent/scandir64-tail.c: Likewise.
> 	* dirent/scandir64.c: Likewise.
> 	* dirent/scandirat.c: Likewise.
> 	* dirent/scandirat64.c: Likewise.
> 	* dirent/versionsort.c: Likewise.
> 	* dirent/versionsort64.c: Likewise.
> 	* include/dirent.h: Likewise.

Ok.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 6/7] Consolidate alphasort{64} and versionsort{64} implementation
  2018-03-02 18:59 ` [PATCH 6/7] Consolidate alphasort{64} and versionsort{64} implementation Adhemerval Zanella
@ 2018-03-02 20:33   ` Joseph Myers
  2018-03-06 11:28     ` Adhemerval Zanella
  2018-04-23 18:01   ` Adhemerval Zanella
  1 sibling, 1 reply; 21+ messages in thread
From: Joseph Myers @ 2018-03-02 20:33 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

On Fri, 2 Mar 2018, Adhemerval Zanella wrote:

> Also on Linux the compat symbol for old non-LFS dirent64 definition
> requires a platform-specific scandir64.c.  For powerpc32 and sparcv9
> it requires to add specific arch-implementation to override the
> generic Linux one because neither ABI exports an compat symbol for
> non-LFS alphasort64 and versionsort64 variant.  Considering both
> architectures do export other compat symbols for other dirent.h
> functions I think this is a bug (I need confirmation).

If it is a bug, it's also not one that can be fixed (in that there would 
be existing binaries expecting both meanings of that symbol at its single 
existing version, with binaries expecting the new meaning probably much 
more common than those expecting the original meaning of that symbol at 
that version).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 6/7] Consolidate alphasort{64} and versionsort{64} implementation
  2018-03-02 20:33   ` Joseph Myers
@ 2018-03-06 11:28     ` Adhemerval Zanella
  0 siblings, 0 replies; 21+ messages in thread
From: Adhemerval Zanella @ 2018-03-06 11:28 UTC (permalink / raw)
  To: Joseph Myers; +Cc: libc-alpha



On 02/03/2018 17:33, Joseph Myers wrote:
> On Fri, 2 Mar 2018, Adhemerval Zanella wrote:
> 
>> Also on Linux the compat symbol for old non-LFS dirent64 definition
>> requires a platform-specific scandir64.c.  For powerpc32 and sparcv9
>> it requires to add specific arch-implementation to override the
>> generic Linux one because neither ABI exports an compat symbol for
>> non-LFS alphasort64 and versionsort64 variant.  Considering both
>> architectures do export other compat symbols for other dirent.h
>> functions I think this is a bug (I need confirmation).
> 
> If it is a bug, it's also not one that can be fixed (in that there would 
> be existing binaries expecting both meanings of that symbol at its single 
> existing version, with binaries expecting the new meaning probably much 
> more common than those expecting the original meaning of that symbol at 
> that version).
> 

Right, so I think this initial approach of keep current symbol versioning
is the correct one.  I will add your remark in commit message.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 4/7] Consolidate Linux getdents{64} implementation
  2018-03-02 18:59 ` [PATCH 4/7] Consolidate Linux getdents{64} implementation Adhemerval Zanella
@ 2018-03-09 18:10   ` Adhemerval Zanella
  2018-04-17 19:42     ` Adhemerval Zanella
  0 siblings, 1 reply; 21+ messages in thread
From: Adhemerval Zanella @ 2018-03-09 18:10 UTC (permalink / raw)
  To: libc-alpha



On 02/03/2018 15:59, Adhemerval Zanella wrote:
> This patch consolidates Linux getdents{64} implementation on just
> the default sysdeps/unix/sysv/linux/getdents{64}{_r}.c ones.
> 
> Although this symbol is used only internally, the non-LFS version
> still need to be build due the non-LFS getdirentries which requires
> its semantic.
> 
> The non-LFS default implementation now uses the wordsize-32 as base
> which uses getdents64 syscall plus adjustment for overflow (it allows
> to use the same code for architectures that does not support non-LFS
> getdents syscall).  It has two main differences to wordsize-32 one:
> 
>   - DIRENT_SET_DP_INO is added to handle alpha requirement to zero
>     the padding.
> 
>   - alloca is removed by allocating a bounded temporary buffer (it
>     increases stack usage by roughly 276 bytes).
> 
> The default implementation handle the Linux requirements:
> 
>   * getdents is only built for _DIRENT_MATCHES_DIRENT64 being 0.
> 
>   * getdents64 is always built and aliased to getdents for ABIs
>     that define _DIRENT_MATCHES_DIRENT64 to 1.
> 
>   * A compat symbol is added for getdents64 for ABI that used to
>     export the old non-LFS version.
> 
> Checked on aarch64-linux-gnu, x86_64-linux-gnu, i686-linux-gnu,
> sparcv9-linux-gnu, sparc64-linux-gnu, powerpc-linux-gnu, and
> powerpc64le-linux-gnu.

Unfortunately MIPS n64 only wire up getdents64 on Linux 3.10, so we
still need to use the non-LFS one and adjust the buffer for the
ABI.  Below it is an updated patch for mips which first tried
getdents64 and if it fails fallbacks to old syscall.  I did a sniff
test on a qemu-system mips64 with dirent tests and saw no regressions.

---

	* sysdeps/unix/sysv/linux/alpha/getdents.c: Add comments with alpha
	requirements.
	 (_DIRENT_MATCHES_DIRENT64): Undef
	* sysdeps/unix/sysv/linux/alpha/getdents64.c: Likewise.
	* sysdeps/unix/sysv/linux/arm/getdents64.c: Remove file.
	* sysdeps/unix/sysv/linux/generic/getdents.c: Likewise.
	* sysdeps/unix/sysv/linux/generic/getdents64.c: Likewise.
	* sysdeps/unix/sysv/linux/generic/wordsize-32/getdents.c: Likewise.
	* sysdeps/unix/sysv/linux/getdents.c: Simplify implementation by
	use getdents64 syscalls as base.
	* sysdeps/unix/sysv/linux/getdents64.c: Likewise and add compatibility
	symbol if required.
	* sysdeps/unix/sysv/linux/hppa/getdents64.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/getdents64.c: Likewise.
	* sysdeps/unix/sysv/linux/m68k/getdents64.c: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/getdents64.c: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/getdents64.c: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/getdents64.c: Likewise.
	* sysdeps/unix/sysv/linux/wordsize-64/getdents.c: Likewise.
	* sysdeps/unix/sysv/linux/wordsize-64/getdents64.c: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c
	(__get_clockfreq_via_proc_openprom): Use __getdents64.
	* sysdeps/unix/sysv/linux/mips/mips64/getdents64.c: New file.

---

diff --git a/sysdeps/unix/sysv/linux/alpha/getdents.c b/sysdeps/unix/sysv/linux/alpha/getdents.c
index dfecfef..64ccf86 100644
--- a/sysdeps/unix/sysv/linux/alpha/getdents.c
+++ b/sysdeps/unix/sysv/linux/alpha/getdents.c
@@ -1,3 +1,11 @@
+/* Although Alpha defines _DIRENT_MATCHES_DIRENT64, 'struct dirent' and
+   'struct dirent64' have slight different internal layout with d_ino
+   being a __ino_t on non-LFS version with an extra __pad field which should
+   be zeroed.  */
+
+#include <dirent.h>
+#undef _DIRENT_MATCHES_DIRENT64
+#define _DIRENT_MATCHES_DIRENT64 0
 #define DIRENT_SET_DP_INO(dp, value) \
   do { (dp)->d_ino = (value); (dp)->__pad = 0; } while (0)
 #include <sysdeps/unix/sysv/linux/getdents.c>
diff --git a/sysdeps/unix/sysv/linux/alpha/getdents64.c b/sysdeps/unix/sysv/linux/alpha/getdents64.c
index 50f1368..53cf93c 100644
--- a/sysdeps/unix/sysv/linux/alpha/getdents64.c
+++ b/sysdeps/unix/sysv/linux/alpha/getdents64.c
@@ -1 +1,10 @@
+/* Although Alpha defines _DIRENT_MATCHES_DIRENT64, 'struct dirent' and
+   'struct dirent64' have slight different internal layout with d_ino
+   being a __ino_t on non-LFS version with an extra __pad field which should
+   be zeroed.  */
+
+#include <dirent.h>
+/* It suppress the __getdents64 to __getdents alias.  */
+#undef _DIRENT_MATCHES_DIRENT64
+#define _DIRENT_MATCHES_DIRENT64 0
 #include <sysdeps/unix/sysv/linux/getdents64.c>
diff --git a/sysdeps/unix/sysv/linux/arm/getdents64.c b/sysdeps/unix/sysv/linux/arm/getdents64.c
deleted file mode 100644
index 0c75fb5..0000000
--- a/sysdeps/unix/sysv/linux/arm/getdents64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/getdents64.c>
diff --git a/sysdeps/unix/sysv/linux/generic/getdents.c b/sysdeps/unix/sysv/linux/generic/getdents.c
deleted file mode 100644
index 14dbbc7..0000000
--- a/sysdeps/unix/sysv/linux/generic/getdents.c
+++ /dev/null
@@ -1 +0,0 @@
-/* Defined in getdents64.c */
diff --git a/sysdeps/unix/sysv/linux/generic/getdents64.c b/sysdeps/unix/sysv/linux/generic/getdents64.c
deleted file mode 100644
index 0f876b8..0000000
--- a/sysdeps/unix/sysv/linux/generic/getdents64.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Copyright (C) 2011-2018 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
-
-   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
-   <http://www.gnu.org/licenses/>.  */
-
-#include <stddef.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <bits/wordsize.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-
-/* The kernel struct linux_dirent64 matches the 'struct getdents64' type.  */
-ssize_t
-__getdents64 (int fd, char *buf, size_t nbytes)
-{
-  return INLINE_SYSCALL (getdents64, 3, fd, buf, nbytes);
-}
-
-#if __WORDSIZE == 64
-strong_alias (__getdents64, __getdents)
-#endif
diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/getdents.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/getdents.c
deleted file mode 100644
index 7158fd1..0000000
--- a/sysdeps/unix/sysv/linux/generic/wordsize-32/getdents.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/* Copyright (C) 1993-2018 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Simplified from sysdeps/unix/sysv/linux/getdents.c.
-
-   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
-   <http://www.gnu.org/licenses/>.  */
-
-#include <alloca.h>
-#include <assert.h>
-#include <errno.h>
-#include <dirent.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <sys/types.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-
-/* Pack the dirent64 struct down into 32-bit offset/inode fields, and
-   ensure that no overflow occurs.  */
-ssize_t
-__getdents (int fd, char *buf, size_t nbytes)
-{
-  union
-  {
-    struct dirent64 k;  /* Kernel structure.  */
-    struct dirent u;
-    char b[1];
-  } *kbuf = (void *) buf, *outp, *inp;
-  size_t kbytes = nbytes;
-  off64_t last_offset = -1;
-  ssize_t retval;
-
-  const size_t size_diff = (offsetof (struct dirent64, d_name)
-                            - offsetof (struct dirent, d_name));
-  if (nbytes <= sizeof (struct dirent))
-    {
-      kbytes = nbytes + offsetof (struct dirent64, d_name)
-        - offsetof (struct dirent, d_name);
-      kbuf = __alloca(kbytes);
-    }
-
-  retval = INLINE_SYSCALL (getdents64, 3, fd, kbuf, kbytes);
-  if (retval == -1)
-    return -1;
-
-  /* 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.  */
-  inp = kbuf;
-  outp = (void *) buf;
-
-  while (&inp->b < &kbuf->b + retval)
-    {
-      const size_t alignment = __alignof__ (struct dirent);
-      /* Since inp->k.d_reclen is already aligned for the kernel
-         structure this may compute a value that is bigger
-         than necessary.  */
-      size_t old_reclen = inp->k.d_reclen;
-      size_t new_reclen = ((old_reclen - size_diff + alignment - 1)
-                           & ~(alignment - 1));
-
-      /* Copy the data out of the old structure into temporary space.
-         Then copy the name, which may overlap if BUF == KBUF.  */
-      const uint64_t d_ino = inp->k.d_ino;
-      const int64_t d_off = inp->k.d_off;
-      const uint8_t d_type = inp->k.d_type;
-
-      memmove (outp->u.d_name, inp->k.d_name,
-               old_reclen - offsetof (struct dirent64, d_name));
-
-      /* Now we have copied the data from INP and access only OUTP.  */
-
-      outp->u.d_ino = d_ino;
-      outp->u.d_off = d_off;
-      if ((sizeof (outp->u.d_ino) != sizeof (inp->k.d_ino)
-           && outp->u.d_ino != d_ino)
-          || (sizeof (outp->u.d_off) != sizeof (inp->k.d_off)
-              && outp->u.d_off != d_off))
-        {
-          /* Overflow.  If there was at least one entry before this one,
-             return them without error, otherwise signal overflow.  */
-          if (last_offset != -1)
-            {
-              __lseek64 (fd, last_offset, SEEK_SET);
-              return outp->b - buf;
-            }
-          __set_errno (EOVERFLOW);
-          return -1;
-        }
-
-      last_offset = d_off;
-      outp->u.d_reclen = new_reclen;
-      outp->u.d_type = d_type;
-
-      inp = (void *) inp + old_reclen;
-      outp = (void *) outp + new_reclen;
-    }
-
-  return outp->b - buf;
-}
diff --git a/sysdeps/unix/sysv/linux/getdents.c b/sysdeps/unix/sysv/linux/getdents.c
index 591ce67..4e52729 100644
--- a/sysdeps/unix/sysv/linux/getdents.c
+++ b/sysdeps/unix/sysv/linux/getdents.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1993-2018 Free Software Foundation, Inc.
+/* Get directory entries.  Linux no-LFS version.
+   Copyright (C) 1993-2018 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
@@ -12,260 +13,102 @@
    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
+   License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <alloca.h>
-#include <assert.h>
-#include <errno.h>
 #include <dirent.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <sys/types.h>
 
-#include <sysdep.h>
-#include <sys/syscall.h>
+#if !_DIRENT_MATCHES_DIRENT64
 
-#include <linux/posix_types.h>
+# include <unistd.h>
+# include <string.h>
+# include <errno.h>
 
-#include <kernel-features.h>
+# ifndef DIRENT_SET_DP_INO
+#  define DIRENT_SET_DP_INO(dp, value) (dp)->d_ino = (value)
+# endif
 
-/* For Linux we need a special version of this file since the
-   definition of `struct dirent' is not the same for the kernel and
-   the libc.  There is one additional field which might be introduced
-   in the kernel structure in the future.
-
-   Here is the kernel definition of `struct dirent' as of 2.1.20:  */
-
-struct kernel_dirent
-  {
-    long int d_ino;
-    __kernel_off_t d_off;
-    unsigned short int d_reclen;
-    char d_name[256];
-  };
-
-struct kernel_dirent64
-  {
-    uint64_t		d_ino;
-    int64_t		d_off;
-    unsigned short int	d_reclen;
-    unsigned char	d_type;
-    char		d_name[256];
-  };
-
-#ifndef __GETDENTS
-# define __GETDENTS __getdents
-#endif
-#ifndef DIRENT_TYPE
-# define DIRENT_TYPE struct dirent
-#endif
-#ifndef DIRENT_SET_DP_INO
-# define DIRENT_SET_DP_INO(dp, value) (dp)->d_ino = (value)
-#endif
-
-/* The problem here is that we cannot simply read the next NBYTES
-   bytes.  We need to take the additional field into account.  We use
-   some heuristic.  Assuming the directory contains names with 14
-   characters on average we can compute an estimated number of entries
-   which fit in the buffer.  Taking this number allows us to specify a
-   reasonable number of bytes to read.  If we should be wrong, we can
-   reset the file descriptor.  In practice the kernel is limiting the
-   amount of data returned much more then the reduced buffer size.  */
+/* Pack the dirent64 struct down into 32-bit offset/inode fields, and
+   ensure that no overflow occurs.  */
 ssize_t
-__GETDENTS (int fd, char *buf, size_t nbytes)
+__getdents (int fd, char *buf, size_t nbytes)
 {
+  union
+  {
+    struct dirent64 k;  /* Kernel structure.  */
+    struct dirent u;
+    char b[1];
+  } *kbuf = (void *) buf, *outp, *inp;
+  size_t kbytes = nbytes;
+  off64_t last_offset = -1;
   ssize_t retval;
 
-  /* The d_ino and d_off fields in kernel_dirent and dirent must have
-     the same sizes and alignments.  */
-  if (sizeof (DIRENT_TYPE) == sizeof (struct dirent)
-      && (sizeof (((struct kernel_dirent *) 0)->d_ino)
-	  == sizeof (((struct dirent *) 0)->d_ino))
-      && (sizeof (((struct kernel_dirent *) 0)->d_off)
-	  == sizeof (((struct dirent *) 0)->d_off))
-      && (offsetof (struct kernel_dirent, d_off)
-	  == offsetof (struct dirent, d_off))
-      && (offsetof (struct kernel_dirent, d_reclen)
-	  == offsetof (struct dirent, d_reclen)))
-    {
-      retval = INLINE_SYSCALL (getdents, 3, fd, buf, nbytes);
+# define size_diff (offsetof (struct dirent64, d_name) \
+		    - offsetof (struct dirent, d_name))
+  char kbuftmp[sizeof (struct dirent) + size_diff];
+  if (nbytes <= sizeof (struct dirent))
+    kbuf = (void*) kbuftmp;
 
-      /* The kernel added the d_type value after the name.  Change
-	 this now.  */
-      if (retval != -1)
-	{
-	  union
-	  {
-	    struct kernel_dirent k;
-	    struct dirent u;
-	  } *kbuf = (void *) buf;
+  retval = INLINE_SYSCALL_CALL (getdents64, fd, kbuf, kbytes);
+  if (retval == -1)
+    return -1;
 
-	  while ((char *) kbuf < buf + retval)
-	    {
-	      char d_type = *((char *) kbuf + kbuf->k.d_reclen - 1);
-	      memmove (kbuf->u.d_name, kbuf->k.d_name,
-		       strlen (kbuf->k.d_name) + 1);
-	      kbuf->u.d_type = d_type;
+  /* 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.  */
+  inp = kbuf;
+  outp = (void *) buf;
 
-	      kbuf = (void *) ((char *) kbuf + kbuf->k.d_reclen);
-	    }
-	}
-
-      return retval;
-    }
-
-  off64_t last_offset = -1;
-
-#ifdef __NR_getdents64
-  {
-    union
+  while (&inp->b < &kbuf->b + retval)
     {
-      struct kernel_dirent64 k;
-      DIRENT_TYPE u;
-      char b[1];
-    } *kbuf = (void *) buf, *outp, *inp;
-    size_t kbytes = nbytes;
-    if (offsetof (DIRENT_TYPE, d_name)
-	< offsetof (struct kernel_dirent64, d_name)
-	&& nbytes <= sizeof (DIRENT_TYPE))
-      {
-	kbytes = (nbytes + offsetof (struct kernel_dirent64, d_name)
-		  - offsetof (DIRENT_TYPE, d_name));
-	kbuf = __alloca(kbytes);
-      }
-    retval = INLINE_SYSCALL (getdents64, 3, fd, kbuf, kbytes);
-    const size_t size_diff = (offsetof (struct kernel_dirent64, d_name)
-			      - offsetof (DIRENT_TYPE, d_name));
-
-    /* Return the error if encountered.  */
-    if (retval == -1)
-      return -1;
-
-    /* If the structure returned by the kernel is identical to what we
-       need, don't do any conversions.  */
-    if (offsetof (DIRENT_TYPE, d_name)
-	== offsetof (struct kernel_dirent64, d_name)
-	&& sizeof (outp->u.d_ino) == sizeof (inp->k.d_ino)
-	&& sizeof (outp->u.d_off) == sizeof (inp->k.d_off))
-      return retval;
-
-    /* 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.  */
-    inp = kbuf;
-    outp = (void *) buf;
-
-    while (&inp->b < &kbuf->b + retval)
-      {
-	const size_t alignment = __alignof__ (DIRENT_TYPE);
-	/* Since inp->k.d_reclen is already aligned for the kernel
-	   structure this may compute a value that is bigger
-	   than necessary.  */
-	size_t old_reclen = inp->k.d_reclen;
-	size_t new_reclen = ((old_reclen - size_diff + alignment - 1)
-			     & ~(alignment - 1));
-
-	/* Copy the data out of the old structure into temporary space.
-	   Then copy the name, which may overlap if BUF == KBUF.  */
-	const uint64_t d_ino = inp->k.d_ino;
-	const int64_t d_off = inp->k.d_off;
-	const uint8_t d_type = inp->k.d_type;
-
-	memmove (outp->u.d_name, inp->k.d_name,
-		 old_reclen - offsetof (struct kernel_dirent64, d_name));
-
-	/* Now we have copied the data from INP and access only OUTP.  */
-
-	DIRENT_SET_DP_INO (&outp->u, d_ino);
-	outp->u.d_off = d_off;
-	if ((sizeof (outp->u.d_ino) != sizeof (inp->k.d_ino)
-	     && outp->u.d_ino != d_ino)
-	    || (sizeof (outp->u.d_off) != sizeof (inp->k.d_off)
-		&& outp->u.d_off != d_off))
-	  {
-	    /* Overflow.  If there was at least one entry
-	       before this one, return them without error,
-	       otherwise signal overflow.  */
-	    if (last_offset != -1)
-	      {
-		__lseek64 (fd, last_offset, SEEK_SET);
-		return outp->b - buf;
-	      }
-	    __set_errno (EOVERFLOW);
-	    return -1;
-	  }
-
-	last_offset = d_off;
-	outp->u.d_reclen = new_reclen;
-	outp->u.d_type = d_type;
-
-	inp = (void *) inp + old_reclen;
-	outp = (void *) outp + new_reclen;
-      }
-
-    return outp->b - buf;
-  }
-#endif
-  {
-    size_t red_nbytes;
-    struct kernel_dirent *skdp, *kdp;
-    const size_t size_diff = (offsetof (DIRENT_TYPE, d_name)
-			      - offsetof (struct kernel_dirent, d_name));
-
-    red_nbytes = MIN (nbytes
-		      - ((nbytes / (offsetof (DIRENT_TYPE, d_name) + 14))
-			 * size_diff),
-		      nbytes - size_diff);
-
-    skdp = kdp = __alloca (red_nbytes);
-
-    retval = INLINE_SYSCALL (getdents, 3, fd, (char *) kdp, red_nbytes);
-
-    if (retval == -1)
-      return -1;
-
-    DIRENT_TYPE *dp = (DIRENT_TYPE *) buf;
-    while ((char *) kdp < (char *) skdp + retval)
-      {
-	const size_t alignment = __alignof__ (DIRENT_TYPE);
-	/* Since kdp->d_reclen is already aligned for the kernel structure
-	   this may compute a value that is bigger than necessary.  */
-	size_t new_reclen = ((kdp->d_reclen + size_diff + alignment - 1)
-			     & ~(alignment - 1));
-	if ((char *) dp + new_reclen > buf + nbytes)
-	  {
-	    /* Our heuristic failed.  We read too many entries.  Reset
-	       the stream.  */
-	    assert (last_offset != -1);
-	    __lseek64 (fd, last_offset, SEEK_SET);
-
-	    if ((char *) dp == buf)
-	      {
-		/* The buffer the user passed in is too small to hold even
-		   one entry.  */
-		__set_errno (EINVAL);
-		return -1;
-	      }
-
-	    break;
-	  }
+      const size_t alignment = __alignof__ (struct dirent);
+      /* Since inp->k.d_reclen is already aligned for the kernel
+         structure this may compute a value that is bigger
+         than necessary.  */
+      size_t old_reclen = inp->k.d_reclen;
+      size_t new_reclen = ((old_reclen - size_diff + alignment - 1)
+                           & ~(alignment - 1));
+
+      /* Copy the data out of the old structure into temporary space.
+         Then copy the name, which may overlap if BUF == KBUF.  */
+      const uint64_t d_ino = inp->k.d_ino;
+      const int64_t d_off = inp->k.d_off;
+      const uint8_t d_type = inp->k.d_type;
+
+      memmove (outp->u.d_name, inp->k.d_name,
+               old_reclen - offsetof (struct dirent64, d_name));
+
+      /* Now we have copied the data from INP and access only OUTP.  */
+
+      DIRENT_SET_DP_INO (&outp->u, d_ino);
+      outp->u.d_off = d_off;
+      if ((sizeof (outp->u.d_ino) != sizeof (inp->k.d_ino)
+           && outp->u.d_ino != d_ino)
+          || (sizeof (outp->u.d_off) != sizeof (inp->k.d_off)
+              && outp->u.d_off != d_off))
+        {
+          /* Overflow.  If there was at least one entry before this one,
+             return them without error, otherwise signal overflow.  */
+          if (last_offset != -1)
+            {
+              __lseek64 (fd, last_offset, SEEK_SET);
+              return outp->b - buf;
+            }
+          __set_errno (EOVERFLOW);
+          return -1;
+        }
+
+      last_offset = d_off;
+      outp->u.d_reclen = new_reclen;
+      outp->u.d_type = d_type;
+
+      inp = (void *) inp + old_reclen;
+      outp = (void *) outp + new_reclen;
+    }
 
-	last_offset = kdp->d_off;
-	DIRENT_SET_DP_INO(dp, kdp->d_ino);
-	dp->d_off = kdp->d_off;
-	dp->d_reclen = new_reclen;
-	dp->d_type = *((char *) kdp + kdp->d_reclen - 1);
-	memcpy (dp->d_name, kdp->d_name,
-		kdp->d_reclen - offsetof (struct kernel_dirent, d_name));
+  return outp->b - buf;
+}
 
-	dp = (DIRENT_TYPE *) ((char *) dp + new_reclen);
-	kdp = (struct kernel_dirent *) (((char *) kdp) + kdp->d_reclen);
-      }
+# undef DIRENT_SET_DP_INO
 
-    return (char *) dp - buf;
-  }
-}
+#endif /* _DIRENT_MATCHES_DIRENT64  */
diff --git a/sysdeps/unix/sysv/linux/getdents64.c b/sysdeps/unix/sysv/linux/getdents64.c
index 805917e..f37fe15 100644
--- a/sysdeps/unix/sysv/linux/getdents64.c
+++ b/sysdeps/unix/sysv/linux/getdents64.c
@@ -1,3 +1,77 @@
-#define __GETDENTS __getdents64
-#define DIRENT_TYPE struct dirent64
-#include <sysdeps/unix/sysv/linux/getdents.c>
+/* Get directory entries.  Linux LFS version.
+   Copyright (C) 1997-2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+
+/* The kernel struct linux_dirent64 matches the 'struct getdents64' type.  */
+ssize_t
+__getdents64 (int fd, char *buf, size_t nbytes)
+{
+  return INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes);
+}
+
+#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>
+
+/* kernel definition of as of 3.2.  */
+struct compat_linux_dirent
+{
+  /* Both d_ino and d_off are compat_ulong_t which are defined in all
+     architectures as 'u32'.  */
+  uint32_t        d_ino;
+  uint32_t        d_off;
+  unsigned short  d_reclen;
+  char            d_name[1];
+};
+
+ssize_t
+__old_getdents64 (int fd, char *buf, size_t nbytes)
+{
+  ssize_t retval = INLINE_SYSCALL_CALL (getdents, fd, buf, nbytes);
+
+  /* The kernel added the d_type value after the name.  Change this now.  */
+  if (retval != -1)
+    {
+      union
+      {
+	struct compat_linux_dirent k;
+	struct dirent u;
+      } *kbuf = (void *) buf;
+
+      while ((char *) kbuf < buf + retval)
+	{
+	  char d_type = *((char *) kbuf + kbuf->k.d_reclen - 1);
+	  memmove (kbuf->u.d_name, kbuf->k.d_name,
+		   strlen (kbuf->k.d_name) + 1);
+	  kbuf->u.d_type = d_type;
+
+	  kbuf = (void *) ((char *) kbuf + kbuf->k.d_reclen);
+	}
+     }
+  return retval;
+}
+# endif /* SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)  */
+#endif /* _DIRENT_MATCHES_DIRENT64  */
diff --git a/sysdeps/unix/sysv/linux/hppa/getdents64.c b/sysdeps/unix/sysv/linux/hppa/getdents64.c
deleted file mode 100644
index 0c75fb5..0000000
--- a/sysdeps/unix/sysv/linux/hppa/getdents64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/getdents64.c>
diff --git a/sysdeps/unix/sysv/linux/i386/getdents64.c b/sysdeps/unix/sysv/linux/i386/getdents64.c
deleted file mode 100644
index 0a2c194..0000000
--- a/sysdeps/unix/sysv/linux/i386/getdents64.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Copyright (C) 2000-2018 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
-   <http://www.gnu.org/licenses/>.  */
-
-#define __GETDENTS __getdents64
-#define DIRENT_TYPE struct dirent64
-
-#include <sysdeps/unix/sysv/linux/getdents.c>
-
-#include <shlib-compat.h>
-
-#undef __READDIR
-#undef __GETDENTS
-#undef DIRENT_TYPE
-
-#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-
-#include <olddirent.h>
-
-#define __GETDENTS __old_getdents64
-#define DIRENT_TYPE struct __old_dirent64
-#define kernel_dirent old_kernel_dirent
-#define kernel_dirent64 old_kernel_dirent64
-
-#include <sysdeps/unix/sysv/linux/getdents.c>
-#endif
diff --git a/sysdeps/unix/sysv/linux/m68k/getdents64.c b/sysdeps/unix/sysv/linux/m68k/getdents64.c
deleted file mode 100644
index 0c75fb5..0000000
--- a/sysdeps/unix/sysv/linux/m68k/getdents64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/getdents64.c>
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/getdents64.c b/sysdeps/unix/sysv/linux/mips/mips64/getdents64.c
new file mode 100644
index 0000000..5b62791
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/mips64/getdents64.c
@@ -0,0 +1,113 @@
+/* Get directory entries.  Linux/MIPSn64 LFS version.
+   Copyright (C) 2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+#include <assert.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <scratch_buffer.h>
+
+ssize_t
+__getdents64 (int fd, char *buf, size_t nbytes)
+{
+  ssize_t ret;
+#ifdef __NR_getdents64
+  ret = INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes);
+  if (ret != -1)
+    return ret;
+#endif
+
+  /* Unfortunately getdents64 was only wire-up for MIPS n64 on Linux 3.10.
+     If syscall is not available it need to fallback to old one.  */
+
+  struct kernel_dirent
+    {
+      unsigned long d_ino;
+      unsigned long d_off;
+      unsigned short int d_reclen;
+      char d_name[256];
+    };
+
+  const size_t size_diff = (offsetof (struct dirent64, d_name)
+			   - offsetof (struct kernel_dirent, d_name));
+
+  size_t red_nbytes = MIN (nbytes
+			   - ((nbytes / (offsetof (struct dirent64, d_name)
+					 + 14)) * size_diff),
+			   nbytes - size_diff);
+
+  struct scratch_buffer tmpbuf;
+  scratch_buffer_init (&tmpbuf);
+  if (!scratch_buffer_set_array_size (&tmpbuf, red_nbytes, sizeof (uint8_t)))
+    INLINE_SYSCALL_ERROR_RETURN_VALUE (ENOMEM);
+
+  struct kernel_dirent *skdp, *kdp;
+  skdp = kdp = tmpbuf.data;
+
+  ssize_t retval = INLINE_SYSCALL_CALL (getdents, fd, kdp, red_nbytes);
+  if (retval == -1)
+    {
+      scratch_buffer_free (&tmpbuf);
+      return -1;
+    }
+
+  off64_t last_offset = -1;
+  struct dirent64 *dp = (struct dirent64 *) buf;
+  while ((char *) kdp < (char *) skdp + retval)
+    {
+      const size_t alignment = __alignof__ (struct dirent64);
+      /* Since kdp->d_reclen is already aligned for the kernel structure
+	 this may compute a value that is bigger than necessary.  */
+      size_t new_reclen = ((kdp->d_reclen + size_diff + alignment - 1)
+			   & ~(alignment - 1));
+      if ((char *) dp + new_reclen > buf + nbytes)
+        {
+	  /* Our heuristic failed.  We read too many entries.  Reset
+	     the stream.  */
+	  assert (last_offset != -1);
+	  __lseek64 (fd, last_offset, SEEK_SET);
+
+	  if ((char *) dp == buf)
+	    {
+	      scratch_buffer_free (&tmpbuf);
+	      INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+	    }
+
+	  break;
+	}
+
+      last_offset = kdp->d_off;
+      dp->d_ino = kdp->d_ino;
+      dp->d_off = kdp->d_off;
+      dp->d_reclen = new_reclen;
+      dp->d_type = *((char *) kdp + kdp->d_reclen - 1);
+      memcpy (dp->d_name, kdp->d_name,
+	      kdp->d_reclen - offsetof (struct kernel_dirent, d_name));
+
+      dp = (struct dirent64 *) ((char *) dp + new_reclen);
+      kdp = (struct kernel_dirent *) (((char *) kdp) + kdp->d_reclen);
+    }
+
+  scratch_buffer_free (&tmpbuf);
+  return (char *) dp - buf;
+}
+#if _DIRENT_MATCHES_DIRENT64
+strong_alias (__getdents64, __getdents)
+#endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/getdents64.c b/sysdeps/unix/sysv/linux/powerpc/getdents64.c
deleted file mode 100644
index 0c75fb5..0000000
--- a/sysdeps/unix/sysv/linux/powerpc/getdents64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/getdents64.c>
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/getdents64.c b/sysdeps/unix/sysv/linux/s390/s390-32/getdents64.c
deleted file mode 100644
index 0c75fb5..0000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getdents64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/getdents64.c>
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/getdents64.c b/sysdeps/unix/sysv/linux/sparc/sparc32/getdents64.c
deleted file mode 100644
index 0c75fb5..0000000
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/getdents64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/getdents64.c>
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c b/sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c
index c54d301..6838a77 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c
@@ -90,12 +90,12 @@ __get_clockfreq_via_proc_openprom (void)
   if (obp_fd != -1)
     {
       unsigned long int buf[4096 / sizeof (unsigned long int)];
-      struct dirent *dirp = (struct dirent *) buf;
+      struct dirent64 *dirp = (struct dirent64 *) buf;
       ssize_t len;
 
-      while ((len = __getdents (obp_fd, (char *) dirp, sizeof (buf))) > 0)
+      while ((len = __getdents64 (obp_fd, (char *) dirp, sizeof (buf))) > 0)
 	{
-	  struct dirent *this_dirp = dirp;
+	  struct dirent64 *this_dirp = dirp;
 
 	  while (len > 0)
 	    {
@@ -140,7 +140,7 @@ __get_clockfreq_via_proc_openprom (void)
 		break;
 
 	      len -= this_dirp->d_reclen;
-	      this_dirp = (struct dirent *)
+	      this_dirp = (struct dirent64 *)
 		((char *) this_dirp + this_dirp->d_reclen);
 	    }
 	  if (result != 0)
diff --git a/sysdeps/unix/sysv/linux/wordsize-64/getdents.c b/sysdeps/unix/sysv/linux/wordsize-64/getdents.c
deleted file mode 100644
index 5ea4c57..0000000
--- a/sysdeps/unix/sysv/linux/wordsize-64/getdents.c
+++ /dev/null
@@ -1,4 +0,0 @@
-#define __getdents64 __no___getdents64_decl
-#include <sysdeps/unix/sysv/linux/getdents.c>
-#undef __getdents64
-weak_alias (__getdents, __getdents64);
diff --git a/sysdeps/unix/sysv/linux/wordsize-64/getdents64.c b/sysdeps/unix/sysv/linux/wordsize-64/getdents64.c
deleted file mode 100644
index 0df2c8f..0000000
--- a/sysdeps/unix/sysv/linux/wordsize-64/getdents64.c
+++ /dev/null
@@ -1 +0,0 @@
-/* getdents64 is in getdents.c */
-- 
2.7.4

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/7] Assume O_DIRECTORY for opendir
  2018-03-02 18:59 [PATCH 1/7] Assume O_DIRECTORY for opendir Adhemerval Zanella
                   ` (5 preceding siblings ...)
  2018-03-02 18:59 ` [PATCH 5/7] Consolidate scandir{at}{64} implementation Adhemerval Zanella
@ 2018-04-02 13:59 ` Adhemerval Zanella
  6 siblings, 0 replies; 21+ messages in thread
From: Adhemerval Zanella @ 2018-04-02 13:59 UTC (permalink / raw)
  To: libc-alpha

On 02/03/2018 15:59, Adhemerval Zanella wrote:
> This patch assumes O_DIRECTORY works as defined by POSIX on opendir
> implementation (aligning with other glibc code, for instance pwd).  This
> allows remove both the fallback code to handle system with missing or
> broken O_DIRECTORY along with the Linux specific opendir.c which just
> advertise the working flag.
> 
> Checked on aarch64-linux-gnu, x86_64-linux-gnu, i686-linux-gnu,
> sparcv9-linux-gnu, sparc64-linux-gnu, powerpc-linux-gnu, and
> powerpc64le-linux-gnu.
> 
> 	* sysdeps/posix/opendir.c (o_directory_works, tryopen_o_directory):
> 	Remove definitions.
> 	(opendir_oflags): Use O_DIRECTORY regardless.
> 	(__opendir, __opendirat): Remove need_isdir_precheck usage.
> 	* sysdeps/unix/sysv/linux/opendir.c: Remove file.

If no one opposes it I will commit this shortly.

> ---
>  ChangeLog                         |   8 +++
>  sysdeps/posix/opendir.c           | 108 ++------------------------------------
>  sysdeps/unix/sysv/linux/opendir.c |  20 -------
>  3 files changed, 13 insertions(+), 123 deletions(-)
>  delete mode 100644 sysdeps/unix/sysv/linux/opendir.c
> 
> diff --git a/sysdeps/posix/opendir.c b/sysdeps/posix/opendir.c
> index d925804..dea23b2 100644
> --- a/sysdeps/posix/opendir.c
> +++ b/sysdeps/posix/opendir.c
> @@ -15,24 +15,13 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> -#include <assert.h>
> -#include <errno.h>
> -#include <limits.h>
> -#include <stdbool.h>
> -#include <stddef.h>
> -#include <stdlib.h>
>  #include <dirent.h>
>  #include <fcntl.h>
> -#include <sys/param.h>
> -#include <sys/types.h>
> -#include <sys/stat.h>
> -#include <unistd.h>
> -#include <stdio.h>
> -#include <string.h>
> -
> -#include <dirstream.h>
> +#include <errno.h>
> +#include <stdio.h>	/* For BUFSIZ.  */
> +#include <sys/param.h>	/* For MIN and MAX.  */
> +
>  #include <not-cancel.h>
> -#include <kernel-features.h>
>  
>  /* The st_blksize value of the directory is used as a hint for the
>     size of the buffer which receives struct dirent values from the
> @@ -40,49 +29,8 @@
>     file system provides a bogus value.  */
>  #define MAX_DIR_BUFFER_SIZE 1048576U
>  
> -/* opendir() must not accidentally open something other than a directory.
> -   Some OS's have kernel support for that, some don't.  In the worst
> -   case we have to stat() before the open() AND fstat() after.
> -
> -   We have to test at runtime for kernel support since libc may have
> -   been compiled with different headers to the kernel it's running on.
> -   This test can't be done reliably in the general case.  We'll use
> -   /dev/null, which if it's not a device lots of stuff will break, as
> -   a guinea pig.  It may be missing in chroot environments, so we
> -   make sure to fail safe. */
> -#ifdef O_DIRECTORY
> -# ifdef O_DIRECTORY_WORKS
> -#  define o_directory_works 1
> -#  define tryopen_o_directory() while (1) /* This must not be called.  */
> -# else
> -static int o_directory_works;
> -
> -static void
> -tryopen_o_directory (void)
> -{
> -  int serrno = errno;
> -  int x = __open_nocancel ("/dev/null", O_RDONLY|O_NDELAY|O_DIRECTORY);
> -
> -  if (x >= 0)
> -    {
> -      __close_nocancel_nostatus (x);
> -      o_directory_works = -1;
> -    }
> -  else if (errno != ENOTDIR)
> -    o_directory_works = -1;
> -  else
> -    o_directory_works = 1;
> -
> -  __set_errno (serrno);
> -}
> -# endif
> -# define EXTRA_FLAGS O_DIRECTORY
> -#else
> -# define EXTRA_FLAGS 0
> -#endif
> -
>  enum {
> -  opendir_oflags = O_RDONLY|O_NDELAY|EXTRA_FLAGS|O_LARGEFILE|O_CLOEXEC
> +  opendir_oflags = O_RDONLY|O_NDELAY|O_DIRECTORY|O_LARGEFILE|O_CLOEXEC
>  };
>  
>  static bool
> @@ -98,21 +46,6 @@ invalid_name (const char *name)
>    return false;
>  }
>  
> -
> -static bool
> -need_isdir_precheck (void)
> -{
> -#ifdef O_DIRECTORY
> -  /* Test whether O_DIRECTORY works.  */
> -  if (o_directory_works == 0)
> -    tryopen_o_directory ();
> -
> -  /* We can skip the expensive `stat' call if O_DIRECTORY works.  */
> -  return o_directory_works < 0;
> -#endif
> -  return true;
> -}
> -
>  static DIR *
>  opendir_tail (int fd)
>  {
> @@ -144,22 +77,6 @@ __opendirat (int dfd, const char *name)
>    if (__glibc_unlikely (invalid_name (name)))
>      return NULL;
>  
> -  if (need_isdir_precheck ())
> -    {
> -      /* We first have to check whether the name is for a directory.  We
> -	 cannot do this after the open() call since the open/close operation
> -	 performed on, say, a tape device might have undesirable effects.  */
> -      struct stat64 statbuf;
> -      if (__glibc_unlikely (__fxstatat64 (_STAT_VER, dfd, name,
> -					  &statbuf, 0) < 0))
> -	return NULL;
> -      if (__glibc_unlikely (! S_ISDIR (statbuf.st_mode)))
> -	{
> -	  __set_errno (ENOTDIR);
> -	  return NULL;
> -	}
> -    }
> -
>    return opendir_tail (__openat_nocancel (dfd, name, opendir_oflags));
>  }
>  #endif
> @@ -172,21 +89,6 @@ __opendir (const char *name)
>    if (__glibc_unlikely (invalid_name (name)))
>      return NULL;
>  
> -  if (need_isdir_precheck ())
> -    {
> -      /* We first have to check whether the name is for a directory.  We
> -	 cannot do this after the open() call since the open/close operation
> -	 performed on, say, a tape device might have undesirable effects.  */
> -      struct stat64 statbuf;
> -      if (__glibc_unlikely (__xstat64 (_STAT_VER, name, &statbuf) < 0))
> -	return NULL;
> -      if (__glibc_unlikely (! S_ISDIR (statbuf.st_mode)))
> -	{
> -	  __set_errno (ENOTDIR);
> -	  return NULL;
> -	}
> -    }
> -
>    return opendir_tail (__open_nocancel (name, opendir_oflags));
>  }
>  weak_alias (__opendir, opendir)
> diff --git a/sysdeps/unix/sysv/linux/opendir.c b/sysdeps/unix/sysv/linux/opendir.c
> deleted file mode 100644
> index 2677253..0000000
> --- a/sysdeps/unix/sysv/linux/opendir.c
> +++ /dev/null
> @@ -1,20 +0,0 @@
> -/* Copyright (C) 2000-2018 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
> -   <http://www.gnu.org/licenses/>.  */
> -
> -#define O_DIRECTORY_WORKS	1
> -
> -#include <sysdeps/posix/opendir.c>
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 3/7] Consolidate Linux readdir{64}{_r} implementation
  2018-03-02 18:59 ` [PATCH 3/7] Consolidate Linux readdir{64}{_r} implementation Adhemerval Zanella
@ 2018-04-06 19:49   ` Adhemerval Zanella
  0 siblings, 0 replies; 21+ messages in thread
From: Adhemerval Zanella @ 2018-04-06 19:49 UTC (permalink / raw)
  To: libc-alpha

If no one opposes, I will commit this shortly.

On 02/03/2018 15:59, Adhemerval Zanella wrote:
> This patch consolidates Linux readdir{64}{_r} implementation on just
> the default sysdeps/unix/sysv/linux/readdir{64}{_r}.c ones.  The
> default implementation handle the Linux requirements:
> 
>   * readdir{_r} is only built for _DIRENT_MATCHES_DIRENT64 being 0.
> 
>   * readdir64{_r} is always built and aliased to readdir{_r} for
>     ABI that define _DIRENT_MATCHES_DIRENT64.
> 
>   * A compat symbol is added for readdir64{_r} for ABI that used to
>     export the old non-LFS version.
> 
> Checked on aarch64-linux-gnu, x86_64-linux-gnu, i686-linux-gnu,
> sparcv9-linux-gnu, sparc64-linux-gnu, powerpc-linux-gnu, and
> powerpc64le-linux-gnu.
> 
> 	* sysdeps/posix/readdir.c (__READDIR, __GETDENTS, DIRENTY_TYPE,
> 	__READDIR_ALIAS): Undefine after usage.
> 	* sysdeps/posix/readdir_r.c (__READDIR_R, __GETDENTS, DIRENT_TYPE,
> 	__READDIR_R_ALIAS): Likewise.
> 	* sysdeps/unix/sysv/linux/arm/readdir64.c: Remove file.
> 	* sysdeps/unix/sysv/linux/arm/readdir64_r.c: Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/readdir64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/readdir64_r.c: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/readdir64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/readdir64_r.c: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/readdir64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/readdir64_r.c: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-32/readdir64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-32/readdir64_r.c: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc32/readdir64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc32/readdir64_r.c: Likewise.
> 	* sysdeps/unix/sysv/linux/wordsize-64/readdir.c: Likewise.
> 	* sysdeps/unix/sysv/linux/wordsize-64/readdir64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/wordsize-64/readdir64_r.c: Likewise.
> 	* sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c: Likewise.
> 	* sysdeps/unix/sysv/linux/readdir.c: New file.
> 	* sysdeps/unix/sysv/linux/readdir_r.c: Likewise.
> 	* sysdeps/unix/sysv/linux/readdir64.c: Add compat symbol if required.
> 	* sysdeps/unix/sysv/linux/readdir64_r.c: Likewise.
> ---
>  ChangeLog                                          | 25 +++++++++++
>  sysdeps/posix/readdir.c                            |  5 +++
>  sysdeps/posix/readdir_r.c                          |  5 +++
>  sysdeps/unix/sysv/linux/arm/readdir64.c            |  1 -
>  sysdeps/unix/sysv/linux/arm/readdir64_r.c          |  1 -
>  sysdeps/unix/sysv/linux/m68k/readdir64.c           |  1 -
>  sysdeps/unix/sysv/linux/m68k/readdir64_r.c         |  1 -
>  sysdeps/unix/sysv/linux/powerpc/readdir64.c        |  1 -
>  sysdeps/unix/sysv/linux/powerpc/readdir64_r.c      |  1 -
>  .../sysv/linux/{i386/readdir64_r.c => readdir.c}   | 30 +++----------
>  sysdeps/unix/sysv/linux/readdir64.c                | 51 +++++++++++++++++++++-
>  sysdeps/unix/sysv/linux/readdir64_r.c              | 48 +++++++++++++++++++-
>  .../sysv/linux/{i386/readdir64.c => readdir_r.c}   | 33 +++-----------
>  sysdeps/unix/sysv/linux/s390/s390-32/readdir64.c   |  1 -
>  sysdeps/unix/sysv/linux/s390/s390-32/readdir64_r.c |  1 -
>  sysdeps/unix/sysv/linux/sparc/sparc32/readdir64.c  |  1 -
>  .../unix/sysv/linux/sparc/sparc32/readdir64_r.c    |  1 -
>  sysdeps/unix/sysv/linux/wordsize-64/readdir.c      |  8 ----
>  sysdeps/unix/sysv/linux/wordsize-64/readdir64.c    |  1 -
>  sysdeps/unix/sysv/linux/wordsize-64/readdir64_r.c  |  1 -
>  sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c    |  4 --
>  21 files changed, 141 insertions(+), 80 deletions(-)
>  delete mode 100644 sysdeps/unix/sysv/linux/arm/readdir64.c
>  delete mode 100644 sysdeps/unix/sysv/linux/arm/readdir64_r.c
>  delete mode 100644 sysdeps/unix/sysv/linux/m68k/readdir64.c
>  delete mode 100644 sysdeps/unix/sysv/linux/m68k/readdir64_r.c
>  delete mode 100644 sysdeps/unix/sysv/linux/powerpc/readdir64.c
>  delete mode 100644 sysdeps/unix/sysv/linux/powerpc/readdir64_r.c
>  rename sysdeps/unix/sysv/linux/{i386/readdir64_r.c => readdir.c} (52%)
>  rename sysdeps/unix/sysv/linux/{i386/readdir64.c => readdir_r.c} (51%)
>  delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/readdir64.c
>  delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/readdir64_r.c
>  delete mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/readdir64.c
>  delete mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/readdir64_r.c
>  delete mode 100644 sysdeps/unix/sysv/linux/wordsize-64/readdir.c
>  delete mode 100644 sysdeps/unix/sysv/linux/wordsize-64/readdir64.c
>  delete mode 100644 sysdeps/unix/sysv/linux/wordsize-64/readdir64_r.c
>  delete mode 100644 sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c
> 
> diff --git a/sysdeps/posix/readdir.c b/sysdeps/posix/readdir.c
> index fcd3853..a6ecc0f 100644
> --- a/sysdeps/posix/readdir.c
> +++ b/sysdeps/posix/readdir.c
> @@ -120,3 +120,8 @@ __READDIR (DIR *dirp)
>  #ifdef __READDIR_ALIAS
>  weak_alias (__readdir, readdir)
>  #endif
> +
> +#undef __READDIR
> +#undef __GETDENTS
> +#undef DIRENT_TYPE
> +#undef __READDIR_ALIAS
> diff --git a/sysdeps/posix/readdir_r.c b/sysdeps/posix/readdir_r.c
> index 79030ab..2d691e7 100644
> --- a/sysdeps/posix/readdir_r.c
> +++ b/sysdeps/posix/readdir_r.c
> @@ -152,3 +152,8 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
>  #ifdef __READDIR_R_ALIAS
>  weak_alias (__readdir_r, readdir_r)
>  #endif
> +
> +#undef __READDIR_R
> +#undef __GETDENTS
> +#undef DIRENT_TYPE
> +#undef __READDIR_R_ALIAS
> diff --git a/sysdeps/unix/sysv/linux/arm/readdir64.c b/sysdeps/unix/sysv/linux/arm/readdir64.c
> deleted file mode 100644
> index 2ea26dd..0000000
> --- a/sysdeps/unix/sysv/linux/arm/readdir64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/readdir64.c>
> diff --git a/sysdeps/unix/sysv/linux/arm/readdir64_r.c b/sysdeps/unix/sysv/linux/arm/readdir64_r.c
> deleted file mode 100644
> index 9f54f89..0000000
> --- a/sysdeps/unix/sysv/linux/arm/readdir64_r.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/readdir64_r.c>
> diff --git a/sysdeps/unix/sysv/linux/m68k/readdir64.c b/sysdeps/unix/sysv/linux/m68k/readdir64.c
> deleted file mode 100644
> index 2ea26dd..0000000
> --- a/sysdeps/unix/sysv/linux/m68k/readdir64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/readdir64.c>
> diff --git a/sysdeps/unix/sysv/linux/m68k/readdir64_r.c b/sysdeps/unix/sysv/linux/m68k/readdir64_r.c
> deleted file mode 100644
> index 9f54f89..0000000
> --- a/sysdeps/unix/sysv/linux/m68k/readdir64_r.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/readdir64_r.c>
> diff --git a/sysdeps/unix/sysv/linux/powerpc/readdir64.c b/sysdeps/unix/sysv/linux/powerpc/readdir64.c
> deleted file mode 100644
> index 2ea26dd..0000000
> --- a/sysdeps/unix/sysv/linux/powerpc/readdir64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/readdir64.c>
> diff --git a/sysdeps/unix/sysv/linux/powerpc/readdir64_r.c b/sysdeps/unix/sysv/linux/powerpc/readdir64_r.c
> deleted file mode 100644
> index 9f54f89..0000000
> --- a/sysdeps/unix/sysv/linux/powerpc/readdir64_r.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/readdir64_r.c>
> diff --git a/sysdeps/unix/sysv/linux/i386/readdir64_r.c b/sysdeps/unix/sysv/linux/readdir.c
> similarity index 52%
> rename from sysdeps/unix/sysv/linux/i386/readdir64_r.c
> rename to sysdeps/unix/sysv/linux/readdir.c
> index 31862a0..b99bc96 100644
> --- a/sysdeps/unix/sysv/linux/i386/readdir64_r.c
> +++ b/sysdeps/unix/sysv/linux/readdir.c
> @@ -1,4 +1,5 @@
> -/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
> +/* Read a directory.  Linux no-LFS version.
> +   Copyright (C) 2018 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
> @@ -15,29 +16,8 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> -#define __READDIR_R __readdir64_r
> -#define __GETDENTS __getdents64
> -#define DIRENT_TYPE struct dirent64
> +#include <dirent.h>
>  
> -#include <sysdeps/posix/readdir_r.c>
> -
> -#undef __READDIR_R
> -#undef __GETDENTS
> -#undef DIRENT_TYPE
> -
> -#include <shlib-compat.h>
> -
> -versioned_symbol (libc, __readdir64_r, readdir64_r, GLIBC_2_2);
> -
> -#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
> -
> -#include <olddirent.h>
> -
> -#define __READDIR_R attribute_compat_text_section __old_readdir64_r
> -#define __GETDENTS __old_getdents64
> -#define DIRENT_TYPE struct __old_dirent64
> -
> -#include <sysdeps/posix/readdir_r.c>
> -
> -compat_symbol (libc, __old_readdir64_r, readdir64_r, GLIBC_2_1);
> +#if !_DIRENT_MATCHES_DIRENT64
> +# include <sysdeps/posix/readdir.c>
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/readdir64.c b/sysdeps/unix/sysv/linux/readdir64.c
> index 6d154fe..054e4ff 100644
> --- a/sysdeps/unix/sysv/linux/readdir64.c
> +++ b/sysdeps/unix/sysv/linux/readdir64.c
> @@ -1,8 +1,55 @@
> -#define __READDIR __readdir64
> -#define __GETDENTS __getdents64
> +/* Read a directory.  Linux LFS version.
> +   Copyright (C) 2018 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
> +   <http://www.gnu.org/licenses/>.  */
> +
> +/* When _DIRENT_MATCHES_DIRENT64 is defined we can alias 'readdir64' to
> +   'readdir'.  However the function signatures are not equal due
> +   different return types, so we need to suppress {__}readdir so weak
> +   and strong alias do not throw conflicting types errors.  */
> +#define readdir __no_readdir_decl
> +#define __readdir __no___readdir_decl
> +#include <dirent.h>
> +
> +#define __READDIR   __readdir64
> +#define __GETDENTS  __getdents64
>  #define DIRENT_TYPE struct dirent64
>  
>  #include <sysdeps/posix/readdir.c>
>  
> +#undef __readdir
> +#undef readdir
> +
>  libc_hidden_def (__readdir64)
> +#if _DIRENT_MATCHES_DIRENT64
> +strong_alias (__readdir64, __readdir)
>  weak_alias (__readdir64, readdir64)
> +weak_alias (__readdir64, readdir)
> +#else
> +/* The compat code expects the 'struct direct' with d_ino being a __ino_t
> +   instead of __ino64_t.  */
> +# include <shlib-compat.h>
> +versioned_symbol (libc, __readdir64, readdir64, GLIBC_2_2);
> +# if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
> +#  include <olddirent.h>
> +#  define __READDIR   attribute_compat_text_section __old_readdir64
> +#  define __GETDENTS  __old_getdents64
> +#  define DIRENT_TYPE struct __old_dirent64
> +#  include <sysdeps/posix/readdir.c>
> +libc_hidden_def (__old_readdir64)
> +compat_symbol (libc, __old_readdir64, readdir64, GLIBC_2_1);
> +# endif /* SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)  */
> +#endif /* _DIRENT_MATCHES_DIRENT64  */
> diff --git a/sysdeps/unix/sysv/linux/readdir64_r.c b/sysdeps/unix/sysv/linux/readdir64_r.c
> index 3dfbf4f..22b23d5 100644
> --- a/sysdeps/unix/sysv/linux/readdir64_r.c
> +++ b/sysdeps/unix/sysv/linux/readdir64_r.c
> @@ -1,7 +1,53 @@
> +/* Read a directory in reentrant mode.  Linux LFS version.
> +   Copyright (C) 2018 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
> +   <http://www.gnu.org/licenses/>.  */
> +
> +/* When _DIRENT_MATCHES_DIRENT64 is defined we can alias 'readdir64' to
> +   'readdir'.  However the function signatures are not equal due
> +   different return types, so we need to suppress {__}readdir so weak
> +   and strong alias do not throw conflicting types errors.  */
> +#define readdir_r   __no_readdir_r_decl
> +#define __readdir_r __no___readdir_r_decl
> +#include <dirent.h>
> +
>  #define __READDIR_R __readdir64_r
> -#define __GETDENTS __getdents64
> +#define __GETDENTS  __getdents64
>  #define DIRENT_TYPE struct dirent64
>  
>  #include <sysdeps/posix/readdir_r.c>
>  
> +#undef __readdir_r
> +#undef readdir_r
> +
> +#if _DIRENT_MATCHES_DIRENT64
> +strong_alias (__readdir64_r, __readdir_r)
> +weak_alias (__readdir64_r, readdir_r)
>  weak_alias (__readdir64_r, readdir64_r)
> +#else
> +/* The compat code expects the 'struct direct' with d_ino being a __ino_t
> +   instead of __ino64_t.  */
> +# include <shlib-compat.h>
> +versioned_symbol (libc, __readdir64_r, readdir64_r, GLIBC_2_2);
> +# if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
> +#  include <olddirent.h>
> +#  define __READDIR_R attribute_compat_text_section __old_readdir64_r
> +#  define __GETDENTS  __old_getdents64
> +#  define DIRENT_TYPE struct __old_dirent64
> +#  include <sysdeps/posix/readdir_r.c>
> +compat_symbol (libc, __old_readdir64_r, readdir64_r, GLIBC_2_1);
> +# endif /* SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)  */
> +#endif /* _DIRENT_MATCHES_DIRENT64  */
> diff --git a/sysdeps/unix/sysv/linux/i386/readdir64.c b/sysdeps/unix/sysv/linux/readdir_r.c
> similarity index 51%
> rename from sysdeps/unix/sysv/linux/i386/readdir64.c
> rename to sysdeps/unix/sysv/linux/readdir_r.c
> index 42b7302..7ca9e8e 100644
> --- a/sysdeps/unix/sysv/linux/i386/readdir64.c
> +++ b/sysdeps/unix/sysv/linux/readdir_r.c
> @@ -1,4 +1,5 @@
> -/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
> +/* Read a directory in reentrant mode.  Linux no-LFS version.
> +   Copyright (C) 2018 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
> @@ -15,32 +16,8 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> -#define __READDIR __readdir64
> -#define __GETDENTS __getdents64
> -#define DIRENT_TYPE struct dirent64
> +#include <dirent.h>
>  
> -#include <sysdeps/posix/readdir.c>
> -
> -#include <shlib-compat.h>
> -
> -#undef __READDIR
> -#undef __GETDENTS
> -#undef DIRENT_TYPE
> -
> -libc_hidden_def (__readdir64)
> -versioned_symbol (libc, __readdir64, readdir64, GLIBC_2_2);
> -
> -#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
> -
> -#include <olddirent.h>
> -
> -#define __READDIR attribute_compat_text_section __old_readdir64
> -#define __GETDENTS __old_getdents64
> -#define DIRENT_TYPE struct __old_dirent64
> -
> -#include <sysdeps/posix/readdir.c>
> -
> -libc_hidden_def (__old_readdir64)
> -
> -compat_symbol (libc, __old_readdir64, readdir64, GLIBC_2_1);
> +#if !_DIRENT_MATCHES_DIRENT64
> +# include <sysdeps/posix/readdir_r.c>
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/readdir64.c b/sysdeps/unix/sysv/linux/s390/s390-32/readdir64.c
> deleted file mode 100644
> index 2ea26dd..0000000
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/readdir64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/readdir64.c>
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/readdir64_r.c b/sysdeps/unix/sysv/linux/s390/s390-32/readdir64_r.c
> deleted file mode 100644
> index 9f54f89..0000000
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/readdir64_r.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/readdir64_r.c>
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/readdir64.c b/sysdeps/unix/sysv/linux/sparc/sparc32/readdir64.c
> deleted file mode 100644
> index 2ea26dd..0000000
> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/readdir64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/readdir64.c>
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/readdir64_r.c b/sysdeps/unix/sysv/linux/sparc/sparc32/readdir64_r.c
> deleted file mode 100644
> index 9f54f89..0000000
> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/readdir64_r.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/readdir64_r.c>
> diff --git a/sysdeps/unix/sysv/linux/wordsize-64/readdir.c b/sysdeps/unix/sysv/linux/wordsize-64/readdir.c
> deleted file mode 100644
> index 0d57988..0000000
> --- a/sysdeps/unix/sysv/linux/wordsize-64/readdir.c
> +++ /dev/null
> @@ -1,8 +0,0 @@
> -#define readdir64 __no_readdir64_decl
> -#define __readdir64 __no___readdir64_decl
> -#include <sysdeps/posix/readdir.c>
> -#undef __readdir64
> -strong_alias (__readdir, __readdir64)
> -strong_alias (__readdir, __GI___readdir64)
> -#undef readdir64
> -weak_alias (__readdir, readdir64)
> diff --git a/sysdeps/unix/sysv/linux/wordsize-64/readdir64.c b/sysdeps/unix/sysv/linux/wordsize-64/readdir64.c
> deleted file mode 100644
> index 9796431..0000000
> --- a/sysdeps/unix/sysv/linux/wordsize-64/readdir64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -/* readdir64 is in readdir.c */
> diff --git a/sysdeps/unix/sysv/linux/wordsize-64/readdir64_r.c b/sysdeps/unix/sysv/linux/wordsize-64/readdir64_r.c
> deleted file mode 100644
> index b8fe9a3..0000000
> --- a/sysdeps/unix/sysv/linux/wordsize-64/readdir64_r.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -/* readdir64_r is in readdir_r.c */
> diff --git a/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c b/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c
> deleted file mode 100644
> index 290f2c8..0000000
> --- a/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c
> +++ /dev/null
> @@ -1,4 +0,0 @@
> -#define readdir64_r __no_readdir64_r_decl
> -#include <sysdeps/posix/readdir_r.c>
> -#undef readdir64_r
> -weak_alias (__readdir_r, readdir64_r)
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 4/7] Consolidate Linux getdents{64} implementation
  2018-03-09 18:10   ` Adhemerval Zanella
@ 2018-04-17 19:42     ` Adhemerval Zanella
  2018-04-19 17:29       ` Joseph Myers
  0 siblings, 1 reply; 21+ messages in thread
From: Adhemerval Zanella @ 2018-04-17 19:42 UTC (permalink / raw)
  To: libc-alpha

I will commit this shortly if no one opposes it.
 
> Unfortunately MIPS n64 only wire up getdents64 on Linux 3.10, so we
> still need to use the non-LFS one and adjust the buffer for the
> ABI.  Below it is an updated patch for mips which first tried
> getdents64 and if it fails fallbacks to old syscall.  I did a sniff
> test on a qemu-system mips64 with dirent tests and saw no regressions.
> 
> ---
> 
> 	* sysdeps/unix/sysv/linux/alpha/getdents.c: Add comments with alpha
> 	requirements.
> 	 (_DIRENT_MATCHES_DIRENT64): Undef
> 	* sysdeps/unix/sysv/linux/alpha/getdents64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/arm/getdents64.c: Remove file.
> 	* sysdeps/unix/sysv/linux/generic/getdents.c: Likewise.
> 	* sysdeps/unix/sysv/linux/generic/getdents64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/generic/wordsize-32/getdents.c: Likewise.
> 	* sysdeps/unix/sysv/linux/getdents.c: Simplify implementation by
> 	use getdents64 syscalls as base.
> 	* sysdeps/unix/sysv/linux/getdents64.c: Likewise and add compatibility
> 	symbol if required.
> 	* sysdeps/unix/sysv/linux/hppa/getdents64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/getdents64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/getdents64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/getdents64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-32/getdents64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc32/getdents64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/wordsize-64/getdents.c: Likewise.
> 	* sysdeps/unix/sysv/linux/wordsize-64/getdents64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c
> 	(__get_clockfreq_via_proc_openprom): Use __getdents64.
> 	* sysdeps/unix/sysv/linux/mips/mips64/getdents64.c: New file.
> 
> ---
> 
> diff --git a/sysdeps/unix/sysv/linux/alpha/getdents.c b/sysdeps/unix/sysv/linux/alpha/getdents.c
> index dfecfef..64ccf86 100644
> --- a/sysdeps/unix/sysv/linux/alpha/getdents.c
> +++ b/sysdeps/unix/sysv/linux/alpha/getdents.c
> @@ -1,3 +1,11 @@
> +/* Although Alpha defines _DIRENT_MATCHES_DIRENT64, 'struct dirent' and
> +   'struct dirent64' have slight different internal layout with d_ino
> +   being a __ino_t on non-LFS version with an extra __pad field which should
> +   be zeroed.  */
> +
> +#include <dirent.h>
> +#undef _DIRENT_MATCHES_DIRENT64
> +#define _DIRENT_MATCHES_DIRENT64 0
>  #define DIRENT_SET_DP_INO(dp, value) \
>    do { (dp)->d_ino = (value); (dp)->__pad = 0; } while (0)
>  #include <sysdeps/unix/sysv/linux/getdents.c>
> diff --git a/sysdeps/unix/sysv/linux/alpha/getdents64.c b/sysdeps/unix/sysv/linux/alpha/getdents64.c
> index 50f1368..53cf93c 100644
> --- a/sysdeps/unix/sysv/linux/alpha/getdents64.c
> +++ b/sysdeps/unix/sysv/linux/alpha/getdents64.c
> @@ -1 +1,10 @@
> +/* Although Alpha defines _DIRENT_MATCHES_DIRENT64, 'struct dirent' and
> +   'struct dirent64' have slight different internal layout with d_ino
> +   being a __ino_t on non-LFS version with an extra __pad field which should
> +   be zeroed.  */
> +
> +#include <dirent.h>
> +/* It suppress the __getdents64 to __getdents alias.  */
> +#undef _DIRENT_MATCHES_DIRENT64
> +#define _DIRENT_MATCHES_DIRENT64 0
>  #include <sysdeps/unix/sysv/linux/getdents64.c>
> diff --git a/sysdeps/unix/sysv/linux/arm/getdents64.c b/sysdeps/unix/sysv/linux/arm/getdents64.c
> deleted file mode 100644
> index 0c75fb5..0000000
> --- a/sysdeps/unix/sysv/linux/arm/getdents64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/getdents64.c>
> diff --git a/sysdeps/unix/sysv/linux/generic/getdents.c b/sysdeps/unix/sysv/linux/generic/getdents.c
> deleted file mode 100644
> index 14dbbc7..0000000
> --- a/sysdeps/unix/sysv/linux/generic/getdents.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -/* Defined in getdents64.c */
> diff --git a/sysdeps/unix/sysv/linux/generic/getdents64.c b/sysdeps/unix/sysv/linux/generic/getdents64.c
> deleted file mode 100644
> index 0f876b8..0000000
> --- a/sysdeps/unix/sysv/linux/generic/getdents64.c
> +++ /dev/null
> @@ -1,37 +0,0 @@
> -/* Copyright (C) 2011-2018 Free Software Foundation, Inc.
> -   This file is part of the GNU C Library.
> -   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
> -
> -   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
> -   <http://www.gnu.org/licenses/>.  */
> -
> -#include <stddef.h>
> -#include <stdint.h>
> -#include <unistd.h>
> -#include <sys/types.h>
> -#include <bits/wordsize.h>
> -
> -#include <sysdep.h>
> -#include <sys/syscall.h>
> -
> -/* The kernel struct linux_dirent64 matches the 'struct getdents64' type.  */
> -ssize_t
> -__getdents64 (int fd, char *buf, size_t nbytes)
> -{
> -  return INLINE_SYSCALL (getdents64, 3, fd, buf, nbytes);
> -}
> -
> -#if __WORDSIZE == 64
> -strong_alias (__getdents64, __getdents)
> -#endif
> diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/getdents.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/getdents.c
> deleted file mode 100644
> index 7158fd1..0000000
> --- a/sysdeps/unix/sysv/linux/generic/wordsize-32/getdents.c
> +++ /dev/null
> @@ -1,115 +0,0 @@
> -/* Copyright (C) 1993-2018 Free Software Foundation, Inc.
> -   This file is part of the GNU C Library.
> -   Simplified from sysdeps/unix/sysv/linux/getdents.c.
> -
> -   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
> -   <http://www.gnu.org/licenses/>.  */
> -
> -#include <alloca.h>
> -#include <assert.h>
> -#include <errno.h>
> -#include <dirent.h>
> -#include <stddef.h>
> -#include <stdint.h>
> -#include <string.h>
> -#include <unistd.h>
> -#include <sys/param.h>
> -#include <sys/types.h>
> -
> -#include <sysdep.h>
> -#include <sys/syscall.h>
> -
> -/* Pack the dirent64 struct down into 32-bit offset/inode fields, and
> -   ensure that no overflow occurs.  */
> -ssize_t
> -__getdents (int fd, char *buf, size_t nbytes)
> -{
> -  union
> -  {
> -    struct dirent64 k;  /* Kernel structure.  */
> -    struct dirent u;
> -    char b[1];
> -  } *kbuf = (void *) buf, *outp, *inp;
> -  size_t kbytes = nbytes;
> -  off64_t last_offset = -1;
> -  ssize_t retval;
> -
> -  const size_t size_diff = (offsetof (struct dirent64, d_name)
> -                            - offsetof (struct dirent, d_name));
> -  if (nbytes <= sizeof (struct dirent))
> -    {
> -      kbytes = nbytes + offsetof (struct dirent64, d_name)
> -        - offsetof (struct dirent, d_name);
> -      kbuf = __alloca(kbytes);
> -    }
> -
> -  retval = INLINE_SYSCALL (getdents64, 3, fd, kbuf, kbytes);
> -  if (retval == -1)
> -    return -1;
> -
> -  /* 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.  */
> -  inp = kbuf;
> -  outp = (void *) buf;
> -
> -  while (&inp->b < &kbuf->b + retval)
> -    {
> -      const size_t alignment = __alignof__ (struct dirent);
> -      /* Since inp->k.d_reclen is already aligned for the kernel
> -         structure this may compute a value that is bigger
> -         than necessary.  */
> -      size_t old_reclen = inp->k.d_reclen;
> -      size_t new_reclen = ((old_reclen - size_diff + alignment - 1)
> -                           & ~(alignment - 1));
> -
> -      /* Copy the data out of the old structure into temporary space.
> -         Then copy the name, which may overlap if BUF == KBUF.  */
> -      const uint64_t d_ino = inp->k.d_ino;
> -      const int64_t d_off = inp->k.d_off;
> -      const uint8_t d_type = inp->k.d_type;
> -
> -      memmove (outp->u.d_name, inp->k.d_name,
> -               old_reclen - offsetof (struct dirent64, d_name));
> -
> -      /* Now we have copied the data from INP and access only OUTP.  */
> -
> -      outp->u.d_ino = d_ino;
> -      outp->u.d_off = d_off;
> -      if ((sizeof (outp->u.d_ino) != sizeof (inp->k.d_ino)
> -           && outp->u.d_ino != d_ino)
> -          || (sizeof (outp->u.d_off) != sizeof (inp->k.d_off)
> -              && outp->u.d_off != d_off))
> -        {
> -          /* Overflow.  If there was at least one entry before this one,
> -             return them without error, otherwise signal overflow.  */
> -          if (last_offset != -1)
> -            {
> -              __lseek64 (fd, last_offset, SEEK_SET);
> -              return outp->b - buf;
> -            }
> -          __set_errno (EOVERFLOW);
> -          return -1;
> -        }
> -
> -      last_offset = d_off;
> -      outp->u.d_reclen = new_reclen;
> -      outp->u.d_type = d_type;
> -
> -      inp = (void *) inp + old_reclen;
> -      outp = (void *) outp + new_reclen;
> -    }
> -
> -  return outp->b - buf;
> -}
> diff --git a/sysdeps/unix/sysv/linux/getdents.c b/sysdeps/unix/sysv/linux/getdents.c
> index 591ce67..4e52729 100644
> --- a/sysdeps/unix/sysv/linux/getdents.c
> +++ b/sysdeps/unix/sysv/linux/getdents.c
> @@ -1,4 +1,5 @@
> -/* Copyright (C) 1993-2018 Free Software Foundation, Inc.
> +/* Get directory entries.  Linux no-LFS version.
> +   Copyright (C) 1993-2018 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
> @@ -12,260 +13,102 @@
>     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
> +   License along with the GNU C Library.  If not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> -#include <alloca.h>
> -#include <assert.h>
> -#include <errno.h>
>  #include <dirent.h>
> -#include <stddef.h>
> -#include <stdint.h>
> -#include <string.h>
> -#include <unistd.h>
> -#include <sys/param.h>
> -#include <sys/types.h>
>  
> -#include <sysdep.h>
> -#include <sys/syscall.h>
> +#if !_DIRENT_MATCHES_DIRENT64
>  
> -#include <linux/posix_types.h>
> +# include <unistd.h>
> +# include <string.h>
> +# include <errno.h>
>  
> -#include <kernel-features.h>
> +# ifndef DIRENT_SET_DP_INO
> +#  define DIRENT_SET_DP_INO(dp, value) (dp)->d_ino = (value)
> +# endif
>  
> -/* For Linux we need a special version of this file since the
> -   definition of `struct dirent' is not the same for the kernel and
> -   the libc.  There is one additional field which might be introduced
> -   in the kernel structure in the future.
> -
> -   Here is the kernel definition of `struct dirent' as of 2.1.20:  */
> -
> -struct kernel_dirent
> -  {
> -    long int d_ino;
> -    __kernel_off_t d_off;
> -    unsigned short int d_reclen;
> -    char d_name[256];
> -  };
> -
> -struct kernel_dirent64
> -  {
> -    uint64_t		d_ino;
> -    int64_t		d_off;
> -    unsigned short int	d_reclen;
> -    unsigned char	d_type;
> -    char		d_name[256];
> -  };
> -
> -#ifndef __GETDENTS
> -# define __GETDENTS __getdents
> -#endif
> -#ifndef DIRENT_TYPE
> -# define DIRENT_TYPE struct dirent
> -#endif
> -#ifndef DIRENT_SET_DP_INO
> -# define DIRENT_SET_DP_INO(dp, value) (dp)->d_ino = (value)
> -#endif
> -
> -/* The problem here is that we cannot simply read the next NBYTES
> -   bytes.  We need to take the additional field into account.  We use
> -   some heuristic.  Assuming the directory contains names with 14
> -   characters on average we can compute an estimated number of entries
> -   which fit in the buffer.  Taking this number allows us to specify a
> -   reasonable number of bytes to read.  If we should be wrong, we can
> -   reset the file descriptor.  In practice the kernel is limiting the
> -   amount of data returned much more then the reduced buffer size.  */
> +/* Pack the dirent64 struct down into 32-bit offset/inode fields, and
> +   ensure that no overflow occurs.  */
>  ssize_t
> -__GETDENTS (int fd, char *buf, size_t nbytes)
> +__getdents (int fd, char *buf, size_t nbytes)
>  {
> +  union
> +  {
> +    struct dirent64 k;  /* Kernel structure.  */
> +    struct dirent u;
> +    char b[1];
> +  } *kbuf = (void *) buf, *outp, *inp;
> +  size_t kbytes = nbytes;
> +  off64_t last_offset = -1;
>    ssize_t retval;
>  
> -  /* The d_ino and d_off fields in kernel_dirent and dirent must have
> -     the same sizes and alignments.  */
> -  if (sizeof (DIRENT_TYPE) == sizeof (struct dirent)
> -      && (sizeof (((struct kernel_dirent *) 0)->d_ino)
> -	  == sizeof (((struct dirent *) 0)->d_ino))
> -      && (sizeof (((struct kernel_dirent *) 0)->d_off)
> -	  == sizeof (((struct dirent *) 0)->d_off))
> -      && (offsetof (struct kernel_dirent, d_off)
> -	  == offsetof (struct dirent, d_off))
> -      && (offsetof (struct kernel_dirent, d_reclen)
> -	  == offsetof (struct dirent, d_reclen)))
> -    {
> -      retval = INLINE_SYSCALL (getdents, 3, fd, buf, nbytes);
> +# define size_diff (offsetof (struct dirent64, d_name) \
> +		    - offsetof (struct dirent, d_name))
> +  char kbuftmp[sizeof (struct dirent) + size_diff];
> +  if (nbytes <= sizeof (struct dirent))
> +    kbuf = (void*) kbuftmp;
>  
> -      /* The kernel added the d_type value after the name.  Change
> -	 this now.  */
> -      if (retval != -1)
> -	{
> -	  union
> -	  {
> -	    struct kernel_dirent k;
> -	    struct dirent u;
> -	  } *kbuf = (void *) buf;
> +  retval = INLINE_SYSCALL_CALL (getdents64, fd, kbuf, kbytes);
> +  if (retval == -1)
> +    return -1;
>  
> -	  while ((char *) kbuf < buf + retval)
> -	    {
> -	      char d_type = *((char *) kbuf + kbuf->k.d_reclen - 1);
> -	      memmove (kbuf->u.d_name, kbuf->k.d_name,
> -		       strlen (kbuf->k.d_name) + 1);
> -	      kbuf->u.d_type = d_type;
> +  /* 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.  */
> +  inp = kbuf;
> +  outp = (void *) buf;
>  
> -	      kbuf = (void *) ((char *) kbuf + kbuf->k.d_reclen);
> -	    }
> -	}
> -
> -      return retval;
> -    }
> -
> -  off64_t last_offset = -1;
> -
> -#ifdef __NR_getdents64
> -  {
> -    union
> +  while (&inp->b < &kbuf->b + retval)
>      {
> -      struct kernel_dirent64 k;
> -      DIRENT_TYPE u;
> -      char b[1];
> -    } *kbuf = (void *) buf, *outp, *inp;
> -    size_t kbytes = nbytes;
> -    if (offsetof (DIRENT_TYPE, d_name)
> -	< offsetof (struct kernel_dirent64, d_name)
> -	&& nbytes <= sizeof (DIRENT_TYPE))
> -      {
> -	kbytes = (nbytes + offsetof (struct kernel_dirent64, d_name)
> -		  - offsetof (DIRENT_TYPE, d_name));
> -	kbuf = __alloca(kbytes);
> -      }
> -    retval = INLINE_SYSCALL (getdents64, 3, fd, kbuf, kbytes);
> -    const size_t size_diff = (offsetof (struct kernel_dirent64, d_name)
> -			      - offsetof (DIRENT_TYPE, d_name));
> -
> -    /* Return the error if encountered.  */
> -    if (retval == -1)
> -      return -1;
> -
> -    /* If the structure returned by the kernel is identical to what we
> -       need, don't do any conversions.  */
> -    if (offsetof (DIRENT_TYPE, d_name)
> -	== offsetof (struct kernel_dirent64, d_name)
> -	&& sizeof (outp->u.d_ino) == sizeof (inp->k.d_ino)
> -	&& sizeof (outp->u.d_off) == sizeof (inp->k.d_off))
> -      return retval;
> -
> -    /* 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.  */
> -    inp = kbuf;
> -    outp = (void *) buf;
> -
> -    while (&inp->b < &kbuf->b + retval)
> -      {
> -	const size_t alignment = __alignof__ (DIRENT_TYPE);
> -	/* Since inp->k.d_reclen is already aligned for the kernel
> -	   structure this may compute a value that is bigger
> -	   than necessary.  */
> -	size_t old_reclen = inp->k.d_reclen;
> -	size_t new_reclen = ((old_reclen - size_diff + alignment - 1)
> -			     & ~(alignment - 1));
> -
> -	/* Copy the data out of the old structure into temporary space.
> -	   Then copy the name, which may overlap if BUF == KBUF.  */
> -	const uint64_t d_ino = inp->k.d_ino;
> -	const int64_t d_off = inp->k.d_off;
> -	const uint8_t d_type = inp->k.d_type;
> -
> -	memmove (outp->u.d_name, inp->k.d_name,
> -		 old_reclen - offsetof (struct kernel_dirent64, d_name));
> -
> -	/* Now we have copied the data from INP and access only OUTP.  */
> -
> -	DIRENT_SET_DP_INO (&outp->u, d_ino);
> -	outp->u.d_off = d_off;
> -	if ((sizeof (outp->u.d_ino) != sizeof (inp->k.d_ino)
> -	     && outp->u.d_ino != d_ino)
> -	    || (sizeof (outp->u.d_off) != sizeof (inp->k.d_off)
> -		&& outp->u.d_off != d_off))
> -	  {
> -	    /* Overflow.  If there was at least one entry
> -	       before this one, return them without error,
> -	       otherwise signal overflow.  */
> -	    if (last_offset != -1)
> -	      {
> -		__lseek64 (fd, last_offset, SEEK_SET);
> -		return outp->b - buf;
> -	      }
> -	    __set_errno (EOVERFLOW);
> -	    return -1;
> -	  }
> -
> -	last_offset = d_off;
> -	outp->u.d_reclen = new_reclen;
> -	outp->u.d_type = d_type;
> -
> -	inp = (void *) inp + old_reclen;
> -	outp = (void *) outp + new_reclen;
> -      }
> -
> -    return outp->b - buf;
> -  }
> -#endif
> -  {
> -    size_t red_nbytes;
> -    struct kernel_dirent *skdp, *kdp;
> -    const size_t size_diff = (offsetof (DIRENT_TYPE, d_name)
> -			      - offsetof (struct kernel_dirent, d_name));
> -
> -    red_nbytes = MIN (nbytes
> -		      - ((nbytes / (offsetof (DIRENT_TYPE, d_name) + 14))
> -			 * size_diff),
> -		      nbytes - size_diff);
> -
> -    skdp = kdp = __alloca (red_nbytes);
> -
> -    retval = INLINE_SYSCALL (getdents, 3, fd, (char *) kdp, red_nbytes);
> -
> -    if (retval == -1)
> -      return -1;
> -
> -    DIRENT_TYPE *dp = (DIRENT_TYPE *) buf;
> -    while ((char *) kdp < (char *) skdp + retval)
> -      {
> -	const size_t alignment = __alignof__ (DIRENT_TYPE);
> -	/* Since kdp->d_reclen is already aligned for the kernel structure
> -	   this may compute a value that is bigger than necessary.  */
> -	size_t new_reclen = ((kdp->d_reclen + size_diff + alignment - 1)
> -			     & ~(alignment - 1));
> -	if ((char *) dp + new_reclen > buf + nbytes)
> -	  {
> -	    /* Our heuristic failed.  We read too many entries.  Reset
> -	       the stream.  */
> -	    assert (last_offset != -1);
> -	    __lseek64 (fd, last_offset, SEEK_SET);
> -
> -	    if ((char *) dp == buf)
> -	      {
> -		/* The buffer the user passed in is too small to hold even
> -		   one entry.  */
> -		__set_errno (EINVAL);
> -		return -1;
> -	      }
> -
> -	    break;
> -	  }
> +      const size_t alignment = __alignof__ (struct dirent);
> +      /* Since inp->k.d_reclen is already aligned for the kernel
> +         structure this may compute a value that is bigger
> +         than necessary.  */
> +      size_t old_reclen = inp->k.d_reclen;
> +      size_t new_reclen = ((old_reclen - size_diff + alignment - 1)
> +                           & ~(alignment - 1));
> +
> +      /* Copy the data out of the old structure into temporary space.
> +         Then copy the name, which may overlap if BUF == KBUF.  */
> +      const uint64_t d_ino = inp->k.d_ino;
> +      const int64_t d_off = inp->k.d_off;
> +      const uint8_t d_type = inp->k.d_type;
> +
> +      memmove (outp->u.d_name, inp->k.d_name,
> +               old_reclen - offsetof (struct dirent64, d_name));
> +
> +      /* Now we have copied the data from INP and access only OUTP.  */
> +
> +      DIRENT_SET_DP_INO (&outp->u, d_ino);
> +      outp->u.d_off = d_off;
> +      if ((sizeof (outp->u.d_ino) != sizeof (inp->k.d_ino)
> +           && outp->u.d_ino != d_ino)
> +          || (sizeof (outp->u.d_off) != sizeof (inp->k.d_off)
> +              && outp->u.d_off != d_off))
> +        {
> +          /* Overflow.  If there was at least one entry before this one,
> +             return them without error, otherwise signal overflow.  */
> +          if (last_offset != -1)
> +            {
> +              __lseek64 (fd, last_offset, SEEK_SET);
> +              return outp->b - buf;
> +            }
> +          __set_errno (EOVERFLOW);
> +          return -1;
> +        }
> +
> +      last_offset = d_off;
> +      outp->u.d_reclen = new_reclen;
> +      outp->u.d_type = d_type;
> +
> +      inp = (void *) inp + old_reclen;
> +      outp = (void *) outp + new_reclen;
> +    }
>  
> -	last_offset = kdp->d_off;
> -	DIRENT_SET_DP_INO(dp, kdp->d_ino);
> -	dp->d_off = kdp->d_off;
> -	dp->d_reclen = new_reclen;
> -	dp->d_type = *((char *) kdp + kdp->d_reclen - 1);
> -	memcpy (dp->d_name, kdp->d_name,
> -		kdp->d_reclen - offsetof (struct kernel_dirent, d_name));
> +  return outp->b - buf;
> +}
>  
> -	dp = (DIRENT_TYPE *) ((char *) dp + new_reclen);
> -	kdp = (struct kernel_dirent *) (((char *) kdp) + kdp->d_reclen);
> -      }
> +# undef DIRENT_SET_DP_INO
>  
> -    return (char *) dp - buf;
> -  }
> -}
> +#endif /* _DIRENT_MATCHES_DIRENT64  */
> diff --git a/sysdeps/unix/sysv/linux/getdents64.c b/sysdeps/unix/sysv/linux/getdents64.c
> index 805917e..f37fe15 100644
> --- a/sysdeps/unix/sysv/linux/getdents64.c
> +++ b/sysdeps/unix/sysv/linux/getdents64.c
> @@ -1,3 +1,77 @@
> -#define __GETDENTS __getdents64
> -#define DIRENT_TYPE struct dirent64
> -#include <sysdeps/unix/sysv/linux/getdents.c>
> +/* Get directory entries.  Linux LFS version.
> +   Copyright (C) 1997-2018 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
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <string.h>
> +#include <dirent.h>
> +#include <errno.h>
> +
> +/* The kernel struct linux_dirent64 matches the 'struct getdents64' type.  */
> +ssize_t
> +__getdents64 (int fd, char *buf, size_t nbytes)
> +{
> +  return INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes);
> +}
> +
> +#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>
> +
> +/* kernel definition of as of 3.2.  */
> +struct compat_linux_dirent
> +{
> +  /* Both d_ino and d_off are compat_ulong_t which are defined in all
> +     architectures as 'u32'.  */
> +  uint32_t        d_ino;
> +  uint32_t        d_off;
> +  unsigned short  d_reclen;
> +  char            d_name[1];
> +};
> +
> +ssize_t
> +__old_getdents64 (int fd, char *buf, size_t nbytes)
> +{
> +  ssize_t retval = INLINE_SYSCALL_CALL (getdents, fd, buf, nbytes);
> +
> +  /* The kernel added the d_type value after the name.  Change this now.  */
> +  if (retval != -1)
> +    {
> +      union
> +      {
> +	struct compat_linux_dirent k;
> +	struct dirent u;
> +      } *kbuf = (void *) buf;
> +
> +      while ((char *) kbuf < buf + retval)
> +	{
> +	  char d_type = *((char *) kbuf + kbuf->k.d_reclen - 1);
> +	  memmove (kbuf->u.d_name, kbuf->k.d_name,
> +		   strlen (kbuf->k.d_name) + 1);
> +	  kbuf->u.d_type = d_type;
> +
> +	  kbuf = (void *) ((char *) kbuf + kbuf->k.d_reclen);
> +	}
> +     }
> +  return retval;
> +}
> +# endif /* SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)  */
> +#endif /* _DIRENT_MATCHES_DIRENT64  */
> diff --git a/sysdeps/unix/sysv/linux/hppa/getdents64.c b/sysdeps/unix/sysv/linux/hppa/getdents64.c
> deleted file mode 100644
> index 0c75fb5..0000000
> --- a/sysdeps/unix/sysv/linux/hppa/getdents64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/getdents64.c>
> diff --git a/sysdeps/unix/sysv/linux/i386/getdents64.c b/sysdeps/unix/sysv/linux/i386/getdents64.c
> deleted file mode 100644
> index 0a2c194..0000000
> --- a/sysdeps/unix/sysv/linux/i386/getdents64.c
> +++ /dev/null
> @@ -1,39 +0,0 @@
> -/* Copyright (C) 2000-2018 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
> -   <http://www.gnu.org/licenses/>.  */
> -
> -#define __GETDENTS __getdents64
> -#define DIRENT_TYPE struct dirent64
> -
> -#include <sysdeps/unix/sysv/linux/getdents.c>
> -
> -#include <shlib-compat.h>
> -
> -#undef __READDIR
> -#undef __GETDENTS
> -#undef DIRENT_TYPE
> -
> -#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
> -
> -#include <olddirent.h>
> -
> -#define __GETDENTS __old_getdents64
> -#define DIRENT_TYPE struct __old_dirent64
> -#define kernel_dirent old_kernel_dirent
> -#define kernel_dirent64 old_kernel_dirent64
> -
> -#include <sysdeps/unix/sysv/linux/getdents.c>
> -#endif
> diff --git a/sysdeps/unix/sysv/linux/m68k/getdents64.c b/sysdeps/unix/sysv/linux/m68k/getdents64.c
> deleted file mode 100644
> index 0c75fb5..0000000
> --- a/sysdeps/unix/sysv/linux/m68k/getdents64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/getdents64.c>
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/getdents64.c b/sysdeps/unix/sysv/linux/mips/mips64/getdents64.c
> new file mode 100644
> index 0000000..5b62791
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/getdents64.c
> @@ -0,0 +1,113 @@
> +/* Get directory entries.  Linux/MIPSn64 LFS version.
> +   Copyright (C) 2018 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
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <string.h>
> +#include <dirent.h>
> +#include <errno.h>
> +#include <assert.h>
> +#include <sys/param.h>
> +#include <unistd.h>
> +#include <scratch_buffer.h>
> +
> +ssize_t
> +__getdents64 (int fd, char *buf, size_t nbytes)
> +{
> +  ssize_t ret;
> +#ifdef __NR_getdents64
> +  ret = INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes);
> +  if (ret != -1)
> +    return ret;
> +#endif
> +
> +  /* Unfortunately getdents64 was only wire-up for MIPS n64 on Linux 3.10.
> +     If syscall is not available it need to fallback to old one.  */
> +
> +  struct kernel_dirent
> +    {
> +      unsigned long d_ino;
> +      unsigned long d_off;
> +      unsigned short int d_reclen;
> +      char d_name[256];
> +    };
> +
> +  const size_t size_diff = (offsetof (struct dirent64, d_name)
> +			   - offsetof (struct kernel_dirent, d_name));
> +
> +  size_t red_nbytes = MIN (nbytes
> +			   - ((nbytes / (offsetof (struct dirent64, d_name)
> +					 + 14)) * size_diff),
> +			   nbytes - size_diff);
> +
> +  struct scratch_buffer tmpbuf;
> +  scratch_buffer_init (&tmpbuf);
> +  if (!scratch_buffer_set_array_size (&tmpbuf, red_nbytes, sizeof (uint8_t)))
> +    INLINE_SYSCALL_ERROR_RETURN_VALUE (ENOMEM);
> +
> +  struct kernel_dirent *skdp, *kdp;
> +  skdp = kdp = tmpbuf.data;
> +
> +  ssize_t retval = INLINE_SYSCALL_CALL (getdents, fd, kdp, red_nbytes);
> +  if (retval == -1)
> +    {
> +      scratch_buffer_free (&tmpbuf);
> +      return -1;
> +    }
> +
> +  off64_t last_offset = -1;
> +  struct dirent64 *dp = (struct dirent64 *) buf;
> +  while ((char *) kdp < (char *) skdp + retval)
> +    {
> +      const size_t alignment = __alignof__ (struct dirent64);
> +      /* Since kdp->d_reclen is already aligned for the kernel structure
> +	 this may compute a value that is bigger than necessary.  */
> +      size_t new_reclen = ((kdp->d_reclen + size_diff + alignment - 1)
> +			   & ~(alignment - 1));
> +      if ((char *) dp + new_reclen > buf + nbytes)
> +        {
> +	  /* Our heuristic failed.  We read too many entries.  Reset
> +	     the stream.  */
> +	  assert (last_offset != -1);
> +	  __lseek64 (fd, last_offset, SEEK_SET);
> +
> +	  if ((char *) dp == buf)
> +	    {
> +	      scratch_buffer_free (&tmpbuf);
> +	      INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
> +	    }
> +
> +	  break;
> +	}
> +
> +      last_offset = kdp->d_off;
> +      dp->d_ino = kdp->d_ino;
> +      dp->d_off = kdp->d_off;
> +      dp->d_reclen = new_reclen;
> +      dp->d_type = *((char *) kdp + kdp->d_reclen - 1);
> +      memcpy (dp->d_name, kdp->d_name,
> +	      kdp->d_reclen - offsetof (struct kernel_dirent, d_name));
> +
> +      dp = (struct dirent64 *) ((char *) dp + new_reclen);
> +      kdp = (struct kernel_dirent *) (((char *) kdp) + kdp->d_reclen);
> +    }
> +
> +  scratch_buffer_free (&tmpbuf);
> +  return (char *) dp - buf;
> +}
> +#if _DIRENT_MATCHES_DIRENT64
> +strong_alias (__getdents64, __getdents)
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/powerpc/getdents64.c b/sysdeps/unix/sysv/linux/powerpc/getdents64.c
> deleted file mode 100644
> index 0c75fb5..0000000
> --- a/sysdeps/unix/sysv/linux/powerpc/getdents64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/getdents64.c>
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/getdents64.c b/sysdeps/unix/sysv/linux/s390/s390-32/getdents64.c
> deleted file mode 100644
> index 0c75fb5..0000000
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/getdents64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/getdents64.c>
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/getdents64.c b/sysdeps/unix/sysv/linux/sparc/sparc32/getdents64.c
> deleted file mode 100644
> index 0c75fb5..0000000
> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/getdents64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/getdents64.c>
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c b/sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c
> index c54d301..6838a77 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c
> @@ -90,12 +90,12 @@ __get_clockfreq_via_proc_openprom (void)
>    if (obp_fd != -1)
>      {
>        unsigned long int buf[4096 / sizeof (unsigned long int)];
> -      struct dirent *dirp = (struct dirent *) buf;
> +      struct dirent64 *dirp = (struct dirent64 *) buf;
>        ssize_t len;
>  
> -      while ((len = __getdents (obp_fd, (char *) dirp, sizeof (buf))) > 0)
> +      while ((len = __getdents64 (obp_fd, (char *) dirp, sizeof (buf))) > 0)
>  	{
> -	  struct dirent *this_dirp = dirp;
> +	  struct dirent64 *this_dirp = dirp;
>  
>  	  while (len > 0)
>  	    {
> @@ -140,7 +140,7 @@ __get_clockfreq_via_proc_openprom (void)
>  		break;
>  
>  	      len -= this_dirp->d_reclen;
> -	      this_dirp = (struct dirent *)
> +	      this_dirp = (struct dirent64 *)
>  		((char *) this_dirp + this_dirp->d_reclen);
>  	    }
>  	  if (result != 0)
> diff --git a/sysdeps/unix/sysv/linux/wordsize-64/getdents.c b/sysdeps/unix/sysv/linux/wordsize-64/getdents.c
> deleted file mode 100644
> index 5ea4c57..0000000
> --- a/sysdeps/unix/sysv/linux/wordsize-64/getdents.c
> +++ /dev/null
> @@ -1,4 +0,0 @@
> -#define __getdents64 __no___getdents64_decl
> -#include <sysdeps/unix/sysv/linux/getdents.c>
> -#undef __getdents64
> -weak_alias (__getdents, __getdents64);
> diff --git a/sysdeps/unix/sysv/linux/wordsize-64/getdents64.c b/sysdeps/unix/sysv/linux/wordsize-64/getdents64.c
> deleted file mode 100644
> index 0df2c8f..0000000
> --- a/sysdeps/unix/sysv/linux/wordsize-64/getdents64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -/* getdents64 is in getdents.c */
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 4/7] Consolidate Linux getdents{64} implementation
  2018-04-17 19:42     ` Adhemerval Zanella
@ 2018-04-19 17:29       ` Joseph Myers
  2018-04-19 18:23         ` Adhemerval Zanella
  0 siblings, 1 reply; 21+ messages in thread
From: Joseph Myers @ 2018-04-19 17:29 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

I'm seeing:

/scratch/jmyers/glibc-bot/build/glibcs/mips64-linux-gnu-n32/glibc/libc_pic.a(getdents64.os): In function `__getdents64':
/scratch/jmyers/glibc-bot/build/glibcs/mips64-linux-gnu-n32/glibc-src/dirent/../sysdeps/unix/sysv/linux/mips/mips64/getdents64.c:29: multiple definition of `__getdents'
/scratch/jmyers/glibc-bot/build/glibcs/mips64-linux-gnu-n32/glibc/libc_pic.a(getdents.os):/scratch/jmyers/glibc-bot/build/glibcs/mips64-linux-gnu-n32/glibc-src/dirent/../sysdeps/unix/sysv/linux/getdents.c:35: first defined here

for which this change seems the likely cause.

https://sourceware.org/ml/libc-testresults/2018-q2/msg00093.html

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 4/7] Consolidate Linux getdents{64} implementation
  2018-04-19 17:29       ` Joseph Myers
@ 2018-04-19 18:23         ` Adhemerval Zanella
  0 siblings, 0 replies; 21+ messages in thread
From: Adhemerval Zanella @ 2018-04-19 18:23 UTC (permalink / raw)
  To: Joseph Myers; +Cc: libc-alpha



On 19/04/2018 14:29, Joseph Myers wrote:
> I'm seeing:
> 
> /scratch/jmyers/glibc-bot/build/glibcs/mips64-linux-gnu-n32/glibc/libc_pic.a(getdents64.os): In function `__getdents64':
> /scratch/jmyers/glibc-bot/build/glibcs/mips64-linux-gnu-n32/glibc-src/dirent/../sysdeps/unix/sysv/linux/mips/mips64/getdents64.c:29: multiple definition of `__getdents'
> /scratch/jmyers/glibc-bot/build/glibcs/mips64-linux-gnu-n32/glibc/libc_pic.a(getdents.os):/scratch/jmyers/glibc-bot/build/glibcs/mips64-linux-gnu-n32/glibc-src/dirent/../sysdeps/unix/sysv/linux/getdents.c:35: first defined here
> 
> for which this change seems the likely cause.
> 
> https://sourceware.org/ml/libc-testresults/2018-q2/msg00093.html
> 

It was a wrong last minute change, where I forgot that mips64n32
do not define _DIRENT_MATCHES_DIRENT64. I fixed it on master, thanks
for bring this up and sorry for the trouble.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 5/7] Consolidate scandir{at}{64} implementation
  2018-03-02 18:59 ` [PATCH 5/7] Consolidate scandir{at}{64} implementation Adhemerval Zanella
@ 2018-04-20 13:50   ` Adhemerval Zanella
  2018-04-20 15:30   ` Florian Weimer
  1 sibling, 0 replies; 21+ messages in thread
From: Adhemerval Zanella @ 2018-04-20 13:50 UTC (permalink / raw)
  To: libc-alpha

I will commit this shortly if no one opposes it.

On 02/03/2018 15:59, Adhemerval Zanella wrote:
> This patch consolidates scandir{at}{64} implementation on just
> the default dirent/scandir{at}{64}{_r}.c ones.  It changes the logic
> to follow the conventions used on other code consolidation:
> 
>   * scandir{at} is only built for _DIRENT_MATCHES_DIRENT64 being 0.
> 
>   * scandir{at}{64} is always built and aliased to getdents for ABIs
>     that define _DIRENT_MATCHES_DIRENT64 to 1.
> 
> Also on Linux the compat symbol for old non-LFS dirent64 definition
> requires a platform-specific scandir64.c.
> 
> Checked on aarch64-linux-gnu, x86_64-linux-gnu, i686-linux-gnu,
> sparcv9-linux-gnu, sparc64-linux-gnu, powerpc-linux-gnu, and
> powerpc64le-linux-gnu.
> 
> 	* dirent/scandir-tail-common.c: New file.
> 	* dirent/scandir-tail.c: Use scandir-tail-common.c.
> 	(__scandir_tail): Build iff _DIRENT_MATCHES_DIRENT64 is not defined.
> 	* dirent/scandir.c: Use scandir-tail-common.c.
> 	* dirent/scandirat.c: Likewise.
> 	* dirent/scandir64-tail.c: Use scandir-tail-common.c.
> 	* dirent/scandir64.c (scandir64): Always build and alias to scandir
> 	if _DIRENT_MATCHES_DIRENT64 is defined.
> 	* dirent/scandirat64.c (scandirat64): Likewise.
> 	* include/dirent.h (__scandir_tail): Only define iff
> 	_DIRENT_MATCHES_DIRENT64 is not defined.
> 	(__scandir64_tail): Define regardless.
> 	(__scandirat, scandirat64): Remove libc_hidden_proto.
> 	* sysdeps/unix/sysv/linux/arm/scandir64.c: Remove file.
> 	* sysdeps/unix/sysv/linux/m68k/scandir64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/scandir64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-32/scandir64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/scandir64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc32/scandir64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/scandir64.c: New file.
> ---
>  ChangeLog                                          |  21 +++++
>  dirent/scandir-tail-common.c                       | 103 +++++++++++++++++++++
>  dirent/scandir-tail.c                              |  95 ++-----------------
>  dirent/scandir.c                                   |  27 +-----
>  dirent/scandir64-tail.c                            |  10 +-
>  dirent/scandir64.c                                 |  23 +++--
>  dirent/scandirat.c                                 |  30 +-----
>  dirent/scandirat64.c                               |  23 +++--
>  include/dirent.h                                   |  18 ++--
>  sysdeps/unix/sysv/linux/arm/scandir64.c            |   1 -
>  sysdeps/unix/sysv/linux/m68k/scandir64.c           |   1 -
>  .../unix/sysv/linux/powerpc/powerpc32/scandir64.c  |   1 -
>  sysdeps/unix/sysv/linux/s390/s390-32/scandir64.c   |   1 -
>  sysdeps/unix/sysv/linux/{i386 => }/scandir64.c     |  37 ++++----
>  sysdeps/unix/sysv/linux/sparc/sparc32/scandir64.c  |   1 -
>  15 files changed, 198 insertions(+), 194 deletions(-)
>  create mode 100644 dirent/scandir-tail-common.c
>  delete mode 100644 sysdeps/unix/sysv/linux/arm/scandir64.c
>  delete mode 100644 sysdeps/unix/sysv/linux/m68k/scandir64.c
>  delete mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/scandir64.c
>  delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/scandir64.c
>  rename sysdeps/unix/sysv/linux/{i386 => }/scandir64.c (81%)
>  delete mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/scandir64.c
> 
> diff --git a/dirent/scandir-tail-common.c b/dirent/scandir-tail-common.c
> new file mode 100644
> index 0000000..f89cf77
> --- /dev/null
> +++ b/dirent/scandir-tail-common.c
> @@ -0,0 +1,103 @@
> +/* Common implementation for scandir{at}.
> +   Copyright (C) 2018 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
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <string.h>
> +#include <errno.h>
> +
> +int
> +SCANDIR_TAIL (DIR *dp,
> +              DIRENT_TYPE ***namelist,
> +              int (*select) (const DIRENT_TYPE *),
> +              int (*cmp) (const DIRENT_TYPE **, const DIRENT_TYPE **))
> +{
> +  if (dp == NULL)
> +    return -1;
> +
> +  int save = errno;
> +  __set_errno (0);
> +
> +  int result;
> +  struct scandir_cancel_struct c = { .dp = dp };
> +  __libc_cleanup_push (&__scandir_cancel_handler, &c);
> +
> +  DIRENT_TYPE **v = NULL;
> +  size_t vsize = 0;
> +  DIRENT_TYPE *d;
> +  while ((d = READDIR (dp)) != NULL)
> +    {
> +      if (select != NULL)
> +        {
> +          int selected = (*select) (d);
> +
> +	  /* The SELECT function might have set errno to non-zero on
> +	     success.  It was zero before and it needs to be again to
> +	     make the later tests work.  */
> +	  __set_errno (0);
> +
> +          if (!selected)
> +            continue;
> +        }
> +
> +      if (__glibc_unlikely (c.cnt == vsize))
> +        {
> +          if (vsize == 0)
> +            vsize = 10;
> +          else
> +            vsize *= 2;
> +          DIRENT_TYPE **new = realloc (v, vsize * sizeof *v);
> +          if (new == NULL)
> +            break;
> +          c.v = v = new;
> +        }
> +
> +      size_t dsize = &d->d_name[_D_ALLOC_NAMLEN (d)] - (char *) d;
> +      DIRENT_TYPE *vnew = malloc (dsize);
> +      if (vnew == NULL)
> +        break;
> +      v[c.cnt++] = (DIRENT_TYPE *) memcpy (vnew, d, dsize);
> +
> +      /* Ignore errors from readdir, malloc or realloc.  These functions
> +	 might have set errno to non-zero on success.  It was zero before
> +	 and it needs to be again to make the latter tests work.  */
> +      __set_errno (0);
> +    }
> +
> +  if (__glibc_likely (errno == 0))
> +    {
> +      __closedir (dp);
> +
> +      /* Sort the list if we have a comparison function to sort with.  */
> +      if (cmp != NULL)
> +	qsort (v, c.cnt, sizeof *v, (__compar_fn_t) cmp);
> +
> +      *namelist = v;
> +      result = c.cnt;
> +    }
> +  else
> +    {
> +      /* This frees everything and calls closedir.  */
> +      __scandir_cancel_handler (&c);
> +      result = -1;
> +    }
> +
> +  __libc_cleanup_pop (0);
> +
> +  if (result >= 0)
> +    __set_errno (save);
> +  return result;
> +}
> diff --git a/dirent/scandir-tail.c b/dirent/scandir-tail.c
> index 67c9c92..7395dc4 100644
> --- a/dirent/scandir-tail.c
> +++ b/dirent/scandir-tail.c
> @@ -17,96 +17,13 @@
>     <http://www.gnu.org/licenses/>.  */
>  
>  #include <dirent.h>
> -#include <errno.h>
> -#include <stdlib.h>
> -#include <string.h>
> -#include <libc-lock.h>
>  
> -#ifndef SCANDIR_TAIL
> -# define SCANDIR_TAIL	__scandir_tail
> -# define READDIR	__readdir
> -# define DIRENT_TYPE	struct dirent
> -#endif
> -
> -int
> -SCANDIR_TAIL (DIR *dp,
> -              DIRENT_TYPE ***namelist,
> -              int (*select) (const DIRENT_TYPE *),
> -              int (*cmp) (const DIRENT_TYPE **, const DIRENT_TYPE **))
> -{
> -  if (dp == NULL)
> -    return -1;
> -
> -  int save = errno;
> -  __set_errno (0);
> -
> -  int result;
> -  struct scandir_cancel_struct c = { .dp = dp };
> -  __libc_cleanup_push (&__scandir_cancel_handler, &c);
> -
> -  DIRENT_TYPE **v = NULL;
> -  size_t vsize = 0;
> -  DIRENT_TYPE *d;
> -  while ((d = READDIR (dp)) != NULL)
> -    {
> -      if (select != NULL)
> -        {
> -          int selected = (*select) (d);
> -
> -	  /* The SELECT function might have set errno to non-zero on
> -	     success.  It was zero before and it needs to be again to
> -	     make the later tests work.  */
> -	  __set_errno (0);
> -
> -          if (!selected)
> -            continue;
> -        }
> +#if !_DIRENT_MATCHES_DIRENT64
>  
> -      if (__glibc_unlikely (c.cnt == vsize))
> -        {
> -          if (vsize == 0)
> -            vsize = 10;
> -          else
> -            vsize *= 2;
> -          DIRENT_TYPE **new = realloc (v, vsize * sizeof *v);
> -          if (new == NULL)
> -            break;
> -          c.v = v = new;
> -        }
> +# define SCANDIR_TAIL  __scandir_tail
> +# define READDIR       __readdir
> +# define DIRENT_TYPE   struct dirent
>  
> -      size_t dsize = &d->d_name[_D_ALLOC_NAMLEN (d)] - (char *) d;
> -      DIRENT_TYPE *vnew = malloc (dsize);
> -      if (vnew == NULL)
> -        break;
> -      v[c.cnt++] = (DIRENT_TYPE *) memcpy (vnew, d, dsize);
> +# include <dirent/scandir-tail-common.c>
>  
> -      /* Ignore errors from readdir, malloc or realloc.  These functions
> -	 might have set errno to non-zero on success.  It was zero before
> -	 and it needs to be again to make the latter tests work.  */
> -      __set_errno (0);
> -    }
> -
> -  if (__glibc_likely (errno == 0))
> -    {
> -      __closedir (dp);
> -
> -      /* Sort the list if we have a comparison function to sort with.  */
> -      if (cmp != NULL)
> -	qsort (v, c.cnt, sizeof *v, (__compar_fn_t) cmp);
> -
> -      *namelist = v;
> -      result = c.cnt;
> -    }
> -  else
> -    {
> -      /* This frees everything and calls closedir.  */
> -      __scandir_cancel_handler (&c);
> -      result = -1;
> -    }
> -
> -  __libc_cleanup_pop (0);
> -
> -  if (result >= 0)
> -    __set_errno (save);
> -  return result;
> -}
> +#endif
> diff --git a/dirent/scandir.c b/dirent/scandir.c
> index b24e157..6d8352d 100644
> --- a/dirent/scandir.c
> +++ b/dirent/scandir.c
> @@ -15,31 +15,14 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> -/* We need to avoid the header declaration of scandir64, because
> -   the types don't match scandir and then the compiler will
> -   complain about the mismatch when we do the alias below.  */
> -#define scandir64       __renamed_scandir64
> -
>  #include <dirent.h>
>  
> -#undef  scandir64
> -
> -#ifndef SCANDIR
> -# define SCANDIR        scandir
> -# define SCANDIR_TAIL   __scandir_tail
> -# define DIRENT_TYPE    struct dirent
> -#endif
> -
> -
> +#if !_DIRENT_MATCHES_DIRENT64
>  int
> -SCANDIR (const char *dir,
> -	 DIRENT_TYPE ***namelist,
> -	 int (*select) (const DIRENT_TYPE *),
> -	 int (*cmp) (const DIRENT_TYPE **, const DIRENT_TYPE **))
> +scandir (const char *dir, struct dirent ***namelist,
> +	 int (*select) (const struct dirent *),
> +	 int (*cmp) (const struct dirent **, const struct dirent **))
>  {
> -  return SCANDIR_TAIL (__opendir (dir), namelist, select, cmp);
> +  return __scandir_tail (__opendir (dir), namelist, select, cmp);
>  }
> -
> -#if _DIRENT_MATCHES_DIRENT64
> -weak_alias (scandir, scandir64)
>  #endif
> diff --git a/dirent/scandir64-tail.c b/dirent/scandir64-tail.c
> index 8d5cc07..4e873d4 100644
> --- a/dirent/scandir64-tail.c
> +++ b/dirent/scandir64-tail.c
> @@ -18,9 +18,7 @@
>  
>  #include <dirent.h>
>  
> -#if !_DIRENT_MATCHES_DIRENT64
> -# define SCANDIR_TAIL   __scandir64_tail
> -# define READDIR        __readdir64
> -# define DIRENT_TYPE    struct dirent64
> -# include <scandir-tail.c>
> -#endif
> +#define SCANDIR_TAIL   __scandir64_tail
> +#define READDIR        __readdir64
> +#define DIRENT_TYPE    struct dirent64
> +#include <scandir-tail-common.c>
> diff --git a/dirent/scandir64.c b/dirent/scandir64.c
> index 0c63fa9..6bdd462 100644
> --- a/dirent/scandir64.c
> +++ b/dirent/scandir64.c
> @@ -15,15 +15,18 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> +#define scandir __no_scandir_decl
>  #include <dirent.h>
> -
> -/* scandir.c defines scandir64 as an alias if _DIRENT_MATCHES_DIRENT64.  */
> -#if !_DIRENT_MATCHES_DIRENT64
> -
> -# define SCANDIR        scandir64
> -# define SCANDIR_TAIL   __scandir64_tail
> -# define DIRENT_TYPE    struct dirent64
> -
> -# include <dirent/scandir.c>
> -
> +#undef scandir
> +
> +int
> +scandir64 (const char *dir, struct dirent64 ***namelist,
> +	   int (*select) (const struct dirent64 *),
> +	   int (*cmp) (const struct dirent64 **, const struct dirent64 **))
> +{
> +  return __scandir64_tail (__opendir (dir), namelist, select, cmp);
> +}
> +
> +#if _DIRENT_MATCHES_DIRENT64
> +weak_alias (scandir64, scandir)
>  #endif
> diff --git a/dirent/scandirat.c b/dirent/scandirat.c
> index 96a1b0e..8dad1e8 100644
> --- a/dirent/scandirat.c
> +++ b/dirent/scandirat.c
> @@ -15,35 +15,15 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> -/* We need to avoid the header declaration of scandir64, because
> -   the types don't match scandir and then the compiler will
> -   complain about the mismatch when we do the alias below.  */
> -#define scandirat64       __renamed_scandirat64
> -
>  #include <dirent.h>
>  
> -#undef  scandirat64
> -
> -#ifndef SCANDIRAT
> -# define SCANDIRAT	__scandirat
> -# define SCANDIR_TAIL	__scandir_tail
> -# define DIRENT_TYPE	struct dirent
> -# define SCANDIRAT_WEAK_ALIAS
> -#endif
> -
> +#if !_DIRENT_MATCHES_DIRENT64
>  int
> -SCANDIRAT (int dfd, const char *dir,
> -	   DIRENT_TYPE ***namelist,
> -	   int (*select) (const DIRENT_TYPE *),
> -	   int (*cmp) (const DIRENT_TYPE **, const DIRENT_TYPE **))
> +__scandirat (int dfd, const char *dir, struct dirent ***namelist,
> +	     int (*select) (const struct dirent *),
> +	     int (*cmp) (const struct dirent **, const struct dirent **))
>  {
> -  return SCANDIR_TAIL (__opendirat (dfd, dir), namelist, select, cmp);
> +  return __scandir_tail (__opendirat (dfd, dir), namelist, select, cmp);
>  }
> -libc_hidden_def (SCANDIRAT)
> -#ifdef SCANDIRAT_WEAK_ALIAS
>  weak_alias (__scandirat, scandirat)
>  #endif
> -
> -#if _DIRENT_MATCHES_DIRENT64
> -weak_alias (scandirat, scandirat64)
> -#endif
> diff --git a/dirent/scandirat64.c b/dirent/scandirat64.c
> index 520ae7c..7e5e209 100644
> --- a/dirent/scandirat64.c
> +++ b/dirent/scandirat64.c
> @@ -15,15 +15,18 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> +#define scandirat __no_scandirat_decl
>  #include <dirent.h>
> -
> -/* scandirat.c defines scandirat64 as an alias if _DIRENT_MATCHES_DIRENT64.  */
> -#if !_DIRENT_MATCHES_DIRENT64
> -
> -# define SCANDIRAT      scandirat64
> -# define SCANDIR_TAIL   __scandir64_tail
> -# define DIRENT_TYPE    struct dirent64
> -
> -# include <scandirat.c>
> -
> +#undef scandirat
> +
> +int
> +scandirat64 (int dfd, const char *dir, struct dirent64 ***namelist,
> +	     int (*select) (const struct dirent64 *),
> +	     int (*cmp) (const struct dirent64 **, const struct dirent64 **))
> +{
> +  return __scandir64_tail (__opendirat (dfd, dir), namelist, select, cmp);
> +}
> +
> +#if _DIRENT_MATCHES_DIRENT64
> +weak_alias (scandirat64, scandirat)
>  #endif
> diff --git a/include/dirent.h b/include/dirent.h
> index cc8f189..f8f1942 100644
> --- a/include/dirent.h
> +++ b/include/dirent.h
> @@ -57,25 +57,23 @@ extern int __scandir_tail (DIR *dp,
>  			   int (*cmp) (const struct dirent **,
>  				       const struct dirent **))
>    attribute_hidden;
> -#  if _DIRENT_MATCHES_DIRENT64
> -#   define __scandir64_tail (dp, namelist, select, cmp)         \
> -  __scandir_tail (dp, (struct dirent ***) (namelist),           \
> -		  (int (*) (const struct dirent *)) (select),   \
> -		  (int (*) (const struct dirent **,             \
> -			    const struct dirent **)) (cmp))
> -#  else
> +#  if !_DIRENT_MATCHES_DIRENT64
> +extern int __scandir_tail (DIR *dp,
> +			   struct dirent ***namelist,
> +			   int (*select) (const struct dirent *),
> +			   int (*cmp) (const struct dirent **,
> +					 const struct dirent **))
> +  attribute_hidden;
> +#  endif
>  extern int __scandir64_tail (DIR *dp,
>  			     struct dirent64 ***namelist,
>  			     int (*select) (const struct dirent64 *),
>  			     int (*cmp) (const struct dirent64 **,
>  					 const struct dirent64 **))
>    attribute_hidden;
> -#  endif
>  
>  libc_hidden_proto (__rewinddir)
>  extern __typeof (scandirat) __scandirat;
> -libc_hidden_proto (__scandirat)
> -libc_hidden_proto (scandirat64)
>  
>  #  if IS_IN (rtld) && !defined NO_RTLD_HIDDEN
>  extern __typeof (__rewinddir) __rewinddir attribute_hidden;
> diff --git a/sysdeps/unix/sysv/linux/arm/scandir64.c b/sysdeps/unix/sysv/linux/arm/scandir64.c
> deleted file mode 100644
> index 506fd88..0000000
> --- a/sysdeps/unix/sysv/linux/arm/scandir64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/scandir64.c>
> diff --git a/sysdeps/unix/sysv/linux/m68k/scandir64.c b/sysdeps/unix/sysv/linux/m68k/scandir64.c
> deleted file mode 100644
> index 506fd88..0000000
> --- a/sysdeps/unix/sysv/linux/m68k/scandir64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/scandir64.c>
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/scandir64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc32/scandir64.c
> deleted file mode 100644
> index 506fd88..0000000
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/scandir64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/scandir64.c>
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/scandir64.c b/sysdeps/unix/sysv/linux/s390/s390-32/scandir64.c
> deleted file mode 100644
> index 506fd88..0000000
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/scandir64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/scandir64.c>
> diff --git a/sysdeps/unix/sysv/linux/i386/scandir64.c b/sysdeps/unix/sysv/linux/scandir64.c
> similarity index 81%
> rename from sysdeps/unix/sysv/linux/i386/scandir64.c
> rename to sysdeps/unix/sysv/linux/scandir64.c
> index 50590c3..efb502f 100644
> --- a/sysdeps/unix/sysv/linux/i386/scandir64.c
> +++ b/sysdeps/unix/sysv/linux/scandir64.c
> @@ -15,26 +15,28 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> +#define scandir __no_scandir_decl
>  #include <dirent.h>
> +#undef scandir
>  
> -#define SCANDIR		__scandir64
> -#define SCANDIR_TAIL	__scandir64_tail
> -#define DIRENT_TYPE	struct dirent64
> -
> -#include <dirent/scandir.c>
> -
> -#undef	SCANDIR
> -#undef	SCANDIR_TAIL
> -#undef	DIRENT_TYPE
> -
> -#include <shlib-compat.h>
> +int
> +__scandir64 (const char *dir, struct dirent64 ***namelist,
> +	   int (*select) (const struct dirent64 *),
> +	   int (*cmp) (const struct dirent64 **, const struct dirent64 **))
> +{
> +  return __scandir64_tail (__opendir (dir), namelist, select, cmp);
> +}
>  
> +#if _DIRENT_MATCHES_DIRENT64
> +weak_alias (__scandir64, scandir64)
> +weak_alias (__scandir64, scandir)
> +#else
> +# include <shlib-compat.h>
>  versioned_symbol (libc, __scandir64, scandir64, GLIBC_2_2);
> -
> -#if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_2)
> -# include <string.h>
> -# include <errno.h>
> -# include "olddirent.h"
> +# if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_2)
> +#  include <string.h>
> +#  include <errno.h>
> +#  include "olddirent.h"
>  
>  int
>  __old_scandir64 (const char *dir, struct __old_dirent64 ***namelist,
> @@ -133,4 +135,5 @@ __old_scandir64 (const char *dir, struct __old_dirent64 ***namelist,
>  }
>  compat_symbol (libc, __old_scandir64, scandir64, GLIBC_2_1);
>  
> -#endif
> +# endif /* SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_2)  */
> +#endif /* _DIRENT_MATCHES_DIRENT64  */
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/scandir64.c b/sysdeps/unix/sysv/linux/sparc/sparc32/scandir64.c
> deleted file mode 100644
> index 506fd88..0000000
> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/scandir64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/scandir64.c>
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 5/7] Consolidate scandir{at}{64} implementation
  2018-03-02 18:59 ` [PATCH 5/7] Consolidate scandir{at}{64} implementation Adhemerval Zanella
  2018-04-20 13:50   ` Adhemerval Zanella
@ 2018-04-20 15:30   ` Florian Weimer
  2018-04-20 15:56     ` Adhemerval Zanella
  1 sibling, 1 reply; 21+ messages in thread
From: Florian Weimer @ 2018-04-20 15:30 UTC (permalink / raw)
  To: Adhemerval Zanella, libc-alpha

On 03/02/2018 07:59 PM, Adhemerval Zanella wrote:
>    * scandir{at}{64} is always built and aliased to getdents for ABIs
>      that define _DIRENT_MATCHES_DIRENT64 to 1.

This should probably say “scandir” instead of “getdents”.

Looks okay otherwise.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 5/7] Consolidate scandir{at}{64} implementation
  2018-04-20 15:30   ` Florian Weimer
@ 2018-04-20 15:56     ` Adhemerval Zanella
  0 siblings, 0 replies; 21+ messages in thread
From: Adhemerval Zanella @ 2018-04-20 15:56 UTC (permalink / raw)
  To: Florian Weimer, libc-alpha



On 20/04/2018 12:30, Florian Weimer wrote:
> On 03/02/2018 07:59 PM, Adhemerval Zanella wrote:
>>    * scandir{at}{64} is always built and aliased to getdents for ABIs
>>      that define _DIRENT_MATCHES_DIRENT64 to 1.
> 
> This should probably say “scandir” instead of “getdents”.
> 
> Looks okay otherwise.
> 
> Thanks,
> Florian

I will fix it, thanks.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 6/7] Consolidate alphasort{64} and versionsort{64} implementation
  2018-03-02 18:59 ` [PATCH 6/7] Consolidate alphasort{64} and versionsort{64} implementation Adhemerval Zanella
  2018-03-02 20:33   ` Joseph Myers
@ 2018-04-23 18:01   ` Adhemerval Zanella
  1 sibling, 0 replies; 21+ messages in thread
From: Adhemerval Zanella @ 2018-04-23 18:01 UTC (permalink / raw)
  To: libc-alpha

I will commit this shortly if no one opposes it.

On 02/03/2018 15:59, Adhemerval Zanella wrote:
> This patch consolidates both alphasort{64} and versionsort{64}
> implementation on just the default dirent/alphasort{64}c and
> dirent/versionsort{64} respectively.  It changes the logic
> to follow the conventions used on other code consolidation:
> 
>   * the non-LFS variant is only built for _DIRENT_MATCHES_DIRENT64 being 0.
> 
>   * the LFS variant is always built and aliased to getdents for ABIs
>     that define _DIRENT_MATCHES_DIRENT64 to 1.
> 
> Also on Linux the compat symbol for old non-LFS dirent64 definition
> requires a platform-specific scandir64.c.  For powerpc32 and sparcv9
> it requires to add specific arch-implementation to override the
> generic Linux one because neither ABI exports an compat symbol for
> non-LFS alphasort64 and versionsort64 variant.  Considering both
> architectures do export other compat symbols for other dirent.h
> functions I think this is a bug (I need confirmation).
> 
> Checked on aarch64-linux-gnu, x86_64-linux-gnu, i686-linux-gnu,
> sparcv9-linux-gnu, sparc64-linux-gnu, powerpc-linux-gnu, and
> powerpc64le-linux-gnu.
> 
> 	* dirent/alphasort.c (alphasort): Build iff _DIRENT_MATCHES_DIRENT64 is
> 	defined.
> 	* dirent/versionsort.c (versionsort): Likewise.
> 	* dirent/alphasort64.c (alphasort64): Build regardless and alias to
> 	alphasort if _DIRENT_MATCHES_DIRENT64 is defined.
> 	* dirent/versionsort64.c (versionsort64): Likewise.
> 	* sysdeps/unix/sysv/linux/i386/alphasort64.c: Remove file.
> 	* sysdeps/unix/sysv/linux/arm/alphasort64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/arm/versionsort64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/alphasort64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/versionsort64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-32/alphasort64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-32/versionsort64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/versionsort64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/alphasort64.c: New file.
> 	* sysdeps/unix/sysv/linux/versionsort64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/alphasort64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/versionsort64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc32/alphasort64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc32/versionsort64.c: Likewise.
> ---
>  ChangeLog                                          | 21 +++++++++++++++++++++
>  dirent/alphasort.c                                 | 13 ++-----------
>  dirent/alphasort64.c                               |  7 ++++---
>  dirent/versionsort.c                               | 12 ++----------
>  dirent/versionsort64.c                             |  7 ++++---
>  sysdeps/unix/sysv/linux/{i386 => }/alphasort64.c   | 22 +++++++++++-----------
>  sysdeps/unix/sysv/linux/arm/alphasort64.c          |  1 -
>  sysdeps/unix/sysv/linux/arm/versionsort64.c        |  1 -
>  sysdeps/unix/sysv/linux/m68k/alphasort64.c         |  1 -
>  sysdeps/unix/sysv/linux/m68k/versionsort64.c       |  1 -
>  .../sysv/linux/powerpc/powerpc32/alphasort64.c     |  3 +++
>  .../sysv/linux/powerpc/powerpc32/versionsort64.c   |  3 +++
>  sysdeps/unix/sysv/linux/s390/s390-32/alphasort64.c |  1 -
>  .../unix/sysv/linux/s390/s390-32/versionsort64.c   |  1 -
>  .../unix/sysv/linux/sparc/sparc32/alphasort64.c    |  3 +++
>  .../unix/sysv/linux/sparc/sparc32/versionsort64.c  |  3 +++
>  sysdeps/unix/sysv/linux/{i386 => }/versionsort64.c | 22 +++++++++++-----------
>  17 files changed, 67 insertions(+), 55 deletions(-)
>  rename sysdeps/unix/sysv/linux/{i386 => }/alphasort64.c (77%)
>  delete mode 100644 sysdeps/unix/sysv/linux/arm/alphasort64.c
>  delete mode 100644 sysdeps/unix/sysv/linux/arm/versionsort64.c
>  delete mode 100644 sysdeps/unix/sysv/linux/m68k/alphasort64.c
>  delete mode 100644 sysdeps/unix/sysv/linux/m68k/versionsort64.c
>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/alphasort64.c
>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/versionsort64.c
>  delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/alphasort64.c
>  delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/versionsort64.c
>  create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/alphasort64.c
>  create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/versionsort64.c
>  rename sysdeps/unix/sysv/linux/{i386 => }/versionsort64.c (77%)
> 
> diff --git a/dirent/alphasort.c b/dirent/alphasort.c
> index a6cd151..6b2a707 100644
> --- a/dirent/alphasort.c
> +++ b/dirent/alphasort.c
> @@ -15,23 +15,14 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> -/* We need to avoid the header declaration of alphasort64, because
> -   the types don't match alphasort and then the compiler will
> -   complain about the mismatch when we do the alias below.  */
> -#define alphasort64     __renamed_alphasort64
> -
>  #include <dirent.h>
>  
> -#undef  alphasort64
> -
> -#include <string.h>
> +#if !_DIRENT_MATCHES_DIRENT64
> +# include <string.h>
>  
>  int
>  alphasort (const struct dirent **a, const struct dirent **b)
>  {
>    return strcoll ((*a)->d_name, (*b)->d_name);
>  }
> -
> -#if _DIRENT_MATCHES_DIRENT64
> -weak_alias (alphasort, alphasort64)
>  #endif
> diff --git a/dirent/alphasort64.c b/dirent/alphasort64.c
> index 3a47a97..b822333 100644
> --- a/dirent/alphasort64.c
> +++ b/dirent/alphasort64.c
> @@ -15,16 +15,17 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> +#define alphasort __no_alphasort_decl
>  #include <dirent.h>
> +#undef alphasort
>  #include <string.h>
>  
> -/* alphasort.c defines alphasort64 as an alias if _DIRENT_MATCHES_DIRENT64.  */
> -#if !_DIRENT_MATCHES_DIRENT64
> -
>  int
>  alphasort64 (const struct dirent64 **a, const struct dirent64 **b)
>  {
>    return strcoll ((*a)->d_name, (*b)->d_name);
>  }
>  
> +#if _DIRENT_MATCHES_DIRENT64
> +weak_alias (alphasort64, alphasort)
>  #endif
> diff --git a/dirent/versionsort.c b/dirent/versionsort.c
> index 5ec15e8..ca38c2d 100644
> --- a/dirent/versionsort.c
> +++ b/dirent/versionsort.c
> @@ -15,16 +15,10 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> -/* We need to avoid the header declaration of versionsort64, because
> -   the types don't match versionsort and then the compiler will
> -   complain about the mismatch when we do the alias below.  */
> -#define versionsort64     __renamed_versionsort64
> -
>  #include <dirent.h>
>  
> -#undef  versionsort64
> -
> -#include <string.h>
> +#if !_DIRENT_MATCHES_DIRENT64
> +# include <string.h>
>  
>  int
>  versionsort (const struct dirent **a, const struct dirent **b)
> @@ -32,6 +26,4 @@ versionsort (const struct dirent **a, const struct dirent **b)
>    return __strverscmp ((*a)->d_name, (*b)->d_name);
>  }
>  
> -#if _DIRENT_MATCHES_DIRENT64
> -weak_alias (versionsort, versionsort64)
>  #endif
> diff --git a/dirent/versionsort64.c b/dirent/versionsort64.c
> index 7689c26..8f47e60 100644
> --- a/dirent/versionsort64.c
> +++ b/dirent/versionsort64.c
> @@ -15,16 +15,17 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> +#define versionsort __no_versionsort_decl
>  #include <dirent.h>
> +#undef versionsort
>  #include <string.h>
>  
> -/* versionsort.c defines a versionsort64 alias if _DIRENT_MATCHES_DIRENT64.  */
> -#if !_DIRENT_MATCHES_DIRENT64
> -
>  int
>  versionsort64 (const struct dirent64 **a, const struct dirent64 **b)
>  {
>    return __strverscmp ((*a)->d_name, (*b)->d_name);
>  }
>  
> +#if !_DIRENT_MATCHES_DIRENT64
> +weak_alias (versionsort64, versionsort)
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/i386/alphasort64.c b/sysdeps/unix/sysv/linux/alphasort64.c
> similarity index 77%
> rename from sysdeps/unix/sysv/linux/i386/alphasort64.c
> rename to sysdeps/unix/sysv/linux/alphasort64.c
> index ee3b00b..7eee9d0 100644
> --- a/sysdeps/unix/sysv/linux/i386/alphasort64.c
> +++ b/sysdeps/unix/sysv/linux/alphasort64.c
> @@ -15,7 +15,9 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> +#define alphasort __no_alphasort_decl
>  #include <dirent.h>
> +#undef alphasort
>  #include <string.h>
>  
>  int
> @@ -24,17 +26,14 @@ __alphasort64 (const struct dirent64 **a, const struct dirent64 **b)
>    return strcoll ((*a)->d_name, (*b)->d_name);
>  }
>  
> -#include <shlib-compat.h>
> -
> +#ifdef _DIRENT_MATCHES_DIRENT64
> +weak_alias (__alphasort64, alphasort64)
> +weak_alias (__alphasort64, alphasort)
> +#else
> +# include <shlib-compat.h>
>  versioned_symbol (libc, __alphasort64, alphasort64, GLIBC_2_2);
> -
> -#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
> -
> -#include <olddirent.h>
> -
> -int
> -__old_alphasort64 (const struct __old_dirent64 **a,
> -		   const struct __old_dirent64 **b);
> +# if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
> +#  include <olddirent.h>
>  
>  int
>  attribute_compat_text_section
> @@ -45,4 +44,5 @@ __old_alphasort64 (const struct __old_dirent64 **a,
>  }
>  
>  compat_symbol (libc, __old_alphasort64, alphasort64, GLIBC_2_1);
> -#endif
> +# endif /* SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)  */
> +#endif /* _DIRENT_MATCHES_DIRENT64  */
> diff --git a/sysdeps/unix/sysv/linux/arm/alphasort64.c b/sysdeps/unix/sysv/linux/arm/alphasort64.c
> deleted file mode 100644
> index 0b5ae47..0000000
> --- a/sysdeps/unix/sysv/linux/arm/alphasort64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/alphasort64.c>
> diff --git a/sysdeps/unix/sysv/linux/arm/versionsort64.c b/sysdeps/unix/sysv/linux/arm/versionsort64.c
> deleted file mode 100644
> index 144b691..0000000
> --- a/sysdeps/unix/sysv/linux/arm/versionsort64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/versionsort64.c>
> diff --git a/sysdeps/unix/sysv/linux/m68k/alphasort64.c b/sysdeps/unix/sysv/linux/m68k/alphasort64.c
> deleted file mode 100644
> index 0b5ae47..0000000
> --- a/sysdeps/unix/sysv/linux/m68k/alphasort64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/alphasort64.c>
> diff --git a/sysdeps/unix/sysv/linux/m68k/versionsort64.c b/sysdeps/unix/sysv/linux/m68k/versionsort64.c
> deleted file mode 100644
> index 144b691..0000000
> --- a/sysdeps/unix/sysv/linux/m68k/versionsort64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/versionsort64.c>
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/alphasort64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc32/alphasort64.c
> new file mode 100644
> index 0000000..c7de3a7
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/alphasort64.c
> @@ -0,0 +1,3 @@
> +/* Although powerpc32 define _DIRENT_MATCHES_DIRENT64=0 and have compat
> +   mode for 2.1, it does have a compat symbol for alphasort64.  */
> +#include <dirent/alphasort64.c>
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/versionsort64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc32/versionsort64.c
> new file mode 100644
> index 0000000..ee0e866
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/versionsort64.c
> @@ -0,0 +1,3 @@
> +/* Although powerpc32 define _DIRENT_MATCHES_DIRENT64=0 and have compat
> +   mode for 2.1, it does have a compat symbol for alphasort64.  */
> +#include <dirent/versionsort64.c>
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/alphasort64.c b/sysdeps/unix/sysv/linux/s390/s390-32/alphasort64.c
> deleted file mode 100644
> index 0b5ae47..0000000
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/alphasort64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/alphasort64.c>
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/versionsort64.c b/sysdeps/unix/sysv/linux/s390/s390-32/versionsort64.c
> deleted file mode 100644
> index 144b691..0000000
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/versionsort64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/unix/sysv/linux/i386/versionsort64.c>
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/alphasort64.c b/sysdeps/unix/sysv/linux/sparc/sparc32/alphasort64.c
> new file mode 100644
> index 0000000..3970086
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/alphasort64.c
> @@ -0,0 +1,3 @@
> +/* Although sparc32 define _DIRENT_MATCHES_DIRENT64=0 and have compat
> +   mode for 2.1, it does have a compat symbol for alphasort64.  */
> +#include <dirent/alphasort64.c>
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/versionsort64.c b/sysdeps/unix/sysv/linux/sparc/sparc32/versionsort64.c
> new file mode 100644
> index 0000000..b195442
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/versionsort64.c
> @@ -0,0 +1,3 @@
> +/* Although sparc32 define _DIRENT_MATCHES_DIRENT64=0 and have compat
> +   mode for 2.1, it does have a compat symbol for alphasort64.  */
> +#include <dirent/versionsort64.c>
> diff --git a/sysdeps/unix/sysv/linux/i386/versionsort64.c b/sysdeps/unix/sysv/linux/versionsort64.c
> similarity index 77%
> rename from sysdeps/unix/sysv/linux/i386/versionsort64.c
> rename to sysdeps/unix/sysv/linux/versionsort64.c
> index 1777eb2..a3a3a66 100644
> --- a/sysdeps/unix/sysv/linux/i386/versionsort64.c
> +++ b/sysdeps/unix/sysv/linux/versionsort64.c
> @@ -15,7 +15,9 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> +#define versionsort __no_versionsort_decl
>  #include <dirent.h>
> +#undef versionsort
>  #include <string.h>
>  
>  int
> @@ -24,17 +26,14 @@ __versionsort64 (const struct dirent64 **a, const struct dirent64 **b)
>    return __strverscmp ((*a)->d_name, (*b)->d_name);
>  }
>  
> -#include <shlib-compat.h>
> -
> +#if _DIRENT_MATCHES_DIRENT64
> +weak_alias (__versionsort64, versionsort64)
> +weak_alias (__versionsort64, versionsort)
> +#else
> +# include <shlib-compat.h>
>  versioned_symbol (libc, __versionsort64, versionsort64, GLIBC_2_2);
> -
> -#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
> -
> -#include <olddirent.h>
> -
> -int
> -__old_versionsort64 (const struct __old_dirent64 **a,
> -		     const struct __old_dirent64 **b);
> +# if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
> +#  include <olddirent.h>
>  
>  int
>  attribute_compat_text_section
> @@ -45,4 +44,5 @@ __old_versionsort64 (const struct __old_dirent64 **a,
>  }
>  
>  compat_symbol (libc, __old_versionsort64, versionsort64, GLIBC_2_1);
> -#endif
> +# endif /* SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)  */
> +#endif /* _DIRENT_MATCHES_DIRENT64  */
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 7/7] Consolidate getdirentries{64} implementation
  2018-03-02 18:59 ` [PATCH 7/7] Consolidate getdirentries{64} implementation Adhemerval Zanella
@ 2018-04-25 19:49   ` Adhemerval Zanella
  0 siblings, 0 replies; 21+ messages in thread
From: Adhemerval Zanella @ 2018-04-25 19:49 UTC (permalink / raw)
  To: libc-alpha

I will commit this shortly if no one opposes it.

On 02/03/2018 15:59, Adhemerval Zanella wrote:
> This patch consolidates Linux getdirentries{64} implementation on just
> the default sysdeps/unix/sysv/linux/getdirentries{64} ones.  The default
> implementation handles the Linux requirements:
> 
>   * getdirentries is only built for _DIRENT_MATCHES_DIRENT64 being 0.
> 
>   * getdirentries64 is always built and aliased to getdents for ABIs
>     that define _DIRENT_MATCHES_DIRENT64 to 1.
> 
> Checked on aarch64-linux-gnu, x86_64-linux-gnu, i686-linux-gnu,
> sparcv9-linux-gnu, sparc64-linux-gnu, powerpc-linux-gnu, and
> powerpc64le-linux-gnu.
> 
> 	* sysdeps/unix/sysv/linux/getdirentries.c (getdirentries): Build iff
> 	_DIRENT_MATCHES_DIRENT64 is not defined.
> 	* sysdeps/unix/sysv/linux/getdirentries64.c (getdirentries64): Open
> 	implementation and alias to getdirentries if _DIRENT_MATCHES_DIRENT64
> 	is defined.
> 	* sysdeps/unix/sysv/linux/wordsize-64/getdirentries.c: Remove file.
> 	* sysdeps/unix/sysv/linux/wordsize-64/getdirentries64.c: Remove file.
> ---
>  ChangeLog                                          |  8 +++++
>  sysdeps/unix/sysv/linux/getdirentries.c            | 21 +++++------
>  sysdeps/unix/sysv/linux/getdirentries64.c          | 41 ++++++++++++++++++++--
>  .../unix/sysv/linux/wordsize-64/getdirentries.c    |  3 --
>  .../unix/sysv/linux/wordsize-64/getdirentries64.c  |  1 -
>  5 files changed, 54 insertions(+), 20 deletions(-)
>  delete mode 100644 sysdeps/unix/sysv/linux/wordsize-64/getdirentries.c
>  delete mode 100644 sysdeps/unix/sysv/linux/wordsize-64/getdirentries64.c
> 
> diff --git a/sysdeps/unix/sysv/linux/getdirentries.c b/sysdeps/unix/sysv/linux/getdirentries.c
> index bc40292..23f626b 100644
> --- a/sysdeps/unix/sysv/linux/getdirentries.c
> +++ b/sysdeps/unix/sysv/linux/getdirentries.c
> @@ -16,26 +16,21 @@
>     <http://www.gnu.org/licenses/>.  */
>  
>  #include <dirent.h>
> -#include <unistd.h>
> -
> -#ifndef GETDIRENTRIES
> -# define GETDIRENTRIES getdirentries
> -# define __GETDENTS __getdents
> -#else
> -# define off_t off64_t
> -# define __lseek __lseek64
> -#endif
> +
> +#if !_DIRENT_MATCHES_DIRENT64
> +# include <unistd.h>
>  
>  ssize_t
> -GETDIRENTRIES (int fd, char *buf, size_t nbytes, off_t *basep)
> +getdirentries (int fd, char *buf, size_t nbytes, off_t *basep)
>  {
> -  off_t base = __lseek (fd, (off_t) 0, SEEK_CUR);
> -  ssize_t result;
> +  off_t base = __lseek (fd, 0, SEEK_CUR);
>  
> -  result = __GETDENTS (fd, buf, nbytes);
> +  ssize_t result = __getdents (fd, buf, nbytes);
>  
>    if (result != -1)
>      *basep = base;
>  
>    return result;
>  }
> +
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/getdirentries64.c b/sysdeps/unix/sysv/linux/getdirentries64.c
> index e486a36..c1a23a7 100644
> --- a/sysdeps/unix/sysv/linux/getdirentries64.c
> +++ b/sysdeps/unix/sysv/linux/getdirentries64.c
> @@ -1,3 +1,38 @@
> -#define GETDIRENTRIES getdirentries64
> -#define __GETDENTS __getdents64
> -#include "getdirentries.c"
> +/* Copyright (C) 1993-2018 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
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#define getdirentries __no_getdirentries_decl
> +#include <dirent.h>
> +#undef getdirentries
> +#include <unistd.h>
> +
> +ssize_t
> +getdirentries64 (int fd, char *buf, size_t nbytes, off64_t *basep)
> +{
> +  off64_t base = __lseek64 (fd, (off_t) 0, SEEK_CUR);
> +
> +  ssize_t result = __getdents64 (fd, buf, nbytes);
> +
> +  if (result != -1)
> +    *basep = base;
> +
> +  return result;
> +}
> +
> +#if _DIRENT_MATCHES_DIRENT64
> +weak_alias (getdirentries64, getdirentries)
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/wordsize-64/getdirentries.c b/sysdeps/unix/sysv/linux/wordsize-64/getdirentries.c
> deleted file mode 100644
> index 298d1e9..0000000
> --- a/sysdeps/unix/sysv/linux/wordsize-64/getdirentries.c
> +++ /dev/null
> @@ -1,3 +0,0 @@
> -#include "../getdirentries.c"
> -
> -weak_alias (getdirentries, getdirentries64)
> diff --git a/sysdeps/unix/sysv/linux/wordsize-64/getdirentries64.c b/sysdeps/unix/sysv/linux/wordsize-64/getdirentries64.c
> deleted file mode 100644
> index 622baf0..0000000
> --- a/sysdeps/unix/sysv/linux/wordsize-64/getdirentries64.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -/* Defined in getdirentries.c.  */
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2018-04-25 19:49 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-02 18:59 [PATCH 1/7] Assume O_DIRECTORY for opendir Adhemerval Zanella
2018-03-02 18:59 ` [PATCH 2/7] Define _DIRENT_MATCHES_DIRENT64 regardless Adhemerval Zanella
2018-03-02 19:30   ` Andreas Schwab
2018-03-02 18:59 ` [PATCH 3/7] Consolidate Linux readdir{64}{_r} implementation Adhemerval Zanella
2018-04-06 19:49   ` Adhemerval Zanella
2018-03-02 18:59 ` [PATCH 6/7] Consolidate alphasort{64} and versionsort{64} implementation Adhemerval Zanella
2018-03-02 20:33   ` Joseph Myers
2018-03-06 11:28     ` Adhemerval Zanella
2018-04-23 18:01   ` Adhemerval Zanella
2018-03-02 18:59 ` [PATCH 4/7] Consolidate Linux getdents{64} implementation Adhemerval Zanella
2018-03-09 18:10   ` Adhemerval Zanella
2018-04-17 19:42     ` Adhemerval Zanella
2018-04-19 17:29       ` Joseph Myers
2018-04-19 18:23         ` Adhemerval Zanella
2018-03-02 18:59 ` [PATCH 7/7] Consolidate getdirentries{64} implementation Adhemerval Zanella
2018-04-25 19:49   ` Adhemerval Zanella
2018-03-02 18:59 ` [PATCH 5/7] Consolidate scandir{at}{64} implementation Adhemerval Zanella
2018-04-20 13:50   ` Adhemerval Zanella
2018-04-20 15:30   ` Florian Weimer
2018-04-20 15:56     ` Adhemerval Zanella
2018-04-02 13:59 ` [PATCH 1/7] Assume O_DIRECTORY for opendir Adhemerval Zanella

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).