1 1.11 christos /* $NetBSD: nbfs.c,v 1.11 2014/03/21 16:43:00 christos Exp $ */ 2 1.1 bjh21 3 1.1 bjh21 /*- 4 1.1 bjh21 * Copyright (c) 2006 Ben Harris 5 1.4 bjh21 * Copyright (c) 1993 6 1.4 bjh21 * The Regents of the University of California. All rights reserved. 7 1.1 bjh21 * 8 1.1 bjh21 * Redistribution and use in source and binary forms, with or without 9 1.1 bjh21 * modification, are permitted provided that the following conditions 10 1.1 bjh21 * are met: 11 1.1 bjh21 * 1. Redistributions of source code must retain the above copyright 12 1.1 bjh21 * notice, this list of conditions and the following disclaimer. 13 1.1 bjh21 * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 bjh21 * notice, this list of conditions and the following disclaimer in the 15 1.1 bjh21 * documentation and/or other materials provided with the distribution. 16 1.4 bjh21 * 3. Neither the name of the University nor the names of its contributors 17 1.4 bjh21 * may be used to endorse or promote products derived from this software 18 1.4 bjh21 * without specific prior written permission. 19 1.4 bjh21 * 20 1.4 bjh21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 1.4 bjh21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 1.4 bjh21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 1.4 bjh21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 1.4 bjh21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 1.4 bjh21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 1.4 bjh21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 1.4 bjh21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 1.4 bjh21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 1.4 bjh21 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 1.4 bjh21 * SUCH DAMAGE. 31 1.4 bjh21 */ 32 1.4 bjh21 33 1.4 bjh21 /* 34 1.4 bjh21 * Copyright (c) 1996 35 1.4 bjh21 * Matthias Drochner. All rights reserved. 36 1.4 bjh21 * 37 1.4 bjh21 * Redistribution and use in source and binary forms, with or without 38 1.4 bjh21 * modification, are permitted provided that the following conditions 39 1.4 bjh21 * are met: 40 1.4 bjh21 * 1. Redistributions of source code must retain the above copyright 41 1.4 bjh21 * notice, this list of conditions and the following disclaimer. 42 1.4 bjh21 * 2. Redistributions in binary form must reproduce the above copyright 43 1.4 bjh21 * notice, this list of conditions and the following disclaimer in the 44 1.4 bjh21 * documentation and/or other materials provided with the distribution. 45 1.4 bjh21 * 46 1.1 bjh21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 47 1.1 bjh21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 48 1.1 bjh21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 49 1.1 bjh21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 50 1.1 bjh21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 51 1.1 bjh21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 52 1.1 bjh21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 53 1.1 bjh21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 54 1.1 bjh21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 55 1.1 bjh21 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 1.1 bjh21 */ 57 1.1 bjh21 58 1.1 bjh21 #include <sys/types.h> 59 1.1 bjh21 #include <sys/param.h> 60 1.1 bjh21 #include <sys/disklabel.h> 61 1.1 bjh21 #include <sys/queue.h> 62 1.4 bjh21 #include <ufs/ufs/dinode.h> 63 1.4 bjh21 #include <ufs/ufs/dir.h> 64 1.1 bjh21 #include <lib/libkern/libkern.h> 65 1.1 bjh21 #include <lib/libsa/stand.h> 66 1.4 bjh21 #include <lib/libsa/lfs.h> 67 1.1 bjh21 #include <lib/libsa/ufs.h> 68 1.1 bjh21 #include <riscoscalls.h> 69 1.1 bjh21 #include <riscosdisk.h> 70 1.1 bjh21 71 1.1 bjh21 #include "nbfs.h" 72 1.1 bjh21 73 1.4 bjh21 struct fs_ops file_system[] = { 74 1.4 bjh21 FS_OPS(ffsv1), FS_OPS(ffsv2), FS_OPS(lfsv1), FS_OPS(lfsv2) 75 1.4 bjh21 }; 76 1.1 bjh21 77 1.1 bjh21 int nfsys = __arraycount(file_system); 78 1.1 bjh21 79 1.1 bjh21 struct nbfs_open_file { 80 1.1 bjh21 struct open_file f; 81 1.1 bjh21 int fileswitch_handle; 82 1.1 bjh21 LIST_ENTRY(nbfs_open_file) link; 83 1.1 bjh21 }; 84 1.1 bjh21 85 1.1 bjh21 static LIST_HEAD(, nbfs_open_file) nbfs_open_files; 86 1.1 bjh21 87 1.6 bjh21 static os_error const *maperr(int saerr); 88 1.6 bjh21 89 1.1 bjh21 /* 90 1.1 bjh21 * Given a RISC OS special field and pathname, open the relevant 91 1.1 bjh21 * device and return a pointer to the remainder of the pathname. 92 1.1 bjh21 */ 93 1.1 bjh21 static int 94 1.1 bjh21 nbfs_devopen(struct open_file *f, char const *special, char const *fname, 95 1.1 bjh21 char const **rest) 96 1.1 bjh21 { 97 1.1 bjh21 unsigned int drive = 0, part = RAW_PART; 98 1.1 bjh21 int err; 99 1.1 bjh21 100 1.1 bjh21 if (*fname++ != ':') 101 1.1 bjh21 return EINVAL; 102 1.1 bjh21 while (isdigit((unsigned char)*fname)) 103 1.1 bjh21 drive = drive * 10 + *fname++ - '0'; 104 1.1 bjh21 if (islower((unsigned char)*fname)) 105 1.1 bjh21 part = *fname++ - 'a'; 106 1.1 bjh21 else if (isupper((unsigned char)*fname)) 107 1.1 bjh21 part = *fname++ - 'A'; 108 1.1 bjh21 if (*fname != '.' && *fname != '\0') 109 1.1 bjh21 return EINVAL; 110 1.1 bjh21 err = rodisk_open(f, special, drive, part); 111 1.8 skrll if (err != 0) 112 1.8 skrll return err; 113 1.1 bjh21 *rest = fname; 114 1.8 skrll if (**rest == '.') 115 1.8 skrll (*rest)++; 116 1.1 bjh21 return 0; 117 1.1 bjh21 } 118 1.1 bjh21 119 1.1 bjh21 static int 120 1.1 bjh21 nbfs_fileopen(struct open_file *f, char const *tail) 121 1.1 bjh21 { 122 1.1 bjh21 char *file, *p; 123 1.1 bjh21 int i, error = ENOENT; 124 1.1 bjh21 125 1.1 bjh21 if (tail[0] == '$' && tail[1] == '.') 126 1.1 bjh21 tail += 2; 127 1.1 bjh21 file = alloc(strlen(tail) + 2); 128 1.1 bjh21 strcpy(file, "/"); 129 1.1 bjh21 strcat(file, tail); 130 1.1 bjh21 for (p = file + 1; *p != '\0'; p++) { 131 1.8 skrll if (*p == '.') 132 1.8 skrll *p = '/'; 133 1.8 skrll else if (*p == '/') 134 1.8 skrll *p = '.'; 135 1.1 bjh21 } 136 1.1 bjh21 if (strcmp(tail, "$") == 0) 137 1.1 bjh21 strcpy(file, "/"); 138 1.1 bjh21 139 1.1 bjh21 for (i = 0; i < nfsys; i++) { 140 1.1 bjh21 error = FS_OPEN(&file_system[i])(file, f); 141 1.1 bjh21 if (error == 0 || error == ENOENT) { 142 1.1 bjh21 f->f_ops = &file_system[i]; 143 1.1 bjh21 break; 144 1.1 bjh21 } 145 1.1 bjh21 } 146 1.1 bjh21 dealloc(file, strlen(file) + 1); 147 1.1 bjh21 return error; 148 1.1 bjh21 } 149 1.1 bjh21 150 1.1 bjh21 static int 151 1.1 bjh21 nbfs_fopen(struct open_file *f, char const *special, char const *path) 152 1.1 bjh21 { 153 1.1 bjh21 char const *tail; 154 1.1 bjh21 int err; 155 1.1 bjh21 156 1.1 bjh21 err = nbfs_devopen(f, special, path, &tail); 157 1.8 skrll if (err != 0) 158 1.8 skrll return err; 159 1.1 bjh21 err = nbfs_fileopen(f, tail); 160 1.1 bjh21 if (err != 0) 161 1.1 bjh21 DEV_CLOSE(f->f_dev)(f); 162 1.1 bjh21 return err; 163 1.1 bjh21 } 164 1.1 bjh21 165 1.1 bjh21 static int 166 1.1 bjh21 nbfs_fclose(struct open_file *f) 167 1.1 bjh21 { 168 1.1 bjh21 int ferr, derr; 169 1.1 bjh21 170 1.1 bjh21 ferr = FS_CLOSE(f->f_ops)(f); 171 1.1 bjh21 derr = DEV_CLOSE(f->f_dev)(f); 172 1.1 bjh21 return ferr != 0 ? ferr : derr; 173 1.1 bjh21 } 174 1.1 bjh21 175 1.6 bjh21 os_error const * 176 1.1 bjh21 nbfs_open(struct nbfs_reg *r) 177 1.1 bjh21 { 178 1.1 bjh21 int reason = r->r0; 179 1.1 bjh21 char const *fname = (char const *)r->r1; 180 1.1 bjh21 int fh = r->r3; 181 1.1 bjh21 char const *special = (char const *)r->r6; 182 1.1 bjh21 int err; 183 1.1 bjh21 struct nbfs_open_file *nof = NULL; 184 1.1 bjh21 struct stat st; 185 1.1 bjh21 186 1.6 bjh21 switch (reason) { 187 1.6 bjh21 case 0: /* Open for read */ 188 1.6 bjh21 case 1: /* Create and open for update */ 189 1.6 bjh21 case 2: /* Open for update */ 190 1.1 bjh21 nof = alloc(sizeof(*nof)); 191 1.1 bjh21 memset(nof, 0, sizeof(*nof)); 192 1.1 bjh21 err = nbfs_fopen(&nof->f, special, fname); 193 1.8 skrll if (err != 0) 194 1.8 skrll goto fail; 195 1.1 bjh21 err = FS_STAT(nof->f.f_ops)(&nof->f, &st); 196 1.8 skrll if (err != 0) 197 1.8 skrll goto fail; 198 1.1 bjh21 nof->fileswitch_handle = fh; 199 1.1 bjh21 LIST_INSERT_HEAD(&nbfs_open_files, nof, link); 200 1.1 bjh21 r->r0 = 0x40000000; 201 1.8 skrll if (S_ISDIR(st.st_mode)) 202 1.8 skrll r->r0 |= 0x20000000; 203 1.1 bjh21 r->r1 = (uint32_t)nof; 204 1.1 bjh21 r->r2 = DEV_BSIZE; 205 1.1 bjh21 r->r3 = st.st_size; 206 1.1 bjh21 r->r4 = st.st_size; 207 1.1 bjh21 return NULL; 208 1.6 bjh21 default: 209 1.6 bjh21 err = EINVAL; 210 1.6 bjh21 goto fail; 211 1.1 bjh21 } 212 1.1 bjh21 fail: 213 1.1 bjh21 if (nof != NULL) 214 1.1 bjh21 dealloc(nof, sizeof(*nof)); 215 1.6 bjh21 return maperr(err); 216 1.1 bjh21 } 217 1.1 bjh21 218 1.6 bjh21 os_error const * 219 1.1 bjh21 nbfs_getbytes(struct nbfs_reg *r) 220 1.1 bjh21 { 221 1.1 bjh21 struct nbfs_open_file *nof = (struct nbfs_open_file *)r->r1; 222 1.1 bjh21 void *buf = (void *)r->r2; 223 1.1 bjh21 size_t size = r->r3; 224 1.1 bjh21 off_t off = r->r4; 225 1.1 bjh21 int err; 226 1.1 bjh21 227 1.1 bjh21 err = FS_SEEK(nof->f.f_ops)(&nof->f, off, SEEK_SET); 228 1.8 skrll if (err == -1) 229 1.8 skrll return maperr(err); 230 1.1 bjh21 err = FS_READ(nof->f.f_ops)(&nof->f, buf, size, NULL); 231 1.8 skrll if (err != 0) 232 1.8 skrll return maperr(err); 233 1.1 bjh21 return NULL; 234 1.1 bjh21 } 235 1.1 bjh21 236 1.6 bjh21 os_error const * 237 1.1 bjh21 nbfs_putbytes(struct nbfs_reg *r) 238 1.1 bjh21 { 239 1.6 bjh21 static os_error const err = {0, "nbfs_putbytes"}; 240 1.1 bjh21 241 1.1 bjh21 return &err; 242 1.1 bjh21 } 243 1.1 bjh21 244 1.6 bjh21 os_error const * 245 1.1 bjh21 nbfs_args(struct nbfs_reg *r) 246 1.1 bjh21 { 247 1.6 bjh21 static os_error const err = {0, "nbfs_args"}; 248 1.1 bjh21 249 1.1 bjh21 return &err; 250 1.1 bjh21 } 251 1.1 bjh21 252 1.6 bjh21 os_error const * 253 1.1 bjh21 nbfs_close(struct nbfs_reg *r) 254 1.1 bjh21 { 255 1.1 bjh21 struct nbfs_open_file *nof = (struct nbfs_open_file *)r->r1; 256 1.1 bjh21 /* uint32_t loadaddr = r->r2; */ 257 1.1 bjh21 /* uint32_t execaddr = r->r3; */ 258 1.1 bjh21 int err; 259 1.1 bjh21 260 1.1 bjh21 err = nbfs_fclose(&nof->f); 261 1.9 skrll if (err != 0) 262 1.9 skrll return maperr(err); 263 1.1 bjh21 LIST_REMOVE(nof, link); 264 1.1 bjh21 dealloc(nof, sizeof(*nof)); 265 1.1 bjh21 return NULL; 266 1.1 bjh21 } 267 1.1 bjh21 268 1.6 bjh21 os_error const * 269 1.1 bjh21 nbfs_file(struct nbfs_reg *r) 270 1.1 bjh21 { 271 1.1 bjh21 int reason = r->r0; 272 1.1 bjh21 char const *fname = (char const *)r->r1; 273 1.5 bjh21 void *buf = (void *)r->r2; 274 1.1 bjh21 char const *special = (char const *)r->r6; 275 1.1 bjh21 struct open_file f; 276 1.1 bjh21 int err; 277 1.1 bjh21 struct stat st; 278 1.1 bjh21 279 1.1 bjh21 memset(&f, 0, sizeof(f)); 280 1.1 bjh21 err = nbfs_fopen(&f, special, fname); 281 1.1 bjh21 if (err != 0 && err != ENOENT) 282 1.6 bjh21 return maperr(err); 283 1.1 bjh21 switch (reason) { 284 1.6 bjh21 case 0: /* Save file */ 285 1.6 bjh21 case 1: /* Write catalogue information */ 286 1.6 bjh21 case 2: /* Write load address */ 287 1.6 bjh21 case 3: /* Write execution address */ 288 1.6 bjh21 case 4: /* Write attributes */ 289 1.6 bjh21 case 6: /* Delete object */ 290 1.6 bjh21 case 7: /* Create file */ 291 1.6 bjh21 case 8: /* Create directory */ 292 1.6 bjh21 nbfs_fclose(&f); 293 1.6 bjh21 err = EROFS; 294 1.6 bjh21 goto fail; 295 1.6 bjh21 case 5: /* Read catalogue information */ 296 1.6 bjh21 case 255: /* Load file */ 297 1.1 bjh21 if (err == ENOENT) 298 1.1 bjh21 r->r0 = r->r2 = r->r3 = r->r4 = r->r5 = 0; 299 1.1 bjh21 else { 300 1.1 bjh21 err = FS_STAT(f.f_ops)(&f, &st); 301 1.8 skrll if (err != 0) 302 1.8 skrll goto fail; 303 1.2 bjh21 r->r0 = S_ISDIR(st.st_mode) ? 304 1.2 bjh21 fileswitch_IS_DIR : fileswitch_IS_FILE; 305 1.2 bjh21 r->r2 = r->r3 = 0; 306 1.2 bjh21 r->r4 = st.st_size; 307 1.3 bjh21 r->r5 = fileswitch_ATTR_OWNER_READ | 308 1.3 bjh21 fileswitch_ATTR_WORLD_READ; 309 1.5 bjh21 if (reason == 255) { 310 1.5 bjh21 err = FS_READ(f.f_ops) 311 1.5 bjh21 (&f, buf, st.st_size, NULL); 312 1.8 skrll if (err != 0) 313 1.8 skrll goto fail; 314 1.5 bjh21 /* R6 should really be the leaf name */ 315 1.5 bjh21 r->r6 = r->r1; 316 1.5 bjh21 } 317 1.1 bjh21 } 318 1.1 bjh21 break; 319 1.1 bjh21 default: 320 1.6 bjh21 nbfs_fclose(&f); 321 1.6 bjh21 err = EINVAL; 322 1.1 bjh21 goto fail; 323 1.1 bjh21 } 324 1.1 bjh21 nbfs_fclose(&f); 325 1.1 bjh21 return NULL; 326 1.1 bjh21 fail: 327 1.1 bjh21 nbfs_fclose(&f); 328 1.6 bjh21 return maperr(err); 329 1.1 bjh21 } 330 1.1 bjh21 331 1.4 bjh21 static int 332 1.4 bjh21 nbfs_filename_ok(char const *f) 333 1.4 bjh21 { 334 1.4 bjh21 335 1.4 bjh21 while (*f) 336 1.4 bjh21 if (strchr(":*#$&@^%\\", *f++) != NULL) 337 1.4 bjh21 return 0; 338 1.4 bjh21 return 1; 339 1.4 bjh21 } 340 1.4 bjh21 341 1.6 bjh21 static os_error const * 342 1.4 bjh21 nbfs_func_dirents(struct nbfs_reg *r) 343 1.4 bjh21 { 344 1.4 bjh21 int reason = r->r0; 345 1.4 bjh21 char const *fname = (char const *)r->r1; 346 1.4 bjh21 char const *special = (char const *)r->r6; 347 1.4 bjh21 struct open_file f; 348 1.4 bjh21 struct stat st; 349 1.4 bjh21 int err; 350 1.4 bjh21 struct fileswitch_dirent *fdp; 351 1.4 bjh21 size_t resid; 352 1.4 bjh21 size_t maxcount = r->r3; 353 1.4 bjh21 size_t count = 0; 354 1.4 bjh21 size_t skip = r->r4; 355 1.4 bjh21 ssize_t off = 0; 356 1.4 bjh21 size_t buflen = r->r5; 357 1.10 mrg char dirbuf[UFS_DIRBLKSIZ]; 358 1.4 bjh21 char *outp = (char *)r->r2; 359 1.4 bjh21 360 1.4 bjh21 err = nbfs_fopen(&f, special, fname); 361 1.4 bjh21 if (err != 0) 362 1.6 bjh21 return maperr(err); 363 1.4 bjh21 err = FS_STAT(f.f_ops)(&f, &st); 364 1.4 bjh21 if (err != 0) 365 1.4 bjh21 goto fail; 366 1.6 bjh21 if (!S_ISDIR(st.st_mode)) { 367 1.6 bjh21 err = ENOTDIR; 368 1.4 bjh21 goto fail; 369 1.6 bjh21 } 370 1.10 mrg while (FS_READ(f.f_ops)(&f, dirbuf, UFS_DIRBLKSIZ, &resid) == 0 && 371 1.4 bjh21 resid == 0) { 372 1.4 bjh21 struct direct *dp, *edp; 373 1.4 bjh21 374 1.4 bjh21 dp = (struct direct *) dirbuf; 375 1.10 mrg edp = (struct direct *) (dirbuf + UFS_DIRBLKSIZ); 376 1.4 bjh21 377 1.4 bjh21 for (; dp < edp; dp = (void *)((char *)dp + dp->d_reclen)) { 378 1.4 bjh21 size_t entsiz = 0; 379 1.4 bjh21 int i; 380 1.4 bjh21 381 1.4 bjh21 if (dp->d_ino == 0) 382 1.4 bjh21 continue; 383 1.4 bjh21 /* 384 1.4 bjh21 * Skip ., .., and names with characters that RISC 385 1.4 bjh21 * OS doesn't allow. 386 1.4 bjh21 */ 387 1.4 bjh21 if (strcmp(dp->d_name, ".") == 0 || 388 1.4 bjh21 strcmp(dp->d_name, "..") == 0 || 389 1.4 bjh21 !nbfs_filename_ok(dp->d_name)) 390 1.4 bjh21 continue; 391 1.4 bjh21 if (off++ < skip) 392 1.4 bjh21 continue; 393 1.4 bjh21 394 1.4 bjh21 switch (reason) { 395 1.4 bjh21 case 14: 396 1.4 bjh21 entsiz = strlen(dp->d_name) + 1; 397 1.8 skrll if (buflen < entsiz) 398 1.8 skrll goto out; 399 1.4 bjh21 strcpy(outp, dp->d_name); 400 1.4 bjh21 break; 401 1.4 bjh21 case 15: 402 1.4 bjh21 entsiz = ALIGN(offsetof( 403 1.4 bjh21 struct fileswitch_dirent, name) 404 1.4 bjh21 + strlen(dp->d_name) + 1); 405 1.8 skrll if (buflen < entsiz) 406 1.8 skrll goto out; 407 1.4 bjh21 408 1.4 bjh21 fdp = (struct fileswitch_dirent *)outp; 409 1.4 bjh21 fdp->loadaddr = 0; 410 1.4 bjh21 fdp->execaddr = 0; 411 1.4 bjh21 fdp->length = 0; 412 1.4 bjh21 fdp->attr = 0; 413 1.4 bjh21 fdp->objtype = dp->d_type == DT_DIR ? 414 1.4 bjh21 fileswitch_IS_DIR : fileswitch_IS_FILE; 415 1.4 bjh21 strcpy(fdp->name, dp->d_name); 416 1.4 bjh21 for (i = 0; fdp->name[i] != '\0'; i++) 417 1.4 bjh21 if (fdp->name[i] == '.') 418 1.4 bjh21 fdp->name[i] = '/'; 419 1.4 bjh21 break; 420 1.4 bjh21 } 421 1.4 bjh21 outp += entsiz; 422 1.4 bjh21 buflen -= entsiz; 423 1.4 bjh21 if (++count == maxcount) 424 1.4 bjh21 goto out; 425 1.4 bjh21 } 426 1.4 bjh21 } 427 1.4 bjh21 off = -1; 428 1.4 bjh21 out: 429 1.4 bjh21 nbfs_fclose(&f); 430 1.4 bjh21 r->r3 = count; 431 1.4 bjh21 r->r4 = off; 432 1.4 bjh21 return NULL; 433 1.4 bjh21 fail: 434 1.4 bjh21 nbfs_fclose(&f); 435 1.6 bjh21 return maperr(err); 436 1.4 bjh21 } 437 1.4 bjh21 438 1.6 bjh21 os_error const * 439 1.1 bjh21 nbfs_func(struct nbfs_reg *r) 440 1.1 bjh21 { 441 1.4 bjh21 static os_error error = {0, "nbfs_func"}; 442 1.1 bjh21 int reason = r->r0; 443 1.1 bjh21 444 1.4 bjh21 switch (reason) { 445 1.4 bjh21 case 14: 446 1.4 bjh21 case 15: 447 1.4 bjh21 return nbfs_func_dirents(r); 448 1.1 bjh21 449 1.4 bjh21 case 16: /* Shut down */ 450 1.4 bjh21 return NULL; 451 1.4 bjh21 default: 452 1.11 christos snprintf(error.errmess, sizeof(error.errmess), 453 1.11 christos "nbfs_func %d not implemented", reason); 454 1.4 bjh21 return &error; 455 1.4 bjh21 } 456 1.1 bjh21 } 457 1.6 bjh21 458 1.6 bjh21 #define FSERR(x) (0x10000 | (NBFS_FSNUM << 8) | (x)) 459 1.6 bjh21 460 1.6 bjh21 static struct { 461 1.6 bjh21 int saerr; 462 1.6 bjh21 os_error roerr; 463 1.6 bjh21 } const errmap[] = { 464 1.6 bjh21 { ECTLR, { FSERR(ECTLR), "Bad parent filing system" } }, 465 1.6 bjh21 { EUNIT, { FSERR(0xAC), "Bad drive number" } }, 466 1.6 bjh21 { EPART, { FSERR(EPART), "Bad partition" } }, 467 1.6 bjh21 { ERDLAB, { FSERR(ERDLAB), "Can't read disk label" } }, 468 1.6 bjh21 { EUNLAB, { FSERR(EUNLAB), "Unlabeled" } }, 469 1.6 bjh21 { ENOENT, { FSERR(0xD6), "No such file or directory" } }, 470 1.6 bjh21 { EIO, { FSERR(EIO), "Input/output error" } }, 471 1.6 bjh21 { EINVAL, { FSERR(EINVAL), "Invalid argument" } }, 472 1.6 bjh21 { ENOTDIR, { FSERR(ENOTDIR), "Not a directory" } }, 473 1.6 bjh21 { EROFS, { FSERR(0xC9), "Read-only file system" } }, 474 1.6 bjh21 }; 475 1.6 bjh21 476 1.6 bjh21 static os_error const *maperr(int err) 477 1.6 bjh21 { 478 1.6 bjh21 int i; 479 1.6 bjh21 static const os_error defaulterr = { FSERR(0), "Unknown NBFS error" }; 480 1.6 bjh21 481 1.6 bjh21 for (i = 0; i < sizeof(errmap) / sizeof(errmap[0]); i++) 482 1.6 bjh21 if (err == errmap[i].saerr) 483 1.6 bjh21 return &errmap[i].roerr; 484 1.6 bjh21 return &defaulterr; 485 1.6 bjh21 } 486