]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/xinstall/xinstall.c
install: Always use a temporary file.
[FreeBSD/FreeBSD.git] / usr.bin / xinstall / xinstall.c
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/mman.h>
35 #include <sys/mount.h>
36 #include <sys/stat.h>
37 #include <sys/time.h>
38 #include <sys/wait.h>
39
40 #include <err.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <grp.h>
44 #include <libgen.h>
45 #ifdef WITH_MD5
46 #include <md5.h>
47 #endif
48 #include <paths.h>
49 #include <pwd.h>
50 #ifdef WITH_RIPEMD160
51 #include <ripemd.h>
52 #endif
53 #include <sha.h>
54 #include <sha256.h>
55 #include <sha512.h>
56 #include <spawn.h>
57 #include <stdint.h>
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <string.h>
61 #include <sysexits.h>
62 #include <unistd.h>
63 #include <vis.h>
64
65 #include "mtree.h"
66
67 /*
68  * Memory strategy threshold, in pages: if physmem is larger than this, use a
69  * large buffer.
70  */
71 #define PHYSPAGES_THRESHOLD (32*1024)
72
73 /* Maximum buffer size in bytes - do not allow it to grow larger than this. */
74 #define BUFSIZE_MAX (2*1024*1024)
75
76 /*
77  * Small (default) buffer size in bytes. It's inefficient for this to be
78  * smaller than MAXPHYS.
79  */
80 #define BUFSIZE_SMALL (MAXPHYS)
81
82 /*
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.
86  */
87 #ifdef UF_SETTABLE
88 #define HAVE_STRUCT_STAT_ST_FLAGS 1
89 #else
90 #define HAVE_STRUCT_STAT_ST_FLAGS 0
91 #endif
92
93 #define MAX_CMP_SIZE    (16 * 1024 * 1024)
94
95 #define LN_ABSOLUTE     0x01
96 #define LN_RELATIVE     0x02
97 #define LN_HARD         0x04
98 #define LN_SYMBOLIC     0x08
99 #define LN_MIXED        0x10
100
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"
105
106 typedef union {
107 #ifdef WITH_MD5
108         MD5_CTX         MD5;
109 #endif
110 #ifdef WITH_RIPEMD160
111         RIPEMD160_CTX   RIPEMD160;
112 #endif
113         SHA1_CTX        SHA1;
114         SHA256_CTX      SHA256;
115         SHA512_CTX      SHA512;
116 }       DIGEST_CTX;
117
118 static enum {
119         DIGEST_NONE = 0,
120 #ifdef WITH_MD5
121         DIGEST_MD5,
122 #endif
123 #ifdef WITH_RIPEMD160
124         DIGEST_RIPEMD160,
125 #endif
126         DIGEST_SHA1,
127         DIGEST_SHA256,
128         DIGEST_SHA512,
129 } digesttype = DIGEST_NONE;
130
131 extern char **environ;
132
133 static gid_t gid;
134 static uid_t uid;
135 static int dobackup, docompare, dodir, dolink, dopreserve, dostrip, dounpriv,
136     safecopy, verbose;
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;
139 static FILE *metafp;
140 static const char *group, *owner;
141 static const char *suffix = BACKUP_SUFFIX;
142 static char *destdir, *digest, *fflags, *metafile, *tags;
143
144 static int      compare(int, const char *, size_t, int, const char *, size_t,
145                     char **);
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);
164
165 int
166 main(int argc, char *argv[])
167 {
168         struct stat from_sb, to_sb;
169         mode_t *set;
170         u_long fset;
171         int ch, no_target;
172         u_int iflags;
173         char *p;
174         const char *to_name;
175
176         fset = 0;
177         iflags = 0;
178         set = NULL;
179         group = owner = NULL;
180         while ((ch = getopt(argc, argv, "B:bCcD:df:g:h:l:M:m:N:o:pSsT:Uv")) !=
181              -1)
182                 switch((char)ch) {
183                 case 'B':
184                         suffix = optarg;
185                         /* FALLTHROUGH */
186                 case 'b':
187                         dobackup = 1;
188                         break;
189                 case 'C':
190                         docompare = 1;
191                         break;
192                 case 'c':
193                         /* For backwards compatibility. */
194                         break;
195                 case 'D':
196                         destdir = optarg;
197                         break;
198                 case 'd':
199                         dodir = 1;
200                         break;
201                 case 'f':
202                         haveopt_f = 1;
203                         fflags = optarg;
204                         break;
205                 case 'g':
206                         haveopt_g = 1;
207                         group = optarg;
208                         break;
209                 case 'h':
210                         digest = optarg;
211                         break;
212                 case 'l':
213                         for (p = optarg; *p != '\0'; p++)
214                                 switch (*p) {
215                                 case 's':
216                                         dolink &= ~(LN_HARD|LN_MIXED);
217                                         dolink |= LN_SYMBOLIC;
218                                         break;
219                                 case 'h':
220                                         dolink &= ~(LN_SYMBOLIC|LN_MIXED);
221                                         dolink |= LN_HARD;
222                                         break;
223                                 case 'm':
224                                         dolink &= ~(LN_SYMBOLIC|LN_HARD);
225                                         dolink |= LN_MIXED;
226                                         break;
227                                 case 'a':
228                                         dolink &= ~LN_RELATIVE;
229                                         dolink |= LN_ABSOLUTE;
230                                         break;
231                                 case 'r':
232                                         dolink &= ~LN_ABSOLUTE;
233                                         dolink |= LN_RELATIVE;
234                                         break;
235                                 default:
236                                         errx(1, "%c: invalid link type", *p);
237                                         /* NOTREACHED */
238                                 }
239                         break;
240                 case 'M':
241                         metafile = optarg;
242                         break;
243                 case 'm':
244                         haveopt_m = 1;
245                         free(set);
246                         if (!(set = setmode(optarg)))
247                                 errx(EX_USAGE, "invalid file mode: %s",
248                                      optarg);
249                         break;
250                 case 'N':
251                         if (!setup_getid(optarg))
252                                 err(EX_OSERR, "Unable to use user and group "
253                                     "databases in `%s'", optarg);
254                         break;
255                 case 'o':
256                         haveopt_o = 1;
257                         owner = optarg;
258                         break;
259                 case 'p':
260                         docompare = dopreserve = 1;
261                         break;
262                 case 'S':
263                         safecopy = 1;
264                         break;
265                 case 's':
266                         dostrip = 1;
267                         break;
268                 case 'T':
269                         tags = optarg;
270                         break;
271                 case 'U':
272                         dounpriv = 1;
273                         break;
274                 case 'v':
275                         verbose = 1;
276                         break;
277                 case '?':
278                 default:
279                         usage();
280                 }
281         argc -= optind;
282         argv += optind;
283
284         /* some options make no sense when creating directories */
285         if (dostrip && dodir) {
286                 warnx("-d and -s may not be specified together");
287                 usage();
288         }
289
290         /*
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.
293          */
294         if (set != NULL)
295                 mode = getmode(set, dodir ? S_IFDIR : 0) & ~S_IFDIR;
296         free(set);
297
298         if (getenv("DONTSTRIP") != NULL) {
299                 warnx("DONTSTRIP set - will not strip installed binaries");
300                 dostrip = 0;
301         }
302
303         /* must have at least two arguments, except when creating directories */
304         if (argc == 0 || (argc == 1 && !dodir))
305                 usage();
306
307         if (digest != NULL) {
308                 if (strcmp(digest, "none") == 0) {
309                         digesttype = DIGEST_NONE;
310 #ifdef WITH_MD5
311                 } else if (strcmp(digest, "md5") == 0) {
312                        digesttype = DIGEST_MD5;
313 #endif
314 #ifdef WITH_RIPEMD160
315                 } else if (strcmp(digest, "rmd160") == 0) {
316                         digesttype = DIGEST_RIPEMD160;
317 #endif
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;
324                 } else {
325                         warnx("unknown digest `%s'", digest);
326                         usage();
327                 }
328         }
329
330         /* get group and owner id's */
331         if (group != NULL && !dounpriv) {
332                 if (gid_from_group(group, &gid) == -1) {
333                         id_t id;
334                         if (!parseid(group, &id))
335                                 errx(1, "unknown group %s", group);
336                         gid = id;
337                 }
338         } else
339                 gid = (gid_t)-1;
340
341         if (owner != NULL && !dounpriv) {
342                 if (uid_from_user(owner, &uid) == -1) {
343                         id_t id;
344                         if (!parseid(owner, &id))
345                                 errx(1, "unknown user %s", owner);
346                         uid = id;
347                 }
348         } else
349                 uid = (uid_t)-1;
350
351         if (fflags != NULL && !dounpriv) {
352                 if (strtofflags(&fflags, &fset, NULL))
353                         errx(EX_USAGE, "%s: invalid flag", fflags);
354                 iflags |= SETFLAGS;
355         }
356
357         if (metafile != NULL) {
358                 if ((metafp = fopen(metafile, "a")) == NULL)
359                         warn("open %s", metafile);
360         } else
361                 digesttype = DIGEST_NONE;
362
363         if (dodir) {
364                 for (; *argv != NULL; ++argv)
365                         install_dir(*argv);
366                 exit(EX_OK);
367                 /* NOTREACHED */
368         }
369
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)) {
377                                 if (argc != 2) {
378                                         errno = ENOTDIR;
379                                         err(EX_USAGE, "%s", to_name);
380                                 }
381                                 install(*argv, to_name, fset, iflags);
382                                 exit(EX_OK);
383                         }
384                 }
385                 for (; *argv != to_name; ++argv)
386                         install(*argv, to_name, fset, iflags | DIRECTORY);
387                 exit(EX_OK);
388                 /* NOTREACHED */
389         }
390
391         /* can't do file1 file2 directory/file */
392         if (argc != 2) {
393                 if (no_target)
394                         warnx("target directory `%s' does not exist", 
395                             argv[argc - 1]);
396                 else
397                         warnx("target `%s' is not a directory",
398                             argv[argc - 1]);
399                 usage();
400         }
401
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)) {
406                         errno = EFTYPE;
407                         err(EX_OSERR, "%s", to_name);
408                 }
409                 if (to_sb.st_dev == from_sb.st_dev &&
410                     to_sb.st_ino == from_sb.st_ino)
411                         errx(EX_USAGE, 
412                             "%s and %s are the same file", *argv, to_name);
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         struct stat     to_sb;
662
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);
668                 } else {
669                         if (stat(to_name, &to_sb))
670                                 err(EX_OSERR, "%s: stat", to_name);
671                         if (S_ISREG(to_sb.st_mode)) {
672                                 /*
673                                  * XXX: hard links to anything other than
674                                  * plain files are not metalogged
675                                  */
676                                 int omode;
677                                 const char *oowner, *ogroup;
678                                 char *offlags;
679                                 char *dres;
680
681                                 /*
682                                  * XXX: use underlying perms, unless
683                                  * overridden on command line.
684                                  */
685                                 omode = mode;
686                                 if (!haveopt_m)
687                                         mode = (to_sb.st_mode & 0777);
688                                 oowner = owner;
689                                 if (!haveopt_o)
690                                         owner = NULL;
691                                 ogroup = group;
692                                 if (!haveopt_g)
693                                         group = NULL;
694                                 offlags = fflags;
695                                 if (!haveopt_f)
696                                         fflags = NULL;
697                                 dres = digest_file(from_name);
698                                 metadata_log(to_name, "file", NULL, NULL,
699                                     dres, to_sb.st_size);
700                                 free(dres);
701                                 mode = omode;
702                                 owner = oowner;
703                                 group = ogroup;
704                                 fflags = offlags;
705                         }
706                         return;
707                 }
708         }
709
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);
718                 return;
719         }
720
721         if (dolink & LN_RELATIVE) {
722                 char *to_name_copy, *cp, *d, *ld, *ls, *s;
723
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                 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");
750                 }
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");
755                 free(to_name_copy);
756
757                 /* Trim common path components. */
758                 ls = ld = NULL;
759                 for (s = src, d = dst; *s == *d; ls = s, ld = d, s++, d++)
760                         continue;
761                 /*
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.
768                  */
769                 if ((ls != NULL && *ls != '/') || (ld != NULL && *ld != '/'))
770                         s--, d--;
771                 while (*s != '/')
772                         s--, d--;
773
774                 /* Count the number of directories we need to backtrack. */
775                 for (++d, lnk[0] = '\0'; *d; d++)
776                         if (*d == '/')
777                                 (void)strlcat(lnk, "../", sizeof(lnk));
778
779                 (void)strlcat(lnk, ++s, sizeof(lnk));
780
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);
784                 return;
785         }
786
787         /*
788          * If absolute or relative was not specified, try the names the
789          * user provided.
790          */
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);
794 }
795
796 /*
797  * install --
798  *      build a path name and install the file
799  */
800 static void
801 install(const char *from_name, const char *to_name, u_long fset, u_int flags)
802 {
803         struct stat from_sb, temp_sb, to_sb;
804         struct timespec tsb[2];
805         int devnull, files_match, from_fd, serrno, stripped, target;
806         int temp_fd, to_fd;
807         char backup[MAXPATHLEN], *p, pathbuf[MAXPATHLEN], tempfile[MAXPATHLEN];
808         char *digestresult;
809
810         digestresult = NULL;
811         files_match = stripped = 0;
812         from_fd = -1;
813         to_fd = -1;
814
815         /* If try to install NULL file to a directory, fails. */
816         if (flags & DIRECTORY || strcmp(from_name, _PATH_DEVNULL)) {
817                 if (!dolink) {
818                         if (stat(from_name, &from_sb))
819                                 err(EX_OSERR, "%s", from_name);
820                         if (!S_ISREG(from_sb.st_mode)) {
821                                 errno = EFTYPE;
822                                 err(EX_OSERR, "%s", from_name);
823                         }
824                 }
825                 /* Build the target path. */
826                 if (flags & DIRECTORY) {
827                         (void)snprintf(pathbuf, sizeof(pathbuf), "%s%s%s",
828                             to_name,
829                             to_name[strlen(to_name) - 1] == '/' ? "" : "/",
830                             (p = strrchr(from_name, '/')) ? ++p : from_name);
831                         to_name = pathbuf;
832                 }
833                 devnull = 0;
834         } else {
835                 devnull = 1;
836         }
837
838         target = (lstat(to_name, &to_sb) == 0);
839
840         if (dolink) {
841                 makelink(from_name, to_name, target ? &to_sb : NULL);
842                 return;
843         }
844
845         if (target && !S_ISREG(to_sb.st_mode) && !S_ISLNK(to_sb.st_mode)) {
846                 errno = EFTYPE;
847                 warn("%s", to_name);
848                 return;
849         }
850
851         if (!devnull && (from_fd = open(from_name, O_RDONLY, 0)) < 0)
852                 err(EX_OSERR, "%s", from_name);
853
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);
858                 if (devnull)
859                         files_match = to_sb.st_size == 0;
860                 else
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));
864
865                 /* Close "to" file unless we match. */
866                 if (!files_match)
867                         (void)close(to_fd);
868         }
869
870         if (!files_match) {
871                 to_fd = create_tempfile(to_name, tempfile,
872                     sizeof(tempfile));
873                 if (to_fd < 0)
874                         err(EX_OSERR, "%s", tempfile);
875                 if (!devnull) {
876                         if (dostrip) {
877                                 stripped = strip(tempfile, to_fd, from_name,
878                                     &digestresult);
879                         }
880                         if (!stripped) {
881                                 digestresult = copy(from_fd, from_name, to_fd,
882                                     tempfile, from_sb.st_size);
883                         }
884                 }
885         }
886
887         if (dostrip) {
888                 if (!stripped)
889                         (void)strip(tempfile, to_fd, NULL, &digestresult);
890
891                 /*
892                  * Re-open our fd on the target, in case
893                  * we did not strip in-place.
894                  */
895                 close(to_fd);
896                 to_fd = open(tempfile, O_RDONLY, 0);
897                 if (to_fd < 0)
898                         err(EX_OSERR, "stripping %s", to_name);
899         }
900
901         /*
902          * Compare the stripped temp file with the target.
903          */
904         if (docompare && dostrip && target && S_ISREG(to_sb.st_mode)) {
905                 temp_fd = to_fd;
906
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);
910
911                 if (fstat(temp_fd, &temp_sb)) {
912                         serrno = errno;
913                         (void)unlink(tempfile);
914                         errno = serrno;
915                         err(EX_OSERR, "%s", tempfile);
916                 }
917
918                 if (compare(temp_fd, tempfile, (size_t)temp_sb.st_size, to_fd,
919                             to_name, (size_t)to_sb.st_size, &digestresult)
920                             == 0) {
921                         /*
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.
925                          */
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);
930                         } else {
931                                 files_match = 1;
932                                 (void)unlink(tempfile);
933                         }
934                         (void) close(temp_fd);
935                 }
936         } else if (dostrip)
937                 digestresult = digest_file(tempfile);
938
939         /*
940          * Move the new file into place if the files are different (or
941          * just not compared).
942          */
943         if (!files_match) {
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);
948 #endif
949                 if (target && dobackup) {
950                         if ((size_t)snprintf(backup, MAXPATHLEN, "%s%s", to_name,
951                             suffix) != strlen(to_name) + strlen(suffix)) {
952                                 unlink(tempfile);
953                                 errx(EX_OSERR, "%s: backup filename too long",
954                                     to_name);
955                         }
956                         if (verbose)
957                                 (void)printf("install: %s -> %s\n", to_name, backup);
958                         if (unlink(backup) < 0 && errno != ENOENT) {
959                                 serrno = errno;
960 #if HAVE_STRUCT_STAT_ST_FLAGS
961                                 if (to_sb.st_flags & NOCHANGEBITS)
962                                         (void)chflags(to_name, to_sb.st_flags);
963 #endif
964                                 unlink(tempfile);
965                                 errno = serrno;
966                                 err(EX_OSERR, "unlink: %s", backup);
967                         }
968                         if (link(to_name, backup) < 0) {
969                                 serrno = errno;
970                                 unlink(tempfile);
971 #if HAVE_STRUCT_STAT_ST_FLAGS
972                                 if (to_sb.st_flags & NOCHANGEBITS)
973                                         (void)chflags(to_name, to_sb.st_flags);
974 #endif
975                                 errno = serrno;
976                                 err(EX_OSERR, "link: %s to %s", to_name,
977                                      backup);
978                         }
979                 }
980                 if (verbose)
981                         (void)printf("install: %s -> %s\n", from_name, to_name);
982                 if (rename(tempfile, to_name) < 0) {
983                         serrno = errno;
984                         unlink(tempfile);
985                         errno = serrno;
986                         err(EX_OSERR, "rename: %s to %s",
987                             tempfile, to_name);
988                 }
989
990                 /* Re-open to_fd so we aren't hosed by the rename(2). */
991                 (void) close(to_fd);
992                 if ((to_fd = open(to_name, O_RDONLY, 0)) < 0)
993                         err(EX_OSERR, "%s", to_name);
994         }
995
996         /*
997          * Preserve the timestamp of the source file if necessary.
998          */
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);
1003         }
1004
1005         if (fstat(to_fd, &to_sb) == -1) {
1006                 serrno = errno;
1007                 (void)unlink(to_name);
1008                 errno = serrno;
1009                 err(EX_OSERR, "%s", to_name);
1010         }
1011
1012         /*
1013          * Set owner, group, mode for target; do the chown first,
1014          * chown may lose the setuid bits.
1015          */
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);
1023 #endif
1024         }
1025
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) {
1029                         serrno = errno;
1030                         (void)unlink(to_name);
1031                         errno = serrno;
1032                         err(EX_OSERR,"%s: chown/chgrp", to_name);
1033                 }
1034         }
1035         if (mode != (to_sb.st_mode & ALLPERMS)) {
1036                 if (fchmod(to_fd,
1037                     dounpriv ? mode & (S_IRWXU|S_IRWXG|S_IRWXO) : mode)) {
1038                         serrno = errno;
1039                         (void)unlink(to_name);
1040                         errno = serrno;
1041                         err(EX_OSERR, "%s: chmod", to_name);
1042                 }
1043         }
1044 #if HAVE_STRUCT_STAT_ST_FLAGS
1045         /*
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.
1051          */
1052         if (!dounpriv && !devnull && (flags & SETFLAGS ||
1053             (from_sb.st_flags & ~UF_NODUMP) != to_sb.st_flags) &&
1054             fchflags(to_fd,
1055             flags & SETFLAGS ? fset : from_sb.st_flags & ~UF_NODUMP)) {
1056                 if (flags & SETFLAGS) {
1057                         if (errno == EOPNOTSUPP)
1058                                 warn("%s: chflags", to_name);
1059                         else {
1060                                 serrno = errno;
1061                                 (void)unlink(to_name);
1062                                 errno = serrno;
1063                                 err(EX_OSERR, "%s: chflags", to_name);
1064                         }
1065                 }
1066         }
1067 #endif
1068
1069         (void)close(to_fd);
1070         if (!devnull)
1071                 (void)close(from_fd);
1072
1073         metadata_log(to_name, "file", tsb, NULL, digestresult, to_sb.st_size);
1074         free(digestresult);
1075 }
1076
1077 /*
1078  * compare --
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.
1082  */
1083 static int
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,
1086         char **dresp)
1087 {
1088         char *p, *q;
1089         int rv;
1090         int do_digest, done_compare;
1091         DIGEST_CTX ctx;
1092
1093         rv = 0;
1094         if (from_len != to_len)
1095                 return 1;
1096
1097         do_digest = (digesttype != DIGEST_NONE && dresp != NULL &&
1098             *dresp == NULL);
1099         if (from_len <= MAX_CMP_SIZE) {
1100                 if (do_digest)
1101                         digest_init(&ctx);
1102                 done_compare = 0;
1103                 if (trymmap(from_len) && trymmap(to_len)) {
1104                         p = mmap(NULL, from_len, PROT_READ, MAP_SHARED,
1105                             from_fd, (off_t)0);
1106                         if (p == MAP_FAILED)
1107                                 goto out;
1108                         q = mmap(NULL, from_len, PROT_READ, MAP_SHARED,
1109                             to_fd, (off_t)0);
1110                         if (q == MAP_FAILED) {
1111                                 munmap(p, from_len);
1112                                 goto out;
1113                         }
1114
1115                         rv = memcmp(p, q, from_len);
1116                         if (do_digest)
1117                                 digest_update(&ctx, p, from_len);
1118                         munmap(p, from_len);
1119                         munmap(q, from_len);
1120                         done_compare = 1;
1121                 }
1122         out:
1123                 if (!done_compare) {
1124                         static char *buf, *buf1, *buf2;
1125                         static size_t bufsize;
1126                         int n1, n2;
1127
1128                         if (buf == NULL) {
1129                                 /*
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.
1133                                  */
1134                                 if (sysconf(_SC_PHYS_PAGES) >
1135                                     PHYSPAGES_THRESHOLD)
1136                                         bufsize = MIN(BUFSIZE_MAX, MAXPHYS * 8);
1137                                 else
1138                                         bufsize = BUFSIZE_SMALL;
1139                                 buf = malloc(bufsize * 2);
1140                                 if (buf == NULL)
1141                                         err(1, "Not enough memory");
1142                                 buf1 = buf;
1143                                 buf2 = buf + bufsize;
1144                         }
1145                         rv = 0;
1146                         lseek(from_fd, 0, SEEK_SET);
1147                         lseek(to_fd, 0, SEEK_SET);
1148                         while (rv == 0) {
1149                                 n1 = read(from_fd, buf1, bufsize);
1150                                 if (n1 == 0)
1151                                         break;          /* EOF */
1152                                 else if (n1 > 0) {
1153                                         n2 = read(to_fd, buf2, n1);
1154                                         if (n2 == n1)
1155                                                 rv = memcmp(buf1, buf2, n1);
1156                                         else
1157                                                 rv = 1; /* out of sync */
1158                                 } else
1159                                         rv = 1;         /* read failure */
1160                                 if (do_digest)
1161                                         digest_update(&ctx, buf1, n1);
1162                         }
1163                         lseek(from_fd, 0, SEEK_SET);
1164                         lseek(to_fd, 0, SEEK_SET);
1165                 }
1166         } else
1167                 rv = 1; /* don't bother in this case */
1168
1169         if (do_digest) {
1170                 if (rv == 0)
1171                         *dresp = digest_end(&ctx, NULL);
1172                 else
1173                         (void)digest_end(&ctx, NULL);
1174         }
1175
1176         return rv;
1177 }
1178
1179 /*
1180  * create_tempfile --
1181  *      create a temporary file based on path and open it
1182  */
1183 static int
1184 create_tempfile(const char *path, char *temp, size_t tsize)
1185 {
1186         char *p;
1187
1188         (void)strncpy(temp, path, tsize);
1189         temp[tsize - 1] = '\0';
1190         if ((p = strrchr(temp, '/')) != NULL)
1191                 p++;
1192         else
1193                 p = temp;
1194         (void)strncpy(p, "INS@XXXXXX", &temp[tsize - 1] - p);
1195         temp[tsize - 1] = '\0';
1196         return (mkstemp(temp));
1197 }
1198
1199 /*
1200  * copy --
1201  *      copy from one file to another
1202  */
1203 static char *
1204 copy(int from_fd, const char *from_name, int to_fd, const char *to_name,
1205     off_t size)
1206 {
1207         static char *buf = NULL;
1208         static size_t bufsize;
1209         int nr, nw;
1210         int serrno;
1211 #ifndef BOOTSTRAP_XINSTALL
1212         ssize_t ret;
1213 #endif
1214         char *p;
1215         int done_copy;
1216         DIGEST_CTX ctx;
1217
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);
1223
1224 #ifndef BOOTSTRAP_XINSTALL
1225         /* Try copy_file_range() if no digest is requested */
1226         if (digesttype == DIGEST_NONE) {
1227                 ret = 1;
1228                 while (ret > 0) {
1229                         ret = copy_file_range(from_fd, NULL, to_fd, NULL,
1230                             SSIZE_MAX, 0);
1231                 }
1232                 if (ret == 0) {
1233                         /* DIGEST_NONE always returns NULL */
1234                         return (NULL);
1235                 }
1236                 if (errno != EINVAL) {
1237                         serrno = errno;
1238                         (void)unlink(to_name);
1239                         errno = serrno;
1240                         err(EX_OSERR, "%s", to_name);
1241                 }
1242                 /* Fall back */
1243         }
1244
1245 #endif
1246         digest_init(&ctx);
1247
1248         done_copy = 0;
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);
1253                 if (nw != size) {
1254                         serrno = errno;
1255                         (void)unlink(to_name);
1256                         if (nw >= 0) {
1257                                 errx(EX_OSERR,
1258      "short write to %s: %jd bytes written, %jd bytes asked to write",
1259                                     to_name, (uintmax_t)nw, (uintmax_t)size);
1260                         } else {
1261                                 errno = serrno;
1262                                 err(EX_OSERR, "%s", to_name);
1263                         }
1264                 }
1265                 digest_update(&ctx, p, size);
1266                 (void)munmap(p, size);
1267                 done_copy = 1;
1268         }
1269         if (!done_copy) {
1270                 if (buf == NULL) {
1271                         /*
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.
1275                          */
1276                         if (sysconf(_SC_PHYS_PAGES) >
1277                             PHYSPAGES_THRESHOLD)
1278                                 bufsize = MIN(BUFSIZE_MAX, MAXPHYS * 8);
1279                         else
1280                                 bufsize = BUFSIZE_SMALL;
1281                         buf = malloc(bufsize);
1282                         if (buf == NULL)
1283                                 err(1, "Not enough memory");
1284                 }
1285                 while ((nr = read(from_fd, buf, bufsize)) > 0) {
1286                         if ((nw = write(to_fd, buf, nr)) != nr) {
1287                                 serrno = errno;
1288                                 (void)unlink(to_name);
1289                                 if (nw >= 0) {
1290                                         errx(EX_OSERR,
1291      "short write to %s: %jd bytes written, %jd bytes asked to write",
1292                                             to_name, (uintmax_t)nw,
1293                                             (uintmax_t)size);
1294                                 } else {
1295                                         errno = serrno;
1296                                         err(EX_OSERR, "%s", to_name);
1297                                 }
1298                         }
1299                         digest_update(&ctx, buf, nr);
1300                 }
1301                 if (nr != 0) {
1302                         serrno = errno;
1303                         (void)unlink(to_name);
1304                         errno = serrno;
1305                         err(EX_OSERR, "%s", from_name);
1306                 }
1307         }
1308         if (safecopy && fsync(to_fd) == -1) {
1309                 serrno = errno;
1310                 (void)unlink(to_name);
1311                 errno = serrno;
1312                 err(EX_OSERR, "fsync failed for %s", to_name);
1313         }
1314         return (digest_end(&ctx, NULL));
1315 }
1316
1317 /*
1318  * strip --
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)
1323  *      to *dresp.
1324  */
1325 static int
1326 strip(const char *to_name, int to_fd, const char *from_name, char **dresp)
1327 {
1328         const char *stripbin;
1329         const char *args[5];
1330         char *prefixed_from_name;
1331         pid_t pid;
1332         int error, serrno, status;
1333
1334         prefixed_from_name = NULL;
1335         stripbin = getenv("STRIPBIN");
1336         if (stripbin == NULL)
1337                 stripbin = "strip";
1338         args[0] = stripbin;
1339         if (from_name == NULL) {
1340                 args[1] = to_name;
1341                 args[2] = NULL;
1342         } else {
1343                 args[1] = "-o";
1344                 args[2] = to_name;
1345
1346                 /* Prepend './' if from_name begins with '-' */
1347                 if (from_name[0] == '-') {
1348                         if (asprintf(&prefixed_from_name, "./%s", from_name) == -1)
1349                                 return (0);
1350                         args[3] = prefixed_from_name;
1351                 } else {
1352                         args[3] = from_name;
1353                 }
1354                 args[4] = NULL;
1355         }
1356         error = posix_spawnp(&pid, stripbin, NULL, NULL,
1357             __DECONST(char **, args), environ);
1358         if (error != 0) {
1359                 (void)unlink(to_name);
1360                 errc(error == EAGAIN || error == EPROCLIM || error == ENOMEM ?
1361                     EX_TEMPFAIL : EX_OSERR, error, "spawn %s", stripbin);
1362         }
1363         free(prefixed_from_name);
1364         if (waitpid(pid, &status, 0) == -1) {
1365                 error = errno;
1366                 (void)unlink(to_name);
1367                 errc(EX_SOFTWARE, error, "wait");
1368                 /* NOTREACHED */
1369         }
1370         if (status != 0) {
1371                 if (from_name != NULL)
1372                         return (0);
1373                 (void)unlink(to_name);
1374                 errx(EX_SOFTWARE, "strip command %s failed on %s",
1375                     stripbin, to_name);
1376         }
1377         if (from_name != NULL && safecopy && fsync(to_fd) == -1) {
1378                 serrno = errno;
1379                 (void)unlink(to_name);
1380                 errno = serrno;
1381                 err(EX_OSERR, "fsync failed for %s", to_name);
1382         }
1383         if (dresp != NULL)
1384                 *dresp = digest_file(to_name);
1385         return (1);
1386 }
1387
1388 /*
1389  * install_dir --
1390  *      build directory hierarchy
1391  */
1392 static void
1393 install_dir(char *path)
1394 {
1395         char *p;
1396         struct stat sb;
1397         int ch, tried_mkdir;
1398
1399         for (p = path;; ++p)
1400                 if (!*p || (p != path && *p  == '/')) {
1401                         tried_mkdir = 0;
1402                         ch = *p;
1403                         *p = '\0';
1404 again:
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) {
1409                                         tried_mkdir = 1;
1410                                         if (errno == EEXIST)
1411                                                 goto again;
1412                                         err(EX_OSERR, "mkdir %s", path);
1413                                 }
1414                                 if (verbose)
1415                                         (void)printf("install: mkdir %s\n",
1416                                             path);
1417                         } else if (!S_ISDIR(sb.st_mode))
1418                                 errx(EX_OSERR, "%s exists but is not a directory", path);
1419                         if (!(*p = ch))
1420                                 break;
1421                 }
1422
1423         if (!dounpriv) {
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);
1430         }
1431         metadata_log(path, "dir", NULL, NULL, NULL, 0);
1432 }
1433
1434 /*
1435  * metadata_log --
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.
1439  */
1440 static void
1441 metadata_log(const char *path, const char *type, struct timespec *ts,
1442         const char *slink, const char *digestresult, off_t size)
1443 {
1444         static const char extra[] = { ' ', '\t', '\n', '\\', '#', '\0' };
1445         const char *p;
1446         char *buf;
1447         size_t buflen, destlen;
1448         struct flock metalog_lock;
1449
1450         if (!metafp)    
1451                 return;
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) {
1458                 warn(NULL);
1459                 return;
1460         }
1461
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);
1469                 free(buf);
1470                 return;
1471         }
1472
1473         /* Remove destdir. */
1474         p = path;
1475         if (destdir) {
1476                 destlen = strlen(destdir);
1477                 if (strncmp(p, destdir, destlen) == 0 &&
1478                     (p[destlen] == '/' || p[destlen] == '\0'))
1479                         p += destlen;
1480         }
1481         while (*p && *p == '/')
1482                 p++;
1483         strsnvis(buf, buflen, p, VIS_OCTAL, extra);
1484         p = buf;
1485         /* Print details. */
1486         fprintf(metafp, ".%s%s type=%s", *p ? "/" : "", p, type);
1487         if (owner)
1488                 fprintf(metafp, " uname=%s", owner);
1489         if (group)
1490                 fprintf(metafp, " gname=%s", group);
1491         fprintf(metafp, " mode=%#o", mode);
1492         if (slink) {
1493                 strsnvis(buf, buflen, slink, VIS_CSTYLE, extra);
1494                 fprintf(metafp, " link=%s", buf);
1495         }
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);
1503         if (fflags)
1504                 fprintf(metafp, " flags=%s", fflags);
1505         if (tags)
1506                 fprintf(metafp, " tags=%s", tags);
1507         fputc('\n', metafp);
1508         /* Flush line. */
1509         fflush(metafp);
1510
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);
1515         free(buf);
1516 }
1517
1518 /*
1519  * usage --
1520  *      print a usage message and die
1521  */
1522 static void
1523 usage(void)
1524 {
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"
1529 "               file1 file2\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");
1537         exit(EX_USAGE);
1538         /* NOTREACHED */
1539 }
1540
1541 /*
1542  * trymmap --
1543  *      return true (1) if mmap should be tried, false (0) if not.
1544  */
1545 static int
1546 trymmap(size_t filesize)
1547 {
1548         /*
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.
1556          *
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.
1560          *
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?
1563          */
1564         return (filesize > 4 * MAXBSIZE && filesize < 8 * 1024 * 1024);
1565 }