annotate osdep/scandir.c @ 12398:45595c6fbe0a

Restore ftp support (was erroneusly disabled while fixing bogus errors on conection failure)
author rtognimp
date Sun, 02 May 2004 20:05:44 +0000
parents edfe34c5405d
children 261022c048cd
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
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
7 #include "../config.h"
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)
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
90 return -1;
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:
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 #endif
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
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
122 #if STANDALONE_MAIN
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
123 int
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
124 main(int argc, char **argv)
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
125 {
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
126 struct dirent **namelist;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
127 int i, n;
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
128
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
129 n = scandir("/etc", &namelist, NULL, alphasort);
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 for (i = 0; i < n; i++)
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
132 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
133 }
25fd5c47e31a Add a scandir() implementation for systems that do not have it in libc.
jkeil
parents:
diff changeset
134 #endif