perl 4.0.00: (no release announcement available)
[p5sagit/p5-mst-13.2.git] / os2 / director.c
CommitLineData
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 27int attributes = A_DIR | A_HIDDEN;
28
29
30static char *getdirent(char *);
31static void free_dircontents(struct _dircontents *);
32
33static HDIR hdir;
34static USHORT count;
35static FILEFINDBUF find;
57ebbfd0 36static BOOL lower;
39c3038c 37
38
39DIR *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
116void closedir(DIR * dirp)
117{
118 free_dircontents(dirp -> dd_contents);
119 free(dirp);
120}
121
122
123struct 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
147void 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
162long telldir(DIR * dirp)
163{
164 return dirp -> dd_loc;
165}
166
167
168static 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 183static
184#endif
185int 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 223static 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