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