diff --git a/distrib/sets/lists/minix/mi b/distrib/sets/lists/minix/mi index d92484ffc..bab08efc0 100644 --- a/distrib/sets/lists/minix/mi +++ b/distrib/sets/lists/minix/mi @@ -2340,6 +2340,7 @@ ./usr/man/man1/basename.1 minix-sys ./usr/man/man1/bdes.1 minix-sys ./usr/man/man1/bg.1 minix-sys +./usr/man/man1/bpm.1 minix-sys ./usr/man/man1/break.1 minix-sys obsolete ./usr/man/man1/bsdtar.1 minix-sys ./usr/man/man1/bsfilt.1 minix-sys @@ -2557,6 +2558,11 @@ ./usr/man/man1/pathchk.1 minix-sys ./usr/man/man1/pax.1 minix-sys ./usr/man/man1/ping.1 minix-sys obsolete +./usr/man/man1/pkg_add.1 minix-sys +./usr/man/man1/pkg_admin.1 minix-sys +./usr/man/man1/pkg_create.1 minix-sys +./usr/man/man1/pkg_delete.1 minix-sys +./usr/man/man1/pkg_info.1 minix-sys ./usr/man/man1/pkg_view.1 minix-sys obsolete ./usr/man/man1/playwave.1 minix-sys ./usr/man/man1/popd.1 minix-sys @@ -5339,10 +5345,13 @@ ./usr/preserve minix-sys ./usr/run minix-sys ./usr/sbin minix-sys +./usr/sbin/audit-packages minix-sys +./usr/sbin/bpm minix-sys ./usr/sbin/btrace minix-sys ./usr/sbin/chown minix-sys ./usr/sbin/chroot minix-sys ./usr/sbin/diskctl minix-sys +./usr/sbin/download-vulnerability-list minix-sys ./usr/sbin/fbdctl minix-sys ./usr/sbin/group minix-sys ./usr/sbin/groupadd minix-sys @@ -5358,6 +5367,11 @@ ./usr/sbin/mkproto minix-sys ./usr/sbin/mtree minix-sys ./usr/sbin/newfs_mfs minix-sys +./usr/sbin/pkg_add minix-sys +./usr/sbin/pkg_admin minix-sys +./usr/sbin/pkg_create minix-sys +./usr/sbin/pkg_delete minix-sys +./usr/sbin/pkg_info minix-sys ./usr/sbin/postinstall minix-sys ./usr/sbin/pwd_mkdb minix-sys ./usr/sbin/rdate minix-sys diff --git a/external/bsd/Makefile b/external/bsd/Makefile index 5ffc60d61..6776000d3 100644 --- a/external/bsd/Makefile +++ b/external/bsd/Makefile @@ -10,7 +10,7 @@ SUBDIR= byacc fetch file flex less \ SUBDIR+= atf .endif .if (${MKCRYPTO} != "no") -#SUBDIR+= pkg_install +SUBDIR+= pkg_install .endif # IP Filter .if (${MKIPFILTER} != "no") diff --git a/external/bsd/pkg_install/Makefile b/external/bsd/pkg_install/Makefile new file mode 100644 index 000000000..210e0f7ac --- /dev/null +++ b/external/bsd/pkg_install/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2008/09/30 19:19:56 joerg Exp $ + +SUBDIR= lib .WAIT sbin + +.include diff --git a/external/bsd/pkg_install/Makefile.inc b/external/bsd/pkg_install/Makefile.inc new file mode 100644 index 000000000..d6de60e41 --- /dev/null +++ b/external/bsd/pkg_install/Makefile.inc @@ -0,0 +1,13 @@ +# $NetBSD: Makefile.inc,v 1.4 2011/09/16 16:41:20 joerg Exp $ + +DIST= ${NETBSDSRCDIR}/external/bsd/pkg_install/dist + +USE_FORT?=yes # network client + +CPPFLAGS+=-I${DIST}/lib +CPPFLAGS+=-I${NETBSDSRCDIR}/external/bsd/pkg_install/lib +CPPFLAGS+=-DHAVE_CONFIG_H -DNETBSD -DHAVE_SSL +CPPFLAGS+=-DSYSCONFDIR='"/etc"' + +WARNS= 4 +CWARNFLAGS+= -Wno-missing-noreturn diff --git a/external/bsd/pkg_install/dist/add/add.h b/external/bsd/pkg_install/dist/add/add.h new file mode 100644 index 000000000..cc26e75fb --- /dev/null +++ b/external/bsd/pkg_install/dist/add/add.h @@ -0,0 +1,50 @@ +/* $NetBSD: add.h,v 1.1.1.7 2011/02/18 22:32:27 aymeric Exp $ */ + +/* from FreeBSD Id: add.h,v 1.8 1997/02/22 16:09:15 peter Exp */ + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Include and define various things wanted by the add command. + * + */ + +#ifndef _INST_ADD_H_INCLUDE +#define _INST_ADD_H_INCLUDE + +extern char *Destdir; +extern char *OverrideMachine; +extern char *Prefix; +extern char *View; +extern char *Viewbase; +extern Boolean NoView; +extern Boolean NoInstall; +extern Boolean NoRecord; +extern Boolean Force; +extern Boolean Automatic; +extern int LicenseCheck; +extern int Replace; +extern int ReplaceSame; + +extern Boolean ForceDepends; +extern Boolean ForceDepending; + +int make_hierarchy(char *); +void apply_perms(char *, char **, int); + +int pkg_perform(lpkg_head_t *); + +#endif /* _INST_ADD_H_INCLUDE */ diff --git a/external/bsd/pkg_install/dist/add/main.c b/external/bsd/pkg_install/dist/add/main.c new file mode 100644 index 000000000..c6f7b8c0a --- /dev/null +++ b/external/bsd/pkg_install/dist/add/main.c @@ -0,0 +1,221 @@ +/* $NetBSD: main.c,v 1.1.1.10 2011/02/18 22:32:27 aymeric Exp $ */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: main.c,v 1.1.1.10 2011/02/18 22:32:27 aymeric Exp $"); + +/* + * + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * This is the add module. + * + */ + +#if HAVE_ERR_H +#include +#endif +#if HAVE_SYS_PARAM_H +#include +#endif +#include "lib.h" +#include "add.h" + +static char Options[] = "AC:DIK:LP:RVW:fhm:np:t:Uuvw:"; + +char *Destdir = NULL; +char *OverrideMachine = NULL; +char *Prefix = NULL; +char *View = NULL; +char *Viewbase = NULL; +Boolean NoView = FALSE; +Boolean NoInstall = FALSE; +Boolean NoRecord = FALSE; +Boolean Automatic = FALSE; +Boolean ForceDepends = FALSE; +/* + * Normally, updating fails if the dependencies of a depending package + * are not satisfied by the package to be updated. ForceDepending + * turns that failure into a warning. + */ +Boolean ForceDepending = FALSE; + +int LicenseCheck = 0; +int Replace = 0; +int ReplaceSame = 0; + +static void +usage(void) +{ + (void) fprintf(stderr, "%s\n%s\n%s\n%s\n", + "usage: pkg_add [-AfhILnRuVv] [-C config] [-P destdir] [-K pkg_dbdir]", + " [-m machine] [-p prefix] [-s verification-type", + " [-W viewbase] [-w view]\n", + " [[ftp|http]://[user[:password]@]host[:port]][/path/]pkg-name ..."); + exit(1); +} + +int +main(int argc, char **argv) +{ + int ch, error=0; + lpkg_head_t pkgs; + + setprogname(argv[0]); + while ((ch = getopt(argc, argv, Options)) != -1) { + switch (ch) { + case 'A': + Automatic = TRUE; + break; + + case 'C': + config_file = optarg; + break; + + case 'D': + ForceDepending = TRUE; + break; + + case 'P': + Destdir = optarg; + break; + + case 'f': + Force = TRUE; + ForceDepends = TRUE; + ForceDepending = TRUE; + break; + + case 'I': + NoInstall = TRUE; + break; + + case 'K': + pkgdb_set_dir(optarg, 3); + break; + + case 'L': + NoView = TRUE; + break; + + case 'R': + NoRecord = TRUE; + break; + + case 'm': + OverrideMachine = optarg; + break; + + case 'n': + Fake = TRUE; + Verbose = TRUE; + break; + + case 'p': + Prefix = optarg; + break; + + case 'U': + ReplaceSame = 1; + Replace = 1; + break; + + case 'u': + Replace = 1; + break; + + case 'V': + show_version(); + /* NOTREACHED */ + + case 'v': + Verbose = TRUE; + break; + + case 'W': + Viewbase = optarg; + break; + + case 'w': + View = optarg; + break; + + case 'h': + case '?': + default: + usage(); + break; + } + } + argc -= optind; + argv += optind; + + pkg_install_config(); + + if (Destdir != NULL) { + char *pkgdbdir; + + pkgdbdir = xasprintf("%s/%s", Destdir, config_pkg_dbdir); + pkgdb_set_dir(pkgdbdir, 4); + free(pkgdbdir); + } + + process_pkg_path(); + TAILQ_INIT(&pkgs); + + if (argc == 0) { + /* If no packages, yelp */ + warnx("missing package name(s)"); + usage(); + } + + if (strcasecmp(do_license_check, "no") == 0) + LicenseCheck = 0; + else if (strcasecmp(do_license_check, "yes") == 0) + LicenseCheck = 1; + else if (strcasecmp(do_license_check, "always") == 0) + LicenseCheck = 2; + else + errx(1, "Unknown value of the configuration variable" + "CHECK_LICENSE"); + + if (LicenseCheck) + load_license_lists(); + + /* Get all the remaining package names, if any */ + for (; argc > 0; --argc, ++argv) { + lpkg_t *lpp; + + if (IS_STDIN(*argv)) + lpp = alloc_lpkg("-"); + else + lpp = alloc_lpkg(*argv); + + TAILQ_INSERT_TAIL(&pkgs, lpp, lp_link); + } + + error += pkg_perform(&pkgs); + if (error != 0) { + warnx("%d package addition%s failed", error, error == 1 ? "" : "s"); + exit(1); + } + exit(0); +} diff --git a/external/bsd/pkg_install/dist/add/perform.c b/external/bsd/pkg_install/dist/add/perform.c new file mode 100644 index 000000000..7a9cbbbc2 --- /dev/null +++ b/external/bsd/pkg_install/dist/add/perform.c @@ -0,0 +1,1607 @@ +/* $NetBSD: perform.c,v 1.4 2013/04/20 15:29:22 wiz Exp $ */ +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: perform.c,v 1.4 2013/04/20 15:29:22 wiz Exp $"); + +/*- + * Copyright (c) 2003 Grant Beattie + * Copyright (c) 2005 Dieter Baron + * Copyright (c) 2007 Roland Illig + * Copyright (c) 2008, 2009 Joerg Sonnenberger + * Copyright (c) 2010 Thomas Klausner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#if HAVE_ERR_H +#include +#endif +#include +#if HAVE_FCNTL_H +#include +#endif +#include +#include +#include + +#include +#include + +#include "lib.h" +#include "add.h" +#include "version.h" + +struct pkg_meta { + char *meta_contents; + char *meta_comment; + char *meta_desc; + char *meta_mtree; + char *meta_build_version; + char *meta_build_info; + char *meta_size_pkg; + char *meta_size_all; + char *meta_required_by; + char *meta_display; + char *meta_install; + char *meta_deinstall; + char *meta_preserve; + char *meta_views; + char *meta_installed_info; +}; + +struct pkg_task { + char *pkgname; + + const char *prefix; + char *install_prefix; + + char *logdir; + char *install_logdir; + char *install_logdir_real; + char *other_version; + + package_t plist; + + struct pkg_meta meta_data; + + struct archive *archive; + struct archive_entry *entry; + + char *buildinfo[BI_ENUM_COUNT]; + + size_t dep_length, dep_allocated; + char **dependencies; +}; + +static const struct pkg_meta_desc { + size_t entry_offset; + const char *entry_filename; + int required_file; + mode_t perm; +} pkg_meta_descriptors[] = { + { offsetof(struct pkg_meta, meta_contents), CONTENTS_FNAME, 1, 0644 }, + { offsetof(struct pkg_meta, meta_comment), COMMENT_FNAME, 1, 0444}, + { offsetof(struct pkg_meta, meta_desc), DESC_FNAME, 1, 0444}, + { offsetof(struct pkg_meta, meta_install), INSTALL_FNAME, 0, 0555 }, + { offsetof(struct pkg_meta, meta_deinstall), DEINSTALL_FNAME, 0, 0555 }, + { offsetof(struct pkg_meta, meta_display), DISPLAY_FNAME, 0, 0444 }, + { offsetof(struct pkg_meta, meta_mtree), MTREE_FNAME, 0, 0444 }, + { offsetof(struct pkg_meta, meta_build_version), BUILD_VERSION_FNAME, 0, 0444 }, + { offsetof(struct pkg_meta, meta_build_info), BUILD_INFO_FNAME, 0, 0444 }, + { offsetof(struct pkg_meta, meta_size_pkg), SIZE_PKG_FNAME, 0, 0444 }, + { offsetof(struct pkg_meta, meta_size_all), SIZE_ALL_FNAME, 0, 0444 }, + { offsetof(struct pkg_meta, meta_preserve), PRESERVE_FNAME, 0, 0444 }, + { offsetof(struct pkg_meta, meta_views), VIEWS_FNAME, 0, 0444 }, + { offsetof(struct pkg_meta, meta_required_by), REQUIRED_BY_FNAME, 0, 0644 }, + { offsetof(struct pkg_meta, meta_installed_info), INSTALLED_INFO_FNAME, 0, 0644 }, + { 0, NULL, 0, 0 }, +}; + +static int pkg_do(const char *, int, int); + +static int +end_of_version(const char *opsys, const char *version_end) +{ + if (*version_end == '\0') + return 1; + + if (strcmp(opsys, "NetBSD") == 0) { + if (strncmp(version_end, "_ALPHA", 6) == 0 + || strncmp(version_end, "_BETA", 5) == 0 + || strncmp(version_end, "_RC", 3) == 0 + || strncmp(version_end, "_STABLE", 7) == 0 + || strncmp(version_end, "_PATCH", 6) == 0) + return 1; + } + + return 0; +} + +static int +compatible_platform(const char *opsys, const char *host, const char *package) +{ + int i = 0; + + /* returns 1 if host and package operating system match */ + if (strcmp(host, package) == 0) + return 1; + + /* accept, if host version is a minor release of package version */ + if (strncmp(host, package, strlen(package)) == 0) + return 1; + + /* find offset of first difference */ + for (i=0; (host[i] != '\0') && (host[i] == package[i]);) + i++; + + if (end_of_version(opsys, host+i) && end_of_version(opsys, package+i)) + return 1; + + return 0; +} + +static int +mkdir_p(const char *path) +{ + char *p, *cur_end; + int done, saved_errno; + struct stat sb; + + /* + * Handle the easy case of direct success or + * pre-existing directory first. + */ + if (mkdir(path, 0777) == 0) + return 0; + if (stat(path, &sb) == 0) { + if (S_ISDIR(sb.st_mode)) + return 0; + errno = ENOTDIR; + return -1; + } + + cur_end = p = xstrdup(path); + + for (;;) { + /* + * First skip leading slashes either from / or + * from the last iteration. + */ + cur_end += strspn(cur_end, "/"); + /* Find end of actual directory name. */ + cur_end += strcspn(cur_end, "/"); + + /* + * Remember if this is the last component and + * overwrite / if needed. + */ + done = (*cur_end == '\0'); + *cur_end = '\0'; + + if (mkdir(p, 0777) == -1) { + saved_errno = errno; + if (stat(p, &sb) == 0) { + if (S_ISDIR(sb.st_mode)) + goto pass; + errno = ENOTDIR; + } else { + errno = saved_errno; + } + free(p); + return -1; + } +pass: + if (done) + break; + *cur_end = '/'; + } + + free(p); + return 0; +} + +/* + * Read meta data from archive. + * Bail out if a required entry is missing or entries are in the wrong order. + */ +static int +read_meta_data(struct pkg_task *pkg) +{ + const struct pkg_meta_desc *descr, *last_descr; + const char *fname; + char **target; + int64_t size; + int r, found_required; + + found_required = 0; + + r = ARCHIVE_OK; + last_descr = 0; + + if (pkg->entry != NULL) + goto skip_header; + + for (;;) { + r = archive_read_next_header(pkg->archive, &pkg->entry); + if (r != ARCHIVE_OK) + break; +skip_header: + fname = archive_entry_pathname(pkg->entry); + + for (descr = pkg_meta_descriptors; descr->entry_filename; + ++descr) { + if (strcmp(descr->entry_filename, fname) == 0) + break; + } + if (descr->entry_filename == NULL) + break; + + if (descr->required_file) + ++found_required; + + target = (char **)((char *)&pkg->meta_data + + descr->entry_offset); + if (*target) { + warnx("duplicate entry, package corrupt"); + return -1; + } + if (descr < last_descr) { + warnx("misordered package"); + return -1; + } + last_descr = descr; + + size = archive_entry_size(pkg->entry); + if (size > SSIZE_MAX - 1) { + warnx("package meta data too large to process"); + return -1; + } + *target = xmalloc(size + 1); + if (archive_read_data(pkg->archive, *target, size) != size) { + warnx("cannot read package meta data"); + return -1; + } + (*target)[size] = '\0'; + } + + if (r != ARCHIVE_OK) + pkg->entry = NULL; + if (r == ARCHIVE_EOF) + r = ARCHIVE_OK; + + for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { + if (descr->required_file) + --found_required; + } + + return !found_required && r == ARCHIVE_OK ? 0 : -1; +} + +/* + * Free meta data. + */ +static void +free_meta_data(struct pkg_task *pkg) +{ + const struct pkg_meta_desc *descr; + char **target; + + for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { + target = (char **)((char *)&pkg->meta_data + + descr->entry_offset); + free(*target); + *target = NULL; + } +} + +/* + * Parse PLIST and populate pkg. + */ +static int +pkg_parse_plist(struct pkg_task *pkg) +{ + plist_t *p; + + parse_plist(&pkg->plist, pkg->meta_data.meta_contents); + if ((p = find_plist(&pkg->plist, PLIST_NAME)) == NULL) { + warnx("Invalid PLIST: missing @name"); + return -1; + } + if (pkg->pkgname == NULL) + pkg->pkgname = xstrdup(p->name); + else if (strcmp(pkg->pkgname, p->name) != 0) { + warnx("Signature and PLIST differ on package name"); + return -1; + } + if ((p = find_plist(&pkg->plist, PLIST_CWD)) == NULL) { + warnx("Invalid PLIST: missing @cwd"); + return -1; + } + + if (Prefix != NULL && + strcmp(p->name, Prefix) != 0) { + size_t len; + + delete_plist(&pkg->plist, FALSE, PLIST_CWD, NULL); + add_plist_top(&pkg->plist, PLIST_CWD, Prefix); + free(pkg->meta_data.meta_contents); + stringify_plist(&pkg->plist, &pkg->meta_data.meta_contents, &len, + Prefix); + pkg->prefix = Prefix; + } else + pkg->prefix = p->name; + + if (Destdir != NULL) + pkg->install_prefix = xasprintf("%s/%s", Destdir, pkg->prefix); + else + pkg->install_prefix = xstrdup(pkg->prefix); + + return 0; +} + +/* + * Helper function to extract value from a string of the + * form key=value ending at eol. + */ +static char * +dup_value(const char *line, const char *eol) +{ + const char *key; + char *val; + + key = strchr(line, '='); + val = xmalloc(eol - key); + memcpy(val, key + 1, eol - key - 1); + val[eol - key - 1] = '\0'; + return val; +} + +static int +check_already_installed(struct pkg_task *pkg) +{ + char *filename; + int fd; + + filename = pkgdb_pkg_file(pkg->pkgname, CONTENTS_FNAME); + fd = open(filename, O_RDONLY); + free(filename); + if (fd == -1) + return 1; + close(fd); + + if (ReplaceSame) { + struct stat sb; + + pkg->install_logdir_real = pkg->install_logdir; + pkg->install_logdir = xasprintf("%s.xxxxxx", pkg->install_logdir); + if (stat(pkg->install_logdir, &sb) == 0) { + warnx("package `%s' already has a temporary update " + "directory `%s', remove it manually", + pkg->pkgname, pkg->install_logdir); + return -1; + } + return 1; + } + + if (Force) + return 1; + + /* We can only arrive here for explicitly requested packages. */ + if (!Automatic && is_automatic_installed(pkg->pkgname)) { + if (Fake || + mark_as_automatic_installed(pkg->pkgname, 0) == 0) + warnx("package `%s' was already installed as " + "dependency, now marked as installed " + "manually", pkg->pkgname); + } else { + warnx("package `%s' already recorded as installed", + pkg->pkgname); + } + return 0; + +} + +static int +check_other_installed(struct pkg_task *pkg) +{ + FILE *f, *f_pkg; + size_t len; + char *pkgbase, *iter, *filename; + package_t plist; + plist_t *p; + int status; + + if (pkg->install_logdir_real) { + pkg->other_version = xstrdup(pkg->pkgname); + return 0; + } + + pkgbase = xstrdup(pkg->pkgname); + + if ((iter = strrchr(pkgbase, '-')) == NULL) { + free(pkgbase); + warnx("Invalid package name %s", pkg->pkgname); + return -1; + } + *iter = '\0'; + pkg->other_version = find_best_matching_installed_pkg(pkgbase); + free(pkgbase); + if (pkg->other_version == NULL) + return 0; + + if (!Replace) { + /* XXX This is redundant to the implicit conflict check. */ + warnx("A different version of %s is already installed: %s", + pkg->pkgname, pkg->other_version); + return -1; + } + + filename = pkgdb_pkg_file(pkg->other_version, REQUIRED_BY_FNAME); + errno = 0; + f = fopen(filename, "r"); + free(filename); + if (f == NULL) { + if (errno == ENOENT) { + /* No packages depend on this, so everything is well. */ + return 0; + } + warnx("Can't open +REQUIRED_BY of %s", pkg->other_version); + return -1; + } + + status = 0; + + while ((iter = fgetln(f, &len)) != NULL) { + if (iter[len - 1] == '\n') + iter[len - 1] = '\0'; + filename = pkgdb_pkg_file(iter, CONTENTS_FNAME); + if ((f_pkg = fopen(filename, "r")) == NULL) { + warnx("Can't open +CONTENTS of depending package %s", + iter); + fclose(f); + return -1; + } + read_plist(&plist, f_pkg); + fclose(f_pkg); + for (p = plist.head; p != NULL; p = p->next) { + if (p->type == PLIST_IGNORE) { + p = p->next; + continue; + } else if (p->type != PLIST_PKGDEP) + continue; + /* + * XXX This is stricter than necessary. + * XXX One pattern might be fulfilled by + * XXX a different package and still need this + * XXX one for a different pattern. + */ + if (pkg_match(p->name, pkg->other_version) == 0) + continue; + if (pkg_match(p->name, pkg->pkgname) == 1) + continue; /* Both match, ok. */ + warnx("Dependency of %s fulfilled by %s, but not by %s", + iter, pkg->other_version, pkg->pkgname); + if (!ForceDepending) + status = -1; + break; + } + free_plist(&plist); + } + + fclose(f); + + return status; +} + +/* + * Read package build information from meta data. + */ +static int +read_buildinfo(struct pkg_task *pkg) +{ + const char *data, *eol, *next_line; + + data = pkg->meta_data.meta_build_info; + + for (; data != NULL && *data != '\0'; data = next_line) { + if ((eol = strchr(data, '\n')) == NULL) { + eol = data + strlen(data); + next_line = eol; + } else + next_line = eol + 1; + + if (strncmp(data, "OPSYS=", 6) == 0) + pkg->buildinfo[BI_OPSYS] = dup_value(data, eol); + else if (strncmp(data, "OS_VERSION=", 11) == 0) + pkg->buildinfo[BI_OS_VERSION] = dup_value(data, eol); + else if (strncmp(data, "MACHINE_ARCH=", 13) == 0) + pkg->buildinfo[BI_MACHINE_ARCH] = dup_value(data, eol); + else if (strncmp(data, "IGNORE_RECOMMENDED=", 19) == 0) + pkg->buildinfo[BI_IGNORE_RECOMMENDED] = dup_value(data, + eol); + else if (strncmp(data, "USE_ABI_DEPENDS=", 16) == 0) + pkg->buildinfo[BI_USE_ABI_DEPENDS] = dup_value(data, + eol); + else if (strncmp(data, "LICENSE=", 8) == 0) + pkg->buildinfo[BI_LICENSE] = dup_value(data, eol); + else if (strncmp(data, "PKGTOOLS_VERSION=", 17) == 0) + pkg->buildinfo[BI_PKGTOOLS_VERSION] = dup_value(data, + eol); + } + if (pkg->buildinfo[BI_OPSYS] == NULL || + pkg->buildinfo[BI_OS_VERSION] == NULL || + pkg->buildinfo[BI_MACHINE_ARCH] == NULL) { + warnx("Not all required build information are present."); + return -1; + } + + if ((pkg->buildinfo[BI_USE_ABI_DEPENDS] != NULL && + strcasecmp(pkg->buildinfo[BI_USE_ABI_DEPENDS], "YES") != 0) || + (pkg->buildinfo[BI_IGNORE_RECOMMENDED] != NULL && + strcasecmp(pkg->buildinfo[BI_IGNORE_RECOMMENDED], "NO") != 0)) { + warnx("%s was built to ignore ABI dependencies", pkg->pkgname); + } + + return 0; +} + +/* + * Free buildinfo. + */ +static void +free_buildinfo(struct pkg_task *pkg) +{ + size_t i; + + for (i = 0; i < BI_ENUM_COUNT; ++i) { + free(pkg->buildinfo[i]); + pkg->buildinfo[i] = NULL; + } +} + +/* + * Write meta data files to pkgdb after creating the directory. + */ +static int +write_meta_data(struct pkg_task *pkg) +{ + const struct pkg_meta_desc *descr; + char *filename, **target; + size_t len; + ssize_t ret; + int fd; + + if (Fake) + return 0; + + if (mkdir_p(pkg->install_logdir)) { + warn("Can't create pkgdb entry: %s", pkg->install_logdir); + return -1; + } + + for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { + target = (char **)((char *)&pkg->meta_data + + descr->entry_offset); + if (*target == NULL) + continue; + filename = xasprintf("%s/%s", pkg->install_logdir, + descr->entry_filename); + (void)unlink(filename); + fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, descr->perm); + if (fd == -1) { + warn("Can't open meta data file: %s", filename); + return -1; + } + len = strlen(*target); + do { + ret = write(fd, *target, len); + if (ret == -1) { + warn("Can't write meta data file: %s", + filename); + free(filename); + close(fd); + return -1; + } + len -= ret; + } while (ret > 0); + if (close(fd) == -1) { + warn("Can't close meta data file: %s", filename); + free(filename); + return -1; + } + free(filename); + } + + return 0; +} + +/* + * Helper function for extract_files. + */ +static int +copy_data_to_disk(struct archive *reader, struct archive *writer, + const char *filename) +{ + int r; + const void *buff; + size_t size; + off_t offset; + + for (;;) { + r = archive_read_data_block(reader, &buff, &size, &offset); + if (r == ARCHIVE_EOF) + return 0; + if (r != ARCHIVE_OK) { + warnx("Read error for %s: %s", filename, + archive_error_string(reader)); + return -1; + } + r = archive_write_data_block(writer, buff, size, offset); + if (r != ARCHIVE_OK) { + warnx("Write error for %s: %s", filename, + archive_error_string(writer)); + return -1; + } + } +} + +/* + * Extract package. + * Any misordered, missing or unlisted file in the package is an error. + */ + +static const int extract_flags = ARCHIVE_EXTRACT_OWNER | + ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_UNLINK | + ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR; + +static int +extract_files(struct pkg_task *pkg) +{ + char cmd[MaxPathSize]; + const char *owner, *group, *permissions; + struct archive *writer; + int r; + plist_t *p; + const char *last_file; + char *fullpath; + + if (Fake) + return 0; + + if (mkdir_p(pkg->install_prefix)) { + warn("Can't create prefix: %s", pkg->install_prefix); + return -1; + } + + if (!NoRecord && !pkgdb_open(ReadWrite)) { + warn("Can't open pkgdb for writing"); + return -1; + } + + if (chdir(pkg->install_prefix) == -1) { + warn("Can't change into prefix: %s", pkg->install_prefix); + return -1; + } + + writer = archive_write_disk_new(); + archive_write_disk_set_options(writer, extract_flags); + archive_write_disk_set_standard_lookup(writer); + + owner = NULL; + group = NULL; + permissions = NULL; + last_file = NULL; + + r = -1; + + for (p = pkg->plist.head; p != NULL; p = p->next) { + switch (p->type) { + case PLIST_FILE: + last_file = p->name; + if (pkg->entry == NULL) { + warnx("PLIST entry not in package (%s)", + archive_entry_pathname(pkg->entry)); + goto out; + } + if (strcmp(p->name, archive_entry_pathname(pkg->entry))) { + warnx("PLIST entry and package don't match (%s vs %s)", + p->name, archive_entry_pathname(pkg->entry)); + goto out; + } + fullpath = xasprintf("%s/%s", pkg->prefix, p->name); + pkgdb_store(fullpath, pkg->pkgname); + free(fullpath); + if (Verbose) + printf("%s", p->name); + break; + + case PLIST_PKGDIR: + fullpath = xasprintf("%s/%s", pkg->prefix, p->name); + mkdir_p(fullpath); + free(fullpath); + add_pkgdir(pkg->pkgname, pkg->prefix, p->name); + continue; + + case PLIST_CMD: + if (format_cmd(cmd, sizeof(cmd), p->name, pkg->prefix, last_file)) + return -1; + printf("Executing '%s'\n", cmd); + if (!Fake && system(cmd)) + warnx("command '%s' failed", cmd); /* XXX bail out? */ + continue; + + case PLIST_CHMOD: + permissions = p->name; + continue; + + case PLIST_CHOWN: + owner = p->name; + continue; + + case PLIST_CHGRP: + group = p->name; + continue; + + case PLIST_IGNORE: + p = p->next; + continue; + + default: + continue; + } + + r = archive_write_header(writer, pkg->entry); + if (r != ARCHIVE_OK) { + warnx("Failed to write %s for %s: %s", + archive_entry_pathname(pkg->entry), + pkg->pkgname, + archive_error_string(writer)); + goto out; + } + + if (owner != NULL) + archive_entry_set_uname(pkg->entry, owner); + if (group != NULL) + archive_entry_set_uname(pkg->entry, group); + if (permissions != NULL) { + mode_t mode; + + mode = archive_entry_mode(pkg->entry); + mode = getmode(setmode(permissions), mode); + archive_entry_set_mode(pkg->entry, mode); + } + + r = copy_data_to_disk(pkg->archive, writer, + archive_entry_pathname(pkg->entry)); + if (r) + goto out; + if (Verbose) + printf("\n"); + + r = archive_read_next_header(pkg->archive, &pkg->entry); + if (r == ARCHIVE_EOF) { + pkg->entry = NULL; + continue; + } + if (r != ARCHIVE_OK) { + warnx("Failed to read from archive for %s: %s", + pkg->pkgname, + archive_error_string(pkg->archive)); + goto out; + } + } + + if (pkg->entry != NULL) { + warnx("Package contains entries not in PLIST: %s", + archive_entry_pathname(pkg->entry)); + goto out; + } + + r = 0; + +out: + if (!NoRecord) + pkgdb_close(); + archive_write_close(writer); + archive_write_finish(writer); + + return r; +} + +/* + * Register dependencies after sucessfully installing the package. + */ +static void +pkg_register_depends(struct pkg_task *pkg) +{ + int fd; + size_t text_len, i; + char *required_by, *text; + + if (Fake) + return; + + text = xasprintf("%s\n", pkg->pkgname); + text_len = strlen(text); + + for (i = 0; i < pkg->dep_length; ++i) { + required_by = pkgdb_pkg_file(pkg->dependencies[i], REQUIRED_BY_FNAME); + + fd = open(required_by, O_WRONLY | O_APPEND | O_CREAT, 0644); + if (fd == -1) { + warn("can't open dependency file '%s'," + "registration is incomplete!", required_by); + } else if (write(fd, text, text_len) != (ssize_t)text_len) { + warn("can't write to dependency file `%s'", required_by); + close(fd); + } else if (close(fd) == -1) + warn("cannot close file %s", required_by); + + free(required_by); + } + + free(text); +} + +/* + * Reduce the result from uname(3) to a canonical form. + */ +static void +normalise_platform(struct utsname *host_name) +{ +#ifdef NUMERIC_VERSION_ONLY + size_t span; + + span = strspn(host_name->release, "0123456789."); + host_name->release[span] = '\0'; +#endif +} + +/* + * Check build platform of the package against local host. + */ +static int +check_platform(struct pkg_task *pkg) +{ + struct utsname host_uname; + const char *effective_arch; + int fatal; + + if (uname(&host_uname) < 0) { + if (Force) { + warnx("uname() failed, continuing."); + return 0; + } else { + warnx("uname() failed, aborting."); + return -1; + } + } + + normalise_platform(&host_uname); + + if (OverrideMachine != NULL) + effective_arch = OverrideMachine; + else + effective_arch = MACHINE_ARCH; + + /* If either the OS or arch are different, bomb */ + if (strcmp(OPSYS_NAME, pkg->buildinfo[BI_OPSYS]) || + strcmp(effective_arch, pkg->buildinfo[BI_MACHINE_ARCH]) != 0) + fatal = 1; + else + fatal = 0; + + if (fatal || + compatible_platform(OPSYS_NAME, host_uname.release, + pkg->buildinfo[BI_OS_VERSION]) != 1) { + warnx("Warning: package `%s' was built for a platform:", + pkg->pkgname); + warnx("%s/%s %s (pkg) vs. %s/%s %s (this host)", + pkg->buildinfo[BI_OPSYS], + pkg->buildinfo[BI_MACHINE_ARCH], + pkg->buildinfo[BI_OS_VERSION], + OPSYS_NAME, + effective_arch, + host_uname.release); + if (!Force && fatal) + return -1; + } + return 0; +} + +static int +check_pkgtools_version(struct pkg_task *pkg) +{ + const char *val = pkg->buildinfo[BI_PKGTOOLS_VERSION]; + int version; + + if (val == NULL) { + warnx("Warning: package `%s' lacks pkg_install version data", + pkg->pkgname); + return 0; + } + + if (strlen(val) != 8 || strspn(val, "0123456789") != 8) { + warnx("Warning: package `%s' contains an invalid pkg_install version", + pkg->pkgname); + return Force ? 0 : -1; + } + version = atoi(val); + if (version > PKGTOOLS_VERSION) { + warnx("%s: package `%s' was built with a newer pkg_install version", + Force ? "Warning" : "Error", pkg->pkgname); + return Force ? 0 : -1; + } + return 0; +} + +/* + * Run the install script. + */ +static int +run_install_script(struct pkg_task *pkg, const char *argument) +{ + int ret; + char *filename; + + if (pkg->meta_data.meta_install == NULL || NoInstall) + return 0; + + if (Destdir != NULL) + setenv(PKG_DESTDIR_VNAME, Destdir, 1); + setenv(PKG_PREFIX_VNAME, pkg->prefix, 1); + setenv(PKG_METADATA_DIR_VNAME, pkg->logdir, 1); + setenv(PKG_REFCOUNT_DBDIR_VNAME, config_pkg_refcount_dbdir, 1); + + if (Verbose) + printf("Running install with PRE-INSTALL for %s.\n", pkg->pkgname); + if (Fake) + return 0; + + filename = pkgdb_pkg_file(pkg->pkgname, INSTALL_FNAME); + + ret = 0; + errno = 0; + if (fcexec(pkg->install_logdir, filename, pkg->pkgname, argument, + (void *)NULL)) { + if (errno != 0) + warn("exec of install script failed"); + else + warnx("install script returned error status"); + ret = -1; + } + free(filename); + + return ret; +} + +struct find_conflict_data { + const char *pkg; + const char *old_pkg; + const char *pattern; +}; + +static int +check_explicit_conflict_iter(const char *cur_pkg, void *cookie) +{ + struct find_conflict_data *data = cookie; + + if (data->old_pkg && strcmp(data->old_pkg, cur_pkg) == 0) + return 0; + + warnx("Package `%s' conflicts with `%s', and `%s' is installed.", + data->pkg, data->pattern, cur_pkg); + + return 1; +} + +static int +check_explicit_conflict(struct pkg_task *pkg) +{ + struct find_conflict_data data; + char *installed, *installed_pattern; + plist_t *p; + int status; + + status = 0; + + for (p = pkg->plist.head; p != NULL; p = p->next) { + if (p->type == PLIST_IGNORE) { + p = p->next; + continue; + } + if (p->type != PLIST_PKGCFL) + continue; + data.pkg = pkg->pkgname; + data.old_pkg = pkg->other_version; + data.pattern = p->name; + status |= match_installed_pkgs(p->name, + check_explicit_conflict_iter, &data); + } + + if (some_installed_package_conflicts_with(pkg->pkgname, + pkg->other_version, &installed, &installed_pattern)) { + warnx("Installed package `%s' conflicts with `%s' when trying to install `%s'.", + installed, installed_pattern, pkg->pkgname); + free(installed); + free(installed_pattern); + status |= -1; + } + + return status; +} + +static int +check_implicit_conflict(struct pkg_task *pkg) +{ + plist_t *p; + char *fullpath, *existing; + int status; + + if (!pkgdb_open(ReadOnly)) { +#if notyet /* XXX empty pkgdb without database? */ + warn("Can't open pkgdb for reading"); + return -1; +#else + return 0; +#endif + } + + status = 0; + + for (p = pkg->plist.head; p != NULL; p = p->next) { + if (p->type == PLIST_IGNORE) { + p = p->next; + continue; + } else if (p->type != PLIST_FILE) + continue; + + fullpath = xasprintf("%s/%s", pkg->prefix, p->name); + existing = pkgdb_retrieve(fullpath); + free(fullpath); + if (existing == NULL) + continue; + if (pkg->other_version != NULL && + strcmp(pkg->other_version, existing) == 0) + continue; + + warnx("Conflicting PLIST with %s: %s", existing, p->name); + if (!Force) { + status = -1; + if (!Verbose) + break; + } + } + + pkgdb_close(); + return status; +} + +static int +check_dependencies(struct pkg_task *pkg) +{ + plist_t *p; + char *best_installed; + int status; + size_t i; + + status = 0; + + for (p = pkg->plist.head; p != NULL; p = p->next) { + if (p->type == PLIST_IGNORE) { + p = p->next; + continue; + } else if (p->type != PLIST_PKGDEP) + continue; + + best_installed = find_best_matching_installed_pkg(p->name); + + if (best_installed == NULL) { + /* XXX check cyclic dependencies? */ + if (Fake || NoRecord) { + if (!Force) { + warnx("Missing dependency %s\n", + p->name); + status = -1; + break; + } + warnx("Missing dependency %s, continuing", + p->name); + continue; + } + if (pkg_do(p->name, 1, 0)) { + if (ForceDepends) { + warnx("Can't install dependency %s, " + "continuing", p->name); + continue; + } else { + warnx("Can't install dependency %s", + p->name); + status = -1; + break; + } + } + best_installed = find_best_matching_installed_pkg(p->name); + if (best_installed == NULL && ForceDepends) { + warnx("Missing dependency %s ignored", p->name); + continue; + } else if (best_installed == NULL) { + warnx("Just installed dependency %s disappeared", p->name); + status = -1; + break; + } + } + for (i = 0; i < pkg->dep_length; ++i) { + if (strcmp(best_installed, pkg->dependencies[i]) == 0) + break; + } + if (i < pkg->dep_length) { + /* Already used as dependency, so skip it. */ + free(best_installed); + continue; + } + if (pkg->dep_length + 1 >= pkg->dep_allocated) { + char **tmp; + pkg->dep_allocated = 2 * pkg->dep_allocated + 1; + pkg->dependencies = xrealloc(pkg->dependencies, + pkg->dep_allocated * sizeof(*tmp)); + } + pkg->dependencies[pkg->dep_length++] = best_installed; + } + + return status; +} + +/* + * If this package uses pkg_views, register it in the default view. + */ +static void +pkg_register_views(struct pkg_task *pkg) +{ + if (Fake || NoView || pkg->meta_data.meta_views == NULL) + return; + + if (Verbose) { + printf("%s/pkg_view -d %s %s%s %s%s %sadd %s\n", + BINDIR, pkgdb_get_dir(), + View ? "-w " : "", View ? View : "", + Viewbase ? "-W " : "", Viewbase ? Viewbase : "", + Verbose ? "-v " : "", pkg->pkgname); + } + + fexec_skipempty(BINDIR "/pkg_view", "-d", pkgdb_get_dir(), + View ? "-w " : "", View ? View : "", + Viewbase ? "-W " : "", Viewbase ? Viewbase : "", + Verbose ? "-v " : "", "add", pkg->pkgname, + (void *)NULL); +} + +static int +preserve_meta_data_file(struct pkg_task *pkg, const char *name) +{ + char *old_file, *new_file; + int rv; + + if (Fake) + return 0; + + old_file = pkgdb_pkg_file(pkg->other_version, name); + new_file = xasprintf("%s/%s", pkg->install_logdir, name); + rv = 0; + if (rename(old_file, new_file) == -1 && errno != ENOENT) { + warn("Can't move %s from %s to %s", name, old_file, new_file); + rv = -1; + } + free(old_file); + free(new_file); + return rv; +} + +static int +start_replacing(struct pkg_task *pkg) +{ + if (preserve_meta_data_file(pkg, REQUIRED_BY_FNAME)) + return -1; + + if (preserve_meta_data_file(pkg, PRESERVE_FNAME)) + return -1; + + if (pkg->meta_data.meta_installed_info == NULL && + preserve_meta_data_file(pkg, INSTALLED_INFO_FNAME)) + return -1; + + if (Verbose || Fake) { + printf("%s/pkg_delete -K %s -p %s%s%s '%s'\n", + BINDIR, pkgdb_get_dir(), pkg->prefix, + Destdir ? " -P ": "", Destdir ? Destdir : "", + pkg->other_version); + } + if (!Fake) + fexec_skipempty(BINDIR "/pkg_delete", "-K", pkgdb_get_dir(), + "-p", pkg->prefix, + Destdir ? "-P": "", Destdir ? Destdir : "", + pkg->other_version, NULL); + + /* XXX Check return value and do what? */ + return 0; +} + +static int check_input(const char *line, size_t len) +{ + if (line == NULL || len == 0) + return 1; + switch (*line) { + case 'Y': + case 'y': + case 'T': + case 't': + case '1': + return 0; + default: + return 1; + } +} + +static int +check_signature(struct pkg_task *pkg, int invalid_sig) +{ + char *line; + size_t len; + + if (strcasecmp(verified_installation, "never") == 0) + return 0; + if (strcasecmp(verified_installation, "always") == 0) { + if (invalid_sig) + warnx("No valid signature found, rejected"); + return invalid_sig; + } + if (strcasecmp(verified_installation, "trusted") == 0) { + if (!invalid_sig) + return 0; + fprintf(stderr, "No valid signature found for %s.\n", + pkg->pkgname); + fprintf(stderr, + "Do you want to proceed with the installation [y/n]?\n"); + line = fgetln(stdin, &len); + if (check_input(line, len)) { + fprintf(stderr, "Cancelling installation\n"); + return 1; + } + return 0; + } + if (strcasecmp(verified_installation, "interactive") == 0) { + fprintf(stderr, "Do you want to proceed with " + "the installation of %s [y/n]?\n", pkg->pkgname); + line = fgetln(stdin, &len); + if (check_input(line, len)) { + fprintf(stderr, "Cancelling installation\n"); + return 1; + } + return 0; + } + warnx("Unknown value of configuration variable VERIFIED_INSTALLATION"); + return 1; +} + +static int +check_vulnerable(struct pkg_task *pkg) +{ + static struct pkg_vulnerabilities *pv; + int require_check; + char *line; + size_t len; + + if (strcasecmp(check_vulnerabilities, "never") == 0) + return 0; + else if (strcasecmp(check_vulnerabilities, "always") == 0) + require_check = 1; + else if (strcasecmp(check_vulnerabilities, "interactive") == 0) + require_check = 0; + else { + warnx("Unknown value of the configuration variable" + "CHECK_VULNERABILITIES"); + return 1; + } + + if (pv == NULL) { + pv = read_pkg_vulnerabilities_file(pkg_vulnerabilities_file, + require_check, 0); + if (pv == NULL) + return require_check; + } + + if (!audit_package(pv, pkg->pkgname, NULL, 2)) + return 0; + + if (require_check) + return 1; + + fprintf(stderr, "Do you want to proceed with the installation of %s" + " [y/n]?\n", pkg->pkgname); + line = fgetln(stdin, &len); + if (check_input(line, len)) { + fprintf(stderr, "Cancelling installation\n"); + return 1; + } + return 0; +} + +static int +check_license(struct pkg_task *pkg) +{ + if (LicenseCheck == 0) + return 0; + + if ((pkg->buildinfo[BI_LICENSE] == NULL || + *pkg->buildinfo[BI_LICENSE] == '\0')) { + + if (LicenseCheck == 1) + return 0; + warnx("No LICENSE set for package `%s'", pkg->pkgname); + return 1; + } + + switch (acceptable_license(pkg->buildinfo[BI_LICENSE])) { + case 0: + warnx("License `%s' of package `%s' is not acceptable", + pkg->buildinfo[BI_LICENSE], pkg->pkgname); + return 1; + case 1: + return 0; + default: + warnx("Invalid LICENSE for package `%s'", pkg->pkgname); + return 1; + } +} + +/* + * Install a single package. + */ +static int +pkg_do(const char *pkgpath, int mark_automatic, int top_level) +{ + char *archive_name; + int status, invalid_sig; + struct pkg_task *pkg; + + pkg = xcalloc(1, sizeof(*pkg)); + + status = -1; + + pkg->archive = find_archive(pkgpath, top_level, &archive_name); + if (pkg->archive == NULL) { + warnx("no pkg found for '%s', sorry.", pkgpath); + goto clean_find_archive; + } + + invalid_sig = pkg_verify_signature(archive_name, &pkg->archive, &pkg->entry, + &pkg->pkgname); + free(archive_name); + + if (pkg->archive == NULL) + goto clean_memory; + + if (read_meta_data(pkg)) + goto clean_memory; + + /* Parse PLIST early, so that messages can use real package name. */ + if (pkg_parse_plist(pkg)) + goto clean_memory; + + if (check_signature(pkg, invalid_sig)) + goto clean_memory; + + if (read_buildinfo(pkg)) + goto clean_memory; + + if (check_pkgtools_version(pkg)) + goto clean_memory; + + if (check_vulnerable(pkg)) + goto clean_memory; + + if (check_license(pkg)) + goto clean_memory; + + if (pkg->meta_data.meta_mtree != NULL) + warnx("mtree specification in pkg `%s' ignored", pkg->pkgname); + + if (pkg->meta_data.meta_views != NULL) { + pkg->logdir = xstrdup(pkg->prefix); + pkgdb_set_dir(dirname_of(pkg->logdir), 4); + } else { + pkg->logdir = xasprintf("%s/%s", config_pkg_dbdir, pkg->pkgname); + } + + if (Destdir != NULL) + pkg->install_logdir = xasprintf("%s/%s", Destdir, pkg->logdir); + else + pkg->install_logdir = xstrdup(pkg->logdir); + + if (NoRecord && !Fake) { + const char *tmpdir; + + tmpdir = getenv("TMPDIR"); + if (tmpdir == NULL) + tmpdir = "/tmp"; + + free(pkg->install_logdir); + pkg->install_logdir = xasprintf("%s/pkg_install.XXXXXX", tmpdir); + /* XXX pkg_add -u... */ + if (mkdtemp(pkg->install_logdir) == NULL) { + warn("mkdtemp failed"); + goto clean_memory; + } + } + + switch (check_already_installed(pkg)) { + case 0: + status = 0; + goto clean_memory; + case 1: + break; + case -1: + goto clean_memory; + } + + if (check_platform(pkg)) + goto clean_memory; + + if (check_other_installed(pkg)) + goto clean_memory; + + if (check_explicit_conflict(pkg)) + goto clean_memory; + + if (check_implicit_conflict(pkg)) + goto clean_memory; + + if (pkg->other_version != NULL) { + /* + * Replacing an existing package. + * Write meta-data, get rid of the old version, + * install/update dependencies and finally extract. + */ + if (write_meta_data(pkg)) + goto nuke_pkgdb; + + if (start_replacing(pkg)) + goto nuke_pkgdb; + + if (pkg->install_logdir_real) { + rename(pkg->install_logdir, pkg->install_logdir_real); + free(pkg->install_logdir); + pkg->install_logdir = pkg->install_logdir_real; + pkg->install_logdir_real = NULL; + } + + if (check_dependencies(pkg)) + goto nuke_pkgdb; + } else { + /* + * Normal installation. + * Install/update dependencies first and + * write the current package to disk afterwards. + */ + if (check_dependencies(pkg)) + goto clean_memory; + + if (write_meta_data(pkg)) + goto nuke_pkgdb; + } + + if (run_install_script(pkg, "PRE-INSTALL")) + goto nuke_pkgdb; + + if (extract_files(pkg)) + goto nuke_pkg; + + if (run_install_script(pkg, "POST-INSTALL")) + goto nuke_pkgdb; + + /* XXX keep +INSTALL_INFO for updates? */ + /* XXX keep +PRESERVE for updates? */ + if (mark_automatic) + mark_as_automatic_installed(pkg->pkgname, 1); + + pkg_register_depends(pkg); + + if (Verbose) + printf("Package %s registered in %s\n", pkg->pkgname, pkg->install_logdir); + + if (pkg->meta_data.meta_display != NULL) + fputs(pkg->meta_data.meta_display, stdout); + + pkg_register_views(pkg); + + status = 0; + goto clean_memory; + +nuke_pkg: + if (!Fake) { + if (pkg->other_version) { + warnx("Updating of %s to %s failed.", + pkg->other_version, pkg->pkgname); + warnx("Remember to run pkg_admin rebuild-tree after fixing this."); + } + delete_package(FALSE, &pkg->plist, FALSE, Destdir); + } + +nuke_pkgdb: + if (!Fake) { + if (recursive_remove(pkg->install_logdir, 1)) + warn("Couldn't remove %s", pkg->install_logdir); + free(pkg->install_logdir_real); + free(pkg->install_logdir); + free(pkg->logdir); + pkg->install_logdir_real = NULL; + pkg->install_logdir = NULL; + pkg->logdir = NULL; + } + +clean_memory: + if (pkg->logdir != NULL && NoRecord && !Fake) { + if (recursive_remove(pkg->install_logdir, 1)) + warn("Couldn't remove %s", pkg->install_logdir); + } + free(pkg->install_prefix); + free(pkg->install_logdir_real); + free(pkg->install_logdir); + free(pkg->logdir); + free_buildinfo(pkg); + free_plist(&pkg->plist); + free_meta_data(pkg); + if (pkg->archive) + archive_read_finish(pkg->archive); + free(pkg->other_version); + free(pkg->pkgname); +clean_find_archive: + free(pkg); + return status; +} + +int +pkg_perform(lpkg_head_t *pkgs) +{ + int errors = 0; + lpkg_t *lpp; + + while ((lpp = TAILQ_FIRST(pkgs)) != NULL) { + if (pkg_do(lpp->lp_name, Automatic, 1)) + ++errors; + TAILQ_REMOVE(pkgs, lpp, lp_link); + free_lpkg(lpp); + } + + return errors; +} diff --git a/external/bsd/pkg_install/dist/add/pkg_add.1 b/external/bsd/pkg_install/dist/add/pkg_add.1 new file mode 100644 index 000000000..26c3f6ded --- /dev/null +++ b/external/bsd/pkg_install/dist/add/pkg_add.1 @@ -0,0 +1,448 @@ +.\" $NetBSD: pkg_add.1,v 1.1.1.12 2011/02/18 22:32:28 aymeric Exp $ +.\" +.\" FreeBSD install - a package for the installation and maintenance +.\" of non-core utilities. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" Jordan K. Hubbard +.\" +.\" +.\" @(#)pkg_add.1 +.\" +.Dd June 16, 2010 +.Dt PKG_ADD 1 +.Os +.Sh NAME +.Nm pkg_add +.Nd a utility for installing and upgrading software package distributions +.Sh SYNOPSIS +.Nm +.Op Fl AfILnRUuVv +.Op Fl C Ar config +.Op Fl K Ar pkg_dbdir +.Op Fl m Ar machine +.Op Fl P Ar destdir +.Op Fl p Ar prefix +.Op Fl W Ar viewbase +.Op Fl w Ar view +.Ar Oo Oo Li ftp|http Oc Ns Li :// Ns Oo Ar user Oc Ns \ +Oo Li \&: Ns Ar password Oc \ +Ns Li @ Oc Ns Ar host Ns Oo Li \&: Ns Ar port Oc Ns \ +Oo Li / Ns Ar path/ Oc Ns Ar pkg-name ... +.Sh DESCRIPTION +The +.Nm +command is used to extract and upgrade packages that have been +previously created with the +.Xr pkg_create 1 +command. +Packages are prepared collections of pre-built binaries, documentation, +configurations, installation instructions and/or other files. +.Nm +can recursively install other packages that the current package +depends on or requires from both local disk and via FTP or HTTP. +.Sh WARNING +.Bf -emphasis +Since the +.Nm +command may execute scripts or programs contained within a package file, +your system may be susceptible to +.Dq Trojan horses +or other subtle +attacks from miscreants who create dangerous package files. +.Pp +You are advised to verify the competence and identity of those who +provide installable package files. +For extra protection, use the digital signatures provided where possible +(see the +.Xr pkg_install.conf 5 ) , +or, failing that, use +.Xr tar 1 +to extract the package file, and inspect its contents and scripts +to ensure it poses no danger to your system's integrity. +Pay particular attention to any +.Pa +INSTALL +or +.Pa +DEINSTALL +files, and inspect the +.Pa +CONTENTS +file for +.Cm @cwd , +.Cm @mode +(check for setuid), +.Cm @dirrm , +.Cm @exec , +and +.Cm @unexec +directives, and/or use the +.Xr pkg_info 1 +command to examine the package file. +.Ef +.Sh OPTIONS +The following command line arguments are supported: +.Bl -tag -width indent +.It Ar pkg-name [ ... ] +The named packages are installed. +.Nm +will first try to use +.Ar pkg-name +as full URL or path name without any wildcard processing. +If that fails, +.Nm +will try to match packages using wildcard processing. +If that fails as well and +.Ar pkg-name +does not contain any /, the entries of the +.Dv PKG_PATH +variable are searched using the wildcard processing rules. +.It Fl A +Mark package as installed automatically, as dependency of another +package. +You can use +.Dl Ic pkg_admin set automatic=YES +to mark packages this way after installation, and +.Dl Ic pkg_admin unset automatic +to remove the mark. +If you +.Nm +a package without specifying +.Fl A +after it had already been automatically installed, the mark is +removed. +.It Fl C Ar config +Read the configuration file from +.Ar config +instead of the system default. +.It Fl f +Force installation to proceed even if prerequisite packages are not +installed or the install script fails. +Although +.Nm +will still try to find and auto-install missing prerequisite packages, +a failure to find one will not be fatal. +This flag also overrides the fatal error when the operating system or +architecture the package was built on differ from that of the host. +.It Fl D +Force updating even if the dependencies of depending packages are not +satisfied by the new package. +This is used by "make replace", after which one would typically +replace the depending packages. +.It Fl I +If an installation script exists for a given package, do not execute it. +.It Fl K Ar pkg_dbdir +Override the value of the +.Dv PKG_DBDIR +configuration option with the value +.Ar pkg_dbdir . +.It Fl L +Don't add the package to any views after installation. +.It Fl m +Override the machine architecture returned by uname with +.Ar machine . +.It Fl n +Don't actually install a package, just report the steps that +would be taken if it was. +.It Fl P Ar destdir +Prefix all file and directory names with +.Ar destdir . +For packages without install scripts this has the same behavior as +using +.Xr chroot 8 . +.It Fl p Ar prefix +Override the prefix stored in the package with +.Ar prefix . +.It Fl R +Do not record the installation of a package. +This implies +.Fl I . +This means that you cannot deinstall it later, so only use this option if +you know what you are doing! +.It Fl U +Replace an already installed version from a package. +Implies +.Fl u . +.It Fl u +If the package that's being installed is already installed, +an update is performed. +Installed dependent packages are updated recursively, if they are too +old to fulfill the dependencies of the to-be-installed version. +See below for a more detailed description of the process. +.It Fl V +Print version number and exit. +.It Fl v +Turn on verbose output. +.It Fl W Ar viewbase +Passed down to +.Xr pkg_view 1 +for managed views. +.It Fl w Ar view +Passed down to +.Xr pkg_view 1 +for managed views. +.El +.Pp +One or more +.Ar pkg-name +arguments may be specified, each being either a file containing the +package (these usually ending with the +.Dq .tgz +suffix) or a +URL pointing at a file available on an ftp or web site. +Thus you may extract files directly from their anonymous ftp or WWW +locations (e.g., +.Nm +ftp://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/i386/3.1_2007Q2/shells/bash-3.2.9.tgz +or +.Nm +http://www.example.org/packages/screen-4.0.tbz). +Note: For ftp transfers, if you wish to use +.Bf -emphasis +passive mode +.Ef +ftp in such transfers, set the variable +.Bf -emphasis +FTP_PASSIVE_MODE +.Ef +to some value in your environment. +Otherwise, the more standard ACTIVE mode may be used. +If +.Nm +consistently fails to fetch a package from a site known to work, +it may be because you have a firewall that demands the usage of +.Bf -emphasis +passive mode +.Ef +ftp. +.Sh TECHNICAL DETAILS +.Nm +extracts each package's meta data (including the +.Dq packing list ) +to memory and then runs through the following sequence to fully extract +the contents of the package: +.Bl -enum -offset indent +.It +A check is made to determine if the package or another version of it +is already recorded as installed. +If it is, +installation is terminated if the +.Fl u +or +.Fl U +options are not given. +.Pp +If the same version is installed and +.Fl U +is not given, it is marked as manually installed and process stops. +If the +.Fl u +option is given, it's assumed the package should be replaced by the +new version instead. +Before doing so, all packages that depend on the +pkg being upgraded are checked if they also work with the new version. +If that test is not successful, the dependent packages are updated first. +The replacing is then prepared by moving an existing +.Pa +REQUIRED_BY +file aside (if it exists), and running +.Xr pkg_delete 1 +on the installed package. +Installation then proceeds as if the package +was not installed, and restores the +.Pa +REQUIRED_BY +file afterwards. +.It +The package build information is extracted from the +.Pa +BUILD_INFO +file and compared against the result of +.Xr uname 3 . +If the operating system or architecture of the package differ from +that of the host, installation is aborted. +This behavior is overridable with the +.Fl f +flag. +.It +The package build information from +.Pa +BUILD_INFO +is then checked for +.Ev USE_ABI_DEPENDS=NO +(or +.Ev IGNORE_RECOMMENDED ) . +If the package was built with ABI dependency recommendations ignored, +a warning will be issued. +.It +A check is made to determine if the package conflicts (from +.Cm @pkgcfl +directives, see +.Xr pkg_create 1 ) +with an already recorded as installed package or if an installed package +conflicts with the package. +If it is, installation is terminated. +.It +The file list of the package is compared to the file lists of the +installed packages. +If there is any overlap, the installation is terminated. +.It +All package dependencies (from +.Cm @pkgdep +directives, see +.Xr pkg_create 1 ) +are read from the packing list. +If any of these required packages are not currently installed, +an attempt is made to find and install it; +if the missing package cannot be found or installed, +the installation is terminated. +.It +If the package contains an +.Ar install +script, it is executed with the following arguments: +.Bl -tag -width indentindent +.It Ar pkg-name +The name of the package being installed. +.It Cm PRE-INSTALL +Keyword denoting that the script is to perform any actions needed before +the package is installed. +.El +.Pp +If the +.Ar install +script exits with a non-zero status code, the installation is terminated. +.It +The files from the file list are extracted to the chosen prefix. +.It +If an +.Ar install +script exists for the package, it is executed with the following arguments: +.Bl -tag -width indentindent +.It Ar pkg_name +The name of the package being installed. +.It Cm POST-INSTALL +Keyword denoting that the script is to perform any actions needed +after the package has been installed. +.El +.It +After installation is complete, a copy of the packing list, +.Ar deinstall +script, description, and display files are copied into +.Pa \*[Lt]PKG_DBDIR\*[Gt]/\*[Lt]pkg-name\*[Gt] +for subsequent possible use by +.Xr pkg_delete 1 . +Any package dependencies are recorded in the other packages' +.Pa +REQUIRED_BY +file. +.It +If the package is a depoted package, then add it to the registered +by calling +.Xr pkg_view 1 +accordingly. +.It +Finally, if we were upgrading a package, any +.Pa +REQUIRED_BY +file that was moved aside before upgrading was started is now moved +back into place. +.El +.Pp +The +.Ar install +script is called with the environment variable +.Ev PKG_PREFIX +set to the installation prefix (see the +.Fl p +option above). +This allows a package author to write a script +that reliably performs some action on the directory where the package +is installed, even if the user might change it with the +.Fl p +flag to +.Cm pkg_add . +The scripts are also called with the +.Ev PKG_METADATA_DIR +environment variable set to the location of the +.Pa +* +meta-data files, and with the +.Ev PKG_REFCOUNT_DBDIR +environment variable set to the location of the package reference counts +database directory. +If the +.Fl P +flag was given to +.Nm , +.Ev PKG_DESTDIR +will be set to +.Ar destdir . +Additionally, +.Ev PKG_METADATA_DIR +and +.Ev PKG_REFCOUNT_DBDIR +are prefixed with +.Ar destdir . +.Sh ENVIRONMENT +See +.Xr pkg_install.conf 5 +for options, that can also be specified using the environment. +Packages using views are also affected by the environment variables +documented for +.Xr pkg_view 1 . +.Sh EXAMPLES +In all cases, +.Nm +will try to install binary packages listed in dependencies list. +.Pp +You can specify a compiled binary package explicitly on the command line. +.Bd -literal +# pkg_add /usr/pkgsrc/packages/All/tcsh-6.14.00.tgz +.Ed +.Pp +If you omit the version number, +.Nm +will install the latest version available. +With +.Fl v , +.Nm +emits more messages to terminal. +.Bd -literal +# pkg_add -v /usr/pkgsrc/packages/All/unzip +.Ed +.Pp +You can grab a compiled binary package from remote location by specifying +a URL. +The base URL can also be provided by the configuration variable, +.Dv PKG_PATH . +.Bd -literal +# pkg_add -v ftp://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/i386/3.1_2007Q2/All/firefox-2.0.0.4.tgz + +# export PKG_PATH=ftp://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/i386/3.1_2007Q2/All +# pkg_add -v firefox +.Ed +.Sh SEE ALSO +.Xr pkg_admin 1 , +.Xr pkg_create 1 , +.Xr pkg_delete 1 , +.Xr pkg_info 1 , +.Xr pkg_install.conf 5 , +.Xr pkgsrc 7 +.Sh AUTHORS +.Bl -tag -width indent -compact +.It "Jordan Hubbard" +Initial work and ongoing development. +.It "John Kohl" +.Nx +refinements. +.It "Hubert Feyrer" +.Nx +wildcard dependency processing, pkgdb, upgrading, etc. +.It Thomas Klausner +HTTP support. +.It Joerg Sonnenberger +Rewrote most of the code base to work without external commands. +.El +.Sh BUGS +Package upgrading needs a lot more work to be really universal. +.Pp +Sure to be others. diff --git a/external/bsd/pkg_install/dist/admin/admin.h b/external/bsd/pkg_install/dist/admin/admin.h new file mode 100644 index 000000000..ea5b783d9 --- /dev/null +++ b/external/bsd/pkg_install/dist/admin/admin.h @@ -0,0 +1,39 @@ +/*- + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +extern int quiet; +extern int verbose; + +void check(char **); + +void audit_pkgdb(int, char **); +void audit_pkg(int, char **); +void audit_batch(int, char **); +void audit_history(int, char **); +void check_pkg_vulnerabilities(int, char **); +void fetch_pkg_vulnerabilities(int, char **); + +void usage(void); diff --git a/external/bsd/pkg_install/dist/admin/audit-packages.8 b/external/bsd/pkg_install/dist/admin/audit-packages.8 new file mode 100644 index 000000000..2a8dbb728 --- /dev/null +++ b/external/bsd/pkg_install/dist/admin/audit-packages.8 @@ -0,0 +1,66 @@ +.\" $NetBSD: audit-packages.8,v 1.1.1.1 2010/04/23 20:54:06 joerg Exp $ +.\" +.\" Copyright (c) 2010 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Thomas Klausner. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd March 18, 2010 +.Dt AUDIT-PACKAGES 8 +.Os +.Sh NAME +.Nm audit-packages +.Nd report vulnerabilities for the installed packages +.Sh SYNOPSIS +.Nm +.Op Fl deqsVv +.Op Fl c Ar config_file +.Op Fl F Ar file +.Op Fl g Ar file +.Op Fl h Ar file +.Op Fl K Ar pkg_dbdir +.Op Fl n Ar package +.Op Fl p Ar package +.Op Fl Q Ar varname +.Op Fl t Ar type +.Sh DESCRIPTION +.Nm +is deprecated. +Please use the +.Cm audit , +.Cm audit-pkg , +.Cm audit-batch , +and +.Cm fetch-pkg-vulnerabilities +commands of +.Xr pkg_admin 1 +instead. +.Pp +The +.Nm +script is installed for backwards compatibility only and will +eventually be removed. +.Sh SEE ALSO +.Xr pkg_admin 1 diff --git a/external/bsd/pkg_install/dist/admin/audit-packages.sh.in b/external/bsd/pkg_install/dist/admin/audit-packages.sh.in new file mode 100644 index 000000000..dfd9814ce --- /dev/null +++ b/external/bsd/pkg_install/dist/admin/audit-packages.sh.in @@ -0,0 +1,130 @@ +#!/bin/sh + +pkg_admin=@PKG_ADMIN@ + +usage() { + echo 'Usage: audit-packages [-deqsVv] [-c config_file] [-F file]' >& $2 + echo ' [-g file] [-h file]' >& $2 + echo ' [-K pkg_dbdir] [-n package] [-p package]' >& $2 + echo ' [-Q varname] [-t type]' >& $2 + echo "Please use the audit, audit-pkg, audit-batch and fetch-pkg-vulnerabilities" >& $2 + echo "commands of pkg_admin instead." >& $2 + exit $1 +} + +do_pkgdb= +do_eol= +do_fetch= +do_quiet= +do_sign= +do_verbose= +do_check_file= +do_check_pattern= +do_check_installed= +do_check_vul_file= +do_limit_type= +do_print_var= + +args=`getopt F:K:Q:Vc:deg:h:n:p:qst:v $*` +if [ $? -ne 0 ]; then + usage 1 2 +fi + +set -- $args + +while [ $# -gt 0 ]; do + case "$1" in + -F) + do_check_file=$2 + shift + ;; + -K) + do_pkgdb="$1 $2" + shift + ;; + -Q) + do_print_var="$2" + shift + ;; + -V) + exec ${pkg_admin} -V + ;; + -c) + echo "The audit-packages wrapper does not support -c" >&2 + echo "Please use the audit, audit-pkg, audit-batch and fetch-pkg-vulnerabilities" >& 2 + echo "commands of pkg_admin instead." >& 2 + exit 1 + ;; + -d) + do_fetch=1 + ;; + -e) + do_eol=-e + ;; + -g) + echo "The audit-packages wrapper does not support -g" >&2 + echo "Please switch to \`\`pkg_admin fetch-pkg-vulnerabilities''." >&2 + exit 1 + ;; + -h) + do_check_vul_file=$2 + shift + ;; + -n) + do_check_pattern=$2 + shift + ;; + -p) + do_check_installed=$2 + shift + ;; + -q) + do_quiet=-q + ;; + -s) + do_sign=-s + ;; + -t) + do_limit_type="-t $2" + shift + ;; + -v) + do_verbose="$do_verbose -v" + ;; + esac + shift +done + +if [ -n "${do_fetch}" ]; then + exec ${pkg_admin} ${do_pkgdb} fetch-pkg-vulnerabilities ${do_sign} +fi + +if [ -n "${do_check_vul_file}" ]; then + exec ${pkg_admin} ${do_pkgdb} check-pkg-vulnerabilities ${do_sign} "${do_check_vul_file}" +fi + +if [ -n "${do_print_var}" ]; then + exec ${pkg_admin} ${do_pkgdb} config-var "${do_print_var}" +fi + +if [ -n "${do_check_file}" ]; then + if [ -n "${do_check_pattern}" -o -n "${do_check_installed}" ]; then + echo "Only one of -F, -n or -p is interpreted at a time." >& 2 + usage 1 2 + fi + exec ${pkg_admin} ${do_pkgdb} ${do_verbose} ${do_quiet} audit-pkg \ + ${do_eol} ${do_limit_type} ${do_check_file} +fi + +if [ -n "${do_check_pattern}" ]; then + if [ -n "${do_check_installed}" ]; then + echo "Only one of -F, -n or -p is interpreted at a time." >& 2 + usage 1 2 + fi + exec ${pkg_admin} ${do_pkgdb} ${do_verbose} ${do_quiet} audit-pkg \ + ${do_eol} ${do_limit_type} ${do_check_pattern} +fi + +# If do_check_installed is empty, all packages are checked. +exec ${pkg_admin} ${do_pkgdb} ${do_verbose} ${do_quiet} audit \ + ${do_eol} ${do_limit_type} ${do_check_installed} diff --git a/external/bsd/pkg_install/dist/admin/audit.c b/external/bsd/pkg_install/dist/admin/audit.c new file mode 100644 index 000000000..7f4e6a745 --- /dev/null +++ b/external/bsd/pkg_install/dist/admin/audit.c @@ -0,0 +1,507 @@ +/* $NetBSD: audit.c,v 1.1.1.9 2011/02/18 22:32:28 aymeric Exp $ */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: audit.c,v 1.1.1.9 2011/02/18 22:32:28 aymeric Exp $"); + +/*- + * Copyright (c) 2008 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_ERR_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif +#if HAVE_SIGNAL_H +#include +#endif +#if HAVE_STDIO_H +#include +#endif +#if HAVE_STRING_H +#include +#endif +#ifdef NETBSD +#include +#else +#include +#endif + +#include + +#include "admin.h" +#include "lib.h" + +static int check_signature = 0; +static const char *limit_vul_types = NULL; +static int update_pkg_vuln = 0; + +static struct pkg_vulnerabilities *pv; + +static const char audit_options[] = "est:"; + +static void +parse_options(int argc, char **argv, const char *options) +{ + int ch; + + optreset = 1; + /* + * optind == 0 is interpreted as partial reset request + * by GNU getopt, so compensate against this and cleanup + * at the end. + */ + optind = 1; + ++argc; + --argv; + + while ((ch = getopt(argc, argv, options)) != -1) { + switch (ch) { + case 'e': + check_eol = "yes"; + break; + case 's': + check_signature = 1; + break; + case 't': + limit_vul_types = optarg; + break; + case 'u': + update_pkg_vuln = 1; + break; + default: + usage(); + /* NOTREACHED */ + } + } + + --optind; /* See above comment. */ +} + +static int +check_exact_pkg(const char *pkg) +{ + return audit_package(pv, pkg, limit_vul_types, quiet ? 0 : 1); +} + +static int +check_batch_exact_pkgs(const char *fname) +{ + FILE *f; + char buf[4096], *line, *eol; + int ret; + + ret = 0; + if (strcmp(fname, "-") == 0) + f = stdin; + else { + f = fopen(fname, "r"); + if (f == NULL) + err(EXIT_FAILURE, "Failed to open input file %s", + fname); + } + while ((line = fgets(buf, sizeof(buf), f)) != NULL) { + eol = line + strlen(line); + if (eol == line) + continue; + --eol; + if (*eol == '\n') { + if (eol == line) + continue; + *eol = '\0'; + } + ret |= check_exact_pkg(line); + } + if (f != stdin) + fclose(f); + + return ret; +} + +static int +check_one_installed_pkg(const char *pkg, void *cookie) +{ + int *ret = cookie; + + *ret |= check_exact_pkg(pkg); + return 0; +} + +static int +check_installed_pattern(const char *pattern) +{ + int ret = 0; + + match_installed_pkgs(pattern, check_one_installed_pkg, &ret); + + return ret; +} + +static void +check_and_read_pkg_vulnerabilities(void) +{ + struct stat st; + time_t now; + + if (pkg_vulnerabilities_file == NULL) + errx(EXIT_FAILURE, "PKG_VULNERABILITIES is not set"); + + if (verbose >= 1) { + if (stat(pkg_vulnerabilities_file, &st) == -1) { + if (errno == ENOENT) + errx(EXIT_FAILURE, + "pkg-vulnerabilities not found, run %s -d", + getprogname()); + errx(EXIT_FAILURE, "pkg-vulnerabilities not readable"); + } + now = time(NULL); + now -= st.st_mtime; + if (now < 0) + warnx("pkg-vulnerabilities is from the future"); + else if (now > 86400 * 7) + warnx("pkg-vulnerabilities is out of date (%ld days old)", + (long)(now / 86400)); + else if (verbose >= 2) + warnx("pkg-vulnerabilities is %ld day%s old", + (long)(now / 86400), now / 86400 == 1 ? "" : "s"); + } + + pv = read_pkg_vulnerabilities_file(pkg_vulnerabilities_file, 0, check_signature); +} + +void +audit_pkgdb(int argc, char **argv) +{ + int rv; + + parse_options(argc, argv, audit_options); + argv += optind; + + check_and_read_pkg_vulnerabilities(); + + rv = 0; + if (*argv == NULL) + rv |= check_installed_pattern("*"); + else { + for (; *argv != NULL; ++argv) + rv |= check_installed_pattern(*argv); + } + free_pkg_vulnerabilities(pv); + + if (rv == 0 && verbose >= 1) + fputs("No vulnerabilities found\n", stderr); + exit(rv ? EXIT_FAILURE : EXIT_SUCCESS); +} + +void +audit_pkg(int argc, char **argv) +{ + int rv; + + parse_options(argc, argv, audit_options); + argv += optind; + + check_and_read_pkg_vulnerabilities(); + rv = 0; + for (; *argv != NULL; ++argv) + rv |= check_exact_pkg(*argv); + + free_pkg_vulnerabilities(pv); + + if (rv == 0 && verbose >= 1) + fputs("No vulnerabilities found\n", stderr); + exit(rv ? EXIT_FAILURE : EXIT_SUCCESS); +} + +void +audit_batch(int argc, char **argv) +{ + int rv; + + parse_options(argc, argv, audit_options); + argv += optind; + + check_and_read_pkg_vulnerabilities(); + rv = 0; + for (; *argv != NULL; ++argv) + rv |= check_batch_exact_pkgs(*argv); + free_pkg_vulnerabilities(pv); + + if (rv == 0 && verbose >= 1) + fputs("No vulnerabilities found\n", stderr); + exit(rv ? EXIT_FAILURE : EXIT_SUCCESS); +} + +void +check_pkg_vulnerabilities(int argc, char **argv) +{ + parse_options(argc, argv, "s"); + if (argc != optind + 1) + usage(); + + pv = read_pkg_vulnerabilities_file(argv[optind], 0, check_signature); + free_pkg_vulnerabilities(pv); +} + +void +fetch_pkg_vulnerabilities(int argc, char **argv) +{ + struct pkg_vulnerabilities *pv_check; + char *buf; + size_t buf_len, buf_fetched; + ssize_t cur_fetched; + struct url *url; + struct url_stat st; + fetchIO *f; + int fd; + struct stat sb; + char my_flags[20]; + const char *flags; + + parse_options(argc, argv, "su"); + if (argc != optind) + usage(); + + if (verbose >= 2) + fprintf(stderr, "Fetching %s\n", pkg_vulnerabilities_url); + + url = fetchParseURL(pkg_vulnerabilities_url); + if (url == NULL) + errx(EXIT_FAILURE, + "Could not parse location of pkg_vulnerabilities: %s", + fetchLastErrString); + + flags = fetch_flags; + if (update_pkg_vuln) { + fd = open(pkg_vulnerabilities_file, O_RDONLY); + if (fd != -1 && fstat(fd, &sb) != -1) { + url->last_modified = sb.st_mtime; + snprintf(my_flags, sizeof(my_flags), "%si", + fetch_flags); + flags = my_flags; + } else + update_pkg_vuln = 0; + if (fd != -1) + close(fd); + } + + f = fetchXGet(url, &st, flags); + if (f == NULL && update_pkg_vuln && + fetchLastErrCode == FETCH_UNCHANGED) { + if (verbose >= 1) + fprintf(stderr, "%s is not newer\n", + pkg_vulnerabilities_url); + exit(EXIT_SUCCESS); + } + + if (f == NULL) + errx(EXIT_FAILURE, "Could not fetch vulnerability file: %s", + fetchLastErrString); + + if (st.size > SSIZE_MAX - 1) + errx(EXIT_FAILURE, "pkg-vulnerabilities is too large"); + + buf_len = st.size; + buf = xmalloc(buf_len + 1); + buf_fetched = 0; + + while (buf_fetched < buf_len) { + cur_fetched = fetchIO_read(f, buf + buf_fetched, + buf_len - buf_fetched); + if (cur_fetched == 0) + errx(EXIT_FAILURE, + "Truncated pkg-vulnerabilities received"); + else if (cur_fetched == -1) + errx(EXIT_FAILURE, + "IO error while fetching pkg-vulnerabilities: %s", + fetchLastErrString); + buf_fetched += cur_fetched; + } + + buf[buf_len] = '\0'; + + pv_check = read_pkg_vulnerabilities_memory(buf, buf_len, check_signature); + free_pkg_vulnerabilities(pv_check); + + fd = open(pkg_vulnerabilities_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) + err(EXIT_FAILURE, "Cannot create pkg-vulnerability file %s", + pkg_vulnerabilities_file); + + if (write(fd, buf, buf_len) != (ssize_t)buf_len) + err(EXIT_FAILURE, "Cannot write pkg-vulnerability file"); + if (close(fd) == -1) + err(EXIT_FAILURE, "Cannot close pkg-vulnerability file after write"); + + free(buf); + + exit(EXIT_SUCCESS); +} + +static int +check_pkg_history_pattern(const char *pkg, const char *pattern) +{ + const char *delim, *end_base; + + if (strpbrk(pattern, "*[") != NULL) { + end_base = NULL; + for (delim = pattern; + *delim != '\0' && *delim != '['; delim++) { + if (*delim == '-') + end_base = delim; + } + + if (end_base == NULL) + errx(EXIT_FAILURE, "Missing - in wildcard pattern %s", + pattern); + if ((delim = strchr(pattern, '>')) != NULL || + (delim = strchr(pattern, '<')) != NULL) + errx(EXIT_FAILURE, + "Mixed relational and wildcard patterns in %s", + pattern); + } else if ((delim = strchr(pattern, '>')) != NULL) { + end_base = delim; + if ((delim = strchr(pattern, '<')) != NULL && delim < end_base) + errx(EXIT_FAILURE, "Inverted operators in %s", + pattern); + } else if ((delim = strchr(pattern, '<')) != NULL) { + end_base = delim; + } else if ((end_base = strrchr(pattern, '-')) == NULL) { + errx(EXIT_FAILURE, "Missing - in absolute pattern %s", + pattern); + } + + if (strncmp(pkg, pattern, end_base - pattern) != 0) + return 0; + if (pkg[end_base - pattern] != '\0') + return 0; + + return 1; +} + +static int +check_pkg_history1(const char *pkg, const char *pattern) +{ + const char *open_brace, *close_brace, *inner_brace, *suffix, *iter; + size_t prefix_len, suffix_len, middle_len; + char *expanded_pkg; + + open_brace = strchr(pattern, '{'); + if (open_brace == NULL) { + if ((close_brace = strchr(pattern, '}')) != NULL) + errx(EXIT_FAILURE, "Unbalanced {} in pattern %s", + pattern); + return check_pkg_history_pattern(pkg, pattern); + } + close_brace = strchr(open_brace, '}'); + if (strchr(pattern, '}') != close_brace) + errx(EXIT_FAILURE, "Unbalanced {} in pattern %s", + pattern); + + while ((inner_brace = strchr(open_brace + 1, '{')) != NULL) { + if (inner_brace >= close_brace) + break; + open_brace = inner_brace; + } + + expanded_pkg = xmalloc(strlen(pattern)); /* {} are going away... */ + + prefix_len = open_brace - pattern; + suffix = close_brace + 1; + suffix_len = strlen(suffix) + 1; + memcpy(expanded_pkg, pattern, prefix_len); + + ++open_brace; + + do { + iter = strchr(open_brace, ','); + if (iter == NULL || iter > close_brace) + iter = close_brace; + + middle_len = iter - open_brace; + memcpy(expanded_pkg + prefix_len, open_brace, middle_len); + memcpy(expanded_pkg + prefix_len + middle_len, suffix, + suffix_len); + if (check_pkg_history1(pkg, expanded_pkg)) { + free(expanded_pkg); + return 1; + } + open_brace = iter + 1; + } while (iter < close_brace); + + free(expanded_pkg); + return 0; +} + +static void +check_pkg_history(const char *pkg) +{ + size_t i; + + for (i = 0; i < pv->entries; ++i) { + if (!quick_pkg_match(pv->vulnerability[i], pkg)) + continue; + if (strcmp("eol", pv->classification[i]) == 0) + continue; + if (check_pkg_history1(pkg, pv->vulnerability[i]) == 0) + continue; + + printf("%s %s %s\n", pv->vulnerability[i], + pv->classification[i], pv->advisory[i]); + } +} + +void +audit_history(int argc, char **argv) +{ + parse_options(argc, argv, "st:"); + argv += optind; + + check_and_read_pkg_vulnerabilities(); + for (; *argv != NULL; ++argv) + check_pkg_history(*argv); + + free_pkg_vulnerabilities(pv); + exit(EXIT_SUCCESS); +} diff --git a/external/bsd/pkg_install/dist/admin/check.c b/external/bsd/pkg_install/dist/admin/check.c new file mode 100644 index 000000000..d9de28687 --- /dev/null +++ b/external/bsd/pkg_install/dist/admin/check.c @@ -0,0 +1,259 @@ +/* $NetBSD: check.c,v 1.1.1.4 2010/01/30 21:33:23 joerg Exp $ */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: check.c,v 1.1.1.4 2010/01/30 21:33:23 joerg Exp $"); + +/*- + * Copyright (c) 1999-2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Hubert Feyrer . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_DIRENT_H +#include +#endif +#if HAVE_ERR_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif +#ifndef NETBSD +#include +#else +#include +#endif +#if HAVE_LIMITS_H +#include +#endif +#if HAVE_STDIO_H +#include +#endif +#if HAVE_STRING_H +#include +#endif + +#include "admin.h" +#include "lib.h" + +static int checkpattern_fn(const char *, void *); + +/* + * Assumes CWD is in /var/db/pkg/! + */ +static void +check1pkg(const char *pkgdir, int *filecnt, int *pkgcnt) +{ + FILE *f; + plist_t *p; + package_t Plist; + char *PkgName, *dirp = NULL, *md5file; + char file[MaxPathSize]; + char *content; + + content = pkgdb_pkg_file(pkgdir, CONTENTS_FNAME); + f = fopen(content, "r"); + if (f == NULL) + err(EXIT_FAILURE, "can't open %s", content); + free(content); + + read_plist(&Plist, f); + p = find_plist(&Plist, PLIST_NAME); + if (p == NULL) + errx(EXIT_FAILURE, "Package %s has no @name, aborting.", + pkgdir); + PkgName = p->name; + for (p = Plist.head; p; p = p->next) { + switch (p->type) { + case PLIST_FILE: + if (dirp == NULL) { + warnx("dirp not initialized, please send-pr!"); + abort(); + } + + (void) snprintf(file, sizeof(file), "%s/%s", dirp, p->name); + + if (isfile(file) || islinktodir(file)) { + if (p->next && p->next->type == PLIST_COMMENT) { + if (strncmp(p->next->name, CHECKSUM_HEADER, ChecksumHeaderLen) == 0) { + if ((md5file = MD5File(file, NULL)) != NULL) { + /* Mismatch? */ + if (strcmp(md5file, p->next->name + ChecksumHeaderLen) != 0) + printf("%s fails MD5 checksum\n", file); + + free(md5file); + } + } else if (strncmp(p->next->name, SYMLINK_HEADER, SymlinkHeaderLen) == 0) { + char buf[MaxPathSize + SymlinkHeaderLen]; + int cc; + + (void) strlcpy(buf, SYMLINK_HEADER, sizeof(buf)); + if ((cc = readlink(file, &buf[SymlinkHeaderLen], + sizeof(buf) - SymlinkHeaderLen - 1)) < 0) { + warnx("can't readlink `%s'", file); + } else { + buf[SymlinkHeaderLen + cc] = 0x0; + if (strcmp(buf, p->next->name) != 0) { + printf("symlink (%s) is not same as recorded value, %s: %s\n", + file, buf, p->next->name); + } + } + } + } + + (*filecnt)++; + } else if (isbrokenlink(file)) { + warnx("%s: Symlink `%s' exists and is in %s but target does not exist!", PkgName, file, CONTENTS_FNAME); + } else { + warnx("%s: File `%s' is in %s but not on filesystem!", PkgName, file, CONTENTS_FNAME); + } + break; + case PLIST_CWD: + if (strcmp(p->name, ".") != 0) + dirp = p->name; + else + dirp = pkgdb_pkg_dir(pkgdir); + break; + case PLIST_IGNORE: + p = p->next; + break; + case PLIST_SHOW_ALL: + case PLIST_SRC: + case PLIST_CMD: + case PLIST_CHMOD: + case PLIST_CHOWN: + case PLIST_CHGRP: + case PLIST_COMMENT: + case PLIST_NAME: + case PLIST_UNEXEC: + case PLIST_DISPLAY: + case PLIST_PKGDEP: + case PLIST_DIR_RM: + case PLIST_OPTION: + case PLIST_PKGCFL: + case PLIST_BLDDEP: + case PLIST_PKGDIR: + break; + } + } + free_plist(&Plist); + fclose(f); + (*pkgcnt)++; +} + +struct checkpattern_arg { + int filecnt; + int pkgcnt; + int got_match; +}; + +static int +checkpattern_fn(const char *pkg, void *vp) +{ + struct checkpattern_arg *arg = vp; + + check1pkg(pkg, &arg->filecnt, &arg->pkgcnt); + if (!quiet) + printf("."); + + arg->got_match = 1; + + return 0; +} + +static void +check_pkg(const char *pkg, int *filecnt, int *pkgcnt, int allow_unmatched) +{ + struct checkpattern_arg arg; + char *pattern; + + arg.filecnt = *filecnt; + arg.pkgcnt = *pkgcnt; + arg.got_match = 0; + + if (match_installed_pkgs(pkg, checkpattern_fn, &arg) == -1) + errx(EXIT_FAILURE, "Cannot process pkdbdb"); + if (arg.got_match != 0) { + *filecnt = arg.filecnt; + *pkgcnt = arg.pkgcnt; + return; + } + + if (ispkgpattern(pkg)) { + if (allow_unmatched) + return; + errx(EXIT_FAILURE, "No matching pkg for %s.", pkg); + } + + pattern = xasprintf("%s-[0-9]*", pkg); + + if (match_installed_pkgs(pattern, checkpattern_fn, &arg) == -1) + errx(EXIT_FAILURE, "Cannot process pkdbdb"); + + if (arg.got_match == 0) + errx(EXIT_FAILURE, "cannot find package %s", pkg); + free(pattern); + + *filecnt = arg.filecnt; + *pkgcnt = arg.pkgcnt; +} + +void +check(char **argv) +{ + int filecnt, pkgcnt; + + filecnt = 0; + pkgcnt = 0; + setbuf(stdout, NULL); + + if (*argv == NULL) { + check_pkg("*", &filecnt, &pkgcnt, 1); + } else { + for (; *argv != NULL; ++argv) + check_pkg(*argv, &filecnt, &pkgcnt, 0); + } + + printf("\n"); + printf("Checked %d file%s from %d package%s.\n", + filecnt, (filecnt == 1) ? "" : "s", + pkgcnt, (pkgcnt == 1) ? "" : "s"); +} diff --git a/external/bsd/pkg_install/dist/admin/download-vulnerability-list.8 b/external/bsd/pkg_install/dist/admin/download-vulnerability-list.8 new file mode 100644 index 000000000..b475f64f4 --- /dev/null +++ b/external/bsd/pkg_install/dist/admin/download-vulnerability-list.8 @@ -0,0 +1,54 @@ +.\" $NetBSD: download-vulnerability-list.8,v 1.1.1.1 2010/04/23 20:54:06 joerg Exp $ +.\" +.\" Copyright (c) 2010 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Thomas Klausner. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd March 18, 2010 +.Dt DOWNLOAD-VULNERABILITY-LIST 8 +.Os +.Sh NAME +.Nm download-vulnerability-list +.Nd download vulnerability list used for checking installed packages +.Sh SYNOPSIS +.Nm +.Op Fl hs +.Op Fl c Ar config_file +.Sh DESCRIPTION +.Nm +is deprecated. +Please use the +.Cm fetch-pkg-vulnerabilities +command of +.Xr pkg_admin 1 +instead. +.Pp +The +.Nm +script is installed for backwards compatibility only and will +eventually be removed. +.Sh SEE ALSO +.Xr pkg_admin 1 diff --git a/external/bsd/pkg_install/dist/admin/download-vulnerability-list.sh.in b/external/bsd/pkg_install/dist/admin/download-vulnerability-list.sh.in new file mode 100644 index 000000000..c2e5184f4 --- /dev/null +++ b/external/bsd/pkg_install/dist/admin/download-vulnerability-list.sh.in @@ -0,0 +1,37 @@ +#!/bin/sh + +pkg_admin=@PKG_ADMIN@ + +usage() { + echo 'Usage: download-vulnerability-list [-hs] [-c config_file]' >& $2 + echo "Please use \`\`pkg_admin fetch-pkg-vulnerabilities'' instead." >& $2 + exit $1 +} + +do_sign= + +args=`getopt c:hs $*` +if [ $? -ne 0 ]; then + usage 1 2 +fi + +set -- $args + +while [ $# -gt 0 ]; do + case "$1" in + -c) + echo "The download-vulnerability-list wrapper does not support -c" >&2 + echo "Please switch to \`\`pkg_admin fetch-pkg-vulnerabilities''." >&2 + exit 1 + ;; + -h) + usage 0 1 + ;; + -s) + do_sign=-s + ;; + esac + shift +done + +exec ${pkg_admin} fetch-pkg-vulnerabilities ${do_sign} diff --git a/external/bsd/pkg_install/dist/admin/main.c b/external/bsd/pkg_install/dist/admin/main.c new file mode 100644 index 000000000..56a5353c4 --- /dev/null +++ b/external/bsd/pkg_install/dist/admin/main.c @@ -0,0 +1,754 @@ +/* $NetBSD: main.c,v 1.1.1.15 2010/04/23 20:54:07 joerg Exp $ */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: main.c,v 1.1.1.15 2010/04/23 20:54:07 joerg Exp $"); + +/*- + * Copyright (c) 1999-2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Hubert Feyrer and + * by Joerg Sonnenberger . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_DIRENT_H +#include +#endif +#if HAVE_ERR_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif +#ifndef NETBSD +#include +#else +#include +#endif +#if HAVE_LIMITS_H +#include +#endif +#if HAVE_STDIO_H +#include +#endif +#if HAVE_STRING_H +#include +#endif + +#ifndef BOOTSTRAP +#include +#include +#endif + +#include "admin.h" +#include "lib.h" + +#define DEFAULT_SFX ".t[bg]z" /* default suffix for ls{all,best} */ + +struct pkgdb_count { + size_t files; + size_t directories; + size_t packages; +}; + +static const char Options[] = "C:K:SVbd:qs:v"; + +int quiet, verbose; + +static void set_unset_variable(char **, Boolean); + +/* print usage message and exit */ +void +usage(void) +{ + (void) fprintf(stderr, "usage: %s [-bqSVv] [-C config] [-d lsdir] [-K pkg_dbdir] [-s sfx] command [args ...]\n" + "Where 'commands' and 'args' are:\n" + " rebuild - rebuild pkgdb from +CONTENTS files\n" + " rebuild-tree - rebuild +REQUIRED_BY files from forward deps\n" + " check [pkg ...] - check md5 checksum of installed files\n" + " add pkg ... - add pkg files to database\n" + " delete pkg ... - delete file entries for pkg in database\n" + " set variable=value pkg ... - set installation variable for package\n" + " unset variable pkg ... - unset installation variable for package\n" + " lsall /path/to/pkgpattern - list all pkgs matching the pattern\n" + " lsbest /path/to/pkgpattern - list pkgs matching the pattern best\n" + " dump - dump database\n" + " pmatch pattern pkg - returns true if pkg matches pattern, otherwise false\n" + " fetch-pkg-vulnerabilities [-s] - fetch new vulnerability file\n" + " check-pkg-vulnerabilities [-s] - check syntax and checksums of the vulnerability file\n" + " audit [-es] [-t type] ... - check installed packages for vulnerabilities\n" + " audit-pkg [-es] [-t type] ... - check listed packages for vulnerabilities\n" + " audit-batch [-es] [-t type] ... - check packages in listed files for vulnerabilities\n" + " audit-history [-t type] ... - print all advisories for package names\n" + " check-license - check if condition is acceptable\n" + " check-single-license - check if license is acceptable\n" + " config-var name - print current value of the configuration variable\n" + " check-signature ... - verify the signature of packages\n" + " x509-sign-package pkg spkg key cert - create X509 signature\n" + " gpg-sign-package pkg spkg - create GPG signature\n", + getprogname()); + exit(EXIT_FAILURE); +} + +/* + * add1pkg() + * adds the files listed in the +CONTENTS of into the + * pkgdb.byfile.db database file in the current package dbdir. It + * returns the number of files added to the database file. + */ +static int +add_pkg(const char *pkgdir, void *vp) +{ + FILE *f; + plist_t *p; + package_t Plist; + char *contents; + char *PkgName, *dirp; + char file[MaxPathSize]; + struct pkgdb_count *count; + + if (!pkgdb_open(ReadWrite)) + err(EXIT_FAILURE, "cannot open pkgdb"); + + count = vp; + ++count->packages; + + contents = pkgdb_pkg_file(pkgdir, CONTENTS_FNAME); + if ((f = fopen(contents, "r")) == NULL) + errx(EXIT_FAILURE, "%s: can't open `%s'", pkgdir, CONTENTS_FNAME); + free(contents); + + read_plist(&Plist, f); + if ((p = find_plist(&Plist, PLIST_NAME)) == NULL) { + errx(EXIT_FAILURE, "Package `%s' has no @name, aborting.", pkgdir); + } + + PkgName = p->name; + dirp = NULL; + for (p = Plist.head; p; p = p->next) { + switch(p->type) { + case PLIST_FILE: + if (dirp == NULL) { + errx(EXIT_FAILURE, "@cwd not yet found, please send-pr!"); + } + (void) snprintf(file, sizeof(file), "%s/%s", dirp, p->name); + if (!(isfile(file) || islinktodir(file))) { + if (isbrokenlink(file)) { + warnx("%s: Symlink `%s' exists and is in %s but target does not exist!", + PkgName, file, CONTENTS_FNAME); + } else { + warnx("%s: File `%s' is in %s but not on filesystem!", + PkgName, file, CONTENTS_FNAME); + } + } else { + pkgdb_store(file, PkgName); + ++count->files; + } + break; + case PLIST_PKGDIR: + add_pkgdir(PkgName, dirp, p->name); + ++count->directories; + break; + case PLIST_CWD: + if (strcmp(p->name, ".") != 0) + dirp = p->name; + else + dirp = pkgdb_pkg_dir(pkgdir); + break; + case PLIST_IGNORE: + p = p->next; + break; + case PLIST_SHOW_ALL: + case PLIST_SRC: + case PLIST_CMD: + case PLIST_CHMOD: + case PLIST_CHOWN: + case PLIST_CHGRP: + case PLIST_COMMENT: + case PLIST_NAME: + case PLIST_UNEXEC: + case PLIST_DISPLAY: + case PLIST_PKGDEP: + case PLIST_DIR_RM: + case PLIST_OPTION: + case PLIST_PKGCFL: + case PLIST_BLDDEP: + break; + } + } + free_plist(&Plist); + fclose(f); + pkgdb_close(); + + return 0; +} + +static void +delete1pkg(const char *pkgdir) +{ + if (!pkgdb_open(ReadWrite)) + err(EXIT_FAILURE, "cannot open pkgdb"); + (void) pkgdb_remove_pkg(pkgdir); + pkgdb_close(); +} + +static void +rebuild(void) +{ + char *cachename; + struct pkgdb_count count; + + count.files = 0; + count.directories = 0; + count.packages = 0; + + cachename = pkgdb_get_database(); + if (unlink(cachename) != 0 && errno != ENOENT) + err(EXIT_FAILURE, "unlink %s", cachename); + + setbuf(stdout, NULL); + + iterate_pkg_db(add_pkg, &count); + + printf("\n"); + printf("Stored %" PRIzu " file%s and %zu explicit director%s" + " from %"PRIzu " package%s in %s.\n", + count.files, count.files == 1 ? "" : "s", + count.directories, count.directories == 1 ? "y" : "ies", + count.packages, count.packages == 1 ? "" : "s", + cachename); +} + +static int +lspattern(const char *pkg, void *vp) +{ + const char *dir = vp; + printf("%s/%s\n", dir, pkg); + return 0; +} + +static int +lsbasepattern(const char *pkg, void *vp) +{ + puts(pkg); + return 0; +} + +static int +remove_required_by(const char *pkgname, void *cookie) +{ + char *path; + + path = pkgdb_pkg_file(pkgname, REQUIRED_BY_FNAME); + + if (unlink(path) == -1 && errno != ENOENT) + err(EXIT_FAILURE, "Cannot remove %s", path); + + free(path); + + return 0; +} + +static void +add_required_by(const char *pattern, const char *required_by) +{ + char *best_installed, *path; + int fd; + size_t len; + + best_installed = find_best_matching_installed_pkg(pattern); + if (best_installed == NULL) { + warnx("Dependency %s of %s unresolved", pattern, required_by); + return; + } + + path = pkgdb_pkg_file(best_installed, REQUIRED_BY_FNAME); + free(best_installed); + + if ((fd = open(path, O_WRONLY | O_APPEND | O_CREAT, 0644)) == -1) + errx(EXIT_FAILURE, "Cannot write to %s", path); + free(path); + + len = strlen(required_by); + if (write(fd, required_by, len) != (ssize_t)len || + write(fd, "\n", 1) != 1 || + close(fd) == -1) + errx(EXIT_FAILURE, "Cannot write to %s", path); +} + + +static int +add_depends_of(const char *pkgname, void *cookie) +{ + FILE *fp; + plist_t *p; + package_t plist; + char *path; + + path = pkgdb_pkg_file(pkgname, CONTENTS_FNAME); + if ((fp = fopen(path, "r")) == NULL) + errx(EXIT_FAILURE, "Cannot read %s of package %s", + CONTENTS_FNAME, pkgname); + free(path); + read_plist(&plist, fp); + fclose(fp); + + for (p = plist.head; p; p = p->next) { + if (p->type == PLIST_PKGDEP) + add_required_by(p->name, pkgname); + } + + free_plist(&plist); + + return 0; +} + +static void +rebuild_tree(void) +{ + if (iterate_pkg_db(remove_required_by, NULL) == -1) + errx(EXIT_FAILURE, "cannot iterate pkgdb"); + if (iterate_pkg_db(add_depends_of, NULL) == -1) + errx(EXIT_FAILURE, "cannot iterate pkgdb"); +} + +int +main(int argc, char *argv[]) +{ + Boolean use_default_sfx = TRUE; + Boolean show_basename_only = FALSE; + char lsdir[MaxPathSize]; + char sfx[MaxPathSize]; + char *lsdirp = NULL; + int ch; + + setprogname(argv[0]); + + if (argc < 2) + usage(); + + while ((ch = getopt(argc, argv, Options)) != -1) + switch (ch) { + case 'C': + config_file = optarg; + break; + + case 'K': + pkgdb_set_dir(optarg, 3); + break; + + case 'S': + sfx[0] = 0x0; + use_default_sfx = FALSE; + break; + + case 'V': + show_version(); + /* NOTREACHED */ + + case 'b': + show_basename_only = TRUE; + break; + + case 'd': + (void) strlcpy(lsdir, optarg, sizeof(lsdir)); + lsdirp = lsdir; + break; + + case 'q': + quiet = 1; + break; + + case 's': + (void) strlcpy(sfx, optarg, sizeof(sfx)); + use_default_sfx = FALSE; + break; + + case 'v': + ++verbose; + break; + + default: + usage(); + /* NOTREACHED */ + } + + argc -= optind; + argv += optind; + + if (argc <= 0) { + usage(); + } + + /* + * config-var is reading the config file implicitly, + * so skip it here. + */ + if (strcasecmp(argv[0], "config-var") != 0) + pkg_install_config(); + + if (use_default_sfx) + (void) strlcpy(sfx, DEFAULT_SFX, sizeof(sfx)); + + if (strcasecmp(argv[0], "pmatch") == 0) { + + char *pattern, *pkg; + + argv++; /* "pmatch" */ + + if (argv[0] == NULL || argv[1] == NULL) { + usage(); + } + + pattern = argv[0]; + pkg = argv[1]; + + if (pkg_match(pattern, pkg)){ + return 0; + } else { + return 1; + } + + } else if (strcasecmp(argv[0], "rebuild") == 0) { + + rebuild(); + printf("Done.\n"); + + + } else if (strcasecmp(argv[0], "rebuild-tree") == 0) { + + rebuild_tree(); + printf("Done.\n"); + + } else if (strcasecmp(argv[0], "check") == 0) { + argv++; /* "check" */ + + check(argv); + + if (!quiet) { + printf("Done.\n"); + } + + } else if (strcasecmp(argv[0], "lsall") == 0) { + argv++; /* "lsall" */ + + while (*argv != NULL) { + /* args specified */ + int rc; + const char *basep, *dir; + + dir = lsdirp ? lsdirp : dirname_of(*argv); + basep = basename_of(*argv); + + if (show_basename_only) + rc = match_local_files(dir, use_default_sfx, 1, basep, lsbasepattern, NULL); + else + rc = match_local_files(dir, use_default_sfx, 1, basep, lspattern, __UNCONST(dir)); + if (rc == -1) + errx(EXIT_FAILURE, "Error from match_local_files(\"%s\", \"%s\", ...)", + dir, basep); + + argv++; + } + + } else if (strcasecmp(argv[0], "lsbest") == 0) { + argv++; /* "lsbest" */ + + while (*argv != NULL) { + /* args specified */ + const char *basep, *dir; + char *p; + + dir = lsdirp ? lsdirp : dirname_of(*argv); + basep = basename_of(*argv); + + p = find_best_matching_file(dir, basep, use_default_sfx, 1); + + if (p) { + if (show_basename_only) + printf("%s\n", p); + else + printf("%s/%s\n", dir, p); + free(p); + } + + argv++; + } + } else if (strcasecmp(argv[0], "list") == 0 || + strcasecmp(argv[0], "dump") == 0) { + + pkgdb_dump(); + + } else if (strcasecmp(argv[0], "add") == 0) { + struct pkgdb_count count; + + count.files = 0; + count.directories = 0; + count.packages = 0; + + for (++argv; *argv != NULL; ++argv) + add_pkg(*argv, &count); + } else if (strcasecmp(argv[0], "delete") == 0) { + argv++; /* "delete" */ + while (*argv != NULL) { + delete1pkg(*argv); + argv++; + } + } else if (strcasecmp(argv[0], "set") == 0) { + argv++; /* "set" */ + set_unset_variable(argv, FALSE); + } else if (strcasecmp(argv[0], "unset") == 0) { + argv++; /* "unset" */ + set_unset_variable(argv, TRUE); + } else if (strcasecmp(argv[0], "config-var") == 0) { + argv++; + if (argv == NULL || argv[1] != NULL) + errx(EXIT_FAILURE, "config-var takes exactly one argument"); + pkg_install_show_variable(argv[0]); + } else if (strcasecmp(argv[0], "check-license") == 0) { + if (argv[1] == NULL) + errx(EXIT_FAILURE, "check-license takes exactly one argument"); + + load_license_lists(); + + switch (acceptable_pkg_license(argv[1])) { + case 0: + puts("no"); + return 0; + case 1: + puts("yes"); + return 0; + case -1: + errx(EXIT_FAILURE, "invalid license condition"); + } + } else if (strcasecmp(argv[0], "check-single-license") == 0) { + if (argv[1] == NULL) + errx(EXIT_FAILURE, "check-license takes exactly one argument"); + load_license_lists(); + + switch (acceptable_license(argv[1])) { + case 0: + puts("no"); + return 0; + case 1: + puts("yes"); + return 0; + case -1: + errx(EXIT_FAILURE, "invalid license"); + } + } +#ifndef BOOTSTRAP + else if (strcasecmp(argv[0], "findbest") == 0) { + struct url *url; + char *output; + int rc; + + process_pkg_path(); + + rc = 0; + for (++argv; *argv != NULL; ++argv) { + url = find_best_package(NULL, *argv, 1); + if (url == NULL) { + rc = 1; + continue; + } + output = fetchStringifyURL(url); + puts(output); + fetchFreeURL(url); + free(output); + } + + return rc; + } else if (strcasecmp(argv[0], "fetch-pkg-vulnerabilities") == 0) { + fetch_pkg_vulnerabilities(--argc, ++argv); + } else if (strcasecmp(argv[0], "check-pkg-vulnerabilities") == 0) { + check_pkg_vulnerabilities(--argc, ++argv); + } else if (strcasecmp(argv[0], "audit") == 0) { + audit_pkgdb(--argc, ++argv); + } else if (strcasecmp(argv[0], "audit-pkg") == 0) { + audit_pkg(--argc, ++argv); + } else if (strcasecmp(argv[0], "audit-batch") == 0) { + audit_batch(--argc, ++argv); + } else if (strcasecmp(argv[0], "audit-history") == 0) { + audit_history(--argc, ++argv); + } else if (strcasecmp(argv[0], "check-signature") == 0) { + struct archive *pkg; + int rc; + + rc = 0; + for (--argc, ++argv; argc > 0; --argc, ++argv) { + char *archive_name; + + pkg = open_archive(*argv, &archive_name); + if (pkg == NULL) { + warnx("%s could not be opened", *argv); + continue; + } + if (pkg_full_signature_check(archive_name, &pkg)) + rc = 1; + free(archive_name); + if (!pkg) + archive_read_finish(pkg); + } + return rc; + } else if (strcasecmp(argv[0], "x509-sign-package") == 0) { +#ifdef HAVE_SSL + --argc; + ++argv; + if (argc != 4) + errx(EXIT_FAILURE, "x509-sign-package takes exactly four arguments"); + pkg_sign_x509(argv[0], argv[1], argv[2], argv[3]); +#else + errx(EXIT_FAILURE, "OpenSSL support is not included"); +#endif + } else if (strcasecmp(argv[0], "gpg-sign-package") == 0) { + --argc; + ++argv; + if (argc != 2) + errx(EXIT_FAILURE, "gpg-sign-package takes exactly two arguments"); + pkg_sign_gpg(argv[0], argv[1]); + } +#endif + else { + usage(); + } + + return 0; +} + +struct set_installed_info_arg { + char *variable; + char *value; + int got_match; +}; + +static int +set_installed_info_var(const char *name, void *cookie) +{ + struct set_installed_info_arg *arg = cookie; + char *filename; + int retval; + + filename = pkgdb_pkg_file(name, INSTALLED_INFO_FNAME); + + retval = var_set(filename, arg->variable, arg->value); + + free(filename); + arg->got_match = 1; + + return retval; +} + +static void +set_unset_variable(char **argv, Boolean unset) +{ + struct set_installed_info_arg arg; + char *eq; + char *variable; + int ret = 0; + + if (argv[0] == NULL || argv[1] == NULL) + usage(); + + variable = NULL; + + if (unset) { + arg.variable = argv[0]; + arg.value = NULL; + } else { + eq = NULL; + if ((eq=strchr(argv[0], '=')) == NULL) + usage(); + + variable = xmalloc(eq-argv[0]+1); + strlcpy(variable, argv[0], eq-argv[0]+1); + + arg.variable = variable; + arg.value = eq+1; + + if (strcmp(variable, AUTOMATIC_VARNAME) == 0 && + strcasecmp(arg.value, "yes") != 0 && + strcasecmp(arg.value, "no") != 0) { + errx(EXIT_FAILURE, + "unknown value `%s' for " AUTOMATIC_VARNAME, + arg.value); + } + } + if (strpbrk(arg.variable, "ABCDEFGHIJKLMNOPQRSTUVWXYZ") != NULL) { + free(variable); + errx(EXIT_FAILURE, + "variable name must not contain uppercase letters"); + } + + argv++; + while (*argv != NULL) { + arg.got_match = 0; + if (match_installed_pkgs(*argv, set_installed_info_var, &arg) == -1) + errx(EXIT_FAILURE, "Cannot process pkdbdb"); + if (arg.got_match == 0) { + char *pattern; + + if (ispkgpattern(*argv)) { + warnx("no matching pkg for `%s'", *argv); + ret++; + } else { + pattern = xasprintf("%s-[0-9]*", *argv); + + if (match_installed_pkgs(pattern, set_installed_info_var, &arg) == -1) + errx(EXIT_FAILURE, "Cannot process pkdbdb"); + + if (arg.got_match == 0) { + warnx("cannot find package %s", *argv); + ++ret; + } + free(pattern); + } + } + + argv++; + } + + if (ret > 0) + exit(EXIT_FAILURE); + + free(variable); + + return; +} diff --git a/external/bsd/pkg_install/dist/admin/pkg_admin.1 b/external/bsd/pkg_install/dist/admin/pkg_admin.1 new file mode 100644 index 000000000..7794af2a2 --- /dev/null +++ b/external/bsd/pkg_install/dist/admin/pkg_admin.1 @@ -0,0 +1,324 @@ +.\" $NetBSD: pkg_admin.1,v 1.1.1.12 2013/04/20 15:26:52 wiz Exp $ +.\" +.\" Copyright (c) 1999-2010 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Hubert Feyrer . +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the NetBSD +.\" Foundation, Inc. and its contributors. +.\" 4. Neither the name of The NetBSD Foundation nor the names of its +.\" contributors may be used to endorse or promote products derived +.\" from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd December 14, 2012 +.Dt PKG_ADMIN 1 +.Os +.Sh NAME +.Nm pkg_admin +.Nd perform various administrative tasks to the pkg system +.Sh SYNOPSIS +.Nm +.Op Fl bqSVv +.Op Fl C Ar config +.Op Fl d Ar lsdir +.Op Fl K Ar pkg_dbdir +.Op Fl s Ar sfx_pattern +.Ar command Op args ... +.Sh DESCRIPTION +This command performs various administrative tasks around the +.Nx +Packages System. +.Sh OPTIONS +The following command-line options are supported: +.Bl -tag -width indent +.It Fl b +Print only the base names when matching package names for +.Cm lsall +and +.Cm lsbest . +.It Fl C Ar config +Read the configuration file from +.Ar config +instead of the system default. +.It Fl d Ar lsdir +Set +.Ar lsdir +as the path to the directory in which to find matching package names for +.Cm lsall +and +.Cm lsbest . +.It Fl K Ar pkg_dbdir +Override the value of the +.Dv PKG_DBDIR +configuration option with the value +.Ar pkg_dbdir . +.It Fl q +Perform checks in a quiet manner. +In normal operation, +.Nm +prints a +.Sq \&. +to standard output to indicate progress. +This option suppresses this progress indicator. +.It Fl S +Set the shell glob pattern for package suffixes when matching package +names for +.Cm lsall +and +.Cm lsbest +to be the null suffix. +.It Fl s Ar sfx_pattern +Set the shell glob pattern for package suffixes when matching package +names for +.Cm lsall +and +.Cm lsbest . +The default pattern is ".t[bg]z". +.It Fl V +Print version number and exit. +.It Fl v +Be more verbose. +.El +.Pp +The following commands are supported: +.Bl -tag -width indent +.It Cm add Ar pkg ... +For each listed package, write the absolute pathnames of the files listed in +its +.Pa +CONTENTS +file together with the package they belong to into the package database. +This should be used only by +.Xr pkg_view 1 . +.It Cm audit Oo Fl es Oc Oo Fl t Ar type Oc Oo Ar pkg Oc ... +Check the listed installed packages for vulnerabilities. +If no package is given, check all installed packages. +If +.Fl e +is given, override the +.Dv CHECK_END_OF_LIFE +option from +.Xr pkg_install.conf 5 +with +.Qq Li yes . +If +.Fl s +is given, check the signature of the pkg-vulnerabilities file before using it. +.Fl t +restricts the reported vulnerabilities to type +.Ar type . +.It Cm audit-pkg Oo Fl es Oc Oo Fl t Ar type Oc Oo Ar pkg Oc ... +Like +.Cm audit , +but check only the given package names or patterns. +.It Cm audit-batch Oo Fl es Oc Oo Fl t Ar type Oc Oo Ar pkg-list Oc ... +Like +.Cm audit-pkg , +but read the package names or patterns one per line from the given files. +.It Cm audit-history Oo Fl s Oc Oo Fl t Ar type Oc Oo Ar pkgbase Oc ... +Print all vulnerabilities for the given base package names. +.It Cm check Op Ar pkg ... +Use this command to check the files belonging to some or all of the +packages installed on the local machine against the checksum +which was recorded in the +.Pa +CONTENTS +files at package installation time. +Symbolic links also have their integrity checked against the recorded +value at package installation time. +If no additional argument is given, the files of all installed packages +are checked, else only the named packages will be checked (wildcards can +be used here, see +.Xr pkg_info 1 ) . +.Pp +The packages' +.Pa +CONTENTS +files will be parsed and the +checksum will be checked for every file found. +A warning message is printed if the expected checksum differs from the +checksum of the file on disk. +Symbolic links are also checked, ensuring that the targets on disk are +the same as the contents recorded at package installation time. +.It Cm check-license Ar condition +Check if +.Ar condition +can be fulfilled with the currently set of accepted licenses. +Prints either yes or no to stdout if the condition can be parsed, +otherwise it exits with error. +.It Cm check-pkg-vulnerabilities Oo Fl s Oc Ar file +Check format and hashes in the pkg-vulnerabilities file +.Ar file . +If +.Fl s +is given, also check the embedded signature. +.It Cm check-signature Ar file ... +Reports if +.Ar file +is a correctly signed package. +.It Cm check-single-license Ar license +Check if +.Ar license +is a valid license name and if it is in the set of acceptable licenses. +Prints either yes or no to stdout if the condition can be parsed, +otherwise it exits with error. +.It Cm config-var Ar variable +Print the current value of +.Ar variable +as used after parsing the configuration file. +.It Cm delete Ar pkg ... +For each listed package, remove all file entries in the package database that +belong to the package. +This should be used only by +.Xr pkg_view 1 . +.It Cm dump +Dump the contents of the package database, similar to +.Cm pkg_info -F . +Columns are printed for the key field used in the pkgdb - the filename -, +and the data field - the package the file belongs to. +.It Cm fetch-pkg-vulnerabilities Oo Fl su Oc +Fetch a new pkg-vulnerabilities file, check the format and if +.Fl s +is given the signature. +If all checks are passed, write it to pkgdb. +If +.Fl u +is given, the fetch is conditional and the file transfer is only done if +the remote version is newer than the one in pkgdb. +.It Cm findbest Ar pattern ... +Search the entries of +.Dv PKG_PATH +for packages matching +.Ar pattern . +Print the URL of the best matching package to stdout for each pattern. +If a pattern is not matched, it is skipped and the command will return +a failure. +.It Cm lsall Ar /dir/pkgpattern +.It Cm lsbest Ar /dir/pkgpattern +List all/best package matching pattern in the given directory +.Pa /dir . +If the +.Fl d +flag is given, then that directory path overrides +.Pa /dir . +Can be used to work around limitations of /bin/sh and other +filename globbing mechanisms. +This option implements matching of +pkg-wildcards against arbitrary files and directories, useful mainly in +the build system itself. +See +.Xr pkg_info 1 +for a description of the pattern. +.Pp +Example: +.Bd -literal +yui# cd /usr/pkgsrc/packages/i386ELF/All/ +yui# ls unzip* +unzip-5.40.tgz unzip-5.41.tgz +yui# pkg_admin lsall 'unzip*' +/usr/pkgsrc/packages/i386ELF/All/unzip-5.40.tgz +/usr/pkgsrc/packages/i386ELF/All/unzip-5.41.tgz +yui# pkg_admin lsall 'unzip\*[Ge]5.40' +/usr/pkgsrc/packages/i386ELF/All/unzip-5.40.tgz +/usr/pkgsrc/packages/i386ELF/All/unzip-5.41.tgz +yui# pkg_admin lsall 'unzip\*[Ge]5.41' +/usr/pkgsrc/packages/i386ELF/All/unzip-5.41.tgz +yui# pkg_admin lsbest 'unzip\*[Ge]5.40' +/usr/pkgsrc/packages/i386ELF/All/unzip-5.41.tgz +yui# pkg_admin lsall /usr/pkgsrc/packages/i386ELF/All/'{mit,unproven}-pthread*' +/usr/pkgsrc/packages/i386ELF/All/mit-pthreads-1.60b6.tgz +/usr/pkgsrc/packages/i386ELF/All/unproven-pthreads-0.15.tgz +.Ed +.It Cm pmatch Ar pattern Ar pkg +Returns true if +.Ar pkg +matches +.Ar pattern , +otherwise returns false. +.It Cm rebuild +Rebuild the package database mapping from scratch, using the +.Pa +CONTENTS +files of the installed packages. +This option is only intended for recovery after system crashes +during package installation and removal. +.It Cm rebuild-tree +Rebuild the +REQUIRED_BY files from scratch by reresolving all dependencies. +.Pp +This option is intended to be used for fixing inconsistencies between +the records of depending and depended-on packages, such as can arise +by the use of +.Cm pkg_delete -f . +.It Cm set Ar variable=value pkg ... +Set variable with information about the installed package. +Use +.Cm unset +to remove a variable. +.Pp +Packages that are not installed directly by the user but pulled in as +dependencies are marked by setting +.Dq automatic=YES . +.It Cm gpg-sign-package pkg spkg +Sign the binary package +.Ar pkg +using GPG and write the result to +.Ar spkg . +.It Cm x509-sign-package pkg spkg key cert +Sign the binary package +.Ar pkg +using the key +.Ar key +and the certificate +.Ar cert , +using +.Ar spkg +as output file. +.It Cm unset Ar variable pkg ... +Remove an installation variable. +.El +.Sh ENVIRONMENT +See +.Xr pkg_install.conf 5 +for options, that can also be specified using the environment. +.Sh FILES +.Bl -tag -width /var/db/pkg/pkgdb.byfile.db -compact +.It Pa /var/db/pkg/pkgdb.byfile.db +.It Pa /var/db/pkg/\*[Lt]pkg\*[Gt]/+CONTENTS +.El +.Sh SEE ALSO +.Xr pkg_add 1 , +.Xr pkg_create 1 , +.Xr pkg_delete 1 , +.Xr pkg_info 1 , +.Xr pkg_view 1 , +.Xr pkg_install.conf 5 , +.Xr pkgsrc 7 +.Sh HISTORY +The +.Nm +command first appeared in +.Nx 1.4 . +.Sh AUTHORS +The +.Nm +command was written by Hubert Feyrer. diff --git a/external/bsd/pkg_install/dist/bpm/bpm.1 b/external/bsd/pkg_install/dist/bpm/bpm.1 new file mode 100644 index 000000000..e60f48f2b --- /dev/null +++ b/external/bsd/pkg_install/dist/bpm/bpm.1 @@ -0,0 +1,114 @@ +.\" $NetBSD: bpm.1,v 1.4 2013/07/20 21:40:04 wiz Exp $ */ +.\" +.\" Copyright (c) 2003,2009 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Alistair Crooks (agc@NetBSD.org) +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd August 3, 2007 +.Dt BPM 1 +.Os +.Sh NAME +.Nm bpm +.Nd menu-based binary package manager +.Sh SYNOPSIS +.Nm +.Op Fl hnVv +.Op Fl b Ar baseURL +.Op Fl m Ar machine +.Op Fl r Ar release +.Op Fl w Ar seconds +.Sh DESCRIPTION +The +.Nm +command is used to locate and install binary packages from any +reachable URL. +.Pp +The following command-line options are supported: +.Bl -tag -width indent +.It Fl b Ar baseURL +Specify a base URL from which to download binary packages. +The default URL is +.Pa ftp://ftp.NetBSD.org/pub/pkgsrc/packages . +.It Fl h +Print a help message and then exit. +.It Fl m Ar machine +Use +.Ar machine +as the machine architecture to be used, instead of that returned by +.Xr uname 1 . +.It Fl n +Don't actually execute the commands to add the package. +.It Fl r Ar release +Use +.Ar release +as the operating system release to be used, instead of that returned by +.Xr uname 1 . +.It Fl V +Print version number and exit. +.It Fl v +Turn on verbose output. +.It Fl w Ar seconds +The number of +.Ar seconds +to wait after displaying an error message and returning to +normal menu operations. +.El +.Pp +.Nm +provides a menu-based binary package manager for +.Nx . +.Nm +first connects to the URL using +.Xr ftp 1 , +and displays a list of categories for which binary packages exist. +If no categories are displayed, it could +be that the machine architecture or operating system release string +have been wrongly interpreted, and that it will be necessary to override +this values by means of the command line options. +Within a category, a list of packages will be displayed, and by selecting +one using the number assigned to it, the package will be downloaded +automatically, and installed, using the +.Xr pkg_add 1 +utility. +It is also possible to change the category currently being examined, +and to quit from the utility, simply by selecting the appropriate choices +on the menu. +.Sh ENVIRONMENT +The environment variables which govern the behavior of +.Xr ftp 1 +and +.Xr pkg_add 1 +are valid for +.Nm . +.Sh SEE ALSO +.Xr ftp 1 , +.Xr pkg_add 1 , +.Xr uname 1 +.Sh AUTHORS +The +.Nm +utility was written by +.An Alistair Crooks Aq Mt agc@NetBSD.org . diff --git a/external/bsd/pkg_install/dist/bpm/bpm.sh.in b/external/bsd/pkg_install/dist/bpm/bpm.sh.in new file mode 100644 index 000000000..69e4f971d --- /dev/null +++ b/external/bsd/pkg_install/dist/bpm/bpm.sh.in @@ -0,0 +1,220 @@ +#! /bin/sh +# +# $NetBSD: bpm.sh.in,v 1.3 2012/02/21 18:36:16 wiz Exp $ +# +# Copyright (c) 2003,2009 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Alistair Crooks (agc@NetBSD.org) +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +die() +{ + echo >&2 "$@" + exit 1 +} + +check_prog() +{ + _var="$1"; _name="$2" + + eval _tmp=\"\$$_var\" + if [ "x$_tmp" != "x" ]; then + # Variable is already set (by the user, for example) + return 0 + fi + + for _d in `echo $PATH | tr ':' ' '`; do + if [ -x "$_d/$_name" ]; then + # Program found + eval $_var=\""$_d/$_name"\" + return 1 + fi + done + + die "$_name not found in path." +} + +check_prog awkprog awk +check_prog echoprog echo +check_prog ftpprog ftp +check_prog idprog id +check_prog moreprog more +check_prog pkg_addprog pkg_add +check_prog rmprog rm +check_prog sedprog sed +check_prog suprog su +check_prog unameprog uname + +# print version and exit +version() { + $pkg_addprog -V + exit 0 +} + +# temporary files +tmpcategories=/tmp/categories.$$ +tmppackages=/tmp/packages.$$ + +# some base parameters +base=ftp://ftp.NetBSD.org/pub/pkgsrc/packages +release=`${unameprog} -r | ${sedprog} -e 's/_STABLE//'` +machine=`${unameprog} -m` + +sleepsecs=1 + +doit="" + +while [ $# -gt 0 ]; do + case $1 in + -V) version ;; + -b) base=$2; shift ;; + -h) ${echoprog} "$0 [-b BaseURL] [-h] [-m machine] [-n] [-r release] [-v] [-w secs]"; exit 0;; + -m) machine=$2; shift ;; + -n) doit=":" ;; + -r) release=$2; shift ;; + -v) set -x ;; + -w) sleepsecs=$2; shift ;; + *) break ;; + esac + shift +done + +category="" + +while true; do + # if we don't have a packages file, then we need to choose a category + case "$category" in + "") # get possible categories + if [ ! -f $tmpcategories ]; then + ${echoprog} "Downloading package categories from ${base}..." + ${echoprog} "** QUIT" > $tmpcategories + ${echoprog} ls | ${ftpprog} ${base}/${release}/${machine}/ 2>/dev/null | \ + ${awkprog} 'NF == 9 { if ($9 != "All") print $9 }' >> $tmpcategories + fi + + # check for bad release numbering + # - it usually shows with 0 categories being displayed + ${awkprog} 'END { if (NR == 1) { print "\n\n\n*** No categories found - is the OS release set properly? ***\n\n\n" } }' < $tmpcategories + + # display possible categories + ${awkprog} '{ print NR ". " $0 }' < $tmpcategories | ${moreprog} + + # read a category number from the user + ${echoprog} -n "Please type the category number: " + read choice + + # validate user's choice + case "$choice" in + 0|1) ${rmprog} -f $tmpcategories $tmppackages; exit 0 ;; + [2-9]|[0-9]*) category=`${awkprog} 'NR == '$choice' { print }' < $tmpcategories` ;; + *) category="" ;; + esac + case "$category" in + "") ${echoprog} "No such category \"$choice\"" + sleep $sleepsecs + continue + ;; + esac + + # get possible packages + ${echoprog} "" + ${echoprog} "Downloading package names from ${base}/${category}..." + ${echoprog} "** QUIT" > $tmppackages + ${echoprog} "** Change category" >> $tmppackages + ${echoprog} ls | ${ftpprog} ${base}/${release}/${machine}/${category}/ 2>/dev/null \ + | ${awkprog} 'NF == 11 { print $9 }' >> $tmppackages + ;; + esac + + # display possible packages + ${awkprog} '{ print NR ". " $0 }' < $tmppackages | ${moreprog} + + # read a package number from the user + ${echoprog} -n "Please type the package number: " + read choice + + # validate user's choice + case "$choice" in + 1) ${rmprog} -f $tmppackages $tmpcategories; exit 0 ;; + 2) category=""; continue ;; # no package to install - choose new category + [3-9]|[0-9]*) package=`${awkprog} 'NR == '$choice' { print }' < $tmppackages` ;; + *) package="" ;; + esac + case "$package" in + "") ${echoprog} "No such package \"$choice\"" + sleep $sleepsecs + continue + ;; + esac + + # check it's not already installed + pkgbase=`${echoprog} ${package} | ${sedprog} -e 's|-[0-9].*||'` + installed=`pkg_info -e $pkgbase` + case "$installed" in + "") ;; + *) ${echoprog} "$package selected, but $installed already installed" + sleep $sleepsecs + continue + ;; + esac + + # Tell people what we're doing + ${echoprog} "" + ${echoprog} "Adding package ${base}/${release}/${machine}/${category}/${package}" + + cmd="env PKG_PATH=${base}/${release}/${machine}/All ${pkg_addprog} ${package}" + + # check if we need to become root for this + if [ `${idprog} -u` != 0 ]; then + ${echoprog} "Becoming root@`/bin/hostname` to add a binary package" + ${echoprog} -n "`${echoprog} ${suprog} | $awkprog '{ print $1 }'` " + $doit ${suprog} root -c "$cmd" + success=$? + else + $doit $cmd + success=$? + fi + + # give feedback after adding the package + case $success in + 0) ${echoprog} "$package successfully installed" ;; + *) ${echoprog} "Problems when installing $package - please try again" ;; + esac + + ${echoprog} "" + ${echoprog} -n "[Q]uit, [C]hange category, [I]nstall another package: " + read choice + + case "$choice" in + [Qq]) break ;; + [Cc]) category="" ;; + [Ii]) ;; + esac +done + +${rmprog} -f $tmpcategories $tmppackages + +exit 0 diff --git a/external/bsd/pkg_install/dist/create/build.c b/external/bsd/pkg_install/dist/create/build.c new file mode 100644 index 000000000..5ea7b8eff --- /dev/null +++ b/external/bsd/pkg_install/dist/create/build.c @@ -0,0 +1,422 @@ +/* $NetBSD: build.c,v 1.1.1.8 2010/04/23 20:54:07 joerg Exp $ */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: build.c,v 1.1.1.8 2010/04/23 20:54:07 joerg Exp $"); + +/*- + * Copyright (c) 2007 Joerg Sonnenberger . + * All rights reserved. + * + * This code was developed as part of Google's Summer of Code 2007 program. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * This is the main body of the create module. + * + */ + +#include "lib.h" +#include "create.h" + +#if HAVE_ERR_H +#include +#endif +#if HAVE_GRP_H +#include +#endif +#if HAVE_PWD_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif + +#include +#include + +static struct memory_file *contents_file; +static struct memory_file *comment_file; +static struct memory_file *desc_file; +static struct memory_file *install_file; +static struct memory_file *deinstall_file; +static struct memory_file *display_file; +static struct memory_file *build_version_file; +static struct memory_file *build_info_file; +static struct memory_file *size_pkg_file; +static struct memory_file *size_all_file; +static struct memory_file *preserve_file; +static struct memory_file *views_file; + +static void +write_meta_file(struct memory_file *file, struct archive *archive) +{ + struct archive_entry *entry; + + entry = archive_entry_new(); + archive_entry_set_pathname(entry, file->name); + archive_entry_copy_stat(entry, &file->st); + + archive_entry_set_uname(entry, file->owner); + archive_entry_set_gname(entry, file->group); + + if (archive_write_header(archive, entry)) + errx(2, "cannot write to archive: %s", archive_error_string(archive)); + + archive_write_data(archive, file->data, file->len); + + archive_entry_free(entry); +} + +static void +write_entry(struct archive *archive, struct archive_entry *entry) +{ + char buf[16384]; + const char *name; + int fd; + off_t len; + ssize_t buf_len; + + if (archive_entry_pathname(entry) == NULL) { + warnx("entry with NULL path"); + return; + } + + if (archive_write_header(archive, entry)) { + errx(2, "cannot write %s to archive: %s", + archive_entry_pathname(entry), + archive_error_string(archive)); + } + + /* Only regular files can have data. */ + if (archive_entry_filetype(entry) != AE_IFREG || + archive_entry_size(entry) == 0) { + archive_entry_free(entry); + return; + } + + name = archive_entry_pathname(entry); + + if ((fd = open(name, O_RDONLY)) == -1) + err(2, "cannot open data file %s", name); + + len = archive_entry_size(entry); + + while (len > 0) { + buf_len = (len > (off_t)sizeof(buf)) ? (ssize_t)sizeof(buf) : (ssize_t)len; + + if ((buf_len = read(fd, buf, buf_len)) == 0) + break; + else if (buf_len < 0) + err(2, "cannot read from %s", name); + + archive_write_data(archive, buf, (size_t)buf_len); + len -= buf_len; + } + + close(fd); + + archive_entry_free(entry); +} + +static void +write_normal_file(const char *name, struct archive *archive, + struct archive_entry_linkresolver *resolver, + const char *owner, const char *group) +{ + char buf[16384]; + ssize_t buf_len; + struct archive_entry *entry, *sparse_entry; + struct stat st; + + if (lstat(name, &st) == -1) + err(2, "lstat failed for file %s", name); + + entry = archive_entry_new(); + archive_entry_set_pathname(entry, name); + archive_entry_copy_stat(entry, &st); + + if (owner != NULL) { + uid_t uid; + + archive_entry_set_uname(entry, owner); + if (uid_from_user(owner, &uid) == -1) + errx(2, "user %s unknown", owner); + archive_entry_set_uid(entry, uid); + } else { + archive_entry_set_uname(entry, user_from_uid(st.st_uid, 1)); + } + + if (group != NULL) { + gid_t gid; + + archive_entry_set_gname(entry, group); + if (gid_from_group(group, &gid) == -1) + errx(2, "group %s unknown", group); + archive_entry_set_gid(entry, gid); + } else { + archive_entry_set_gname(entry, group_from_gid(st.st_gid, 1)); + } + + if ((st.st_mode & S_IFMT) == S_IFLNK) { + buf_len = readlink(name, buf, sizeof buf); + if (buf_len < 0) + err(2, "cannot read symlink %s", name); + buf[buf_len] = '\0'; + archive_entry_set_symlink(entry, buf); + } + + archive_entry_linkify(resolver, &entry, &sparse_entry); + + if (entry != NULL) + write_entry(archive, entry); + if (sparse_entry != NULL) + write_entry(archive, sparse_entry); +} + +static void +make_dist(const char *pkg, const char *suffix, const package_t *plist) +{ + char *archive_name; + const char *owner, *group; + const plist_t *p; + struct archive *archive; + struct archive_entry *entry, *sparse_entry; + struct archive_entry_linkresolver *resolver; + char *initial_cwd; + + archive = archive_write_new(); + archive_write_set_format_pax_restricted(archive); + if ((resolver = archive_entry_linkresolver_new()) == NULL) + errx(2, "cannot create link resolver"); + archive_entry_linkresolver_set_strategy(resolver, + archive_format(archive)); + + if (CompressionType == NULL) { + if (strcmp(suffix, "tbz") == 0 || + strcmp(suffix, "tar.bz2") == 0) + CompressionType = "bzip2"; + else if (strcmp(suffix, "tgz") == 0 || + strcmp(suffix, "tar.gz") == 0) + CompressionType = "gzip"; + else + CompressionType = "none"; + } + + if (strcmp(CompressionType, "bzip2") == 0) + archive_write_set_compression_bzip2(archive); + else if (strcmp(CompressionType, "gzip") == 0) + archive_write_set_compression_gzip(archive); + else if (strcmp(CompressionType, "xz") == 0) + archive_write_set_compression_xz(archive); + else if (strcmp(CompressionType, "none") == 0) + archive_write_set_compression_none(archive); + else + errx(1, "Unspported compression type for -F: %s", + CompressionType); + + archive_name = xasprintf("%s.%s", pkg, suffix); + + if (archive_write_open_file(archive, archive_name)) + errx(2, "cannot create archive: %s", archive_error_string(archive)); + + free(archive_name); + + owner = DefaultOwner; + group = DefaultGroup; + + write_meta_file(contents_file, archive); + write_meta_file(comment_file, archive); + write_meta_file(desc_file, archive); + + if (Install) + write_meta_file(install_file, archive); + if (DeInstall) + write_meta_file(deinstall_file, archive); + if (Display) + write_meta_file(display_file, archive); + if (BuildVersion) + write_meta_file(build_version_file, archive); + if (BuildInfo) + write_meta_file(build_info_file, archive); + if (SizePkg) + write_meta_file(size_pkg_file, archive); + if (SizeAll) + write_meta_file(size_all_file, archive); + if (Preserve) + write_meta_file(preserve_file, archive); + if (create_views) + write_meta_file(views_file, archive); + + initial_cwd = getcwd(NULL, 0); + + for (p = plist->head; p; p = p->next) { + if (p->type == PLIST_FILE) { + write_normal_file(p->name, archive, resolver, owner, group); + } else if (p->type == PLIST_CWD) { + chdir(p->name); + } else if (p->type == PLIST_IGNORE) { + p = p->next; + } else if (p->type == PLIST_CHOWN) { + if (p->name != NULL) + owner = p->name; + else + owner = DefaultOwner; + } else if (p->type == PLIST_CHGRP) { + if (p->name != NULL) + group = p->name; + else + group = DefaultGroup; + } + } + + entry = NULL; + archive_entry_linkify(resolver, &entry, &sparse_entry); + while (entry != NULL) { + write_entry(archive, entry); + entry = NULL; + archive_entry_linkify(resolver, &entry, &sparse_entry); + } + + archive_entry_linkresolver_free(resolver); + + if (archive_write_close(archive)) + errx(2, "cannot finish archive: %s", archive_error_string(archive)); + archive_write_finish(archive); + + free(initial_cwd); +} + +static struct memory_file * +load_and_add(package_t *plist, const char *input_name, + const char *target_name, mode_t perm) +{ + struct memory_file *file; + + file = load_memory_file(input_name, target_name, DefaultOwner, + DefaultGroup, perm); + add_plist(plist, PLIST_IGNORE, NULL); + add_plist(plist, PLIST_FILE, target_name); + + return file; +} + +static struct memory_file * +make_and_add(package_t *plist, const char *target_name, + char *content, mode_t perm) +{ + struct memory_file *file; + + file = make_memory_file(target_name, content, strlen(content), + DefaultOwner, DefaultGroup, perm); + add_plist(plist, PLIST_IGNORE, NULL); + add_plist(plist, PLIST_FILE, target_name); + + return file; +} + +int +pkg_build(const char *pkg, const char *full_pkg, const char *suffix, + package_t *plist) +{ + char *plist_buf; + size_t plist_len; + + /* Now put the release specific items in */ + add_plist(plist, PLIST_CWD, "."); + comment_file = make_and_add(plist, COMMENT_FNAME, Comment, 0444); + desc_file = make_and_add(plist, DESC_FNAME, Desc, 0444); + + if (Install) { + install_file = load_and_add(plist, Install, INSTALL_FNAME, + 0555); + } + if (DeInstall) { + deinstall_file = load_and_add(plist, DeInstall, + DEINSTALL_FNAME, 0555); + } + if (Display) { + display_file = load_and_add(plist, Display, + DISPLAY_FNAME, 0444); + add_plist(plist, PLIST_DISPLAY, DISPLAY_FNAME); + } + if (BuildVersion) { + build_version_file = load_and_add(plist, BuildVersion, + BUILD_VERSION_FNAME, 0444); + } + if (BuildInfo) { + build_info_file = load_and_add(plist, BuildInfo, + BUILD_INFO_FNAME, 0444); + } + if (SizePkg) { + size_pkg_file = load_and_add(plist, SizePkg, + SIZE_PKG_FNAME, 0444); + } + if (SizeAll) { + size_all_file = load_and_add(plist, SizeAll, + SIZE_ALL_FNAME, 0444); + } + if (Preserve) { + preserve_file = load_and_add(plist, Preserve, + PRESERVE_FNAME, 0444); + } + if (create_views) + views_file = make_and_add(plist, VIEWS_FNAME, xstrdup(""), 0444); + + /* Finally, write out the packing list */ + stringify_plist(plist, &plist_buf, &plist_len, realprefix); + contents_file = make_memory_file(CONTENTS_FNAME, plist_buf, plist_len, + DefaultOwner, DefaultGroup, 0644); + + /* And stick it into a tar ball */ + make_dist(pkg, suffix, plist); + + return TRUE; /* Success */ +} diff --git a/external/bsd/pkg_install/dist/create/create.h b/external/bsd/pkg_install/dist/create/create.h new file mode 100644 index 000000000..53b15f9bc --- /dev/null +++ b/external/bsd/pkg_install/dist/create/create.h @@ -0,0 +1,77 @@ +/* $NetBSD: create.h,v 1.1.1.5 2009/11/05 18:39:02 joerg Exp $ */ + +/* from FreeBSD Id: create.h,v 1.13 1997/10/08 07:46:19 charnier Exp */ + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Include and define various things wanted by the create command. + * + */ + +#ifndef _INST_CREATE_H_INCLUDE +#define _INST_CREATE_H_INCLUDE + +struct memory_file { + struct stat st; + const char *name; + const char *owner; + const char *group; + mode_t mode; + + char *data; + size_t len; +}; + +extern char *Prefix; +extern char *Comment; +extern char *Desc; +extern char *Display; +extern char *Install; +extern char *DeInstall; +extern char *Contents; +extern char *Pkgdeps; +extern char *BuildPkgdeps; +extern char *Pkgcfl; +extern char *BuildVersion; +extern char *BuildInfo; +extern char *SizePkg; +extern char *SizeAll; +extern char *Preserve; +extern char *realprefix; +extern char *DefaultOwner; +extern char *DefaultGroup; +extern const char *CompressionType; +extern int PlistOnly; +extern int RelativeLinks; +extern int update_pkgdb; +extern int create_views; + +void check_list(package_t *, const char *); +void copy_plist(char *, package_t *); + +struct memory_file + *load_memory_file(const char *, const char *, + const char *, const char *, mode_t); +struct memory_file + *make_memory_file(const char *, void *, size_t, + const char *, const char *, mode_t); +void free_memory_file(struct memory_file *); + +int pkg_perform(const char *); +int pkg_build(const char *, const char *, const char *, package_t *plist); + +#endif /* _INST_CREATE_H_INCLUDE */ diff --git a/external/bsd/pkg_install/dist/create/main.c b/external/bsd/pkg_install/dist/create/main.c new file mode 100644 index 000000000..325d12ba8 --- /dev/null +++ b/external/bsd/pkg_install/dist/create/main.c @@ -0,0 +1,217 @@ +/* $NetBSD: main.c,v 1.1.1.7 2010/01/30 21:33:31 joerg Exp $ */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: main.c,v 1.1.1.7 2010/01/30 21:33:31 joerg Exp $"); + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * This is the create module. + * + */ + +#if HAVE_ERR_H +#include +#endif +#include "lib.h" +#include "create.h" + +static const char Options[] = "B:C:D:EF:I:K:L:OP:S:T:UVb:c:d:f:g:i:k:ln:p:r:s:u:v"; + +char *Prefix = NULL; +char *Comment = NULL; +char *Desc = NULL; +char *Display = NULL; +char *Install = NULL; +char *DeInstall = NULL; +char *Contents = NULL; +char *Pkgdeps = NULL; +char *BuildPkgdeps = NULL; +char *Pkgcfl = NULL; +char *BuildVersion = NULL; +char *BuildInfo = NULL; +char *SizePkg = NULL; +char *SizeAll = NULL; +char *Preserve = NULL; +char *DefaultOwner = NULL; +char *DefaultGroup = NULL; +char *realprefix = NULL; +const char *CompressionType = NULL; +int update_pkgdb = 1; +int create_views = 0; +int PlistOnly = 0; +int RelativeLinks = 0; +Boolean File2Pkg = FALSE; + +static void +usage(void) +{ + fprintf(stderr, + "usage: pkg_create [-ElOUVv] [-B build-info-file] [-b build-version-file]\n" + " [-C cpkgs] [-D displayfile] [-F compression] \n" + " [-I realprefix] [-i iscript]\n" + " [-K pkg_dbdir] [-k dscript]\n" + " [-n preserve-file] [-P dpkgs] [-p prefix] [-r rscript]\n" + " [-S size-all-file] [-s size-pkg-file]\n" + " [-T buildpkgs] [-u owner] [-g group]\n" + " -c comment -d description -f packlist\n" + " pkg-name\n"); + exit(1); +} + +int +main(int argc, char **argv) +{ + int ch; + + setprogname(argv[0]); + while ((ch = getopt(argc, argv, Options)) != -1) + switch (ch) { + case 'v': + Verbose = TRUE; + break; + + case 'E': + create_views = 1; + break; + + case 'F': + CompressionType = optarg; + break; + + case 'I': + realprefix = optarg; + break; + + case 'O': + PlistOnly = 1; + break; + + case 'U': + update_pkgdb = 0; + break; + + case 'p': + Prefix = optarg; + break; + + case 's': + SizePkg = optarg; + break; + + case 'S': + SizeAll = optarg; + break; + + case 'f': + Contents = optarg; + break; + + case 'c': + Comment = optarg; + break; + + case 'd': + Desc = optarg; + break; + + case 'g': + DefaultGroup = optarg; + break; + + case 'i': + Install = optarg; + break; + + case 'K': + pkgdb_set_dir(optarg, 3); + break; + + case 'k': + DeInstall = optarg; + break; + + case 'l': + RelativeLinks = 1; + break; + + case 'L': + warnx("Obsolete -L option ignored"); + break; + + case 'u': + DefaultOwner = optarg; + break; + + case 'D': + Display = optarg; + break; + + case 'n': + Preserve = optarg; + break; + + case 'P': + Pkgdeps = optarg; + break; + + case 'T': + BuildPkgdeps = optarg; + break; + + case 'C': + Pkgcfl = optarg; + break; + + case 'b': + BuildVersion = optarg; + break; + + case 'B': + BuildInfo = optarg; + break; + + case 'V': + show_version(); + /* NOTREACHED */ + + case '?': + default: + usage(); + break; + } + + argc -= optind; + argv += optind; + + pkg_install_config(); + + if (argc == 0) { + warnx("missing package name"); + usage(); + } + if (argc != 1) { + warnx("only one package name allowed"); + usage(); + } + + if (pkg_perform(*argv)) + return 0; + if (Verbose) { + if (PlistOnly) + warnx("package registration failed"); + else + warnx("package creation failed"); + } + return 1; +} diff --git a/external/bsd/pkg_install/dist/create/perform.c b/external/bsd/pkg_install/dist/create/perform.c new file mode 100644 index 000000000..f23f66e25 --- /dev/null +++ b/external/bsd/pkg_install/dist/create/perform.c @@ -0,0 +1,244 @@ +/* $NetBSD: perform.c,v 1.1.1.5 2009/11/05 18:39:02 joerg Exp $ */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: perform.c,v 1.1.1.5 2009/11/05 18:39:02 joerg Exp $"); + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * This is the main body of the create module. + * + */ + +#include "lib.h" +#include "create.h" + +#if HAVE_ERR_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif + +static void +sanity_check(void) +{ + if (!Comment) + errx(2, "required package comment string is missing (-c comment)"); + if (!Desc) + errx(2, "required package description string is missing (-d desc)"); + if (!Contents) + errx(2, "required package contents list is missing (-f [-]file)"); +} + +static void +register_depends(package_t *plist, char *deps, int build_only) +{ + char *cp; + + if (Verbose && !PlistOnly) { + if (build_only) + printf("Registering build depends:"); + else + printf("Registering depends:"); + } + while (deps) { + cp = strsep(&deps, " \t\n"); + if (*cp) { + char *best_installed; + best_installed = find_best_matching_installed_pkg(cp); + if (best_installed != NULL) { + add_plist(plist, PLIST_BLDDEP, best_installed); + if (Verbose && !PlistOnly && build_only) + printf(" %s", cp); + } else + warnx("No matching package installed for %s", cp); + free(best_installed); + if (!build_only) { + add_plist(plist, PLIST_PKGDEP, cp); + if (Verbose && !PlistOnly) + printf(" %s", cp); + } + } + } + if (Verbose && !PlistOnly) + printf(".\n"); +} + +/* + * Expect "fname" to point at a file, and read it into + * the buffer returned. + */ +static char * +fileGetContents(char *fname) +{ + char *contents; + struct stat sb; + int fd; + + if (stat(fname, &sb) == FAIL) { + errx(2, "can't stat '%s'", fname); + } + + contents = xmalloc((size_t) (sb.st_size) + 1); + fd = open(fname, O_RDONLY, 0); + if (fd == FAIL) { + errx(2, "unable to open '%s' for reading", fname); + } + if (read(fd, contents, (size_t) sb.st_size) != (ssize_t) sb.st_size) { + errx(2, "short read on '%s' - did not get %lld bytes", + fname, (long long) sb.st_size); + } + close(fd); + contents[(size_t) sb.st_size] = '\0'; + return contents; +} + +/* + * Get a string parameter as a file spec or as a "contents follow -" spec + */ +static void +get_dash_string(char **s) +{ + if (**s == '-') + *s = xstrdup(*s + 1); + else + *s = fileGetContents(*s); +} + +int +pkg_perform(const char *pkg) +{ + char *cp; + FILE *pkg_in; + package_t plist; + const char *full_pkg, *suffix; + char *allocated_pkg; + int retval; + + /* Break the package name into base and desired suffix (if any) */ + if ((cp = strrchr(pkg, '.')) != NULL) { + allocated_pkg = xmalloc(cp - pkg + 1); + memcpy(allocated_pkg, pkg, cp - pkg); + allocated_pkg[cp - pkg] = '\0'; + suffix = cp + 1; + full_pkg = pkg; + pkg = allocated_pkg; + } else { + allocated_pkg = NULL; + full_pkg = pkg; + suffix = "tgz"; + } + + /* Preliminary setup */ + sanity_check(); + if (Verbose && !PlistOnly) + printf("Creating package %s\n", pkg); + get_dash_string(&Comment); + get_dash_string(&Desc); + if (IS_STDIN(Contents)) + pkg_in = stdin; + else { + pkg_in = fopen(Contents, "r"); + if (!pkg_in) + errx(2, "unable to open contents file '%s' for input", Contents); + } + + plist.head = plist.tail = NULL; + + /* Stick the dependencies, if any, at the top */ + if (Pkgdeps) + register_depends(&plist, Pkgdeps, 0); + + /* + * Put the build dependencies after the dependencies. + * This works due to the evaluation order in pkg_add. + */ + if (BuildPkgdeps) + register_depends(&plist, BuildPkgdeps, 1); + + /* Put the conflicts directly after the dependencies, if any */ + if (Pkgcfl) { + if (Verbose && !PlistOnly) + printf("Registering conflicts:"); + while (Pkgcfl) { + cp = strsep(&Pkgcfl, " \t\n"); + if (*cp) { + add_plist(&plist, PLIST_PKGCFL, cp); + if (Verbose && !PlistOnly) + printf(" %s", cp); + } + } + if (Verbose && !PlistOnly) + printf(".\n"); + } + + /* Slurp in the packing list */ + append_plist(&plist, pkg_in); + + if (pkg_in != stdin) + fclose(pkg_in); + + /* Prefix should override the packing list */ + if (Prefix) { + delete_plist(&plist, FALSE, PLIST_CWD, NULL); + add_plist_top(&plist, PLIST_CWD, Prefix); + } + /* + * Run down the list and see if we've named it, if not stick in a name + * at the top. + */ + if (find_plist(&plist, PLIST_NAME) == NULL) { + add_plist_top(&plist, PLIST_NAME, basename_of(pkg)); + } + + /* Make first "real contents" pass over it */ + check_list(&plist, basename_of(pkg)); + + /* + * We're just here for to dump out a revised plist for the FreeBSD ports + * hack. It's not a real create in progress. + */ + if (PlistOnly) { + write_plist(&plist, stdout, realprefix); + retval = TRUE; + } else { +#ifdef BOOTSTRAP + warnx("Package building is not supported in bootstrap mode"); + retval = FALSE; +#else + retval = pkg_build(pkg, full_pkg, suffix, &plist); +#endif + } + + /* Cleanup */ + free(Comment); + free(Desc); + free_plist(&plist); + + free(allocated_pkg); + + return retval; +} diff --git a/external/bsd/pkg_install/dist/create/pkg_create.1 b/external/bsd/pkg_install/dist/create/pkg_create.1 new file mode 100644 index 000000000..1c614643d --- /dev/null +++ b/external/bsd/pkg_install/dist/create/pkg_create.1 @@ -0,0 +1,504 @@ +.\" $NetBSD: pkg_create.1,v 1.1.1.8 2010/04/23 20:54:08 joerg Exp $ +.\" +.\" FreeBSD install - a package for the installation and maintenance +.\" of non-core utilities. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" Jordan K. Hubbard +.\" +.\" +.\" @(#)pkg_create.1 +.\" from FreeBSD Id: pkg_create.1,v 1.19 1997/05/02 22:00:05 max Exp +.\" +.\" hacked up by John Kohl for NetBSD--fixed a few bugs, extended keywords, +.\" added dependency tracking, etc. +.\" +.\" [jkh] Took John's changes back and made some additional extensions for +.\" better integration with FreeBSD's new ports collection. +.\" +.Dd January 20, 2010 +.Dt PKG_CREATE 1 +.Os +.Sh NAME +.Nm pkg_create +.Nd a utility for creating software package distributions +.Sh SYNOPSIS +.Nm +.Op Fl ElOUVv +.Bk -words +.Op Fl B Ar build-info-file +.Ek +.Bk -words +.Op Fl b Ar build-version-file +.Ek +.Bk -words +.Op Fl C Ar cpkgs +.Ek +.Bk -words +.Op Fl D Ar displayfile +.Ek +.Bk -words +.Op Fl F Ar compression +.Ek +.Bk -words +.Op Fl g Ar group +.Ek +.Bk -words +.Op Fl I Ar realprefix +.Ek +.Bk -words +.Op Fl i Ar iscript +.Ek +.Bk -words +.Op Fl K Ar pkg_dbdir +.Ek +.Bk -words +.Op Fl k Ar dscript +.Ek +.Bk -words +.Op Fl n Ar preserve-file +.Ek +.Bk -words +.Op Fl P Ar dpkgs +.Ek +.Bk -words +.Op Fl T Ar buildpkgs +.Ek +.Bk -words +.Op Fl p Ar prefix +.Ek +.Bk -words +.Op Fl S Ar size-all-file +.Ek +.Bk -words +.Op Fl s Ar size-pkg-file +.Ek +.Bk -words +.Op Fl t Ar template +.Ek +.Bk -words +.Op Fl u Ar owner +.Ek +.Bk -words +.Fl c Ar comment +.Ek +.Bk -words +.Fl d Ar description +.Ek +.Bk -words +.Fl f Ar packlist +.Ek +.Ar pkg-name +.Sh DESCRIPTION +The +.Nm +command is used to create packages that will subsequently be fed to +one of the package extraction/info utilities. +The input description and command line arguments for the creation of a +package are not really meant to be human-generated, though it is easy +enough to do so. +It is more expected that you will use a front-end tool for +the job rather than muddling through it yourself. +Nonetheless, a short description of the input syntax is included in this +document. +.Sh OPTIONS +The following command line options are supported: +.Bl -tag -width indent +.It Fl B Ar build-info-file +Install the file +.Ar build-info-file +so that users of binary packages can see what +.Xr make 1 +definitions +were used to control the build when creating the +binary package. +This allows various build definitions to be retained in a binary package +and viewed wherever it is installed, using +.Xr pkg_info 1 . +.It Fl b Ar build-version-file +Install the file +.Ar build-version-file +so that users of binary packages can see what versions of +the files used to control the build were used when creating the +binary package. +This allows some fine-grained version control information to be retained +in a binary package and viewed wherever it is installed, using +.Xr pkg_info 1 . +.It Fl C Ar cpkgs +Set the initial package conflict list to +.Ar cpkgs . +This is assumed to be a whitespace separated list of package names +and is meant as a convenient shorthand for specifying multiple +.Cm @pkgcfl +directives in the packing list (see PACKING LIST DETAILS section below). +.It Fl c Ar [-]desc +Fetch package +.Pq one line description +from file +.Ar desc +or, if preceded by +.Cm - , +the argument itself. +This string should also give some idea of which version of the product +(if any) the package represents. +.It Fl D Ar displayfile +Display the file after installing the package. +Useful for things like legal notices on almost-free software, etc. +.It Fl d Ar [-]desc +Fetch long description for package from file +.Ar desc +or, if preceded by +.Cm - , +the argument itself. +.It Fl E +Add an empty views file to the package. +.It Fl F Ar compression +Use +.Ar compression +as compression algorithm. +This overrides the heuristic to guess the compression type from the +output name. +Currently supported values are bzip2, gzip, none and xz. +.It Fl f Ar packlist +Fetch +.Pq packing list +for package from the file +.Ar packlist +or +.Cm stdin +if +.Ar packlist +is a +.Cm - +(dash). +.It Fl g Ar group +Make +.Ar group +the default group ownership instead of extracting it from the file system. +.It Fl I Ar realprefix +Provide the real prefix, as opposed to the staging prefix, for use in +staged installations of packages. +.It Fl i Ar iscript +Set +.Ar iscript +to be the install procedure for the package. +This can be any executable program (or shell script). +It will be invoked automatically when the package is later installed. +.It Fl K Ar pkg_dbdir +Override the value of the +.Dv PKG_DBDIR +configuration option with the value +.Ar pkg_dbdir . +.It Fl k Ar dscript +Set +.Ar dscript +to be the de-install procedure for the package. +This can be any executable program (or shell script). +It will be invoked automatically +when the package is later (if ever) de-installed. +.It Fl l +Check that any symbolic links which are to be placed in the package are +relative to the current prefix. +This means using +.Xr unlink 2 +and +.Xr symlink 2 +to remove and re-link +any symbolic links which are targeted at full path names. +.It Fl n Ar preserve-file +The file is used to denote that the package should not be deleted. +This is intended for use where the deletion of packages may present +a bootstrap problem. +.It Fl O +Go into a +.Pq packing list only +mode. +This is used to do +.Pq fake pkg_add +operations when a package is installed. +In such cases, it is necessary to know what the final, adjusted packing +list will look like. +.It Fl P Ar dpkgs +Set the initial package dependency list to +.Ar dpkgs . +This is assumed to be a whitespace separated list of package names +and is meant as a convenient shorthand for specifying multiple +.Cm @pkgdep +directives in the packing list (see PACKING LIST DETAILS section below). +In addition, the exact versions of the packages referred to in the +.Ar dpkgs +list will be added to the packing list in the form of +.Cm @blddep +directives. +.It Fl T Ar buildpkgs +The exact versions of the packages referred to in the +.Ar buildpkgs +list will be added to the packing list in the form of +.Cm @blddep +directives. +This directives are stored after those created by the +.Fl P +option. +.Ar buildpkgs +is assumed to be a whitespace separated list of package names. +.It Fl p Ar prefix +Set +.Ar prefix +as the initial directory +.Pq base +to start from in selecting files for +the package. +.It Fl S Ar size-all-file +Store the given file for later querying with the +.Xr pkg_info 1 +.Fl S +flag. +The file is expected to contain the size (in bytes) of all files of +this package plus any required packages added up and stored as a +ASCII string, terminated by a newline. +.It Fl s Ar size-pkg-file +Store the given file for later querying with the +.Xr pkg_info 1 +.Fl s +flag. +The file is expected to contain the size (in bytes) of all files of +this package added up and stored as a ASCII string, terminated by a newline. +.It Fl t Ar template +Use +.Ar template +as the input to +.Xr mktemp 3 . +By default, this is the string +.Pa /tmp/instmp.XXXXXX , +but it may be necessary to override it in the situation where +space in your +.Pa /tmp +directory is limited. +Be sure to leave some number of +.Sq X +characters for +.Xr mktemp 3 +to fill in with a unique ID. +.It Fl U +Do not update the package file database with any file information. +.It Fl u Ar owner +Make +.Ar owner +the default owner instead of extracting it from the file system. +.It Fl V +Print version number and exit. +.It Fl v +Turn on verbose output. +.El +.Sh PACKING LIST DETAILS +The +.Pq packing list +format (see +.Fl f ) +is fairly simple, being +nothing more than a single column of filenames to include in the +package. +However, since absolute pathnames are generally a bad idea +for a package that could be installed potentially anywhere, there is +another method of specifying where things are supposed to go +and, optionally, what ownership and mode information they should be +installed with. +This is done by embedding specialized command sequences +in the packing list. +Briefly described, these sequences are: +.Bl -tag -width indent -compact +.It Cm @cwd Ar directory +Set the internal directory pointer to point to +.Ar directory . +All subsequent filenames will be assumed relative to this directory. +Note: +.Cm @cd +is also an alias for this command. +.It Cm @src Ar directory +This command is supported for compatibility only. +It was formerly used to override +.Cm @cwd +during package creation. +.It Cm @exec Ar command +Execute +.Ar command +as part of the unpacking process. +If +.Ar command +contains any of the following sequences somewhere in it, they will +be expanded inline. +For the following examples, assume that +.Cm @cwd +is set to +.Pa /usr/local +and the last extracted file was +.Pa bin/emacs . +.Bl -tag -width indent -compact +.It Cm "\&%F" +Expands to the last filename extracted (as specified), in the example case +.Pa bin/emacs +.It Cm "\&%D" +Expand to the current directory prefix, as set with +.Cm @cwd , +in the example case +.Pa /usr/local . +.It Cm "\&%B" +Expand to the +.Pq basename +of the fully qualified filename, that +is the current directory prefix, plus the last filespec, minus +the trailing filename. +In the example case, that would be +.Pa /usr/local/bin . +.It Cm "\&%f" +Expand to the +.Pq filename +part of the fully qualified name, or +the converse of +.Cm \&%B , +being in the example case, +.Pa emacs . +.El +.It Cm @unexec Ar command +Execute +.Ar command +as part of the deinstallation process. +Expansion of special +.Cm \&% +sequences is the same as for +.Cm @exec . +This command is not executed during the package add, as +.Cm @exec +is, but rather when the package is deleted. +This is useful for deleting links and other ancillary files that were created +as a result of adding the package, but not directly known to the package's +table of contents (and hence not automatically removable). +The advantage of using +.Cm @unexec +over a deinstallation script is that you can use the +.Pq special sequence expansion +to get at files regardless of where they've +been potentially redirected (see +.Fl p ) . +.It Cm @mode Ar mode +Set default permission for all subsequently extracted files to +.Ar mode . +Format is the same as that used by the +.Cm chmod +command (well, considering that it's later handed off to it, that's +no surprise). +Use without an arg to set back to default (extraction) permissions. +.It Cm @option Ar option +Set internal package options, the only currently supported one +being +.Ar preserve , +which tells pkg_add to move any existing files out of the way, +preserving the previous contents (which are also resurrected on +pkg_delete, so caveat emptor). +.It Cm @owner Ar user +Set default ownership for all subsequently extracted files to +.Ar user . +Use without an arg to set back to default (extraction) +ownership. +.It Cm @group Ar group +Set default group ownership for all subsequently extracted files to +.Ar group . +Use without an arg to set back to default (extraction) +group ownership. +.It Cm @comment Ar string +Embed a comment in the packing list. +Useful in trying to document some particularly hairy sequence that +may trip someone up later. +.It Cm @ignore +Used internally to tell extraction to ignore the next file (don't +copy it anywhere), as it's used for some special purpose. +.It Cm @name Ar name +Set the name of the package. +This is mandatory and is usually put at the top. +This name is potentially different than the name of the file it came in, +and is used when keeping track of the package for later deinstallation. +Note that +.Nm +will derive this field from the +.Ar pkg-name +and add it automatically if none is given. +.It Cm @pkgdir Ar name +Declare directory +.Pa name +as managed. +If it does not exist at installation time, it is created. +If this directory is no longer referenced by packages and the last +file or directory in it is deleted, the directory is removed as well. +.It Cm @dirrm Ar name +This command is supported for compatibility only. +If directory +.Pa name +exists, it will be deleted at deinstall time. +.It Cm @display Ar name +Declare +.Pa name +as the file to be displayed at install time (see +.Fl D +above). +.It Cm @pkgdep Ar pkgname +Declare a dependency on the +.Ar pkgname +package. +The +.Ar pkgname +package must be installed before this package may be +installed, and this package must be deinstalled before the +.Ar pkgname +package is deinstalled. +Multiple +.Cm @pkgdep +directives may be used if the package depends on multiple other packages. +.It Cm @blddep Ar pkgname +Declare that this package was built with the exact version +of +.Ar pkgname +(since the +.Cm @pkgdep +directive may contain wildcards or relational +package version information). +.It Cm @pkgcfl Ar pkgcflname +Declare a conflict with the +.Ar pkgcflname +package, as the two packages contain references to the same files, +and so cannot co-exist on the same system. +.El +.Sh ENVIRONMENT +See +.Xr pkg_install.conf 5 +for options, that can also be specified using the environment. +.Sh SEE ALSO +.Xr pkg_add 1 , +.Xr pkg_admin 1 , +.Xr pkg_delete 1 , +.Xr pkg_info 1 , +.Xr pkg_install.conf 5 +.Xr pkgsrc 7 +.Sh HISTORY +The +.Nm +command first appeared in +.Fx . +.Sh AUTHORS +.Bl -tag -width indent -compact +.It Jordan Hubbard +most of the work +.It John Kohl +refined it for +.Nx +.It Hubert Feyrer +.Nx +wildcard dependency processing, pkgdb, pkg size recording etc. +.El diff --git a/external/bsd/pkg_install/dist/create/pl.c b/external/bsd/pkg_install/dist/create/pl.c new file mode 100644 index 000000000..7aa0f2811 --- /dev/null +++ b/external/bsd/pkg_install/dist/create/pl.c @@ -0,0 +1,211 @@ +/* $NetBSD: pl.c,v 1.1.1.4 2009/11/05 18:39:03 joerg Exp $ */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: pl.c,v 1.1.1.4 2009/11/05 18:39:03 joerg Exp $"); + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Routines for dealing with the packing list. + * + */ + +#include "lib.h" +#include "create.h" +#if HAVE_ERR_H +#include +#endif +#ifndef NETBSD +#include +#else +#include +#endif + +/* + * Check that any symbolic link is relative to the prefix + */ +static void +CheckSymlink(char *name, char *prefix, size_t prefixcc) +{ + char newtgt[MaxPathSize]; + char oldtgt[MaxPathSize]; + char *slash; + int slashc; + int cc; + int i; + + if ((cc = readlink(name, oldtgt, sizeof(oldtgt) - 1)) > 0) { + oldtgt[cc] = 0; + if (strncmp(oldtgt, prefix, prefixcc) == 0 && oldtgt[prefixcc] == '/') { + for (slashc = 0, slash = &name[prefixcc + 1]; (slash = strchr(slash, '/')) != (char *) NULL; slash++, slashc++) { + } + for (cc = i = 0; i < slashc; i++) { + strlcpy(&newtgt[cc], "../", sizeof(newtgt) - cc); + cc += 3; + } + strlcpy(&newtgt[cc], &oldtgt[prefixcc + 1], sizeof(newtgt) - cc); + (void) fprintf(stderr, "Full pathname symlink `%s' is target of `%s' - adjusting to `%s'\n", oldtgt, name, newtgt); + if (unlink(name) != 0) { + warn("can't unlink `%s'", name); + } else if (symlink(newtgt, name) != 0) { + warn("can't symlink `%s' called `%s'", newtgt, name); + } + } + } +} + +/* + * Check a list for files that require preconversion + */ +void +check_list(package_t *pkg, const char *PkgName) +{ + struct stat st; + plist_t *tmp; + plist_t *p; + char buf[ChecksumHeaderLen + LegibleChecksumLen]; + char target[MaxPathSize + SymlinkHeaderLen]; + char name[MaxPathSize]; + char *cwd = NULL; + char *pkgname = NULL; + int cc; + + /* Open Package Database for writing */ + if (update_pkgdb && !pkgdb_open(ReadWrite)) + err(EXIT_FAILURE, "can't open pkgdb"); + + for (p = pkg->head; p; p = p->next) { + switch (p->type) { + case PLIST_CWD: + cwd = p->name; + break; + case PLIST_NAME: + pkgname = p->name; + break; + case PLIST_IGNORE: + p = p->next; + break; + case PLIST_PKGDIR: + if (cwd == NULL) + errx(2, "@pkgdir without preceding @cwd found"); + if (pkgname == NULL) + errx(2, "@pkgdir without preceding @name found"); + if (update_pkgdb) { + add_pkgdir(pkgname, cwd, p->name); + /* mkdir_p(cwd, p->name); */ + } + break; + case PLIST_FILE: + /* + * pkgdb handling - usually, we enter files + * into the pkgdb as soon as they hit the disk, + * but as they are present before pkg_create + * starts, it's ok to do this somewhere here + */ + if (cwd == NULL) + errx(2, "file without preceding @cwd found"); + if (update_pkgdb) { + char *s, t[MaxPathSize]; + + (void) snprintf(t, sizeof(t), "%s%s%s", + cwd, + (strcmp(cwd, "/") == 0) ? "" : "/", + p->name); + + s = pkgdb_retrieve(t); + if (s && PlistOnly) + warnx("Overwriting %s - " + "pkg %s bogus/conflicting?", t, s); + else { + pkgdb_store(t, PkgName); + } + } + + /* prepend DESTDIR if set? - HF */ + (void) snprintf(name, sizeof(name), "%s%s%s", + cwd, + (strcmp(cwd, "/") == 0) ? "" : "/", + p->name); + if (lstat(name, &st) < 0) { + warnx("can't stat `%s'", name); + continue; + } + switch (st.st_mode & S_IFMT) { + case S_IFDIR: + warnx("Warning - directory `%s' in PLIST", name); + break; + case S_IFLNK: + if (RelativeLinks) { + CheckSymlink(name, cwd, strlen(cwd)); + } + (void) strlcpy(target, SYMLINK_HEADER, + sizeof(target)); + if ((cc = readlink(name, &target[SymlinkHeaderLen], + sizeof(target) - SymlinkHeaderLen - 1)) < 0) { + warnx("can't readlink `%s'", name); + continue; + } + target[SymlinkHeaderLen + cc] = 0x0; + tmp = new_plist_entry(); + tmp->name = xstrdup(target); + tmp->type = PLIST_COMMENT; + tmp->next = p->next; + tmp->prev = p; + if (p == pkg->tail) { + pkg->tail = tmp; + } + p->next = tmp; + p = tmp; + break; + case S_IFCHR: + warnx("Warning - char special device `%s' in PLIST", name); + break; + case S_IFBLK: + warnx("Warning - block special device `%s' in PLIST", name); + break; + default: + (void) strlcpy(buf, CHECKSUM_HEADER, + sizeof(buf)); + if (MD5File(name, &buf[ChecksumHeaderLen]) != (char *) NULL) { + tmp = new_plist_entry(); + tmp->name = xstrdup(buf); + tmp->type = PLIST_COMMENT; /* PLIST_MD5 - HF */ + tmp->next = p->next; + tmp->prev = p; + if (p == pkg->tail) { + pkg->tail = tmp; + } + p->next = tmp; + p = tmp; + } + break; + } + break; + default: + break; + } + } + + if (update_pkgdb) { + pkgdb_close(); + } +} diff --git a/external/bsd/pkg_install/dist/create/util.c b/external/bsd/pkg_install/dist/create/util.c new file mode 100644 index 000000000..d17b1fed7 --- /dev/null +++ b/external/bsd/pkg_install/dist/create/util.c @@ -0,0 +1,163 @@ +/*- + * Copyright (c) 2007 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_ERR_H +#include +#endif +#if HAVE_PWD_H +#include +#endif +#if HAVE_PWD_H +#include +#endif +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_STRING_H +#include +#endif +#if HAVE_TIME_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif + +#include "lib.h" +#include "create.h" + +static void +update_ids(struct memory_file *file) +{ + if (file->owner != NULL) { + uid_t uid; + + if (uid_from_user(file->owner, &uid) == -1) + errx(2, "user %s unknown", file->owner); + file->st.st_uid = uid; + } else { + file->owner = user_from_uid(file->st.st_uid, 1); + } + + if (file->group != NULL) { + gid_t gid; + + if (gid_from_group(file->group, &gid) == -1) + errx(2, "group %s unknown", file->group); + file->group = file->group; + file->st.st_gid = gid; + } else { + file->group = group_from_gid(file->st.st_gid, 1); + } +} + +struct memory_file * +make_memory_file(const char *archive_name, void *data, size_t len, + const char *owner, const char *group, mode_t mode) +{ + struct memory_file *file; + + file = xmalloc(sizeof(*file)); + file->name = archive_name; + file->owner = owner; + file->group = group; + file->data = data; + file->len = len; + + memset(&file->st, 0, sizeof(file->st)); + + file->st.st_atime = file->st.st_ctime = file->st.st_mtime = time(NULL); + + file->st.st_nlink = 1; + file->st.st_size = len; + file->st.st_mode = mode | S_IFREG; + + update_ids(file); + + return file; +} + +struct memory_file * +load_memory_file(const char *disk_name, + const char *archive_name, const char *owner, const char *group, + mode_t mode) +{ + struct memory_file *file; + int fd; + + file = xmalloc(sizeof(*file)); + file->name = archive_name; + file->owner = owner; + file->group = group; + file->mode = mode; + + fd = open(disk_name, O_RDONLY); + if (fd == -1) + err(2, "cannot open file %s", disk_name); + if (fstat(fd, &file->st) == -1) + err(2, "cannot stat file %s", disk_name); + + update_ids(file); + + if ((file->st.st_mode & S_IFMT) != S_IFREG) + errx(1, "meta data file %s is not regular file", disk_name); + if (file->st.st_size > SSIZE_MAX) + errx(2, "meta data file too large: %s", disk_name); + file->data = xmalloc(file->st.st_size); + + if (read(fd, file->data, file->st.st_size) != file->st.st_size) + err(2, "cannot read file into memory %s", disk_name); + + file->len = file->st.st_size; + + close(fd); + + return file; +} + +void +free_memory_file(struct memory_file *file) +{ + if (file != NULL) { + free(file->data); + free(file); + } +} diff --git a/external/bsd/pkg_install/dist/delete/pkg_delete.1 b/external/bsd/pkg_install/dist/delete/pkg_delete.1 new file mode 100644 index 000000000..2ee40c4c8 --- /dev/null +++ b/external/bsd/pkg_install/dist/delete/pkg_delete.1 @@ -0,0 +1,300 @@ +.\" $NetBSD: pkg_delete.1,v 1.1.1.8 2010/04/23 20:54:08 joerg Exp $ +.\" +.\" FreeBSD install - a package for the installation and maintenance +.\" of non-core utilities. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" Jordan K. Hubbard +.\" +.\" +.\" from FreeBSD: @(#)pkg_delete.1 +.\" +.Dd January 20, 2010 +.Dt PKG_DELETE 1 +.Os +.Sh NAME +.Nm pkg_delete +.Nd a utility for deleting previously installed software package distributions +.Sh SYNOPSIS +.Nm +.Op Fl ADFfkNnORrVv +.Op Fl K Ar pkg_dbdir +.Op Fl P Ar destdir +.Op Fl p Ar prefix +.Ar pkg-name ... +.Sh DESCRIPTION +The +.Nm +command is used to delete packages that have been previously installed +with the +.Xr pkg_add 1 +command. +The given packages are sorted, so that the dependencies needed by a +package are deleted after the package. +Before any action is executed, +.Nm +checks for packages that are marked as +.Cm preserved +or have depending packages left. +If the +.Fl k +flag is given, preserved packages are skipped and not removed. +Unless the +.Fl f +flag is given, +.Nm +stops on the first error. +.Sh WARNING +.Bf -emphasis +Since the +.Nm +command may execute scripts or programs provided by a package file, +your system may be susceptible to +.Dq Trojan horses +or other subtle +attacks from miscreants who create dangerous package files. +.Pp +You are advised to verify the competence and identity of those who +provide installable package files. +For extra protection, examine all the package control files in the +package record directory +.Pa \*[Lt]PKG_DBDIR\*[Gt]/\*[Lt]pkg-name\*[Gt]/ ) . +Pay particular +attention to any +.Pa +INSTALL +or +.Pa +DEINSTALL +files, and inspect the +.Pa +CONTENTS +file for +.Cm @cwd , +.Cm @mode +(check for setuid), +.Cm @dirrm , +.Cm @exec , +and +.Cm @unexec +directives, and/or use the +.Xr pkg_info 1 +command to examine the installed package control files. +.Ef +.Sh OPTIONS +The following command line options are supported: +.Bl -tag -width indent +.It Ar pkg-name ... +The named packages are deinstalled, wildcards can be used, see +.Xr pkg_info 1 . +If no version is given, the one currently installed +will be removed. +If the +.Fl F +flag is given, one or more (absolute) filenames may be specified and +the package database will be consulted for the package to which the +given file belongs. +These packages are then deinstalled. +.It Fl A +Recursively remove all automatically installed packages that were needed +by the given packages and are no longer required. +Does not remove manually installed packages; see also the +.Fl R +flag. +.It Fl D +If a deinstallation script exists for a given package, do not execute it. +.It Fl F +Any +.Ar pkg-name +given will be interpreted as pathname which is +subsequently transformed in a (real) package name via the package +database. +That way, packages can be deleted by giving a filename +instead of the package-name. +.It Fl f +Force removal of the package, even if a dependency is recorded or the +deinstall script fails. +This might break the package database; see +.Xr pkg_admin 1 +on how to repair it. +.It Fl ff +Force removal of the package, even if the package is marked as a +.Cm preserved +package. +Note that this is a dangerous operation. +See also the +.Fl k +option. +.It Fl K Ar pkg_dbdir +Override the value of the +.Dv PKG_DBDIR +configuration option with the value +.Ar pkg_dbdir . +.It Fl k +Silently skip all packages that are marked as +.Cm preserved . +.It Fl N +Remove the package's registration and its entries from the package database, +but leave the files installed. +Don't run any deinstall scripts or +.Cm @unexec +lines either. +.It Fl n +Don't actually deinstall a package, just report the steps that +would be taken. +.It Fl O +Only delete the package's entries from the package database; do not +touch the package or its files itself. +.It Fl P Ar destdir +Prefix all file and directory names with +.Ar destdir . +For packages without install scripts this has the same behavior as +using +.Xr chroot 8 . +.It Fl p Ar prefix +Set +.Ar prefix +as the directory in which to delete files from any installed packages +which do not explicitly set theirs. +For most packages, the prefix will +be set automatically to the installed location by +.Xr pkg_add 1 . +.It Fl R +Recursively remove all packages that were needed by the given packages +and are no longer required. +This option overrides the +.Fl A +flag. +.It Fl r +Recursively remove all packages that require one of the packages given. +.It Fl V +Print version number and exit. +.It Fl v +Turn on verbose output. +.El +.Sh TECHNICAL DETAILS +.Nm +does pretty much what it says. +It examines installed package records in +.Pa \*[Lt]PKG_DBDIR\*[Gt]/\*[Lt]pkg-name\*[Gt] , +deletes the package contents, and finally removes the package records. +.Pp +If a package is required by other installed packages, +.Nm +will list those dependent packages and refuse to delete the package +(unless the +.Fl f +option is given). +.Pp +If a package has been marked as a +.Cm preserved +package, it will not be able to be deleted +(unless more than one occurrence of the +.Fl f +option is given). +.Pp +If a filename is given instead of a package name, the package of which +the given file belongs to can be deleted if the +.Fl F +flag is given. +The filename needs to be absolute, see the output produced by the +.Xr pkg_info 1 +.Fl aF +command. +.Pp +If a +.Cm deinstall +script exists for the package, it is executed before and after +any files are removed. +It is this script's responsibility to clean up any additional messy details +around the package's installation, since all +.Nm +knows how to do is delete the files created in the original distribution. +The +.Ic deinstall +script is called as: +.Bd -filled -offset indent -compact +.Cm deinstall +.Aq Ar pkg-name +.Ar VIEW-DEINSTALL +.Ed +before removing the package from a view, and as: +.Bd -filled -offset indent -compact +.Cm deinstall +.Aq Ar pkg-name +.Ar DEINSTALL +.Ed +before deleting all files and as: +.Bd -filled -offset indent -compact +.Cm deinstall +.Aq Ar pkg-name +.Ar POST-DEINSTALL +.Ed +after deleting them. +Passing the keywords +.Ar VIEW-DEINSTALL , +.Ar DEINSTALL , +and +.Ar POST-DEINSTALL +lets you potentially write only one program/script that handles all +aspects of installation and deletion. +.Pp +All scripts are called with the environment variable +.Ev PKG_PREFIX +set to the installation prefix (see the +.Fl p +option above). +This allows a package author to write a script +that reliably performs some action on the directory where the package +is installed, even if the user might have changed it by specifying the +.Fl p +option when running +.Nm +or +.Xr pkg_add 1 . +The scripts are also called with the +.Ev PKG_METADATA_DIR +environment variable set to the location of the +.Pa +* +meta-data files, and with the +.Ev PKG_REFCOUNT_DBDIR +environment variable set to the location of the package reference counts +database directory. +If the +.Fl P +flag was given to +.Nm , +.Ev PKG_DESTDIR +will be set to +.Ar destdir . +.Sh ENVIRONMENT +See +.Xr pkg_install.conf 5 +for options, that can also be specified using the environment. +.Sh SEE ALSO +.Xr pkg_add 1 , +.Xr pkg_admin 1 , +.Xr pkg_create 1 , +.Xr pkg_info 1 , +.Xr pkg_install.conf 5 +.Xr pkgsrc 7 +.Sh AUTHORS +.Bl -tag -width indent -compact +.It "Jordan Hubbard" +most of the work +.It "John Kohl" +refined it for +.Nx +.It "Hubert Feyrer" +.Nx +wildcard dependency processing, pkgdb, recursive "down" +delete, etc. +.It Joerg Sonnenberger +Rewrote most of the code to compute correct order of deinstallation +and to improve error handling. +.El diff --git a/external/bsd/pkg_install/dist/delete/pkg_delete.c b/external/bsd/pkg_install/dist/delete/pkg_delete.c new file mode 100644 index 000000000..9c0fc38f7 --- /dev/null +++ b/external/bsd/pkg_install/dist/delete/pkg_delete.c @@ -0,0 +1,928 @@ +/*- + * Copyright (c) 2009 Joerg Sonnenberger . + * Copyright (c) 2003 Johnny Lam . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: pkg_delete.c,v 1.1.1.8 2012/02/19 17:46:46 tron Exp $"); + +#if HAVE_ERR_H +#include +#endif +#include +#include + +#include "lib.h" + +static const char *pkgdb; +static const char *destdir; +static const char *prefix; + +static int keep_preserve; +static int no_deinstall; +static int find_by_filename; +static int unregister_only; +static int pkgdb_update_only; +static int delete_recursive; +static int delete_new_leaves; +static int delete_automatic_leaves; + +static void +usage(void) +{ + fprintf(stderr, "usage: pkg_delete [-DFfkNnORrVv] [-K pkg_dbdir]" + " [-P destdir] [-p prefix] pkg-name ...\n"); + exit(1); +} + +static int +add_by_filename(lpkg_head_t *pkgs, const char *filename) +{ + lpkg_t *lpp; + char *s; + + if ((s = pkgdb_retrieve(filename)) == NULL) { + warnx("No matching package for file `%s' in pkgdb", filename); + return 1; + } + + /* XXX Verify that pkgdb is consistent? Trust it for now... */ + + lpp = alloc_lpkg(s); + TAILQ_INSERT_TAIL(pkgs, lpp, lp_link); + return 0; +} + +static int +add_by_pattern(lpkg_head_t *pkgs, const char *pattern) +{ + switch (add_installed_pkgs_by_pattern(pattern, pkgs)) { + case 0: + warnx("No package matching `%s' found", pattern); + return 1; + case -1: + warnx("Error while iterating package database for `%s'", + pattern); + return 1; + default: + return 0; + } +} + +/* + * The argument is either a fixed package name or an absolute path. + * The latter is recognized for legacy compatibility and must point + * into the package database. + */ +static int +add_by_pkgname(lpkg_head_t *pkgs, char *pkg) +{ + char *s; + lpkg_t *lpp; + size_t l; + const char *orig_pkg = pkg; + + if (pkg[0] == '/') { + l = strlen(pkgdb); + if (strncmp(pkg, pkgdb, l) || pkg[l] != '/') { + warnx("Absolute path is not relative to " + "package database, skipping: %s", pkg); + return 1; + } + pkg += l + 1; + } + l = strcspn(pkg, "/"); + if (pkg[l + strspn(pkg + l, "/")] != '\0') { + warnx("`%s' is not a package name, skipping", orig_pkg); + return 1; + } + pkg[l] = '\0'; + + s = pkgdb_pkg_file(pkg, CONTENTS_FNAME); + if (fexists(s)) { + free(s); + lpp = alloc_lpkg(pkg); + TAILQ_INSERT_TAIL(pkgs, lpp, lp_link); + return 0; + } + free(s); + + switch (add_installed_pkgs_by_basename(pkg, pkgs)) { + case 0: + warnx("No matching package for basename `%s' of `%s'", + pkg, orig_pkg); + return 1; + case -1: + warnx("Error expanding basename `%s' of `%s'", + pkg, orig_pkg); + return 1; + default: + return 0; + } +} + +/* + * Evaluate +REQUIRED_BY. This function is used for four different + * tasks: + * 0: check if no depending packages remain + * 1: like 0, but prepend the depending packages to pkgs if they exist + * 2: print remaining packages to stderr + * 3: check all and at least one depending packages have been removed + */ +static int +process_required_by(const char *pkg, lpkg_head_t *pkgs, + lpkg_head_t *sorted_pkgs, int action) +{ + char line[MaxPathSize], *eol, *fname; + FILE *fp; + lpkg_t *lpp; + int got_match, got_miss; + + fname = pkgdb_pkg_file(pkg, REQUIRED_BY_FNAME); + if (!fexists(fname)) { + free(fname); + return 0; + } + + if ((fp = fopen(fname, "r")) == NULL) { + warn("Failed to open `%s'", fname); + free(fname); + return -1; + } + free(fname); + + got_match = 0; + got_miss = 0; + + while (fgets(line, sizeof(line), fp)) { + if ((eol = strrchr(line, '\n')) != NULL) + *eol = '\0'; + TAILQ_FOREACH(lpp, sorted_pkgs, lp_link) { + if (strcmp(lpp->lp_name, line) == 0) + break; + } + if (lpp != NULL) { + got_match = 1; + continue; + } + got_miss = 1; + if (pkgs) { + TAILQ_FOREACH(lpp, pkgs, lp_link) { + if (strcmp(lpp->lp_name, line) == 0) + break; + } + if (lpp != NULL) + continue; + } + switch (action) { + case 0: + fclose(fp); + return 1; + case 1: + lpp = alloc_lpkg(line); + TAILQ_INSERT_HEAD(pkgs, lpp, lp_link); + break; + case 2: + fprintf(stderr, "\t%s\n", line); + break; + case 3: + fclose(fp); + return 0; + } + } + + fclose(fp); + + return (action == 3 ? got_match : got_miss); +} + +/* + * Main function to order the patterns from the command line and + * add the subtrees for -r processing as needed. + * + * The first part ensures that all packages are listed at most once + * in pkgs. Afterwards the list is scanned for packages without depending + * packages. Each such package is moved to sorted_pkgs in order. + * If -r is given, all dependencies are inserted at the head of pkgs. + * The loop has to continue as long as progress is made. This can happen + * either because another package has been added to pkgs due to recursion + * (head of pkgs changed) or because a package has no more depending packages + * (tail of sorted_pkgs changed). + * + * If no progress is made, the remaining packages are moved to sorted_pkgs + * and an error is returned for the !Force case. + */ +static int +sort_and_recurse(lpkg_head_t *pkgs, lpkg_head_t *sorted_pkgs) +{ + lpkg_t *lpp, *lpp2, *lpp_next, *lpp_old_tail, *lpp_old_head; + int rv; + + TAILQ_FOREACH_SAFE(lpp, pkgs, lp_link, lpp_next) { + TAILQ_FOREACH(lpp2, pkgs, lp_link) { + if (lpp != lpp2 && + strcmp(lpp->lp_name, lpp2->lp_name) == 0) + break; + } + if (lpp2 == NULL) + continue; + TAILQ_REMOVE(pkgs, lpp, lp_link); + free_lpkg(lpp); + } + + while (!TAILQ_EMPTY(pkgs)) { + lpp_old_tail = TAILQ_LAST(sorted_pkgs, _lpkg_head_t); + lpp_old_head = TAILQ_FIRST(pkgs); + + TAILQ_FOREACH_SAFE(lpp, pkgs, lp_link, lpp_next) { + rv = process_required_by(lpp->lp_name, pkgs, + sorted_pkgs, delete_recursive ? 1 : 0); + if (rv) + continue; + TAILQ_REMOVE(pkgs, lpp, lp_link); + TAILQ_INSERT_TAIL(sorted_pkgs, lpp, lp_link); + } + + if (lpp_old_tail == TAILQ_LAST(sorted_pkgs, _lpkg_head_t) && + lpp_old_head == TAILQ_FIRST(pkgs)) + break; + } + + if (TAILQ_EMPTY(pkgs)) + return 0; + + while (!TAILQ_EMPTY(pkgs)) { + lpp = TAILQ_FIRST(pkgs); + TAILQ_REMOVE(pkgs, lpp, lp_link); + fprintf(stderr, + "Package `%s' is still required by other packages:\n", + lpp->lp_name); + process_required_by(lpp->lp_name, NULL, sorted_pkgs, 2); + if (Force) { + TAILQ_INSERT_TAIL(sorted_pkgs, lpp, lp_link); + } else + free_lpkg(lpp); + } + + return !Force; +} + +struct find_leaves_data { + lpkg_head_t *pkgs; + int progress; +}; + +/* + * Iterator for finding leaf packages. + * Packages that are marked as not for deletion are not considered as + * leaves. For all other packages it is checked if at least one package + * that depended on them is to be removed AND no depending package remains. + * If that is the case, the package is appended to the sorted list. + * As this package can't have depending packages left, the topological order + * remains consistent. + */ +static int +find_new_leaves_iter(const char *pkg, void *cookie) +{ + char *fname; + struct find_leaves_data *data = cookie; + lpkg_t *lpp; + + fname = pkgdb_pkg_file(pkg, PRESERVE_FNAME); + if (fexists(fname)) { + free(fname); + return 0; + } + free(fname); + + if (delete_automatic_leaves && !delete_new_leaves && + !is_automatic_installed(pkg)) + return 0; + + /* Check whether this package is already on the list first. */ + TAILQ_FOREACH(lpp, data->pkgs, lp_link) { + if (strcmp(lpp->lp_name, pkg) == 0) + return 0; + } + + if (process_required_by(pkg, NULL, data->pkgs, 3) == 1) { + lpp = alloc_lpkg(pkg); + TAILQ_INSERT_TAIL(data->pkgs, lpp, lp_link); + data->progress = 1; + } + + return 0; +} + +/* + * Iterate over all installed packages and look for new leaf packages. + * As long as the loop adds one new leaf package, processing continues. + */ +static void +find_new_leaves(lpkg_head_t *pkgs) +{ + struct find_leaves_data data; + + data.pkgs = pkgs; + do { + data.progress = 0; + iterate_pkg_db(find_new_leaves_iter, &data); + } while (data.progress); +} + +/* + * Check that no entry on the package list is marked as not for deletion. + */ +static int +find_preserve_pkgs(lpkg_head_t *pkgs) +{ + lpkg_t *lpp, *lpp_next; + char *fname; + int found_preserve; + + found_preserve = 0; + TAILQ_FOREACH_SAFE(lpp, pkgs, lp_link, lpp_next) { + fname = pkgdb_pkg_file(lpp->lp_name, PRESERVE_FNAME); + if (!fexists(fname)) { + free(fname); + continue; + } + free(fname); + if (keep_preserve) { + TAILQ_REMOVE(pkgs, lpp, lp_link); + free_lpkg(lpp); + continue; + } + if (!found_preserve) + warnx("The following packages are marked as not " + "for deletion:"); + found_preserve = 1; + fprintf(stderr, "\t%s\n", lpp->lp_name); + } + if (!found_preserve) + return 0; + if (Force == 0 || (!unregister_only && Force == 1)) + return 1; + fprintf(stderr, "...but will delete them anyway\n"); + return 0; +} + +/* + * Remove package from view. This is calling pkg_deinstall again. + */ +static int +remove_pkg_from_view(const char *pkg) +{ + char line[MaxPathSize], *fname, *eol; + FILE *fp; + + fname = pkgdb_pkg_file(pkg, VIEWS_FNAME); + if (isemptyfile(fname)) { + free(fname); + return 0; + } + if ((fp = fopen(fname, "r")) == NULL) { + warn("Unable to open `%s', aborting", fname); + free(fname); + return 1; + } + free(fname); + while (fgets(line, sizeof(line), fp) != NULL) { + if ((eol = strrchr(line, '\n')) != NULL) + *eol = '\0'; + if (Verbose || Fake) + printf("Deleting package `%s' instance from `%s' view\n", + pkg, line); + if (Fake) + continue; + if (fexec_skipempty(BINDIR "/pkg_delete", "-K", line, + Fake ? "-n" : "", + (Force > 1) ? "-f" : "", + (Force > 0) ? "-f" : "", + pkg, NULL) != 0) { + warnx("Unable to delete package `%s' from view `%s'", + pkg, line); + fclose(fp); + return 1; + } + } + fclose(fp); + return 0; +} + +/* + * Run the +DEINSTALL script. Depending on whether this is + * a depoted package and whether this pre- or post-deinstall phase, + * different arguments are passed down. + */ +static int +run_deinstall_script(const char *pkg, int do_postdeinstall) +{ + const char *target, *text; + char *fname, *fname2, *pkgdir; + int rv; + + fname = pkgdb_pkg_file(pkg, DEINSTALL_FNAME); + if (!fexists(fname)) { + free(fname); + return 0; + } + + fname2 = pkgdb_pkg_file(pkg, DEPOT_FNAME); + if (fexists(fname2)) { + if (do_postdeinstall) { + free(fname); + free(fname2); + return 0; + } + target = "VIEW-DEINSTALL"; + text = "view deinstall"; + } else if (do_postdeinstall) { + target = "POST-DEINSTALL"; + text = "post-deinstall"; + } else { + target = "DEINSTALL"; + text = "deinstall"; + } + free(fname2); + + if (Fake) { + printf("Would execute %s script with argument %s now\n", + text, target); + free(fname); + return 0; + } + + pkgdir = pkgdb_pkg_dir(pkg); + if (chmod(fname, 0555)) + warn("chmod of `%s' failed", fname); + rv = fcexec(pkgdir, fname, pkg, target, NULL); + if (rv) + warnx("%s script returned error status", text); + free(pkgdir); + free(fname); + return rv; +} + +/* + * Copy lines from fname to fname_tmp, filtering out lines equal to text. + * Afterwards rename fname_tmp to fname; + */ +static int +remove_line(const char *fname, const char *fname_tmp, const char *text) +{ + FILE *fp, *fp_out; + char line[MaxPathSize], *eol; + int rv; + + if ((fp = fopen(fname, "r")) == NULL) { + warn("Unable to open `%s'", fname); + return 1; + } + if ((fp_out = fopen(fname_tmp, "w")) == NULL) { + warn("Unable to open `%s'", fname_tmp); + fclose(fp); + return 1; + } + + while (fgets(line, sizeof(line), fp) != NULL) { + if ((eol = strrchr(line, '\n')) != NULL) + *eol = '\0'; + if (strcmp(line, text) == 0) + continue; + fprintf(fp_out, "%s\n", line); + } + fclose(fp); + + if (fclose(fp_out) == EOF) { + remove(fname_tmp); + warnx("Failure while closing `%s' temp file", fname_tmp); + return 1; + } + + if (rename(fname_tmp, fname) == -1) { + warn("Unable to rename `%s' to `%s'", fname_tmp, fname); + rv = 1; + } else + rv = 0; + remove(fname_tmp); + + return rv; +} + +/* + * Unregister the package from the depot it is registered in. + */ +static int +remove_pkg_from_depot(const char *pkg) +{ + FILE *fp; + char line[MaxPathSize], *eol; + char *fname, *fname2; + int rv; + + fname = pkgdb_pkg_file(pkg, DEPOT_FNAME); + if (isemptyfile(fname)) { + free(fname); + return 0; + } + + if (Verbose) + printf("Attempting to remove the `%s' registration " + "on package `%s'\n", fname, pkg); + + if (Fake) { + free(fname); + return 1; + } + + if ((fp = fopen(fname, "r")) == NULL) { + warn("Unable to open `%s' file", fname); + free(fname); + return 1; + } + if (fgets(line, sizeof(line), fp) == NULL) { + fclose(fp); + warnx("Empty depot file `%s'", fname); + free(fname); + return 1; + } + if ((eol = strrchr(line, '\n')) != NULL) + *eol = '\0'; + fclose(fp); + free(fname); + + fname = pkgdb_pkg_file(pkg, VIEWS_FNAME); + fname2 = pkgdb_pkg_file(pkg, VIEWS_FNAME_TMP); + rv = remove_line(fname, fname2, line); + free(fname2); + free(fname); + + return rv; +} + +/* + * remove_depend is used as iterator function below. + * The passed-in package name should be removed from the + * +REQUIRED_BY list of the dependency. Such an entry + * can miss in a fully correct package database, if the pattern + * matches more than one package. + */ +static int +remove_depend(const char *cur_pkg, void *cookie) +{ + const char *pkg = cookie; + char *fname, *fname2; + int rv; + + fname = pkgdb_pkg_file(cur_pkg, REQUIRED_BY_FNAME); + if (isemptyfile(fname)) { + free(fname); + return 0; + } + fname2 = pkgdb_pkg_file(cur_pkg, REQUIRED_BY_FNAME_TMP); + + rv = remove_line(fname, fname2, pkg); + + free(fname2); + free(fname); + + return rv; +} + +static int +remove_pkg(const char *pkg) +{ + FILE *fp; + char *fname, *pkgdir; + package_t plist; + plist_t *p; + int is_depoted_pkg, rv, late_error; + + if (pkgdb_update_only) + return pkgdb_remove_pkg(pkg) ? 0 : 1; + + fname = pkgdb_pkg_file(pkg, CONTENTS_FNAME); + if (!fexists(fname)) { + warnx("package `%s' is not installed, `%s' missing", pkg, fname); + free(fname); + return 1; + } + free(fname); + + /* +REQUIRED_BY and +PRESERVE already checked */ + if (remove_pkg_from_view(pkg)) + return 1; + + /* + * The views related code has bad error handling, if e.g. + * the deinstall script fails, the package remains unregistered. + */ + + fname = pkgdb_pkg_file(pkg, CONTENTS_FNAME); + if ((fp = fopen(fname, "r")) == NULL) { + warnx("Failed to open `%s'", fname); + free(fname); + return 1; + } + read_plist(&plist, fp); + fclose(fp); + + /* + * If a prefix has been provided, remove the first @cwd and + * prepend that prefix. This allows removing packages without + * @cwd if really necessary. pkg_admin rebuild is likely needed + * afterwards though. + */ + if (prefix) { + delete_plist(&plist, FALSE, PLIST_CWD, NULL); + add_plist_top(&plist, PLIST_CWD, prefix); + } + if ((p = find_plist(&plist, PLIST_CWD)) == NULL) { + warnx("Package `%s' doesn't have a prefix", pkg); + return 1; + } + + if (find_plist(&plist, PLIST_NAME) == NULL) { + /* Cheat a bit to allow removal of such bad packages. */ + warnx("Package `%s' doesn't have a name", pkg); + add_plist_top(&plist, PLIST_NAME, pkg); + } + + setenv(PKG_REFCOUNT_DBDIR_VNAME, config_pkg_refcount_dbdir, 1); + fname = pkgdb_pkg_dir(pkg); + setenv(PKG_METADATA_DIR_VNAME, fname, 1); + free(fname); + setenv(PKG_PREFIX_VNAME, p->name, 1); + + if (!no_deinstall && !unregister_only) { + if (run_deinstall_script(pkg, 0) && !Force) + return 1; + } + + late_error = 0; + + if (Fake) + printf("Attempting to delete package `%s'\n", pkg); + else if (delete_package(FALSE, &plist, unregister_only, + destdir) == FAIL) { + warnx("couldn't entirely delete package `%s'", pkg); + /* + * XXX It could be nice to error out here explicitly, + * XXX but this is problematic for missing or changed files. + * XXX At least the inability to remove files at all should + * XXX be handled though. + */ + } + + /* + * Past the point of no return. Files are gone, all that is left + * is cleaning up registered dependencies and removing the meta data. + * Errors in the remaining part are counted, but don't stop the + * processing. + */ + + fname = pkgdb_pkg_file(pkg, DEPOT_FNAME); + if (fexists(fname)) { + late_error |= remove_pkg_from_depot(pkg); + /* XXX error checking */ + } else { + for (p = plist.head; p; p = p->next) { + if (p->type != PLIST_PKGDEP) + continue; + if (Verbose) + printf("Attempting to remove dependency " + "on package `%s'\n", p->name); + if (Fake) + continue; + match_installed_pkgs(p->name, remove_depend, + __UNCONST(pkg)); + } + } + free(fname); + + free_plist(&plist); + + if (!no_deinstall && !unregister_only) + late_error |= run_deinstall_script(pkg, 1); + + fname = pkgdb_pkg_file(pkg, VIEWS_FNAME); + if (fexists(fname)) + is_depoted_pkg = TRUE; + else + is_depoted_pkg = FALSE; + free(fname); + + if (Fake) + return 0; + + /* + * Kill the pkgdb subdirectory. The files have been removed, so + * this is way beyond the point of no return. + */ + pkgdir = pkgdb_pkg_dir(pkg); + (void) remove_files(pkgdir, "+*"); + rv = 1; + if (isemptydir(pkgdir)&& rmdir(pkgdir) == 0) + rv = 0; + else if (is_depoted_pkg) + warnx("Depot directory `%s' is not empty", pkgdir); + else if (!Force) + warnx("Couldn't remove package directory in `%s'", pkgdir); + else if (recursive_remove(pkgdir, 1)) + warn("Couldn't remove package directory `%s'", pkgdir); + else + warnx("Package directory `%s' forcefully removed", pkgdir); + free(pkgdir); + + return rv | late_error; +} + +int +main(int argc, char *argv[]) +{ + lpkg_head_t pkgs, sorted_pkgs; + int ch, r, has_error; + unsigned long bad_count; + + TAILQ_INIT(&pkgs); + TAILQ_INIT(&sorted_pkgs); + + setprogname(argv[0]); + while ((ch = getopt(argc, argv, "ADFfK:kNnOP:p:RrVv")) != -1) { + switch (ch) { + case 'A': + delete_automatic_leaves = 1; + break; + case 'D': + no_deinstall = 1; + break; + case 'F': + find_by_filename = 1; + break; + case 'f': + ++Force; + break; + case 'K': + pkgdb_set_dir(optarg, 3); + break; + case 'k': + keep_preserve = 1; + break; + case 'N': + unregister_only = 1; + break; + case 'n': + Fake = 1; + break; + case 'O': + pkgdb_update_only = 1; + break; + case 'P': + destdir = optarg; + break; + case 'p': + prefix = optarg; + break; + case 'R': + delete_new_leaves = 1; + break; + case 'r': + delete_recursive = 1; + break; + case 'V': + show_version(); + /* NOTREACHED */ + case 'v': + ++Verbose; + break; + default: + usage(); + break; + } + } + + pkg_install_config(); + + pkgdb = xstrdup(pkgdb_get_dir()); + + if (destdir != NULL) { + char *pkgdbdir; + + pkgdbdir = xasprintf("%s/%s", destdir, pkgdb); + pkgdb_set_dir(pkgdbdir, 4); + free(pkgdbdir); + } + + argc -= optind; + argv += optind; + + if (argc == 0) { + if (find_by_filename) + warnx("Missing filename(s)"); + else + warnx("Missing package name(s)"); + usage(); + } + + if (Fake) + r = pkgdb_open(ReadOnly); + else + r = pkgdb_open(ReadWrite); + + if (!r) + errx(EXIT_FAILURE, "Opening pkgdb failed"); + + /* First, process all command line options. */ + + has_error = 0; + for (; argc != 0; --argc, ++argv) { + if (find_by_filename) + has_error |= add_by_filename(&pkgs, *argv); + else if (ispkgpattern(*argv)) + has_error |= add_by_pattern(&pkgs, *argv); + else + has_error |= add_by_pkgname(&pkgs, *argv); + } + + if (has_error && !Force) { + pkgdb_close(); + return EXIT_FAILURE; + } + + /* Second, reorder and recursive if necessary. */ + + if (sort_and_recurse(&pkgs, &sorted_pkgs)) { + pkgdb_close(); + return EXIT_FAILURE; + } + + /* Third, add leaves if necessary. */ + + if (delete_new_leaves || delete_automatic_leaves) + find_new_leaves(&sorted_pkgs); + + /* + * Now that all packages to remove are known, check + * if all are removable. After that, start the actual + * removal. + */ + + if (find_preserve_pkgs(&sorted_pkgs)) { + pkgdb_close(); + return EXIT_FAILURE; + } + + setenv(PKG_REFCOUNT_DBDIR_VNAME, pkgdb_refcount_dir(), 1); + + bad_count = 0; + while (!TAILQ_EMPTY(&sorted_pkgs)) { + lpkg_t *lpp; + + lpp = TAILQ_FIRST(&sorted_pkgs); + TAILQ_REMOVE(&sorted_pkgs, lpp, lp_link); + if (remove_pkg(lpp->lp_name)) { + ++bad_count; + if (!Force) + break; + } + free_lpkg(lpp); + } + + pkgdb_close(); + + if (Force && bad_count && Verbose) + warnx("Removal of %lu packages failed", bad_count); + + return bad_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/external/bsd/pkg_install/dist/info/info.h b/external/bsd/pkg_install/dist/info/info.h new file mode 100644 index 000000000..f6b967019 --- /dev/null +++ b/external/bsd/pkg_install/dist/info/info.h @@ -0,0 +1,134 @@ +/* $NetBSD: info.h,v 1.1.1.5 2009/10/07 13:19:42 joerg Exp $ */ + +/* from FreeBSD Id: info.h,v 1.10 1997/02/22 16:09:40 peter Exp */ + +/*- + * Copyright (c) 2008 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 23 August 1993 + * + * Include and define various things wanted by the info command. + * + */ + +#ifndef _INST_INFO_H_INCLUDE +#define _INST_INFO_H_INCLUDE + +struct pkg_meta { + char *meta_contents; + char *meta_comment; + char *meta_desc; + char *meta_mtree; + char *meta_build_version; + char *meta_build_info; + char *meta_size_pkg; + char *meta_size_all; + char *meta_required_by; + char *meta_display; + char *meta_install; + char *meta_deinstall; + char *meta_preserve; + char *meta_views; + char *meta_installed_info; + int is_installed; +}; + +#ifndef MAXINDEXSIZE +#define MAXINDEXSIZE 60 +#endif + +#ifndef MAXNAMESIZE +#define MAXNAMESIZE 20 +#endif + +#define SHOW_COMMENT 0x00001 +#define SHOW_DESC 0x00002 +#define SHOW_PLIST 0x00004 +#define SHOW_INSTALL 0x00008 +#define SHOW_DEINSTALL 0x00010 +#define SHOW_PREFIX 0x00040 +#define SHOW_INDEX 0x00080 +#define SHOW_FILES 0x00100 +#define SHOW_DISPLAY 0x00200 +#define SHOW_REQBY 0x00400 +#define SHOW_MTREE 0x00800 +#define SHOW_BUILD_VERSION 0x01000 +#define SHOW_BUILD_INFO 0x02000 +#define SHOW_DEPENDS 0x04000 +#define SHOW_PKG_SIZE 0x08000 +#define SHOW_ALL_SIZE 0x10000 +#define SHOW_BLD_DEPENDS 0x20000 +#define SHOW_BI_VAR 0x40000 +#define SHOW_SUMMARY 0x80000 +#define SHOW_FULL_REQBY 0x100000 + +enum which { + WHICH_ALL, + WHICH_USER, + WHICH_LIST +}; + +extern int Flags; +extern enum which Which; +extern Boolean File2Pkg; +extern Boolean Quiet; +extern const char *InfoPrefix; +extern const char *BuildInfoVariable; +extern lpkg_head_t pkgs; + +int CheckForPkg(const char *); +int CheckForBestPkg(const char *); + +void show_file(const char *, const char *, Boolean); +void show_var(const char *, const char *); +void show_plist(const char *, package_t *, pl_ent_t); +void show_files(const char *, package_t *); +void show_depends(const char *, package_t *); +void show_bld_depends(const char *, package_t *); +void show_index(const char *, const char *); +void show_summary(struct pkg_meta *, package_t *, const char *); +void show_list(lpkg_head_t *, const char *); + +int pkg_perform(lpkg_head_t *); + +#endif /* _INST_INFO_H_INCLUDE */ diff --git a/external/bsd/pkg_install/dist/info/main.c b/external/bsd/pkg_install/dist/info/main.c new file mode 100644 index 000000000..d443eb826 --- /dev/null +++ b/external/bsd/pkg_install/dist/info/main.c @@ -0,0 +1,328 @@ +/* $NetBSD: main.c,v 1.1.1.9 2013/04/20 15:26:53 wiz Exp $ */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: main.c,v 1.1.1.9 2013/04/20 15:26:53 wiz Exp $"); + +/* + * + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * This is the add module. + * + */ + +#if HAVE_SYS_IOCTL_H +#include +#endif + +#if HAVE_ERR_H +#include +#endif + +#include "lib.h" +#include "info.h" + +static const char Options[] = ".aBbcDde:E:fFhIiK:kLl:mNnpQ:qrRsSuvVX"; + +int Flags = 0; +enum which Which = WHICH_LIST; +Boolean File2Pkg = FALSE; +Boolean Quiet = FALSE; +const char *InfoPrefix = ""; +const char *BuildInfoVariable = ""; +lpkg_head_t pkgs; + +static void +usage(void) +{ + fprintf(stderr, "%s\n%s\n%s\n%s\n", + "usage: pkg_info [-BbcDdFfhIikLmNnpqRrSsVvX] [-E pkg-name] [-e pkg-name]", + " [-K pkg_dbdir] [-l prefix] pkg-name ...", + " pkg_info [-a | -u] [flags]", + " pkg_info [-Q variable] pkg-name ..."); + exit(1); +} + +int +main(int argc, char **argv) +{ + char *CheckPkg = NULL; + char *BestCheckPkg = NULL; + lpkg_t *lpp; + int ch; + int rc; + + setprogname(argv[0]); + while ((ch = getopt(argc, argv, Options)) != -1) + switch (ch) { + case '.': /* for backward compatibility */ + break; + + case 'a': + Which = WHICH_ALL; + break; + + case 'B': + Flags |= SHOW_BUILD_INFO; + break; + + case 'b': + Flags |= SHOW_BUILD_VERSION; + break; + + case 'c': + Flags |= SHOW_COMMENT; + break; + + case 'D': + Flags |= SHOW_DISPLAY; + break; + + case 'd': + Flags |= SHOW_DESC; + break; + + case 'E': + BestCheckPkg = optarg; + break; + + case 'e': + CheckPkg = optarg; + break; + + case 'f': + Flags |= SHOW_PLIST; + break; + + case 'F': + File2Pkg = 1; + break; + + case 'I': + Flags |= SHOW_INDEX; + break; + + case 'i': + Flags |= SHOW_INSTALL; + break; + + case 'K': + pkgdb_set_dir(optarg, 3); + break; + + case 'k': + Flags |= SHOW_DEINSTALL; + break; + + case 'L': + Flags |= SHOW_FILES; + break; + + case 'l': + InfoPrefix = optarg; + break; + + case 'm': + Flags |= SHOW_MTREE; + break; + + case 'N': + Flags |= SHOW_BLD_DEPENDS; + break; + + case 'n': + Flags |= SHOW_DEPENDS; + break; + + case 'p': + Flags |= SHOW_PREFIX; + break; + + case 'Q': + Flags |= SHOW_BI_VAR; + BuildInfoVariable = optarg; + break; + + case 'q': + Quiet = TRUE; + break; + + case 'r': + Flags |= SHOW_FULL_REQBY; + break; + + case 'R': + Flags |= SHOW_REQBY; + break; + + case 's': + Flags |= SHOW_PKG_SIZE; + break; + + case 'S': + Flags |= SHOW_ALL_SIZE; + break; + + case 'u': + Which = WHICH_USER; + break; + + case 'v': + Verbose = TRUE; + /* Reasonable definition of 'everything' */ + Flags = SHOW_COMMENT | SHOW_DESC | SHOW_PLIST | SHOW_INSTALL | + SHOW_DEINSTALL | SHOW_DISPLAY | SHOW_MTREE | + SHOW_REQBY | SHOW_BLD_DEPENDS | SHOW_DEPENDS | SHOW_PKG_SIZE | SHOW_ALL_SIZE; + break; + + case 'V': + show_version(); + /* NOTREACHED */ + + case 'X': + Flags |= SHOW_SUMMARY; + break; + + case 'h': + case '?': + default: + usage(); + /* NOTREACHED */ + } + + argc -= optind; + argv += optind; + + pkg_install_config(); + + if (argc == 0 && !Flags && !CheckPkg) { + /* No argument or relevant flags specified - assume -I */ + Flags = SHOW_INDEX; + /* assume -a if neither -u nor -a is given */ + if (Which == WHICH_LIST) + Which = WHICH_ALL; + } + + if (CheckPkg != NULL && BestCheckPkg != NULL) { + warnx("-E and -e are mutally exlusive"); + usage(); + } + + if (argc != 0 && CheckPkg != NULL) { + warnx("can't give any additional arguments to -e"); + usage(); + } + + if (argc != 0 && BestCheckPkg != NULL) { + warnx("can't give any additional arguments to -E"); + usage(); + } + + if (argc != 0 && Which != WHICH_LIST) { + warnx("can't use both -a/-u and package name"); + usage(); + } + + /* Set some reasonable defaults */ + if (!Flags) + Flags = SHOW_COMMENT | SHOW_DESC | SHOW_REQBY + | SHOW_DEPENDS | SHOW_DISPLAY; + + /* -Fe /filename -> change CheckPkg to real packagename */ + if (CheckPkg) { + if (File2Pkg) { + char *s; + + if (!pkgdb_open(ReadOnly)) + err(EXIT_FAILURE, "cannot open pkgdb"); + + s = pkgdb_retrieve(CheckPkg); + + if (s == NULL) + errx(EXIT_FAILURE, "No matching pkg for %s.", CheckPkg); + CheckPkg = xstrdup(s); + + pkgdb_close(); + } + return CheckForPkg(CheckPkg); + } + + if (BestCheckPkg) + return CheckForBestPkg(BestCheckPkg); + + TAILQ_INIT(&pkgs); + + /* Get all the remaining package names, if any */ + if (File2Pkg && Which == WHICH_LIST) + if (!pkgdb_open(ReadOnly)) { + err(EXIT_FAILURE, "cannot open pkgdb"); + } + while (*argv) { + /* pkgdb: if -F flag given, don't add pkgnames to the "pkgs" + * queue but rather resolve the given filenames to pkgnames + * using pkgdb_retrieve, then add them. */ + if (File2Pkg) { + char *s; + + s = pkgdb_retrieve(*argv); + + if (s) { + lpp = alloc_lpkg(s); + TAILQ_INSERT_TAIL(&pkgs, lpp, lp_link); + } else + errx(EXIT_FAILURE, "No matching pkg for %s.", *argv); + } else { + if (ispkgpattern(*argv)) { + switch (add_installed_pkgs_by_pattern(*argv, &pkgs)) { + case 0: + errx(EXIT_FAILURE, "No matching pkg for %s.", *argv); + case -1: + errx(EXIT_FAILURE, "Error during search in pkgdb for %s", *argv); + } + } else { + const char *dbdir; + + dbdir = pkgdb_get_dir(); + if (**argv == '/' && strncmp(*argv, dbdir, strlen(dbdir)) == 0) { + *argv += strlen(dbdir) + 1; + if ((*argv)[strlen(*argv) - 1] == '/') { + (*argv)[strlen(*argv) - 1] = 0; + } + } + lpp = alloc_lpkg(*argv); + TAILQ_INSERT_TAIL(&pkgs, lpp, lp_link); + } + } + argv++; + } + + if (File2Pkg) + pkgdb_close(); + + /* If no packages, yelp */ + if (TAILQ_FIRST(&pkgs) == NULL && Which == WHICH_LIST && !CheckPkg) + warnx("missing package name(s)"), usage(); + + rc = pkg_perform(&pkgs); + exit(rc); + /* NOTREACHED */ +} diff --git a/external/bsd/pkg_install/dist/info/perform.c b/external/bsd/pkg_install/dist/info/perform.c new file mode 100644 index 000000000..9d8555a41 --- /dev/null +++ b/external/bsd/pkg_install/dist/info/perform.c @@ -0,0 +1,665 @@ +/* $NetBSD: perform.c,v 1.1.1.13 2010/02/20 04:41:55 joerg Exp $ */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +#if HAVE_SYS_QUEUE_H +#include +#endif +#if HAVE_SYS_WAIT_H +#include +#endif +__RCSID("$NetBSD: perform.c,v 1.1.1.13 2010/02/20 04:41:55 joerg Exp $"); + +/*- + * Copyright (c) 2008 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 23 Aug 1993 + * + * This is the main body of the info module. + * + */ + +#include "lib.h" +#include "info.h" + +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif + +#ifndef BOOTSTRAP +#include +#include +#endif +#if HAVE_ERR_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif +#if HAVE_SIGNAL_H +#include +#endif +#if HAVE_DIRENT_H +#include +#endif +#if HAVE_CTYPE_H +#include +#endif +#include + +#define LOAD_CONTENTS (1 << 0) +#define LOAD_COMMENT (1 << 1) +#define LOAD_DESC (1 << 2) +#define LOAD_INSTALL (1 << 3) +#define LOAD_DEINSTALL (1 << 4) +#define LOAD_DISPLAY (1 << 5) +#define LOAD_MTREE (1 << 6) +#define LOAD_BUILD_VERSION (1 << 7) +#define LOAD_BUILD_INFO (1 << 8) +#define LOAD_SIZE_PKG (1 << 9) +#define LOAD_SIZE_ALL (1 << 10) +#define LOAD_PRESERVE (1 << 11) +#define LOAD_VIEWS (1 << 12) +#define LOAD_REQUIRED_BY (1 << 13) +#define LOAD_INSTALLED_INFO (1 << 14) + +static const struct pkg_meta_desc { + size_t entry_offset; + const char *entry_filename; + int entry_mask; + int required_file; +} pkg_meta_descriptors[] = { + { offsetof(struct pkg_meta, meta_contents), CONTENTS_FNAME, + LOAD_CONTENTS, 1}, + { offsetof(struct pkg_meta, meta_comment), COMMENT_FNAME, + LOAD_COMMENT, 1 }, + { offsetof(struct pkg_meta, meta_desc), DESC_FNAME, + LOAD_DESC, 1 }, + { offsetof(struct pkg_meta, meta_install), INSTALL_FNAME, + LOAD_INSTALL, 0 }, + { offsetof(struct pkg_meta, meta_deinstall), DEINSTALL_FNAME, + LOAD_DEINSTALL, 0 }, + { offsetof(struct pkg_meta, meta_display), DISPLAY_FNAME, + LOAD_DISPLAY, 0 }, + { offsetof(struct pkg_meta, meta_mtree), MTREE_FNAME, + LOAD_MTREE, 0 }, + { offsetof(struct pkg_meta, meta_build_version), BUILD_VERSION_FNAME, + LOAD_BUILD_VERSION, 0 }, + { offsetof(struct pkg_meta, meta_build_info), BUILD_INFO_FNAME, + LOAD_BUILD_INFO, 0 }, + { offsetof(struct pkg_meta, meta_size_pkg), SIZE_PKG_FNAME, + LOAD_SIZE_PKG, 0 }, + { offsetof(struct pkg_meta, meta_size_all), SIZE_ALL_FNAME, + LOAD_SIZE_ALL, 0 }, + { offsetof(struct pkg_meta, meta_preserve), PRESERVE_FNAME, + LOAD_PRESERVE, 0 }, + { offsetof(struct pkg_meta, meta_views), VIEWS_FNAME, + LOAD_VIEWS, 0 }, + { offsetof(struct pkg_meta, meta_required_by), REQUIRED_BY_FNAME, + LOAD_REQUIRED_BY, 0 }, + { offsetof(struct pkg_meta, meta_installed_info), INSTALLED_INFO_FNAME, + LOAD_INSTALLED_INFO, 0 }, + { 0, NULL, 0, 0 }, +}; + +static int desired_meta_data; + +static void +free_pkg_meta(struct pkg_meta *meta) +{ + const struct pkg_meta_desc *descr; + + for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) + free(*(char **)((char *)meta + descr->entry_offset)); + + free(meta); +} + +#ifndef BOOTSTRAP +static struct pkg_meta * +read_meta_data_from_archive(struct archive *archive, + struct archive_entry *entry) +{ + struct pkg_meta *meta; + const char *fname; + const struct pkg_meta_desc *descr, *last_descr; + char **target; + int64_t size; + int r, found_required; + + found_required = 0; + + meta = xcalloc(1, sizeof(*meta)); + + last_descr = 0; + if (entry != NULL) { + r = ARCHIVE_OK; + goto has_entry; + } + + while ((r = archive_read_next_header(archive, &entry)) == ARCHIVE_OK) { +has_entry: + fname = archive_entry_pathname(entry); + + for (descr = pkg_meta_descriptors; descr->entry_filename; + ++descr) { + if (strcmp(descr->entry_filename, fname) == 0) + break; + } + if (descr->entry_filename == NULL) + break; + + if (descr->required_file) + ++found_required; + + target = (char **)((char *)meta + descr->entry_offset); + if (*target) + errx(2, "duplicate entry, package corrupt"); + if (descr < last_descr) + warnx("misordered package, continuing"); + else + last_descr = descr; + + if ((descr->entry_mask & desired_meta_data) == 0) { + if (archive_read_data_skip(archive)) + errx(2, "cannot read package meta data"); + continue; + } + + size = archive_entry_size(entry); + if (size > SSIZE_MAX - 1) + errx(2, "package meta data too large to process"); + *target = xmalloc(size + 1); + if (archive_read_data(archive, *target, size) != size) + errx(2, "cannot read package meta data"); + (*target)[size] = '\0'; + } + + for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { + if (descr->required_file) + --found_required; + } + + meta->is_installed = 0; + if (found_required != 0 || (r != ARCHIVE_OK && r != ARCHIVE_EOF)) { + free_pkg_meta(meta); + meta = NULL; + } + + return meta; +} +#endif + +static struct pkg_meta * +read_meta_data_from_pkgdb(const char *pkg) +{ + struct pkg_meta *meta; + const struct pkg_meta_desc *descr; + char **target; + char *fname; + int fd; + struct stat st; + + meta = xcalloc(1, sizeof(*meta)); + + for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { + if ((descr->entry_mask & desired_meta_data) == 0) + continue; + + fname = pkgdb_pkg_file(pkg, descr->entry_filename); + fd = open(fname, O_RDONLY, 0); + free(fname); + if (fd == -1) { + if (errno == ENOENT && descr->required_file == 0) + continue; + err(2, "cannot read meta data file %s of package %s", + descr->entry_filename, pkg); + } + target = (char **)((char *)meta + descr->entry_offset); + + if (fstat(fd, &st) == -1) + err(2, "cannot stat meta data"); + if ((st.st_mode & S_IFMT) != S_IFREG) + errx(1, "meta data is not regular file"); + if (st.st_size > SSIZE_MAX - 1) + err(2, "meta data file too large to process"); + *target = xmalloc(st.st_size + 1); + if (read(fd, *target, st.st_size) != st.st_size) + err(2, "cannot read meta data"); + (*target)[st.st_size] = '\0'; + close(fd); + } + + meta->is_installed = 1; + + return meta; +} + +static void +build_full_reqby(lpkg_head_t *reqby, struct pkg_meta *meta, int limit) +{ + char *iter, *eol, *next; + lpkg_t *lpp; + struct pkg_meta *meta_dep; + + if (limit == 65536) + errx(1, "Cycle in the dependency tree, bailing out"); + + if (meta->is_installed == 0 || meta->meta_required_by == NULL) + return; + + for (iter = meta->meta_required_by; *iter != '\0'; iter = next) { + eol = iter + strcspn(iter, "\n"); + if (*eol == '\n') + next = eol + 1; + else + next = eol; + if (iter == eol) + continue; + TAILQ_FOREACH(lpp, reqby, lp_link) { + if (strlen(lpp->lp_name) + iter != eol) + continue; + if (memcmp(lpp->lp_name, iter, eol - iter) == 0) + break; + } + if (lpp != NULL) + continue; + *eol = '\0'; + lpp = alloc_lpkg(iter); + if (next != eol) + *eol = '\n'; + + meta_dep = read_meta_data_from_pkgdb(lpp->lp_name); + if (meta_dep == NULL) + continue; + build_full_reqby(reqby, meta_dep, limit + 1); + free_pkg_meta(meta_dep); + + TAILQ_INSERT_HEAD(reqby, lpp, lp_link); + } +} + +static lfile_head_t files; + +static int +pkg_do(const char *pkg) +{ + struct pkg_meta *meta; + int code = 0; + const char *binpkgfile = NULL; + char *pkgdir; + + if (IS_URL(pkg) || (fexists(pkg) && isfile(pkg))) { +#ifdef BOOTSTRAP + errx(2, "Binary packages not supported during bootstrap"); +#else + struct archive *archive; + struct archive_entry *entry; + char *archive_name, *pkgname; + + archive = open_archive(pkg, &archive_name); + if (archive == NULL) { + warnx("can't find package `%s', skipped", pkg); + return -1; + } + pkgname = NULL; + entry = NULL; + pkg_verify_signature(archive_name, &archive, &entry, &pkgname); + if (archive == NULL) + return -1; + free(pkgname); + + meta = read_meta_data_from_archive(archive, entry); + archive_read_finish(archive); + if (!IS_URL(pkg)) + binpkgfile = pkg; +#endif + } else { + /* + * It's not an uninstalled package, try and find it among the + * installed + */ + pkgdir = pkgdb_pkg_dir(pkg); + if (!fexists(pkgdir) || !(isdir(pkgdir) || islinktodir(pkgdir))) { + switch (add_installed_pkgs_by_basename(pkg, &pkgs)) { + case 1: + return 0; + case 0: + /* No match */ + warnx("can't find package `%s'", pkg); + return 1; + case -1: + errx(EXIT_FAILURE, "Error during search in pkgdb for %s", pkg); + } + } + free(pkgdir); + meta = read_meta_data_from_pkgdb(pkg); + } + + if (meta == NULL) { + warnx("invalid package `%s' skipped", pkg); + return 1; + } + + /* + * Index is special info type that has to override all others to make + * any sense. + */ + if (Flags & SHOW_INDEX) { + char tmp[MaxPathSize]; + + (void) snprintf(tmp, sizeof(tmp), "%-19s ", pkg); + show_index(meta->meta_comment, tmp); + } else if (Flags & SHOW_BI_VAR) { + if (strcspn(BuildInfoVariable, "ABCDEFGHIJKLMNOPQRSTUVWXYZ") + == strlen(BuildInfoVariable)) { + if (meta->meta_installed_info) + show_var(meta->meta_installed_info, BuildInfoVariable); + } else { + if (meta->meta_build_info) + show_var(meta->meta_build_info, BuildInfoVariable); + else + warnx("Build information missing"); + } + } else { + package_t plist; + + /* Read the contents list */ + parse_plist(&plist, meta->meta_contents); + + /* Start showing the package contents */ + if (!Quiet && !(Flags & SHOW_SUMMARY)) { + printf("%sInformation for %s:\n\n", InfoPrefix, pkg); + if (meta->meta_preserve) { + printf("*** PACKAGE MAY NOT BE DELETED ***\n"); + } + } + if (Flags & SHOW_SUMMARY) { + show_summary(meta, &plist, binpkgfile); + } + if (Flags & SHOW_COMMENT) { + show_file(meta->meta_comment, "Comment:\n", TRUE); + } + if (Flags & SHOW_DEPENDS) { + show_depends("Requires:\n", &plist); + } + if (Flags & SHOW_BLD_DEPENDS) { + show_bld_depends("Built using:\n", &plist); + } + if ((Flags & SHOW_REQBY) && meta->meta_required_by) { + show_file(meta->meta_required_by, "Required by:\n", TRUE); + } + if ((Flags & SHOW_FULL_REQBY) && meta->is_installed) { + lpkg_head_t reqby; + TAILQ_INIT(&reqby); + build_full_reqby(&reqby, meta, 0); + show_list(&reqby, "Full required by list:\n"); + } + if (Flags & SHOW_DESC) { + show_file(meta->meta_desc, "Description:\n", TRUE); + } + if ((Flags & SHOW_DISPLAY) && meta->meta_display) { + show_file(meta->meta_display, "Install notice:\n", + TRUE); + } + if (Flags & SHOW_PLIST) { + show_plist("Packing list:\n", &plist, PLIST_SHOW_ALL); + } + if ((Flags & SHOW_INSTALL) && meta->meta_install) { + show_file(meta->meta_install, "Install script:\n", + TRUE); + } + if ((Flags & SHOW_DEINSTALL) && meta->meta_deinstall) { + show_file(meta->meta_deinstall, "De-Install script:\n", + TRUE); + } + if ((Flags & SHOW_MTREE) && meta->meta_mtree) { + show_file(meta->meta_mtree, "mtree file:\n", TRUE); + } + if (Flags & SHOW_PREFIX) { + show_plist("Prefix(s):\n", &plist, PLIST_CWD); + } + if (Flags & SHOW_FILES) { + show_files("Files:\n", &plist); + } + if ((Flags & SHOW_BUILD_VERSION) && meta->meta_build_version) { + show_file(meta->meta_build_version, "Build version:\n", + TRUE); + } + if (Flags & SHOW_BUILD_INFO) { + if (meta->meta_build_info) { + show_file(meta->meta_build_info, "Build information:\n", + TRUE); + } + if (meta->meta_installed_info) { + show_file(meta->meta_installed_info, "Installed information:\n", + TRUE); + } + } + if ((Flags & SHOW_PKG_SIZE) && meta->meta_size_pkg) { + show_file(meta->meta_size_pkg, "Size of this package in bytes: ", + TRUE); + } + if ((Flags & SHOW_ALL_SIZE) && meta->meta_size_all) { + show_file(meta->meta_size_all, "Size in bytes including required pkgs: ", + TRUE); + } + if (!Quiet && !(Flags & SHOW_SUMMARY)) { + if (meta->meta_preserve) { + printf("*** PACKAGE MAY NOT BE DELETED ***\n\n"); + } + puts(InfoPrefix); + } + free_plist(&plist); + } + free_pkg_meta(meta); + return code; +} + +struct print_matching_arg { + const char *pattern; + int got_match; +}; + +static int +print_matching_pkg(const char *pkgname, void *cookie) +{ + struct print_matching_arg *arg= cookie; + + if (pkg_match(arg->pattern, pkgname)) { + if (!Quiet) + puts(pkgname); + arg->got_match = 1; + } + + return 0; +} + +/* + * Returns 0 if at least one package matching pkgname. + * Returns 1 otherwise. + * + * If -q was not specified, print all matching packages to stdout. + */ +int +CheckForPkg(const char *pkgname) +{ + struct print_matching_arg arg; + + arg.pattern = pkgname; + arg.got_match = 0; + + if (iterate_pkg_db(print_matching_pkg, &arg) == -1) { + warnx("cannot iterate pkgdb"); + return 1; + } + + if (arg.got_match == 0 && !ispkgpattern(pkgname)) { + char *pattern; + + pattern = xasprintf("%s-[0-9]*", pkgname); + + arg.pattern = pattern; + arg.got_match = 0; + + if (iterate_pkg_db(print_matching_pkg, &arg) == -1) { + free(pattern); + warnx("cannot iterate pkgdb"); + return 1; + } + free(pattern); + } + + if (arg.got_match) + return 0; + else + return 1; +} + +/* + * Returns 0 if at least one package matching pkgname. + * Returns 1 otherwise. + * + * If -q was not specified, print best match to stdout. + */ +int +CheckForBestPkg(const char *pkgname) +{ + char *pattern, *best_match; + + best_match = find_best_matching_installed_pkg(pkgname); + if (best_match == NULL) { + if (ispkgpattern(pkgname)) + return 1; + + pattern = xasprintf("%s-[0-9]*", pkgname); + best_match = find_best_matching_installed_pkg(pattern); + free(pattern); + } + + if (best_match == NULL) + return 1; + if (!Quiet) + puts(best_match); + free(best_match); + return 0; +} + +static int +perform_single_pkg(const char *pkg, void *cookie) +{ + int *err_cnt = cookie; + + if (Which == WHICH_ALL || !is_automatic_installed(pkg)) + *err_cnt += pkg_do(pkg); + + return 0; +} + +int +pkg_perform(lpkg_head_t *pkghead) +{ + int err_cnt = 0; + + TAILQ_INIT(&files); + + desired_meta_data = 0; + if ((Flags & (SHOW_INDEX | SHOW_BI_VAR)) == 0) + desired_meta_data |= LOAD_PRESERVE; + if ((Flags & (SHOW_INDEX | SHOW_BI_VAR)) == 0) + desired_meta_data |= LOAD_CONTENTS; + if (Flags & (SHOW_COMMENT | SHOW_INDEX | SHOW_SUMMARY)) + desired_meta_data |= LOAD_COMMENT; + if (Flags & (SHOW_BI_VAR | SHOW_BUILD_INFO | SHOW_SUMMARY)) + desired_meta_data |= LOAD_BUILD_INFO | LOAD_INSTALLED_INFO; + if (Flags & (SHOW_SUMMARY | SHOW_PKG_SIZE)) + desired_meta_data |= LOAD_SIZE_PKG; + if (Flags & SHOW_ALL_SIZE) + desired_meta_data |= LOAD_SIZE_ALL; + if (Flags & (SHOW_SUMMARY | SHOW_DESC)) + desired_meta_data |= LOAD_DESC; + if (Flags & (SHOW_REQBY | SHOW_FULL_REQBY)) + desired_meta_data |= LOAD_REQUIRED_BY; + if (Flags & SHOW_DISPLAY) + desired_meta_data |= LOAD_DISPLAY; + if (Flags & SHOW_INSTALL) + desired_meta_data |= LOAD_INSTALL; + if (Flags & SHOW_DEINSTALL) + desired_meta_data |= LOAD_DEINSTALL; + if (Flags & SHOW_MTREE) + desired_meta_data |= LOAD_MTREE; + if (Flags & SHOW_BUILD_VERSION) + desired_meta_data |= LOAD_BUILD_VERSION; + + if (Which != WHICH_LIST) { + if (File2Pkg) { + /* Show all files with the package they belong to */ + if (pkgdb_dump() == -1) + err_cnt = 1; + } else { + if (iterate_pkg_db(perform_single_pkg, &err_cnt) == -1) + err_cnt = 1; + } + } else { + /* Show info on individual pkg(s) */ + lpkg_t *lpp; + + while ((lpp = TAILQ_FIRST(pkghead)) != NULL) { + TAILQ_REMOVE(pkghead, lpp, lp_link); + err_cnt += pkg_do(lpp->lp_name); + free_lpkg(lpp); + } + } + return err_cnt; +} diff --git a/external/bsd/pkg_install/dist/info/pkg_info.1 b/external/bsd/pkg_install/dist/info/pkg_info.1 new file mode 100644 index 000000000..a00aaae55 --- /dev/null +++ b/external/bsd/pkg_install/dist/info/pkg_info.1 @@ -0,0 +1,349 @@ +.\" $NetBSD: pkg_info.1,v 1.1.1.6 2013/04/20 15:26:53 wiz Exp $ +.\" +.\" FreeBSD install - a package for the installation and maintenance +.\" of non-core utilities. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" Jordan K. Hubbard +.\" +.\" +.\" @(#)pkg_info.1 +.\" +.Dd December 14, 2012 +.Dt PKG_INFO 1 +.Os +.Sh NAME +.Nm pkg_info +.Nd a utility for displaying information on software packages +.Sh SYNOPSIS +.Nm +.Op Fl BbcDdFfhIikLmNnpqRrSsVvX +.Op Fl E Ar pkg-name +.Op Fl e Ar pkg-name +.Op Fl K Ar pkg_dbdir +.Op Fl l Ar prefix +.Ar pkg-name ... +.Nm +.Op Fl a | Fl u +.Op flags +.Nm +.Op Fl Q Ar variable +.Ar pkg-name ... +.Sh DESCRIPTION +The +.Nm +command is used to dump out information for packages, which may be either +packed up in files or already installed on the system with the +.Xr pkg_create 1 +command. +.Pp +The +.Ar pkg-name +may be the name of an installed package (with our without version), a +pattern matching several installed packages (see the +.Sx PACKAGE WILDCARDS +section for a description of possible patterns), +the pathname to a +binary package, a filename belonging to an installed +package (with +.Fl F ) , +or a URL to an FTP-available package. +.Pp +The following command line options are available: +.Bl -tag -width indent +.It Fl a +Show information for all currently installed packages. +See also +.Fl u . +When neither +.Fl a +nor +.Fl u +is given, the former is assumed. +.It Fl B +Show some of the important definitions used when building +the binary package (the +.Dq Build information ) +for each package. +Additionally, any installation information variables +(lowercase) can be queried, too. +In particular, +.Ar automatic +tells if a package was installed automatically +as a dependency of another package. +.It Fl b +Show the +.Nx +RCS Id strings from the files used in the construction +of the binary package (the +.Dq Build version ) +for each package. +These files are the package Makefile, any patch files, any checksum +files, and the packing list file. +.It Fl c +Show the one-line comment field for each package. +.It Fl D +Show the install-message file (if any) for each package. +.It Fl d +Show the long-description field for each package. +.It Fl E Ar pkg-name +This option +allows you to test for the existence of a given package. +If a package identified by +.Ar pkg-name +is currently installed, return code is 0, otherwise 1. +The name of the best matching package found installed is printed to +stdout unless turned off using the +.Fl q +option. +.Ar pkg-name +can contain wildcards (see the +.Sx PACKAGE WILDCARDS +section below). +.It Fl e Ar pkg-name +This option +allows you to test for the existence of a given package. +If a package identified by +.Ar pkg-name +is currently installed, return code is 0, otherwise 1. +The names of any package(s) found installed are printed to +stdout unless turned off using the +.Fl q +option. +.Ar pkg-name +can contain wildcards (see the +.Sx PACKAGE WILDCARDS +section below). +.It Fl F +Interpret any +.Ar pkg-name +given as filename, and query information on the package that +file belongs to. +This can be used to query information on a per-file basis. +See the +.Sx TECHNICAL DETAILS +section below for more information. +.It Fl f +Show the packing list instructions for each package. +.It Fl h +Print usage message and exit. +.It Fl I +Show the index entry for each package. +This option is assumed when no arguments or relevant flags are specified. +.It Fl i +Show the install script (if any) for each package. +.It Fl K Ar pkg_dbdir +Override the value of the +.Dv PKG_DBDIR +configuration option with the value +.Ar pkg_dbdir . +.It Fl k +Show the de-install script (if any) for each package. +.It Fl L +Show the files within each package. +This is different from just viewing the packing list, since full pathnames +for everything are generated. +Files that were created dynamically during installation of the package +are not listed. +.It Fl l Ar prefix +Prefix each information category header (see +.Fl q ) +shown with +.Ar prefix . +This is primarily of use to front-end programs that want to request a +lot of different information fields at once for a package, but don't +necessary want the output intermingled in such a way that they can't +organize it. +This lets you add a special token to the start of each field. +.It Fl m +Show the mtree file (if any) for each package. +.It Fl N +Show which packages each package was built with (exact dependencies), if any. +.It Fl n +Show which packages each package needs (depends upon), if any. +.It Fl p +Show the installation prefix for each package. +.It Fl Q Ar variable +Show the definition of +.Ar variable +from the build information for each package. +An empty string is returned if no such variable definition is found for +the package(s). +.It Fl q +Be +.Dq quiet +in emitting report headers and such, just dump the +raw info (basically, assume a non-human reading). +.It Fl R +For each package, show the packages that require it. +.It Fl r +For each package, show the packages that require it. +Continue recursively to show all dependents. +.It Fl S +Show the size of this package and all the packages it requires, +in bytes. +.It Fl s +Show the size of this package in bytes. +The size is calculated by adding up the size of each file of the package. +.It Fl u +Show information for all user-installed packages: +automatically installed packages (as dependencies +of other packages) are not displayed. +See also +.Fl a . +.It Fl V +Print version number and exit. +.It Fl v +Turn on verbose output. +.It Fl X +Print summary information for each package. +The summary format is +described in +.Xr pkg_summary 5 . +Its primary use is to contain all information about the contents of a +(remote) binary package repository needed by package managing software. +.El +.Sh TECHNICAL DETAILS +Package info is either extracted from package files named on the +command line, or from already installed package information +in +.Pa \*[Lt]PKG_DBDIR\*[Gt]/\*[Lt]pkg-name\*[Gt] . +.Pp +When the +.Fl F +option is used, +a filename can be given instead of a package name to query +information on the (installed) package that file belongs to. +The filename is resolved to a package name using the package database. +The filename must be absolute, as in the output of +.Dl pkg_info -aF . +For example, +.Dl pkg_info -eF /path/to/file +can be used to display the package the given file belongs to, and +.Dl pkg_info -LF /path/to/file +can be used to display all files belonging to the package the given +file belongs to. +.Sh PACKAGE WILDCARDS +In the places where a package name/version is expected, e.g., for the +.Fl e +option, several forms can be used. +Either use a package name with or without version, or specify a +package wildcard that gets matched against all installed packages. +.Pp +Package wildcards use +.Xr fnmatch 3 . +In addition, +.Xr csh 1 +style {,} alternates have been implemented. +Package version numbers can also be matched in a relational manner +using the +.Dq \*[Ge] , +.Dq \*[Le] , +.Dq \*[Gt] , +and +.Dq \*[Lt] +operators. +For example, +.Dl pkg_info -e 'name\*[Ge]1.3' +will match versions 1.3 and later of the +.Dq name +package. +(Make sure to use shell quoting.) +Additionally, ranges can be defined, by giving both a lower bound +.Po with +.Dq \*[Gt] +or +.Dq \*[Ge] +.Pc +as well as an upper bound +.Po with +.Dq \*[Lt] +or +. Dq \*[Le] +.Pc . +The lower bound has to come first. +For example, +.Dl pkg_info -e 'name\*[Ge]1.3\*[Lt]2.0' +will match versions 1.3 (inclusive) to 2.0 (exclusive) of package +.Dq name . +.Pp +The collating sequence of the various package version numbers is +unusual, but strives to be consistent. +The magic string +.Dq alpha +equates to +.Dq alpha version , +and sorts before a beta version. +The magic string +.Dq beta +equates to +.Dq beta version , +and sorts before a release candidate. +The magic string +.Dq rc +equates to +.Dq release candidate , +and sorts before a release. +The magic string +.Dq pre , +short for +.Dq pre-release , +is a synonym for +.Dq rc . +For example, +.Dq name-1.3alpha2 +will sort before +.Dq name-1.3beta1 , +and they both sort before +.Dq name-1.3rc1 . +Similarly, +.Dq name-1.3rc3 +will sort before +.Dq name-1.3 , +and after +.Dq name-1.2.9 . +The magic string +.Dq pl +equates to +.Dq patch level , +and has the same value as a dot +.Pq Sq \&. +in the dewey-decimal ordering schemes, +as does the underscore +.Pq Sq _ . +Additionally, alphabetic characters sort in the same place as +their numeric counterparts, so that +.Dq name-1.2e +has the same sorting value as +.Dq name-1.2.5 . +.Sh ENVIRONMENT +See +.Xr pkg_install.conf 5 +for options, that can also be specified using the environment. +.Sh SEE ALSO +.Xr pkg_add 1 , +.Xr pkg_admin 1 , +.Xr pkg_create 1 , +.Xr pkg_delete 1 , +.Xr pkg_install.conf 5 +.Xr pkgsrc 7 +.Sh AUTHORS +.Bl -tag -width indent -compact +.It "Jordan Hubbard" +most of the work +.It "John Kohl" +refined it for +.Nx +.It "Hubert Feyrer" +.Nx +wildcard dependency processing, pkgdb, depends displaying, +pkg size display, and more. +.El diff --git a/external/bsd/pkg_install/dist/info/show.c b/external/bsd/pkg_install/dist/info/show.c new file mode 100644 index 000000000..1b8d29e33 --- /dev/null +++ b/external/bsd/pkg_install/dist/info/show.c @@ -0,0 +1,430 @@ +/* $NetBSD: show.c,v 1.3 2012/02/21 18:36:16 wiz Exp $ */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: show.c,v 1.3 2012/02/21 18:36:16 wiz Exp $"); + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 23 Aug 1993 + * + * Various display routines for the info module. + * + */ +/*- + * Copyright (c) 1999-2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Hubert Feyrer . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#if HAVE_ERR_H +#include +#endif + +#include "defs.h" +#include "lib.h" +#include "info.h" + +/* Structure to define entries for the "show table" */ +typedef struct show_t { + pl_ent_t sh_type; /* type of entry */ + const char *sh_quiet; /* message when quiet */ + const char *sh_verbose; /* message when verbose */ +} show_t; + +/* + * The entries in this table must be ordered the same as + * pl_ent_t constants + */ +static const show_t showv[] = { + {PLIST_FILE, "", "\tFile: "}, + {PLIST_CWD, "@cwd ", "\tCWD to: "}, + {PLIST_CMD, "@exec ", "\tEXEC ''"}, + {PLIST_CHMOD, "@chmod ", "\tCHMOD to "}, + {PLIST_CHOWN, "@chown ", "\tCHOWN to "}, + {PLIST_CHGRP, "@chgrp ", "\tCHGRP to "}, + {PLIST_COMMENT, "@comment ", "\tComment: "}, + {PLIST_IGNORE, "@ignore", "Ignore next file:"}, + {PLIST_NAME, "@name ", "\tPackage name: "}, + {PLIST_UNEXEC, "@unexec ", "\tUNEXEC ''"}, + {PLIST_SRC, "@src: ", "\tSRC to: "}, + {PLIST_DISPLAY, "@display ", "\tInstall message file: "}, + {PLIST_PKGDEP, "@pkgdep ", "\tPackage depends on: "}, + {PLIST_DIR_RM, "@dirrm ", "\tObsolete deinstall directory removal hint: "}, + {PLIST_OPTION, "@option ", "\tPackage has option: "}, + {PLIST_PKGCFL, "@pkgcfl ", "\tPackage conflicts with: "}, + {PLIST_BLDDEP, "@blddep ", "\tPackage depends exactly on: "}, + {PLIST_PKGDIR, "@pkgdir ", "\tManaged directory: "}, + {-1, NULL, NULL} +}; + +static int print_string_as_var(const char *, const char *); + +void +show_file(const char *buf, const char *title, Boolean separator) +{ + size_t len; + + if (!Quiet) + printf("%s%s", InfoPrefix, title); + + len = strlen(buf); + if (len == 0 || buf[len - 1] != '\n') + puts(buf); + else + fputs(buf, stdout); + + if (!Quiet || separator) + printf("\n"); +} + +void +show_var(const char *buf, const char *variable) +{ + char *value; + + if (buf == NULL) + return; + + if ((value = var_get_memory(buf, variable)) != NULL) { + (void) printf("%s\n", value); + free(value); + } +} + +void +show_index(const char *buf, const char *title) +{ + size_t len; + + if (!Quiet) + printf("%s%s", InfoPrefix, title); + + len = strlen(buf); + if (len == 0 || buf[len - 1] != '\n') + puts(buf); + else + fputs(buf, stdout); +} + +/* + * Show a packing list item type. If type is PLIST_SHOW_ALL, show all + */ +void +show_plist(const char *title, package_t *plist, pl_ent_t type) +{ + plist_t *p; + Boolean ign; + + if (!Quiet) { + printf("%s%s", InfoPrefix, title); + } + for (ign = FALSE, p = plist->head; p; p = p->next) { + if (p->type == type || type == PLIST_SHOW_ALL) { + switch (p->type) { + case PLIST_FILE: + printf("%s%s", + Quiet ? showv[p->type].sh_quiet : + showv[p->type].sh_verbose, p->name); + if (ign) { + if (!Quiet) { + printf(" (ignored)"); + } + ign = FALSE; + } + break; + case PLIST_CHMOD: + case PLIST_CHOWN: + case PLIST_CHGRP: + printf("%s%s", + Quiet ? showv[p->type].sh_quiet : + showv[p->type].sh_verbose, + p->name ? p->name : "(clear default)"); + break; + case PLIST_IGNORE: + printf("%s", Quiet ? showv[p->type].sh_quiet : + showv[p->type].sh_verbose); + ign = TRUE; + break; + case PLIST_CWD: + case PLIST_CMD: + case PLIST_SRC: + case PLIST_UNEXEC: + case PLIST_COMMENT: + case PLIST_NAME: + case PLIST_DISPLAY: + case PLIST_PKGDEP: + case PLIST_DIR_RM: + case PLIST_OPTION: + case PLIST_PKGCFL: + case PLIST_BLDDEP: + case PLIST_PKGDIR: + printf("%s%s", + Quiet ? showv[p->type].sh_quiet : + showv[p->type].sh_verbose, + p->name ? p->name : "(null)"); + break; + default: + warnx("unknown command type %d (%s)", p->type, p->name); + } + (void) fputc('\n', stdout); + } + } +} + +/* + * Show all files in the packing list (except ignored ones) + */ +void +show_files(const char *title, package_t *plist) +{ + plist_t *p; + Boolean ign; + const char *dir = "."; + + if (!Quiet) { + printf("%s%s", InfoPrefix, title); + } + for (ign = FALSE, p = plist->head; p; p = p->next) { + switch (p->type) { + case PLIST_FILE: + if (!ign) { + printf("%s%s%s\n", dir, + (strcmp(dir, "/") == 0) ? "" : "/", p->name); + } + ign = FALSE; + break; + case PLIST_CWD: + dir = p->name; + break; + case PLIST_IGNORE: + ign = TRUE; + break; + default: + break; + } + } +} + +/* + * Show dependencies (packages this pkg requires) + */ +void +show_depends(const char *title, package_t *plist) +{ + plist_t *p; + int nodepends; + + nodepends = 1; + for (p = plist->head; p && nodepends; p = p->next) { + switch (p->type) { + case PLIST_PKGDEP: + nodepends = 0; + break; + default: + break; + } + } + if (nodepends) + return; + + if (!Quiet) { + printf("%s%s", InfoPrefix, title); + } + for (p = plist->head; p; p = p->next) { + switch (p->type) { + case PLIST_PKGDEP: + printf("%s\n", p->name); + break; + default: + break; + } + } + + printf("\n"); +} + +/* + * Show exact dependencies (packages this pkg was built with) + */ +void +show_bld_depends(const char *title, package_t *plist) +{ + plist_t *p; + int nodepends; + + nodepends = 1; + for (p = plist->head; p && nodepends; p = p->next) { + switch (p->type) { + case PLIST_BLDDEP: + nodepends = 0; + break; + default: + break; + } + } + if (nodepends) + return; + + if (!Quiet) { + printf("%s%s", InfoPrefix, title); + } + for (p = plist->head; p; p = p->next) { + switch (p->type) { + case PLIST_BLDDEP: + printf("%s\n", p->name); + break; + default: + break; + } + } + + printf("\n"); +} + + +/* + * Show entry for pkg_summary.txt file. + */ +void +show_summary(struct pkg_meta *meta, package_t *plist, const char *binpkgfile) +{ + static const char *bi_vars[] = { + "PKGPATH", + "CATEGORIES", + "PROVIDES", + "REQUIRES", + "PKG_OPTIONS", + "OPSYS", + "OS_VERSION", + "MACHINE_ARCH", + "LICENSE", + "HOMEPAGE", + "PKGTOOLS_VERSION", + "BUILD_DATE", + "PREV_PKGPATH", + "SUPERSEDES", + NULL + }; + + plist_t *p; + struct stat st; + + for (p = plist->head; p; p = p->next) { + switch (p->type) { + case PLIST_NAME: + printf("PKGNAME=%s\n", p->name); + break; + case PLIST_PKGDEP: + printf("DEPENDS=%s\n", p->name); + break; + case PLIST_PKGCFL: + printf("CONFLICTS=%s\n", p->name); + break; + + default: + break; + } + } + + print_string_as_var("COMMENT", meta->meta_comment); + if (meta->meta_size_pkg) + print_string_as_var("SIZE_PKG", meta->meta_size_pkg); + + if (meta->meta_build_info) + var_copy_list(meta->meta_build_info, bi_vars); + else + warnx("Build information missing"); + + if (binpkgfile != NULL && stat(binpkgfile, &st) == 0) { + const char *base; + + base = strrchr(binpkgfile, '/'); + if (base == NULL) + base = binpkgfile; + else + base++; + printf("FILE_NAME=%s\n", base); + printf("FILE_SIZE=%" MY_PRIu64 "\n", (uint64_t)st.st_size); + /* XXX: DIGETS */ + } + + print_string_as_var("DESCRIPTION", meta->meta_desc); + putc('\n', stdout); +} + +/* + * Print the contents of file fname as value of variable var to stdout. + */ +static int +print_string_as_var(const char *var, const char *str) +{ + const char *eol; + + while ((eol = strchr(str, '\n')) != NULL) { + printf("%s=%.*s\n", var, (int)(eol - str), str); + str = eol + 1; + } + if (*str) + printf("%s=%s\n", var, str); + + return 0; +} + +void +show_list(lpkg_head_t *pkghead, const char *title) +{ + lpkg_t *lpp; + + if (!Quiet) + printf("%s%s", InfoPrefix, title); + + while ((lpp = TAILQ_FIRST(pkghead)) != NULL) { + TAILQ_REMOVE(pkghead, lpp, lp_link); + puts(lpp->lp_name); + free_lpkg(lpp); + } + + if (!Quiet) + printf("\n"); +} diff --git a/external/bsd/pkg_install/dist/lib/automatic.c b/external/bsd/pkg_install/dist/lib/automatic.c new file mode 100644 index 000000000..5af338c64 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/automatic.c @@ -0,0 +1,105 @@ +/* $NetBSD: automatic.c,v 1.1.1.2 2009/02/02 20:44:05 joerg Exp $ */ + +/*- + * Copyright (c) 2005 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: automatic.c,v 1.1.1.2 2009/02/02 20:44:05 joerg Exp $"); + +#if HAVE_ASSERT_H +#include +#endif +#if HAVE_ERR_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif +#if HAVE_STRING_H +#include +#endif +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#include "lib.h" + +Boolean +is_automatic_installed(const char *pkg) +{ + char *filename, *value; + Boolean ret; + + assert(pkg[0] != '/'); + + filename = pkgdb_pkg_file(pkg, INSTALLED_INFO_FNAME); + + value = var_get(filename, AUTOMATIC_VARNAME); + + if (value && strcasecmp(value, "yes") == 0) + ret = TRUE; + else + ret = FALSE; + + free(value); + free(filename); + + return ret; +} + +int +mark_as_automatic_installed(const char *pkg, int value) +{ + char *filename; + int retval; + + assert(pkg[0] != '/'); + + filename = pkgdb_pkg_file(pkg, INSTALLED_INFO_FNAME); + + retval = var_set(filename, AUTOMATIC_VARNAME, value ? "yes" : NULL); + + free(filename); + + return retval; +} diff --git a/external/bsd/pkg_install/dist/lib/config.h.in b/external/bsd/pkg_install/dist/lib/config.h.in new file mode 100644 index 000000000..2c57ea336 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/config.h.in @@ -0,0 +1,196 @@ +/* lib/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#undef HAVE_ASSERT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_CTYPE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_DIRENT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERRNO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FNCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FNMATCH_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GLOB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GRP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `db' library (-ldb). */ +#undef HAVE_LIBDB + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PWD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SIGNAL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDARG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_CDEFS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_FILE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_QUEUE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UTSNAME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `vfork' function. */ +#undef HAVE_VFORK + +/* Define to 1 if you have the header file. */ +#undef HAVE_VIS_H + +/* Define to 1 if the `z' modifider for printf is missing. */ +#undef MISSING_SIZE_T_SUPPORT + +/* Defined when PRIu64 is missing or broken */ +#undef NEED_PRI_MACRO + +/* Defined when to retain only the numeric OS version */ +#undef NUMERIC_VERSION_ONLY + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* The size of `int', as computed by sizeof. */ +#undef SIZEOF_INT + +/* The size of `long', as computed by sizeof. */ +#undef SIZEOF_LONG + +/* The size of `long long', as computed by sizeof. */ +#undef SIZEOF_LONG_LONG + +/* The size of `size_t', as computed by sizeof. */ +#undef SIZEOF_SIZE_T + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT32_T + +/* Define for Solaris 2.5.1 so the uint64_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT64_T + +/* Define for Solaris 2.5.1 so the uint8_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT8_T + +/* Define to the type of an unsigned integer type of width exactly 16 bits if + such a type exists and the standard includes do not define it. */ +#undef uint16_t + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef uint32_t + +/* Define to the type of an unsigned integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +#undef uint64_t + +/* Define to the type of an unsigned integer type of width exactly 8 bits if + such a type exists and the standard includes do not define it. */ +#undef uint8_t + +#if !HAVE_VFORK +# define vfork fork +#endif + +#ifndef MISSING_SIZE_T_SUPPORT +# define PRIzu "zu" +#elif SIZEOF_SIZE_T == SIZEOF_INT +# define PRIzu "u" +#elif SIZEOF_SIZE_T == SIZEOF_LONG +# define PRIzu "lu" +#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG +# define PRIzu "llu" +#else +# errror "Unknown size_t size" +#endif + diff --git a/external/bsd/pkg_install/dist/lib/conflicts.c b/external/bsd/pkg_install/dist/lib/conflicts.c new file mode 100644 index 000000000..0ca0544b9 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/conflicts.c @@ -0,0 +1,166 @@ +/* $NetBSD: conflicts.c,v 1.1.1.4 2010/01/30 21:33:43 joerg Exp $ */ + +/*- + * Copyright (c) 2007 Roland Illig . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * XXX: Reading the +CONTENTS files of all installed packages is + * rather slow. Since this check is necessary to avoid conflicting + * packages, it should not be removed. + * + * TODO: Put all the information that is currently in the +CONTENTS + * files into one large file or another database. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#if HAVE_SYS_CDEFS_H +#include +#endif + +__RCSID("$NetBSD: conflicts.c,v 1.1.1.4 2010/01/30 21:33:43 joerg Exp $"); + +#if HAVE_ERR_H +#include +#endif + +#include "dewey.h" +#include "lib.h" + +/** + * Data structure to keep the intermediate result of the conflict + * search. ''pkgname'' is the package in question. The first + * installed package that conflicts is filled into + * ''conflicting_pkgname''. The pattern that leads to the conflict is + * also filled in to help the user in deciding what to do with the + * conflict. + */ +struct package_conflict { + const char *pkgname; + const char *skip_pkgname; + char **conflicting_pkgname; + char **conflicting_pattern; +}; + +static FILE * +fopen_contents(const char *pkgname, const char *mode) +{ + char *fname; + FILE *f; + + fname = pkgdb_pkg_file(pkgname, CONTENTS_FNAME); + f = fopen(fname, mode); + if (f == NULL) { + err(EXIT_FAILURE, "%s", fname); + /* NOTREACHED */ + } + free(fname); + return f; +} + + +static int +check_package_conflict(const char *pkgname, void *v) +{ + struct package_conflict *conflict = v; + package_t pkg; + plist_t *p; + FILE *f; + int rv; + + if (conflict->skip_pkgname != NULL && + strcmp(conflict->skip_pkgname, pkgname) == 0) + return 0; + + rv = 0; + + f = fopen_contents(pkgname, "r"); + read_plist(&pkg, f); + (void)fclose(f); + + for (p = pkg.head; p; p = p->next) { + if (p->type != PLIST_PKGCFL) + continue; + + if (pkg_match(p->name, conflict->pkgname) == 1) { + *(conflict->conflicting_pkgname) = xstrdup(pkgname); + *(conflict->conflicting_pattern) = xstrdup(p->name); + rv = 1 /* nonzero, stop iterating */; + break; + } + } + + free_plist(&pkg); + return rv; +} + +/** + * Checks if some installed package has a pkgcfl entry that matches + * PkgName. If such an entry is found, the package name is returned in + * inst_pkgname, the matching pattern in inst_pattern, and the function + * returns a non-zero value. Otherwise, zero is returned and the result + * variables are set to NULL. + */ +int +some_installed_package_conflicts_with(const char *pkgname, + const char *skip_pkgname, char **inst_pkgname, char **inst_pattern) +{ + struct package_conflict cfl; + int rv; + + cfl.pkgname = pkgname; + cfl.skip_pkgname = skip_pkgname; + *inst_pkgname = NULL; + *inst_pattern = NULL; + cfl.conflicting_pkgname = inst_pkgname; + cfl.conflicting_pattern = inst_pattern; + rv = iterate_pkg_db(check_package_conflict, &cfl); + if (rv == -1) { + errx(EXIT_FAILURE, "Couldn't read list of installed packages."); + /* NOTREACHED */ + } + return *inst_pkgname != NULL; +} + +#if 0 +int main(int argc, char **argv) +{ + char *pkg, *patt; + + if (some_installed_package_conflicts_with(argv[1], &pkg, &patt)) + printf("yes: package %s conflicts with %s, pattern %s\n", pkg, argv[1], patt); + else + printf("no\n"); + return 0; +} +#endif diff --git a/external/bsd/pkg_install/dist/lib/defs.h b/external/bsd/pkg_install/dist/lib/defs.h new file mode 100644 index 000000000..96fa75fb1 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/defs.h @@ -0,0 +1,75 @@ +/* $NetBSD: defs.h,v 1.3 2012/02/21 18:36:17 wiz Exp $ */ + +/*- + * Copyright (c) 1999,2000,2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Alistair Crooks (agc@NetBSD.org) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef DEFS_H_ +#define DEFS_H_ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_ERR_H +#include +#endif +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_STRING_H +#include +#endif + +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +/* + * Some systems such as OpenBSD-3.6 do not provide PRIu64. + * Others such as AIX-4.3.2 have a broken PRIu64 which includes + * a leading "%". + */ +#ifdef NEED_PRI_MACRO +# if SIZEOF_INT == 8 +# define MY_PRIu64 "u" +# elif SIZEOF_LONG == 8 +# define MY_PRIu64 "lu" +# elif SIZEOF_LONG_LONG == 8 +# define MY_PRIu64 "llu" +# else +# error "unable to find a suitable PRIu64" +# endif +#else +# define MY_PRIu64 PRIu64 +#endif + +#endif /* !DEFS_H_ */ diff --git a/external/bsd/pkg_install/dist/lib/dewey.c b/external/bsd/pkg_install/dist/lib/dewey.c new file mode 100644 index 000000000..8aafd0ab7 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/dewey.c @@ -0,0 +1,320 @@ +/* $NetBSD: dewey.c,v 1.3 2009/03/08 14:53:16 joerg Exp $ */ + +/* + * Copyright © 2002 Alistair G. Crooks. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include + +#if HAVE_CTYPE_H +#include +#endif +#if HAVE_STDLIB_H +#include +#endif + +#include "defs.h" +#include "dewey.h" + +#define PKG_PATTERN_MAX 1024 + +/* do not modify these values, or things will NOT work */ +enum { + Alpha = -3, + Beta = -2, + RC = -1, + Dot = 0, + Patch = 1 +}; + +/* this struct defines a version number */ +typedef struct arr_t { + unsigned c; /* # of version numbers */ + unsigned size; /* size of array */ + int *v; /* array of decimal numbers */ + int netbsd; /* any "nb" suffix */ +} arr_t; + +/* this struct describes a test */ +typedef struct test_t { + const char *s; /* string representation */ + unsigned len; /* length of string */ + int t; /* enumerated type of test */ +} test_t; + + +/* the tests that are recognised. */ + const test_t tests[] = { + { "<=", 2, DEWEY_LE }, + { "<", 1, DEWEY_LT }, + { ">=", 2, DEWEY_GE }, + { ">", 1, DEWEY_GT }, + { "==", 2, DEWEY_EQ }, + { "!=", 2, DEWEY_NE }, + { NULL, 0, 0 } +}; + + const test_t modifiers[] = { + { "alpha", 5, Alpha }, + { "beta", 4, Beta }, + { "pre", 3, RC }, + { "rc", 2, RC }, + { "pl", 2, Dot }, + { "_", 1, Dot }, + { ".", 1, Dot }, + { NULL, 0, 0 } +}; + + + +/* locate the test in the tests array */ +int +dewey_mktest(int *op, const char *test) +{ + const test_t *tp; + + for (tp = tests ; tp->s ; tp++) { + if (strncasecmp(test, tp->s, tp->len) == 0) { + *op = tp->t; + return tp->len; + } + } + return -1; +} + +/* + * make a component of a version number. + * '.' encodes as Dot which is '0' + * '_' encodes as 'patch level', or 'Dot', which is 0. + * 'pl' encodes as 'patch level', or 'Dot', which is 0. + * 'alpha' encodes as 'alpha version', or Alpha, which is -3. + * 'beta' encodes as 'beta version', or Beta, which is -2. + * 'rc' encodes as 'release candidate', or RC, which is -1. + * 'nb' encodes as 'netbsd version', which is used after all other tests + */ +static int +mkcomponent(arr_t *ap, const char *num) +{ + static const char alphas[] = "abcdefghijklmnopqrstuvwxyz"; + const test_t *modp; + int n; + const char *cp; + + if (ap->c == ap->size) { + if (ap->size == 0) { + ap->size = 62; + if ((ap->v = malloc(ap->size * sizeof(int))) == NULL) + err(EXIT_FAILURE, "mkver malloc failed"); + } else { + ap->size *= 2; + if ((ap->v = realloc(ap->v, ap->size * sizeof(int))) + == NULL) + err(EXIT_FAILURE, "mkver realloc failed"); + } + } + if (isdigit((unsigned char)*num)) { + for (cp = num, n = 0 ; isdigit((unsigned char)*num) ; num++) { + n = (n * 10) + (*num - '0'); + } + ap->v[ap->c++] = n; + return (int)(num - cp); + } + for (modp = modifiers ; modp->s ; modp++) { + if (strncasecmp(num, modp->s, modp->len) == 0) { + ap->v[ap->c++] = modp->t; + return modp->len; + } + } + if (strncasecmp(num, "nb", 2) == 0) { + for (cp = num, num += 2, n = 0 ; isdigit((unsigned char)*num) ; num++) { + n = (n * 10) + (*num - '0'); + } + ap->netbsd = n; + return (int)(num - cp); + } + if (isalpha((unsigned char)*num)) { + ap->v[ap->c++] = Dot; + cp = strchr(alphas, tolower((unsigned char)*num)); + if (ap->c == ap->size) { + ap->size *= 2; + if ((ap->v = realloc(ap->v, ap->size * sizeof(int))) == NULL) + err(EXIT_FAILURE, "mkver realloc failed"); + } + ap->v[ap->c++] = (int)(cp - alphas) + 1; + return 1; + } + return 1; +} + +/* make a version number string into an array of comparable ints */ +static int +mkversion(arr_t *ap, const char *num) +{ + ap->c = 0; + ap->size = 0; + ap->v = NULL; + ap->netbsd = 0; + + while (*num) { + num += mkcomponent(ap, num); + } + return 1; +} + +static void +freeversion(arr_t *ap) +{ + free(ap->v); + ap->v = NULL; + ap->c = 0; + ap->size = 0; +} + +#define DIGIT(v, c, n) (((n) < (c)) ? v[n] : 0) + +/* compare the result against the test we were expecting */ +static int +result(int cmp, int tst) +{ + switch(tst) { + case DEWEY_LT: + return cmp < 0; + case DEWEY_LE: + return cmp <= 0; + case DEWEY_GT: + return cmp > 0; + case DEWEY_GE: + return cmp >= 0; + case DEWEY_EQ: + return cmp == 0; + case DEWEY_NE: + return cmp != 0; + default: + return 0; + } +} + +/* do the test on the 2 vectors */ +static int +vtest(arr_t *lhs, int tst, arr_t *rhs) +{ + int cmp; + unsigned int c, i; + + for (i = 0, c = MAX(lhs->c, rhs->c) ; i < c ; i++) { + if ((cmp = DIGIT(lhs->v, lhs->c, i) - DIGIT(rhs->v, rhs->c, i)) != 0) { + return result(cmp, tst); + } + } + return result(lhs->netbsd - rhs->netbsd, tst); +} + +/* + * Compare two dewey decimal numbers + */ +int +dewey_cmp(const char *lhs, int op, const char *rhs) +{ + arr_t right; + arr_t left; + int retval; + + if (!mkversion(&left, lhs)) + return 0; + if (!mkversion(&right, rhs)) { + freeversion(&left); + return 0; + } + retval = vtest(&left, op, &right); + freeversion(&left); + freeversion(&right); + return retval; +} + +/* + * Perform dewey match on "pkg" against "pattern". + * Return 1 on match, 0 on non-match, -1 on error. + */ +int +dewey_match(const char *pattern, const char *pkg) +{ + const char *version; + const char *sep, *sep2; + int op, op2; + int n; + + /* compare names */ + if ((version=strrchr(pkg, '-')) == NULL) { + return 0; + } + if ((sep = strpbrk(pattern, "<>")) == NULL) + return -1; + /* compare name lengths */ + if ((sep-pattern != version-pkg) || + strncmp(pkg, pattern, (size_t)(version-pkg)) != 0) + return 0; + version++; + + /* extract comparison operator */ + if ((n = dewey_mktest(&op, sep)) < 0) { + return 0; + } + /* skip operator */ + sep += n; + + /* if greater than, look for less than */ + sep2 = NULL; + if (op == DEWEY_GT || op == DEWEY_GE) { + if ((sep2 = strchr(sep, '<')) != NULL) { + if ((n = dewey_mktest(&op2, sep2)) < 0) { + return 0; + } + /* compare upper limit */ + if (!dewey_cmp(version, op2, sep2+n)) + return 0; + } + } + + /* compare only pattern / lower limit */ + if (sep2) { + char ver[PKG_PATTERN_MAX]; + + strlcpy(ver, sep, MIN((ssize_t)sizeof(ver), sep2-sep+1)); + if (dewey_cmp(version, op, ver)) + return 1; + } + else { + if (dewey_cmp(version, op, sep)) + return 1; + } + + return 0; +} + diff --git a/external/bsd/pkg_install/dist/lib/dewey.h b/external/bsd/pkg_install/dist/lib/dewey.h new file mode 100644 index 000000000..a8a628e39 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/dewey.h @@ -0,0 +1,19 @@ +/* $NetBSD: dewey.h,v 1.1.1.1 2008/09/30 19:00:27 joerg Exp $ */ + +#ifndef _INST_LIB_DEWEY_H_ +#define _INST_LIB_DEWEY_H_ + +int dewey_cmp(const char *, int, const char *); +int dewey_match(const char *, const char *); +int dewey_mktest(int *, const char *); + +enum { + DEWEY_LT, + DEWEY_LE, + DEWEY_EQ, + DEWEY_GE, + DEWEY_GT, + DEWEY_NE +}; + +#endif /* _INST_LIB_DEWEY_H_ */ diff --git a/external/bsd/pkg_install/dist/lib/fexec.c b/external/bsd/pkg_install/dist/lib/fexec.c new file mode 100644 index 000000000..af44eed2b --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/fexec.c @@ -0,0 +1,167 @@ +/* $NetBSD: fexec.c,v 1.1.1.3 2009/08/06 16:55:26 joerg Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Matthias Scheler. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +#if HAVE_SYS_WAIT_H +#include +#endif + +#if HAVE_ERR_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_STDARG_H +#include +#endif +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif + +#include "lib.h" + +__RCSID("$NetBSD: fexec.c,v 1.1.1.3 2009/08/06 16:55:26 joerg Exp $"); + +static int vfcexec(const char *, int, const char *, va_list); + +/* + * fork, then change current working directory to path and + * execute the command and arguments in the argv array. + * wait for the command to finish, then return the exit status. + */ +int +pfcexec(const char *path, const char *file, const char **argv) +{ + pid_t child; + int status; + + child = vfork(); + switch (child) { + case 0: + if ((path != NULL) && (chdir(path) < 0)) + _exit(127); + + (void)execvp(file, __UNCONST(argv)); + _exit(127); + /* NOTREACHED */ + case -1: + return -1; + } + + while (waitpid(child, &status, 0) < 0) { + if (errno != EINTR) + return -1; + } + + if (!WIFEXITED(status)) + return -1; + + return WEXITSTATUS(status); +} + +static int +vfcexec(const char *path, int skipempty, const char *arg, va_list ap) +{ + const char **argv; + size_t argv_size, argc; + int retval; + + argv_size = 16; + argv = xcalloc(argv_size, sizeof(*argv)); + + argv[0] = arg; + argc = 1; + + do { + if (argc == argv_size) { + argv_size *= 2; + argv = xrealloc(argv, argv_size * sizeof(*argv)); + } + arg = va_arg(ap, const char *); + if (skipempty && arg && strlen(arg) == 0) + continue; + argv[argc++] = arg; + } while (arg != NULL); + + retval = pfcexec(path, argv[0], argv); + free(argv); + return retval; +} + +int +fexec(const char *arg, ...) +{ + va_list ap; + int result; + + va_start(ap, arg); + result = vfcexec(NULL, 0, arg, ap); + va_end(ap); + + return result; +} + +int +fexec_skipempty(const char *arg, ...) +{ + va_list ap; + int result; + + va_start(ap, arg); + result = vfcexec(NULL, 1, arg, ap); + va_end(ap); + + return result; +} + +int +fcexec(const char *path, const char *arg, ...) +{ + va_list ap; + int result; + + va_start(ap, arg); + result = vfcexec(path, 0, arg, ap); + va_end(ap); + + return result; +} diff --git a/external/bsd/pkg_install/dist/lib/file.c b/external/bsd/pkg_install/dist/lib/file.c new file mode 100644 index 000000000..a16f0374b --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/file.c @@ -0,0 +1,374 @@ +/* $NetBSD: file.c,v 1.1.1.6 2011/02/18 22:32:30 aymeric Exp $ */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +#if HAVE_SYS_PARAM_H +#include +#endif +#if HAVE_SYS_QUEUE_H +#include +#endif +__RCSID("$NetBSD: file.c,v 1.1.1.6 2011/02/18 22:32:30 aymeric Exp $"); + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Miscellaneous file access utilities. + * + */ + +#include "lib.h" + +#if HAVE_SYS_WAIT_H +#include +#endif + +#if HAVE_ASSERT_H +#include +#endif +#if HAVE_ERR_H +#include +#endif +#if HAVE_GLOB_H +#include +#endif +#if HAVE_PWD_H +#include +#endif +#if HAVE_TIME_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif + + +/* + * Quick check to see if a file (or dir ...) exists + */ +Boolean +fexists(const char *fname) +{ + struct stat dummy; + if (!lstat(fname, &dummy)) + return TRUE; + return FALSE; +} + +/* + * Quick check to see if something is a directory + */ +Boolean +isdir(const char *fname) +{ + struct stat sb; + + if (lstat(fname, &sb) != FAIL && S_ISDIR(sb.st_mode)) + return TRUE; + else + return FALSE; +} + +/* + * Check if something is a link to a directory + */ +Boolean +islinktodir(const char *fname) +{ + struct stat sb; + + if (lstat(fname, &sb) != FAIL && S_ISLNK(sb.st_mode)) { + if (stat(fname, &sb) != FAIL && S_ISDIR(sb.st_mode)) + return TRUE; /* link to dir! */ + else + return FALSE; /* link to non-dir */ + } else + return FALSE; /* non-link */ +} + +/* + * Check if something is a link that points to nonexistant target. + */ +Boolean +isbrokenlink(const char *fname) +{ + struct stat sb; + + if (lstat(fname, &sb) != FAIL && S_ISLNK(sb.st_mode)) { + if (stat(fname, &sb) != FAIL) + return FALSE; /* link target exists! */ + else + return TRUE; /* link target missing*/ + } else + return FALSE; /* non-link */ +} + +/* + * Check to see if file is a dir, and is empty + */ +Boolean +isemptydir(const char *fname) +{ + if (isdir(fname) || islinktodir(fname)) { + DIR *dirp; + struct dirent *dp; + + dirp = opendir(fname); + if (!dirp) + return FALSE; /* no perms, leave it alone */ + for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { + if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, "..")) { + closedir(dirp); + return FALSE; + } + } + (void) closedir(dirp); + return TRUE; + } + return FALSE; +} + +/* + * Check if something is a regular file + */ +Boolean +isfile(const char *fname) +{ + struct stat sb; + if (stat(fname, &sb) != FAIL && S_ISREG(sb.st_mode)) + return TRUE; + return FALSE; +} + +/* + * Check to see if file is a file and is empty. If nonexistent or not + * a file, say "it's empty", otherwise return TRUE if zero sized. + */ +Boolean +isemptyfile(const char *fname) +{ + struct stat sb; + if (stat(fname, &sb) != FAIL && S_ISREG(sb.st_mode)) { + if (sb.st_size != 0) + return FALSE; + } + return TRUE; +} + +/* This struct defines the leading part of a valid URL name */ +typedef struct url_t { + const char *u_s; /* the leading part of the URL */ + int u_len; /* its length */ +} url_t; + +/* A table of valid leading strings for URLs */ +static const url_t urls[] = { +#define STR_AND_SIZE(str) { str, sizeof(str) - 1 } + STR_AND_SIZE("file://"), + STR_AND_SIZE("ftp://"), + STR_AND_SIZE("http://"), + STR_AND_SIZE("https://"), +#undef STR_AND_SIZE + {NULL, 0} +}; + +/* + * Returns length of leading part of any URL from urls table, or -1 + */ +int +URLlength(const char *fname) +{ + const url_t *up; + int i; + + if (fname != (char *) NULL) { + for (i = 0; isspace((unsigned char) *fname); i++) { + fname++; + } + for (up = urls; up->u_s; up++) { + if (strncmp(fname, up->u_s, up->u_len) == 0) { + return i + up->u_len; /* ... + sizeof(up->u_s); - HF */ + } + } + } + return -1; +} + +/* + * Takes a filename and package name, returning (in "try") the canonical + * "preserve" name for it. + */ +Boolean +make_preserve_name(char *try, size_t max, const char *name, const char *file) +{ + size_t len, i; + + if ((len = strlen(file)) == 0) + return FALSE; + i = len - 1; + strncpy(try, file, max); + if (try[i] == '/') /* Catch trailing slash early and save checking in the loop */ + --i; + for (; i; i--) { + if (try[i] == '/') { + try[i + 1] = '.'; + strncpy(&try[i + 2], &file[i + 1], max - i - 2); + break; + } + } + if (!i) { + try[0] = '.'; + strncpy(try + 1, file, max - 1); + } + /* I should probably be called rude names for these inline assignments */ + strncat(try, ".", max -= strlen(try)); + strncat(try, name, max -= strlen(name)); + strncat(try, ".", max--); + strncat(try, "backup", max -= 6); + return TRUE; +} + +void +remove_files(const char *path, const char *pattern) +{ + char fpath[MaxPathSize]; + glob_t globbed; + int i; + size_t j; + + (void) snprintf(fpath, sizeof(fpath), "%s/%s", path, pattern); + if ((i=glob(fpath, GLOB_NOSORT, NULL, &globbed)) != 0) { + switch(i) { + case GLOB_NOMATCH: + warn("no files matching ``%s'' found", fpath); + break; + case GLOB_ABORTED: + warn("globbing aborted"); + break; + case GLOB_NOSPACE: + warn("out-of-memory during globbing"); + break; + default: + warn("unknown error during globbing"); + break; + } + return; + } + + /* deleting globbed files */ + for (j = 0; j < globbed.gl_pathc; j++) + if (unlink(globbed.gl_pathv[j]) < 0) + warn("can't delete ``%s''", globbed.gl_pathv[j]); + + return; +} + +/* + * Using fmt, replace all instances of: + * + * %F With the parameter "name" + * %D With the parameter "dir" + * %B Return the directory part ("base") of %D/%F + * %f Return the filename part of %D/%F + * + * Check that no overflows can occur. + */ +int +format_cmd(char *buf, size_t size, const char *fmt, const char *dir, const char *name) +{ + size_t remaining, quoted; + char *bufp, *tmp; + char *cp; + + for (bufp = buf, remaining = size; remaining > 1 && *fmt;) { + if (*fmt != '%') { + *bufp++ = *fmt++; + --remaining; + continue; + } + + if (*++fmt != 'D' && name == NULL) { + warnx("no last file available for '%s' command", buf); + return -1; + } + switch (*fmt) { + case 'F': + quoted = shquote(name, bufp, remaining); + if (quoted >= remaining) { + warnx("overflow during quoting"); + return -1; + } + bufp += quoted; + remaining -= quoted; + break; + + case 'D': + quoted = shquote(dir, bufp, remaining); + if (quoted >= remaining) { + warnx("overflow during quoting"); + return -1; + } + bufp += quoted; + remaining -= quoted; + break; + + case 'B': + tmp = xasprintf("%s/%s", dir, name); + cp = strrchr(tmp, '/'); + *cp = '\0'; + quoted = shquote(tmp, bufp, remaining); + free(tmp); + if (quoted >= remaining) { + warnx("overflow during quoting"); + return -1; + } + bufp += quoted; + remaining -= quoted; + break; + + case 'f': + tmp = xasprintf("%s/%s", dir, name); + cp = strrchr(tmp, '/') + 1; + quoted = shquote(cp, bufp, remaining); + free(tmp); + if (quoted >= remaining) { + warnx("overflow during quoting"); + return -1; + } + bufp += quoted; + remaining -= quoted; + break; + + default: + if (remaining == 1) { + warnx("overflow during quoting"); + return -1; + } + *bufp++ = '%'; + *bufp++ = *fmt; + remaining -= 2; + break; + } + ++fmt; + } + *bufp = '\0'; + return 0; +} diff --git a/external/bsd/pkg_install/dist/lib/global.c b/external/bsd/pkg_install/dist/lib/global.c new file mode 100644 index 000000000..27cd4f334 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/global.c @@ -0,0 +1,38 @@ +/* $NetBSD: global.c,v 1.1.1.2 2009/02/02 20:44:06 joerg Exp $ */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: global.c,v 1.1.1.2 2009/02/02 20:44:06 joerg Exp $"); + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + + * 18 July 1993 + * + * Semi-convenient place to stick some needed globals. + * + */ + +#include "lib.h" + +/* These are global for all utils */ +Boolean Verbose = FALSE; +Boolean Fake = FALSE; +Boolean Force = FALSE; diff --git a/external/bsd/pkg_install/dist/lib/gpgsig.c b/external/bsd/pkg_install/dist/lib/gpgsig.c new file mode 100644 index 000000000..8091d4a12 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/gpgsig.c @@ -0,0 +1,248 @@ +/* $NetBSD: gpgsig.c,v 1.1.1.2 2009/08/06 16:55:27 joerg Exp $ */ +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif + +__RCSID("$NetBSD: gpgsig.c,v 1.1.1.2 2009/08/06 16:55:27 joerg Exp $"); + +/*- + * Copyright (c) 2008 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef NETBSD +#include +#else +#include +#endif +#ifndef NETBSD +#include +#else +#include +#endif + +#include "lib.h" + +static void +verify_signature(const char *input, size_t input_len, const char *keyring, + const char *detached_signature) +{ + const char *argv[8], **argvp; + pid_t child; + int fd[2], status; + + if (pipe(fd) == -1) + err(EXIT_FAILURE, "cannot create input pipes"); + + child = vfork(); + if (child == -1) + err(EXIT_FAILURE, "cannot fork GPG process"); + if (child == 0) { + close(fd[1]); + close(STDIN_FILENO); + if (dup2(fd[0], STDIN_FILENO) == -1) { + static const char err_msg[] = + "cannot redirect stdin of GPG process\n"; + write(STDERR_FILENO, err_msg, sizeof(err_msg) - 1); + _exit(255); + } + close(fd[0]); + argvp = argv; + *argvp++ = gpg_cmd; + *argvp++ = "--verify"; + if (keyring != NULL) { + *argvp++ = "--no-default-keyring"; + *argvp++ = "--keyring"; + *argvp++ = keyring; + } + + if (detached_signature != NULL) + *argvp++ = detached_signature; + *argvp++ = "-"; + + *argvp = NULL; + + execvp(gpg_cmd, __UNCONST(argv)); + _exit(255); + } + close(fd[0]); + if (write(fd[1], input, input_len) != (ssize_t)input_len) + errx(EXIT_FAILURE, "Short read from GPG"); + close(fd[1]); + waitpid(child, &status, 0); + if (status) + errx(EXIT_FAILURE, "GPG could not verify the signature"); +} + +int +inline_gpg_verify(const char *content, size_t len, const char *keyring) +{ + verify_signature(content, len, keyring, NULL); + + return 0; +} + +int +detached_gpg_verify(const char *content, size_t len, + const char *signature, size_t signature_len, const char *keyring) +{ + int fd; + const char *tmpdir; + char *tempsig; + ssize_t ret; + + if (gpg_cmd == NULL) { + warnx("GPG variable not set, failing signature check"); + return -1; + } + + if ((tmpdir = getenv("TMPDIR")) == NULL) + tmpdir = "/tmp"; + tempsig = xasprintf("%s/pkg_install.XXXXXX", tmpdir); + + fd = mkstemp(tempsig); + if (fd == -1) { + warnx("Creating temporary file for GPG signature failed"); + return -1; + } + + while (signature_len) { + ret = write(fd, signature, signature_len); + if (ret == -1) + err(EXIT_FAILURE, "Write to GPG failed"); + if (ret == 0) + errx(EXIT_FAILURE, "Short write to GPG"); + signature_len -= ret; + signature += ret; + } + + verify_signature(content, len, keyring, tempsig); + + unlink(tempsig); + close(fd); + free(tempsig); + + return 0; +} + +int +detached_gpg_sign(const char *content, size_t len, char **sig, size_t *sig_len, + const char *keyring, const char *user) +{ + const char *argv[12], **argvp; + pid_t child; + int fd_in[2], fd_out[2], status; + size_t allocated; + ssize_t ret; + + if (gpg_cmd == NULL) + errx(EXIT_FAILURE, "GPG variable not set"); + + if (pipe(fd_in) == -1) + err(EXIT_FAILURE, "cannot create input pipes"); + if (pipe(fd_out) == -1) + err(EXIT_FAILURE, "cannot create output pipes"); + + child = fork(); + if (child == -1) + err(EXIT_FAILURE, "cannot fork GPG process"); + if (child == 0) { + close(fd_in[1]); + close(STDIN_FILENO); + if (dup2(fd_in[0], STDIN_FILENO) == -1) { + static const char err_msg[] = + "cannot redirect stdin of GPG process\n"; + write(STDERR_FILENO, err_msg, sizeof(err_msg) - 1); + _exit(255); + } + close(fd_in[0]); + + close(fd_out[0]); + close(STDOUT_FILENO); + if (dup2(fd_out[1], STDOUT_FILENO) == -1) { + static const char err_msg[] = + "cannot redirect stdout of GPG process\n"; + write(STDERR_FILENO, err_msg, sizeof(err_msg) - 1); + _exit(255); + } + close(fd_out[1]); + + argvp = argv; + *argvp++ = gpg_cmd; + *argvp++ = "--detach-sign"; + *argvp++ = "--armor"; + *argvp++ = "--output"; + *argvp++ = "-"; + if (user != NULL) { + *argvp++ = "--local-user"; + *argvp++ = user; + } + if (keyring != NULL) { + *argvp++ = "--no-default-keyring"; + *argvp++ = "--secret-keyring"; + *argvp++ = keyring; + } + + *argvp++ = "-"; + *argvp = NULL; + + execvp(gpg_cmd, __UNCONST(argv)); + _exit(255); + } + close(fd_in[0]); + if (write(fd_in[1], content, len) != (ssize_t)len) + errx(EXIT_FAILURE, "Short read from GPG"); + close(fd_in[1]); + + allocated = 1024; + *sig = xmalloc(allocated); + *sig_len = 0; + + close(fd_out[1]); + + while ((ret = read(fd_out[0], *sig + *sig_len, + allocated - *sig_len)) > 0) { + *sig_len += ret; + if (*sig_len == allocated) { + allocated *= 2; + *sig = xrealloc(*sig, allocated); + } + } + + close(fd_out[0]); + + waitpid(child, &status, 0); + if (status) + errx(EXIT_FAILURE, "GPG could not create signature"); + + return 0; +} diff --git a/external/bsd/pkg_install/dist/lib/iterate.c b/external/bsd/pkg_install/dist/lib/iterate.c new file mode 100644 index 000000000..080dbf760 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/iterate.c @@ -0,0 +1,485 @@ +/* $NetBSD: iterate.c,v 1.1.1.4 2010/01/30 21:33:47 joerg Exp $ */ + +/*- + * Copyright (c) 2007 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#if HAVE_ERR_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif + +#include "lib.h" + +/* + * Generic iteration function: + * - get new entries from srciter, stop on NULL + * - call matchiter for those entries, stop on non-null return value. + */ +int +iterate_pkg_generic_src(int (*matchiter)(const char *, void *), + void *match_cookie, const char *(*srciter)(void *), void *src_cookie) +{ + int retval; + const char *entry; + + retval = 0; + + while ((entry = (*srciter)(src_cookie)) != NULL) { + if ((retval = (*matchiter)(entry, match_cookie)) != 0) + break; + } + + return retval; +} + +struct pkg_dir_iter_arg { + DIR *dirp; + int filter_suffix; + int allow_nonfiles; +}; + +static const char * +pkg_dir_iter(void *cookie) +{ + struct pkg_dir_iter_arg *arg = cookie; + struct dirent *dp; + size_t len; + + while ((dp = readdir(arg->dirp)) != NULL) { +#if defined(DT_UNKNOWN) && defined(DT_DIR) + if (arg->allow_nonfiles == 0 && + dp->d_type != DT_UNKNOWN && dp->d_type != DT_REG) + continue; +#endif + len = strlen(dp->d_name); + /* .tbz or .tgz suffix length + some prefix*/ + if (len < 5) + continue; + if (arg->filter_suffix == 0 || + memcmp(dp->d_name + len - 4, ".tgz", 4) == 0 || + memcmp(dp->d_name + len - 4, ".tbz", 4) == 0) + return dp->d_name; + } + return NULL; +} + +/* + * Call matchiter for every package in the directory. + */ +int +iterate_local_pkg_dir(const char *dir, int filter_suffix, int allow_nonfiles, + int (*matchiter)(const char *, void *), void *cookie) +{ + struct pkg_dir_iter_arg arg; + int retval; + + if ((arg.dirp = opendir(dir)) == NULL) + return -1; + + arg.filter_suffix = filter_suffix; + arg.allow_nonfiles = allow_nonfiles; + retval = iterate_pkg_generic_src(matchiter, cookie, pkg_dir_iter, &arg); + + if (closedir(arg.dirp) == -1) + return -1; + return retval; +} + +static const char * +pkg_db_iter(void *cookie) +{ + DIR *dirp = cookie; + struct dirent *dp; + + while ((dp = readdir(dirp)) != NULL) { + if (strcmp(dp->d_name, ".") == 0) + continue; + if (strcmp(dp->d_name, "..") == 0) + continue; + if (strcmp(dp->d_name, "pkgdb.byfile.db") == 0) + continue; + if (strcmp(dp->d_name, ".cookie") == 0) + continue; + if (strcmp(dp->d_name, "pkg-vulnerabilities") == 0) + continue; +#if defined(DT_UNKNOWN) && defined(DT_DIR) + if (dp->d_type != DT_UNKNOWN && dp->d_type != DT_DIR) + continue; +#endif + return dp->d_name; + } + return NULL; +} + +/* + * Call matchiter for every installed package. + */ +int +iterate_pkg_db(int (*matchiter)(const char *, void *), void *cookie) +{ + DIR *dirp; + int retval; + + if ((dirp = opendir(pkgdb_get_dir())) == NULL) { + if (errno == ENOENT) + return 0; /* No pkgdb directory == empty pkgdb */ + return -1; + } + + retval = iterate_pkg_generic_src(matchiter, cookie, pkg_db_iter, dirp); + + if (closedir(dirp) == -1) + return -1; + return retval; +} + +static int +match_by_basename(const char *pkg, void *cookie) +{ + const char *target = cookie; + const char *pkg_version; + + if ((pkg_version = strrchr(pkg, '-')) == NULL) { + warnx("Entry %s in pkgdb is not a valid package name", pkg); + return 0; + } + if (strncmp(pkg, target, pkg_version - pkg) == 0 && + pkg + strlen(target) == pkg_version) + return 1; + else + return 0; +} + +static int +match_by_pattern(const char *pkg, void *cookie) +{ + const char *pattern = cookie; + + return pkg_match(pattern, pkg); +} + +struct add_matching_arg { + lpkg_head_t *pkghead; + int got_match; + int (*match_fn)(const char *pkg, void *cookie); + void *cookie; +}; + +static int +match_and_add(const char *pkg, void *cookie) +{ + struct add_matching_arg *arg = cookie; + lpkg_t *lpp; + + if ((*arg->match_fn)(pkg, arg->cookie) == 1) { + arg->got_match = 1; + + lpp = alloc_lpkg(pkg); + TAILQ_INSERT_TAIL(arg->pkghead, lpp, lp_link); + } + return 0; +} + +/* + * Find all installed packages with the given basename and add them + * to pkghead. + * Returns -1 on error, 0 if no match was found and 1 otherwise. + */ +int +add_installed_pkgs_by_basename(const char *pkgbase, lpkg_head_t *pkghead) +{ + struct add_matching_arg arg; + + arg.pkghead = pkghead; + arg.got_match = 0; + arg.match_fn = match_by_basename; + arg.cookie = __UNCONST(pkgbase); + + if (iterate_pkg_db(match_and_add, &arg) == -1) { + warnx("could not process pkgdb"); + return -1; + } + return arg.got_match; +} + +/* + * Match all installed packages against pattern, add the matches to pkghead. + * Returns -1 on error, 0 if no match was found and 1 otherwise. + */ +int +add_installed_pkgs_by_pattern(const char *pattern, lpkg_head_t *pkghead) +{ + struct add_matching_arg arg; + + arg.pkghead = pkghead; + arg.got_match = 0; + arg.match_fn = match_by_pattern; + arg.cookie = __UNCONST(pattern); + + if (iterate_pkg_db(match_and_add, &arg) == -1) { + warnx("could not process pkgdb"); + return -1; + } + return arg.got_match; +} + +struct best_installed_match_arg { + const char *pattern; + char *best_current_match; +}; + +static int +match_best_installed(const char *pkg, void *cookie) +{ + struct best_installed_match_arg *arg = cookie; + + switch (pkg_order(arg->pattern, pkg, arg->best_current_match)) { + case 0: + case 2: + /* + * Either current package doesn't match or + * the older match is better. Nothing to do. + */ + break; + case 1: + /* Current package is better, remember it. */ + free(arg->best_current_match); + arg->best_current_match = xstrdup(pkg); + break; + } + return 0; +} + +/* + * Returns a copy of the name of best matching package. + * If no package matched the pattern or an error occured, return NULL. + */ +char * +find_best_matching_installed_pkg(const char *pattern) +{ + struct best_installed_match_arg arg; + + arg.pattern = pattern; + arg.best_current_match = NULL; + + if (iterate_pkg_db(match_best_installed, &arg) == -1) { + warnx("could not process pkgdb"); + return NULL; + } + + return arg.best_current_match; +} + +struct call_matching_arg { + const char *pattern; + int (*call_fn)(const char *pkg, void *cookie); + void *cookie; +}; + +static int +match_and_call(const char *pkg, void *cookie) +{ + struct call_matching_arg *arg = cookie; + + if (pkg_match(arg->pattern, pkg) == 1) { + return (*arg->call_fn)(pkg, arg->cookie); + } else + return 0; +} + +/* + * Find all packages that match the given pattern and call the function + * for each of them. Iteration stops if the callback return non-0. + * Returns -1 on error, 0 if the iteration finished or whatever the + * callback returned otherwise. + */ +int +match_installed_pkgs(const char *pattern, int (*cb)(const char *, void *), + void *cookie) +{ + struct call_matching_arg arg; + + arg.pattern = pattern; + arg.call_fn = cb; + arg.cookie = cookie; + + return iterate_pkg_db(match_and_call, &arg); +} + +struct best_file_match_arg { + const char *pattern; + char *best_current_match_filtered; + char *best_current_match; + int filter_suffix; +}; + +static int +match_best_file(const char *filename, void *cookie) +{ + struct best_file_match_arg *arg = cookie; + const char *active_filename; + char *filtered_filename; + + if (arg->filter_suffix) { + size_t len; + + len = strlen(filename); + if (len < 5 || + (memcmp(filename + len - 4, ".tgz", 4) != 0 && + memcmp(filename + len - 4, ".tbz", 4) != 0)) { + warnx("filename %s does not contain a recognized suffix", filename); + return -1; + } + filtered_filename = xmalloc(len - 4 + 1); + memcpy(filtered_filename, filename, len - 4); + filtered_filename[len - 4] = '\0'; + active_filename = filtered_filename; + } else { + filtered_filename = NULL; + active_filename = filename; + } + + switch (pkg_order(arg->pattern, active_filename, arg->best_current_match_filtered)) { + case 0: + case 2: + /* + * Either current package doesn't match or + * the older match is better. Nothing to do. + */ + free(filtered_filename); + return 0; + case 1: + /* Current package is better, remember it. */ + free(arg->best_current_match); + free(arg->best_current_match_filtered); + arg->best_current_match = xstrdup(filename); + if (filtered_filename != NULL) + arg->best_current_match_filtered = filtered_filename; + else + arg->best_current_match_filtered = xstrdup(active_filename); + return 0; + default: + errx(EXIT_FAILURE, "Invalid error from pkg_order"); + /* NOTREACHED */ + } +} + +/* + * Returns a copy of the name of best matching file. + * If no package matched the pattern or an error occured, return NULL. + */ +char * +find_best_matching_file(const char *dir, const char *pattern, int filter_suffix, int allow_nonfiles) +{ + struct best_file_match_arg arg; + + arg.filter_suffix = filter_suffix; + arg.pattern = pattern; + arg.best_current_match = NULL; + arg.best_current_match_filtered = NULL; + + if (iterate_local_pkg_dir(dir, filter_suffix, allow_nonfiles, match_best_file, &arg) == -1) { + warnx("could not process directory"); + return NULL; + } + free(arg.best_current_match_filtered); + + return arg.best_current_match; +} + +struct call_matching_file_arg { + const char *pattern; + int (*call_fn)(const char *pkg, void *cookie); + void *cookie; + int filter_suffix; +}; + +static int +match_file_and_call(const char *filename, void *cookie) +{ + struct call_matching_file_arg *arg = cookie; + const char *active_filename; + char *filtered_filename; + int ret; + + if (arg->filter_suffix) { + size_t len; + + len = strlen(filename); + if (len < 5 || + (memcmp(filename + len - 4, ".tgz", 4) != 0 && + memcmp(filename + len - 4, ".tbz", 4) != 0)) { + warnx("filename %s does not contain a recognized suffix", filename); + return -1; + } + filtered_filename = xmalloc(len - 4 + 1); + memcpy(filtered_filename, filename, len - 4); + filtered_filename[len - 4] = '\0'; + active_filename = filtered_filename; + } else { + filtered_filename = NULL; + active_filename = filename; + } + + ret = pkg_match(arg->pattern, active_filename); + free(filtered_filename); + + if (ret == 1) + return (*arg->call_fn)(filename, arg->cookie); + else + return 0; +} + +/* + * Find all packages that match the given pattern and call the function + * for each of them. Iteration stops if the callback return non-0. + * Returns -1 on error, 0 if the iteration finished or whatever the + * callback returned otherwise. + */ +int +match_local_files(const char *dir, int filter_suffix, int allow_nonfiles, const char *pattern, + int (*cb)(const char *, void *), void *cookie) +{ + struct call_matching_file_arg arg; + + arg.pattern = pattern; + arg.call_fn = cb; + arg.cookie = cookie; + arg.filter_suffix = filter_suffix; + + return iterate_local_pkg_dir(dir, filter_suffix, allow_nonfiles, match_file_and_call, &arg); +} diff --git a/external/bsd/pkg_install/dist/lib/lib.h b/external/bsd/pkg_install/dist/lib/lib.h new file mode 100644 index 000000000..d664cd244 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/lib.h @@ -0,0 +1,457 @@ +/* $NetBSD: lib.h,v 1.6 2010/06/26 00:17:13 joerg Exp $ */ + +/* from FreeBSD Id: lib.h,v 1.25 1997/10/08 07:48:03 charnier Exp */ + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Include and define various things wanted by the library routines. + * + */ + +#ifndef _INST_LIB_LIB_H_ +#define _INST_LIB_LIB_H_ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_PARAM_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_FILE_H +#include +#endif +#if HAVE_SYS_QUEUE_H +#include +#endif + +#if HAVE_CTYPE_H +#include +#endif +#if HAVE_DIRENT_H +#include +#endif +#if HAVE_STDIO_H +#include +#endif +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_STDARG_H +#include +#endif +#if HAVE_STRING_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif + +/* Macros */ +#ifndef __UNCONST +#define __UNCONST(a) ((void *)(unsigned long)(const void *)(a)) +#endif + +#define SUCCESS (0) +#define FAIL (-1) + +#ifndef TRUE +#define TRUE (1) +#endif + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef OPSYS_NAME +#define OPSYS_NAME "NetBSD" +#endif + +#ifndef DEF_UMASK +#define DEF_UMASK 022 +#endif + +#ifndef PATH_MAX +# ifdef MAXPATHLEN +# define PATH_MAX MAXPATHLEN +# else +# define PATH_MAX 1024 +# endif +#endif + +enum { + MaxPathSize = PATH_MAX +}; + +/* The names of our "special" files */ +#define CONTENTS_FNAME "+CONTENTS" +#define COMMENT_FNAME "+COMMENT" +#define DESC_FNAME "+DESC" +#define INSTALL_FNAME "+INSTALL" +#define DEINSTALL_FNAME "+DEINSTALL" +#define REQUIRED_BY_FNAME "+REQUIRED_BY" +#define REQUIRED_BY_FNAME_TMP "+REQUIRED_BY.tmp" +#define DISPLAY_FNAME "+DISPLAY" +#define MTREE_FNAME "+MTREE_DIRS" +#define BUILD_VERSION_FNAME "+BUILD_VERSION" +#define BUILD_INFO_FNAME "+BUILD_INFO" +#define INSTALLED_INFO_FNAME "+INSTALLED_INFO" +#define SIZE_PKG_FNAME "+SIZE_PKG" +#define SIZE_ALL_FNAME "+SIZE_ALL" +#define PRESERVE_FNAME "+PRESERVE" +#define VIEWS_FNAME "+VIEWS" +#define VIEWS_FNAME_TMP "+VIEWS.tmp" +#define DEPOT_FNAME "+DEPOT" + +/* The names of special variables */ +#define AUTOMATIC_VARNAME "automatic" + +/* Prefix for extended PLIST cmd */ +#define CMD_CHAR '@' + +/* The name of the "prefix" environment variable given to scripts */ +#define PKG_PREFIX_VNAME "PKG_PREFIX" + +/* The name of the "destdir" environment variable given to scripts */ +#define PKG_DESTDIR_VNAME "PKG_DESTDIR" + +/* + * The name of the "metadatadir" environment variable given to scripts. + * This variable holds the location of the +-files for this package. + */ +#define PKG_METADATA_DIR_VNAME "PKG_METADATA_DIR" + +/* + * The name of the environment variable holding the location to the + * reference-counts database directory. + */ +#define PKG_REFCOUNT_DBDIR_VNAME "PKG_REFCOUNT_DBDIR" + +#define PKG_PATTERN_MAX MaxPathSize /* max length of pattern, including nul */ +#define PKG_SUFFIX_MAX 10 /* max length of suffix, including nul */ + +enum { + ReadWrite, + ReadOnly +}; + + +/* Enumerated constants for plist entry types */ +typedef enum pl_ent_t { + PLIST_SHOW_ALL = -1, + PLIST_FILE, /* 0 */ + PLIST_CWD, /* 1 */ + PLIST_CMD, /* 2 */ + PLIST_CHMOD, /* 3 */ + PLIST_CHOWN, /* 4 */ + PLIST_CHGRP, /* 5 */ + PLIST_COMMENT, /* 6 */ + PLIST_IGNORE, /* 7 */ + PLIST_NAME, /* 8 */ + PLIST_UNEXEC, /* 9 */ + PLIST_SRC, /* 10 */ + PLIST_DISPLAY, /* 11 */ + PLIST_PKGDEP, /* 12 */ + PLIST_DIR_RM, /* 13 */ + PLIST_OPTION, /* 14 */ + PLIST_PKGCFL, /* 15 */ + PLIST_BLDDEP, /* 16 */ + PLIST_PKGDIR /* 17 */ +} pl_ent_t; + +/* Enumerated constants for build info */ +typedef enum bi_ent_t { + BI_OPSYS, /* 0 */ + BI_OS_VERSION, /* 1 */ + BI_MACHINE_ARCH, /* 2 */ + BI_IGNORE_RECOMMENDED, /* 3 */ + BI_USE_ABI_DEPENDS, /* 4 */ + BI_LICENSE, /* 5 */ + BI_PKGTOOLS_VERSION, /* 6 */ + BI_ENUM_COUNT /* 7 */ +} bi_ent_t; + +/* Types */ +typedef unsigned int Boolean; + +/* This structure describes a packing list entry */ +typedef struct plist_t { + struct plist_t *prev; /* previous entry */ + struct plist_t *next; /* next entry */ + char *name; /* name of entry */ + Boolean marked; /* whether entry has been marked */ + pl_ent_t type; /* type of entry */ +} plist_t; + +/* This structure describes a package's complete packing list */ +typedef struct package_t { + plist_t *head; /* head of list */ + plist_t *tail; /* tail of list */ +} package_t; + +#define SYMLINK_HEADER "Symlink:" +#define CHECKSUM_HEADER "MD5:" + +enum { + ChecksumHeaderLen = 4, /* strlen(CHECKSUM_HEADER) */ + SymlinkHeaderLen = 8, /* strlen(SYMLINK_HEADER) */ + ChecksumLen = 16, + LegibleChecksumLen = 33 +}; + +/* List of files */ +typedef struct _lfile_t { + TAILQ_ENTRY(_lfile_t) lf_link; + char *lf_name; +} lfile_t; +TAILQ_HEAD(_lfile_head_t, _lfile_t); +typedef struct _lfile_head_t lfile_head_t; +#define LFILE_ADD(lfhead,lfp,str) do { \ + lfp = xmalloc(sizeof(lfile_t)); \ + lfp->lf_name = str; \ + TAILQ_INSERT_TAIL(lfhead,lfp,lf_link); \ + } while(0) + +/* List of packages */ +typedef struct _lpkg_t { + TAILQ_ENTRY(_lpkg_t) lp_link; + char *lp_name; +} lpkg_t; +TAILQ_HEAD(_lpkg_head_t, _lpkg_t); +typedef struct _lpkg_head_t lpkg_head_t; + +struct pkg_vulnerabilities { + size_t entries; + char **vulnerability; + char **classification; + char **advisory; +}; + +/* If URLlength()>0, then there is a ftp:// or http:// in the string, + * and this must be an URL. Hide this behind a more obvious name. */ +#define IS_URL(str) (URLlength(str) > 0) + +#define IS_STDIN(str) ((str) != NULL && !strcmp((str), "-")) +#define IS_FULLPATH(str) ((str) != NULL && (str)[0] == '/') + +/* Conflict handling (conflicts.c) */ +int some_installed_package_conflicts_with(const char *, const char *, char **, char **); + + +/* Prototypes */ +/* Misc */ +void show_version(void); +int fexec(const char *, ...); +int fexec_skipempty(const char *, ...); +int fcexec(const char *, const char *, ...); +int pfcexec(const char *, const char *, const char **); + +/* variables file handling */ + +char *var_get(const char *, const char *); +char *var_get_memory(const char *, const char *); +int var_set(const char *, const char *, const char *); +int var_copy_list(const char *, const char **); + +/* automatically installed as dependency */ + +Boolean is_automatic_installed(const char *); +int mark_as_automatic_installed(const char *, int); + +/* String */ +const char *basename_of(const char *); +const char *dirname_of(const char *); +const char *suffix_of(const char *); +int pkg_match(const char *, const char *); +int pkg_order(const char *, const char *, const char *); +int ispkgpattern(const char *); +int quick_pkg_match(const char *, const char *); + +/* Iterator functions */ +int iterate_pkg_generic_src(int (*)(const char *, void *), void *, + const char *(*)(void *),void *); +int iterate_local_pkg_dir(const char *, int, int, int (*)(const char *, void *), + void *); +int iterate_pkg_db(int (*)(const char *, void *), void *); + +int add_installed_pkgs_by_basename(const char *, lpkg_head_t *); +int add_installed_pkgs_by_pattern(const char *, lpkg_head_t *); +char *find_best_matching_installed_pkg(const char *); +char *find_best_matching_file(const char *, const char *, int, int); +int match_installed_pkgs(const char *, int (*)(const char *, void *), void *); +int match_local_files(const char *, int, int, const char *, int (*cb)(const char *, void *), void *); + +/* File */ +Boolean fexists(const char *); +Boolean isdir(const char *); +Boolean islinktodir(const char *); +Boolean isemptydir(const char *); +Boolean isemptyfile(const char *); +Boolean isfile(const char *); +Boolean isbrokenlink(const char *); +Boolean isempty(const char *); +int URLlength(const char *); +Boolean make_preserve_name(char *, size_t, const char *, const char *); +void remove_files(const char *, const char *); +int format_cmd(char *, size_t, const char *, const char *, const char *); + +int recursive_remove(const char *, int); + +void add_pkgdir(const char *, const char *, const char *); +void delete_pkgdir(const char *, const char *, const char *); +int has_pkgdir(const char *); + +/* pkg_io.c: Local and remote archive handling */ +struct archive; +struct archive_entry; + +struct archive *open_archive(const char *, char **); +struct archive *find_archive(const char *, int, char **); +void process_pkg_path(void); +struct url *find_best_package(const char *, const char *, int); + +/* Packing list */ +plist_t *new_plist_entry(void); +plist_t *last_plist(package_t *); +plist_t *find_plist(package_t *, pl_ent_t); +char *find_plist_option(package_t *, const char *); +void plist_delete(package_t *, Boolean, pl_ent_t, char *); +void free_plist(package_t *); +void mark_plist(package_t *); +void csum_plist_entry(char *, plist_t *); +void add_plist(package_t *, pl_ent_t, const char *); +void add_plist_top(package_t *, pl_ent_t, const char *); +void delete_plist(package_t *, Boolean, pl_ent_t, char *); +void write_plist(package_t *, FILE *, char *); +void stringify_plist(package_t *, char **, size_t *, const char *); +void parse_plist(package_t *, const char *); +void read_plist(package_t *, FILE *); +void append_plist(package_t *, FILE *); +int delete_package(Boolean, package_t *, Boolean, const char *); + +/* Package Database */ +int pkgdb_open(int); +void pkgdb_close(void); +int pkgdb_store(const char *, const char *); +char *pkgdb_retrieve(const char *); +int pkgdb_dump(void); +int pkgdb_remove(const char *); +int pkgdb_remove_pkg(const char *); +char *pkgdb_refcount_dir(void); +char *pkgdb_get_database(void); +const char *pkgdb_get_dir(void); +/* + * Priorities: + * 0 builtin default + * 1 config file + * 2 environment + * 3 command line + * 4 destdir/views reset + */ +void pkgdb_set_dir(const char *, int); +char *pkgdb_pkg_dir(const char *); +char *pkgdb_pkg_file(const char *, const char *); + +/* List of packages functions */ +lpkg_t *alloc_lpkg(const char *); +lpkg_t *find_on_queue(lpkg_head_t *, const char *); +void free_lpkg(lpkg_t *); + +/* Read pkg_vulnerabilities from file */ +struct pkg_vulnerabilities *read_pkg_vulnerabilities_file(const char *, int, int); +/* Read pkg_vulnerabilities from memory */ +struct pkg_vulnerabilities *read_pkg_vulnerabilities_memory(void *, size_t, int); +void free_pkg_vulnerabilities(struct pkg_vulnerabilities *); +int audit_package(struct pkg_vulnerabilities *, const char *, const char *, + int); + +/* Parse configuration file */ +void pkg_install_config(void); +/* Print configuration variable */ +void pkg_install_show_variable(const char *); + +/* Package signature creation and validation */ +int pkg_verify_signature(const char *, struct archive **, struct archive_entry **, char **); +int pkg_full_signature_check(const char *, struct archive **); +#ifdef HAVE_SSL +void pkg_sign_x509(const char *, const char *, const char *, const char *); +#endif + +void pkg_sign_gpg(const char *, const char *); + +#ifdef HAVE_SSL +/* PKCS7 signing/verification */ +int easy_pkcs7_verify(const char *, size_t, const char *, size_t, + const char *, int); +int easy_pkcs7_sign(const char *, size_t, char **, size_t *, const char *, + const char *); +#endif + +int inline_gpg_verify(const char *, size_t, const char *); +int detached_gpg_verify(const char *, size_t, const char *, size_t, + const char *); +int detached_gpg_sign(const char *, size_t, char **, size_t *, const char *, + const char *); + +/* License handling */ +int add_licenses(const char *); +int acceptable_license(const char *); +int acceptable_pkg_license(const char *); +void load_license_lists(void); + +/* Helper functions for memory allocation */ +char *xstrdup(const char *); +void *xrealloc(void *, size_t); +void *xcalloc(size_t, size_t); +void *xmalloc(size_t); +char *xasprintf(const char *, ...); + +/* Externs */ +extern Boolean Verbose; +extern Boolean Fake; +extern Boolean Force; +extern const char *cert_chain_file; +extern const char *certs_packages; +extern const char *certs_pkg_vulnerabilities; +extern const char *check_eol; +extern const char *check_vulnerabilities; +extern const char *config_file; +extern const char *config_pkg_dbdir; +extern const char *config_pkg_path; +extern const char *config_pkg_refcount_dbdir; +extern const char *do_license_check; +extern const char *verified_installation; +extern const char *gpg_cmd; +extern const char *gpg_keyring_pkgvuln; +extern const char *gpg_keyring_sign; +extern const char *gpg_keyring_verify; +extern const char *gpg_sign_as; +extern char fetch_flags[]; + +extern const char *pkg_vulnerabilities_dir; +extern const char *pkg_vulnerabilities_file; +extern const char *pkg_vulnerabilities_url; +extern const char *ignore_advisories; +extern const char tnf_vulnerability_base[]; + +extern const char *acceptable_licenses; +extern const char *default_acceptable_licenses; + +#endif /* _INST_LIB_LIB_H_ */ diff --git a/external/bsd/pkg_install/dist/lib/license.c b/external/bsd/pkg_install/dist/lib/license.c new file mode 100644 index 000000000..6af3b1040 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/license.c @@ -0,0 +1,318 @@ +/* $NetBSD: license.c,v 1.4 2013/04/20 15:29:23 wiz Exp $ */ + +/*- + * Copyright (c) 2009 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#if HAVE_ERR_H +#include +#endif +#include +#include + +#include "lib.h" + +#define HASH_SIZE 521 + +const char *default_acceptable_licenses = + "apache-1.1 apache-2.0 " + "arphic-public " + "artistic artistic-2.0 " + "boost-license " + "cc-by-sa-v3.0 " + "cddl-1.0 " + "cpl-1.0 " + "epl-v1.0 " + "gnu-fdl-v1.1 gnu-fdl-v1.2 gnu-fdl-v1.3 " + "gnu-gpl-v1 " + "gnu-gpl-v2 gnu-lgpl-v2 gnu-lgpl-v2.1 " + "gnu-gpl-v3 gnu-lgpl-v3 " + "ibm-public-license-1.0 " + "ipafont " + "isc " + "lppl-1.3c " + "lucent " + "miros " + "mit " + "mpl-1.0 mpl-1.1 mpl-2.0 " + "mplusfont " + "ofl-v1.0 ofl-v1.1 " + "original-bsd modified-bsd 2-clause-bsd " + "php " + "png-license " + "postgresql-license " + "public-domain " + "python-software-foundation " + "qpl-v1.0 " + "sleepycat-public " + "unlicense " + "x11 " + "zlib " + "zpl"; + +#ifdef DEBUG +static size_t hash_collisions; +#endif + +static char **license_hash[HASH_SIZE]; +static const char license_spaces[] = " \t\n"; +static const char license_chars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-."; + +static size_t +hash_license(const char *license, size_t len) +{ + size_t hash; + + for (hash = 0; *license && len; ++license, --len) + hash = *license + hash * 32; + return hash % HASH_SIZE; +} + +static void +add_license_internal(const char *license, size_t len) +{ + char *new_license; + size_t slot, i; + + slot = hash_license(license, len); + + new_license = malloc(len + 1); + memcpy(new_license, license, len); + new_license[len] = '\0'; + + if (license_hash[slot] == NULL) { + license_hash[slot] = calloc(sizeof(char *), 2); + license_hash[slot][0] = new_license; + } else { + for (i = 0; license_hash[slot][i]; ++i) { + if (!memcmp(license_hash[slot][i], license, len) && + license_hash[slot][i][len] == '\0') { + free(new_license); + return; + } + } + +#ifdef DEBUG + ++hash_collisions; +#endif + + license_hash[slot] = realloc(license_hash[slot], + sizeof(char *) * (i + 2)); + license_hash[slot][i] = new_license; + license_hash[slot][i + 1] = NULL; + } +} + +int +add_licenses(const char *line) +{ + const char *next; + + if (line == NULL) + return 0; + + for (line += strspn(line, license_spaces); line; ) { + next = line + strspn(line, license_chars); + if (next == line) + return *line ? -1 : 0; + add_license_internal(line, next - line); + line = next + strspn(next, license_spaces); + if (next == line) + return *line ? -1 : 0; + } + return 0; +} + +static int +acceptable_license_internal(const char *license, size_t len) +{ + size_t slot, i; + + slot = hash_license(license, len); + + if (license_hash[slot] == NULL) + return 0; + + for (i = 0; license_hash[slot][i]; ++i) { + if (strncmp(license_hash[slot][i], license, len) == 0 && + license_hash[slot][i][len] == '\0') + return 1; + } + + return 0; +} + +int +acceptable_license(const char *license) +{ + size_t len; + + len = strlen(license); + if (strspn(license, license_chars) != len) { + warnx("Invalid character in license name at position %" PRIzu, len); + return -1; + } + + return acceptable_license_internal(license, len); +} + +static int +acceptable_pkg_license_internal(const char **licensep, int toplevel, const char *start) +{ + const char *license = *licensep; + int need_parenthesis, is_true = 0; + int expr_type = 0; /* 0: unset, 1: or, 2: and */ + size_t len; + + license += strspn(license, license_spaces); + + if (*license == '(' && !toplevel) { + need_parenthesis = 1; + ++license; + license += strspn(license, license_spaces); + } else { + need_parenthesis = 0; + } + + for (;;) { + if (*license == '(') { + switch (acceptable_pkg_license_internal(&license, 0, start)) { + case -1: + return -1; + case 0: + if (expr_type == 2) + is_true = 0; + break; + case 1: + is_true = 1; + break; + } + license += strspn(license, license_spaces); + } else { + len = strspn(license, license_chars); + if (len == 0) { + warnx("Invalid character in license name at position %" PRIzu, license - start + 1); + return -1; + } + + if (acceptable_license_internal(license, len)) { + if (expr_type != 2) + is_true = 1; + } else if (expr_type == 2) { + is_true = 0; + } + + license += len; + + len = strspn(license, license_spaces); + if (len == 0 && *license && *license != ')') { + warnx("Missing space at position %" PRIzu, license - start + 1); + return -1; + } + license += len; + } + + if (*license == ')') { + if (!need_parenthesis) { + warnx("Missing open parenthesis at position %" PRIzu, license - start + 1); + return -1; + } + *licensep = license + 1; + return is_true; + } + if (*license == '\0') { + if (need_parenthesis) { + warnx("Unbalanced parenthesis at position %" PRIzu, license - start + 1); + return -1; + } + *licensep = license; + return is_true; + } + + if (strncmp(license, "AND", 3) == 0) { + if (expr_type == 1) { + warnx("Invalid operator in OR expression at position %" PRIzu, license - start + 1); + return -1; + } + expr_type = 2; + license += 3; + } else if (strncmp(license, "OR", 2) == 0) { + if (expr_type == 2) { + warnx("Invalid operator in AND expression at position %" PRIzu, license - start + 1); + return -1; + } + expr_type = 1; + license += 2; + } else { + warnx("Invalid operator at position %" PRIzu, license - start + 1); + return -1; + } + len = strspn(license, license_spaces); + if (len == 0 && *license != '(') { + warnx("Missing space at position %" PRIzu, license - start + 1); + return -1; + } + license += len; + } +} + +int +acceptable_pkg_license(const char *license) +{ + int ret; + + ret = acceptable_pkg_license_internal(&license, 1, license); + if (ret == -1) + return -1; + license += strspn(license, license_spaces); + if (*license) { + warnx("Trailing garbage in license specification"); + return -1; + } + return ret; +} + +void +load_license_lists(void) +{ + if (add_licenses(getenv("PKGSRC_ACCEPTABLE_LICENSES"))) + errx(EXIT_FAILURE, "syntax error in PKGSRC_ACCEPTABLE_LICENSES"); + if (add_licenses(acceptable_licenses)) + errx(EXIT_FAILURE, "syntax error in ACCEPTABLE_LICENSES"); + if (add_licenses(getenv("PKGSRC_DEFAULT_ACCEPTABLE_LICENSES"))) + errx(EXIT_FAILURE, "syntax error in PKGSRC_DEFAULT_ACCEPTABLE_LICENSES"); + if (add_licenses(default_acceptable_licenses)) + errx(EXIT_FAILURE, "syntax error in DEFAULT_ACCEPTABLE_LICENSES"); +} diff --git a/external/bsd/pkg_install/dist/lib/lpkg.c b/external/bsd/pkg_install/dist/lib/lpkg.c new file mode 100644 index 000000000..aacdc2f89 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/lpkg.c @@ -0,0 +1,70 @@ +/* $NetBSD: lpkg.c,v 1.1.1.2 2009/02/02 20:44:06 joerg Exp $ */ + +/* + * Copyright (c) 1999 Christian E. Hopps + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Package-list auxiliary functions + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_ERR_H +#include +#endif +#include "lib.h" + +/* + * Add a package to the (add/recursive delete) list + */ +lpkg_t * +alloc_lpkg(const char *pkgname) +{ + lpkg_t *lpp; + + lpp = xmalloc(sizeof(*lpp)); + lpp->lp_name = xstrdup(pkgname); + return (lpp); +} + +void +free_lpkg(lpkg_t *lpp) +{ + free(lpp->lp_name); + free(lpp); +} + +lpkg_t * +find_on_queue(lpkg_head_t *qp, const char *name) +{ + lpkg_t *lpp; + + for (lpp = TAILQ_FIRST(qp); lpp; lpp = TAILQ_NEXT(lpp, lp_link)) + if (!strcmp(name, lpp->lp_name)) + return (lpp); + return (0); +} diff --git a/external/bsd/pkg_install/dist/lib/opattern.c b/external/bsd/pkg_install/dist/lib/opattern.c new file mode 100644 index 000000000..80960338f --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/opattern.c @@ -0,0 +1,213 @@ +/* $NetBSD: opattern.c,v 1.1.1.3 2012/02/19 17:46:47 tron Exp $ */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: opattern.c,v 1.1.1.3 2012/02/19 17:46:47 tron Exp $"); + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Miscellaneous string utilities. + * + */ + +#if HAVE_ASSERT_H +#include +#endif +#if HAVE_ERR_H +#include +#endif +#if HAVE_FNMATCH_H +#include +#endif +#include "lib.h" +#include "dewey.h" + +/* pull in definitions and macros for resizing arrays as we go */ +#include "defs.h" + +/* + * Perform alternate match on "pkg" against "pattern", + * calling pkg_match (recursively) to resolve any other patterns. + * Return 1 on match, 0 otherwise + */ +static int +alternate_match(const char *pattern, const char *pkg) +{ + char *sep; + char buf[MaxPathSize]; + char *last; + char *alt; + char *cp; + int cnt; + int found; + + if ((sep = strchr(pattern, '{')) == (char *) NULL) { + errx(EXIT_FAILURE, "alternate_match(): '{' expected in `%s'", pattern); + } + (void) strncpy(buf, pattern, (size_t) (sep - pattern)); + alt = &buf[sep - pattern]; + last = (char *) NULL; + for (cnt = 0, cp = sep; *cp && last == (char *) NULL; cp++) { + if (*cp == '{') { + cnt++; + } else if (*cp == '}' && --cnt == 0 && last == (char *) NULL) { + last = cp + 1; + } + } + if (cnt != 0) { + errx(EXIT_FAILURE, "Malformed alternate `%s'", pattern); + } + for (found = 0, cp = sep + 1; *sep != '}'; cp = sep + 1) { + for (cnt = 0, sep = cp; cnt > 0 || (cnt == 0 && *sep != '}' && *sep != ','); sep++) { + if (*sep == '{') { + cnt++; + } else if (*sep == '}') { + cnt--; + } + } + (void) snprintf(alt, sizeof(buf) - (alt - buf), "%.*s%s", (int) (sep - cp), cp, last); + if (pkg_match(buf, pkg) == 1) { + found = 1; + } + } + return found; +} + +/* + * Perform glob match on "pkg" against "pattern". + * Return 1 on match, 0 otherwise + */ +static int +glob_match(const char *pattern, const char *pkg) +{ + return fnmatch(pattern, pkg, FNM_PERIOD) == 0; +} + +/* + * Perform simple match on "pkg" against "pattern". + * Return 1 on match, 0 otherwise + */ +static int +simple_match(const char *pattern, const char *pkg) +{ + return strcmp(pattern, pkg) == 0; +} + +/* + * Performs a fast check if pattern can ever match pkg. + * Returns 1 if a match is possible and 0 otherwise. + */ +int +quick_pkg_match(const char *pattern, const char *pkg) +{ +#define simple(x) (isalnum((unsigned char)(x)) || (x) == '-') + if (!simple(pattern[0])) + return 1; + if (pattern[0] != pkg[0]) + return 0; + + if (!simple(pattern[1])) + return 1; + if (pattern[1] != pkg[1]) + return 0; + return 1; +#undef simple +} + +/* + * Match pkg against pattern, return 1 if matching, 0 else + */ +int +pkg_match(const char *pattern, const char *pkg) +{ + if (!quick_pkg_match(pattern, pkg)) + return 0; + + if (strchr(pattern, '{') != (char *) NULL) { + /* emulate csh-type alternates */ + return alternate_match(pattern, pkg); + } + if (strpbrk(pattern, "<>") != (char *) NULL) { + int ret; + + /* perform relational dewey match on version number */ + ret = dewey_match(pattern, pkg); + if (ret < 0) + errx(EXIT_FAILURE, "dewey_match returned error"); + return ret; + } + if (strpbrk(pattern, "*?[]") != (char *) NULL) { + /* glob match */ + if (glob_match(pattern, pkg)) + return 1; + } + + /* no alternate, dewey or glob match -> simple compare */ + if (simple_match(pattern, pkg)) + return 1; + + /* globbing patterns and simple matches may be specified with or + * without the version number, so check for both cases. */ + + { + char *pattern_ver; + int retval; + + pattern_ver = xasprintf("%s-[0-9]*", pattern); + retval = glob_match(pattern_ver, pkg); + free(pattern_ver); + return retval; + } +} + +int +pkg_order(const char *pattern, const char *first_pkg, const char *second_pkg) +{ + const char *first_version; + const char *second_version; + + if (first_pkg == NULL && second_pkg == NULL) + return 0; + + if (first_pkg == NULL) + return pkg_match(pattern, second_pkg) ? 2 : 0; + if (second_pkg == NULL) + return pkg_match(pattern, first_pkg) ? 1 : 0; + + first_version = strrchr(first_pkg, '-'); + second_version = strrchr(second_pkg, '-'); + + if (first_version == NULL || !pkg_match(pattern, first_pkg)) + return pkg_match(pattern, second_pkg) ? 2 : 0; + + if (second_version == NULL || !pkg_match(pattern, second_pkg)) + return pkg_match(pattern, first_pkg) ? 1 : 0; + + if (dewey_cmp(first_version + 1, DEWEY_GT, second_version + 1)) + return 1; + else if (dewey_cmp(first_version + 1, DEWEY_LT, second_version + 1)) + return 2; + else if (strcmp(first_pkg, second_pkg) < 0) + return 1; + else + return 2; +} diff --git a/external/bsd/pkg_install/dist/lib/parse-config.c b/external/bsd/pkg_install/dist/lib/parse-config.c new file mode 100644 index 000000000..d7664439c --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/parse-config.c @@ -0,0 +1,271 @@ +/* $NetBSD: parse-config.c,v 1.1.1.11 2010/06/26 00:14:31 joerg Exp $ */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: parse-config.c,v 1.1.1.11 2010/06/26 00:14:31 joerg Exp $"); + +/*- + * Copyright (c) 2008, 2009 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if HAVE_ERR_H +#include +#endif +#include +#if HAVE_STRING_H +#include +#endif + +#ifndef BOOTSTRAP +#include +#endif + +#include "lib.h" + +static int cache_connections = 16; +static int cache_connections_host = 4; + +const char *config_file = SYSCONFDIR"/pkg_install.conf"; + +char fetch_flags[10] = ""; /* Workaround Mac OS X linker issues with BSS */ +static const char *active_ftp; +static const char *verbose_netio; +static const char *ignore_proxy; +const char *cache_index = "yes"; +const char *cert_chain_file; +const char *certs_packages; +const char *certs_pkg_vulnerabilities; +const char *check_eol = "yes"; +const char *check_vulnerabilities; +static const char *config_cache_connections; +static const char *config_cache_connections_host; +const char *config_pkg_dbdir; +const char *config_pkg_path; +const char *config_pkg_refcount_dbdir; +const char *do_license_check; +const char *verified_installation; +const char *gpg_cmd; +const char *gpg_keyring_pkgvuln; +const char *gpg_keyring_sign; +const char *gpg_keyring_verify; +const char *gpg_sign_as; +const char *pkg_vulnerabilities_dir; +const char *pkg_vulnerabilities_file; +const char *pkg_vulnerabilities_url; +const char *ignore_advisories = NULL; +const char tnf_vulnerability_base[] = "http://ftp.NetBSD.org/pub/NetBSD/packages/vulns"; +const char *acceptable_licenses = NULL; + +static struct config_variable { + const char *name; + const char **var; +} config_variables[] = { + { "ACCEPTABLE_LICENSES", &acceptable_licenses }, + { "ACTIVE_FTP", &active_ftp }, + { "CACHE_INDEX", &cache_index }, + { "CACHE_CONNECTIONS", &config_cache_connections }, + { "CACHE_CONNECTIONS_HOST", &config_cache_connections_host }, + { "CERTIFICATE_ANCHOR_PKGS", &certs_packages }, + { "CERTIFICATE_ANCHOR_PKGVULN", &certs_pkg_vulnerabilities }, + { "CERTIFICATE_CHAIN", &cert_chain_file }, + { "CHECK_LICENSE", &do_license_check }, + { "CHECK_END_OF_LIFE", &check_eol }, + { "CHECK_VULNERABILITIES", &check_vulnerabilities }, + { "DEFAULT_ACCEPTABLE_LICENSES", &default_acceptable_licenses }, + { "GPG", &gpg_cmd }, + { "GPG_KEYRING_PKGVULN", &gpg_keyring_pkgvuln }, + { "GPG_KEYRING_SIGN", &gpg_keyring_sign }, + { "GPG_KEYRING_VERIFY", &gpg_keyring_verify }, + { "GPG_SIGN_AS", &gpg_sign_as }, + { "IGNORE_PROXY", &ignore_proxy }, + { "IGNORE_URL", &ignore_advisories }, + { "PKG_DBDIR", &config_pkg_dbdir }, + { "PKG_PATH", &config_pkg_path }, + { "PKG_REFCOUNT_DBDIR", &config_pkg_refcount_dbdir }, + { "PKGVULNDIR", &pkg_vulnerabilities_dir }, + { "PKGVULNURL", &pkg_vulnerabilities_url }, + { "VERBOSE_NETIO", &verbose_netio }, + { "VERIFIED_INSTALLATION", &verified_installation }, + { NULL, NULL }, /* For use by pkg_install_show_variable */ + { NULL, NULL } +}; + +char *config_tmp_variables[sizeof config_variables/sizeof config_variables[0]]; + +static void +parse_pkg_install_conf(void) +{ + struct config_variable *var; + FILE *fp; + char *line, *value; + size_t len, var_len, i; + + fp = fopen(config_file, "r"); + if (!fp) { + if (errno != ENOENT) + warn("Can't open '%s' for reading", config_file); + return; + } + + while ((line = fgetln(fp, &len)) != (char *) NULL) { + if (line[len - 1] == '\n') + --len; + for (i = 0; (var = &config_variables[i])->name != NULL; ++i) { + var_len = strlen(var->name); + if (strncmp(var->name, line, var_len) != 0) + continue; + if (line[var_len] != '=') + continue; + line += var_len + 1; + len -= var_len + 1; + if (config_tmp_variables[i]) + value = xasprintf("%s\n%.*s", + config_tmp_variables[i], (int)len, line); + else + value = xasprintf("%.*s", (int)len, line); + free(config_tmp_variables[i]); + config_tmp_variables[i] = value; + break; + } + } + + for (i = 0; (var = &config_variables[i])->name != NULL; ++i) { + if (config_tmp_variables[i] == NULL) + continue; + *var->var = config_tmp_variables[i]; + config_tmp_variables[i] = NULL; + } + + fclose(fp); +} + +void +pkg_install_config(void) +{ + int do_cache_index; + char *value; + + parse_pkg_install_conf(); + + if ((value = getenv("PKG_DBDIR")) != NULL) + pkgdb_set_dir(value, 2); + else if (config_pkg_dbdir != NULL) + pkgdb_set_dir(config_pkg_dbdir, 1); + config_pkg_dbdir = xstrdup(pkgdb_get_dir()); + + if ((value = getenv("PKG_REFCOUNT_DBDIR")) != NULL) + config_pkg_refcount_dbdir = value; + else if (config_pkg_refcount_dbdir == NULL) + config_pkg_refcount_dbdir = xasprintf("%s.refcount", + pkgdb_get_dir()); + + if (pkg_vulnerabilities_dir == NULL) + pkg_vulnerabilities_dir = pkgdb_get_dir(); + pkg_vulnerabilities_file = xasprintf("%s/pkg-vulnerabilities", + pkg_vulnerabilities_dir); + if (pkg_vulnerabilities_url == NULL) { + pkg_vulnerabilities_url = xasprintf("%s/pkg-vulnerabilities.gz", + tnf_vulnerability_base); + } + if (verified_installation == NULL) + verified_installation = "never"; + + if (check_vulnerabilities == NULL) + check_vulnerabilities = "never"; + + if (do_license_check == NULL) + do_license_check = "no"; + + if ((value = getenv("PKG_PATH")) != NULL) + config_pkg_path = value; + + if (strcasecmp(cache_index, "yes") == 0) + do_cache_index = 1; + else { + if (strcasecmp(cache_index, "no")) + warnx("Invalid value for configuration option " + "CACHE_INDEX"); + do_cache_index = 0; + } + + if (config_cache_connections && *config_cache_connections) { + long v = strtol(config_cache_connections, &value, 10); + if (*value == '\0') { + if (v >= INT_MAX || v < 0) + v = -1; + cache_connections = v; + } + } + config_cache_connections = xasprintf("%d", cache_connections); + + if (config_cache_connections_host) { + long v = strtol(config_cache_connections_host, &value, 10); + if (*value == '\0') { + if (v >= INT_MAX || v < 0) + v = -1; + cache_connections_host = v; + } + } + config_cache_connections_host = xasprintf("%d", cache_connections_host); + +#ifndef BOOTSTRAP + fetchConnectionCacheInit(cache_connections, cache_connections_host); +#endif + + snprintf(fetch_flags, sizeof(fetch_flags), "%s%s%s%s", + (do_cache_index) ? "c" : "", + (verbose_netio && *verbose_netio) ? "v" : "", + (active_ftp && *active_ftp) ? "a" : "", + (ignore_proxy && *ignore_proxy) ? "d" : ""); +} + +void +pkg_install_show_variable(const char *var_name) +{ + struct config_variable *var; + const char *tmp_value = NULL; + + for (var = config_variables; var->name != NULL; ++var) { + if (strcmp(var->name, var_name) == 0) + break; + } + if (var->name == NULL) { + var->name = var_name; + var->var = &tmp_value; + } + + pkg_install_config(); + + if (*var->var != NULL) + puts(*var->var); +} diff --git a/external/bsd/pkg_install/dist/lib/pkcs7.c b/external/bsd/pkg_install/dist/lib/pkcs7.c new file mode 100644 index 000000000..e61a504e8 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/pkcs7.c @@ -0,0 +1,332 @@ +/* $NetBSD: pkcs7.c,v 1.1.1.4 2009/08/06 16:55:27 joerg Exp $ */ +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif + +__RCSID("$NetBSD: pkcs7.c,v 1.1.1.4 2009/08/06 16:55:27 joerg Exp $"); + +/*- + * Copyright (c) 2004, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Love Hörnquist Åstrand + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#if HAVE_ERR_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include "lib.h" + +#ifndef NS_ANY_CA +#define NS_ANY_CA (NS_SSL_CA|NS_SMIME_CA|NS_OBJSIGN_CA) +#endif + +static const unsigned int pkg_key_usage = XKU_CODE_SIGN | XKU_SMIME; + +static int +check_ca(X509 *cert) +{ + if ((cert->ex_flags & EXFLAG_KUSAGE) != 0 && + (cert->ex_kusage & KU_KEY_CERT_SIGN) != KU_KEY_CERT_SIGN) + return 0; + if ((cert->ex_flags & EXFLAG_BCONS) != 0) + return (cert->ex_flags & EXFLAG_CA) == EXFLAG_CA; + if ((cert->ex_flags & (EXFLAG_V1|EXFLAG_SS)) == (EXFLAG_V1|EXFLAG_SS)) + return 1; + if ((cert->ex_flags & EXFLAG_KUSAGE) != 0) + return 1; + if ((cert->ex_flags & EXFLAG_NSCERT) != 0 && + (cert->ex_nscert & NS_ANY_CA) != 0) + return 1; + return 0; +} + +static STACK_OF(X509) * +file_to_certs(const char *file) +{ + unsigned long ret; + STACK_OF(X509) *certs; + FILE *f; + + if ((f = fopen(file, "r")) == NULL) { + warn("open failed %s", file); + return NULL; + } + + certs = sk_X509_new_null(); + for (;;) { + X509 *cert; + + cert = PEM_read_X509(f, NULL, NULL, NULL); + if (cert == NULL) { + ret = ERR_GET_REASON(ERR_peek_error()); + if (ret == PEM_R_NO_START_LINE) { + /* End of file reached. no error */ + ERR_clear_error(); + break; + } + sk_X509_free(certs); + warnx("Can't read certificate in file: %s", file); + fclose(f); + return NULL; + } + sk_X509_insert(certs, cert, sk_X509_num(certs)); + } + + fclose(f); + + if (sk_X509_num(certs) == 0) { + sk_X509_free(certs); + certs = NULL; + warnx("No certificate found in file %s", file); + } + + return certs; +} + +int +easy_pkcs7_verify(const char *content, size_t len, + const char *signature, size_t signature_len, + const char *anchor, int is_pkg) +{ + STACK_OF(X509) *cert_chain, *signers; + X509_STORE *store; + BIO *sig, *in; + PKCS7 *p7; + int i, status; + X509_NAME *name; + char *subject; + + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + + status = -1; + + if (cert_chain_file) + cert_chain = file_to_certs(cert_chain_file); + else + cert_chain = NULL; + + store = X509_STORE_new(); + if (store == NULL) { + sk_X509_free(cert_chain); + warnx("Failed to create certificate store"); + return -1; + } + + X509_STORE_load_locations(store, anchor, NULL); + + in = BIO_new_mem_buf(__UNCONST(content), len); + sig = BIO_new_mem_buf(__UNCONST(signature), signature_len); + signers = NULL; + + p7 = PEM_read_bio_PKCS7(sig, NULL, NULL, NULL); + if (p7 == NULL) { + warnx("Failed to parse the signature"); + goto cleanup; + } + + if (PKCS7_verify(p7, cert_chain, store, in, NULL, 0) != 1) { + warnx("Failed to verify signature"); + goto cleanup; + } + + signers = PKCS7_get0_signers(p7, NULL, 0); + if (signers == NULL) { + warnx("Failed to get signers"); + goto cleanup; + } + + if (sk_X509_num(signers) == 0) { + warnx("No signers found"); + goto cleanup; + } + + for (i = 0; i < sk_X509_num(signers); i++) { + /* Compute ex_xkusage */ + X509_check_purpose(sk_X509_value(signers, i), -1, -1); + + if (check_ca(sk_X509_value(signers, i))) { + warnx("CA keys are not valid for signatures"); + goto cleanup; + } + if (is_pkg) { + if (sk_X509_value(signers, i)->ex_xkusage != pkg_key_usage) { + warnx("Certificate must have CODE SIGNING " + "and EMAIL PROTECTION property"); + goto cleanup; + } + } else { + if (sk_X509_value(signers, i)->ex_xkusage != 0) { + warnx("Certificate must not have any property"); + goto cleanup; + } + } + } + + printf("Sigature ok, signed by:\n"); + + for (i = 0; i < sk_X509_num(signers); i++) { + name = X509_get_subject_name(sk_X509_value(signers, i)); + subject = X509_NAME_oneline(name, NULL, 0); + + printf("\t%s\n", subject); + + OPENSSL_free(subject); + } + + status = 0; + +cleanup: + sk_X509_free(cert_chain); + sk_X509_free(signers); + X509_STORE_free(store); + + PKCS7_free(p7); + BIO_free(in); + BIO_free(sig); + + return status; +} + +static int +ssl_pass_cb(char *buf, int size, int rwflag, void *u) +{ + + if (EVP_read_pw_string(buf, size, "Passphrase :", 0)) { +#if OPENSSL_VERSION >= 0x0090608fL + OPENSSL_cleanse(buf, size); +#else + memset(buf, 0, size); +#endif + return 0; + } + return strlen(buf); +} + +int +easy_pkcs7_sign(const char *content, size_t len, + char **signature, size_t *signature_len, + const char *key_file, const char *cert_file) +{ + FILE *f; + X509 *certificate; + STACK_OF(X509) *c, *cert_chain; + EVP_PKEY *private_key; + char *tmp_sig; + BIO *out, *in; + PKCS7 *p7; + int status; + + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + + status = -1; + private_key = NULL; + cert_chain = NULL; + in = NULL; + + c = file_to_certs(cert_file); + + if (sk_X509_num(c) != 1) { + warnx("More then one certificate in the certificate file"); + goto cleanup; + } + certificate = sk_X509_value(c, 0); + + /* Compute ex_kusage */ + X509_check_purpose(certificate, -1, 0); + + if (check_ca(certificate)) { + warnx("CA keys are not valid for signatures"); + goto cleanup; + } + + if (certificate->ex_xkusage != pkg_key_usage) { + warnx("Certificate must have CODE SIGNING " + "and EMAIL PROTECTION property"); + goto cleanup; + } + + if (cert_chain_file) + cert_chain = file_to_certs(cert_chain_file); + + if ((f = fopen(key_file, "r")) == NULL) { + warn("Failed to open private key file %s", key_file); + goto cleanup; + } + private_key = PEM_read_PrivateKey(f, NULL, ssl_pass_cb, NULL); + fclose(f); + if (private_key == NULL) { + warnx("Can't read private key: %s", key_file); + goto cleanup; + } + + if (X509_check_private_key(certificate, private_key) != 1) { + warnx("The private key %s doesn't match the certificate %s", + key_file, cert_file); + goto cleanup; + } + + in = BIO_new_mem_buf(__UNCONST(content), len); + + p7 = PKCS7_sign(certificate, private_key, cert_chain, in, + PKCS7_DETACHED|PKCS7_NOATTR|PKCS7_BINARY); + if (p7 == NULL) { + warnx("Failed to create signature structure"); + goto cleanup; + } + + out = BIO_new(BIO_s_mem()); + PEM_write_bio_PKCS7(out, p7); + *signature_len = BIO_get_mem_data(out, &tmp_sig); + *signature = xmalloc(*signature_len); + memcpy(*signature, tmp_sig, *signature_len); + BIO_free_all(out); + + PKCS7_free(p7); + + status = 0; + +cleanup: + sk_X509_free(c); + sk_X509_free(cert_chain); + EVP_PKEY_free(private_key); + BIO_free(in); + + return status; +} diff --git a/external/bsd/pkg_install/dist/lib/pkg_install.conf.5.in b/external/bsd/pkg_install/dist/lib/pkg_install.conf.5.in new file mode 100644 index 000000000..d287cdaa6 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/pkg_install.conf.5.in @@ -0,0 +1,216 @@ +.\" $NetBSD: pkg_install.conf.5.in,v 1.1.1.13 2013/04/20 15:26:53 wiz Exp $ +.\" +.\" Copyright (c) 2008, 2009, 2012 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Thomas Klausner. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd February 22, 2012 +.Dt PKG_INSTALL.CONF 5 +.Os +.Sh NAME +.Nm pkg_install.conf +.Nd configuration file for package installation tools +.Sh DESCRIPTION +The file +.Nm +contains system defaults for the package installation tools +as a list of variable-value pairs. +Each line has the format +.Ev VARIABLE=VALUE . +If the value consists of more than one line, each line is prefixed with +.Ev VARIABLE= . +.Pp +The current value of a variable can be checked by running +.Dl Ic pkg_admin config-var VARIABLE +.Pp +Some variables are overriden by environmental variables of the same name. +Those are marked by (*). +.Pp +The following variables are supported: +.Bl -tag -width indent +.It Dv ACCEPTABLE_LICENSES +Space-separated list of licenses packages are allowed to carry. +License names are case-sensitive. +.It Dv ACTIVE_FTP +Force the use of active FTP. +.It Dv CACHE_INDEX +Cache directory listenings in memory. +This avoids retransfers of the large directory index for HTTP and is +enabled by default. +.It Dv CERTIFICATE_ANCHOR_PKGS +Path to the file containing the certificates used for validating +binary packages. +A package is trusted when a certificate chain ends in one of the +certificates contained in this file. +The certificates must be PEM-encoded. +.It Dv CERTIFICATE_ANCHOR_PKGVULN +Analogous to +.Dv CERTIFICATE_ANCHOR_PKGS . +The +.Pa pkg-vulnerabilities +is trusted when a certificate chain ends in one of the certificates +contained in this file. +.It Dv CERTIFICATE_CHAIN +Path to a file containing additional certificates that can be used +for completing certificate chains when validating binary packages or +pkg-vulnerabilities files. +.It Dv CHECK_LICENSE +Check the license conditions of packages before installing them. +Supported values are: +.Bl -tag -width interactiveXX +.It Dv no +The check is not performed. +.It Dv yes +The check is performed if the package has license conditions set. +.It Dv always +Passing the license check is required. +Missing license conditions are considered an error. +.El +.It Dv CHECK_END_OF_LIFE +During vulnerability checks, consider packages that have reached end-of-life +as vulnerable. +This option is enabled by default. +.It Dv CHECK_VULNERABILITIES +Check for vulnerabilities when installing packages. +Supported values are: +.Bl -tag -width interactiveXX +.It Dv never +No check is performed. +.It Dv always +Passing the vulnerability check is required. +A missing pkg-vulnerabilities file is considered an error. +.It Dv interactive +The user is always asked to confirm installation of vulnerable packages. +.El +.It Dv CONFIG_CACHE_CONNECTIONS +Limit the global connection cache to this value. +For FTP, this is the number of sessions without active command. +For HTTP, this is the number of connections open with keep-alive. +.It Dv CONFIG_CACHE_CONNECTIONS_HOST +Like +.Dv CONFIG_CACHE_CONNECTIONS , +but limit the number of connections to the host as well. +See +.Xr fetch 3 +for further details +.It Dv DEFAULT_ACCEPTABLE_LICENSES +Space-separated list of common Free and Open Source licenses packages are +allowed to carry. +The default value contains all OSI approved licenses in pkgsrc on the date +pkg_install was released. +License names are case-sensitive. +.It Dv GPG +Path to +.Xr gpg 1 , +which can be used to verify the signature in the +.Pa pkg-vulnerabilities +file when running +.Dl Ic pkg_admin check-pkg-vulnerabilities -s +or +.Dl Ic pkg_admin fetch-pkg-vulnerabilities -s +It can also be used to verify and sign binary packages. +.It Dv GPG_KEYRING_PKGVULN +Non-default keyring to use for verifying GPG signatures of +.Pa pkg-vulnerabilities . +.It Dv GPG_KEYRING_SIGN +Non-default keyring to use for signing packages with GPG. +.It Dv GPG_KEYRING_VERIFY +Non-default keyring to use for verifying GPG signature of packages. +.It Dv GPG_SIGN_AS +User-id to use for signing packages. +.It Dv IGNORE_PROXY +Use direct connections and ignore +.Ev FTP_PROXY +and +.Ev HTTP_PROXY . +.It Dv IGNORE_URL +One line per advisory which should be ignored when running +.Dl Ic pkg_admin audit +The URL from the +.Pa pkg-vulnerabilities +file should be used as value. +.It Dv PKG_DBDIR (*) +Location of the packages database. +This option is always overriden by the argument of the +.Fl K +option. +.It Dv PKG_PATH (*) +Search path for packages. +The entries are separated by semicolon. +Each entry specifies a directory or URL to search for packages. +.It Dv PKG_REFCOUNT_DBDIR (*) +Location of the package reference counts database directory. +The default value is +.Pa ${PKG_DBDIR}.refcount . +.It Dv PKGVULNDIR +Directory name in which the +.Pa pkg-vulnerabilities +file resides. +Default is +.Pa ${PKG_DBDIR} . +.It Dv PKGVULNURL +URL which is used for updating the local +.Pa pkg-vulnerabilities +file when running +.Dl Ic pkg_admin fetch-pkg-vulnerabilities +The default location is ftp.NetBSD.org using HTTP. +.Em Note : +Usually, only the compression type should be changed. +Currently supported are uncompressed files and files compressed by +.Xr bzip2 1 +.Pq Pa .bz2 +or +.Xr gzip 1 +.Pq Pa .gz . +.It Dv VERBOSE_NETIO +Log details of network IO to stderr. +.It Dv VERIFIED_INSTALLATION +Set trust level used when installation. +Supported values are: +.Bl -tag -width interactiveXX +.It Dv never +No signature checks are performed. +.It Dv always +A valid signature is required. +If the binary package can not be verified, the installation is terminated +.It Dv trusted +A valid signature is required. +If the binary package can not be verified, the user is asked interactively. +.It Dv interactive +The user is always asked interactively when installing a package. +.El +.El +.Sh FILES +.Bl -tag -width ".Pa @SYSCONFDIR@/pkg_install.conf" +.It Pa @SYSCONFDIR@/pkg_install.conf +Default location for the file described in this manual page. +.El +.Sh SEE ALSO +.Xr pkg_add 1 , +.Xr pkg_admin 1 , +.Xr pkg_create 1 , +.Xr pkg_delete 1 , +.Xr pkg_info 1 diff --git a/external/bsd/pkg_install/dist/lib/pkg_io.c b/external/bsd/pkg_install/dist/lib/pkg_io.c new file mode 100644 index 000000000..3639e764c --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/pkg_io.c @@ -0,0 +1,383 @@ +/* $NetBSD: pkg_io.c,v 1.1.1.9 2010/04/23 20:54:11 joerg Exp $ */ +/*- + * Copyright (c) 2008, 2009 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif + +__RCSID("$NetBSD: pkg_io.c,v 1.1.1.9 2010/04/23 20:54:11 joerg Exp $"); + +#include +#include +#if HAVE_ERR_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#include +#include + +#include "lib.h" + +struct pkg_path { + TAILQ_ENTRY(pkg_path) pl_link; + char *pl_path; +}; + +static char *orig_cwd, *last_toplevel; +static TAILQ_HEAD(, pkg_path) pkg_path = TAILQ_HEAD_INITIALIZER(pkg_path); + +struct fetch_archive { + struct url *url; + fetchIO *fetch; + char buffer[32768]; + off_t size; + int restart; +}; + +static int +fetch_archive_open(struct archive *a, void *client_data) +{ + struct fetch_archive *f = client_data; + struct url_stat us; + + f->fetch = fetchXGet(f->url, &us, fetch_flags); + if (f->fetch == NULL) + return ENOENT; + f->size = us.size; + f->restart = 1; + f->url->offset = 0; + return 0; +} + +static ssize_t +fetch_archive_read(struct archive *a, void *client_data, + const void **buffer) +{ + struct fetch_archive *f = client_data; + struct url_stat us; + ssize_t rv; + + *buffer = f->buffer; + rv = fetchIO_read(f->fetch, f->buffer, sizeof(f->buffer)); + if (rv > 0) { + f->url->offset += rv; + return rv; + } + if (f->restart == 0) + return rv; + if (rv == 0) { + if (f->size == -1) + return 0; + if (f->url->offset == f->size) + return 0; + } + f->restart = 0; + if (1) { + char *url = fetchStringifyURL(f->url); + fprintf(stderr, "Trying to reconnect %s\n", url); + free(url); + } + fetchIO_close(f->fetch); + f->fetch = fetchXGet(f->url, &us, fetch_flags); + if (f->fetch == NULL) + return -1; + if (us.size != f->size) + return -1; + rv = fetchIO_read(f->fetch, f->buffer, sizeof(f->buffer)); + if (rv > 0) + f->url->offset += rv; + return rv; +} + +static int +fetch_archive_close(struct archive *a, void *client_data) +{ + struct fetch_archive *f = client_data; + + if (f->fetch != NULL) + fetchIO_close(f->fetch); + fetchFreeURL(f->url); + free(f); + return 0; +} + +static struct archive * +open_archive_by_url(struct url *url, char **archive_name) +{ + struct fetch_archive *f; + struct archive *a; + + f = xmalloc(sizeof(*f)); + f->url = fetchCopyURL(url); + + *archive_name = fetchStringifyURL(url); + + a = archive_read_new(); + archive_read_support_compression_all(a); + archive_read_support_format_all(a); + if (archive_read_open(a, f, fetch_archive_open, fetch_archive_read, + fetch_archive_close)) { + free(*archive_name); + *archive_name = NULL; + archive_read_finish(a); + return NULL; + } + + return a; +} + +struct archive * +open_archive(const char *url, char **archive_name) +{ + struct url *u; + struct archive *a; + + *archive_name = NULL; + + if (!IS_URL(url)) { + a = archive_read_new(); + archive_read_support_compression_all(a); + archive_read_support_format_all(a); + if (archive_read_open_filename(a, url, 1024)) { + archive_read_close(a); + return NULL; + } + *archive_name = xstrdup(url); + return a; + } + + if ((u = fetchParseURL(url)) == NULL) + return NULL; + + a = open_archive_by_url(u, archive_name); + + fetchFreeURL(u); + return a; +} + +static int +strip_suffix(char *filename) +{ + size_t len; + + len = strlen(filename); + if (len <= 4) + return 0; + if (strcmp(filename + len - 4, ".tgz") == 0 || + strcmp(filename + len - 4, ".tbz") == 0) { + filename[len - 4] = '\0'; + return 1; + } else + return 0; +} + +static int +find_best_package_int(struct url *url, const char *pattern, + struct url **best_url) +{ + char *cur_match, *url_pattern, *best_match = NULL; + struct url_list ue; + size_t i; + + if (*best_url) { + if ((best_match = fetchUnquoteFilename(*best_url)) == NULL) + return -1; + } else + best_match = NULL; + + if (best_match && strip_suffix(best_match) == 0) { + free(best_match); + return -1; + } + + for (i = 0; pattern[i] != '\0'; ++i) { + if (!isalnum((unsigned char)(pattern[i])) && + (pattern[i]) != '-') + break; + } + url_pattern = xasprintf("%*.*s*", (int)i, (int)i, pattern); + + fetchInitURLList(&ue); + if (fetchList(&ue, url, url_pattern, fetch_flags)) { + char *base_url; + base_url = fetchStringifyURL(url); + warnx("Can't process %s/%s: %s", base_url, url_pattern, + fetchLastErrString); + free(base_url); + free(url_pattern); + fetchFreeURLList(&ue); + return -1; + } + free(url_pattern); + + for (i = 0; i < ue.length; ++i) { + cur_match = fetchUnquoteFilename(ue.urls + i); + + if (cur_match == NULL) { + free(best_match); + fetchFreeURLList(&ue); + return -1; + } + if (strip_suffix(cur_match) == 0) { + free(cur_match); + continue; + } + if (pkg_order(pattern, cur_match, best_match) == 1) { + if (*best_url) + fetchFreeURL(*best_url); + *best_url = fetchCopyURL(ue.urls + i); + free(best_match); + best_match = cur_match; + cur_match = NULL; + if (*best_url == NULL) { + free(best_match); + return -1; + } + } + free(cur_match); + } + free(best_match); + fetchFreeURLList(&ue); + return 0; +} + +void +process_pkg_path(void) +{ + char cwd[PATH_MAX]; + int relative_path; + struct pkg_path *pl; + const char *start, *next; + size_t len; + + if (getcwd(cwd, sizeof(cwd)) == NULL) + errx(EXIT_FAILURE, "getcwd failed"); + + orig_cwd = xstrdup(cwd); + + if (config_pkg_path == NULL) + return; + + for (start = config_pkg_path; *start; start = next) { + len = strcspn(start, ";"); + if (*(next = start + len) != '\0') + ++next; + + relative_path = !IS_FULLPATH(start) && !IS_URL(start); + pl = xmalloc(sizeof(*pl)); + pl->pl_path = xasprintf("%s%s%*.*s", + relative_path ? cwd : "", len && relative_path ? "/" : "", + (int)len, (int)len, start); + TAILQ_INSERT_TAIL(&pkg_path, pl, pl_link); + } +} + +struct url * +find_best_package(const char *toplevel, const char *pattern, int do_path) +{ + struct url *url, *best_match = NULL; + struct pkg_path *pl; + + if (toplevel) { + url = fetchParseURL(last_toplevel); + if (url != NULL) { + find_best_package_int(url, pattern, &best_match); + /* XXX Check return value and complain */ + fetchFreeURL(url); + } + } + if (!do_path) + return best_match; + + TAILQ_FOREACH(pl, &pkg_path, pl_link) { + url = fetchParseURL(pl->pl_path); + if (url != NULL) { + find_best_package_int(url, pattern, &best_match); + /* XXX Check return value and complain */ + fetchFreeURL(url); + } + } + + return best_match; +} + +struct archive * +find_archive(const char *fname, int top_level, char **archive_name) +{ + struct archive *a; + struct url *best_match; + char *full_fname, *last_slash; + int search_path; + + search_path = 0; + if (IS_FULLPATH(fname) || IS_URL(fname)) { + full_fname = xstrdup(fname); + } else { + if (strchr(fname, '/') == NULL) + search_path = 1; + full_fname = xasprintf("%s/%s", orig_cwd, fname); + } + + last_slash = strrchr(full_fname, '/'); + if (top_level) { + free(last_toplevel); + *last_slash = '\0'; + last_toplevel = xstrdup(full_fname); + *last_slash = '/'; + } + + a = open_archive(full_fname, archive_name); + if (a != NULL) { + free(full_fname); + return a; + } + + fname = last_slash + 1; + *last_slash = '\0'; + + best_match = find_best_package(full_fname, fname, 0); + + if (search_path && best_match == NULL) + best_match = find_best_package(last_toplevel, fname, 1); + + free(full_fname); + + if (best_match == NULL) + return NULL; + a = open_archive_by_url(best_match, archive_name); + fetchFreeURL(best_match); + return a; +} diff --git a/external/bsd/pkg_install/dist/lib/pkg_signature.c b/external/bsd/pkg_install/dist/lib/pkg_signature.c new file mode 100644 index 000000000..8886c7ab6 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/pkg_signature.c @@ -0,0 +1,710 @@ +/* $NetBSD: pkg_signature.c,v 1.2 2013/09/11 12:59:19 khorben Exp $ */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: pkg_signature.c,v 1.2 2013/09/11 12:59:19 khorben Exp $"); + +/*- + * Copyright (c) 2008 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if HAVE_SYS_WAIT_H +#include +#endif +#include +#if HAVE_ERR_H +#include +#endif +#include +#include +#include +#ifndef NETBSD +#include +#else +#include +#endif +#include +#ifdef NETBSD +#include +#else +#include +#endif + +#include +#include + +#include "lib.h" + +#define HASH_FNAME "+PKG_HASH" +#define SIGNATURE_FNAME "+PKG_SIGNATURE" +#define GPG_SIGNATURE_FNAME "+PKG_GPG_SIGNATURE" + +struct signature_archive { + struct archive *archive; + off_t pkg_size; + size_t sign_block_len, sign_block_number, sign_cur_block; + char **sign_blocks; + unsigned char *sign_buf; +}; + +static void +hash_block(unsigned char *buf, size_t buf_len, + char hash[SHA512_DIGEST_STRING_LENGTH]) +{ + unsigned char digest[SHA512_DIGEST_LENGTH]; + SHA512_CTX hash_ctx; + int i; + + SHA512_Init(&hash_ctx); + SHA512_Update(&hash_ctx, buf, buf_len); + SHA512_Final(digest, &hash_ctx); + for (i = 0; i < SHA512_DIGEST_LENGTH; ++i) { + unsigned char c; + + c = digest[i] / 16; + if (c < 10) + hash[2 * i] = '0' + c; + else + hash[2 * i] = 'a' - 10 + c; + + c = digest[i] % 16; + if (c < 10) + hash[2 * i + 1] = '0' + c; + else + hash[2 * i + 1] = 'a' - 10 + c; + } + hash[2 * i] = '\0'; +} + +static ssize_t +verify_signature_read_cb(struct archive *archive, void *cookie, const void **buf) +{ + struct signature_archive *state = cookie; + char hash[SHA512_DIGEST_STRING_LENGTH]; + ssize_t len, expected; + + if (state->sign_cur_block >= state->sign_block_number) + return 0; + + /* The following works for sign_block_len > 1 */ + if (state->sign_cur_block + 1 == state->sign_block_number) + expected = state->pkg_size % state->sign_block_len; + else + expected = state->sign_block_len; + + len = archive_read_data(state->archive, state->sign_buf, expected); + if (len != expected) { + warnx("Short read from package"); + return -1; + } + + hash_block(state->sign_buf, len, hash); + + if (strcmp(hash, state->sign_blocks[state->sign_cur_block]) != 0) { + warnx("Invalid signature of block %llu", + (unsigned long long)state->sign_cur_block); + return -1; + } + ++state->sign_cur_block; + *buf = state->sign_buf; + return len; +} + +static void +free_signature_int(struct signature_archive *state) +{ + size_t i; + + if (state->sign_blocks != NULL) { + for (i = 0; i < state->sign_block_number; ++i) + free(state->sign_blocks[i]); + } + free(state->sign_blocks); + free(state->sign_buf); + free(state); +} + +static int +verify_signature_close_cb(struct archive *archive, void *cookie) +{ + struct signature_archive *state = cookie; + + archive_read_finish(state->archive); + free_signature_int(state); + return 0; +} + +static int +read_file_from_archive(const char *archive_name, struct archive *archive, + struct archive_entry **entry, + const char *fname, char **content, size_t *len) +{ + int r; + + *content = NULL; + *len = 0; + +retry: + if (*entry == NULL && + (r = archive_read_next_header(archive, entry)) != ARCHIVE_OK) { + if (r == ARCHIVE_FATAL) { + warnx("Cannot read from archive `%s': %s", + archive_name, archive_error_string(archive)); + } else { + warnx("Premature end of archive `%s'", archive_name); + } + *entry = NULL; + return -1; + } + if (strcmp(archive_entry_pathname(*entry), "//") == 0) { + archive_read_data_skip(archive); + *entry = NULL; + goto retry; + } + + if (strcmp(fname, archive_entry_pathname(*entry)) != 0) + return 1; + + if (archive_entry_size(*entry) > SSIZE_MAX - 1) { + warnx("Signature of archive `%s' too large to process", + archive_name); + return 1; + } + *len = archive_entry_size(*entry); + *content = xmalloc(*len + 1); + + if (archive_read_data(archive, *content, *len) != (ssize_t)*len) { + warnx("Cannot read complete %s from archive `%s'", fname, + archive_name); + free(*content); + *len = 0; + *content = NULL; + return 1; + } + (*content)[*len] = '\0'; + *entry = NULL; + + return 0; +} + +static int +parse_hash_file(const char *hash_file, char **pkgname, + struct signature_archive *state) +{ + static const char block1[] = "pkgsrc signature\n\nversion: 1\npkgname: "; + static const char block2[] = "algorithm: SHA512\nblock size: "; + static const char block3[] = "file size: "; + static const char block4[] = "end pkgsrc signature\n"; + char *next; + size_t i, len; + + *pkgname = NULL; + + if (strncmp(hash_file, block1, strlen(block1)) != 0) + goto cleanup; + hash_file += strlen(block1); + + len = strcspn(hash_file, "\n"); + *pkgname = xmalloc(len + 1); + memcpy(*pkgname, hash_file, len); + (*pkgname)[len] = '\0'; + for (i = 0; i < len; ++i) { + if (!isgraph((unsigned char)(*pkgname)[i])) + goto cleanup; + } + hash_file += len + 1; + + if (strncmp(hash_file, block2, strlen(block2)) != 0) + goto cleanup; + hash_file += strlen(block2); + + errno = 0; + if (!isdigit((unsigned char)*hash_file)) + goto cleanup; + state->sign_block_len = strtoul(hash_file, &next, 10); + hash_file = next; + + /* Assert sane minimum block size of 1KB */ + if (*hash_file++ != '\n' || errno == ERANGE || state->sign_block_len < 1024) + goto cleanup; + + if (strncmp(hash_file, block3, strlen(block3)) != 0) + goto cleanup; + hash_file += strlen(block3); + + errno = 0; + if (!isdigit((unsigned char)*hash_file)) + goto cleanup; + if (/* CONSTCOND */sizeof(off_t) >= sizeof(long long)) + state->pkg_size = strtoll(hash_file, &next, 10); + else + state->pkg_size = strtol(hash_file, &next, 10); + hash_file = next; + if (*hash_file++ != '\n' || errno == ERANGE || state->pkg_size < 1) + goto cleanup; + + if (*hash_file++ != '\n') + goto cleanup; + + if (state->pkg_size / state->sign_block_len > SSIZE_MAX) + goto cleanup; + state->sign_block_number = (state->pkg_size + + state->sign_block_len - 1) / state->sign_block_len; + + state->sign_buf = xmalloc(state->sign_block_len); + state->sign_blocks = xcalloc(state->sign_block_number, sizeof(char *)); + + for (i = 0; i < state->sign_block_number; ++i) { + len = strspn(hash_file, "01234567889abcdef"); + if (len != SHA512_DIGEST_LENGTH * 2 || hash_file[len] != '\n') + goto cleanup_hashes; + state->sign_blocks[i] = xmalloc(len + 1); + memcpy(state->sign_blocks[i], hash_file, len); + state->sign_blocks[i][len] = '\0'; + hash_file += len + 1; + } + + if (strcmp(hash_file, block4) != 0) + goto cleanup_hashes; + + return 0; + +cleanup_hashes: + for (i = 0; i < state->sign_block_number; ++i) + free(state->sign_blocks[i]); + free(state->sign_blocks); + state->sign_blocks = NULL; + +cleanup: + warnx("Unknown format of hash file"); + free(*pkgname); + *pkgname = NULL; + return -1; +} + +int +pkg_verify_signature(const char *archive_name, struct archive **archive, + struct archive_entry **entry, char **pkgname) +{ + struct signature_archive *state; + struct archive_entry *my_entry; + struct archive *a; + char *hash_file, *signature_file; + size_t hash_len, signature_len; + int r, has_sig; + + *pkgname = NULL; + + state = xcalloc(sizeof(*state), 1); + + r = read_file_from_archive(archive_name, *archive, entry, HASH_FNAME, + &hash_file, &hash_len); + if (r == -1) { + archive_read_finish(*archive); + *archive = NULL; + free(state); + goto no_valid_signature; + } else if (r == 1) { + free(state); + goto no_valid_signature; + } + + if (parse_hash_file(hash_file, pkgname, state)) + goto no_valid_signature; + + r = read_file_from_archive(archive_name, *archive, entry, SIGNATURE_FNAME, + &signature_file, &signature_len); + if (r == -1) { + archive_read_finish(*archive); + *archive = NULL; + free(state); + free(hash_file); + goto no_valid_signature; + } else if (r != 0) { + if (*entry != NULL) + r = read_file_from_archive(archive_name, *archive, + entry, GPG_SIGNATURE_FNAME, + &signature_file, &signature_len); + if (r == -1) { + archive_read_finish(*archive); + *archive = NULL; + free(state); + free(hash_file); + goto no_valid_signature; + } else if (r != 0) { + free(hash_file); + free(state); + goto no_valid_signature; + } + has_sig = !detached_gpg_verify(hash_file, hash_len, + signature_file, signature_len, gpg_keyring_verify); + + free(signature_file); + } else { +#ifdef HAVE_SSL + has_sig = !easy_pkcs7_verify(hash_file, hash_len, signature_file, + signature_len, certs_packages, 1); + + free(signature_file); +#else + warnx("No OpenSSL support compiled in, skipping signature"); + has_sig = 0; + free(signature_file); +#endif + } + + r = archive_read_next_header(*archive, &my_entry); + if (r != ARCHIVE_OK) { + warnx("Cannot read inner package: %s", + archive_error_string(*archive)); + free_signature_int(state); + goto no_valid_signature; + } + + if (archive_entry_size(my_entry) != state->pkg_size) { + warnx("Package size doesn't match signature"); + free_signature_int(state); + goto no_valid_signature; + } + + state->archive = *archive; + + a = archive_read_new(); + archive_read_support_compression_all(a); + archive_read_support_format_all(a); + if (archive_read_open(a, state, NULL, verify_signature_read_cb, + verify_signature_close_cb)) { + warnx("Can't open signed package file"); + archive_read_finish(a); + goto no_valid_signature; + } + *archive = a; + *entry = NULL; + + return has_sig ? 0 : -1; + +no_valid_signature: + return -1; +} + +int +pkg_full_signature_check(const char *archive_name, struct archive **archive) +{ + struct archive_entry *entry = NULL; + char *pkgname; + int r; + + if (pkg_verify_signature(archive_name, archive, &entry, &pkgname)) + return -1; + if (pkgname == NULL) + return 0; + + /* XXX read PLIST and compare pkgname */ + while ((r = archive_read_next_header(*archive, &entry)) == ARCHIVE_OK) + archive_read_data_skip(*archive); + + free(pkgname); + return r == ARCHIVE_EOF ? 0 : -1; +} + +static char * +extract_pkgname(int fd) +{ + package_t plist; + plist_t *p; + struct archive *a; + struct archive_entry *entry; + char *buf; + ssize_t len; + int r; + + a = archive_read_new(); + archive_read_support_compression_all(a); + archive_read_support_format_all(a); + if (archive_read_open_fd(a, fd, 1024)) { + warnx("Cannot open binary package: %s", + archive_error_string(a)); + archive_read_finish(a); + return NULL; + } + + r = archive_read_next_header(a, &entry); + if (r != ARCHIVE_OK) { + warnx("Cannot extract package name: %s", + r == ARCHIVE_EOF ? "EOF" : archive_error_string(a)); + archive_read_finish(a); + return NULL; + } + if (strcmp(archive_entry_pathname(entry), "+CONTENTS") != 0) { + warnx("Invalid binary package, doesn't start with +CONTENTS"); + archive_read_finish(a); + return NULL; + } + if (archive_entry_size(entry) > SSIZE_MAX - 1) { + warnx("+CONTENTS too large to process"); + archive_read_finish(a); + return NULL; + } + + len = archive_entry_size(entry); + buf = xmalloc(len + 1); + + if (archive_read_data(a, buf, len) != len) { + warnx("Short read when extracing +CONTENTS"); + free(buf); + archive_read_finish(a); + return NULL; + } + buf[len] = '\0'; + + archive_read_finish(a); + + parse_plist(&plist, buf); + free(buf); + p = find_plist(&plist, PLIST_NAME); + if (p != NULL) { + buf = xstrdup(p->name); + } else { + warnx("Invalid PLIST: missing @name"); + buf = NULL; + } + free_plist(&plist); + + if (lseek(fd, 0, SEEK_SET) != 0) { + warn("Cannot seek in archive"); + free(buf); + return NULL; + } + + return buf; +} + +static const char hash_template[] = +"pkgsrc signature\n" +"\n" +"version: 1\n" +"pkgname: %s\n" +"algorithm: SHA512\n" +"block size: 65536\n" +"file size: %lld\n" +"\n"; + +static const char hash_trailer[] = "end pkgsrc signature\n"; + +#ifdef HAVE_SSL +void +pkg_sign_x509(const char *name, const char *output, const char *key_file, const char *cert_file) +{ + struct archive *pkg; + struct archive_entry *entry, *hash_entry, *sign_entry; + int fd; + struct stat sb; + char *hash_file, *signature_file, *tmp, *pkgname, hash[SHA512_DIGEST_STRING_LENGTH]; + unsigned char block[65536]; + off_t i, size; + size_t block_len, signature_len; + + if ((fd = open(name, O_RDONLY)) == -1) + err(EXIT_FAILURE, "Cannot open binary package %s", name); + if (fstat(fd, &sb) == -1) + err(EXIT_FAILURE, "Cannot stat %s", name); + + entry = archive_entry_new(); + archive_entry_copy_stat(entry, &sb); + + pkgname = extract_pkgname(fd); + hash_file = xasprintf(hash_template, pkgname, + (long long)archive_entry_size(entry)); + free(pkgname); + + for (i = 0; i < archive_entry_size(entry); i += block_len) { + if (i + (off_t)sizeof(block) < archive_entry_size(entry)) + block_len = sizeof(block); + else + block_len = archive_entry_size(entry) % sizeof(block); + if (read(fd, block, block_len) != (ssize_t)block_len) + err(2, "short read"); + hash_block(block, block_len, hash); + tmp = xasprintf("%s%s\n", hash_file, hash); + free(hash_file); + hash_file = tmp; + } + tmp = xasprintf("%s%s", hash_file, hash_trailer); + free(hash_file); + hash_file = tmp; + + if (easy_pkcs7_sign(hash_file, strlen(hash_file), &signature_file, + &signature_len, key_file, cert_file)) + err(EXIT_FAILURE, "Cannot sign hash file"); + + lseek(fd, 0, SEEK_SET); + + sign_entry = archive_entry_clone(entry); + hash_entry = archive_entry_clone(entry); + pkgname = strrchr(name, '/'); + archive_entry_set_pathname(entry, pkgname != NULL ? pkgname + 1 : name); + archive_entry_set_pathname(hash_entry, HASH_FNAME); + archive_entry_set_pathname(sign_entry, SIGNATURE_FNAME); + archive_entry_set_size(hash_entry, strlen(hash_file)); + archive_entry_set_size(sign_entry, signature_len); + + pkg = archive_write_new(); + archive_write_set_compression_none(pkg); + archive_write_set_format_ar_bsd(pkg); + archive_write_open_filename(pkg, output); + + archive_write_header(pkg, hash_entry); + archive_write_data(pkg, hash_file, strlen(hash_file)); + archive_write_finish_entry(pkg); + archive_entry_free(hash_entry); + + archive_write_header(pkg, sign_entry); + archive_write_data(pkg, signature_file, signature_len); + archive_write_finish_entry(pkg); + archive_entry_free(sign_entry); + + size = archive_entry_size(entry); + archive_write_header(pkg, entry); + + for (i = 0; i < size; i += block_len) { + if (i + (off_t)sizeof(block) < size) + block_len = sizeof(block); + else + block_len = size % sizeof(block); + if (read(fd, block, block_len) != (ssize_t)block_len) + err(2, "short read"); + archive_write_data(pkg, block, block_len); + } + archive_write_finish_entry(pkg); + archive_entry_free(entry); + + archive_write_finish(pkg); + + close(fd); + + exit(0); +} +#endif + +void +pkg_sign_gpg(const char *name, const char *output) +{ + struct archive *pkg; + struct archive_entry *entry, *hash_entry, *sign_entry; + int fd; + struct stat sb; + char *hash_file, *signature_file, *tmp, *pkgname, hash[SHA512_DIGEST_STRING_LENGTH]; + unsigned char block[65536]; + off_t i, size; + size_t block_len, signature_len; + + if ((fd = open(name, O_RDONLY)) == -1) + err(EXIT_FAILURE, "Cannot open binary package %s", name); + if (fstat(fd, &sb) == -1) + err(EXIT_FAILURE, "Cannot stat %s", name); + + entry = archive_entry_new(); + archive_entry_copy_stat(entry, &sb); + + pkgname = extract_pkgname(fd); + hash_file = xasprintf(hash_template, pkgname, + (long long)archive_entry_size(entry)); + free(pkgname); + + for (i = 0; i < archive_entry_size(entry); i += block_len) { + if (i + (off_t)sizeof(block) < archive_entry_size(entry)) + block_len = sizeof(block); + else + block_len = archive_entry_size(entry) % sizeof(block); + if (read(fd, block, block_len) != (ssize_t)block_len) + err(2, "short read"); + hash_block(block, block_len, hash); + tmp = xasprintf("%s%s\n", hash_file, hash); + free(hash_file); + hash_file = tmp; + } + tmp = xasprintf("%s%s", hash_file, hash_trailer); + free(hash_file); + hash_file = tmp; + + if (detached_gpg_sign(hash_file, strlen(hash_file), &signature_file, + &signature_len, gpg_keyring_sign, gpg_sign_as)) + err(EXIT_FAILURE, "Cannot sign hash file"); + + lseek(fd, 0, SEEK_SET); + + sign_entry = archive_entry_clone(entry); + hash_entry = archive_entry_clone(entry); + pkgname = strrchr(name, '/'); + archive_entry_set_pathname(entry, pkgname != NULL ? pkgname + 1 : name); + archive_entry_set_pathname(hash_entry, HASH_FNAME); + archive_entry_set_pathname(sign_entry, GPG_SIGNATURE_FNAME); + archive_entry_set_size(hash_entry, strlen(hash_file)); + archive_entry_set_size(sign_entry, signature_len); + + pkg = archive_write_new(); + archive_write_set_compression_none(pkg); + archive_write_set_format_ar_bsd(pkg); + archive_write_open_filename(pkg, output); + + archive_write_header(pkg, hash_entry); + archive_write_data(pkg, hash_file, strlen(hash_file)); + archive_write_finish_entry(pkg); + archive_entry_free(hash_entry); + + archive_write_header(pkg, sign_entry); + archive_write_data(pkg, signature_file, signature_len); + archive_write_finish_entry(pkg); + archive_entry_free(sign_entry); + + size = archive_entry_size(entry); + archive_write_header(pkg, entry); + + for (i = 0; i < size; i += block_len) { + if (i + (off_t)sizeof(block) < size) + block_len = sizeof(block); + else + block_len = size % sizeof(block); + if (read(fd, block, block_len) != (ssize_t)block_len) + err(2, "short read"); + archive_write_data(pkg, block, block_len); + } + archive_write_finish_entry(pkg); + archive_entry_free(entry); + + archive_write_finish(pkg); + + close(fd); + + exit(0); +} diff --git a/external/bsd/pkg_install/dist/lib/pkg_summary.5 b/external/bsd/pkg_install/dist/lib/pkg_summary.5 new file mode 100644 index 000000000..110b7dddc --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/pkg_summary.5 @@ -0,0 +1,138 @@ +.\" $NetBSD: pkg_summary.5,v 1.4 2012/02/19 17:49:09 tron Exp $ +.\" +.\" Copyright (c) 2006 The NetBSD Foundation +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the NetBSD Foundation nor the names of its +.\" contributors may be used to endorse or promote products derived from +.\" this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION AND ITS CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT +.\" NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +.\" FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +.\" SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd April 11, 2009 +.Dt PKG_SUMMARY 5 +.Os +.Sh NAME +.Nm pkg_summary +.Nd summary of binary package repository +.Sh DESCRIPTION +The file +.Nm +contains information about each package in a binary package +repository as a list of variable-value pairs. +The variables describing different packages are separated by one empty +line. +Each line has the format +.Ev VARIABLE=VALUE . +If the value consists of more than one line, each line is prefixed with +.Ev VARIABLE= . +Multi-line variables are guaranteed to be in consecutive lines. +.Pp +The following variables are used: +.Bl -tag -width indent +.It Ev BUILD_DATE +(required) The date and time when the package was built. +.It Ev CATEGORIES +(required) A list of categories which this package fits in, separated by +space. +.It Ev COMMENT +(required) A one-line description of the package. +.It Ev CONFLICTS +(optional) A list of dewey patterns of packages the package conflicts +with, one per line. +If missing, this package has no conflicts. +.It Ev DEPENDS +(optional) A list of dewey patterns of packages the package depends +on, one per line. +If missing, this package has no dependencies. +.It Ev DESCRIPTION +(required) A more detailed description of the package. +.\" DIGEST +.It Ev FILE_CKSUM +(optional) A checksum type supported by +.Xr digest 1 +and checksum separated by space character. +.It Ev FILE_NAME +(optional) The name of the binary package file. +If not given, +.Pa PKGNAME.tgz +can be assumed. +.It Ev FILE_SIZE +(optional) The size of the binary package file, in bytes. +.It Ev HOMEPAGE +(optional) A URL where more information about the package can be found. +.It Ev LICENSE +(optional) The type of license this package is distributed under. +If empty or missing, it is OSI-approved. +.It Ev MACHINE_ARCH +(required) The architecture on which the package was compiled. +.It Ev OPSYS +(required) The operating system on which the package was compiled. +.It Ev OS_VERSION +(required) The version of the operating system on which the package +was compiled. +.It Ev PKG_OPTIONS +(optional) Any options selected to compile this package. +If missing, the package does not support options. +.It Ev PKGNAME +(required) The name of the package. +.It Ev PKGPATH +(required) The path of the package directory within pkgsrc. +.It Ev PKGTOOLS_VERSION +(required) The version of the package tools used to create the package. +.It Ev PREV_PKGPATH +(optional) The previous path of the package directory within pkgsrc when +a package was moved. +(See +.Ev SUPERSEDES +below for a renamed package.) +.It Ev PROVIDES +(optional) A list of shared libraries provided by the package, +including major version number, one per line. +If missing, this package does not provide shared libraries. +.It Ev REQUIRES +(optional) A list of shared libraries needed by the package, including +major version number, one per line. +If missing, this package does not require shared libraries. +.It Ev SIZE_PKG +(required) The size of the package when installed, in bytes. +.It Ev SUPERSEDES +(optional) A list of dewey patterns of previous packages this +package replaces, one per line. +This is used for package renaming. +.El +.Pp +The +.Nm pkg_summary +file can be generated using the +.Xr pkg_info 1 +.Fl X +option. +For example, the following will list this data for all installed packages: +.Pp +.Dl "pkg_info -X -a" +.Sh SEE ALSO +.Xr digest 1 , +.Xr pkg_info 1 +.Sh HISTORY +The +.Nm pkg_summary +format was first officially documented in April 2006. diff --git a/external/bsd/pkg_install/dist/lib/pkgdb.c b/external/bsd/pkg_install/dist/lib/pkgdb.c new file mode 100644 index 000000000..098e5f02a --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/pkgdb.c @@ -0,0 +1,339 @@ +/* $NetBSD: pkgdb.c,v 1.1.1.8 2010/04/23 20:54:11 joerg Exp $ */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: pkgdb.c,v 1.1.1.8 2010/04/23 20:54:11 joerg Exp $"); + +/*- + * Copyright (c) 1999-2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Hubert Feyrer . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef NETBSD +#include +#else +#include +#endif +#if HAVE_ERR_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif +#if HAVE_STDARG_H +#include +#endif +#if HAVE_STDIO_H +#include +#endif +#if HAVE_STRING_H +#include +#endif + +#include "lib.h" + +#define PKGDB_FILE "pkgdb.byfile.db" /* indexed by filename */ + +/* + * Where we put logging information by default if PKG_DBDIR is unset. + */ +#ifndef DEF_LOG_DIR +#define DEF_LOG_DIR "/var/db/pkg" +#endif + +/* just in case we change the environment variable name */ +#define PKG_DBDIR "PKG_DBDIR" + +static DB *pkgdbp; +static char pkgdb_dir_default[] = DEF_LOG_DIR; +static char *pkgdb_dir = pkgdb_dir_default; +static int pkgdb_dir_prio = 0; + +/* + * Return name of cache file in the buffer that was passed. + */ +char * +pkgdb_get_database(void) +{ + return xasprintf("%s/%s", pkgdb_get_dir(), PKGDB_FILE); +} + +/* + * Open the pkg-database + * Return value: + * 1: everything ok + * 0: error + */ +int +pkgdb_open(int mode) +{ + BTREEINFO info; + char *cachename; + + /* try our btree format first */ + info.flags = 0; + info.cachesize = 2*1024*1024; + info.maxkeypage = 0; + info.minkeypage = 0; + info.psize = 4096; + info.compare = NULL; + info.prefix = NULL; + info.lorder = 0; + cachename = pkgdb_get_database(); + pkgdbp = (DB *) dbopen(cachename, + (mode == ReadOnly) ? O_RDONLY : O_RDWR | O_CREAT, + 0644, DB_BTREE, (void *) &info); + free(cachename); + return (pkgdbp != NULL); +} + +/* + * Close the pkg database + */ +void +pkgdb_close(void) +{ + if (pkgdbp != NULL) { + (void) (*pkgdbp->close) (pkgdbp); + pkgdbp = NULL; + } +} + +/* + * Store value "val" with key "key" in database + * Return value is as from ypdb_store: + * 0: ok + * 1: key already present + * -1: some other error, see errno + */ +int +pkgdb_store(const char *key, const char *val) +{ + DBT keyd, vald; + + if (pkgdbp == NULL) + return -1; + + keyd.data = __UNCONST(key); + keyd.size = strlen(key) + 1; + vald.data = __UNCONST(val); + vald.size = strlen(val) + 1; + + if (keyd.size > MaxPathSize || vald.size > MaxPathSize) + return -1; + + return (*pkgdbp->put) (pkgdbp, &keyd, &vald, R_NOOVERWRITE); +} + +/* + * Recall value for given key + * Return value: + * NULL if some error occurred or value for key not found (check errno!) + * String for "value" else + */ +char * +pkgdb_retrieve(const char *key) +{ + DBT keyd, vald; + int status; + char *eos; + static int corruption_warning; + + if (pkgdbp == NULL) + return NULL; + + keyd.data = __UNCONST(key); + keyd.size = strlen(key) + 1; + errno = 0; /* to be sure it's 0 if the key doesn't match anything */ + + vald.data = (void *)NULL; + vald.size = 0; + status = (*pkgdbp->get) (pkgdbp, &keyd, &vald, 0); + if (status) + return NULL; + eos = memchr(vald.data, 0, vald.size); + if (eos == NULL || eos + 1 != (char *)vald.data + vald.size) { + if (!corruption_warning) { + warnx("pkgdb corrupted, please run ``pkg_admin rebuild''"); + corruption_warning = 1; + } + return NULL; + } + + return vald.data; +} + +/* dump contents of the database to stdout */ +int +pkgdb_dump(void) +{ + DBT key; + DBT val; + int type; + + if (pkgdb_open(ReadOnly)) { + for (type = R_FIRST ; (*pkgdbp->seq)(pkgdbp, &key, &val, type) == 0 ; type = R_NEXT) { + printf("file: %.*s pkg: %.*s\n", + (int) key.size, (char *) key.data, + (int) val.size, (char *) val.data); + } + pkgdb_close(); + return 0; + } else + return -1; +} + +/* + * Remove data set from pkgdb + * Return value as ypdb_delete: + * 0: everything ok + * 1: key not present + * -1: some error occurred (see errno) + */ +int +pkgdb_remove(const char *key) +{ + DBT keyd; + + if (pkgdbp == NULL) + return -1; + + keyd.data = __UNCONST(key); + keyd.size = strlen(key) + 1; + if (keyd.size > MaxPathSize) + return -1; + + return (*pkgdbp->del) (pkgdbp, &keyd, 0); +} + +/* + * Remove any entry from the cache which has a data field of `pkg'. + * Return value: + * 1: everything ok + * 0: error + */ +int +pkgdb_remove_pkg(const char *pkg) +{ + DBT data; + DBT key; + int type; + int ret; + size_t cc; + char *cachename; + + if (pkgdbp == NULL) { + return 0; + } + cachename = pkgdb_get_database(); + cc = strlen(pkg); + for (ret = 1, type = R_FIRST; (*pkgdbp->seq)(pkgdbp, &key, &data, type) == 0 ; type = R_NEXT) { + if ((cc + 1) == data.size && strncmp(data.data, pkg, cc) == 0) { + if (Verbose) { + printf("Removing file `%s' from %s\n", (char *)key.data, cachename); + } + switch ((*pkgdbp->del)(pkgdbp, &key, 0)) { + case -1: + warn("Error removing `%s' from %s", (char *)key.data, cachename); + ret = 0; + break; + case 1: + warn("Key `%s' not present in %s", (char *)key.data, cachename); + ret = 0; + break; + + } + } + } + free(cachename); + return ret; +} + +/* + * Return the location of the package reference counts database directory. + */ +char * +pkgdb_refcount_dir(void) +{ + static char buf[MaxPathSize]; + char *tmp; + + if ((tmp = getenv(PKG_REFCOUNT_DBDIR_VNAME)) != NULL) + strlcpy(buf, tmp, sizeof(buf)); + else + snprintf(buf, sizeof(buf), "%s.refcount", pkgdb_get_dir()); + return buf; +} + +/* + * Return directory where pkgdb is stored + */ +const char * +pkgdb_get_dir(void) +{ + + return pkgdb_dir; +} + +/* + * Set the first place we look for where pkgdb is stored. + */ +void +pkgdb_set_dir(const char *dir, int prio) +{ + + if (prio < pkgdb_dir_prio) + return; + + pkgdb_dir_prio = prio; + + if (dir == pkgdb_dir) + return; + if (pkgdb_dir != pkgdb_dir_default) + free(pkgdb_dir); + pkgdb_dir = xstrdup(dir); +} + +char * +pkgdb_pkg_dir(const char *pkg) +{ + return xasprintf("%s/%s", pkgdb_get_dir(), pkg); +} + +char * +pkgdb_pkg_file(const char *pkg, const char *file) +{ + return xasprintf("%s/%s/%s", pkgdb_get_dir(), pkg, file); +} diff --git a/external/bsd/pkg_install/dist/lib/pkgsrc.7 b/external/bsd/pkg_install/dist/lib/pkgsrc.7 new file mode 100644 index 000000000..db7bb2e53 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/pkgsrc.7 @@ -0,0 +1,54 @@ +.\" $NetBSD: pkgsrc.7,v 1.1.1.1 2008/09/30 19:00:27 joerg Exp $ +.\" +.\" Copyright (c) 2007 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Thomas Klausner. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd March 2, 2007 +.Dt PKGSRC 7 +.Os +.Sh NAME +.Nm pkgsrc +.Nd NetBSD packages collection (framework for third-party software) +.Sh DESCRIPTION +The +.Nx +Packages Collection (pkgsrc) is a framework for building and +maintaining third-party software on +.Nx +and other +.Ux Ns -like +systems. +It is used to enable freely available software to be configured +and built easily on supported platforms. +.Pp +Tools are available to install ready-to-use packages and to perform +various administrative tasks for the package system. +.Sh SEE ALSO +.Xr pkg_add 1 , +.Xr pkg_delete 1 , +.Xr pkg_info 1 , +.Pa http://www.netbsd.org/docs/pkgsrc/ diff --git a/external/bsd/pkg_install/dist/lib/plist.c b/external/bsd/pkg_install/dist/lib/plist.c new file mode 100644 index 000000000..64aaa1217 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/plist.c @@ -0,0 +1,783 @@ +/* $NetBSD: plist.c,v 1.1.1.5 2009/08/06 16:55:28 joerg Exp $ */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: plist.c,v 1.1.1.5 2009/08/06 16:55:28 joerg Exp $"); + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * General packing list routines. + * + */ + +/*- + * Copyright (c) 2008, 2009 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "lib.h" +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_ERR_H +#include +#endif +#ifndef NETBSD +#include +#else +#include +#endif + +static int delete_with_parents(const char *, Boolean, Boolean); + +/* This struct defines a plist command type */ +typedef struct cmd_t { + const char *c_s; /* string to recognise */ + pl_ent_t c_type; /* type of command */ + int c_argc; /* # of arguments */ + int c_subst; /* can substitute real prefix */ +} cmd_t; + +/* Commands to recognise */ +static const cmd_t cmdv[] = { + {"cwd", PLIST_CWD, 1, 1}, + {"src", PLIST_SRC, 1, 1}, + {"exec", PLIST_CMD, 1, 0}, + {"unexec", PLIST_UNEXEC, 1, 0}, + {"mode", PLIST_CHMOD, 1, 0}, + {"owner", PLIST_CHOWN, 1, 0}, + {"group", PLIST_CHGRP, 1, 0}, + {"comment", PLIST_COMMENT, 1, 0}, + {"ignore", PLIST_IGNORE, 0, 0}, + {"name", PLIST_NAME, 1, 0}, + {"display", PLIST_DISPLAY, 1, 0}, + {"pkgdep", PLIST_PKGDEP, 1, 0}, + {"pkgcfl", PLIST_PKGCFL, 1, 0}, + {"pkgdir", PLIST_PKGDIR, 1, 0}, + {"dirrm", PLIST_DIR_RM, 1, 0}, + {"option", PLIST_OPTION, 1, 0}, + {"blddep", PLIST_BLDDEP, 1, 0}, + {NULL, FAIL, 0, 0} +}; + +/* + * Add an item to the end of a packing list + */ +void +add_plist(package_t *p, pl_ent_t type, const char *arg) +{ + plist_t *tmp; + + tmp = new_plist_entry(); + tmp->name = (arg == NULL) ? NULL : xstrdup(arg); + tmp->type = type; + if (!p->head) { + p->head = p->tail = tmp; + } else { + tmp->prev = p->tail; + p->tail->next = tmp; + p->tail = tmp; + } +} + +/* + * Add an item to the start of a packing list + */ +void +add_plist_top(package_t *p, pl_ent_t type, const char *arg) +{ + plist_t *tmp; + + tmp = new_plist_entry(); + tmp->name = (arg == NULL) ? NULL : xstrdup(arg); + tmp->type = type; + if (!p->head) { + p->head = p->tail = tmp; + } else { + tmp->next = p->head; + p->head->prev = tmp; + p->head = tmp; + } +} + +/* + * Return the last (most recent) entry in a packing list + */ +plist_t * +last_plist(package_t *p) +{ + return p->tail; +} + +/* + * Mark all items in a packing list to prevent iteration over them + */ +void +mark_plist(package_t *pkg) +{ + plist_t *pp; + + for (pp = pkg->head; pp; pp = pp->next) { + pp->marked = TRUE; + } +} + +/* + * Find a given item in a packing list and, if so, return it (else NULL) + */ +plist_t * +find_plist(package_t *pkg, pl_ent_t type) +{ + plist_t *pp; + + for (pp = pkg->head; pp && pp->type != type; pp = pp->next) { + } + return pp; +} + +/* + * Look for a specific boolean option argument in the list + */ +char * +find_plist_option(package_t *pkg, const char *name) +{ + plist_t *p; + + for (p = pkg->head; p; p = p->next) { + if (p->type == PLIST_OPTION + && strcmp(p->name, name) == 0) { + return p->name; + } + } + + return (char *) NULL; +} + +/* + * Delete plist item 'type' in the list (if 'name' is non-null, match it + * too.) If 'all' is set, delete all items, not just the first occurance. + */ +void +delete_plist(package_t *pkg, Boolean all, pl_ent_t type, char *name) +{ + plist_t *p = pkg->head; + + while (p) { + plist_t *pnext = p->next; + + if (p->type == type && (!name || !strcmp(name, p->name))) { + free(p->name); + if (p->prev) + p->prev->next = pnext; + else + pkg->head = pnext; + if (pnext) + pnext->prev = p->prev; + else + pkg->tail = p->prev; + free(p); + if (!all) + return; + p = pnext; + } else + p = p->next; + } +} + +/* + * Allocate a new packing list entry, and return a pointer to it. + */ +plist_t * +new_plist_entry(void) +{ + return xcalloc(1, sizeof(plist_t)); +} + +/* + * Free an entire packing list + */ +void +free_plist(package_t *pkg) +{ + plist_t *p = pkg->head; + + while (p) { + plist_t *p1 = p->next; + + free(p->name); + free(p); + p = p1; + } + pkg->head = pkg->tail = NULL; +} + +/* + * For an ASCII string denoting a plist command, return its code and + * optionally its argument(s) + */ +static int +plist_cmd(const char *s, char **arg) +{ + const cmd_t *cmdp; + const char *cp, *sp; + char *sp2; + + sp = NULL; /* Older GCC can't detect that the loop is executed */ + + for (cmdp = cmdv; cmdp->c_s; ++cmdp) { + for (sp = s, cp = cmdp->c_s; *sp && *cp; ++cp, ++sp) + if (*sp != *cp) + break; + if (*cp == '\0') + break; + } + + if (cmdp->c_s == NULL || arg == NULL) + return cmdp->c_type; + + while (isspace((unsigned char)*sp)) + ++sp; + *arg = xstrdup(sp); + if (*sp) { + sp2 = *arg + strlen(*arg) - 1; + /* + * The earlier loop ensured that at least one non-whitespace + * is in the string. + */ + while (isspace((unsigned char)*sp2)) + --sp2; + sp2[1] = '\0'; + } + return cmdp->c_type; +} + +/* + * Parse a packaging list from a memory buffer. + */ +void +parse_plist(package_t *pkg, const char *buf) +{ + int cmd; + char *line, *cp; + const char *eol, *next; + size_t len; + + pkg->head = NULL; + pkg->tail = NULL; + + for (; *buf; buf = next) { + /* Until add_plist can deal with trailing whitespace. */ + if ((eol = strchr(buf, '\n')) != NULL) { + next = eol + 1; + len = eol - buf; + } else { + len = strlen(buf); + next = buf + len; + } + + while (len && isspace((unsigned char)buf[len - 1])) + --len; + + if (len == 0) + continue; + + line = xmalloc(len + 1); + memcpy(line, buf, len); + line[len] = '\0'; + + if (*(cp = line) == CMD_CHAR) { + if ((cmd = plist_cmd(line + 1, &cp)) == FAIL) { + warnx("Unrecognised PLIST command `%s'", line); + continue; + } + if (*cp == '\0') { + free(cp); + cp = NULL; + } + } else { + cmd = PLIST_FILE; + } + add_plist(pkg, cmd, cp); + free(cp); + } +} + +/* + * Read a packing list from a file + */ +void +append_plist(package_t *pkg, FILE * fp) +{ + char pline[MaxPathSize]; + char *cp; + int cmd; + int len; + int free_cp; + + while (fgets(pline, MaxPathSize, fp) != (char *) NULL) { + for (len = strlen(pline); len && + isspace((unsigned char) pline[len - 1]);) { + pline[--len] = '\0'; + } + if (len == 0) { + continue; + } + free_cp = 0; + if (*(cp = pline) == CMD_CHAR) { + if ((cmd = plist_cmd(pline + 1, &cp)) == FAIL) { + warnx("Unrecognised PLIST command `%s'", pline); + continue; + } + if (*cp == '\0') { + free(cp); + cp = NULL; + } + free_cp = 1; + } else { + cmd = PLIST_FILE; + } + add_plist(pkg, cmd, cp); + if (free_cp) + free(cp); + } +} + +void +read_plist(package_t *pkg, FILE * fp) +{ + pkg->head = NULL; + pkg->tail = NULL; + + append_plist(pkg, fp); +} + +/* + * Write a packing list to a file, converting commands to ASCII equivs + */ +void +write_plist(package_t *pkg, FILE * fp, char *realprefix) +{ + plist_t *p; + const cmd_t *cmdp; + + for (p = pkg->head; p; p = p->next) { + if (p->type == PLIST_FILE) { + /* Fast-track files - these are the most common */ + (void) fprintf(fp, "%s\n", p->name); + continue; + } + for (cmdp = cmdv; cmdp->c_type != FAIL && cmdp->c_type != p->type; cmdp++) { + } + if (cmdp->c_type == FAIL) { + warnx("Unknown PLIST command type %d (%s)", p->type, p->name); + } else if (cmdp->c_argc == 0) { + (void) fprintf(fp, "%c%s\n", CMD_CHAR, cmdp->c_s); + } else if (cmdp->c_subst && realprefix) { + (void) fprintf(fp, "%c%s %s\n", CMD_CHAR, cmdp->c_s, realprefix); + } else { + (void) fprintf(fp, "%c%s %s\n", CMD_CHAR, cmdp->c_s, + (p->name) ? p->name : ""); + } + } +} + +/* + * Like write_plist, but compute memory string. + */ +void +stringify_plist(package_t *pkg, char **real_buf, size_t *real_len, + const char *realprefix) +{ + plist_t *p; + const cmd_t *cmdp; + char *buf; + size_t len; + int item_len; + + /* Pass One: compute output size only. */ + len = 0; + + for (p = pkg->head; p; p = p->next) { + if (p->type == PLIST_FILE) { + len += strlen(p->name) + 1; + continue; + } + for (cmdp = cmdv; cmdp->c_type != FAIL && cmdp->c_type != p->type; cmdp++) { + } + if (cmdp->c_type == FAIL) + continue; + if (cmdp->c_argc == 0) + len += 1 + strlen(cmdp->c_s) + 1; + else if (cmdp->c_subst && realprefix) + len += 1 + strlen(cmdp->c_s) + 1 + strlen(realprefix) + 1; + else + len += 1 + strlen(cmdp->c_s) + 1 + strlen(p->name ? p->name : "") + 1; + } + + /* Pass Two: build actual string. */ + buf = xmalloc(len + 1); + *real_buf = buf; + *real_len = len; + ++len; + +#define UPDATE_LEN \ +do { \ + if (item_len < 0 || (size_t)item_len > len) \ + errx(2, "Size computation failed, aborted."); \ + buf += item_len; \ + len -= item_len; \ +} while (/* CONSTCOND */0) + + for (p = pkg->head; p; p = p->next) { + if (p->type == PLIST_FILE) { + /* Fast-track files - these are the most common */ + item_len = snprintf(buf, len, "%s\n", p->name); + UPDATE_LEN; + continue; + } + for (cmdp = cmdv; cmdp->c_type != FAIL && cmdp->c_type != p->type; cmdp++) { + } + if (cmdp->c_type == FAIL) { + warnx("Unknown PLIST command type %d (%s)", p->type, p->name); + } else if (cmdp->c_argc == 0) { + item_len = snprintf(buf, len, "%c%s\n", CMD_CHAR, cmdp->c_s); + UPDATE_LEN; + } else if (cmdp->c_subst && realprefix) { + item_len = snprintf(buf, len, "%c%s %s\n", CMD_CHAR, cmdp->c_s, realprefix); + UPDATE_LEN; + } else { + item_len = snprintf(buf, len, "%c%s %s\n", CMD_CHAR, cmdp->c_s, + (p->name) ? p->name : ""); + UPDATE_LEN; + } + } + + if (len != 1) + errx(2, "Size computation failed, aborted."); +} + +/* + * Delete the results of a package installation. + * + * This is here rather than in the pkg_delete code because pkg_add needs to + * run it too in cases of failure. + */ +int +delete_package(Boolean ign_err, package_t *pkg, Boolean NoDeleteFiles, + const char *destdir) +{ + plist_t *p; + const char *last_file = ""; + int fail = SUCCESS; + Boolean preserve; + char tmp[MaxPathSize]; + const char *prefix = NULL, *name = NULL; + + if (!pkgdb_open(ReadWrite)) { + err(EXIT_FAILURE, "cannot open pkgdb"); + } + + preserve = find_plist_option(pkg, "preserve") ? TRUE : FALSE; + + for (p = pkg->head; p; p = p->next) { + switch (p->type) { + case PLIST_NAME: + name = p->name; + break; + case PLIST_CWD: + if (prefix == NULL) + prefix = p->name; + break; + default: + break; + } + } + + if (name == NULL || prefix == NULL) + errx(EXIT_FAILURE, "broken PLIST"); + + /* + * Remove database entries first, directory removal is done + * in the main loop below. + */ + for (p = pkg->head; p; p = p->next) { + if (p->type == PLIST_PKGDIR) + delete_pkgdir(name, prefix, p->name); + } + + for (p = pkg->head; p; p = p->next) { + switch (p->type) { + case PLIST_NAME: + /* Handled already */ + break; + + case PLIST_PKGDIR: + case PLIST_DIR_RM: + (void) snprintf(tmp, sizeof(tmp), "%s/%s", + prefix, p->name); + if (has_pkgdir(tmp)) + continue; + (void) snprintf(tmp, sizeof(tmp), "%s%s%s/%s", + destdir ? destdir : "", destdir ? "/" : "", + prefix, p->name); + if (!fexists(tmp)) { + if (p->type == PLIST_PKGDIR) + warnx("Directory `%s' disappeared, skipping", tmp); + } else if (!isdir(tmp)) { + warnx("attempting to delete a file `%s' as a directory\n" + "this packing list is incorrect - ignoring delete request", tmp); + } else if (delete_with_parents(tmp, ign_err, TRUE)) + fail = FAIL; + break; + + case PLIST_IGNORE: + p = p->next; + break; + + case PLIST_UNEXEC: + if (NoDeleteFiles) + break; + format_cmd(tmp, sizeof(tmp), p->name, prefix, last_file); + printf("Executing `%s'\n", tmp); + if (!Fake && system(tmp)) { + warnx("unexec command for `%s' failed", tmp); + fail = FAIL; + } + break; + + case PLIST_FILE: + last_file = p->name; + (void) snprintf(tmp, sizeof(tmp), "%s%s%s/%s", + destdir ? destdir : "", destdir ? "/" : "", + prefix, p->name); + if (isdir(tmp)) { + warnx("attempting to delete directory `%s' as a file\n" + "this packing list is incorrect - ignoring delete request", tmp); + } else { + int restored = 0; /* restored from preserve? */ + + if (p->next && p->next->type == PLIST_COMMENT) { + if (strncmp(p->next->name, CHECKSUM_HEADER, ChecksumHeaderLen) == 0) { + char *cp, buf[LegibleChecksumLen]; + + if ((cp = MD5File(tmp, buf)) != NULL) { + /* Mismatch? */ + if (strcmp(cp, p->next->name + ChecksumHeaderLen) != 0) { + printf("original MD5 checksum failed, %s: %s\n", + Force ? "deleting anyway" : "not deleting", tmp); + if (!Force) { + fail = FAIL; + goto pkgdb_cleanup; + } + } + } + } else if (strncmp(p->next->name, SYMLINK_HEADER, SymlinkHeaderLen) == 0) { + char buf[MaxPathSize + SymlinkHeaderLen]; + int cc; + + (void) strlcpy(buf, SYMLINK_HEADER, + sizeof(buf)); + if ((cc = readlink(tmp, &buf[SymlinkHeaderLen], + sizeof(buf) - SymlinkHeaderLen - 1)) < 0) { + warn("can't readlink `%s'", tmp); + goto pkgdb_cleanup; + } + buf[SymlinkHeaderLen + cc] = 0x0; + if (strcmp(buf, p->next->name) != 0) { + if ((cc = readlink(&buf[SymlinkHeaderLen], &buf[SymlinkHeaderLen], + sizeof(buf) - SymlinkHeaderLen)) < 0) { + printf("symlink %s is not same as recorded value, %s: %s\n", + buf, Force ? "deleting anyway" : "not deleting", tmp); + if (!Force) { + fail = FAIL; + goto pkgdb_cleanup; + } + } + buf[SymlinkHeaderLen + cc] = 0x0; + if (strcmp(buf, p->next->name) != 0) { + printf("symlink %s is not same as recorded value, %s: %s\n", + buf, Force ? "deleting anyway" : "not deleting", tmp); + if (!Force) { + fail = FAIL; + goto pkgdb_cleanup; + } + } + } + } + } + if (Verbose && !NoDeleteFiles) + printf("Delete file %s\n", tmp); + if (!Fake && !NoDeleteFiles) { + if (delete_with_parents(tmp, ign_err, FALSE)) + fail = FAIL; + if (preserve && name) { + char tmp2[MaxPathSize]; + + if (make_preserve_name(tmp2, MaxPathSize, name, tmp)) { + if (fexists(tmp2)) { + if (rename(tmp2, tmp)) + warn("preserve: unable to restore %s as %s", + tmp2, tmp); + else + restored = 1; + } + } + } + } + +pkgdb_cleanup: + if (!Fake) { + if (!restored) { + errno = 0; + if (pkgdb_remove(tmp) && errno) + perror("pkgdb_remove"); + } + } + } + break; + default: + break; + } + } + pkgdb_close(); + return fail; +} + +/* + * Selectively delete a hierarchy + * Returns 1 on error, 0 else. + */ +static int +delete_with_parents(const char *fname, Boolean ign_err, Boolean ign_nonempty) +{ + char *cp, *cp2; + + if (remove(fname)) { + if (!ign_err && (!ign_nonempty || errno != ENOTEMPTY)) + warnx("Couldn't remove %s", fname); + return 0; + } + cp = xstrdup(fname); + while (*cp) { + if ((cp2 = strrchr(cp, '/')) != NULL) + *cp2 = '\0'; + if (!isemptydir(cp)) + break; + if (has_pkgdir(cp)) + break; + if (rmdir(cp)) + break; + } + free(cp); + + return 0; +} + +void +add_pkgdir(const char *pkg, const char *prefix, const char *path) +{ + char *fullpath, *oldvalue, *newvalue; + + fullpath = xasprintf("%s/%s", prefix, path); + oldvalue = pkgdb_retrieve(fullpath); + if (oldvalue) { + if (strncmp(oldvalue, "@pkgdir ", 8) != 0) + errx(EXIT_FAILURE, "Internal error while processing pkgdb, run pkg_admin rebuild"); + newvalue = xasprintf("%s %s", oldvalue, pkg); + pkgdb_remove(fullpath); + } else { + newvalue = xasprintf("@pkgdir %s", pkg); + } + pkgdb_store(fullpath, newvalue); + + free(fullpath); + free(newvalue); +} + +void +delete_pkgdir(const char *pkg, const char *prefix, const char *path) +{ + size_t pkg_len, len; + char *fullpath, *oldvalue, *newvalue, *iter; + + fullpath = xasprintf("%s/%s", prefix, path); + oldvalue = pkgdb_retrieve(fullpath); + if (oldvalue && strncmp(oldvalue, "@pkgdir ", 8) == 0) { + newvalue = xstrdup(oldvalue); + iter = newvalue + 8; + pkg_len = strlen(pkg); + while (*iter) { + if (strncmp(iter, pkg, pkg_len) == 0 && + (iter[pkg_len] == ' ' || iter[pkg_len] == '\0')) { + len = strlen(iter + pkg_len); + memmove(iter, iter + pkg_len + 1, len); + if (len == 0) + *iter = '\0'; + } else { + iter += strcspn(iter, " "); + iter += strspn(iter, " "); + } + } + pkgdb_remove(fullpath); + if (iter != newvalue + 8) + pkgdb_store(fullpath, newvalue); + free(newvalue); + } + free(fullpath); +} + +int +has_pkgdir(const char *path) +{ + const char *value; + + value = pkgdb_retrieve(path); + + if (value && strncmp(value, "@pkgdir ", 8) == 0) + return 1; + else + return 0; +} diff --git a/external/bsd/pkg_install/dist/lib/remove.c b/external/bsd/pkg_install/dist/lib/remove.c new file mode 100644 index 000000000..fc767b930 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/remove.c @@ -0,0 +1,195 @@ +/* $NetBSD: remove.c,v 1.1.1.2 2009/08/06 16:55:29 joerg Exp $ */ + +/*- + * Copyright (c) 2008 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#if HAVE_SYS_CDEFS_H +#include +#endif + +__RCSID("$NetBSD: remove.c,v 1.1.1.2 2009/08/06 16:55:29 joerg Exp $"); + +#if HAVE_DIRENT_H +#include +#endif +#if HAVE_ERR_H +#include +#endif +#include +#if HAVE_FCNTL_H +#include +#endif +#include +#include +#include +#include +#include + +#include "lib.h" + +static int +safe_fchdir(int cwd) +{ + int tmp_errno, rv; + + tmp_errno = errno; + rv = fchdir(cwd); + errno = tmp_errno; + + return rv; +} + +static int +long_remove(const char **path_ptr, int missing_ok, int *did_chdir) +{ + char tmp_path[PATH_MAX + 1]; + const char *path; + size_t i, len; + int rv; + + path = *path_ptr; + len = strlen(path); + *did_chdir = 0; + + while (len >= PATH_MAX) { + for (i = PATH_MAX - 1; i > 0; --i) { + if (path[i] == '/') + break; + } + if (i == 0) { + errno = ENAMETOOLONG; + return -1; /* Assumes PATH_MAX > NAME_MAX */ + } + memcpy(tmp_path, path, i); + tmp_path[i] = '\0'; + if (chdir(tmp_path)) + return -1; + *did_chdir = 1; + path += i + 1; + len -= i + 1; + } + + if (remove(path) == 0 || (errno == ENOENT && missing_ok)) + rv = 0; + else + rv = -1; + + *path_ptr = path; + + return rv; +} + +static int +recursive_remove_internal(const char *path, int missing_ok, int cwd) +{ + DIR *dir; + struct dirent *de; + const char *sub_path; + char *subdir; + int did_chdir, rv; + + /* + * If the argument is longer than PATH_MAX, long_remove + * will try to shorten it using chdir. So before returning, + * make sure to fchdir back to the original cwd. + */ + sub_path = path; + if (long_remove(&sub_path, missing_ok, &did_chdir) == 0) + rv = 0; + else if (errno != ENOTEMPTY) /* Other errors are terminal. */ + rv = -1; + else + rv = 1; + + if (rv != 1) { + if (did_chdir && safe_fchdir(cwd) == -1 && rv == 0) + rv = -1; + return rv; + } + + if ((dir = opendir(sub_path)) == NULL) { + if (errno == EMFILE) + warn("opendir failed"); + return -1; + } + + if (did_chdir && fchdir(cwd) == -1) + return -1; + + rv = 0; + + while ((de = readdir(dir)) != NULL) { + if (strcmp(de->d_name, ".") == 0) + continue; + if (strcmp(de->d_name, "..") == 0) + continue; + subdir = xasprintf("%s/%s", path, de->d_name); + rv = recursive_remove_internal(subdir, 1, cwd); + free(subdir); + } + + closedir(dir); + + safe_fchdir(cwd); + + rv |= long_remove(&path, missing_ok, &did_chdir); + + if (did_chdir && safe_fchdir(cwd) == -1 && rv == 0) + rv = -1; + + return rv; +} + +int +recursive_remove(const char *path, int missing_ok) +{ + int orig_cwd, rv; + + /* First try the easy case of regular file or empty directory. */ + if (remove(path) == 0 || (errno == ENOENT && missing_ok)) + return 0; + + /* + * If the path is too long, long_remove will use chdir to shorten it, + * so remember the current directory first. + */ + if ((orig_cwd = open(".", O_RDONLY)) == -1) + return -1; + + rv = recursive_remove_internal(path, missing_ok, orig_cwd); + + close(orig_cwd); + return rv; +} diff --git a/external/bsd/pkg_install/dist/lib/str.c b/external/bsd/pkg_install/dist/lib/str.c new file mode 100644 index 000000000..0284e59f5 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/str.c @@ -0,0 +1,102 @@ +/* $NetBSD: str.c,v 1.1.1.2 2009/02/02 20:44:08 joerg Exp $ */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: str.c,v 1.1.1.2 2009/02/02 20:44:08 joerg Exp $"); + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Miscellaneous string utilities. + * + */ + +#if HAVE_ASSERT_H +#include +#endif +#if HAVE_ERR_H +#include +#endif +#if HAVE_FNMATCH_H +#include +#endif +#include "lib.h" +#include "dewey.h" + +/* pull in definitions and macros for resizing arrays as we go */ +#include "defs.h" + +/* + * Return the suffix portion of a path + */ +const char * +suffix_of(const char *str) +{ + const char *dot; + + return ((dot = strrchr(basename_of(str), '.')) == NULL) ? "" : dot + 1; +} + +/* + * Return the filename portion of a path + */ +const char * +basename_of(const char *str) +{ + const char *slash; + + return ((slash = strrchr(str, '/')) == NULL) ? str : slash + 1; +} + +/* + * Return the dirname portion of a path + */ +const char * +dirname_of(const char *path) +{ + size_t cc; + char *s; + static char buf[MaxPathSize]; + + if ((s = strrchr(path, '/')) == NULL) { + return "."; + } + if (s == path) { + /* "/foo" -> return "/" */ + return "/"; + } + cc = (size_t) (s - path); + if (cc >= sizeof(buf)) + errx(EXIT_FAILURE, "dirname_of: too long dirname: '%s'", path); + (void) memcpy(buf, path, cc); + buf[cc] = 0; + return buf; +} + +/* + * Does the pkgname contain any of the special chars ("{[]?*<>")? + * If so, return 1, else 0 + */ +int +ispkgpattern(const char *pkg) +{ + return strpbrk(pkg, "<>[]?*{") != NULL; +} diff --git a/external/bsd/pkg_install/dist/lib/var.c b/external/bsd/pkg_install/dist/lib/var.c new file mode 100644 index 000000000..0db661371 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/var.c @@ -0,0 +1,345 @@ +/* $NetBSD: var.c,v 1.2 2013/05/16 19:19:44 martin Exp $ */ + +/*- + * Copyright (c) 2005, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron, Thomas Klausner, Johnny Lam, and Joerg Sonnenberger. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: var.c,v 1.2 2013/05/16 19:19:44 martin Exp $"); + +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_ERR_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_STDIO_H +#include +#endif + +#include "lib.h" + +static const char *var_cmp(const char *, size_t, const char *, size_t); +static void var_print(FILE *, const char *, const char *); + +/* + * Copy the specified varibales from the file fname to stdout. + */ +int +var_copy_list(const char *buf, const char **variables) +{ + const char *eol, *next; + size_t len; + int i; + + for (; *buf; buf = next) { + if ((eol = strchr(buf, '\n')) != NULL) { + next = eol + 1; + len = eol - buf; + } else { + next = eol; + len = strlen(buf); + } + + for (i=0; variables[i]; i++) { + if (var_cmp(buf, len, variables[i], + strlen(variables[i])) != NULL) { + printf("%.*s\n", (int)len, buf); + break; + } + } + } + return 0; +} + +/* + * Print the value of variable from the file fname to stdout. + */ +char * +var_get(const char *fname, const char *variable) +{ + FILE *fp; + char *line; + size_t len; + size_t varlen; + char *value; + size_t valuelen; + size_t thislen; + const char *p; + + varlen = strlen(variable); + if (varlen == 0) + return NULL; + + fp = fopen(fname, "r"); + if (!fp) { + if (errno != ENOENT) + warn("var_get: can't open '%s' for reading", fname); + return NULL; + } + + value = NULL; + valuelen = 0; + + while ((line = fgetln(fp, &len)) != (char *) NULL) { + if (line[len - 1] == '\n') + --len; + if ((p=var_cmp(line, len, variable, varlen)) == NULL) + continue; + + thislen = line+len - p; + if (value) { + value = xrealloc(value, valuelen+thislen+2); + value[valuelen++] = '\n'; + } + else { + value = xmalloc(thislen+1); + } + sprintf(value+valuelen, "%.*s", (int)thislen, p); + valuelen += thislen; + } + (void) fclose(fp); + return value; +} + +/* + * Print the value of variable from the memory buffer to stdout. + */ +char * +var_get_memory(const char *buf, const char *variable) +{ + const char *eol, *next, *data; + size_t len, varlen, thislen, valuelen; + char *value; + + varlen = strlen(variable); + if (varlen == 0) + return NULL; + + value = NULL; + valuelen = 0; + + for (; buf && *buf; buf = next) { + if ((eol = strchr(buf, '\n')) != NULL) { + next = eol + 1; + len = eol - buf; + } else { + next = eol; + len = strlen(buf); + } + if ((data = var_cmp(buf, len, variable, varlen)) == NULL) + continue; + + thislen = buf + len - data; + if (value) { + value = xrealloc(value, valuelen+thislen+2); + value[valuelen++] = '\n'; + } + else { + value = xmalloc(thislen+1); + } + sprintf(value + valuelen, "%.*s", (int)thislen, data); + valuelen += thislen; + } + return value; +} + +/* + * Add given variable with given value to file, overwriting any + * previous occurrence. + */ +int +var_set(const char *fname, const char *variable, const char *value) +{ + FILE *fp; + FILE *fout; + char *tmpname; + int fd; + char *line; + size_t len; + size_t varlen; + Boolean done; + struct stat st; + + varlen = strlen(variable); + if (varlen == 0) + return 0; + + fp = fopen(fname, "r"); + if (fp == NULL) { + if (errno != ENOENT) { + warn("var_set: can't open '%s' for reading", fname); + return -1; + } + if (value == NULL) + return 0; /* Nothing to do */ + } + + tmpname = xasprintf("%s.XXXXXX", fname); + if ((fd = mkstemp(tmpname)) < 0) { + free(tmpname); + if (fp != NULL) + fclose(fp); + warn("var_set: can't open temp file for '%s' for writing", + fname); + return -1; + } + if (chmod(tmpname, 0644) < 0) { + close(fd); + if (fp != NULL) + fclose(fp); + free(tmpname); + warn("var_set: can't set permissions for temp file for '%s'", + fname); + return -1; + } + if ((fout=fdopen(fd, "w")) == NULL) { + close(fd); + remove(tmpname); + free(tmpname); + if (fp != NULL) + fclose(fp); + warn("var_set: can't open temp file for '%s' for writing", + fname); + return -1; + } + + done = FALSE; + + if (fp) { + while ((line = fgetln(fp, &len)) != (char *) NULL) { + if (var_cmp(line, len, variable, varlen) == NULL) + fprintf(fout, "%.*s", (int)len, line); + else { + if (!done && value) { + var_print(fout, variable, value); + done = TRUE; + } + } + } + (void) fclose(fp); + } + + if (!done && value) + var_print(fout, variable, value); + + if (fclose(fout) < 0) { + free(tmpname); + warn("var_set: write error for '%s'", fname); + return -1; + } + + if (stat(tmpname, &st) < 0) { + free(tmpname); + warn("var_set: cannot stat tempfile for '%s'", fname); + return -1; + } + + if (st.st_size == 0) { + if (remove(tmpname) < 0) { + free(tmpname); + warn("var_set: cannot remove tempfile for '%s'", + fname); + return -1; + } + free(tmpname); + if (remove(fname) < 0) { + warn("var_set: cannot remove '%s'", fname); + return -1; + } + return 0; + } + + if (rename(tmpname, fname) < 0) { + free(tmpname); + warn("var_set: cannot move tempfile to '%s'", fname); + return -1; + } + free(tmpname); + return 0; +} + +/* + * Check if line contains variable var, return pointer to its value or NULL. + */ +static const char * +var_cmp(const char *line, size_t linelen, const char *var, size_t varlen) +{ + /* + * We expect lines to look like one of the following + * forms: + * VAR=value + * VAR= value + * We print out the value of VAR, or nothing if it + * doesn't exist. + */ + if (linelen < varlen+1) + return NULL; + if (strncmp(var, line, varlen) != 0) + return NULL; + + line += varlen; + if (*line != '=') + return NULL; + + ++line; + linelen -= varlen+1; + if (linelen > 0 && *line == ' ') + ++line; + return line; +} + +/* + * Print given variable with value to file f. + */ +static void +var_print(FILE *f, const char *variable, const char *value) +{ + const char *p; + + while ((p=strchr(value, '\n')) != NULL) { + if (p != value) + fprintf(f, "%s=%.*s\n", variable, (int)(p-value), value); + value = p+1; + } + + if (*value) + fprintf(f, "%s=%s\n", variable, value); +} diff --git a/external/bsd/pkg_install/dist/lib/version.c b/external/bsd/pkg_install/dist/lib/version.c new file mode 100644 index 000000000..f3d7ab8ef --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/version.c @@ -0,0 +1,49 @@ +/* $NetBSD: version.c,v 1.1.1.3 2010/02/03 14:24:00 joerg Exp $ */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: version.c,v 1.1.1.3 2010/02/03 14:24:00 joerg Exp $"); + +/* + * Copyright (c) 2001 Thomas Klausner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if HAVE_STDIO_H +#include +#endif + +#include "lib.h" +#include "version.h" + +void +show_version(void) +{ + printf("%d\n", PKGTOOLS_VERSION); + exit (0); +} + diff --git a/external/bsd/pkg_install/dist/lib/version.h b/external/bsd/pkg_install/dist/lib/version.h new file mode 100644 index 000000000..b90c2e707 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/version.h @@ -0,0 +1,32 @@ +/* $NetBSD: version.h,v 1.10 2013/04/20 15:29:23 wiz Exp $ */ + +/* + * Copyright (c) 2001 Thomas Klausner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _INST_LIB_VERSION_H_ +#define _INST_LIB_VERSION_H_ + +#define PKGTOOLS_VERSION 20130131 + +#endif /* _INST_LIB_VERSION_H_ */ diff --git a/external/bsd/pkg_install/dist/lib/vulnerabilities-file.c b/external/bsd/pkg_install/dist/lib/vulnerabilities-file.c new file mode 100644 index 000000000..e183689cc --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/vulnerabilities-file.c @@ -0,0 +1,652 @@ +/* $NetBSD: vulnerabilities-file.c,v 1.1.1.5 2010/06/26 00:14:33 joerg Exp $ */ + +/*- + * Copyright (c) 2008, 2010 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: vulnerabilities-file.c,v 1.1.1.5 2010/06/26 00:14:33 joerg Exp $"); + +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_WAIT_H +#include +#endif +#ifndef BOOTSTRAP +#include +#endif +#include +#if HAVE_ERR_H +#include +#endif +#include +#include +#include +#include +#include +#ifndef NETBSD +#include +#include +#else +#include +#include +#endif +#include + +#include "lib.h" + +static struct pkg_vulnerabilities *read_pkg_vulnerabilities_archive(struct archive *, int); +static struct pkg_vulnerabilities *parse_pkg_vuln(const char *, size_t, int); + +static const char pgp_msg_start[] = "-----BEGIN PGP SIGNED MESSAGE-----\n"; +static const char pgp_msg_end[] = "-----BEGIN PGP SIGNATURE-----\n"; +static const char pkcs7_begin[] = "-----BEGIN PKCS7-----\n"; +static const char pkcs7_end[] = "-----END PKCS7-----\n"; + +static void +verify_signature_pkcs7(const char *input) +{ +#ifdef HAVE_SSL + const char *begin_pkgvul, *end_pkgvul, *begin_sig, *end_sig; + + if (strncmp(input, pgp_msg_start, strlen(pgp_msg_start)) == 0) { + begin_pkgvul = input + strlen(pgp_msg_start); + if ((end_pkgvul = strstr(begin_pkgvul, pgp_msg_end)) == NULL) + errx(EXIT_FAILURE, "Invalid PGP signature"); + if ((begin_sig = strstr(end_pkgvul, pkcs7_begin)) == NULL) + errx(EXIT_FAILURE, "No PKCS7 signature"); + } else { + begin_pkgvul = input; + if ((begin_sig = strstr(begin_pkgvul, pkcs7_begin)) == NULL) + errx(EXIT_FAILURE, "No PKCS7 signature"); + end_pkgvul = begin_sig; + } + if ((end_sig = strstr(begin_sig, pkcs7_end)) == NULL) + errx(EXIT_FAILURE, "Invalid PKCS7 signature"); + end_sig += strlen(pkcs7_end); + + if (easy_pkcs7_verify(begin_pkgvul, end_pkgvul - begin_pkgvul, + begin_sig, end_sig - begin_sig, certs_pkg_vulnerabilities, 0)) + errx(EXIT_FAILURE, "Unable to verify PKCS7 signature"); +#else + errx(EXIT_FAILURE, "OpenSSL support is not compiled in"); +#endif +} + +static void +verify_signature(const char *input, size_t input_len) +{ + if (gpg_cmd == NULL && certs_pkg_vulnerabilities == NULL) + errx(EXIT_FAILURE, + "At least GPG or CERTIFICATE_ANCHOR_PKGVULN " + "must be configured"); + if (gpg_cmd != NULL) + inline_gpg_verify(input, input_len, gpg_keyring_pkgvuln); + if (certs_pkg_vulnerabilities != NULL) + verify_signature_pkcs7(input); +} + +static void * +sha512_hash_init(void) +{ + static SHA512_CTX hash_ctx; + + SHA512_Init(&hash_ctx); + return &hash_ctx; +} + +static void +sha512_hash_update(void *ctx, const void *data, size_t len) +{ + SHA512_CTX *hash_ctx = ctx; + + SHA512_Update(hash_ctx, data, len); +} + +static const char * +sha512_hash_finish(void *ctx) +{ + static char hash[SHA512_DIGEST_STRING_LENGTH]; + unsigned char digest[SHA512_DIGEST_LENGTH]; + SHA512_CTX *hash_ctx = ctx; + int i; + + SHA512_Final(digest, hash_ctx); + for (i = 0; i < SHA512_DIGEST_LENGTH; ++i) { + unsigned char c; + + c = digest[i] / 16; + if (c < 10) + hash[2 * i] = '0' + c; + else + hash[2 * i] = 'a' - 10 + c; + + c = digest[i] % 16; + if (c < 10) + hash[2 * i + 1] = '0' + c; + else + hash[2 * i + 1] = 'a' - 10 + c; + } + hash[2 * i] = '\0'; + + return hash; +} + +static void * +sha1_hash_init(void) +{ + static SHA1_CTX hash_ctx; + + SHA1Init(&hash_ctx); + return &hash_ctx; +} + +static void +sha1_hash_update(void *ctx, const void *data, size_t len) +{ + SHA1_CTX *hash_ctx = ctx; + + SHA1Update(hash_ctx, data, len); +} + +static const char * +sha1_hash_finish(void *ctx) +{ + static char hash[SHA1_DIGEST_STRING_LENGTH]; + SHA1_CTX *hash_ctx = ctx; + + SHA1End(hash_ctx, hash); + + return hash; +} + +static const struct hash_algorithm { + const char *name; + size_t name_len; + void * (*init)(void); + void (*update)(void *, const void *, size_t); + const char * (* finish)(void *); +} hash_algorithms[] = { + { "SHA512", 6, sha512_hash_init, sha512_hash_update, + sha512_hash_finish }, + { "SHA1", 4, sha1_hash_init, sha1_hash_update, + sha1_hash_finish }, + { NULL, 0, NULL, NULL, NULL } +}; + +static void +verify_hash(const char *input, const char *hash_line) +{ + const struct hash_algorithm *hash; + void *ctx; + const char *last_start, *next, *hash_value; + int in_pgp_msg; + + for (hash = hash_algorithms; hash->name != NULL; ++hash) { + if (strncmp(hash_line, hash->name, hash->name_len)) + continue; + if (isspace((unsigned char)hash_line[hash->name_len])) + break; + } + if (hash->name == NULL) { + const char *end_name; + for (end_name = hash_line; *end_name != '\0'; ++end_name) { + if (!isalnum((unsigned char)*end_name)) + break; + } + warnx("Unsupported hash algorithm: %.*s", + (int)(end_name - hash_line), hash_line); + return; + } + + hash_line += hash->name_len; + if (!isspace((unsigned char)*hash_line)) + errx(EXIT_FAILURE, "Invalid #CHECKSUM"); + while (isspace((unsigned char)*hash_line) && *hash_line != '\n') + ++hash_line; + + if (*hash_line == '\n') + errx(EXIT_FAILURE, "Invalid #CHECKSUM"); + + ctx = (*hash->init)(); + if (strncmp(input, pgp_msg_start, strlen(pgp_msg_start)) == 0) { + input += strlen(pgp_msg_start); + in_pgp_msg = 1; + } else { + in_pgp_msg = 0; + } + for (last_start = input; *input != '\0'; input = next) { + if ((next = strchr(input, '\n')) == NULL) + errx(EXIT_FAILURE, "Missing newline in pkg-vulnerabilities"); + ++next; + if (in_pgp_msg && strncmp(input, pgp_msg_end, strlen(pgp_msg_end)) == 0) + break; + if (!in_pgp_msg && strncmp(input, pkcs7_begin, strlen(pkcs7_begin)) == 0) + break; + if (*input == '\n' || + strncmp(input, "Hash:", 5) == 0 || + strncmp(input, "# $NetBSD", 9) == 0 || + strncmp(input, "#CHECKSUM", 9) == 0) { + (*hash->update)(ctx, last_start, input - last_start); + last_start = next; + } + } + (*hash->update)(ctx, last_start, input - last_start); + hash_value = (*hash->finish)(ctx); + if (strncmp(hash_line, hash_value, strlen(hash_value))) + errx(EXIT_FAILURE, "%s hash doesn't match", hash->name); + hash_line += strlen(hash_value); + + while (isspace((unsigned char)*hash_line) && *hash_line != '\n') + ++hash_line; + + if (!isspace((unsigned char)*hash_line)) + errx(EXIT_FAILURE, "Invalid #CHECKSUM"); +} + +static void +add_vulnerability(struct pkg_vulnerabilities *pv, size_t *allocated, const char *line) +{ + size_t len_pattern, len_class, len_url; + const char *start_pattern, *start_class, *start_url; + + start_pattern = line; + + start_class = line; + while (*start_class != '\0' && !isspace((unsigned char)*start_class)) + ++start_class; + len_pattern = start_class - line; + + while (*start_class != '\n' && isspace((unsigned char)*start_class)) + ++start_class; + + if (*start_class == '0' || *start_class == '\n') + errx(EXIT_FAILURE, "Input error: missing classification"); + + start_url = start_class; + while (*start_url != '\0' && !isspace((unsigned char)*start_url)) + ++start_url; + len_class = start_url - start_class; + + while (*start_url != '\n' && isspace((unsigned char)*start_url)) + ++start_url; + + if (*start_url == '0' || *start_url == '\n') + errx(EXIT_FAILURE, "Input error: missing URL"); + + line = start_url; + while (*line != '\0' && !isspace((unsigned char)*line)) + ++line; + len_url = line - start_url; + + if (pv->entries == *allocated) { + if (*allocated == 0) + *allocated = 16; + else if (*allocated <= SSIZE_MAX / 2) + *allocated *= 2; + else + errx(EXIT_FAILURE, "Too many vulnerabilities"); + pv->vulnerability = xrealloc(pv->vulnerability, + sizeof(char *) * *allocated); + pv->classification = xrealloc(pv->classification, + sizeof(char *) * *allocated); + pv->advisory = xrealloc(pv->advisory, + sizeof(char *) * *allocated); + } + + pv->vulnerability[pv->entries] = xmalloc(len_pattern + 1); + memcpy(pv->vulnerability[pv->entries], start_pattern, len_pattern); + pv->vulnerability[pv->entries][len_pattern] = '\0'; + pv->classification[pv->entries] = xmalloc(len_class + 1); + memcpy(pv->classification[pv->entries], start_class, len_class); + pv->classification[pv->entries][len_class] = '\0'; + pv->advisory[pv->entries] = xmalloc(len_url + 1); + memcpy(pv->advisory[pv->entries], start_url, len_url); + pv->advisory[pv->entries][len_url] = '\0'; + + ++pv->entries; +} + +struct pkg_vulnerabilities * +read_pkg_vulnerabilities_memory(void *buf, size_t len, int check_sum) +{ +#ifdef BOOTSTRAP + errx(EXIT_FAILURE, "Audit functions are unsupported during bootstrap"); +#else + struct archive *a; + struct pkg_vulnerabilities *pv; + + if ((a = archive_read_new()) == NULL) + errx(EXIT_FAILURE, "memory allocation failed"); + + if (archive_read_support_compression_all(a) != ARCHIVE_OK || + archive_read_support_format_raw(a) != ARCHIVE_OK || + archive_read_open_memory(a, buf, len) != ARCHIVE_OK) + errx(EXIT_FAILURE, "Cannot open pkg_vulnerabilies buffer: %s", + archive_error_string(a)); + + pv = read_pkg_vulnerabilities_archive(a, check_sum); + + return pv; +#endif +} + +struct pkg_vulnerabilities * +read_pkg_vulnerabilities_file(const char *path, int ignore_missing, int check_sum) +{ +#ifdef BOOTSTRAP + errx(EXIT_FAILURE, "Audit functions are unsupported during bootstrap"); +#else + struct archive *a; + struct pkg_vulnerabilities *pv; + int fd; + + if ((fd = open(path, O_RDONLY)) == -1) { + if (errno == ENOENT && ignore_missing) + return NULL; + err(EXIT_FAILURE, "Cannot open %s", path); + } + + if ((a = archive_read_new()) == NULL) + errx(EXIT_FAILURE, "memory allocation failed"); + + if (archive_read_support_compression_all(a) != ARCHIVE_OK || + archive_read_support_format_raw(a) != ARCHIVE_OK || + archive_read_open_fd(a, fd, 65536) != ARCHIVE_OK) + errx(EXIT_FAILURE, "Cannot open ``%s'': %s", path, + archive_error_string(a)); + + pv = read_pkg_vulnerabilities_archive(a, check_sum); + close(fd); + + return pv; +#endif +} + +#ifndef BOOTSTRAP +static struct pkg_vulnerabilities * +read_pkg_vulnerabilities_archive(struct archive *a, int check_sum) +{ + struct archive_entry *ae; + struct pkg_vulnerabilities *pv; + char *buf; + size_t buf_len, off; + ssize_t r; + + if (archive_read_next_header(a, &ae) != ARCHIVE_OK) + errx(EXIT_FAILURE, "Cannot read pkg_vulnerabilities: %s", + archive_error_string(a)); + + off = 0; + buf_len = 65536; + buf = xmalloc(buf_len + 1); + + for (;;) { + r = archive_read_data(a, buf + off, buf_len - off); + if (r <= 0) + break; + off += r; + if (off == buf_len) { + buf_len *= 2; + if (buf_len < off) + errx(EXIT_FAILURE, "pkg_vulnerabilties too large"); + buf = xrealloc(buf, buf_len + 1); + } + } + + if (r != ARCHIVE_OK) + errx(EXIT_FAILURE, "Cannot read pkg_vulnerabilities: %s", + archive_error_string(a)); + + archive_read_close(a); + + buf[off] = '\0'; + pv = parse_pkg_vuln(buf, off, check_sum); + free(buf); + return pv; +} + +static struct pkg_vulnerabilities * +parse_pkg_vuln(const char *input, size_t input_len, int check_sum) +{ + struct pkg_vulnerabilities *pv; + long version; + char *end; + const char *iter, *next; + size_t allocated_vulns; + int in_pgp_msg; + + pv = xmalloc(sizeof(*pv)); + + allocated_vulns = pv->entries = 0; + pv->vulnerability = NULL; + pv->classification = NULL; + pv->advisory = NULL; + + if (strlen(input) != input_len) + errx(1, "Invalid input (NUL character found)"); + + if (check_sum) + verify_signature(input, input_len); + + if (strncmp(input, pgp_msg_start, strlen(pgp_msg_start)) == 0) { + iter = input + strlen(pgp_msg_start); + in_pgp_msg = 1; + } else { + iter = input; + in_pgp_msg = 0; + } + + for (; *iter; iter = next) { + if ((next = strchr(iter, '\n')) == NULL) + errx(EXIT_FAILURE, "Missing newline in pkg-vulnerabilities"); + ++next; + if (*iter == '\0' || *iter == '\n') + continue; + if (strncmp(iter, "Hash:", 5) == 0) + continue; + if (strncmp(iter, "# $NetBSD", 9) == 0) + continue; + if (*iter == '#' && isspace((unsigned char)iter[1])) { + for (++iter; iter != next; ++iter) { + if (!isspace((unsigned char)*iter)) + errx(EXIT_FAILURE, "Invalid header"); + } + continue; + } + + if (strncmp(iter, "#FORMAT", 7) != 0) + errx(EXIT_FAILURE, "Input header is malformed"); + + iter += 7; + if (!isspace((unsigned char)*iter)) + errx(EXIT_FAILURE, "Invalid #FORMAT"); + ++iter; + version = strtol(iter, &end, 10); + if (iter == end || version != 1 || *end != '.') + errx(EXIT_FAILURE, "Input #FORMAT"); + iter = end + 1; + version = strtol(iter, &end, 10); + if (iter == end || version != 1 || *end != '.') + errx(EXIT_FAILURE, "Input #FORMAT"); + iter = end + 1; + version = strtol(iter, &end, 10); + if (iter == end || version != 0) + errx(EXIT_FAILURE, "Input #FORMAT"); + for (iter = end; iter != next; ++iter) { + if (!isspace((unsigned char)*iter)) + errx(EXIT_FAILURE, "Input #FORMAT"); + } + break; + } + if (*iter == '\0') + errx(EXIT_FAILURE, "Missing #CHECKSUM or content"); + + for (iter = next; *iter; iter = next) { + if ((next = strchr(iter, '\n')) == NULL) + errx(EXIT_FAILURE, "Missing newline in pkg-vulnerabilities"); + ++next; + if (*iter == '\0' || *iter == '\n') + continue; + if (in_pgp_msg && strncmp(iter, pgp_msg_end, strlen(pgp_msg_end)) == 0) + break; + if (!in_pgp_msg && strncmp(iter, pkcs7_begin, strlen(pkcs7_begin)) == 0) + break; + if (*iter == '#' && + (iter[1] == '\0' || iter[1] == '\n' || isspace((unsigned char)iter[1]))) + continue; + if (strncmp(iter, "#CHECKSUM", 9) == 0) { + iter += 9; + if (!isspace((unsigned char)*iter)) + errx(EXIT_FAILURE, "Invalid #CHECKSUM"); + while (isspace((unsigned char)*iter)) + ++iter; + verify_hash(input, iter); + continue; + } + if (*iter == '#') { + /* + * This should really be an error, + * but it is still used. + */ + /* errx(EXIT_FAILURE, "Invalid data line starting with #"); */ + continue; + } + add_vulnerability(pv, &allocated_vulns, iter); + } + + if (pv->entries != allocated_vulns) { + pv->vulnerability = xrealloc(pv->vulnerability, + sizeof(char *) * pv->entries); + pv->classification = xrealloc(pv->classification, + sizeof(char *) * pv->entries); + pv->advisory = xrealloc(pv->advisory, + sizeof(char *) * pv->entries); + } + + return pv; +} +#endif + +void +free_pkg_vulnerabilities(struct pkg_vulnerabilities *pv) +{ + size_t i; + + for (i = 0; i < pv->entries; ++i) { + free(pv->vulnerability[i]); + free(pv->classification[i]); + free(pv->advisory[i]); + } + free(pv->vulnerability); + free(pv->classification); + free(pv->advisory); + free(pv); +} + +static int +check_ignored_entry(struct pkg_vulnerabilities *pv, size_t i) +{ + const char *iter, *next; + size_t entry_len, url_len; + + if (ignore_advisories == NULL) + return 0; + + url_len = strlen(pv->advisory[i]); + + for (iter = ignore_advisories; *iter; iter = next) { + if ((next = strchr(iter, '\n')) == NULL) { + entry_len = strlen(iter); + next = iter + entry_len; + } else { + entry_len = next - iter; + ++next; + } + if (url_len != entry_len) + continue; + if (strncmp(pv->advisory[i], iter, entry_len) == 0) + return 1; + } + return 0; +} + +int +audit_package(struct pkg_vulnerabilities *pv, const char *pkgname, + const char *limit_vul_types, int output_type) +{ + FILE *output = output_type == 1 ? stdout : stderr; + size_t i; + int retval, do_eol; + + retval = 0; + + do_eol = (strcasecmp(check_eol, "yes") == 0); + + for (i = 0; i < pv->entries; ++i) { + if (check_ignored_entry(pv, i)) + continue; + if (limit_vul_types != NULL && + strcmp(limit_vul_types, pv->classification[i])) + continue; + if (!pkg_match(pv->vulnerability[i], pkgname)) + continue; + if (strcmp("eol", pv->classification[i]) == 0) { + if (!do_eol) + continue; + retval = 1; + if (output_type == 0) { + puts(pkgname); + continue; + } + fprintf(output, + "Package %s has reached end-of-life (eol), " + "see %s/eol-packages\n", pkgname, + tnf_vulnerability_base); + continue; + } + retval = 1; + if (output_type == 0) { + puts(pkgname); + } else { + fprintf(output, + "Package %s has a %s vulnerability, see %s\n", + pkgname, pv->classification[i], pv->advisory[i]); + } + } + return retval; +} diff --git a/external/bsd/pkg_install/dist/lib/xwrapper.c b/external/bsd/pkg_install/dist/lib/xwrapper.c new file mode 100644 index 000000000..45e745746 --- /dev/null +++ b/external/bsd/pkg_install/dist/lib/xwrapper.c @@ -0,0 +1,102 @@ +/* $NetBSD: xwrapper.c,v 1.1.1.1 2009/02/02 20:44:09 joerg Exp $ */ + +/*- + * Copyright (c) 2008 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#if HAVE_SYS_CDEFS_H +#include +#endif +__RCSID("$NetBSD: xwrapper.c,v 1.1.1.1 2009/02/02 20:44:09 joerg Exp $"); + +#if HAVE_ERR_H +#include +#endif +#include +#include +#include +#include + +#include "lib.h" + +char * +xasprintf(const char *fmt, ...) +{ + va_list ap; + char *buf; + + va_start(ap, fmt); + if (vasprintf(&buf, fmt, ap) == -1) + err(1, "asprintf failed"); + va_end(ap); + return buf; +} + +void * +xmalloc(size_t len) +{ + void *ptr; + + if ((ptr = malloc(len)) == NULL) + err(1, "malloc failed"); + return ptr; +} + +void * +xcalloc(size_t len, size_t n) +{ + void *ptr; + + if ((ptr = calloc(len, n)) == NULL) + err(1, "calloc failed"); + return ptr; +} + +void * +xrealloc(void *buf, size_t len) +{ + void *ptr; + + if ((ptr = realloc(buf, len)) == NULL) + err(1, "realloc failed"); + return ptr; +} + +char * +xstrdup(const char *str) +{ + char *buf; + + if ((buf = strdup(str)) == NULL) + err(1, "strdup failed"); + return buf; +} diff --git a/external/bsd/pkg_install/dist/x509/pkgsrc.cnf b/external/bsd/pkg_install/dist/x509/pkgsrc.cnf new file mode 100644 index 000000000..2a1c79459 --- /dev/null +++ b/external/bsd/pkg_install/dist/x509/pkgsrc.cnf @@ -0,0 +1,136 @@ +# $NetBSD: pkgsrc.cnf,v 1.1.1.1 2009/02/02 20:44:09 joerg Exp $ +# +# OpenSSL sample configuration file for use by pkgsrc.sh +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./pkgsrc # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several ctificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem# The private key +RANDFILE = $dir/private/.rand # private random number file + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = default # use public key default MD +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 2048 +default_keyfile = privkey.pem +default_md = sha1 +distinguished_name = req_distinguished_name +x509_extensions = v3_ca # The extentions to add to the self signed cert + +string_mask = utf8only + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = AU +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Some-State + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = Internet Widgits Pty Ltd + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +#organizationalUnitName_default = + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +[ pkgkey ] +nsComment = "Certificate for binary pkgsrc packages" + +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +subjectAltName=email:move + +extendedKeyUsage = codeSigning, emailProtection + +[ pkgsec ] +nsComment = "Certificate for pkg-vulnerabilities" + +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +subjectAltName=email:move + +[ v3_ca ] +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid:always,issuer:always +basicConstraints = critical,CA:true diff --git a/external/bsd/pkg_install/dist/x509/pkgsrc.sh b/external/bsd/pkg_install/dist/x509/pkgsrc.sh new file mode 100644 index 000000000..aab77c803 --- /dev/null +++ b/external/bsd/pkg_install/dist/x509/pkgsrc.sh @@ -0,0 +1,63 @@ +#!/bin/sh +# +# $NetBSD: pkgsrc.sh,v 1.1.1.1 2009/02/02 20:44:09 joerg Exp $ +# + +CA="openssl ca -config pkgsrc.cnf" +REQ="openssl req -config pkgsrc.cnf" + +set -e + +new_ca() { + if [ -f $1/serial ]; then + echo "CA already exists, exiting" >& 2 + exit 1 + fi + + mkdir -p $1/certs $1/crl $1/newcerts $1/private + echo "00" > $1/serial + touch $1/index.txt + + echo "Making CA certificate ..." + $REQ -new -keyout $1/private/cakey.pem \ + -out $1/careq.pem + $CA -out $1/cacert.pem -batch \ + -keyfile $1/private/cakey.pem -selfsign \ + -infiles $1/careq.pem +} + +new_pkgkey() { + $REQ -new -keyout pkgkey_key.pem -out pkgkey_req.pem + $CA -extensions pkgkey -policy policy_match -out pkgkey_cert.pem -infiles pkgkey_req.pem + rm pkgkey_req.pem + echo "Signed certificate is in pkgkey_cert.pem, key in pkgkey_key.pem" +} + +new_pkgsec() { + $REQ -new -keyout pkgsec_key.pem -out pkgsec_req.pem + $CA -extensions pkgsec -policy policy_match -out pkgsec_cert.pem -infiles pkgsec_req.pem + rm pkgsec_req.pem + echo "Signed certificate is in pkgsec_cert.pem, key in pkgsec_key.pem" +} + +usage() { + echo "$0:" + echo "setup - create new CA in ./pkgsrc for use by pkg_install" + echo "pkgkey - create and sign a certificate for binary packages" + echo "pkgsec - create and sign a certificate for pkg-vulnerabilities" +} + +case "$1" in +setup) + new_ca ./pkgsrc + ;; +pkgkey) + new_pkgkey + ;; +pkgsec) + new_pkgsec + ;; +*) + usage + ;; +esac diff --git a/external/bsd/pkg_install/dist/x509/signing.txt b/external/bsd/pkg_install/dist/x509/signing.txt new file mode 100644 index 000000000..3af3d1fea --- /dev/null +++ b/external/bsd/pkg_install/dist/x509/signing.txt @@ -0,0 +1,59 @@ +Use of digital signatures in pkg_install +---------------------------------------- + +(1) pkg_vulnerabilities: list of known vulnerabilities, provided by + the pkgsrc security team and updated regulary +(2) binary packages: check who provided binary packages + +For (1) gpg is currently the only choice. After pkgsrcCon (?) a PKCS7 +signature will be added as well. With the pkg_install-renovation branch, +PKCS7 is the only supported verification mechanism for (2) and preferred +for (1) once the infrastructure exists. + +PKCS7 is a format to use RSA public key cryptography with X509 +certificates. Those are commonly used for SSL. X509 implements a +hierachical trust model. For this purpose it means that one or more +certificates are installed and marked as trusted. A certificate used for +signing a binary package or pkg_vulnerabilities will have to be included +in the list to be trusted OR it must be itself signed by a trusted +certificate. The original list is called the TRUST ANCHOR. + +Optionally, a second list of certificates can be provided to fill gaps. +Let's assume A is a trust anchor and C is used to sign a package. C +itself is not signed by A, so it won't be trusted. Instead, there's a +third certificate B; and C includes a signature with B. The certificate +chain file can now provide B signed by A. This gives a certificate chain +of C -> B (included in the package) -> A (with the chain file) and the +signature is valid and trusted. + + +Practical implications for pkgsrc users: +- get the pkgsrc-security certificate and point CERTIFICATE_ANCHOR_PKGVULN to it +- get the certificate used by your bulk builder and point +CERTIFICATE_ANCHOR_PKGS to it +- at some later point a CA for pkgsrc might be created, in that case it +will serve as certificate for both purposes; a list of all certificates +will be provided in that case to point CERTIFICATE_CHAIN to. + + +How to create your own keys: + +The pkgsrc.sh script and the corresponding pkgsrc.cnf file provide a working +wrapper around the OpenSSL command line tool. + +The root certificate can be created by running "sh pkgsrc.sh setup", +the output can found in the pkgsrc subdirectory of the current directory. +The meta data is for human beings and displayed e.g. by pkg_add, but not +relevant for cryptographic purposes. pkgsrc/newcerts/00.pem is the +public key and can be used as trust anchor. +A certificate for signing packages can be created by running +"sh pkgsrc.sh pkgkey". The private key can be found in pkgkey_key.pem +and the certificate in pkgkey_cert.pem. +Similary, "sh pkgsrc.sh pkgsec" will create a certificate/key pair for +signing pkg-vulnerabilities. + +How to verify a certificate: +- decode the data with "openssl x509 -text -noout -in newcert.pem" +- "Issuer" is vouching for the identity (and reliability) of "Subject" +- "X509v3 Basic Constraints" should list "CA:FALSE" for all keys that are not allowed + to sign further keys. diff --git a/external/bsd/pkg_install/lib/Makefile b/external/bsd/pkg_install/lib/Makefile new file mode 100644 index 000000000..223aedb22 --- /dev/null +++ b/external/bsd/pkg_install/lib/Makefile @@ -0,0 +1,28 @@ +# $NetBSD: Makefile,v 1.9 2010/04/23 20:56:01 joerg Exp $ +# Original from FreeBSD, no rcs id. + +LIBISPRIVATE= yes + +LIB= install +SRCS= automatic.c conflicts.c dewey.c \ + fexec.c file.c global.c gpgsig.c iterate.c license.c lpkg.c \ + opattern.c parse-config.c pkcs7.c pkg_signature.c \ + pkgdb.c pkg_io.c plist.c remove.c \ + str.c version.c var.c vulnerabilities-file.c xwrapper.c +MAN= pkg_install.conf.5 pkg_summary.5 + +version.o: version.h version.c + +.include + +pkg_install.conf.5: ${DIST}/lib/pkg_install.conf.5.in + ${TOOL_SED} -e 's,@SYSCONFDIR@,/etc,' \ + ${DIST}/lib/pkg_install.conf.5.in > ${.TARGET} + +.PATH: ${DIST}/lib + +CLEANFILES+= pkg_install.conf.5 + +CPPFLAGS+= -DNETBSD + +.include diff --git a/external/bsd/pkg_install/lib/config.h b/external/bsd/pkg_install/lib/config.h new file mode 100644 index 000000000..b60891a51 --- /dev/null +++ b/external/bsd/pkg_install/lib/config.h @@ -0,0 +1,197 @@ +/* lib/config.h. Generated from config.h.in by configure. */ +/* lib/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_CTYPE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DIRENT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ERR_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FNCTL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_FNMATCH_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_GLOB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_GRP_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `db' library (-ldb). */ +/* #undef HAVE_LIBDB */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDARG_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_CDEFS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_FILE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_QUEUE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UTSNAME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vfork' function. */ +#define HAVE_VFORK 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_VIS_H 1 + +/* Define to 1 if the `z' modifider for printf is missing. */ +/* #undef MISSING_SIZE_T_SUPPORT */ + +/* Defined when PRIu64 is missing or broken */ +/* #undef NEED_PRI_MACRO */ + +/* Defined when to retain only the numeric OS version */ +/* #undef NUMERIC_VERSION_ONLY */ + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "joerg@NetBSD.org" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "pkg_install" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "pkg_install 20090911" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "pkg_install" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "20090911" + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 8 + +/* The size of `long long', as computed by sizeof. */ +#define SIZEOF_LONG_LONG 8 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 8 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT32_T */ + +/* Define for Solaris 2.5.1 so the uint64_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT64_T */ + +/* Define for Solaris 2.5.1 so the uint8_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT8_T */ + +/* Define to the type of an unsigned integer type of width exactly 16 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint16_t */ + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint32_t */ + +/* Define to the type of an unsigned integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint64_t */ + +/* Define to the type of an unsigned integer type of width exactly 8 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint8_t */ + +#if !HAVE_VFORK +# define vfork fork +#endif + +#ifndef MISSING_SIZE_T_SUPPORT +# define PRIzu "zu" +#elif SIZEOF_SIZE_T == SIZEOF_INT +# define PRIzu "u" +#elif SIZEOF_SIZE_T == SIZEOF_LONG +# define PRIzu "lu" +#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG +# define PRIzu "llu" +#else +# errror "Unknown size_t size" +#endif + diff --git a/external/bsd/pkg_install/lib/nbcompat.h b/external/bsd/pkg_install/lib/nbcompat.h new file mode 100644 index 000000000..da3a49c91 --- /dev/null +++ b/external/bsd/pkg_install/lib/nbcompat.h @@ -0,0 +1,8 @@ +/* $NetBSD: nbcompat.h,v 1.1 2008/09/30 19:19:56 joerg Exp $ */ + +/* + * In pkgsrc, libnbcompat is used to provide compatibility functions. + * This is not needed on native NetBSD, so provide an empty header. + */ + +#include diff --git a/external/bsd/pkg_install/prepare-import.sh b/external/bsd/pkg_install/prepare-import.sh new file mode 100644 index 000000000..a9b410d72 --- /dev/null +++ b/external/bsd/pkg_install/prepare-import.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# $NetBSD: prepare-import.sh,v 1.4 2013/04/20 15:30:34 wiz Exp $ +# +# Copy new pkgsrc/pkgtools/pkg_install/files to dist. +# Run this script and check for additional files and +# directories to prune, only relevant content is included. + +set -e + +cd dist +rm -f Makefile.in README config* install-sh tkpkg +rm -f */Makefile.in */*.cat* +rm -rf CVS */CVS view diff --git a/external/bsd/pkg_install/sbin/Makefile b/external/bsd/pkg_install/sbin/Makefile new file mode 100644 index 000000000..1e883c161 --- /dev/null +++ b/external/bsd/pkg_install/sbin/Makefile @@ -0,0 +1,6 @@ +# $NetBSD: Makefile,v 1.3 2009/02/02 20:47:21 joerg Exp $ + +SUBDIR= bpm pkg_add pkg_admin pkg_create \ + pkg_delete pkg_info + +.include \ No newline at end of file diff --git a/external/bsd/pkg_install/sbin/Makefile.inc b/external/bsd/pkg_install/sbin/Makefile.inc new file mode 100644 index 000000000..66b2b2fa6 --- /dev/null +++ b/external/bsd/pkg_install/sbin/Makefile.inc @@ -0,0 +1,25 @@ +# $NetBSD: Makefile.inc,v 1.3 2010/11/05 09:09:01 he Exp $ + +.include + +.include "${.PARSEDIR}/../Makefile.inc" + +LIBINSTALL != cd ${.PARSEDIR}/../lib && ${PRINTOBJDIR} + +BINDIR?= /usr/sbin +CPPFLAGS+= -DBINDIR='"${BINDIR}"' + +DPADD+= ${LIBINSTALL}/libinstall.a +LDADD+= -L${LIBINSTALL} -linstall -ltermcap + +DPADD+= ${LIBFETCH} ${LIBSSL} ${LIBCRYPTO} +LDADD+= -lfetch -lssl -lcrypto + +DPADD+= ${LIBARCHIVE} +LDADD+= -larchive + +DPADD+= ${LIBZ} ${LIBBZ2} +LDADD+= -lz -lbz2 + +DPADD+= ${LIBLZMA} +LDADD+= -llzma diff --git a/external/bsd/pkg_install/sbin/bpm/Makefile b/external/bsd/pkg_install/sbin/bpm/Makefile new file mode 100644 index 000000000..1c4785d8f --- /dev/null +++ b/external/bsd/pkg_install/sbin/bpm/Makefile @@ -0,0 +1,15 @@ +# $NetBSD: Makefile,v 1.1 2008/09/30 19:19:56 joerg Exp $ + +SCRIPTS= bpm.sh +MAN= bpm.1 + +.include + +.PATH: ${DIST}/bpm + +CLEANFILES+= bpm.sh + +bpm.sh: ${DIST}/bpm/bpm.sh.in + ${TOOL_CAT} ${DIST}/bpm/bpm.sh.in > ${.TARGET} + +.include diff --git a/external/bsd/pkg_install/sbin/pkg_add/Makefile b/external/bsd/pkg_install/sbin/pkg_add/Makefile new file mode 100644 index 000000000..a58ad03e1 --- /dev/null +++ b/external/bsd/pkg_install/sbin/pkg_add/Makefile @@ -0,0 +1,13 @@ +# $NetBSD: Makefile,v 1.2 2009/02/02 20:47:21 joerg Exp $ +# Original from FreeBSD, no rcs id. + +PROG= pkg_add +SRCS= main.c perform.c + +.include + +.PATH: ${DIST}/add + +CPPFLAGS+= -DMACHINE_ARCH=\"${MACHINE_ARCH}\" + +.include diff --git a/external/bsd/pkg_install/sbin/pkg_admin/Makefile b/external/bsd/pkg_install/sbin/pkg_admin/Makefile new file mode 100644 index 000000000..afceb35c2 --- /dev/null +++ b/external/bsd/pkg_install/sbin/pkg_admin/Makefile @@ -0,0 +1,22 @@ +# $NetBSD: Makefile,v 1.2 2009/02/02 20:47:21 joerg Exp $ + +PROG= pkg_admin +SRCS= audit.c check.c main.c + +SCRIPTS= audit-packages.sh download-vulnerability-list.sh +CLEANFILES= audit-packages.sh download-vulnerability-list.sh + +audit-packages.sh: audit-packages.sh.in + sed -e 's|@PKG_ADMIN@|/usr/sbin/pkg_admin|' \ + ${DIST}/admin/audit-packages.sh.in > $@ + +download-vulnerability-list.sh: download-vulnerability-list.sh.in + sed -e 's|@PKG_ADMIN@|/usr/sbin/pkg_admin|' \ + ${DIST}/admin/download-vulnerability-list.sh.in > $@ + +LINK_PKGVUL= yes + +.include + +.PATH: ${DIST}/admin +.include diff --git a/external/bsd/pkg_install/sbin/pkg_create/Makefile b/external/bsd/pkg_install/sbin/pkg_create/Makefile new file mode 100644 index 000000000..8ced49515 --- /dev/null +++ b/external/bsd/pkg_install/sbin/pkg_create/Makefile @@ -0,0 +1,11 @@ +# $NetBSD: Makefile,v 1.2 2009/02/02 20:47:21 joerg Exp $ +# Original from FreeBSD, no rcs id. + +PROG= pkg_create +SRCS= main.c perform.c pl.c util.c build.c + +.include + +.PATH: ${DIST}/create + +.include diff --git a/external/bsd/pkg_install/sbin/pkg_delete/Makefile b/external/bsd/pkg_install/sbin/pkg_delete/Makefile new file mode 100644 index 000000000..794222a71 --- /dev/null +++ b/external/bsd/pkg_install/sbin/pkg_delete/Makefile @@ -0,0 +1,10 @@ +# $NetBSD: Makefile,v 1.2 2009/02/25 21:23:17 joerg Exp $ +# Original from FreeBSD, no rcs id. + +PROG= pkg_delete + +.include + +.PATH: ${DIST}/delete + +.include diff --git a/external/bsd/pkg_install/sbin/pkg_info/Makefile b/external/bsd/pkg_install/sbin/pkg_info/Makefile new file mode 100644 index 000000000..1addc2f6b --- /dev/null +++ b/external/bsd/pkg_install/sbin/pkg_info/Makefile @@ -0,0 +1,13 @@ +# $NetBSD: Makefile,v 1.3 2011/05/26 12:56:26 joerg Exp $ +# Original from FreeBSD, no rcs id + +PROG= pkg_info +SRCS= main.c perform.c show.c + +.include + +.PATH: ${DIST}/info + +CWARNFLAGS.clang+= -Wno-format-security + +.include