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