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