perl 4.0.00: (no release announcement available)
[p5sagit/p5-mst-13.2.git] / msdos / directory.c
CommitLineData
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 47static char rcsid[] = "$Header: directory.c,v 4.0 91/03/20 01:34:24 lwall Locked $";
b1248f16 48#endif
49
50DIR *
51opendir(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
137struct direct *
138readdir(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
157long
158telldir(DIR *dirp)
159{
160 return (long) dirp->curr; /* ouch! pointer to long cast */
161}
162
163void
164seekdir(DIR *dirp, long loc)
165{
166 dirp->curr = (char *) loc; /* ouch! long to pointer cast */
167}
168
169void
170rewinddir(DIR *dirp)
171{
172 dirp->curr = dirp->start;
173}
174
175void
176closedir(DIR *dirp)
177{
178 free(dirp->start);
179 free(dirp);
180}