comparison osdep/scandir.c @ 9380:edfe34c5405d

linux->osdep
author arpi
date Sun, 09 Feb 2003 20:18:23 +0000
parents linux/scandir.c@25fd5c47e31a
children 261022c048cd
comparison
equal deleted inserted replaced
9379:475bb1a6ef75 9380:edfe34c5405d
1 /*
2 * scandir, alphasort - scan a directory
3 *
4 * implementation for systems that do not have it in libc
5 */
6
7 #include "../config.h"
8
9 #ifndef HAVE_SCANDIR
10
11 #include <sys/types.h>
12 #include <dirent.h>
13 #include <stdlib.h>
14 #include <stddef.h>
15 #include <string.h>
16
17 /*
18 * convenience helper function for scandir's |compar()| function:
19 * sort directory entries using strcoll(3)
20 */
21 int
22 alphasort(const void *_a, const void *_b)
23 {
24 struct dirent **a = (struct dirent **)_a;
25 struct dirent **b = (struct dirent **)_b;
26 return strcoll((*a)->d_name, (*b)->d_name);
27 }
28
29
30 #define strverscmp(a,b) strcoll(a,b) /* for now */
31
32 /*
33 * convenience helper function for scandir's |compar()| function:
34 * sort directory entries using GNU |strverscmp()|
35 */
36 int
37 versionsort(const void *_a, const void *_b)
38 {
39 struct dirent **a = (struct dirent **)_a;
40 struct dirent **b = (struct dirent **)_b;
41 return strverscmp((*a)->d_name, (*b)->d_name);
42 }
43
44 /*
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.
49 *
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.
56 *
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.
60 */
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 **))
66 {
67 int i, len;
68 int used, allocated;
69 DIR *dir;
70 struct dirent *ent, *ent2;
71 struct dirent **namelist = NULL;
72
73 if ((dir = opendir(dirname)) == NULL)
74 return -1;
75
76 used = 0;
77 allocated = 2;
78 namelist = malloc(allocated * sizeof(struct dirent *));
79 if (!namelist)
80 goto error;
81
82 while ((ent = readdir(dir)) != NULL) {
83
84 if (select != NULL && !select(ent))
85 continue;
86
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 return -1;
91
92 if (used >= allocated) {
93 allocated *= 2;
94 namelist = realloc(namelist, allocated * sizeof(struct dirent *));
95 if (!namelist)
96 goto error;
97 }
98 memcpy(ent2, ent, len);
99 namelist[used++] = ent2;
100 }
101 closedir(dir);
102
103 if (compar)
104 qsort(namelist, used, sizeof(struct dirent *),
105 (int (*)(const void *, const void *)) compar);
106
107 *ret_namelist = namelist;
108 return used;
109
110
111 error:
112 if (namelist) {
113 for (i = 0; i < used; i++)
114 free(namelist[i]);
115 free(namelist);
116 }
117 return -1;
118 }
119 #endif
120
121
122 #if STANDALONE_MAIN
123 int
124 main(int argc, char **argv)
125 {
126 struct dirent **namelist;
127 int i, n;
128
129 n = scandir("/etc", &namelist, NULL, alphasort);
130
131 for (i = 0; i < n; i++)
132 printf("%s\n", namelist[i]->d_name);
133 }
134 #endif