|
|
1.1.1.2 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ 1.1 root 6: 1.1.1.2 ! root 7: #ifndef lint ! 8: static char sccsid[] = "@(#)tape.c 5.3 (Berkeley) 7/13/85"; ! 9: #endif not lint 1.1 root 10: 11: #include "restore.h" 12: #include <dumprestor.h> 13: #include <sys/ioctl.h> 14: #include <sys/mtio.h> 15: #include <sys/file.h> 16: #include <setjmp.h> 17: #include <sys/stat.h> 18: 19: static long fssize = MAXBSIZE; 20: static int mt = -1; 21: static int pipein = 0; 1.1.1.2 ! root 22: static char magtape[BUFSIZ]; ! 23: static int bct; ! 24: static char *tbf; 1.1 root 25: static union u_spcl endoftapemark; 26: static long blksread; 27: static long tapesread; 28: static jmp_buf restart; 29: static int gettingfile = 0; /* restart has a valid frame */ 30: 31: static int ofile; 32: static char *map; 33: static char lnkbuf[MAXPATHLEN + 1]; 34: static int pathlen; 35: 36: /* 37: * Set up an input source 38: */ 39: setinput(source) 40: char *source; 41: { 42: #ifdef RRESTORE 1.1.1.2 ! root 43: char *host, *tape; 1.1 root 44: #endif RRESTORE 45: 1.1.1.2 ! root 46: flsht(); ! 47: if (bflag) ! 48: newtapebuf(ntrec); ! 49: else ! 50: newtapebuf(NTREC > HIGHDENSITYTREC ? NTREC : HIGHDENSITYTREC); 1.1 root 51: terminal = stdin; 52: #ifdef RRESTORE 53: host = source; 1.1.1.2 ! root 54: tape = index(host, ':'); ! 55: if (tape == 0) { 1.1 root 56: nohost: 57: msg("need keyletter ``f'' and device ``host:tape''\n"); 58: done(1); 59: } 1.1.1.2 ! root 60: *tape++ = '\0'; ! 61: (void) strcpy(magtape, tape); 1.1 root 62: if (rmthost(host) == 0) 63: done(1); 64: setuid(getuid()); /* no longer need or want root privileges */ 65: #else 66: if (strcmp(source, "-") == 0) { 67: /* 68: * Since input is coming from a pipe we must establish 69: * our own connection to the terminal. 70: */ 71: terminal = fopen("/dev/tty", "r"); 72: if (terminal == NULL) { 1.1.1.2 ! root 73: perror("Cannot open(\"/dev/tty\")"); ! 74: terminal = fopen("/dev/null", "r"); ! 75: if (terminal == NULL) { ! 76: perror("Cannot open(\"/dev/null\")"); ! 77: done(1); ! 78: } 1.1 root 79: } 80: pipein++; 81: } 1.1.1.2 ! root 82: (void) strcpy(magtape, source); 1.1 root 83: #endif RRESTORE 84: } 85: 1.1.1.2 ! root 86: newtapebuf(size) ! 87: long size; ! 88: { ! 89: static tbfsize = -1; ! 90: ! 91: ntrec = size; ! 92: if (size <= tbfsize) ! 93: return; ! 94: if (tbf != NULL) ! 95: free(tbf); ! 96: tbf = (char *)malloc(size * TP_BSIZE); ! 97: if (tbf == NULL) { ! 98: fprintf(stderr, "Cannot allocate space for tape buffer\n"); ! 99: done(1); ! 100: } ! 101: tbfsize = size; ! 102: } ! 103: 1.1 root 104: /* 105: * Verify that the tape drive can be accessed and 106: * that it actually is a dump tape. 107: */ 108: setup() 109: { 110: int i, j, *ip; 111: struct stat stbuf; 112: extern char *ctime(); 113: extern int xtrmap(), xtrmapskip(); 114: 115: vprintf(stdout, "Verify tape and initialize maps\n"); 116: #ifdef RRESTORE 117: if ((mt = rmtopen(magtape, 0)) < 0) 118: #else 119: if (pipein) 120: mt = 0; 121: else if ((mt = open(magtape, 0)) < 0) 122: #endif 123: { 124: perror(magtape); 125: done(1); 126: } 127: volno = 1; 128: setdumpnum(); 129: flsht(); 1.1.1.2 ! root 130: if (!pipein && !bflag) ! 131: findtapeblksize(); 1.1 root 132: if (gethead(&spcl) == FAIL) { 133: bct--; /* push back this block */ 134: cvtflag++; 135: if (gethead(&spcl) == FAIL) { 136: fprintf(stderr, "Tape is not a dump tape\n"); 137: done(1); 138: } 139: fprintf(stderr, "Converting to new file system format.\n"); 140: } 141: if (pipein) { 142: endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : NFS_MAGIC; 143: endoftapemark.s_spcl.c_type = TS_END; 144: ip = (int *)&endoftapemark; 145: j = sizeof(union u_spcl) / sizeof(int); 146: i = 0; 147: do 148: i += *ip++; 149: while (--j); 150: endoftapemark.s_spcl.c_checksum = CHECKSUM - i; 151: } 1.1.1.2 ! root 152: if (vflag || command == 't' || command == 'T') { ! 153: fprintf(stdout, "Dump date: %s", ctime(&spcl.c_date)); ! 154: if (spcl.c_ddate == 0) ! 155: fprintf(stdout, "Dumped from: the epoch\n"); ! 156: else ! 157: fprintf(stdout, "Dumped from: %s", ctime(&spcl.c_ddate)); 1.1 root 158: } 1.1.1.2 ! root 159: if (command == 'T') ! 160: return; 1.1 root 161: dumptime = spcl.c_ddate; 162: dumpdate = spcl.c_date; 163: if (stat(".", &stbuf) < 0) { 164: perror("cannot stat ."); 165: done(1); 166: } 1.1.1.2 ! root 167: if (stbuf.st_blksize > 0 && stbuf.st_blksize <= MAXBSIZE) ! 168: fssize = stbuf.st_blksize; ! 169: if (((fssize - 1) & fssize) != 0) { 1.1 root 170: fprintf(stderr, "bad block size %d\n", fssize); 171: done(1); 172: } 173: if (checkvol(&spcl, (long)1) == FAIL) { 174: fprintf(stderr, "Tape is not volume 1 of the dump\n"); 175: done(1); 176: } 177: if (readhdr(&spcl) == FAIL) 178: panic("no header after volume mark!\n"); 179: findinode(&spcl, 1); 180: if (checktype(&spcl, TS_CLRI) == FAIL) { 181: fprintf(stderr, "Cannot find file removal list\n"); 182: done(1); 183: } 184: maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1; 185: dprintf(stdout, "maxino = %d\n", maxino); 186: map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); 187: if (map == (char *)NIL) 188: panic("no memory for file removal list\n"); 189: clrimap = map; 190: curfile.action = USING; 191: getfile(xtrmap, xtrmapskip); 192: if (checktype(&spcl, TS_BITS) == FAIL) { 193: fprintf(stderr, "Cannot find file dump list\n"); 194: done(1); 195: } 196: map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); 197: if (map == (char *)NULL) 198: panic("no memory for file dump list\n"); 199: dumpmap = map; 200: curfile.action = USING; 201: getfile(xtrmap, xtrmapskip); 202: } 203: 204: /* 205: * Prompt user to load a new dump volume. 206: * "Nextvol" is the next suggested volume to use. 207: * This suggested volume is enforced when doing full 208: * or incremental restores, but can be overrridden by 209: * the user when only extracting a subset of the files. 210: */ 211: getvol(nextvol) 212: long nextvol; 213: { 214: long newvol; 215: long savecnt, i; 216: union u_spcl tmpspcl; 217: # define tmpbuf tmpspcl.s_spcl 218: 1.1.1.2 ! root 219: if (nextvol == 1) { 1.1 root 220: tapesread = 0; 1.1.1.2 ! root 221: gettingfile = 0; ! 222: } 1.1 root 223: if (pipein) { 224: if (nextvol != 1) 225: panic("Changing volumes on pipe input?\n"); 226: if (volno == 1) 227: return; 228: goto gethdr; 229: } 230: savecnt = blksread; 231: again: 232: if (pipein) 233: done(1); /* pipes do not get a second chance */ 234: if (command == 'R' || command == 'r' || curfile.action != SKIP) 235: newvol = nextvol; 236: else 237: newvol = 0; 238: while (newvol <= 0) { 239: if (tapesread == 0) { 240: fprintf(stderr, "%s%s%s%s%s", 241: "You have not read any tapes yet.\n", 242: "Unless you know which volume your", 243: " file(s) are on you should start\n", 244: "with the last volume and work", 245: " towards towards the first.\n"); 246: } else { 247: fprintf(stderr, "You have read volumes"); 248: strcpy(tbf, ": "); 249: for (i = 1; i < 32; i++) 250: if (tapesread & (1 << i)) { 251: fprintf(stderr, "%s%d", tbf, i); 252: strcpy(tbf, ", "); 253: } 254: fprintf(stderr, "\n"); 255: } 256: do { 257: fprintf(stderr, "Specify next volume #: "); 258: (void) fflush(stderr); 259: (void) fgets(tbf, BUFSIZ, terminal); 260: } while (!feof(terminal) && tbf[0] == '\n'); 261: if (feof(terminal)) 262: done(1); 263: newvol = atoi(tbf); 264: if (newvol <= 0) { 265: fprintf(stderr, 266: "Volume numbers are positive numerics\n"); 267: } 268: } 269: if (newvol == volno) { 270: tapesread |= 1 << volno; 271: return; 272: } 273: closemt(); 1.1.1.2 ! root 274: fprintf(stderr, "Mount tape volume %d\n", newvol); ! 275: fprintf(stderr, "then enter tape name (default: %s) ", magtape); 1.1 root 276: (void) fflush(stderr); 1.1.1.2 ! root 277: (void) fgets(tbf, BUFSIZ, terminal); ! 278: if (feof(terminal)) ! 279: done(1); ! 280: if (tbf[0] != '\n') { ! 281: (void) strcpy(magtape, tbf); ! 282: magtape[strlen(magtape) - 1] = '\0'; ! 283: } 1.1 root 284: #ifdef RRESTORE 285: if ((mt = rmtopen(magtape, 0)) == -1) 286: #else 287: if ((mt = open(magtape, 0)) == -1) 288: #endif 289: { 1.1.1.2 ! root 290: fprintf(stderr, "Cannot open %s\n", magtape); ! 291: volno = -1; 1.1 root 292: goto again; 293: } 294: gethdr: 295: volno = newvol; 296: setdumpnum(); 297: flsht(); 298: if (readhdr(&tmpbuf) == FAIL) { 299: fprintf(stderr, "tape is not dump tape\n"); 300: volno = 0; 301: goto again; 302: } 303: if (checkvol(&tmpbuf, volno) == FAIL) { 304: fprintf(stderr, "Wrong volume (%d)\n", tmpbuf.c_volume); 305: volno = 0; 306: goto again; 307: } 308: if (tmpbuf.c_date != dumpdate || tmpbuf.c_ddate != dumptime) { 309: fprintf(stderr, "Wrong dump date\n\tgot: %s", 310: ctime(&tmpbuf.c_date)); 311: fprintf(stderr, "\twanted: %s", ctime(&dumpdate)); 312: volno = 0; 313: goto again; 314: } 315: tapesread |= 1 << volno; 316: blksread = savecnt; 317: if (curfile.action == USING) { 318: if (volno == 1) 319: panic("active file into volume 1\n"); 320: return; 321: } 322: (void) gethead(&spcl); 323: findinode(&spcl, curfile.action == UNKNOWN ? 1 : 0); 324: if (gettingfile) { 325: gettingfile = 0; 326: longjmp(restart, 1); 327: } 328: } 329: 330: /* 331: * handle multiple dumps per tape by skipping forward to the 332: * appropriate one. 333: */ 334: setdumpnum() 335: { 336: struct mtop tcom; 337: 338: if (dumpnum == 1 || volno != 1) 339: return; 340: if (pipein) { 341: fprintf(stderr, "Cannot have multiple dumps on pipe input\n"); 342: done(1); 343: } 344: tcom.mt_op = MTFSF; 345: tcom.mt_count = dumpnum - 1; 346: #ifdef RRESTORE 347: rmtioctl(MTFSF, dumpnum - 1); 348: #else 349: if (ioctl(mt, (int)MTIOCTOP, (char *)&tcom) < 0) 350: perror("ioctl MTFSF"); 351: #endif 352: } 353: 354: extractfile(name) 355: char *name; 356: { 357: int mode; 358: time_t timep[2]; 359: struct entry *ep; 360: extern int xtrlnkfile(), xtrlnkskip(); 361: extern int xtrfile(), xtrskip(); 362: 363: curfile.name = name; 364: curfile.action = USING; 365: timep[0] = curfile.dip->di_atime; 366: timep[1] = curfile.dip->di_mtime; 367: mode = curfile.dip->di_mode; 368: switch (mode & IFMT) { 369: 370: default: 371: fprintf(stderr, "%s: unknown file mode 0%o\n", name, mode); 372: skipfile(); 373: return (FAIL); 374: 375: case IFDIR: 376: if (mflag) { 377: ep = lookupname(name); 378: if (ep == NIL || ep->e_flags & EXTRACT) 379: panic("unextracted directory %s\n", name); 380: skipfile(); 381: return (GOOD); 382: } 383: vprintf(stdout, "extract file %s\n", name); 384: return (genliteraldir(name, curfile.ino)); 385: 386: case IFLNK: 387: lnkbuf[0] = '\0'; 388: pathlen = 0; 389: getfile(xtrlnkfile, xtrlnkskip); 390: if (pathlen == 0) { 391: vprintf(stdout, 392: "%s: zero length symbolic link (ignored)\n", name); 1.1.1.2 ! root 393: return (GOOD); ! 394: } ! 395: return (linkit(lnkbuf, name, SYMLINK)); 1.1 root 396: 397: case IFCHR: 398: case IFBLK: 399: vprintf(stdout, "extract special file %s\n", name); 400: if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) { 401: fprintf(stderr, "%s: ", name); 402: (void) fflush(stderr); 403: perror("cannot create special file"); 404: skipfile(); 405: return (FAIL); 406: } 407: (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid); 408: (void) chmod(name, mode); 409: skipfile(); 410: utime(name, timep); 411: return (GOOD); 412: 413: case IFREG: 414: vprintf(stdout, "extract file %s\n", name); 415: if ((ofile = creat(name, 0666)) < 0) { 416: fprintf(stderr, "%s: ", name); 417: (void) fflush(stderr); 418: perror("cannot create file"); 419: skipfile(); 420: return (FAIL); 421: } 422: (void) fchown(ofile, curfile.dip->di_uid, curfile.dip->di_gid); 423: (void) fchmod(ofile, mode); 424: getfile(xtrfile, xtrskip); 425: (void) close(ofile); 426: utime(name, timep); 427: return (GOOD); 428: } 429: /* NOTREACHED */ 430: } 431: 432: /* 433: * skip over bit maps on the tape 434: */ 435: skipmaps() 436: { 437: 438: while (checktype(&spcl, TS_CLRI) == GOOD || 439: checktype(&spcl, TS_BITS) == GOOD) 440: skipfile(); 441: } 442: 443: /* 444: * skip over a file on the tape 445: */ 446: skipfile() 447: { 448: extern int null(); 449: 450: curfile.action = SKIP; 451: getfile(null, null); 452: } 453: 454: /* 455: * Do the file extraction, calling the supplied functions 456: * with the blocks 457: */ 458: getfile(f1, f2) 459: int (*f2)(), (*f1)(); 460: { 461: register int i; 462: int curblk = 0; 463: off_t size = spcl.c_dinode.di_size; 464: static char clearedbuf[MAXBSIZE]; 465: char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE]; 1.1.1.2 ! root 466: char junk[TP_BSIZE]; 1.1 root 467: 468: if (checktype(&spcl, TS_END) == GOOD) 469: panic("ran off end of tape\n"); 470: if (ishead(&spcl) == FAIL) 471: panic("not at beginning of a file\n"); 472: if (!gettingfile && setjmp(restart) != 0) 473: return; 474: gettingfile++; 475: loop: 476: for (i = 0; i < spcl.c_count; i++) { 477: if (spcl.c_addr[i]) { 478: readtape(&buf[curblk++][0]); 479: if (curblk == fssize / TP_BSIZE) { 480: (*f1)(buf, size > TP_BSIZE ? 481: (long) (fssize) : 482: (curblk - 1) * TP_BSIZE + size); 483: curblk = 0; 484: } 485: } else { 486: if (curblk > 0) { 487: (*f1)(buf, size > TP_BSIZE ? 488: (long) (curblk * TP_BSIZE) : 489: (curblk - 1) * TP_BSIZE + size); 490: curblk = 0; 491: } 492: (*f2)(clearedbuf, size > TP_BSIZE ? 493: (long) TP_BSIZE : size); 494: } 1.1.1.2 ! root 495: if ((size -= TP_BSIZE) <= 0) { ! 496: for (i++; i < spcl.c_count; i++) ! 497: if (spcl.c_addr[i]) ! 498: readtape(junk); 1.1 root 499: break; 1.1.1.2 ! root 500: } 1.1 root 501: } 502: if (readhdr(&spcl) == GOOD && size > 0) { 503: if (checktype(&spcl, TS_ADDR) == GOOD) 504: goto loop; 505: dprintf(stdout, "Missing address (header) block for %s\n", 506: curfile.name); 507: } 508: if (curblk > 0) 509: (*f1)(buf, (curblk * TP_BSIZE) + size); 510: findinode(&spcl, 1); 511: gettingfile = 0; 512: } 513: 514: /* 515: * The next routines are called during file extraction to 516: * put the data into the right form and place. 517: */ 518: xtrfile(buf, size) 519: char *buf; 520: long size; 521: { 522: 523: if (write(ofile, buf, (int) size) == -1) { 524: fprintf(stderr, "write error extracting inode %d, name %s\n", 525: curfile.ino, curfile.name); 526: perror("write"); 527: done(1); 528: } 529: } 530: 531: xtrskip(buf, size) 532: char *buf; 533: long size; 534: { 535: 536: #ifdef lint 537: buf = buf; 538: #endif 539: if (lseek(ofile, size, 1) == (long)-1) { 540: fprintf(stderr, "seek error extracting inode %d, name %s\n", 541: curfile.ino, curfile.name); 542: perror("lseek"); 543: done(1); 544: } 545: } 546: 547: xtrlnkfile(buf, size) 548: char *buf; 549: long size; 550: { 551: 552: pathlen += size; 553: if (pathlen > MAXPATHLEN) { 554: fprintf(stderr, "symbolic link name: %s->%s%s; too long %d\n", 555: curfile.name, lnkbuf, buf, pathlen); 556: done(1); 557: } 558: (void) strcat(lnkbuf, buf); 559: } 560: 561: xtrlnkskip(buf, size) 562: char *buf; 563: long size; 564: { 565: 566: #ifdef lint 567: buf = buf, size = size; 568: #endif 569: fprintf(stderr, "unallocated block in symbolic link %s\n", 570: curfile.name); 571: done(1); 572: } 573: 574: xtrmap(buf, size) 575: char *buf; 576: long size; 577: { 578: 579: bcopy(buf, map, size); 580: map += size; 581: } 582: 583: xtrmapskip(buf, size) 584: char *buf; 585: long size; 586: { 587: 588: #ifdef lint 589: buf = buf; 590: #endif 591: panic("hole in map\n"); 592: map += size; 593: } 594: 595: null() {;} 596: 597: /* 598: * Do the tape i/o, dealing with volume changes 599: * etc.. 600: */ 601: readtape(b) 602: char *b; 603: { 604: register long i; 605: long rd, newvol; 606: int cnt; 607: 1.1.1.2 ! root 608: if (bct < ntrec) { ! 609: bcopy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE); ! 610: blksread++; ! 611: return; ! 612: } ! 613: for (i = 0; i < ntrec; i++) ! 614: ((struct s_spcl *)&tbf[i*TP_BSIZE])->c_magic = 0; ! 615: bct = 0; ! 616: cnt = ntrec*TP_BSIZE; ! 617: rd = 0; ! 618: getmore: 1.1 root 619: #ifdef RRESTORE 1.1.1.2 ! root 620: i = rmtread(&tbf[rd], cnt); 1.1 root 621: #else 1.1.1.2 ! root 622: i = read(mt, &tbf[rd], cnt); 1.1 root 623: #endif 1.1.1.2 ! root 624: if (i > 0 && i != ntrec*TP_BSIZE) { ! 625: if (pipein) { 1.1 root 626: rd += i; 627: cnt -= i; 628: if (cnt > 0) 629: goto getmore; 630: i = rd; 1.1.1.2 ! root 631: } else { ! 632: if (i % TP_BSIZE != 0) ! 633: panic("partial block read: %d should be %d\n", ! 634: i, ntrec * TP_BSIZE); ! 635: bcopy((char *)&endoftapemark, &tbf[i], ! 636: (long)TP_BSIZE); 1.1 root 637: } 1.1.1.2 ! root 638: } ! 639: if (i < 0) { ! 640: fprintf(stderr, "Tape read error while "); ! 641: switch (curfile.action) { ! 642: default: ! 643: fprintf(stderr, "trying to set up tape\n"); ! 644: break; ! 645: case UNKNOWN: ! 646: fprintf(stderr, "trying to resyncronize\n"); ! 647: break; ! 648: case USING: ! 649: fprintf(stderr, "restoring %s\n", curfile.name); ! 650: break; ! 651: case SKIP: ! 652: fprintf(stderr, "skipping over inode %d\n", ! 653: curfile.ino); ! 654: break; ! 655: } ! 656: if (!yflag && !reply("continue")) ! 657: done(1); ! 658: i = ntrec*TP_BSIZE; ! 659: bzero(tbf, i); 1.1 root 660: #ifdef RRESTORE 1.1.1.2 ! root 661: if (rmtseek(i, 1) < 0) 1.1 root 662: #else 1.1.1.2 ! root 663: if (lseek(mt, i, 1) == (long)-1) 1.1 root 664: #endif 1.1.1.2 ! root 665: { ! 666: perror("continuation failed"); ! 667: done(1); 1.1 root 668: } 1.1.1.2 ! root 669: } ! 670: if (i == 0) { ! 671: if (!pipein) { 1.1 root 672: newvol = volno + 1; 673: volno = 0; 674: getvol(newvol); 675: readtape(b); 676: return; 677: } 1.1.1.2 ! root 678: if (rd % TP_BSIZE != 0) ! 679: panic("partial block read: %d should be %d\n", ! 680: rd, ntrec * TP_BSIZE); ! 681: bcopy((char *)&endoftapemark, &tbf[rd], (long)TP_BSIZE); 1.1 root 682: } 683: bcopy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE); 684: blksread++; 685: } 686: 1.1.1.2 ! root 687: findtapeblksize() ! 688: { ! 689: register long i; ! 690: ! 691: for (i = 0; i < ntrec; i++) ! 692: ((struct s_spcl *)&tbf[i * TP_BSIZE])->c_magic = 0; ! 693: bct = 0; ! 694: #ifdef RRESTORE ! 695: i = rmtread(tbf, ntrec * TP_BSIZE); ! 696: #else ! 697: i = read(mt, tbf, ntrec * TP_BSIZE); ! 698: #endif ! 699: if (i <= 0) { ! 700: perror("Tape read error"); ! 701: done(1); ! 702: } ! 703: if (i % TP_BSIZE != 0) { ! 704: fprintf(stderr, "Tape block size (%d) %s (%d)\n", ! 705: i, "is not a multiple of dump block size", TP_BSIZE); ! 706: done(1); ! 707: } ! 708: ntrec = i / TP_BSIZE; ! 709: vprintf(stdout, "Tape block size is %d\n", ntrec); ! 710: } ! 711: 1.1 root 712: flsht() 713: { 714: 1.1.1.2 ! root 715: bct = ntrec+1; 1.1 root 716: } 717: 718: closemt() 719: { 720: if (mt < 0) 721: return; 722: #ifdef RRESTORE 723: rmtclose(); 724: #else 725: (void) close(mt); 726: #endif 727: } 728: 729: checkvol(b, t) 730: struct s_spcl *b; 731: long t; 732: { 733: 734: if (b->c_volume != t) 735: return(FAIL); 736: return(GOOD); 737: } 738: 739: readhdr(b) 740: struct s_spcl *b; 741: { 742: 743: if (gethead(b) == FAIL) { 744: dprintf(stdout, "readhdr fails at %d blocks\n", blksread); 745: return(FAIL); 746: } 747: return(GOOD); 748: } 749: 750: /* 751: * read the tape into buf, then return whether or 752: * or not it is a header block. 753: */ 754: gethead(buf) 755: struct s_spcl *buf; 756: { 757: long i; 758: union u_ospcl { 759: char dummy[TP_BSIZE]; 760: struct s_ospcl { 761: long c_type; 762: long c_date; 763: long c_ddate; 764: long c_volume; 765: long c_tapea; 766: u_short c_inumber; 767: long c_magic; 768: long c_checksum; 769: struct odinode { 770: unsigned short odi_mode; 771: u_short odi_nlink; 772: u_short odi_uid; 773: u_short odi_gid; 774: long odi_size; 775: long odi_rdev; 776: char odi_addr[36]; 777: long odi_atime; 778: long odi_mtime; 779: long odi_ctime; 780: } c_dinode; 781: long c_count; 782: char c_addr[256]; 783: } s_ospcl; 784: } u_ospcl; 785: 786: if (!cvtflag) { 787: readtape((char *)buf); 788: if (buf->c_magic != NFS_MAGIC || checksum((int *)buf) == FAIL) 789: return(FAIL); 790: goto good; 791: } 792: readtape((char *)(&u_ospcl.s_ospcl)); 793: bzero((char *)buf, (long)TP_BSIZE); 794: buf->c_type = u_ospcl.s_ospcl.c_type; 795: buf->c_date = u_ospcl.s_ospcl.c_date; 796: buf->c_ddate = u_ospcl.s_ospcl.c_ddate; 797: buf->c_volume = u_ospcl.s_ospcl.c_volume; 798: buf->c_tapea = u_ospcl.s_ospcl.c_tapea; 799: buf->c_inumber = u_ospcl.s_ospcl.c_inumber; 800: buf->c_checksum = u_ospcl.s_ospcl.c_checksum; 801: buf->c_magic = u_ospcl.s_ospcl.c_magic; 802: buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode; 803: buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink; 804: buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid; 805: buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid; 806: buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size; 807: buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev; 808: buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime; 809: buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime; 810: buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime; 811: buf->c_count = u_ospcl.s_ospcl.c_count; 812: bcopy(u_ospcl.s_ospcl.c_addr, buf->c_addr, (long)256); 813: if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC || 814: checksum((int *)(&u_ospcl.s_ospcl)) == FAIL) 815: return(FAIL); 816: buf->c_magic = NFS_MAGIC; 817: 818: good: 819: switch (buf->c_type) { 820: 821: case TS_CLRI: 822: case TS_BITS: 823: /* 824: * Have to patch up missing information in bit map headers 825: */ 826: buf->c_inumber = 0; 827: buf->c_dinode.di_size = buf->c_count * TP_BSIZE; 828: for (i = 0; i < buf->c_count; i++) 829: buf->c_addr[i]++; 830: break; 831: 832: case TS_TAPE: 833: case TS_END: 834: buf->c_inumber = 0; 835: break; 836: 837: case TS_INODE: 838: case TS_ADDR: 839: break; 840: 841: default: 842: panic("gethead: unknown inode type %d\n", buf->c_type); 843: break; 844: } 845: if (dflag) 846: accthdr(buf); 847: return(GOOD); 848: } 849: 850: /* 851: * Check that a header is where it belongs and predict the next header 852: */ 853: accthdr(header) 854: struct s_spcl *header; 855: { 856: static ino_t previno = 0x7fffffff; 857: static int prevtype; 858: static long predict; 859: long blks, i; 860: 861: if (header->c_type == TS_TAPE) { 862: fprintf(stderr, "Volume header\n"); 863: return; 864: } 865: if (previno == 0x7fffffff) 866: goto newcalc; 867: switch (prevtype) { 868: case TS_BITS: 869: fprintf(stderr, "Dump mask header"); 870: break; 871: case TS_CLRI: 872: fprintf(stderr, "Remove mask header"); 873: break; 874: case TS_INODE: 875: fprintf(stderr, "File header, ino %d", previno); 876: break; 877: case TS_ADDR: 878: fprintf(stderr, "File continuation header, ino %d", previno); 879: break; 880: case TS_END: 881: fprintf(stderr, "End of tape header"); 882: break; 883: } 884: if (predict != blksread - 1) 885: fprintf(stderr, "; predicted %d blocks, got %d blocks", 886: predict, blksread - 1); 887: fprintf(stderr, "\n"); 888: newcalc: 889: blks = 0; 890: if (header->c_type != TS_END) 891: for (i = 0; i < header->c_count; i++) 892: if (header->c_addr[i] != 0) 893: blks++; 894: predict = blks; 895: blksread = 0; 896: prevtype = header->c_type; 897: previno = header->c_inumber; 898: } 899: 900: /* 901: * Find an inode header. 902: * Complain if had to skip, and complain is set. 903: */ 904: findinode(header, complain) 905: struct s_spcl *header; 906: int complain; 907: { 908: static long skipcnt = 0; 909: 910: curfile.name = "<name unknown>"; 911: curfile.action = UNKNOWN; 912: curfile.dip = (struct dinode *)NIL; 913: curfile.ino = 0; 914: if (ishead(header) == FAIL) { 915: skipcnt++; 916: while (gethead(header) == FAIL) 917: skipcnt++; 918: } 919: for (;;) { 920: if (checktype(header, TS_INODE) == GOOD) { 921: curfile.dip = &header->c_dinode; 922: curfile.ino = header->c_inumber; 923: break; 924: } 925: if (checktype(header, TS_END) == GOOD) { 926: curfile.ino = maxino; 927: break; 928: } 929: if (checktype(header, TS_CLRI) == GOOD) { 930: curfile.name = "<file removal list>"; 931: break; 932: } 933: if (checktype(header, TS_BITS) == GOOD) { 934: curfile.name = "<file dump list>"; 935: break; 936: } 937: while (gethead(header) == FAIL) 938: skipcnt++; 939: } 940: if (skipcnt > 0 && complain) 941: fprintf(stderr, "resync restore, skipped %d blocks\n", skipcnt); 942: skipcnt = 0; 943: } 944: 945: /* 946: * return whether or not the buffer contains a header block 947: */ 948: ishead(buf) 949: struct s_spcl *buf; 950: { 951: 952: if (buf->c_magic != NFS_MAGIC) 953: return(FAIL); 954: return(GOOD); 955: } 956: 957: checktype(b, t) 958: struct s_spcl *b; 959: int t; 960: { 961: 962: if (b->c_type != t) 963: return(FAIL); 964: return(GOOD); 965: } 966: 967: checksum(b) 968: register int *b; 969: { 970: register int i, j; 971: 972: j = sizeof(union u_spcl) / sizeof(int); 973: i = 0; 974: do 975: i += *b++; 976: while (--j); 977: if (i != CHECKSUM) { 978: fprintf(stderr, "Checksum error %o, inode %d file %s\n", i, 979: curfile.ino, curfile.name); 980: return(FAIL); 981: } 982: return(GOOD); 983: } 984: 985: #ifdef RRESTORE 986: /* VARARGS1 */ 987: msg(cp, a1, a2, a3) 988: char *cp; 989: { 990: 991: fprintf(stderr, cp, a1, a2, a3); 992: } 993: #endif RRESTORE
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.