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