1 /* Copyright (C) 1992-1998, 2000, 2002-2003, 2009-2010 Free Software
3 This file is part of the GNU C Library.
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
27 # include <bits/libc-lock.h>
30 #if ! defined __builtin_expect && __GNUC__ < 3
31 # define __builtin_expect(expr, expected) (expr)
36 #ifndef _D_EXACT_NAMLEN
37 # define _D_EXACT_NAMLEN(d) strlen ((d)->d_name)
39 #ifndef _D_ALLOC_NAMLEN
40 # define _D_ALLOC_NAMLEN(d) (_D_EXACT_NAMLEN (d) + 1)
45 # define SCANDIR scandir
46 # define READDIR __readdir
47 # define DIRENT_TYPE struct dirent
50 # define SCANDIR scandir
51 # define READDIR readdir
52 # define DIRENT_TYPE struct dirent
53 # define __opendir opendir
54 # define __closedir closedir
55 # define __set_errno(val) errno = (val)
57 /* The results of opendir() in this file are not used with dirfd and fchdir,
58 and we do not leak fds to any single-threaded code that could use stdio,
59 therefore save some unnecessary recursion in fchdir.c and opendir_safer.c.
60 FIXME - if the kernel ever adds support for multi-thread safety for
61 avoiding standard fds, then we should use opendir_safer. */
66 #ifndef SCANDIR_CANCEL
67 # define SCANDIR_CANCEL
68 struct scandir_cancel_struct
77 cancel_handler (void *arg)
79 struct scandir_cancel_struct *cp = arg;
83 for (i = 0; i < cp->cnt; ++i)
86 (void) __closedir (cp->dp);
93 SCANDIR (const char *dir,
94 DIRENT_TYPE ***namelist,
95 int (*select) (const DIRENT_TYPE *),
96 int (*cmp) (const DIRENT_TYPE **, const DIRENT_TYPE **))
98 DIR *dp = __opendir (dir);
99 DIRENT_TYPE **v = NULL;
101 struct scandir_cancel_struct c;
115 __libc_cleanup_push (cancel_handler, &c);
118 while ((d = READDIR (dp)) != NULL)
120 int use_it = select == NULL;
125 /* The select function might have changed errno. It was
126 zero before and it need to be again to make the latter
136 /* Ignore errors from select or readdir */
139 if (__builtin_expect (c.cnt == vsize, 0))
146 new = (DIRENT_TYPE **) realloc (v, vsize * sizeof (*v));
153 dsize = &d->d_name[_D_ALLOC_NAMLEN (d)] - (char *) d;
154 vnew = (DIRENT_TYPE *) malloc (dsize);
158 v[c.cnt++] = (DIRENT_TYPE *) memcpy (vnew, d, dsize);
162 if (__builtin_expect (errno, 0) != 0)
173 /* Sort the list if we have a comparison function to sort with. */
175 qsort (v, c.cnt, sizeof (*v), (int (*) (const void *, const void *)) cmp);
181 __libc_cleanup_pop (0);
184 (void) __closedir (dp);