Message ID | 1520017165-15830-5-git-send-email-adhemerval.zanella@linaro.org |
---|---|
State | Accepted |
Commit | c0123b3b1118419210879e935620eb2ad987c2f1 |
Headers | show |
Series | [1/7] Assume O_DIRECTORY for opendir | expand |
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> >
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
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.
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>