1 /* $NetBSD: dosfile.c,v 1.14 2008/12/14 17:03:43 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 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 int 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 int 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 int 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 int 173 dos_write(struct open_file *f, void *start, size_t size, size_t *resid) 174 { 175 return EROFS; 176 } 177 178 int 179 dos_stat(struct open_file *f, struct stat *sb) 180 { 181 struct dosfile *df; 182 df = (struct dosfile *) f->f_fsdata; 183 184 sb->st_mode = 0444; 185 sb->st_nlink = 1; 186 sb->st_uid = 0; 187 sb->st_gid = 0; 188 sb->st_size = -1; 189 return 0; 190 } 191 192 off_t 193 dos_seek(struct open_file *f, off_t offset, int where) 194 { 195 struct dosfile *df; 196 int doswhence, res; 197 #ifdef DOS_CHECK 198 int checkoffs; 199 #endif 200 df = (struct dosfile *) f->f_fsdata; 201 202 switch (where) { 203 case SEEK_SET: 204 doswhence = 0; 205 #ifdef DOS_CHECK 206 checkoffs = offset; /* don't trust DOS */ 207 #endif 208 break; 209 case SEEK_CUR: 210 doswhence = 1; 211 #ifdef DOS_CHECK 212 checkoffs = df->off + offset; 213 #endif 214 break; 215 case SEEK_END: 216 doswhence = 2; 217 #ifdef DOS_CHECK 218 checkoffs = -1; /* we dont know len */ 219 #endif 220 break; 221 default: 222 errno = EOFFSET; 223 return -1; 224 } 225 res = dosseek(df->doshandle, offset, doswhence); 226 if (res == -1) { 227 errno = dos2errno(); 228 return -1; 229 } 230 #ifdef DOS_CHECK 231 if ((checkoffs != -1) && (res != checkoffs)) { 232 printf("dosfile: unexpected seek result (%d+%d(%d)=%d)\n", 233 df->off, offset, where, res); 234 errno = EOFFSET; 235 return -1; 236 } 237 #endif 238 df->off = res; 239 return res; 240 } 241