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