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