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