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