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