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