1 /*
2 t4k_replacements.c
3
4 Replacements for functions not present locally on a system.
5
6 Copyright 2007, 2008, 2009, 2010.
7 Authors: David Bruce, Aviral Dasgupta, Hatari Project
8 Project email: <tuxmath-devel@lists.sourceforge.net>
9 Project website: http://tux4kids.alioth.debian.org
10
11 t4k_replacements.c is part of the t4k_common library.
12
13 t4k_common is free software: you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 3 of the License, or
16 (at your option) any later version.
17
18 t4k_common is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program. If not, see <http://www.gnu.org/licenses/>. */
25
26 #include "config.h"
27
28 #include <dirent.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <strings.h>
32 #include <stdio.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37
38 /* TODO Is this required at all? */
39 #ifdef WIN32
40 # undef DATADIR
41 # include <windows.h>
42 #endif /* WIN32 */
43
44 /* Prefer strcoll, but use strcmp otherwise, for string comparison */
45 #ifdef HAVE_STRCOLL
46 # define _str_Compare(s1, s2) strcoll((s1), (s2))
47 #else
48 # define _str_Compare(s1, s2) strcmp((s1), (s2))
49 #endif
50
51 /* replacement for alphasort; works on Windows too! */
52 #ifndef HAVE_ALPHASORT
alphasort(const struct dirent ** d1,const struct dirent ** d2)53 int alphasort(const struct dirent **d1, const struct dirent **d2) {
54 return _str_Compare((*d1)->d_name, (*d2)->d_name);
55 }
56 #endif //!HAVE_ALPHASORT
57
58 #ifndef HAVE_SCANDIR
59 # ifdef WIN32
scandir(const char * dirname,struct dirent *** namelist,int (* sdfilter)(const struct dirent *),int (* dcomp)(const struct dirent **,const struct dirent **))60 int scandir(const char *dirname, struct dirent ***namelist, int (*sdfilter)(const struct dirent *), int (*dcomp)(const struct dirent**, const struct dirent**))
61 {
62 int len;
63 char *findIn, *d;
64 WIN32_FIND_DATA find;
65 HANDLE h;
66 int nDir = 0, NDir = 0;
67 struct dirent **dir = 0, *selectDir;
68 unsigned long ret;
69
70 len = strlen(dirname);
71 findIn = (char *)malloc(len+5);
72 strcpy(findIn, dirname);
73 printf("scandir : findIn orign=%s\n", findIn);
74 for (d = findIn; *d; d++)
75 if (*d=='/')
76 *d='\\';
77 if ((len==0))
78 {
79 strcpy(findIn, ".\\*");
80 }
81 if ((len==1)&& (d[-1]=='.'))
82 {
83 strcpy(findIn, ".\\*");
84 }
85 if ((len>0) && (d[-1]=='\\'))
86 {
87 *d++ = '*';
88 *d = 0;
89 }
90 if ((len>1) && (d[-1]=='.') && (d[-2]=='\\'))
91 {
92 d[-1] = '*';
93 }
94 if ((len>1) && (d[-2]!='\\') && (d[-1]!='*'))
95 {
96 *d++ = '\\';
97 *d++ = '*';
98 *d = 0;
99 }
100
101 printf("scandir : findIn processed=%s\n", findIn);
102 if ((h=FindFirstFile(findIn, &find))==INVALID_HANDLE_VALUE)
103 {
104 printf("scandir : FindFirstFile error\n");
105 ret = GetLastError();
106 if (ret != ERROR_NO_MORE_FILES)
107 {
108 // TODO: return some error code
109 }
110 *namelist = dir;
111 return nDir;
112 }
113 do
114 {
115 printf("scandir : findFile=%s\n", find.cFileName);
116 selectDir=(struct dirent*)malloc(sizeof(struct dirent)+strlen(find.cFileName));
117 strcpy(selectDir->d_name, find.cFileName);
118 if (!sdfilter || (*sdfilter)(selectDir))
119 {
120 if (nDir==NDir)
121 {
122 struct dirent **tempDir = (struct dirent **)calloc(sizeof(struct dirent*), NDir+33);
123 if (NDir)
124 memcpy(tempDir, dir, sizeof(struct dirent*)*NDir);
125 if (dir)
126 free(dir);
127 dir = tempDir;
128 NDir += 32;
129 }
130 dir[nDir] = selectDir;
131 nDir++;
132 dir[nDir] = 0;
133 }
134 else
135 {
136 free(selectDir);
137 }
138 }
139 while (FindNextFile(h, &find));
140 ret = GetLastError();
141 if (ret != ERROR_NO_MORE_FILES)
142 {
143 // TODO: return some error code
144 }
145 FindClose(h);
146
147 free (findIn);
148
149 if (dcomp)
150 qsort (dir, nDir, sizeof(*dir),dcomp);
151
152 *namelist = dir;
153 return nDir;
154 }
155 # elif defined(__BEOS__) || defined(__HAIKU__) || (defined(__sun) && defined(__SVR4))
156
157 #undef DIRSIZ
158
159 #define DIRSIZ(dp) \
160 ((sizeof(struct dirent) - sizeof(dp)->d_name) + \
161 (((dp)->d_reclen + 1 + 3) &~ 3))
162
163 #if defined(__sun) && defined(__SVR4)
164 # define dirfd(d) ((d)->dd_fd)
165 #elif defined(__BEOS__)
166 #ifndef (__HAIKU__)
167 #else
168 # define dirfd(d) ((d)->fd)
169 #endif
170 #endif
171
scandir(const char * dirname,struct dirent *** namelist,int (* sdfilter)(const struct dirent *),int (* dcomp)(const struct dirent **,const struct dirent **))172 int scandir(const char *dirname, struct dirent ***namelist, int (*sdfilter)(const struct dirent *), int (*dcomp)(const struct dirent**, const struct dirent**))
173 {
174 struct dirent *d, *p, **names;
175 struct stat stb;
176 size_t nitems;
177 size_t arraysz;
178 DIR *dirp;
179
180 if ((dirp = opendir(dirname)) == NULL)
181 return(-1);
182
183 if (fstat(dirfd(dirp), &stb) < 0)
184 return(-1);
185
186 /*
187 * estimate the array size by taking the size of the directory file
188 * and dividing it by a multiple of the minimum size entry.
189 */
190 arraysz = (stb.st_size / 24);
191
192 names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
193 if (names == NULL)
194 return(-1);
195
196 nitems = 0;
197
198 while ((d = readdir(dirp)) != NULL)
199 {
200
201 if (sdfilter != NULL && !(*sdfilter)(d))
202 continue; /* just selected names */
203
204 /*
205 * Make a minimum size copy of the data
206 */
207
208 p = (struct dirent *)malloc(DIRSIZ(d));
209 if (p == NULL)
210 return(-1);
211
212 p->d_ino = d->d_ino;
213 p->d_reclen = d->d_reclen;
214 /*p->d_namlen = d->d_namlen;*/
215 memcpy(p->d_name, d->d_name, p->d_reclen + 1);
216
217 /*
218 * Check to make sure the array has space left and
219 * realloc the maximum size.
220 */
221
222 if (++nitems >= arraysz)
223 {
224
225 if (fstat(dirfd(dirp), &stb) < 0)
226 return(-1); /* just might have grown */
227
228 arraysz = stb.st_size / 12;
229
230 names = (struct dirent **)realloc((char *)names, arraysz * sizeof(struct dirent *));
231 if (names == NULL)
232 return(-1);
233 }
234
235 names[nitems-1] = p;
236 }
237
238 closedir(dirp);
239
240 if (nitems && dcomp != NULL)
241 qsort(names, nitems, sizeof(struct dirent *), dcomp);
242
243 *namelist = names;
244
245 return nitems;
246 }
247 # else // Display a "fatal" error and exit on other platforms
248 # error t4kcommon : scandir not implemented for your platform. Report at tuxmath-devel@lists.sourceforge.net
249 /* NOTE Removed in favour of compile time preprocessor error macro. *//*
250 int scandir(const char *dirname, struct dirent ***namelist, int (*sdfilter)(struct dirent *), int (*dcomp)(const void *, const void *)) {
251 fprintf(stderr, "scandir (t4kcommon) fatal: unimplemented on your platform.\n");
252 exit(EXIT_SUCCESS);
253 }
254 */
255 # endif // Platform selection.
256 #endif //!HAVE_SCANDIR
257