1 /* 2 * Copyright (c) 1983 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 8 /* All Rights Reserved */ 9 10 /* 11 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 12 * Use is subject to license terms. 13 */ 14 15 #include <setjmp.h> 16 #include "restore.h" 17 #include <byteorder.h> 18 #include <rmt.h> 19 #include <sys/mtio.h> 20 #include <utime.h> 21 #include <sys/errno.h> 22 #include <sys/fdio.h> 23 #include <sys/sysmacros.h> /* for expdev */ 24 #include <assert.h> 25 #include <limits.h> 26 #include <priv_utils.h> 27 #include <aclutils.h> 28 29 #define MAXINO 65535 /* KLUDGE */ 30 31 #define MAXTAPES 128 32 33 static size_t fssize = MAXBSIZE; /* preferred size of writes to filesystem */ 34 int mt = -1; 35 static int continuemap = 0; 36 char magtape[BUFSIZ]; 37 int pipein = 0; 38 char *host; /* used in dumprmt.c */ 39 daddr32_t rec_position; 40 static char *archivefile; /* used in metamucil.c */ 41 static int bct; /* block # index into tape record buffer */ 42 static int numtrec; /* # of logical blocks in current tape record */ 43 static char *tbf = NULL; 44 static size_t tbfsize = 0; 45 static int recsread; 46 union u_spcl u_spcl; 47 static union u_spcl endoftapemark; 48 static struct s_spcl dumpinfo; 49 static long blksread; /* # of logical blocks actually read/touched */ 50 static long tapea; /* current logical block # on tape */ 51 static uchar_t tapesread[MAXTAPES]; 52 static jmp_buf restart; 53 static int gettingfile = 0; /* restart has a valid frame */ 54 static int ofile; 55 static char *map, *beginmap; 56 static char *endmap; 57 static char lnkbuf[MAXPATHLEN + 2]; 58 static int pathlen; 59 static int inodeinfo; /* Have starting volume information */ 60 static int hostinfo; /* Have dump host information */ 61 62 static int autoload_tape(void); 63 static void setdumpnum(void); 64 static void metacheck(struct s_spcl *); 65 static void xtrmeta(char *, size_t); 66 static void metaskip(char *, size_t); 67 static void xtrfile(char *, size_t); 68 static void xtrskip(char *, size_t); 69 static void xtrlnkfile(char *, size_t); 70 static void xtrlnkskip(char *, size_t); 71 static void xtrmap(char *, size_t); 72 static void xtrmapskip(char *, size_t); 73 static void readtape(char *); 74 static int checkvol(struct s_spcl *, int); 75 static void accthdr(struct s_spcl *); 76 static int ishead(struct s_spcl *); 77 static int checktype(struct s_spcl *, int); 78 static void metaset(char *name); 79 80 /* 81 * Set up an input source 82 */ 83 void 84 setinput(char *source, char *archive) 85 { 86 87 flsht(); 88 archivefile = archive; 89 if (bflag == 0) { 90 ntrec = ((CARTRIDGETREC > HIGHDENSITYTREC) ? 91 (NTREC > CARTRIDGETREC ? NTREC : CARTRIDGETREC) : 92 (NTREC > HIGHDENSITYTREC ? NTREC : HIGHDENSITYTREC)); 93 saved_ntrec = (ntrec * (tp_bsize/DEV_BSIZE)); 94 } 95 newtapebuf(ntrec); 96 terminal = stdin; 97 98 if (source == NULL) { 99 /* A can't-happen */ 100 (void) fprintf(stderr, 101 gettext("Internal consistency check failed.\n")); 102 done(1); 103 } 104 105 if (strchr(source, ':')) { 106 char *tape; 107 108 host = source; 109 tape = strchr(host, ':'); 110 *tape++ = '\0'; 111 if (strlen(tape) > (sizeof (magtape) - 1)) { 112 (void) fprintf(stderr, gettext("Tape name too long\n")); 113 done(1); 114 } 115 (void) strcpy(magtape, tape); 116 if (rmthost(host, ntrec) == 0) 117 done(1); 118 } else { 119 if (strlen(source) > (sizeof (magtape) - 1)) { 120 (void) fprintf(stderr, gettext("Tape name too long\n")); 121 done(1); 122 } 123 /* Not remote, no need for privileges */ 124 __priv_relinquish(); 125 host = NULL; 126 if (strcmp(source, "-") == 0) { 127 /* 128 * Since input is coming from a pipe we must establish 129 * our own connection to the terminal. 130 */ 131 terminal = fopen("/dev/tty", "r"); 132 if (terminal == NULL) { 133 int saverr = errno; 134 char *msg = 135 gettext("Cannot open(\"/dev/tty\")"); 136 errno = saverr; 137 perror(msg); 138 terminal = fopen("/dev/null", "r"); 139 if (terminal == NULL) { 140 saverr = errno; 141 msg = gettext( 142 "Cannot open(\"/dev/null\")"); 143 errno = saverr; 144 perror(msg); 145 done(1); 146 } 147 } 148 pipein++; 149 if (archive) { 150 (void) fprintf(stderr, gettext( 151 "Cannot specify an archive file when reading from a pipe\n")); 152 done(1); 153 } 154 } 155 (void) strcpy(magtape, source); 156 } 157 } 158 159 void 160 newtapebuf(size_t size) 161 { 162 size_t nsize; 163 164 nsize = size * tp_bsize; 165 ntrec = size; 166 if (nsize <= tbfsize) 167 return; 168 if (tbf != NULL) 169 free(tbf); 170 tbf = (char *)malloc(nsize); 171 if (tbf == NULL) { 172 (void) fprintf(stderr, 173 gettext("Cannot allocate space for buffer\n")); 174 done(1); 175 } 176 tbfsize = nsize; 177 } 178 179 /* 180 * Verify that the tape drive can be accessed and 181 * that it actually is a dump tape. 182 */ 183 void 184 setup(void) 185 { 186 int i, j; 187 int32_t *ip; 188 struct stat stbuf; 189 size_t mapsize; 190 char *syment = RESTORESYMTABLE; 191 192 vprintf(stdout, gettext("Verify volume and initialize maps\n")); 193 if (archivefile) { 194 mt = open(archivefile, O_RDONLY|O_LARGEFILE); 195 if (mt < 0) { 196 perror(archivefile); 197 done(1); 198 } 199 volno = 0; 200 } else if (host) { 201 if ((mt = rmtopen(magtape, O_RDONLY)) < 0) { 202 perror(magtape); 203 done(1); 204 } 205 volno = 1; 206 } else { 207 if (pipein) 208 mt = 0; 209 else if ((mt = open(magtape, O_RDONLY|O_LARGEFILE)) < 0) { 210 perror(magtape); 211 done(1); 212 } 213 volno = 1; 214 } 215 setdumpnum(); 216 flsht(); 217 if (!pipein && !bflag) 218 if (archivefile) 219 findtapeblksize(ARCHIVE_FILE); 220 else 221 findtapeblksize(TAPE_FILE); 222 if (bflag == 1) { 223 tape_rec_size = saved_ntrec * DEV_BSIZE; 224 } 225 226 /* 227 * Get the first header. If c_magic is NOT NFS_MAGIC or if 228 * the checksum is in error, it will fail. The magic could then 229 * be either OFS_MAGIC or MTB_MAGIC. If OFS_MAGIC, assume we 230 * have an old dump, and try to convert it. If it is MTB_MAGIC, we 231 * procees this after. 232 */ 233 if ((gethead(&spcl) == FAIL) && (spcl.c_magic != MTB_MAGIC)) { 234 bct--; /* push back this block */ 235 blksread--; 236 tapea--; 237 cvtflag++; 238 if (gethead(&spcl) == FAIL) { 239 (void) fprintf(stderr, 240 gettext("Volume is not in dump format\n")); 241 done(1); 242 } 243 (void) fprintf(stderr, 244 gettext("Converting to new file system format.\n")); 245 } 246 /* 247 * The above gethead will have failed if the magic is 248 * MTB_MAGIC. If that is true, we need to adjust tp_bsize. 249 * We have assumed to this time that tp_bsize was 1024, if 250 * this is a newer dump, get the real tp_bsize from the header, 251 * and recalculate ntrec, numtrec. 252 */ 253 if (spcl.c_magic == MTB_MAGIC) { 254 tp_bsize = spcl.c_tpbsize; 255 if ((tp_bsize % TP_BSIZE_MIN != 0) || 256 (tp_bsize > TP_BSIZE_MAX)) { 257 (void) fprintf(stderr, 258 gettext("Volume is not in dump format\n")); 259 done(1); 260 } 261 ntrec = (tape_rec_size/tp_bsize); 262 numtrec = ntrec; 263 newtapebuf(ntrec); 264 bct--; /* push back this block */ 265 blksread--; 266 tapea--; 267 /* we have to re-do this in case checksum is wrong */ 268 if (gethead(&spcl) == FAIL) { 269 (void) fprintf(stderr, 270 gettext("Volume is not in dump format\n")); 271 done(1); 272 } 273 } 274 if (vflag) 275 byteorder_banner(byteorder, stdout); 276 if (pipein) { 277 endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : 278 ((tp_bsize == TP_BSIZE_MIN) ? NFS_MAGIC : MTB_MAGIC); 279 endoftapemark.s_spcl.c_type = TS_END; 280 281 /* 282 * include this since the `resync' loop in findinode 283 * expects to find a header with the c_date field 284 * filled in. 285 */ 286 endoftapemark.s_spcl.c_date = spcl.c_date; 287 288 ip = (int32_t *)&endoftapemark; 289 /*LINTED [assertion always true]*/ 290 assert((sizeof (endoftapemark) % sizeof (int32_t)) == 0); 291 j = sizeof (endoftapemark) / sizeof (int32_t); 292 i = 0; 293 do 294 i += *ip++; 295 while (--j) 296 ; 297 endoftapemark.s_spcl.c_checksum = CHECKSUM - i; 298 } 299 if (vflag && command != 't') 300 printdumpinfo(); 301 dumptime = spcl.c_ddate; 302 dumpdate = spcl.c_date; 303 if (stat(".", &stbuf) < 0) { 304 perror(gettext("cannot stat .")); 305 done(1); 306 } 307 if (stbuf.st_blksize >= tp_bsize && stbuf.st_blksize <= MAXBSIZE) { 308 /* LINTED: value fits in a size_t */ 309 fssize = stbuf.st_blksize; 310 } else { 311 fssize = MAXBSIZE; 312 } 313 314 if (checkvol(&spcl, 1) == FAIL) { 315 (void) fprintf(stderr, 316 gettext("This is not volume 1 of the dump\n")); 317 done(1); 318 } 319 if (readhdr(&spcl) == FAIL) 320 panic(gettext("no header after volume mark!\n")); 321 322 findinode(&spcl); /* sets curfile, resyncs the tape if need be */ 323 if (checktype(&spcl, TS_CLRI) == FAIL) { 324 (void) fprintf(stderr, 325 gettext("Cannot find file removal list\n")); 326 done(1); 327 } 328 maxino = (unsigned)((spcl.c_count * tp_bsize * NBBY) + 1); 329 dprintf(stdout, "maxino = %lu\n", maxino); 330 /* 331 * Allocate space for at least MAXINO inodes to allow us 332 * to restore partial dump tapes written before dump was 333 * fixed to write out the entire inode map. 334 */ 335 if (maxino > ULONG_MAX) { 336 (void) fprintf(stderr, 337 gettext("file system too large\n")); 338 done(1); 339 } 340 /* LINTED maxino size-checked above */ 341 mapsize = (size_t)d_howmany(maxino > MAXINO ? maxino : MAXINO, NBBY); 342 beginmap = map = calloc((size_t)1, mapsize); 343 if (map == (char *)NIL) { 344 (void) fprintf(stderr, 345 gettext("no memory for file removal list\n")); 346 done(1); 347 } 348 endmap = map + mapsize; 349 clrimap = map; 350 curfile.action = USING; 351 continuemap = 1; 352 getfile(xtrmap, xtrmapskip); 353 if (MAXINO > maxino) 354 maxino = MAXINO; 355 if (checktype(&spcl, TS_BITS) == FAIL) { 356 /* if we have TS_CLRI then no TS_BITS then a TS_END */ 357 /* then we have an empty dump file */ 358 if (gethead(&spcl) == GOOD && 359 checktype(&spcl, TS_END) == GOOD) { 360 if ((command == 'r') || (command == 'R')) { 361 initsymtable(syment); 362 dumpsymtable(syment, volno); 363 } 364 done(0); 365 } 366 /* otherwise we have an error */ 367 (void) fprintf(stderr, gettext("Cannot find file dump list\n")); 368 done(1); 369 } 370 /* LINTED maxino size-checked above */ 371 mapsize = (size_t)d_howmany(maxino, NBBY); 372 beginmap = map = calloc((size_t)1, mapsize); 373 if (map == (char *)NULL) { 374 (void) fprintf(stderr, 375 gettext("no memory for file dump list\n")); 376 done(1); 377 } 378 endmap = map + mapsize; 379 dumpmap = map; 380 curfile.action = USING; 381 continuemap = 1; 382 getfile(xtrmap, xtrmapskip); 383 continuemap = 0; 384 } 385 386 /* 387 * Initialize fssize variable for 'R' command to work. 388 */ 389 void 390 setupR(void) 391 { 392 struct stat stbuf; 393 394 if (stat(".", &stbuf) < 0) { 395 perror(gettext("cannot stat .")); 396 done(1); 397 } 398 if (stbuf.st_blksize >= tp_bsize && stbuf.st_blksize <= MAXBSIZE) { 399 /* LINTED: value fits in a size_t */ 400 fssize = stbuf.st_blksize; 401 } else { 402 fssize = MAXBSIZE; 403 } 404 } 405 406 /* 407 * Prompt user to load a new dump volume. 408 * "Nextvol" is the next suggested volume to use. 409 * This suggested volume is enforced when doing full 410 * or incremental restores, but can be overrridden by 411 * the user when only extracting a subset of the files. 412 * 413 * first_time is used with archive files and can have 1 of 3 states: 414 * FT_STATE_1 Tape has not been read yet 415 * FT_STATE_2 Tape has been read but not positioned past directory 416 * information 417 * FT_STATE_3 Tape has been read and is reading file information 418 */ 419 #define FT_STATE_1 1 420 #define FT_STATE_2 2 421 #define FT_STATE_3 3 422 423 void 424 getvol(int nextvol) 425 { 426 int newvol; 427 long savecnt, savetapea, wantnext; 428 long i; 429 union u_spcl tmpspcl; 430 #define tmpbuf tmpspcl.s_spcl 431 char buf[TP_BSIZE_MAX]; 432 static int first_time = FT_STATE_1; 433 434 if (tbf == NULL) { 435 (void) fprintf(stderr, gettext( 436 "Internal consistency failure in getvol: tbf is NULL\n")); 437 done(1); 438 } 439 440 if (nextvol == 1) { 441 for (i = 0; i < MAXTAPES; i++) 442 tapesread[i] = 0; 443 gettingfile = 0; 444 } 445 if (pipein) { 446 if (nextvol != 1) 447 panic(gettext("changing volumes on pipe input\n")); 448 if (volno == 1) 449 return; 450 goto gethdr; 451 } 452 savecnt = blksread; /* ignore volume verification tape i/o */ 453 savetapea = tapea; 454 again: 455 if (pipein) 456 done(1); /* pipes do not get a second chance */ 457 if (command == 'R' || command == 'r' || curfile.action != SKIP) { 458 wantnext = 1; 459 newvol = nextvol; 460 } else { 461 wantnext = 0; 462 newvol = 0; 463 } 464 465 if (autoload) { 466 if ((volno == 1) && (nextvol == 1)) { 467 tapesread[volno-1]++; 468 return; 469 } 470 if (autoload_tape()) { 471 wantnext = 1; 472 newvol = nextvol; 473 goto gethdr; 474 } 475 } 476 477 while (newvol <= 0) { 478 int n = 0; 479 480 for (i = 0; i < MAXTAPES; i++) 481 if (tapesread[i]) 482 n++; 483 if (n == 0) { 484 (void) fprintf(stderr, "%s", gettext( 485 "You have not read any volumes yet.\n\ 486 Unless you know which volume your file(s) are on you should start\n\ 487 with the last volume and work towards the first.\n")); 488 } else { 489 (void) fprintf(stderr, 490 gettext("You have read volumes")); 491 (void) strcpy(tbf, ": "); 492 for (i = 0; i < MAXTAPES; i++) 493 if (tapesread[i]) { 494 (void) fprintf(stderr, "%s%ld", 495 tbf, i+1); 496 (void) strcpy(tbf, ", "); 497 } 498 (void) fprintf(stderr, "\n"); 499 } 500 do { 501 (void) fprintf(stderr, 502 gettext("Specify next volume #: ")); 503 (void) fflush(stderr); 504 /* LINTED tbfsize is limited to a few MB */ 505 (void) fgets(tbf, (int)tbfsize, terminal); 506 } while (!feof(terminal) && tbf[0] == '\n'); 507 if (feof(terminal)) 508 done(1); 509 newvol = atoi(tbf); 510 if (newvol <= 0) { 511 (void) fprintf(stderr, gettext( 512 "Volume numbers are positive numerics\n")); 513 } 514 if (newvol > MAXTAPES) { 515 (void) fprintf(stderr, gettext( 516 "This program can only deal with %d volumes\n"), 517 MAXTAPES); 518 newvol = 0; 519 } 520 } 521 if (newvol == volno) { 522 tapesread[volno-1]++; 523 return; 524 } 525 closemt(ALLOW_OFFLINE); 526 /* 527 * XXX: if we are switching devices, we should probably try 528 * the device once without prompting to enable unattended 529 * operation. 530 */ 531 if (host) 532 (void) fprintf(stderr, gettext( 533 "Mount volume %d\nthen enter volume name on host %s (default: %s) "), 534 newvol, host, magtape); 535 else 536 (void) fprintf(stderr, gettext( 537 "Mount volume %d\nthen enter volume name (default: %s) "), 538 newvol, magtape); 539 (void) fflush(stderr); 540 /* LINTED tbfsize is limited to a few MB */ 541 (void) fgets(tbf, (int)tbfsize, terminal); 542 if (feof(terminal)) 543 done(1); 544 /* 545 * XXX We don't allow rotating among tape hosts, just drives. 546 */ 547 if (tbf[0] != '\n') { 548 (void) strncpy(magtape, tbf, sizeof (magtape)); 549 magtape[sizeof (magtape) - 1] = '\0'; 550 /* LINTED unsigned -> signed conversion ok */ 551 i = (int)strlen(magtape); 552 if (magtape[i - 1] == '\n') 553 magtape[i - 1] = '\0'; 554 } 555 if ((host != NULL && (mt = rmtopen(magtape, O_RDONLY)) == -1) || 556 (host == NULL && 557 (mt = open(magtape, O_RDONLY|O_LARGEFILE)) == -1)) { 558 int error = errno; 559 (void) fprintf(stderr, gettext("Cannot open %s: %s\n"), 560 magtape, strerror(error)); 561 volno = -1; 562 goto again; 563 } 564 gethdr: 565 volno = newvol; 566 setdumpnum(); 567 flsht(); 568 if (!pipein && !bflag && archivefile && (first_time == FT_STATE_1)) { 569 first_time = FT_STATE_2; 570 findtapeblksize(TAPE_FILE); 571 } 572 if (readhdr(&tmpbuf) == FAIL) { 573 (void) fprintf(stderr, 574 gettext("volume is not in dump format\n")); 575 volno = 0; 576 goto again; 577 } 578 if (checkvol(&tmpbuf, volno) == FAIL) { 579 (void) fprintf(stderr, gettext("Wrong volume (%d)\n"), 580 tmpbuf.c_volume); 581 volno = 0; 582 goto again; 583 } 584 585 if (((time_t)(tmpbuf.c_date) != dumpdate) || 586 ((time_t)(tmpbuf.c_ddate) != dumptime)) { 587 char *tmp_ct; 588 time_t lc_date = (time_t)tmpbuf.c_date; 589 590 /* 591 * This is used to save the return value from lctime(), 592 * since that's volatile across lctime() invocations. 593 */ 594 tmp_ct = strdup(lctime(&lc_date)); 595 if (tmp_ct == (char *)0) { 596 (void) fprintf(stderr, gettext( 597 "Cannot allocate space for time string\n")); 598 done(1); 599 } 600 601 (void) fprintf(stderr, 602 gettext("Wrong dump date\n\tgot: %s\twanted: %s"), 603 tmp_ct, lctime(&dumpdate)); 604 volno = 0; 605 free(tmp_ct); 606 goto again; 607 } 608 tapesread[volno-1]++; 609 blksread = savecnt; 610 tapea = savetapea; 611 /* 612 * If continuing from the previous volume, skip over any 613 * blocks read already at the end of the previous volume. 614 * 615 * If coming to this volume at random, skip to the beginning 616 * of the next record. 617 */ 618 if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) { 619 if (!wantnext) { 620 if (archivefile && first_time == FT_STATE_2) { 621 first_time = FT_STATE_3; 622 } 623 recsread = tmpbuf.c_firstrec; 624 tapea = tmpbuf.c_tapea; 625 dprintf(stdout, 626 "restore skipping %d records\n", 627 tmpbuf.c_count); 628 for (i = tmpbuf.c_count; i > 0; i--) 629 readtape(buf); 630 } else if (tmpbuf.c_firstrec != 0) { 631 savecnt = blksread; 632 savetapea = tapea; 633 634 if (archivefile && first_time == FT_STATE_2) { 635 /* 636 * subtract 2, 1 for archive file's TS_END 637 * and 1 for tape's TS_TAPE 638 */ 639 first_time = FT_STATE_3; 640 i = tapea - tmpbuf.c_tapea - 2; 641 } else { 642 i = tapea - tmpbuf.c_tapea; 643 } 644 if (i > 0) 645 dprintf(stdout, gettext( 646 "restore skipping %d duplicate records\n"), 647 i); 648 else if (i < 0) 649 dprintf(stdout, gettext( 650 "restore duplicate record botch (%d)\n"), 651 i); 652 while (--i >= 0) 653 readtape(buf); 654 blksread = savecnt; 655 tapea = savetapea + 1; /* <= (void) gethead() below */ 656 } 657 } 658 if (curfile.action == USING) { 659 if (volno == 1) 660 panic(gettext("active file into volume 1\n")); 661 return; 662 } 663 (void) gethead(&spcl); 664 findinode(&spcl); /* do we always restart files in full? */ 665 if (gettingfile) { /* i.e. will we lose metadata? */ 666 gettingfile = 0; 667 longjmp(restart, 1); /* will this set f1 & f2? */ 668 } 669 } 670 671 /* 672 * handle multiple dumps per tape by skipping forward to the 673 * appropriate one. Note we don't use absolute positioning, 674 * as that may take a very long time. 675 */ 676 static void 677 setdumpnum(void) 678 { 679 struct mtop tcom; 680 int retval; 681 682 if (dumpnum == 1 || volno != 1) 683 return; 684 if (pipein) { 685 (void) fprintf(stderr, 686 gettext("Cannot have multiple dumps on pipe input\n")); 687 done(1); 688 } 689 tcom.mt_op = MTFSF; 690 tcom.mt_count = dumpnum - 1; 691 if (host) 692 retval = rmtioctl(MTFSF, dumpnum - 1); 693 else 694 retval = ioctl(mt, (int)MTIOCTOP, (char *)&tcom); 695 if (retval < 0) 696 perror("ioctl MTFSF"); 697 } 698 699 void 700 printdumpinfo(void) 701 { 702 int i; 703 time_t date; 704 static char *epoch = NULL; 705 706 if (epoch == NULL) { 707 epoch = strdup(gettext("the epoch\n")); 708 if (epoch == NULL) { 709 (void) fprintf(stderr, gettext("Out of memory\n")); 710 return; 711 } 712 } 713 714 date = (time_t)dumpinfo.c_date; 715 (void) fprintf(stdout, 716 gettext("Dump date: %s"), lctime(&date)); 717 718 date = (time_t)dumpinfo.c_ddate; 719 (void) fprintf(stdout, gettext("Dumped from: %s"), 720 (dumpinfo.c_ddate == 0) ? epoch : lctime(&date)); 721 if (hostinfo) { 722 (void) fprintf(stdout, 723 gettext("Level %d dump of %s on %.*s:%s\n"), 724 dumpinfo.c_level, dumpinfo.c_filesys, 725 sizeof (dumpinfo.c_host), dumpinfo.c_host, dumpinfo.c_dev); 726 (void) fprintf(stdout, 727 gettext("Label: %.*s\n"), 728 sizeof (dumpinfo.c_label), dumpinfo.c_label); 729 } 730 if (inodeinfo) { 731 (void) fprintf(stdout, 732 gettext("Starting inode numbers by volume:\n")); 733 for (i = 1; i <= dumpinfo.c_volume; i++) 734 (void) fprintf(stdout, gettext("\tVolume %d: %6d\n"), 735 i, dumpinfo.c_inos[i]); 736 } 737 } 738 739 int 740 extractfile(char *name) 741 { 742 static int complained_chown = 0; 743 static int complained_lchown = 0; 744 static int complained_chmod = 0; 745 static int complained_utime = 0; 746 static int complained_mknod = 0; 747 mode_t mode; 748 time_t timep[2]; 749 struct entry *ep; 750 uid_t uid; 751 gid_t gid; 752 char *errmsg; 753 int result, saverr; 754 dev_t full_dev; 755 int dfd; 756 char *rname; 757 758 curfile.name = name; 759 curfile.action = USING; 760 timep[0] = (time_t)curfile.dip->di_atime; 761 timep[1] = (time_t)curfile.dip->di_mtime; 762 mode = curfile.dip->di_mode; 763 764 uid = curfile.dip->di_suid == UID_LONG ? 765 curfile.dip->di_uid : (uid_t)curfile.dip->di_suid; 766 gid = curfile.dip->di_sgid == GID_LONG ? 767 curfile.dip->di_gid : (gid_t)curfile.dip->di_sgid; 768 769 resolve(name, &dfd, &rname); 770 if (dfd != AT_FDCWD) { 771 if (fchdir(dfd) < 0) { 772 saverr = errno; 773 (void) fprintf(stderr, gettext( 774 "%s: unable to set attribute context: %s\n"), 775 rname, strerror(saverr)); 776 skipfile(); 777 (void) close(dfd); 778 return (FAIL); 779 } 780 } 781 782 switch (mode & IFMT) { 783 784 default: 785 (void) fprintf(stderr, gettext("%s: unknown file mode 0%lo\n"), 786 rname, (ulong_t)(mode&IFMT)); 787 skipfile(); 788 result = FAIL; 789 break; 790 791 case IFSOCK: 792 vprintf(stdout, gettext("skipped socket %s\n"), rname); 793 skipfile(); 794 result = GOOD; 795 break; 796 797 case IFDIR: 798 if (mflag) { 799 ep = lookupname(name); 800 if (ep == NIL || ep->e_flags & EXTRACT) { 801 panic(gettext( 802 "directory %s was not restored\n"), 803 rname); 804 skipfile(); 805 result = FAIL; 806 break; 807 } 808 skipfile(); 809 result = GOOD; 810 break; 811 } 812 vprintf(stdout, gettext("extract file %s\n"), rname); 813 result = genliteraldir(rname, curfile.ino); 814 break; 815 816 case IFLNK: 817 lnkbuf[0] = '\0'; 818 pathlen = 0; 819 getfile(xtrlnkfile, xtrlnkskip); 820 if (pathlen == 0) { 821 vprintf(stdout, gettext( 822 "%s: zero length symbolic link (ignored)\n"), 823 rname); 824 result = GOOD; 825 break; 826 } 827 if ((result = lf_linkit(lnkbuf, rname, SYMLINK)) != GOOD) 828 break; 829 830 /* 1254700: set uid/gid (previously missing) */ 831 if (lchown(rname, uid, gid) < 0 && !complained_lchown) { 832 /* Just a warning */ 833 saverr = errno; 834 errmsg = gettext( 835 "Unable to restore ownership of symlink %s: %s\n"); 836 (void) fprintf(stderr, errmsg, 837 rname, strerror(saverr)); 838 (void) fprintf(stderr, gettext( 839 "Additional such failures will be ignored.\n")); 840 complained_lchown = 1; 841 } 842 metaset(rname); 843 result = GOOD; 844 break; 845 846 case IFCHR: 847 case IFBLK: 848 case IFIFO: 849 vprintf(stdout, gettext("extract special file %s\n"), rname); 850 /* put device rdev into dev_t expanded format */ 851 /* XXX does this always do the right thing? */ 852 /* XXX does dump do the right thing? */ 853 if (((curfile.dip->di_ordev & 0xFFFF0000) == 0) || 854 ((curfile.dip->di_ordev & 0xFFFF0000) == 0xFFFF0000)) { 855 full_dev = expdev((unsigned)(curfile.dip->di_ordev)); 856 } else { 857 /* LINTED sign extension ok */ 858 full_dev = (unsigned)(curfile.dip->di_ordev); 859 } 860 861 if (mknod(rname, mode, full_dev) < 0) { 862 struct stat64 s[1]; 863 864 saverr = errno; 865 if ((stat64(rname, s)) || 866 ((s->st_mode & S_IFMT) != (mode & S_IFMT)) || 867 (s->st_rdev != full_dev)) { 868 if (saverr != EPERM || !complained_mknod) { 869 (void) fprintf(stderr, "%s: ", rname); 870 (void) fflush(stderr); 871 errno = saverr; 872 perror(gettext( 873 "cannot create special file")); 874 if (saverr == EPERM) { 875 (void) fprintf(stderr, gettext( 876 "Additional such failures will be ignored.\n")); 877 complained_mknod = 1; 878 } 879 } 880 skipfile(); 881 result = FAIL; 882 break; 883 } 884 } 885 if (chown(rname, uid, gid) < 0 && !complained_chown) { 886 /* Just a warning */ 887 saverr = errno; 888 errmsg = gettext( 889 "Unable to restore ownership of %s: %s\n"); 890 (void) fprintf(stderr, errmsg, 891 rname, strerror(saverr)); 892 (void) fprintf(stderr, gettext( 893 "Additional such failures will be ignored.\n")); 894 complained_chown = 1; 895 } 896 if (chmod(rname, mode) < 0 && !complained_chmod) { 897 saverr = errno; 898 errmsg = gettext( 899 "Unable to restore permissions on %s: %s\n"); 900 (void) fprintf(stderr, errmsg, 901 rname, strerror(saverr)); 902 (void) fprintf(stderr, gettext( 903 "Additional such failures will be ignored.\n")); 904 complained_chmod = 1; 905 } 906 skipfile(); 907 metaset(rname); /* skipfile() got the metadata, if any */ 908 if (utime(rname, (struct utimbuf *)timep) < 0 && 909 !complained_utime) { 910 saverr = errno; 911 errmsg = gettext( 912 "Unable to restore times on %s: %s\n"); 913 (void) fprintf(stderr, errmsg, 914 rname, strerror(saverr)); 915 (void) fprintf(stderr, gettext( 916 "Additional such failures will be ignored.\n")); 917 complained_utime = 1; 918 } 919 result = GOOD; 920 break; 921 922 case IFREG: 923 vprintf(stdout, gettext("extract file %s\n"), rname); 924 925 /* 926 * perform a restrictive creat(2) initally, we'll 927 * fchmod(2) according to the archive later after 928 * we've written the blocks. 929 */ 930 ofile = creat64(rname, 0600); 931 932 if (ofile < 0) { 933 saverr = errno; 934 errmsg = gettext("cannot create file"); 935 (void) fprintf(stderr, "%s: ", rname); 936 (void) fflush(stderr); 937 errno = saverr; 938 perror(errmsg); 939 skipfile(); 940 result = FAIL; 941 break; 942 } 943 if (fchown(ofile, uid, gid) < 0 && !complained_chown) { 944 /* Just a warning */ 945 saverr = errno; 946 errmsg = gettext( 947 "Unable to restore ownership of %s: %s\n"); 948 (void) fprintf(stderr, errmsg, 949 rname, strerror(saverr)); 950 (void) fprintf(stderr, gettext( 951 "Additional such failures will be ignored.\n")); 952 complained_chown = 1; 953 } 954 955 getfile(xtrfile, xtrskip); 956 metaset(rname); 957 958 /* 959 * the fchmod(2) has to come after getfile() as some POSIX 960 * implementations clear the S_ISUID and S_ISGID bits of the 961 * file after every write(2). 962 */ 963 if (fchmod(ofile, mode) < 0 && !complained_chmod) { 964 saverr = errno; 965 errmsg = gettext( 966 "Unable to restore permissions on %s: %s\n"); 967 (void) fprintf(stderr, errmsg, 968 rname, strerror(saverr)); 969 (void) fprintf(stderr, gettext( 970 "Additional such failures will be ignored.\n")); 971 complained_chmod = 1; 972 } 973 974 /* 975 * Some errors don't get reported until we close(2), so 976 * check for them. 977 * XXX unlink the file if an error is reported? 978 */ 979 if (close(ofile) < 0) { 980 saverr = errno; 981 errmsg = gettext("error closing file"); 982 (void) fprintf(stderr, "%s: ", rname); 983 (void) fflush(stderr); 984 errno = saverr; 985 perror(errmsg); 986 result = FAIL; 987 break; 988 } 989 if (utime(rname, (struct utimbuf *)timep) < 0 && 990 !complained_utime) { 991 saverr = errno; 992 errmsg = gettext( 993 "Unable to restore times on %s: %s\n"); 994 (void) fprintf(stderr, errmsg, 995 rname, strerror(saverr)); 996 (void) fprintf(stderr, gettext( 997 "Additional such failures will be ignored.\n")); 998 complained_utime = 1; 999 } 1000 1001 result = GOOD; 1002 break; 1003 } 1004 if (dfd != AT_FDCWD) { 1005 fchdir(savepwd); 1006 (void) close(dfd); 1007 } 1008 return (result); 1009 } 1010 1011 /* 1012 * skip over bit maps on the tape 1013 */ 1014 void 1015 skipmaps(void) 1016 { 1017 continuemap = 1; 1018 while (checktype(&spcl, TS_CLRI) == GOOD || 1019 checktype(&spcl, TS_BITS) == GOOD) 1020 skipfile(); 1021 continuemap = 0; 1022 } 1023 1024 /* 1025 * skip over a file on the tape 1026 */ 1027 void 1028 skipfile(void) 1029 { 1030 curfile.action = SKIP; 1031 getfile(null, null); 1032 } 1033 /* 1034 * Do the file extraction, calling the supplied functions 1035 * with the blocks 1036 */ 1037 void 1038 getfile(void (*f1)(), void (*f2)()) 1039 { 1040 int i; 1041 size_t curblk = 0; 1042 offset_t size = (offset_t)spcl.c_dinode.di_size; 1043 static char clearedbuf[MAXBSIZE]; 1044 char buf[TP_BSIZE_MAX]; 1045 char *bufptr; 1046 char junk[TP_BSIZE_MAX]; 1047 1048 assert(MAXBSIZE >= tp_bsize); 1049 1050 metaset(NULL); /* flush old metadata */ 1051 if (checktype(&spcl, TS_END) == GOOD) { 1052 panic(gettext("ran off end of volume\n")); 1053 return; 1054 } 1055 if (ishead(&spcl) == FAIL) { 1056 panic(gettext("not at beginning of a file\n")); 1057 return; 1058 } 1059 metacheck(&spcl); /* check for metadata in header */ 1060 if (!gettingfile && setjmp(restart) != 0) { 1061 gettingfile = 0; /* paranoia; longjmp'er should do */ 1062 return; 1063 } 1064 gettingfile++; 1065 loop: 1066 if ((spcl.c_dinode.di_mode & IFMT) == IFSHAD) { 1067 f1 = xtrmeta; 1068 f2 = metaskip; 1069 } 1070 for (i = 0, bufptr = buf; i < spcl.c_count; i++) { 1071 if ((i >= TP_NINDIR) || (spcl.c_addr[i])) { 1072 readtape(bufptr); 1073 bufptr += tp_bsize; 1074 curblk++; 1075 if (curblk == (fssize / tp_bsize)) { 1076 (*f1)(buf, size > tp_bsize ? 1077 (size_t)(fssize) : 1078 /* LINTED size <= tp_bsize */ 1079 (curblk - 1) * tp_bsize + (size_t)size); 1080 curblk = 0; 1081 bufptr = buf; 1082 } 1083 } else { 1084 if (curblk > 0) { 1085 (*f1)(buf, size > tp_bsize ? 1086 (size_t)(curblk * tp_bsize) : 1087 /* LINTED size <= tp_bsize */ 1088 (curblk - 1) * tp_bsize + (size_t)size); 1089 curblk = 0; 1090 bufptr = buf; 1091 } 1092 (*f2)(clearedbuf, size > tp_bsize ? 1093 /* LINTED size <= tp_bsize */ 1094 (long)tp_bsize : (size_t)size); 1095 } 1096 if ((size -= tp_bsize) <= 0) { 1097 for (i++; i < spcl.c_count; i++) 1098 if ((i >= TP_NINDIR) || (spcl.c_addr[i])) 1099 readtape(junk); 1100 break; 1101 } 1102 } 1103 if (curblk > 0) { 1104 /* 1105 * Ok to cast size to size_t here. The above for loop reads 1106 * data into the buffer then writes it to the output file. The 1107 * call to f1 here is to write out the data that's in the 1108 * buffer that has not yet been written to the file. 1109 * This will be less than N-KB of data, since the 1110 * above loop writes to the file in filesystem- 1111 * blocksize chunks. 1112 */ 1113 /* LINTED: size fits into a size_t at this point */ 1114 (*f1)(buf, (curblk * tp_bsize) + (size_t)size); 1115 1116 curblk = 0; 1117 bufptr = buf; 1118 } 1119 if ((readhdr(&spcl) == GOOD) && (checktype(&spcl, TS_ADDR) == GOOD)) { 1120 if (continuemap) 1121 size = (offset_t)spcl.c_count * tp_bsize; 1122 /* big bitmap */ 1123 else if ((size <= 0) && 1124 ((spcl.c_dinode.di_mode & IFMT) == IFSHAD)) { 1125 /* LINTED unsigned to signed conversion ok */ 1126 size = spcl.c_dinode.di_size; 1127 } 1128 if (size > 0) 1129 goto loop; 1130 } 1131 if (size > 0) 1132 dprintf(stdout, 1133 gettext("Missing address (header) block for %s\n"), 1134 curfile.name); 1135 findinode(&spcl); 1136 gettingfile = 0; 1137 } 1138 1139 /* 1140 * The next routines are called during file extraction to 1141 * put the data into the right form and place. 1142 */ 1143 static void 1144 xtrfile(char *buf, size_t size) 1145 { 1146 if (write(ofile, buf, (size_t)size) == -1) { 1147 int saverr = errno; 1148 (void) fprintf(stderr, 1149 gettext("write error extracting inode %d, name %s\n"), 1150 curfile.ino, curfile.name); 1151 errno = saverr; 1152 perror("write"); 1153 done(1); 1154 } 1155 } 1156 1157 /* 1158 * Even though size is a size_t, it's seeking to a relative 1159 * offset. Thus, the seek could go beyond 2 GB, so lseek64 is needed. 1160 */ 1161 1162 /*ARGSUSED*/ 1163 static void 1164 xtrskip(char *buf, size_t size) 1165 { 1166 if (lseek64(ofile, (offset_t)size, 1) == -1) { 1167 int saverr = errno; 1168 (void) fprintf(stderr, 1169 gettext("seek error extracting inode %d, name %s\n"), 1170 curfile.ino, curfile.name); 1171 errno = saverr; 1172 perror("lseek64"); 1173 done(1); 1174 } 1175 } 1176 1177 /* these are local to the next five functions */ 1178 static char *metadata = NULL; 1179 static size_t metasize = 0; 1180 1181 static void 1182 metacheck(struct s_spcl *head) 1183 { 1184 if (! (head->c_flags & DR_HASMETA)) 1185 return; 1186 if ((metadata = malloc(metasize = (size_t)sizeof (head->c_shadow))) 1187 == NULL) { 1188 (void) fprintf(stderr, 1189 gettext("Cannot malloc for metadata\n")); 1190 done(1); 1191 } 1192 bcopy(&(head->c_shadow), metadata, metasize); 1193 } 1194 1195 static void 1196 xtrmeta(char *buf, size_t size) 1197 { 1198 if ((metadata == NULL) && ((spcl.c_dinode.di_mode & IFMT) != IFSHAD)) 1199 return; 1200 if ((metadata = realloc(metadata, metasize + size)) == NULL) { 1201 (void) fprintf(stderr, 1202 gettext("Cannot malloc for metadata\n")); 1203 done(1); 1204 } 1205 bcopy(buf, metadata + metasize, size); 1206 metasize += size; 1207 } 1208 1209 /* ARGSUSED */ 1210 static void 1211 metaskip(char *buf, size_t size) 1212 { 1213 if (metadata == NULL) 1214 return; 1215 if ((metadata = realloc(metadata, metasize + size)) == NULL) { 1216 (void) fprintf(stderr, 1217 gettext("Cannot malloc for metadata\n")); 1218 done(1); 1219 } 1220 bzero(metadata + metasize, size); 1221 metasize += size; 1222 } 1223 1224 static void 1225 metaset(char *name) 1226 { 1227 if (metadata == NULL) 1228 return; 1229 if (name != NULL) 1230 metaproc(name, metadata, metasize); 1231 (void) free(metadata); 1232 metadata = NULL; 1233 metasize = 0; 1234 } 1235 1236 void 1237 metaget(char **data, size_t *size) 1238 { 1239 *data = metadata; 1240 *size = metasize; 1241 } 1242 1243 static void 1244 fsd_acl(char *name, char *aclp, unsigned size) 1245 { 1246 static aclent_t *aclent = NULL; 1247 ufs_acl_t *diskacl; 1248 static int n = 0; 1249 acl_t *set_aclp; 1250 uint_t i; 1251 int saverr, j; 1252 1253 if (aclp == NULL) { 1254 if (aclent != NULL) 1255 free(aclent); 1256 aclent = NULL; 1257 n = 0; 1258 return; 1259 } 1260 1261 /*LINTED [aclp is malloc'd]*/ 1262 diskacl = (ufs_acl_t *)aclp; 1263 /* LINTED: result fits in an int */ 1264 j = size / sizeof (*diskacl); 1265 normacls(byteorder, diskacl, j); 1266 1267 i = n; 1268 n += j; 1269 aclent = realloc(aclent, n * (size_t)sizeof (*aclent)); 1270 if (aclent == NULL) { 1271 (void) fprintf(stderr, gettext("Cannot malloc acl list\n")); 1272 done(1); 1273 } 1274 1275 j = 0; 1276 while (i < n) { 1277 aclent[i].a_type = diskacl[j].acl_tag; 1278 aclent[i].a_id = diskacl[j].acl_who; 1279 aclent[i].a_perm = diskacl[j].acl_perm; 1280 ++i; 1281 ++j; 1282 } 1283 1284 set_aclp = acl_to_aclp(ACLENT_T, aclent, n); 1285 if (set_aclp == NULL) { 1286 (void) fprintf(stderr, gettext("Cannot build acl_t\n")); 1287 done(1); 1288 } 1289 1290 if (acl_set(name, set_aclp) == -1) { 1291 static int once = 0; 1292 1293 /* 1294 * Treat some errors from the acl subsystem specially to 1295 * avoid being too noisy: 1296 * 1297 * ENOSYS - ACLs not supported on this file system 1298 * EPERM - not the owner or not privileged 1299 * 1300 * The following is also supported for backwards compat. 1301 * since acl(2) used to return the wrong errno: 1302 * 1303 * EINVAL - not the owner of the object 1304 */ 1305 if (errno == ENOSYS || errno == EPERM || errno == EINVAL) { 1306 if (once == 0) { 1307 saverr = errno; 1308 ++once; 1309 fprintf(stderr, 1310 gettext("setacl failed: %s\n"), 1311 strerror(saverr)); 1312 } 1313 } else { 1314 saverr = errno; 1315 fprintf(stderr, gettext("setacl on %s failed: %s\n"), 1316 name, strerror(saverr)); 1317 } 1318 } 1319 acl_free(set_aclp); 1320 } 1321 1322 static struct fsdtypes { 1323 int type; 1324 void (*function)(); 1325 } fsdtypes[] = { 1326 {FSD_ACL, fsd_acl}, 1327 {FSD_DFACL, fsd_acl}, 1328 {0, NULL} 1329 }; 1330 1331 void 1332 metaproc(char *name, char *mdata, size_t msize) 1333 { 1334 struct fsdtypes *fsdtype; 1335 ufs_fsd_t *fsd; 1336 char *c; 1337 1338 /* 1339 * for the whole shadow inode, dispatch each piece 1340 * to the appropriate function. 1341 */ 1342 c = mdata; 1343 /* LINTED (c - mdata) fits into a size_t */ 1344 while ((size_t)(c - mdata) < msize) { 1345 /*LINTED [mdata is malloc'd]*/ 1346 fsd = (ufs_fsd_t *)c; 1347 assert((fsd->fsd_size % 4) == 0); 1348 /* LINTED: lint thinks pointers are signed */ 1349 c += FSD_RECSZ(fsd, fsd->fsd_size); 1350 if ((fsd->fsd_type == FSD_FREE) || 1351 ((unsigned)(fsd->fsd_size) <= sizeof (ufs_fsd_t)) || 1352 (c > (mdata + msize))) 1353 break; 1354 for (fsdtype = fsdtypes; fsdtype->type; fsdtype++) 1355 if (fsdtype->type == fsd->fsd_type) 1356 (*fsdtype->function)(name, fsd->fsd_data, 1357 (unsigned)(fsd->fsd_size) - 1358 sizeof (fsd->fsd_type) - 1359 sizeof (fsd->fsd_size)); 1360 /* ^^^ be sure to change if fsd ever changes ^^^ */ 1361 } 1362 1363 /* reset the state of all the functions */ 1364 for (fsdtype = fsdtypes; fsdtype->type; fsdtype++) 1365 (*fsdtype->function)(NULL, NULL, 0); 1366 } 1367 1368 static void 1369 xtrlnkfile(char *buf, size_t size) 1370 { 1371 /* LINTED: signed/unsigned mix ok */ 1372 pathlen += size; 1373 if (pathlen > MAXPATHLEN) { 1374 (void) fprintf(stderr, 1375 gettext("symbolic link name: %s->%s%s; too long %d\n"), 1376 curfile.name, lnkbuf, buf, pathlen); 1377 done(1); 1378 } 1379 buf[size] = '\0'; 1380 (void) strcat(lnkbuf, buf); 1381 /* add an extra NULL to make this a legal complex string */ 1382 lnkbuf[pathlen+1] = '\0'; 1383 } 1384 1385 /*ARGSUSED*/ 1386 static void 1387 xtrlnkskip(char *buf, size_t size) 1388 { 1389 (void) fprintf(stderr, 1390 gettext("unallocated block in symbolic link %s\n"), 1391 curfile.name); 1392 done(1); 1393 } 1394 1395 static void 1396 xtrmap(char *buf, size_t size) 1397 { 1398 if ((map+size) > endmap) { 1399 int64_t mapsize, increment; 1400 int64_t diff; 1401 1402 if (spcl.c_type != TS_ADDR) { 1403 (void) fprintf(stderr, 1404 gettext("xtrmap: current record not TS_ADDR\n")); 1405 done(1); 1406 } 1407 if ((spcl.c_count < 0) || (spcl.c_count > TP_NINDIR)) { 1408 (void) fprintf(stderr, 1409 gettext("xtrmap: illegal c_count field (%d)\n"), 1410 spcl.c_count); 1411 done(1); 1412 } 1413 1414 increment = d_howmany( 1415 ((spcl.c_count * tp_bsize * NBBY) + 1), NBBY); 1416 mapsize = endmap - beginmap + increment; 1417 if (mapsize > UINT_MAX) { 1418 (void) fprintf(stderr, 1419 gettext("xtrmap: maximum bitmap size exceeded")); 1420 done(1); 1421 } 1422 1423 diff = map - beginmap; 1424 /* LINTED mapsize checked above */ 1425 beginmap = realloc(beginmap, (size_t)mapsize); 1426 if (beginmap == NULL) { 1427 (void) fprintf(stderr, 1428 gettext("xtrmap: realloc failed\n")); 1429 done(1); 1430 } 1431 map = beginmap + diff; 1432 endmap = beginmap + mapsize; 1433 /* LINTED endmap - map cannot exceed 32 bits */ 1434 bzero(map, (size_t)(endmap - map)); 1435 maxino = NBBY * mapsize + 1; 1436 } 1437 1438 bcopy(buf, map, size); 1439 /* LINTED character pointers aren't signed */ 1440 map += size; 1441 } 1442 1443 /*ARGSUSED*/ 1444 static void 1445 xtrmapskip(char *buf, size_t size) 1446 { 1447 (void) fprintf(stderr, gettext("hole in map\n")); 1448 done(1); 1449 } 1450 1451 /*ARGSUSED*/ 1452 void 1453 null(char *buf, size_t size) 1454 { 1455 } 1456 1457 /* 1458 * Do the tape i/o, dealing with volume changes 1459 * etc.. 1460 */ 1461 static void 1462 readtape(char *b) 1463 { 1464 int i; 1465 int rd, newvol; 1466 int cnt; 1467 struct s_spcl *sp; 1468 int32_t expected_magic; 1469 1470 if (tbf == NULL) { 1471 (void) fprintf(stderr, gettext( 1472 "Internal consistency failure in readtape: tbf is NULL\n")); 1473 done(1); 1474 } 1475 expected_magic = ((tp_bsize == TP_BSIZE_MIN) ? NFS_MAGIC : MTB_MAGIC); 1476 1477 top: 1478 if (bct < numtrec) { 1479 /* 1480 * check for old-dump floppy EOM -- it may appear in 1481 * the middle of a buffer. The Dflag used to be used for 1482 * this, but since it doesn't hurt to always do this we 1483 * got rid of the Dflag. 1484 */ 1485 /*LINTED [tbf = malloc()]*/ 1486 sp = &((union u_spcl *)&tbf[bct*tp_bsize])->s_spcl; 1487 if (sp->c_magic == expected_magic && sp->c_type == TS_EOM && 1488 (time_t)(sp->c_date) == dumpdate && 1489 (time_t)(sp->c_ddate) == dumptime) { 1490 for (i = 0; i < ntrec; i++) 1491 /*LINTED [tbf = malloc()]*/ 1492 ((struct s_spcl *) 1493 &tbf[i*tp_bsize])->c_magic = 0; 1494 bct = 0; 1495 rd = 0; 1496 i = 0; 1497 goto nextvol; 1498 } 1499 bcopy(&tbf[(bct++*tp_bsize)], b, (size_t)tp_bsize); 1500 blksread++; 1501 tapea++; 1502 return; 1503 } 1504 /*LINTED [assertion always true]*/ 1505 assert(sizeof (union u_spcl) == TP_BSIZE_MAX); 1506 for (i = 0; i < ntrec; i++) 1507 /*LINTED [tbf = malloc()]*/ 1508 ((struct s_spcl *)&tbf[i*sizeof (struct s_spcl)])->c_magic = 0; 1509 if (numtrec == 0) { 1510 /* LINTED unsigned/signed assignment ok */ 1511 numtrec = ntrec; 1512 } 1513 /* LINTED unsigned/signed assignment ok */ 1514 cnt = ntrec*tp_bsize; 1515 rd = 0; 1516 getmore: 1517 if (host) 1518 i = rmtread(&tbf[rd], cnt); 1519 else 1520 i = read(mt, &tbf[rd], cnt); 1521 /* 1522 * Check for mid-tape short read error. 1523 * If found, return rest of buffer. 1524 */ 1525 if (numtrec < ntrec && i != 0) { 1526 /* LINTED unsigned/signed assignment ok */ 1527 numtrec = ntrec; 1528 goto top; 1529 } 1530 /* 1531 * Handle partial block read. 1532 */ 1533 if (i > 0 && i != ntrec*tp_bsize) { 1534 if (pipein) { 1535 rd += i; 1536 cnt -= i; 1537 if (cnt > 0) 1538 goto getmore; 1539 i = rd; 1540 } else { 1541 if (i % tp_bsize != 0) 1542 panic(gettext( 1543 "partial block read: %d should be %d\n"), 1544 i, ntrec * tp_bsize); 1545 numtrec = i / tp_bsize; 1546 if (numtrec == 0) 1547 /* 1548 * it's possible to read only 512 bytes 1549 * from a QIC device... 1550 */ 1551 i = 0; 1552 } 1553 } 1554 /* 1555 * Handle read error. 1556 */ 1557 if (i < 0) { 1558 switch (curfile.action) { 1559 default: 1560 (void) fprintf(stderr, gettext( 1561 "Read error while trying to set up volume\n")); 1562 break; 1563 case UNKNOWN: 1564 (void) fprintf(stderr, gettext( 1565 "Read error while trying to resynchronize\n")); 1566 break; 1567 case USING: 1568 (void) fprintf(stderr, gettext( 1569 "Read error while restoring %s\n"), 1570 curfile.name); 1571 break; 1572 case SKIP: 1573 (void) fprintf(stderr, gettext( 1574 "Read error while skipping over inode %d\n"), 1575 curfile.ino); 1576 break; 1577 } 1578 if (!yflag && !reply(gettext("continue"))) 1579 done(1); 1580 /* LINTED: unsigned->signed conversion ok */ 1581 i = (int)(ntrec*tp_bsize); 1582 bzero(tbf, (size_t)i); 1583 if ((host != 0 && rmtseek(i, 1) < 0) || 1584 (host == 0 && (lseek64(mt, (offset_t)i, 1) == 1585 (off64_t)-1))) { 1586 perror(gettext("continuation failed")); 1587 done(1); 1588 } 1589 } 1590 /* 1591 * Handle end of tape. The Dflag used to be used, but since it doesn't 1592 * hurt to always check we got rid if it. 1593 */ 1594 1595 /* 1596 * if the first record in the buffer just read is EOM, 1597 * change volumes. 1598 */ 1599 /*LINTED [tbf = malloc()]*/ 1600 sp = &((union u_spcl *)tbf)->s_spcl; 1601 if (i != 0 && sp->c_magic == expected_magic && sp->c_type == TS_EOM && 1602 (time_t)(sp->c_date) == dumpdate && 1603 (time_t)(sp->c_ddate) == dumptime) { 1604 i = 0; 1605 } 1606 nextvol: 1607 if (i == 0) { 1608 if (!pipein) { 1609 newvol = volno + 1; 1610 volno = 0; 1611 numtrec = 0; 1612 getvol(newvol); 1613 readtape(b); /* XXX tail recursion, not goto top? */ 1614 return; 1615 } 1616 /* XXX if panic returns, should we round rd up? */ 1617 /* XXX if we do, then we should zero the intervening space */ 1618 if (rd % tp_bsize != 0) 1619 panic(gettext("partial block read: %d should be %d\n"), 1620 rd, ntrec * tp_bsize); 1621 bcopy((char *)&endoftapemark, &tbf[rd], (size_t)tp_bsize); 1622 } 1623 bct = 0; 1624 bcopy(&tbf[(bct++*tp_bsize)], b, (size_t)tp_bsize); 1625 blksread++; 1626 recsread++; 1627 tapea++; 1628 rec_position++; 1629 } 1630 1631 void 1632 findtapeblksize(int arfile) 1633 { 1634 int i; 1635 1636 if (tbf == NULL) { 1637 (void) fprintf(stderr, gettext( 1638 "Internal consistency failure in findtapeblksize: " 1639 "tbf is NULL\n")); 1640 assert(tbf != NULL); 1641 done(1); 1642 } 1643 1644 for (i = 0; i < ntrec; i++) 1645 /*LINTED [tbf = malloc()]*/ 1646 ((struct s_spcl *)&tbf[i * tp_bsize])->c_magic = 0; 1647 bct = 0; 1648 if (host && arfile == TAPE_FILE) 1649 tape_rec_size = rmtread(tbf, ntrec * tp_bsize); 1650 else 1651 tape_rec_size = read(mt, tbf, ntrec * tp_bsize); 1652 recsread++; 1653 rec_position++; 1654 if (tape_rec_size == (ssize_t)-1) { 1655 int saverr = errno; 1656 char *errmsg = gettext("Media read error"); 1657 errno = saverr; 1658 perror(errmsg); 1659 done(1); 1660 } 1661 if (tape_rec_size % tp_bsize != 0) { 1662 (void) fprintf(stderr, gettext( 1663 "Record size (%d) is not a multiple of dump block size (%d)\n"), 1664 tape_rec_size, tp_bsize); 1665 done(1); 1666 } 1667 ntrec = (int)tape_rec_size / tp_bsize; 1668 /* LINTED unsigned/signed assignment ok */ 1669 numtrec = ntrec; 1670 vprintf(stdout, gettext("Media block size is %d\n"), ntrec*2); 1671 } 1672 1673 void 1674 flsht(void) 1675 { 1676 /* LINTED unsigned/signed assignment ok */ 1677 bct = ntrec+1; 1678 } 1679 1680 void 1681 closemt(int mode) 1682 { 1683 /* 1684 * If mode == FORCE_OFFLINE then we're not done but 1685 * we need to change tape. So, rewind and unload current 1686 * tape before loading the new one. 1687 */ 1688 1689 static struct mtop mtop = { MTOFFL, 0 }; 1690 1691 if (mt < 0) 1692 return; 1693 if (offline || mode == FORCE_OFFLINE) 1694 (void) fprintf(stderr, gettext("Rewinding tape\n")); 1695 if (host) { 1696 if (offline || mode == FORCE_OFFLINE) 1697 (void) rmtioctl(MTOFFL, 1); 1698 rmtclose(); 1699 } else if (pipein) { 1700 char buffy[MAXBSIZE]; 1701 1702 while (read(mt, buffy, sizeof (buffy)) > 0) { 1703 continue; 1704 /*LINTED [assertion always true]*/ 1705 } 1706 (void) close(mt); 1707 } else { 1708 /* 1709 * Only way to tell if this is a floppy is to issue an ioctl 1710 * but why waste one - if the eject fails, tough! 1711 */ 1712 if (offline || mode == FORCE_OFFLINE) 1713 (void) ioctl(mt, MTIOCTOP, &mtop); 1714 (void) ioctl(mt, FDEJECT, 0); 1715 (void) close(mt); 1716 } 1717 mt = -1; 1718 } 1719 1720 static int 1721 checkvol(struct s_spcl *b, int t) 1722 { 1723 1724 if (b->c_volume != t) 1725 return (FAIL); 1726 return (GOOD); 1727 } 1728 1729 int 1730 readhdr(struct s_spcl *b) 1731 { 1732 1733 if (gethead(b) == FAIL) { 1734 dprintf(stdout, gettext("readhdr fails at %ld blocks\n"), 1735 blksread); 1736 return (FAIL); 1737 } 1738 return (GOOD); 1739 } 1740 1741 /* 1742 * read the tape into buf, then return whether or 1743 * or not it is a header block. 1744 */ 1745 int 1746 gethead(struct s_spcl *buf) 1747 { 1748 int i; 1749 union u_ospcl { 1750 char dummy[TP_BSIZE_MIN]; 1751 struct s_ospcl { 1752 int32_t c_type; 1753 int32_t c_date; 1754 int32_t c_ddate; 1755 int32_t c_volume; 1756 int32_t c_tapea; 1757 ushort_t c_inumber; 1758 int32_t c_magic; 1759 int32_t c_checksum; 1760 struct odinode { 1761 unsigned short odi_mode; 1762 ushort_t odi_nlink; 1763 ushort_t odi_uid; 1764 ushort_t odi_gid; 1765 int32_t odi_size; 1766 int32_t odi_rdev; 1767 char odi_addr[36]; 1768 int32_t odi_atime; 1769 int32_t odi_mtime; 1770 int32_t odi_ctime; 1771 } c_dinode; 1772 int32_t c_count; 1773 char c_baddr[256]; 1774 } s_ospcl; 1775 } u_ospcl; 1776 1777 if (cvtflag) { 1778 readtape((char *)(&u_ospcl.s_ospcl)); 1779 bzero((char *)buf, (size_t)TP_BSIZE_MIN); 1780 buf->c_type = u_ospcl.s_ospcl.c_type; 1781 buf->c_date = u_ospcl.s_ospcl.c_date; 1782 buf->c_ddate = u_ospcl.s_ospcl.c_ddate; 1783 buf->c_volume = u_ospcl.s_ospcl.c_volume; 1784 buf->c_tapea = u_ospcl.s_ospcl.c_tapea; 1785 buf->c_inumber = u_ospcl.s_ospcl.c_inumber; 1786 buf->c_checksum = u_ospcl.s_ospcl.c_checksum; 1787 buf->c_magic = u_ospcl.s_ospcl.c_magic; 1788 buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode; 1789 /* LINTED: unsigned/signed combination ok */ 1790 buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink; 1791 buf->c_dinode.di_size = 1792 (unsigned)(u_ospcl.s_ospcl.c_dinode.odi_size); 1793 buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid; 1794 buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid; 1795 buf->c_dinode.di_suid = UID_LONG; 1796 buf->c_dinode.di_sgid = GID_LONG; 1797 buf->c_dinode.di_ordev = u_ospcl.s_ospcl.c_dinode.odi_rdev; 1798 buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime; 1799 buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime; 1800 buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime; 1801 buf->c_count = u_ospcl.s_ospcl.c_count; 1802 bcopy(u_ospcl.s_ospcl.c_baddr, buf->c_addr, 1803 sizeof (u_ospcl.s_ospcl.c_baddr)); 1804 1805 /*CONSTANTCONDITION*/ 1806 assert(sizeof (u_ospcl.s_ospcl) < sizeof (union u_spcl)); 1807 1808 /* we byte-swap the new spclrec, but checksum the old */ 1809 /* (see comments in normspcl()) */ 1810 if (normspcl(byteorder, buf, 1811 (int *)(&u_ospcl.s_ospcl), sizeof (u_ospcl.s_ospcl), 1812 OFS_MAGIC)) 1813 return (FAIL); 1814 buf->c_magic = 1815 ((tp_bsize == TP_BSIZE_MIN) ? NFS_MAGIC : MTB_MAGIC); 1816 } else { 1817 readtape((char *)buf); 1818 if (normspcl(byteorder, buf, (int *)buf, tp_bsize, 1819 ((tp_bsize == TP_BSIZE_MIN) ? NFS_MAGIC : MTB_MAGIC))) 1820 return (FAIL); 1821 } 1822 1823 switch (buf->c_type) { 1824 1825 case TS_CLRI: 1826 case TS_BITS: 1827 /* 1828 * Have to patch up missing information in bit map headers 1829 */ 1830 buf->c_inumber = 0; 1831 buf->c_dinode.di_size = (offset_t)buf->c_count * tp_bsize; 1832 for (i = 0; i < buf->c_count && i < TP_NINDIR; i++) 1833 buf->c_addr[i] = 1; 1834 break; 1835 1836 case TS_TAPE: 1837 case TS_END: 1838 if (dumpinfo.c_date == 0) { 1839 dumpinfo.c_date = spcl.c_date; 1840 dumpinfo.c_ddate = spcl.c_ddate; 1841 } 1842 if (!hostinfo && spcl.c_host[0] != '\0') { 1843 bcopy(spcl.c_label, dumpinfo.c_label, 1844 sizeof (spcl.c_label)); 1845 bcopy(spcl.c_filesys, dumpinfo.c_filesys, 1846 sizeof (spcl.c_filesys)); 1847 bcopy(spcl.c_dev, dumpinfo.c_dev, 1848 sizeof (spcl.c_dev)); 1849 bcopy(spcl.c_host, dumpinfo.c_host, 1850 sizeof (spcl.c_host)); 1851 dumpinfo.c_level = spcl.c_level; 1852 hostinfo++; 1853 if (c_label != NULL && 1854 strncmp(c_label, spcl.c_label, 1855 sizeof (spcl.c_label)) 1856 != 0) { 1857 (void) fprintf(stderr, gettext( 1858 "Incorrect tape label. Expected `%s', got `%.*s'\n"), 1859 c_label, 1860 sizeof (spcl.c_label), spcl.c_label); 1861 done(1); 1862 } 1863 } 1864 if (!inodeinfo && (spcl.c_flags & DR_INODEINFO)) { 1865 dumpinfo.c_volume = spcl.c_volume; 1866 bcopy(spcl.c_inos, dumpinfo.c_inos, 1867 sizeof (spcl.c_inos)); 1868 inodeinfo++; 1869 } 1870 buf->c_inumber = 0; 1871 break; 1872 1873 case TS_INODE: 1874 case TS_ADDR: 1875 break; 1876 1877 default: 1878 panic(gettext("%s: unknown inode type %d\n"), 1879 "gethead", buf->c_type); 1880 return (FAIL); 1881 } 1882 if (dflag) 1883 accthdr(buf); 1884 return (GOOD); 1885 } 1886 1887 /* 1888 * Check that a header is where it belongs and predict the next header 1889 */ 1890 static void 1891 accthdr(struct s_spcl *header) 1892 { 1893 static ino_t previno = (ino_t)(unsigned)-1; 1894 static int prevtype; 1895 static long predict; 1896 int blks, i; 1897 1898 if (header->c_type == TS_TAPE) { 1899 if (header->c_firstrec) 1900 (void) fprintf(stderr, 1901 gettext("Volume header begins with record %d"), 1902 header->c_firstrec); 1903 else 1904 (void) fprintf(stderr, gettext("Volume header")); 1905 (void) fprintf(stderr, "\n"); 1906 previno = (ino_t)(unsigned)-1; 1907 return; 1908 } 1909 if (previno == (ino_t)(unsigned)-1) 1910 goto newcalc; 1911 switch (prevtype) { 1912 case TS_BITS: 1913 (void) fprintf(stderr, gettext("Dump mask header")); 1914 break; 1915 case TS_CLRI: 1916 (void) fprintf(stderr, gettext("Remove mask header")); 1917 break; 1918 case TS_INODE: 1919 (void) fprintf(stderr, 1920 gettext("File header, ino %d at record %d"), 1921 previno, rec_position); 1922 break; 1923 case TS_ADDR: 1924 (void) fprintf(stderr, 1925 gettext("File continuation header, ino %d"), 1926 previno); 1927 break; 1928 case TS_END: 1929 (void) fprintf(stderr, gettext("End of media header")); 1930 break; 1931 } 1932 if (predict != blksread - 1) 1933 (void) fprintf(stderr, 1934 gettext("; predicted %ld blocks, got %ld blocks"), 1935 predict, blksread - 1); 1936 (void) fprintf(stderr, "\n"); 1937 newcalc: 1938 blks = 0; 1939 if (header->c_type != TS_END) 1940 for (i = 0; i < header->c_count; i++) 1941 if ((i >= TP_NINDIR) || (header->c_addr[i] != 0)) 1942 blks++; 1943 predict = blks; 1944 blksread = 0; 1945 prevtype = header->c_type; 1946 previno = header->c_inumber; 1947 } 1948 1949 /* 1950 * Try to determine which volume a file resides on. 1951 */ 1952 int 1953 volnumber(ino_t inum) 1954 { 1955 int i; 1956 1957 if (inodeinfo == 0) 1958 return (0); 1959 for (i = 1; i <= dumpinfo.c_volume; i++) 1960 if (inum < (ino_t)(unsigned)(dumpinfo.c_inos[i])) 1961 break; 1962 return (i - 1); 1963 } 1964 1965 /* 1966 * Find an inode header. 1967 * Note that *header must be stable storage, as curfile will end up with 1968 * pointers into it. 1969 */ 1970 void 1971 findinode(struct s_spcl *header) 1972 { 1973 long skipcnt = 0; 1974 int i; 1975 char buf[TP_BSIZE_MAX]; 1976 1977 curfile.name = gettext("<name unknown>"); 1978 curfile.action = UNKNOWN; 1979 curfile.dip = (struct dinode *)NULL; 1980 curfile.ino = 0; 1981 curfile.ts = 0; 1982 if (ishead(header) == FAIL) { 1983 skipcnt++; 1984 while (gethead(header) == FAIL || 1985 (time_t)(header->c_date) != dumpdate) 1986 skipcnt++; 1987 } 1988 for (;;) { 1989 if (checktype(header, TS_ADDR) == GOOD) { 1990 /* 1991 * Skip up to the beginning of the next record 1992 */ 1993 for (i = 0; i < header->c_count; i++) 1994 if ((i >= TP_NINDIR) || (header->c_addr[i])) 1995 readtape(buf); 1996 (void) gethead(header); 1997 continue; 1998 } 1999 if (checktype(header, TS_INODE) == GOOD) { 2000 curfile.dip = &header->c_dinode; 2001 if (curfile.dip->di_suid != UID_LONG) 2002 curfile.dip->di_uid = curfile.dip->di_suid; 2003 if (curfile.dip->di_sgid != GID_LONG) 2004 curfile.dip->di_gid = curfile.dip->di_sgid; 2005 curfile.ino = header->c_inumber; 2006 curfile.ts = TS_INODE; 2007 break; 2008 } 2009 if (checktype(header, TS_END) == GOOD) { 2010 curfile.ino = maxino; 2011 curfile.ts = TS_END; 2012 break; 2013 } 2014 if (checktype(header, TS_CLRI) == GOOD) { 2015 curfile.name = gettext("<file removal list>"); 2016 curfile.ts = TS_CLRI; 2017 break; 2018 } 2019 if (checktype(header, TS_BITS) == GOOD) { 2020 curfile.name = gettext("<file dump list>"); 2021 curfile.ts = TS_BITS; 2022 break; 2023 } 2024 while (gethead(header) == FAIL) 2025 skipcnt++; 2026 } 2027 if (skipcnt > 0) 2028 (void) fprintf(stderr, 2029 gettext("resync restore, skipped %d blocks\n"), 2030 skipcnt); 2031 } 2032 2033 /* 2034 * return whether or not the buffer contains a header block 2035 */ 2036 static int 2037 ishead(struct s_spcl *buf) 2038 { 2039 if (buf->c_magic != 2040 ((tp_bsize == TP_BSIZE_MIN) ? NFS_MAGIC : MTB_MAGIC)) 2041 return (FAIL); 2042 return (GOOD); 2043 } 2044 2045 static int 2046 checktype(struct s_spcl *b, int t) 2047 { 2048 if (b->c_type != t) 2049 return (FAIL); 2050 return (GOOD); 2051 } 2052 2053 /* 2054 * If autoloading is enabled, attempt to do it. If we succeed, 2055 * return non-zero. 2056 */ 2057 static int 2058 autoload_tape(void) 2059 { 2060 int result = 0; /* assume failure */ 2061 int tries; 2062 int fd; 2063 2064 if (autoload) { 2065 /* 2066 * Wait for the tape to autoload. Note that the delay 2067 * period doesn't take into account however long it takes 2068 * for the open to fail (measured at 21 seconds for an 2069 * Exabyte 8200 under 2.7 on an Ultra 2). 2070 */ 2071 2072 /* rewind tape and offline drive before loading new tape */ 2073 closemt(FORCE_OFFLINE); 2074 (void) fprintf(stderr, 2075 gettext("Attempting to autoload next volume\n")); 2076 for (tries = 0; tries < autoload_tries; tries++) { 2077 if (host) { 2078 if (rmtopen(magtape, O_RDONLY) >= 0) { 2079 rmtclose(); 2080 result = 1; 2081 break; 2082 } 2083 } else { 2084 if ((fd = open(magtape, O_RDONLY|O_LARGEFILE, 2085 0600)) >= 0) { 2086 (void) close(fd); 2087 result = 1; 2088 break; 2089 } 2090 } 2091 (void) sleep(autoload_period); 2092 } 2093 if (result == 0) { 2094 /* Assume caller will deal with manual change-over */ 2095 (void) fprintf(stderr, 2096 gettext("Autoload timed out\n")); 2097 } else { 2098 if ((host != NULL && 2099 (mt = rmtopen(magtape, O_RDONLY)) == -1) || 2100 (host == NULL && 2101 (mt = open(magtape, O_RDONLY|O_LARGEFILE)) == -1)) { 2102 (void) fprintf(stderr, gettext( 2103 "Autoload could not re-open tape\n")); 2104 result = 0; 2105 } else { 2106 (void) fprintf(stderr, gettext( 2107 "Tape loaded\n")); 2108 } 2109 } 2110 } 2111 2112 return (result); 2113 } 2114