1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 2012, 2013 SRI International 5 * Copyright (c) 1987, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #ifndef lint 34 static const char copyright[] = 35 "@(#) Copyright (c) 1987, 1993\n\ 36 The Regents of the University of California. All rights reserved.\n"; 37 #endif /* not lint */ 38 39 #if 0 40 #ifndef lint 41 static char sccsid[] = "@(#)xinstall.c 8.1 (Berkeley) 7/21/93"; 42 #endif /* not lint */ 43 #endif 44 45 #include <sys/cdefs.h> 46 __FBSDID("$FreeBSD$"); 47 48 #include <sys/param.h> 49 #include <sys/mman.h> 50 #include <sys/mount.h> 51 #include <sys/stat.h> 52 #include <sys/time.h> 53 #include <sys/wait.h> 54 55 #include <err.h> 56 #include <errno.h> 57 #include <fcntl.h> 58 #include <grp.h> 59 #include <libgen.h> 60 #ifdef WITH_MD5 61 #include <md5.h> 62 #endif 63 #include <paths.h> 64 #include <pwd.h> 65 #ifdef WITH_RIPEMD160 66 #include <ripemd.h> 67 #endif 68 #include <sha.h> 69 #include <sha256.h> 70 #include <sha512.h> 71 #include <spawn.h> 72 #include <stdint.h> 73 #include <stdio.h> 74 #include <stdlib.h> 75 #include <string.h> 76 #include <sysexits.h> 77 #include <unistd.h> 78 #include <vis.h> 79 80 #include "mtree.h" 81 82 /* 83 * Memory strategy threshold, in pages: if physmem is larger then this, use a 84 * large buffer. 85 */ 86 #define PHYSPAGES_THRESHOLD (32*1024) 87 88 /* Maximum buffer size in bytes - do not allow it to grow larger than this. */ 89 #define BUFSIZE_MAX (2*1024*1024) 90 91 /* 92 * Small (default) buffer size in bytes. It's inefficient for this to be 93 * smaller than MAXPHYS. 94 */ 95 #define BUFSIZE_SMALL (MAXPHYS) 96 97 /* 98 * We need to build xinstall during the bootstrap stage when building on a 99 * non-FreeBSD system. Linux does not have the st_flags and st_birthtime 100 * members in struct stat so we need to omit support for changing those fields. 101 */ 102 #ifdef UF_SETTABLE 103 #define HAVE_STRUCT_STAT_ST_FLAGS 1 104 #else 105 #define HAVE_STRUCT_STAT_ST_FLAGS 0 106 #endif 107 108 #define MAX_CMP_SIZE (16 * 1024 * 1024) 109 110 #define LN_ABSOLUTE 0x01 111 #define LN_RELATIVE 0x02 112 #define LN_HARD 0x04 113 #define LN_SYMBOLIC 0x08 114 #define LN_MIXED 0x10 115 116 #define DIRECTORY 0x01 /* Tell install it's a directory. */ 117 #define SETFLAGS 0x02 /* Tell install to set flags. */ 118 #define NOCHANGEBITS (UF_IMMUTABLE | UF_APPEND | SF_IMMUTABLE | SF_APPEND) 119 #define BACKUP_SUFFIX ".old" 120 121 typedef union { 122 #ifdef WITH_MD5 123 MD5_CTX MD5; 124 #endif 125 #ifdef WITH_RIPEMD160 126 RIPEMD160_CTX RIPEMD160; 127 #endif 128 SHA1_CTX SHA1; 129 SHA256_CTX SHA256; 130 SHA512_CTX SHA512; 131 } DIGEST_CTX; 132 133 static enum { 134 DIGEST_NONE = 0, 135 #ifdef WITH_MD5 136 DIGEST_MD5, 137 #endif 138 #ifdef WITH_RIPEMD160 139 DIGEST_RIPEMD160, 140 #endif 141 DIGEST_SHA1, 142 DIGEST_SHA256, 143 DIGEST_SHA512, 144 } digesttype = DIGEST_NONE; 145 146 extern char **environ; 147 148 static gid_t gid; 149 static uid_t uid; 150 static int dobackup, docompare, dodir, dolink, dopreserve, dostrip, dounpriv, 151 safecopy, verbose; 152 static int haveopt_f, haveopt_g, haveopt_m, haveopt_o; 153 static mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 154 static FILE *metafp; 155 static const char *group, *owner; 156 static const char *suffix = BACKUP_SUFFIX; 157 static char *destdir, *digest, *fflags, *metafile, *tags; 158 159 static int compare(int, const char *, size_t, int, const char *, size_t, 160 char **); 161 static char *copy(int, const char *, int, const char *, off_t); 162 static int create_newfile(const char *, int, struct stat *); 163 static int create_tempfile(const char *, char *, size_t); 164 static char *quiet_mktemp(char *template); 165 static char *digest_file(const char *); 166 static void digest_init(DIGEST_CTX *); 167 static void digest_update(DIGEST_CTX *, const char *, size_t); 168 static char *digest_end(DIGEST_CTX *, char *); 169 static int do_link(const char *, const char *, const struct stat *); 170 static void do_symlink(const char *, const char *, const struct stat *); 171 static void makelink(const char *, const char *, const struct stat *); 172 static void install(const char *, const char *, u_long, u_int); 173 static void install_dir(char *); 174 static void metadata_log(const char *, const char *, struct timespec *, 175 const char *, const char *, off_t); 176 static int parseid(const char *, id_t *); 177 static int strip(const char *, int, const char *, char **); 178 static int trymmap(size_t); 179 static void usage(void); 180 181 int 182 main(int argc, char *argv[]) 183 { 184 struct stat from_sb, to_sb; 185 mode_t *set; 186 u_long fset; 187 int ch, no_target; 188 u_int iflags; 189 char *p; 190 const char *to_name; 191 192 fset = 0; 193 iflags = 0; 194 group = owner = NULL; 195 while ((ch = getopt(argc, argv, "B:bCcD:df:g:h:l:M:m:N:o:pSsT:Uv")) != 196 -1) 197 switch((char)ch) { 198 case 'B': 199 suffix = optarg; 200 /* FALLTHROUGH */ 201 case 'b': 202 dobackup = 1; 203 break; 204 case 'C': 205 docompare = 1; 206 break; 207 case 'c': 208 /* For backwards compatibility. */ 209 break; 210 case 'D': 211 destdir = optarg; 212 break; 213 case 'd': 214 dodir = 1; 215 break; 216 case 'f': 217 haveopt_f = 1; 218 fflags = optarg; 219 break; 220 case 'g': 221 haveopt_g = 1; 222 group = optarg; 223 break; 224 case 'h': 225 digest = optarg; 226 break; 227 case 'l': 228 for (p = optarg; *p != '\0'; p++) 229 switch (*p) { 230 case 's': 231 dolink &= ~(LN_HARD|LN_MIXED); 232 dolink |= LN_SYMBOLIC; 233 break; 234 case 'h': 235 dolink &= ~(LN_SYMBOLIC|LN_MIXED); 236 dolink |= LN_HARD; 237 break; 238 case 'm': 239 dolink &= ~(LN_SYMBOLIC|LN_HARD); 240 dolink |= LN_MIXED; 241 break; 242 case 'a': 243 dolink &= ~LN_RELATIVE; 244 dolink |= LN_ABSOLUTE; 245 break; 246 case 'r': 247 dolink &= ~LN_ABSOLUTE; 248 dolink |= LN_RELATIVE; 249 break; 250 default: 251 errx(1, "%c: invalid link type", *p); 252 /* NOTREACHED */ 253 } 254 break; 255 case 'M': 256 metafile = optarg; 257 break; 258 case 'm': 259 haveopt_m = 1; 260 if (!(set = setmode(optarg))) 261 errx(EX_USAGE, "invalid file mode: %s", 262 optarg); 263 mode = getmode(set, 0); 264 free(set); 265 break; 266 case 'N': 267 if (!setup_getid(optarg)) 268 err(EX_OSERR, "Unable to use user and group " 269 "databases in `%s'", optarg); 270 break; 271 case 'o': 272 haveopt_o = 1; 273 owner = optarg; 274 break; 275 case 'p': 276 docompare = dopreserve = 1; 277 break; 278 case 'S': 279 safecopy = 1; 280 break; 281 case 's': 282 dostrip = 1; 283 break; 284 case 'T': 285 tags = optarg; 286 break; 287 case 'U': 288 dounpriv = 1; 289 break; 290 case 'v': 291 verbose = 1; 292 break; 293 case '?': 294 default: 295 usage(); 296 } 297 argc -= optind; 298 argv += optind; 299 300 /* some options make no sense when creating directories */ 301 if (dostrip && dodir) { 302 warnx("-d and -s may not be specified together"); 303 usage(); 304 } 305 306 if (getenv("DONTSTRIP") != NULL) { 307 warnx("DONTSTRIP set - will not strip installed binaries"); 308 dostrip = 0; 309 } 310 311 /* must have at least two arguments, except when creating directories */ 312 if (argc == 0 || (argc == 1 && !dodir)) 313 usage(); 314 315 if (digest != NULL) { 316 if (strcmp(digest, "none") == 0) { 317 digesttype = DIGEST_NONE; 318 #ifdef WITH_MD5 319 } else if (strcmp(digest, "md5") == 0) { 320 digesttype = DIGEST_MD5; 321 #endif 322 #ifdef WITH_RIPEMD160 323 } else if (strcmp(digest, "rmd160") == 0) { 324 digesttype = DIGEST_RIPEMD160; 325 #endif 326 } else if (strcmp(digest, "sha1") == 0) { 327 digesttype = DIGEST_SHA1; 328 } else if (strcmp(digest, "sha256") == 0) { 329 digesttype = DIGEST_SHA256; 330 } else if (strcmp(digest, "sha512") == 0) { 331 digesttype = DIGEST_SHA512; 332 } else { 333 warnx("unknown digest `%s'", digest); 334 usage(); 335 } 336 } 337 338 /* need to make a temp copy so we can compare stripped version */ 339 if (docompare && dostrip) 340 safecopy = 1; 341 342 /* get group and owner id's */ 343 if (group != NULL && !dounpriv) { 344 if (gid_from_group(group, &gid) == -1) { 345 id_t id; 346 if (!parseid(group, &id)) 347 errx(1, "unknown group %s", group); 348 gid = id; 349 } 350 } else 351 gid = (gid_t)-1; 352 353 if (owner != NULL && !dounpriv) { 354 if (uid_from_user(owner, &uid) == -1) { 355 id_t id; 356 if (!parseid(owner, &id)) 357 errx(1, "unknown user %s", owner); 358 uid = id; 359 } 360 } else 361 uid = (uid_t)-1; 362 363 if (fflags != NULL && !dounpriv) { 364 if (strtofflags(&fflags, &fset, NULL)) 365 errx(EX_USAGE, "%s: invalid flag", fflags); 366 iflags |= SETFLAGS; 367 } 368 369 if (metafile != NULL) { 370 if ((metafp = fopen(metafile, "a")) == NULL) 371 warn("open %s", metafile); 372 } else 373 digesttype = DIGEST_NONE; 374 375 if (dodir) { 376 for (; *argv != NULL; ++argv) 377 install_dir(*argv); 378 exit(EX_OK); 379 /* NOTREACHED */ 380 } 381 382 to_name = argv[argc - 1]; 383 no_target = stat(to_name, &to_sb); 384 if (!no_target && S_ISDIR(to_sb.st_mode)) { 385 if (dolink & LN_SYMBOLIC) { 386 if (lstat(to_name, &to_sb) != 0) 387 err(EX_OSERR, "%s vanished", to_name); 388 if (S_ISLNK(to_sb.st_mode)) { 389 if (argc != 2) { 390 errno = ENOTDIR; 391 err(EX_USAGE, "%s", to_name); 392 } 393 install(*argv, to_name, fset, iflags); 394 exit(EX_OK); 395 } 396 } 397 for (; *argv != to_name; ++argv) 398 install(*argv, to_name, fset, iflags | DIRECTORY); 399 exit(EX_OK); 400 /* NOTREACHED */ 401 } 402 403 /* can't do file1 file2 directory/file */ 404 if (argc != 2) { 405 if (no_target) 406 warnx("target directory `%s' does not exist", 407 argv[argc - 1]); 408 else 409 warnx("target `%s' is not a directory", 410 argv[argc - 1]); 411 usage(); 412 } 413 414 if (!no_target && !dolink) { 415 if (stat(*argv, &from_sb)) 416 err(EX_OSERR, "%s", *argv); 417 if (!S_ISREG(to_sb.st_mode)) { 418 errno = EFTYPE; 419 err(EX_OSERR, "%s", to_name); 420 } 421 if (to_sb.st_dev == from_sb.st_dev && 422 to_sb.st_ino == from_sb.st_ino) 423 errx(EX_USAGE, 424 "%s and %s are the same file", *argv, to_name); 425 } 426 install(*argv, to_name, fset, iflags); 427 exit(EX_OK); 428 /* NOTREACHED */ 429 } 430 431 static char * 432 digest_file(const char *name) 433 { 434 435 switch (digesttype) { 436 #ifdef WITH_MD5 437 case DIGEST_MD5: 438 return (MD5File(name, NULL)); 439 #endif 440 #ifdef WITH_RIPEMD160 441 case DIGEST_RIPEMD160: 442 return (RIPEMD160_File(name, NULL)); 443 #endif 444 case DIGEST_SHA1: 445 return (SHA1_File(name, NULL)); 446 case DIGEST_SHA256: 447 return (SHA256_File(name, NULL)); 448 case DIGEST_SHA512: 449 return (SHA512_File(name, NULL)); 450 default: 451 return (NULL); 452 } 453 } 454 455 static void 456 digest_init(DIGEST_CTX *c) 457 { 458 459 switch (digesttype) { 460 case DIGEST_NONE: 461 break; 462 #ifdef WITH_MD5 463 case DIGEST_MD5: 464 MD5Init(&(c->MD5)); 465 break; 466 #endif 467 #ifdef WITH_RIPEMD160 468 case DIGEST_RIPEMD160: 469 RIPEMD160_Init(&(c->RIPEMD160)); 470 break; 471 #endif 472 case DIGEST_SHA1: 473 SHA1_Init(&(c->SHA1)); 474 break; 475 case DIGEST_SHA256: 476 SHA256_Init(&(c->SHA256)); 477 break; 478 case DIGEST_SHA512: 479 SHA512_Init(&(c->SHA512)); 480 break; 481 } 482 } 483 484 static void 485 digest_update(DIGEST_CTX *c, const char *data, size_t len) 486 { 487 488 switch (digesttype) { 489 case DIGEST_NONE: 490 break; 491 #ifdef WITH_MD5 492 case DIGEST_MD5: 493 MD5Update(&(c->MD5), data, len); 494 break; 495 #endif 496 #ifdef WITH_RIPEMD160 497 case DIGEST_RIPEMD160: 498 RIPEMD160_Update(&(c->RIPEMD160), data, len); 499 break; 500 #endif 501 case DIGEST_SHA1: 502 SHA1_Update(&(c->SHA1), data, len); 503 break; 504 case DIGEST_SHA256: 505 SHA256_Update(&(c->SHA256), data, len); 506 break; 507 case DIGEST_SHA512: 508 SHA512_Update(&(c->SHA512), data, len); 509 break; 510 } 511 } 512 513 static char * 514 digest_end(DIGEST_CTX *c, char *buf) 515 { 516 517 switch (digesttype) { 518 #ifdef WITH_MD5 519 case DIGEST_MD5: 520 return (MD5End(&(c->MD5), buf)); 521 #endif 522 #ifdef WITH_RIPEMD160 523 case DIGEST_RIPEMD160: 524 return (RIPEMD160_End(&(c->RIPEMD160), buf)); 525 #endif 526 case DIGEST_SHA1: 527 return (SHA1_End(&(c->SHA1), buf)); 528 case DIGEST_SHA256: 529 return (SHA256_End(&(c->SHA256), buf)); 530 case DIGEST_SHA512: 531 return (SHA512_End(&(c->SHA512), buf)); 532 default: 533 return (NULL); 534 } 535 } 536 537 /* 538 * parseid -- 539 * parse uid or gid from arg into id, returning non-zero if successful 540 */ 541 static int 542 parseid(const char *name, id_t *id) 543 { 544 char *ep; 545 errno = 0; 546 *id = (id_t)strtoul(name, &ep, 10); 547 if (errno || *ep != '\0') 548 return (0); 549 return (1); 550 } 551 552 /* 553 * quiet_mktemp -- 554 * mktemp implementation used mkstemp to avoid mktemp warnings. We 555 * really do need mktemp semantics here as we will be creating a link. 556 */ 557 static char * 558 quiet_mktemp(char *template) 559 { 560 int fd; 561 562 if ((fd = mkstemp(template)) == -1) 563 return (NULL); 564 close (fd); 565 if (unlink(template) == -1) 566 err(EX_OSERR, "unlink %s", template); 567 return (template); 568 } 569 570 /* 571 * do_link -- 572 * make a hard link, obeying dorename if set 573 * return -1 on failure 574 */ 575 static int 576 do_link(const char *from_name, const char *to_name, 577 const struct stat *target_sb) 578 { 579 char tmpl[MAXPATHLEN]; 580 int ret; 581 582 if (safecopy && target_sb != NULL) { 583 (void)snprintf(tmpl, sizeof(tmpl), "%s.inst.XXXXXX", to_name); 584 /* This usage is safe. */ 585 if (quiet_mktemp(tmpl) == NULL) 586 err(EX_OSERR, "%s: mktemp", tmpl); 587 ret = link(from_name, tmpl); 588 if (ret == 0) { 589 if (target_sb->st_mode & S_IFDIR && rmdir(to_name) == 590 -1) { 591 unlink(tmpl); 592 err(EX_OSERR, "%s", to_name); 593 } 594 #if HAVE_STRUCT_STAT_ST_FLAGS 595 if (target_sb->st_flags & NOCHANGEBITS) 596 (void)chflags(to_name, target_sb->st_flags & 597 ~NOCHANGEBITS); 598 #endif 599 if (verbose) 600 printf("install: link %s -> %s\n", 601 from_name, to_name); 602 ret = rename(tmpl, to_name); 603 /* 604 * If rename has posix semantics, then the temporary 605 * file may still exist when from_name and to_name point 606 * to the same file, so unlink it unconditionally. 607 */ 608 (void)unlink(tmpl); 609 } 610 return (ret); 611 } else { 612 if (verbose) 613 printf("install: link %s -> %s\n", 614 from_name, to_name); 615 return (link(from_name, to_name)); 616 } 617 } 618 619 /* 620 * do_symlink -- 621 * Make a symbolic link, obeying dorename if set. Exit on failure. 622 */ 623 static void 624 do_symlink(const char *from_name, const char *to_name, 625 const struct stat *target_sb) 626 { 627 char tmpl[MAXPATHLEN]; 628 629 if (safecopy && target_sb != NULL) { 630 (void)snprintf(tmpl, sizeof(tmpl), "%s.inst.XXXXXX", to_name); 631 /* This usage is safe. */ 632 if (quiet_mktemp(tmpl) == NULL) 633 err(EX_OSERR, "%s: mktemp", tmpl); 634 635 if (symlink(from_name, tmpl) == -1) 636 err(EX_OSERR, "symlink %s -> %s", from_name, tmpl); 637 638 if (target_sb->st_mode & S_IFDIR && rmdir(to_name) == -1) { 639 (void)unlink(tmpl); 640 err(EX_OSERR, "%s", to_name); 641 } 642 #if HAVE_STRUCT_STAT_ST_FLAGS 643 if (target_sb->st_flags & NOCHANGEBITS) 644 (void)chflags(to_name, target_sb->st_flags & 645 ~NOCHANGEBITS); 646 #endif 647 if (verbose) 648 printf("install: symlink %s -> %s\n", 649 from_name, to_name); 650 if (rename(tmpl, to_name) == -1) { 651 /* Remove temporary link before exiting. */ 652 (void)unlink(tmpl); 653 err(EX_OSERR, "%s: rename", to_name); 654 } 655 } else { 656 if (verbose) 657 printf("install: symlink %s -> %s\n", 658 from_name, to_name); 659 if (symlink(from_name, to_name) == -1) 660 err(EX_OSERR, "symlink %s -> %s", from_name, to_name); 661 } 662 } 663 664 /* 665 * makelink -- 666 * make a link from source to destination 667 */ 668 static void 669 makelink(const char *from_name, const char *to_name, 670 const struct stat *target_sb) 671 { 672 char src[MAXPATHLEN], dst[MAXPATHLEN], lnk[MAXPATHLEN]; 673 struct stat to_sb; 674 675 /* Try hard links first. */ 676 if (dolink & (LN_HARD|LN_MIXED)) { 677 if (do_link(from_name, to_name, target_sb) == -1) { 678 if ((dolink & LN_HARD) || errno != EXDEV) 679 err(EX_OSERR, "link %s -> %s", from_name, to_name); 680 } else { 681 if (stat(to_name, &to_sb)) 682 err(EX_OSERR, "%s: stat", to_name); 683 if (S_ISREG(to_sb.st_mode)) { 684 /* 685 * XXX: hard links to anything other than 686 * plain files are not metalogged 687 */ 688 int omode; 689 const char *oowner, *ogroup; 690 char *offlags; 691 char *dres; 692 693 /* 694 * XXX: use underlying perms, unless 695 * overridden on command line. 696 */ 697 omode = mode; 698 if (!haveopt_m) 699 mode = (to_sb.st_mode & 0777); 700 oowner = owner; 701 if (!haveopt_o) 702 owner = NULL; 703 ogroup = group; 704 if (!haveopt_g) 705 group = NULL; 706 offlags = fflags; 707 if (!haveopt_f) 708 fflags = NULL; 709 dres = digest_file(from_name); 710 metadata_log(to_name, "file", NULL, NULL, 711 dres, to_sb.st_size); 712 free(dres); 713 mode = omode; 714 owner = oowner; 715 group = ogroup; 716 fflags = offlags; 717 } 718 return; 719 } 720 } 721 722 /* Symbolic links. */ 723 if (dolink & LN_ABSOLUTE) { 724 /* Convert source path to absolute. */ 725 if (realpath(from_name, src) == NULL) 726 err(EX_OSERR, "%s: realpath", from_name); 727 do_symlink(src, to_name, target_sb); 728 /* XXX: src may point outside of destdir */ 729 metadata_log(to_name, "link", NULL, src, NULL, 0); 730 return; 731 } 732 733 if (dolink & LN_RELATIVE) { 734 char *to_name_copy, *cp, *d, *ld, *ls, *s; 735 736 if (*from_name != '/') { 737 /* this is already a relative link */ 738 do_symlink(from_name, to_name, target_sb); 739 /* XXX: from_name may point outside of destdir. */ 740 metadata_log(to_name, "link", NULL, from_name, NULL, 0); 741 return; 742 } 743 744 /* Resolve pathnames. */ 745 if (realpath(from_name, src) == NULL) 746 err(EX_OSERR, "%s: realpath", from_name); 747 748 /* 749 * The last component of to_name may be a symlink, 750 * so use realpath to resolve only the directory. 751 */ 752 to_name_copy = strdup(to_name); 753 if (to_name_copy == NULL) 754 err(EX_OSERR, "%s: strdup", to_name); 755 cp = dirname(to_name_copy); 756 if (realpath(cp, dst) == NULL) 757 err(EX_OSERR, "%s: realpath", cp); 758 /* .. and add the last component. */ 759 if (strcmp(dst, "/") != 0) { 760 if (strlcat(dst, "/", sizeof(dst)) > sizeof(dst)) 761 errx(1, "resolved pathname too long"); 762 } 763 strcpy(to_name_copy, to_name); 764 cp = basename(to_name_copy); 765 if (strlcat(dst, cp, sizeof(dst)) > sizeof(dst)) 766 errx(1, "resolved pathname too long"); 767 free(to_name_copy); 768 769 /* Trim common path components. */ 770 ls = ld = NULL; 771 for (s = src, d = dst; *s == *d; ls = s, ld = d, s++, d++) 772 continue; 773 /* 774 * If we didn't end after a directory separator, then we've 775 * falsely matched the last component. For example, if one 776 * invoked install -lrs /lib/foo.so /libexec/ then the source 777 * would terminate just after the separator while the 778 * destination would terminate in the middle of 'libexec', 779 * leading to a full directory getting falsely eaten. 780 */ 781 if ((ls != NULL && *ls != '/') || (ld != NULL && *ld != '/')) 782 s--, d--; 783 while (*s != '/') 784 s--, d--; 785 786 /* Count the number of directories we need to backtrack. */ 787 for (++d, lnk[0] = '\0'; *d; d++) 788 if (*d == '/') 789 (void)strlcat(lnk, "../", sizeof(lnk)); 790 791 (void)strlcat(lnk, ++s, sizeof(lnk)); 792 793 do_symlink(lnk, to_name, target_sb); 794 /* XXX: Link may point outside of destdir. */ 795 metadata_log(to_name, "link", NULL, lnk, NULL, 0); 796 return; 797 } 798 799 /* 800 * If absolute or relative was not specified, try the names the 801 * user provided. 802 */ 803 do_symlink(from_name, to_name, target_sb); 804 /* XXX: from_name may point outside of destdir. */ 805 metadata_log(to_name, "link", NULL, from_name, NULL, 0); 806 } 807 808 /* 809 * install -- 810 * build a path name and install the file 811 */ 812 static void 813 install(const char *from_name, const char *to_name, u_long fset, u_int flags) 814 { 815 struct stat from_sb, temp_sb, to_sb; 816 struct timespec tsb[2]; 817 int devnull, files_match, from_fd, serrno, stripped, target; 818 int tempcopy, temp_fd, to_fd; 819 char backup[MAXPATHLEN], *p, pathbuf[MAXPATHLEN], tempfile[MAXPATHLEN]; 820 char *digestresult; 821 822 digestresult = NULL; 823 files_match = stripped = 0; 824 from_fd = -1; 825 to_fd = -1; 826 827 /* If try to install NULL file to a directory, fails. */ 828 if (flags & DIRECTORY || strcmp(from_name, _PATH_DEVNULL)) { 829 if (!dolink) { 830 if (stat(from_name, &from_sb)) 831 err(EX_OSERR, "%s", from_name); 832 if (!S_ISREG(from_sb.st_mode)) { 833 errno = EFTYPE; 834 err(EX_OSERR, "%s", from_name); 835 } 836 } 837 /* Build the target path. */ 838 if (flags & DIRECTORY) { 839 (void)snprintf(pathbuf, sizeof(pathbuf), "%s%s%s", 840 to_name, 841 to_name[strlen(to_name) - 1] == '/' ? "" : "/", 842 (p = strrchr(from_name, '/')) ? ++p : from_name); 843 to_name = pathbuf; 844 } 845 devnull = 0; 846 } else { 847 devnull = 1; 848 } 849 850 target = (lstat(to_name, &to_sb) == 0); 851 852 if (dolink) { 853 if (target && !safecopy) { 854 if (to_sb.st_mode & S_IFDIR && rmdir(to_name) == -1) 855 err(EX_OSERR, "%s", to_name); 856 #if HAVE_STRUCT_STAT_ST_FLAGS 857 if (to_sb.st_flags & NOCHANGEBITS) 858 (void)chflags(to_name, 859 to_sb.st_flags & ~NOCHANGEBITS); 860 #endif 861 unlink(to_name); 862 } 863 makelink(from_name, to_name, target ? &to_sb : NULL); 864 return; 865 } 866 867 if (target && !S_ISREG(to_sb.st_mode) && !S_ISLNK(to_sb.st_mode)) { 868 errno = EFTYPE; 869 warn("%s", to_name); 870 return; 871 } 872 873 /* Only copy safe if the target exists. */ 874 tempcopy = safecopy && target; 875 876 if (!devnull && (from_fd = open(from_name, O_RDONLY, 0)) < 0) 877 err(EX_OSERR, "%s", from_name); 878 879 /* If we don't strip, we can compare first. */ 880 if (docompare && !dostrip && target && S_ISREG(to_sb.st_mode)) { 881 if ((to_fd = open(to_name, O_RDONLY, 0)) < 0) 882 err(EX_OSERR, "%s", to_name); 883 if (devnull) 884 files_match = to_sb.st_size == 0; 885 else 886 files_match = !(compare(from_fd, from_name, 887 (size_t)from_sb.st_size, to_fd, 888 to_name, (size_t)to_sb.st_size, &digestresult)); 889 890 /* Close "to" file unless we match. */ 891 if (!files_match) 892 (void)close(to_fd); 893 } 894 895 if (!files_match) { 896 if (tempcopy) { 897 to_fd = create_tempfile(to_name, tempfile, 898 sizeof(tempfile)); 899 if (to_fd < 0) 900 err(EX_OSERR, "%s", tempfile); 901 } else { 902 if ((to_fd = create_newfile(to_name, target, 903 &to_sb)) < 0) 904 err(EX_OSERR, "%s", to_name); 905 if (verbose) 906 (void)printf("install: %s -> %s\n", 907 from_name, to_name); 908 } 909 if (!devnull) { 910 if (dostrip) 911 stripped = strip(tempcopy ? tempfile : to_name, 912 to_fd, from_name, &digestresult); 913 if (!stripped) 914 digestresult = copy(from_fd, from_name, to_fd, 915 tempcopy ? tempfile : to_name, from_sb.st_size); 916 } 917 } 918 919 if (dostrip) { 920 if (!stripped) 921 (void)strip(tempcopy ? tempfile : to_name, to_fd, 922 NULL, &digestresult); 923 924 /* 925 * Re-open our fd on the target, in case 926 * we did not strip in-place. 927 */ 928 close(to_fd); 929 to_fd = open(tempcopy ? tempfile : to_name, O_RDONLY, 0); 930 if (to_fd < 0) 931 err(EX_OSERR, "stripping %s", to_name); 932 } 933 934 /* 935 * Compare the stripped temp file with the target. 936 */ 937 if (docompare && dostrip && target && S_ISREG(to_sb.st_mode)) { 938 temp_fd = to_fd; 939 940 /* Re-open to_fd using the real target name. */ 941 if ((to_fd = open(to_name, O_RDONLY, 0)) < 0) 942 err(EX_OSERR, "%s", to_name); 943 944 if (fstat(temp_fd, &temp_sb)) { 945 serrno = errno; 946 (void)unlink(tempfile); 947 errno = serrno; 948 err(EX_OSERR, "%s", tempfile); 949 } 950 951 if (compare(temp_fd, tempfile, (size_t)temp_sb.st_size, to_fd, 952 to_name, (size_t)to_sb.st_size, &digestresult) 953 == 0) { 954 /* 955 * If target has more than one link we need to 956 * replace it in order to snap the extra links. 957 * Need to preserve target file times, though. 958 */ 959 if (to_sb.st_nlink != 1) { 960 tsb[0] = to_sb.st_atim; 961 tsb[1] = to_sb.st_mtim; 962 (void)utimensat(AT_FDCWD, tempfile, tsb, 0); 963 } else { 964 files_match = 1; 965 (void)unlink(tempfile); 966 } 967 (void) close(temp_fd); 968 } 969 } else if (dostrip) 970 digestresult = digest_file(tempfile); 971 972 /* 973 * Move the new file into place if doing a safe copy 974 * and the files are different (or just not compared). 975 */ 976 if (tempcopy && !files_match) { 977 #if HAVE_STRUCT_STAT_ST_FLAGS 978 /* Try to turn off the immutable bits. */ 979 if (to_sb.st_flags & NOCHANGEBITS) 980 (void)chflags(to_name, to_sb.st_flags & ~NOCHANGEBITS); 981 #endif 982 if (dobackup) { 983 if ((size_t)snprintf(backup, MAXPATHLEN, "%s%s", to_name, 984 suffix) != strlen(to_name) + strlen(suffix)) { 985 unlink(tempfile); 986 errx(EX_OSERR, "%s: backup filename too long", 987 to_name); 988 } 989 if (verbose) 990 (void)printf("install: %s -> %s\n", to_name, backup); 991 if (unlink(backup) < 0 && errno != ENOENT) { 992 serrno = errno; 993 #if HAVE_STRUCT_STAT_ST_FLAGS 994 if (to_sb.st_flags & NOCHANGEBITS) 995 (void)chflags(to_name, to_sb.st_flags); 996 #endif 997 unlink(tempfile); 998 errno = serrno; 999 err(EX_OSERR, "unlink: %s", backup); 1000 } 1001 if (link(to_name, backup) < 0) { 1002 serrno = errno; 1003 unlink(tempfile); 1004 #if HAVE_STRUCT_STAT_ST_FLAGS 1005 if (to_sb.st_flags & NOCHANGEBITS) 1006 (void)chflags(to_name, to_sb.st_flags); 1007 #endif 1008 errno = serrno; 1009 err(EX_OSERR, "link: %s to %s", to_name, 1010 backup); 1011 } 1012 } 1013 if (verbose) 1014 (void)printf("install: %s -> %s\n", from_name, to_name); 1015 if (rename(tempfile, to_name) < 0) { 1016 serrno = errno; 1017 unlink(tempfile); 1018 errno = serrno; 1019 err(EX_OSERR, "rename: %s to %s", 1020 tempfile, to_name); 1021 } 1022 1023 /* Re-open to_fd so we aren't hosed by the rename(2). */ 1024 (void) close(to_fd); 1025 if ((to_fd = open(to_name, O_RDONLY, 0)) < 0) 1026 err(EX_OSERR, "%s", to_name); 1027 } 1028 1029 /* 1030 * Preserve the timestamp of the source file if necessary. 1031 */ 1032 if (dopreserve && !files_match && !devnull) { 1033 tsb[0] = from_sb.st_atim; 1034 tsb[1] = from_sb.st_mtim; 1035 (void)utimensat(AT_FDCWD, to_name, tsb, 0); 1036 } 1037 1038 if (fstat(to_fd, &to_sb) == -1) { 1039 serrno = errno; 1040 (void)unlink(to_name); 1041 errno = serrno; 1042 err(EX_OSERR, "%s", to_name); 1043 } 1044 1045 /* 1046 * Set owner, group, mode for target; do the chown first, 1047 * chown may lose the setuid bits. 1048 */ 1049 if (!dounpriv && ((gid != (gid_t)-1 && gid != to_sb.st_gid) || 1050 (uid != (uid_t)-1 && uid != to_sb.st_uid) || 1051 (mode != (to_sb.st_mode & ALLPERMS)))) { 1052 #if HAVE_STRUCT_STAT_ST_FLAGS 1053 /* Try to turn off the immutable bits. */ 1054 if (to_sb.st_flags & NOCHANGEBITS) 1055 (void)fchflags(to_fd, to_sb.st_flags & ~NOCHANGEBITS); 1056 #endif 1057 } 1058 1059 if (!dounpriv && ((gid != (gid_t)-1 && gid != to_sb.st_gid) || 1060 (uid != (uid_t)-1 && uid != to_sb.st_uid))) { 1061 if (fchown(to_fd, uid, gid) == -1) { 1062 serrno = errno; 1063 (void)unlink(to_name); 1064 errno = serrno; 1065 err(EX_OSERR,"%s: chown/chgrp", to_name); 1066 } 1067 } 1068 if (mode != (to_sb.st_mode & ALLPERMS)) { 1069 if (fchmod(to_fd, 1070 dounpriv ? mode & (S_IRWXU|S_IRWXG|S_IRWXO) : mode)) { 1071 serrno = errno; 1072 (void)unlink(to_name); 1073 errno = serrno; 1074 err(EX_OSERR, "%s: chmod", to_name); 1075 } 1076 } 1077 #if HAVE_STRUCT_STAT_ST_FLAGS 1078 /* 1079 * If provided a set of flags, set them, otherwise, preserve the 1080 * flags, except for the dump flag. 1081 * NFS does not support flags. Ignore EOPNOTSUPP flags if we're just 1082 * trying to turn off UF_NODUMP. If we're trying to set real flags, 1083 * then warn if the fs doesn't support it, otherwise fail. 1084 */ 1085 if (!dounpriv && !devnull && (flags & SETFLAGS || 1086 (from_sb.st_flags & ~UF_NODUMP) != to_sb.st_flags) && 1087 fchflags(to_fd, 1088 flags & SETFLAGS ? fset : from_sb.st_flags & ~UF_NODUMP)) { 1089 if (flags & SETFLAGS) { 1090 if (errno == EOPNOTSUPP) 1091 warn("%s: chflags", to_name); 1092 else { 1093 serrno = errno; 1094 (void)unlink(to_name); 1095 errno = serrno; 1096 err(EX_OSERR, "%s: chflags", to_name); 1097 } 1098 } 1099 } 1100 #endif 1101 1102 (void)close(to_fd); 1103 if (!devnull) 1104 (void)close(from_fd); 1105 1106 metadata_log(to_name, "file", tsb, NULL, digestresult, to_sb.st_size); 1107 free(digestresult); 1108 } 1109 1110 /* 1111 * compare -- 1112 * Compare two files; non-zero means files differ. 1113 * Compute digest and return its address in *dresp 1114 * unless it points to pre-computed digest. 1115 */ 1116 static int 1117 compare(int from_fd, const char *from_name __unused, size_t from_len, 1118 int to_fd, const char *to_name __unused, size_t to_len, 1119 char **dresp) 1120 { 1121 char *p, *q; 1122 int rv; 1123 int do_digest, done_compare; 1124 DIGEST_CTX ctx; 1125 1126 rv = 0; 1127 if (from_len != to_len) 1128 return 1; 1129 1130 do_digest = (digesttype != DIGEST_NONE && dresp != NULL && 1131 *dresp == NULL); 1132 if (from_len <= MAX_CMP_SIZE) { 1133 if (do_digest) 1134 digest_init(&ctx); 1135 done_compare = 0; 1136 if (trymmap(from_len) && trymmap(to_len)) { 1137 p = mmap(NULL, from_len, PROT_READ, MAP_SHARED, 1138 from_fd, (off_t)0); 1139 if (p == MAP_FAILED) 1140 goto out; 1141 q = mmap(NULL, from_len, PROT_READ, MAP_SHARED, 1142 to_fd, (off_t)0); 1143 if (q == MAP_FAILED) { 1144 munmap(p, from_len); 1145 goto out; 1146 } 1147 1148 rv = memcmp(p, q, from_len); 1149 if (do_digest) 1150 digest_update(&ctx, p, from_len); 1151 munmap(p, from_len); 1152 munmap(q, from_len); 1153 done_compare = 1; 1154 } 1155 out: 1156 if (!done_compare) { 1157 static char *buf, *buf1, *buf2; 1158 static size_t bufsize; 1159 int n1, n2; 1160 1161 if (buf == NULL) { 1162 /* 1163 * Note that buf and bufsize are static. If 1164 * malloc() fails, it will fail at the start 1165 * and not copy only some files. 1166 */ 1167 if (sysconf(_SC_PHYS_PAGES) > 1168 PHYSPAGES_THRESHOLD) 1169 bufsize = MIN(BUFSIZE_MAX, MAXPHYS * 8); 1170 else 1171 bufsize = BUFSIZE_SMALL; 1172 buf = malloc(bufsize * 2); 1173 if (buf == NULL) 1174 err(1, "Not enough memory"); 1175 buf1 = buf; 1176 buf2 = buf + bufsize; 1177 } 1178 rv = 0; 1179 lseek(from_fd, 0, SEEK_SET); 1180 lseek(to_fd, 0, SEEK_SET); 1181 while (rv == 0) { 1182 n1 = read(from_fd, buf1, bufsize); 1183 if (n1 == 0) 1184 break; /* EOF */ 1185 else if (n1 > 0) { 1186 n2 = read(to_fd, buf2, n1); 1187 if (n2 == n1) 1188 rv = memcmp(buf1, buf2, n1); 1189 else 1190 rv = 1; /* out of sync */ 1191 } else 1192 rv = 1; /* read failure */ 1193 if (do_digest) 1194 digest_update(&ctx, buf1, n1); 1195 } 1196 lseek(from_fd, 0, SEEK_SET); 1197 lseek(to_fd, 0, SEEK_SET); 1198 } 1199 } else 1200 rv = 1; /* don't bother in this case */ 1201 1202 if (do_digest) { 1203 if (rv == 0) 1204 *dresp = digest_end(&ctx, NULL); 1205 else 1206 (void)digest_end(&ctx, NULL); 1207 } 1208 1209 return rv; 1210 } 1211 1212 /* 1213 * create_tempfile -- 1214 * create a temporary file based on path and open it 1215 */ 1216 static int 1217 create_tempfile(const char *path, char *temp, size_t tsize) 1218 { 1219 char *p; 1220 1221 (void)strncpy(temp, path, tsize); 1222 temp[tsize - 1] = '\0'; 1223 if ((p = strrchr(temp, '/')) != NULL) 1224 p++; 1225 else 1226 p = temp; 1227 (void)strncpy(p, "INS@XXXXXX", &temp[tsize - 1] - p); 1228 temp[tsize - 1] = '\0'; 1229 return (mkstemp(temp)); 1230 } 1231 1232 /* 1233 * create_newfile -- 1234 * create a new file, overwriting an existing one if necessary 1235 */ 1236 static int 1237 create_newfile(const char *path, int target, struct stat *sbp) 1238 { 1239 char backup[MAXPATHLEN]; 1240 int saved_errno = 0; 1241 int newfd; 1242 1243 if (target) { 1244 /* 1245 * Unlink now... avoid ETXTBSY errors later. Try to turn 1246 * off the append/immutable bits -- if we fail, go ahead, 1247 * it might work. 1248 */ 1249 #if HAVE_STRUCT_STAT_ST_FLAGS 1250 if (sbp->st_flags & NOCHANGEBITS) 1251 (void)chflags(path, sbp->st_flags & ~NOCHANGEBITS); 1252 #endif 1253 1254 if (dobackup) { 1255 if ((size_t)snprintf(backup, MAXPATHLEN, "%s%s", 1256 path, suffix) != strlen(path) + strlen(suffix)) { 1257 saved_errno = errno; 1258 #if HAVE_STRUCT_STAT_ST_FLAGS 1259 if (sbp->st_flags & NOCHANGEBITS) 1260 (void)chflags(path, sbp->st_flags); 1261 #endif 1262 errno = saved_errno; 1263 errx(EX_OSERR, "%s: backup filename too long", 1264 path); 1265 } 1266 (void)snprintf(backup, MAXPATHLEN, "%s%s", 1267 path, suffix); 1268 if (verbose) 1269 (void)printf("install: %s -> %s\n", 1270 path, backup); 1271 if (rename(path, backup) < 0) { 1272 saved_errno = errno; 1273 #if HAVE_STRUCT_STAT_ST_FLAGS 1274 if (sbp->st_flags & NOCHANGEBITS) 1275 (void)chflags(path, sbp->st_flags); 1276 #endif 1277 errno = saved_errno; 1278 err(EX_OSERR, "rename: %s to %s", path, backup); 1279 } 1280 } else 1281 if (unlink(path) < 0) 1282 saved_errno = errno; 1283 } 1284 1285 newfd = open(path, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR); 1286 if (newfd < 0 && saved_errno != 0) 1287 errno = saved_errno; 1288 return newfd; 1289 } 1290 1291 /* 1292 * copy -- 1293 * copy from one file to another 1294 */ 1295 static char * 1296 copy(int from_fd, const char *from_name, int to_fd, const char *to_name, 1297 off_t size) 1298 { 1299 static char *buf = NULL; 1300 static size_t bufsize; 1301 int nr, nw; 1302 int serrno; 1303 #ifndef BOOTSTRAP_XINSTALL 1304 ssize_t ret; 1305 #endif 1306 char *p; 1307 int done_copy; 1308 DIGEST_CTX ctx; 1309 1310 /* Rewind file descriptors. */ 1311 if (lseek(from_fd, (off_t)0, SEEK_SET) == (off_t)-1) 1312 err(EX_OSERR, "lseek: %s", from_name); 1313 if (lseek(to_fd, (off_t)0, SEEK_SET) == (off_t)-1) 1314 err(EX_OSERR, "lseek: %s", to_name); 1315 1316 #ifndef BOOTSTRAP_XINSTALL 1317 /* Try copy_file_range() if no digest is requested */ 1318 if (digesttype == DIGEST_NONE) { 1319 ret = 1; 1320 while (ret > 0) { 1321 ret = copy_file_range(from_fd, NULL, to_fd, NULL, 1322 SSIZE_MAX, 0); 1323 } 1324 if (ret == 0) { 1325 /* DIGEST_NONE always returns NULL */ 1326 return (NULL); 1327 } 1328 if (errno != EINVAL) { 1329 serrno = errno; 1330 (void)unlink(to_name); 1331 errno = serrno; 1332 err(EX_OSERR, "%s", to_name); 1333 } 1334 /* Fall back */ 1335 } 1336 1337 #endif 1338 digest_init(&ctx); 1339 1340 done_copy = 0; 1341 if (trymmap((size_t)size) && 1342 (p = mmap(NULL, (size_t)size, PROT_READ, MAP_SHARED, 1343 from_fd, (off_t)0)) != MAP_FAILED) { 1344 nw = write(to_fd, p, size); 1345 if (nw != size) { 1346 serrno = errno; 1347 (void)unlink(to_name); 1348 if (nw >= 0) { 1349 errx(EX_OSERR, 1350 "short write to %s: %jd bytes written, %jd bytes asked to write", 1351 to_name, (uintmax_t)nw, (uintmax_t)size); 1352 } else { 1353 errno = serrno; 1354 err(EX_OSERR, "%s", to_name); 1355 } 1356 } 1357 digest_update(&ctx, p, size); 1358 (void)munmap(p, size); 1359 done_copy = 1; 1360 } 1361 if (!done_copy) { 1362 if (buf == NULL) { 1363 /* 1364 * Note that buf and bufsize are static. If 1365 * malloc() fails, it will fail at the start 1366 * and not copy only some files. 1367 */ 1368 if (sysconf(_SC_PHYS_PAGES) > 1369 PHYSPAGES_THRESHOLD) 1370 bufsize = MIN(BUFSIZE_MAX, MAXPHYS * 8); 1371 else 1372 bufsize = BUFSIZE_SMALL; 1373 buf = malloc(bufsize); 1374 if (buf == NULL) 1375 err(1, "Not enough memory"); 1376 } 1377 while ((nr = read(from_fd, buf, bufsize)) > 0) { 1378 if ((nw = write(to_fd, buf, nr)) != nr) { 1379 serrno = errno; 1380 (void)unlink(to_name); 1381 if (nw >= 0) { 1382 errx(EX_OSERR, 1383 "short write to %s: %jd bytes written, %jd bytes asked to write", 1384 to_name, (uintmax_t)nw, 1385 (uintmax_t)size); 1386 } else { 1387 errno = serrno; 1388 err(EX_OSERR, "%s", to_name); 1389 } 1390 } 1391 digest_update(&ctx, buf, nr); 1392 } 1393 if (nr != 0) { 1394 serrno = errno; 1395 (void)unlink(to_name); 1396 errno = serrno; 1397 err(EX_OSERR, "%s", from_name); 1398 } 1399 } 1400 if (safecopy && fsync(to_fd) == -1) { 1401 serrno = errno; 1402 (void)unlink(to_name); 1403 errno = serrno; 1404 err(EX_OSERR, "fsync failed for %s", to_name); 1405 } 1406 return (digest_end(&ctx, NULL)); 1407 } 1408 1409 /* 1410 * strip -- 1411 * Use strip(1) to strip the target file. 1412 * Just invoke strip(1) on to_name if from_name is NULL, else try 1413 * to run "strip -o to_name from_name" and return 0 on failure. 1414 * Return 1 on success and assign result of digest_file(to_name) 1415 * to *dresp. 1416 */ 1417 static int 1418 strip(const char *to_name, int to_fd, const char *from_name, char **dresp) 1419 { 1420 const char *stripbin; 1421 const char *args[5]; 1422 char *prefixed_from_name; 1423 pid_t pid; 1424 int error, serrno, status; 1425 1426 prefixed_from_name = NULL; 1427 stripbin = getenv("STRIPBIN"); 1428 if (stripbin == NULL) 1429 stripbin = "strip"; 1430 args[0] = stripbin; 1431 if (from_name == NULL) { 1432 args[1] = to_name; 1433 args[2] = NULL; 1434 } else { 1435 args[1] = "-o"; 1436 args[2] = to_name; 1437 1438 /* Prepend './' if from_name begins with '-' */ 1439 if (from_name[0] == '-') { 1440 if (asprintf(&prefixed_from_name, "./%s", from_name) == -1) 1441 return (0); 1442 args[3] = prefixed_from_name; 1443 } else { 1444 args[3] = from_name; 1445 } 1446 args[4] = NULL; 1447 } 1448 error = posix_spawnp(&pid, stripbin, NULL, NULL, 1449 __DECONST(char **, args), environ); 1450 if (error != 0) { 1451 (void)unlink(to_name); 1452 errc(error == EAGAIN || error == EPROCLIM || error == ENOMEM ? 1453 EX_TEMPFAIL : EX_OSERR, error, "spawn %s", stripbin); 1454 } 1455 free(prefixed_from_name); 1456 if (waitpid(pid, &status, 0) == -1) { 1457 error = errno; 1458 (void)unlink(to_name); 1459 errc(EX_SOFTWARE, error, "wait"); 1460 /* NOTREACHED */ 1461 } 1462 if (status != 0) { 1463 if (from_name != NULL) 1464 return (0); 1465 (void)unlink(to_name); 1466 errx(EX_SOFTWARE, "strip command %s failed on %s", 1467 stripbin, to_name); 1468 } 1469 if (from_name != NULL && safecopy && fsync(to_fd) == -1) { 1470 serrno = errno; 1471 (void)unlink(to_name); 1472 errno = serrno; 1473 err(EX_OSERR, "fsync failed for %s", to_name); 1474 } 1475 if (dresp != NULL) 1476 *dresp = digest_file(to_name); 1477 return (1); 1478 } 1479 1480 /* 1481 * install_dir -- 1482 * build directory hierarchy 1483 */ 1484 static void 1485 install_dir(char *path) 1486 { 1487 char *p; 1488 struct stat sb; 1489 int ch, tried_mkdir; 1490 1491 for (p = path;; ++p) 1492 if (!*p || (p != path && *p == '/')) { 1493 tried_mkdir = 0; 1494 ch = *p; 1495 *p = '\0'; 1496 again: 1497 if (stat(path, &sb) != 0) { 1498 if (errno != ENOENT || tried_mkdir) 1499 err(EX_OSERR, "stat %s", path); 1500 if (mkdir(path, 0755) < 0) { 1501 tried_mkdir = 1; 1502 if (errno == EEXIST) 1503 goto again; 1504 err(EX_OSERR, "mkdir %s", path); 1505 } 1506 if (verbose) 1507 (void)printf("install: mkdir %s\n", 1508 path); 1509 } else if (!S_ISDIR(sb.st_mode)) 1510 errx(EX_OSERR, "%s exists but is not a directory", path); 1511 if (!(*p = ch)) 1512 break; 1513 } 1514 1515 if (!dounpriv) { 1516 if ((gid != (gid_t)-1 || uid != (uid_t)-1) && 1517 chown(path, uid, gid)) 1518 warn("chown %u:%u %s", uid, gid, path); 1519 /* XXXBED: should we do the chmod in the dounpriv case? */ 1520 if (chmod(path, mode)) 1521 warn("chmod %o %s", mode, path); 1522 } 1523 metadata_log(path, "dir", NULL, NULL, NULL, 0); 1524 } 1525 1526 /* 1527 * metadata_log -- 1528 * if metafp is not NULL, output mtree(8) full path name and settings to 1529 * metafp, to allow permissions to be set correctly by other tools, 1530 * or to allow integrity checks to be performed. 1531 */ 1532 static void 1533 metadata_log(const char *path, const char *type, struct timespec *ts, 1534 const char *slink, const char *digestresult, off_t size) 1535 { 1536 static const char extra[] = { ' ', '\t', '\n', '\\', '#', '\0' }; 1537 const char *p; 1538 char *buf; 1539 size_t destlen; 1540 struct flock metalog_lock; 1541 1542 if (!metafp) 1543 return; 1544 /* Buffer for strsvis(3). */ 1545 buf = (char *)malloc(4 * strlen(path) + 1); 1546 if (buf == NULL) { 1547 warnx("%s", strerror(ENOMEM)); 1548 return; 1549 } 1550 1551 /* Lock log file. */ 1552 metalog_lock.l_start = 0; 1553 metalog_lock.l_len = 0; 1554 metalog_lock.l_whence = SEEK_SET; 1555 metalog_lock.l_type = F_WRLCK; 1556 if (fcntl(fileno(metafp), F_SETLKW, &metalog_lock) == -1) { 1557 warn("can't lock %s", metafile); 1558 free(buf); 1559 return; 1560 } 1561 1562 /* Remove destdir. */ 1563 p = path; 1564 if (destdir) { 1565 destlen = strlen(destdir); 1566 if (strncmp(p, destdir, destlen) == 0 && 1567 (p[destlen] == '/' || p[destlen] == '\0')) 1568 p += destlen; 1569 } 1570 while (*p && *p == '/') 1571 p++; 1572 strsvis(buf, p, VIS_OCTAL, extra); 1573 p = buf; 1574 /* Print details. */ 1575 fprintf(metafp, ".%s%s type=%s", *p ? "/" : "", p, type); 1576 if (owner) 1577 fprintf(metafp, " uname=%s", owner); 1578 if (group) 1579 fprintf(metafp, " gname=%s", group); 1580 fprintf(metafp, " mode=%#o", mode); 1581 if (slink) { 1582 strsvis(buf, slink, VIS_CSTYLE, extra); /* encode link */ 1583 fprintf(metafp, " link=%s", buf); 1584 } 1585 if (*type == 'f') /* type=file */ 1586 fprintf(metafp, " size=%lld", (long long)size); 1587 if (ts != NULL && dopreserve) 1588 fprintf(metafp, " time=%lld.%09ld", 1589 (long long)ts[1].tv_sec, ts[1].tv_nsec); 1590 if (digestresult && digest) 1591 fprintf(metafp, " %s=%s", digest, digestresult); 1592 if (fflags) 1593 fprintf(metafp, " flags=%s", fflags); 1594 if (tags) 1595 fprintf(metafp, " tags=%s", tags); 1596 fputc('\n', metafp); 1597 /* Flush line. */ 1598 fflush(metafp); 1599 1600 /* Unlock log file. */ 1601 metalog_lock.l_type = F_UNLCK; 1602 if (fcntl(fileno(metafp), F_SETLKW, &metalog_lock) == -1) 1603 warn("can't unlock %s", metafile); 1604 free(buf); 1605 } 1606 1607 /* 1608 * usage -- 1609 * print a usage message and die 1610 */ 1611 static void 1612 usage(void) 1613 { 1614 (void)fprintf(stderr, 1615 "usage: install [-bCcpSsUv] [-f flags] [-g group] [-m mode] [-o owner]\n" 1616 " [-M log] [-D dest] [-h hash] [-T tags]\n" 1617 " [-B suffix] [-l linkflags] [-N dbdir]\n" 1618 " file1 file2\n" 1619 " install [-bCcpSsUv] [-f flags] [-g group] [-m mode] [-o owner]\n" 1620 " [-M log] [-D dest] [-h hash] [-T tags]\n" 1621 " [-B suffix] [-l linkflags] [-N dbdir]\n" 1622 " file1 ... fileN directory\n" 1623 " install -dU [-vU] [-g group] [-m mode] [-N dbdir] [-o owner]\n" 1624 " [-M log] [-D dest] [-h hash] [-T tags]\n" 1625 " directory ...\n"); 1626 exit(EX_USAGE); 1627 /* NOTREACHED */ 1628 } 1629 1630 /* 1631 * trymmap -- 1632 * return true (1) if mmap should be tried, false (0) if not. 1633 */ 1634 static int 1635 trymmap(size_t filesize) 1636 { 1637 /* 1638 * This function existed to skip mmap() for NFS file systems whereas 1639 * nowadays mmap() should be perfectly safe. Nevertheless, using mmap() 1640 * only reduces the number of system calls if we need multiple read() 1641 * syscalls, i.e. if the file size is > MAXBSIZE. However, mmap() is 1642 * more expensive than read() so set the threshold at 4 fewer syscalls. 1643 * Additionally, for larger file size mmap() can significantly increase 1644 * the number of page faults, so avoid it in that case. 1645 * 1646 * Note: the 8MB limit is not based on any meaningful benchmarking 1647 * results, it is simply reusing the same value that was used before 1648 * and also matches bin/cp. 1649 * 1650 * XXX: Maybe we shouldn't bother with mmap() at all, since we use 1651 * MAXBSIZE the syscall overhead of read() shouldn't be too high? 1652 */ 1653 return (filesize > 4 * MAXBSIZE && filesize < 8 * 1024 * 1024); 1654 } 1655