annotate osdep/scandir.c @ 23573:21c28c2645fe

Revert r23530. r23530 breaks policy: notification was not sent to mailing list, agreements of other devs were not received. Code also should be reviewed/cleaned up/fixed.
author voroshil
date Thu, 21 Jun 2007 08:18:51 +0000
parents 936209c39ed1
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
8288
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
1 /*
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
2 * scandir, alphasort - scan a directory
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
3 *
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
4 * implementation for systems that do not have it in libc
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
5 */
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
6
16985
08cac43f1e38 Unify include paths, -I.. is in CFLAGS.
diego
parents: 16061
diff changeset
7 #include "config.h"
8288
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
8
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
9 #include <sys/types.h>
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
10 #include <dirent.h>
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
11 #include <stdlib.h>
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
12 #include <stddef.h>
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
13 #include <string.h>
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
14
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
15 /*
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
16 * convenience helper function for scandir's |compar()| function:
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
17 * sort directory entries using strcoll(3)
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
18 */
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
19 int
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
20 alphasort(const void *_a, const void *_b)
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
21 {
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
22 struct dirent **a = (struct dirent **)_a;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
23 struct dirent **b = (struct dirent **)_b;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
24 return strcoll((*a)->d_name, (*b)->d_name);
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
25 }
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
26
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
27
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
28 #define strverscmp(a,b) strcoll(a,b) /* for now */
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
29
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
30 /*
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
31 * convenience helper function for scandir's |compar()| function:
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
32 * sort directory entries using GNU |strverscmp()|
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
33 */
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
34 int
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
35 versionsort(const void *_a, const void *_b)
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
36 {
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
37 struct dirent **a = (struct dirent **)_a;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
38 struct dirent **b = (struct dirent **)_b;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
39 return strverscmp((*a)->d_name, (*b)->d_name);
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
40 }
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
41
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
42 /*
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
43 * The scandir() function reads the directory dirname and builds an
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
44 * array of pointers to directory entries using malloc(3). It returns
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
45 * the number of entries in the array. A pointer to the array of
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
46 * directory entries is stored in the location referenced by namelist.
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
47 *
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
48 * The select parameter is a pointer to a user supplied subroutine
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
49 * which is called by scandir() to select which entries are to be
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
50 * included in the array. The select routine is passed a pointer to
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
51 * a directory entry and should return a non-zero value if the
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
52 * directory entry is to be included in the array. If select is null,
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
53 * then all the directory entries will be included.
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
54 *
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
55 * The compar parameter is a pointer to a user supplied subroutine
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
56 * which is passed to qsort(3) to sort the completed array. If this
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
57 * pointer is null, the array is not sorted.
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
58 */
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
59 int
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
60 scandir(const char *dirname,
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
61 struct dirent ***ret_namelist,
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
62 int (*select)(const struct dirent *),
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
63 int (*compar)(const struct dirent **, const struct dirent **))
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
64 {
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
65 int i, len;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
66 int used, allocated;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
67 DIR *dir;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
68 struct dirent *ent, *ent2;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
69 struct dirent **namelist = NULL;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
70
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
71 if ((dir = opendir(dirname)) == NULL)
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
72 return -1;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
73
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
74 used = 0;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
75 allocated = 2;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
76 namelist = malloc(allocated * sizeof(struct dirent *));
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
77 if (!namelist)
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
78 goto error;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
79
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
80 while ((ent = readdir(dir)) != NULL) {
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
81
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
82 if (select != NULL && !select(ent))
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
83 continue;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
84
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
85 /* duplicate struct direct for this entry */
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
86 len = offsetof(struct dirent, d_name) + strlen(ent->d_name) + 1;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
87 if ((ent2 = malloc(len)) == NULL)
16061
261022c048cd add some closedir() to fix some opendir() leaks
aurel
parents: 9380
diff changeset
88 goto error;
8288
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
89
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
90 if (used >= allocated) {
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
91 allocated *= 2;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
92 namelist = realloc(namelist, allocated * sizeof(struct dirent *));
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
93 if (!namelist)
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
94 goto error;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
95 }
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
96 memcpy(ent2, ent, len);
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
97 namelist[used++] = ent2;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
98 }
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
99 closedir(dir);
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
100
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
101 if (compar)
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
102 qsort(namelist, used, sizeof(struct dirent *),
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
103 (int (*)(const void *, const void *)) compar);
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
104
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
105 *ret_namelist = namelist;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
106 return used;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
107
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
108
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
109 error:
16061
261022c048cd add some closedir() to fix some opendir() leaks
aurel
parents: 9380
diff changeset
110 closedir(dir);
261022c048cd add some closedir() to fix some opendir() leaks
aurel
parents: 9380
diff changeset
111
8288
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
112 if (namelist) {
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
113 for (i = 0; i < used; i++)
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
114 free(namelist[i]);
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
115 free(namelist);
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
116 }
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
117 return -1;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
118 }
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
119
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
120
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
121 #if STANDALONE_MAIN
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
122 int
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
123 main(int argc, char **argv)
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
124 {
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
125 struct dirent **namelist;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
126 int i, n;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
127
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
128 n = scandir("/etc", &namelist, NULL, alphasort);
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
129
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
130 for (i = 0; i < n; i++)
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
131 printf("%s\n", namelist[i]->d_name);
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
132 }
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
133 #endif