diff options
author | Ulrich Drepper <drepper@gmail.com> | 2011-08-09 09:57:55 -0400 |
---|---|---|
committer | Ulrich Drepper <drepper@gmail.com> | 2011-08-09 09:57:55 -0400 |
commit | c55fbd1ea768f9fdef34a01377702c0d72cbc213 (patch) | |
tree | 0e67d339ad240756843292384535c40cad03df95 /dirent/scandir.c | |
parent | 879165f25a1a6b13995e43c11e88b1a21b6f101e (diff) | |
download | glibc-c55fbd1ea768f9fdef34a01377702c0d72cbc213.tar.gz |
Implement scandirat function
Diffstat (limited to 'dirent/scandir.c')
-rw-r--r-- | dirent/scandir.c | 122 |
1 files changed, 3 insertions, 119 deletions
diff --git a/dirent/scandir.c b/dirent/scandir.c index e90b942b1d..3f69a8db77 100644 --- a/dirent/scandir.c +++ b/dirent/scandir.c @@ -18,44 +18,14 @@ 02111-1307 USA. */ #include <dirent.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <bits/libc-lock.h> +#include <fcntl.h> #ifndef SCANDIR # define SCANDIR scandir -# define READDIR __readdir +# define SCANDIRAT scandirat # define DIRENT_TYPE struct dirent #endif -#ifndef SCANDIR_CANCEL -# define SCANDIR_CANCEL -struct scandir_cancel_struct -{ - DIR *dp; - void *v; - size_t cnt; -}; - -# 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); -} -# else -extern void __scandir_cancel_handler (void *arg); -# endif -#endif - int SCANDIR (dir, namelist, select, cmp) @@ -64,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 (__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; + return SCANDIRAT (AT_FDCWD, dir, namelist, select, cmp); } |