Mercurial > mplayer.hg
annotate osdep/scandir.c @ 23035:e8afcfccf359
Always deallocate glyphs. Fixes a memory leak.
author | eugeni |
---|---|
date | Sat, 21 Apr 2007 10:56:28 +0000 |
parents | 936209c39ed1 |
children |
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 | 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 | 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 | 110 closedir(dir); |
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 |