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)
50 #ifndef SCANDIR_CANCEL
51 # define SCANDIR_CANCEL
52 struct scandir_cancel_struct
61 cancel_handler (void *arg)
63 struct scandir_cancel_struct *cp = arg;
67 for (i = 0; i < cp->cnt; ++i)
70 (void) __closedir (cp->dp);
77 SCANDIR (const char *dir,
78 DIRENT_TYPE ***namelist,
79 int (*select) (const DIRENT_TYPE *),
80 int (*cmp) (const DIRENT_TYPE **, const DIRENT_TYPE **))
82 DIR *dp = __opendir (dir);
83 DIRENT_TYPE **v = NULL;
85 struct scandir_cancel_struct c;
99 __libc_cleanup_push (cancel_handler, &c);
102 while ((d = READDIR (dp)) != NULL)
104 int use_it = select == NULL;
109 /* The select function might have changed errno. It was
110 zero before and it need to be again to make the latter
120 /* Ignore errors from select or readdir */
123 if (__builtin_expect (c.cnt == vsize, 0))
130 new = (DIRENT_TYPE **) realloc (v, vsize * sizeof (*v));
137 dsize = &d->d_name[_D_ALLOC_NAMLEN (d)] - (char *) d;
138 vnew = (DIRENT_TYPE *) malloc (dsize);
142 v[c.cnt++] = (DIRENT_TYPE *) memcpy (vnew, d, dsize);
146 if (__builtin_expect (errno, 0) != 0)
157 /* Sort the list if we have a comparison function to sort with. */
159 qsort (v, c.cnt, sizeof (*v), (int (*) (const void *, const void *)) cmp);
165 __libc_cleanup_pop (0);
168 (void) __closedir (dp);