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