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