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