missing dot
[mplayer/greg.git] / osdep / scandir.c
blob739e65571ac233df1bd12ff28377d0c2df338fd4
1 /*
2 * scandir, alphasort - scan a directory
4 * implementation for systems that do not have it in libc
5 */
7 #include "config.h"
9 #ifndef HAVE_SCANDIR
11 #include <sys/types.h>
12 #include <dirent.h>
13 #include <stdlib.h>
14 #include <stddef.h>
15 #include <string.h>
18 * convenience helper function for scandir's |compar()| function:
19 * sort directory entries using strcoll(3)
21 int
22 alphasort(const void *_a, const void *_b)
24 struct dirent **a = (struct dirent **)_a;
25 struct dirent **b = (struct dirent **)_b;
26 return strcoll((*a)->d_name, (*b)->d_name);
30 #define strverscmp(a,b) strcoll(a,b) /* for now */
33 * convenience helper function for scandir's |compar()| function:
34 * sort directory entries using GNU |strverscmp()|
36 int
37 versionsort(const void *_a, const void *_b)
39 struct dirent **a = (struct dirent **)_a;
40 struct dirent **b = (struct dirent **)_b;
41 return strverscmp((*a)->d_name, (*b)->d_name);
45 * The scandir() function reads the directory dirname and builds an
46 * array of pointers to directory entries using malloc(3). It returns
47 * the number of entries in the array. A pointer to the array of
48 * directory entries is stored in the location referenced by namelist.
50 * The select parameter is a pointer to a user supplied subroutine
51 * which is called by scandir() to select which entries are to be
52 * included in the array. The select routine is passed a pointer to
53 * a directory entry and should return a non-zero value if the
54 * directory entry is to be included in the array. If select is null,
55 * then all the directory entries will be included.
57 * The compar parameter is a pointer to a user supplied subroutine
58 * which is passed to qsort(3) to sort the completed array. If this
59 * pointer is null, the array is not sorted.
61 int
62 scandir(const char *dirname,
63 struct dirent ***ret_namelist,
64 int (*select)(const struct dirent *),
65 int (*compar)(const struct dirent **, const struct dirent **))
67 int i, len;
68 int used, allocated;
69 DIR *dir;
70 struct dirent *ent, *ent2;
71 struct dirent **namelist = NULL;
73 if ((dir = opendir(dirname)) == NULL)
74 return -1;
76 used = 0;
77 allocated = 2;
78 namelist = malloc(allocated * sizeof(struct dirent *));
79 if (!namelist)
80 goto error;
82 while ((ent = readdir(dir)) != NULL) {
84 if (select != NULL && !select(ent))
85 continue;
87 /* duplicate struct direct for this entry */
88 len = offsetof(struct dirent, d_name) + strlen(ent->d_name) + 1;
89 if ((ent2 = malloc(len)) == NULL)
90 goto error;
92 if (used >= allocated) {
93 allocated *= 2;
94 namelist = realloc(namelist, allocated * sizeof(struct dirent *));
95 if (!namelist)
96 goto error;
98 memcpy(ent2, ent, len);
99 namelist[used++] = ent2;
101 closedir(dir);
103 if (compar)
104 qsort(namelist, used, sizeof(struct dirent *),
105 (int (*)(const void *, const void *)) compar);
107 *ret_namelist = namelist;
108 return used;
111 error:
112 closedir(dir);
114 if (namelist) {
115 for (i = 0; i < used; i++)
116 free(namelist[i]);
117 free(namelist);
119 return -1;
121 #endif
124 #if STANDALONE_MAIN
126 main(int argc, char **argv)
128 struct dirent **namelist;
129 int i, n;
131 n = scandir("/etc", &namelist, NULL, alphasort);
133 for (i = 0; i < n; i++)
134 printf("%s\n", namelist[i]->d_name);
136 #endif