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