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