scandir.c 1.0 KB

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