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