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