|
|
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_rcsid[] = "Hatari $Id: scandir.c,v 1.2 2006/07/22 15:49:23 thothy Exp $";
10:
11: #include <string.h>
12: #include <strings.h>
13: #include <stdio.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:
21: /*-----------------------------------------------------------------------
22: * Here come alphasort and scandir for BeOS and SunOS
23: *-----------------------------------------------------------------------*/
24: #if defined(__BEOS__) || (defined(__sun) && defined(__SVR4))
25:
26: #undef DIRSIZ
27:
28: #define DIRSIZ(dp) \
29: ((sizeof(struct dirent) - sizeof(dp)->d_name) + \
30: (((dp)->d_reclen + 1 + 3) &~ 3))
31:
32: #if defined(__sun) && defined(__SVR4)
33: # define dirfd(d) ((d)->dd_fd)
34: #elif defined(__BEOS__)
35: # define dirfd(d) ((d)->fd)
36: #endif
37:
38:
39: /*-----------------------------------------------------------------------*/
40: /*
41: Alphabetic order comparison routine.
42: */
43: int alphasort(const void *d1, const void *d2)
44: {
45: return strcmp((*(struct dirent * const *)d1)->d_name, (*(struct dirent * const *)d2)->d_name);
46: }
47:
48:
49: /*-----------------------------------------------------------------------*/
50: /*
51: Scan a directory for all its entries
52: */
53: int scandir(const char *dirname, struct dirent ***namelist, int (*sdfilter)(struct dirent *), int (*dcomp)(const void *, const void *))
54: {
55: struct dirent *d, *p, **names;
56: struct stat stb;
57: size_t nitems;
58: size_t arraysz;
59: DIR *dirp;
60:
61: if ((dirp = opendir(dirname)) == NULL)
62: return(-1);
63:
64: if (fstat(dirfd(dirp), &stb) < 0)
65: return(-1);
66:
67: /*
68: * estimate the array size by taking the size of the directory file
69: * and dividing it by a multiple of the minimum size entry.
70: */
71: arraysz = (stb.st_size / 24);
72:
73: names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
74: if (names == NULL)
75: return(-1);
76:
77: nitems = 0;
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)
91: return(-1);
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:
103: if (++nitems >= arraysz)
104: {
105:
106: if (fstat(dirfd(dirp), &stb) < 0)
107: return(-1); /* just might have grown */
108:
109: arraysz = stb.st_size / 12;
110:
111: names = (struct dirent **)realloc((char *)names, arraysz * sizeof(struct dirent *));
112: if (names == NULL)
113: return(-1);
114: }
115:
116: names[nitems-1] = p;
117: }
118:
119: closedir(dirp);
120:
121: if (nitems && dcomp != NULL)
122: qsort(names, nitems, sizeof(struct dirent *), dcomp);
123:
124: *namelist = names;
125:
126: return nitems;
127: }
128:
129:
130: #endif /* __BEOS__ || __sun */
131:
132:
133: /*-----------------------------------------------------------------------
134: * Here come alphasort and scandir for Windows
135: *-----------------------------------------------------------------------*/
136: #if defined(WIN32)
137:
138: #undef DATADIR // stupid windows.h defines DATADIR, too
139: #include <windows.h>
140:
141: /*-----------------------------------------------------------------------*/
142: /*
143: Alphabetic order comparison routine.
144: */
145: int alphasort(const void *d1, const void *d2)
146: {
147: return stricmp((*(struct dirent * const *)d1)->d_name, (*(struct dirent * const *)d2)->d_name);
148: }
149:
150: /*-----------------------------------------------------------------------*/
151: /*
152: Scan a directory for all its entries
153: */
154: int scandir(const char *dirname, struct dirent ***namelist, int (*sdfilter)(struct dirent *), int (*dcomp)(const void *, const void *))
155: {
156: int len;
157: char *findIn, *d;
158: WIN32_FIND_DATA find;
159: HANDLE h;
160: int nDir = 0, NDir = 0;
161: struct dirent **dir = 0, *selectDir;
162: unsigned long ret;
163:
164: len = strlen(dirname);
165: findIn = (char *)malloc(len+5);
166: strcpy(findIn, dirname);
167: printf("scandir : findIn orign=%s\n", findIn);
168: for (d = findIn; *d; d++)
169: if (*d=='/')
170: *d='\\';
171: if ((len==0))
172: {
173: strcpy(findIn, ".\\*");
174: }
175: if ((len==1)&& (d[-1]=='.'))
176: {
177: strcpy(findIn, ".\\*");
178: }
179: if ((len>0) && (d[-1]=='\\'))
180: {
181: *d++ = '*';
182: *d = 0;
183: }
184: if ((len>1) && (d[-1]=='.') && (d[-2]=='\\'))
185: {
186: d[-1] = '*';
187: }
188: if ((len>1) && (d[-2]!='\\') && (d[-1]!='*'))
189: {
190: *d++ = '\\';
191: *d++ = '*';
192: *d = 0;
193: }
194:
195: printf("scandir : findIn processed=%s\n", findIn);
196: if ((h=FindFirstFile(findIn, &find))==INVALID_HANDLE_VALUE)
197: {
198: printf("scandir : FindFirstFile error\n");
199: ret = GetLastError();
200: if (ret != ERROR_NO_MORE_FILES)
201: {
202: // TODO: return some error code
203: }
204: *namelist = dir;
205: return nDir;
206: }
207: do
208: {
209: printf("scandir : findFile=%s\n", find.cFileName);
210: selectDir=(struct dirent*)malloc(sizeof(struct dirent)+strlen(find.cFileName));
211: strcpy(selectDir->d_name, find.cFileName);
212: if (!sdfilter || (*sdfilter)(selectDir))
213: {
214: if (nDir==NDir)
215: {
216: struct dirent **tempDir = (struct dirent **)calloc(sizeof(struct dirent*), NDir+33);
217: if (NDir)
218: memcpy(tempDir, dir, sizeof(struct dirent*)*NDir);
219: if (dir)
220: free(dir);
221: dir = tempDir;
222: NDir += 32;
223: }
224: dir[nDir] = selectDir;
225: nDir++;
226: dir[nDir] = 0;
227: }
228: else
229: {
230: free(selectDir);
231: }
232: }
233: while (FindNextFile(h, &find));
234: ret = GetLastError();
235: if (ret != ERROR_NO_MORE_FILES)
236: {
237: // TODO: return some error code
238: }
239: FindClose(h);
240:
241: free (findIn);
242:
243: if (dcomp)
244: qsort (dir, nDir, sizeof(*dir),dcomp);
245:
246: *namelist = dir;
247: return nDir;
248: }
249:
250: #endif /* WIN32 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.