2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (c) 2012, 2013 SRI International
5 * Copyright (c) 1987, 1993
6 * The Regents of the University of California. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
33 #include <sys/param.h>
35 #include <sys/mount.h>
68 * Memory strategy threshold, in pages: if physmem is larger than this, use a
71 #define PHYSPAGES_THRESHOLD (32*1024)
73 /* Maximum buffer size in bytes - do not allow it to grow larger than this. */
74 #define BUFSIZE_MAX (2*1024*1024)
77 * Small (default) buffer size in bytes. It's inefficient for this to be
78 * smaller than MAXPHYS.
80 #define BUFSIZE_SMALL (MAXPHYS)
83 * We need to build xinstall during the bootstrap stage when building on a
84 * non-FreeBSD system. Linux does not have the st_flags and st_birthtime
85 * members in struct stat so we need to omit support for changing those fields.
88 #define HAVE_STRUCT_STAT_ST_FLAGS 1
90 #define HAVE_STRUCT_STAT_ST_FLAGS 0
93 #define MAX_CMP_SIZE (16 * 1024 * 1024)
95 #define LN_ABSOLUTE 0x01
96 #define LN_RELATIVE 0x02
98 #define LN_SYMBOLIC 0x08
101 #define DIRECTORY 0x01 /* Tell install it's a directory. */
102 #define SETFLAGS 0x02 /* Tell install to set flags. */
103 #define NOCHANGEBITS (UF_IMMUTABLE | UF_APPEND | SF_IMMUTABLE | SF_APPEND)
104 #define BACKUP_SUFFIX ".old"
110 #ifdef WITH_RIPEMD160
111 RIPEMD160_CTX RIPEMD160;
123 #ifdef WITH_RIPEMD160
129 } digesttype = DIGEST_NONE;
131 extern char **environ;
135 static int dobackup, docompare, dodir, dolink, dopreserve, dostrip, dounpriv,
137 static int haveopt_f, haveopt_g, haveopt_m, haveopt_o;
138 static mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
140 static const char *group, *owner;
141 static const char *suffix = BACKUP_SUFFIX;
142 static char *destdir, *digest, *fflags, *metafile, *tags;
144 static int compare(int, const char *, size_t, int, const char *, size_t,
146 static char *copy(int, const char *, int, const char *, off_t);
147 static int create_tempfile(const char *, char *, size_t);
148 static char *quiet_mktemp(char *template);
149 static char *digest_file(const char *);
150 static void digest_init(DIGEST_CTX *);
151 static void digest_update(DIGEST_CTX *, const char *, size_t);
152 static char *digest_end(DIGEST_CTX *, char *);
153 static int do_link(const char *, const char *, const struct stat *);
154 static void do_symlink(const char *, const char *, const struct stat *);
155 static void makelink(const char *, const char *, const struct stat *);
156 static void install(const char *, const char *, u_long, u_int);
157 static void install_dir(char *);
158 static void metadata_log(const char *, const char *, struct timespec *,
159 const char *, const char *, off_t);
160 static int parseid(const char *, id_t *);
161 static int strip(const char *, int, const char *, char **);
162 static int trymmap(size_t);
163 static void usage(void);
166 main(int argc, char *argv[])
168 struct stat from_sb, to_sb;
179 group = owner = NULL;
180 while ((ch = getopt(argc, argv, "B:bCcD:df:g:h:l:M:m:N:o:pSsT:Uv")) !=
193 /* For backwards compatibility. */
213 for (p = optarg; *p != '\0'; p++)
216 dolink &= ~(LN_HARD|LN_MIXED);
217 dolink |= LN_SYMBOLIC;
220 dolink &= ~(LN_SYMBOLIC|LN_MIXED);
224 dolink &= ~(LN_SYMBOLIC|LN_HARD);
228 dolink &= ~LN_RELATIVE;
229 dolink |= LN_ABSOLUTE;
232 dolink &= ~LN_ABSOLUTE;
233 dolink |= LN_RELATIVE;
236 errx(1, "%c: invalid link type", *p);
246 if (!(set = setmode(optarg)))
247 errx(EX_USAGE, "invalid file mode: %s",
251 if (!setup_getid(optarg))
252 err(EX_OSERR, "Unable to use user and group "
253 "databases in `%s'", optarg);
260 docompare = dopreserve = 1;
284 /* some options make no sense when creating directories */
285 if (dostrip && dodir) {
286 warnx("-d and -s may not be specified together");
291 * Default permissions based on whether we're a directory or not, since
292 * an +X may mean that we need to set the execute bit.
295 mode = getmode(set, dodir ? S_IFDIR : 0) & ~S_IFDIR;
298 if (getenv("DONTSTRIP") != NULL) {
299 warnx("DONTSTRIP set - will not strip installed binaries");
303 /* must have at least two arguments, except when creating directories */
304 if (argc == 0 || (argc == 1 && !dodir))
307 if (digest != NULL) {
308 if (strcmp(digest, "none") == 0) {
309 digesttype = DIGEST_NONE;
311 } else if (strcmp(digest, "md5") == 0) {
312 digesttype = DIGEST_MD5;
314 #ifdef WITH_RIPEMD160
315 } else if (strcmp(digest, "rmd160") == 0) {
316 digesttype = DIGEST_RIPEMD160;
318 } else if (strcmp(digest, "sha1") == 0) {
319 digesttype = DIGEST_SHA1;
320 } else if (strcmp(digest, "sha256") == 0) {
321 digesttype = DIGEST_SHA256;
322 } else if (strcmp(digest, "sha512") == 0) {
323 digesttype = DIGEST_SHA512;
325 warnx("unknown digest `%s'", digest);
330 /* get group and owner id's */
331 if (group != NULL && !dounpriv) {
332 if (gid_from_group(group, &gid) == -1) {
334 if (!parseid(group, &id))
335 errx(1, "unknown group %s", group);
341 if (owner != NULL && !dounpriv) {
342 if (uid_from_user(owner, &uid) == -1) {
344 if (!parseid(owner, &id))
345 errx(1, "unknown user %s", owner);
351 if (fflags != NULL && !dounpriv) {
352 if (strtofflags(&fflags, &fset, NULL))
353 errx(EX_USAGE, "%s: invalid flag", fflags);
357 if (metafile != NULL) {
358 if ((metafp = fopen(metafile, "a")) == NULL)
359 warn("open %s", metafile);
361 digesttype = DIGEST_NONE;
364 for (; *argv != NULL; ++argv)
370 to_name = argv[argc - 1];
371 no_target = stat(to_name, &to_sb);
372 if (!no_target && S_ISDIR(to_sb.st_mode)) {
373 if (dolink & LN_SYMBOLIC) {
374 if (lstat(to_name, &to_sb) != 0)
375 err(EX_OSERR, "%s vanished", to_name);
376 if (S_ISLNK(to_sb.st_mode)) {
379 err(EX_USAGE, "%s", to_name);
381 install(*argv, to_name, fset, iflags);
385 for (; *argv != to_name; ++argv)
386 install(*argv, to_name, fset, iflags | DIRECTORY);
391 /* can't do file1 file2 directory/file */
394 warnx("target directory `%s' does not exist",
397 warnx("target `%s' is not a directory",
402 if (!no_target && !dolink) {
403 if (stat(*argv, &from_sb))
404 err(EX_OSERR, "%s", *argv);
405 if (!S_ISREG(to_sb.st_mode)) {
407 err(EX_OSERR, "%s", to_name);
409 if (to_sb.st_dev == from_sb.st_dev &&
410 to_sb.st_ino == from_sb.st_ino)
412 "%s and %s are the same file", *argv, to_name);
414 install(*argv, to_name, fset, iflags);
420 digest_file(const char *name)
423 switch (digesttype) {
426 return (MD5File(name, NULL));
428 #ifdef WITH_RIPEMD160
429 case DIGEST_RIPEMD160:
430 return (RIPEMD160_File(name, NULL));
433 return (SHA1_File(name, NULL));
435 return (SHA256_File(name, NULL));
437 return (SHA512_File(name, NULL));
444 digest_init(DIGEST_CTX *c)
447 switch (digesttype) {
455 #ifdef WITH_RIPEMD160
456 case DIGEST_RIPEMD160:
457 RIPEMD160_Init(&(c->RIPEMD160));
461 SHA1_Init(&(c->SHA1));
464 SHA256_Init(&(c->SHA256));
467 SHA512_Init(&(c->SHA512));
473 digest_update(DIGEST_CTX *c, const char *data, size_t len)
476 switch (digesttype) {
481 MD5Update(&(c->MD5), data, len);
484 #ifdef WITH_RIPEMD160
485 case DIGEST_RIPEMD160:
486 RIPEMD160_Update(&(c->RIPEMD160), data, len);
490 SHA1_Update(&(c->SHA1), data, len);
493 SHA256_Update(&(c->SHA256), data, len);
496 SHA512_Update(&(c->SHA512), data, len);
502 digest_end(DIGEST_CTX *c, char *buf)
505 switch (digesttype) {
508 return (MD5End(&(c->MD5), buf));
510 #ifdef WITH_RIPEMD160
511 case DIGEST_RIPEMD160:
512 return (RIPEMD160_End(&(c->RIPEMD160), buf));
515 return (SHA1_End(&(c->SHA1), buf));
517 return (SHA256_End(&(c->SHA256), buf));
519 return (SHA512_End(&(c->SHA512), buf));
527 * parse uid or gid from arg into id, returning non-zero if successful
530 parseid(const char *name, id_t *id)
534 *id = (id_t)strtoul(name, &ep, 10);
535 if (errno || *ep != '\0')
542 * mktemp implementation used mkstemp to avoid mktemp warnings. We
543 * really do need mktemp semantics here as we will be creating a link.
546 quiet_mktemp(char *template)
550 if ((fd = mkstemp(template)) == -1)
553 if (unlink(template) == -1)
554 err(EX_OSERR, "unlink %s", template);
560 * make a hard link, obeying dorename if set
561 * return -1 on failure
564 do_link(const char *from_name, const char *to_name,
565 const struct stat *target_sb)
567 char tmpl[MAXPATHLEN];
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);
577 if (target_sb->st_mode & S_IFDIR && rmdir(to_name) ==
580 err(EX_OSERR, "%s", to_name);
582 #if HAVE_STRUCT_STAT_ST_FLAGS
583 if (target_sb->st_flags & NOCHANGEBITS)
584 (void)chflags(to_name, target_sb->st_flags &
588 printf("install: link %s -> %s\n",
590 ret = rename(tmpl, to_name);
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.
601 printf("install: link %s -> %s\n",
603 return (link(from_name, to_name));
609 * Make a symbolic link, obeying dorename if set. Exit on failure.
612 do_symlink(const char *from_name, const char *to_name,
613 const struct stat *target_sb)
615 char tmpl[MAXPATHLEN];
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);
623 if (symlink(from_name, tmpl) == -1)
624 err(EX_OSERR, "symlink %s -> %s", from_name, tmpl);
626 if (target_sb->st_mode & S_IFDIR && rmdir(to_name) == -1) {
628 err(EX_OSERR, "%s", to_name);
630 #if HAVE_STRUCT_STAT_ST_FLAGS
631 if (target_sb->st_flags & NOCHANGEBITS)
632 (void)chflags(to_name, target_sb->st_flags &
636 printf("install: symlink %s -> %s\n",
638 if (rename(tmpl, to_name) == -1) {
639 /* Remove temporary link before exiting. */
641 err(EX_OSERR, "%s: rename", to_name);
645 printf("install: symlink %s -> %s\n",
647 if (symlink(from_name, to_name) == -1)
648 err(EX_OSERR, "symlink %s -> %s", from_name, to_name);
654 * make a link from source to destination
657 makelink(const char *from_name, const char *to_name,
658 const struct stat *target_sb)
660 char src[MAXPATHLEN], dst[MAXPATHLEN], lnk[MAXPATHLEN];
663 /* Try hard links first. */
664 if (dolink & (LN_HARD|LN_MIXED)) {
665 if (do_link(from_name, to_name, target_sb) == -1) {
666 if ((dolink & LN_HARD) || errno != EXDEV)
667 err(EX_OSERR, "link %s -> %s", from_name, to_name);
669 if (stat(to_name, &to_sb))
670 err(EX_OSERR, "%s: stat", to_name);
671 if (S_ISREG(to_sb.st_mode)) {
673 * XXX: hard links to anything other than
674 * plain files are not metalogged
677 const char *oowner, *ogroup;
682 * XXX: use underlying perms, unless
683 * overridden on command line.
687 mode = (to_sb.st_mode & 0777);
697 dres = digest_file(from_name);
698 metadata_log(to_name, "file", NULL, NULL,
699 dres, to_sb.st_size);
710 /* Symbolic links. */
711 if (dolink & LN_ABSOLUTE) {
712 /* Convert source path to absolute. */
713 if (realpath(from_name, src) == NULL)
714 err(EX_OSERR, "%s: realpath", from_name);
715 do_symlink(src, to_name, target_sb);
716 /* XXX: src may point outside of destdir */
717 metadata_log(to_name, "link", NULL, src, NULL, 0);
721 if (dolink & LN_RELATIVE) {
722 char *to_name_copy, *cp, *d, *ld, *ls, *s;
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);
732 /* Resolve pathnames. */
733 if (realpath(from_name, src) == NULL)
734 err(EX_OSERR, "%s: realpath", from_name);
737 * The last component of to_name may be a symlink,
738 * so use realpath to resolve only the directory.
740 to_name_copy = strdup(to_name);
741 if (to_name_copy == NULL)
742 err(EX_OSERR, "%s: strdup", to_name);
743 cp = dirname(to_name_copy);
744 if (realpath(cp, dst) == NULL)
745 err(EX_OSERR, "%s: realpath", cp);
746 /* .. and add the last component. */
747 if (strcmp(dst, "/") != 0) {
748 if (strlcat(dst, "/", sizeof(dst)) > sizeof(dst))
749 errx(1, "resolved pathname too long");
751 strcpy(to_name_copy, to_name);
752 cp = basename(to_name_copy);
753 if (strlcat(dst, cp, sizeof(dst)) > sizeof(dst))
754 errx(1, "resolved pathname too long");
757 /* Trim common path components. */
759 for (s = src, d = dst; *s == *d; ls = s, ld = d, s++, d++)
762 * If we didn't end after a directory separator, then we've
763 * falsely matched the last component. For example, if one
764 * invoked install -lrs /lib/foo.so /libexec/ then the source
765 * would terminate just after the separator while the
766 * destination would terminate in the middle of 'libexec',
767 * leading to a full directory getting falsely eaten.
769 if ((ls != NULL && *ls != '/') || (ld != NULL && *ld != '/'))
774 /* Count the number of directories we need to backtrack. */
775 for (++d, lnk[0] = '\0'; *d; d++)
777 (void)strlcat(lnk, "../", sizeof(lnk));
779 (void)strlcat(lnk, ++s, sizeof(lnk));
781 do_symlink(lnk, to_name, target_sb);
782 /* XXX: Link may point outside of destdir. */
783 metadata_log(to_name, "link", NULL, lnk, NULL, 0);
788 * If absolute or relative was not specified, try the names the
791 do_symlink(from_name, to_name, target_sb);
792 /* XXX: from_name may point outside of destdir. */
793 metadata_log(to_name, "link", NULL, from_name, NULL, 0);
798 * build a path name and install the file
801 install(const char *from_name, const char *to_name, u_long fset, u_int flags)
803 struct stat from_sb, temp_sb, to_sb;
804 struct timespec tsb[2];
805 int devnull, files_match, from_fd, serrno, stripped, target;
807 char backup[MAXPATHLEN], *p, pathbuf[MAXPATHLEN], tempfile[MAXPATHLEN];
811 files_match = stripped = 0;
815 /* If try to install NULL file to a directory, fails. */
816 if (flags & DIRECTORY || strcmp(from_name, _PATH_DEVNULL)) {
818 if (stat(from_name, &from_sb))
819 err(EX_OSERR, "%s", from_name);
820 if (!S_ISREG(from_sb.st_mode)) {
822 err(EX_OSERR, "%s", from_name);
825 /* Build the target path. */
826 if (flags & DIRECTORY) {
827 (void)snprintf(pathbuf, sizeof(pathbuf), "%s%s%s",
829 to_name[strlen(to_name) - 1] == '/' ? "" : "/",
830 (p = strrchr(from_name, '/')) ? ++p : from_name);
838 target = (lstat(to_name, &to_sb) == 0);
841 makelink(from_name, to_name, target ? &to_sb : NULL);
845 if (target && !S_ISREG(to_sb.st_mode) && !S_ISLNK(to_sb.st_mode)) {
851 if (!devnull && (from_fd = open(from_name, O_RDONLY, 0)) < 0)
852 err(EX_OSERR, "%s", from_name);
854 /* If we don't strip, we can compare first. */
855 if (docompare && !dostrip && target && S_ISREG(to_sb.st_mode)) {
856 if ((to_fd = open(to_name, O_RDONLY, 0)) < 0)
857 err(EX_OSERR, "%s", to_name);
859 files_match = to_sb.st_size == 0;
861 files_match = !(compare(from_fd, from_name,
862 (size_t)from_sb.st_size, to_fd,
863 to_name, (size_t)to_sb.st_size, &digestresult));
865 /* Close "to" file unless we match. */
871 to_fd = create_tempfile(to_name, tempfile,
874 err(EX_OSERR, "%s", tempfile);
877 stripped = strip(tempfile, to_fd, from_name,
881 digestresult = copy(from_fd, from_name, to_fd,
882 tempfile, from_sb.st_size);
889 (void)strip(tempfile, to_fd, NULL, &digestresult);
892 * Re-open our fd on the target, in case
893 * we did not strip in-place.
896 to_fd = open(tempfile, O_RDONLY, 0);
898 err(EX_OSERR, "stripping %s", to_name);
902 * Compare the stripped temp file with the target.
904 if (docompare && dostrip && target && S_ISREG(to_sb.st_mode)) {
907 /* Re-open to_fd using the real target name. */
908 if ((to_fd = open(to_name, O_RDONLY, 0)) < 0)
909 err(EX_OSERR, "%s", to_name);
911 if (fstat(temp_fd, &temp_sb)) {
913 (void)unlink(tempfile);
915 err(EX_OSERR, "%s", tempfile);
918 if (compare(temp_fd, tempfile, (size_t)temp_sb.st_size, to_fd,
919 to_name, (size_t)to_sb.st_size, &digestresult)
922 * If target has more than one link we need to
923 * replace it in order to snap the extra links.
924 * Need to preserve target file times, though.
926 if (to_sb.st_nlink != 1) {
927 tsb[0] = to_sb.st_atim;
928 tsb[1] = to_sb.st_mtim;
929 (void)utimensat(AT_FDCWD, tempfile, tsb, 0);
932 (void)unlink(tempfile);
934 (void) close(temp_fd);
937 digestresult = digest_file(tempfile);
940 * Move the new file into place if the files are different (or
941 * just not compared).
944 #if HAVE_STRUCT_STAT_ST_FLAGS
945 /* Try to turn off the immutable bits. */
946 if (to_sb.st_flags & NOCHANGEBITS)
947 (void)chflags(to_name, to_sb.st_flags & ~NOCHANGEBITS);
949 if (target && dobackup) {
950 if ((size_t)snprintf(backup, MAXPATHLEN, "%s%s", to_name,
951 suffix) != strlen(to_name) + strlen(suffix)) {
953 errx(EX_OSERR, "%s: backup filename too long",
957 (void)printf("install: %s -> %s\n", to_name, backup);
958 if (unlink(backup) < 0 && errno != ENOENT) {
960 #if HAVE_STRUCT_STAT_ST_FLAGS
961 if (to_sb.st_flags & NOCHANGEBITS)
962 (void)chflags(to_name, to_sb.st_flags);
966 err(EX_OSERR, "unlink: %s", backup);
968 if (link(to_name, backup) < 0) {
971 #if HAVE_STRUCT_STAT_ST_FLAGS
972 if (to_sb.st_flags & NOCHANGEBITS)
973 (void)chflags(to_name, to_sb.st_flags);
976 err(EX_OSERR, "link: %s to %s", to_name,
981 (void)printf("install: %s -> %s\n", from_name, to_name);
982 if (rename(tempfile, to_name) < 0) {
986 err(EX_OSERR, "rename: %s to %s",
990 /* Re-open to_fd so we aren't hosed by the rename(2). */
992 if ((to_fd = open(to_name, O_RDONLY, 0)) < 0)
993 err(EX_OSERR, "%s", to_name);
997 * Preserve the timestamp of the source file if necessary.
999 if (dopreserve && !files_match && !devnull) {
1000 tsb[0] = from_sb.st_atim;
1001 tsb[1] = from_sb.st_mtim;
1002 (void)utimensat(AT_FDCWD, to_name, tsb, 0);
1005 if (fstat(to_fd, &to_sb) == -1) {
1007 (void)unlink(to_name);
1009 err(EX_OSERR, "%s", to_name);
1013 * Set owner, group, mode for target; do the chown first,
1014 * chown may lose the setuid bits.
1016 if (!dounpriv && ((gid != (gid_t)-1 && gid != to_sb.st_gid) ||
1017 (uid != (uid_t)-1 && uid != to_sb.st_uid) ||
1018 (mode != (to_sb.st_mode & ALLPERMS)))) {
1019 #if HAVE_STRUCT_STAT_ST_FLAGS
1020 /* Try to turn off the immutable bits. */
1021 if (to_sb.st_flags & NOCHANGEBITS)
1022 (void)fchflags(to_fd, to_sb.st_flags & ~NOCHANGEBITS);
1026 if (!dounpriv && ((gid != (gid_t)-1 && gid != to_sb.st_gid) ||
1027 (uid != (uid_t)-1 && uid != to_sb.st_uid))) {
1028 if (fchown(to_fd, uid, gid) == -1) {
1030 (void)unlink(to_name);
1032 err(EX_OSERR,"%s: chown/chgrp", to_name);
1035 if (mode != (to_sb.st_mode & ALLPERMS)) {
1037 dounpriv ? mode & (S_IRWXU|S_IRWXG|S_IRWXO) : mode)) {
1039 (void)unlink(to_name);
1041 err(EX_OSERR, "%s: chmod", to_name);
1044 #if HAVE_STRUCT_STAT_ST_FLAGS
1046 * If provided a set of flags, set them, otherwise, preserve the
1047 * flags, except for the dump flag.
1048 * NFS does not support flags. Ignore EOPNOTSUPP flags if we're just
1049 * trying to turn off UF_NODUMP. If we're trying to set real flags,
1050 * then warn if the fs doesn't support it, otherwise fail.
1052 if (!dounpriv && !devnull && (flags & SETFLAGS ||
1053 (from_sb.st_flags & ~UF_NODUMP) != to_sb.st_flags) &&
1055 flags & SETFLAGS ? fset : from_sb.st_flags & ~UF_NODUMP)) {
1056 if (flags & SETFLAGS) {
1057 if (errno == EOPNOTSUPP)
1058 warn("%s: chflags", to_name);
1061 (void)unlink(to_name);
1063 err(EX_OSERR, "%s: chflags", to_name);
1071 (void)close(from_fd);
1073 metadata_log(to_name, "file", tsb, NULL, digestresult, to_sb.st_size);
1079 * Compare two files; non-zero means files differ.
1080 * Compute digest and return its address in *dresp
1081 * unless it points to pre-computed digest.
1084 compare(int from_fd, const char *from_name __unused, size_t from_len,
1085 int to_fd, const char *to_name __unused, size_t to_len,
1090 int do_digest, done_compare;
1094 if (from_len != to_len)
1097 do_digest = (digesttype != DIGEST_NONE && dresp != NULL &&
1099 if (from_len <= MAX_CMP_SIZE) {
1103 if (trymmap(from_len) && trymmap(to_len)) {
1104 p = mmap(NULL, from_len, PROT_READ, MAP_SHARED,
1106 if (p == MAP_FAILED)
1108 q = mmap(NULL, from_len, PROT_READ, MAP_SHARED,
1110 if (q == MAP_FAILED) {
1111 munmap(p, from_len);
1115 rv = memcmp(p, q, from_len);
1117 digest_update(&ctx, p, from_len);
1118 munmap(p, from_len);
1119 munmap(q, from_len);
1123 if (!done_compare) {
1124 static char *buf, *buf1, *buf2;
1125 static size_t bufsize;
1130 * Note that buf and bufsize are static. If
1131 * malloc() fails, it will fail at the start
1132 * and not copy only some files.
1134 if (sysconf(_SC_PHYS_PAGES) >
1135 PHYSPAGES_THRESHOLD)
1136 bufsize = MIN(BUFSIZE_MAX, MAXPHYS * 8);
1138 bufsize = BUFSIZE_SMALL;
1139 buf = malloc(bufsize * 2);
1141 err(1, "Not enough memory");
1143 buf2 = buf + bufsize;
1146 lseek(from_fd, 0, SEEK_SET);
1147 lseek(to_fd, 0, SEEK_SET);
1149 n1 = read(from_fd, buf1, bufsize);
1153 n2 = read(to_fd, buf2, n1);
1155 rv = memcmp(buf1, buf2, n1);
1157 rv = 1; /* out of sync */
1159 rv = 1; /* read failure */
1161 digest_update(&ctx, buf1, n1);
1163 lseek(from_fd, 0, SEEK_SET);
1164 lseek(to_fd, 0, SEEK_SET);
1167 rv = 1; /* don't bother in this case */
1171 *dresp = digest_end(&ctx, NULL);
1173 (void)digest_end(&ctx, NULL);
1180 * create_tempfile --
1181 * create a temporary file based on path and open it
1184 create_tempfile(const char *path, char *temp, size_t tsize)
1188 (void)strncpy(temp, path, tsize);
1189 temp[tsize - 1] = '\0';
1190 if ((p = strrchr(temp, '/')) != NULL)
1194 (void)strncpy(p, "INS@XXXXXX", &temp[tsize - 1] - p);
1195 temp[tsize - 1] = '\0';
1196 return (mkstemp(temp));
1201 * copy from one file to another
1204 copy(int from_fd, const char *from_name, int to_fd, const char *to_name,
1207 static char *buf = NULL;
1208 static size_t bufsize;
1211 #ifndef BOOTSTRAP_XINSTALL
1218 /* Rewind file descriptors. */
1219 if (lseek(from_fd, (off_t)0, SEEK_SET) == (off_t)-1)
1220 err(EX_OSERR, "lseek: %s", from_name);
1221 if (lseek(to_fd, (off_t)0, SEEK_SET) == (off_t)-1)
1222 err(EX_OSERR, "lseek: %s", to_name);
1224 #ifndef BOOTSTRAP_XINSTALL
1225 /* Try copy_file_range() if no digest is requested */
1226 if (digesttype == DIGEST_NONE) {
1229 ret = copy_file_range(from_fd, NULL, to_fd, NULL,
1233 /* DIGEST_NONE always returns NULL */
1236 if (errno != EINVAL) {
1238 (void)unlink(to_name);
1240 err(EX_OSERR, "%s", to_name);
1249 if (trymmap((size_t)size) &&
1250 (p = mmap(NULL, (size_t)size, PROT_READ, MAP_SHARED,
1251 from_fd, (off_t)0)) != MAP_FAILED) {
1252 nw = write(to_fd, p, size);
1255 (void)unlink(to_name);
1258 "short write to %s: %jd bytes written, %jd bytes asked to write",
1259 to_name, (uintmax_t)nw, (uintmax_t)size);
1262 err(EX_OSERR, "%s", to_name);
1265 digest_update(&ctx, p, size);
1266 (void)munmap(p, size);
1272 * Note that buf and bufsize are static. If
1273 * malloc() fails, it will fail at the start
1274 * and not copy only some files.
1276 if (sysconf(_SC_PHYS_PAGES) >
1277 PHYSPAGES_THRESHOLD)
1278 bufsize = MIN(BUFSIZE_MAX, MAXPHYS * 8);
1280 bufsize = BUFSIZE_SMALL;
1281 buf = malloc(bufsize);
1283 err(1, "Not enough memory");
1285 while ((nr = read(from_fd, buf, bufsize)) > 0) {
1286 if ((nw = write(to_fd, buf, nr)) != nr) {
1288 (void)unlink(to_name);
1291 "short write to %s: %jd bytes written, %jd bytes asked to write",
1292 to_name, (uintmax_t)nw,
1296 err(EX_OSERR, "%s", to_name);
1299 digest_update(&ctx, buf, nr);
1303 (void)unlink(to_name);
1305 err(EX_OSERR, "%s", from_name);
1308 if (safecopy && fsync(to_fd) == -1) {
1310 (void)unlink(to_name);
1312 err(EX_OSERR, "fsync failed for %s", to_name);
1314 return (digest_end(&ctx, NULL));
1319 * Use strip(1) to strip the target file.
1320 * Just invoke strip(1) on to_name if from_name is NULL, else try
1321 * to run "strip -o to_name from_name" and return 0 on failure.
1322 * Return 1 on success and assign result of digest_file(to_name)
1326 strip(const char *to_name, int to_fd, const char *from_name, char **dresp)
1328 const char *stripbin;
1329 const char *args[5];
1330 char *prefixed_from_name;
1332 int error, serrno, status;
1334 prefixed_from_name = NULL;
1335 stripbin = getenv("STRIPBIN");
1336 if (stripbin == NULL)
1339 if (from_name == NULL) {
1346 /* Prepend './' if from_name begins with '-' */
1347 if (from_name[0] == '-') {
1348 if (asprintf(&prefixed_from_name, "./%s", from_name) == -1)
1350 args[3] = prefixed_from_name;
1352 args[3] = from_name;
1356 error = posix_spawnp(&pid, stripbin, NULL, NULL,
1357 __DECONST(char **, args), environ);
1359 (void)unlink(to_name);
1360 errc(error == EAGAIN || error == EPROCLIM || error == ENOMEM ?
1361 EX_TEMPFAIL : EX_OSERR, error, "spawn %s", stripbin);
1363 free(prefixed_from_name);
1364 if (waitpid(pid, &status, 0) == -1) {
1366 (void)unlink(to_name);
1367 errc(EX_SOFTWARE, error, "wait");
1371 if (from_name != NULL)
1373 (void)unlink(to_name);
1374 errx(EX_SOFTWARE, "strip command %s failed on %s",
1377 if (from_name != NULL && safecopy && fsync(to_fd) == -1) {
1379 (void)unlink(to_name);
1381 err(EX_OSERR, "fsync failed for %s", to_name);
1384 *dresp = digest_file(to_name);
1390 * build directory hierarchy
1393 install_dir(char *path)
1397 int ch, tried_mkdir;
1399 for (p = path;; ++p)
1400 if (!*p || (p != path && *p == '/')) {
1405 if (stat(path, &sb) != 0) {
1406 if (errno != ENOENT || tried_mkdir)
1407 err(EX_OSERR, "stat %s", path);
1408 if (mkdir(path, 0755) < 0) {
1410 if (errno == EEXIST)
1412 err(EX_OSERR, "mkdir %s", path);
1415 (void)printf("install: mkdir %s\n",
1417 } else if (!S_ISDIR(sb.st_mode))
1418 errx(EX_OSERR, "%s exists but is not a directory", path);
1424 if ((gid != (gid_t)-1 || uid != (uid_t)-1) &&
1425 chown(path, uid, gid))
1426 warn("chown %u:%u %s", uid, gid, path);
1427 /* XXXBED: should we do the chmod in the dounpriv case? */
1428 if (chmod(path, mode))
1429 warn("chmod %o %s", mode, path);
1431 metadata_log(path, "dir", NULL, NULL, NULL, 0);
1436 * if metafp is not NULL, output mtree(8) full path name and settings to
1437 * metafp, to allow permissions to be set correctly by other tools,
1438 * or to allow integrity checks to be performed.
1441 metadata_log(const char *path, const char *type, struct timespec *ts,
1442 const char *slink, const char *digestresult, off_t size)
1444 static const char extra[] = { ' ', '\t', '\n', '\\', '#', '\0' };
1447 size_t buflen, destlen;
1448 struct flock metalog_lock;
1452 /* Buffer for strsnvis(3), used for both path and slink. */
1453 buflen = strlen(path);
1454 if (slink && strlen(slink) > buflen)
1455 buflen = strlen(slink);
1456 buflen = 4 * buflen + 1;
1457 if ((buf = malloc(buflen)) == NULL) {
1462 /* Lock log file. */
1463 metalog_lock.l_start = 0;
1464 metalog_lock.l_len = 0;
1465 metalog_lock.l_whence = SEEK_SET;
1466 metalog_lock.l_type = F_WRLCK;
1467 if (fcntl(fileno(metafp), F_SETLKW, &metalog_lock) == -1) {
1468 warn("can't lock %s", metafile);
1473 /* Remove destdir. */
1476 destlen = strlen(destdir);
1477 if (strncmp(p, destdir, destlen) == 0 &&
1478 (p[destlen] == '/' || p[destlen] == '\0'))
1481 while (*p && *p == '/')
1483 strsnvis(buf, buflen, p, VIS_OCTAL, extra);
1485 /* Print details. */
1486 fprintf(metafp, ".%s%s type=%s", *p ? "/" : "", p, type);
1488 fprintf(metafp, " uname=%s", owner);
1490 fprintf(metafp, " gname=%s", group);
1491 fprintf(metafp, " mode=%#o", mode);
1493 strsnvis(buf, buflen, slink, VIS_CSTYLE, extra);
1494 fprintf(metafp, " link=%s", buf);
1496 if (*type == 'f') /* type=file */
1497 fprintf(metafp, " size=%lld", (long long)size);
1498 if (ts != NULL && dopreserve)
1499 fprintf(metafp, " time=%lld.%09ld",
1500 (long long)ts[1].tv_sec, ts[1].tv_nsec);
1501 if (digestresult && digest)
1502 fprintf(metafp, " %s=%s", digest, digestresult);
1504 fprintf(metafp, " flags=%s", fflags);
1506 fprintf(metafp, " tags=%s", tags);
1507 fputc('\n', metafp);
1511 /* Unlock log file. */
1512 metalog_lock.l_type = F_UNLCK;
1513 if (fcntl(fileno(metafp), F_SETLKW, &metalog_lock) == -1)
1514 warn("can't unlock %s", metafile);
1520 * print a usage message and die
1525 (void)fprintf(stderr,
1526 "usage: install [-bCcpSsUv] [-f flags] [-g group] [-m mode] [-o owner]\n"
1527 " [-M log] [-D dest] [-h hash] [-T tags]\n"
1528 " [-B suffix] [-l linkflags] [-N dbdir]\n"
1530 " install [-bCcpSsUv] [-f flags] [-g group] [-m mode] [-o owner]\n"
1531 " [-M log] [-D dest] [-h hash] [-T tags]\n"
1532 " [-B suffix] [-l linkflags] [-N dbdir]\n"
1533 " file1 ... fileN directory\n"
1534 " install -dU [-vU] [-g group] [-m mode] [-N dbdir] [-o owner]\n"
1535 " [-M log] [-D dest] [-h hash] [-T tags]\n"
1536 " directory ...\n");
1543 * return true (1) if mmap should be tried, false (0) if not.
1546 trymmap(size_t filesize)
1549 * This function existed to skip mmap() for NFS file systems whereas
1550 * nowadays mmap() should be perfectly safe. Nevertheless, using mmap()
1551 * only reduces the number of system calls if we need multiple read()
1552 * syscalls, i.e. if the file size is > MAXBSIZE. However, mmap() is
1553 * more expensive than read() so set the threshold at 4 fewer syscalls.
1554 * Additionally, for larger file size mmap() can significantly increase
1555 * the number of page faults, so avoid it in that case.
1557 * Note: the 8MB limit is not based on any meaningful benchmarking
1558 * results, it is simply reusing the same value that was used before
1559 * and also matches bin/cp.
1561 * XXX: Maybe we shouldn't bother with mmap() at all, since we use
1562 * MAXBSIZE the syscall overhead of read() shouldn't be too high?
1564 return (filesize > 4 * MAXBSIZE && filesize < 8 * 1024 * 1024);