Home | History | Annotate | Line # | Download | only in dosboot
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