Import of pkgsrc-2013Q2

This commit is contained in:
2013-09-26 17:14:40 +02:00
commit 785076ae39
74991 changed files with 4380255 additions and 0 deletions

View File

@@ -0,0 +1,71 @@
# $NetBSD: Makefile.in,v 1.33 2012/05/15 16:43:54 christos Exp $
srcdir= @srcdir@
pkgdbdir= @pkgdbdir@
mandir= @mandir@
datarootdir= @datarootdir@
sysconfdir= @sysconfdir@
cat5dir= $(mandir)/cat5
cat7dir= $(mandir)/cat7
man5dir= $(mandir)/man5
man7dir= $(mandir)/man7
BOOTSTRAP= @bootstrap@
SSL_SUPPORT= @ssl_support@
RANLIB= @RANLIB@
AR= @AR@
CC= @CC@
CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir)
DEFS= @DEFS@ -DDEF_LOG_DIR=\"$(pkgdbdir)\"
CFLAGS= @CFLAGS@
INSTALL= @INSTALL@
LIB= libinstall.a
OBJS= automatic.o conflicts.o dewey.o fexec.o file.o \
gpgsig.o global.o iterate.o license.o lpkg.o opattern.o \
parse-config.o pkgdb.o plist.o remove.o \
str.o var.o version.o vulnerabilities-file.o xwrapper.o
CPPFLAGS+= -DSYSCONFDIR=\"$(sysconfdir)\"
.if !empty(BOOTSTRAP)
CPPFLAGS+= -DBOOTSTRAP
.else
OBJS+= pkg_io.o pkg_signature.o
.endif
.if !empty(SSL_SUPPORT)
CPPFLAGS+= -DHAVE_SSL
OBJS+= pkcs7.o
.endif
all: $(LIB)
.c.o:
$(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c $<
$(LIB): $(OBJS)
$(AR) crv $@ $(OBJS)
$(RANLIB) $@
clean:
rm -f $(OBJS) $(LIB)
install:
$(INSTALL) -m 755 -d ${DESTDIR}$(man5dir)
$(INSTALL) -m 755 -d ${DESTDIR}$(man7dir)
$(INSTALL) -m 444 pkg_summary.5 ${DESTDIR}$(man5dir)/pkg_summary.5
$(INSTALL) -m 444 pkg_install.conf.5 ${DESTDIR}$(man5dir)/pkg_install.conf.5
$(INSTALL) -m 444 pkgsrc.7 ${DESTDIR}$(man7dir)/pkgsrc.7
.if defined(MANINSTALL) && !empty(MANINSTALL:Mcatinstall)
$(INSTALL) -m 755 -d ${DESTDIR}$(cat5dir)
$(INSTALL) -m 755 -d ${DESTDIR}$(cat7dir)
$(INSTALL) -m 444 pkg_summary.cat ${DESTDIR}$(cat5dir)/pkg_summary.0
$(INSTALL) -m 444 pkg_install.conf.cat ${DESTDIR}$(cat5dir)/pkg_install.conf.0
$(INSTALL) -m 444 pkgsrc.cat ${DESTDIR}$(cat7dir)/pkgsrc.0
.endif

View File

@@ -0,0 +1,105 @@
/* $NetBSD: automatic.c,v 1.5 2009/02/02 12:35:01 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 <nbcompat.h>
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
__RCSID("$NetBSD: automatic.c,v 1.5 2009/02/02 12:35:01 joerg Exp $");
#if HAVE_ASSERT_H
#include <assert.h>
#endif
#if HAVE_ERR_H
#include <err.h>
#endif
#if HAVE_ERRNO_H
#include <errno.h>
#endif
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
#if HAVE_STRING_H
#include <string.h>
#endif
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#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;
}

View File

@@ -0,0 +1,196 @@
/* lib/config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <assert.h> header file. */
#undef HAVE_ASSERT_H
/* Define to 1 if you have the <ctype.h> header file. */
#undef HAVE_CTYPE_H
/* Define to 1 if you have the <dirent.h> header file. */
#undef HAVE_DIRENT_H
/* Define to 1 if you have the <errno.h> header file. */
#undef HAVE_ERRNO_H
/* Define to 1 if you have the <err.h> header file. */
#undef HAVE_ERR_H
/* Define to 1 if you have the <fnctl.h> header file. */
#undef HAVE_FNCTL_H
/* Define to 1 if you have the <fnmatch.h> header file. */
#undef HAVE_FNMATCH_H
/* Define to 1 if you have the <glob.h> header file. */
#undef HAVE_GLOB_H
/* Define to 1 if you have the <grp.h> header file. */
#undef HAVE_GRP_H
/* Define to 1 if you have the <inttypes.h> 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 <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <pwd.h> header file. */
#undef HAVE_PWD_H
/* Define to 1 if you have the <signal.h> header file. */
#undef HAVE_SIGNAL_H
/* Define to 1 if you have the <stdarg.h> header file. */
#undef HAVE_STDARG_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdio.h> header file. */
#undef HAVE_STDIO_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/cdefs.h> header file. */
#undef HAVE_SYS_CDEFS_H
/* Define to 1 if you have the <sys/file.h> header file. */
#undef HAVE_SYS_FILE_H
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#undef HAVE_SYS_IOCTL_H
/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define to 1 if you have the <sys/queue.h> header file. */
#undef HAVE_SYS_QUEUE_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <sys/utsname.h> header file. */
#undef HAVE_SYS_UTSNAME_H
/* Define to 1 if you have the <sys/wait.h> header file. */
#undef HAVE_SYS_WAIT_H
/* Define to 1 if you have the <time.h> header file. */
#undef HAVE_TIME_H
/* Define to 1 if you have the <unistd.h> 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 <vis.h> 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 <sys/synch.h>,
<pthread.h>, or <semaphore.h> 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 <sys/synch.h>,
<pthread.h>, or <semaphore.h> 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 <sys/synch.h>,
<pthread.h>, or <semaphore.h> 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

View File

@@ -0,0 +1,166 @@
/* $NetBSD: conflicts.c,v 1.10 2010/01/22 13:30:42 joerg Exp $ */
/*-
* Copyright (c) 2007 Roland Illig <rillig@NetBSD.org>.
* 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 <nbcompat.h>
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
__RCSID("$NetBSD: conflicts.c,v 1.10 2010/01/22 13:30:42 joerg Exp $");
#if HAVE_ERR_H
#include <err.h>
#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

View File

@@ -0,0 +1,75 @@
/* $NetBSD: defs.h,v 1.10 2012/02/21 18:32:14 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 <nbcompat.h>
#if HAVE_ERR_H
#include <err.h>
#endif
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if HAVE_STRING_H
#include <string.h>
#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_ */

View File

@@ -0,0 +1,320 @@
/* $NetBSD: dewey.c,v 1.11 2009/03/06 15:18:42 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 <nbcompat.h>
#if HAVE_CTYPE_H
#include <ctype.h>
#endif
#if HAVE_STDLIB_H
#include <stdlib.h>
#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;
}

View File

@@ -0,0 +1,19 @@
/* $NetBSD: dewey.h,v 1.2 2007/04/16 12:55:35 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_ */

View File

@@ -0,0 +1,167 @@
/* $NetBSD: fexec.c,v 1.12 2009/08/02 17:56:45 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 <nbcompat.h>
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
#if HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#if HAVE_ERR_H
#include <err.h>
#endif
#if HAVE_ERRNO_H
#include <errno.h>
#endif
#if HAVE_STDARG_H
#include <stdarg.h>
#endif
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "lib.h"
__RCSID("$NetBSD: fexec.c,v 1.12 2009/08/02 17:56:45 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;
}

View File

@@ -0,0 +1,374 @@
/* $NetBSD: file.c,v 1.30 2010/09/15 13:18:02 joerg Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <nbcompat.h>
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#if HAVE_SYS_QUEUE_H
#include <sys/queue.h>
#endif
__RCSID("$NetBSD: file.c,v 1.30 2010/09/15 13:18: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
*
* Miscellaneous file access utilities.
*
*/
#include "lib.h"
#if HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#if HAVE_ASSERT_H
#include <assert.h>
#endif
#if HAVE_ERR_H
#include <err.h>
#endif
#if HAVE_GLOB_H
#include <glob.h>
#endif
#if HAVE_PWD_H
#include <pwd.h>
#endif
#if HAVE_TIME_H
#include <time.h>
#endif
#if HAVE_FCNTL_H
#include <fcntl.h>
#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;
}

View File

@@ -0,0 +1,38 @@
/* $NetBSD: global.c,v 1.5 2009/02/02 12:35:01 joerg Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <nbcompat.h>
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
__RCSID("$NetBSD: global.c,v 1.5 2009/02/02 12:35:01 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;

View File

@@ -0,0 +1,248 @@
/* $NetBSD: gpgsig.c,v 1.3 2009/08/02 17:56:45 joerg Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <nbcompat.h>
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
__RCSID("$NetBSD: gpgsig.c,v 1.3 2009/08/02 17:56:45 joerg Exp $");
/*-
* Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>.
* 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 <sys/wait.h>
#ifndef NETBSD
#include <nbcompat/err.h>
#else
#include <err.h>
#endif
#ifndef NETBSD
#include <nbcompat/stdlib.h>
#else
#include <stdlib.h>
#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;
}

View File

@@ -0,0 +1,485 @@
/* $NetBSD: iterate.c,v 1.8 2010/01/22 13:30:42 joerg Exp $ */
/*-
* Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>.
* 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 <nbcompat.h>
#if HAVE_ERR_H
#include <err.h>
#endif
#if HAVE_ERRNO_H
#include <errno.h>
#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);
}

View File

@@ -0,0 +1,457 @@
/* $NetBSD: lib.h,v 1.64 2010/06/16 23:02:49 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 <nbcompat.h>
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#if HAVE_SYS_QUEUE_H
#include <sys/queue.h>
#endif
#if HAVE_CTYPE_H
#include <ctype.h>
#endif
#if HAVE_DIRENT_H
#include <dirent.h>
#endif
#if HAVE_STDIO_H
#include <stdio.h>
#endif
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if HAVE_STDARG_H
#include <stdarg.h>
#endif
#if HAVE_STRING_H
#include <string.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#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_ */

View File

@@ -0,0 +1,319 @@
/* $NetBSD: license.c,v 1.33 2013/05/05 21:09:59 rodent Exp $ */
/*-
* Copyright (c) 2009 Joerg Sonnenberger <joerg@NetBSD.org>.
* 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 <nbcompat.h>
#if HAVE_ERR_H
#include <err.h>
#endif
#include <stdlib.h>
#include <string.h>
#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 "
"sgi-free-software-b-v2.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");
}

View File

@@ -0,0 +1,70 @@
/* $NetBSD: lpkg.c,v 1.6 2009/02/02 12:35:01 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 <nbcompat.h>
#if HAVE_ERR_H
#include <err.h>
#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);
}

View File

@@ -0,0 +1,213 @@
/* $NetBSD: opattern.c,v 1.6 2012/01/28 12:33:05 joerg Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <nbcompat.h>
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
__RCSID("$NetBSD: opattern.c,v 1.6 2012/01/28 12:33:05 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 <assert.h>
#endif
#if HAVE_ERR_H
#include <err.h>
#endif
#if HAVE_FNMATCH_H
#include <fnmatch.h>
#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;
}

View File

@@ -0,0 +1,271 @@
/* $NetBSD: parse-config.c,v 1.15 2010/06/16 23:02:49 joerg Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <nbcompat.h>
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
__RCSID("$NetBSD: parse-config.c,v 1.15 2010/06/16 23:02:49 joerg Exp $");
/*-
* Copyright (c) 2008, 2009 Joerg Sonnenberger <joerg@NetBSD.org>.
* 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 <err.h>
#endif
#include <errno.h>
#if HAVE_STRING_H
#include <string.h>
#endif
#ifndef BOOTSTRAP
#include <fetch.h>
#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);
}

View File

@@ -0,0 +1,332 @@
/* $NetBSD: pkcs7.c,v 1.5 2009/08/02 17:56:45 joerg Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <nbcompat.h>
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
__RCSID("$NetBSD: pkcs7.c,v 1.5 2009/08/02 17:56:45 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 <lha@it.su.se>
*
* 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 <err.h>
#endif
#include <openssl/pkcs7.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#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;
}

View File

@@ -0,0 +1,216 @@
.\" $NetBSD: pkg_install.conf.5.in,v 1.17 2012/12/17 04:34:02 agc 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

View File

@@ -0,0 +1,173 @@
PKG_INSTALL.CONF(5) NetBSD File Formats Manual PKG_INSTALL.CONF(5)
NNAAMMEE
ppkkgg__iinnssttaallll..ccoonnff -- configuration file for package installation tools
DDEESSCCRRIIPPTTIIOONN
The file ppkkgg__iinnssttaallll..ccoonnff contains system defaults for the package
installation tools as a list of variable-value pairs. Each line has the
format VARIABLE=VALUE. If the value consists of more than one line, each
line is prefixed with VARIABLE=.
The current value of a variable can be checked by running
ppkkgg__aaddmmiinn ccoonnffiigg--vvaarr VVAARRIIAABBLLEE
Some variables are overriden by environmental variables of the same name.
Those are marked by (*).
The following variables are supported:
ACCEPTABLE_LICENSES
Space-separared list of licenses packages are allowed to carry.
License names are case-sensitive.
ACTIVE_FTP
Force the use of active FTP.
CACHE_INDEX
Cache directory listenings in memory. This avoids retransfers of
the large directory index for HTTP and is enabled by default.
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 cer-
tificates must be PEM-encoded.
CERTIFICATE_ANCHOR_PKGVULN
Analogous to CERTIFICATE_ANCHOR_PKGS. The _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s is
trusted when a certificate chain ends in one of the certificates
contained in this file.
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.
CHECK_LICENSE
Check the license conditions of packages before installing them.
Supported values are:
no The check is not performed.
yes The check is performed if the package has license
conditions set.
always Passing the license check is required. Missing
license conditions are considered an error.
CHECK_END_OF_LIFE
During vulnerability checks, consider packages that have reached
end-of-life as vulnerable. This option is enabled by default.
CHECK_VULNERABILITIES
Check for vulnerabilities when installing packages. Supported
values are:
never No check is performed.
always Passing the vulnerability check is required. A
missing pkg-vulnerabilities file is considered an
error.
interactive The user is always asked to confirm installation
of vulnerable packages.
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.
CONFIG_CACHE_CONNECTIONS_HOST
Like CONFIG_CACHE_CONNECTIONS, but limit the number of connec-
tions to the host as well. See fetch(3) for further details
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.
GPG Path to gpg(1), which can be used to verify the signature in the
_p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file when running
ppkkgg__aaddmmiinn cchheecckk--ppkkgg--vvuullnneerraabbiilliittiieess --ss
or
ppkkgg__aaddmmiinn ffeettcchh--ppkkgg--vvuullnneerraabbiilliittiieess --ss
It can also be used to verify and sign binary packages.
GPG_KEYRING_PKGVULN
Non-default keyring to use for verifying GPG signatures of
_p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s.
GPG_KEYRING_SIGN
Non-default keyring to use for signing packages with GPG.
GPG_KEYRING_VERIFY
Non-default keyring to use for verifying GPG signature of pack-
ages.
GPG_SIGN_AS
User-id to use for signing packages.
IGNORE_PROXY
Use direct connections and ignore FTP_PROXY and HTTP_PROXY.
IGNORE_URL
One line per advisory which should be ignored when running
ppkkgg__aaddmmiinn aauuddiitt
The URL from the _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file should be used as
value.
PKG_DBDIR (*)
Location of the packages database. This option is always overri-
den by the argument of the --KK option.
PKG_PATH (*)
Search path for packages. The entries are separated by semi-
colon. Each entry specifies a directory or URL to search for
packages.
PKG_REFCOUNT_DBDIR (*)
Location of the package reference counts database directory. The
default value is _$_{_P_K_G___D_B_D_I_R_}_._r_e_f_c_o_u_n_t.
PKGVULNDIR
Directory name in which the _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file resides.
Default is _$_{_P_K_G___D_B_D_I_R_}.
PKGVULNURL
URL which is used for updating the local _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file
when running
ppkkgg__aaddmmiinn ffeettcchh--ppkkgg--vvuullnneerraabbiilliittiieess
The default location is ftp.NetBSD.org using HTTP. _N_o_t_e: Usu-
ally, only the compression type should be changed. Currently
supported are uncompressed files and files compressed by bzip2(1)
(_._b_z_2) or gzip(1) (_._g_z).
VERBOSE_NETIO
Log details of network IO to stderr.
VERIFIED_INSTALLATION
Set trust level used when installation. Supported values are:
never No signature checks are performed.
always A valid signature is required. If the binary
package can not be verified, the installation is
terminated
trusted A valid signature is required. If the binary
package can not be verified, the user is asked
interactively.
interactive The user is always asked interactively when
installing a package.
FFIILLEESS
@SYSCONFDIR@/pkg_install.conf Default location for the file described in
this manual page.
SSEEEE AALLSSOO
pkg_add(1), pkg_admin(1) pkg_create(1), pkg_delete(1), pkg_info(1)
NetBSD 5.0 February 22, 2012 NetBSD 5.0

View File

@@ -0,0 +1,383 @@
/* $NetBSD: pkg_io.c,v 1.11 2010/04/20 00:39:13 joerg Exp $ */
/*-
* Copyright (c) 2008, 2009 Joerg Sonnenberger <joerg@NetBSD.org>.
* 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 <nbcompat.h>
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
__RCSID("$NetBSD: pkg_io.c,v 1.11 2010/04/20 00:39:13 joerg Exp $");
#include <archive.h>
#include <archive_entry.h>
#if HAVE_ERR_H
#include <err.h>
#endif
#if HAVE_ERRNO_H
#include <errno.h>
#endif
#include <fetch.h>
#include <stdlib.h>
#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;
}

View File

@@ -0,0 +1,713 @@
/* $NetBSD: pkg_signature.c,v 1.10 2010/02/20 04:40:03 joerg Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <nbcompat.h>
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
__RCSID("$NetBSD: pkg_signature.c,v 1.10 2010/02/20 04:40:03 joerg Exp $");
/*-
* Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>.
* 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 <sys/wait.h>
#endif
#include <ctype.h>
#if HAVE_ERR_H
#include <err.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#ifndef NETBSD
#include <nbcompat/sha2.h>
#else
#include <sha2.h>
#endif
#include <signal.h>
#ifdef NETBSD
#include <unistd.h>
#else
#include <nbcompat/unistd.h>
#endif
#include <archive.h>
#include <archive_entry.h>
#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 = xmalloc(sizeof(*state));
state->sign_blocks = NULL;
state->sign_buf = NULL;
state->archive = NULL;
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);
}

View File

@@ -0,0 +1,138 @@
.\" $NetBSD: pkg_summary.5,v 1.10 2011/10/19 21:15:39 cheusov 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.

View File

@@ -0,0 +1,113 @@
PKG_SUMMARY(5) NetBSD File Formats Manual PKG_SUMMARY(5)
NNAAMMEE
ppkkgg__ssuummmmaarryy -- summary of binary package repository
DDEESSCCRRIIPPTTIIOONN
The file ppkkgg__ssuummmmaarryy 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 VARIABLE=VALUE. If the value consists of more than one
line, each line is prefixed with VARIABLE=. Multi-line variables are
guaranteed to be in consecutive lines.
The following variables are used:
BUILD_DATE
(required) The date and time when the package was built.
CATEGORIES
(required) A list of categories which this package fits in, sepa-
rated by space.
COMMENT
(required) A one-line description of the package.
CONFLICTS
(optional) A list of dewey patterns of packages the package con-
flicts with, one per line. If missing, this package has no con-
flicts.
DEPENDS
(optional) A list of dewey patterns of packages the package
depends on, one per line. If missing, this package has no depen-
dencies.
DESCRIPTION
(required) A more detailed description of the package.
FILE_NAME
(optional) The name of the binary package file. If not given,
_P_K_G_N_A_M_E_._t_g_z can be assumed.
FILE_SIZE
(optional) The size of the binary package file, in bytes.
HOMEPAGE
(optional) A URL where more information about the package can be
found.
LICENSE
(optional) The type of license this package is distributed under.
If empty or missing, it is OSI-approved.
MACHINE_ARCH
(required) The architecture on which the package was compiled.
OPSYS (required) The operating system on which the package was com-
piled.
OS_VERSION
(required) The version of the operating system on which the pack-
age was compiled.
PKG_OPTIONS
(optional) Any options selected to compile this package. If
missing, the package does not support options.
PKGNAME
(required) The name of the package.
PKGPATH
(required) The path of the package directory within pkgsrc.
PKGTOOLS_VERSION
(required) The version of the package tools used to create the
package.
PREV_PKGPATH
(optional) The previous path of the package directory within
pkgsrc when a package was moved. (See SUPERSEDES below for a
renamed package.)
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.
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.
SIZE_PKG
(required) The size of the package when installed, in bytes.
SUPERSEDES
(optional) A list of dewey patterns of previous packages this
package replaces, one per line. This is used for package renam-
ing.
The ppkkgg__ssuummmmaarryy file can be generated using the pkg_info(1) --XX option.
For example, the following will list this data for all installed pack-
ages:
pkg_info -X -a
SSEEEE AALLSSOO
pkg_info(1)
HHIISSTTOORRYY
The ppkkgg__ssuummmmaarryy format was first officially documented in April 2006.
NetBSD 5.0 April 11, 2009 NetBSD 5.0

View File

@@ -0,0 +1,339 @@
/* $NetBSD: pkgdb.c,v 1.39 2010/04/20 21:22:38 joerg Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <nbcompat.h>
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
__RCSID("$NetBSD: pkgdb.c,v 1.39 2010/04/20 21:22:38 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 <hubert@feyrer.de>.
*
* 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 <db.h>
#else
#include <nbcompat/db.h>
#endif
#if HAVE_ERR_H
#include <err.h>
#endif
#if HAVE_ERRNO_H
#include <errno.h>
#endif
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
#if HAVE_STDARG_H
#include <stdarg.h>
#endif
#if HAVE_STDIO_H
#include <stdio.h>
#endif
#if HAVE_STRING_H
#include <string.h>
#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);
}

View File

@@ -0,0 +1,54 @@
.\" $NetBSD: pkgsrc.7,v 1.2 2007/10/07 12:59:14 kano 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/

View File

@@ -0,0 +1,19 @@
PKGSRC(7) NetBSD Miscellaneous Information Manual PKGSRC(7)
NNAAMMEE
ppkkggssrrcc -- NetBSD packages collection (framework for third-party software)
DDEESSCCRRIIPPTTIIOONN
The NetBSD Packages Collection (pkgsrc) is a framework for building and
maintaining third-party software on NetBSD and other UNIX-like systems.
It is used to enable freely available software to be configured and built
easily on supported platforms.
Tools are available to install ready-to-use packages and to perform vari-
ous administrative tasks for the package system.
SSEEEE AALLSSOO
pkg_add(1), pkg_delete(1), pkg_info(1),
_h_t_t_p_:_/_/_w_w_w_._n_e_t_b_s_d_._o_r_g_/_d_o_c_s_/_p_k_g_s_r_c_/
NetBSD 5.0 March 2, 2007 NetBSD 5.0

View File

@@ -0,0 +1,783 @@
/* $NetBSD: plist.c,v 1.29 2009/08/02 17:56:45 joerg Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <nbcompat.h>
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
__RCSID("$NetBSD: plist.c,v 1.29 2009/08/02 17:56:45 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 <joerg@NetBSD.org>.
* 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 <errno.h>
#endif
#if HAVE_ERR_H
#include <err.h>
#endif
#ifndef NETBSD
#include <nbcompat/md5.h>
#else
#include <md5.h>
#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;
}

View File

@@ -0,0 +1,195 @@
/* $NetBSD: remove.c,v 1.3 2009/08/02 17:56:45 joerg Exp $ */
/*-
* Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>.
* 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 <nbcompat.h>
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
__RCSID("$NetBSD: remove.c,v 1.3 2009/08/02 17:56:45 joerg Exp $");
#if HAVE_DIRENT_H
#include <dirent.h>
#endif
#if HAVE_ERR_H
#include <err.h>
#endif
#include <errno.h>
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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;
}

View File

@@ -0,0 +1,102 @@
/* $NetBSD: str.c,v 1.26 2009/02/02 12:35:01 joerg Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <nbcompat.h>
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
__RCSID("$NetBSD: str.c,v 1.26 2009/02/02 12:35:01 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 <assert.h>
#endif
#if HAVE_ERR_H
#include <err.h>
#endif
#if HAVE_FNMATCH_H
#include <fnmatch.h>
#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;
}

View File

@@ -0,0 +1,345 @@
/* $NetBSD: var.c,v 1.9 2013/05/17 07:27:29 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 <nbcompat.h>
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
__RCSID("$NetBSD: var.c,v 1.9 2013/05/17 07:27:29 martin Exp $");
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_ERR_H
#include <err.h>
#endif
#if HAVE_ERRNO_H
#include <errno.h>
#endif
#if HAVE_STDIO_H
#include <stdio.h>
#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);
}

View File

@@ -0,0 +1,49 @@
/* $NetBSD: version.c,v 1.7 2010/02/03 14:20:14 joerg Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <nbcompat.h>
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
__RCSID("$NetBSD: version.c,v 1.7 2010/02/03 14:20:14 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 <stdio.h>
#endif
#include "lib.h"
#include "version.h"
void
show_version(void)
{
printf("%d\n", PKGTOOLS_VERSION);
exit (0);
}

View File

@@ -0,0 +1,32 @@
/* $NetBSD: version.h,v 1.165 2013/01/31 10:25:30 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_ */

View File

@@ -0,0 +1,652 @@
/* $NetBSD: vulnerabilities-file.c,v 1.7 2010/06/16 23:02:49 joerg Exp $ */
/*-
* Copyright (c) 2008, 2010 Joerg Sonnenberger <joerg@NetBSD.org>.
* 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 <nbcompat.h>
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
__RCSID("$NetBSD: vulnerabilities-file.c,v 1.7 2010/06/16 23:02:49 joerg Exp $");
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifndef BOOTSTRAP
#include <archive.h>
#endif
#include <ctype.h>
#if HAVE_ERR_H
#include <err.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#ifndef NETBSD
#include <nbcompat/sha1.h>
#include <nbcompat/sha2.h>
#else
#include <sha1.h>
#include <sha2.h>
#endif
#include <unistd.h>
#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;
}

View File

@@ -0,0 +1,102 @@
/* $NetBSD: xwrapper.c,v 1.2 2009/02/02 12:35:01 joerg Exp $ */
/*-
* Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>.
* 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 <nbcompat.h>
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
__RCSID("$NetBSD: xwrapper.c,v 1.2 2009/02/02 12:35:01 joerg Exp $");
#if HAVE_ERR_H
#include <err.h>
#endif
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;
}