1: #define MAXINO 3000 2: #define BITS 8 3: #define MAXXTR 60 4: #define NCACHE 3 5: 6: #ifndef STANDALONE 7: #include <stdio.h> 8: #include <signal.h> 9: #endif 10: #include <sys/param.h> 11: #include <sys/inode.h> 12: #include <sys/ino.h> 13: #include <sys/fblk.h> 14: #include <sys/filsys.h> 15: #include <sys/dir.h> 16: #include <dumprestor.h> 17: 18: #define MWORD(m,i) (m[(unsigned)(i-1)/MLEN]) 19: #define MBIT(i) (1<<((unsigned)(i-1)%MLEN)) 20: #define BIS(i,w) (MWORD(w,i) |= MBIT(i)) 21: #define BIC(i,w) (MWORD(w,i) &= ~MBIT(i)) 22: #define BIT(i,w) (MWORD(w,i) & MBIT(i)) 23: 24: struct filsys sblock; 25: 26: int fi; 27: ino_t ino, maxi, curino; 28: 29: int mt; 30: char tapename[] = "/dev/rmt1"; 31: char *magtape = tapename; 32: #ifdef STANDALONE 33: char mbuf[50]; 34: #endif 35: 36: #ifndef STANDALONE 37: daddr_t seekpt; 38: int df, ofile; 39: char dirfile[] = "rstXXXXXX"; 40: 41: struct { 42: ino_t t_ino; 43: daddr_t t_seekpt; 44: } inotab[MAXINO]; 45: int ipos; 46: 47: #define ONTAPE 1 48: #define XTRACTD 2 49: #define XINUSE 4 50: struct xtrlist { 51: ino_t x_ino; 52: char x_flags; 53: } xtrlist[MAXXTR]; 54: 55: char name[12]; 56: 57: char drblock[BSIZE]; 58: int bpt; 59: #endif 60: 61: int eflag; 62: 63: int volno = 1; 64: 65: struct dinode tino, dino; 66: daddr_t taddr[NADDR]; 67: 68: daddr_t curbno; 69: 70: short dumpmap[MSIZ]; 71: short clrimap[MSIZ]; 72: 73: 74: int bct = NTREC+1; 75: char tbf[NTREC*BSIZE]; 76: 77: struct cache { 78: daddr_t c_bno; 79: int c_time; 80: char c_block[BSIZE]; 81: } cache[NCACHE]; 82: int curcache; 83: 84: main(argc, argv) 85: char *argv[]; 86: { 87: register char *cp; 88: char command; 89: int done(); 90: 91: #ifndef STANDALONE 92: mktemp(dirfile); 93: if (argc < 2) { 94: usage: 95: printf("Usage: restor x file file..., restor r filesys, or restor t\n"); 96: exit(1); 97: } 98: argv++; 99: argc -= 2; 100: for (cp = *argv++; *cp; cp++) { 101: switch (*cp) { 102: case '-': 103: break; 104: case 'f': 105: magtape = *argv++; 106: argc--; 107: break; 108: case 'r': 109: case 'R': 110: case 't': 111: case 'x': 112: command = *cp; 113: break; 114: default: 115: printf("Bad key character %c\n", *cp); 116: goto usage; 117: } 118: } 119: if (command == 'x') { 120: if (signal(SIGINT, done) == SIG_IGN) 121: signal(SIGINT, SIG_IGN); 122: if (signal(SIGTERM, done) == SIG_IGN) 123: signal(SIGTERM, SIG_IGN); 124: 125: df = creat(dirfile, 0666); 126: if (df < 0) { 127: printf("restor: %s - cannot create directory temporary\n", dirfile); 128: exit(1); 129: } 130: close(df); 131: df = open(dirfile, 2); 132: } 133: doit(command, argc, argv); 134: if (command == 'x') 135: unlink(dirfile); 136: exit(0); 137: #else 138: magtape = "tape"; 139: doit('r', 1, 0); 140: #endif 141: } 142: 143: doit(command, argc, argv) 144: char command; 145: int argc; 146: char *argv[]; 147: { 148: extern char *ctime(); 149: register i, k; 150: ino_t d; 151: #ifndef STANDALONE 152: int xtrfile(), skip(); 153: #endif 154: int rstrfile(), rstrskip(); 155: struct dinode *ip, *ip1; 156: 157: #ifndef STANDALONE 158: if ((mt = open(magtape, 0)) < 0) { 159: printf("%s: cannot open tape\n", magtape); 160: exit(1); 161: } 162: #else 163: do { 164: printf("Tape? "); 165: gets(mbuf); 166: mt = open(mbuf, 0); 167: } while (mt == -1); 168: magtape = mbuf; 169: #endif 170: switch(command) { 171: #ifndef STANDALONE 172: case 't': 173: if (readhdr(&spcl) == 0) { 174: printf("Tape is not a dump tape\n"); 175: exit(1); 176: } 177: printf("Dump date: %s", ctime(&spcl.c_date)); 178: printf("Dumped from: %s", ctime(&spcl.c_ddate)); 179: return; 180: case 'x': 181: if (readhdr(&spcl) == 0) { 182: printf("Tape is not a dump tape\n"); 183: exit(1); 184: } 185: if (checkvol(&spcl, 1) == 0) { 186: printf("Tape is not volume 1 of the dump\n"); 187: exit(1); 188: } 189: pass1(); /* This sets the various maps on the way by */ 190: i = 0; 191: while (i < MAXXTR-1 && argc--) { 192: if ((d = psearch(*argv)) == 0 || BIT(d, dumpmap) == 0) { 193: printf("%s: not on the tape\n", *argv++); 194: continue; 195: } 196: xtrlist[i].x_ino = d; 197: xtrlist[i].x_flags |= XINUSE; 198: printf("%s: inode %u\n", *argv, d); 199: argv++; 200: i++; 201: } 202: newvol: 203: flsht(); 204: close(mt); 205: getvol: 206: printf("Mount desired tape volume: Specify volume #: "); 207: if (gets(tbf) == NULL) 208: return; 209: volno = atoi(tbf); 210: if (volno <= 0) { 211: printf("Volume numbers are positive numerics\n"); 212: goto getvol; 213: } 214: mt = open(magtape, 0); 215: if (readhdr(&spcl) == 0) { 216: printf("tape is not dump tape\n"); 217: goto newvol; 218: } 219: if (checkvol(&spcl, volno) == 0) { 220: printf("Wrong volume (%d)\n", spcl.c_volume); 221: goto newvol; 222: } 223: rbits: 224: while (gethead(&spcl) == 0) 225: ; 226: if (checktype(&spcl, TS_INODE) == 1) { 227: printf("Can't find inode mask!\n"); 228: goto newvol; 229: } 230: if (checktype(&spcl, TS_BITS) == 0) 231: goto rbits; 232: readbits(dumpmap); 233: i = 0; 234: for (k = 0; xtrlist[k].x_flags; k++) { 235: if (BIT(xtrlist[k].x_ino, dumpmap)) { 236: xtrlist[k].x_flags |= ONTAPE; 237: i++; 238: } 239: } 240: while (i > 0) { 241: again: 242: if (ishead(&spcl) == 0) 243: while(gethead(&spcl) == 0) 244: ; 245: if (checktype(&spcl, TS_END) == 1) { 246: printf("end of tape\n"); 247: checkdone: 248: for (k = 0; xtrlist[k].x_flags; k++) 249: if ((xtrlist[k].x_flags&XTRACTD) == 0) 250: goto newvol; 251: return; 252: } 253: if (checktype(&spcl, TS_INODE) == 0) { 254: gethead(&spcl); 255: goto again; 256: } 257: d = spcl.c_inumber; 258: for (k = 0; xtrlist[k].x_flags; k++) { 259: if (d == xtrlist[k].x_ino) { 260: printf("extract file %u\n", xtrlist[k].x_ino); 261: sprintf(name, "%u", xtrlist[k].x_ino); 262: if ((ofile = creat(name, 0666)) < 0) { 263: printf("%s: cannot create file\n", name); 264: i--; 265: continue; 266: } 267: chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid); 268: getfile(ino, xtrfile, skip, spcl.c_dinode.di_size); 269: i--; 270: xtrlist[k].x_flags |= XTRACTD; 271: close(ofile); 272: goto done; 273: } 274: } 275: gethead(&spcl); 276: done: 277: ; 278: } 279: goto checkdone; 280: #endif 281: case 'r': 282: case 'R': 283: #ifndef STANDALONE 284: if ((fi = open(*argv, 2)) < 0) { 285: printf("%s: cannot open\n", *argv); 286: exit(1); 287: } 288: #else 289: do { 290: char charbuf[50]; 291: 292: printf("Disk? "); 293: gets(charbuf); 294: fi = open(charbuf, 2); 295: } while (fi == -1); 296: #endif 297: #ifndef STANDALONE 298: if (command == 'R') { 299: printf("Enter starting volume number: "); 300: if (gets(tbf) == EOF) { 301: volno = 1; 302: printf("\n"); 303: } 304: else 305: volno = atoi(tbf); 306: } 307: else 308: #endif 309: volno = 1; 310: printf("Last chance before scribbling on %s. ", 311: #ifdef STANDALONE 312: "disk"); 313: #else 314: *argv); 315: #endif 316: while (getchar() != '\n'); 317: dread((daddr_t)1, (char *)&sblock, sizeof(sblock)); 318: maxi = (sblock.s_isize-2)*INOPB; 319: if (readhdr(&spcl) == 0) { 320: printf("Missing volume record\n"); 321: exit(1); 322: } 323: if (checkvol(&spcl, volno) == 0) { 324: printf("Tape is not volume %d\n", volno); 325: exit(1); 326: } 327: gethead(&spcl); 328: for (;;) { 329: ragain: 330: if (ishead(&spcl) == 0) { 331: printf("Missing header block\n"); 332: while (gethead(&spcl) == 0) 333: ; 334: eflag++; 335: } 336: if (checktype(&spcl, TS_END) == 1) { 337: printf("End of tape\n"); 338: close(mt); 339: dwrite( (daddr_t) 1, (char *) &sblock); 340: return; 341: } 342: if (checktype(&spcl, TS_CLRI) == 1) { 343: readbits(clrimap); 344: for (ino = 1; ino <= maxi; ino++) 345: if (BIT(ino, clrimap) == 0) { 346: getdino(ino, &tino); 347: if (tino.di_mode == 0) 348: continue; 349: itrunc(&tino); 350: clri(&tino); 351: putdino(ino, &tino); 352: } 353: dwrite( (daddr_t) 1, (char *) &sblock); 354: goto ragain; 355: } 356: if (checktype(&spcl, TS_BITS) == 1) { 357: readbits(dumpmap); 358: goto ragain; 359: } 360: if (checktype(&spcl, TS_INODE) == 0) { 361: printf("Unknown header type\n"); 362: eflag++; 363: gethead(&spcl); 364: goto ragain; 365: } 366: ino = spcl.c_inumber; 367: if (eflag) 368: printf("Resynced at inode %u\n", ino); 369: eflag = 0; 370: if (ino > maxi) { 371: printf("%u: ilist too small\n", ino); 372: gethead(&spcl); 373: goto ragain; 374: } 375: dino = spcl.c_dinode; 376: getdino(ino, &tino); 377: curbno = 0; 378: itrunc(&tino); 379: clri(&tino); 380: for (i = 0; i < NADDR; i++) 381: taddr[i] = 0; 382: l3tol(taddr, dino.di_addr, 1); 383: getfile(ino, rstrfile, rstrskip, dino.di_size); 384: ip = &tino; 385: ltol3(ip->di_addr, taddr, NADDR); 386: ip1 = &dino; 387: ip->di_mode = ip1->di_mode; 388: ip->di_nlink = ip1->di_nlink; 389: ip->di_uid = ip1->di_uid; 390: ip->di_gid = ip1->di_gid; 391: ip->di_size = ip1->di_size; 392: ip->di_atime = ip1->di_atime; 393: ip->di_mtime = ip1->di_mtime; 394: ip->di_ctime = ip1->di_ctime; 395: putdino(ino, &tino); 396: } 397: } 398: } 399: 400: /* 401: * Read the tape, bulding up a directory structure for extraction 402: * by name 403: */ 404: #ifndef STANDALONE 405: pass1() 406: { 407: register i; 408: struct dinode *ip; 409: int putdir(), null(); 410: 411: while (gethead(&spcl) == 0) { 412: printf("Can't find directory header!\n"); 413: } 414: for (;;) { 415: if (checktype(&spcl, TS_BITS) == 1) { 416: readbits(dumpmap); 417: continue; 418: } 419: if (checktype(&spcl, TS_CLRI) == 1) { 420: readbits(clrimap); 421: continue; 422: } 423: if (checktype(&spcl, TS_INODE) == 0) { 424: finish: 425: flsh(); 426: close(mt); 427: return; 428: } 429: ip = &spcl.c_dinode; 430: i = ip->di_mode & IFMT; 431: if (i != IFDIR) { 432: goto finish; 433: } 434: inotab[ipos].t_ino = spcl.c_inumber; 435: inotab[ipos++].t_seekpt = seekpt; 436: getfile(spcl.c_inumber, putdir, null, spcl.c_dinode.di_size); 437: putent("\000\000/"); 438: } 439: } 440: #endif 441: 442: /* 443: * Do the file extraction, calling the supplied functions 444: * with the blocks 445: */ 446: getfile(n, f1, f2, size) 447: ino_t n; 448: int (*f2)(), (*f1)(); 449: long size; 450: { 451: register i; 452: struct spcl addrblock; 453: char buf[BSIZE]; 454: 455: addrblock = spcl; 456: curino = n; 457: goto start; 458: for (;;) { 459: if (gethead(&addrblock) == 0) { 460: printf("Missing address (header) block\n"); 461: goto eloop; 462: } 463: if (checktype(&addrblock, TS_ADDR) == 0) { 464: spcl = addrblock; 465: curino = 0; 466: return; 467: } 468: start: 469: for (i = 0; i < addrblock.c_count; i++) { 470: if (addrblock.c_addr[i]) { 471: readtape(buf); 472: (*f1)(buf, size > BSIZE ? (long) BSIZE : size); 473: } 474: else { 475: clearbuf(buf); 476: (*f2)(buf, size > BSIZE ? (long) BSIZE : size); 477: } 478: if ((size -= BSIZE) <= 0) { 479: eloop: 480: while (gethead(&spcl) == 0) 481: ; 482: if (checktype(&spcl, TS_ADDR) == 1) 483: goto eloop; 484: curino = 0; 485: return; 486: } 487: } 488: } 489: } 490: 491: /* 492: * Do the tape i\/o, dealling with volume changes 493: * etc.. 494: */ 495: readtape(b) 496: char *b; 497: { 498: register i; 499: struct spcl tmpbuf; 500: 501: if (bct >= NTREC) { 502: for (i = 0; i < NTREC; i++) 503: ((struct spcl *)&tbf[i*BSIZE])->c_magic = 0; 504: bct = 0; 505: if ((i = read(mt, tbf, NTREC*BSIZE)) < 0) { 506: printf("Tape read error: inode %u\n", curino); 507: eflag++; 508: for (i = 0; i < NTREC; i++) 509: clearbuf(&tbf[i*BSIZE]); 510: } 511: if (i == 0) { 512: bct = NTREC + 1; 513: volno++; 514: loop: 515: flsht(); 516: close(mt); 517: printf("Mount volume %d\n", volno); 518: while (getchar() != '\n') 519: ; 520: if ((mt = open(magtape, 0)) == -1) { 521: printf("Cannot open tape!\n"); 522: goto loop; 523: } 524: if (readhdr(&tmpbuf) == 0) { 525: printf("Not a dump tape.Try again\n"); 526: goto loop; 527: } 528: if (checkvol(&tmpbuf, volno) == 0) { 529: printf("Wrong tape. Try again\n"); 530: goto loop; 531: } 532: readtape(b); 533: return; 534: } 535: } 536: copy(&tbf[(bct++*BSIZE)], b, BSIZE); 537: } 538: 539: flsht() 540: { 541: bct = NTREC+1; 542: } 543: 544: copy(f, t, s) 545: register char *f, *t; 546: { 547: register i; 548: 549: i = s; 550: do 551: *t++ = *f++; 552: while (--i); 553: } 554: 555: clearbuf(cp) 556: register char *cp; 557: { 558: register i; 559: 560: i = BSIZE; 561: do 562: *cp++ = 0; 563: while (--i); 564: } 565: 566: /* 567: * Put and get the directory entries from the compressed 568: * directory file 569: */ 570: #ifndef STANDALONE 571: putent(cp) 572: char *cp; 573: { 574: register i; 575: 576: for (i = 0; i < sizeof(ino_t); i++) 577: writec(*cp++); 578: for (i = 0; i < DIRSIZ; i++) { 579: writec(*cp); 580: if (*cp++ == 0) 581: return; 582: } 583: return; 584: } 585: 586: getent(bf) 587: register char *bf; 588: { 589: register i; 590: 591: for (i = 0; i < sizeof(ino_t); i++) 592: *bf++ = readc(); 593: for (i = 0; i < DIRSIZ; i++) 594: if ((*bf++ = readc()) == 0) 595: return; 596: return; 597: } 598: 599: /* 600: * read/write te directory file 601: */ 602: writec(c) 603: char c; 604: { 605: drblock[bpt++] = c; 606: seekpt++; 607: if (bpt >= BSIZE) { 608: bpt = 0; 609: write(df, drblock, BSIZE); 610: } 611: } 612: 613: readc() 614: { 615: if (bpt >= BSIZE) { 616: read(df, drblock, BSIZE); 617: bpt = 0; 618: } 619: return(drblock[bpt++]); 620: } 621: 622: mseek(pt) 623: daddr_t pt; 624: { 625: bpt = BSIZE; 626: lseek(df, pt, 0); 627: } 628: 629: flsh() 630: { 631: write(df, drblock, bpt+1); 632: } 633: 634: /* 635: * search the directory inode ino 636: * looking for entry cp 637: */ 638: ino_t 639: search(inum, cp) 640: ino_t inum; 641: char *cp; 642: { 643: register i; 644: struct direct dir; 645: 646: for (i = 0; i < MAXINO; i++) 647: if (inotab[i].t_ino == inum) { 648: goto found; 649: } 650: return(0); 651: found: 652: mseek(inotab[i].t_seekpt); 653: do { 654: getent((char *)&dir); 655: if (direq(dir.d_name, "/")) 656: return(0); 657: } while (direq(dir.d_name, cp) == 0); 658: return(dir.d_ino); 659: } 660: 661: /* 662: * Search the directory tree rooted at inode 2 663: * for the path pointed at by n 664: */ 665: psearch(n) 666: char *n; 667: { 668: register char *cp, *cp1; 669: char c; 670: 671: ino = 2; 672: if (*(cp = n) == '/') 673: cp++; 674: next: 675: cp1 = cp + 1; 676: while (*cp1 != '/' && *cp1) 677: cp1++; 678: c = *cp1; 679: *cp1 = 0; 680: ino = search(ino, cp); 681: if (ino == 0) { 682: *cp1 = c; 683: return(0); 684: } 685: *cp1 = c; 686: if (c == '/') { 687: cp = cp1+1; 688: goto next; 689: } 690: return(ino); 691: } 692: 693: direq(s1, s2) 694: register char *s1, *s2; 695: { 696: register i; 697: 698: for (i = 0; i < DIRSIZ; i++) 699: if (*s1++ == *s2) { 700: if (*s2++ == 0) 701: return(1); 702: } else 703: return(0); 704: return(1); 705: } 706: #endif 707: 708: /* 709: * read/write a disk block, be sure to update the buffer 710: * cache if needed. 711: */ 712: dwrite(bno, b) 713: daddr_t bno; 714: char *b; 715: { 716: register i; 717: 718: for (i = 0; i < NCACHE; i++) { 719: if (cache[i].c_bno == bno) { 720: copy(b, cache[i].c_block, BSIZE); 721: cache[i].c_time = 0; 722: break; 723: } 724: else 725: cache[i].c_time++; 726: } 727: lseek(fi, bno*BSIZE, 0); 728: if(write(fi, b, BSIZE) != BSIZE) { 729: #ifdef STANDALONE 730: printf("disk write error %D\n", bno); 731: #else 732: fprintf(stderr, "disk write error %ld\n", bno); 733: #endif 734: exit(1); 735: } 736: } 737: 738: dread(bno, buf, cnt) 739: daddr_t bno; 740: char *buf; 741: { 742: register i, j; 743: 744: j = 0; 745: for (i = 0; i < NCACHE; i++) { 746: if (++curcache >= NCACHE) 747: curcache = 0; 748: if (cache[curcache].c_bno == bno) { 749: copy(cache[curcache].c_block, buf, cnt); 750: cache[curcache].c_time = 0; 751: return; 752: } 753: else { 754: cache[curcache].c_time++; 755: if (cache[j].c_time < cache[curcache].c_time) 756: j = curcache; 757: } 758: } 759: 760: lseek(fi, bno*BSIZE, 0); 761: if (read(fi, cache[j].c_block, BSIZE) != BSIZE) { 762: #ifdef STANDALONE 763: printf("read error %D\n", bno); 764: #else 765: printf("read error %ld\n", bno); 766: #endif 767: exit(1); 768: } 769: copy(cache[j].c_block, buf, cnt); 770: cache[j].c_time = 0; 771: cache[j].c_bno = bno; 772: } 773: 774: /* 775: * the inode manpulation routines. Like the system. 776: * 777: * clri zeros the inode 778: */ 779: clri(ip) 780: struct dinode *ip; 781: { 782: int i, *p; 783: i = sizeof(struct dinode)/sizeof(int); 784: p = (int *)ip; 785: do 786: *p++ = 0; 787: while(--i); 788: } 789: 790: /* 791: * itrunc/tloop/bfree free all of the blocks pointed at by the inode 792: */ 793: itrunc(ip) 794: register struct dinode *ip; 795: { 796: register i; 797: daddr_t bn, iaddr[NADDR]; 798: 799: if (ip->di_mode == 0) 800: return; 801: i = ip->di_mode & IFMT; 802: if (i != IFDIR && i != IFREG) 803: return; 804: l3tol(iaddr, ip->di_addr, NADDR); 805: for(i=NADDR-1;i>=0;i--) { 806: bn = iaddr[i]; 807: if(bn == 0) continue; 808: switch(i) { 809: 810: default: 811: bfree(bn); 812: break; 813: 814: case NADDR-3: 815: tloop(bn, 0, 0); 816: break; 817: 818: case NADDR-2: 819: tloop(bn, 1, 0); 820: break; 821: 822: case NADDR-1: 823: tloop(bn, 1, 1); 824: } 825: } 826: ip->di_size = 0; 827: } 828: 829: tloop(bn, f1, f2) 830: daddr_t bn; 831: int f1, f2; 832: { 833: register i; 834: daddr_t nb; 835: union { 836: char data[BSIZE]; 837: daddr_t indir[NINDIR]; 838: } ibuf; 839: 840: dread(bn, ibuf.data, BSIZE); 841: for(i=NINDIR-1;i>=0;i--) { 842: nb = ibuf.indir[i]; 843: if(nb) { 844: if(f1) 845: tloop(nb, f2, 0); 846: else 847: bfree(nb); 848: } 849: } 850: bfree(bn); 851: } 852: 853: bfree(bn) 854: daddr_t bn; 855: { 856: register i; 857: union { 858: char data[BSIZE]; 859: struct fblk frees; 860: } fbuf; 861: 862: if(sblock.s_nfree >= NICFREE) { 863: fbuf.df_nfree = sblock.s_nfree; 864: for(i=0;i<NICFREE;i++) 865: fbuf.df_free[i] = sblock.s_free[i]; 866: sblock.s_nfree = 0; 867: dwrite(bn, fbuf.data); 868: } 869: sblock.s_free[sblock.s_nfree++] = bn; 870: } 871: 872: /* 873: * allocate a block off the free list. 874: */ 875: daddr_t 876: balloc() 877: { 878: daddr_t bno; 879: register i; 880: static char zeroes[BSIZE]; 881: union { 882: char data[BSIZE]; 883: struct fblk frees; 884: } fbuf; 885: 886: if(sblock.s_nfree == 0 || (bno=sblock.s_free[--sblock.s_nfree]) == 0) { 887: #ifdef STANDALONE 888: printf("Out of space\n"); 889: #else 890: fprintf(stderr, "Out of space.\n"); 891: #endif 892: exit(1); 893: } 894: if(sblock.s_nfree == 0) { 895: dread(bno, fbuf.data, BSIZE); 896: sblock.s_nfree = fbuf.df_nfree; 897: for(i=0;i<NICFREE;i++) 898: sblock.s_free[i] = fbuf.df_free[i]; 899: } 900: dwrite(bno, zeroes); 901: return(bno); 902: } 903: 904: /* 905: * map a block number into a block address, ensuring 906: * all of the correct indirect blocks are around. Allocate 907: * the block requested. 908: */ 909: daddr_t 910: bmap(iaddr, bn) 911: daddr_t iaddr[NADDR]; 912: daddr_t bn; 913: { 914: register i; 915: int j, sh; 916: daddr_t nb, nnb; 917: daddr_t indir[NINDIR]; 918: 919: /* 920: * blocks 0..NADDR-4 are direct blocks 921: */ 922: if(bn < NADDR-3) { 923: iaddr[bn] = nb = balloc(); 924: return(nb); 925: } 926: 927: /* 928: * addresses NADDR-3, NADDR-2, and NADDR-1 929: * have single, double, triple indirect blocks. 930: * the first step is to determine 931: * how many levels of indirection. 932: */ 933: sh = 0; 934: nb = 1; 935: bn -= NADDR-3; 936: for(j=3; j>0; j--) { 937: sh += NSHIFT; 938: nb <<= NSHIFT; 939: if(bn < nb) 940: break; 941: bn -= nb; 942: } 943: if(j == 0) { 944: return((daddr_t)0); 945: } 946: 947: /* 948: * fetch the address from the inode 949: */ 950: if((nb = iaddr[NADDR-j]) == 0) { 951: iaddr[NADDR-j] = nb = balloc(); 952: } 953: 954: /* 955: * fetch through the indirect blocks 956: */ 957: for(; j<=3; j++) { 958: dread(nb, (char *)indir, BSIZE); 959: sh -= NSHIFT; 960: i = (bn>>sh) & NMASK; 961: nnb = indir[i]; 962: if(nnb == 0) { 963: nnb = balloc(); 964: indir[i] = nnb; 965: dwrite(nb, (char *)indir); 966: } 967: nb = nnb; 968: } 969: return(nb); 970: } 971: 972: /* 973: * read the tape into buf, then return whether or 974: * or not it is a header block. 975: */ 976: gethead(buf) 977: struct spcl *buf; 978: { 979: readtape((char *)buf); 980: if (buf->c_magic != MAGIC || checksum((int *) buf) == 0) 981: return(0); 982: return(1); 983: } 984: 985: /* 986: * return whether or not the buffer contains a header block 987: */ 988: ishead(buf) 989: struct spcl *buf; 990: { 991: if (buf->c_magic != MAGIC || checksum((int *) buf) == 0) 992: return(0); 993: return(1); 994: } 995: 996: checktype(b, t) 997: struct spcl *b; 998: int t; 999: { 1000: return(b->c_type == t); 1001: } 1002: 1003: 1004: checksum(b) 1005: int *b; 1006: { 1007: register i, j; 1008: 1009: j = BSIZE/sizeof(int); 1010: i = 0; 1011: do 1012: i += *b++; 1013: while (--j); 1014: if (i != CHECKSUM) { 1015: printf("Checksum error %o\n", i); 1016: return(0); 1017: } 1018: return(1); 1019: } 1020: 1021: checkvol(b, t) 1022: struct spcl *b; 1023: int t; 1024: { 1025: if (b->c_volume == t) 1026: return(1); 1027: return(0); 1028: } 1029: 1030: readhdr(b) 1031: struct spcl *b; 1032: { 1033: if (gethead(b) == 0) 1034: return(0); 1035: if (checktype(b, TS_TAPE) == 0) 1036: return(0); 1037: return(1); 1038: } 1039: 1040: /* 1041: * The next routines are called during file extraction to 1042: * put the data into the right form and place. 1043: */ 1044: #ifndef STANDALONE 1045: xtrfile(b, size) 1046: char *b; 1047: long size; 1048: { 1049: write(ofile, b, (int) size); 1050: } 1051: 1052: null() {;} 1053: 1054: skip() 1055: { 1056: lseek(ofile, (long) BSIZE, 1); 1057: } 1058: #endif 1059: 1060: 1061: rstrfile(b, s) 1062: char *b; 1063: long s; 1064: { 1065: daddr_t d; 1066: 1067: d = bmap(taddr, curbno); 1068: dwrite(d, b); 1069: curbno += 1; 1070: } 1071: 1072: rstrskip(b, s) 1073: char *b; 1074: long s; 1075: { 1076: curbno += 1; 1077: } 1078: 1079: #ifndef STANDALONE 1080: putdir(b) 1081: char *b; 1082: { 1083: register struct direct *dp; 1084: register i; 1085: 1086: for (dp = (struct direct *) b, i = 0; i < BSIZE; dp++, i += sizeof(*dp)) { 1087: if (dp->d_ino == 0) 1088: continue; 1089: putent((char *) dp); 1090: } 1091: } 1092: #endif 1093: 1094: /* 1095: * read/write an inode from the disk 1096: */ 1097: getdino(inum, b) 1098: ino_t inum; 1099: struct dinode *b; 1100: { 1101: daddr_t bno; 1102: char buf[BSIZE]; 1103: 1104: bno = (ino - 1)/INOPB; 1105: bno += 2; 1106: dread(bno, buf, BSIZE); 1107: copy(&buf[((inum-1)%INOPB)*sizeof(struct dinode)], (char *) b, sizeof(struct dinode)); 1108: } 1109: 1110: putdino(inum, b) 1111: ino_t inum; 1112: struct dinode *b; 1113: { 1114: daddr_t bno; 1115: char buf[BSIZE]; 1116: 1117: bno = ((ino - 1)/INOPB) + 2; 1118: dread(bno, buf, BSIZE); 1119: copy((char *) b, &buf[((inum-1)%INOPB)*sizeof(struct dinode)], sizeof(struct dinode)); 1120: dwrite(bno, buf); 1121: } 1122: 1123: /* 1124: * read a bit mask from the tape into m. 1125: */ 1126: readbits(m) 1127: short *m; 1128: { 1129: register i; 1130: 1131: i = spcl.c_count; 1132: 1133: while (i--) { 1134: readtape((char *) m); 1135: m += (BSIZE/(MLEN/BITS)); 1136: } 1137: while (gethead(&spcl) == 0) 1138: ; 1139: } 1140: 1141: done() 1142: { 1143: #ifndef STANDALONE 1144: unlink(dirfile); 1145: #endif 1146: exit(0); 1147: }