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