|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: * ! 6: * @(#)sys.c 7.7 (Berkeley) 7/1/88 ! 7: */ ! 8: ! 9: #include "param.h" ! 10: #include "inode.h" ! 11: #include "fs.h" ! 12: #include "dir.h" ! 13: #include "reboot.h" ! 14: #include "saio.h" ! 15: ! 16: #define isdigit(c) ((u_int)((c) - '0') <= 9) ! 17: #define isspace(c) ((c) == ' ' || (c) == '\t') ! 18: #define isupper(c) ((u_int)((c) - 'A') <= 'Z' - 'A') ! 19: #define tolower(c) ((c) - 'A' + 'a') ! 20: ! 21: ino_t dlook(); ! 22: ! 23: struct dirstuff { ! 24: int loc; ! 25: struct iob *io; ! 26: }; ! 27: ! 28: struct iob iob[NFILES]; ! 29: ! 30: static ! 31: openi(n, io) ! 32: register struct iob *io; ! 33: { ! 34: register struct dinode *dp; ! 35: int cc; ! 36: ! 37: io->i_offset = 0; ! 38: io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff; ! 39: io->i_cc = io->i_fs.fs_bsize; ! 40: io->i_ma = io->i_buf; ! 41: cc = devread(io); ! 42: dp = (struct dinode *)io->i_buf; ! 43: io->i_ino.i_ic = dp[itoo(&io->i_fs, n)].di_ic; ! 44: return (cc); ! 45: } ! 46: ! 47: static ! 48: find(path, file) ! 49: register char *path; ! 50: struct iob *file; ! 51: { ! 52: register char *q; ! 53: char *dir, c; ! 54: int n; ! 55: ! 56: if (path == NULL || *path == '\0') { ! 57: printf("null path\n"); ! 58: return (0); ! 59: } ! 60: ! 61: if (openi((ino_t) ROOTINO, file) < 0) { ! 62: printf("can't read root inode\n"); ! 63: return (0); ! 64: } ! 65: dir = path; ! 66: while (*path) { ! 67: while (*path == '/') ! 68: path++; ! 69: q = path; ! 70: while(*q != '/' && *q != '\0') ! 71: q++; ! 72: c = *q; ! 73: *q = '\0'; ! 74: if (q == path) path = "." ; /* "/" means "/." */ ! 75: ! 76: if ((n = dlook(path, file, dir)) != 0) { ! 77: if (c == '\0') ! 78: break; ! 79: if (openi(n, file) < 0) ! 80: return (0); ! 81: *q = c; ! 82: path = q; ! 83: continue; ! 84: } else { ! 85: printf("%s: not found\n", path); ! 86: return (0); ! 87: } ! 88: } ! 89: return (n); ! 90: } ! 91: ! 92: #define NBUFS 4 ! 93: static char b[NBUFS][MAXBSIZE]; ! 94: static daddr_t blknos[NBUFS]; ! 95: ! 96: static daddr_t ! 97: sbmap(io, bn) ! 98: register struct iob *io; ! 99: daddr_t bn; ! 100: { ! 101: register struct inode *ip; ! 102: int i, j, sh; ! 103: daddr_t nb, *bap; ! 104: ! 105: ip = &io->i_ino; ! 106: if (bn < 0) { ! 107: printf("bn negative\n"); ! 108: return ((daddr_t)0); ! 109: } ! 110: ! 111: /* ! 112: * blocks 0..NDADDR are direct blocks ! 113: */ ! 114: if(bn < NDADDR) { ! 115: nb = ip->i_db[bn]; ! 116: return (nb); ! 117: } ! 118: ! 119: /* ! 120: * addresses NIADDR have single and double indirect blocks. ! 121: * the first step is to determine how many levels of indirection. ! 122: */ ! 123: sh = 1; ! 124: bn -= NDADDR; ! 125: for (j = NIADDR; j > 0; j--) { ! 126: sh *= NINDIR(&io->i_fs); ! 127: if (bn < sh) ! 128: break; ! 129: bn -= sh; ! 130: } ! 131: if (j == 0) { ! 132: printf("bn ovf %D\n", bn); ! 133: return ((daddr_t)0); ! 134: } ! 135: ! 136: /* ! 137: * fetch the first indirect block address from the inode ! 138: */ ! 139: nb = ip->i_ib[NIADDR - j]; ! 140: if (nb == 0) { ! 141: printf("bn void %D\n",bn); ! 142: return ((daddr_t)0); ! 143: } ! 144: ! 145: /* ! 146: * fetch through the indirect blocks ! 147: */ ! 148: for (; j <= NIADDR; j++) { ! 149: if (blknos[j] != nb) { ! 150: io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff; ! 151: io->i_ma = b[j]; ! 152: io->i_cc = io->i_fs.fs_bsize; ! 153: if (devread(io) != io->i_fs.fs_bsize) { ! 154: if (io->i_error) ! 155: errno = io->i_error; ! 156: printf("bn %D: read error\n", io->i_bn); ! 157: return ((daddr_t)0); ! 158: } ! 159: blknos[j] = nb; ! 160: } ! 161: bap = (daddr_t *)b[j]; ! 162: sh /= NINDIR(&io->i_fs); ! 163: i = (bn / sh) % NINDIR(&io->i_fs); ! 164: nb = bap[i]; ! 165: if(nb == 0) { ! 166: printf("bn void %D\n",bn); ! 167: return ((daddr_t)0); ! 168: } ! 169: } ! 170: return (nb); ! 171: } ! 172: ! 173: static ino_t ! 174: dlook(s, io, dir) ! 175: char *s; ! 176: register struct iob *io; ! 177: char *dir; ! 178: { ! 179: register struct direct *dp; ! 180: register struct inode *ip; ! 181: struct dirstuff dirp; ! 182: int len; ! 183: ! 184: if (s == NULL || *s == '\0') ! 185: return (0); ! 186: ip = &io->i_ino; ! 187: if ((ip->i_mode&IFMT) != IFDIR) { ! 188: printf("%s: not a directory\n", dir); ! 189: return (0); ! 190: } ! 191: if (ip->i_size == 0) { ! 192: printf("%s: zero length directory\n", dir); ! 193: return (0); ! 194: } ! 195: len = strlen(s); ! 196: dirp.loc = 0; ! 197: dirp.io = io; ! 198: for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { ! 199: if(dp->d_ino == 0) ! 200: continue; ! 201: if (dp->d_namlen == len && !strcmp(s, dp->d_name)) ! 202: return (dp->d_ino); ! 203: } ! 204: return (0); ! 205: } ! 206: ! 207: /* ! 208: * get next entry in a directory. ! 209: */ ! 210: struct direct * ! 211: readdir(dirp) ! 212: register struct dirstuff *dirp; ! 213: { ! 214: register struct direct *dp; ! 215: register struct iob *io; ! 216: daddr_t lbn, d; ! 217: int off; ! 218: ! 219: io = dirp->io; ! 220: for(;;) { ! 221: if (dirp->loc >= io->i_ino.i_size) ! 222: return (NULL); ! 223: off = blkoff(&io->i_fs, dirp->loc); ! 224: if (off == 0) { ! 225: lbn = lblkno(&io->i_fs, dirp->loc); ! 226: d = sbmap(io, lbn); ! 227: if(d == 0) ! 228: return (NULL); ! 229: io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff; ! 230: io->i_ma = io->i_buf; ! 231: io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn); ! 232: if (devread(io) < 0) { ! 233: errno = io->i_error; ! 234: printf("bn %D: directory read error\n", ! 235: io->i_bn); ! 236: return (NULL); ! 237: } ! 238: } ! 239: dp = (struct direct *)(io->i_buf + off); ! 240: dirp->loc += dp->d_reclen; ! 241: if (dp->d_ino == 0) ! 242: continue; ! 243: return (dp); ! 244: } ! 245: } ! 246: ! 247: lseek(fdesc, addr, ptr) ! 248: int fdesc, ptr; ! 249: off_t addr; ! 250: { ! 251: register struct iob *io; ! 252: ! 253: #ifndef SMALL ! 254: if (ptr != L_SET) { ! 255: printf("Seek not from beginning of file\n"); ! 256: errno = EOFFSET; ! 257: return (-1); ! 258: } ! 259: #endif ! 260: fdesc -= 3; ! 261: if (fdesc < 0 || fdesc >= NFILES || ! 262: ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) { ! 263: errno = EBADF; ! 264: return (-1); ! 265: } ! 266: io->i_offset = addr; ! 267: io->i_bn = addr / DEV_BSIZE; ! 268: io->i_cc = 0; ! 269: return (0); ! 270: } ! 271: ! 272: getc(fdesc) ! 273: int fdesc; ! 274: { ! 275: register struct iob *io; ! 276: register struct fs *fs; ! 277: register char *p; ! 278: int c, lbn, off, size, diff; ! 279: ! 280: ! 281: if (fdesc >= 0 && fdesc <= 2) ! 282: return (getchar()); ! 283: fdesc -= 3; ! 284: if (fdesc < 0 || fdesc >= NFILES || ! 285: ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { ! 286: errno = EBADF; ! 287: return (-1); ! 288: } ! 289: p = io->i_ma; ! 290: if (io->i_cc <= 0) { ! 291: if ((io->i_flgs & F_FILE) != 0) { ! 292: diff = io->i_ino.i_size - io->i_offset; ! 293: if (diff <= 0) ! 294: return (-1); ! 295: fs = &io->i_fs; ! 296: lbn = lblkno(fs, io->i_offset); ! 297: io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff; ! 298: off = blkoff(fs, io->i_offset); ! 299: size = blksize(fs, &io->i_ino, lbn); ! 300: } else { ! 301: io->i_bn = io->i_offset / DEV_BSIZE; ! 302: off = 0; ! 303: size = DEV_BSIZE; ! 304: } ! 305: io->i_ma = io->i_buf; ! 306: io->i_cc = size; ! 307: if (devread(io) < 0) { ! 308: errno = io->i_error; ! 309: return (-1); ! 310: } ! 311: if ((io->i_flgs & F_FILE) != 0) { ! 312: if (io->i_offset - off + size >= io->i_ino.i_size) ! 313: io->i_cc = diff + off; ! 314: io->i_cc -= off; ! 315: } ! 316: p = &io->i_buf[off]; ! 317: } ! 318: io->i_cc--; ! 319: io->i_offset++; ! 320: c = (unsigned)*p++; ! 321: io->i_ma = p; ! 322: return (c); ! 323: } ! 324: ! 325: int errno; ! 326: ! 327: read(fdesc, buf, count) ! 328: int fdesc, count; ! 329: char *buf; ! 330: { ! 331: register i, size; ! 332: register struct iob *file; ! 333: register struct fs *fs; ! 334: int lbn, off; ! 335: ! 336: errno = 0; ! 337: if (fdesc >= 0 & fdesc <= 2) { ! 338: i = count; ! 339: do { ! 340: *buf = getchar(); ! 341: } while (--i && *buf++ != '\n'); ! 342: return (count - i); ! 343: } ! 344: fdesc -= 3; ! 345: if (fdesc < 0 || fdesc >= NFILES || ! 346: ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { ! 347: errno = EBADF; ! 348: return (-1); ! 349: } ! 350: if ((file->i_flgs&F_READ) == 0) { ! 351: errno = EBADF; ! 352: return (-1); ! 353: } ! 354: #ifndef SMALL ! 355: if ((file->i_flgs & F_FILE) == 0) { ! 356: file->i_cc = count; ! 357: file->i_ma = buf; ! 358: file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE); ! 359: i = devread(file); ! 360: if (i < 0) ! 361: errno = file->i_error; ! 362: else ! 363: file->i_offset += i; ! 364: return (i); ! 365: } ! 366: #endif ! 367: if (file->i_offset+count > file->i_ino.i_size) ! 368: count = file->i_ino.i_size - file->i_offset; ! 369: if ((i = count) <= 0) ! 370: return (0); ! 371: /* ! 372: * While reading full blocks, do I/O into user buffer. ! 373: * Anything else uses getc(). ! 374: */ ! 375: fs = &file->i_fs; ! 376: while (i) { ! 377: off = blkoff(fs, file->i_offset); ! 378: lbn = lblkno(fs, file->i_offset); ! 379: size = blksize(fs, &file->i_ino, lbn); ! 380: if (off == 0 && size <= i) { ! 381: file->i_bn = fsbtodb(fs, sbmap(file, lbn)) + ! 382: file->i_boff; ! 383: file->i_cc = size; ! 384: file->i_ma = buf; ! 385: if (devread(file) < 0) { ! 386: errno = file->i_error; ! 387: return (-1); ! 388: } ! 389: file->i_offset += size; ! 390: file->i_cc = 0; ! 391: buf += size; ! 392: i -= size; ! 393: } else { ! 394: size -= off; ! 395: if (size > i) ! 396: size = i; ! 397: i -= size; ! 398: do { ! 399: *buf++ = getc(fdesc+3); ! 400: } while (--size); ! 401: } ! 402: } ! 403: return (count); ! 404: } ! 405: ! 406: #ifndef SMALL ! 407: write(fdesc, buf, count) ! 408: int fdesc, count; ! 409: char *buf; ! 410: { ! 411: register i; ! 412: register struct iob *file; ! 413: ! 414: errno = 0; ! 415: if (fdesc >= 0 && fdesc <= 2) { ! 416: i = count; ! 417: while (i--) ! 418: putchar(*buf++); ! 419: return (count); ! 420: } ! 421: fdesc -= 3; ! 422: if (fdesc < 0 || fdesc >= NFILES || ! 423: ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { ! 424: errno = EBADF; ! 425: return (-1); ! 426: } ! 427: if ((file->i_flgs&F_WRITE) == 0) { ! 428: errno = EBADF; ! 429: return (-1); ! 430: } ! 431: file->i_cc = count; ! 432: file->i_ma = buf; ! 433: file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE); ! 434: i = devwrite(file); ! 435: file->i_offset += count; ! 436: if (i < 0) ! 437: errno = file->i_error; ! 438: return (i); ! 439: } ! 440: #endif ! 441: ! 442: int openfirst = 1; ! 443: u_int opendev; /* last device opened */ ! 444: extern u_int bootdev; ! 445: ! 446: open(str, how) ! 447: char *str; ! 448: int how; ! 449: { ! 450: register char *t; ! 451: register int cnt; ! 452: register struct iob *file; ! 453: int fdesc, args[8], *argp; ! 454: ! 455: if (openfirst) { ! 456: for (cnt = 0; cnt < NFILES; cnt++) ! 457: iob[cnt].i_flgs = 0; ! 458: openfirst = 0; ! 459: } ! 460: ! 461: for (fdesc = 0;; fdesc++) { ! 462: if (fdesc == NFILES) ! 463: _stop("No more file slots"); ! 464: if (iob[fdesc].i_flgs == 0) { ! 465: file = &iob[fdesc]; ! 466: file->i_flgs |= F_ALLOC; ! 467: file->i_adapt = file->i_ctlr = file->i_unit = ! 468: file->i_part = 0; ! 469: break; ! 470: } ! 471: } ! 472: ! 473: for (cnt = 0; cnt < sizeof(args)/sizeof(args[0]); args[cnt++] = 0); ! 474: #ifndef SMALL ! 475: for (t = str; *t && *t != '/' && *t != ':' && *t != '('; ++t) ! 476: if (isupper(*t)) ! 477: *t = tolower(*t); ! 478: switch(*t) { ! 479: case '(': /* type(adapt, ctlr, drive, partition)file */ ! 480: if ((file->i_ino.i_dev = getdev(str, t - str)) == -1) ! 481: goto bad; ! 482: for (argp = args + 4, cnt = 0; *t != ')'; ++cnt) { ! 483: for (++t; isspace(*t); ++t); ! 484: if (*t == ')') ! 485: break; ! 486: if (!isdigit(*t)) ! 487: goto badspec; ! 488: *argp++ = atoi(t); ! 489: for (++t; isdigit(*t); ++t); ! 490: if (*t != ',' && *t != ')' || cnt == 4) ! 491: goto badspec; ! 492: } ! 493: for (++t; isspace(*t); ++t); ! 494: argp -= 4; ! 495: file->i_adapt = *argp++; ! 496: file->i_ctlr = *argp++; ! 497: file->i_unit = *argp++; ! 498: file->i_part = *argp; ! 499: break; ! 500: case ':': /* [A-Za-z]*[0-9]*[A-Za-z]:file */ ! 501: for (t = str; *t != ':' && !isdigit(*t); ++t); ! 502: if ((file->i_ino.i_dev = getdev(str, t - str)) == -1) ! 503: goto bad; ! 504: if ((file->i_unit = getunit(t)) == -1) ! 505: goto bad; ! 506: for (; isdigit(*t); ++t); ! 507: if (*t >= 'a' && *t <= 'h') ! 508: file->i_part = *t++ - 'a'; ! 509: if (*t != ':') { ! 510: errno = EOFFSET; ! 511: goto badspec; ! 512: } ! 513: for (++t; isspace(*t); ++t); ! 514: break; ! 515: case '/': ! 516: default: /* default bootstrap unit and device */ ! 517: #else ! 518: { ! 519: #endif /* SMALL */ ! 520: file->i_ino.i_dev = B_TYPE(bootdev); ! 521: file->i_adapt = B_ADAPTOR(bootdev); ! 522: file->i_ctlr = B_CONTROLLER(bootdev); ! 523: file->i_unit = B_UNIT(bootdev); ! 524: file->i_part = B_PARTITION(bootdev); ! 525: t = str; ! 526: } ! 527: ! 528: opendev = MAKEBOOTDEV(file->i_ino.i_dev, file->i_adapt, file->i_ctlr, ! 529: file->i_unit, file->i_part); ! 530: ! 531: if (errno = devopen(file)) ! 532: goto bad; ! 533: ! 534: if (*t == '\0') { ! 535: file->i_flgs |= how + 1; ! 536: file->i_cc = 0; ! 537: file->i_offset = 0; ! 538: return (fdesc+3); ! 539: } ! 540: #ifndef SMALL ! 541: else if (how != 0) { ! 542: printf("Can't write files yet.. Sorry\n"); ! 543: errno = EIO; ! 544: goto bad; ! 545: } ! 546: #endif ! 547: file->i_ma = (char *)(&file->i_fs); ! 548: file->i_cc = SBSIZE; ! 549: file->i_bn = SBOFF / DEV_BSIZE + file->i_boff; ! 550: file->i_offset = 0; ! 551: if (devread(file) < 0) { ! 552: errno = file->i_error; ! 553: printf("super block read error\n"); ! 554: goto bad; ! 555: } ! 556: if ((cnt = find(t, file)) == 0) { ! 557: errno = ESRCH; ! 558: goto bad; ! 559: } ! 560: if (openi(cnt, file) < 0) { ! 561: errno = file->i_error; ! 562: goto bad; ! 563: } ! 564: file->i_offset = 0; ! 565: file->i_cc = 0; ! 566: file->i_flgs |= F_FILE | (how+1); ! 567: return (fdesc+3); ! 568: ! 569: #ifndef SMALL ! 570: badspec: ! 571: printf("malformed device specification\nusage: device(adaptor, controller, drive, partition)file\n"); ! 572: #endif ! 573: bad: ! 574: file->i_flgs = 0; ! 575: return (-1); ! 576: } ! 577: ! 578: #ifndef SMALL ! 579: static ! 580: getdev(str, len) ! 581: register char *str; ! 582: int len; ! 583: { ! 584: register struct devsw *dp; ! 585: register int i; ! 586: char savedch = str[len]; ! 587: ! 588: str[len] = '\0'; ! 589: for (dp = devsw, i = 0; i < ndevs; dp++, i++) ! 590: if (dp->dv_name && strcmp(str, dp->dv_name) == 0) { ! 591: str[len] = savedch; ! 592: return (i); ! 593: } ! 594: printf("Unknown device\nKnown devices are:\n"); ! 595: for (dp = devsw, i = 0; i < ndevs; dp++, i++) ! 596: if (dp->dv_name) ! 597: printf(" %s", dp->dv_name); ! 598: printf("\n"); ! 599: errno = ENXIO; ! 600: return (-1); ! 601: } ! 602: ! 603: static ! 604: getunit(cp) ! 605: register char *cp; ! 606: { ! 607: int unit; ! 608: ! 609: unit = atoi(cp); ! 610: if ((u_int)unit > 255) { ! 611: printf("minor device number out of range (0-255)\n"); ! 612: errno = EUNIT; ! 613: return (-1); ! 614: } ! 615: return (unit); ! 616: } ! 617: #endif /* SMALL */ ! 618: ! 619: close(fdesc) ! 620: int fdesc; ! 621: { ! 622: struct iob *file; ! 623: ! 624: fdesc -= 3; ! 625: if (fdesc < 0 || fdesc >= NFILES || ! 626: ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { ! 627: errno = EBADF; ! 628: return (-1); ! 629: } ! 630: if ((file->i_flgs&F_FILE) == 0) ! 631: devclose(file); ! 632: file->i_flgs = 0; ! 633: return (0); ! 634: } ! 635: ! 636: #ifndef SMALL ! 637: ioctl(fdesc, cmd, arg) ! 638: int fdesc, cmd; ! 639: char *arg; ! 640: { ! 641: register struct iob *file; ! 642: int error = 0; ! 643: ! 644: fdesc -= 3; ! 645: if (fdesc < 0 || fdesc >= NFILES || ! 646: ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { ! 647: errno = EBADF; ! 648: return (-1); ! 649: } ! 650: switch (cmd) { ! 651: ! 652: case SAIOHDR: ! 653: file->i_flgs |= F_HDR; ! 654: break; ! 655: ! 656: case SAIOCHECK: ! 657: file->i_flgs |= F_CHECK; ! 658: break; ! 659: ! 660: case SAIOHCHECK: ! 661: file->i_flgs |= F_HCHECK; ! 662: break; ! 663: ! 664: case SAIONOBAD: ! 665: file->i_flgs |= F_NBSF; ! 666: break; ! 667: ! 668: case SAIODOBAD: ! 669: file->i_flgs &= ~F_NBSF; ! 670: break; ! 671: ! 672: default: ! 673: error = devioctl(file, cmd, arg); ! 674: break; ! 675: } ! 676: if (error < 0) ! 677: errno = file->i_error; ! 678: return (error); ! 679: } ! 680: #endif /* SMALL */ ! 681: ! 682: exit() ! 683: { ! 684: _stop("Exit called"); ! 685: } ! 686: ! 687: _stop(s) ! 688: char *s; ! 689: { ! 690: int i; ! 691: ! 692: for (i = 0; i < NFILES; i++) ! 693: if (iob[i].i_flgs != 0) ! 694: close(i); ! 695: printf("%s\n", s); ! 696: _rtt(); ! 697: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.