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 * 4. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #ifndef lint 36 #if 0 37 static char sccsid[] = "@(#)tape.c 8.9 (Berkeley) 5/1/95"; 38 #endif 39 #endif /* not lint */ 40 41 #include <sys/cdefs.h> 42 __FBSDID("$FreeBSD$"); 43 44 #include <sys/param.h> 45 #include <sys/file.h> 46 #include <sys/mtio.h> 47 #include <sys/stat.h> 48 #include <sys/time.h> 49 #include <sys/extattr.h> 50 #include <sys/acl.h> 51 52 #include <ufs/ufs/extattr.h> 53 #include <ufs/ufs/dinode.h> 54 #include <protocols/dumprestore.h> 55 56 #include <errno.h> 57 #include <limits.h> 58 #include <paths.h> 59 #include <setjmp.h> 60 #include <stdint.h> 61 #include <stdio.h> 62 #include <stdlib.h> 63 #include <string.h> 64 #include <time.h> 65 #include <timeconv.h> 66 #include <unistd.h> 67 68 #include "restore.h" 69 #include "extern.h" 70 71 static long fssize = MAXBSIZE; 72 static int mt = -1; 73 static int pipein = 0; 74 static int pipecmdin = 0; 75 static FILE *popenfp = NULL; 76 static char *magtape; 77 static int blkcnt; 78 static int numtrec; 79 static char *tapebuf; 80 static union u_spcl endoftapemark; 81 static long byteslide = 0; 82 static long blksread; /* blocks read since last header */ 83 static int64_t tapeaddr = 0; /* current TP_BSIZE tape record */ 84 static long tapesread; 85 static jmp_buf restart; 86 static int gettingfile = 0; /* restart has a valid frame */ 87 static char *host = NULL; 88 static int readmapflag; 89 90 static int ofile; 91 static char *map; 92 static char lnkbuf[MAXPATHLEN + 1]; 93 static int pathlen; 94 95 int Bcvt; /* Swap Bytes */ 96 int oldinofmt; /* FreeBSD 1 inode format needs cvt */ 97 98 #define FLUSHTAPEBUF() blkcnt = ntrec + 1 99 100 char *namespace_names[] = EXTATTR_NAMESPACE_NAMES; 101 102 static void accthdr(struct s_spcl *); 103 static int checksum(int *); 104 static void findinode(struct s_spcl *); 105 static void findtapeblksize(void); 106 static char *setupextattr(int); 107 static void xtrattr(char *, long); 108 static void set_extattr_link(char *, void *, int); 109 static void set_extattr_fd(int, char *, void *, int); 110 static int gethead(struct s_spcl *); 111 static void readtape(char *); 112 static void setdumpnum(void); 113 static u_long swabl(u_long); 114 static u_char *swablong(u_char *, int); 115 static u_char *swabshort(u_char *, int); 116 static void terminateinput(void); 117 static void xtrfile(char *, long); 118 static void xtrlnkfile(char *, long); 119 static void xtrlnkskip(char *, long); 120 static void xtrmap(char *, long); 121 static void xtrmapskip(char *, long); 122 static void xtrskip(char *, long); 123 124 /* 125 * Set up an input source 126 */ 127 void 128 setinput(char *source, int ispipecommand) 129 { 130 FLUSHTAPEBUF(); 131 if (bflag) 132 newtapebuf(ntrec); 133 else 134 newtapebuf(NTREC > HIGHDENSITYTREC ? NTREC : HIGHDENSITYTREC); 135 terminal = stdin; 136 137 if (ispipecommand) 138 pipecmdin++; 139 else 140 #ifdef RRESTORE 141 if (strchr(source, ':')) { 142 host = source; 143 source = strchr(host, ':'); 144 *source++ = '\0'; 145 if (rmthost(host) == 0) 146 done(1); 147 } else 148 #endif 149 if (strcmp(source, "-") == 0) { 150 /* 151 * Since input is coming from a pipe we must establish 152 * our own connection to the terminal. 153 */ 154 terminal = fopen(_PATH_TTY, "r"); 155 if (terminal == NULL) { 156 (void)fprintf(stderr, "cannot open %s: %s\n", 157 _PATH_TTY, strerror(errno)); 158 terminal = fopen(_PATH_DEVNULL, "r"); 159 if (terminal == NULL) { 160 (void)fprintf(stderr, "cannot open %s: %s\n", 161 _PATH_DEVNULL, strerror(errno)); 162 done(1); 163 } 164 } 165 pipein++; 166 } 167 /* no longer need or want root privileges */ 168 if (setuid(getuid()) != 0) { 169 fprintf(stderr, "setuid failed\n"); 170 done(1); 171 } 172 magtape = strdup(source); 173 if (magtape == NULL) { 174 fprintf(stderr, "Cannot allocate space for magtape buffer\n"); 175 done(1); 176 } 177 } 178 179 void 180 newtapebuf(long size) 181 { 182 static int tapebufsize = -1; 183 184 ntrec = size; 185 if (size <= tapebufsize) 186 return; 187 if (tapebuf != NULL) 188 free(tapebuf - TP_BSIZE); 189 tapebuf = malloc((size+1) * TP_BSIZE); 190 if (tapebuf == NULL) { 191 fprintf(stderr, "Cannot allocate space for tape buffer\n"); 192 done(1); 193 } 194 tapebuf += TP_BSIZE; 195 tapebufsize = size; 196 } 197 198 /* 199 * Verify that the tape drive can be accessed and 200 * that it actually is a dump tape. 201 */ 202 void 203 setup(void) 204 { 205 int i, j, *ip; 206 struct stat stbuf; 207 208 vprintf(stdout, "Verify tape and initialize maps\n"); 209 if (pipecmdin) { 210 if (setenv("RESTORE_VOLUME", "1", 1) == -1) { 211 fprintf(stderr, "Cannot set $RESTORE_VOLUME: %s\n", 212 strerror(errno)); 213 done(1); 214 } 215 popenfp = popen(magtape, "r"); 216 mt = popenfp ? fileno(popenfp) : -1; 217 } else 218 #ifdef RRESTORE 219 if (host) 220 mt = rmtopen(magtape, 0); 221 else 222 #endif 223 if (pipein) 224 mt = 0; 225 else 226 mt = open(magtape, O_RDONLY, 0); 227 if (mt < 0) { 228 fprintf(stderr, "%s: %s\n", magtape, strerror(errno)); 229 done(1); 230 } 231 volno = 1; 232 setdumpnum(); 233 FLUSHTAPEBUF(); 234 if (!pipein && !pipecmdin && !bflag) 235 findtapeblksize(); 236 if (gethead(&spcl) == FAIL) { 237 fprintf(stderr, "Tape is not a dump tape\n"); 238 done(1); 239 } 240 if (pipein) { 241 endoftapemark.s_spcl.c_magic = FS_UFS2_MAGIC; 242 endoftapemark.s_spcl.c_type = TS_END; 243 ip = (int *)&endoftapemark; 244 j = sizeof(union u_spcl) / sizeof(int); 245 i = 0; 246 do 247 i += *ip++; 248 while (--j); 249 endoftapemark.s_spcl.c_checksum = CHECKSUM - i; 250 } 251 if (vflag || command == 't') 252 printdumpinfo(); 253 dumptime = _time64_to_time(spcl.c_ddate); 254 dumpdate = _time64_to_time(spcl.c_date); 255 if (stat(".", &stbuf) < 0) { 256 fprintf(stderr, "cannot stat .: %s\n", strerror(errno)); 257 done(1); 258 } 259 if (stbuf.st_blksize > 0 && stbuf.st_blksize < TP_BSIZE ) 260 fssize = TP_BSIZE; 261 if (stbuf.st_blksize >= TP_BSIZE && stbuf.st_blksize <= MAXBSIZE) 262 fssize = stbuf.st_blksize; 263 if (((TP_BSIZE - 1) & stbuf.st_blksize) != 0) { 264 fprintf(stderr, "Warning: filesystem with non-multiple-of-%d " 265 "blocksize (%d);\n", TP_BSIZE, stbuf.st_blksize); 266 fssize = roundup(fssize, TP_BSIZE); 267 fprintf(stderr, "\twriting using blocksize %ld\n", fssize); 268 } 269 if (spcl.c_volume != 1) { 270 fprintf(stderr, "Tape is not volume 1 of the dump\n"); 271 done(1); 272 } 273 if (gethead(&spcl) == FAIL) { 274 dprintf(stdout, "header read failed at %ld blocks\n", blksread); 275 panic("no header after volume mark!\n"); 276 } 277 findinode(&spcl); 278 if (spcl.c_type != TS_CLRI) { 279 fprintf(stderr, "Cannot find file removal list\n"); 280 done(1); 281 } 282 maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1; 283 dprintf(stdout, "maxino = %ju\n", (uintmax_t)maxino); 284 map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); 285 if (map == NULL) 286 panic("no memory for active inode map\n"); 287 usedinomap = map; 288 curfile.action = USING; 289 getfile(xtrmap, xtrmapskip, xtrmapskip); 290 if (spcl.c_type != TS_BITS) { 291 fprintf(stderr, "Cannot find file dump list\n"); 292 done(1); 293 } 294 map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); 295 if (map == (char *)NULL) 296 panic("no memory for file dump list\n"); 297 dumpmap = map; 298 curfile.action = USING; 299 getfile(xtrmap, xtrmapskip, xtrmapskip); 300 /* 301 * If there may be whiteout entries on the tape, pretend that the 302 * whiteout inode exists, so that the whiteout entries can be 303 * extracted. 304 */ 305 SETINO(WINO, dumpmap); 306 /* 'r' restores don't call getvol() for tape 1, so mark it as read. */ 307 if (command == 'r') 308 tapesread = 1; 309 } 310 311 /* 312 * Prompt user to load a new dump volume. 313 * "Nextvol" is the next suggested volume to use. 314 * This suggested volume is enforced when doing full 315 * or incremental restores, but can be overridden by 316 * the user when only extracting a subset of the files. 317 */ 318 void 319 getvol(long nextvol) 320 { 321 int64_t prevtapea; 322 long i, newvol, savecnt; 323 union u_spcl tmpspcl; 324 # define tmpbuf tmpspcl.s_spcl 325 char buf[TP_BSIZE]; 326 327 if (nextvol == 1) { 328 tapesread = 0; 329 gettingfile = 0; 330 } 331 prevtapea = tapeaddr; 332 savecnt = blksread; 333 if (pipein) { 334 if (nextvol != 1) { 335 panic("Changing volumes on pipe input?\n"); 336 /* Avoid looping if we couldn't ask the user. */ 337 if (yflag || ferror(terminal) || feof(terminal)) 338 done(1); 339 } 340 if (volno == 1) 341 return; 342 goto gethdr; 343 } 344 again: 345 if (pipein) 346 done(1); /* pipes do not get a second chance */ 347 if (command == 'R' || command == 'r' || curfile.action != SKIP) 348 newvol = nextvol; 349 else 350 newvol = 0; 351 while (newvol <= 0) { 352 if (tapesread == 0) { 353 fprintf(stderr, "%s%s%s%s%s%s%s", 354 "You have not read any tapes yet.\n", 355 "If you are extracting just a few files,", 356 " start with the last volume\n", 357 "and work towards the first; restore", 358 " can quickly skip tapes that\n", 359 "have no further files to extract.", 360 " Otherwise, begin with volume 1.\n"); 361 } else { 362 fprintf(stderr, "You have read volumes"); 363 strcpy(buf, ": "); 364 for (i = 0; i < 32; i++) 365 if (tapesread & (1 << i)) { 366 fprintf(stderr, "%s%ld", buf, i + 1); 367 strcpy(buf, ", "); 368 } 369 fprintf(stderr, "\n"); 370 } 371 do { 372 fprintf(stderr, "Specify next volume #: "); 373 (void) fflush(stderr); 374 if (fgets(buf, BUFSIZ, terminal) == NULL) 375 done(1); 376 } while (buf[0] == '\n'); 377 newvol = atoi(buf); 378 if (newvol <= 0) { 379 fprintf(stderr, 380 "Volume numbers are positive numerics\n"); 381 } 382 } 383 if (newvol == volno) { 384 tapesread |= 1 << (volno - 1); 385 return; 386 } 387 closemt(); 388 fprintf(stderr, "Mount tape volume %ld\n", newvol); 389 fprintf(stderr, "Enter ``none'' if there are no more tapes\n"); 390 fprintf(stderr, "otherwise enter tape name (default: %s) ", magtape); 391 (void) fflush(stderr); 392 if (fgets(buf, BUFSIZ, terminal) == NULL) 393 done(1); 394 if (!strcmp(buf, "none\n")) { 395 terminateinput(); 396 return; 397 } 398 if (buf[0] != '\n') { 399 (void) strcpy(magtape, buf); 400 magtape[strlen(magtape) - 1] = '\0'; 401 } 402 if (pipecmdin) { 403 char volno[sizeof("2147483647")]; 404 405 (void)sprintf(volno, "%ld", newvol); 406 if (setenv("RESTORE_VOLUME", volno, 1) == -1) { 407 fprintf(stderr, "Cannot set $RESTORE_VOLUME: %s\n", 408 strerror(errno)); 409 done(1); 410 } 411 popenfp = popen(magtape, "r"); 412 mt = popenfp ? fileno(popenfp) : -1; 413 } else 414 #ifdef RRESTORE 415 if (host) 416 mt = rmtopen(magtape, 0); 417 else 418 #endif 419 mt = open(magtape, O_RDONLY, 0); 420 421 if (mt == -1) { 422 fprintf(stderr, "Cannot open %s\n", magtape); 423 volno = -1; 424 goto again; 425 } 426 gethdr: 427 volno = newvol; 428 setdumpnum(); 429 FLUSHTAPEBUF(); 430 if (gethead(&tmpbuf) == FAIL) { 431 dprintf(stdout, "header read failed at %ld blocks\n", blksread); 432 fprintf(stderr, "tape is not dump tape\n"); 433 volno = 0; 434 goto again; 435 } 436 if (tmpbuf.c_volume != volno) { 437 fprintf(stderr, "Wrong volume (%jd)\n", 438 (intmax_t)tmpbuf.c_volume); 439 volno = 0; 440 goto again; 441 } 442 if (_time64_to_time(tmpbuf.c_date) != dumpdate || 443 _time64_to_time(tmpbuf.c_ddate) != dumptime) { 444 time_t t = _time64_to_time(tmpbuf.c_date); 445 fprintf(stderr, "Wrong dump date\n\tgot: %s", ctime(&t)); 446 fprintf(stderr, "\twanted: %s", ctime(&dumpdate)); 447 volno = 0; 448 goto again; 449 } 450 tapesread |= 1 << (volno - 1); 451 blksread = savecnt; 452 /* 453 * If continuing from the previous volume, skip over any 454 * blocks read already at the end of the previous volume. 455 * 456 * If coming to this volume at random, skip to the beginning 457 * of the next record. 458 */ 459 dprintf(stdout, "last rec %jd, tape starts with %jd\n", 460 (intmax_t)prevtapea, (intmax_t)tmpbuf.c_tapea); 461 if (tmpbuf.c_type == TS_TAPE) { 462 if (curfile.action != USING) { 463 /* 464 * XXX Dump incorrectly sets c_count to 1 in the 465 * volume header of the first tape, so ignore 466 * c_count when volno == 1. 467 */ 468 if (volno != 1) 469 for (i = tmpbuf.c_count; i > 0; i--) 470 readtape(buf); 471 } else if (tmpbuf.c_tapea <= prevtapea) { 472 /* 473 * Normally the value of c_tapea in the volume 474 * header is the record number of the header itself. 475 * However in the volume header following an EOT- 476 * terminated tape, it is the record number of the 477 * first continuation data block (dump bug?). 478 * 479 * The next record we want is `prevtapea + 1'. 480 */ 481 i = prevtapea + 1 - tmpbuf.c_tapea; 482 dprintf(stderr, "Skipping %ld duplicate record%s.\n", 483 i, i > 1 ? "s" : ""); 484 while (--i >= 0) 485 readtape(buf); 486 } 487 } 488 if (curfile.action == USING) { 489 if (volno == 1) 490 panic("active file into volume 1\n"); 491 return; 492 } 493 (void) gethead(&spcl); 494 findinode(&spcl); 495 if (gettingfile) { 496 gettingfile = 0; 497 longjmp(restart, 1); 498 } 499 } 500 501 /* 502 * Handle unexpected EOF. 503 */ 504 static void 505 terminateinput(void) 506 { 507 508 if (gettingfile && curfile.action == USING) { 509 printf("Warning: %s %s\n", 510 "End-of-input encountered while extracting", curfile.name); 511 } 512 curfile.name = "<name unknown>"; 513 curfile.action = UNKNOWN; 514 curfile.mode = 0; 515 curfile.ino = maxino; 516 if (gettingfile) { 517 gettingfile = 0; 518 longjmp(restart, 1); 519 } 520 } 521 522 /* 523 * handle multiple dumps per tape by skipping forward to the 524 * appropriate one. 525 */ 526 static void 527 setdumpnum(void) 528 { 529 struct mtop tcom; 530 531 if (dumpnum == 1 || volno != 1) 532 return; 533 if (pipein) { 534 fprintf(stderr, "Cannot have multiple dumps on pipe input\n"); 535 done(1); 536 } 537 tcom.mt_op = MTFSF; 538 tcom.mt_count = dumpnum - 1; 539 #ifdef RRESTORE 540 if (host) 541 rmtioctl(MTFSF, dumpnum - 1); 542 else 543 #endif 544 if (!pipecmdin && ioctl(mt, MTIOCTOP, (char *)&tcom) < 0) 545 fprintf(stderr, "ioctl MTFSF: %s\n", strerror(errno)); 546 } 547 548 void 549 printdumpinfo(void) 550 { 551 time_t t; 552 t = _time64_to_time(spcl.c_date); 553 fprintf(stdout, "Dump date: %s", ctime(&t)); 554 t = _time64_to_time(spcl.c_ddate); 555 fprintf(stdout, "Dumped from: %s", 556 (spcl.c_ddate == 0) ? "the epoch\n" : ctime(&t)); 557 if (spcl.c_host[0] == '\0') 558 return; 559 fprintf(stderr, "Level %jd dump of %s on %s:%s\n", 560 (intmax_t)spcl.c_level, spcl.c_filesys, spcl.c_host, spcl.c_dev); 561 fprintf(stderr, "Label: %s\n", spcl.c_label); 562 } 563 564 int 565 extractfile(char *name) 566 { 567 int flags; 568 uid_t uid; 569 gid_t gid; 570 mode_t mode; 571 int extsize; 572 struct timespec mtimep[2], ctimep[2]; 573 struct entry *ep; 574 char *buf; 575 576 curfile.name = name; 577 curfile.action = USING; 578 mtimep[0].tv_sec = curfile.atime_sec; 579 mtimep[0].tv_nsec = curfile.atime_nsec; 580 mtimep[1].tv_sec = curfile.mtime_sec; 581 mtimep[1].tv_nsec = curfile.mtime_nsec; 582 ctimep[0].tv_sec = curfile.atime_sec; 583 ctimep[0].tv_nsec = curfile.atime_nsec; 584 ctimep[1].tv_sec = curfile.birthtime_sec; 585 ctimep[1].tv_nsec = curfile.birthtime_nsec; 586 extsize = curfile.extsize; 587 uid = getuid(); 588 if (uid == 0) 589 uid = curfile.uid; 590 gid = curfile.gid; 591 mode = curfile.mode; 592 flags = curfile.file_flags; 593 switch (mode & IFMT) { 594 595 default: 596 fprintf(stderr, "%s: unknown file mode 0%o\n", name, mode); 597 skipfile(); 598 return (FAIL); 599 600 case IFSOCK: 601 vprintf(stdout, "skipped socket %s\n", name); 602 skipfile(); 603 return (GOOD); 604 605 case IFDIR: 606 if (mflag) { 607 ep = lookupname(name); 608 if (ep == NULL || ep->e_flags & EXTRACT) 609 panic("unextracted directory %s\n", name); 610 skipfile(); 611 return (GOOD); 612 } 613 vprintf(stdout, "extract file %s\n", name); 614 return (genliteraldir(name, curfile.ino)); 615 616 case IFLNK: 617 lnkbuf[0] = '\0'; 618 pathlen = 0; 619 buf = setupextattr(extsize); 620 getfile(xtrlnkfile, xtrattr, xtrlnkskip); 621 if (pathlen == 0) { 622 vprintf(stdout, 623 "%s: zero length symbolic link (ignored)\n", name); 624 return (GOOD); 625 } 626 if (linkit(lnkbuf, name, SYMLINK) == GOOD) { 627 if (extsize > 0) 628 set_extattr_link(name, buf, extsize); 629 (void) lchown(name, uid, gid); 630 (void) lchmod(name, mode); 631 (void) utimensat(AT_FDCWD, name, ctimep, 632 AT_SYMLINK_NOFOLLOW); 633 (void) utimensat(AT_FDCWD, name, mtimep, 634 AT_SYMLINK_NOFOLLOW); 635 (void) lchflags(name, flags); 636 return (GOOD); 637 } 638 return (FAIL); 639 640 case IFIFO: 641 vprintf(stdout, "extract fifo %s\n", name); 642 if (Nflag) { 643 skipfile(); 644 return (GOOD); 645 } 646 if (uflag) 647 (void) unlink(name); 648 if (mkfifo(name, 0600) < 0) { 649 fprintf(stderr, "%s: cannot create fifo: %s\n", 650 name, strerror(errno)); 651 skipfile(); 652 return (FAIL); 653 } 654 if (extsize == 0) { 655 skipfile(); 656 } else { 657 buf = setupextattr(extsize); 658 getfile(xtrnull, xtrattr, xtrnull); 659 set_extattr_file(name, buf, extsize); 660 } 661 (void) chown(name, uid, gid); 662 (void) chmod(name, mode); 663 (void) utimensat(AT_FDCWD, name, ctimep, 0); 664 (void) utimensat(AT_FDCWD, name, mtimep, 0); 665 (void) chflags(name, flags); 666 return (GOOD); 667 668 case IFCHR: 669 case IFBLK: 670 vprintf(stdout, "extract special file %s\n", name); 671 if (Nflag) { 672 skipfile(); 673 return (GOOD); 674 } 675 if (uflag) 676 (void) unlink(name); 677 if (mknod(name, (mode & (IFCHR | IFBLK)) | 0600, 678 (int)curfile.rdev) < 0) { 679 fprintf(stderr, "%s: cannot create special file: %s\n", 680 name, strerror(errno)); 681 skipfile(); 682 return (FAIL); 683 } 684 if (extsize == 0) { 685 skipfile(); 686 } else { 687 buf = setupextattr(extsize); 688 getfile(xtrnull, xtrattr, xtrnull); 689 set_extattr_file(name, buf, extsize); 690 } 691 (void) chown(name, uid, gid); 692 (void) chmod(name, mode); 693 (void) utimensat(AT_FDCWD, name, ctimep, 0); 694 (void) utimensat(AT_FDCWD, name, mtimep, 0); 695 (void) chflags(name, flags); 696 return (GOOD); 697 698 case IFREG: 699 vprintf(stdout, "extract file %s\n", name); 700 if (Nflag) { 701 skipfile(); 702 return (GOOD); 703 } 704 if (uflag) 705 (void) unlink(name); 706 if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC, 707 0600)) < 0) { 708 fprintf(stderr, "%s: cannot create file: %s\n", 709 name, strerror(errno)); 710 skipfile(); 711 return (FAIL); 712 } 713 buf = setupextattr(extsize); 714 getfile(xtrfile, xtrattr, xtrskip); 715 if (extsize > 0) 716 set_extattr_fd(ofile, name, buf, extsize); 717 (void) fchown(ofile, uid, gid); 718 (void) fchmod(ofile, mode); 719 (void) futimens(ofile, ctimep); 720 (void) futimens(ofile, mtimep); 721 (void) fchflags(ofile, flags); 722 (void) close(ofile); 723 return (GOOD); 724 } 725 /* NOTREACHED */ 726 } 727 728 /* 729 * Set attributes for a file. 730 */ 731 void 732 set_extattr_file(char *name, void *buf, int size) 733 { 734 struct extattr *eap, *eaend; 735 736 vprintf(stdout, "Set attributes for %s:", name); 737 eaend = buf + size; 738 for (eap = buf; eap < eaend; eap = EXTATTR_NEXT(eap)) { 739 /* 740 * Make sure this entry is complete. 741 */ 742 if (EXTATTR_NEXT(eap) > eaend || eap->ea_length <= 0) { 743 dprintf(stdout, "\n\t%scorrupted", 744 eap == buf ? "" : "remainder "); 745 break; 746 } 747 if (eap->ea_namespace == EXTATTR_NAMESPACE_EMPTY) 748 continue; 749 vprintf(stdout, "\n\t%s, (%d bytes), %*s", 750 namespace_names[eap->ea_namespace], eap->ea_length, 751 eap->ea_namelength, eap->ea_name); 752 /* 753 * First we try the general attribute setting interface. 754 * However, some attributes can only be set by root or 755 * by using special interfaces (for example, ACLs). 756 */ 757 if (extattr_set_file(name, eap->ea_namespace, eap->ea_name, 758 EXTATTR_CONTENT(eap), EXTATTR_CONTENT_SIZE(eap)) != -1) { 759 dprintf(stdout, " (set using extattr_set_file)"); 760 continue; 761 } 762 /* 763 * If the general interface refuses to set the attribute, 764 * then we try all the specialized interfaces that we 765 * know about. 766 */ 767 if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM && 768 !strcmp(eap->ea_name, POSIX1E_ACL_ACCESS_EXTATTR_NAME)) { 769 if (acl_set_file(name, ACL_TYPE_ACCESS, 770 EXTATTR_CONTENT(eap)) != -1) { 771 dprintf(stdout, " (set using acl_set_file)"); 772 continue; 773 } 774 } 775 if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM && 776 !strcmp(eap->ea_name, POSIX1E_ACL_DEFAULT_EXTATTR_NAME)) { 777 if (acl_set_file(name, ACL_TYPE_DEFAULT, 778 EXTATTR_CONTENT(eap)) != -1) { 779 dprintf(stdout, " (set using acl_set_file)"); 780 continue; 781 } 782 } 783 vprintf(stdout, " (unable to set)"); 784 } 785 vprintf(stdout, "\n"); 786 } 787 788 /* 789 * Set attributes for a symbolic link. 790 */ 791 static void 792 set_extattr_link(char *name, void *buf, int size) 793 { 794 struct extattr *eap, *eaend; 795 796 vprintf(stdout, "Set attributes for %s:", name); 797 eaend = buf + size; 798 for (eap = buf; eap < eaend; eap = EXTATTR_NEXT(eap)) { 799 /* 800 * Make sure this entry is complete. 801 */ 802 if (EXTATTR_NEXT(eap) > eaend || eap->ea_length <= 0) { 803 dprintf(stdout, "\n\t%scorrupted", 804 eap == buf ? "" : "remainder "); 805 break; 806 } 807 if (eap->ea_namespace == EXTATTR_NAMESPACE_EMPTY) 808 continue; 809 vprintf(stdout, "\n\t%s, (%d bytes), %*s", 810 namespace_names[eap->ea_namespace], eap->ea_length, 811 eap->ea_namelength, eap->ea_name); 812 /* 813 * First we try the general attribute setting interface. 814 * However, some attributes can only be set by root or 815 * by using special interfaces (for example, ACLs). 816 */ 817 if (extattr_set_link(name, eap->ea_namespace, eap->ea_name, 818 EXTATTR_CONTENT(eap), EXTATTR_CONTENT_SIZE(eap)) != -1) { 819 dprintf(stdout, " (set using extattr_set_link)"); 820 continue; 821 } 822 /* 823 * If the general interface refuses to set the attribute, 824 * then we try all the specialized interfaces that we 825 * know about. 826 */ 827 if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM && 828 !strcmp(eap->ea_name, POSIX1E_ACL_ACCESS_EXTATTR_NAME)) { 829 if (acl_set_link_np(name, ACL_TYPE_ACCESS, 830 EXTATTR_CONTENT(eap)) != -1) { 831 dprintf(stdout, " (set using acl_set_link_np)"); 832 continue; 833 } 834 } 835 if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM && 836 !strcmp(eap->ea_name, POSIX1E_ACL_DEFAULT_EXTATTR_NAME)) { 837 if (acl_set_link_np(name, ACL_TYPE_DEFAULT, 838 EXTATTR_CONTENT(eap)) != -1) { 839 dprintf(stdout, " (set using acl_set_link_np)"); 840 continue; 841 } 842 } 843 vprintf(stdout, " (unable to set)"); 844 } 845 vprintf(stdout, "\n"); 846 } 847 848 /* 849 * Set attributes on a file descriptor. 850 */ 851 static void 852 set_extattr_fd(int fd, char *name, void *buf, int size) 853 { 854 struct extattr *eap, *eaend; 855 856 vprintf(stdout, "Set attributes for %s:", name); 857 eaend = buf + size; 858 for (eap = buf; eap < eaend; eap = EXTATTR_NEXT(eap)) { 859 /* 860 * Make sure this entry is complete. 861 */ 862 if (EXTATTR_NEXT(eap) > eaend || eap->ea_length <= 0) { 863 dprintf(stdout, "\n\t%scorrupted", 864 eap == buf ? "" : "remainder "); 865 break; 866 } 867 if (eap->ea_namespace == EXTATTR_NAMESPACE_EMPTY) 868 continue; 869 vprintf(stdout, "\n\t%s, (%d bytes), %*s", 870 namespace_names[eap->ea_namespace], eap->ea_length, 871 eap->ea_namelength, eap->ea_name); 872 /* 873 * First we try the general attribute setting interface. 874 * However, some attributes can only be set by root or 875 * by using special interfaces (for example, ACLs). 876 */ 877 if (extattr_set_fd(fd, eap->ea_namespace, eap->ea_name, 878 EXTATTR_CONTENT(eap), EXTATTR_CONTENT_SIZE(eap)) != -1) { 879 dprintf(stdout, " (set using extattr_set_fd)"); 880 continue; 881 } 882 /* 883 * If the general interface refuses to set the attribute, 884 * then we try all the specialized interfaces that we 885 * know about. 886 */ 887 if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM && 888 !strcmp(eap->ea_name, POSIX1E_ACL_ACCESS_EXTATTR_NAME)) { 889 if (acl_set_fd(fd, EXTATTR_CONTENT(eap)) != -1) { 890 dprintf(stdout, " (set using acl_set_fd)"); 891 continue; 892 } 893 } 894 if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM && 895 !strcmp(eap->ea_name, POSIX1E_ACL_DEFAULT_EXTATTR_NAME)) { 896 if (acl_set_file(name, ACL_TYPE_DEFAULT, 897 EXTATTR_CONTENT(eap)) != -1) { 898 dprintf(stdout, " (set using acl_set_file)"); 899 continue; 900 } 901 } 902 vprintf(stdout, " (unable to set)"); 903 } 904 vprintf(stdout, "\n"); 905 } 906 907 /* 908 * skip over bit maps on the tape 909 */ 910 void 911 skipmaps(void) 912 { 913 914 while (spcl.c_type == TS_BITS || spcl.c_type == TS_CLRI) 915 skipfile(); 916 } 917 918 /* 919 * skip over a file on the tape 920 */ 921 void 922 skipfile(void) 923 { 924 925 curfile.action = SKIP; 926 getfile(xtrnull, xtrnull, xtrnull); 927 } 928 929 /* 930 * Extract a file from the tape. 931 * When an allocated block is found it is passed to the fill function; 932 * when an unallocated block (hole) is found, a zeroed buffer is passed 933 * to the skip function. 934 */ 935 void 936 getfile(void (*datafill)(char *, long), void (*attrfill)(char *, long), 937 void (*skip)(char *, long)) 938 { 939 int i; 940 off_t size; 941 int curblk, attrsize; 942 void (*fillit)(char *, long); 943 static char clearedbuf[MAXBSIZE]; 944 char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE]; 945 char junk[TP_BSIZE]; 946 947 curblk = 0; 948 size = spcl.c_size; 949 attrsize = spcl.c_extsize; 950 if (spcl.c_type == TS_END) 951 panic("ran off end of tape\n"); 952 if (spcl.c_magic != FS_UFS2_MAGIC) 953 panic("not at beginning of a file\n"); 954 if (!gettingfile && setjmp(restart) != 0) 955 return; 956 gettingfile++; 957 fillit = datafill; 958 if (size == 0 && attrsize > 0) { 959 fillit = attrfill; 960 size = attrsize; 961 attrsize = 0; 962 } 963 loop: 964 for (i = 0; i < spcl.c_count; i++) { 965 if (!readmapflag && i > TP_NINDIR) { 966 if (Dflag) { 967 fprintf(stderr, "spcl.c_count = %jd\n", 968 (intmax_t)spcl.c_count); 969 break; 970 } else 971 panic("spcl.c_count = %jd\n", 972 (intmax_t)spcl.c_count); 973 } 974 if (readmapflag || spcl.c_addr[i]) { 975 readtape(&buf[curblk++][0]); 976 if (curblk == fssize / TP_BSIZE) { 977 (*fillit)((char *)buf, (long)(size > TP_BSIZE ? 978 fssize : (curblk - 1) * TP_BSIZE + size)); 979 curblk = 0; 980 } 981 } else { 982 if (curblk > 0) { 983 (*fillit)((char *)buf, (long)(size > TP_BSIZE ? 984 curblk * TP_BSIZE : 985 (curblk - 1) * TP_BSIZE + size)); 986 curblk = 0; 987 } 988 (*skip)(clearedbuf, (long)(size > TP_BSIZE ? 989 TP_BSIZE : size)); 990 } 991 if ((size -= TP_BSIZE) <= 0) { 992 if (size > -TP_BSIZE && curblk > 0) { 993 (*fillit)((char *)buf, 994 (long)((curblk * TP_BSIZE) + size)); 995 curblk = 0; 996 } 997 if (attrsize > 0) { 998 fillit = attrfill; 999 size = attrsize; 1000 attrsize = 0; 1001 continue; 1002 } 1003 if (spcl.c_count - i > 1) 1004 dprintf(stdout, "skipping %d junk block(s)\n", 1005 spcl.c_count - i - 1); 1006 for (i++; i < spcl.c_count; i++) { 1007 if (!readmapflag && i > TP_NINDIR) { 1008 if (Dflag) { 1009 fprintf(stderr, 1010 "spcl.c_count = %jd\n", 1011 (intmax_t)spcl.c_count); 1012 break; 1013 } else 1014 panic("spcl.c_count = %jd\n", 1015 (intmax_t)spcl.c_count); 1016 } 1017 if (readmapflag || spcl.c_addr[i]) 1018 readtape(junk); 1019 } 1020 break; 1021 } 1022 } 1023 if (gethead(&spcl) == GOOD && size > 0) { 1024 if (spcl.c_type == TS_ADDR) 1025 goto loop; 1026 dprintf(stdout, 1027 "Missing address (header) block for %s at %ld blocks\n", 1028 curfile.name, blksread); 1029 } 1030 if (curblk > 0) 1031 panic("getfile: lost data\n"); 1032 findinode(&spcl); 1033 gettingfile = 0; 1034 } 1035 1036 /* 1037 * These variables are shared between the next two functions. 1038 */ 1039 static int extbufsize = 0; 1040 static char *extbuf; 1041 static int extloc; 1042 1043 /* 1044 * Allocate a buffer into which to extract extended attributes. 1045 */ 1046 static char * 1047 setupextattr(int extsize) 1048 { 1049 1050 extloc = 0; 1051 if (extsize <= extbufsize) 1052 return (extbuf); 1053 if (extbufsize > 0) 1054 free(extbuf); 1055 if ((extbuf = malloc(extsize)) != NULL) { 1056 extbufsize = extsize; 1057 return (extbuf); 1058 } 1059 extbufsize = 0; 1060 extbuf = NULL; 1061 fprintf(stderr, "Cannot extract %d bytes %s for inode %ju, name %s\n", 1062 extsize, "of extended attributes", (uintmax_t)curfile.ino, 1063 curfile.name); 1064 return (NULL); 1065 } 1066 1067 /* 1068 * Extract the next block of extended attributes. 1069 */ 1070 static void 1071 xtrattr(char *buf, long size) 1072 { 1073 1074 if (extloc + size > extbufsize) 1075 panic("overrun attribute buffer\n"); 1076 memmove(&extbuf[extloc], buf, size); 1077 extloc += size; 1078 } 1079 1080 /* 1081 * Write out the next block of a file. 1082 */ 1083 static void 1084 xtrfile(char *buf, long size) 1085 { 1086 1087 if (Nflag) 1088 return; 1089 if (write(ofile, buf, (int) size) == -1) { 1090 fprintf(stderr, 1091 "write error extracting inode %ju, name %s\nwrite: %s\n", 1092 (uintmax_t)curfile.ino, curfile.name, strerror(errno)); 1093 } 1094 } 1095 1096 /* 1097 * Skip over a hole in a file. 1098 */ 1099 /* ARGSUSED */ 1100 static void 1101 xtrskip(char *buf, long size) 1102 { 1103 1104 if (lseek(ofile, size, SEEK_CUR) == -1) { 1105 fprintf(stderr, 1106 "seek error extracting inode %ju, name %s\nlseek: %s\n", 1107 (uintmax_t)curfile.ino, curfile.name, strerror(errno)); 1108 done(1); 1109 } 1110 } 1111 1112 /* 1113 * Collect the next block of a symbolic link. 1114 */ 1115 static void 1116 xtrlnkfile(char *buf, long size) 1117 { 1118 1119 pathlen += size; 1120 if (pathlen > MAXPATHLEN) { 1121 fprintf(stderr, "symbolic link name: %s->%s%s; too long %d\n", 1122 curfile.name, lnkbuf, buf, pathlen); 1123 done(1); 1124 } 1125 (void) strcat(lnkbuf, buf); 1126 } 1127 1128 /* 1129 * Skip over a hole in a symbolic link (should never happen). 1130 */ 1131 /* ARGSUSED */ 1132 static void 1133 xtrlnkskip(char *buf, long size) 1134 { 1135 1136 fprintf(stderr, "unallocated block in symbolic link %s\n", 1137 curfile.name); 1138 done(1); 1139 } 1140 1141 /* 1142 * Collect the next block of a bit map. 1143 */ 1144 static void 1145 xtrmap(char *buf, long size) 1146 { 1147 1148 memmove(map, buf, size); 1149 map += size; 1150 } 1151 1152 /* 1153 * Skip over a hole in a bit map (should never happen). 1154 */ 1155 /* ARGSUSED */ 1156 static void 1157 xtrmapskip(char *buf, long size) 1158 { 1159 1160 panic("hole in map\n"); 1161 map += size; 1162 } 1163 1164 /* 1165 * Noop, when an extraction function is not needed. 1166 */ 1167 /* ARGSUSED */ 1168 void 1169 xtrnull(char *buf, long size) 1170 { 1171 1172 return; 1173 } 1174 1175 /* 1176 * Read TP_BSIZE blocks from the input. 1177 * Handle read errors, and end of media. 1178 */ 1179 static void 1180 readtape(char *buf) 1181 { 1182 long rd, newvol, i, oldnumtrec; 1183 int cnt, seek_failed; 1184 1185 if (blkcnt + (byteslide > 0) < numtrec) { 1186 memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE) + byteslide], (long)TP_BSIZE); 1187 blksread++; 1188 tapeaddr++; 1189 return; 1190 } 1191 if (numtrec > 0) 1192 memmove(&tapebuf[-TP_BSIZE], 1193 &tapebuf[(numtrec-1) * TP_BSIZE], (long)TP_BSIZE); 1194 oldnumtrec = numtrec; 1195 for (i = 0; i < ntrec; i++) 1196 ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; 1197 if (numtrec == 0) 1198 numtrec = ntrec; 1199 cnt = ntrec * TP_BSIZE; 1200 rd = 0; 1201 getmore: 1202 #ifdef RRESTORE 1203 if (host) 1204 i = rmtread(&tapebuf[rd], cnt); 1205 else 1206 #endif 1207 i = read(mt, &tapebuf[rd], cnt); 1208 /* 1209 * Check for mid-tape short read error. 1210 * If found, skip rest of buffer and start with the next. 1211 */ 1212 if (!pipein && !pipecmdin && numtrec < ntrec && i > 0) { 1213 dprintf(stdout, "mid-media short read error.\n"); 1214 numtrec = ntrec; 1215 } 1216 /* 1217 * Handle partial block read. 1218 */ 1219 if ((pipein || pipecmdin) && i == 0 && rd > 0) 1220 i = rd; 1221 else if (i > 0 && i != ntrec * TP_BSIZE) { 1222 if (pipein || pipecmdin) { 1223 rd += i; 1224 cnt -= i; 1225 if (cnt > 0) 1226 goto getmore; 1227 i = rd; 1228 } else { 1229 /* 1230 * Short read. Process the blocks read. 1231 */ 1232 if (i % TP_BSIZE != 0) 1233 vprintf(stdout, 1234 "partial block read: %ld should be %ld\n", 1235 i, ntrec * TP_BSIZE); 1236 numtrec = i / TP_BSIZE; 1237 } 1238 } 1239 /* 1240 * Handle read error. 1241 */ 1242 if (i < 0) { 1243 fprintf(stderr, "Tape read error while "); 1244 switch (curfile.action) { 1245 default: 1246 fprintf(stderr, "trying to set up tape\n"); 1247 break; 1248 case UNKNOWN: 1249 fprintf(stderr, "trying to resynchronize\n"); 1250 break; 1251 case USING: 1252 fprintf(stderr, "restoring %s\n", curfile.name); 1253 break; 1254 case SKIP: 1255 fprintf(stderr, "skipping over inode %ju\n", 1256 (uintmax_t)curfile.ino); 1257 break; 1258 } 1259 if (!yflag && !reply("continue")) 1260 done(1); 1261 i = ntrec * TP_BSIZE; 1262 memset(tapebuf, 0, i); 1263 #ifdef RRESTORE 1264 if (host) 1265 seek_failed = (rmtseek(i, 1) < 0); 1266 else 1267 #endif 1268 seek_failed = (lseek(mt, i, SEEK_CUR) == (off_t)-1); 1269 1270 if (seek_failed) { 1271 fprintf(stderr, 1272 "continuation failed: %s\n", strerror(errno)); 1273 done(1); 1274 } 1275 } 1276 /* 1277 * Handle end of tape. 1278 */ 1279 if (i == 0) { 1280 vprintf(stdout, "End-of-tape encountered\n"); 1281 if (!pipein) { 1282 newvol = volno + 1; 1283 volno = 0; 1284 numtrec = 0; 1285 getvol(newvol); 1286 readtape(buf); 1287 return; 1288 } 1289 if (rd % TP_BSIZE != 0) 1290 panic("partial block read: %ld should be %ld\n", 1291 rd, ntrec * TP_BSIZE); 1292 terminateinput(); 1293 memmove(&tapebuf[rd], &endoftapemark, (long)TP_BSIZE); 1294 } 1295 if (oldnumtrec == 0) 1296 blkcnt = 0; 1297 else 1298 blkcnt -= oldnumtrec; 1299 memmove(buf, 1300 &tapebuf[(blkcnt++ * TP_BSIZE) + byteslide], (long)TP_BSIZE); 1301 blksread++; 1302 tapeaddr++; 1303 } 1304 1305 static void 1306 findtapeblksize(void) 1307 { 1308 long i; 1309 1310 for (i = 0; i < ntrec; i++) 1311 ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; 1312 blkcnt = 0; 1313 #ifdef RRESTORE 1314 if (host) 1315 i = rmtread(tapebuf, ntrec * TP_BSIZE); 1316 else 1317 #endif 1318 i = read(mt, tapebuf, ntrec * TP_BSIZE); 1319 1320 if (i <= 0) { 1321 fprintf(stderr, "tape read error: %s\n", strerror(errno)); 1322 done(1); 1323 } 1324 if (i % TP_BSIZE != 0) { 1325 fprintf(stderr, "Tape block size (%ld) %s (%d)\n", 1326 i, "is not a multiple of dump block size", TP_BSIZE); 1327 done(1); 1328 } 1329 ntrec = i / TP_BSIZE; 1330 numtrec = ntrec; 1331 vprintf(stdout, "Tape block size is %ld\n", ntrec); 1332 } 1333 1334 void 1335 closemt(void) 1336 { 1337 1338 if (mt < 0) 1339 return; 1340 if (pipecmdin) { 1341 pclose(popenfp); 1342 popenfp = NULL; 1343 } else 1344 #ifdef RRESTORE 1345 if (host) 1346 rmtclose(); 1347 else 1348 #endif 1349 (void) close(mt); 1350 } 1351 1352 /* 1353 * Read the next block from the tape. 1354 * If it is not any valid header, return an error. 1355 */ 1356 static int 1357 gethead(struct s_spcl *buf) 1358 { 1359 long i; 1360 1361 readtape((char *)buf); 1362 if (buf->c_magic != FS_UFS2_MAGIC && buf->c_magic != NFS_MAGIC) { 1363 if (buf->c_magic == OFS_MAGIC) { 1364 fprintf(stderr, 1365 "Format of dump tape is too old. Must use\n"); 1366 fprintf(stderr, 1367 "a version of restore from before 2002.\n"); 1368 return (FAIL); 1369 } 1370 if (swabl(buf->c_magic) != FS_UFS2_MAGIC && 1371 buf->c_magic != NFS_MAGIC) { 1372 if (buf->c_magic == OFS_MAGIC) { 1373 fprintf(stderr, 1374 "Format of dump tape is too old. Must use\n"); 1375 fprintf(stderr, 1376 "a version of restore from before 2002.\n"); 1377 } 1378 return (FAIL); 1379 } 1380 if (!Bcvt) { 1381 vprintf(stdout, "Note: Doing Byte swapping\n"); 1382 Bcvt = 1; 1383 } 1384 } 1385 if (checksum((int *)buf) == FAIL) 1386 return (FAIL); 1387 if (Bcvt) { 1388 swabst((u_char *)"8l4s1q8l2q17l", (u_char *)buf); 1389 swabst((u_char *)"l",(u_char *) &buf->c_level); 1390 swabst((u_char *)"2l4q",(u_char *) &buf->c_flags); 1391 } 1392 readmapflag = 0; 1393 1394 switch (buf->c_type) { 1395 1396 case TS_CLRI: 1397 case TS_BITS: 1398 /* 1399 * Have to patch up missing information in bit map headers 1400 */ 1401 buf->c_size = buf->c_count * TP_BSIZE; 1402 if (buf->c_count > TP_NINDIR) 1403 readmapflag = 1; 1404 else 1405 for (i = 0; i < buf->c_count; i++) 1406 buf->c_addr[i]++; 1407 /* FALL THROUGH */ 1408 1409 case TS_TAPE: 1410 if (buf->c_magic == NFS_MAGIC && 1411 (buf->c_flags & NFS_DR_NEWINODEFMT) == 0) 1412 oldinofmt = 1; 1413 /* FALL THROUGH */ 1414 1415 case TS_END: 1416 buf->c_inumber = 0; 1417 /* FALL THROUGH */ 1418 1419 case TS_ADDR: 1420 case TS_INODE: 1421 /* 1422 * For old dump tapes, have to copy up old fields to 1423 * new locations. 1424 */ 1425 if (buf->c_magic == NFS_MAGIC) { 1426 buf->c_tapea = buf->c_old_tapea; 1427 buf->c_firstrec = buf->c_old_firstrec; 1428 buf->c_date = _time32_to_time(buf->c_old_date); 1429 buf->c_ddate = _time32_to_time(buf->c_old_ddate); 1430 buf->c_atime = _time32_to_time(buf->c_old_atime); 1431 buf->c_mtime = _time32_to_time(buf->c_old_mtime); 1432 buf->c_birthtime = 0; 1433 buf->c_birthtimensec = 0; 1434 buf->c_extsize = 0; 1435 } 1436 break; 1437 1438 default: 1439 panic("gethead: unknown inode type %d\n", buf->c_type); 1440 break; 1441 } 1442 if (dumpdate != 0 && _time64_to_time(buf->c_date) != dumpdate) 1443 fprintf(stderr, "Header with wrong dumpdate.\n"); 1444 /* 1445 * If we're restoring a filesystem with the old (FreeBSD 1) 1446 * format inodes, copy the uid/gid to the new location 1447 */ 1448 if (oldinofmt) { 1449 buf->c_uid = buf->c_spare1[1]; 1450 buf->c_gid = buf->c_spare1[2]; 1451 } 1452 buf->c_magic = FS_UFS2_MAGIC; 1453 tapeaddr = buf->c_tapea; 1454 if (dflag) 1455 accthdr(buf); 1456 return(GOOD); 1457 } 1458 1459 /* 1460 * Check that a header is where it belongs and predict the next header 1461 */ 1462 static void 1463 accthdr(struct s_spcl *header) 1464 { 1465 static ino_t previno = 0x7fffffff; 1466 static int prevtype; 1467 static long predict; 1468 long blks, i; 1469 1470 if (header->c_type == TS_TAPE) { 1471 fprintf(stderr, "Volume header "); 1472 if (header->c_firstrec) 1473 fprintf(stderr, "begins with record %jd", 1474 (intmax_t)header->c_firstrec); 1475 fprintf(stderr, "\n"); 1476 previno = 0x7fffffff; 1477 return; 1478 } 1479 if (previno == 0x7fffffff) 1480 goto newcalc; 1481 switch (prevtype) { 1482 case TS_BITS: 1483 fprintf(stderr, "Dumped inodes map header"); 1484 break; 1485 case TS_CLRI: 1486 fprintf(stderr, "Used inodes map header"); 1487 break; 1488 case TS_INODE: 1489 fprintf(stderr, "File header, ino %ju", (uintmax_t)previno); 1490 break; 1491 case TS_ADDR: 1492 fprintf(stderr, "File continuation header, ino %ju", 1493 (uintmax_t)previno); 1494 break; 1495 case TS_END: 1496 fprintf(stderr, "End of tape header"); 1497 break; 1498 } 1499 if (predict != blksread - 1) 1500 fprintf(stderr, "; predicted %ld blocks, got %ld blocks", 1501 predict, blksread - 1); 1502 fprintf(stderr, "\n"); 1503 newcalc: 1504 blks = 0; 1505 if (header->c_type != TS_END) 1506 for (i = 0; i < header->c_count; i++) 1507 if (readmapflag || header->c_addr[i] != 0) 1508 blks++; 1509 predict = blks; 1510 blksread = 0; 1511 prevtype = header->c_type; 1512 previno = header->c_inumber; 1513 } 1514 1515 /* 1516 * Find an inode header. 1517 * Complain if had to skip. 1518 */ 1519 static void 1520 findinode(struct s_spcl *header) 1521 { 1522 static long skipcnt = 0; 1523 long i; 1524 char buf[TP_BSIZE]; 1525 int htype; 1526 1527 curfile.name = "<name unknown>"; 1528 curfile.action = UNKNOWN; 1529 curfile.mode = 0; 1530 curfile.ino = 0; 1531 do { 1532 htype = header->c_type; 1533 switch (htype) { 1534 1535 case TS_ADDR: 1536 /* 1537 * Skip up to the beginning of the next record 1538 */ 1539 for (i = 0; i < header->c_count; i++) 1540 if (header->c_addr[i]) 1541 readtape(buf); 1542 while (gethead(header) == FAIL || 1543 _time64_to_time(header->c_date) != dumpdate) { 1544 skipcnt++; 1545 if (Dflag) { 1546 byteslide++; 1547 if (byteslide < TP_BSIZE) { 1548 blkcnt--; 1549 blksread--; 1550 } else 1551 byteslide = 0; 1552 } 1553 } 1554 break; 1555 1556 case TS_INODE: 1557 curfile.mode = header->c_mode; 1558 curfile.uid = header->c_uid; 1559 curfile.gid = header->c_gid; 1560 curfile.file_flags = header->c_file_flags; 1561 curfile.rdev = header->c_rdev; 1562 curfile.atime_sec = header->c_atime; 1563 curfile.atime_nsec = header->c_atimensec; 1564 curfile.mtime_sec = header->c_mtime; 1565 curfile.mtime_nsec = header->c_mtimensec; 1566 curfile.birthtime_sec = header->c_birthtime; 1567 curfile.birthtime_nsec = header->c_birthtimensec; 1568 curfile.extsize = header->c_extsize; 1569 curfile.size = header->c_size; 1570 curfile.ino = header->c_inumber; 1571 break; 1572 1573 case TS_END: 1574 /* If we missed some tapes, get another volume. */ 1575 if (tapesread & (tapesread + 1)) { 1576 getvol(0); 1577 continue; 1578 } 1579 curfile.ino = maxino; 1580 break; 1581 1582 case TS_CLRI: 1583 curfile.name = "<file removal list>"; 1584 break; 1585 1586 case TS_BITS: 1587 curfile.name = "<file dump list>"; 1588 break; 1589 1590 case TS_TAPE: 1591 if (Dflag) 1592 fprintf(stderr, "unexpected tape header\n"); 1593 else 1594 panic("unexpected tape header\n"); 1595 1596 default: 1597 if (Dflag) 1598 fprintf(stderr, "unknown tape header type %d\n", 1599 spcl.c_type); 1600 else 1601 panic("unknown tape header type %d\n", 1602 spcl.c_type); 1603 while (gethead(header) == FAIL || 1604 _time64_to_time(header->c_date) != dumpdate) { 1605 skipcnt++; 1606 if (Dflag) { 1607 byteslide++; 1608 if (byteslide < TP_BSIZE) { 1609 blkcnt--; 1610 blksread--; 1611 } else 1612 byteslide = 0; 1613 } 1614 } 1615 1616 } 1617 } while (htype == TS_ADDR); 1618 if (skipcnt > 0) 1619 fprintf(stderr, "resync restore, skipped %ld %s\n", 1620 skipcnt, Dflag ? "bytes" : "blocks"); 1621 skipcnt = 0; 1622 } 1623 1624 static int 1625 checksum(int *buf) 1626 { 1627 int i, j; 1628 1629 j = sizeof(union u_spcl) / sizeof(int); 1630 i = 0; 1631 if (!Bcvt) { 1632 do 1633 i += *buf++; 1634 while (--j); 1635 } else { 1636 /* What happens if we want to read restore tapes 1637 for a 16bit int machine??? */ 1638 do 1639 i += swabl(*buf++); 1640 while (--j); 1641 } 1642 1643 if (i != CHECKSUM) { 1644 fprintf(stderr, "Checksum error %o, inode %ju file %s\n", i, 1645 (uintmax_t)curfile.ino, curfile.name); 1646 return(FAIL); 1647 } 1648 return(GOOD); 1649 } 1650 1651 #ifdef RRESTORE 1652 #include <stdarg.h> 1653 1654 void 1655 msg(const char *fmt, ...) 1656 { 1657 va_list ap; 1658 va_start(ap, fmt); 1659 (void)vfprintf(stderr, fmt, ap); 1660 va_end(ap); 1661 } 1662 #endif /* RRESTORE */ 1663 1664 static u_char * 1665 swabshort(u_char *sp, int n) 1666 { 1667 char c; 1668 1669 while (--n >= 0) { 1670 c = sp[0]; sp[0] = sp[1]; sp[1] = c; 1671 sp += 2; 1672 } 1673 return (sp); 1674 } 1675 1676 static u_char * 1677 swablong(u_char *sp, int n) 1678 { 1679 char c; 1680 1681 while (--n >= 0) { 1682 c = sp[0]; sp[0] = sp[3]; sp[3] = c; 1683 c = sp[2]; sp[2] = sp[1]; sp[1] = c; 1684 sp += 4; 1685 } 1686 return (sp); 1687 } 1688 1689 static u_char * 1690 swabquad(u_char *sp, int n) 1691 { 1692 char c; 1693 1694 while (--n >= 0) { 1695 c = sp[0]; sp[0] = sp[7]; sp[7] = c; 1696 c = sp[1]; sp[1] = sp[6]; sp[6] = c; 1697 c = sp[2]; sp[2] = sp[5]; sp[5] = c; 1698 c = sp[3]; sp[3] = sp[4]; sp[4] = c; 1699 sp += 8; 1700 } 1701 return (sp); 1702 } 1703 1704 void 1705 swabst(u_char *cp, u_char *sp) 1706 { 1707 int n = 0; 1708 1709 while (*cp) { 1710 switch (*cp) { 1711 case '0': case '1': case '2': case '3': case '4': 1712 case '5': case '6': case '7': case '8': case '9': 1713 n = (n * 10) + (*cp++ - '0'); 1714 continue; 1715 1716 case 's': case 'w': case 'h': 1717 if (n == 0) 1718 n = 1; 1719 sp = swabshort(sp, n); 1720 break; 1721 1722 case 'l': 1723 if (n == 0) 1724 n = 1; 1725 sp = swablong(sp, n); 1726 break; 1727 1728 case 'q': 1729 if (n == 0) 1730 n = 1; 1731 sp = swabquad(sp, n); 1732 break; 1733 1734 case 'b': 1735 if (n == 0) 1736 n = 1; 1737 sp += n; 1738 break; 1739 1740 default: 1741 fprintf(stderr, "Unknown conversion character: %c\n", 1742 *cp); 1743 done(0); 1744 break; 1745 } 1746 cp++; 1747 n = 0; 1748 } 1749 } 1750 1751 static u_long 1752 swabl(u_long x) 1753 { 1754 swabst((u_char *)"l", (u_char *)&x); 1755 return (x); 1756 } 1757