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