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