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