2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * $FreeBSD: src/lib/libc/gen/scandir.c,v 1.5.6.1 2001/03/05 09:52:13 obrien Exp $
31 * @(#)scandir.c 8.3 (Berkeley) 1/2/94
35 * Scan the directory dirname calling select to make a list of selected
36 * directory entries then sort using qsort and compare routine dcomp.
37 * Returns the number of entries and a pointer to a list of pointers to
38 * struct dirent (through namelist). Returns -1 if there were any errors.
41 #include "namespace.h"
42 #include <sys/types.h>
48 #include "un-namespace.h"
50 #include "gen_private.h"
53 scandir(const char *dirname
, struct dirent
***namelist
,
54 int (*select
)(const struct dirent
*),
55 int (*dcomp
)(const struct dirent
**, const struct dirent
**))
57 struct dirent
*d
, *p
, **names
= NULL
;
58 size_t arraysz
, nitems
= 0;
62 if ((dirp
= opendir(dirname
)) == NULL
)
64 if (_fstat(dirp
->dd_fd
, &stb
) < 0)
68 * Estimate the array size by taking the size of the directory file
69 * and dividing it by a multiple of the minimum size entry.
70 * Ensure that the size does fit into memory without overflooding.
72 if (stb
.st_size
/ 24 > SIZE_T_MAX
)
74 arraysz
= stb
.st_size
/ 24;
75 names
= (struct dirent
**)malloc(arraysz
* sizeof(struct dirent
*));
79 while ((d
= readdir(dirp
)) != NULL
) {
80 if (select
!= NULL
&& !(*select
)(d
))
81 continue; /* just selected names */
83 * Make a minimum size copy of the data
85 p
= (struct dirent
*)malloc(_DIRENT_DIRSIZ(d
));
89 p
->d_type
= d
->d_type
;
90 p
->d_namlen
= d
->d_namlen
;
91 bcopy(d
->d_name
, p
->d_name
, p
->d_namlen
+ 1);
93 * Check to make sure the array has space left and
94 * realloc the maximum size.
96 if (nitems
>= arraysz
) {
97 const int inc
= 10; /* increase by this much */
98 struct dirent
**names2
;
100 names2
= (struct dirent
**)realloc((char *)names
,
101 (arraysz
+ inc
) * sizeof(struct dirent
*));
102 if (names2
== NULL
) {
112 if (nitems
&& dcomp
!= NULL
)
113 qsort(names
, nitems
, sizeof(struct dirent
*),
114 (int (*)(const void *, const void *))dcomp
);
120 free(names
[--nitems
]);
127 * Alphabetic order comparison routine for those who want it.
130 alphasort(const struct dirent
**d1
, const struct dirent
**d2
)
132 return(strcmp((*d1
)->d_name
, (*d2
)->d_name
));