dosfile.c revision 1.1 1 /* $NetBSD: dosfile.c,v 1.1 2024/06/29 13:45:14 rin Exp $ */
2
3 /*
4 * Copyright (c) 1996
5 * Matthias Drochner. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29 /*
30 * DOS filesystem for libsa
31 * standalone - uses no device, works only with DOS running
32 * needs lowlevel parts from dos_file.S
33 */
34
35 #include <lib/libsa/stand.h>
36
37 #include "diskbuf.h"
38 #include "dosfile.h"
39
40 extern int dosopen(const char *);
41 extern void dosclose(int);
42 extern int dosread(int, char *, int);
43 extern int dosseek(int, int, int);
44
45 struct dosfile {
46 int doshandle, off;
47 };
48
49 extern int doserrno; /* in dos_file.S */
50
51 static int dos2errno(void);
52
53 static int
54 dos2errno(void)
55 {
56 int err;
57
58 switch (doserrno) {
59 case 1: /* invalid function number */
60 case 4: /* too many open files */
61 case 12: /* invalid access mode */
62 default:
63 err = EIO;
64 break;
65 case 2: /* file not found */
66 case 3: /* path not found */
67 err = ENOENT;
68 break;
69 case 5: /* access denied */
70 err = EPERM;
71 break;
72 case 6: /* invalid handle */
73 err = EINVAL;
74 break;
75 }
76 return err;
77 }
78
79 __compactcall int
80 dos_open(const char *path, struct open_file *f)
81 {
82 struct dosfile *df;
83
84 df = (struct dosfile *) alloc(sizeof(*df));
85 if (!df)
86 return -1;
87
88 df->off = 0;
89 df->doshandle = dosopen(path);
90 if (df->doshandle < 0) {
91 #ifdef DEBUG
92 printf("DOS error %d\n", doserrno);
93 #endif
94 dealloc(df, sizeof(*df));
95 return dos2errno();
96 }
97 f->f_fsdata = (void *) df;
98 return 0;
99 }
100
101 __compactcall int
102 dos_read(struct open_file *f, void *addr, size_t size, size_t *resid)
103 {
104 struct dosfile *df;
105 int got;
106 static int tc = 0;
107
108 df = (struct dosfile *) f->f_fsdata;
109
110 if (!(tc++ % 4))
111 twiddle();
112
113 if ((unsigned long) addr >= 0x10000) {
114 u_int lsize = size;
115
116 while (lsize > 0) {
117 u_int tsize;
118 size_t tgot;
119 char *p = addr;
120
121 tsize = lsize;
122
123 if (tsize > DISKBUFSIZE)
124 tsize = DISKBUFSIZE;
125
126 alloc_diskbuf(dos_read);
127
128 tgot = dosread(df->doshandle, diskbufp, tsize);
129 if (tgot < 0) {
130 #ifdef DEBUG
131 printf("DOS error %d\n", doserrno);
132 #endif
133 return dos2errno();
134 }
135 memcpy(p, diskbufp, tgot);
136
137 p += tgot;
138 lsize -= tgot;
139
140 if (tgot != tsize)
141 break; /* EOF */
142 }
143 got = size - lsize;
144 } else {
145 got = dosread(df->doshandle, addr, size);
146
147 if (got < 0) {
148 #ifdef DEBUG
149 printf("DOS error %d\n", doserrno);
150 #endif
151 return dos2errno();
152 }
153 }
154
155 df->off += got;
156 size -= got;
157
158 if (resid)
159 *resid = size;
160 return 0;
161 }
162
163 __compactcall int
164 dos_close(struct open_file *f)
165 {
166 struct dosfile *df;
167 df = (struct dosfile *) f->f_fsdata;
168
169 dosclose(df->doshandle);
170
171 if (df)
172 dealloc(df, sizeof(*df));
173 return 0;
174 }
175
176 __compactcall int
177 dos_write(struct open_file *f, void *start, size_t size, size_t *resid)
178 {
179 return EROFS;
180 }
181
182 __compactcall int
183 dos_stat(struct open_file *f, struct stat *sb)
184 {
185 sb->st_mode = 0444;
186 sb->st_nlink = 1;
187 sb->st_uid = 0;
188 sb->st_gid = 0;
189 sb->st_size = -1;
190 return 0;
191 }
192
193 __compactcall off_t
194 dos_seek(struct open_file *f, off_t offset, int where)
195 {
196 struct dosfile *df;
197 int doswhence, res;
198 #ifdef DOS_CHECK
199 int checkoffs;
200 #endif
201 df = (struct dosfile *) f->f_fsdata;
202
203 switch (where) {
204 case SEEK_SET:
205 doswhence = 0;
206 #ifdef DOS_CHECK
207 checkoffs = offset; /* don't trust DOS */
208 #endif
209 break;
210 case SEEK_CUR:
211 doswhence = 1;
212 #ifdef DOS_CHECK
213 checkoffs = df->off + offset;
214 #endif
215 break;
216 case SEEK_END:
217 doswhence = 2;
218 #ifdef DOS_CHECK
219 checkoffs = -1; /* we dont know len */
220 #endif
221 break;
222 default:
223 errno = EOFFSET;
224 return -1;
225 }
226 res = dosseek(df->doshandle, offset, doswhence);
227 if (res == -1) {
228 errno = dos2errno();
229 return -1;
230 }
231 #ifdef DOS_CHECK
232 if ((checkoffs != -1) && (res != checkoffs)) {
233 printf("dosfile: unexpected seek result (%d+%d(%d)=%d)\n",
234 df->off, offset, where, res);
235 errno = EOFFSET;
236 return -1;
237 }
238 #endif
239 df->off = res;
240 return res;
241 }
242