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