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