perl 5.0 alpha 2
[p5sagit/p5-mst-13.2.git] / msdos / directory.c
CommitLineData
79072805 1/* $RCSfile: directory.c,v $$Revision: 4.1 $$Date: 92/08/07 18:24:42 $
b1248f16 2 *
3 * (C) Copyright 1987, 1988, 1990 Diomidis Spinellis.
4 *
6e21c824 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.
b1248f16 7 *
8 * $Log: directory.c,v $
79072805 9 * Revision 4.1 92/08/07 18:24:42 lwall
10 *
6e21c824 11 * Revision 4.0.1.1 91/06/07 11:22:24 lwall
12 * patch4: new copyright notice
13 *
fe14fcc3 14 * Revision 4.0 91/03/20 01:34:24 lwall
15 * 4.0 baseline.
16 *
b1248f16 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
79072805 52static char rcsid[] = "$RCSfile: directory.c,v $$Revision: 4.1 $$Date: 92/08/07 18:24:42 $";
b1248f16 53#endif
54
55DIR *
56opendir(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
142struct direct *
143readdir(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
162long
163telldir(DIR *dirp)
164{
165 return (long) dirp->curr; /* ouch! pointer to long cast */
166}
167
168void
169seekdir(DIR *dirp, long loc)
170{
171 dirp->curr = (char *) loc; /* ouch! long to pointer cast */
172}
173
174void
175rewinddir(DIR *dirp)
176{
177 dirp->curr = dirp->start;
178}
179
180void
181closedir(DIR *dirp)
182{
183 free(dirp->start);
184 free(dirp);
185}