Commit | Line | Data |
fe14fcc3 |
1 | /* $Header: directory.c,v 4.0 91/03/20 01:34:24 lwall Locked $ |
b1248f16 |
2 | * |
3 | * (C) Copyright 1987, 1988, 1990 Diomidis Spinellis. |
4 | * |
5 | * You may distribute under the terms of the GNU General Public License |
6 | * as specified in the README file that comes with the perl 3.0 kit. |
7 | * |
8 | * $Log: directory.c,v $ |
fe14fcc3 |
9 | * Revision 4.0 91/03/20 01:34:24 lwall |
10 | * 4.0 baseline. |
11 | * |
b1248f16 |
12 | * Revision 3.0.1.1 90/03/27 16:07:37 lwall |
13 | * patch16: MSDOS support |
14 | * |
15 | * Revision 1.3 90/03/16 22:39:40 dds |
16 | * Fixed malloc problem. |
17 | * |
18 | * Revision 1.2 88/07/23 00:08:39 dds |
19 | * Added inode non-zero filling. |
20 | * |
21 | * Revision 1.1 88/07/23 00:03:50 dds |
22 | * Initial revision |
23 | * |
24 | */ |
25 | |
26 | /* |
27 | * UNIX compatible directory access functions |
28 | */ |
29 | |
30 | #include <sys/types.h> |
31 | #include <sys/dir.h> |
32 | #include <stddef.h> |
33 | #include <stdlib.h> |
34 | #include <string.h> |
35 | #include <dos.h> |
36 | #include <ctype.h> |
37 | |
38 | /* |
39 | * File names are converted to lowercase if the |
40 | * CONVERT_TO_LOWER_CASE variable is defined. |
41 | */ |
42 | #define CONVERT_TO_LOWER_CASE |
43 | |
44 | #define PATHLEN 65 |
45 | |
46 | #ifndef lint |
fe14fcc3 |
47 | static char rcsid[] = "$Header: directory.c,v 4.0 91/03/20 01:34:24 lwall Locked $"; |
b1248f16 |
48 | #endif |
49 | |
50 | DIR * |
51 | opendir(char *filename) |
52 | { |
53 | DIR *p; |
54 | char *oldresult, *result; |
55 | union REGS srv; |
56 | struct SREGS segregs; |
57 | register reslen = 0; |
58 | char scannamespc[PATHLEN]; |
59 | char *scanname = scannamespc; /* To take address we need a pointer */ |
60 | |
61 | /* |
62 | * Structure used by the MS-DOS directory system calls. |
63 | */ |
64 | struct dir_buff { |
65 | char reserved[21]; /* Reserved for MS-DOS */ |
66 | unsigned char attribute; /* Attribute */ |
67 | unsigned int time; /* Time */ |
68 | unsigned int date; /* Date */ |
69 | long size; /* Size of file */ |
70 | char fn[13]; /* Filename */ |
71 | } buffspc, *buff = &buffspc; |
72 | |
73 | |
74 | if (!(p = (DIR *) malloc(sizeof(DIR)))) |
75 | return NULL; |
76 | |
77 | /* Initialize result to use realloc on it */ |
78 | if (!(result = malloc(1))) { |
79 | free(p); |
80 | return NULL; |
81 | } |
82 | |
83 | /* Create the search pattern */ |
84 | strcpy(scanname, filename); |
85 | if (strchr("/\\", *(scanname + strlen(scanname) - 1)) == NULL) |
86 | strcat(scanname, "/*.*"); |
87 | else |
88 | strcat(scanname, "*.*"); |
89 | |
90 | segread(&segregs); |
91 | #if ( defined(M_I86LM) || defined(M_I86CM) || defined(M_I86HM) ) |
92 | segregs.ds = FP_SEG(buff); |
93 | srv.x.dx = FP_OFF(buff); |
94 | #else |
95 | srv.x.dx = (unsigned int) buff; |
96 | #endif |
97 | srv.h.ah = 0x1a; /* Set DTA to DS:DX */ |
98 | intdosx(&srv, &srv, &segregs); |
99 | |
100 | #if ( defined(M_I86LM) || defined(M_I86CM) || defined(M_I86HM) ) |
101 | segregs.ds = FP_SEG(scanname); |
102 | srv.x.dx = FP_OFF(scanname); |
103 | #else |
104 | srv.x.dx = (unsigned int) scanname; |
105 | #endif |
106 | srv.x.cx = 0xff; /* Search mode */ |
107 | |
108 | for (srv.h.ah = 0x4e; !intdosx(&srv, &srv, &segregs); srv.h.ah = 0x4f) { |
109 | if ((result = (char *) realloc(result, reslen + strlen(buff->fn) + 1)) == |
110 | NULL) { |
111 | free(p); |
112 | free(oldresult); |
113 | return NULL; |
114 | } |
115 | oldresult = result; |
116 | #ifdef CONVERT_TO_LOWER_CASE |
117 | strcpy(result + reslen, strlwr(buff->fn)); |
118 | #else |
119 | strcpy(result + reslen, buff->fn); |
120 | #endif |
121 | reslen += strlen(buff->fn) + 1; |
122 | } |
123 | |
124 | if (!(result = realloc(result, reslen + 1))) { |
125 | free(p); |
126 | free(oldresult); |
127 | return NULL; |
128 | } else { |
129 | p->start = result; |
130 | p->curr = result; |
131 | *(result + reslen) = '\0'; |
132 | return p; |
133 | } |
134 | } |
135 | |
136 | |
137 | struct direct * |
138 | readdir(DIR *dirp) |
139 | { |
140 | char *p; |
141 | register len; |
142 | static dummy; |
143 | |
144 | p = dirp->curr; |
145 | len = strlen(p); |
146 | if (*p) { |
147 | dirp->curr += len + 1; |
148 | strcpy(dirp->dirstr.d_name, p); |
149 | dirp->dirstr.d_namlen = len; |
150 | /* To fool programs */ |
151 | dirp->dirstr.d_ino = ++dummy; |
152 | return &(dirp->dirstr); |
153 | } else |
154 | return NULL; |
155 | } |
156 | |
157 | long |
158 | telldir(DIR *dirp) |
159 | { |
160 | return (long) dirp->curr; /* ouch! pointer to long cast */ |
161 | } |
162 | |
163 | void |
164 | seekdir(DIR *dirp, long loc) |
165 | { |
166 | dirp->curr = (char *) loc; /* ouch! long to pointer cast */ |
167 | } |
168 | |
169 | void |
170 | rewinddir(DIR *dirp) |
171 | { |
172 | dirp->curr = dirp->start; |
173 | } |
174 | |
175 | void |
176 | closedir(DIR *dirp) |
177 | { |
178 | free(dirp->start); |
179 | free(dirp); |
180 | } |