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