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