1*c1022ef1Srin /* $NetBSD: dosfile.c,v 1.2 2024/06/29 13:46:40 rin Exp $ */
21ecb4f3fSrin
31ecb4f3fSrin /*
41ecb4f3fSrin * Copyright (c) 1996
51ecb4f3fSrin * Matthias Drochner. All rights reserved.
61ecb4f3fSrin *
71ecb4f3fSrin * Redistribution and use in source and binary forms, with or without
81ecb4f3fSrin * modification, are permitted provided that the following conditions
91ecb4f3fSrin * are met:
101ecb4f3fSrin * 1. Redistributions of source code must retain the above copyright
111ecb4f3fSrin * notice, this list of conditions and the following disclaimer.
121ecb4f3fSrin * 2. Redistributions in binary form must reproduce the above copyright
131ecb4f3fSrin * notice, this list of conditions and the following disclaimer in the
141ecb4f3fSrin * documentation and/or other materials provided with the distribution.
151ecb4f3fSrin *
161ecb4f3fSrin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
171ecb4f3fSrin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
181ecb4f3fSrin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
191ecb4f3fSrin * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
201ecb4f3fSrin * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
211ecb4f3fSrin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
221ecb4f3fSrin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
231ecb4f3fSrin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
241ecb4f3fSrin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
251ecb4f3fSrin * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
261ecb4f3fSrin *
271ecb4f3fSrin */
281ecb4f3fSrin
291ecb4f3fSrin /*
301ecb4f3fSrin * DOS filesystem for libsa
311ecb4f3fSrin * standalone - uses no device, works only with DOS running
321ecb4f3fSrin * needs lowlevel parts from dos_file.S
331ecb4f3fSrin */
341ecb4f3fSrin
351ecb4f3fSrin #include <lib/libsa/stand.h>
361ecb4f3fSrin
371ecb4f3fSrin #include "diskbuf.h"
381ecb4f3fSrin #include "dosfile.h"
391ecb4f3fSrin
401ecb4f3fSrin struct dosfile {
411ecb4f3fSrin int doshandle, off;
421ecb4f3fSrin };
431ecb4f3fSrin
441ecb4f3fSrin extern int doserrno; /* in dos_file.S */
451ecb4f3fSrin
461ecb4f3fSrin static int dos2errno(void);
471ecb4f3fSrin
481ecb4f3fSrin static int
dos2errno(void)491ecb4f3fSrin dos2errno(void)
501ecb4f3fSrin {
511ecb4f3fSrin int err;
521ecb4f3fSrin
531ecb4f3fSrin switch (doserrno) {
541ecb4f3fSrin case 1: /* invalid function number */
551ecb4f3fSrin case 4: /* too many open files */
561ecb4f3fSrin case 12: /* invalid access mode */
571ecb4f3fSrin default:
581ecb4f3fSrin err = EIO;
591ecb4f3fSrin break;
601ecb4f3fSrin case 2: /* file not found */
611ecb4f3fSrin case 3: /* path not found */
621ecb4f3fSrin err = ENOENT;
631ecb4f3fSrin break;
641ecb4f3fSrin case 5: /* access denied */
651ecb4f3fSrin err = EPERM;
661ecb4f3fSrin break;
671ecb4f3fSrin case 6: /* invalid handle */
681ecb4f3fSrin err = EINVAL;
691ecb4f3fSrin break;
701ecb4f3fSrin }
711ecb4f3fSrin return err;
721ecb4f3fSrin }
731ecb4f3fSrin
741ecb4f3fSrin __compactcall int
dos_open(const char * path,struct open_file * f)751ecb4f3fSrin dos_open(const char *path, struct open_file *f)
761ecb4f3fSrin {
771ecb4f3fSrin struct dosfile *df;
781ecb4f3fSrin
791ecb4f3fSrin df = (struct dosfile *) alloc(sizeof(*df));
801ecb4f3fSrin if (!df)
811ecb4f3fSrin return -1;
821ecb4f3fSrin
831ecb4f3fSrin df->off = 0;
841ecb4f3fSrin df->doshandle = dosopen(path);
851ecb4f3fSrin if (df->doshandle < 0) {
861ecb4f3fSrin #ifdef DEBUG
871ecb4f3fSrin printf("DOS error %d\n", doserrno);
881ecb4f3fSrin #endif
891ecb4f3fSrin dealloc(df, sizeof(*df));
901ecb4f3fSrin return dos2errno();
911ecb4f3fSrin }
921ecb4f3fSrin f->f_fsdata = (void *) df;
931ecb4f3fSrin return 0;
941ecb4f3fSrin }
951ecb4f3fSrin
961ecb4f3fSrin __compactcall int
dos_read(struct open_file * f,void * addr,size_t size,size_t * resid)971ecb4f3fSrin dos_read(struct open_file *f, void *addr, size_t size, size_t *resid)
981ecb4f3fSrin {
991ecb4f3fSrin struct dosfile *df;
1001ecb4f3fSrin int got;
1011ecb4f3fSrin static int tc = 0;
1021ecb4f3fSrin
1031ecb4f3fSrin df = (struct dosfile *) f->f_fsdata;
1041ecb4f3fSrin
1051ecb4f3fSrin if (!(tc++ % 4))
1061ecb4f3fSrin twiddle();
1071ecb4f3fSrin
1081ecb4f3fSrin if ((unsigned long) addr >= 0x10000) {
1091ecb4f3fSrin u_int lsize = size;
1101ecb4f3fSrin
1111ecb4f3fSrin while (lsize > 0) {
1121ecb4f3fSrin u_int tsize;
1131ecb4f3fSrin size_t tgot;
1141ecb4f3fSrin char *p = addr;
1151ecb4f3fSrin
1161ecb4f3fSrin tsize = lsize;
1171ecb4f3fSrin
1181ecb4f3fSrin if (tsize > DISKBUFSIZE)
1191ecb4f3fSrin tsize = DISKBUFSIZE;
1201ecb4f3fSrin
1211ecb4f3fSrin alloc_diskbuf(dos_read);
1221ecb4f3fSrin
1231ecb4f3fSrin tgot = dosread(df->doshandle, diskbufp, tsize);
1241ecb4f3fSrin if (tgot < 0) {
1251ecb4f3fSrin #ifdef DEBUG
1261ecb4f3fSrin printf("DOS error %d\n", doserrno);
1271ecb4f3fSrin #endif
1281ecb4f3fSrin return dos2errno();
1291ecb4f3fSrin }
1301ecb4f3fSrin memcpy(p, diskbufp, tgot);
1311ecb4f3fSrin
1321ecb4f3fSrin p += tgot;
1331ecb4f3fSrin lsize -= tgot;
1341ecb4f3fSrin
1351ecb4f3fSrin if (tgot != tsize)
1361ecb4f3fSrin break; /* EOF */
1371ecb4f3fSrin }
1381ecb4f3fSrin got = size - lsize;
1391ecb4f3fSrin } else {
1401ecb4f3fSrin got = dosread(df->doshandle, addr, size);
1411ecb4f3fSrin
1421ecb4f3fSrin if (got < 0) {
1431ecb4f3fSrin #ifdef DEBUG
1441ecb4f3fSrin printf("DOS error %d\n", doserrno);
1451ecb4f3fSrin #endif
1461ecb4f3fSrin return dos2errno();
1471ecb4f3fSrin }
1481ecb4f3fSrin }
1491ecb4f3fSrin
1501ecb4f3fSrin df->off += got;
1511ecb4f3fSrin size -= got;
1521ecb4f3fSrin
1531ecb4f3fSrin if (resid)
1541ecb4f3fSrin *resid = size;
1551ecb4f3fSrin return 0;
1561ecb4f3fSrin }
1571ecb4f3fSrin
1581ecb4f3fSrin __compactcall int
dos_close(struct open_file * f)1591ecb4f3fSrin dos_close(struct open_file *f)
1601ecb4f3fSrin {
1611ecb4f3fSrin struct dosfile *df;
1621ecb4f3fSrin df = (struct dosfile *) f->f_fsdata;
1631ecb4f3fSrin
1641ecb4f3fSrin dosclose(df->doshandle);
1651ecb4f3fSrin
1661ecb4f3fSrin if (df)
1671ecb4f3fSrin dealloc(df, sizeof(*df));
1681ecb4f3fSrin return 0;
1691ecb4f3fSrin }
1701ecb4f3fSrin
1711ecb4f3fSrin __compactcall int
dos_write(struct open_file * f,void * start,size_t size,size_t * resid)1721ecb4f3fSrin dos_write(struct open_file *f, void *start, size_t size, size_t *resid)
1731ecb4f3fSrin {
1741ecb4f3fSrin return EROFS;
1751ecb4f3fSrin }
1761ecb4f3fSrin
1771ecb4f3fSrin __compactcall int
dos_stat(struct open_file * f,struct stat * sb)1781ecb4f3fSrin dos_stat(struct open_file *f, struct stat *sb)
1791ecb4f3fSrin {
1801ecb4f3fSrin sb->st_mode = 0444;
1811ecb4f3fSrin sb->st_nlink = 1;
1821ecb4f3fSrin sb->st_uid = 0;
1831ecb4f3fSrin sb->st_gid = 0;
1841ecb4f3fSrin sb->st_size = -1;
1851ecb4f3fSrin return 0;
1861ecb4f3fSrin }
1871ecb4f3fSrin
1881ecb4f3fSrin __compactcall off_t
dos_seek(struct open_file * f,off_t offset,int where)1891ecb4f3fSrin dos_seek(struct open_file *f, off_t offset, int where)
1901ecb4f3fSrin {
1911ecb4f3fSrin struct dosfile *df;
1921ecb4f3fSrin int doswhence, res;
1931ecb4f3fSrin #ifdef DOS_CHECK
1941ecb4f3fSrin int checkoffs;
1951ecb4f3fSrin #endif
1961ecb4f3fSrin df = (struct dosfile *) f->f_fsdata;
1971ecb4f3fSrin
1981ecb4f3fSrin switch (where) {
1991ecb4f3fSrin case SEEK_SET:
2001ecb4f3fSrin doswhence = 0;
2011ecb4f3fSrin #ifdef DOS_CHECK
2021ecb4f3fSrin checkoffs = offset; /* don't trust DOS */
2031ecb4f3fSrin #endif
2041ecb4f3fSrin break;
2051ecb4f3fSrin case SEEK_CUR:
2061ecb4f3fSrin doswhence = 1;
2071ecb4f3fSrin #ifdef DOS_CHECK
2081ecb4f3fSrin checkoffs = df->off + offset;
2091ecb4f3fSrin #endif
2101ecb4f3fSrin break;
2111ecb4f3fSrin case SEEK_END:
2121ecb4f3fSrin doswhence = 2;
2131ecb4f3fSrin #ifdef DOS_CHECK
2141ecb4f3fSrin checkoffs = -1; /* we dont know len */
2151ecb4f3fSrin #endif
2161ecb4f3fSrin break;
2171ecb4f3fSrin default:
2181ecb4f3fSrin errno = EOFFSET;
2191ecb4f3fSrin return -1;
2201ecb4f3fSrin }
2211ecb4f3fSrin res = dosseek(df->doshandle, offset, doswhence);
2221ecb4f3fSrin if (res == -1) {
2231ecb4f3fSrin errno = dos2errno();
2241ecb4f3fSrin return -1;
2251ecb4f3fSrin }
2261ecb4f3fSrin #ifdef DOS_CHECK
2271ecb4f3fSrin if ((checkoffs != -1) && (res != checkoffs)) {
2281ecb4f3fSrin printf("dosfile: unexpected seek result (%d+%d(%d)=%d)\n",
2291ecb4f3fSrin df->off, offset, where, res);
2301ecb4f3fSrin errno = EOFFSET;
2311ecb4f3fSrin return -1;
2321ecb4f3fSrin }
2331ecb4f3fSrin #endif
2341ecb4f3fSrin df->off = res;
2351ecb4f3fSrin return res;
2361ecb4f3fSrin }
237