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)
38 # define SCANDIR scandir
39 # define READDIR __readdir
40 # define DIRENT_TYPE struct dirent
43 # define SCANDIR scandir
44 # define READDIR readdir
45 # define DIRENT_TYPE struct dirent
46 # define __opendir opendir
47 # define __closedir closedir
48 # define __set_errno(val) errno = (val)
50 /* The results of opendir() in this file are not used with dirfd and fchdir,
51 and we do not leak fds to any single-threaded code that could use stdio,
52 therefore save some unnecessary recursion in fchdir.c and opendir_safer.c.
53 FIXME - if the kernel ever adds support for multi-thread safety for
54 avoiding standard fds, then we should use opendir_safer. */
59 #ifndef SCANDIR_CANCEL
60 # define SCANDIR_CANCEL
61 struct scandir_cancel_struct
70 cancel_handler (void *arg)
72 struct scandir_cancel_struct *cp = arg;
76 for (i = 0; i < cp->cnt; ++i)
79 (void) __closedir (cp->dp);
86 SCANDIR (const char *dir,
87 DIRENT_TYPE ***namelist,
88 int (*select) (const DIRENT_TYPE *),
89 int (*cmp) (const DIRENT_TYPE **, const DIRENT_TYPE **))
91 DIR *dp = __opendir (dir);
92 DIRENT_TYPE **v = NULL;
94 struct scandir_cancel_struct c;
108 __libc_cleanup_push (cancel_handler, &c);
111 while ((d = READDIR (dp)) != NULL)
113 int use_it = select == NULL;
118 /* The select function might have changed errno. It was
119 zero before and it need to be again to make the latter
129 /* Ignore errors from select or readdir */
132 if (__builtin_expect (c.cnt == vsize, 0))
139 new = (DIRENT_TYPE **) realloc (v, vsize * sizeof (*v));
146 dsize = &d->d_name[_D_ALLOC_NAMLEN (d)] - (char *) d;
147 vnew = (DIRENT_TYPE *) malloc (dsize);
151 v[c.cnt++] = (DIRENT_TYPE *) memcpy (vnew, d, dsize);
155 if (__builtin_expect (errno, 0) != 0)
166 /* Sort the list if we have a comparison function to sort with. */
168 qsort (v, c.cnt, sizeof (*v), (int (*) (const void *, const void *)) cmp);
174 __libc_cleanup_pop (0);
177 (void) __closedir (dp);