scandir.c raw

   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);
  48