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