Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/dbm/src/dirent.c @ 3:150b72113545
Add DBM and legacydb support
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Tue, 05 Aug 2014 18:32:02 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2:a945361df361 | 3:150b72113545 |
---|---|
1 #ifdef OS2 | |
2 | |
3 #include <stdio.h> | |
4 #include <stdlib.h> | |
5 #include <string.h> | |
6 #include <ctype.h> | |
7 | |
8 #include <dirent.h> | |
9 #include <errno.h> | |
10 | |
11 /*#ifndef __EMX__ | |
12 #include <libx.h> | |
13 #endif */ | |
14 | |
15 #define INCL_DOSFILEMGR | |
16 #define INCL_DOSERRORS | |
17 #include <os2.h> | |
18 | |
19 #if OS2 >= 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 loses 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 | |
57 struct _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 */ | |
73 static char | |
74 getFSType(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 OS2 >= 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 OS2 >= 2 | |
106 if (DosQueryFSAttach(drive, 0, FSAIL_QUERYNAME, (PVOID)info, &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, (PVOID)info, &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 | |
125 char * | |
126 abs_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 OS2 >= 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 | |
145 DIR * | |
146 openxdir(const char *path, unsigned att_mask) | |
147 { | |
148 DIR *dir; | |
149 char name[MAXPATHLEN+3]; | |
150 Word rc; | |
151 | |
152 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 OS2 >= 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 | |
205 DIR * | |
206 opendir(const char *pathname) | |
207 { | |
208 return openxdir(pathname, 0); | |
209 } | |
210 | |
211 struct dirent * | |
212 readdir(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 OS2 >= 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 OS2 >= 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 | |
268 long | |
269 telldir(DIR *dir) | |
270 { | |
271 return dir->number; | |
272 } | |
273 | |
274 void | |
275 seekdir(DIR *dir, long off) | |
276 { | |
277 if (dir->number > off) { | |
278 char name[MAXPATHLEN+2]; | |
279 Word rc; | |
280 | |
281 DosFindClose(dir->handle); | |
282 | |
283 strcpy(name, dir->name); | |
284 strcat(name, "*"); | |
285 | |
286 dir->handle = HDIR_CREATE; | |
287 dir->count = 32767; | |
288 #if OS2 >= 2 | |
289 rc = DosFindFirst(name, &dir->handle, dir->attrmask, | |
290 dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD); | |
291 #else | |
292 rc = DosFindFirst((PSZ)name, &dir->handle, dir->attrmask, | |
293 (PFILEFINDBUF)dir->ffbuf, sizeof dir->ffbuf, &dir->count, 0); | |
294 #endif | |
295 switch (rc) { | |
296 default: | |
297 error(rc); | |
298 return; | |
299 case NO_ERROR: | |
300 case ERROR_NO_MORE_FILES: | |
301 ; | |
302 } | |
303 | |
304 dir->number = 0; | |
305 dir->index = 0; | |
306 dir->next = (FFBUF *)dir->ffbuf; | |
307 } | |
308 | |
309 while (dir->number < off && readdir(dir)) | |
310 ; | |
311 } | |
312 | |
313 void | |
314 closedir(DIR *dir) | |
315 { | |
316 DosFindClose(dir->handle); | |
317 free(dir); | |
318 } | |
319 | |
320 /*****************************************************************************/ | |
321 | |
322 #ifdef TEST | |
323 | |
324 main(int argc, char **argv) | |
325 { | |
326 int i; | |
327 DIR *dir; | |
328 struct dirent *ep; | |
329 | |
330 for (i = 1; i < argc; ++i) { | |
331 dir = opendir(argv[i]); | |
332 if (!dir) | |
333 continue; | |
334 while (ep = readdir(dir)) | |
335 if (strchr("\\/:", argv[i] [strlen(argv[i]) - 1])) | |
336 printf("%s%s\n", argv[i], ep->d_name); | |
337 else | |
338 printf("%s/%s\n", argv[i], ep->d_name); | |
339 closedir(dir); | |
340 } | |
341 | |
342 return 0; | |
343 } | |
344 | |
345 #endif | |
346 | |
347 #endif /* OS2 */ | |
348 |