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