1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * Copyright (c) 1980 Regents of the University of California. 32 * All rights reserved. The Berkeley software License Agreement 33 * specifies the terms and conditions for redistribution. 34 */ 35 36 #include "dump.h" 37 #include <rmt.h> 38 #include <sys/mtio.h> 39 #include <limits.h> 40 #include <priv_utils.h> 41 #include "roll_log.h" 42 #include <unistd.h> 43 44 char *filesystem; 45 char *host; 46 char *debug_chdir; 47 char *dumpdev; 48 char *sdumpdev; 49 char *tlabel; 50 time_t *telapsed; 51 time_t *tstart_writing; 52 53 uchar_t *clrmap; 54 uchar_t *dirmap; 55 uchar_t *filmap; 56 uchar_t *nodmap; 57 uchar_t *shamap; 58 uchar_t *activemap; 59 60 int archive; 61 int autoload; 62 int autoload_period; 63 int autoload_tries; 64 int archive_opened; 65 int doingverify; 66 int disk_dynamic; 67 int dumpstate; 68 int dumptoarchive; 69 int fi; 70 int leftover; 71 int nadded; 72 int offline; 73 int verify; 74 75 uint_t etapes; 76 ulong_t tsize; 77 ino_t ino; 78 off_t pos; 79 pid_t dumppid; 80 u_offset_t esize; 81 union u_shadow c_shadow_save[1]; 82 83 int notify = 0; /* notify operator flag */ 84 int blockswritten = 0; /* number of blocks written on current tape */ 85 uint_t tapeno = 0; /* current tape number */ 86 daddr32_t filenum = 0; /* current file number on tape */ 87 int density = 0; /* density in bytes/0.1" */ 88 int tenthsperirg; /* inter-record-gap in 0.1"'s */ 89 uint_t ntrec = 0; /* # tape blocks in each tape record */ 90 uint_t saved_ntrec = 0; /* saved value of ntrec */ 91 uint_t forceflag = 0; /* forced to change tp_bsize */ 92 int cartridge = 0; /* assume non-cartridge tape */ 93 uint_t tracks; /* # tracks on a cartridge tape */ 94 int diskette = 0; /* assume not dumping to a diskette */ 95 int printsize = 0; /* just print estimated size and exit */ 96 int mapfd = -1; /* if >= 0, file descriptor for mmap */ 97 int32_t tp_bsize = TP_BSIZE_MIN; /* tape block record size (frag size) */ 98 #ifdef DEBUG 99 int xflag; /* debugging switch */ 100 #endif 101 102 char *myname; 103 104 /* 105 * This should be struct fs, but there are trailing bits on disk 106 * that we also need to read in as part of it. It's an array of 107 * longs instead of char to force proper alignment. 108 */ 109 static long sblock_buf[SBSIZE/sizeof (long)]; 110 111 #ifdef __STDC__ 112 static char *mb(u_offset_t); 113 static void nextstate(int); 114 #else 115 static char *mb(); 116 static void nextstate(); 117 #endif 118 119 extern jmp_buf checkpoint_buf; /* context for return from checkpoint */ 120 #define FUDGE_FACTOR 0x2000000 121 122 int 123 main(int argc, char *argv[]) 124 { 125 char *arg; 126 int bflag = 0, i, error = 0, saverr; 127 double fetapes = 0.0; 128 struct mnttab *dt; 129 char msgbuf[3000], *msgp; 130 char kbsbuf[BUFSIZ]; 131 u_offset_t esize_shift = 0; 132 int32_t new_mult = 0; 133 time32_t snapdate; 134 135 host = NULL; 136 137 if (myname = strrchr(argv[0], '/')) 138 myname++; 139 else 140 myname = argv[0]; 141 142 if (strcmp("hsmdump", myname) == 0) { 143 msg(gettext("hsmdump emulation is no longer supported.\n")); 144 Exit(X_ABORT); 145 } 146 147 tape = DEFTAPE; 148 autoload_period = 12; 149 autoload_tries = 12; /* traditional default of ~2.5 minutes */ 150 151 (void) setlocale(LC_ALL, ""); 152 #if !defined(TEXT_DOMAIN) 153 #define TEXT_DOMAIN "SYS_TEST" 154 #endif /* TEXT_DOMAIN */ 155 (void) textdomain(TEXT_DOMAIN); 156 157 /* 158 * If someone strips the set-uid bit, dump will still work for local 159 * tapes. Fail when we try to access a remote tape. 160 */ 161 (void) __init_suid_priv(0, PRIV_NET_PRIVADDR, (char *)NULL); 162 163 if (sysinfo(SI_HOSTNAME, spcl.c_host, sizeof (spcl.c_host)) < 0) { 164 saverr = errno; 165 msg(gettext("Could not get host name: %s\n"), 166 strerror(saverr)); 167 bzero(spcl.c_host, sizeof (spcl.c_host)); 168 } 169 170 dumppid = getpid(); 171 tsize = 0; /* no default size, detect EOT dynamically */ 172 173 archive_opened = 0; 174 disk = NULL; 175 dname = NULL; 176 disk_dynamic = 0; 177 increm = NINCREM; 178 incno = '9'; 179 uflag = 0; 180 arg = "u"; 181 tlabel = "none"; 182 if (argc > 1) { 183 argv++; 184 argc--; 185 arg = *argv; 186 if (*arg == '-') 187 arg++; 188 } 189 while (*arg) 190 switch (*arg++) { /* BE CAUTIOUS OF FALLTHROUGHS */ 191 case 'M': 192 /* 193 * This undocumented option causes each process to 194 * mkdir debug_chdir/getpid(), and chdir to it. This is 195 * to ease the collection of profiling information and 196 * core dumps. 197 */ 198 if (argc > 1) { 199 argv++; 200 argc--; 201 debug_chdir = *argv; 202 msg(gettext( 203 "Each process shall try to chdir to %s/<pid>\n"), 204 debug_chdir); 205 child_chdir(); 206 } else { 207 msg(gettext("Missing move-to-dir (M) name\n")); 208 dumpabort(); 209 /*NOTREACHED*/ 210 } 211 break; 212 213 case 'w': 214 lastdump('w'); /* tell us only what has to be done */ 215 exit(0); 216 break; 217 218 case 'W': /* what to do */ 219 lastdump('W'); /* tell state of what has been done */ 220 exit(0); /* do nothing else */ 221 break; 222 223 case 'T': 224 if (argc > 1) { 225 int count; 226 int multiplier; 227 char units; 228 229 argv++; 230 argc--; 231 count = atoi(*argv); 232 if (count < 1) { 233 msg(gettext( 234 "Unreasonable autoload timeout period\n")); 235 dumpabort(); 236 /*NOTREACHED*/ 237 } 238 units = *(*argv + strlen(*argv) - 1); 239 switch (units) { 240 case 's': 241 multiplier = 1; 242 break; 243 case 'h': 244 multiplier = 3600; 245 break; 246 case '0': case '1': case '2': case '3': case '4': 247 case '5': case '6': case '7': case '8': case '9': 248 case 'm': 249 multiplier = 60; 250 break; 251 default: 252 msg(gettext( 253 "Unknown timeout units indicator `%c'\n"), 254 units); 255 dumpabort(); 256 /*NOTREACHED*/ 257 } 258 autoload_tries = 1 + 259 ((count * multiplier) / autoload_period); 260 } else { 261 msg(gettext("Missing autoload timeout period\n")); 262 dumpabort(); 263 /*NOTREACHED*/ 264 } 265 break; 266 267 case 'f': /* output file */ 268 if (argc > 1) { 269 argv++; 270 argc--; 271 tape = *argv; 272 if (*tape == '\0') { 273 msg(gettext("Bad output device name\n")); 274 dumpabort(); 275 /*NOTREACHED*/ 276 } 277 } else { 278 msg(gettext("Missing output device name\n")); 279 dumpabort(); 280 /*NOTREACHED*/ 281 } 282 if (strcmp(tape, "-") == 0 && verify) { 283 msg(gettext( 284 "Cannot verify when dumping to standard out.\n")); 285 dumpabort(); 286 /*NOTREACHED*/ 287 } 288 break; 289 290 case 'd': /* density, in bits per inch */ 291 if (argc > 1) { 292 argv++; 293 argc--; 294 density = atoi(*argv) / 10; 295 if (density <= 0) { 296 msg(gettext( 297 "Density must be a positive integer\n")); 298 dumpabort(); 299 /*NOTREACHED*/ 300 } 301 } else { 302 msg(gettext("Missing density\n")); 303 dumpabort(); 304 /*NOTREACHED*/ 305 } 306 break; 307 308 case 's': /* tape size, feet */ 309 if (argc > 1) { 310 argv++; 311 argc--; 312 tsize = atol(*argv); 313 if ((*argv[0] == '-') || (tsize == 0)) { 314 msg(gettext( 315 "Tape size must be a positive integer\n")); 316 dumpabort(); 317 /*NOTREACHED*/ 318 } 319 } else { 320 msg(gettext("Missing tape size\n")); 321 dumpabort(); 322 /*NOTREACHED*/ 323 } 324 break; 325 326 case 't': /* tracks */ 327 if (argc > 1) { 328 argv++; 329 argc--; 330 tracks = atoi(*argv); 331 } else { 332 msg(gettext("Missing track count\n")); 333 dumpabort(); 334 /*NOTREACHED*/ 335 } 336 break; 337 338 case 'b': /* blocks per tape write */ 339 if (argc > 1) { 340 argv++; 341 argc--; 342 bflag++; 343 /* 344 * We save the ntrec in case we need to change 345 * tp_bsize later, we will have to recalculate 346 * it. 347 */ 348 saved_ntrec = ntrec = atoi(*argv); 349 if (ntrec == 0 || (ntrec&1) || ntrec > (MAXNTREC*2)) { 350 msg(gettext( 351 "Block size must be a positive, even integer <= %d\n"), 352 MAXNTREC*2); 353 dumpabort(); 354 /*NOTREACHED*/ 355 } 356 ntrec /= (tp_bsize/DEV_BSIZE); 357 } else { 358 msg(gettext("Missing blocking factor\n")); 359 dumpabort(); 360 /*NOTREACHED*/ 361 } 362 break; 363 364 case 'c': /* Tape is cart. not 9-track */ 365 case 'C': /* 'C' to be consistent with 'D' */ 366 cartridge++; 367 break; 368 369 case '0': /* dump level */ 370 case '1': 371 case '2': 372 case '3': 373 case '4': 374 case '5': 375 case '6': 376 case '7': 377 case '8': 378 case '9': 379 incno = arg[-1]; 380 break; 381 382 case 'u': /* update /etc/dumpdates */ 383 uflag++; 384 break; 385 386 case 'n': /* notify operators */ 387 notify++; 388 break; 389 390 case 'a': /* create archive file */ 391 archive = 1; 392 if (argc > 1) { 393 argv++; 394 argc--; 395 if (**argv == '\0') { 396 msg(gettext("Bad archive file name\n")); 397 dumpabort(); 398 /*NOTREACHED*/ 399 } 400 archivefile = strdup(*argv); 401 if (archivefile == NULL) { 402 saverr = errno; 403 msg(gettext("Cannot allocate memory: %s\n"), 404 strerror(saverr)); 405 dumpabort(); 406 /*NOTREACHED*/ 407 } 408 } else { 409 msg(gettext("Missing archive file name\n")); 410 dumpabort(); 411 /*NOTREACHED*/ 412 } 413 break; 414 415 case 'v': 416 verify++; 417 doingverify++; 418 if (strcmp(tape, "-") == 0) { 419 msg(gettext( 420 "Cannot verify when dumping to standard out.\n")); 421 dumpabort(); 422 /*NOTREACHED*/ 423 } 424 break; 425 426 case 'D': 427 diskette++; 428 break; 429 430 case 'N': 431 if (argc > 1) { 432 argv++; 433 argc--; 434 if (**argv == '\0') { 435 msg(gettext("Missing name for dumpdates " 436 "entry.\n")); 437 dumpabort(); 438 /*NOTREACHED*/ 439 } 440 dname = *argv; 441 if (strlen(dname) > MAXNAMLEN + 2) { 442 msg(gettext("Dumpdates entry name too " 443 "long.\n")); 444 dumpabort(); 445 /*NOTREACHED*/ 446 } 447 for (i = 0; i < strlen(dname); i++) { 448 if (isspace(*(dname+i))) { 449 msg(gettext("Dumpdates entry name may " 450 "not contain white space.\n")); 451 dumpabort(); 452 /*NOTREACHED*/ 453 } 454 } 455 } else { 456 msg(gettext("Missing name for dumpdates entry.\n")); 457 dumpabort(); 458 /*NOTREACHED*/ 459 } 460 break; 461 case 'L': 462 if (argc > 1) { 463 argv++; 464 argc--; 465 if (**argv == '\0') { 466 msg(gettext("Missing tape label name\n")); 467 dumpabort(); 468 /*NOTREACHED*/ 469 } 470 tlabel = *argv; 471 if (strlen(tlabel) > (sizeof (spcl.c_label) - 1)) { 472 tlabel[sizeof (spcl.c_label) - 1] = '\0'; 473 msg(gettext( 474 "Truncating label to maximum supported length: `%s'\n"), 475 tlabel); 476 } 477 } else { 478 msg(gettext("Missing tape label name\n")); 479 dumpabort(); 480 /*NOTREACHED*/ 481 } 482 break; 483 484 case 'l': 485 autoload++; 486 break; 487 488 case 'o': 489 offline++; 490 break; 491 492 case 'S': 493 printsize++; 494 break; 495 496 #ifdef DEBUG 497 case 'z': 498 xflag++; 499 break; 500 #endif 501 502 default: 503 msg(gettext("Bad option `%c'\n"), arg[-1]); 504 dumpabort(); 505 /*NOTREACHED*/ 506 } 507 if (argc > 1) { 508 argv++; 509 argc--; 510 if (**argv == '\0') { 511 msg(gettext("Bad disk name\n")); 512 dumpabort(); 513 /*NOTREACHED*/ 514 } 515 disk = *argv; 516 disk_dynamic = 0; 517 } 518 if (disk == NULL) { 519 (void) fprintf(stderr, gettext( 520 "Usage: %s [0123456789fustdWwnNDCcbavloS [argument]] filesystem\n"), 521 myname); 522 Exit(X_ABORT); 523 } 524 if (!filenum) 525 filenum = 1; 526 527 if (signal(SIGINT, interrupt) == SIG_IGN) 528 (void) signal(SIGINT, SIG_IGN); 529 530 if (strcmp(tape, "-") == 0) { 531 pipeout++; 532 tape = gettext("standard output"); 533 dumpdev = sdumpdev = strdup(tape); 534 if (dumpdev == NULL) { 535 saverr = errno; 536 msg(gettext("Cannot allocate memory: %s\n"), 537 strerror(saverr)); 538 dumpabort(); 539 /*NOTREACHED*/ 540 } 541 /*CONSTANTCONDITION*/ 542 assert(sizeof (spcl.c_label) > 5); 543 (void) strcpy(spcl.c_label, "none"); 544 } else if (*tape == '+') { 545 nextdevice(); 546 (void) strcpy(spcl.c_label, tlabel); 547 } else { 548 /* if not already set, set diskette to default */ 549 if (diskette && strcmp(tape, DEFTAPE) == 0) 550 tape = DISKETTE; 551 nextdevice(); 552 (void) strcpy(spcl.c_label, tlabel); 553 } 554 if (cartridge && diskette) { 555 error = 1; 556 msg(gettext("Cannot select both cartridge and diskette\n")); 557 } 558 if (density && diskette) { 559 error = 1; 560 msg(gettext("Cannot select density of diskette\n")); 561 } 562 if (tracks && diskette) { 563 error = 1; 564 msg(gettext("Cannot select number of tracks of diskette\n")); 565 } 566 if (error) { 567 dumpabort(); 568 /*NOTREACHED*/ 569 } 570 571 /* 572 * Determine how to default tape size and density 573 * 574 * density tape size 575 * 9-track 1600 bpi (160 bytes/.1") 2300 ft. 576 * 9-track 6250 bpi (625 bytes/.1") 2300 ft. 577 * 578 * Most Sun-2's came with 4 track (20MB) cartridge tape drives, 579 * while most other machines (Sun-3's and non-Sun's) come with 580 * 9 track (45MB) cartridge tape drives. Some Sun-2's came with 581 * 9 track drives, but there is no way for the software to detect 582 * which drive type is installed. Sigh... We make the gross 583 * assumption that #ifdef mc68010 will test for a Sun-2. 584 * 585 * cartridge 8000 bpi (100 bytes/.1") 425 * tracks ft. 586 */ 587 if (density == 0) 588 density = cartridge ? 100 : 625; 589 if (tracks == 0) 590 tracks = 9; 591 if (!bflag) { 592 if (cartridge) 593 ntrec = CARTRIDGETREC; 594 else if (diskette) 595 ntrec = NTREC; 596 else if (density >= 625) 597 ntrec = HIGHDENSITYTREC; 598 else 599 ntrec = NTREC; 600 /* 601 * save ntrec in case we have to change tp_bsize later. 602 */ 603 saved_ntrec = (ntrec * (tp_bsize/DEV_BSIZE)); 604 } 605 if (!diskette) { 606 tsize *= 12L*10L; 607 if (cartridge) 608 tsize *= tracks; 609 } 610 rmtinit(msg, Exit); 611 if (host) { 612 char *cp = strchr(host, '@'); 613 if (cp == (char *)0) 614 cp = host; 615 else 616 cp++; 617 618 if (rmthost(host, ntrec) == 0) { 619 msg(gettext("Cannot connect to tape host `%s'\n"), cp); 620 dumpabort(); 621 /*NOTREACHED*/ 622 } 623 } 624 if (signal(SIGHUP, sigAbort) == SIG_IGN) 625 (void) signal(SIGHUP, SIG_IGN); 626 if (signal(SIGTRAP, sigAbort) == SIG_IGN) 627 (void) signal(SIGTRAP, SIG_IGN); 628 if (signal(SIGFPE, sigAbort) == SIG_IGN) 629 (void) signal(SIGFPE, SIG_IGN); 630 if (signal(SIGBUS, sigAbort) == SIG_IGN) 631 (void) signal(SIGBUS, SIG_IGN); 632 if (signal(SIGSEGV, sigAbort) == SIG_IGN) 633 (void) signal(SIGSEGV, SIG_IGN); 634 if (signal(SIGTERM, sigAbort) == SIG_IGN) 635 (void) signal(SIGTERM, SIG_IGN); 636 if (signal(SIGUSR1, sigAbort) == SIG_IGN) 637 (void) signal(SIGUSR1, SIG_IGN); 638 if (signal(SIGPIPE, sigAbort) == SIG_IGN) 639 (void) signal(SIGPIPE, SIG_IGN); 640 641 mnttabread(); /* /etc/fstab, /etc/mtab snarfed */ 642 643 /* 644 * disk can be either the full special file name, 645 * the suffix of the special file name, 646 * the special name missing the leading '/', 647 * the file system name with or without the leading '/'. 648 * NB: we attempt to avoid dumping the block device 649 * (using rawname) because specfs and the vm system 650 * are not necessarily in sync. 651 */ 652 653 /* 654 * Attempt to roll the log if its root user before doing the dump. 655 * There's nothing the user can do if we are unable to roll the log, 656 * so we'll silently ignore failures. 657 */ 658 if (getuid() == 0 && rl_roll_log(disk) != RL_SUCCESS && 659 disk[0] != '/') { 660 /* Try it again with leading '/'. */ 661 char *slashed; 662 663 slashed = (char *)malloc(strlen(disk) + 2); 664 if (slashed != (char *)NULL) { 665 (void) sprintf(slashed, "%c%s", '/', disk); 666 (void) rl_roll_log(slashed); 667 free(slashed); 668 } 669 } 670 dt = mnttabsearch(disk, 0); 671 if (dt != 0) { 672 filesystem = dt->mnt_mountp; 673 if (disk_dynamic) { 674 /* LINTED: disk is not NULL */ 675 free(disk); 676 } 677 disk = rawname(dt->mnt_special); 678 disk_dynamic = (disk != dt->mnt_special); 679 680 (void) strncpy(spcl.c_dev, dt->mnt_special, 681 sizeof (spcl.c_dev)); 682 spcl.c_dev[sizeof (spcl.c_dev) - 1] = '\0'; 683 (void) strncpy(spcl.c_filesys, dt->mnt_mountp, 684 sizeof (spcl.c_filesys)); 685 spcl.c_filesys[sizeof (spcl.c_filesys) - 1] = '\0'; 686 } else { 687 (void) strncpy(spcl.c_dev, disk, sizeof (spcl.c_dev)); 688 spcl.c_dev[sizeof (spcl.c_dev) - 1] = '\0'; 689 #ifdef PARTIAL 690 /* check for partial filesystem dump */ 691 partial_check(); 692 dt = mnttabsearch(disk, 1); 693 if (dt != 0) { 694 filesystem = dt->mnt_mountp; 695 if (disk_dynamic) 696 free(disk); 697 disk = rawname(dt->mnt_special); 698 disk_dynamic = (disk != dt->mnt_special); 699 700 (void) strncpy(spcl.c_filesys, 701 "a partial file system", sizeof (spcl.c_filesys)); 702 spcl.c_filesys[sizeof (spcl.c_filesys) - 1] = '\0'; 703 } 704 else 705 #endif /* PARTIAL */ 706 { 707 char *old_disk = disk; 708 709 (void) strncpy(spcl.c_filesys, 710 "an unlisted file system", 711 sizeof (spcl.c_filesys)); 712 spcl.c_filesys[sizeof (spcl.c_filesys) - 1] = '\0'; 713 714 disk = rawname(old_disk); 715 if (disk != old_disk) { 716 if (disk_dynamic) 717 free(old_disk); 718 disk_dynamic = 1; 719 } 720 /* 721 * If disk == old_disk, then disk_dynamic's state 722 * does not change. 723 */ 724 } 725 } 726 727 fi = open64(disk, O_RDONLY); 728 729 if (fi < 0) { 730 saverr = errno; 731 msg(gettext("Cannot open dump device `%s': %s\n"), 732 disk, strerror(saverr)); 733 Exit(X_ABORT); 734 } 735 736 if (sscanf(&incno, "%1d", &spcl.c_level) != 1) { 737 msg(gettext("Bad dump level `%c' specified\n"), incno); 738 dumpabort(); 739 /*NOTREACHED*/ 740 } 741 getitime(); /* /etc/dumpdates snarfed */ 742 743 sblock = (struct fs *)&sblock_buf; 744 sync(); 745 746 bread((diskaddr_t)SBLOCK, (uchar_t *)sblock, (long)SBSIZE); 747 if ((sblock->fs_magic != FS_MAGIC) && 748 (sblock->fs_magic != MTB_UFS_MAGIC)) { 749 msg(gettext( 750 "Warning - super-block on device `%s' is corrupt - run fsck\n"), 751 disk); 752 dumpabort(); 753 /*NOTREACHED*/ 754 } 755 756 if (sblock->fs_magic == FS_MAGIC && 757 (sblock->fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 && 758 sblock->fs_version != UFS_VERSION_MIN)) { 759 msg(gettext("Unrecognized UFS version: %d\n"), 760 sblock->fs_version); 761 dumpabort(); 762 /*NOTREACHED*/ 763 } 764 765 if (sblock->fs_magic == MTB_UFS_MAGIC && 766 (sblock->fs_version < MTB_UFS_VERSION_MIN || 767 sblock->fs_version > MTB_UFS_VERSION_1)) { 768 msg(gettext("Unrecognized UFS version: %d\n"), 769 sblock->fs_version); 770 dumpabort(); 771 /*NOTREACHED*/ 772 } 773 774 /* 775 * Try to set up for using mmap(2). It only works on the block 776 * device, but if we can use it, things go somewhat faster. If 777 * we can't open it, we'll silently fall back to the old method 778 * (read/memcpy). We also only try this if it's been cleanly 779 * unmounted. Dumping a live filesystem this way runs into 780 * buffer consistency problems. Of course, we don't support 781 * running dump on a mounted filesystem, but some people do it 782 * anyway. 783 */ 784 if (sblock->fs_clean == FSCLEAN) { 785 char *block = unrawname(disk); 786 787 if (block != NULL) { 788 mapfd = open(block, O_RDONLY, 0); 789 free(block); 790 } 791 } 792 793 restart: 794 bread((diskaddr_t)SBLOCK, (uchar_t *)sblock, (long)SBSIZE); 795 if ((sblock->fs_magic != FS_MAGIC) && 796 (sblock->fs_magic != MTB_UFS_MAGIC)) { /* paranoia */ 797 msg(gettext("bad super-block magic number, run fsck\n")); 798 dumpabort(); 799 /*NOTREACHED*/ 800 } 801 802 if (sblock->fs_magic == FS_MAGIC && 803 (sblock->fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 && 804 sblock->fs_version != UFS_VERSION_MIN)) { 805 msg(gettext("Unrecognized UFS version: %d\n"), 806 sblock->fs_version); 807 dumpabort(); 808 /*NOTREACHED*/ 809 } 810 811 if (sblock->fs_magic == MTB_UFS_MAGIC && 812 (sblock->fs_version < MTB_UFS_VERSION_MIN || 813 sblock->fs_version > MTB_UFS_VERSION_1)) { 814 msg(gettext("Unrecognized UFS version: %d\n"), 815 sblock->fs_version); 816 dumpabort(); 817 /*NOTREACHED*/ 818 } 819 820 if (!doingactive) 821 allocino(); 822 823 /* XXX should sanity-check the super block before trusting/using it */ 824 825 /* LINTED XXX time truncated - tolerate until tape format changes */ 826 spcl.c_date = (time32_t)time((time_t *)NULL); 827 bcopy(&(spcl.c_shadow), c_shadow_save, sizeof (c_shadow_save)); 828 829 snapdate = is_fssnap_dump(disk); 830 if (snapdate) 831 spcl.c_date = snapdate; 832 833 if (!printsize) { 834 msg(gettext("Date of this level %c dump: %s\n"), 835 incno, prdate(spcl.c_date)); 836 msg(gettext("Date of last level %c dump: %s\n"), 837 (uchar_t)lastincno, prdate(spcl.c_ddate)); 838 msg(gettext("Dumping %s "), disk); 839 if (filesystem != 0) 840 msgtail("(%.*s:%s) ", 841 /* LINTED unsigned -> signed cast ok */ 842 (int)sizeof (spcl.c_host), spcl.c_host, filesystem); 843 msgtail(gettext("to %s.\n"), sdumpdev); 844 } 845 846 esize = f_esize = o_esize = 0; 847 msiz = roundup(d_howmany(sblock->fs_ipg * sblock->fs_ncg, NBBY), 848 TP_BSIZE_MAX); 849 if (!doingactive) { 850 clrmap = (uchar_t *)xcalloc(msiz, sizeof (*clrmap)); 851 filmap = (uchar_t *)xcalloc(msiz, sizeof (*filmap)); 852 dirmap = (uchar_t *)xcalloc(msiz, sizeof (*dirmap)); 853 nodmap = (uchar_t *)xcalloc(msiz, sizeof (*nodmap)); 854 shamap = (uchar_t *)xcalloc(msiz, sizeof (*shamap)); 855 activemap = (uchar_t *)xcalloc(msiz, sizeof (*activemap)); 856 } else { 857 if (clrmap == NULL || filmap == NULL || dirmap == NULL || 858 nodmap == NULL || shamap == NULL || activemap == NULL) { 859 msg(gettext( 860 "Internal error: NULL map pointer while re-dumping active files")); 861 dumpabort(); 862 /*NOTREACHED*/ 863 } 864 bzero(clrmap, msiz); 865 bzero(filmap, msiz); 866 bzero(dirmap, msiz); 867 bzero(nodmap, msiz); 868 bzero(shamap, msiz); 869 /* retain active map */ 870 } 871 872 dumpstate = DS_INIT; 873 dumptoarchive = 1; 874 875 /* 876 * Read cylinder group inode-used bitmaps to avoid reading clear inodes. 877 */ 878 { 879 uchar_t *clrp = clrmap; 880 struct cg *cgp = 881 (struct cg *)xcalloc((uint_t)sblock->fs_cgsize, 1); 882 883 for (i = 0; i < sblock->fs_ncg; i++) { 884 bread(fsbtodb(sblock, cgtod(sblock, i)), 885 (uchar_t *)cgp, sblock->fs_cgsize); 886 bcopy(cg_inosused(cgp), clrp, 887 (int)sblock->fs_ipg / NBBY); 888 clrp += sblock->fs_ipg / NBBY; 889 } 890 free((char *)cgp); 891 /* XXX right-shift clrmap one bit. why? */ 892 for (i = 0; clrp > clrmap; i <<= NBBY) { 893 i |= *--clrp & ((1<<NBBY) - 1); 894 *clrp = i >> 1; 895 } 896 } 897 898 if (!printsize) { 899 msgp = gettext("Mapping (Pass I) [regular files]\n"); 900 msg(msgp); 901 } 902 903 ino = 0; 904 #ifdef PARTIAL 905 if (partial_mark(argc, argv)) { 906 #endif /* PARTIAL */ 907 if (!doingactive) 908 pass(mark, clrmap); /* mark updates 'x'_esize */ 909 else 910 pass(active_mark, clrmap); /* updates 'x'_esize */ 911 #ifdef PARTIAL 912 } 913 #endif /* PARTIAL */ 914 do { 915 if (!printsize) { 916 msgp = gettext("Mapping (Pass II) [directories]\n"); 917 msg(msgp); 918 } 919 nadded = 0; 920 ino = 0; 921 pass(add, dirmap); 922 } while (nadded); 923 924 ino = 0; /* adjust estimated size for shadow inodes */ 925 pass(markshad, nodmap); 926 ino = 0; 927 pass(estshad, shamap); 928 freeshad(); 929 930 bmapest(clrmap); 931 bmapest(nodmap); 932 esize = o_esize + f_esize; 933 if (diskette) { 934 /* estimate number of floppies */ 935 if (tsize != 0) 936 fetapes = (double)(esize + ntrec) / (double)tsize; 937 } else if (cartridge) { 938 /* 939 * Estimate number of tapes, assuming streaming stops at 940 * the end of each block written, and not in mid-block. 941 * Assume no erroneous blocks; this can be compensated for 942 * with an artificially low tape size. 943 */ 944 tenthsperirg = 16; /* actually 15.48, says Archive */ 945 if (tsize != 0) 946 fetapes = ((double)esize /* blocks */ 947 * (tp_bsize /* bytes/block */ 948 * (1.0/density)) /* 0.1" / byte */ 949 + 950 (double)esize /* blocks */ 951 * (1.0/ntrec) /* streaming-stops per block */ 952 * tenthsperirg) /* 0.1" / streaming-stop */ 953 * (1.0 / tsize); /* tape / 0.1" */ 954 } else { 955 /* Estimate number of tapes, for old fashioned 9-track tape */ 956 #ifdef sun 957 /* sun has long irg's */ 958 tenthsperirg = (density == 625) ? 6 : 12; 959 #else 960 tenthsperirg = (density == 625) ? 5 : 8; 961 #endif 962 if (tsize != 0) 963 fetapes = ((double)esize /* blocks */ 964 * (tp_bsize /* bytes / block */ 965 * (1.0/density)) /* 0.1" / byte */ 966 + 967 (double)esize /* blocks */ 968 * (1.0/ntrec) /* IRG's / block */ 969 * tenthsperirg) /* 0.1" / IRG */ 970 * (1.0 / tsize); /* tape / 0.1" */ 971 } 972 973 etapes = fetapes; /* truncating assignment */ 974 etapes++; 975 /* count the nodemap on each additional tape */ 976 for (i = 1; i < etapes; i++) 977 bmapest(nodmap); 978 /* 979 * If the above bmapest is called, it changes o_esize and f_esize. 980 * So we will recalculate esize here anyway to make sure. 981 * Also, add tape headers and trailer records. 982 */ 983 esize = o_esize + f_esize + etapes + ntrec; 984 985 /* 986 * If the estimated number of tp_bsize tape blocks is greater than 987 * INT_MAX we have to adjust tp_bsize and ntrec to handle 988 * the larger dump. esize is an estimate, so we 'fudge' 989 * INT_MAX a little. If tp_bsize is adjusted, it will be adjusted 990 * to the size needed for this dump (2048, 4096, 8192, ...) 991 */ 992 if (esize > (INT_MAX - FUDGE_FACTOR)) { /* esize is too big */ 993 forceflag++; 994 esize_shift = 995 ((esize + (INT_MAX - FUDGE_FACTOR) - 1)/ 996 ((u_offset_t)(INT_MAX - FUDGE_FACTOR))) - 1; 997 if ((esize_shift > ESIZE_SHIFT_MAX) || (ntrec == 0)) { 998 msgp = gettext( 999 "Block factor %d ('b' flag) is too small for this size dump."); 1000 msg(msgp, saved_ntrec); 1001 dumpabort(); 1002 /*NOTREACHED*/ 1003 } 1004 /* 1005 * recalculate esize from: 1006 * o_esize - header tape records 1007 * (f_esize + (num_mult -1)) >> esize_shift - new non-header 1008 * tape records for files/maps 1009 * etapes - TS_TAPE records 1010 * ntrec - TS_END records 1011 * 1012 * ntrec is adjusted so a tape record is still 'b' flag 1013 * number of DEV_BSIZE (512) in size 1014 */ 1015 new_mult = (tp_bsize << esize_shift)/tp_bsize; 1016 tp_bsize = (tp_bsize << esize_shift); 1017 esize = o_esize + ((f_esize + 1018 (new_mult - 1)) >> esize_shift) + etapes + ntrec; 1019 ntrec = (saved_ntrec/(tp_bsize/DEV_BSIZE)); 1020 } 1021 if (forceflag != 0) { 1022 msgp = gettext( 1023 "Forcing larger tape block size (%d).\n"); 1024 msg(msgp, tp_bsize); 1025 } 1026 alloctape(); /* allocate tape buffers */ 1027 1028 assert((tp_bsize / DEV_BSIZE != 0) && (tp_bsize % DEV_BSIZE == 0)); 1029 /* 1030 * If all we wanted was the size estimate, 1031 * just print it out and exit. 1032 */ 1033 if (printsize) { 1034 (void) printf("%llu\n", esize * tp_bsize); 1035 Exit(0); 1036 } 1037 1038 if (tsize != 0) { 1039 if (diskette) 1040 msgp = gettext( 1041 "Estimated %lld blocks (%s) on %3.2f diskettes.\n"); 1042 else 1043 msgp = gettext( 1044 "Estimated %lld blocks (%s) on %3.2f tapes.\n"); 1045 1046 msg(msgp, 1047 (esize*(tp_bsize/DEV_BSIZE)), mb(esize), fetapes); 1048 } else { 1049 msgp = gettext("Estimated %lld blocks (%s).\n"); 1050 msg(msgp, (esize*(tp_bsize/DEV_BSIZE)), mb(esize)); 1051 } 1052 1053 dumpstate = DS_CLRI; 1054 1055 otape(1); /* bitmap is the first to tape write */ 1056 *telapsed = 0; 1057 (void) time(tstart_writing); 1058 1059 /* filmap indicates all non-directory inodes */ 1060 { 1061 uchar_t *np, *fp, *dp; 1062 np = nodmap; 1063 dp = dirmap; 1064 fp = filmap; 1065 for (i = 0; i < msiz; i++) 1066 *fp++ = *np++ ^ *dp++; 1067 } 1068 1069 while (dumpstate != DS_DONE) { 1070 /* 1071 * When we receive EOT notification from 1072 * the writer, the signal handler calls 1073 * rollforward and then jumps here. 1074 */ 1075 (void) setjmp(checkpoint_buf); 1076 switch (dumpstate) { 1077 case DS_INIT: 1078 /* 1079 * We get here if a tape error occurred 1080 * after releasing the name lock but before 1081 * the volume containing the last of the 1082 * dir info was completed. We have to start 1083 * all over in this case. 1084 */ 1085 { 1086 char *rmsg = gettext( 1087 "Warning - output error occurred after releasing name lock\n\ 1088 \tThe dump will restart\n"); 1089 msg(rmsg); 1090 goto restart; 1091 } 1092 /* NOTREACHED */ 1093 case DS_START: 1094 case DS_CLRI: 1095 ino = UFSROOTINO; 1096 dumptoarchive = 1; 1097 bitmap(clrmap, TS_CLRI); 1098 nextstate(DS_BITS); 1099 /* FALLTHROUGH */ 1100 case DS_BITS: 1101 ino = UFSROOTINO; 1102 dumptoarchive = 1; 1103 if (BIT(UFSROOTINO, nodmap)) /* empty dump check */ 1104 bitmap(nodmap, TS_BITS); 1105 nextstate(DS_DIRS); 1106 if (!doingverify) { 1107 msgp = gettext( 1108 "Dumping (Pass III) [directories]\n"); 1109 msg(msgp); 1110 } 1111 /* FALLTHROUGH */ 1112 case DS_DIRS: 1113 dumptoarchive = 1; 1114 pass(dirdump, dirmap); 1115 nextstate(DS_FILES); 1116 if (!doingverify) { 1117 msgp = gettext( 1118 "Dumping (Pass IV) [regular files]\n"); 1119 msg(msgp); 1120 } 1121 /* FALLTHROUGH */ 1122 case DS_FILES: 1123 dumptoarchive = 0; 1124 1125 pass(lf_dump, filmap); 1126 1127 flushcmds(); 1128 dumpstate = DS_END; /* don't reset ino */ 1129 /* FALLTHROUGH */ 1130 case DS_END: 1131 dumptoarchive = 1; 1132 spcl.c_type = TS_END; 1133 for (i = 0; i < ntrec; i++) { 1134 spclrec(); 1135 } 1136 flusht(); 1137 break; 1138 case DS_DONE: 1139 break; 1140 default: 1141 msg(gettext("Internal state error\n")); 1142 dumpabort(); 1143 /*NOTREACHED*/ 1144 } 1145 } 1146 1147 if ((! doingactive) && (! active)) 1148 trewind(); 1149 if (verify && !doingverify) { 1150 msgp = gettext("Finished writing last dump volume\n"); 1151 msg(msgp); 1152 Exit(X_VERIFY); 1153 } 1154 if (spcl.c_volume > 1) 1155 (void) snprintf(msgbuf, sizeof (msgbuf), 1156 gettext("%lld blocks (%s) on %ld volumes"), 1157 ((uint64_t)spcl.c_tapea*(tp_bsize/DEV_BSIZE)), 1158 mb((u_offset_t)(unsigned)(spcl.c_tapea)), 1159 spcl.c_volume); 1160 else 1161 (void) snprintf(msgbuf, sizeof (msgbuf), 1162 gettext("%lld blocks (%s) on 1 volume"), 1163 ((uint64_t)spcl.c_tapea*(tp_bsize/DEV_BSIZE)), 1164 mb((u_offset_t)(unsigned)(spcl.c_tapea))); 1165 if (timeclock((time_t)0) != (time_t)0) { 1166 (void) snprintf(kbsbuf, sizeof (kbsbuf), 1167 gettext(" at %ld KB/sec"), 1168 (long)(((float)spcl.c_tapea / (float)timeclock((time_t)0)) 1169 * 1000.0)); 1170 (void) strcat(msgbuf, kbsbuf); 1171 } 1172 (void) strcat(msgbuf, "\n"); 1173 msg(msgbuf); 1174 (void) timeclock((time_t)-1); 1175 1176 if (archive) 1177 msg(gettext("Archiving dump to `%s'\n"), archivefile); 1178 if (active && !verify) { 1179 nextstate(DS_INIT); 1180 activepass(); 1181 goto restart; 1182 } 1183 msgp = gettext("DUMP IS DONE\n"); 1184 msg(msgp); 1185 broadcast(msgp); 1186 if (! doingactive) 1187 putitime(); 1188 Exit(X_FINOK); 1189 1190 /*NOTREACHED*/ 1191 return (0); 1192 } 1193 1194 void 1195 sigAbort(int sig) 1196 { 1197 char *sigtype; 1198 1199 switch (sig) { 1200 case SIGHUP: 1201 sigtype = "SIGHUP"; 1202 break; 1203 case SIGTRAP: 1204 sigtype = "SIGTRAP"; 1205 break; 1206 case SIGFPE: 1207 sigtype = "SIGFPE"; 1208 break; 1209 case SIGBUS: 1210 msg(gettext("%s ABORTING!\n"), "SIGBUS()"); 1211 (void) signal(SIGUSR2, SIG_DFL); 1212 abort(); 1213 /*NOTREACHED*/ 1214 case SIGSEGV: 1215 msg(gettext("%s ABORTING!\n"), "SIGSEGV()"); 1216 (void) signal(SIGUSR2, SIG_DFL); 1217 abort(); 1218 /*NOTREACHED*/ 1219 case SIGALRM: 1220 sigtype = "SIGALRM"; 1221 break; 1222 case SIGTERM: 1223 sigtype = "SIGTERM"; 1224 break; 1225 case SIGPIPE: 1226 msg(gettext("Broken pipe\n")); 1227 dumpabort(); 1228 /*NOTREACHED*/ 1229 default: 1230 sigtype = "SIGNAL"; 1231 break; 1232 } 1233 msg(gettext("%s() try rewriting\n"), sigtype); 1234 if (pipeout) { 1235 msg(gettext("Unknown signal, Cannot recover\n")); 1236 dumpabort(); 1237 /*NOTREACHED*/ 1238 } 1239 msg(gettext("Rewriting attempted as response to unknown signal.\n")); 1240 (void) fflush(stderr); 1241 (void) fflush(stdout); 1242 close_rewind(); 1243 Exit(X_REWRITE); 1244 } 1245 1246 /* Note that returned value is malloc'd if != cp && != NULL */ 1247 char * 1248 rawname(char *cp) 1249 { 1250 struct stat64 st; 1251 char *dp; 1252 extern char *getfullrawname(); 1253 1254 if (stat64(cp, &st) < 0 || (st.st_mode & S_IFMT) != S_IFBLK) 1255 return (cp); 1256 1257 dp = getfullrawname(cp); 1258 if (dp == 0) 1259 return (0); 1260 if (*dp == '\0') { 1261 free(dp); 1262 return (0); 1263 } 1264 1265 if (stat64(dp, &st) < 0 || (st.st_mode & S_IFMT) != S_IFCHR) { 1266 free(dp); 1267 return (cp); 1268 } 1269 1270 return (dp); 1271 } 1272 1273 static char * 1274 mb(u_offset_t blks) 1275 { 1276 static char buf[16]; 1277 1278 if (blks < 1024) 1279 (void) snprintf(buf, sizeof (buf), "%lldKB", blks); 1280 else 1281 (void) snprintf(buf, sizeof (buf), "%.2fMB", 1282 ((double)(blks*tp_bsize)) / (double)(1024*1024)); 1283 return (buf); 1284 } 1285 1286 #ifdef signal 1287 void (*nsignal(int sig, void (*act)(int)))(int) 1288 { 1289 struct sigaction sa, osa; 1290 1291 sa.sa_handler = act; 1292 (void) sigemptyset(&sa.sa_mask); 1293 sa.sa_flags = SA_RESTART; 1294 if (sigaction(sig, &sa, &osa) < 0) 1295 return ((void (*)(int))-1); 1296 return (osa.sa_handler); 1297 } 1298 #endif 1299 1300 static void 1301 nextstate(int state) 1302 { 1303 /* LINTED assigned value never used - kept for documentary purposes */ 1304 dumpstate = state; 1305 /* LINTED assigned value never used - kept for documentary purposes */ 1306 ino = 0; 1307 /* LINTED assigned value never used - kept for documentary purposes */ 1308 pos = 0; 1309 leftover = 0; 1310 } 1311 1312 /* 1313 * timeclock() function, for keeping track of how much time we've spent 1314 * writing to the tape device. it always returns the amount of time 1315 * already spent, in milliseconds. if you pass it a positive, then that's 1316 * telling it that we're writing, so the time counts. if you pass it a 1317 * zero, then that's telling it we're not writing; perhaps we're waiting 1318 * for user input. 1319 * 1320 * a state of -1 resets everything. 1321 */ 1322 time32_t 1323 timeclock(time32_t state) 1324 { 1325 static int *currentState = NULL; 1326 static struct timeval *clockstart; 1327 static time32_t *emilli; 1328 1329 struct timeval current[1]; 1330 int fd, saverr; 1331 1332 #ifdef DEBUG 1333 fprintf(stderr, "pid=%d timeclock ", getpid()); 1334 if (state == (time32_t)-1) 1335 fprintf(stderr, "cleared\n"); 1336 else if (state > 0) 1337 fprintf(stderr, "ticking\n"); 1338 else 1339 fprintf(stderr, "paused\n"); 1340 #endif /* DEBUG */ 1341 1342 /* if we haven't setup the shared memory, init */ 1343 if (currentState == (int *)NULL) { 1344 if ((fd = open("/dev/zero", O_RDWR)) < 0) { 1345 saverr = errno; 1346 msg(gettext("Cannot open `%s': %s\n"), 1347 "/dev/zero", strerror(saverr)); 1348 dumpabort(); 1349 /*NOTREACHED*/ 1350 } 1351 /*LINTED [mmap always returns an aligned value]*/ 1352 currentState = (int *)mmap((char *)0, getpagesize(), 1353 PROT_READ|PROT_WRITE, MAP_SHARED, fd, (off_t)0); 1354 if (currentState == (int *)-1) { 1355 saverr = errno; 1356 msg(gettext( 1357 "Cannot memory map monitor variables: %s\n"), 1358 strerror(saverr)); 1359 dumpabort(); 1360 /*NOTREACHED*/ 1361 } 1362 (void) close(fd); 1363 1364 /* LINTED currentState is sufficiently aligned */ 1365 clockstart = (struct timeval *)(currentState + 1); 1366 emilli = (time32_t *)(clockstart + 1); 1367 /* Note everything is initialized to zero via /dev/zero */ 1368 } 1369 1370 if (state == (time32_t)-1) { 1371 bzero(clockstart, sizeof (*clockstart)); 1372 *currentState = 0; 1373 *emilli = (time32_t)0; 1374 return (0); 1375 } 1376 1377 (void) gettimeofday(current, NULL); 1378 1379 if (*currentState != 0) { 1380 current->tv_usec += 1000000; 1381 current->tv_sec--; 1382 1383 /* LINTED: result will fit in a time32_t */ 1384 *emilli += (current->tv_sec - clockstart->tv_sec) * 1000; 1385 /* LINTED: result will fit in a time32_t */ 1386 *emilli += (current->tv_usec - clockstart->tv_usec) / 1000; 1387 } 1388 1389 if (state != 0) 1390 bcopy(current, clockstart, sizeof (current)); 1391 1392 *currentState = state; 1393 1394 return (*emilli); 1395 } 1396 1397 static int 1398 statcmp(const struct stat64 *left, const struct stat64 *right) 1399 { 1400 int result = 1; 1401 1402 if ((left->st_dev == right->st_dev) && 1403 (left->st_ino == right->st_ino) && 1404 (left->st_mode == right->st_mode) && 1405 (left->st_nlink == right->st_nlink) && 1406 (left->st_uid == right->st_uid) && 1407 (left->st_gid == right->st_gid) && 1408 (left->st_rdev == right->st_rdev) && 1409 (left->st_ctim.tv_sec == right->st_ctim.tv_sec) && 1410 (left->st_ctim.tv_nsec == right->st_ctim.tv_nsec) && 1411 (left->st_mtim.tv_sec == right->st_mtim.tv_sec) && 1412 (left->st_mtim.tv_nsec == right->st_mtim.tv_nsec)) { 1413 /* 1414 * Unlike in the ufsrestore version 1415 * st_blocks and st_blksiz are not 1416 * compared. The reason for this is 1417 * problems with zfs dump files. Zfs 1418 * changes it's statistics in those 1419 * fields. 1420 */ 1421 result = 0; 1422 } 1423 1424 return (result); 1425 } 1426 1427 /* 1428 * Safely open a file or device. 1429 */ 1430 static int 1431 safe_open_common(const char *filename, int mode, int perms, int device) 1432 { 1433 int fd; 1434 int working_mode; 1435 int saverr; 1436 char *errtext; 1437 struct stat64 pre_stat, pre_lstat; 1438 struct stat64 post_stat, post_lstat; 1439 1440 /* 1441 * Don't want to be spoofed into trashing something we 1442 * shouldn't, thus the following rigamarole. If it doesn't 1443 * exist, we create it and proceed. Otherwise, require that 1444 * what's there be a real file with no extraneous links and 1445 * owned by whoever ran us. 1446 * 1447 * The silliness with using both lstat() and fstat() is to avoid 1448 * race-condition games with someone replacing the file with a 1449 * symlink after we've opened it. If there was an flstat(), 1450 * we wouldn't need the fstat(). 1451 * 1452 * The initial open with the hard-coded flags is ok even if we 1453 * are intending to open only for reading. If it succeeds, 1454 * then the file did not exist, and we'll synthesize an appropriate 1455 * complaint below. Otherwise, it does exist, so we won't be 1456 * truncating it with the open. 1457 */ 1458 if ((fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_LARGEFILE, 1459 perms)) < 0) { 1460 if (errno == EEXIST) { 1461 if (lstat64(filename, &pre_lstat) < 0) { 1462 return (-1); 1463 } 1464 1465 if (stat64(filename, &pre_stat) < 0) { 1466 return (-1); 1467 } 1468 1469 working_mode = mode & (O_WRONLY|O_RDWR|O_RDONLY); 1470 working_mode |= O_LARGEFILE; 1471 if ((fd = open(filename, working_mode)) < 0) { 1472 if (errno == ENOENT) { 1473 errtext = gettext( 1474 "Unexpected condition detected: %s used to exist, but doesn't any longer\n"); 1475 msg(errtext, filename); 1476 syslog(LOG_WARNING, errtext, filename); 1477 errno = ENOENT; 1478 } 1479 return (-1); 1480 } 1481 1482 if (lstat64(filename, &post_lstat) < 0) { 1483 saverr = errno; 1484 (void) close(fd); 1485 errno = saverr; 1486 return (-1); 1487 } 1488 1489 if (fstat64(fd, &post_stat) < 0) { 1490 saverr = errno; 1491 (void) close(fd); 1492 errno = saverr; 1493 return (-1); 1494 } 1495 1496 /* 1497 * Can't just use memcmp(3C), because the access 1498 * time is updated by open(2). 1499 */ 1500 if (statcmp(&pre_lstat, &post_lstat) != 0) { 1501 errtext = gettext("Unexpected change detected: " 1502 "%s's lstat(2) information changed\n"); 1503 msg(errtext, filename); 1504 syslog(LOG_WARNING, errtext, filename); 1505 errno = EPERM; 1506 return (-1); 1507 } 1508 1509 if (statcmp(&pre_stat, &post_stat) != 0) { 1510 errtext = gettext("Unexpected change detected: " 1511 "%s's stat(2) information changed\n"), 1512 msg(errtext, filename); 1513 syslog(LOG_WARNING, errtext, filename); 1514 errno = EPERM; 1515 return (-1); 1516 } 1517 1518 /* 1519 * If inode, device, or type are wrong, bail out. 1520 * Note using post_stat instead of post_lstat for the 1521 * S_ISCHR() test. This is to allow the /dev -> 1522 * /devices bit to work, as long as the final target 1523 * is a character device (i.e., raw disk or tape). 1524 */ 1525 if (device && !(S_ISCHR(post_stat.st_mode)) && 1526 !(S_ISFIFO(post_stat.st_mode)) && 1527 !(S_ISREG(post_lstat.st_mode))) { 1528 errtext = gettext("Unexpected condition " 1529 "detected: %s is not a supported device\n"), 1530 msg(errtext, filename); 1531 syslog(LOG_WARNING, errtext, filename); 1532 (void) close(fd); 1533 errno = EPERM; 1534 return (-1); 1535 } else if (!device && 1536 (!S_ISREG(post_lstat.st_mode) || 1537 (post_stat.st_ino != post_lstat.st_ino) || 1538 (post_stat.st_dev != post_lstat.st_dev))) { 1539 errtext = gettext("Unexpected condition " 1540 "detected: %s is not a regular file\n"), 1541 msg(errtext, filename); 1542 syslog(LOG_WARNING, errtext, filename); 1543 (void) close(fd); 1544 errno = EPERM; 1545 return (-1); 1546 } 1547 1548 /* 1549 * Bad link count implies someone's linked our 1550 * target to something else, which we probably 1551 * shouldn't step on. 1552 */ 1553 if (post_lstat.st_nlink != 1) { 1554 errtext = gettext("Unexpected condition " 1555 "detected: %s must have exactly one " 1556 "link\n"), msg(errtext, filename); 1557 syslog(LOG_WARNING, errtext, filename); 1558 (void) close(fd); 1559 errno = EPERM; 1560 return (-1); 1561 } 1562 /* 1563 * Root might make a file, but non-root might 1564 * need to open it. If the permissions let us 1565 * get this far, then let it through. 1566 */ 1567 if (post_lstat.st_uid != getuid() && 1568 post_lstat.st_uid != 0) { 1569 errtext = gettext("Unsupported " 1570 "condition detected: %s " 1571 "must be owned by uid %ld or 0\n"), 1572 msg(errtext, filename, (long)getuid()); 1573 syslog(LOG_WARNING, errtext, filename, 1574 (long)getuid()); 1575 (void) close(fd); 1576 errno = EPERM; 1577 return (-1); 1578 } 1579 if (mode & O_TRUNC) { 1580 if (ftruncate(fd, (off_t)0) < 0) { 1581 msg("ftruncate(%s): %s\n", 1582 filename, strerror(errno)); 1583 (void) close(fd); 1584 return (-1); 1585 } 1586 } 1587 } else { 1588 /* 1589 * Didn't exist, but couldn't open it. 1590 */ 1591 return (-1); 1592 } 1593 } else { 1594 /* 1595 * If truncating open succeeded for a read-only open, 1596 * bail out, as we really shouldn't have succeeded. 1597 */ 1598 if (mode & O_RDONLY) { 1599 /* Undo the O_CREAT */ 1600 (void) unlink(filename); 1601 msg("open(%s): %s\n", 1602 filename, strerror(ENOENT)); 1603 (void) close(fd); 1604 errno = ENOENT; 1605 return (-1); 1606 } 1607 } 1608 1609 return (fd); 1610 } 1611 1612 /* 1613 * Safely open a file. 1614 */ 1615 int 1616 safe_file_open(const char *filename, int mode, int perms) 1617 { 1618 return (safe_open_common(filename, mode, perms, 0)); 1619 } 1620 1621 /* 1622 * Safely open a device. 1623 */ 1624 int 1625 safe_device_open(const char *filename, int mode, int perms) 1626 { 1627 return (safe_open_common(filename, mode, perms, 1)); 1628 } 1629 1630 /* 1631 * STDIO version of safe_open 1632 */ 1633 FILE * 1634 safe_fopen(const char *filename, const char *smode, int perms) 1635 { 1636 int fd; 1637 int bmode; 1638 1639 /* 1640 * accepts only modes "r", "r+", and "w" 1641 */ 1642 if (smode[0] == 'r') { 1643 if (smode[1] == '\0') { 1644 bmode = O_RDONLY; 1645 } else if ((smode[1] == '+') && (smode[2] == '\0')) { 1646 bmode = O_RDWR; 1647 } 1648 } else if ((smode[0] == 'w') && (smode[1] == '\0')) { 1649 bmode = O_WRONLY; 1650 } else { 1651 msg(gettext("internal error: safe_fopen: invalid mode `%s'\n"), 1652 smode); 1653 return (NULL); 1654 } 1655 1656 fd = safe_file_open(filename, bmode, perms); 1657 1658 /* 1659 * caller is expected to report error. 1660 */ 1661 if (fd >= 0) 1662 return (fdopen(fd, smode)); 1663 1664 return ((FILE *)NULL); 1665 } 1666 1667 void 1668 child_chdir(void) 1669 { 1670 char name[MAXPATHLEN]; 1671 1672 if (debug_chdir != NULL) { 1673 snprintf(name, sizeof (name), "%s/%ld", 1674 debug_chdir, (long)getpid()); 1675 if (mkdir(name, 0755) < 0) 1676 msg("mkdir(%s): %s", name, strerror(errno)); 1677 if (chdir(name) < 0) 1678 msg("chdir(%s): %s", name, strerror(errno)); 1679 } 1680 } 1681