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