xref: /aosp_15_r20/external/musl/src/dirent/scandir.c (revision c9945492fdd68bbe62686c5b452b4dc1be3f8453)
1*c9945492SAndroid Build Coastguard Worker #include <dirent.h>
2*c9945492SAndroid Build Coastguard Worker #include <string.h>
3*c9945492SAndroid Build Coastguard Worker #include <stdlib.h>
4*c9945492SAndroid Build Coastguard Worker #include <stdint.h>
5*c9945492SAndroid Build Coastguard Worker #include <errno.h>
6*c9945492SAndroid Build Coastguard Worker #include <stddef.h>
7*c9945492SAndroid Build Coastguard Worker 
scandir(const char * path,struct dirent *** res,int (* sel)(const struct dirent *),int (* cmp)(const struct dirent **,const struct dirent **))8*c9945492SAndroid Build Coastguard Worker int scandir(const char *path, struct dirent ***res,
9*c9945492SAndroid Build Coastguard Worker 	int (*sel)(const struct dirent *),
10*c9945492SAndroid Build Coastguard Worker 	int (*cmp)(const struct dirent **, const struct dirent **))
11*c9945492SAndroid Build Coastguard Worker {
12*c9945492SAndroid Build Coastguard Worker 	DIR *d = opendir(path);
13*c9945492SAndroid Build Coastguard Worker 	struct dirent *de, **names=0, **tmp;
14*c9945492SAndroid Build Coastguard Worker 	size_t cnt=0, len=0;
15*c9945492SAndroid Build Coastguard Worker 	int old_errno = errno;
16*c9945492SAndroid Build Coastguard Worker 
17*c9945492SAndroid Build Coastguard Worker 	if (!d) return -1;
18*c9945492SAndroid Build Coastguard Worker 
19*c9945492SAndroid Build Coastguard Worker 	while ((errno=0), (de = readdir(d))) {
20*c9945492SAndroid Build Coastguard Worker 		if (sel && !sel(de)) continue;
21*c9945492SAndroid Build Coastguard Worker 		if (cnt >= len) {
22*c9945492SAndroid Build Coastguard Worker 			len = 2*len+1;
23*c9945492SAndroid Build Coastguard Worker 			if (len > SIZE_MAX/sizeof *names) break;
24*c9945492SAndroid Build Coastguard Worker 			tmp = realloc(names, len * sizeof *names);
25*c9945492SAndroid Build Coastguard Worker 			if (!tmp) break;
26*c9945492SAndroid Build Coastguard Worker 			names = tmp;
27*c9945492SAndroid Build Coastguard Worker 		}
28*c9945492SAndroid Build Coastguard Worker 		names[cnt] = malloc(de->d_reclen);
29*c9945492SAndroid Build Coastguard Worker 		if (!names[cnt]) break;
30*c9945492SAndroid Build Coastguard Worker 		memcpy(names[cnt++], de, de->d_reclen);
31*c9945492SAndroid Build Coastguard Worker 	}
32*c9945492SAndroid Build Coastguard Worker 
33*c9945492SAndroid Build Coastguard Worker 	closedir(d);
34*c9945492SAndroid Build Coastguard Worker 
35*c9945492SAndroid Build Coastguard Worker 	if (errno) {
36*c9945492SAndroid Build Coastguard Worker 		if (names) while (cnt-->0) free(names[cnt]);
37*c9945492SAndroid Build Coastguard Worker 		free(names);
38*c9945492SAndroid Build Coastguard Worker 		return -1;
39*c9945492SAndroid Build Coastguard Worker 	}
40*c9945492SAndroid Build Coastguard Worker 	errno = old_errno;
41*c9945492SAndroid Build Coastguard Worker 
42*c9945492SAndroid Build Coastguard Worker 	if (cmp) qsort(names, cnt, sizeof *names, (int (*)(const void *, const void *))cmp);
43*c9945492SAndroid Build Coastguard Worker 	*res = names;
44*c9945492SAndroid Build Coastguard Worker 	return cnt;
45*c9945492SAndroid Build Coastguard Worker }
46