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