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