annotate osdep/scandir.c @ 20962:a95ed9a69caf

Put files fully owned by my under GPL v2 "or later"
author reimar
date Fri, 17 Nov 2006 10:03:33 +0000
parents 08cac43f1e38
children 936209c39ed1
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 #ifndef HAVE_SCANDIR
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
10
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
11 #include <sys/types.h>
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
12 #include <dirent.h>
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
13 #include <stdlib.h>
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
14 #include <stddef.h>
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
15 #include <string.h>
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
16
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
17 /*
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
18 * 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
19 * sort directory entries using strcoll(3)
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
20 */
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
21 int
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
22 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
23 {
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
24 struct dirent **a = (struct dirent **)_a;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
25 struct dirent **b = (struct dirent **)_b;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
26 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
27 }
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
28
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 #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
31
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
32 /*
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
33 * 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
34 * sort directory entries using GNU |strverscmp()|
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
35 */
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
36 int
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
37 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
38 {
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
39 struct dirent **a = (struct dirent **)_a;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
40 struct dirent **b = (struct dirent **)_b;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
41 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
42 }
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
43
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
44 /*
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
45 * 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
46 * 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
47 * 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
48 * 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
49 *
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
50 * 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
51 * 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
52 * 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
53 * 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
54 * 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
55 * 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
56 *
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
57 * 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
58 * 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
59 * 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
60 */
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
61 int
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
62 scandir(const char *dirname,
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
63 struct dirent ***ret_namelist,
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
64 int (*select)(const struct dirent *),
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
65 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
66 {
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
67 int i, len;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
68 int used, allocated;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
69 DIR *dir;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
70 struct dirent *ent, *ent2;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
71 struct dirent **namelist = NULL;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
72
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
73 if ((dir = opendir(dirname)) == NULL)
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
74 return -1;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
75
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
76 used = 0;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
77 allocated = 2;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
78 namelist = malloc(allocated * sizeof(struct dirent *));
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
79 if (!namelist)
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
80 goto error;
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 while ((ent = readdir(dir)) != NULL) {
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
83
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
84 if (select != NULL && !select(ent))
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
85 continue;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
86
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
87 /* duplicate struct direct for this entry */
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
88 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
89 if ((ent2 = malloc(len)) == NULL)
16061
261022c048cd add some closedir() to fix some opendir() leaks
aurel
parents: 9380
diff changeset
90 goto error;
8288
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
91
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
92 if (used >= allocated) {
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
93 allocated *= 2;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
94 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
95 if (!namelist)
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
96 goto error;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
97 }
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
98 memcpy(ent2, ent, len);
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
99 namelist[used++] = ent2;
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 closedir(dir);
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
102
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
103 if (compar)
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
104 qsort(namelist, used, sizeof(struct dirent *),
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
105 (int (*)(const void *, const void *)) compar);
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
106
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
107 *ret_namelist = namelist;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
108 return used;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
109
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
110
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
111 error:
16061
261022c048cd add some closedir() to fix some opendir() leaks
aurel
parents: 9380
diff changeset
112 closedir(dir);
261022c048cd add some closedir() to fix some opendir() leaks
aurel
parents: 9380
diff changeset
113
8288
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
114 if (namelist) {
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
115 for (i = 0; i < used; i++)
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
116 free(namelist[i]);
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
117 free(namelist);
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 return -1;
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 #endif
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
122
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
123
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
124 #if STANDALONE_MAIN
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
125 int
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
126 main(int argc, char **argv)
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 struct dirent **namelist;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
129 int i, n;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
130
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
131 n = scandir("/etc", &namelist, NULL, alphasort);
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 for (i = 0; i < n; i++)
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
134 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
135 }
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
136 #endif