1 /* $NetBSD: dosfile.c,v 1.6 2001/07/07 22:57:57 perry 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 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed for the NetBSD Project 18 * by Matthias Drochner. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 */ 34 35 /* 36 * DOS filesystem for libsa 37 * standalone - uses no device, works only with DOS running 38 * needs lowlevel parts from dos_file.S 39 */ 40 41 #include <lib/libsa/stand.h> 42 43 #include "diskbuf.h" 44 #include "dosfile.h" 45 46 extern int dosopen __P((char *)); 47 extern void dosclose __P((int)); 48 extern int dosread __P((int, char *, int)); 49 extern int dosseek __P((int, int, int)); 50 51 struct dosfile { 52 int doshandle, off; 53 }; 54 55 extern int doserrno; /* in dos_file.S */ 56 57 static int dos2errno __P((void)); 58 59 static int 60 dos2errno() 61 { 62 int err; 63 64 switch (doserrno) { 65 case 1: 66 case 4: 67 case 12: 68 default: 69 err = EIO; 70 case 2: 71 case 3: 72 err = ENOENT; 73 case 5: 74 err = EPERM; 75 case 6: 76 err = EINVAL; 77 } 78 return (err); 79 } 80 81 int 82 dos_open(path, f) 83 char *path; 84 struct open_file *f; 85 { 86 struct dosfile *df; 87 88 df = (struct dosfile *) alloc(sizeof(*df)); 89 if (!df) 90 return (-1); 91 92 df->off = 0; 93 df->doshandle = dosopen(path); 94 if (df->doshandle < 0) { 95 #ifdef DEBUG 96 printf("DOS error %d\n", doserrno); 97 #endif 98 free(df, sizeof(*df)); 99 return (dos2errno()); 100 } 101 f->f_fsdata = (void *) df; 102 return (0); 103 } 104 105 int 106 dos_read(f, addr, size, resid) 107 struct open_file *f; 108 void *addr; 109 size_t size; 110 size_t *resid; /* out */ 111 { 112 struct dosfile *df; 113 int got; 114 static int tc = 0; 115 116 df = (struct dosfile *) f->f_fsdata; 117 118 if (!(tc++ % 4)) 119 twiddle(); 120 121 if ((unsigned long) addr >= 0x10000) { 122 u_int lsize = size; 123 124 while (lsize > 0) { 125 u_int tsize; 126 int tgot; 127 128 tsize = lsize; 129 130 if (tsize > DISKBUFSIZE) 131 tsize = DISKBUFSIZE; 132 133 diskbuf_user = dos_read; 134 135 tgot = dosread(df->doshandle, diskbuf, tsize); 136 137 if (tgot < 0) { 138 #ifdef DEBUG 139 printf("DOS error %d\n", doserrno); 140 #endif 141 return (dos2errno()); 142 } 143 memcpy(addr, diskbuf, tgot); 144 145 (unsigned long)addr += tgot; 146 lsize -= tgot; 147 148 if (tgot != tsize) 149 break; /* EOF */ 150 } 151 got = size - lsize; 152 } else { 153 got = dosread(df->doshandle, addr, size); 154 155 if (got < 0) { 156 #ifdef DEBUG 157 printf("DOS error %d\n", doserrno); 158 #endif 159 return (dos2errno()); 160 } 161 } 162 163 df->off += got; 164 size -= got; 165 166 if (resid) 167 *resid = size; 168 return (0); 169 } 170 171 int 172 dos_close(f) 173 struct open_file *f; 174 { 175 struct dosfile *df; 176 df = (struct dosfile *) f->f_fsdata; 177 178 dosclose(df->doshandle); 179 180 if (df) 181 free(df, sizeof(*df)); 182 return (0); 183 } 184 185 int 186 dos_write(f, start, size, resid) 187 struct open_file *f; 188 void *start; 189 size_t size; 190 size_t *resid; /* out */ 191 { 192 return (EROFS); 193 } 194 195 int 196 dos_stat(f, sb) 197 struct open_file *f; 198 struct stat *sb; 199 { 200 struct dosfile *df; 201 df = (struct dosfile *) f->f_fsdata; 202 203 sb->st_mode = 0444; 204 sb->st_nlink = 1; 205 sb->st_uid = 0; 206 sb->st_gid = 0; 207 sb->st_size = -1; 208 return (0); 209 } 210 211 off_t 212 dos_seek(f, offset, where) 213 struct open_file *f; 214 off_t offset; 215 int where; 216 { 217 struct dosfile *df; 218 int doswhence, res; 219 #ifdef DOS_CHECK 220 int checkoffs; 221 #endif 222 df = (struct dosfile *) f->f_fsdata; 223 224 switch (where) { 225 case SEEK_SET: 226 doswhence = 0; 227 #ifdef DOS_CHECK 228 checkoffs = offset; /* don't trust DOS */ 229 #endif 230 break; 231 case SEEK_CUR: 232 doswhence = 1; 233 #ifdef DOS_CHECK 234 checkoffs = df->off + offset; 235 #endif 236 break; 237 case SEEK_END: 238 doswhence = 2; 239 #ifdef DOS_CHECK 240 checkoffs = -1; /* we dont know len */ 241 #endif 242 break; 243 default: 244 errno = EOFFSET; 245 return (-1); 246 } 247 res = dosseek(df->doshandle, offset, doswhence); 248 if (res == -1) { 249 errno = dos2errno(); 250 return (-1); 251 } 252 #ifdef DOS_CHECK 253 if ((checkoffs != -1) && (res != checkoffs)) { 254 printf("dosfile: unexpected seek result (%d+%d(%d)=%d)\n", 255 df->off, offset, where, res); 256 errno = EOFFSET; 257 return (-1); 258 } 259 #endif 260 df->off = res; 261 return (res); 262 } 263