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