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