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