|
|
1.1 ! root 1: /* ! 2: * @(#)sys.c 1.1 86/02/03 Copyright (c) 1985 by Sun Microsystems, Inc. ! 3: */ ! 4: ! 5: /* ! 6: * Basic file system reading code for standalone I/O system. ! 7: * Simulates a primitive UNIX I/O system (read(), write(), open(), etc). ! 8: * Does not attempt writes to file systems, tho writing to whole devices ! 9: * is supported, when the driver supports it. ! 10: */ ! 11: ! 12: #include "param.h" ! 13: #include "saio.h" ! 14: #include "../h/dir.h" ! 15: #include "../h/time.h" ! 16: #include "../h/vnode.h" ! 17: #include "../ufs/fs.h" ! 18: #include "../ufs/inode.h" ! 19: /* ! 20: * This struct keeps track of an open file in the standalone I/O system. ! 21: * ! 22: * It includes an IOB for device addess, an inode, a buffer for reading ! 23: * indirect blocks and inodes, and a buffer for the superblock of the ! 24: * file system (if any). ! 25: */ ! 26: struct iob { ! 27: struct saioreq i_si; /* I/O request block for this file */ ! 28: struct inode i_ino; /* Inode for this file */ ! 29: char i_buf[MAXBSIZE];/* Buffer for reading inodes & dirs */ ! 30: union { ! 31: struct fs ui_fs; /* Superblock for file system */ ! 32: char dummy[SBSIZE]; ! 33: } i_un; ! 34: }; ! 35: #define i_flgs i_si.si_flgs ! 36: #define i_boottab i_si.si_boottab ! 37: #define i_devdata i_si.si_devdata ! 38: #define i_ctlr i_si.si_ctlr ! 39: #define i_unit i_si.si_unit ! 40: #define i_boff i_si.si_boff ! 41: #define i_cyloff i_si.si_cyloff ! 42: #define i_offset i_si.si_offset ! 43: #define i_bn i_si.si_bn ! 44: #define i_ma i_si.si_ma ! 45: #define i_cc i_si.si_cc ! 46: #define i_fs i_un.ui_fs ! 47: ! 48: /* These are the pools of buffers, iob's, etc. */ ! 49: #define NBUFS (NIADDR+1) /* NOT! a variable */ ! 50: char b[NBUFS][MAXBSIZE]; ! 51: daddr_t blknos[NBUFS]; ! 52: struct iob iob[NFILES]; ! 53: ! 54: ino_t dlook(); ! 55: ! 56: struct dirstuff { ! 57: int loc; ! 58: struct iob *io; ! 59: }; ! 60: ! 61: static ! 62: openi(n,io) ! 63: ino_t n; ! 64: register struct iob *io; ! 65: { ! 66: register struct dinode *dp; ! 67: ! 68: io->i_offset = 0; ! 69: io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)); ! 70: io->i_cc = io->i_fs.fs_bsize; ! 71: io->i_ma = io->i_buf; ! 72: /* FIXME: this call to devread() does not check for errors! */ ! 73: devread(&io->i_si); ! 74: dp = (struct dinode *)io->i_buf; ! 75: io->i_ino.i_ic = dp[itoo(&io->i_fs, n)].di_ic; ! 76: } ! 77: ! 78: static ino_t ! 79: find(path, file) ! 80: register char *path; ! 81: struct iob *file; ! 82: { ! 83: register char *q; ! 84: char c; ! 85: ino_t n; ! 86: ! 87: if (path==NULL || *path=='\0') { ! 88: printf("null path\n"); ! 89: return(0); ! 90: } ! 91: ! 92: openi((ino_t) ROOTINO, file); ! 93: while (*path) { ! 94: while (*path == '/') ! 95: path++; ! 96: q = path; ! 97: while(*q != '/' && *q != '\0') ! 98: q++; ! 99: c = *q; ! 100: *q = '\0'; ! 101: ! 102: if ((n=dlook(path, file))!=0) { ! 103: if (c=='\0') ! 104: break; ! 105: openi(n, file); ! 106: *q = c; ! 107: path = q; ! 108: continue; ! 109: } else { ! 110: printf("%s not found\n",path); ! 111: return(0); ! 112: } ! 113: } ! 114: return(n); ! 115: } ! 116: ! 117: static daddr_t ! 118: sbmap(io, bn) ! 119: register struct iob *io; ! 120: daddr_t bn; ! 121: { ! 122: register struct inode *ip; ! 123: register int i, j, sh; ! 124: register daddr_t nb, *bap; ! 125: ! 126: ip = &io->i_ino; ! 127: ! 128: /* ! 129: * blocks 0..NDADDR are direct blocks ! 130: */ ! 131: if(bn < NDADDR) { ! 132: nb = ip->i_db[bn]; ! 133: return(nb); ! 134: } ! 135: ! 136: #ifndef BOOTBLOCK ! 137: /* ! 138: * addresses NIADDR have single and double indirect blocks. ! 139: * the first step is to determine how many levels of indirection. ! 140: */ ! 141: sh = 1; ! 142: bn -= NDADDR; ! 143: for (j = NIADDR; j > 0; j--) { ! 144: sh *= NINDIR(&io->i_fs); ! 145: if (bn < sh) ! 146: break; ! 147: bn -= sh; ! 148: } ! 149: if (j == 0) { ! 150: printf("bn ovf %D\n", bn); ! 151: return ((daddr_t)0); ! 152: } ! 153: ! 154: /* ! 155: * fetch the first indirect block address from the inode ! 156: */ ! 157: nb = ip->i_ib[NIADDR - j]; ! 158: if (nb == 0) { ! 159: printf("bn void %D\n",bn); ! 160: return((daddr_t)0); ! 161: } ! 162: ! 163: /* ! 164: * fetch through the indirect blocks ! 165: */ ! 166: for (; j <= NIADDR; j++) { ! 167: if (blknos[j] != nb) { ! 168: io->i_bn = fsbtodb(&io->i_fs, nb); ! 169: io->i_ma = b[j]; ! 170: io->i_cc = io->i_fs.fs_bsize; ! 171: if (devread(&io->i_si) != io->i_cc) ! 172: return((daddr_t)0); ! 173: blknos[j] = nb; ! 174: } ! 175: bap = (daddr_t *)b[j]; ! 176: sh /= NINDIR(&io->i_fs); ! 177: i = (bn / sh) % NINDIR(&io->i_fs); ! 178: nb = bap[i]; ! 179: if(nb == 0) { ! 180: printf("bn void %D\n",bn); ! 181: return((daddr_t)0); ! 182: } ! 183: } ! 184: return(nb); ! 185: #else BOOTBLOCK ! 186: return((daddr_t)0); ! 187: #endif BOOTBLOCK ! 188: } ! 189: ! 190: static ino_t ! 191: dlook(s, io) ! 192: char *s; ! 193: register struct iob *io; ! 194: { ! 195: register struct direct *dp; ! 196: register struct inode *ip; ! 197: struct dirstuff dirp; ! 198: register int len; ! 199: ! 200: ip = &io->i_ino; ! 201: #ifndef BOOTBLOCK ! 202: if (s == NULL || *s == '\0') ! 203: return(0); ! 204: if ((ip->i_mode&IFMT) != IFDIR) { ! 205: printf("not a directory\n"); ! 206: return(0); ! 207: } ! 208: if (ip->i_size == 0) { ! 209: printf("zero length directory\n"); ! 210: return(0); ! 211: } ! 212: #endif ! 213: len = strlen(s); ! 214: dirp.loc = 0; ! 215: dirp.io = io; ! 216: for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { ! 217: if(dp->d_ino == 0) ! 218: continue; ! 219: if (dp->d_namlen == len && !strcmp(s, dp->d_name)) ! 220: return(dp->d_ino); ! 221: #ifndef BOOTBLOCK ! 222: /* Allow "*" to print all names at that level, w/out match */ ! 223: if (!strcmp(s, "*")) ! 224: printf("%s\n", dp->d_name); ! 225: #endif ! 226: } ! 227: return(0); ! 228: } ! 229: ! 230: /* ! 231: * get next entry in a directory. ! 232: */ ! 233: struct direct * ! 234: readdir(dirp) ! 235: register struct dirstuff *dirp; ! 236: { ! 237: register struct direct *dp; ! 238: register struct iob *io; ! 239: register daddr_t lbn, d; ! 240: register int off; ! 241: ! 242: io = dirp->io; ! 243: for(;;) { ! 244: if (dirp->loc >= io->i_ino.i_size) ! 245: return NULL; ! 246: off = blkoff(&io->i_fs, dirp->loc); ! 247: if (off == 0) { ! 248: lbn = lblkno(&io->i_fs, dirp->loc); ! 249: d = sbmap(io, lbn); ! 250: if(d == 0) ! 251: return NULL; ! 252: io->i_bn = fsbtodb(&io->i_fs, d); ! 253: io->i_ma = io->i_buf; ! 254: io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn); ! 255: if (devread(&io->i_si) != io->i_cc) ! 256: return NULL; ! 257: } ! 258: dp = (struct direct *)(io->i_buf + off); ! 259: dirp->loc += dp->d_reclen; ! 260: if (dp->d_ino == 0) ! 261: continue; ! 262: return (dp); ! 263: } ! 264: } ! 265: ! 266: lseek(fdesc, addr, ptr) ! 267: int fdesc; ! 268: register off_t addr; ! 269: int ptr; ! 270: { ! 271: register struct iob *io; ! 272: ! 273: #ifndef BOOTBLOCK ! 274: fdesc -= 3; ! 275: if (fdesc < 0 || fdesc >= NFILES || ! 276: ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) ! 277: return(-1); ! 278: #else ! 279: io = &iob[fdesc - 3]; ! 280: #endif ! 281: io->i_si.si_flgs &= ~F_EOF; ! 282: io->i_offset = addr; ! 283: io->i_bn = addr / DEV_BSIZE; ! 284: io->i_cc = 0; ! 285: return(0); ! 286: } ! 287: ! 288: /* FIXME: possibly make this static and pass iob, eliminating assorted tests? */ ! 289: getc(fdesc) ! 290: int fdesc; ! 291: { ! 292: register struct iob *io; ! 293: register struct fs *fs; ! 294: register char *p; ! 295: register int c, off, size, diff; ! 296: register daddr_t lbn; ! 297: ! 298: ! 299: #ifndef BOOTBLOCK ! 300: if (fdesc >= 0 && fdesc <= 2) ! 301: return(getchar()); ! 302: fdesc -= 3; ! 303: if (fdesc < 0 || fdesc >= NFILES || ! 304: ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) ! 305: return(-1); ! 306: #else ! 307: io = &iob[fdesc -= 3]; ! 308: #endif ! 309: p = io->i_ma; ! 310: if (io->i_cc <= 0) { ! 311: if ((io->i_flgs & F_FILE) != 0) { ! 312: diff = io->i_ino.i_size - io->i_offset; ! 313: if (diff <= 0) ! 314: return (-1); ! 315: fs = &io->i_fs; ! 316: lbn = lblkno(fs, io->i_offset); ! 317: io->i_bn = fsbtodb(fs, sbmap(io, lbn)); ! 318: off = blkoff(fs, io->i_offset); ! 319: size = blksize(fs, &io->i_ino, lbn); ! 320: } else { ! 321: io->i_bn = io->i_offset / DEV_BSIZE; ! 322: off = 0; ! 323: size = DEV_BSIZE; ! 324: } ! 325: io->i_ma = io->i_buf; ! 326: io->i_cc = size; ! 327: if (devread(&io->i_si) != io->i_cc) /* Trap errors */ ! 328: return(-1); ! 329: if ((io->i_flgs & F_FILE) != 0) { ! 330: if (io->i_offset - off + size >= io->i_ino.i_size) ! 331: io->i_cc = diff + off; ! 332: io->i_cc -= off; ! 333: } ! 334: p = &io->i_buf[off]; ! 335: } ! 336: io->i_cc--; ! 337: io->i_offset++; ! 338: c = (unsigned)*p++; ! 339: io->i_ma = p; ! 340: return(c); ! 341: } ! 342: ! 343: ! 344: read(fdesc, buf, count) ! 345: int fdesc; ! 346: register char *buf; ! 347: int count; ! 348: { ! 349: register i,j; ! 350: register struct iob *file; ! 351: ! 352: #ifndef BOOTBLOCK ! 353: if (fdesc >= 0 && fdesc <= 2) { ! 354: i = count; ! 355: do { ! 356: *buf = getchar(); ! 357: } while (--i && *buf++ != '\n'); ! 358: return(count - i); ! 359: } ! 360: fdesc -= 3; ! 361: if (fdesc < 0 || fdesc >= NFILES || ! 362: ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) ! 363: return(-1); ! 364: if ((file->i_flgs&F_READ) == 0) ! 365: return(-1); ! 366: fdesc += 3; ! 367: #else BOOTBLOCK ! 368: file = &iob[fdesc - 3]; ! 369: #endif BOOTBLOCK ! 370: if ((file->i_flgs & F_FILE) == 0) { ! 371: file->i_cc = count; ! 372: file->i_ma = buf; ! 373: file->i_bn = (file->i_offset / DEV_BSIZE); ! 374: i = devread(&file->i_si); ! 375: file->i_offset += count; ! 376: return(i); ! 377: } else { ! 378: if (file->i_offset+count > file->i_ino.i_size) ! 379: count = file->i_ino.i_size - file->i_offset; ! 380: if ((i = count) <= 0) ! 381: return(0); ! 382: #ifdef BOOTBLOCK ! 383: do { ! 384: *buf++ = getc(fdesc); ! 385: } while (--i); ! 386: #else BOOTBLOCK ! 387: while (i > 0) { ! 388: if ((j = file->i_cc) <= 0) { ! 389: *buf++ = getc(fdesc); ! 390: i--; ! 391: } else { ! 392: if (i < j) ! 393: j = i; ! 394: bcopy(file->i_ma, buf, (unsigned)j); ! 395: buf += j; ! 396: file->i_ma += j; ! 397: file->i_offset += j; ! 398: file->i_cc -= j; ! 399: i -= j; ! 400: } ! 401: } ! 402: #endif BOOTBLOCK ! 403: return(count); ! 404: } ! 405: } ! 406: ! 407: #ifndef BOOTBLOCK ! 408: write(fdesc, buf, count) ! 409: int fdesc; ! 410: char *buf; ! 411: int count; ! 412: { ! 413: register i; ! 414: register struct iob *file; ! 415: ! 416: if (fdesc >= 0 && fdesc <= 2) { ! 417: i = count; ! 418: while (i--) ! 419: putchar(*buf++); ! 420: return(count); ! 421: } ! 422: fdesc -= 3; ! 423: if (fdesc < 0 || fdesc >= NFILES || ! 424: ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) ! 425: return(-1); ! 426: if ((file->i_flgs&F_WRITE) == 0) ! 427: return(-1); ! 428: if (count % DEV_BSIZE) ! 429: printf("count=%d?\n", count); ! 430: file->i_cc = count; ! 431: file->i_ma = buf; ! 432: file->i_bn = (file->i_offset / DEV_BSIZE); ! 433: i = devwrite(&file->i_si); ! 434: file->i_offset += count; ! 435: return(i); ! 436: } ! 437: #endif BOOTBLOCK ! 438: ! 439: /* ! 440: * Open a file on a physical device, or open the device itself. ! 441: * ! 442: * The device is identified by a struct bootparam which gives pointers ! 443: * to the struct boottab, containing the device open, strategy and close ! 444: * routines; and the device parameters such as controller #, unit #, etc. ! 445: * ! 446: * If *str == 0, the device is opened, else the named file in the file ! 447: * system on the device is opened. ! 448: */ ! 449: int ! 450: physopen(bp, str, how) ! 451: register struct bootparam *bp; ! 452: char *str; ! 453: int how; ! 454: { ! 455: int fdesc; ! 456: register struct iob *file; ! 457: ! 458: #ifdef BOOTBLOCK ! 459: fdesc = 0; ! 460: file = &iob[0]; ! 461: file->i_flgs |= F_ALLOC; ! 462: #else BOOTBLOCK ! 463: fdesc = getiob(); /* Allocate an IOB */ ! 464: file = &iob[fdesc]; ! 465: #endif BOOTBLOCK ! 466: ! 467: file->i_boottab = bp->bp_boottab; /* Record pointer to boot table */ ! 468: file->i_ctlr = bp->bp_ctlr; ! 469: file->i_unit = bp->bp_unit; ! 470: file->i_boff = bp->bp_part; ! 471: file->i_ino.i_dev = 0; /* Call it device 0 for chuckles */ ! 472: ! 473: return(openfile(fdesc, file, str, how)); ! 474: } ! 475: ! 476: #ifndef BOOTBLOCK ! 477: ! 478: int openfirst = 1; ! 479: ! 480: /* ! 481: * Allocate an IOB for a newly opened file. ! 482: */ ! 483: int ! 484: getiob() ! 485: { ! 486: register int fdesc; ! 487: ! 488: if (openfirst) { ! 489: openfirst = 0; ! 490: for (fdesc = 0; fdesc < NFILES; fdesc++) ! 491: iob[fdesc].i_flgs = 0; ! 492: } ! 493: ! 494: for (fdesc = 0; fdesc < NFILES; fdesc++) ! 495: if (iob[fdesc].i_flgs == 0) ! 496: goto gotfile; ! 497: _stop("No more file slots"); ! 498: gotfile: ! 499: (&iob[fdesc])->i_flgs |= F_ALLOC; ! 500: return fdesc; ! 501: } ! 502: ! 503: /* Hex string scanner for open() */ ! 504: static char * ! 505: openhex(p, ip) ! 506: register char *p; ! 507: int *ip; ! 508: { ! 509: register int ac = 0; ! 510: ! 511: while (*p) { ! 512: if (*p >= '0' && *p <= '9') ! 513: ac = (ac<<4) + (*p - '0'); ! 514: else if (*p >= 'a' && *p <= 'f') ! 515: ac = (ac<<4) + (*p - 'a' + 10); ! 516: else if (*p >= 'A' && *p <= 'F') ! 517: ac = (ac<<4) + (*p - 'A' + 10); ! 518: else ! 519: break; ! 520: p++; ! 521: } ! 522: if (*p == ',') ! 523: p++; ! 524: *ip = ac; ! 525: return (p); ! 526: } ! 527: ! 528: /* ! 529: * Open a device or file-in-file-system-on-device. ! 530: */ ! 531: int ! 532: open(str, how) ! 533: char *str; ! 534: int how; ! 535: { ! 536: register char *cp; ! 537: register struct iob *file; ! 538: register struct boottab *dp; ! 539: register struct boottab **tablep; ! 540: int fdesc; ! 541: long atol(); ! 542: ! 543: extern struct boottab *(devsw[]); ! 544: ! 545: fdesc = getiob(); /* Allocate an IOB */ ! 546: file = &iob[fdesc]; ! 547: ! 548: for (cp = str; *cp && *cp != '('; cp++) ! 549: ; ! 550: if (*cp++ != '(') { ! 551: file->i_flgs = 0; ! 552: goto badsyntax; ! 553: } ! 554: for (tablep = devsw; 0 != (dp = *tablep); tablep++) { ! 555: if (str[0] == dp->b_dev[0] && str[1] == dp->b_dev[1]) ! 556: goto gotdev; ! 557: } ! 558: printf("Unknown device: %c%c; known devices:\n", str[0], str[1]); ! 559: for (tablep = devsw; 0 != (dp = *tablep); tablep++) ! 560: printf(" %s\n", dp->b_desc); ! 561: file->i_flgs = 0; ! 562: return(-1); ! 563: gotdev: ! 564: file->i_boottab = dp; /* Record pointer to boot table */ ! 565: file->i_ino.i_dev = tablep-devsw; ! 566: #ifdef sun ! 567: cp = openhex(cp, &file->i_ctlr); ! 568: #endif ! 569: cp = openhex(cp, &file->i_unit); ! 570: cp = openhex(cp, (int *)&file->i_boff); ! 571: if (*cp == '\0') goto doit; ! 572: if (*cp != ')') { ! 573: badsyntax: ! 574: printf("%s: bad syntax, try dev(ctlr,unit,part)name\n", str); ! 575: return -1; ! 576: } ! 577: do ! 578: cp++; ! 579: while (*cp == ' '); ! 580: ! 581: doit: ! 582: return(openfile(fdesc, file, cp, how)); ! 583: } ! 584: #endif NOOPEN ! 585: ! 586: ! 587: /* ! 588: * File processing for open call ! 589: */ ! 590: openfile(fdesc, file, cp, how) ! 591: int fdesc; ! 592: struct iob *file; ! 593: char *cp; ! 594: int how; ! 595: { ! 596: ino_t ino; ! 597: ! 598: if (devopen(&file->i_si)) { ! 599: file->i_flgs = 0; ! 600: return(-1); /* if devopen fails, open fails */ ! 601: } ! 602: ! 603: if (*cp == '\0') { /* Opening a device */ ! 604: file->i_flgs |= how+1; ! 605: file->i_cc = 0; ! 606: file->i_offset = 0; ! 607: return(fdesc+3); ! 608: } ! 609: /* Opening a file system; read the superblock. */ ! 610: file->i_ma = (char *)(&file->i_fs); ! 611: file->i_cc = SBSIZE; ! 612: file->i_bn = SBLOCK; ! 613: file->i_offset = 0; ! 614: if (devread(&file->i_si) != SBSIZE) { ! 615: file->i_flgs = 0; ! 616: return(-1); ! 617: } ! 618: #ifndef BOOTBLOCK ! 619: if (file->i_fs.fs_magic != FS_MAGIC) { ! 620: printf("Not a file system\n"); ! 621: return(-1); ! 622: } ! 623: #endif ! 624: if ((ino = find(cp, file)) == 0) { ! 625: file->i_flgs = 0; ! 626: return(-1); ! 627: } ! 628: #ifndef BOOTBLOCK ! 629: if (how != 0) { ! 630: printf("Can't write files yet.. Sorry\n"); ! 631: file->i_flgs = 0; ! 632: return(-1); ! 633: } ! 634: #endif ! 635: openi(ino, file); ! 636: file->i_offset = 0; ! 637: file->i_cc = 0; ! 638: file->i_flgs |= F_FILE | (how+1); ! 639: return(fdesc+3); ! 640: } ! 641: ! 642: ! 643: close(fdesc) ! 644: int fdesc; ! 645: { ! 646: register struct iob *file; ! 647: ! 648: fdesc -= 3; ! 649: if (fdesc < 0 || fdesc >= NFILES || ! 650: ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) ! 651: return(-1); ! 652: devclose(&file->i_si); /* For a file-in-filesys or for raw dev */ ! 653: file->i_flgs = 0; ! 654: return(0); ! 655: } ! 656: ! 657: exit() ! 658: { ! 659: _stop((char *)0); ! 660: } ! 661: ! 662: _stop(s) ! 663: char *s; ! 664: { ! 665: register int i; ! 666: ! 667: for (i = 0; i < NFILES; i++) ! 668: if (iob[i].i_flgs != 0) ! 669: close(i); ! 670: if (s) printf("%s\n", s); ! 671: _exit(); ! 672: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.