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