diff options
author | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2018-03-01 09:04:41 -0300 |
---|---|---|
committer | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2018-04-20 13:57:12 -0300 |
commit | c0123b3b1118419210879e935620eb2ad987c2f1 (patch) | |
tree | dd8d6ead4be0d0f492b5e8e10996595097463bf9 | |
parent | 458b94f63e6fc5af1582a98007a1e4769f785fb7 (diff) | |
download | glibc-c0123b3b1118419210879e935620eb2ad987c2f1.zip glibc-c0123b3b1118419210879e935620eb2ad987c2f1.tar.gz glibc-c0123b3b1118419210879e935620eb2ad987c2f1.tar.bz2 |
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.
-rw-r--r-- | ChangeLog | 23 | ||||
-rw-r--r-- | dirent/scandir-tail-common.c | 103 | ||||
-rw-r--r-- | dirent/scandir-tail.c | 95 | ||||
-rw-r--r-- | dirent/scandir.c | 27 | ||||
-rw-r--r-- | dirent/scandir64-tail.c | 10 | ||||
-rw-r--r-- | dirent/scandir64.c | 23 | ||||
-rw-r--r-- | dirent/scandirat.c | 30 | ||||
-rw-r--r-- | dirent/scandirat64.c | 23 | ||||
-rw-r--r-- | include/dirent.h | 18 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/arm/scandir64.c | 1 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/m68k/scandir64.c | 1 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/powerpc32/scandir64.c | 1 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/s390/s390-32/scandir64.c | 1 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/scandir64.c (renamed from sysdeps/unix/sysv/linux/i386/scandir64.c) | 37 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/sparc/sparc32/scandir64.c | 1 |
15 files changed, 200 insertions, 194 deletions
@@ -1,3 +1,26 @@ +2018-04-20 Adhemerval Zanella <adhemerval.zanella@linaro.org> + + * 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 <joseph@codesourcery.com> * 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 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 e533b0b..400835e 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 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 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> |