1: #define MAXINO 3000 2: #define BITS 8 3: #define MAXXTR 60 4: #define NCACHE 3 5: 6: #include <stdio.h> 7: #include <sys/param.h> 8: #include <sys/inode.h> 9: #include <sys/ino.h> 10: #include <sys/fblk.h> 11: #include <sys/filsys.h> 12: #include <sys/dir.h> 13: #include <dumprestor.h> 14: 15: #define MWORD(m,i) (m[(unsigned)(i-1)/MLEN]) 16: #define MBIT(i) (1<<((unsigned)(i-1)%MLEN)) 17: #define BIS(i,w) (MWORD(w,i) |= MBIT(i)) 18: #define BIC(i,w) (MWORD(w,i) &= ~MBIT(i)) 19: #define BIT(i,w) (MWORD(w,i) & MBIT(i)) 20: 21: int mt; 22: char tapename[] = "/dev/rmt1"; 23: char *magtape = tapename; 24: 25: daddr_t seekpt; 26: int ofile; 27: FILE *df; 28: char dirfile[] = "rstXXXXXX"; 29: 30: struct { 31: ino_t t_ino; 32: daddr_t t_seekpt; 33: } inotab[MAXINO]; 34: int ipos; 35: 36: #define ONTAPE 1 37: #define XTRACTD 2 38: #define XINUSE 4 39: 40: short dumpmap[MSIZ]; 41: short clrimap[MSIZ]; 42: 43: 44: int bct = NTREC+1; 45: char tbf[NTREC*BSIZE]; 46: 47: char prebuf[512]; 48: 49: int volno; 50: 51: main(argc, argv) 52: char *argv[]; 53: { 54: extern char *ctime(); 55: 56: mktemp(dirfile); 57: argv++; 58: if (argc>=3 && *argv[0] == 'f') 59: magtape = *++argv; 60: df = fopen(dirfile, "w"); 61: if (df == NULL) { 62: printf("dumpdir: %s - cannot create directory temporary\n", dirfile); 63: exit(1); 64: } 65: 66: if ((mt = open(magtape, 0)) < 0) { 67: printf("%s: cannot open tape\n", magtape); 68: exit(1); 69: } 70: if (readhdr(&spcl) == 0) { 71: printf("Tape is not a dump tape\n"); 72: exit(1); 73: } 74: printf("Dump date: %s", ctime(&spcl.c_date)); 75: printf("Dumped from: %s", ctime(&spcl.c_ddate)); 76: if (checkvol(&spcl, 1) == 0) { 77: printf("Tape is not volume 1 of the dump\n"); 78: exit(1); 79: } 80: pass1(); /* This sets the various maps on the way by */ 81: freopen(dirfile, "r", df); 82: strcpy(prebuf, "/"); 83: printem(prebuf, (ino_t) 2); 84: exit(0); 85: } 86: i = 0; 87: /* 88: * Read the tape, bulding up a directory structure for extraction 89: * by name 90: */ 91: pass1() 92: { 93: register i; 94: struct dinode *ip; 95: int putdir(), null(); 96: 97: while (gethead(&spcl) == 0) { 98: printf("Can't find directory header!\n"); 99: } 100: for (;;) { 101: if (checktype(&spcl, TS_BITS) == 1) { 102: readbits(dumpmap); 103: continue; 104: } 105: if (checktype(&spcl, TS_CLRI) == 1) { 106: readbits(clrimap); 107: continue; 108: } 109: if (checktype(&spcl, TS_INODE) == 0) { 110: finish: 111: flsh(); 112: close(mt); 113: return; 114: } 115: ip = &spcl.c_dinode; 116: i = ip->di_mode & IFMT; 117: if (i != IFDIR) { 118: goto finish; 119: } 120: inotab[ipos].t_ino = spcl.c_inumber; 121: inotab[ipos++].t_seekpt = seekpt; 122: getfile(spcl.c_inumber, putdir, null, spcl.c_dinode.di_size); 123: putent("\000\000/"); 124: } 125: } 126: 127: printem(prefix, inum) 128: char *prefix; 129: ino_t inum; 130: { 131: struct direct dir; 132: register int i; 133: 134: for (i = 0; i < MAXINO; i++) 135: if (inotab[i].t_ino == inum) { 136: goto found; 137: } 138: printf("PANIC - can't find directory %d\n", inum); 139: return; 140: found: 141: mseek(inotab[i].t_seekpt); 142: for (;;) { 143: getent((char *) &dir); 144: if (direq(dir.d_name, "/")) 145: return; 146: if (search(dir.d_ino) != 0 && direq(dir.d_name, ".") == 0 && direq(dir.d_name, "..") == 0) { 147: int len; 148: FILE *tdf; 149: 150: tdf = df; 151: df = fopen(dirfile, "r"); 152: len = strlen(prefix); 153: strncat(prefix, dir.d_name, sizeof(dir.d_name)); 154: strcat(prefix, "/"); 155: printem(prefix, dir.d_ino); 156: prefix[len] = '\0'; 157: fclose(df); 158: df = tdf; 159: } 160: else 161: if (BIT(dir.d_ino, dumpmap)) 162: printf("%5d %s%-.14s\n", dir.d_ino, prefix, dir.d_name); 163: } 164: } 165: /* 166: * Do the file extraction, calling the supplied functions 167: * with the blocks 168: */ 169: getfile(n, f1, f2, size) 170: ino_t n; 171: int (*f2)(), (*f1)(); 172: long size; 173: { 174: register i; 175: struct spcl addrblock; 176: char buf[BSIZE]; 177: 178: addrblock = spcl; 179: goto start; 180: for (;;) { 181: if (gethead(&addrblock) == 0) { 182: printf("Missing address (header) block\n"); 183: goto eloop; 184: } 185: if (checktype(&addrblock, TS_ADDR) == 0) { 186: spcl = addrblock; 187: return; 188: } 189: start: 190: for (i = 0; i < addrblock.c_count; i++) { 191: if (addrblock.c_addr[i]) { 192: readtape(buf); 193: (*f1)(buf, size > BSIZE ? (long) BSIZE : size); 194: } 195: else { 196: clearbuf(buf); 197: (*f2)(buf, size > BSIZE ? (long) BSIZE : size); 198: } 199: if ((size -= BSIZE) <= 0) { 200: eloop: 201: while (gethead(&spcl) == 0) 202: ; 203: if (checktype(&spcl, TS_ADDR) == 1) 204: goto eloop; 205: return; 206: } 207: } 208: } 209: } 210: 211: /* 212: * Do the tape i\/o, dealling with volume changes 213: * etc.. 214: */ 215: readtape(b) 216: char *b; 217: { 218: register i; 219: struct spcl tmpbuf; 220: 221: if (bct >= NTREC) { 222: for (i = 0; i < NTREC; i++) 223: ((struct spcl *)&tbf[i*BSIZE])->c_magic = 0; 224: bct = 0; 225: if ((i = read(mt, tbf, NTREC*BSIZE)) < 0) { 226: exit(1); 227: } 228: if (i == 0) { 229: bct = NTREC + 1; 230: volno++; 231: loop: 232: flsht(); 233: close(mt); 234: printf("Mount volume %d\n", volno); 235: while (getchar() != '\n') 236: ; 237: if ((mt = open(magtape, 0)) == -1) { 238: printf("Cannot open tape!\n"); 239: } 240: if (readhdr(&tmpbuf) == 0) { 241: printf("Not a dump tape.Try again\n"); 242: goto loop; 243: } 244: if (checkvol(&tmpbuf, volno) == 0) { 245: printf("Wrong tape. Try again\n"); 246: goto loop; 247: } 248: readtape(b); 249: return; 250: } 251: } 252: copy(&tbf[(bct++*BSIZE)], b, BSIZE); 253: } 254: 255: flsht() 256: { 257: bct = NTREC+1; 258: } 259: 260: copy(f, t, s) 261: register char *f, *t; 262: { 263: register i; 264: 265: i = s; 266: do 267: *t++ = *f++; 268: while (--i); 269: } 270: 271: clearbuf(cp) 272: register char *cp; 273: { 274: register i; 275: 276: i = BSIZE; 277: do 278: *cp++ = 0; 279: while (--i); 280: } 281: 282: /* 283: * Put and get the directory entries from the compressed 284: * directory file 285: */ 286: putent(cp) 287: char *cp; 288: { 289: register i; 290: 291: for (i = 0; i < sizeof(ino_t); i++) 292: writec(*cp++); 293: for (i = 0; i < DIRSIZ; i++) { 294: writec(*cp); 295: if (*cp++ == 0) 296: return; 297: } 298: return; 299: } 300: 301: getent(bf) 302: register char *bf; 303: { 304: register i; 305: 306: for (i = 0; i < sizeof(ino_t); i++) 307: *bf++ = readc(); 308: for (i = 0; i < DIRSIZ; i++) 309: if ((*bf++ = readc()) == 0) 310: return; 311: return; 312: } 313: 314: /* 315: * read/write te directory file 316: */ 317: writec(c) 318: char c; 319: { 320: seekpt++; 321: fwrite(&c, 1, 1, df); 322: } 323: 324: readc() 325: { 326: char c; 327: 328: fread(&c, 1, 1, df); 329: return(c); 330: } 331: 332: mseek(pt) 333: daddr_t pt; 334: { 335: fseek(df, pt, 0); 336: } 337: 338: flsh() 339: { 340: fflush(df); 341: } 342: 343: /* 344: * search the directory inode ino 345: * looking for entry cp 346: */ 347: search(inum) 348: ino_t inum; 349: { 350: register low, high, probe; 351: 352: low = 0; 353: high = ipos-1; 354: 355: while (low != high) { 356: probe = (high - low + 1)/2 + low; 357: /* 358: printf("low = %d, high = %d, probe = %d, ino = %d, inum = %d\n", low, high, probe, inum, inotab[probe].t_ino); 359: */ 360: if (inum >= inotab[probe].t_ino) 361: low = probe; 362: else 363: high = probe - 1; 364: } 365: return(inum == inotab[low].t_ino); 366: } 367: 368: direq(s1, s2) 369: register char *s1, *s2; 370: { 371: register i; 372: 373: for (i = 0; i < DIRSIZ; i++) 374: if (*s1++ == *s2) { 375: if (*s2++ == 0) 376: return(1); 377: } else 378: return(0); 379: return(1); 380: } 381: 382: /* 383: * read the tape into buf, then return whether or 384: * or not it is a header block. 385: */ 386: gethead(buf) 387: struct spcl *buf; 388: { 389: readtape((char *)buf); 390: if (buf->c_magic != MAGIC || checksum((int *) buf) == 0) 391: return(0); 392: return(1); 393: } 394: 395: /* 396: * return whether or not the buffer contains a header block 397: */ 398: checktype(b, t) 399: struct spcl *b; 400: int t; 401: { 402: return(b->c_type == t); 403: } 404: 405: 406: checksum(b) 407: int *b; 408: { 409: register i, j; 410: 411: j = BSIZE/sizeof(int); 412: i = 0; 413: do 414: i += *b++; 415: while (--j); 416: if (i != CHECKSUM) { 417: printf("Checksum error %o\n", i); 418: return(0); 419: } 420: return(1); 421: } 422: 423: checkvol(b, t) 424: struct spcl *b; 425: int t; 426: { 427: if (b->c_volume == t) 428: return(1); 429: return(0); 430: } 431: 432: readhdr(b) 433: struct spcl *b; 434: { 435: if (gethead(b) == 0) 436: return(0); 437: if (checktype(b, TS_TAPE) == 0) 438: return(0); 439: return(1); 440: } 441: 442: putdir(b) 443: char *b; 444: { 445: register struct direct *dp; 446: register i; 447: 448: for (dp = (struct direct *) b, i = 0; i < BSIZE; dp++, i += sizeof(*dp)) { 449: if (dp->d_ino == 0) 450: continue; 451: putent((char *) dp); 452: } 453: } 454: 455: /* 456: * read a bit mask from the tape into m. 457: */ 458: readbits(m) 459: short *m; 460: { 461: register i; 462: 463: i = spcl.c_count; 464: 465: while (i--) { 466: readtape((char *) m); 467: m += (BSIZE/(MLEN/BITS)); 468: } 469: while (gethead(&spcl) == 0) 470: ; 471: } 472: 473: null() { ; }