Mercurial > dwindows
annotate os2/dirent.c @ 2658:ad6fc7f1a9af
Android: Asset/Resource refactoring for compatibility with other platforms.
Other platforms are able to access the bundled assets via the filesystem.
Android keeps the assets in the Zipped APK archive, so during initialization
we now extract the non-resource (numeric images) into the app cache dir.
dw_app_dir() now returns the path to the application cache.
dw_user_dir() returns either the HOME directory or the path to the
application root directory (usually the parent of the cache).
author | bsmith@81767d24-ef19-dc11-ae90-00e081727c95 |
---|---|
date | Fri, 24 Sep 2021 13:57:16 +0000 |
parents | 6baf177f335c |
children |
rev | line source |
---|---|
3 | 1 #include <stdio.h> |
2 #include <stdlib.h> | |
3 #include <string.h> | |
4 #include <ctype.h> | |
5 | |
525
2ff26b697877
Fixes for building with Innotek GCC. Will have to check for regressions
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
289
diff
changeset
|
6 #define INCL_DOSFILEMGR |
2ff26b697877
Fixes for building with Innotek GCC. Will have to check for regressions
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
289
diff
changeset
|
7 #define INCL_DOSERRORS |
1594
6baf177f335c
Rename compat.c/h dwcompat.c/h and configure option to --with-dwcompat.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
1404
diff
changeset
|
8 #include "dwcompat.h" |
3 | 9 #include <errno.h> |
10 | |
1404
56f311dc23f6
Changes to get the library building with Watcom on OS/2.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
1341
diff
changeset
|
11 #ifdef __WATCOMC__ |
56f311dc23f6
Changes to get the library building with Watcom on OS/2.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
1341
diff
changeset
|
12 #include "platform\dirent.h" |
56f311dc23f6
Changes to get the library building with Watcom on OS/2.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
1341
diff
changeset
|
13 typedef struct _dirdescr DIRW; |
56f311dc23f6
Changes to get the library building with Watcom on OS/2.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
1341
diff
changeset
|
14 #define DIR DIRW |
56f311dc23f6
Changes to get the library building with Watcom on OS/2.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
1341
diff
changeset
|
15 #endif |
56f311dc23f6
Changes to get the library building with Watcom on OS/2.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
1341
diff
changeset
|
16 |
3 | 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 */ | |
525
2ff26b697877
Fixes for building with Innotek GCC. Will have to check for regressions
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
289
diff
changeset
|
62 static char API getFSType(const char *path) |
3 | 63 { |
64 static char cache[1+26]; | |
65 char drive[3], info[512]; | |
66 Word unit, infolen; | |
67 char r; | |
68 | |
289
0e6f09149eaa
Fixed some EMX warnings.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
174
diff
changeset
|
69 if (isalpha((int)path[0]) && path[1] == ':') { |
3 | 70 unit = toupper(path[0]) - '@'; |
71 path += 2; | |
72 } else { | |
73 ULONG driveMap; | |
74 if (DosQueryCurrentDisk(&unit, &driveMap)) | |
75 return 0; | |
76 } | |
77 | |
78 if ((path[0] == '\\' || path[0] == '/') | |
79 && (path[1] == '\\' || path[1] == '/')) | |
80 return 0; | |
81 | |
82 if (cache [unit]) | |
83 return cache [unit]; | |
84 | |
85 drive[0] = '@' + unit; | |
86 drive[1] = ':'; | |
87 drive[2] = '\0'; | |
88 infolen = sizeof info; | |
1341
184b3aedc2ff
Added PMPrintf support to dw_debug() on OS/2.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
528
diff
changeset
|
89 if (DosQueryFSAttach((PSZ)drive, 0, FSAIL_QUERYNAME, (PVOID)info, &infolen)) |
3 | 90 return 0; |
91 if (infolen >= sizeof(FSQBUFFER2)) { | |
92 FSQBUFFER2 *p = (FSQBUFFER2 *)info; | |
93 r = p->szFSDName[p->cbName]; | |
94 } else | |
95 r = 0; | |
96 return cache [unit] = r; | |
97 } | |
98 | |
525
2ff26b697877
Fixes for building with Innotek GCC. Will have to check for regressions
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
289
diff
changeset
|
99 char * API _abs_path(const char *name, char *buffer, int len) |
3 | 100 { |
101 char buf[4]; | |
289
0e6f09149eaa
Fixed some EMX warnings.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
174
diff
changeset
|
102 if (isalpha((int)name[0]) && name[1] == ':' && name[2] == '\0') { |
3 | 103 buf[0] = name[0]; |
104 buf[1] = name[1]; | |
105 buf[2] = '.'; | |
106 buf[3] = '\0'; | |
107 name = buf; | |
108 } | |
109 if (DosQueryPathInfo((PSZ)name, FIL_QUERYFULLNAME, buffer, len)) | |
110 return NULL; | |
111 return buffer; | |
112 } | |
113 | |
525
2ff26b697877
Fixes for building with Innotek GCC. Will have to check for regressions
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
289
diff
changeset
|
114 DIR * API _openxdir(const char *path, unsigned att_mask) |
3 | 115 { |
116 DIR *dir; | |
117 char name[MAXPATHLEN+3]; | |
118 Word rc; | |
119 | |
24
d9e87e8bcf1d
Updated dynamic windows to build with EMX.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
3
diff
changeset
|
120 if(!path) |
d9e87e8bcf1d
Updated dynamic windows to build with EMX.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
3
diff
changeset
|
121 return NULL; |
d9e87e8bcf1d
Updated dynamic windows to build with EMX.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
3
diff
changeset
|
122 |
3 | 123 dir = malloc(sizeof(DIR)); |
124 if (dir == NULL) { | |
125 errno = ENOMEM; | |
126 return NULL; | |
127 } | |
128 | |
129 strncpy(name, path, MAXPATHLEN); | |
130 name[MAXPATHLEN] = '\0'; | |
131 switch (name[strlen(name)-1]) { | |
132 default: | |
133 strcat(name, "\\"); | |
134 case '\\': | |
135 case '/': | |
136 case ':': | |
137 ; | |
138 } | |
139 strcat(name, "."); | |
140 if (!abs_path(name, dir->name, MAXPATHLEN+1)) | |
141 strcpy(dir->name, name); | |
142 if (dir->name[strlen(dir->name)-1] == '\\') | |
143 strcat(dir->name, "*"); | |
144 else | |
145 strcat(dir->name, "\\*"); | |
146 | |
147 dir->fstype = getFSType(dir->name); | |
148 dir->attrmask = att_mask | A_DIR; | |
149 | |
150 dir->handle = HDIR_CREATE; | |
151 dir->count = 100; | |
1341
184b3aedc2ff
Added PMPrintf support to dw_debug() on OS/2.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
528
diff
changeset
|
152 rc = DosFindFirst((PSZ)dir->name, &dir->handle, dir->attrmask, |
3 | 153 dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD); |
154 switch (rc) { | |
155 default: | |
156 free(dir); | |
157 error(rc); | |
158 return NULL; | |
159 case NO_ERROR: | |
160 case ERROR_NO_MORE_FILES: | |
161 ; | |
162 } | |
163 | |
164 dir->number = 0; | |
165 dir->index = 0; | |
166 dir->next = (FFBUF *)dir->ffbuf; | |
167 | |
168 return (DIR *)dir; | |
169 } | |
170 | |
525
2ff26b697877
Fixes for building with Innotek GCC. Will have to check for regressions
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
289
diff
changeset
|
171 DIR * API _opendir(const char *pathname) |
3 | 172 { |
173 return openxdir(pathname, 0); | |
174 } | |
175 | |
525
2ff26b697877
Fixes for building with Innotek GCC. Will have to check for regressions
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
289
diff
changeset
|
176 struct dirent * API _readdir(DIR *dir) |
3 | 177 { |
178 static int dummy_ino = 2; | |
179 | |
180 if (dir->index == dir->count) { | |
181 Word rc; | |
182 dir->count = 100; | |
183 rc = DosFindNext(dir->handle, dir->ffbuf, | |
184 sizeof dir->ffbuf, &dir->count); | |
185 if (rc) { | |
186 error(rc); | |
187 return NULL; | |
188 } | |
189 | |
190 dir->index = 0; | |
191 dir->next = (FFBUF *)dir->ffbuf; | |
192 } | |
193 | |
194 if (dir->index == dir->count) | |
195 return NULL; | |
196 | |
197 memcpy(dir->entry.d_name, dir->next->achName, dir->next->cchName); | |
198 dir->entry.d_name[dir->next->cchName] = '\0'; | |
199 dir->entry.d_ino = dummy_ino++; | |
200 dir->entry.d_reclen = dir->next->cchName; | |
201 dir->entry.d_namlen = dir->next->cchName; | |
202 dir->entry.d_size = dir->next->cbFile; | |
203 dir->entry.d_attribute = dir->next->attrFile; | |
204 dir->entry.d_time = *(USHORT *)&dir->next->ftimeLastWrite; | |
205 dir->entry.d_date = *(USHORT *)&dir->next->fdateLastWrite; | |
206 | |
207 switch (dir->fstype) { | |
208 case 'F': /* FAT */ | |
209 case 'C': /* CDFS */ | |
210 if (dir->next->attrFile & FILE_DIRECTORY) | |
211 strupr(dir->entry.d_name); | |
212 else | |
213 strlwr(dir->entry.d_name); | |
214 } | |
215 | |
216 dir->next = (FFBUF *)((BYTE *)dir->next + dir->next->oNextEntryOffset); | |
217 ++dir->number; | |
218 ++dir->index; | |
219 | |
220 return &dir->entry; | |
221 } | |
222 | |
525
2ff26b697877
Fixes for building with Innotek GCC. Will have to check for regressions
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
289
diff
changeset
|
223 long API _telldir(DIR *dir) |
3 | 224 { |
225 return dir->number; | |
226 } | |
227 | |
525
2ff26b697877
Fixes for building with Innotek GCC. Will have to check for regressions
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
289
diff
changeset
|
228 void API _seekdir(DIR *dir, long off) |
3 | 229 { |
230 if (dir->number > off) { | |
231 char name[MAXPATHLEN+2]; | |
232 Word rc; | |
233 | |
234 DosFindClose(dir->handle); | |
235 | |
236 strcpy(name, dir->name); | |
237 strcat(name, "*"); | |
238 | |
239 dir->handle = HDIR_CREATE; | |
240 dir->count = 32767; | |
1341
184b3aedc2ff
Added PMPrintf support to dw_debug() on OS/2.
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
528
diff
changeset
|
241 rc = DosFindFirst((PSZ)name, &dir->handle, dir->attrmask, |
3 | 242 dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD); |
243 switch (rc) { | |
244 default: | |
245 error(rc); | |
246 return; | |
247 case NO_ERROR: | |
248 case ERROR_NO_MORE_FILES: | |
249 ; | |
250 } | |
251 | |
252 dir->number = 0; | |
253 dir->index = 0; | |
254 dir->next = (FFBUF *)dir->ffbuf; | |
255 } | |
256 | |
257 while (dir->number < off && readdir(dir)) | |
258 ; | |
259 } | |
260 | |
525
2ff26b697877
Fixes for building with Innotek GCC. Will have to check for regressions
bsmith@81767d24-ef19-dc11-ae90-00e081727c95
parents:
289
diff
changeset
|
261 void API _closedir(DIR *dir) |
3 | 262 { |
263 DosFindClose(dir->handle); | |
264 free(dir); | |
265 } | |
266 | |
267 /*****************************************************************************/ | |
268 | |
269 #ifdef TEST | |
270 | |
271 main(int argc, char **argv) | |
272 { | |
273 int i; | |
274 DIR *dir; | |
275 struct dirent *ep; | |
276 | |
277 for (i = 1; i < argc; ++i) { | |
278 dir = opendir(argv[i]); | |
279 if (!dir) | |
280 continue; | |
281 while (ep = readdir(dir)) | |
282 if (strchr("\\/:", argv[i] [strlen(argv[i]) - 1])) | |
283 printf("%s%s\n", argv[i], ep->d_name); | |
284 else | |
285 printf("%s/%s\n", argv[i], ep->d_name); | |
286 closedir(dir); | |
287 } | |
288 | |
289 return 0; | |
290 } | |
291 | |
292 #endif | |
293 |