1 /* $NetBSD: xinstall.c,v 1.125 2016/05/31 06:55:02 pgoyette Exp $ */ 2 3 /* 4 * Copyright (c) 1987, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #define __MKTEMP_OK__ /* All uses of mktemp have been checked */ 33 34 #if HAVE_NBTOOL_CONFIG_H 35 #include "nbtool_config.h" 36 #else 37 #define HAVE_FUTIMES 1 38 #define HAVE_STRUCT_STAT_ST_FLAGS 1 39 #endif 40 41 #include <sys/cdefs.h> 42 #if defined(__COPYRIGHT) && !defined(lint) 43 __COPYRIGHT("@(#) Copyright (c) 1987, 1993\ 44 The Regents of the University of California. All rights reserved."); 45 #endif /* not lint */ 46 47 #if defined(__RCSID) && !defined(lint) 48 #if 0 49 static char sccsid[] = "@(#)xinstall.c 8.1 (Berkeley) 7/21/93"; 50 #else 51 __RCSID("$NetBSD: xinstall.c,v 1.125 2016/05/31 06:55:02 pgoyette Exp $"); 52 #endif 53 #endif /* not lint */ 54 55 #include <sys/param.h> 56 #include <sys/mman.h> 57 #include <sys/stat.h> 58 #include <sys/wait.h> 59 #include <sys/time.h> 60 61 #include <ctype.h> 62 #include <err.h> 63 #include <errno.h> 64 #include <fcntl.h> 65 #include <grp.h> 66 #include <libgen.h> 67 #include <paths.h> 68 #include <pwd.h> 69 #include <stdio.h> 70 #include <stdlib.h> 71 #include <string.h> 72 #include <unistd.h> 73 #include <util.h> 74 #include <vis.h> 75 76 #ifdef HAVE_POSIX_SPAWN 77 #include <spawn.h> 78 #endif 79 80 #include <md5.h> 81 #include <rmd160.h> 82 #include <sha1.h> 83 #include <sha2.h> 84 85 #include "pathnames.h" 86 #include "mtree.h" 87 #include "metachar.h" 88 89 #define BACKUP_SUFFIX ".old" 90 91 static int dobackup, dodir, dostrip, dolink, dopreserve, dorename, dounpriv; 92 static int haveopt_f, haveopt_g, haveopt_m, haveopt_o; 93 static int numberedbackup; 94 static int mode = S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; 95 static char pathbuf[MAXPATHLEN]; 96 static uid_t uid = -1; 97 static gid_t gid = -1; 98 static char *group, *owner, *fflags, *tags; 99 static FILE *metafp; 100 static char *metafile; 101 static u_long fileflags; 102 static char *stripArgs; 103 static char *afterinstallcmd; 104 static const char *suffix = BACKUP_SUFFIX; 105 static char *destdir; 106 107 enum { 108 DIGEST_NONE = 0, 109 DIGEST_MD5, 110 DIGEST_RMD160, 111 DIGEST_SHA1, 112 DIGEST_SHA256, 113 DIGEST_SHA384, 114 DIGEST_SHA512, 115 } digesttype = DIGEST_NONE; 116 117 static char *digest; 118 119 #define LN_ABSOLUTE 0x01 120 #define LN_RELATIVE 0x02 121 #define LN_HARD 0x04 122 #define LN_SYMBOLIC 0x08 123 #define LN_MIXED 0x10 124 125 #define DIRECTORY 0x01 /* Tell install it's a directory. */ 126 #define SETFLAGS 0x02 /* Tell install to set flags. */ 127 #define HASUID 0x04 /* Tell install the uid was given */ 128 #define HASGID 0x08 /* Tell install the gid was given */ 129 130 static void afterinstall(const char *, const char *, int); 131 static void backup(const char *); 132 static char *copy(int, char *, int, char *, off_t); 133 static int do_link(char *, char *); 134 static void do_symlink(char *, char *); 135 static void install(char *, char *, u_int); 136 static void install_dir(char *, u_int); 137 static void makelink(char *, char *); 138 static void metadata_log(const char *, const char *, struct timeval *, 139 const char *, const char *, off_t); 140 static int parseid(char *, id_t *); 141 static void run(const char *, const char *, const char *, int); 142 static void strip(const char *); 143 __dead static void usage(void); 144 static char *xbasename(char *); 145 static char *xdirname(char *); 146 147 int 148 main(int argc, char *argv[]) 149 { 150 struct stat from_sb, to_sb; 151 void *set; 152 u_int iflags; 153 int ch, no_target; 154 char *p, *to_name; 155 156 setprogname(argv[0]); 157 158 iflags = 0; 159 while ((ch = getopt(argc, argv, "a:cbB:dD:f:g:h:l:m:M:N:o:prsS:T:U")) 160 != -1) 161 switch((char)ch) { 162 case 'a': 163 afterinstallcmd = strdup(optarg); 164 if (afterinstallcmd == NULL) 165 err(EXIT_FAILURE, 166 "Can't allocate after command"); 167 break; 168 case 'B': 169 suffix = optarg; 170 numberedbackup = 0; 171 { 172 /* Check if given suffix really generates 173 different suffixes - catch e.g. ".%" */ 174 char suffix_expanded0[FILENAME_MAX], 175 suffix_expanded1[FILENAME_MAX]; 176 (void)snprintf(suffix_expanded0, FILENAME_MAX, 177 suffix, 0); 178 (void)snprintf(suffix_expanded1, FILENAME_MAX, 179 suffix, 1); 180 if (strcmp(suffix_expanded0, suffix_expanded1) 181 != 0) 182 numberedbackup = 1; 183 } 184 /* fall through; -B implies -b */ 185 /*FALLTHROUGH*/ 186 case 'b': 187 dobackup = 1; 188 break; 189 case 'c': 190 /* ignored; was "docopy" which is now the default. */ 191 break; 192 case 'd': 193 dodir = 1; 194 break; 195 case 'D': 196 destdir = optarg; 197 break; 198 #if ! HAVE_NBTOOL_CONFIG_H 199 case 'f': 200 haveopt_f = 1; 201 fflags = optarg; 202 break; 203 #endif 204 case 'g': 205 haveopt_g = 1; 206 group = optarg; 207 break; 208 case 'h': 209 digest = optarg; 210 break; 211 case 'l': 212 for (p = optarg; *p; p++) 213 switch (*p) { 214 case 's': 215 dolink &= ~(LN_HARD|LN_MIXED); 216 dolink |= LN_SYMBOLIC; 217 break; 218 case 'h': 219 dolink &= ~(LN_SYMBOLIC|LN_MIXED); 220 dolink |= LN_HARD; 221 break; 222 case 'm': 223 dolink &= ~(LN_SYMBOLIC|LN_HARD); 224 dolink |= LN_MIXED; 225 break; 226 case 'a': 227 dolink &= ~LN_RELATIVE; 228 dolink |= LN_ABSOLUTE; 229 break; 230 case 'r': 231 dolink &= ~LN_ABSOLUTE; 232 dolink |= LN_RELATIVE; 233 break; 234 default: 235 errx(EXIT_FAILURE, "%c: invalid link type", *p); 236 /* NOTREACHED */ 237 } 238 break; 239 case 'm': 240 haveopt_m = 1; 241 if (!(set = setmode(optarg))) 242 err(EXIT_FAILURE, "Cannot set file mode `%s'", optarg); 243 mode = getmode(set, 0); 244 free(set); 245 break; 246 case 'M': 247 metafile = optarg; 248 break; 249 case 'N': 250 if (! setup_getid(optarg)) 251 errx(EXIT_FAILURE, 252 "Unable to use user and group databases in `%s'", 253 optarg); 254 break; 255 case 'o': 256 haveopt_o = 1; 257 owner = optarg; 258 break; 259 case 'p': 260 dopreserve = 1; 261 break; 262 case 'r': 263 dorename = 1; 264 break; 265 case 'S': 266 stripArgs = strdup(optarg); 267 if (stripArgs == NULL) 268 err(EXIT_FAILURE, "Can't allocate options"); 269 /* fall through; -S implies -s */ 270 /*FALLTHROUGH*/ 271 case 's': 272 dostrip = 1; 273 break; 274 case 'T': 275 tags = optarg; 276 break; 277 case 'U': 278 dounpriv = 1; 279 break; 280 case '?': 281 default: 282 usage(); 283 } 284 argc -= optind; 285 argv += optind; 286 287 /* strip and link options make no sense when creating directories */ 288 if ((dostrip || dolink) && dodir) 289 usage(); 290 291 /* strip and flags make no sense with links */ 292 if ((dostrip || fflags) && dolink) 293 usage(); 294 295 /* must have at least two arguments, except when creating directories */ 296 if (argc < 2 && !dodir) 297 usage(); 298 299 if (digest) { 300 if (0) { 301 } else if (strcmp(digest, "none") == 0) { 302 digesttype = DIGEST_NONE; 303 } else if (strcmp(digest, "md5") == 0) { 304 digesttype = DIGEST_MD5; 305 } else if (strcmp(digest, "rmd160") == 0) { 306 digesttype = DIGEST_RMD160; 307 } else if (strcmp(digest, "sha1") == 0) { 308 digesttype = DIGEST_SHA1; 309 } else if (strcmp(digest, "sha256") == 0) { 310 digesttype = DIGEST_SHA256; 311 } else if (strcmp(digest, "sha384") == 0) { 312 digesttype = DIGEST_SHA384; 313 } else if (strcmp(digest, "sha512") == 0) { 314 digesttype = DIGEST_SHA512; 315 } else { 316 warnx("unknown digest `%s'", digest); 317 usage(); 318 } 319 } 320 321 /* get group and owner id's */ 322 if (group && !dounpriv) { 323 if (gid_from_group(group, &gid) == -1) { 324 id_t id; 325 if (!parseid(group, &id)) 326 errx(EXIT_FAILURE, "unknown group %s", group); 327 gid = id; 328 } 329 iflags |= HASGID; 330 } 331 if (owner && !dounpriv) { 332 if (uid_from_user(owner, &uid) == -1) { 333 id_t id; 334 if (!parseid(owner, &id)) 335 errx(EXIT_FAILURE, "unknown user %s", owner); 336 uid = id; 337 } 338 iflags |= HASUID; 339 } 340 341 #if ! HAVE_NBTOOL_CONFIG_H 342 if (fflags && !dounpriv) { 343 if (string_to_flags(&fflags, &fileflags, NULL)) 344 errx(EXIT_FAILURE, "%s: invalid flag", fflags); 345 /* restore fflags since string_to_flags() changed it */ 346 fflags = flags_to_string(fileflags, "-"); 347 iflags |= SETFLAGS; 348 } 349 #endif 350 351 if (metafile) { 352 if ((metafp = fopen(metafile, "a")) == NULL) 353 warn("open %s", metafile); 354 } else 355 digesttype = DIGEST_NONE; 356 357 if (dodir) { 358 for (; *argv != NULL; ++argv) 359 install_dir(*argv, iflags); 360 exit (0); 361 } 362 363 no_target = stat(to_name = argv[argc - 1], &to_sb); 364 if (!no_target && S_ISDIR(to_sb.st_mode)) { 365 for (; *argv != to_name; ++argv) 366 install(*argv, to_name, iflags | DIRECTORY); 367 exit(0); 368 } 369 370 /* can't do file1 file2 directory/file */ 371 if (argc != 2) { 372 errx(EXIT_FAILURE, "the last argument (%s) " 373 "must name an existing directory", argv[argc - 1]); 374 /* NOTREACHED */ 375 } 376 377 if (!no_target) { 378 /* makelink() handles checks for links */ 379 if (!dolink) { 380 if (stat(*argv, &from_sb)) 381 err(EXIT_FAILURE, "%s: stat", *argv); 382 if (!S_ISREG(to_sb.st_mode)) 383 errx(EXIT_FAILURE, "%s: not a regular file", to_name); 384 if (to_sb.st_dev == from_sb.st_dev && 385 to_sb.st_ino == from_sb.st_ino) 386 errx(EXIT_FAILURE, "%s and %s are the same file", *argv, 387 to_name); 388 } 389 /* 390 * Unlink now... avoid ETXTBSY errors later. Try and turn 391 * off the append/immutable bits -- if we fail, go ahead, 392 * it might work. 393 */ 394 #if ! HAVE_NBTOOL_CONFIG_H 395 #define NOCHANGEBITS (UF_IMMUTABLE | UF_APPEND | SF_IMMUTABLE | SF_APPEND) 396 if (to_sb.st_flags & NOCHANGEBITS) 397 (void)chflags(to_name, 398 to_sb.st_flags & ~(NOCHANGEBITS)); 399 #endif 400 if (dobackup) 401 backup(to_name); 402 else if (!dorename) 403 (void)unlink(to_name); 404 } 405 install(*argv, to_name, iflags); 406 exit(0); 407 } 408 409 /* 410 * parseid -- 411 * parse uid or gid from arg into id, returning non-zero if successful 412 */ 413 static int 414 parseid(char *name, id_t *id) 415 { 416 char *ep; 417 418 errno = 0; 419 *id = (id_t)strtoul(name, &ep, 10); 420 if (errno || *ep != '\0') 421 return (0); 422 return (1); 423 } 424 425 /* 426 * do_link -- 427 * make a hard link, obeying dorename if set 428 * return -1 on failure 429 */ 430 static int 431 do_link(char *from_name, char *to_name) 432 { 433 char tmpl[MAXPATHLEN]; 434 int ret; 435 436 if (dorename) { 437 (void)snprintf(tmpl, sizeof(tmpl), "%s.inst.XXXXXX", to_name); 438 /* This usage is safe. */ 439 if (mktemp(tmpl) == NULL) 440 err(EXIT_FAILURE, "%s: mktemp", tmpl); 441 ret = link(from_name, tmpl); 442 if (ret == 0) { 443 ret = rename(tmpl, to_name); 444 /* If rename has posix semantics, then the temporary 445 * file may still exist when from_name and to_name point 446 * to the same file, so unlink it unconditionally. 447 */ 448 (void)unlink(tmpl); 449 } 450 return (ret); 451 } else 452 return (link(from_name, to_name)); 453 } 454 455 /* 456 * do_symlink -- 457 * make a symbolic link, obeying dorename if set 458 * exit on failure 459 */ 460 static void 461 do_symlink(char *from_name, char *to_name) 462 { 463 char tmpl[MAXPATHLEN]; 464 465 if (dorename) { 466 (void)snprintf(tmpl, sizeof(tmpl), "%s.inst.XXXXXX", to_name); 467 /* This usage is safe. */ 468 if (mktemp(tmpl) == NULL) 469 err(EXIT_FAILURE, "%s: mktemp", tmpl); 470 471 if (symlink(from_name, tmpl) == -1) 472 err(EXIT_FAILURE, "symlink %s -> %s", from_name, tmpl); 473 if (rename(tmpl, to_name) == -1) { 474 /* remove temporary link before exiting */ 475 (void)unlink(tmpl); 476 err(EXIT_FAILURE, "%s: rename", to_name); 477 } 478 } else { 479 if (symlink(from_name, to_name) == -1) 480 err(EXIT_FAILURE, "symlink %s -> %s", from_name, to_name); 481 } 482 } 483 484 /* 485 * makelink -- 486 * make a link from source to destination 487 */ 488 static void 489 makelink(char *from_name, char *to_name) 490 { 491 char src[MAXPATHLEN], dst[MAXPATHLEN], lnk[MAXPATHLEN]; 492 struct stat to_sb; 493 494 /* Try hard links first */ 495 if (dolink & (LN_HARD|LN_MIXED)) { 496 if (do_link(from_name, to_name) == -1) { 497 if ((dolink & LN_HARD) || errno != EXDEV) 498 err(EXIT_FAILURE, "link %s -> %s", from_name, to_name); 499 } else { 500 if (stat(to_name, &to_sb)) 501 err(EXIT_FAILURE, "%s: stat", to_name); 502 if (S_ISREG(to_sb.st_mode)) { 503 /* XXX: hard links to anything 504 * other than plain files are not 505 * metalogged 506 */ 507 int omode; 508 char *oowner, *ogroup, *offlags; 509 char *dres; 510 511 /* XXX: use underlying perms, 512 * unless overridden on command line. 513 */ 514 omode = mode; 515 if (!haveopt_m) 516 mode = (to_sb.st_mode & 0777); 517 oowner = owner; 518 if (!haveopt_o) 519 owner = NULL; 520 ogroup = group; 521 if (!haveopt_g) 522 group = NULL; 523 offlags = fflags; 524 if (!haveopt_f) 525 fflags = NULL; 526 switch (digesttype) { 527 case DIGEST_MD5: 528 dres = MD5File(from_name, NULL); 529 break; 530 case DIGEST_RMD160: 531 dres = RMD160File(from_name, NULL); 532 break; 533 case DIGEST_SHA1: 534 dres = SHA1File(from_name, NULL); 535 break; 536 case DIGEST_SHA256: 537 dres = SHA256_File(from_name, NULL); 538 break; 539 case DIGEST_SHA384: 540 dres = SHA384_File(from_name, NULL); 541 break; 542 case DIGEST_SHA512: 543 dres = SHA512_File(from_name, NULL); 544 break; 545 default: 546 dres = NULL; 547 } 548 metadata_log(to_name, "file", NULL, NULL, 549 dres, to_sb.st_size); 550 free(dres); 551 mode = omode; 552 owner = oowner; 553 group = ogroup; 554 fflags = offlags; 555 } 556 return; 557 } 558 } 559 560 /* Symbolic links */ 561 if (dolink & LN_ABSOLUTE) { 562 /* Convert source path to absolute */ 563 if (realpath(from_name, src) == NULL) 564 err(EXIT_FAILURE, "%s: realpath", from_name); 565 do_symlink(src, to_name); 566 /* XXX: src may point outside of destdir */ 567 metadata_log(to_name, "link", NULL, src, NULL, 0); 568 return; 569 } 570 571 if (dolink & LN_RELATIVE) { 572 char *cp, *d, *s; 573 574 /* Resolve pathnames */ 575 if (realpath(from_name, src) == NULL) 576 err(EXIT_FAILURE, "%s: realpath", from_name); 577 578 /* 579 * The last component of to_name may be a symlink, 580 * so use realpath to resolve only the directory. 581 */ 582 cp = xdirname(to_name); 583 if (realpath(cp, dst) == NULL) 584 err(EXIT_FAILURE, "%s: realpath", cp); 585 /* .. and add the last component */ 586 if (strcmp(dst, "/") != 0) { 587 if (strlcat(dst, "/", sizeof(dst)) > sizeof(dst)) 588 errx(EXIT_FAILURE, "resolved pathname too long"); 589 } 590 cp = xbasename(to_name); 591 if (strlcat(dst, cp, sizeof(dst)) > sizeof(dst)) 592 errx(EXIT_FAILURE, "resolved pathname too long"); 593 594 /* trim common path components */ 595 for (s = src, d = dst; *s == *d; s++, d++) 596 continue; 597 while (*s != '/') 598 s--, d--; 599 600 /* count the number of directories we need to backtrack */ 601 for (++d, lnk[0] = '\0'; *d; d++) 602 if (*d == '/') 603 (void)strlcat(lnk, "../", sizeof(lnk)); 604 605 (void)strlcat(lnk, ++s, sizeof(lnk)); 606 607 do_symlink(lnk, to_name); 608 /* XXX: lnk may point outside of destdir */ 609 metadata_log(to_name, "link", NULL, lnk, NULL, 0); 610 return; 611 } 612 613 /* 614 * If absolute or relative was not specified, 615 * try the names the user provided 616 */ 617 do_symlink(from_name, to_name); 618 /* XXX: from_name may point outside of destdir */ 619 metadata_log(to_name, "link", NULL, from_name, NULL, 0); 620 } 621 622 /* 623 * install -- 624 * build a path name and install the file 625 */ 626 static void 627 install(char *from_name, char *to_name, u_int flags) 628 { 629 struct stat from_sb; 630 struct stat to_sb; 631 struct timeval tv[2]; 632 off_t size; 633 int devnull, from_fd, to_fd, serrno, tmpmode; 634 char *p, tmpl[MAXPATHLEN], *oto_name, *digestresult; 635 636 size = -1; 637 if (!dolink) { 638 /* ensure that from_sb & tv are sane if !dolink */ 639 if (stat(from_name, &from_sb)) 640 err(EXIT_FAILURE, "%s: stat", from_name); 641 size = from_sb.st_size; 642 #if BSD4_4 && !HAVE_NBTOOL_CONFIG_H 643 TIMESPEC_TO_TIMEVAL(&tv[0], &from_sb.st_atimespec); 644 TIMESPEC_TO_TIMEVAL(&tv[1], &from_sb.st_mtimespec); 645 #else 646 tv[0].tv_sec = from_sb.st_atime; 647 tv[0].tv_usec = 0; 648 tv[1].tv_sec = from_sb.st_mtime; 649 tv[1].tv_usec = 0; 650 #endif 651 } 652 653 if (flags & DIRECTORY || strcmp(from_name, _PATH_DEVNULL) != 0) { 654 devnull = 0; 655 if (!dolink) { 656 if (!S_ISREG(from_sb.st_mode)) 657 errx(EXIT_FAILURE, "%s: not a regular file", from_name); 658 } 659 /* Build the target path. */ 660 if (flags & DIRECTORY) { 661 (void)snprintf(pathbuf, sizeof(pathbuf), "%s/%s", 662 to_name, 663 (p = strrchr(from_name, '/')) ? ++p : from_name); 664 to_name = pathbuf; 665 } 666 } else { 667 devnull = 1; 668 size = 0; 669 #if HAVE_STRUCT_STAT_ST_FLAGS 670 from_sb.st_flags = 0; /* XXX */ 671 #endif 672 } 673 674 /* 675 * Unlink now... avoid ETXTBSY errors later. Try and turn 676 * off the append/immutable bits -- if we fail, go ahead, 677 * it might work. 678 */ 679 #if ! HAVE_NBTOOL_CONFIG_H 680 if (stat(to_name, &to_sb) == 0 && 681 to_sb.st_flags & (NOCHANGEBITS)) 682 (void)chflags(to_name, to_sb.st_flags & ~(NOCHANGEBITS)); 683 #endif 684 if (dorename) { 685 (void)snprintf(tmpl, sizeof(tmpl), "%s.inst.XXXXXX", to_name); 686 oto_name = to_name; 687 to_name = tmpl; 688 } else { 689 oto_name = NULL; /* pacify gcc */ 690 if (dobackup) 691 backup(to_name); 692 else 693 (void)unlink(to_name); 694 } 695 696 if (dolink) { 697 makelink(from_name, dorename ? oto_name : to_name); 698 return; 699 } 700 701 /* Create target. */ 702 if (dorename) { 703 if ((to_fd = mkstemp(to_name)) == -1) 704 err(EXIT_FAILURE, "%s: mkstemp", to_name); 705 } else { 706 if ((to_fd = open(to_name, 707 O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR)) < 0) 708 err(EXIT_FAILURE, "%s: open", to_name); 709 } 710 digestresult = NULL; 711 if (!devnull) { 712 if ((from_fd = open(from_name, O_RDONLY, 0)) < 0) { 713 (void)unlink(to_name); 714 err(EXIT_FAILURE, "%s: open", from_name); 715 } 716 digestresult = 717 copy(from_fd, from_name, to_fd, to_name, from_sb.st_size); 718 (void)close(from_fd); 719 } 720 721 if (dostrip) { 722 strip(to_name); 723 724 /* 725 * Re-open our fd on the target, in case we used a strip 726 * that does not work in-place -- like gnu binutils strip. 727 */ 728 close(to_fd); 729 if ((to_fd = open(to_name, O_RDONLY, S_IRUSR | S_IWUSR)) < 0) 730 err(EXIT_FAILURE, "stripping %s", to_name); 731 732 /* 733 * Recalculate size and digestresult after stripping. 734 */ 735 if (fstat(to_fd, &to_sb) != 0) 736 err(EXIT_FAILURE, "%s: fstat", to_name); 737 size = to_sb.st_size; 738 digestresult = 739 copy(to_fd, to_name, -1, NULL, size); 740 741 } 742 743 if (afterinstallcmd != NULL) { 744 afterinstall(afterinstallcmd, to_name, 1); 745 746 /* 747 * Re-open our fd on the target, in case we used an 748 * after-install command that does not work in-place 749 */ 750 close(to_fd); 751 if ((to_fd = open(to_name, O_RDONLY, S_IRUSR | S_IWUSR)) < 0) 752 err(EXIT_FAILURE, "running after install command on %s", to_name); 753 } 754 755 /* 756 * Set owner, group, mode for target; do the chown first, 757 * chown may lose the setuid bits. 758 */ 759 if (!dounpriv && 760 (flags & (HASUID | HASGID)) && fchown(to_fd, uid, gid) == -1) { 761 serrno = errno; 762 (void)unlink(to_name); 763 errc(EXIT_FAILURE, serrno, "%s: chown/chgrp", to_name); 764 } 765 tmpmode = mode; 766 if (dounpriv) 767 tmpmode &= S_IRWXU|S_IRWXG|S_IRWXO; 768 if (fchmod(to_fd, tmpmode) == -1) { 769 serrno = errno; 770 (void)unlink(to_name); 771 errc(EXIT_FAILURE, serrno, "%s: chmod", to_name); 772 } 773 774 /* 775 * Preserve the date of the source file. 776 */ 777 if (dopreserve) { 778 #if HAVE_FUTIMES 779 if (futimes(to_fd, tv) == -1) 780 warn("%s: futimes", to_name); 781 #else 782 if (utimes(to_name, tv) == -1) 783 warn("%s: utimes", to_name); 784 #endif 785 } 786 787 (void)close(to_fd); 788 789 if (dorename) { 790 if (rename(to_name, oto_name) == -1) 791 err(EXIT_FAILURE, "%s: rename", to_name); 792 to_name = oto_name; 793 } 794 795 /* 796 * If provided a set of flags, set them, otherwise, preserve the 797 * flags, except for the dump flag. 798 */ 799 #if ! HAVE_NBTOOL_CONFIG_H 800 if (!dounpriv && chflags(to_name, 801 flags & SETFLAGS ? fileflags : from_sb.st_flags & ~UF_NODUMP) == -1) 802 { 803 if (errno != EOPNOTSUPP || (from_sb.st_flags & ~UF_NODUMP) != 0) 804 warn("%s: chflags", to_name); 805 } 806 #endif 807 808 metadata_log(to_name, "file", tv, NULL, digestresult, size); 809 free(digestresult); 810 } 811 812 /* 813 * copy -- 814 * copy from one file to another, returning a digest. 815 * 816 * If to_fd < 0, just calculate a digest, don't copy. 817 */ 818 static char * 819 copy(int from_fd, char *from_name, int to_fd, char *to_name, off_t size) 820 { 821 ssize_t nr, nw; 822 int serrno; 823 u_char *p; 824 u_char buf[MAXBSIZE]; 825 MD5_CTX ctxMD5; 826 RMD160_CTX ctxRMD160; 827 SHA1_CTX ctxSHA1; 828 SHA256_CTX ctxSHA256; 829 SHA384_CTX ctxSHA384; 830 SHA512_CTX ctxSHA512; 831 832 switch (digesttype) { 833 case DIGEST_MD5: 834 MD5Init(&ctxMD5); 835 break; 836 case DIGEST_RMD160: 837 RMD160Init(&ctxRMD160); 838 break; 839 case DIGEST_SHA1: 840 SHA1Init(&ctxSHA1); 841 break; 842 case DIGEST_SHA256: 843 SHA256_Init(&ctxSHA256); 844 break; 845 case DIGEST_SHA384: 846 SHA384_Init(&ctxSHA384); 847 break; 848 case DIGEST_SHA512: 849 SHA512_Init(&ctxSHA512); 850 break; 851 case DIGEST_NONE: 852 if (to_fd < 0) 853 return NULL; /* no need to do anything */ 854 default: 855 break; 856 } 857 /* 858 * There's no reason to do anything other than close the file 859 * now if it's empty, so let's not bother. 860 */ 861 if (size > 0) { 862 863 /* 864 * Mmap and write if less than 8M (the limit is so we 865 * don't totally trash memory on big files). This is 866 * really a minor hack, but it wins some CPU back. 867 */ 868 869 if (size <= 8 * 1048576) { 870 if ((p = mmap(NULL, (size_t)size, PROT_READ, 871 MAP_FILE|MAP_SHARED, from_fd, (off_t)0)) 872 == MAP_FAILED) { 873 goto mmap_failed; 874 } 875 #if defined(MADV_SEQUENTIAL) && !defined(__APPLE__) 876 if (madvise(p, (size_t)size, MADV_SEQUENTIAL) == -1 877 && errno != EOPNOTSUPP) 878 warn("madvise"); 879 #endif 880 881 if (to_fd >= 0 && write(to_fd, p, size) != size) { 882 serrno = errno; 883 (void)unlink(to_name); 884 errc(EXIT_FAILURE, serrno, "%s: write", 885 to_name); 886 } 887 switch (digesttype) { 888 case DIGEST_MD5: 889 MD5Update(&ctxMD5, p, size); 890 break; 891 case DIGEST_RMD160: 892 RMD160Update(&ctxRMD160, p, size); 893 break; 894 case DIGEST_SHA1: 895 SHA1Update(&ctxSHA1, p, size); 896 break; 897 case DIGEST_SHA256: 898 SHA256_Update(&ctxSHA256, p, size); 899 break; 900 case DIGEST_SHA384: 901 SHA384_Update(&ctxSHA384, p, size); 902 break; 903 case DIGEST_SHA512: 904 SHA512_Update(&ctxSHA512, p, size); 905 break; 906 default: 907 break; 908 } 909 (void)munmap(p, size); 910 } else { 911 mmap_failed: 912 while ((nr = read(from_fd, buf, sizeof(buf))) > 0) { 913 if (to_fd >= 0 && 914 (nw = write(to_fd, buf, nr)) != nr) { 915 serrno = errno; 916 (void)unlink(to_name); 917 errc(EXIT_FAILURE, 918 nw > 0 ? EIO : serrno, 919 "%s: write", to_name); 920 } 921 switch (digesttype) { 922 case DIGEST_MD5: 923 MD5Update(&ctxMD5, buf, nr); 924 break; 925 case DIGEST_RMD160: 926 RMD160Update(&ctxRMD160, buf, nr); 927 break; 928 case DIGEST_SHA1: 929 SHA1Update(&ctxSHA1, buf, nr); 930 break; 931 case DIGEST_SHA256: 932 SHA256_Update(&ctxSHA256, buf, nr); 933 break; 934 case DIGEST_SHA384: 935 SHA384_Update(&ctxSHA384, buf, nr); 936 break; 937 case DIGEST_SHA512: 938 SHA512_Update(&ctxSHA512, buf, nr); 939 break; 940 default: 941 break; 942 } 943 } 944 if (nr != 0) { 945 serrno = errno; 946 (void)unlink(to_name); 947 errc(EXIT_FAILURE, serrno, "%s: read", 948 from_name); 949 } 950 } 951 } 952 switch (digesttype) { 953 case DIGEST_MD5: 954 return MD5End(&ctxMD5, NULL); 955 case DIGEST_RMD160: 956 return RMD160End(&ctxRMD160, NULL); 957 case DIGEST_SHA1: 958 return SHA1End(&ctxSHA1, NULL); 959 case DIGEST_SHA256: 960 return SHA256_End(&ctxSHA256, NULL); 961 case DIGEST_SHA384: 962 return SHA384_End(&ctxSHA384, NULL); 963 case DIGEST_SHA512: 964 return SHA512_End(&ctxSHA512, NULL); 965 default: 966 return NULL; 967 } 968 } 969 970 static void 971 run(const char *command, const char *flags, const char *to_name, int errunlink) 972 { 973 char *args[4]; 974 char *cmd; 975 int status; 976 int rv; 977 size_t i; 978 979 i = 1; 980 status = 0; 981 982 if (needshell(command, 1)) { 983 rv = asprintf(&cmd, "%s %s%s%s", command, flags ? flags : "", 984 flags ? " " : "", to_name); 985 if (rv < 0) { 986 warn("Cannot execute %s", command); 987 goto out; 988 } 989 command = _PATH_BSHELL; 990 flags = "-c"; 991 } else 992 cmd = __UNCONST(to_name); 993 994 args[0] = __UNCONST(command); 995 if (flags) 996 args[i++] = __UNCONST(flags); 997 args[i++] = cmd; 998 args[i] = NULL; 999 1000 #ifdef HAVE_POSIX_SPAWN 1001 if (*command == '/') 1002 rv = posix_spawn(NULL, command, NULL, NULL, args, NULL); 1003 else 1004 rv = posix_spawnp(NULL, command, NULL, NULL, args, NULL); 1005 if (rv != 0) 1006 warnc(rv, "Cannot execute %s", command); 1007 /* 1008 * the wait below will fail if we did not create a child it will 1009 * make rv negative. 1010 */ 1011 #else 1012 switch (vfork()) { 1013 case -1: 1014 rv = errno; 1015 if (errunlink) 1016 (void)unlink(to_name); 1017 errc(EXIT_FAILURE, rv, "vfork"); 1018 /*NOTREACHED*/ 1019 case 0: 1020 if (*command == '/') 1021 execv(command, args); 1022 else 1023 execvp(command, args); 1024 rv = errno; 1025 const char *arr[] = { 1026 getprogname(), 1027 ": exec failed for ", 1028 command, 1029 " (", 1030 strerror(rv), 1031 ")\n", 1032 }; 1033 for (i = 0; i < __arraycount(arr); i++) 1034 write(STDERR_FILENO, arr[i], strlen(arr[i])); 1035 _exit(1); 1036 /*NOTREACHED*/ 1037 default: 1038 break; 1039 } 1040 #endif 1041 rv = wait(&status); 1042 if (cmd != to_name) 1043 free(cmd); 1044 out: 1045 if ((rv < 0 || status) && errunlink) 1046 (void)unlink(to_name); 1047 } 1048 1049 /* 1050 * strip -- 1051 * use strip(1) to strip the target file 1052 */ 1053 static void 1054 strip(const char *to_name) 1055 { 1056 const char *stripprog; 1057 1058 if ((stripprog = getenv("STRIP")) == NULL || *stripprog == '\0') { 1059 #ifdef TARGET_STRIP 1060 stripprog = TARGET_STRIP; 1061 #else 1062 stripprog = _PATH_STRIP; 1063 #endif 1064 } 1065 run(stripprog, stripArgs, to_name, 1); 1066 } 1067 1068 /* 1069 * afterinstall -- 1070 * run provided command on the target file or directory after it's been 1071 * installed and stripped, but before permissions are set or it's renamed 1072 */ 1073 static void 1074 afterinstall(const char *command, const char *to_name, int errunlink) 1075 { 1076 run(command, NULL, to_name, errunlink); 1077 } 1078 1079 /* 1080 * backup -- 1081 * backup file "to_name" to to_name.suffix 1082 * if suffix contains a "%", it's taken as a printf(3) pattern 1083 * used for a numbered backup. 1084 */ 1085 static void 1086 backup(const char *to_name) 1087 { 1088 char bname[FILENAME_MAX]; 1089 1090 if (numberedbackup) { 1091 /* Do numbered backup */ 1092 int cnt; 1093 char suffix_expanded[FILENAME_MAX]; 1094 1095 cnt=0; 1096 do { 1097 (void)snprintf(suffix_expanded, FILENAME_MAX, suffix, 1098 cnt); 1099 (void)snprintf(bname, FILENAME_MAX, "%s%s", to_name, 1100 suffix_expanded); 1101 cnt++; 1102 } while (access(bname, F_OK) == 0); 1103 } else { 1104 /* Do simple backup */ 1105 (void)snprintf(bname, FILENAME_MAX, "%s%s", to_name, suffix); 1106 } 1107 1108 (void)rename(to_name, bname); 1109 } 1110 1111 /* 1112 * install_dir -- 1113 * build directory hierarchy 1114 */ 1115 static void 1116 install_dir(char *path, u_int flags) 1117 { 1118 char *p; 1119 struct stat sb; 1120 int ch; 1121 1122 for (p = path;; ++p) 1123 if (!*p || (p != path && *p == '/')) { 1124 ch = *p; 1125 *p = '\0'; 1126 if (mkdir(path, 0777) < 0) { 1127 /* 1128 * Can't create; path exists or no perms. 1129 * stat() path to determine what's there now. 1130 */ 1131 int sverrno; 1132 sverrno = errno; 1133 if (stat(path, &sb) < 0) { 1134 /* Not there; use mkdir()s error */ 1135 errno = sverrno; 1136 err(EXIT_FAILURE, "%s: mkdir", path); 1137 } 1138 if (!S_ISDIR(sb.st_mode)) { 1139 errx(EXIT_FAILURE, 1140 "%s exists but is not a directory", 1141 path); 1142 } 1143 } 1144 if (!(*p = ch)) 1145 break; 1146 } 1147 1148 if (afterinstallcmd != NULL) 1149 afterinstall(afterinstallcmd, path, 0); 1150 1151 if (!dounpriv && ( 1152 ((flags & (HASUID | HASGID)) && chown(path, uid, gid) == -1) 1153 || chmod(path, mode) == -1 )) { 1154 warn("%s: chown/chmod", path); 1155 } 1156 metadata_log(path, "dir", NULL, NULL, NULL, 0); 1157 } 1158 1159 /* 1160 * metadata_log -- 1161 * if metafp is not NULL, output mtree(8) full path name and settings to 1162 * metafp, to allow permissions to be set correctly by other tools, 1163 * or to allow integrity checks to be performed. 1164 */ 1165 static void 1166 metadata_log(const char *path, const char *type, struct timeval *tv, 1167 const char *slink, const char *digestresult, off_t size) 1168 { 1169 static const char extra[] = { ' ', '\t', '\n', '\\', '#', '\0' }; 1170 const char *p; 1171 char *buf; 1172 size_t destlen; 1173 struct flock metalog_lock; 1174 1175 if (!metafp) 1176 return; 1177 buf = malloc(4 * strlen(path) + 1); /* buf for strsvis(3) */ 1178 if (buf == NULL) { 1179 warn("Can't allocate metadata"); 1180 return; 1181 } 1182 /* lock log file */ 1183 metalog_lock.l_start = 0; 1184 metalog_lock.l_len = 0; 1185 metalog_lock.l_whence = SEEK_SET; 1186 metalog_lock.l_type = F_WRLCK; 1187 if (fcntl(fileno(metafp), F_SETLKW, &metalog_lock) == -1) { 1188 warn("can't lock %s", metafile); 1189 free(buf); 1190 return; 1191 } 1192 1193 p = path; /* remove destdir */ 1194 if (destdir) { 1195 destlen = strlen(destdir); 1196 if (strncmp(p, destdir, destlen) == 0 && 1197 (p[destlen] == '/' || p[destlen] == '\0')) 1198 p += destlen; 1199 } 1200 while (*p && *p == '/') /* remove leading /s */ 1201 p++; 1202 strsvis(buf, p, VIS_CSTYLE, extra); /* encode name */ 1203 p = buf; 1204 /* print details */ 1205 fprintf(metafp, ".%s%s type=%s", *p ? "/" : "", p, type); 1206 if (owner) 1207 fprintf(metafp, " uname=%s", owner); 1208 if (group) 1209 fprintf(metafp, " gname=%s", group); 1210 fprintf(metafp, " mode=%#o", mode); 1211 if (slink) { 1212 strsvis(buf, slink, VIS_CSTYLE, extra); /* encode link */ 1213 fprintf(metafp, " link=%s", buf); 1214 } 1215 if (*type == 'f') /* type=file */ 1216 fprintf(metafp, " size=%lld", (long long)size); 1217 if (tv != NULL && dopreserve) 1218 fprintf(metafp, " time=%lld.%0*lld", 1219 (long long)tv[1].tv_sec, 1220 (tv[1].tv_usec == 0 ? 1 : 9), 1221 (long long)tv[1].tv_usec * 1000); 1222 if (digestresult && digest) 1223 fprintf(metafp, " %s=%s", digest, digestresult); 1224 if (fflags) 1225 fprintf(metafp, " flags=%s", fflags); 1226 if (tags) 1227 fprintf(metafp, " tags=%s", tags); 1228 fputc('\n', metafp); 1229 fflush(metafp); /* flush output */ 1230 /* unlock log file */ 1231 metalog_lock.l_type = F_UNLCK; 1232 if (fcntl(fileno(metafp), F_SETLKW, &metalog_lock) == -1) { 1233 warn("can't unlock %s", metafile); 1234 } 1235 free(buf); 1236 } 1237 1238 /* 1239 * xbasename -- 1240 * libc basename(3) that returns a pointer to a static buffer 1241 * instead of overwriting that passed-in string. 1242 */ 1243 static char * 1244 xbasename(char *path) 1245 { 1246 static char tmp[MAXPATHLEN]; 1247 1248 (void)strlcpy(tmp, path, sizeof(tmp)); 1249 return (basename(tmp)); 1250 } 1251 1252 /* 1253 * xdirname -- 1254 * libc dirname(3) that returns a pointer to a static buffer 1255 * instead of overwriting that passed-in string. 1256 */ 1257 static char * 1258 xdirname(char *path) 1259 { 1260 static char tmp[MAXPATHLEN]; 1261 1262 (void)strlcpy(tmp, path, sizeof(tmp)); 1263 return (dirname(tmp)); 1264 } 1265 1266 /* 1267 * usage -- 1268 * print a usage message and die 1269 */ 1270 static void 1271 usage(void) 1272 { 1273 const char *prog; 1274 1275 prog = getprogname(); 1276 1277 (void)fprintf(stderr, 1278 "usage: %s [-Ubcprs] [-M log] [-D dest] [-T tags] [-B suffix]\n" 1279 " [-a aftercmd] [-f flags] [-m mode] [-N dbdir] [-o owner] [-g group] \n" 1280 " [-l linkflags] [-h hash] [-S stripflags] file1 file2\n" 1281 " %s [-Ubcprs] [-M log] [-D dest] [-T tags] [-B suffix]\n" 1282 " [-a aftercmd] [-f flags] [-m mode] [-N dbdir] [-o owner] [-g group]\n" 1283 " [-l linkflags] [-h hash] [-S stripflags] file1 ... fileN directory\n" 1284 " %s -d [-Up] [-M log] [-D dest] [-T tags] [-a aftercmd] [-m mode]\n" 1285 " [-N dbdir] [-o owner] [-g group] directory ...\n", 1286 prog, prog, prog); 1287 exit(1); 1288 } 1289