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