10 static char **get_dir_list(const char *path)
17 * HACK: MinGW provides numerous POSIX extensions to MSVCRT,
18 * including dirent.h, so parasti ever so lazily has not bothered
19 * to port the code below to FindFirstFile et al.
22 if ((dir = opendir(path)))
26 files = malloc(sizeof (char *));
28 while ((ent = readdir(dir)))
30 if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
33 files[count++] = strdup(ent->d_name);
34 files = realloc(files, (count + 1) * sizeof (char *));
45 static void free_dir_list(void *files)
51 /* Free file names. */
52 for (file = files; *file; free(*file++));
54 /* Free trailing NULL. */
57 /* Free pointer list. */
62 static struct dir_item *add_item(Array items, const char *dir, const char *name)
64 struct dir_item *item = array_add(items);
66 item->path = *dir ? concat_string(dir, "/", name, NULL) : strdup(name);
72 static void del_item(Array items)
74 struct dir_item *item = array_get(items, array_len(items) - 1);
76 free((void *) item->path);
83 * Scan the directory PATH and return an array of dir_item structures
84 * for which FILTER evaluates to non-zero (or all, if FILTER is NULL).
85 * FILTER can associate data with a dir_item for later use by
86 * assigning it to the "data" member. If GET_LIST is non-NULL, it is
87 * used to obtain a NULL-terminated list of names in PATH; this list
88 * is later freed with FREE_LIST. If both are NULL, the default
89 * directory listing mechanism is used.
91 * (FIXME: GET_LIST was added to reduce code duplication when
92 * maintaining the existing "real file system" directory scanning
93 * functionality and at the same time supporting "virtual file system"
94 * directory scanning using custom routines. The result of this is
95 * that dir_scan becomes a ridiculously general piece of code to
96 * "filter and turn an arbitrary list of strings into an array of
97 * dir_item structs". This is too confusing; it's probably better to
98 * support VFS only and adapt accordingly.)
100 Array dir_scan(const char *path,
101 int (*filter) (struct dir_item *),
102 char **(*get_list) (const char *),
103 void (*free_list)(void *))
108 assert((get_list && free_list) || (!get_list && !free_list));
111 get_list = get_dir_list;
114 free_list = free_dir_list;
116 if ((list = get_list(path)))
120 items = array_new(sizeof (struct dir_item));
124 struct dir_item *item;
126 item = add_item(items, path, *file);
128 if (filter && !filter(item))
140 void dir_free(Array items)
142 while (array_len(items))