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