perl 3.0 patch #22 patch #19, continued
[p5sagit/p5-mst-13.2.git] / msdos / directory.c
CommitLineData
b1248f16 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
44static char rcsid[] = "$Header: director.c;v 1.3 90/03/16 22:39:40 dds Exp
45 $";
46#endif
47
48DIR *
49opendir(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
135struct direct *
136readdir(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
155long
156telldir(DIR *dirp)
157{
158 return (long) dirp->curr; /* ouch! pointer to long cast */
159}
160
161void
162seekdir(DIR *dirp, long loc)
163{
164 dirp->curr = (char *) loc; /* ouch! long to pointer cast */
165}
166
167void
168rewinddir(DIR *dirp)
169{
170 dirp->curr = dirp->start;
171}
172
173void
174closedir(DIR *dirp)
175{
176 free(dirp->start);
177 free(dirp);
178}