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