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