github.com/afumu/libc@v0.0.6/musl/src/dirent/scandir.c (about)

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