VirtualBox

source: kBuild/trunk/src/kmk/include/dirent.c@ 30

Last change on this file since 30 was 28, checked in by bird, 22 years ago

From php src/libs/generic.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.5 KB
Line 
1#define OS2VER 2
2#undef INCL_BASE
3#define INCL_BASE
4#include <os2.h>
5
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <ctype.h>
10
11#include <dirent.h>
12#include <errno.h>
13
14/*#ifndef __EMX__
15#include <libx.h>
16#endif */
17
18
19#if OS2VER >= 2
20# define FFBUF FILEFINDBUF3
21# define Word ULONG
22 /*
23 * LS20 recommends a request count of 100, but according to the
24 * APAR text it does not lead to missing files, just to funny
25 * numbers of returned entries.
26 *
27 * LS30 HPFS386 requires a count greater than 2, or some files
28 * are missing (those starting with a character less that '.').
29 *
30 * Novell looses entries which overflow the buffer. In previous
31 * versions of dirent2, this could have lead to missing files
32 * when the average length of 100 directory entries was 40 bytes
33 * or more (quite unlikely for files on a Novell server).
34 *
35 * Conclusion: Make sure that the entries all fit into the buffer
36 * and that the buffer is large enough for more than 2 entries
37 * (each entry is at most 300 bytes long). And ignore the LS20
38 * effect.
39 */
40# define Count 25
41# define BufSz (25 * (sizeof(FILEFINDBUF3)+1))
42#else
43# define FFBUF FILEFINDBUF
44# define Word USHORT
45# define BufSz 1024
46# define Count 3
47#endif
48
49#if defined(__IBMC__) || defined(__IBMCPP__)
50 #define error(rc) _doserrno = rc, errno = EOS2ERR
51#elif defined(MICROSOFT)
52 #define error(rc) _doserrno = rc, errno = 255
53#else
54 #define error(rc) errno = 255
55#endif
56
57struct _dirdescr {
58 HDIR handle; /* DosFindFirst handle */
59 char fstype; /* filesystem type */
60 Word count; /* valid entries in <ffbuf> */
61 long number; /* absolute number of next entry */
62 int index; /* relative number of next entry */
63 FFBUF * next; /* pointer to next entry */
64 char name[MAXPATHLEN+3]; /* directory name */
65 unsigned attrmask; /* attribute mask for seekdir */
66 struct dirent entry; /* buffer for directory entry */
67 BYTE ffbuf[BufSz];
68};
69
70/*
71 * Return first char of filesystem type, or 0 if unknown.
72 */
73static char
74getFSType(const char *path)
75{
76 static char cache[1+26];
77 char drive[3], info[512];
78 Word unit, infolen;
79 char r;
80
81 if (isalpha(path[0]) && path[1] == ':') {
82 unit = toupper(path[0]) - '@';
83 path += 2;
84 } else {
85 ULONG driveMap;
86#if OS2VER >= 2
87 if (DosQueryCurrentDisk(&unit, &driveMap))
88#else
89 if (DosQCurDisk(&unit, &driveMap))
90#endif
91 return 0;
92 }
93
94 if ((path[0] == '\\' || path[0] == '/')
95 && (path[1] == '\\' || path[1] == '/'))
96 return 0;
97
98 if (cache [unit])
99 return cache [unit];
100
101 drive[0] = '@' + unit;
102 drive[1] = ':';
103 drive[2] = '\0';
104 infolen = sizeof info;
105#if OS2VER >= 2
106 if (DosQueryFSAttach(drive, 0, FSAIL_QUERYNAME, (PFSQBUFFER2)(PVOID)&info[0], &infolen))
107 return 0;
108 if (infolen >= sizeof(FSQBUFFER2)) {
109 FSQBUFFER2 *p = (FSQBUFFER2 *)info;
110 r = p->szFSDName[p->cbName];
111 } else
112#else
113 if (DosQFSAttach((PSZ)drive, 0, FSAIL_QUERYNAME, (PFSQBUFFER2)(PVOID)&info[0], &infolen, 0))
114 return 0;
115 if (infolen >= 9) {
116 char *p = info + sizeof(USHORT);
117 p += sizeof(USHORT) + *(USHORT *)p + 1 + sizeof(USHORT);
118 r = *p;
119 } else
120#endif
121 r = 0;
122 return cache [unit] = r;
123}
124
125char *
126abs_path(const char *name, char *buffer, int len)
127{
128 char buf[4];
129 if (isalpha(name[0]) && name[1] == ':' && name[2] == '\0') {
130 buf[0] = name[0];
131 buf[1] = name[1];
132 buf[2] = '.';
133 buf[3] = '\0';
134 name = buf;
135 }
136#if OS2VER >= 2
137 if (DosQueryPathInfo((PSZ)name, FIL_QUERYFULLNAME, buffer, len))
138#else
139 if (DosQPathInfo((PSZ)name, FIL_QUERYFULLNAME, (PBYTE)buffer, len, 0L))
140#endif
141 return NULL;
142 return buffer;
143}
144
145DIR *
146openxdir(const char *path, unsigned att_mask)
147{
148 DIR *dir;
149 char name[MAXPATHLEN+3];
150 Word rc;
151
152 dir = (DIR*)malloc(sizeof(DIR));
153 if (dir == NULL) {
154 errno = ENOMEM;
155 return NULL;
156 }
157
158 strncpy(name, path, MAXPATHLEN);
159 name[MAXPATHLEN] = '\0';
160 switch (name[strlen(name)-1]) {
161 default:
162 strcat(name, "\\");
163 case '\\':
164 case '/':
165 case ':':
166 ;
167 }
168 strcat(name, ".");
169 if (!abs_path(name, dir->name, MAXPATHLEN+1))
170 strcpy(dir->name, name);
171 if (dir->name[strlen(dir->name)-1] == '\\')
172 strcat(dir->name, "*");
173 else
174 strcat(dir->name, "\\*");
175
176 dir->fstype = getFSType(dir->name);
177 dir->attrmask = att_mask | A_DIR;
178
179 dir->handle = HDIR_CREATE;
180 dir->count = 100;
181#if OS2VER >= 2
182 rc = DosFindFirst(dir->name, &dir->handle, dir->attrmask,
183 dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD);
184#else
185 rc = DosFindFirst((PSZ)dir->name, &dir->handle, dir->attrmask,
186 (PFILEFINDBUF)dir->ffbuf, sizeof dir->ffbuf, &dir->count, 0);
187#endif
188 switch (rc) {
189 default:
190 free(dir);
191 error(rc);
192 return NULL;
193 case NO_ERROR:
194 case ERROR_NO_MORE_FILES:
195 ;
196 }
197
198 dir->number = 0;
199 dir->index = 0;
200 dir->next = (FFBUF *)dir->ffbuf;
201
202 return (DIR *)dir;
203}
204
205DIR *
206opendir(const char *pathname)
207{
208 return openxdir(pathname, 0);
209}
210
211struct dirent *
212readdir(DIR *dir)
213{
214 static int dummy_ino = 2;
215
216 if (dir->index == dir->count) {
217 Word rc;
218 dir->count = 100;
219#if OS2VER >= 2
220 rc = DosFindNext(dir->handle, dir->ffbuf,
221 sizeof dir->ffbuf, &dir->count);
222#else
223 rc = DosFindNext(dir->handle, (PFILEFINDBUF)dir->ffbuf,
224 sizeof dir->ffbuf, &dir->count);
225#endif
226 if (rc) {
227 error(rc);
228 return NULL;
229 }
230
231 dir->index = 0;
232 dir->next = (FFBUF *)dir->ffbuf;
233 }
234
235 if (dir->index == dir->count)
236 return NULL;
237
238 memcpy(dir->entry.d_name, dir->next->achName, dir->next->cchName);
239 dir->entry.d_name[dir->next->cchName] = '\0';
240 dir->entry.d_ino = dummy_ino++;
241 dir->entry.d_reclen = dir->next->cchName;
242 dir->entry.d_namlen = dir->next->cchName;
243 dir->entry.d_size = dir->next->cbFile;
244 dir->entry.d_attribute = dir->next->attrFile;
245 dir->entry.d_time = *(USHORT *)&dir->next->ftimeLastWrite;
246 dir->entry.d_date = *(USHORT *)&dir->next->fdateLastWrite;
247
248 switch (dir->fstype) {
249 case 'F': /* FAT */
250 case 'C': /* CDFS */
251 if (dir->next->attrFile & FILE_DIRECTORY)
252 strupr(dir->entry.d_name);
253 else
254 strlwr(dir->entry.d_name);
255 }
256
257#if OS2VER >= 2
258 dir->next = (FFBUF *)((BYTE *)dir->next + dir->next->oNextEntryOffset);
259#else
260 dir->next = (FFBUF *)((BYTE *)dir->next->achName + dir->next->cchName + 1);
261#endif
262 ++dir->number;
263 ++dir->index;
264
265 return &dir->entry;
266}
267
268int readdir_r(DIR *dir, struct dirent *entry, struct dirent **result)
269{
270 *result = readdir(dir);
271 if (*result && entry)
272 memcpy(entry, *result, sizeof(*entry));
273 return *result != NULL ? 0 : 9;
274}
275
276long
277telldir(DIR *dir)
278{
279 return dir->number;
280}
281
282void
283seekdir(DIR *dir, long off)
284{
285 if (dir->number > off) {
286 char name[MAXPATHLEN+2];
287 Word rc;
288
289 DosFindClose(dir->handle);
290
291 strcpy(name, dir->name);
292 strcat(name, "*");
293
294 dir->handle = HDIR_CREATE;
295 dir->count = 32767;
296#if OS2VER >= 2
297 rc = DosFindFirst(name, &dir->handle, dir->attrmask,
298 dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD);
299#else
300 rc = DosFindFirst((PSZ)name, &dir->handle, dir->attrmask,
301 (PFILEFINDBUF)dir->ffbuf, sizeof dir->ffbuf, &dir->count, 0);
302#endif
303 switch (rc) {
304 default:
305 error(rc);
306 return;
307 case NO_ERROR:
308 case ERROR_NO_MORE_FILES:
309 ;
310 }
311
312 dir->number = 0;
313 dir->index = 0;
314 dir->next = (FFBUF *)dir->ffbuf;
315 }
316
317 while (dir->number < off && readdir(dir))
318 ;
319}
320
321void
322closedir(DIR *dir)
323{
324 DosFindClose(dir->handle);
325 free(dir);
326}
327
328/*****************************************************************************/
329
330#ifdef TEST
331
332main(int argc, char **argv)
333{
334 int i;
335 DIR *dir;
336 struct dirent *ep;
337
338 for (i = 1; i < argc; ++i) {
339 dir = opendir(argv[i]);
340 if (!dir)
341 continue;
342 while (ep = readdir(dir))
343 if (strchr("\\/:", argv[i] [strlen(argv[i]) - 1]))
344 printf("%s%s\n", argv[i], ep->d_name);
345 else
346 printf("%s/%s\n", argv[i], ep->d_name);
347 closedir(dir);
348 }
349
350 return 0;
351}
352
353#endif
354
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette