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