Commit | Line | Data |
39c3038c |
1 | /* |
2 | * @(#)dir.c 1.4 87/11/06 Public Domain. |
3 | * |
4 | * A public domain implementation of BSD directory routines for |
5 | * MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield), |
6 | * August 1897 |
7 | * Ported to OS/2 by Kai Uwe Rommel |
57ebbfd0 |
8 | * December 1989, February 1990 |
9 | * Change for HPFS support, October 1990 |
39c3038c |
10 | */ |
11 | |
12 | #include <sys/types.h> |
13 | #include <sys/stat.h> |
14 | #include <sys/dir.h> |
15 | |
57ebbfd0 |
16 | #include <stdlib.h> |
39c3038c |
17 | #include <stdio.h> |
18 | #include <malloc.h> |
19 | #include <string.h> |
57ebbfd0 |
20 | #include <ctype.h> |
39c3038c |
21 | |
22 | #define INCL_NOPM |
23 | #include <os2.h> |
24 | |
25 | |
fe14fcc3 |
26 | #ifndef PERLGLOB |
39c3038c |
27 | int attributes = A_DIR | A_HIDDEN; |
28 | |
29 | |
30 | static char *getdirent(char *); |
31 | static void free_dircontents(struct _dircontents *); |
32 | |
33 | static HDIR hdir; |
34 | static USHORT count; |
35 | static FILEFINDBUF find; |
57ebbfd0 |
36 | static BOOL lower; |
39c3038c |
37 | |
38 | |
39 | DIR *opendir(char *name) |
40 | { |
41 | struct stat statb; |
42 | DIR *dirp; |
43 | char c; |
44 | char *s; |
45 | struct _dircontents *dp; |
46 | char nbuf[MAXPATHLEN + 1]; |
47 | |
48 | strcpy(nbuf, name); |
49 | |
50 | if ( ((c = nbuf[strlen(nbuf) - 1]) == '\\' || c == '/') && |
51 | (strlen(nbuf) > 1) ) |
52 | { |
53 | nbuf[strlen(nbuf) - 1] = 0; |
54 | |
55 | if ( nbuf[strlen(nbuf) - 1] == ':' ) |
56 | strcat(nbuf, "\\."); |
57 | } |
58 | else |
59 | if ( nbuf[strlen(nbuf) - 1] == ':' ) |
60 | strcat(nbuf, "."); |
61 | |
62 | if (stat(nbuf, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR) |
63 | return NULL; |
64 | |
65 | if ( (dirp = malloc(sizeof(DIR))) == NULL ) |
66 | return NULL; |
67 | |
68 | if ( nbuf[strlen(nbuf) - 1] == '.' ) |
69 | strcpy(nbuf + strlen(nbuf) - 1, "*.*"); |
70 | else |
71 | if ( ((c = nbuf[strlen(nbuf) - 1]) == '\\' || c == '/') && |
72 | (strlen(nbuf) == 1) ) |
73 | strcat(nbuf, "*.*"); |
74 | else |
75 | strcat(nbuf, "\\*.*"); |
76 | |
77 | dirp -> dd_loc = 0; |
78 | dirp -> dd_contents = dirp -> dd_cp = NULL; |
79 | |
80 | if ((s = getdirent(nbuf)) == NULL) |
81 | return dirp; |
82 | |
83 | do |
84 | { |
85 | if (((dp = malloc(sizeof(struct _dircontents))) == NULL) || |
86 | ((dp -> _d_entry = malloc(strlen(s) + 1)) == NULL) ) |
87 | { |
88 | if (dp) |
89 | free(dp); |
90 | free_dircontents(dirp -> dd_contents); |
91 | |
92 | return NULL; |
93 | } |
94 | |
95 | if (dirp -> dd_contents) |
96 | dirp -> dd_cp = dirp -> dd_cp -> _d_next = dp; |
97 | else |
98 | dirp -> dd_contents = dirp -> dd_cp = dp; |
99 | |
100 | strcpy(dp -> _d_entry, s); |
101 | dp -> _d_next = NULL; |
102 | |
103 | dp -> _d_size = find.cbFile; |
104 | dp -> _d_mode = find.attrFile; |
105 | dp -> _d_time = *(unsigned *) &(find.ftimeLastWrite); |
106 | dp -> _d_date = *(unsigned *) &(find.fdateLastWrite); |
107 | } |
108 | while ((s = getdirent(NULL)) != NULL); |
109 | |
110 | dirp -> dd_cp = dirp -> dd_contents; |
111 | |
112 | return dirp; |
113 | } |
114 | |
115 | |
116 | void closedir(DIR * dirp) |
117 | { |
118 | free_dircontents(dirp -> dd_contents); |
119 | free(dirp); |
120 | } |
121 | |
122 | |
123 | struct direct *readdir(DIR * dirp) |
124 | { |
125 | static struct direct dp; |
126 | |
127 | if (dirp -> dd_cp == NULL) |
128 | return NULL; |
129 | |
130 | dp.d_namlen = dp.d_reclen = |
131 | strlen(strcpy(dp.d_name, dirp -> dd_cp -> _d_entry)); |
132 | |
39c3038c |
133 | dp.d_ino = 0; |
134 | |
135 | dp.d_size = dirp -> dd_cp -> _d_size; |
136 | dp.d_mode = dirp -> dd_cp -> _d_mode; |
137 | dp.d_time = dirp -> dd_cp -> _d_time; |
138 | dp.d_date = dirp -> dd_cp -> _d_date; |
139 | |
140 | dirp -> dd_cp = dirp -> dd_cp -> _d_next; |
141 | dirp -> dd_loc++; |
142 | |
143 | return &dp; |
144 | } |
145 | |
146 | |
147 | void seekdir(DIR * dirp, long off) |
148 | { |
149 | long i = off; |
150 | struct _dircontents *dp; |
151 | |
152 | if (off >= 0) |
153 | { |
154 | for (dp = dirp -> dd_contents; --i >= 0 && dp; dp = dp -> _d_next); |
155 | |
156 | dirp -> dd_loc = off - (i + 1); |
157 | dirp -> dd_cp = dp; |
158 | } |
159 | } |
160 | |
161 | |
162 | long telldir(DIR * dirp) |
163 | { |
164 | return dirp -> dd_loc; |
165 | } |
166 | |
167 | |
168 | static void free_dircontents(struct _dircontents * dp) |
169 | { |
170 | struct _dircontents *odp; |
171 | |
172 | while (dp) |
173 | { |
174 | if (dp -> _d_entry) |
175 | free(dp -> _d_entry); |
176 | |
177 | dp = (odp = dp) -> _d_next; |
178 | free(odp); |
179 | } |
180 | } |
181 | |
182 | |
fe14fcc3 |
183 | static |
184 | #endif |
185 | int IsFileSystemFAT(char *dir) |
57ebbfd0 |
186 | { |
187 | USHORT nDrive; |
188 | ULONG lMap; |
189 | BYTE bData[64], bName[3]; |
190 | USHORT cbData; |
191 | |
192 | if ( _osmode == DOS_MODE ) |
193 | return TRUE; |
194 | else |
195 | { |
196 | /* We separate FAT and HPFS file systems here. |
197 | * Filenames read from a FAT system are converted to lower case |
198 | * while the case of filenames read from a HPFS (and other future |
199 | * file systems, like Unix-compatibles) is preserved. |
200 | */ |
201 | |
202 | if ( isalpha(dir[0]) && (dir[1] == ':') ) |
203 | nDrive = toupper(dir[0]) - '@'; |
204 | else |
205 | DosQCurDisk(&nDrive, &lMap); |
206 | |
207 | bName[0] = (char) (nDrive + '@'); |
208 | bName[1] = ':'; |
209 | bName[2] = 0; |
210 | |
211 | cbData = sizeof(bData); |
212 | |
213 | if ( !DosQFSAttach(bName, 0U, 1U, bData, &cbData, 0L) ) |
214 | return !strcmp(bData + (*(USHORT *) (bData + 2) + 7), "FAT"); |
215 | else |
216 | return FALSE; |
217 | |
218 | /* End of this ugly code */ |
219 | } |
220 | } |
221 | |
fe14fcc3 |
222 | #ifndef PERLGLOB |
39c3038c |
223 | static char *getdirent(char *dir) |
224 | { |
225 | int done; |
226 | |
227 | if (dir != NULL) |
228 | { /* get first entry */ |
57ebbfd0 |
229 | lower = IsFileSystemFAT(dir); |
230 | |
39c3038c |
231 | hdir = HDIR_CREATE; |
232 | count = 1; |
233 | done = DosFindFirst(dir, &hdir, attributes, |
234 | &find, sizeof(find), &count, 0L); |
235 | } |
236 | else /* get next entry */ |
237 | done = DosFindNext(hdir, &find, sizeof(find), &count); |
238 | |
57ebbfd0 |
239 | if ( lower ) |
240 | strlwr(find.achName); |
241 | |
39c3038c |
242 | if (done == 0) |
243 | return find.achName; |
244 | else |
245 | { |
246 | DosFindClose(hdir); |
247 | return NULL; |
248 | } |
249 | } |
fe14fcc3 |
250 | #endif |