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