From c0123b3b1118419210879e935620eb2ad987c2f1 Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Thu, 1 Mar 2018 09:04:41 -0300 Subject: [PATCH] Consolidate scandir{at}{64} implementation 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 | 23 ++++ dirent/scandir-tail-common.c | 103 ++++++++++++++++++ dirent/scandir-tail.c | 99 ++--------------- dirent/scandir.c | 27 +---- dirent/scandir64-tail.c | 10 +- dirent/scandir64.c | 19 ++-- dirent/scandirat.c | 30 +---- dirent/scandirat64.c | 19 ++-- include/dirent.h | 18 ++- sysdeps/unix/sysv/linux/arm/scandir64.c | 1 - sysdeps/unix/sysv/linux/m68k/scandir64.c | 1 - .../sysv/linux/powerpc/powerpc32/scandir64.c | 1 - .../unix/sysv/linux/s390/s390-32/scandir64.c | 1 - .../unix/sysv/linux/{i386 => }/scandir64.c | 37 ++++--- .../unix/sysv/linux/sparc/sparc32/scandir64.c | 1 - 15 files changed, 198 insertions(+), 192 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/ChangeLog b/ChangeLog index 3cac21d194..3f2c533acd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2018-04-20 Adhemerval Zanella + + * 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. + 2018-04-20 Joseph Myers * sysdeps/unix/sysv/linux/aarch64/bits/hwcap.h (HWCAP_ASIMDFHM): diff --git a/dirent/scandir-tail-common.c b/dirent/scandir-tail-common.c new file mode 100644 index 0000000000..f89cf77b56 --- /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 + . */ + +#include +#include + +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 67c9c92d65..7395dc4a26 100644 --- a/dirent/scandir-tail.c +++ b/dirent/scandir-tail.c @@ -17,96 +17,13 @@ . */ #include -#include -#include -#include -#include -#ifndef SCANDIR_TAIL -# define SCANDIR_TAIL __scandir_tail -# define READDIR __readdir -# define DIRENT_TYPE struct dirent +#if !_DIRENT_MATCHES_DIRENT64 + +# define SCANDIR_TAIL __scandir_tail +# define READDIR __readdir +# define DIRENT_TYPE struct dirent + +# include + #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 (__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.c b/dirent/scandir.c index b24e15724c..6d8352dc9c 100644 --- a/dirent/scandir.c +++ b/dirent/scandir.c @@ -15,31 +15,14 @@ License along with the GNU C Library; if not, see . */ -/* 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 -#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 8d5cc07748..4e873d47d6 100644 --- a/dirent/scandir64-tail.c +++ b/dirent/scandir64-tail.c @@ -18,9 +18,7 @@ #include -#if !_DIRENT_MATCHES_DIRENT64 -# define SCANDIR_TAIL __scandir64_tail -# define READDIR __readdir64 -# define DIRENT_TYPE struct dirent64 -# include -#endif +#define SCANDIR_TAIL __scandir64_tail +#define READDIR __readdir64 +#define DIRENT_TYPE struct dirent64 +#include diff --git a/dirent/scandir64.c b/dirent/scandir64.c index 0c63fa97ef..6bdd4628ad 100644 --- a/dirent/scandir64.c +++ b/dirent/scandir64.c @@ -15,15 +15,18 @@ License along with the GNU C Library; if not, see . */ +#define scandir __no_scandir_decl #include +#undef scandir -/* 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 +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 96a1b0ed30..8dad1e8a21 100644 --- a/dirent/scandirat.c +++ b/dirent/scandirat.c @@ -15,35 +15,15 @@ License along with the GNU C Library; if not, see . */ -/* 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 -#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 520ae7cad7..7e5e209cdf 100644 --- a/dirent/scandirat64.c +++ b/dirent/scandirat64.c @@ -15,15 +15,18 @@ License along with the GNU C Library; if not, see . */ +#define scandirat __no_scandirat_decl #include +#undef scandirat -/* 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 +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 e533b0b59d..400835eefe 100644 --- a/include/dirent.h +++ b/include/dirent.h @@ -58,25 +58,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 506fd8877c..0000000000 --- a/sysdeps/unix/sysv/linux/arm/scandir64.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/sysdeps/unix/sysv/linux/m68k/scandir64.c b/sysdeps/unix/sysv/linux/m68k/scandir64.c deleted file mode 100644 index 506fd8877c..0000000000 --- a/sysdeps/unix/sysv/linux/m68k/scandir64.c +++ /dev/null @@ -1 +0,0 @@ -#include 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 506fd8877c..0000000000 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/scandir64.c +++ /dev/null @@ -1 +0,0 @@ -#include 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 506fd8877c..0000000000 --- a/sysdeps/unix/sysv/linux/s390/s390-32/scandir64.c +++ /dev/null @@ -1 +0,0 @@ -#include 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 50590c3f74..efb502f6e4 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 . */ +#define scandir __no_scandir_decl #include +#undef scandir -#define SCANDIR __scandir64 -#define SCANDIR_TAIL __scandir64_tail -#define DIRENT_TYPE struct dirent64 - -#include - -#undef SCANDIR -#undef SCANDIR_TAIL -#undef DIRENT_TYPE - -#include +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 versioned_symbol (libc, __scandir64, scandir64, GLIBC_2_2); - -#if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_2) -# include -# include -# include "olddirent.h" +# if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_2) +# include +# include +# 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 506fd8877c..0000000000 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/scandir64.c +++ /dev/null @@ -1 +0,0 @@ -#include