Mercurial > dwindows
annotate os2/dirent.c @ 456:935436731b41
Hybrid fix, seems the last change illiminated some important code that
dealt with varying padding sizes in the opposite direction of the box.
This readds that code but optimizes it and includes the groupbox
calculations that were already present in the previous code path.
This fix will be added to the OS/2 tree as well pending testing of this
new code path.
author | bsmith@81767d24-ef19-dc11-ae90-00e081727c95 |
---|---|
date | Wed, 25 Jun 2003 03:39:44 +0000 |
parents | 0e6f09149eaa |
children | 2ff26b697877 |
rev | line source |
---|---|
3 | 1 #include <stdio.h> |
2 #include <stdlib.h> | |
3 #include <string.h> | |
4 #include <ctype.h> | |
5 | |
24
d9e87e8bcf1d
Updated dynamic windows to build with EMX.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
3
diff
changeset
|
6 #include "platform/dirent.h" |
3 | 7 #include <errno.h> |
8 | |
9 /*#ifndef __EMX__ | |
10 #include <libx.h> | |
11 #endif */ | |
12 | |
13 #define INCL_DOSFILEMGR | |
14 #define INCL_DOSERRORS | |
15 #include <os2.h> | |
16 | |
17 # define FFBUF FILEFINDBUF3 | |
18 # define Word ULONG | |
19 /* | |
20 * LS20 recommends a request count of 100, but according to the | |
21 * APAR text it does not lead to missing files, just to funny | |
22 * numbers of returned entries. | |
23 * | |
24 * LS30 HPFS386 requires a count greater than 2, or some files | |
25 * are missing (those starting with a character less that '.'). | |
26 * | |
27 * Novell looses entries which overflow the buffer. In previous | |
28 * versions of dirent2, this could have lead to missing files | |
29 * when the average length of 100 directory entries was 40 bytes | |
30 * or more (quite unlikely for files on a Novell server). | |
31 * | |
32 * Conclusion: Make sure that the entries all fit into the buffer | |
33 * and that the buffer is large enough for more than 2 entries | |
34 * (each entry is at most 300 bytes long). And ignore the LS20 | |
35 * effect. | |
36 */ | |
37 # define Count 25 | |
38 # define BufSz (25 * (sizeof(FILEFINDBUF3)+1)) | |
39 | |
40 #if defined(__IBMC__) || defined(__IBMCPP__) | |
41 #define error(rc) _doserrno = rc, errno = EOS2ERR | |
42 #else | |
43 #define error(rc) errno = 255 | |
44 #endif | |
45 | |
46 struct _dirdescr { | |
47 HDIR handle; /* DosFindFirst handle */ | |
48 char fstype; /* filesystem type */ | |
49 Word count; /* valid entries in <ffbuf> */ | |
50 long number; /* absolute number of next entry */ | |
51 int index; /* relative number of next entry */ | |
52 FFBUF * next; /* pointer to next entry */ | |
53 char name[MAXPATHLEN+3]; /* directory name */ | |
54 unsigned attrmask; /* attribute mask for seekdir */ | |
55 struct dirent entry; /* buffer for directory entry */ | |
56 BYTE ffbuf[BufSz]; | |
57 }; | |
58 | |
59 /* | |
60 * Return first char of filesystem type, or 0 if unknown. | |
61 */ | |
62 static char | |
63 getFSType(const char *path) | |
64 { | |
65 static char cache[1+26]; | |
66 char drive[3], info[512]; | |
67 Word unit, infolen; | |
68 char r; | |
69 | |
289
0e6f09149eaa
Fixed some EMX warnings.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
174
diff
changeset
|
70 if (isalpha((int)path[0]) && path[1] == ':') { |
3 | 71 unit = toupper(path[0]) - '@'; |
72 path += 2; | |
73 } else { | |
74 ULONG driveMap; | |
75 if (DosQueryCurrentDisk(&unit, &driveMap)) | |
76 return 0; | |
77 } | |
78 | |
79 if ((path[0] == '\\' || path[0] == '/') | |
80 && (path[1] == '\\' || path[1] == '/')) | |
81 return 0; | |
82 | |
83 if (cache [unit]) | |
84 return cache [unit]; | |
85 | |
86 drive[0] = '@' + unit; | |
87 drive[1] = ':'; | |
88 drive[2] = '\0'; | |
89 infolen = sizeof info; | |
90 if (DosQueryFSAttach(drive, 0, FSAIL_QUERYNAME, (PVOID)info, &infolen)) | |
91 return 0; | |
92 if (infolen >= sizeof(FSQBUFFER2)) { | |
93 FSQBUFFER2 *p = (FSQBUFFER2 *)info; | |
94 r = p->szFSDName[p->cbName]; | |
95 } else | |
96 r = 0; | |
97 return cache [unit] = r; | |
98 } | |
99 | |
100 char * | |
174
75bf3051235f
Fixes so you can mix compilers.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
24
diff
changeset
|
101 _abs_path(const char *name, char *buffer, int len) |
3 | 102 { |
103 char buf[4]; | |
289
0e6f09149eaa
Fixed some EMX warnings.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
174
diff
changeset
|
104 if (isalpha((int)name[0]) && name[1] == ':' && name[2] == '\0') { |
3 | 105 buf[0] = name[0]; |
106 buf[1] = name[1]; | |
107 buf[2] = '.'; | |
108 buf[3] = '\0'; | |
109 name = buf; | |
110 } | |
111 if (DosQueryPathInfo((PSZ)name, FIL_QUERYFULLNAME, buffer, len)) | |
112 return NULL; | |
113 return buffer; | |
114 } | |
115 | |
116 DIR * | |
174
75bf3051235f
Fixes so you can mix compilers.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
24
diff
changeset
|
117 _openxdir(const char *path, unsigned att_mask) |
3 | 118 { |
119 DIR *dir; | |
120 char name[MAXPATHLEN+3]; | |
121 Word rc; | |
122 | |
24
d9e87e8bcf1d
Updated dynamic windows to build with EMX.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
3
diff
changeset
|
123 if(!path) |
d9e87e8bcf1d
Updated dynamic windows to build with EMX.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
3
diff
changeset
|
124 return NULL; |
d9e87e8bcf1d
Updated dynamic windows to build with EMX.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
3
diff
changeset
|
125 |
3 | 126 dir = malloc(sizeof(DIR)); |
127 if (dir == NULL) { | |
128 errno = ENOMEM; | |
129 return NULL; | |
130 } | |
131 | |
132 strncpy(name, path, MAXPATHLEN); | |
133 name[MAXPATHLEN] = '\0'; | |
134 switch (name[strlen(name)-1]) { | |
135 default: | |
136 strcat(name, "\\"); | |
137 case '\\': | |
138 case '/': | |
139 case ':': | |
140 ; | |
141 } | |
142 strcat(name, "."); | |
143 if (!abs_path(name, dir->name, MAXPATHLEN+1)) | |
144 strcpy(dir->name, name); | |
145 if (dir->name[strlen(dir->name)-1] == '\\') | |
146 strcat(dir->name, "*"); | |
147 else | |
148 strcat(dir->name, "\\*"); | |
149 | |
150 dir->fstype = getFSType(dir->name); | |
151 dir->attrmask = att_mask | A_DIR; | |
152 | |
153 dir->handle = HDIR_CREATE; | |
154 dir->count = 100; | |
155 rc = DosFindFirst(dir->name, &dir->handle, dir->attrmask, | |
156 dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD); | |
157 switch (rc) { | |
158 default: | |
159 free(dir); | |
160 error(rc); | |
161 return NULL; | |
162 case NO_ERROR: | |
163 case ERROR_NO_MORE_FILES: | |
164 ; | |
165 } | |
166 | |
167 dir->number = 0; | |
168 dir->index = 0; | |
169 dir->next = (FFBUF *)dir->ffbuf; | |
170 | |
171 return (DIR *)dir; | |
172 } | |
173 | |
174 DIR * | |
174
75bf3051235f
Fixes so you can mix compilers.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
24
diff
changeset
|
175 _opendir(const char *pathname) |
3 | 176 { |
177 return openxdir(pathname, 0); | |
178 } | |
179 | |
180 struct dirent * | |
174
75bf3051235f
Fixes so you can mix compilers.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
24
diff
changeset
|
181 _readdir(DIR *dir) |
3 | 182 { |
183 static int dummy_ino = 2; | |
184 | |
185 if (dir->index == dir->count) { | |
186 Word rc; | |
187 dir->count = 100; | |
188 rc = DosFindNext(dir->handle, dir->ffbuf, | |
189 sizeof dir->ffbuf, &dir->count); | |
190 if (rc) { | |
191 error(rc); | |
192 return NULL; | |
193 } | |
194 | |
195 dir->index = 0; | |
196 dir->next = (FFBUF *)dir->ffbuf; | |
197 } | |
198 | |
199 if (dir->index == dir->count) | |
200 return NULL; | |
201 | |
202 memcpy(dir->entry.d_name, dir->next->achName, dir->next->cchName); | |
203 dir->entry.d_name[dir->next->cchName] = '\0'; | |
204 dir->entry.d_ino = dummy_ino++; | |
205 dir->entry.d_reclen = dir->next->cchName; | |
206 dir->entry.d_namlen = dir->next->cchName; | |
207 dir->entry.d_size = dir->next->cbFile; | |
208 dir->entry.d_attribute = dir->next->attrFile; | |
209 dir->entry.d_time = *(USHORT *)&dir->next->ftimeLastWrite; | |
210 dir->entry.d_date = *(USHORT *)&dir->next->fdateLastWrite; | |
211 | |
212 switch (dir->fstype) { | |
213 case 'F': /* FAT */ | |
214 case 'C': /* CDFS */ | |
215 if (dir->next->attrFile & FILE_DIRECTORY) | |
216 strupr(dir->entry.d_name); | |
217 else | |
218 strlwr(dir->entry.d_name); | |
219 } | |
220 | |
221 dir->next = (FFBUF *)((BYTE *)dir->next + dir->next->oNextEntryOffset); | |
222 ++dir->number; | |
223 ++dir->index; | |
224 | |
225 return &dir->entry; | |
226 } | |
227 | |
228 long | |
174
75bf3051235f
Fixes so you can mix compilers.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
24
diff
changeset
|
229 _telldir(DIR *dir) |
3 | 230 { |
231 return dir->number; | |
232 } | |
233 | |
234 void | |
174
75bf3051235f
Fixes so you can mix compilers.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
24
diff
changeset
|
235 _seekdir(DIR *dir, long off) |
3 | 236 { |
237 if (dir->number > off) { | |
238 char name[MAXPATHLEN+2]; | |
239 Word rc; | |
240 | |
241 DosFindClose(dir->handle); | |
242 | |
243 strcpy(name, dir->name); | |
244 strcat(name, "*"); | |
245 | |
246 dir->handle = HDIR_CREATE; | |
247 dir->count = 32767; | |
248 rc = DosFindFirst(name, &dir->handle, dir->attrmask, | |
249 dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD); | |
250 switch (rc) { | |
251 default: | |
252 error(rc); | |
253 return; | |
254 case NO_ERROR: | |
255 case ERROR_NO_MORE_FILES: | |
256 ; | |
257 } | |
258 | |
259 dir->number = 0; | |
260 dir->index = 0; | |
261 dir->next = (FFBUF *)dir->ffbuf; | |
262 } | |
263 | |
264 while (dir->number < off && readdir(dir)) | |
265 ; | |
266 } | |
267 | |
268 void | |
174
75bf3051235f
Fixes so you can mix compilers.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
24
diff
changeset
|
269 _closedir(DIR *dir) |
3 | 270 { |
271 DosFindClose(dir->handle); | |
272 free(dir); | |
273 } | |
274 | |
275 /*****************************************************************************/ | |
276 | |
277 #ifdef TEST | |
278 | |
279 main(int argc, char **argv) | |
280 { | |
281 int i; | |
282 DIR *dir; | |
283 struct dirent *ep; | |
284 | |
285 for (i = 1; i < argc; ++i) { | |
286 dir = opendir(argv[i]); | |
287 if (!dir) | |
288 continue; | |
289 while (ep = readdir(dir)) | |
290 if (strchr("\\/:", argv[i] [strlen(argv[i]) - 1])) | |
291 printf("%s%s\n", argv[i], ep->d_name); | |
292 else | |
293 printf("%s/%s\n", argv[i], ep->d_name); | |
294 closedir(dir); | |
295 } | |
296 | |
297 return 0; | |
298 } | |
299 | |
300 #endif | |
301 |