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