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