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