Mercurial > mplayer.hg
annotate osdep/scandir.c @ 15093:b809a370e152
sync 1.167
author | wight |
---|---|
date | Sun, 10 Apr 2005 14:56:20 +0000 |
parents | edfe34c5405d |
children | 261022c048cd |
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 |