xref: /minix3/external/bsd/pkg_install/dist/add/perform.c (revision a824f5a1008ee67499d167f8c48e64aae26960ca)
1*a824f5a1SJean-Baptiste Boric /*	$NetBSD: perform.c,v 1.4 2013/04/20 15:29:22 wiz Exp $	*/
2*a824f5a1SJean-Baptiste Boric #if HAVE_CONFIG_H
3*a824f5a1SJean-Baptiste Boric #include "config.h"
4*a824f5a1SJean-Baptiste Boric #endif
5*a824f5a1SJean-Baptiste Boric #include <nbcompat.h>
6*a824f5a1SJean-Baptiste Boric #if HAVE_SYS_CDEFS_H
7*a824f5a1SJean-Baptiste Boric #include <sys/cdefs.h>
8*a824f5a1SJean-Baptiste Boric #endif
9*a824f5a1SJean-Baptiste Boric __RCSID("$NetBSD: perform.c,v 1.4 2013/04/20 15:29:22 wiz Exp $");
10*a824f5a1SJean-Baptiste Boric 
11*a824f5a1SJean-Baptiste Boric /*-
12*a824f5a1SJean-Baptiste Boric  * Copyright (c) 2003 Grant Beattie <grant@NetBSD.org>
13*a824f5a1SJean-Baptiste Boric  * Copyright (c) 2005 Dieter Baron <dillo@NetBSD.org>
14*a824f5a1SJean-Baptiste Boric  * Copyright (c) 2007 Roland Illig <rillig@NetBSD.org>
15*a824f5a1SJean-Baptiste Boric  * Copyright (c) 2008, 2009 Joerg Sonnenberger <joerg@NetBSD.org>
16*a824f5a1SJean-Baptiste Boric  * Copyright (c) 2010 Thomas Klausner <wiz@NetBSD.org>
17*a824f5a1SJean-Baptiste Boric  * All rights reserved.
18*a824f5a1SJean-Baptiste Boric  *
19*a824f5a1SJean-Baptiste Boric  * Redistribution and use in source and binary forms, with or without
20*a824f5a1SJean-Baptiste Boric  * modification, are permitted provided that the following conditions
21*a824f5a1SJean-Baptiste Boric  * are met:
22*a824f5a1SJean-Baptiste Boric  *
23*a824f5a1SJean-Baptiste Boric  * 1. Redistributions of source code must retain the above copyright
24*a824f5a1SJean-Baptiste Boric  *    notice, this list of conditions and the following disclaimer.
25*a824f5a1SJean-Baptiste Boric  * 2. Redistributions in binary form must reproduce the above copyright
26*a824f5a1SJean-Baptiste Boric  *    notice, this list of conditions and the following disclaimer in
27*a824f5a1SJean-Baptiste Boric  *    the documentation and/or other materials provided with the
28*a824f5a1SJean-Baptiste Boric  *    distribution.
29*a824f5a1SJean-Baptiste Boric  *
30*a824f5a1SJean-Baptiste Boric  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31*a824f5a1SJean-Baptiste Boric  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32*a824f5a1SJean-Baptiste Boric  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
33*a824f5a1SJean-Baptiste Boric  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
34*a824f5a1SJean-Baptiste Boric  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
35*a824f5a1SJean-Baptiste Boric  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
36*a824f5a1SJean-Baptiste Boric  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37*a824f5a1SJean-Baptiste Boric  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
38*a824f5a1SJean-Baptiste Boric  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
39*a824f5a1SJean-Baptiste Boric  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
40*a824f5a1SJean-Baptiste Boric  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41*a824f5a1SJean-Baptiste Boric  * SUCH DAMAGE.
42*a824f5a1SJean-Baptiste Boric  */
43*a824f5a1SJean-Baptiste Boric 
44*a824f5a1SJean-Baptiste Boric #include <sys/utsname.h>
45*a824f5a1SJean-Baptiste Boric #include <sys/stat.h>
46*a824f5a1SJean-Baptiste Boric #if HAVE_ERR_H
47*a824f5a1SJean-Baptiste Boric #include <err.h>
48*a824f5a1SJean-Baptiste Boric #endif
49*a824f5a1SJean-Baptiste Boric #include <errno.h>
50*a824f5a1SJean-Baptiste Boric #if HAVE_FCNTL_H
51*a824f5a1SJean-Baptiste Boric #include <fcntl.h>
52*a824f5a1SJean-Baptiste Boric #endif
53*a824f5a1SJean-Baptiste Boric #include <stdlib.h>
54*a824f5a1SJean-Baptiste Boric #include <string.h>
55*a824f5a1SJean-Baptiste Boric #include <unistd.h>
56*a824f5a1SJean-Baptiste Boric 
57*a824f5a1SJean-Baptiste Boric #include <archive.h>
58*a824f5a1SJean-Baptiste Boric #include <archive_entry.h>
59*a824f5a1SJean-Baptiste Boric 
60*a824f5a1SJean-Baptiste Boric #include "lib.h"
61*a824f5a1SJean-Baptiste Boric #include "add.h"
62*a824f5a1SJean-Baptiste Boric #include "version.h"
63*a824f5a1SJean-Baptiste Boric 
64*a824f5a1SJean-Baptiste Boric struct pkg_meta {
65*a824f5a1SJean-Baptiste Boric 	char *meta_contents;
66*a824f5a1SJean-Baptiste Boric 	char *meta_comment;
67*a824f5a1SJean-Baptiste Boric 	char *meta_desc;
68*a824f5a1SJean-Baptiste Boric 	char *meta_mtree;
69*a824f5a1SJean-Baptiste Boric 	char *meta_build_version;
70*a824f5a1SJean-Baptiste Boric 	char *meta_build_info;
71*a824f5a1SJean-Baptiste Boric 	char *meta_size_pkg;
72*a824f5a1SJean-Baptiste Boric 	char *meta_size_all;
73*a824f5a1SJean-Baptiste Boric 	char *meta_required_by;
74*a824f5a1SJean-Baptiste Boric 	char *meta_display;
75*a824f5a1SJean-Baptiste Boric 	char *meta_install;
76*a824f5a1SJean-Baptiste Boric 	char *meta_deinstall;
77*a824f5a1SJean-Baptiste Boric 	char *meta_preserve;
78*a824f5a1SJean-Baptiste Boric 	char *meta_views;
79*a824f5a1SJean-Baptiste Boric 	char *meta_installed_info;
80*a824f5a1SJean-Baptiste Boric };
81*a824f5a1SJean-Baptiste Boric 
82*a824f5a1SJean-Baptiste Boric struct pkg_task {
83*a824f5a1SJean-Baptiste Boric 	char *pkgname;
84*a824f5a1SJean-Baptiste Boric 
85*a824f5a1SJean-Baptiste Boric 	const char *prefix;
86*a824f5a1SJean-Baptiste Boric 	char *install_prefix;
87*a824f5a1SJean-Baptiste Boric 
88*a824f5a1SJean-Baptiste Boric 	char *logdir;
89*a824f5a1SJean-Baptiste Boric 	char *install_logdir;
90*a824f5a1SJean-Baptiste Boric 	char *install_logdir_real;
91*a824f5a1SJean-Baptiste Boric 	char *other_version;
92*a824f5a1SJean-Baptiste Boric 
93*a824f5a1SJean-Baptiste Boric 	package_t plist;
94*a824f5a1SJean-Baptiste Boric 
95*a824f5a1SJean-Baptiste Boric 	struct pkg_meta meta_data;
96*a824f5a1SJean-Baptiste Boric 
97*a824f5a1SJean-Baptiste Boric 	struct archive *archive;
98*a824f5a1SJean-Baptiste Boric 	struct archive_entry *entry;
99*a824f5a1SJean-Baptiste Boric 
100*a824f5a1SJean-Baptiste Boric 	char *buildinfo[BI_ENUM_COUNT];
101*a824f5a1SJean-Baptiste Boric 
102*a824f5a1SJean-Baptiste Boric 	size_t dep_length, dep_allocated;
103*a824f5a1SJean-Baptiste Boric 	char **dependencies;
104*a824f5a1SJean-Baptiste Boric };
105*a824f5a1SJean-Baptiste Boric 
106*a824f5a1SJean-Baptiste Boric static const struct pkg_meta_desc {
107*a824f5a1SJean-Baptiste Boric 	size_t entry_offset;
108*a824f5a1SJean-Baptiste Boric 	const char *entry_filename;
109*a824f5a1SJean-Baptiste Boric 	int required_file;
110*a824f5a1SJean-Baptiste Boric 	mode_t perm;
111*a824f5a1SJean-Baptiste Boric } pkg_meta_descriptors[] = {
112*a824f5a1SJean-Baptiste Boric 	{ offsetof(struct pkg_meta, meta_contents), CONTENTS_FNAME, 1, 0644 },
113*a824f5a1SJean-Baptiste Boric 	{ offsetof(struct pkg_meta, meta_comment), COMMENT_FNAME, 1, 0444},
114*a824f5a1SJean-Baptiste Boric 	{ offsetof(struct pkg_meta, meta_desc), DESC_FNAME, 1, 0444},
115*a824f5a1SJean-Baptiste Boric 	{ offsetof(struct pkg_meta, meta_install), INSTALL_FNAME, 0, 0555 },
116*a824f5a1SJean-Baptiste Boric 	{ offsetof(struct pkg_meta, meta_deinstall), DEINSTALL_FNAME, 0, 0555 },
117*a824f5a1SJean-Baptiste Boric 	{ offsetof(struct pkg_meta, meta_display), DISPLAY_FNAME, 0, 0444 },
118*a824f5a1SJean-Baptiste Boric 	{ offsetof(struct pkg_meta, meta_mtree), MTREE_FNAME, 0, 0444 },
119*a824f5a1SJean-Baptiste Boric 	{ offsetof(struct pkg_meta, meta_build_version), BUILD_VERSION_FNAME, 0, 0444 },
120*a824f5a1SJean-Baptiste Boric 	{ offsetof(struct pkg_meta, meta_build_info), BUILD_INFO_FNAME, 0, 0444 },
121*a824f5a1SJean-Baptiste Boric 	{ offsetof(struct pkg_meta, meta_size_pkg), SIZE_PKG_FNAME, 0, 0444 },
122*a824f5a1SJean-Baptiste Boric 	{ offsetof(struct pkg_meta, meta_size_all), SIZE_ALL_FNAME, 0, 0444 },
123*a824f5a1SJean-Baptiste Boric 	{ offsetof(struct pkg_meta, meta_preserve), PRESERVE_FNAME, 0, 0444 },
124*a824f5a1SJean-Baptiste Boric 	{ offsetof(struct pkg_meta, meta_views), VIEWS_FNAME, 0, 0444 },
125*a824f5a1SJean-Baptiste Boric 	{ offsetof(struct pkg_meta, meta_required_by), REQUIRED_BY_FNAME, 0, 0644 },
126*a824f5a1SJean-Baptiste Boric 	{ offsetof(struct pkg_meta, meta_installed_info), INSTALLED_INFO_FNAME, 0, 0644 },
127*a824f5a1SJean-Baptiste Boric 	{ 0, NULL, 0, 0 },
128*a824f5a1SJean-Baptiste Boric };
129*a824f5a1SJean-Baptiste Boric 
130*a824f5a1SJean-Baptiste Boric static int pkg_do(const char *, int, int);
131*a824f5a1SJean-Baptiste Boric 
132*a824f5a1SJean-Baptiste Boric static int
end_of_version(const char * opsys,const char * version_end)133*a824f5a1SJean-Baptiste Boric end_of_version(const char *opsys, const char *version_end)
134*a824f5a1SJean-Baptiste Boric {
135*a824f5a1SJean-Baptiste Boric     if (*version_end == '\0')
136*a824f5a1SJean-Baptiste Boric 	return 1;
137*a824f5a1SJean-Baptiste Boric 
138*a824f5a1SJean-Baptiste Boric     if (strcmp(opsys, "NetBSD") == 0) {
139*a824f5a1SJean-Baptiste Boric 	if (strncmp(version_end, "_ALPHA", 6) == 0
140*a824f5a1SJean-Baptiste Boric 	    || strncmp(version_end, "_BETA", 5) == 0
141*a824f5a1SJean-Baptiste Boric 	    || strncmp(version_end, "_RC", 3) == 0
142*a824f5a1SJean-Baptiste Boric 	    || strncmp(version_end, "_STABLE", 7) == 0
143*a824f5a1SJean-Baptiste Boric 	    || strncmp(version_end, "_PATCH", 6) == 0)
144*a824f5a1SJean-Baptiste Boric 	    return 1;
145*a824f5a1SJean-Baptiste Boric     }
146*a824f5a1SJean-Baptiste Boric 
147*a824f5a1SJean-Baptiste Boric     return 0;
148*a824f5a1SJean-Baptiste Boric }
149*a824f5a1SJean-Baptiste Boric 
150*a824f5a1SJean-Baptiste Boric static int
compatible_platform(const char * opsys,const char * host,const char * package)151*a824f5a1SJean-Baptiste Boric compatible_platform(const char *opsys, const char *host, const char *package)
152*a824f5a1SJean-Baptiste Boric {
153*a824f5a1SJean-Baptiste Boric     int i = 0;
154*a824f5a1SJean-Baptiste Boric 
155*a824f5a1SJean-Baptiste Boric     /* returns 1 if host and package operating system match */
156*a824f5a1SJean-Baptiste Boric     if (strcmp(host, package) == 0)
157*a824f5a1SJean-Baptiste Boric 	return 1;
158*a824f5a1SJean-Baptiste Boric 
159*a824f5a1SJean-Baptiste Boric     /* accept, if host version is a minor release of package version */
160*a824f5a1SJean-Baptiste Boric     if (strncmp(host, package, strlen(package)) == 0)
161*a824f5a1SJean-Baptiste Boric 	return 1;
162*a824f5a1SJean-Baptiste Boric 
163*a824f5a1SJean-Baptiste Boric     /* find offset of first difference */
164*a824f5a1SJean-Baptiste Boric     for (i=0; (host[i] != '\0') && (host[i] == package[i]);)
165*a824f5a1SJean-Baptiste Boric 	i++;
166*a824f5a1SJean-Baptiste Boric 
167*a824f5a1SJean-Baptiste Boric     if (end_of_version(opsys, host+i) && end_of_version(opsys, package+i))
168*a824f5a1SJean-Baptiste Boric 	return 1;
169*a824f5a1SJean-Baptiste Boric 
170*a824f5a1SJean-Baptiste Boric     return 0;
171*a824f5a1SJean-Baptiste Boric }
172*a824f5a1SJean-Baptiste Boric 
173*a824f5a1SJean-Baptiste Boric static int
mkdir_p(const char * path)174*a824f5a1SJean-Baptiste Boric mkdir_p(const char *path)
175*a824f5a1SJean-Baptiste Boric {
176*a824f5a1SJean-Baptiste Boric 	char *p, *cur_end;
177*a824f5a1SJean-Baptiste Boric 	int done, saved_errno;
178*a824f5a1SJean-Baptiste Boric 	struct stat sb;
179*a824f5a1SJean-Baptiste Boric 
180*a824f5a1SJean-Baptiste Boric 	/*
181*a824f5a1SJean-Baptiste Boric 	 * Handle the easy case of direct success or
182*a824f5a1SJean-Baptiste Boric 	 * pre-existing directory first.
183*a824f5a1SJean-Baptiste Boric 	 */
184*a824f5a1SJean-Baptiste Boric 	if (mkdir(path, 0777) == 0)
185*a824f5a1SJean-Baptiste Boric 		return 0;
186*a824f5a1SJean-Baptiste Boric 	if (stat(path, &sb) == 0) {
187*a824f5a1SJean-Baptiste Boric 		if (S_ISDIR(sb.st_mode))
188*a824f5a1SJean-Baptiste Boric 			return 0;
189*a824f5a1SJean-Baptiste Boric 		errno = ENOTDIR;
190*a824f5a1SJean-Baptiste Boric 		return -1;
191*a824f5a1SJean-Baptiste Boric 	}
192*a824f5a1SJean-Baptiste Boric 
193*a824f5a1SJean-Baptiste Boric 	cur_end = p = xstrdup(path);
194*a824f5a1SJean-Baptiste Boric 
195*a824f5a1SJean-Baptiste Boric 	for (;;) {
196*a824f5a1SJean-Baptiste Boric 		/*
197*a824f5a1SJean-Baptiste Boric 		 * First skip leading slashes either from / or
198*a824f5a1SJean-Baptiste Boric 		 * from the last iteration.
199*a824f5a1SJean-Baptiste Boric 		 */
200*a824f5a1SJean-Baptiste Boric 		cur_end += strspn(cur_end, "/");
201*a824f5a1SJean-Baptiste Boric 		/* Find end of actual directory name. */
202*a824f5a1SJean-Baptiste Boric 		cur_end += strcspn(cur_end, "/");
203*a824f5a1SJean-Baptiste Boric 
204*a824f5a1SJean-Baptiste Boric 		/*
205*a824f5a1SJean-Baptiste Boric 		 * Remember if this is the last component and
206*a824f5a1SJean-Baptiste Boric 		 * overwrite / if needed.
207*a824f5a1SJean-Baptiste Boric 		 */
208*a824f5a1SJean-Baptiste Boric 		done = (*cur_end == '\0');
209*a824f5a1SJean-Baptiste Boric 		*cur_end = '\0';
210*a824f5a1SJean-Baptiste Boric 
211*a824f5a1SJean-Baptiste Boric 		if (mkdir(p, 0777) == -1) {
212*a824f5a1SJean-Baptiste Boric 			saved_errno = errno;
213*a824f5a1SJean-Baptiste Boric 			if (stat(p, &sb) == 0) {
214*a824f5a1SJean-Baptiste Boric 				if (S_ISDIR(sb.st_mode))
215*a824f5a1SJean-Baptiste Boric 					goto pass;
216*a824f5a1SJean-Baptiste Boric 				errno = ENOTDIR;
217*a824f5a1SJean-Baptiste Boric 			} else {
218*a824f5a1SJean-Baptiste Boric 				errno = saved_errno;
219*a824f5a1SJean-Baptiste Boric 			}
220*a824f5a1SJean-Baptiste Boric 			free(p);
221*a824f5a1SJean-Baptiste Boric 			return -1;
222*a824f5a1SJean-Baptiste Boric 		}
223*a824f5a1SJean-Baptiste Boric pass:
224*a824f5a1SJean-Baptiste Boric 		if (done)
225*a824f5a1SJean-Baptiste Boric 			break;
226*a824f5a1SJean-Baptiste Boric 		*cur_end = '/';
227*a824f5a1SJean-Baptiste Boric 	}
228*a824f5a1SJean-Baptiste Boric 
229*a824f5a1SJean-Baptiste Boric 	free(p);
230*a824f5a1SJean-Baptiste Boric 	return 0;
231*a824f5a1SJean-Baptiste Boric }
232*a824f5a1SJean-Baptiste Boric 
233*a824f5a1SJean-Baptiste Boric /*
234*a824f5a1SJean-Baptiste Boric  * Read meta data from archive.
235*a824f5a1SJean-Baptiste Boric  * Bail out if a required entry is missing or entries are in the wrong order.
236*a824f5a1SJean-Baptiste Boric  */
237*a824f5a1SJean-Baptiste Boric static int
read_meta_data(struct pkg_task * pkg)238*a824f5a1SJean-Baptiste Boric read_meta_data(struct pkg_task *pkg)
239*a824f5a1SJean-Baptiste Boric {
240*a824f5a1SJean-Baptiste Boric 	const struct pkg_meta_desc *descr, *last_descr;
241*a824f5a1SJean-Baptiste Boric 	const char *fname;
242*a824f5a1SJean-Baptiste Boric 	char **target;
243*a824f5a1SJean-Baptiste Boric 	int64_t size;
244*a824f5a1SJean-Baptiste Boric 	int r, found_required;
245*a824f5a1SJean-Baptiste Boric 
246*a824f5a1SJean-Baptiste Boric 	found_required = 0;
247*a824f5a1SJean-Baptiste Boric 
248*a824f5a1SJean-Baptiste Boric 	r = ARCHIVE_OK;
249*a824f5a1SJean-Baptiste Boric 	last_descr = 0;
250*a824f5a1SJean-Baptiste Boric 
251*a824f5a1SJean-Baptiste Boric 	if (pkg->entry != NULL)
252*a824f5a1SJean-Baptiste Boric 		goto skip_header;
253*a824f5a1SJean-Baptiste Boric 
254*a824f5a1SJean-Baptiste Boric 	for (;;) {
255*a824f5a1SJean-Baptiste Boric 		r = archive_read_next_header(pkg->archive, &pkg->entry);
256*a824f5a1SJean-Baptiste Boric 		if (r != ARCHIVE_OK)
257*a824f5a1SJean-Baptiste Boric 				break;
258*a824f5a1SJean-Baptiste Boric skip_header:
259*a824f5a1SJean-Baptiste Boric 		fname = archive_entry_pathname(pkg->entry);
260*a824f5a1SJean-Baptiste Boric 
261*a824f5a1SJean-Baptiste Boric 		for (descr = pkg_meta_descriptors; descr->entry_filename;
262*a824f5a1SJean-Baptiste Boric 		     ++descr) {
263*a824f5a1SJean-Baptiste Boric 			if (strcmp(descr->entry_filename, fname) == 0)
264*a824f5a1SJean-Baptiste Boric 				break;
265*a824f5a1SJean-Baptiste Boric 		}
266*a824f5a1SJean-Baptiste Boric 		if (descr->entry_filename == NULL)
267*a824f5a1SJean-Baptiste Boric 			break;
268*a824f5a1SJean-Baptiste Boric 
269*a824f5a1SJean-Baptiste Boric 		if (descr->required_file)
270*a824f5a1SJean-Baptiste Boric 			++found_required;
271*a824f5a1SJean-Baptiste Boric 
272*a824f5a1SJean-Baptiste Boric 		target = (char **)((char *)&pkg->meta_data +
273*a824f5a1SJean-Baptiste Boric 		    descr->entry_offset);
274*a824f5a1SJean-Baptiste Boric 		if (*target) {
275*a824f5a1SJean-Baptiste Boric 			warnx("duplicate entry, package corrupt");
276*a824f5a1SJean-Baptiste Boric 			return -1;
277*a824f5a1SJean-Baptiste Boric 		}
278*a824f5a1SJean-Baptiste Boric 		if (descr < last_descr) {
279*a824f5a1SJean-Baptiste Boric 			warnx("misordered package");
280*a824f5a1SJean-Baptiste Boric 			return -1;
281*a824f5a1SJean-Baptiste Boric 		}
282*a824f5a1SJean-Baptiste Boric 		last_descr = descr;
283*a824f5a1SJean-Baptiste Boric 
284*a824f5a1SJean-Baptiste Boric 		size = archive_entry_size(pkg->entry);
285*a824f5a1SJean-Baptiste Boric 		if (size > SSIZE_MAX - 1) {
286*a824f5a1SJean-Baptiste Boric 			warnx("package meta data too large to process");
287*a824f5a1SJean-Baptiste Boric 			return -1;
288*a824f5a1SJean-Baptiste Boric 		}
289*a824f5a1SJean-Baptiste Boric 		*target = xmalloc(size + 1);
290*a824f5a1SJean-Baptiste Boric 		if (archive_read_data(pkg->archive, *target, size) != size) {
291*a824f5a1SJean-Baptiste Boric 			warnx("cannot read package meta data");
292*a824f5a1SJean-Baptiste Boric 			return -1;
293*a824f5a1SJean-Baptiste Boric 		}
294*a824f5a1SJean-Baptiste Boric 		(*target)[size] = '\0';
295*a824f5a1SJean-Baptiste Boric 	}
296*a824f5a1SJean-Baptiste Boric 
297*a824f5a1SJean-Baptiste Boric 	if (r != ARCHIVE_OK)
298*a824f5a1SJean-Baptiste Boric 		pkg->entry = NULL;
299*a824f5a1SJean-Baptiste Boric 	if (r == ARCHIVE_EOF)
300*a824f5a1SJean-Baptiste Boric 		r = ARCHIVE_OK;
301*a824f5a1SJean-Baptiste Boric 
302*a824f5a1SJean-Baptiste Boric 	for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) {
303*a824f5a1SJean-Baptiste Boric 		if (descr->required_file)
304*a824f5a1SJean-Baptiste Boric 			--found_required;
305*a824f5a1SJean-Baptiste Boric 	}
306*a824f5a1SJean-Baptiste Boric 
307*a824f5a1SJean-Baptiste Boric 	return !found_required && r == ARCHIVE_OK ? 0 : -1;
308*a824f5a1SJean-Baptiste Boric }
309*a824f5a1SJean-Baptiste Boric 
310*a824f5a1SJean-Baptiste Boric /*
311*a824f5a1SJean-Baptiste Boric  * Free meta data.
312*a824f5a1SJean-Baptiste Boric  */
313*a824f5a1SJean-Baptiste Boric static void
free_meta_data(struct pkg_task * pkg)314*a824f5a1SJean-Baptiste Boric free_meta_data(struct pkg_task *pkg)
315*a824f5a1SJean-Baptiste Boric {
316*a824f5a1SJean-Baptiste Boric 	const struct pkg_meta_desc *descr;
317*a824f5a1SJean-Baptiste Boric 	char **target;
318*a824f5a1SJean-Baptiste Boric 
319*a824f5a1SJean-Baptiste Boric 	for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) {
320*a824f5a1SJean-Baptiste Boric 		target = (char **)((char *)&pkg->meta_data +
321*a824f5a1SJean-Baptiste Boric 		    descr->entry_offset);
322*a824f5a1SJean-Baptiste Boric 		free(*target);
323*a824f5a1SJean-Baptiste Boric 		*target = NULL;
324*a824f5a1SJean-Baptiste Boric 	}
325*a824f5a1SJean-Baptiste Boric }
326*a824f5a1SJean-Baptiste Boric 
327*a824f5a1SJean-Baptiste Boric /*
328*a824f5a1SJean-Baptiste Boric  * Parse PLIST and populate pkg.
329*a824f5a1SJean-Baptiste Boric  */
330*a824f5a1SJean-Baptiste Boric static int
pkg_parse_plist(struct pkg_task * pkg)331*a824f5a1SJean-Baptiste Boric pkg_parse_plist(struct pkg_task *pkg)
332*a824f5a1SJean-Baptiste Boric {
333*a824f5a1SJean-Baptiste Boric 	plist_t *p;
334*a824f5a1SJean-Baptiste Boric 
335*a824f5a1SJean-Baptiste Boric 	parse_plist(&pkg->plist, pkg->meta_data.meta_contents);
336*a824f5a1SJean-Baptiste Boric 	if ((p = find_plist(&pkg->plist, PLIST_NAME)) == NULL) {
337*a824f5a1SJean-Baptiste Boric 		warnx("Invalid PLIST: missing @name");
338*a824f5a1SJean-Baptiste Boric 		return -1;
339*a824f5a1SJean-Baptiste Boric 	}
340*a824f5a1SJean-Baptiste Boric 	if (pkg->pkgname == NULL)
341*a824f5a1SJean-Baptiste Boric 		pkg->pkgname = xstrdup(p->name);
342*a824f5a1SJean-Baptiste Boric 	else if (strcmp(pkg->pkgname, p->name) != 0) {
343*a824f5a1SJean-Baptiste Boric 		warnx("Signature and PLIST differ on package name");
344*a824f5a1SJean-Baptiste Boric 		return -1;
345*a824f5a1SJean-Baptiste Boric 	}
346*a824f5a1SJean-Baptiste Boric 	if ((p = find_plist(&pkg->plist, PLIST_CWD)) == NULL) {
347*a824f5a1SJean-Baptiste Boric 		warnx("Invalid PLIST: missing @cwd");
348*a824f5a1SJean-Baptiste Boric 		return -1;
349*a824f5a1SJean-Baptiste Boric 	}
350*a824f5a1SJean-Baptiste Boric 
351*a824f5a1SJean-Baptiste Boric 	if (Prefix != NULL &&
352*a824f5a1SJean-Baptiste Boric 	    strcmp(p->name, Prefix) != 0) {
353*a824f5a1SJean-Baptiste Boric 		size_t len;
354*a824f5a1SJean-Baptiste Boric 
355*a824f5a1SJean-Baptiste Boric 		delete_plist(&pkg->plist, FALSE, PLIST_CWD, NULL);
356*a824f5a1SJean-Baptiste Boric 		add_plist_top(&pkg->plist, PLIST_CWD, Prefix);
357*a824f5a1SJean-Baptiste Boric 		free(pkg->meta_data.meta_contents);
358*a824f5a1SJean-Baptiste Boric 		stringify_plist(&pkg->plist, &pkg->meta_data.meta_contents, &len,
359*a824f5a1SJean-Baptiste Boric 		    Prefix);
360*a824f5a1SJean-Baptiste Boric 		pkg->prefix = Prefix;
361*a824f5a1SJean-Baptiste Boric 	} else
362*a824f5a1SJean-Baptiste Boric 		pkg->prefix = p->name;
363*a824f5a1SJean-Baptiste Boric 
364*a824f5a1SJean-Baptiste Boric 	if (Destdir != NULL)
365*a824f5a1SJean-Baptiste Boric 		pkg->install_prefix = xasprintf("%s/%s", Destdir, pkg->prefix);
366*a824f5a1SJean-Baptiste Boric 	else
367*a824f5a1SJean-Baptiste Boric 		pkg->install_prefix = xstrdup(pkg->prefix);
368*a824f5a1SJean-Baptiste Boric 
369*a824f5a1SJean-Baptiste Boric 	return 0;
370*a824f5a1SJean-Baptiste Boric }
371*a824f5a1SJean-Baptiste Boric 
372*a824f5a1SJean-Baptiste Boric /*
373*a824f5a1SJean-Baptiste Boric  * Helper function to extract value from a string of the
374*a824f5a1SJean-Baptiste Boric  * form key=value ending at eol.
375*a824f5a1SJean-Baptiste Boric  */
376*a824f5a1SJean-Baptiste Boric static char *
dup_value(const char * line,const char * eol)377*a824f5a1SJean-Baptiste Boric dup_value(const char *line, const char *eol)
378*a824f5a1SJean-Baptiste Boric {
379*a824f5a1SJean-Baptiste Boric 	const char *key;
380*a824f5a1SJean-Baptiste Boric 	char *val;
381*a824f5a1SJean-Baptiste Boric 
382*a824f5a1SJean-Baptiste Boric 	key = strchr(line, '=');
383*a824f5a1SJean-Baptiste Boric 	val = xmalloc(eol - key);
384*a824f5a1SJean-Baptiste Boric 	memcpy(val, key + 1, eol - key - 1);
385*a824f5a1SJean-Baptiste Boric 	val[eol - key - 1] = '\0';
386*a824f5a1SJean-Baptiste Boric 	return val;
387*a824f5a1SJean-Baptiste Boric }
388*a824f5a1SJean-Baptiste Boric 
389*a824f5a1SJean-Baptiste Boric static int
check_already_installed(struct pkg_task * pkg)390*a824f5a1SJean-Baptiste Boric check_already_installed(struct pkg_task *pkg)
391*a824f5a1SJean-Baptiste Boric {
392*a824f5a1SJean-Baptiste Boric 	char *filename;
393*a824f5a1SJean-Baptiste Boric 	int fd;
394*a824f5a1SJean-Baptiste Boric 
395*a824f5a1SJean-Baptiste Boric 	filename = pkgdb_pkg_file(pkg->pkgname, CONTENTS_FNAME);
396*a824f5a1SJean-Baptiste Boric 	fd = open(filename, O_RDONLY);
397*a824f5a1SJean-Baptiste Boric 	free(filename);
398*a824f5a1SJean-Baptiste Boric 	if (fd == -1)
399*a824f5a1SJean-Baptiste Boric 		return 1;
400*a824f5a1SJean-Baptiste Boric 	close(fd);
401*a824f5a1SJean-Baptiste Boric 
402*a824f5a1SJean-Baptiste Boric 	if (ReplaceSame) {
403*a824f5a1SJean-Baptiste Boric 		struct stat sb;
404*a824f5a1SJean-Baptiste Boric 
405*a824f5a1SJean-Baptiste Boric 		pkg->install_logdir_real = pkg->install_logdir;
406*a824f5a1SJean-Baptiste Boric 		pkg->install_logdir = xasprintf("%s.xxxxxx", pkg->install_logdir);
407*a824f5a1SJean-Baptiste Boric 		if (stat(pkg->install_logdir, &sb) == 0) {
408*a824f5a1SJean-Baptiste Boric 			warnx("package `%s' already has a temporary update "
409*a824f5a1SJean-Baptiste Boric 			    "directory `%s', remove it manually",
410*a824f5a1SJean-Baptiste Boric 			    pkg->pkgname, pkg->install_logdir);
411*a824f5a1SJean-Baptiste Boric 			return -1;
412*a824f5a1SJean-Baptiste Boric 		}
413*a824f5a1SJean-Baptiste Boric 		return 1;
414*a824f5a1SJean-Baptiste Boric 	}
415*a824f5a1SJean-Baptiste Boric 
416*a824f5a1SJean-Baptiste Boric 	if (Force)
417*a824f5a1SJean-Baptiste Boric 		return 1;
418*a824f5a1SJean-Baptiste Boric 
419*a824f5a1SJean-Baptiste Boric 	/* We can only arrive here for explicitly requested packages. */
420*a824f5a1SJean-Baptiste Boric 	if (!Automatic && is_automatic_installed(pkg->pkgname)) {
421*a824f5a1SJean-Baptiste Boric 		if (Fake ||
422*a824f5a1SJean-Baptiste Boric 		    mark_as_automatic_installed(pkg->pkgname, 0) == 0)
423*a824f5a1SJean-Baptiste Boric 			warnx("package `%s' was already installed as "
424*a824f5a1SJean-Baptiste Boric 			      "dependency, now marked as installed "
425*a824f5a1SJean-Baptiste Boric 			      "manually", pkg->pkgname);
426*a824f5a1SJean-Baptiste Boric 	} else {
427*a824f5a1SJean-Baptiste Boric 		warnx("package `%s' already recorded as installed",
428*a824f5a1SJean-Baptiste Boric 		      pkg->pkgname);
429*a824f5a1SJean-Baptiste Boric 	}
430*a824f5a1SJean-Baptiste Boric 	return 0;
431*a824f5a1SJean-Baptiste Boric 
432*a824f5a1SJean-Baptiste Boric }
433*a824f5a1SJean-Baptiste Boric 
434*a824f5a1SJean-Baptiste Boric static int
check_other_installed(struct pkg_task * pkg)435*a824f5a1SJean-Baptiste Boric check_other_installed(struct pkg_task *pkg)
436*a824f5a1SJean-Baptiste Boric {
437*a824f5a1SJean-Baptiste Boric 	FILE *f, *f_pkg;
438*a824f5a1SJean-Baptiste Boric 	size_t len;
439*a824f5a1SJean-Baptiste Boric 	char *pkgbase, *iter, *filename;
440*a824f5a1SJean-Baptiste Boric 	package_t plist;
441*a824f5a1SJean-Baptiste Boric 	plist_t *p;
442*a824f5a1SJean-Baptiste Boric 	int status;
443*a824f5a1SJean-Baptiste Boric 
444*a824f5a1SJean-Baptiste Boric 	if (pkg->install_logdir_real) {
445*a824f5a1SJean-Baptiste Boric 		pkg->other_version = xstrdup(pkg->pkgname);
446*a824f5a1SJean-Baptiste Boric 		return 0;
447*a824f5a1SJean-Baptiste Boric 	}
448*a824f5a1SJean-Baptiste Boric 
449*a824f5a1SJean-Baptiste Boric 	pkgbase = xstrdup(pkg->pkgname);
450*a824f5a1SJean-Baptiste Boric 
451*a824f5a1SJean-Baptiste Boric 	if ((iter = strrchr(pkgbase, '-')) == NULL) {
452*a824f5a1SJean-Baptiste Boric 		free(pkgbase);
453*a824f5a1SJean-Baptiste Boric 		warnx("Invalid package name %s", pkg->pkgname);
454*a824f5a1SJean-Baptiste Boric 		return -1;
455*a824f5a1SJean-Baptiste Boric 	}
456*a824f5a1SJean-Baptiste Boric 	*iter = '\0';
457*a824f5a1SJean-Baptiste Boric 	pkg->other_version = find_best_matching_installed_pkg(pkgbase);
458*a824f5a1SJean-Baptiste Boric 	free(pkgbase);
459*a824f5a1SJean-Baptiste Boric 	if (pkg->other_version == NULL)
460*a824f5a1SJean-Baptiste Boric 		return 0;
461*a824f5a1SJean-Baptiste Boric 
462*a824f5a1SJean-Baptiste Boric 	if (!Replace) {
463*a824f5a1SJean-Baptiste Boric 		/* XXX This is redundant to the implicit conflict check. */
464*a824f5a1SJean-Baptiste Boric 		warnx("A different version of %s is already installed: %s",
465*a824f5a1SJean-Baptiste Boric 		    pkg->pkgname, pkg->other_version);
466*a824f5a1SJean-Baptiste Boric 		return -1;
467*a824f5a1SJean-Baptiste Boric 	}
468*a824f5a1SJean-Baptiste Boric 
469*a824f5a1SJean-Baptiste Boric 	filename = pkgdb_pkg_file(pkg->other_version, REQUIRED_BY_FNAME);
470*a824f5a1SJean-Baptiste Boric 	errno = 0;
471*a824f5a1SJean-Baptiste Boric 	f = fopen(filename, "r");
472*a824f5a1SJean-Baptiste Boric 	free(filename);
473*a824f5a1SJean-Baptiste Boric 	if (f == NULL) {
474*a824f5a1SJean-Baptiste Boric 		if (errno == ENOENT) {
475*a824f5a1SJean-Baptiste Boric 			/* No packages depend on this, so everything is well. */
476*a824f5a1SJean-Baptiste Boric 			return 0;
477*a824f5a1SJean-Baptiste Boric 		}
478*a824f5a1SJean-Baptiste Boric 		warnx("Can't open +REQUIRED_BY of %s", pkg->other_version);
479*a824f5a1SJean-Baptiste Boric 		return -1;
480*a824f5a1SJean-Baptiste Boric 	}
481*a824f5a1SJean-Baptiste Boric 
482*a824f5a1SJean-Baptiste Boric 	status = 0;
483*a824f5a1SJean-Baptiste Boric 
484*a824f5a1SJean-Baptiste Boric 	while ((iter = fgetln(f, &len)) != NULL) {
485*a824f5a1SJean-Baptiste Boric 		if (iter[len - 1] == '\n')
486*a824f5a1SJean-Baptiste Boric 			iter[len - 1] = '\0';
487*a824f5a1SJean-Baptiste Boric 		filename = pkgdb_pkg_file(iter, CONTENTS_FNAME);
488*a824f5a1SJean-Baptiste Boric 		if ((f_pkg = fopen(filename, "r")) == NULL) {
489*a824f5a1SJean-Baptiste Boric 			warnx("Can't open +CONTENTS of depending package %s",
490*a824f5a1SJean-Baptiste Boric 			    iter);
491*a824f5a1SJean-Baptiste Boric 			fclose(f);
492*a824f5a1SJean-Baptiste Boric 			return -1;
493*a824f5a1SJean-Baptiste Boric 		}
494*a824f5a1SJean-Baptiste Boric 		read_plist(&plist, f_pkg);
495*a824f5a1SJean-Baptiste Boric 		fclose(f_pkg);
496*a824f5a1SJean-Baptiste Boric 		for (p = plist.head; p != NULL; p = p->next) {
497*a824f5a1SJean-Baptiste Boric 			if (p->type == PLIST_IGNORE) {
498*a824f5a1SJean-Baptiste Boric 				p = p->next;
499*a824f5a1SJean-Baptiste Boric 				continue;
500*a824f5a1SJean-Baptiste Boric 			} else if (p->type != PLIST_PKGDEP)
501*a824f5a1SJean-Baptiste Boric 				continue;
502*a824f5a1SJean-Baptiste Boric 			/*
503*a824f5a1SJean-Baptiste Boric 			 * XXX This is stricter than necessary.
504*a824f5a1SJean-Baptiste Boric 			 * XXX One pattern might be fulfilled by
505*a824f5a1SJean-Baptiste Boric 			 * XXX a different package and still need this
506*a824f5a1SJean-Baptiste Boric 			 * XXX one for a different pattern.
507*a824f5a1SJean-Baptiste Boric 			 */
508*a824f5a1SJean-Baptiste Boric 			if (pkg_match(p->name, pkg->other_version) == 0)
509*a824f5a1SJean-Baptiste Boric 				continue;
510*a824f5a1SJean-Baptiste Boric 			if (pkg_match(p->name, pkg->pkgname) == 1)
511*a824f5a1SJean-Baptiste Boric 				continue; /* Both match, ok. */
512*a824f5a1SJean-Baptiste Boric 			warnx("Dependency of %s fulfilled by %s, but not by %s",
513*a824f5a1SJean-Baptiste Boric 			    iter, pkg->other_version, pkg->pkgname);
514*a824f5a1SJean-Baptiste Boric 			if (!ForceDepending)
515*a824f5a1SJean-Baptiste Boric 				status = -1;
516*a824f5a1SJean-Baptiste Boric 			break;
517*a824f5a1SJean-Baptiste Boric 		}
518*a824f5a1SJean-Baptiste Boric 		free_plist(&plist);
519*a824f5a1SJean-Baptiste Boric 	}
520*a824f5a1SJean-Baptiste Boric 
521*a824f5a1SJean-Baptiste Boric 	fclose(f);
522*a824f5a1SJean-Baptiste Boric 
523*a824f5a1SJean-Baptiste Boric 	return status;
524*a824f5a1SJean-Baptiste Boric }
525*a824f5a1SJean-Baptiste Boric 
526*a824f5a1SJean-Baptiste Boric /*
527*a824f5a1SJean-Baptiste Boric  * Read package build information from meta data.
528*a824f5a1SJean-Baptiste Boric  */
529*a824f5a1SJean-Baptiste Boric static int
read_buildinfo(struct pkg_task * pkg)530*a824f5a1SJean-Baptiste Boric read_buildinfo(struct pkg_task *pkg)
531*a824f5a1SJean-Baptiste Boric {
532*a824f5a1SJean-Baptiste Boric 	const char *data, *eol, *next_line;
533*a824f5a1SJean-Baptiste Boric 
534*a824f5a1SJean-Baptiste Boric 	data = pkg->meta_data.meta_build_info;
535*a824f5a1SJean-Baptiste Boric 
536*a824f5a1SJean-Baptiste Boric 	for (; data != NULL && *data != '\0'; data = next_line) {
537*a824f5a1SJean-Baptiste Boric 		if ((eol = strchr(data, '\n')) == NULL) {
538*a824f5a1SJean-Baptiste Boric 			eol = data + strlen(data);
539*a824f5a1SJean-Baptiste Boric 			next_line = eol;
540*a824f5a1SJean-Baptiste Boric 		} else
541*a824f5a1SJean-Baptiste Boric 			next_line = eol + 1;
542*a824f5a1SJean-Baptiste Boric 
543*a824f5a1SJean-Baptiste Boric 		if (strncmp(data, "OPSYS=", 6) == 0)
544*a824f5a1SJean-Baptiste Boric 			pkg->buildinfo[BI_OPSYS] = dup_value(data, eol);
545*a824f5a1SJean-Baptiste Boric 		else if (strncmp(data, "OS_VERSION=", 11) == 0)
546*a824f5a1SJean-Baptiste Boric 			pkg->buildinfo[BI_OS_VERSION] = dup_value(data, eol);
547*a824f5a1SJean-Baptiste Boric 		else if (strncmp(data, "MACHINE_ARCH=", 13) == 0)
548*a824f5a1SJean-Baptiste Boric 			pkg->buildinfo[BI_MACHINE_ARCH] = dup_value(data, eol);
549*a824f5a1SJean-Baptiste Boric 		else if (strncmp(data, "IGNORE_RECOMMENDED=", 19) == 0)
550*a824f5a1SJean-Baptiste Boric 			pkg->buildinfo[BI_IGNORE_RECOMMENDED] = dup_value(data,
551*a824f5a1SJean-Baptiste Boric 			    eol);
552*a824f5a1SJean-Baptiste Boric 		else if (strncmp(data, "USE_ABI_DEPENDS=", 16) == 0)
553*a824f5a1SJean-Baptiste Boric 			pkg->buildinfo[BI_USE_ABI_DEPENDS] = dup_value(data,
554*a824f5a1SJean-Baptiste Boric 			    eol);
555*a824f5a1SJean-Baptiste Boric 		else if (strncmp(data, "LICENSE=", 8) == 0)
556*a824f5a1SJean-Baptiste Boric 			pkg->buildinfo[BI_LICENSE] = dup_value(data, eol);
557*a824f5a1SJean-Baptiste Boric 		else if (strncmp(data, "PKGTOOLS_VERSION=", 17) == 0)
558*a824f5a1SJean-Baptiste Boric 			pkg->buildinfo[BI_PKGTOOLS_VERSION] = dup_value(data,
559*a824f5a1SJean-Baptiste Boric 			    eol);
560*a824f5a1SJean-Baptiste Boric 	}
561*a824f5a1SJean-Baptiste Boric 	if (pkg->buildinfo[BI_OPSYS] == NULL ||
562*a824f5a1SJean-Baptiste Boric 	    pkg->buildinfo[BI_OS_VERSION] == NULL ||
563*a824f5a1SJean-Baptiste Boric 	    pkg->buildinfo[BI_MACHINE_ARCH] == NULL) {
564*a824f5a1SJean-Baptiste Boric 		warnx("Not all required build information are present.");
565*a824f5a1SJean-Baptiste Boric 		return -1;
566*a824f5a1SJean-Baptiste Boric 	}
567*a824f5a1SJean-Baptiste Boric 
568*a824f5a1SJean-Baptiste Boric 	if ((pkg->buildinfo[BI_USE_ABI_DEPENDS] != NULL &&
569*a824f5a1SJean-Baptiste Boric 	    strcasecmp(pkg->buildinfo[BI_USE_ABI_DEPENDS], "YES") != 0) ||
570*a824f5a1SJean-Baptiste Boric 	    (pkg->buildinfo[BI_IGNORE_RECOMMENDED] != NULL &&
571*a824f5a1SJean-Baptiste Boric 	    strcasecmp(pkg->buildinfo[BI_IGNORE_RECOMMENDED], "NO") != 0)) {
572*a824f5a1SJean-Baptiste Boric 		warnx("%s was built to ignore ABI dependencies", pkg->pkgname);
573*a824f5a1SJean-Baptiste Boric 	}
574*a824f5a1SJean-Baptiste Boric 
575*a824f5a1SJean-Baptiste Boric 	return 0;
576*a824f5a1SJean-Baptiste Boric }
577*a824f5a1SJean-Baptiste Boric 
578*a824f5a1SJean-Baptiste Boric /*
579*a824f5a1SJean-Baptiste Boric  * Free buildinfo.
580*a824f5a1SJean-Baptiste Boric  */
581*a824f5a1SJean-Baptiste Boric static void
free_buildinfo(struct pkg_task * pkg)582*a824f5a1SJean-Baptiste Boric free_buildinfo(struct pkg_task *pkg)
583*a824f5a1SJean-Baptiste Boric {
584*a824f5a1SJean-Baptiste Boric 	size_t i;
585*a824f5a1SJean-Baptiste Boric 
586*a824f5a1SJean-Baptiste Boric 	for (i = 0; i < BI_ENUM_COUNT; ++i) {
587*a824f5a1SJean-Baptiste Boric 		free(pkg->buildinfo[i]);
588*a824f5a1SJean-Baptiste Boric 		pkg->buildinfo[i] = NULL;
589*a824f5a1SJean-Baptiste Boric 	}
590*a824f5a1SJean-Baptiste Boric }
591*a824f5a1SJean-Baptiste Boric 
592*a824f5a1SJean-Baptiste Boric /*
593*a824f5a1SJean-Baptiste Boric  * Write meta data files to pkgdb after creating the directory.
594*a824f5a1SJean-Baptiste Boric  */
595*a824f5a1SJean-Baptiste Boric static int
write_meta_data(struct pkg_task * pkg)596*a824f5a1SJean-Baptiste Boric write_meta_data(struct pkg_task *pkg)
597*a824f5a1SJean-Baptiste Boric {
598*a824f5a1SJean-Baptiste Boric 	const struct pkg_meta_desc *descr;
599*a824f5a1SJean-Baptiste Boric 	char *filename, **target;
600*a824f5a1SJean-Baptiste Boric 	size_t len;
601*a824f5a1SJean-Baptiste Boric 	ssize_t ret;
602*a824f5a1SJean-Baptiste Boric 	int fd;
603*a824f5a1SJean-Baptiste Boric 
604*a824f5a1SJean-Baptiste Boric 	if (Fake)
605*a824f5a1SJean-Baptiste Boric 		return 0;
606*a824f5a1SJean-Baptiste Boric 
607*a824f5a1SJean-Baptiste Boric 	if (mkdir_p(pkg->install_logdir)) {
608*a824f5a1SJean-Baptiste Boric 		warn("Can't create pkgdb entry: %s", pkg->install_logdir);
609*a824f5a1SJean-Baptiste Boric 		return -1;
610*a824f5a1SJean-Baptiste Boric 	}
611*a824f5a1SJean-Baptiste Boric 
612*a824f5a1SJean-Baptiste Boric 	for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) {
613*a824f5a1SJean-Baptiste Boric 		target = (char **)((char *)&pkg->meta_data +
614*a824f5a1SJean-Baptiste Boric 		    descr->entry_offset);
615*a824f5a1SJean-Baptiste Boric 		if (*target == NULL)
616*a824f5a1SJean-Baptiste Boric 			continue;
617*a824f5a1SJean-Baptiste Boric 		filename = xasprintf("%s/%s", pkg->install_logdir,
618*a824f5a1SJean-Baptiste Boric 		    descr->entry_filename);
619*a824f5a1SJean-Baptiste Boric 		(void)unlink(filename);
620*a824f5a1SJean-Baptiste Boric 		fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, descr->perm);
621*a824f5a1SJean-Baptiste Boric 		if (fd == -1) {
622*a824f5a1SJean-Baptiste Boric 			warn("Can't open meta data file: %s", filename);
623*a824f5a1SJean-Baptiste Boric 			return -1;
624*a824f5a1SJean-Baptiste Boric 		}
625*a824f5a1SJean-Baptiste Boric 		len = strlen(*target);
626*a824f5a1SJean-Baptiste Boric 		do {
627*a824f5a1SJean-Baptiste Boric 			ret = write(fd, *target, len);
628*a824f5a1SJean-Baptiste Boric 			if (ret == -1) {
629*a824f5a1SJean-Baptiste Boric 				warn("Can't write meta data file: %s",
630*a824f5a1SJean-Baptiste Boric 				    filename);
631*a824f5a1SJean-Baptiste Boric 				free(filename);
632*a824f5a1SJean-Baptiste Boric 				close(fd);
633*a824f5a1SJean-Baptiste Boric 				return -1;
634*a824f5a1SJean-Baptiste Boric 			}
635*a824f5a1SJean-Baptiste Boric 			len -= ret;
636*a824f5a1SJean-Baptiste Boric 		} while (ret > 0);
637*a824f5a1SJean-Baptiste Boric 		if (close(fd) == -1) {
638*a824f5a1SJean-Baptiste Boric 			warn("Can't close meta data file: %s", filename);
639*a824f5a1SJean-Baptiste Boric 			free(filename);
640*a824f5a1SJean-Baptiste Boric 			return -1;
641*a824f5a1SJean-Baptiste Boric 		}
642*a824f5a1SJean-Baptiste Boric 		free(filename);
643*a824f5a1SJean-Baptiste Boric 	}
644*a824f5a1SJean-Baptiste Boric 
645*a824f5a1SJean-Baptiste Boric 	return 0;
646*a824f5a1SJean-Baptiste Boric }
647*a824f5a1SJean-Baptiste Boric 
648*a824f5a1SJean-Baptiste Boric /*
649*a824f5a1SJean-Baptiste Boric  * Helper function for extract_files.
650*a824f5a1SJean-Baptiste Boric  */
651*a824f5a1SJean-Baptiste Boric static int
copy_data_to_disk(struct archive * reader,struct archive * writer,const char * filename)652*a824f5a1SJean-Baptiste Boric copy_data_to_disk(struct archive *reader, struct archive *writer,
653*a824f5a1SJean-Baptiste Boric     const char *filename)
654*a824f5a1SJean-Baptiste Boric {
655*a824f5a1SJean-Baptiste Boric 	int r;
656*a824f5a1SJean-Baptiste Boric 	const void *buff;
657*a824f5a1SJean-Baptiste Boric 	size_t size;
658*a824f5a1SJean-Baptiste Boric 	off_t offset;
659*a824f5a1SJean-Baptiste Boric 
660*a824f5a1SJean-Baptiste Boric 	for (;;) {
661*a824f5a1SJean-Baptiste Boric 		r = archive_read_data_block(reader, &buff, &size, &offset);
662*a824f5a1SJean-Baptiste Boric 		if (r == ARCHIVE_EOF)
663*a824f5a1SJean-Baptiste Boric 			return 0;
664*a824f5a1SJean-Baptiste Boric 		if (r != ARCHIVE_OK) {
665*a824f5a1SJean-Baptiste Boric 			warnx("Read error for %s: %s", filename,
666*a824f5a1SJean-Baptiste Boric 			    archive_error_string(reader));
667*a824f5a1SJean-Baptiste Boric 			return -1;
668*a824f5a1SJean-Baptiste Boric 		}
669*a824f5a1SJean-Baptiste Boric 		r = archive_write_data_block(writer, buff, size, offset);
670*a824f5a1SJean-Baptiste Boric 		if (r != ARCHIVE_OK) {
671*a824f5a1SJean-Baptiste Boric 			warnx("Write error for %s: %s", filename,
672*a824f5a1SJean-Baptiste Boric 			    archive_error_string(writer));
673*a824f5a1SJean-Baptiste Boric 			return -1;
674*a824f5a1SJean-Baptiste Boric 		}
675*a824f5a1SJean-Baptiste Boric 	}
676*a824f5a1SJean-Baptiste Boric }
677*a824f5a1SJean-Baptiste Boric 
678*a824f5a1SJean-Baptiste Boric /*
679*a824f5a1SJean-Baptiste Boric  * Extract package.
680*a824f5a1SJean-Baptiste Boric  * Any misordered, missing or unlisted file in the package is an error.
681*a824f5a1SJean-Baptiste Boric  */
682*a824f5a1SJean-Baptiste Boric 
683*a824f5a1SJean-Baptiste Boric static const int extract_flags = ARCHIVE_EXTRACT_OWNER |
684*a824f5a1SJean-Baptiste Boric     ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_UNLINK |
685*a824f5a1SJean-Baptiste Boric     ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR;
686*a824f5a1SJean-Baptiste Boric 
687*a824f5a1SJean-Baptiste Boric static int
extract_files(struct pkg_task * pkg)688*a824f5a1SJean-Baptiste Boric extract_files(struct pkg_task *pkg)
689*a824f5a1SJean-Baptiste Boric {
690*a824f5a1SJean-Baptiste Boric 	char    cmd[MaxPathSize];
691*a824f5a1SJean-Baptiste Boric 	const char *owner, *group, *permissions;
692*a824f5a1SJean-Baptiste Boric 	struct archive *writer;
693*a824f5a1SJean-Baptiste Boric 	int r;
694*a824f5a1SJean-Baptiste Boric 	plist_t *p;
695*a824f5a1SJean-Baptiste Boric 	const char *last_file;
696*a824f5a1SJean-Baptiste Boric 	char *fullpath;
697*a824f5a1SJean-Baptiste Boric 
698*a824f5a1SJean-Baptiste Boric 	if (Fake)
699*a824f5a1SJean-Baptiste Boric 		return 0;
700*a824f5a1SJean-Baptiste Boric 
701*a824f5a1SJean-Baptiste Boric 	if (mkdir_p(pkg->install_prefix)) {
702*a824f5a1SJean-Baptiste Boric 		warn("Can't create prefix: %s", pkg->install_prefix);
703*a824f5a1SJean-Baptiste Boric 		return -1;
704*a824f5a1SJean-Baptiste Boric 	}
705*a824f5a1SJean-Baptiste Boric 
706*a824f5a1SJean-Baptiste Boric 	if (!NoRecord && !pkgdb_open(ReadWrite)) {
707*a824f5a1SJean-Baptiste Boric 		warn("Can't open pkgdb for writing");
708*a824f5a1SJean-Baptiste Boric 		return -1;
709*a824f5a1SJean-Baptiste Boric 	}
710*a824f5a1SJean-Baptiste Boric 
711*a824f5a1SJean-Baptiste Boric 	if (chdir(pkg->install_prefix) == -1) {
712*a824f5a1SJean-Baptiste Boric 		warn("Can't change into prefix: %s", pkg->install_prefix);
713*a824f5a1SJean-Baptiste Boric 		return -1;
714*a824f5a1SJean-Baptiste Boric 	}
715*a824f5a1SJean-Baptiste Boric 
716*a824f5a1SJean-Baptiste Boric 	writer = archive_write_disk_new();
717*a824f5a1SJean-Baptiste Boric 	archive_write_disk_set_options(writer, extract_flags);
718*a824f5a1SJean-Baptiste Boric 	archive_write_disk_set_standard_lookup(writer);
719*a824f5a1SJean-Baptiste Boric 
720*a824f5a1SJean-Baptiste Boric 	owner = NULL;
721*a824f5a1SJean-Baptiste Boric 	group = NULL;
722*a824f5a1SJean-Baptiste Boric 	permissions = NULL;
723*a824f5a1SJean-Baptiste Boric 	last_file = NULL;
724*a824f5a1SJean-Baptiste Boric 
725*a824f5a1SJean-Baptiste Boric 	r = -1;
726*a824f5a1SJean-Baptiste Boric 
727*a824f5a1SJean-Baptiste Boric 	for (p = pkg->plist.head; p != NULL; p = p->next) {
728*a824f5a1SJean-Baptiste Boric 		switch (p->type) {
729*a824f5a1SJean-Baptiste Boric 		case PLIST_FILE:
730*a824f5a1SJean-Baptiste Boric 			last_file = p->name;
731*a824f5a1SJean-Baptiste Boric 			if (pkg->entry == NULL) {
732*a824f5a1SJean-Baptiste Boric 				warnx("PLIST entry not in package (%s)",
733*a824f5a1SJean-Baptiste Boric 				    archive_entry_pathname(pkg->entry));
734*a824f5a1SJean-Baptiste Boric 				goto out;
735*a824f5a1SJean-Baptiste Boric 			}
736*a824f5a1SJean-Baptiste Boric 			if (strcmp(p->name, archive_entry_pathname(pkg->entry))) {
737*a824f5a1SJean-Baptiste Boric 				warnx("PLIST entry and package don't match (%s vs %s)",
738*a824f5a1SJean-Baptiste Boric 				    p->name, archive_entry_pathname(pkg->entry));
739*a824f5a1SJean-Baptiste Boric 				goto out;
740*a824f5a1SJean-Baptiste Boric 			}
741*a824f5a1SJean-Baptiste Boric 			fullpath = xasprintf("%s/%s", pkg->prefix, p->name);
742*a824f5a1SJean-Baptiste Boric 			pkgdb_store(fullpath, pkg->pkgname);
743*a824f5a1SJean-Baptiste Boric 			free(fullpath);
744*a824f5a1SJean-Baptiste Boric 			if (Verbose)
745*a824f5a1SJean-Baptiste Boric 				printf("%s", p->name);
746*a824f5a1SJean-Baptiste Boric 			break;
747*a824f5a1SJean-Baptiste Boric 
748*a824f5a1SJean-Baptiste Boric 		case PLIST_PKGDIR:
749*a824f5a1SJean-Baptiste Boric 			fullpath = xasprintf("%s/%s", pkg->prefix, p->name);
750*a824f5a1SJean-Baptiste Boric 			mkdir_p(fullpath);
751*a824f5a1SJean-Baptiste Boric 			free(fullpath);
752*a824f5a1SJean-Baptiste Boric 			add_pkgdir(pkg->pkgname, pkg->prefix, p->name);
753*a824f5a1SJean-Baptiste Boric 			continue;
754*a824f5a1SJean-Baptiste Boric 
755*a824f5a1SJean-Baptiste Boric 		case PLIST_CMD:
756*a824f5a1SJean-Baptiste Boric 			if (format_cmd(cmd, sizeof(cmd), p->name, pkg->prefix, last_file))
757*a824f5a1SJean-Baptiste Boric 				return -1;
758*a824f5a1SJean-Baptiste Boric 			printf("Executing '%s'\n", cmd);
759*a824f5a1SJean-Baptiste Boric 			if (!Fake && system(cmd))
760*a824f5a1SJean-Baptiste Boric 				warnx("command '%s' failed", cmd); /* XXX bail out? */
761*a824f5a1SJean-Baptiste Boric 			continue;
762*a824f5a1SJean-Baptiste Boric 
763*a824f5a1SJean-Baptiste Boric 		case PLIST_CHMOD:
764*a824f5a1SJean-Baptiste Boric 			permissions = p->name;
765*a824f5a1SJean-Baptiste Boric 			continue;
766*a824f5a1SJean-Baptiste Boric 
767*a824f5a1SJean-Baptiste Boric 		case PLIST_CHOWN:
768*a824f5a1SJean-Baptiste Boric 			owner = p->name;
769*a824f5a1SJean-Baptiste Boric 			continue;
770*a824f5a1SJean-Baptiste Boric 
771*a824f5a1SJean-Baptiste Boric 		case PLIST_CHGRP:
772*a824f5a1SJean-Baptiste Boric 			group = p->name;
773*a824f5a1SJean-Baptiste Boric 			continue;
774*a824f5a1SJean-Baptiste Boric 
775*a824f5a1SJean-Baptiste Boric 		case PLIST_IGNORE:
776*a824f5a1SJean-Baptiste Boric 			p = p->next;
777*a824f5a1SJean-Baptiste Boric 			continue;
778*a824f5a1SJean-Baptiste Boric 
779*a824f5a1SJean-Baptiste Boric 		default:
780*a824f5a1SJean-Baptiste Boric 			continue;
781*a824f5a1SJean-Baptiste Boric 		}
782*a824f5a1SJean-Baptiste Boric 
783*a824f5a1SJean-Baptiste Boric 		r = archive_write_header(writer, pkg->entry);
784*a824f5a1SJean-Baptiste Boric 		if (r != ARCHIVE_OK) {
785*a824f5a1SJean-Baptiste Boric 			warnx("Failed to write %s for %s: %s",
786*a824f5a1SJean-Baptiste Boric 			    archive_entry_pathname(pkg->entry),
787*a824f5a1SJean-Baptiste Boric 			    pkg->pkgname,
788*a824f5a1SJean-Baptiste Boric 			    archive_error_string(writer));
789*a824f5a1SJean-Baptiste Boric 			goto out;
790*a824f5a1SJean-Baptiste Boric 		}
791*a824f5a1SJean-Baptiste Boric 
792*a824f5a1SJean-Baptiste Boric 		if (owner != NULL)
793*a824f5a1SJean-Baptiste Boric 			archive_entry_set_uname(pkg->entry, owner);
794*a824f5a1SJean-Baptiste Boric 		if (group != NULL)
795*a824f5a1SJean-Baptiste Boric 			archive_entry_set_uname(pkg->entry, group);
796*a824f5a1SJean-Baptiste Boric 		if (permissions != NULL) {
797*a824f5a1SJean-Baptiste Boric 			mode_t mode;
798*a824f5a1SJean-Baptiste Boric 
799*a824f5a1SJean-Baptiste Boric 			mode = archive_entry_mode(pkg->entry);
800*a824f5a1SJean-Baptiste Boric 			mode = getmode(setmode(permissions), mode);
801*a824f5a1SJean-Baptiste Boric 			archive_entry_set_mode(pkg->entry, mode);
802*a824f5a1SJean-Baptiste Boric 		}
803*a824f5a1SJean-Baptiste Boric 
804*a824f5a1SJean-Baptiste Boric 		r = copy_data_to_disk(pkg->archive, writer,
805*a824f5a1SJean-Baptiste Boric 		    archive_entry_pathname(pkg->entry));
806*a824f5a1SJean-Baptiste Boric 		if (r)
807*a824f5a1SJean-Baptiste Boric 			goto out;
808*a824f5a1SJean-Baptiste Boric 		if (Verbose)
809*a824f5a1SJean-Baptiste Boric 			printf("\n");
810*a824f5a1SJean-Baptiste Boric 
811*a824f5a1SJean-Baptiste Boric 		r = archive_read_next_header(pkg->archive, &pkg->entry);
812*a824f5a1SJean-Baptiste Boric 		if (r == ARCHIVE_EOF) {
813*a824f5a1SJean-Baptiste Boric 			pkg->entry = NULL;
814*a824f5a1SJean-Baptiste Boric 			continue;
815*a824f5a1SJean-Baptiste Boric 		}
816*a824f5a1SJean-Baptiste Boric 		if (r != ARCHIVE_OK) {
817*a824f5a1SJean-Baptiste Boric 			warnx("Failed to read from archive for %s: %s",
818*a824f5a1SJean-Baptiste Boric 			    pkg->pkgname,
819*a824f5a1SJean-Baptiste Boric 			    archive_error_string(pkg->archive));
820*a824f5a1SJean-Baptiste Boric 			goto out;
821*a824f5a1SJean-Baptiste Boric 		}
822*a824f5a1SJean-Baptiste Boric 	}
823*a824f5a1SJean-Baptiste Boric 
824*a824f5a1SJean-Baptiste Boric 	if (pkg->entry != NULL) {
825*a824f5a1SJean-Baptiste Boric 		warnx("Package contains entries not in PLIST: %s",
826*a824f5a1SJean-Baptiste Boric 		    archive_entry_pathname(pkg->entry));
827*a824f5a1SJean-Baptiste Boric 		goto out;
828*a824f5a1SJean-Baptiste Boric 	}
829*a824f5a1SJean-Baptiste Boric 
830*a824f5a1SJean-Baptiste Boric 	r = 0;
831*a824f5a1SJean-Baptiste Boric 
832*a824f5a1SJean-Baptiste Boric out:
833*a824f5a1SJean-Baptiste Boric 	if (!NoRecord)
834*a824f5a1SJean-Baptiste Boric 		pkgdb_close();
835*a824f5a1SJean-Baptiste Boric 	archive_write_close(writer);
836*a824f5a1SJean-Baptiste Boric 	archive_write_finish(writer);
837*a824f5a1SJean-Baptiste Boric 
838*a824f5a1SJean-Baptiste Boric 	return r;
839*a824f5a1SJean-Baptiste Boric }
840*a824f5a1SJean-Baptiste Boric 
841*a824f5a1SJean-Baptiste Boric /*
842*a824f5a1SJean-Baptiste Boric  * Register dependencies after sucessfully installing the package.
843*a824f5a1SJean-Baptiste Boric  */
844*a824f5a1SJean-Baptiste Boric static void
pkg_register_depends(struct pkg_task * pkg)845*a824f5a1SJean-Baptiste Boric pkg_register_depends(struct pkg_task *pkg)
846*a824f5a1SJean-Baptiste Boric {
847*a824f5a1SJean-Baptiste Boric 	int fd;
848*a824f5a1SJean-Baptiste Boric 	size_t text_len, i;
849*a824f5a1SJean-Baptiste Boric 	char *required_by, *text;
850*a824f5a1SJean-Baptiste Boric 
851*a824f5a1SJean-Baptiste Boric 	if (Fake)
852*a824f5a1SJean-Baptiste Boric 		return;
853*a824f5a1SJean-Baptiste Boric 
854*a824f5a1SJean-Baptiste Boric 	text = xasprintf("%s\n", pkg->pkgname);
855*a824f5a1SJean-Baptiste Boric 	text_len = strlen(text);
856*a824f5a1SJean-Baptiste Boric 
857*a824f5a1SJean-Baptiste Boric 	for (i = 0; i < pkg->dep_length; ++i) {
858*a824f5a1SJean-Baptiste Boric 		required_by = pkgdb_pkg_file(pkg->dependencies[i], REQUIRED_BY_FNAME);
859*a824f5a1SJean-Baptiste Boric 
860*a824f5a1SJean-Baptiste Boric 		fd = open(required_by, O_WRONLY | O_APPEND | O_CREAT, 0644);
861*a824f5a1SJean-Baptiste Boric 		if (fd == -1) {
862*a824f5a1SJean-Baptiste Boric 			warn("can't open dependency file '%s',"
863*a824f5a1SJean-Baptiste Boric 			    "registration is incomplete!", required_by);
864*a824f5a1SJean-Baptiste Boric 		} else if (write(fd, text, text_len) != (ssize_t)text_len) {
865*a824f5a1SJean-Baptiste Boric 			warn("can't write to dependency file `%s'", required_by);
866*a824f5a1SJean-Baptiste Boric 			close(fd);
867*a824f5a1SJean-Baptiste Boric 		} else if (close(fd) == -1)
868*a824f5a1SJean-Baptiste Boric 			warn("cannot close file %s", required_by);
869*a824f5a1SJean-Baptiste Boric 
870*a824f5a1SJean-Baptiste Boric 		free(required_by);
871*a824f5a1SJean-Baptiste Boric 	}
872*a824f5a1SJean-Baptiste Boric 
873*a824f5a1SJean-Baptiste Boric 	free(text);
874*a824f5a1SJean-Baptiste Boric }
875*a824f5a1SJean-Baptiste Boric 
876*a824f5a1SJean-Baptiste Boric /*
877*a824f5a1SJean-Baptiste Boric  * Reduce the result from uname(3) to a canonical form.
878*a824f5a1SJean-Baptiste Boric  */
879*a824f5a1SJean-Baptiste Boric static void
normalise_platform(struct utsname * host_name)880*a824f5a1SJean-Baptiste Boric normalise_platform(struct utsname *host_name)
881*a824f5a1SJean-Baptiste Boric {
882*a824f5a1SJean-Baptiste Boric #ifdef NUMERIC_VERSION_ONLY
883*a824f5a1SJean-Baptiste Boric 	size_t span;
884*a824f5a1SJean-Baptiste Boric 
885*a824f5a1SJean-Baptiste Boric 	span = strspn(host_name->release, "0123456789.");
886*a824f5a1SJean-Baptiste Boric 	host_name->release[span] = '\0';
887*a824f5a1SJean-Baptiste Boric #endif
888*a824f5a1SJean-Baptiste Boric }
889*a824f5a1SJean-Baptiste Boric 
890*a824f5a1SJean-Baptiste Boric /*
891*a824f5a1SJean-Baptiste Boric  * Check build platform of the package against local host.
892*a824f5a1SJean-Baptiste Boric  */
893*a824f5a1SJean-Baptiste Boric static int
check_platform(struct pkg_task * pkg)894*a824f5a1SJean-Baptiste Boric check_platform(struct pkg_task *pkg)
895*a824f5a1SJean-Baptiste Boric {
896*a824f5a1SJean-Baptiste Boric 	struct utsname host_uname;
897*a824f5a1SJean-Baptiste Boric 	const char *effective_arch;
898*a824f5a1SJean-Baptiste Boric 	int fatal;
899*a824f5a1SJean-Baptiste Boric 
900*a824f5a1SJean-Baptiste Boric 	if (uname(&host_uname) < 0) {
901*a824f5a1SJean-Baptiste Boric 		if (Force) {
902*a824f5a1SJean-Baptiste Boric 			warnx("uname() failed, continuing.");
903*a824f5a1SJean-Baptiste Boric 			return 0;
904*a824f5a1SJean-Baptiste Boric 		} else {
905*a824f5a1SJean-Baptiste Boric 			warnx("uname() failed, aborting.");
906*a824f5a1SJean-Baptiste Boric 			return -1;
907*a824f5a1SJean-Baptiste Boric 		}
908*a824f5a1SJean-Baptiste Boric 	}
909*a824f5a1SJean-Baptiste Boric 
910*a824f5a1SJean-Baptiste Boric 	normalise_platform(&host_uname);
911*a824f5a1SJean-Baptiste Boric 
912*a824f5a1SJean-Baptiste Boric 	if (OverrideMachine != NULL)
913*a824f5a1SJean-Baptiste Boric 		effective_arch = OverrideMachine;
914*a824f5a1SJean-Baptiste Boric 	else
915*a824f5a1SJean-Baptiste Boric 		effective_arch = MACHINE_ARCH;
916*a824f5a1SJean-Baptiste Boric 
917*a824f5a1SJean-Baptiste Boric 	/* If either the OS or arch are different, bomb */
918*a824f5a1SJean-Baptiste Boric 	if (strcmp(OPSYS_NAME, pkg->buildinfo[BI_OPSYS]) ||
919*a824f5a1SJean-Baptiste Boric 	    strcmp(effective_arch, pkg->buildinfo[BI_MACHINE_ARCH]) != 0)
920*a824f5a1SJean-Baptiste Boric 		fatal = 1;
921*a824f5a1SJean-Baptiste Boric 	else
922*a824f5a1SJean-Baptiste Boric 		fatal = 0;
923*a824f5a1SJean-Baptiste Boric 
924*a824f5a1SJean-Baptiste Boric 	if (fatal ||
925*a824f5a1SJean-Baptiste Boric 	    compatible_platform(OPSYS_NAME, host_uname.release,
926*a824f5a1SJean-Baptiste Boric 				pkg->buildinfo[BI_OS_VERSION]) != 1) {
927*a824f5a1SJean-Baptiste Boric 		warnx("Warning: package `%s' was built for a platform:",
928*a824f5a1SJean-Baptiste Boric 		    pkg->pkgname);
929*a824f5a1SJean-Baptiste Boric 		warnx("%s/%s %s (pkg) vs. %s/%s %s (this host)",
930*a824f5a1SJean-Baptiste Boric 		    pkg->buildinfo[BI_OPSYS],
931*a824f5a1SJean-Baptiste Boric 		    pkg->buildinfo[BI_MACHINE_ARCH],
932*a824f5a1SJean-Baptiste Boric 		    pkg->buildinfo[BI_OS_VERSION],
933*a824f5a1SJean-Baptiste Boric 		    OPSYS_NAME,
934*a824f5a1SJean-Baptiste Boric 		    effective_arch,
935*a824f5a1SJean-Baptiste Boric 		    host_uname.release);
936*a824f5a1SJean-Baptiste Boric 		if (!Force && fatal)
937*a824f5a1SJean-Baptiste Boric 			return -1;
938*a824f5a1SJean-Baptiste Boric 	}
939*a824f5a1SJean-Baptiste Boric 	return 0;
940*a824f5a1SJean-Baptiste Boric }
941*a824f5a1SJean-Baptiste Boric 
942*a824f5a1SJean-Baptiste Boric static int
check_pkgtools_version(struct pkg_task * pkg)943*a824f5a1SJean-Baptiste Boric check_pkgtools_version(struct pkg_task *pkg)
944*a824f5a1SJean-Baptiste Boric {
945*a824f5a1SJean-Baptiste Boric 	const char *val = pkg->buildinfo[BI_PKGTOOLS_VERSION];
946*a824f5a1SJean-Baptiste Boric 	int version;
947*a824f5a1SJean-Baptiste Boric 
948*a824f5a1SJean-Baptiste Boric 	if (val == NULL) {
949*a824f5a1SJean-Baptiste Boric 		warnx("Warning: package `%s' lacks pkg_install version data",
950*a824f5a1SJean-Baptiste Boric 		    pkg->pkgname);
951*a824f5a1SJean-Baptiste Boric 		return 0;
952*a824f5a1SJean-Baptiste Boric 	}
953*a824f5a1SJean-Baptiste Boric 
954*a824f5a1SJean-Baptiste Boric 	if (strlen(val) != 8 || strspn(val, "0123456789") != 8) {
955*a824f5a1SJean-Baptiste Boric 		warnx("Warning: package `%s' contains an invalid pkg_install version",
956*a824f5a1SJean-Baptiste Boric 		    pkg->pkgname);
957*a824f5a1SJean-Baptiste Boric 		return Force ? 0 : -1;
958*a824f5a1SJean-Baptiste Boric 	}
959*a824f5a1SJean-Baptiste Boric 	version = atoi(val);
960*a824f5a1SJean-Baptiste Boric 	if (version > PKGTOOLS_VERSION) {
961*a824f5a1SJean-Baptiste Boric 		warnx("%s: package `%s' was built with a newer pkg_install version",
962*a824f5a1SJean-Baptiste Boric 		    Force ? "Warning" : "Error", pkg->pkgname);
963*a824f5a1SJean-Baptiste Boric 		return Force ? 0 : -1;
964*a824f5a1SJean-Baptiste Boric 	}
965*a824f5a1SJean-Baptiste Boric 	return 0;
966*a824f5a1SJean-Baptiste Boric }
967*a824f5a1SJean-Baptiste Boric 
968*a824f5a1SJean-Baptiste Boric /*
969*a824f5a1SJean-Baptiste Boric  * Run the install script.
970*a824f5a1SJean-Baptiste Boric  */
971*a824f5a1SJean-Baptiste Boric static int
run_install_script(struct pkg_task * pkg,const char * argument)972*a824f5a1SJean-Baptiste Boric run_install_script(struct pkg_task *pkg, const char *argument)
973*a824f5a1SJean-Baptiste Boric {
974*a824f5a1SJean-Baptiste Boric 	int ret;
975*a824f5a1SJean-Baptiste Boric 	char *filename;
976*a824f5a1SJean-Baptiste Boric 
977*a824f5a1SJean-Baptiste Boric 	if (pkg->meta_data.meta_install == NULL || NoInstall)
978*a824f5a1SJean-Baptiste Boric 		return 0;
979*a824f5a1SJean-Baptiste Boric 
980*a824f5a1SJean-Baptiste Boric 	if (Destdir != NULL)
981*a824f5a1SJean-Baptiste Boric 		setenv(PKG_DESTDIR_VNAME, Destdir, 1);
982*a824f5a1SJean-Baptiste Boric 	setenv(PKG_PREFIX_VNAME, pkg->prefix, 1);
983*a824f5a1SJean-Baptiste Boric 	setenv(PKG_METADATA_DIR_VNAME, pkg->logdir, 1);
984*a824f5a1SJean-Baptiste Boric 	setenv(PKG_REFCOUNT_DBDIR_VNAME, config_pkg_refcount_dbdir, 1);
985*a824f5a1SJean-Baptiste Boric 
986*a824f5a1SJean-Baptiste Boric 	if (Verbose)
987*a824f5a1SJean-Baptiste Boric 		printf("Running install with PRE-INSTALL for %s.\n", pkg->pkgname);
988*a824f5a1SJean-Baptiste Boric 	if (Fake)
989*a824f5a1SJean-Baptiste Boric 		return 0;
990*a824f5a1SJean-Baptiste Boric 
991*a824f5a1SJean-Baptiste Boric 	filename = pkgdb_pkg_file(pkg->pkgname, INSTALL_FNAME);
992*a824f5a1SJean-Baptiste Boric 
993*a824f5a1SJean-Baptiste Boric 	ret = 0;
994*a824f5a1SJean-Baptiste Boric 	errno = 0;
995*a824f5a1SJean-Baptiste Boric 	if (fcexec(pkg->install_logdir, filename, pkg->pkgname, argument,
996*a824f5a1SJean-Baptiste Boric 	    (void *)NULL)) {
997*a824f5a1SJean-Baptiste Boric 		if (errno != 0)
998*a824f5a1SJean-Baptiste Boric 			warn("exec of install script failed");
999*a824f5a1SJean-Baptiste Boric 		else
1000*a824f5a1SJean-Baptiste Boric 			warnx("install script returned error status");
1001*a824f5a1SJean-Baptiste Boric 		ret = -1;
1002*a824f5a1SJean-Baptiste Boric 	}
1003*a824f5a1SJean-Baptiste Boric 	free(filename);
1004*a824f5a1SJean-Baptiste Boric 
1005*a824f5a1SJean-Baptiste Boric 	return ret;
1006*a824f5a1SJean-Baptiste Boric }
1007*a824f5a1SJean-Baptiste Boric 
1008*a824f5a1SJean-Baptiste Boric struct find_conflict_data {
1009*a824f5a1SJean-Baptiste Boric 	const char *pkg;
1010*a824f5a1SJean-Baptiste Boric 	const char *old_pkg;
1011*a824f5a1SJean-Baptiste Boric 	const char *pattern;
1012*a824f5a1SJean-Baptiste Boric };
1013*a824f5a1SJean-Baptiste Boric 
1014*a824f5a1SJean-Baptiste Boric static int
check_explicit_conflict_iter(const char * cur_pkg,void * cookie)1015*a824f5a1SJean-Baptiste Boric check_explicit_conflict_iter(const char *cur_pkg, void *cookie)
1016*a824f5a1SJean-Baptiste Boric {
1017*a824f5a1SJean-Baptiste Boric 	struct find_conflict_data *data = cookie;
1018*a824f5a1SJean-Baptiste Boric 
1019*a824f5a1SJean-Baptiste Boric 	if (data->old_pkg && strcmp(data->old_pkg, cur_pkg) == 0)
1020*a824f5a1SJean-Baptiste Boric 		return 0;
1021*a824f5a1SJean-Baptiste Boric 
1022*a824f5a1SJean-Baptiste Boric 	warnx("Package `%s' conflicts with `%s', and `%s' is installed.",
1023*a824f5a1SJean-Baptiste Boric 	    data->pkg, data->pattern, cur_pkg);
1024*a824f5a1SJean-Baptiste Boric 
1025*a824f5a1SJean-Baptiste Boric 	return 1;
1026*a824f5a1SJean-Baptiste Boric }
1027*a824f5a1SJean-Baptiste Boric 
1028*a824f5a1SJean-Baptiste Boric static int
check_explicit_conflict(struct pkg_task * pkg)1029*a824f5a1SJean-Baptiste Boric check_explicit_conflict(struct pkg_task *pkg)
1030*a824f5a1SJean-Baptiste Boric {
1031*a824f5a1SJean-Baptiste Boric 	struct find_conflict_data data;
1032*a824f5a1SJean-Baptiste Boric 	char *installed, *installed_pattern;
1033*a824f5a1SJean-Baptiste Boric 	plist_t *p;
1034*a824f5a1SJean-Baptiste Boric 	int status;
1035*a824f5a1SJean-Baptiste Boric 
1036*a824f5a1SJean-Baptiste Boric 	status = 0;
1037*a824f5a1SJean-Baptiste Boric 
1038*a824f5a1SJean-Baptiste Boric 	for (p = pkg->plist.head; p != NULL; p = p->next) {
1039*a824f5a1SJean-Baptiste Boric 		if (p->type == PLIST_IGNORE) {
1040*a824f5a1SJean-Baptiste Boric 			p = p->next;
1041*a824f5a1SJean-Baptiste Boric 			continue;
1042*a824f5a1SJean-Baptiste Boric 		}
1043*a824f5a1SJean-Baptiste Boric 		if (p->type != PLIST_PKGCFL)
1044*a824f5a1SJean-Baptiste Boric 			continue;
1045*a824f5a1SJean-Baptiste Boric 		data.pkg = pkg->pkgname;
1046*a824f5a1SJean-Baptiste Boric 		data.old_pkg = pkg->other_version;
1047*a824f5a1SJean-Baptiste Boric 		data.pattern = p->name;
1048*a824f5a1SJean-Baptiste Boric 		status |= match_installed_pkgs(p->name,
1049*a824f5a1SJean-Baptiste Boric 		    check_explicit_conflict_iter, &data);
1050*a824f5a1SJean-Baptiste Boric 	}
1051*a824f5a1SJean-Baptiste Boric 
1052*a824f5a1SJean-Baptiste Boric 	if (some_installed_package_conflicts_with(pkg->pkgname,
1053*a824f5a1SJean-Baptiste Boric 	    pkg->other_version, &installed, &installed_pattern)) {
1054*a824f5a1SJean-Baptiste Boric 		warnx("Installed package `%s' conflicts with `%s' when trying to install `%s'.",
1055*a824f5a1SJean-Baptiste Boric 			installed, installed_pattern, pkg->pkgname);
1056*a824f5a1SJean-Baptiste Boric 		free(installed);
1057*a824f5a1SJean-Baptiste Boric 		free(installed_pattern);
1058*a824f5a1SJean-Baptiste Boric 		status |= -1;
1059*a824f5a1SJean-Baptiste Boric 	}
1060*a824f5a1SJean-Baptiste Boric 
1061*a824f5a1SJean-Baptiste Boric 	return status;
1062*a824f5a1SJean-Baptiste Boric }
1063*a824f5a1SJean-Baptiste Boric 
1064*a824f5a1SJean-Baptiste Boric static int
check_implicit_conflict(struct pkg_task * pkg)1065*a824f5a1SJean-Baptiste Boric check_implicit_conflict(struct pkg_task *pkg)
1066*a824f5a1SJean-Baptiste Boric {
1067*a824f5a1SJean-Baptiste Boric 	plist_t *p;
1068*a824f5a1SJean-Baptiste Boric 	char *fullpath, *existing;
1069*a824f5a1SJean-Baptiste Boric 	int status;
1070*a824f5a1SJean-Baptiste Boric 
1071*a824f5a1SJean-Baptiste Boric 	if (!pkgdb_open(ReadOnly)) {
1072*a824f5a1SJean-Baptiste Boric #if notyet /* XXX empty pkgdb without database? */
1073*a824f5a1SJean-Baptiste Boric 		warn("Can't open pkgdb for reading");
1074*a824f5a1SJean-Baptiste Boric 		return -1;
1075*a824f5a1SJean-Baptiste Boric #else
1076*a824f5a1SJean-Baptiste Boric 		return 0;
1077*a824f5a1SJean-Baptiste Boric #endif
1078*a824f5a1SJean-Baptiste Boric 	}
1079*a824f5a1SJean-Baptiste Boric 
1080*a824f5a1SJean-Baptiste Boric 	status = 0;
1081*a824f5a1SJean-Baptiste Boric 
1082*a824f5a1SJean-Baptiste Boric 	for (p = pkg->plist.head; p != NULL; p = p->next) {
1083*a824f5a1SJean-Baptiste Boric 		if (p->type == PLIST_IGNORE) {
1084*a824f5a1SJean-Baptiste Boric 			p = p->next;
1085*a824f5a1SJean-Baptiste Boric 			continue;
1086*a824f5a1SJean-Baptiste Boric 		} else if (p->type != PLIST_FILE)
1087*a824f5a1SJean-Baptiste Boric 			continue;
1088*a824f5a1SJean-Baptiste Boric 
1089*a824f5a1SJean-Baptiste Boric 		fullpath = xasprintf("%s/%s", pkg->prefix, p->name);
1090*a824f5a1SJean-Baptiste Boric 		existing = pkgdb_retrieve(fullpath);
1091*a824f5a1SJean-Baptiste Boric 		free(fullpath);
1092*a824f5a1SJean-Baptiste Boric 		if (existing == NULL)
1093*a824f5a1SJean-Baptiste Boric 			continue;
1094*a824f5a1SJean-Baptiste Boric 		if (pkg->other_version != NULL &&
1095*a824f5a1SJean-Baptiste Boric 		    strcmp(pkg->other_version, existing) == 0)
1096*a824f5a1SJean-Baptiste Boric 			continue;
1097*a824f5a1SJean-Baptiste Boric 
1098*a824f5a1SJean-Baptiste Boric 		warnx("Conflicting PLIST with %s: %s", existing, p->name);
1099*a824f5a1SJean-Baptiste Boric 		if (!Force) {
1100*a824f5a1SJean-Baptiste Boric 			status = -1;
1101*a824f5a1SJean-Baptiste Boric 			if (!Verbose)
1102*a824f5a1SJean-Baptiste Boric 				break;
1103*a824f5a1SJean-Baptiste Boric 		}
1104*a824f5a1SJean-Baptiste Boric 	}
1105*a824f5a1SJean-Baptiste Boric 
1106*a824f5a1SJean-Baptiste Boric 	pkgdb_close();
1107*a824f5a1SJean-Baptiste Boric 	return status;
1108*a824f5a1SJean-Baptiste Boric }
1109*a824f5a1SJean-Baptiste Boric 
1110*a824f5a1SJean-Baptiste Boric static int
check_dependencies(struct pkg_task * pkg)1111*a824f5a1SJean-Baptiste Boric check_dependencies(struct pkg_task *pkg)
1112*a824f5a1SJean-Baptiste Boric {
1113*a824f5a1SJean-Baptiste Boric 	plist_t *p;
1114*a824f5a1SJean-Baptiste Boric 	char *best_installed;
1115*a824f5a1SJean-Baptiste Boric 	int status;
1116*a824f5a1SJean-Baptiste Boric 	size_t i;
1117*a824f5a1SJean-Baptiste Boric 
1118*a824f5a1SJean-Baptiste Boric 	status = 0;
1119*a824f5a1SJean-Baptiste Boric 
1120*a824f5a1SJean-Baptiste Boric 	for (p = pkg->plist.head; p != NULL; p = p->next) {
1121*a824f5a1SJean-Baptiste Boric 		if (p->type == PLIST_IGNORE) {
1122*a824f5a1SJean-Baptiste Boric 			p = p->next;
1123*a824f5a1SJean-Baptiste Boric 			continue;
1124*a824f5a1SJean-Baptiste Boric 		} else if (p->type != PLIST_PKGDEP)
1125*a824f5a1SJean-Baptiste Boric 			continue;
1126*a824f5a1SJean-Baptiste Boric 
1127*a824f5a1SJean-Baptiste Boric 		best_installed = find_best_matching_installed_pkg(p->name);
1128*a824f5a1SJean-Baptiste Boric 
1129*a824f5a1SJean-Baptiste Boric 		if (best_installed == NULL) {
1130*a824f5a1SJean-Baptiste Boric 			/* XXX check cyclic dependencies? */
1131*a824f5a1SJean-Baptiste Boric 			if (Fake || NoRecord) {
1132*a824f5a1SJean-Baptiste Boric 				if (!Force) {
1133*a824f5a1SJean-Baptiste Boric 					warnx("Missing dependency %s\n",
1134*a824f5a1SJean-Baptiste Boric 					     p->name);
1135*a824f5a1SJean-Baptiste Boric 					status = -1;
1136*a824f5a1SJean-Baptiste Boric 					break;
1137*a824f5a1SJean-Baptiste Boric 				}
1138*a824f5a1SJean-Baptiste Boric 				warnx("Missing dependency %s, continuing",
1139*a824f5a1SJean-Baptiste Boric 				    p->name);
1140*a824f5a1SJean-Baptiste Boric 				continue;
1141*a824f5a1SJean-Baptiste Boric 			}
1142*a824f5a1SJean-Baptiste Boric 			if (pkg_do(p->name, 1, 0)) {
1143*a824f5a1SJean-Baptiste Boric 				if (ForceDepends) {
1144*a824f5a1SJean-Baptiste Boric 					warnx("Can't install dependency %s, "
1145*a824f5a1SJean-Baptiste Boric 					    "continuing", p->name);
1146*a824f5a1SJean-Baptiste Boric 					continue;
1147*a824f5a1SJean-Baptiste Boric 				} else {
1148*a824f5a1SJean-Baptiste Boric 					warnx("Can't install dependency %s",
1149*a824f5a1SJean-Baptiste Boric 					    p->name);
1150*a824f5a1SJean-Baptiste Boric 					status = -1;
1151*a824f5a1SJean-Baptiste Boric 					break;
1152*a824f5a1SJean-Baptiste Boric 				}
1153*a824f5a1SJean-Baptiste Boric 			}
1154*a824f5a1SJean-Baptiste Boric 			best_installed = find_best_matching_installed_pkg(p->name);
1155*a824f5a1SJean-Baptiste Boric 			if (best_installed == NULL && ForceDepends) {
1156*a824f5a1SJean-Baptiste Boric 				warnx("Missing dependency %s ignored", p->name);
1157*a824f5a1SJean-Baptiste Boric 				continue;
1158*a824f5a1SJean-Baptiste Boric 			} else if (best_installed == NULL) {
1159*a824f5a1SJean-Baptiste Boric 				warnx("Just installed dependency %s disappeared", p->name);
1160*a824f5a1SJean-Baptiste Boric 				status = -1;
1161*a824f5a1SJean-Baptiste Boric 				break;
1162*a824f5a1SJean-Baptiste Boric 			}
1163*a824f5a1SJean-Baptiste Boric 		}
1164*a824f5a1SJean-Baptiste Boric 		for (i = 0; i < pkg->dep_length; ++i) {
1165*a824f5a1SJean-Baptiste Boric 			if (strcmp(best_installed, pkg->dependencies[i]) == 0)
1166*a824f5a1SJean-Baptiste Boric 				break;
1167*a824f5a1SJean-Baptiste Boric 		}
1168*a824f5a1SJean-Baptiste Boric 		if (i < pkg->dep_length) {
1169*a824f5a1SJean-Baptiste Boric 			/* Already used as dependency, so skip it. */
1170*a824f5a1SJean-Baptiste Boric 			free(best_installed);
1171*a824f5a1SJean-Baptiste Boric 			continue;
1172*a824f5a1SJean-Baptiste Boric 		}
1173*a824f5a1SJean-Baptiste Boric 		if (pkg->dep_length + 1 >= pkg->dep_allocated) {
1174*a824f5a1SJean-Baptiste Boric 			char **tmp;
1175*a824f5a1SJean-Baptiste Boric 			pkg->dep_allocated = 2 * pkg->dep_allocated + 1;
1176*a824f5a1SJean-Baptiste Boric 			pkg->dependencies = xrealloc(pkg->dependencies,
1177*a824f5a1SJean-Baptiste Boric 			    pkg->dep_allocated * sizeof(*tmp));
1178*a824f5a1SJean-Baptiste Boric 		}
1179*a824f5a1SJean-Baptiste Boric 		pkg->dependencies[pkg->dep_length++] = best_installed;
1180*a824f5a1SJean-Baptiste Boric 	}
1181*a824f5a1SJean-Baptiste Boric 
1182*a824f5a1SJean-Baptiste Boric 	return status;
1183*a824f5a1SJean-Baptiste Boric }
1184*a824f5a1SJean-Baptiste Boric 
1185*a824f5a1SJean-Baptiste Boric /*
1186*a824f5a1SJean-Baptiste Boric  * If this package uses pkg_views, register it in the default view.
1187*a824f5a1SJean-Baptiste Boric  */
1188*a824f5a1SJean-Baptiste Boric static void
pkg_register_views(struct pkg_task * pkg)1189*a824f5a1SJean-Baptiste Boric pkg_register_views(struct pkg_task *pkg)
1190*a824f5a1SJean-Baptiste Boric {
1191*a824f5a1SJean-Baptiste Boric 	if (Fake || NoView || pkg->meta_data.meta_views == NULL)
1192*a824f5a1SJean-Baptiste Boric 		return;
1193*a824f5a1SJean-Baptiste Boric 
1194*a824f5a1SJean-Baptiste Boric 	if (Verbose) {
1195*a824f5a1SJean-Baptiste Boric 		printf("%s/pkg_view -d %s %s%s %s%s %sadd %s\n",
1196*a824f5a1SJean-Baptiste Boric 			BINDIR, pkgdb_get_dir(),
1197*a824f5a1SJean-Baptiste Boric 			View ? "-w " : "", View ? View : "",
1198*a824f5a1SJean-Baptiste Boric 			Viewbase ? "-W " : "", Viewbase ? Viewbase : "",
1199*a824f5a1SJean-Baptiste Boric 			Verbose ? "-v " : "", pkg->pkgname);
1200*a824f5a1SJean-Baptiste Boric 	}
1201*a824f5a1SJean-Baptiste Boric 
1202*a824f5a1SJean-Baptiste Boric 	fexec_skipempty(BINDIR "/pkg_view", "-d", pkgdb_get_dir(),
1203*a824f5a1SJean-Baptiste Boric 			View ? "-w " : "", View ? View : "",
1204*a824f5a1SJean-Baptiste Boric 			Viewbase ? "-W " : "", Viewbase ? Viewbase : "",
1205*a824f5a1SJean-Baptiste Boric 			Verbose ? "-v " : "", "add", pkg->pkgname,
1206*a824f5a1SJean-Baptiste Boric 			(void *)NULL);
1207*a824f5a1SJean-Baptiste Boric }
1208*a824f5a1SJean-Baptiste Boric 
1209*a824f5a1SJean-Baptiste Boric static int
preserve_meta_data_file(struct pkg_task * pkg,const char * name)1210*a824f5a1SJean-Baptiste Boric preserve_meta_data_file(struct pkg_task *pkg, const char *name)
1211*a824f5a1SJean-Baptiste Boric {
1212*a824f5a1SJean-Baptiste Boric 	char *old_file, *new_file;
1213*a824f5a1SJean-Baptiste Boric 	int rv;
1214*a824f5a1SJean-Baptiste Boric 
1215*a824f5a1SJean-Baptiste Boric 	if (Fake)
1216*a824f5a1SJean-Baptiste Boric 		return 0;
1217*a824f5a1SJean-Baptiste Boric 
1218*a824f5a1SJean-Baptiste Boric 	old_file = pkgdb_pkg_file(pkg->other_version, name);
1219*a824f5a1SJean-Baptiste Boric 	new_file = xasprintf("%s/%s", pkg->install_logdir, name);
1220*a824f5a1SJean-Baptiste Boric 	rv = 0;
1221*a824f5a1SJean-Baptiste Boric 	if (rename(old_file, new_file) == -1 && errno != ENOENT) {
1222*a824f5a1SJean-Baptiste Boric 		warn("Can't move %s from %s to %s", name, old_file, new_file);
1223*a824f5a1SJean-Baptiste Boric 		rv = -1;
1224*a824f5a1SJean-Baptiste Boric 	}
1225*a824f5a1SJean-Baptiste Boric 	free(old_file);
1226*a824f5a1SJean-Baptiste Boric 	free(new_file);
1227*a824f5a1SJean-Baptiste Boric 	return rv;
1228*a824f5a1SJean-Baptiste Boric }
1229*a824f5a1SJean-Baptiste Boric 
1230*a824f5a1SJean-Baptiste Boric static int
start_replacing(struct pkg_task * pkg)1231*a824f5a1SJean-Baptiste Boric start_replacing(struct pkg_task *pkg)
1232*a824f5a1SJean-Baptiste Boric {
1233*a824f5a1SJean-Baptiste Boric 	if (preserve_meta_data_file(pkg, REQUIRED_BY_FNAME))
1234*a824f5a1SJean-Baptiste Boric 		return -1;
1235*a824f5a1SJean-Baptiste Boric 
1236*a824f5a1SJean-Baptiste Boric 	if (preserve_meta_data_file(pkg, PRESERVE_FNAME))
1237*a824f5a1SJean-Baptiste Boric 		return -1;
1238*a824f5a1SJean-Baptiste Boric 
1239*a824f5a1SJean-Baptiste Boric 	if (pkg->meta_data.meta_installed_info == NULL &&
1240*a824f5a1SJean-Baptiste Boric 	    preserve_meta_data_file(pkg, INSTALLED_INFO_FNAME))
1241*a824f5a1SJean-Baptiste Boric 		return -1;
1242*a824f5a1SJean-Baptiste Boric 
1243*a824f5a1SJean-Baptiste Boric 	if (Verbose || Fake) {
1244*a824f5a1SJean-Baptiste Boric 		printf("%s/pkg_delete -K %s -p %s%s%s '%s'\n",
1245*a824f5a1SJean-Baptiste Boric 			BINDIR, pkgdb_get_dir(), pkg->prefix,
1246*a824f5a1SJean-Baptiste Boric 			Destdir ? " -P ": "", Destdir ? Destdir : "",
1247*a824f5a1SJean-Baptiste Boric 			pkg->other_version);
1248*a824f5a1SJean-Baptiste Boric 	}
1249*a824f5a1SJean-Baptiste Boric 	if (!Fake)
1250*a824f5a1SJean-Baptiste Boric 		fexec_skipempty(BINDIR "/pkg_delete", "-K", pkgdb_get_dir(),
1251*a824f5a1SJean-Baptiste Boric 		    "-p", pkg->prefix,
1252*a824f5a1SJean-Baptiste Boric 		    Destdir ? "-P": "", Destdir ? Destdir : "",
1253*a824f5a1SJean-Baptiste Boric 		    pkg->other_version, NULL);
1254*a824f5a1SJean-Baptiste Boric 
1255*a824f5a1SJean-Baptiste Boric 	/* XXX Check return value and do what? */
1256*a824f5a1SJean-Baptiste Boric 	return 0;
1257*a824f5a1SJean-Baptiste Boric }
1258*a824f5a1SJean-Baptiste Boric 
check_input(const char * line,size_t len)1259*a824f5a1SJean-Baptiste Boric static int check_input(const char *line, size_t len)
1260*a824f5a1SJean-Baptiste Boric {
1261*a824f5a1SJean-Baptiste Boric 	if (line == NULL || len == 0)
1262*a824f5a1SJean-Baptiste Boric 		return 1;
1263*a824f5a1SJean-Baptiste Boric 	switch (*line) {
1264*a824f5a1SJean-Baptiste Boric 	case 'Y':
1265*a824f5a1SJean-Baptiste Boric 	case 'y':
1266*a824f5a1SJean-Baptiste Boric 	case 'T':
1267*a824f5a1SJean-Baptiste Boric 	case 't':
1268*a824f5a1SJean-Baptiste Boric 	case '1':
1269*a824f5a1SJean-Baptiste Boric 		return 0;
1270*a824f5a1SJean-Baptiste Boric 	default:
1271*a824f5a1SJean-Baptiste Boric 		return 1;
1272*a824f5a1SJean-Baptiste Boric 	}
1273*a824f5a1SJean-Baptiste Boric }
1274*a824f5a1SJean-Baptiste Boric 
1275*a824f5a1SJean-Baptiste Boric static int
check_signature(struct pkg_task * pkg,int invalid_sig)1276*a824f5a1SJean-Baptiste Boric check_signature(struct pkg_task *pkg, int invalid_sig)
1277*a824f5a1SJean-Baptiste Boric {
1278*a824f5a1SJean-Baptiste Boric 	char *line;
1279*a824f5a1SJean-Baptiste Boric 	size_t len;
1280*a824f5a1SJean-Baptiste Boric 
1281*a824f5a1SJean-Baptiste Boric 	if (strcasecmp(verified_installation, "never") == 0)
1282*a824f5a1SJean-Baptiste Boric 		return 0;
1283*a824f5a1SJean-Baptiste Boric 	if (strcasecmp(verified_installation, "always") == 0) {
1284*a824f5a1SJean-Baptiste Boric 		if (invalid_sig)
1285*a824f5a1SJean-Baptiste Boric 			warnx("No valid signature found, rejected");
1286*a824f5a1SJean-Baptiste Boric 		return invalid_sig;
1287*a824f5a1SJean-Baptiste Boric 	}
1288*a824f5a1SJean-Baptiste Boric 	if (strcasecmp(verified_installation, "trusted") == 0) {
1289*a824f5a1SJean-Baptiste Boric 		if (!invalid_sig)
1290*a824f5a1SJean-Baptiste Boric 			return 0;
1291*a824f5a1SJean-Baptiste Boric 		fprintf(stderr, "No valid signature found for %s.\n",
1292*a824f5a1SJean-Baptiste Boric 		    pkg->pkgname);
1293*a824f5a1SJean-Baptiste Boric 		fprintf(stderr,
1294*a824f5a1SJean-Baptiste Boric 		    "Do you want to proceed with the installation [y/n]?\n");
1295*a824f5a1SJean-Baptiste Boric 		line = fgetln(stdin, &len);
1296*a824f5a1SJean-Baptiste Boric 		if (check_input(line, len)) {
1297*a824f5a1SJean-Baptiste Boric 			fprintf(stderr, "Cancelling installation\n");
1298*a824f5a1SJean-Baptiste Boric 			return 1;
1299*a824f5a1SJean-Baptiste Boric 		}
1300*a824f5a1SJean-Baptiste Boric 		return 0;
1301*a824f5a1SJean-Baptiste Boric 	}
1302*a824f5a1SJean-Baptiste Boric 	if (strcasecmp(verified_installation, "interactive") == 0) {
1303*a824f5a1SJean-Baptiste Boric 		fprintf(stderr, "Do you want to proceed with "
1304*a824f5a1SJean-Baptiste Boric 		    "the installation of %s [y/n]?\n", pkg->pkgname);
1305*a824f5a1SJean-Baptiste Boric 		line = fgetln(stdin, &len);
1306*a824f5a1SJean-Baptiste Boric 		if (check_input(line, len)) {
1307*a824f5a1SJean-Baptiste Boric 			fprintf(stderr, "Cancelling installation\n");
1308*a824f5a1SJean-Baptiste Boric 			return 1;
1309*a824f5a1SJean-Baptiste Boric 		}
1310*a824f5a1SJean-Baptiste Boric 		return 0;
1311*a824f5a1SJean-Baptiste Boric 	}
1312*a824f5a1SJean-Baptiste Boric 	warnx("Unknown value of configuration variable VERIFIED_INSTALLATION");
1313*a824f5a1SJean-Baptiste Boric 	return 1;
1314*a824f5a1SJean-Baptiste Boric }
1315*a824f5a1SJean-Baptiste Boric 
1316*a824f5a1SJean-Baptiste Boric static int
check_vulnerable(struct pkg_task * pkg)1317*a824f5a1SJean-Baptiste Boric check_vulnerable(struct pkg_task *pkg)
1318*a824f5a1SJean-Baptiste Boric {
1319*a824f5a1SJean-Baptiste Boric 	static struct pkg_vulnerabilities *pv;
1320*a824f5a1SJean-Baptiste Boric 	int require_check;
1321*a824f5a1SJean-Baptiste Boric 	char *line;
1322*a824f5a1SJean-Baptiste Boric 	size_t len;
1323*a824f5a1SJean-Baptiste Boric 
1324*a824f5a1SJean-Baptiste Boric 	if (strcasecmp(check_vulnerabilities, "never") == 0)
1325*a824f5a1SJean-Baptiste Boric 		return 0;
1326*a824f5a1SJean-Baptiste Boric 	else if (strcasecmp(check_vulnerabilities, "always") == 0)
1327*a824f5a1SJean-Baptiste Boric 		require_check = 1;
1328*a824f5a1SJean-Baptiste Boric 	else if (strcasecmp(check_vulnerabilities, "interactive") == 0)
1329*a824f5a1SJean-Baptiste Boric 		require_check = 0;
1330*a824f5a1SJean-Baptiste Boric 	else {
1331*a824f5a1SJean-Baptiste Boric 		warnx("Unknown value of the configuration variable"
1332*a824f5a1SJean-Baptiste Boric 		    "CHECK_VULNERABILITIES");
1333*a824f5a1SJean-Baptiste Boric 		return 1;
1334*a824f5a1SJean-Baptiste Boric 	}
1335*a824f5a1SJean-Baptiste Boric 
1336*a824f5a1SJean-Baptiste Boric 	if (pv == NULL) {
1337*a824f5a1SJean-Baptiste Boric 		pv = read_pkg_vulnerabilities_file(pkg_vulnerabilities_file,
1338*a824f5a1SJean-Baptiste Boric 		    require_check, 0);
1339*a824f5a1SJean-Baptiste Boric 		if (pv == NULL)
1340*a824f5a1SJean-Baptiste Boric 			return require_check;
1341*a824f5a1SJean-Baptiste Boric 	}
1342*a824f5a1SJean-Baptiste Boric 
1343*a824f5a1SJean-Baptiste Boric 	if (!audit_package(pv, pkg->pkgname, NULL, 2))
1344*a824f5a1SJean-Baptiste Boric 		return 0;
1345*a824f5a1SJean-Baptiste Boric 
1346*a824f5a1SJean-Baptiste Boric 	if (require_check)
1347*a824f5a1SJean-Baptiste Boric 		return 1;
1348*a824f5a1SJean-Baptiste Boric 
1349*a824f5a1SJean-Baptiste Boric 	fprintf(stderr, "Do you want to proceed with the installation of %s"
1350*a824f5a1SJean-Baptiste Boric 	    " [y/n]?\n", pkg->pkgname);
1351*a824f5a1SJean-Baptiste Boric 	line = fgetln(stdin, &len);
1352*a824f5a1SJean-Baptiste Boric 	if (check_input(line, len)) {
1353*a824f5a1SJean-Baptiste Boric 		fprintf(stderr, "Cancelling installation\n");
1354*a824f5a1SJean-Baptiste Boric 		return 1;
1355*a824f5a1SJean-Baptiste Boric 	}
1356*a824f5a1SJean-Baptiste Boric 	return 0;
1357*a824f5a1SJean-Baptiste Boric }
1358*a824f5a1SJean-Baptiste Boric 
1359*a824f5a1SJean-Baptiste Boric static int
check_license(struct pkg_task * pkg)1360*a824f5a1SJean-Baptiste Boric check_license(struct pkg_task *pkg)
1361*a824f5a1SJean-Baptiste Boric {
1362*a824f5a1SJean-Baptiste Boric 	if (LicenseCheck == 0)
1363*a824f5a1SJean-Baptiste Boric 		return 0;
1364*a824f5a1SJean-Baptiste Boric 
1365*a824f5a1SJean-Baptiste Boric 	if ((pkg->buildinfo[BI_LICENSE] == NULL ||
1366*a824f5a1SJean-Baptiste Boric 	     *pkg->buildinfo[BI_LICENSE] == '\0')) {
1367*a824f5a1SJean-Baptiste Boric 
1368*a824f5a1SJean-Baptiste Boric 		if (LicenseCheck == 1)
1369*a824f5a1SJean-Baptiste Boric 			return 0;
1370*a824f5a1SJean-Baptiste Boric 		warnx("No LICENSE set for package `%s'", pkg->pkgname);
1371*a824f5a1SJean-Baptiste Boric 		return 1;
1372*a824f5a1SJean-Baptiste Boric 	}
1373*a824f5a1SJean-Baptiste Boric 
1374*a824f5a1SJean-Baptiste Boric 	switch (acceptable_license(pkg->buildinfo[BI_LICENSE])) {
1375*a824f5a1SJean-Baptiste Boric 	case 0:
1376*a824f5a1SJean-Baptiste Boric 		warnx("License `%s' of package `%s' is not acceptable",
1377*a824f5a1SJean-Baptiste Boric 		    pkg->buildinfo[BI_LICENSE], pkg->pkgname);
1378*a824f5a1SJean-Baptiste Boric 		return 1;
1379*a824f5a1SJean-Baptiste Boric 	case 1:
1380*a824f5a1SJean-Baptiste Boric 		return 0;
1381*a824f5a1SJean-Baptiste Boric 	default:
1382*a824f5a1SJean-Baptiste Boric 		warnx("Invalid LICENSE for package `%s'", pkg->pkgname);
1383*a824f5a1SJean-Baptiste Boric 		return 1;
1384*a824f5a1SJean-Baptiste Boric 	}
1385*a824f5a1SJean-Baptiste Boric }
1386*a824f5a1SJean-Baptiste Boric 
1387*a824f5a1SJean-Baptiste Boric /*
1388*a824f5a1SJean-Baptiste Boric  * Install a single package.
1389*a824f5a1SJean-Baptiste Boric  */
1390*a824f5a1SJean-Baptiste Boric static int
pkg_do(const char * pkgpath,int mark_automatic,int top_level)1391*a824f5a1SJean-Baptiste Boric pkg_do(const char *pkgpath, int mark_automatic, int top_level)
1392*a824f5a1SJean-Baptiste Boric {
1393*a824f5a1SJean-Baptiste Boric 	char *archive_name;
1394*a824f5a1SJean-Baptiste Boric 	int status, invalid_sig;
1395*a824f5a1SJean-Baptiste Boric 	struct pkg_task *pkg;
1396*a824f5a1SJean-Baptiste Boric 
1397*a824f5a1SJean-Baptiste Boric 	pkg = xcalloc(1, sizeof(*pkg));
1398*a824f5a1SJean-Baptiste Boric 
1399*a824f5a1SJean-Baptiste Boric 	status = -1;
1400*a824f5a1SJean-Baptiste Boric 
1401*a824f5a1SJean-Baptiste Boric 	pkg->archive = find_archive(pkgpath, top_level, &archive_name);
1402*a824f5a1SJean-Baptiste Boric 	if (pkg->archive == NULL) {
1403*a824f5a1SJean-Baptiste Boric 		warnx("no pkg found for '%s', sorry.", pkgpath);
1404*a824f5a1SJean-Baptiste Boric 		goto clean_find_archive;
1405*a824f5a1SJean-Baptiste Boric 	}
1406*a824f5a1SJean-Baptiste Boric 
1407*a824f5a1SJean-Baptiste Boric 	invalid_sig = pkg_verify_signature(archive_name, &pkg->archive, &pkg->entry,
1408*a824f5a1SJean-Baptiste Boric 	    &pkg->pkgname);
1409*a824f5a1SJean-Baptiste Boric 	free(archive_name);
1410*a824f5a1SJean-Baptiste Boric 
1411*a824f5a1SJean-Baptiste Boric 	if (pkg->archive == NULL)
1412*a824f5a1SJean-Baptiste Boric 		goto clean_memory;
1413*a824f5a1SJean-Baptiste Boric 
1414*a824f5a1SJean-Baptiste Boric 	if (read_meta_data(pkg))
1415*a824f5a1SJean-Baptiste Boric 		goto clean_memory;
1416*a824f5a1SJean-Baptiste Boric 
1417*a824f5a1SJean-Baptiste Boric 	/* Parse PLIST early, so that messages can use real package name. */
1418*a824f5a1SJean-Baptiste Boric 	if (pkg_parse_plist(pkg))
1419*a824f5a1SJean-Baptiste Boric 		goto clean_memory;
1420*a824f5a1SJean-Baptiste Boric 
1421*a824f5a1SJean-Baptiste Boric 	if (check_signature(pkg, invalid_sig))
1422*a824f5a1SJean-Baptiste Boric 		goto clean_memory;
1423*a824f5a1SJean-Baptiste Boric 
1424*a824f5a1SJean-Baptiste Boric 	if (read_buildinfo(pkg))
1425*a824f5a1SJean-Baptiste Boric 		goto clean_memory;
1426*a824f5a1SJean-Baptiste Boric 
1427*a824f5a1SJean-Baptiste Boric 	if (check_pkgtools_version(pkg))
1428*a824f5a1SJean-Baptiste Boric 		goto clean_memory;
1429*a824f5a1SJean-Baptiste Boric 
1430*a824f5a1SJean-Baptiste Boric 	if (check_vulnerable(pkg))
1431*a824f5a1SJean-Baptiste Boric 		goto clean_memory;
1432*a824f5a1SJean-Baptiste Boric 
1433*a824f5a1SJean-Baptiste Boric 	if (check_license(pkg))
1434*a824f5a1SJean-Baptiste Boric 		goto clean_memory;
1435*a824f5a1SJean-Baptiste Boric 
1436*a824f5a1SJean-Baptiste Boric 	if (pkg->meta_data.meta_mtree != NULL)
1437*a824f5a1SJean-Baptiste Boric 		warnx("mtree specification in pkg `%s' ignored", pkg->pkgname);
1438*a824f5a1SJean-Baptiste Boric 
1439*a824f5a1SJean-Baptiste Boric 	if (pkg->meta_data.meta_views != NULL) {
1440*a824f5a1SJean-Baptiste Boric 		pkg->logdir = xstrdup(pkg->prefix);
1441*a824f5a1SJean-Baptiste Boric 		pkgdb_set_dir(dirname_of(pkg->logdir), 4);
1442*a824f5a1SJean-Baptiste Boric 	} else {
1443*a824f5a1SJean-Baptiste Boric 		pkg->logdir = xasprintf("%s/%s", config_pkg_dbdir, pkg->pkgname);
1444*a824f5a1SJean-Baptiste Boric 	}
1445*a824f5a1SJean-Baptiste Boric 
1446*a824f5a1SJean-Baptiste Boric 	if (Destdir != NULL)
1447*a824f5a1SJean-Baptiste Boric 		pkg->install_logdir = xasprintf("%s/%s", Destdir, pkg->logdir);
1448*a824f5a1SJean-Baptiste Boric 	else
1449*a824f5a1SJean-Baptiste Boric 		pkg->install_logdir = xstrdup(pkg->logdir);
1450*a824f5a1SJean-Baptiste Boric 
1451*a824f5a1SJean-Baptiste Boric 	if (NoRecord && !Fake) {
1452*a824f5a1SJean-Baptiste Boric 		const char *tmpdir;
1453*a824f5a1SJean-Baptiste Boric 
1454*a824f5a1SJean-Baptiste Boric 		tmpdir = getenv("TMPDIR");
1455*a824f5a1SJean-Baptiste Boric 		if (tmpdir == NULL)
1456*a824f5a1SJean-Baptiste Boric 			tmpdir = "/tmp";
1457*a824f5a1SJean-Baptiste Boric 
1458*a824f5a1SJean-Baptiste Boric 		free(pkg->install_logdir);
1459*a824f5a1SJean-Baptiste Boric 		pkg->install_logdir = xasprintf("%s/pkg_install.XXXXXX", tmpdir);
1460*a824f5a1SJean-Baptiste Boric 		/* XXX pkg_add -u... */
1461*a824f5a1SJean-Baptiste Boric 		if (mkdtemp(pkg->install_logdir) == NULL) {
1462*a824f5a1SJean-Baptiste Boric 			warn("mkdtemp failed");
1463*a824f5a1SJean-Baptiste Boric 			goto clean_memory;
1464*a824f5a1SJean-Baptiste Boric 		}
1465*a824f5a1SJean-Baptiste Boric 	}
1466*a824f5a1SJean-Baptiste Boric 
1467*a824f5a1SJean-Baptiste Boric 	switch (check_already_installed(pkg)) {
1468*a824f5a1SJean-Baptiste Boric 	case 0:
1469*a824f5a1SJean-Baptiste Boric 		status = 0;
1470*a824f5a1SJean-Baptiste Boric 		goto clean_memory;
1471*a824f5a1SJean-Baptiste Boric 	case 1:
1472*a824f5a1SJean-Baptiste Boric 		break;
1473*a824f5a1SJean-Baptiste Boric 	case -1:
1474*a824f5a1SJean-Baptiste Boric 		goto clean_memory;
1475*a824f5a1SJean-Baptiste Boric 	}
1476*a824f5a1SJean-Baptiste Boric 
1477*a824f5a1SJean-Baptiste Boric 	if (check_platform(pkg))
1478*a824f5a1SJean-Baptiste Boric 		goto clean_memory;
1479*a824f5a1SJean-Baptiste Boric 
1480*a824f5a1SJean-Baptiste Boric 	if (check_other_installed(pkg))
1481*a824f5a1SJean-Baptiste Boric 		goto clean_memory;
1482*a824f5a1SJean-Baptiste Boric 
1483*a824f5a1SJean-Baptiste Boric 	if (check_explicit_conflict(pkg))
1484*a824f5a1SJean-Baptiste Boric 		goto clean_memory;
1485*a824f5a1SJean-Baptiste Boric 
1486*a824f5a1SJean-Baptiste Boric 	if (check_implicit_conflict(pkg))
1487*a824f5a1SJean-Baptiste Boric 		goto clean_memory;
1488*a824f5a1SJean-Baptiste Boric 
1489*a824f5a1SJean-Baptiste Boric 	if (pkg->other_version != NULL) {
1490*a824f5a1SJean-Baptiste Boric 		/*
1491*a824f5a1SJean-Baptiste Boric 		 * Replacing an existing package.
1492*a824f5a1SJean-Baptiste Boric 		 * Write meta-data, get rid of the old version,
1493*a824f5a1SJean-Baptiste Boric 		 * install/update dependencies and finally extract.
1494*a824f5a1SJean-Baptiste Boric 		 */
1495*a824f5a1SJean-Baptiste Boric 		if (write_meta_data(pkg))
1496*a824f5a1SJean-Baptiste Boric 			goto nuke_pkgdb;
1497*a824f5a1SJean-Baptiste Boric 
1498*a824f5a1SJean-Baptiste Boric 		if (start_replacing(pkg))
1499*a824f5a1SJean-Baptiste Boric 			goto nuke_pkgdb;
1500*a824f5a1SJean-Baptiste Boric 
1501*a824f5a1SJean-Baptiste Boric 		if (pkg->install_logdir_real) {
1502*a824f5a1SJean-Baptiste Boric 			rename(pkg->install_logdir, pkg->install_logdir_real);
1503*a824f5a1SJean-Baptiste Boric 			free(pkg->install_logdir);
1504*a824f5a1SJean-Baptiste Boric 			pkg->install_logdir = pkg->install_logdir_real;
1505*a824f5a1SJean-Baptiste Boric 			pkg->install_logdir_real = NULL;
1506*a824f5a1SJean-Baptiste Boric 		}
1507*a824f5a1SJean-Baptiste Boric 
1508*a824f5a1SJean-Baptiste Boric 		if (check_dependencies(pkg))
1509*a824f5a1SJean-Baptiste Boric 			goto nuke_pkgdb;
1510*a824f5a1SJean-Baptiste Boric 	} else {
1511*a824f5a1SJean-Baptiste Boric 		/*
1512*a824f5a1SJean-Baptiste Boric 		 * Normal installation.
1513*a824f5a1SJean-Baptiste Boric 		 * Install/update dependencies first and
1514*a824f5a1SJean-Baptiste Boric 		 * write the current package to disk afterwards.
1515*a824f5a1SJean-Baptiste Boric 		 */
1516*a824f5a1SJean-Baptiste Boric 		if (check_dependencies(pkg))
1517*a824f5a1SJean-Baptiste Boric 			goto clean_memory;
1518*a824f5a1SJean-Baptiste Boric 
1519*a824f5a1SJean-Baptiste Boric 		if (write_meta_data(pkg))
1520*a824f5a1SJean-Baptiste Boric 			goto nuke_pkgdb;
1521*a824f5a1SJean-Baptiste Boric 	}
1522*a824f5a1SJean-Baptiste Boric 
1523*a824f5a1SJean-Baptiste Boric 	if (run_install_script(pkg, "PRE-INSTALL"))
1524*a824f5a1SJean-Baptiste Boric 		goto nuke_pkgdb;
1525*a824f5a1SJean-Baptiste Boric 
1526*a824f5a1SJean-Baptiste Boric 	if (extract_files(pkg))
1527*a824f5a1SJean-Baptiste Boric 		goto nuke_pkg;
1528*a824f5a1SJean-Baptiste Boric 
1529*a824f5a1SJean-Baptiste Boric 	if (run_install_script(pkg, "POST-INSTALL"))
1530*a824f5a1SJean-Baptiste Boric 		goto nuke_pkgdb;
1531*a824f5a1SJean-Baptiste Boric 
1532*a824f5a1SJean-Baptiste Boric 	/* XXX keep +INSTALL_INFO for updates? */
1533*a824f5a1SJean-Baptiste Boric 	/* XXX keep +PRESERVE for updates? */
1534*a824f5a1SJean-Baptiste Boric 	if (mark_automatic)
1535*a824f5a1SJean-Baptiste Boric 		mark_as_automatic_installed(pkg->pkgname, 1);
1536*a824f5a1SJean-Baptiste Boric 
1537*a824f5a1SJean-Baptiste Boric 	pkg_register_depends(pkg);
1538*a824f5a1SJean-Baptiste Boric 
1539*a824f5a1SJean-Baptiste Boric 	if (Verbose)
1540*a824f5a1SJean-Baptiste Boric 		printf("Package %s registered in %s\n", pkg->pkgname, pkg->install_logdir);
1541*a824f5a1SJean-Baptiste Boric 
1542*a824f5a1SJean-Baptiste Boric 	if (pkg->meta_data.meta_display != NULL)
1543*a824f5a1SJean-Baptiste Boric 		fputs(pkg->meta_data.meta_display, stdout);
1544*a824f5a1SJean-Baptiste Boric 
1545*a824f5a1SJean-Baptiste Boric 	pkg_register_views(pkg);
1546*a824f5a1SJean-Baptiste Boric 
1547*a824f5a1SJean-Baptiste Boric 	status = 0;
1548*a824f5a1SJean-Baptiste Boric 	goto clean_memory;
1549*a824f5a1SJean-Baptiste Boric 
1550*a824f5a1SJean-Baptiste Boric nuke_pkg:
1551*a824f5a1SJean-Baptiste Boric 	if (!Fake) {
1552*a824f5a1SJean-Baptiste Boric 		if (pkg->other_version) {
1553*a824f5a1SJean-Baptiste Boric 			warnx("Updating of %s to %s failed.",
1554*a824f5a1SJean-Baptiste Boric 			    pkg->other_version, pkg->pkgname);
1555*a824f5a1SJean-Baptiste Boric 			warnx("Remember to run pkg_admin rebuild-tree after fixing this.");
1556*a824f5a1SJean-Baptiste Boric 		}
1557*a824f5a1SJean-Baptiste Boric 		delete_package(FALSE, &pkg->plist, FALSE, Destdir);
1558*a824f5a1SJean-Baptiste Boric 	}
1559*a824f5a1SJean-Baptiste Boric 
1560*a824f5a1SJean-Baptiste Boric nuke_pkgdb:
1561*a824f5a1SJean-Baptiste Boric 	if (!Fake) {
1562*a824f5a1SJean-Baptiste Boric 		if (recursive_remove(pkg->install_logdir, 1))
1563*a824f5a1SJean-Baptiste Boric 			warn("Couldn't remove %s", pkg->install_logdir);
1564*a824f5a1SJean-Baptiste Boric 		free(pkg->install_logdir_real);
1565*a824f5a1SJean-Baptiste Boric 		free(pkg->install_logdir);
1566*a824f5a1SJean-Baptiste Boric 		free(pkg->logdir);
1567*a824f5a1SJean-Baptiste Boric 		pkg->install_logdir_real = NULL;
1568*a824f5a1SJean-Baptiste Boric 		pkg->install_logdir = NULL;
1569*a824f5a1SJean-Baptiste Boric 		pkg->logdir = NULL;
1570*a824f5a1SJean-Baptiste Boric 	}
1571*a824f5a1SJean-Baptiste Boric 
1572*a824f5a1SJean-Baptiste Boric clean_memory:
1573*a824f5a1SJean-Baptiste Boric 	if (pkg->logdir != NULL && NoRecord && !Fake) {
1574*a824f5a1SJean-Baptiste Boric 		if (recursive_remove(pkg->install_logdir, 1))
1575*a824f5a1SJean-Baptiste Boric 			warn("Couldn't remove %s", pkg->install_logdir);
1576*a824f5a1SJean-Baptiste Boric 	}
1577*a824f5a1SJean-Baptiste Boric 	free(pkg->install_prefix);
1578*a824f5a1SJean-Baptiste Boric 	free(pkg->install_logdir_real);
1579*a824f5a1SJean-Baptiste Boric 	free(pkg->install_logdir);
1580*a824f5a1SJean-Baptiste Boric 	free(pkg->logdir);
1581*a824f5a1SJean-Baptiste Boric 	free_buildinfo(pkg);
1582*a824f5a1SJean-Baptiste Boric 	free_plist(&pkg->plist);
1583*a824f5a1SJean-Baptiste Boric 	free_meta_data(pkg);
1584*a824f5a1SJean-Baptiste Boric 	if (pkg->archive)
1585*a824f5a1SJean-Baptiste Boric 		archive_read_finish(pkg->archive);
1586*a824f5a1SJean-Baptiste Boric 	free(pkg->other_version);
1587*a824f5a1SJean-Baptiste Boric 	free(pkg->pkgname);
1588*a824f5a1SJean-Baptiste Boric clean_find_archive:
1589*a824f5a1SJean-Baptiste Boric 	free(pkg);
1590*a824f5a1SJean-Baptiste Boric 	return status;
1591*a824f5a1SJean-Baptiste Boric }
1592*a824f5a1SJean-Baptiste Boric 
1593*a824f5a1SJean-Baptiste Boric int
pkg_perform(lpkg_head_t * pkgs)1594*a824f5a1SJean-Baptiste Boric pkg_perform(lpkg_head_t *pkgs)
1595*a824f5a1SJean-Baptiste Boric {
1596*a824f5a1SJean-Baptiste Boric 	int     errors = 0;
1597*a824f5a1SJean-Baptiste Boric 	lpkg_t *lpp;
1598*a824f5a1SJean-Baptiste Boric 
1599*a824f5a1SJean-Baptiste Boric 	while ((lpp = TAILQ_FIRST(pkgs)) != NULL) {
1600*a824f5a1SJean-Baptiste Boric 		if (pkg_do(lpp->lp_name, Automatic, 1))
1601*a824f5a1SJean-Baptiste Boric 			++errors;
1602*a824f5a1SJean-Baptiste Boric 		TAILQ_REMOVE(pkgs, lpp, lp_link);
1603*a824f5a1SJean-Baptiste Boric 		free_lpkg(lpp);
1604*a824f5a1SJean-Baptiste Boric 	}
1605*a824f5a1SJean-Baptiste Boric 
1606*a824f5a1SJean-Baptiste Boric 	return errors;
1607*a824f5a1SJean-Baptiste Boric }
1608