1 #include <dirent.h>
2 #include <stdlib.h>
3
4 #include "scandir.h"
5 #include "util.h"
6
ag_scandir(const char * dirname,struct dirent *** namelist,filter_fp filter,void * baton)7 int ag_scandir(const char *dirname,
8 struct dirent ***namelist,
9 filter_fp filter,
10 void *baton) {
11 DIR *dirp = NULL;
12 struct dirent **names = NULL;
13 struct dirent *entry, *d;
14 int names_len = 32;
15 int results_len = 0;
16
17 dirp = opendir(dirname);
18 if (dirp == NULL) {
19 goto fail;
20 }
21
22 names = malloc(sizeof(struct dirent *) * names_len);
23 if (names == NULL) {
24 goto fail;
25 }
26
27 while ((entry = readdir(dirp)) != NULL) {
28 if ((*filter)(dirname, entry, baton) == FALSE) {
29 continue;
30 }
31 if (results_len >= names_len) {
32 struct dirent **tmp_names = names;
33 names_len *= 2;
34 names = realloc(names, sizeof(struct dirent *) * names_len);
35 if (names == NULL) {
36 free(tmp_names);
37 goto fail;
38 }
39 }
40
41 #if defined(__MINGW32__) || defined(__CYGWIN__)
42 d = malloc(sizeof(struct dirent));
43 #else
44 d = malloc(_DIRENT_RECLEN(entry->d_namlen));
45 #endif
46
47 if (d == NULL) {
48 goto fail;
49 }
50 #if defined(__MINGW32__) || defined(__CYGWIN__)
51 memcpy(d, entry, sizeof(struct dirent));
52 #else
53 memcpy(d, entry, _DIRENT_RECLEN(entry->d_namlen));
54 #endif
55
56 names[results_len] = d;
57 results_len++;
58 }
59
60 closedir(dirp);
61 *namelist = names;
62 return results_len;
63
64 fail:
65 if (dirp) {
66 closedir(dirp);
67 }
68
69 if (names != NULL) {
70 int i;
71 for (i = 0; i < results_len; i++) {
72 free(names[i]);
73 }
74 free(names);
75 }
76 return -1;
77 }
78