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