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