|
|
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: /*-----------------------------------------------------------------------
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
! 32: int alphasort(const void *d1, const void *d2)
! 33: {
! 34: return strcmp((*(struct dirent * const *)d1)->d_name,
! 35: (*(struct dirent * const *)d2)->d_name);
! 36: }
! 37: #endif
! 38:
! 39:
! 40: #if !HAVE_SCANDIR
! 41:
! 42: #undef DIRSIZ
1.1 root 43: #define DIRSIZ(dp) \
44: ((sizeof(struct dirent) - sizeof(dp)->d_name) + \
45: (((dp)->d_reclen + 1 + 3) &~ 3))
46:
1.1.1.2 root 47: #if (defined(__sun) && defined(__SVR4)) || defined(__CEGCC__)
1.1 root 48: # define dirfd(d) ((d)->dd_fd)
49: #elif defined(__BEOS__)
50: # define dirfd(d) ((d)->fd)
51: #endif
52:
53:
1.1.1.2 root 54: /**
55: * Scan a directory for all its entries
1.1.1.6 root 56: * Return -1 on error, number of entries on success
1.1.1.2 root 57: */
1.1 root 58: int scandir(const char *dirname, struct dirent ***namelist, int (*sdfilter)(struct dirent *), int (*dcomp)(const void *, const void *))
59: {
1.1.1.6 root 60: struct dirent *d, *p = NULL, **names = NULL;
1.1 root 61: struct stat stb;
1.1.1.6 root 62: size_t nitems = 0;
1.1 root 63: size_t arraysz;
64: DIR *dirp;
65:
66: if ((dirp = opendir(dirname)) == NULL)
1.1.1.6 root 67: goto error_out;
1.1 root 68:
69: if (fstat(dirfd(dirp), &stb) < 0)
1.1.1.6 root 70: goto error_out;
1.1 root 71:
72: /*
73: * estimate the array size by taking the size of the directory file
74: * and dividing it by a multiple of the minimum size entry.
75: */
76: arraysz = (stb.st_size / 24);
77:
78: names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
79: if (names == NULL)
1.1.1.6 root 80: goto error_out;
1.1 root 81:
82: while ((d = readdir(dirp)) != NULL)
83: {
84:
85: if (sdfilter != NULL && !(*sdfilter)(d))
86: continue; /* just selected names */
87:
88: /*
89: * Make a minimum size copy of the data
90: */
91:
92: p = (struct dirent *)malloc(DIRSIZ(d));
93: if (p == NULL)
1.1.1.6 root 94: goto error_out;
1.1 root 95:
96: p->d_ino = d->d_ino;
97: p->d_reclen = d->d_reclen;
98: /*p->d_namlen = d->d_namlen;*/
99: memcpy(p->d_name, d->d_name, p->d_reclen + 1);
100:
101: /*
102: * Check to make sure the array has space left and
103: * realloc the maximum size.
104: */
105:
1.1.1.6 root 106: if ((nitems+1) >= arraysz)
1.1 root 107: {
1.1.1.6 root 108: struct dirent **tmp;
109:
1.1 root 110: if (fstat(dirfd(dirp), &stb) < 0)
1.1.1.6 root 111: goto error_out; /* just might have grown */
1.1 root 112:
113: arraysz = stb.st_size / 12;
114:
1.1.1.6 root 115: tmp = (struct dirent **)realloc((char *)names, arraysz * sizeof(struct dirent *));
116: if (tmp == NULL)
117: goto error_out;
118: names = tmp;
1.1 root 119: }
120:
1.1.1.6 root 121: names[nitems++] = p;
122: p = NULL;
1.1 root 123: }
124:
125: closedir(dirp);
126:
127: if (nitems && dcomp != NULL)
128: qsort(names, nitems, sizeof(struct dirent *), dcomp);
129:
130: *namelist = names;
131:
132: return nitems;
1.1.1.6 root 133:
134: error_out:
135: if (names)
136: {
137: int i;
138: for (i = 0; i < nitems; i++)
139: free(names[i]);
140: free(names);
141: }
142: if (dirp)
143: closedir(dirp);
144: return -1;
1.1 root 145: }
1.1.1.7 ! root 146: #endif /* !HAVE_SCANDIR */
1.1 root 147:
148:
1.1.1.7 ! root 149: #endif /* !WIN32 */
1.1 root 150:
151:
152: /*-----------------------------------------------------------------------
153: * Here come alphasort and scandir for Windows
154: *-----------------------------------------------------------------------*/
1.1.1.2 root 155: #if defined(WIN32) || defined(__CEGCC__)
1.1 root 156:
157: #include <windows.h>
1.1.1.2 root 158: #include <wchar.h>
1.1 root 159:
160: /*-----------------------------------------------------------------------*/
1.1.1.2 root 161: /**
162: * Alphabetic order comparison routine.
163: */
1.1 root 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: /*-----------------------------------------------------------------------*/
1.1.1.2 root 170: /**
171: * Scan a directory for all its entries
172: */
1.1 root 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);
1.1.1.2 root 185: if (!findIn)
186: return -1;
187:
1.1 root 188: strcpy(findIn, dirname);
1.1.1.2 root 189: Log_Printf(LOG_DEBUG, "scandir : findIn orign='%s'\n", findIn);
190:
1.1 root 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: }
1.1.1.5 root 211: if ((len>1) && !(d[-2]=='\\' && d[-1]=='*') )
1.1 root 212: {
213: *d++ = '\\';
214: *d++ = '*';
215: *d = 0;
216: }
217:
1.1.1.2 root 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)
1.1 root 232: {
1.1.1.2 root 233: Log_Printf(LOG_DEBUG, "scandir : FindFirstFile error\n");
1.1 root 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: }
1.1.1.2 root 242:
1.1 root 243: do
244: {
1.1.1.2 root 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
1.1 root 249: strcpy(selectDir->d_name, find.cFileName);
1.1.1.2 root 250: #endif
251: //Log_Printf(LOG_DEBUG, "scandir : findFile='%s'\n", selectDir->d_name);
1.1 root 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: }
1.1.1.5 root 272:
1.1.1.2 root 273: #if defined(__CEGCC__)
274: ret = FindNextFileW(h, &find);
275: #else
276: ret = FindNextFile(h, &find);
277: #endif
1.1 root 278: }
1.1.1.2 root 279: while (ret);
280:
1.1 root 281: ret = GetLastError();
282: if (ret != ERROR_NO_MORE_FILES)
283: {
284: // TODO: return some error code
1.1.1.3 root 285: Log_Printf(LOG_DEBUG, "scandir: last error = %ld\n", ret);
1.1 root 286: }
1.1.1.2 root 287:
1.1 root 288: FindClose(h);
289:
1.1.1.2 root 290: free(findIn);
291:
292: #if defined(__CEGCC__)
293: free(findInW);
294: #endif
1.1 root 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.