xref: /minix/sys/arch/i386/stand/lib/dosfile.c (revision 84d9c625)
1 /*	$NetBSD: dosfile.c,v 1.16 2013/10/20 21:06:37 christos 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
dos2errno(void)54 dos2errno(void)
55 {
56 	int err;
57 
58 	switch (doserrno) {
59 	    case 1:
60 	    case 4:
61 	    case 12:
62 	    default:
63 		err = EIO;
64 	    case 2:
65 	    case 3:
66 		err = ENOENT;
67 	    case 5:
68 		err = EPERM;
69 	    case 6:
70 		err = EINVAL;
71 	}
72 	return err;
73 }
74 
75 __compactcall int
dos_open(const char * path,struct open_file * f)76 dos_open(const char *path, struct open_file *f)
77 {
78 	struct dosfile *df;
79 
80 	df = (struct dosfile *) alloc(sizeof(*df));
81 	if (!df)
82 		return -1;
83 
84 	df->off = 0;
85 	df->doshandle = dosopen(path);
86 	if (df->doshandle < 0) {
87 #ifdef DEBUG
88 		printf("DOS error %d\n", doserrno);
89 #endif
90 		dealloc(df, sizeof(*df));
91 		return dos2errno();
92 	}
93 	f->f_fsdata = (void *) df;
94 	return 0;
95 }
96 
97 __compactcall int
dos_read(struct open_file * f,void * addr,size_t size,size_t * resid)98 dos_read(struct open_file *f, void *addr, size_t size, size_t *resid)
99 {
100 	struct dosfile *df;
101 	int             got;
102 	static int      tc = 0;
103 
104 	df = (struct dosfile *) f->f_fsdata;
105 
106 	if (!(tc++ % 4))
107 		twiddle();
108 
109 	if ((unsigned long) addr >= 0x10000) {
110 		u_int           lsize = size;
111 
112 		while (lsize > 0) {
113 			u_int           tsize;
114 			size_t          tgot;
115 			char		*p = addr;
116 
117 			tsize = lsize;
118 
119 			if (tsize > DISKBUFSIZE)
120 				tsize = DISKBUFSIZE;
121 
122 			alloc_diskbuf(dos_read);
123 
124 			tgot = dosread(df->doshandle, diskbufp, tsize);
125 			if (tgot < 0) {
126 #ifdef DEBUG
127 				printf("DOS error %d\n", doserrno);
128 #endif
129 				return dos2errno();
130 			}
131 			memcpy(p, diskbufp, tgot);
132 
133 			p += tgot;
134 			lsize -= tgot;
135 
136 			if (tgot != tsize)
137 				break;	/* EOF */
138 		}
139 		got = size - lsize;
140 	} else {
141 		got = dosread(df->doshandle, addr, size);
142 
143 		if (got < 0) {
144 #ifdef DEBUG
145 			printf("DOS error %d\n", doserrno);
146 #endif
147 			return dos2errno();
148 		}
149 	}
150 
151 	df->off += got;
152 	size -= got;
153 
154 	if (resid)
155 		*resid = size;
156 	return 0;
157 }
158 
159 __compactcall int
dos_close(struct open_file * f)160 dos_close(struct open_file *f)
161 {
162 	struct dosfile *df;
163 	df = (struct dosfile *) f->f_fsdata;
164 
165 	dosclose(df->doshandle);
166 
167 	if (df)
168 		dealloc(df, sizeof(*df));
169 	return 0;
170 }
171 
172 __compactcall int
dos_write(struct open_file * f,void * start,size_t size,size_t * resid)173 dos_write(struct open_file *f, void *start, size_t size, size_t *resid)
174 {
175 	return EROFS;
176 }
177 
178 __compactcall int
dos_stat(struct open_file * f,struct stat * sb)179 dos_stat(struct open_file *f, struct stat *sb)
180 {
181 	sb->st_mode = 0444;
182 	sb->st_nlink = 1;
183 	sb->st_uid = 0;
184 	sb->st_gid = 0;
185 	sb->st_size = -1;
186 	return 0;
187 }
188 
189 __compactcall off_t
dos_seek(struct open_file * f,off_t offset,int where)190 dos_seek(struct open_file *f, off_t offset, int where)
191 {
192 	struct dosfile *df;
193 	int             doswhence, res;
194 #ifdef DOS_CHECK
195 	int             checkoffs;
196 #endif
197 	df = (struct dosfile *) f->f_fsdata;
198 
199 	switch (where) {
200 	case SEEK_SET:
201 		doswhence = 0;
202 #ifdef DOS_CHECK
203 		checkoffs = offset;	/* don't trust DOS */
204 #endif
205 		break;
206 	case SEEK_CUR:
207 		doswhence = 1;
208 #ifdef DOS_CHECK
209 		checkoffs = df->off + offset;
210 #endif
211 		break;
212 	case SEEK_END:
213 		doswhence = 2;
214 #ifdef DOS_CHECK
215 		checkoffs = -1;	/* we dont know len */
216 #endif
217 		break;
218 	default:
219 		errno = EOFFSET;
220 		return -1;
221 	}
222 	res = dosseek(df->doshandle, offset, doswhence);
223 	if (res == -1) {
224 		errno = dos2errno();
225 		return -1;
226 	}
227 #ifdef DOS_CHECK
228 	if ((checkoffs != -1) && (res != checkoffs)) {
229 		printf("dosfile: unexpected seek result (%d+%d(%d)=%d)\n",
230 		       df->off, offset, where, res);
231 		errno = EOFFSET;
232 		return -1;
233 	}
234 #endif
235 	df->off = res;
236 	return res;
237 }
238