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