1 /* Logic guts of scandir*.
2 Copyright (C) 1992-2018 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library 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 GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
23 #include <libc-lock.h>
26 # define SCANDIR_TAIL __scandir_tail
27 # define READDIR __readdir
28 # define DIRENT_TYPE struct dirent
32 SCANDIR_TAIL (DIR *dp
,
33 DIRENT_TYPE
***namelist
,
34 int (*select
) (const DIRENT_TYPE
*),
35 int (*cmp
) (const DIRENT_TYPE
**, const DIRENT_TYPE
**))
44 struct scandir_cancel_struct c
= { .dp
= dp
};
45 __libc_cleanup_push (&__scandir_cancel_handler
, &c
);
47 DIRENT_TYPE
**v
= NULL
;
50 while ((d
= READDIR (dp
)) != NULL
)
54 int selected
= (*select
) (d
);
56 /* The SELECT function might have set errno to non-zero on
57 success. It was zero before and it needs to be again to
58 make the later tests work. */
65 if (__glibc_unlikely (c
.cnt
== vsize
))
71 DIRENT_TYPE
**new = realloc (v
, vsize
* sizeof *v
);
77 size_t dsize
= &d
->d_name
[_D_ALLOC_NAMLEN (d
)] - (char *) d
;
78 DIRENT_TYPE
*vnew
= malloc (dsize
);
81 v
[c
.cnt
++] = (DIRENT_TYPE
*) memcpy (vnew
, d
, dsize
);
83 /* Ignore errors from readdir, malloc or realloc. These functions
84 might have set errno to non-zero on success. It was zero before
85 and it needs to be again to make the latter tests work. */
89 if (__glibc_likely (errno
== 0))
93 /* Sort the list if we have a comparison function to sort with. */
95 qsort (v
, c
.cnt
, sizeof *v
, (__compar_fn_t
) cmp
);
102 /* This frees everything and calls closedir. */
103 __scandir_cancel_handler (&c
);
107 __libc_cleanup_pop (0);