perl 4.0.00: (no release announcement available)
[p5sagit/p5-mst-13.2.git] / msdos / directory.c
1 /* $Header: directory.c,v 4.0 91/03/20 01:34:24 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 4.0  91/03/20  01:34:24  lwall
10  * 4.0 baseline.
11  * 
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
47 static char rcsid[] = "$Header: directory.c,v 4.0 91/03/20 01:34:24 lwall Locked $";
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 }