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