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