From 098e6c37e3835dee6506593d88313502f35b0987 Mon Sep 17 00:00:00 2001 From: joseph Date: Tue, 6 Sep 2011 15:08:18 +0000 Subject: Merge changes between r14661 and r15223 from /fsf/trunk. git-svn-id: svn://svn.eglibc.org/trunk@15224 7b3dc134-2b1b-0410-93df-9e9f96275f8d --- libc/dirent/Makefile | 5 +- libc/dirent/Versions | 3 + libc/dirent/dirent.h | 45 ++++++++++++++- libc/dirent/opendir.c | 13 ++++- libc/dirent/scandir.c | 125 +++------------------------------------- libc/dirent/scandir64.c | 10 +--- libc/dirent/scandirat.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++ libc/dirent/scandirat64.c | 26 +++++++++ 8 files changed, 238 insertions(+), 133 deletions(-) create mode 100644 libc/dirent/scandirat.c create mode 100644 libc/dirent/scandirat64.c (limited to 'libc/dirent') diff --git a/libc/dirent/Makefile b/libc/dirent/Makefile index ef639f209..07f706e67 100644 --- a/libc/dirent/Makefile +++ b/libc/dirent/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1991-2000,2002,2003,2005,2006 Free Software Foundation, Inc. +# Copyright (C) 1991-2000,2002,2003,2005,2006,2011 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 @@ -25,7 +25,8 @@ headers := dirent.h bits/dirent.h routines := opendir closedir readdir readdir_r rewinddir \ seekdir telldir scandir alphasort versionsort \ getdents getdents64 dirfd readdir64 readdir64_r scandir64 \ - alphasort64 versionsort64 fdopendir + alphasort64 versionsort64 fdopendir \ + scandirat scandirat64 distribute := dirstream.h tests := list tst-seekdir opendir-tst1 bug-readdir1 tst-fdopendir \ diff --git a/libc/dirent/Versions b/libc/dirent/Versions index 41c158442..d976d373f 100644 --- a/libc/dirent/Versions +++ b/libc/dirent/Versions @@ -44,4 +44,7 @@ libc { GLIBC_2.4 { fdopendir; } + GLIBC_2.15 { + scandirat; scandirat64; + } } diff --git a/libc/dirent/dirent.h b/libc/dirent/dirent.h index bb4ede158..6a5a0ef81 100644 --- a/libc/dirent/dirent.h +++ b/libc/dirent/dirent.h @@ -1,4 +1,5 @@ -/* Copyright (C) 1991-2000,2003-2005,2009,2010 Free Software Foundation, Inc. +/* Copyright (C) 1991-2000,2003-2005,2009,2010,2011 + 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 @@ -247,7 +248,10 @@ extern int dirfd (DIR *__dirp) __THROW __nonnull ((1)); /* Scan the directory DIR, calling SELECTOR on each directory entry. Entries for which SELECT returns nonzero are individually malloc'd, sorted using qsort with CMP, and collected in a malloc'd array in - *NAMELIST. Returns the number of entries selected, or -1 on error. */ + *NAMELIST. Returns the number of entries selected, or -1 on error. + + This function is a cancellation point and therefore not marked with + __THROW. */ # ifndef __USE_FILE_OFFSET64 extern int scandir (__const char *__restrict __dir, struct dirent ***__restrict __namelist, @@ -280,6 +284,43 @@ extern int scandir64 (__const char *__restrict __dir, __nonnull ((1, 2)); # endif +# ifdef __USE_GNU +/* Similar to `scandir' but a relative DIR name is interpreted relative + to the directory for which DFD is a descriptor. + + This function is a cancellation point and therefore not marked with + __THROW. */ +# ifndef __USE_FILE_OFFSET64 +extern int scandirat (int __dfd, __const char *__restrict __dir, + struct dirent ***__restrict __namelist, + int (*__selector) (__const struct dirent *), + int (*__cmp) (__const struct dirent **, + __const struct dirent **)) + __nonnull ((2, 3)); +# else +# ifdef __REDIRECT +extern int __REDIRECT (scandirat, + (int __dfd, __const char *__restrict __dir, + struct dirent ***__restrict __namelist, + int (*__selector) (__const struct dirent *), + int (*__cmp) (__const struct dirent **, + __const struct dirent **)), + scandirat64) __nonnull ((2, 3)); +# else +# define scandirat scandirat64 +# endif +# endif + +/* This function is like `scandir' but it uses the 64bit dirent structure. + Please note that the CMP function must now work with struct dirent64 **. */ +extern int scandirat64 (int __dfd, __const char *__restrict __dir, + struct dirent64 ***__restrict __namelist, + int (*__selector) (__const struct dirent64 *), + int (*__cmp) (__const struct dirent64 **, + __const struct dirent64 **)) + __nonnull ((2, 3)); +# endif + /* Function to compare two `struct dirent's alphabetically. */ # ifndef __USE_FILE_OFFSET64 extern int alphasort (__const struct dirent **__e1, diff --git a/libc/dirent/opendir.c b/libc/dirent/opendir.c index 771013f6e..6375b6786 100644 --- a/libc/dirent/opendir.c +++ b/libc/dirent/opendir.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1995, 1996, 1997, 2011 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 @@ -21,13 +21,20 @@ #include -/* Open a directory stream on NAME. */ DIR * -__opendir (const char *name) +__opendirat (int dfd, const char *name) { __set_errno (ENOSYS); return NULL; } + + +/* Open a directory stream on NAME. */ +DIR * +__opendir (const char *name) +{ + return __opendirat (AT_FDCWD, name); +} weak_alias (__opendir, opendir) stub_warning (opendir) diff --git a/libc/dirent/scandir.c b/libc/dirent/scandir.c index 2e03578a3..3f69a8db7 100644 --- a/libc/dirent/scandir.c +++ b/libc/dirent/scandir.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1992-1998,2000,2002,2003,2009 Free Software Foundation, Inc. +/* Copyright (C) 1992-1998,2000,2002,2003,2009,2011 + 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 @@ -17,38 +18,12 @@ 02111-1307 USA. */ #include -#include -#include -#include -#include +#include #ifndef SCANDIR -#define SCANDIR scandir -#define READDIR __readdir -#define DIRENT_TYPE struct dirent -#endif - -#ifndef SCANDIR_CANCEL -#define SCANDIR_CANCEL -struct scandir_cancel_struct -{ - DIR *dp; - void *v; - size_t cnt; -}; - -static void -cancel_handler (void *arg) -{ - struct scandir_cancel_struct *cp = arg; - size_t i; - void **v = cp->v; - - for (i = 0; i < cp->cnt; ++i) - free (v[i]); - free (v); - (void) __closedir (cp->dp); -} +# define SCANDIR scandir +# define SCANDIRAT scandirat +# define DIRENT_TYPE struct dirent #endif @@ -59,91 +34,5 @@ SCANDIR (dir, namelist, select, cmp) int (*select) (const DIRENT_TYPE *); int (*cmp) (const DIRENT_TYPE **, const DIRENT_TYPE **); { - DIR *dp = __opendir (dir); - DIRENT_TYPE **v = NULL; - size_t vsize = 0; - struct scandir_cancel_struct c; - DIRENT_TYPE *d; - int save; - - if (dp == NULL) - return -1; - - save = errno; - __set_errno (0); - - c.dp = dp; - c.v = NULL; - c.cnt = 0; - __libc_cleanup_push (cancel_handler, &c); - - while ((d = READDIR (dp)) != NULL) - { - int use_it = select == NULL; - - if (! use_it) - { - use_it = select (d); - /* The select function might have changed errno. It was - zero before and it need to be again to make the latter - tests work. */ - __set_errno (0); - } - - if (use_it) - { - DIRENT_TYPE *vnew; - size_t dsize; - - /* Ignore errors from select or readdir */ - __set_errno (0); - - if (__builtin_expect (c.cnt == vsize, 0)) - { - DIRENT_TYPE **new; - if (vsize == 0) - vsize = 10; - else - vsize *= 2; - new = (DIRENT_TYPE **) realloc (v, vsize * sizeof (*v)); - if (new == NULL) - break; - v = new; - c.v = (void *) v; - } - - dsize = &d->d_name[_D_ALLOC_NAMLEN (d)] - (char *) d; - vnew = (DIRENT_TYPE *) malloc (dsize); - if (vnew == NULL) - break; - - v[c.cnt++] = (DIRENT_TYPE *) memcpy (vnew, d, dsize); - } - } - - if (__builtin_expect (errno, 0) != 0) - { - save = errno; - - while (c.cnt > 0) - free (v[--c.cnt]); - free (v); - c.cnt = -1; - } - else - { - /* Sort the list if we have a comparison function to sort with. */ - if (cmp != NULL) - qsort (v, c.cnt, sizeof (*v), - (int (*) (const void *, const void *)) cmp); - - *namelist = v; - } - - __libc_cleanup_pop (0); - - (void) __closedir (dp); - __set_errno (save); - - return c.cnt; + return SCANDIRAT (AT_FDCWD, dir, namelist, select, cmp); } diff --git a/libc/dirent/scandir64.c b/libc/dirent/scandir64.c index b7bd65465..21a936e4b 100644 --- a/libc/dirent/scandir64.c +++ b/libc/dirent/scandir64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000, 2009 Free Software Foundation, Inc. +/* Copyright (C) 2000, 2009, 2011 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 @@ -19,13 +19,7 @@ #include #define SCANDIR scandir64 -#define READDIR __readdir64 +#define SCANDIRAT scandirat64 #define DIRENT_TYPE struct dirent64 -int scandir64 (__const char *__restrict __dir, - struct dirent64 ***__restrict __namelist, - int (*__selector) (__const struct dirent64 *), - int (*__cmp) (__const struct dirent64 **, - __const struct dirent64 **)); - #include diff --git a/libc/dirent/scandirat.c b/libc/dirent/scandirat.c new file mode 100644 index 000000000..3eda9702e --- /dev/null +++ b/libc/dirent/scandirat.c @@ -0,0 +1,144 @@ +/* Copyright (C) 1992-1998,2000,2002,2003,2009,2011 + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +#ifndef SCANDIRAT +# define SCANDIRAT scandirat +# define READDIR __readdir +# define DIRENT_TYPE struct dirent +#endif + +#ifndef SKIP_SCANDIR_CANCEL +void +__scandir_cancel_handler (void *arg) +{ + struct scandir_cancel_struct *cp = arg; + size_t i; + void **v = cp->v; + + for (i = 0; i < cp->cnt; ++i) + free (v[i]); + free (v); + (void) __closedir (cp->dp); +} +#endif + + +int +SCANDIRAT (dfd, dir, namelist, select, cmp) + int dfd; + const char *dir; + DIRENT_TYPE ***namelist; + int (*select) (const DIRENT_TYPE *); + int (*cmp) (const DIRENT_TYPE **, const DIRENT_TYPE **); +{ + DIR *dp = __opendirat (dfd, dir); + DIRENT_TYPE **v = NULL; + size_t vsize = 0; + struct scandir_cancel_struct c; + DIRENT_TYPE *d; + int save; + + if (dp == NULL) + return -1; + + save = errno; + __set_errno (0); + + c.dp = dp; + c.v = NULL; + c.cnt = 0; + __libc_cleanup_push (__scandir_cancel_handler, &c); + + while ((d = READDIR (dp)) != NULL) + { + int use_it = select == NULL; + + if (! use_it) + { + use_it = select (d); + /* The select function might have changed errno. It was + zero before and it need to be again to make the latter + tests work. */ + __set_errno (0); + } + + if (use_it) + { + DIRENT_TYPE *vnew; + size_t dsize; + + /* Ignore errors from select or readdir */ + __set_errno (0); + + if (__builtin_expect (c.cnt == vsize, 0)) + { + DIRENT_TYPE **new; + if (vsize == 0) + vsize = 10; + else + vsize *= 2; + new = (DIRENT_TYPE **) realloc (v, vsize * sizeof (*v)); + if (new == NULL) + break; + v = new; + c.v = (void *) v; + } + + dsize = &d->d_name[_D_ALLOC_NAMLEN (d)] - (char *) d; + vnew = (DIRENT_TYPE *) malloc (dsize); + if (vnew == NULL) + break; + + v[c.cnt++] = (DIRENT_TYPE *) memcpy (vnew, d, dsize); + } + } + + if (__builtin_expect (errno, 0) != 0) + { + save = errno; + + while (c.cnt > 0) + free (v[--c.cnt]); + free (v); + c.cnt = -1; + } + else + { + /* Sort the list if we have a comparison function to sort with. */ + if (cmp != NULL) + qsort (v, c.cnt, sizeof (*v), + (int (*) (const void *, const void *)) cmp); + + *namelist = v; + } + + __libc_cleanup_pop (0); + + (void) __closedir (dp); + __set_errno (save); + + return c.cnt; +} +libc_hidden_def (SCANDIRAT) diff --git a/libc/dirent/scandirat64.c b/libc/dirent/scandirat64.c new file mode 100644 index 000000000..d41bdd1d6 --- /dev/null +++ b/libc/dirent/scandirat64.c @@ -0,0 +1,26 @@ +/* Copyright (C) 2000, 2009, 2011 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#define SCANDIRAT scandirat64 +#define READDIR __readdir64 +#define DIRENT_TYPE struct dirent64 +#define SKIP_SCANDIR_CANCEL 1 + +#include "scandirat.c" -- cgit v1.2.3