|
|
1.1 root 1: /*
2: Hatari - scandir.c
3:
4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
6:
7: scandir function for BEOS, SunOS etc..
8: */
9: const char ScanDir_fileid[] = "Hatari scandir.c : " __DATE__ " " __TIME__;
10:
11: #include <string.h>
12: #include <stdio.h>
13: #include <stdlib.h>
14: #include <sys/types.h>
15: #include <sys/stat.h>
16: #include <fcntl.h>
17: #include <unistd.h>
18:
19: #include "scandir.h"
20: #include "log.h"
21:
22: /*-----------------------------------------------------------------------
23: * Here come alphasort and scandir for POSIX-like OSes
24: *-----------------------------------------------------------------------*/
25: #if !defined(WIN32) && !defined(__CEGCC__)
26:
27: /**
28: * Alphabetic order comparison routine.
29: */
30: #if !HAVE_ALPHASORT
31: int alphasort(const void *d1, const void *d2)
32: {
33: return strcmp((*(struct dirent * const *)d1)->d_name,
34: (*(struct dirent * const *)d2)->d_name);
35: }
36: #endif
37:
38:
39: #if !HAVE_SCANDIR
40:
41: #undef DIRSIZ
42:
43: #define DIRSIZ(dp) \
44: ((sizeof(struct dirent) - sizeof(dp)->d_name) + \
45: (((dp)->d_reclen + 1 + 3) &~ 3))
46:
47: #if (defined(__sun) && defined(__SVR4)) || defined(__CEGCC__)
48: # define dirfd(d) ((d)->dd_fd)
49: #elif defined(__BEOS__)
50: # define dirfd(d) ((d)->fd)
51: #endif
52:
53:
54: /*-----------------------------------------------------------------------*/
55: /**
56: * Scan a directory for all its entries
57: * Return -1 on error, number of entries on success
58: */
59: int scandir(const char *dirname, struct dirent ***namelist, int (*sdfilter)(struct dirent *), int (*dcomp)(const void *, const void *))
60: {
61: struct dirent *d, *p = NULL, **names = NULL;
62: struct stat stb;
63: size_t nitems = 0;
64: size_t arraysz;
65: DIR *dirp;
66:
67: if ((dirp = opendir(dirname)) == NULL)
68: goto error_out;
69:
70: if (fstat(dirfd(dirp), &stb) < 0)
71: goto error_out;
72:
73: /*
74: * estimate the array size by taking the size of the directory file
75: * and dividing it by a multiple of the minimum size entry.
76: */
77: arraysz = (stb.st_size / 24);
78:
79: names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
80: if (names == NULL)
81: goto error_out;
82:
83: while ((d = readdir(dirp)) != NULL)
84: {
85:
86: if (sdfilter != NULL && !(*sdfilter)(d))
87: continue; /* just selected names */
88:
89: /*
90: * Make a minimum size copy of the data
91: */
92:
93: p = (struct dirent *)malloc(DIRSIZ(d));
94: if (p == NULL)
95: goto error_out;
96:
97: p->d_ino = d->d_ino;
98: p->d_reclen = d->d_reclen;
99: /*p->d_namlen = d->d_namlen;*/
100: memcpy(p->d_name, d->d_name, p->d_reclen + 1);
101:
102: /*
103: * Check to make sure the array has space left and
104: * realloc the maximum size.
105: */
106:
107: if ((nitems+1) >= arraysz)
108: {
109: struct dirent **tmp;
110:
111: if (fstat(dirfd(dirp), &stb) < 0)
112: goto error_out; /* just might have grown */
113:
114: arraysz = stb.st_size / 12;
115:
116: tmp = (struct dirent **)realloc((char *)names, arraysz * sizeof(struct dirent *));
117: if (tmp == NULL)
118: goto error_out;
119: names = tmp;
120: }
121:
122: names[nitems++] = p;
123: p = NULL;
124: }
125:
126: closedir(dirp);
127:
128: if (nitems && dcomp != NULL)
129: qsort(names, nitems, sizeof(struct dirent *), dcomp);
130:
131: *namelist = names;
132:
133: return nitems;
134:
135: error_out:
136: if (names)
137: {
138: int i;
139: for (i = 0; i < nitems; i++)
140: free(names[i]);
141: free(names);
142: }
143: if (dirp)
144: closedir(dirp);
145: return -1;
146: }
147: #endif /* !HAVE_SCANDIR */
148:
149: #endif /* !WIN32 */
150:
151:
152: /*-----------------------------------------------------------------------
153: * Here come alphasort and scandir for Windows
154: *-----------------------------------------------------------------------*/
155: #if defined(WIN32) || defined(__CEGCC__)
156:
157: #include <windows.h>
158: #include <wchar.h>
159:
160: /*-----------------------------------------------------------------------*/
161: /**
162: * Alphabetic order comparison routine.
163: */
164: int alphasort(const void *d1, const void *d2)
165: {
166: return stricmp((*(struct dirent * const *)d1)->d_name, (*(struct dirent * const *)d2)->d_name);
167: }
168:
169: /*-----------------------------------------------------------------------*/
170: /**
171: * Scan a directory for all its entries
172: */
173: int scandir(const char *dirname, struct dirent ***namelist, int (*sdfilter)(struct dirent *), int (*dcomp)(const void *, const void *))
174: {
175: int len;
176: char *findIn, *d;
177: WIN32_FIND_DATA find;
178: HANDLE h;
179: int nDir = 0, NDir = 0;
180: struct dirent **dir = 0, *selectDir;
181: unsigned long ret;
182:
183: len = strlen(dirname);
184: findIn = (char *)malloc(len+5);
185: if (!findIn)
186: return -1;
187:
188: strcpy(findIn, dirname);
189: Log_Printf(LOG_DEBUG, "scandir : findIn orign='%s'\n", findIn);
190:
191: for (d = findIn; *d; d++)
192: if (*d=='/')
193: *d='\\';
194: if ((len==0))
195: {
196: strcpy(findIn, ".\\*");
197: }
198: if ((len==1)&& (d[-1]=='.'))
199: {
200: strcpy(findIn, ".\\*");
201: }
202: if ((len>0) && (d[-1]=='\\'))
203: {
204: *d++ = '*';
205: *d = 0;
206: }
207: if ((len>1) && (d[-1]=='.') && (d[-2]=='\\'))
208: {
209: d[-1] = '*';
210: }
211: if ((len>1) && !(d[-2]=='\\' && d[-1]=='*') )
212: {
213: *d++ = '\\';
214: *d++ = '*';
215: *d = 0;
216: }
217:
218: Log_Printf(LOG_DEBUG, "scandir : findIn processed='%s'\n", findIn);
219:
220: #if defined(__CEGCC__)
221: void *findInW = NULL;
222: findInW = malloc((len+6)*2);
223: if (!findInW)
224: return -1;
225: mbstowcs(findInW, findIn, len+6);
226: h = FindFirstFileW(findInW, &find);
227: #else
228: h = FindFirstFile(findIn, &find);
229: #endif
230:
231: if (h == INVALID_HANDLE_VALUE)
232: {
233: Log_Printf(LOG_DEBUG, "scandir : FindFirstFile error\n");
234: ret = GetLastError();
235: if (ret != ERROR_NO_MORE_FILES)
236: {
237: // TODO: return some error code
238: }
239: *namelist = dir;
240: return nDir;
241: }
242:
243: do
244: {
245: selectDir=(struct dirent*)malloc(sizeof(struct dirent)+lstrlen(find.cFileName)+1);
246: #if defined(__CEGCC__)
247: wcstombs(selectDir->d_name, find.cFileName, lstrlen(find.cFileName)+1);
248: #else
249: strcpy(selectDir->d_name, find.cFileName);
250: #endif
251: //Log_Printf(LOG_DEBUG, "scandir : findFile='%s'\n", selectDir->d_name);
252: if (!sdfilter || (*sdfilter)(selectDir))
253: {
254: if (nDir==NDir)
255: {
256: struct dirent **tempDir = (struct dirent **)calloc(sizeof(struct dirent*), NDir+33);
257: if (NDir)
258: memcpy(tempDir, dir, sizeof(struct dirent*)*NDir);
259: if (dir)
260: free(dir);
261: dir = tempDir;
262: NDir += 32;
263: }
264: dir[nDir] = selectDir;
265: nDir++;
266: dir[nDir] = 0;
267: }
268: else
269: {
270: free(selectDir);
271: }
272:
273: #if defined(__CEGCC__)
274: ret = FindNextFileW(h, &find);
275: #else
276: ret = FindNextFile(h, &find);
277: #endif
278: }
279: while (ret);
280:
281: ret = GetLastError();
282: if (ret != ERROR_NO_MORE_FILES)
283: {
284: // TODO: return some error code
285: Log_Printf(LOG_DEBUG, "scandir: last error = %ld\n", ret);
286: }
287:
288: FindClose(h);
289:
290: free(findIn);
291:
292: #if defined(__CEGCC__)
293: free(findInW);
294: #endif
295:
296: if (dcomp)
297: qsort (dir, nDir, sizeof(*dir),dcomp);
298:
299: *namelist = dir;
300: return nDir;
301: }
302:
303: #endif /* WIN32 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.