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