perl 3.0 patch #37 (combined patch)
[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
8 * December 1989
9 */
10
11#include <sys/types.h>
12#include <sys/stat.h>
13#include <sys/dir.h>
14
15#include <stdio.h>
16#include <malloc.h>
17#include <string.h>
18
19#define INCL_NOPM
20#include <os2.h>
21
22
23int attributes = A_DIR | A_HIDDEN;
24
25
26static char *getdirent(char *);
27static void free_dircontents(struct _dircontents *);
28
29static HDIR hdir;
30static USHORT count;
31static FILEFINDBUF find;
32
33
34DIR *opendir(char *name)
35{
36 struct stat statb;
37 DIR *dirp;
38 char c;
39 char *s;
40 struct _dircontents *dp;
41 char nbuf[MAXPATHLEN + 1];
42
43 strcpy(nbuf, name);
44
45 if ( ((c = nbuf[strlen(nbuf) - 1]) == '\\' || c == '/') &&
46 (strlen(nbuf) > 1) )
47 {
48 nbuf[strlen(nbuf) - 1] = 0;
49
50 if ( nbuf[strlen(nbuf) - 1] == ':' )
51 strcat(nbuf, "\\.");
52 }
53 else
54 if ( nbuf[strlen(nbuf) - 1] == ':' )
55 strcat(nbuf, ".");
56
57 if (stat(nbuf, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
58 return NULL;
59
60 if ( (dirp = malloc(sizeof(DIR))) == NULL )
61 return NULL;
62
63 if ( nbuf[strlen(nbuf) - 1] == '.' )
64 strcpy(nbuf + strlen(nbuf) - 1, "*.*");
65 else
66 if ( ((c = nbuf[strlen(nbuf) - 1]) == '\\' || c == '/') &&
67 (strlen(nbuf) == 1) )
68 strcat(nbuf, "*.*");
69 else
70 strcat(nbuf, "\\*.*");
71
72 dirp -> dd_loc = 0;
73 dirp -> dd_contents = dirp -> dd_cp = NULL;
74
75 if ((s = getdirent(nbuf)) == NULL)
76 return dirp;
77
78 do
79 {
80 if (((dp = malloc(sizeof(struct _dircontents))) == NULL) ||
81 ((dp -> _d_entry = malloc(strlen(s) + 1)) == NULL) )
82 {
83 if (dp)
84 free(dp);
85 free_dircontents(dirp -> dd_contents);
86
87 return NULL;
88 }
89
90 if (dirp -> dd_contents)
91 dirp -> dd_cp = dirp -> dd_cp -> _d_next = dp;
92 else
93 dirp -> dd_contents = dirp -> dd_cp = dp;
94
95 strcpy(dp -> _d_entry, s);
96 dp -> _d_next = NULL;
97
98 dp -> _d_size = find.cbFile;
99 dp -> _d_mode = find.attrFile;
100 dp -> _d_time = *(unsigned *) &(find.ftimeLastWrite);
101 dp -> _d_date = *(unsigned *) &(find.fdateLastWrite);
102 }
103 while ((s = getdirent(NULL)) != NULL);
104
105 dirp -> dd_cp = dirp -> dd_contents;
106
107 return dirp;
108}
109
110
111void closedir(DIR * dirp)
112{
113 free_dircontents(dirp -> dd_contents);
114 free(dirp);
115}
116
117
118struct direct *readdir(DIR * dirp)
119{
120 static struct direct dp;
121
122 if (dirp -> dd_cp == NULL)
123 return NULL;
124
125 dp.d_namlen = dp.d_reclen =
126 strlen(strcpy(dp.d_name, dirp -> dd_cp -> _d_entry));
127
128 strlwr(dp.d_name); /* JF */
129 dp.d_ino = 0;
130
131 dp.d_size = dirp -> dd_cp -> _d_size;
132 dp.d_mode = dirp -> dd_cp -> _d_mode;
133 dp.d_time = dirp -> dd_cp -> _d_time;
134 dp.d_date = dirp -> dd_cp -> _d_date;
135
136 dirp -> dd_cp = dirp -> dd_cp -> _d_next;
137 dirp -> dd_loc++;
138
139 return &dp;
140}
141
142
143void seekdir(DIR * dirp, long off)
144{
145 long i = off;
146 struct _dircontents *dp;
147
148 if (off >= 0)
149 {
150 for (dp = dirp -> dd_contents; --i >= 0 && dp; dp = dp -> _d_next);
151
152 dirp -> dd_loc = off - (i + 1);
153 dirp -> dd_cp = dp;
154 }
155}
156
157
158long telldir(DIR * dirp)
159{
160 return dirp -> dd_loc;
161}
162
163
164static void free_dircontents(struct _dircontents * dp)
165{
166 struct _dircontents *odp;
167
168 while (dp)
169 {
170 if (dp -> _d_entry)
171 free(dp -> _d_entry);
172
173 dp = (odp = dp) -> _d_next;
174 free(odp);
175 }
176}
177
178
179static char *getdirent(char *dir)
180{
181 int done;
182
183 if (dir != NULL)
184 { /* get first entry */
185 hdir = HDIR_CREATE;
186 count = 1;
187 done = DosFindFirst(dir, &hdir, attributes,
188 &find, sizeof(find), &count, 0L);
189 }
190 else /* get next entry */
191 done = DosFindNext(hdir, &find, sizeof(find), &count);
192
193 if (done == 0)
194 return find.achName;
195 else
196 {
197 DosFindClose(hdir);
198 return NULL;
199 }
200}