1 /* Copyright (C) 1992-1998, 2000, 2002, 2003, 2009 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 2, or (at your option) any
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
26 # include <bits/libc-lock.h>
29 #if ! defined __builtin_expect && __GNUC__ < 3
30 # define __builtin_expect(expr, expected) (expr)
37 # define SCANDIR scandir
38 # define READDIR __readdir
39 # define DIRENT_TYPE struct dirent
42 # define SCANDIR scandir
43 # define READDIR readdir
44 # define DIRENT_TYPE struct dirent
45 # define __opendir opendir
46 # define __closedir closedir
47 # define __set_errno(val) errno = (val)
49 /* The results of opendir() in this file are not used with dirfd and fchdir,
50 and we do not leak fds to any single-threaded code that could use stdio,
51 therefore save some unnecessary recursion in fchdir.c and opendir_safer.c.
52 FIXME - if the kernel ever adds support for multi-thread safety for
53 avoiding standard fds, then we should use opendir_safer. */
58 #ifndef SCANDIR_CANCEL
59 # define SCANDIR_CANCEL
60 struct scandir_cancel_struct
69 cancel_handler (void *arg)
71 struct scandir_cancel_struct *cp = arg;
75 for (i = 0; i < cp->cnt; ++i)
78 (void) __closedir (cp->dp);
85 SCANDIR (const char *dir,
86 DIRENT_TYPE ***namelist,
87 int (*select) (const DIRENT_TYPE *),
88 int (*cmp) (const DIRENT_TYPE **, const DIRENT_TYPE **))
90 DIR *dp = __opendir (dir);
91 DIRENT_TYPE **v = NULL;
93 struct scandir_cancel_struct c;
107 __libc_cleanup_push (cancel_handler, &c);
110 while ((d = READDIR (dp)) != NULL)
112 int use_it = select == NULL;
117 /* The select function might have changed errno. It was
118 zero before and it need to be again to make the latter
128 /* Ignore errors from select or readdir */
131 if (__builtin_expect (c.cnt == vsize, 0))
138 new = (DIRENT_TYPE **) realloc (v, vsize * sizeof (*v));
145 dsize = &d->d_name[_D_ALLOC_NAMLEN (d)] - (char *) d;
146 vnew = (DIRENT_TYPE *) malloc (dsize);
150 v[c.cnt++] = (DIRENT_TYPE *) memcpy (vnew, d, dsize);
154 if (__builtin_expect (errno, 0) != 0)
165 /* Sort the list if we have a comparison function to sort with. */
167 qsort (v, c.cnt, sizeof (*v), (int (*) (const void *, const void *)) cmp);
173 __libc_cleanup_pop (0);
176 (void) __closedir (dp);