1: #include <stdio.h> 2: 3: 4: /* old <sys/param.h> */ 5: #include <sys/types.h> 6: #define BSIZE 512 7: 8: /* old <sys/inode.h> */ 9: /* modes */ 10: #define IFMT 0170000 /* type of file */ 11: #define IFDIR 0040000 /* directory */ 12: #define IFCHR 0020000 /* character special */ 13: #define IFMPC 0030000 /* multiplexed char special */ 14: #define IFBLK 0060000 /* block special */ 15: #define IFMPB 0070000 /* multiplexed block special */ 16: #define IFREG 0100000 /* regular */ 17: #define IFLNK 0120000 /* symbolic link */ 18: #define IFQUOT 0140000 /* quota */ 19: #define ISUID 04000 /* set user id on execution */ 20: #define ISGID 02000 /* set group id on execution */ 21: #define ISVTX 01000 /* save swapped text even after use */ 22: #define IREAD 0400 /* read, write, execute permissions */ 23: #define IWRITE 0200 24: #define IEXEC 0100 25: 26: /* old <sys/ino.h> */ 27: /* 28: * Inode structure as it appears on 29: * a disk block. 30: */ 31: struct dinode 32: { 33: u_short di_mode; /* mode and type of file */ 34: short di_nlink; /* number of links to file */ 35: short di_uid; /* owner's user id */ 36: short di_gid; /* owner's group id */ 37: off_t di_size; /* number of bytes in file */ 38: char di_addr[40]; /* disk block addresses */ 39: time_t di_atime; /* time last accessed */ 40: time_t di_mtime; /* time last modified */ 41: time_t di_ctime; /* time created */ 42: }; 43: 44: #define INOPB 8 /* 8 inodes per block */ 45: /* 46: * 39 of the address bytes are used; 47: * 13 addresses of 3 bytes each. 48: */ 49: 50: /* old <sys/dir.h> */ 51: #define DIRSIZ 14 52: 53: struct direct 54: { 55: ino_t d_ino; 56: char d_name[DIRSIZ]; 57: }; 58: 59: /* old <dumprestor.h> */ 60: #define NTREC 20 61: #define MLEN 16 62: #define MSIZ 4096 63: 64: #define TS_TAPE 1 65: #define TS_INODE 2 66: #define TS_BITS 3 67: #define TS_ADDR 4 68: #define TS_END 5 69: #define TS_CLRI 6 70: #define MAGIC (int)60011 71: #define CHECKSUM (int)84446 72: struct spcl 73: { 74: int c_type; 75: time_t c_date; 76: time_t c_ddate; 77: int c_volume; 78: daddr_t c_tapea; 79: ino_t c_inumber; 80: int c_magic; 81: int c_checksum; 82: struct dinode c_dinode; 83: int c_count; 84: char c_addr[BSIZE]; 85: } spcl; 86: 87: struct idates 88: { 89: char id_name[16]; 90: char id_incno; 91: time_t id_ddate; 92: }; 93: 94: /* end of old includes */ 95: 96: #ifdef NONSEPARATE 97: #define MAXINO 1000 98: #else 99: #define MAXINO 2500 100: #endif 101: #define BITS 8 102: #define MAXXTR 60 103: #define NCACHE 3 104: 105: 106: #define MWORD(m,i) (m[(unsigned)(i-1)/MLEN]) 107: #define MBIT(i) (1<<((unsigned)(i-1)%MLEN)) 108: #define BIS(i,w) (MWORD(w,i) |= MBIT(i)) 109: #define BIC(i,w) (MWORD(w,i) &= ~MBIT(i)) 110: #define BIT(i,w) (MWORD(w,i) & MBIT(i)) 111: 112: int mt; 113: char tapename[] = "/dev/rmt8"; 114: char *magtape = tapename; 115: 116: daddr_t seekpt; 117: int ofile; 118: FILE *df; 119: char dirfile[] = "/tmp/rstXXXXXX"; 120: 121: struct { 122: ino_t t_ino; 123: daddr_t t_seekpt; 124: } inotab[MAXINO]; 125: int ipos; 126: 127: #define ONTAPE 1 128: #define XTRACTD 2 129: #define XINUSE 4 130: 131: short dumpmap[MSIZ]; 132: short clrimap[MSIZ]; 133: 134: 135: int bct = NTREC+1; 136: char tbf[NTREC*BSIZE]; 137: 138: char prebuf[512]; 139: 140: int volno; 141: 142: main(argc, argv) 143: char *argv[]; 144: { 145: extern char *ctime(); 146: 147: mktemp(dirfile); 148: argv++; 149: if (argc>=3 && *argv[0] == 'f') 150: magtape = *++argv; 151: df = fopen(dirfile, "w"); 152: if (df == NULL) { 153: printf("dumpdir: %s - cannot create directory temporary\n", dirfile); 154: exit(1); 155: } 156: 157: if ((mt = open(magtape, 0)) < 0) { 158: printf("%s: cannot open tape\n", magtape); 159: exit(1); 160: } 161: if (readhdr(&spcl) == 0) { 162: printf("Tape is not a dump tape\n"); 163: exit(1); 164: } 165: printf("Dump date: %s", ctime(&spcl.c_date)); 166: printf("Dumped from: %s", ctime(&spcl.c_ddate)); 167: if (checkvol(&spcl, 1) == 0) { 168: printf("Tape is not volume 1 of the dump\n"); 169: exit(1); 170: } 171: pass1(); /* This sets the various maps on the way by */ 172: freopen(dirfile, "r", df); 173: strcpy(prebuf, "/"); 174: printem(prebuf, (ino_t) 2); 175: exit(0); 176: } 177: i = 0; 178: /* 179: * Read the tape, bulding up a directory structure for extraction 180: * by name 181: */ 182: pass1() 183: { 184: register i; 185: struct dinode *ip; 186: int putdir(), null(); 187: 188: while (gethead(&spcl) == 0) { 189: printf("Can't find directory header!\n"); 190: } 191: for (;;) { 192: if (checktype(&spcl, TS_BITS) == 1) { 193: readbits(dumpmap); 194: continue; 195: } 196: if (checktype(&spcl, TS_CLRI) == 1) { 197: readbits(clrimap); 198: continue; 199: } 200: if (checktype(&spcl, TS_INODE) == 0) { 201: finish: 202: flsh(); 203: close(mt); 204: return; 205: } 206: ip = &spcl.c_dinode; 207: i = ip->di_mode & IFMT; 208: if (i != IFDIR) { 209: goto finish; 210: } 211: inotab[ipos].t_ino = spcl.c_inumber; 212: inotab[ipos++].t_seekpt = seekpt; 213: getfile(spcl.c_inumber, putdir, null, spcl.c_dinode.di_size); 214: putent("\000\000/"); 215: } 216: } 217: 218: printem(prefix, inum) 219: char *prefix; 220: ino_t inum; 221: { 222: struct direct dir; 223: register int i; 224: 225: for (i = 0; i < MAXINO; i++) 226: if (inotab[i].t_ino == inum) { 227: goto found; 228: } 229: printf("PANIC - can't find directory %d\n", inum); 230: return; 231: found: 232: mseek(inotab[i].t_seekpt); 233: for (;;) { 234: getent((char *) &dir); 235: if (direq(dir.d_name, "/")) 236: return; 237: if (search(dir.d_ino) != 0 && direq(dir.d_name, ".") == 0 && direq(dir.d_name, "..") == 0) { 238: int len; 239: FILE *tdf; 240: 241: tdf = df; 242: df = fopen(dirfile, "r"); 243: len = strlen(prefix); 244: strncat(prefix, dir.d_name, sizeof(dir.d_name)); 245: strcat(prefix, "/"); 246: printem(prefix, dir.d_ino); 247: prefix[len] = '\0'; 248: fclose(df); 249: df = tdf; 250: } 251: else 252: if (BIT(dir.d_ino, dumpmap)) 253: printf("%5d %s%-.14s\n", dir.d_ino, prefix, dir.d_name); 254: } 255: } 256: /* 257: * Do the file extraction, calling the supplied functions 258: * with the blocks 259: */ 260: getfile(n, f1, f2, size) 261: ino_t n; 262: int (*f2)(), (*f1)(); 263: long size; 264: { 265: register i; 266: struct spcl addrblock; 267: char buf[BSIZE]; 268: 269: addrblock = spcl; 270: goto start; 271: for (;;) { 272: if (gethead(&addrblock) == 0) { 273: printf("Missing address (header) block\n"); 274: goto eloop; 275: } 276: if (checktype(&addrblock, TS_ADDR) == 0) { 277: spcl = addrblock; 278: return; 279: } 280: start: 281: for (i = 0; i < addrblock.c_count; i++) { 282: if (addrblock.c_addr[i]) { 283: readtape(buf); 284: (*f1)(buf, size > BSIZE ? (long) BSIZE : size); 285: } 286: else { 287: clearbuf(buf); 288: (*f2)(buf, size > BSIZE ? (long) BSIZE : size); 289: } 290: if ((size -= BSIZE) <= 0) { 291: eloop: 292: while (gethead(&spcl) == 0) 293: ; 294: if (checktype(&spcl, TS_ADDR) == 1) 295: goto eloop; 296: return; 297: } 298: } 299: } 300: } 301: 302: /* 303: * Do the tape i\/o, dealling with volume changes 304: * etc.. 305: */ 306: readtape(b) 307: char *b; 308: { 309: register i; 310: struct spcl tmpbuf; 311: 312: if (bct >= NTREC) { 313: for (i = 0; i < NTREC; i++) 314: ((struct spcl *)&tbf[i*BSIZE])->c_magic = 0; 315: bct = 0; 316: if ((i = read(mt, tbf, NTREC*BSIZE)) < 0) { 317: exit(1); 318: } 319: if (i == 0) { 320: bct = NTREC + 1; 321: volno++; 322: loop: 323: flsht(); 324: close(mt); 325: printf("Mount volume %d\n", volno); 326: while (getchar() != '\n') 327: ; 328: if ((mt = open(magtape, 0)) == -1) { 329: printf("Cannot open tape!\n"); 330: } 331: if (readhdr(&tmpbuf) == 0) { 332: printf("Not a dump tape.Try again\n"); 333: goto loop; 334: } 335: if (checkvol(&tmpbuf, volno) == 0) { 336: printf("Wrong tape. Try again\n"); 337: goto loop; 338: } 339: readtape(b); 340: return; 341: } 342: } 343: copy(&tbf[(bct++*BSIZE)], b, BSIZE); 344: } 345: 346: flsht() 347: { 348: bct = NTREC+1; 349: } 350: 351: copy(f, t, s) 352: register char *f, *t; 353: { 354: register i; 355: 356: i = s; 357: do 358: *t++ = *f++; 359: while (--i); 360: } 361: 362: clearbuf(cp) 363: register char *cp; 364: { 365: register i; 366: 367: i = BSIZE; 368: do 369: *cp++ = 0; 370: while (--i); 371: } 372: 373: /* 374: * Put and get the directory entries from the compressed 375: * directory file 376: */ 377: putent(cp) 378: char *cp; 379: { 380: register i; 381: 382: for (i = 0; i < sizeof(ino_t); i++) 383: writec(*cp++); 384: for (i = 0; i < DIRSIZ; i++) { 385: writec(*cp); 386: if (*cp++ == 0) 387: return; 388: } 389: return; 390: } 391: 392: getent(bf) 393: register char *bf; 394: { 395: register i; 396: 397: for (i = 0; i < sizeof(ino_t); i++) 398: *bf++ = readc(); 399: for (i = 0; i < DIRSIZ; i++) 400: if ((*bf++ = readc()) == 0) 401: return; 402: return; 403: } 404: 405: /* 406: * read/write te directory file 407: */ 408: writec(c) 409: char c; 410: { 411: seekpt++; 412: fwrite(&c, 1, 1, df); 413: } 414: 415: readc() 416: { 417: char c; 418: 419: fread(&c, 1, 1, df); 420: return(c); 421: } 422: 423: mseek(pt) 424: daddr_t pt; 425: { 426: fseek(df, pt, 0); 427: } 428: 429: flsh() 430: { 431: fflush(df); 432: } 433: 434: /* 435: * search the directory inode ino 436: * looking for entry cp 437: */ 438: search(inum) 439: ino_t inum; 440: { 441: register low, high, probe; 442: 443: low = 0; 444: high = ipos-1; 445: 446: while (low != high) { 447: probe = (high - low + 1)/2 + low; 448: /* 449: printf("low = %d, high = %d, probe = %d, ino = %d, inum = %d\n", low, high, probe, inum, inotab[probe].t_ino); 450: */ 451: if (inum >= inotab[probe].t_ino) 452: low = probe; 453: else 454: high = probe - 1; 455: } 456: return(inum == inotab[low].t_ino); 457: } 458: 459: direq(s1, s2) 460: register char *s1, *s2; 461: { 462: register i; 463: 464: for (i = 0; i < DIRSIZ; i++) 465: if (*s1++ == *s2) { 466: if (*s2++ == 0) 467: return(1); 468: } else 469: return(0); 470: return(1); 471: } 472: 473: /* 474: * read the tape into buf, then return whether or 475: * or not it is a header block. 476: */ 477: gethead(buf) 478: struct spcl *buf; 479: { 480: readtape((char *)buf); 481: if (buf->c_magic != MAGIC || checksum((int *) buf) == 0) 482: return(0); 483: return(1); 484: } 485: 486: /* 487: * return whether or not the buffer contains a header block 488: */ 489: checktype(b, t) 490: struct spcl *b; 491: int t; 492: { 493: return(b->c_type == t); 494: } 495: 496: 497: checksum(b) 498: int *b; 499: { 500: register i, j; 501: 502: j = BSIZE/sizeof(int); 503: i = 0; 504: do 505: i += *b++; 506: while (--j); 507: if (i != CHECKSUM) { 508: printf("Checksum error %o\n", i); 509: return(0); 510: } 511: return(1); 512: } 513: 514: checkvol(b, t) 515: struct spcl *b; 516: int t; 517: { 518: if (b->c_volume == t) 519: return(1); 520: return(0); 521: } 522: 523: readhdr(b) 524: struct spcl *b; 525: { 526: if (gethead(b) == 0) 527: return(0); 528: if (checktype(b, TS_TAPE) == 0) 529: return(0); 530: return(1); 531: } 532: 533: putdir(b) 534: char *b; 535: { 536: register struct direct *dp; 537: register i; 538: 539: for (dp = (struct direct *) b, i = 0; i < BSIZE; dp++, i += sizeof(*dp)) { 540: if (dp->d_ino == 0) 541: continue; 542: putent((char *) dp); 543: } 544: } 545: 546: /* 547: * read a bit mask from the tape into m. 548: */ 549: readbits(m) 550: short *m; 551: { 552: register i; 553: 554: i = spcl.c_count; 555: 556: while (i--) { 557: readtape((char *) m); 558: m += (BSIZE/(MLEN/BITS)); 559: } 560: while (gethead(&spcl) == 0) 561: ; 562: } 563: 564: null() { ; }