summaryrefslogtreecommitdiff
path: root/pkgtools/pkg_install/files/add
diff options
context:
space:
mode:
authorjoerg <joerg@pkgsrc.org>2009-02-02 12:34:59 +0000
committerjoerg <joerg@pkgsrc.org>2009-02-02 12:34:59 +0000
commitd7cc6db11bfefd0006364a122a40572d9eb9b739 (patch)
tree4c0fb6728ab9db1b5dc2233bb02e4ef34022a604 /pkgtools/pkg_install/files/add
parentea71974691a75ab2e2b9c62a6fb9dcc136b266de (diff)
downloadpkgsrc-d7cc6db11bfefd0006364a122a40572d9eb9b739.tar.gz
Merge pkg_install-20090201 from pkg_install-renovation branch.
- DB support is always included from libnbcompat if needed - pkg_view and linkfarm are not installed any more; they are not moved into the attic yet, so they can easily be installed as separte package - common configuration file to customise the behavior of various components; this supersedes the old audit-packages.conf - support for PKSC7 signatures (using X509 certs) and GPG signatures for packages in a secure way. See pkg_admin(8) for how to create them and pkg_install.conf(5) for the options to use them - audit-packages and download-vulnerability-list are wrapper scripts around pkg_admin. They try to mimic the classic options if used sanely. "pkg_admin audit" is now an order of magnitude faster than before - pkg_add uses libarchive and libfetch instead of external ftp and tar: - progress bar is currently missing for downloads - "pkg_add -" is no longer supported - no adhoc check for conficts between dependencies and already installed packages - "pkg_add -s" has been replaced with an option in pkg_install.conf, verification of plain detached GPG signatures is no longer supported - optional check for vulnerabilities before adding a package - if /var and /usr/pkg are on different fileystems it is twice as fast now - conflicts due to overlapping plists are checked before installation - pkg_add no longer plays with the process limits - pkg_add and pkg_delete have a new destdir option; scripts have to either be modified to use PKG_DESTDIR or should be disabled - pkg_add -u for now can't be used to update to the exact same version - internal "rm -rf" and "mkdir_p" code - all memory allocation failures are not explicitly fatal - if a file is not removed due to a failed checksum, still remove the entry from pkgdb
Diffstat (limited to 'pkgtools/pkg_install/files/add')
-rw-r--r--pkgtools/pkg_install/files/add/Makefile.in16
-rw-r--r--pkgtools/pkg_install/files/add/add.h10
-rw-r--r--pkgtools/pkg_install/files/add/extract.c340
-rw-r--r--pkgtools/pkg_install/files/add/futil.c151
-rw-r--r--pkgtools/pkg_install/files/add/main.c62
-rw-r--r--pkgtools/pkg_install/files/add/perform.c2079
-rw-r--r--pkgtools/pkg_install/files/add/pkg_add.1173
-rw-r--r--pkgtools/pkg_install/files/add/pkg_add.cat1158
-rw-r--r--pkgtools/pkg_install/files/add/verify.c179
-rw-r--r--pkgtools/pkg_install/files/add/verify.h40
10 files changed, 1392 insertions, 1816 deletions
diff --git a/pkgtools/pkg_install/files/add/Makefile.in b/pkgtools/pkg_install/files/add/Makefile.in
index 39cdc1b6767..1b45ed175b8 100644
--- a/pkgtools/pkg_install/files/add/Makefile.in
+++ b/pkgtools/pkg_install/files/add/Makefile.in
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.in,v 1.18 2008/04/26 17:40:01 joerg Exp $
+# $NetBSD: Makefile.in,v 1.19 2009/02/02 12:35:00 joerg Exp $
srcdir= @srcdir@
@@ -13,17 +13,25 @@ cat1dir= $(mandir)/cat1
CC= @CC@
CCLD= $(CC)
-LIBS= -linstall @LIBS@
CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir) -I../lib
-DEFS= @DEFS@ -DOPSYS_NAME=\"$(OPSYS)\" -DMACHINE_ARCH=\"$(MACHINE_ARCH)\" -DBINDIR=\"$(sbindir)\" -DTAR_CMD=\"@tar@\" -DPAX_CMD=\"@pax@\"
+DEFS= @DEFS@ -DOPSYS_NAME=\"$(OPSYS)\" -DMACHINE_ARCH=\"$(MACHINE_ARCH)\" -DBINDIR=\"$(sbindir)\"
CFLAGS= @CFLAGS@
LDFLAGS= @LDFLAGS@ -L../lib
+SSL_SUPPORT= @ssl_support@
+
+LIBS= -linstall -lfetch -larchive -lbz2 -lz
+.if !empty(SSL_SUPPORT)
+LIBS+= -lcrypto
+CPPFLAGS+= -DHAVE_SSL
+.endif
+LIBS+= @LIBS@
+
INSTALL= @INSTALL@
PROG= pkg_add
-OBJS= main.o perform.o futil.o extract.o verify.o
+OBJS= main.o perform.o
all: $(PROG)
diff --git a/pkgtools/pkg_install/files/add/add.h b/pkgtools/pkg_install/files/add/add.h
index 9fbba20125a..3a6262aa9ae 100644
--- a/pkgtools/pkg_install/files/add/add.h
+++ b/pkgtools/pkg_install/files/add/add.h
@@ -1,4 +1,4 @@
-/* $NetBSD: add.h,v 1.12 2008/04/26 17:40:01 joerg Exp $ */
+/* $NetBSD: add.h,v 1.13 2009/02/02 12:35:00 joerg Exp $ */
/* from FreeBSD Id: add.h,v 1.8 1997/02/22 16:09:15 peter Exp */
@@ -25,6 +25,7 @@
#ifndef _INST_ADD_H_INCLUDE
#define _INST_ADD_H_INCLUDE
+extern char *Destdir;
extern char *OverrideMachine;
extern char *Prefix;
extern char *View;
@@ -35,15 +36,8 @@ extern Boolean NoRecord;
extern Boolean Force;
extern Boolean Automatic;
extern int Replace;
-extern char *Mode;
-extern char *Owner;
-extern char *Group;
-extern char *Directory;
-extern char *PkgName;
-extern char FirstPen[];
int make_hierarchy(char *);
-int extract_plist(char *, package_t *);
void apply_perms(char *, char **, int);
int pkg_perform(lpkg_head_t *);
diff --git a/pkgtools/pkg_install/files/add/extract.c b/pkgtools/pkg_install/files/add/extract.c
deleted file mode 100644
index 0a303e701dd..00000000000
--- a/pkgtools/pkg_install/files/add/extract.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/* $NetBSD: extract.c,v 1.18 2008/04/26 17:40:01 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_QUEUE_H
-#include <sys/queue.h>
-#endif
-#ifndef lint
-#if 0
-static const char *rcsid = "FreeBSD - Id: extract.c,v 1.17 1997/10/08 07:45:35 charnier Exp";
-#else
-__RCSID("$NetBSD: extract.c,v 1.18 2008/04/26 17:40:01 joerg Exp $");
-#endif
-#endif
-
-/*
- * FreeBSD install - a package for the installation and maintainance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * This is the package extraction code for the add module.
- *
- */
-
-#if HAVE_ERR_H
-#include <err.h>
-#endif
-#include "lib.h"
-#include "add.h"
-
-lfile_head_t files;
-lfile_head_t perms;
-
-/*
- * Copy files from staging area to todir.
- * This is only used when the files cannot be directory rename()ed.
- */
-static void
-pushout(char *todir)
-{
- pipe_to_system_t *pipe_to;
- char *file_args[4];
- char **perm_argv;
- int perm_argc = 1;
- lfile_t *lfp;
- int count;
-
- /* set up arguments to run "pax -r -w -p e" */
- file_args[0] = (char *)strrchr(PAX_CMD, '/');
- if (file_args[0] == NULL)
- file_args[0] = PAX_CMD;
- else
- file_args[0]++;
- file_args[1] = "-rwpe";
- file_args[2] = todir;
- file_args[3] = NULL;
-
- /* count entries for files */
- count = 0;
- TAILQ_FOREACH(lfp, &files, lf_link)
- count++;
-
- if (count > 0) {
- /* open pipe, feed it files, close pipe */
- pipe_to = pipe_to_system_begin(PAX_CMD, file_args, NULL);
- while ((lfp = TAILQ_FIRST(&files)) != NULL) {
- fprintf(pipe_to->fp, "%s\n", lfp->lf_name);
- TAILQ_REMOVE(&files, lfp, lf_link);
- free(lfp);
- }
- pipe_to_system_end(pipe_to);
- }
-
- /* count entries for permissions */
- count = 0;
- TAILQ_FOREACH(lfp, &perms, lf_link)
- count++;
-
- if (count > 0) {
- perm_argv = malloc((count + 1) * sizeof(char *));
- perm_argc = 0;
- TAILQ_FOREACH(lfp, &perms, lf_link)
- perm_argv[perm_argc++] = lfp->lf_name;
- perm_argv[perm_argc] = NULL;
- apply_perms(todir, perm_argv, perm_argc);
-
- /* empty the perm list */
- while ((lfp = TAILQ_FIRST(&perms)) != NULL) {
- TAILQ_REMOVE(&perms, lfp, lf_link);
- free(lfp);
- }
- free(perm_argv);
- }
-}
-
-static void
-rollback(char *name, char *home, plist_t *start, plist_t *stop)
-{
- plist_t *q;
- char try[MaxPathSize], bup[MaxPathSize], *dir;
-
- dir = home;
- for (q = start; q != stop; q = q->next) {
- if (q->type == PLIST_FILE) {
- (void) snprintf(try, sizeof(try), "%s/%s", dir, q->name);
- if (make_preserve_name(bup, sizeof(bup), name, try) && fexists(bup)) {
-#if HAVE_CHFLAGS
- (void) chflags(try, 0);
-#endif
- (void) unlink(try);
- if (rename(bup, try))
- warnx("rollback: unable to rename %s back to %s", bup, try);
- }
- } else if (q->type == PLIST_CWD) {
- if (strcmp(q->name, "."))
- dir = q->name;
- else
- dir = home;
- }
- }
-}
-
-
-/*
- * Return 0 on error, 1 for success.
- */
-int
-extract_plist(char *home, package_t *pkg)
-{
- plist_t *p = pkg->head;
- char *last_file;
- char *last_chdir;
- Boolean preserve;
- lfile_t *lfp;
-
- TAILQ_INIT(&files);
- TAILQ_INIT(&perms);
-
- last_chdir = 0;
- preserve = find_plist_option(pkg, "preserve") ? TRUE : FALSE;
-
- /* Reset the world */
- Owner = NULL;
- Group = NULL;
- Mode = NULL;
- last_file = NULL;
- Directory = home;
-
- if (!NoRecord) {
- /* Open Package Database for writing */
- if (!pkgdb_open(ReadWrite)) {
- cleanup(0);
- err(EXIT_FAILURE, "can't open pkgdb");
- }
- }
- /* Do it */
- while (p) {
- char cmd[MaxPathSize];
-
- switch (p->type) {
- case PLIST_NAME:
- PkgName = p->name;
- if (Verbose)
- printf("extract: Package name is %s\n", p->name);
- break;
-
- case PLIST_FILE:
- last_file = p->name;
- if (Verbose)
- printf("extract: %s/%s\n", Directory, p->name);
- if (!Fake) {
- char try[MaxPathSize];
-
- if (strrchr(p->name, '\'')) {
- cleanup(0);
- errx(2, "Bogus filename \"%s\"", p->name);
- }
-
- /* first try to rename it into place */
- (void) snprintf(try, sizeof(try), "%s/%s", Directory, p->name);
- if (fexists(try)) {
-#if HAVE_CHFLAGS
- (void) chflags(try, 0); /* XXX hack - if truly immutable, rename fails */
-#endif
- if (preserve && PkgName) {
- char pf[MaxPathSize];
-
- if (make_preserve_name(pf, sizeof(pf), PkgName, try)) {
- if (rename(try, pf)) {
- warnx(
- "unable to back up %s to %s, aborting pkg_add",
- try, pf);
- rollback(PkgName, home, pkg->head, p);
- return 0;
- }
- }
- }
- }
- if (rename(p->name, try) == 0) {
- if (!NoRecord) {
- /* note in pkgdb */
- char *s, t[MaxPathSize];
- int rc;
-
- (void) snprintf(t, sizeof(t), "%s/%s", Directory, p->name);
-
- s = pkgdb_retrieve(t);
-#ifdef PKGDB_DEBUG
- printf("pkgdb_retrieve(\"%s\")=\"%s\"\n", t, s); /* pkgdb-debug - HF */
-#endif
- if (s)
- warnx("Overwriting %s - pkg %s bogus/conflicting?", t, s);
- else {
- rc = pkgdb_store(t, PkgName);
-#ifdef PKGDB_DEBUG
- printf("pkgdb_store(\"%s\", \"%s\") = %d\n", t, PkgName, rc); /* pkgdb-debug - HF */
-#endif
-
- }
- }
-
- /* try to add to list of perms to be changed and run in bulk. */
- if (p->name[0] == '/')
- pushout(Directory);
-
- LFILE_ADD(&perms, lfp, p->name);
- } else {
- /* rename failed, try copying with a big tar command */
- if (last_chdir != Directory) {
- if (last_chdir != NULL)
- pushout(last_chdir);
- last_chdir = Directory;
- } else if (p->name[0] == '/') {
- pushout(Directory);
- }
-
- if (!NoRecord) {
- /* note in pkgdb */
- /* XXX would be better to store in PUSHOUT, but
- * that would probably affect too much code I prefer
- * not to touch - HF */
-
- char *s, t[MaxPathSize];
- int rc;
-
- LFILE_ADD(&files, lfp, p->name);
- LFILE_ADD(&perms, lfp, p->name);
- if (p->name[0] == '/')
- errx(EXIT_FAILURE, "File names must not be absolute (%s).", p->name);
- else {
- (void) snprintf(t, sizeof(t), "%s/%s", Directory, p->name);
- }
-
- s = pkgdb_retrieve(t);
-#ifdef PKGDB_DEBUG
- printf("pkgdb_retrieve(\"%s\")=\"%s\"\n", t, s); /* pkgdb-debug - HF */
-#endif
- if (s)
- warnx("Overwriting %s - pkg %s bogus/conflicting?", t, s);
- else {
- rc = pkgdb_store(t, PkgName);
-#ifdef PKGDB_DEBUG
- printf("pkgdb_store(\"%s\", \"%s\") = %d\n", t, PkgName, rc); /* pkgdb-debug - HF */
-#endif
- }
- }
- }
- }
- break;
-
- case PLIST_CWD:
- if (Verbose)
- printf("extract: CWD to %s\n", p->name);
- pushout(Directory);
- if (strcmp(p->name, ".")) {
- if (!Fake && make_hierarchy(p->name) == FAIL) {
- cleanup(0);
- errx(2, "unable to make directory '%s'", p->name);
- }
- Directory = p->name;
- } else
- Directory = home;
- break;
-
- case PLIST_CMD:
- format_cmd(cmd, sizeof(cmd), p->name, Directory, last_file);
- pushout(Directory);
- printf("Executing '%s'\n", cmd);
- if (!Fake && system(cmd))
- warnx("command '%s' failed", cmd);
- break;
-
- case PLIST_CHMOD:
- pushout(Directory);
- Mode = p->name;
- break;
-
- case PLIST_CHOWN:
- pushout(Directory);
- Owner = p->name;
- break;
-
- case PLIST_CHGRP:
- pushout(Directory);
- Group = p->name;
- break;
-
- case PLIST_COMMENT:
- break;
-
- case PLIST_IGNORE:
- p = p->next;
- break;
-
- default:
- break;
- }
- p = p->next;
- }
- pushout(Directory);
- if (!NoRecord)
- pkgdb_close();
- return 1;
-}
diff --git a/pkgtools/pkg_install/files/add/futil.c b/pkgtools/pkg_install/files/add/futil.c
deleted file mode 100644
index ee4c2984fd3..00000000000
--- a/pkgtools/pkg_install/files/add/futil.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/* $NetBSD: futil.c,v 1.11 2008/04/26 17:40:01 joerg Exp $ */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <nbcompat.h>
-#if HAVE_SYS_CDEFS_H
-#include <sys/cdefs.h>
-#endif
-#ifndef lint
-#if 0
-static const char *rcsid = "from FreeBSD Id: futil.c,v 1.7 1997/10/08 07:45:39 charnier Exp";
-#else
-__RCSID("$NetBSD: futil.c,v 1.11 2008/04/26 17:40:01 joerg Exp $");
-#endif
-#endif
-
-/*
- * 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.
- *
- */
-
-#if HAVE_ERR_H
-#include <err.h>
-#endif
-#include "lib.h"
-#include "add.h"
-
-/*
- * Assuming dir is a desired directory name, make it and all intervening
- * directories necessary.
- */
-int
-make_hierarchy(char *dir)
-{
- char *cp1, *cp2;
- char *argv[2];
-
- argv[0] = dir;
- argv[1] = NULL;
-
- if (dir[0] == '/')
- cp1 = cp2 = dir + 1;
- else
- cp1 = cp2 = dir;
- while (cp2) {
- if ((cp2 = strchr(cp1, '/')) != NULL)
- *cp2 = '\0';
- if (fexists(dir)) {
- if (!(isdir(dir) || islinktodir(dir)))
- return FAIL;
- } else {
- if (fexec("mkdir", dir, NULL))
- return FAIL;
- apply_perms(NULL, argv, 1);
- }
- /* Put it back */
- if (cp2) {
- *cp2 = '/';
- cp1 = cp2 + 1;
- }
- }
- return SUCCESS;
-}
-
-/*
- * Using permission defaults, apply them as necessary
- */
-void
-apply_perms(char *dir, char **args, int nargs)
-{
- char *cd_to;
- char owner_group[128];
- const char **argv;
- int i;
-
- argv = malloc((nargs + 4) * sizeof(char *));
- /*
- * elements 0..2 are set later depending on Mode.
- * args is a NULL terminated list of file names.
- * by appending them to argv, argv becomes NULL terminated also.
- */
- for (i = 0; i <= nargs; i++)
- argv[i + 3] = args[i];
-
- if (!dir || args[0][0] == '/') /* absolute path? */
- cd_to = "/";
- else
- cd_to = dir;
-
- if (Mode) {
- argv[0] = CHMOD_CMD;
- argv[1] = "-R";
- argv[2] = Mode;
- if (pfcexec(cd_to, argv[0], argv))
- warnx("couldn't change modes of '%s' ... to '%s'",
- args[0], Mode);
- }
- if (Owner != NULL && Group != NULL) {
- if (snprintf(owner_group, sizeof(owner_group),
- "%s:%s", Owner, Group) > sizeof(owner_group)) {
- warnx("'%s:%s' is too long (%lu max)",
- Owner, Group, (unsigned long) sizeof(owner_group));
- free(argv);
- return;
- }
- argv[0] = CHOWN_CMD;
- argv[1] = "-R";
- argv[2] = owner_group;
- if (pfcexec(cd_to, argv[0], argv))
- warnx("couldn't change owner/group of '%s' ... to '%s:%s'",
- args[0], Owner, Group);
- free(argv);
- return;
- }
- if (Owner != NULL) {
- argv[0] = CHOWN_CMD;
- argv[1] = "-R";
- argv[2] = Owner;
- if (pfcexec(cd_to, argv[0], argv))
- warnx("couldn't change owner of '%s' ... to '%s'",
- args[0], Owner);
- free(argv);
-
- return;
- }
- if (Group != NULL) {
- argv[0] = CHGRP_CMD;
- argv[1] = "-R";
- argv[2] = Group;
- if (pfcexec(cd_to, argv[0], argv))
- warnx("couldn't change group of '%s' ... to '%s'",
- args[0], Group);
- }
- free(argv);
-}
diff --git a/pkgtools/pkg_install/files/add/main.c b/pkgtools/pkg_install/files/add/main.c
index 0a722e9b168..4f8280cbcca 100644
--- a/pkgtools/pkg_install/files/add/main.c
+++ b/pkgtools/pkg_install/files/add/main.c
@@ -1,4 +1,4 @@
-/* $NetBSD: main.c,v 1.16 2008/04/26 17:40:01 joerg Exp $ */
+/* $NetBSD: main.c,v 1.17 2009/02/02 12:35:00 joerg Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
@@ -7,13 +7,7 @@
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
-#ifndef lint
-#if 0
-static char *rcsid = "from FreeBSD Id: main.c,v 1.16 1997/10/08 07:45:43 charnier Exp";
-#else
-__RCSID("$NetBSD: main.c,v 1.16 2008/04/26 17:40:01 joerg Exp $");
-#endif
-#endif
+__RCSID("$NetBSD: main.c,v 1.17 2009/02/02 12:35:00 joerg Exp $");
/*
*
@@ -47,10 +41,10 @@ __RCSID("$NetBSD: main.c,v 1.16 2008/04/26 17:40:01 joerg Exp $");
#endif
#include "lib.h"
#include "add.h"
-#include "verify.h"
-static char Options[] = "AIK:LRVW:fhm:np:s:t:uvw:";
+static char Options[] = "AIK:LP:RVW:fhm:np:t:uvw:";
+char *Destdir = NULL;
char *OverrideMachine = NULL;
char *Prefix = NULL;
char *View = NULL;
@@ -60,20 +54,15 @@ Boolean NoInstall = FALSE;
Boolean NoRecord = FALSE;
Boolean Automatic = FALSE;
-char *Mode = NULL;
-char *Owner = NULL;
-char *Group = NULL;
-char *PkgName = NULL;
-char *Directory = NULL;
-char FirstPen[MaxPathSize];
int Replace = 0;
static void
usage(void)
{
- (void) fprintf(stderr, "%s\n%s\n%s\n",
- "usage: pkg_add [-AfhILnRuVv] [-K pkg_dbdir] [-m machine] [-p prefix]",
- " [-s verification-type] [-t template] [-W viewbase] [-w view]",
+ (void) fprintf(stderr, "%s\n%s\n%s\n%s\n",
+ "usage: pkg_add [-AfhILnRuVv] [-C config] [-P destdir] [-K pkg_dbdir]",
+ " [-m machine] [-p prefix] [-s verification-type",
+ " [-W viewbase] [-w view]\n",
" [[ftp|http]://[user[:password]@]host[:port]][/path/]pkg-name ...");
exit(1);
}
@@ -83,8 +72,6 @@ main(int argc, char **argv)
{
int ch, error=0;
lpkg_head_t pkgs;
- struct rlimit rlim;
- int rc;
setprogname(argv[0]);
while ((ch = getopt(argc, argv, Options)) != -1) {
@@ -93,6 +80,13 @@ main(int argc, char **argv)
Automatic = TRUE;
break;
+ case 'C':
+ config_file = optarg;
+
+ case 'P':
+ Destdir = optarg;
+ break;
+
case 'f':
Force = TRUE;
break;
@@ -126,14 +120,6 @@ main(int argc, char **argv)
Prefix = optarg;
break;
- case 's':
- set_verification(optarg);
- break;
-
- case 't':
- strlcpy(FirstPen, optarg, sizeof(FirstPen));
- break;
-
case 'u':
Replace++;
break;
@@ -164,6 +150,8 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
+ pkg_install_config();
+
path_create(getenv("PKG_PATH"));
TAILQ_INIT(&pkgs);
@@ -184,22 +172,6 @@ main(int argc, char **argv)
TAILQ_INSERT_TAIL(&pkgs, lpp, lp_link);
}
-
- /* Increase # of max. open file descriptors as high as possible */
- /* XXX: Why is this necessary? */
- rc = getrlimit(RLIMIT_NOFILE, &rlim);
- if (rc == -1) {
- warn("cannot retrieve max. number of open files resource limit");
- } else {
- rlim.rlim_cur = rlim.rlim_max;
- rc = setrlimit(RLIMIT_NOFILE, &rlim);
- if (rc == -1) {
- warn("cannot increase max. number of open files resource limit, try 'ulimit'");
- } else {
- if (Verbose)
- printf("increasing RLIMIT_NOFILE to max. %ld open files\n", (long)rlim.rlim_cur);
- }
- }
error += pkg_perform(&pkgs);
if (error != 0) {
diff --git a/pkgtools/pkg_install/files/add/perform.c b/pkgtools/pkg_install/files/add/perform.c
index b2a178557a3..5a2d09f98de 100644
--- a/pkgtools/pkg_install/files/add/perform.c
+++ b/pkgtools/pkg_install/files/add/perform.c
@@ -1,5 +1,4 @@
-/* $NetBSD: perform.c,v 1.73 2008/09/17 15:21:30 joerg Exp $ */
-
+/* $NetBSD: perform.c,v 1.74 2009/02/02 12:35:00 joerg Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
#endif
@@ -7,1045 +6,1427 @@
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
-#if HAVE_SYS_QUEUE_H
-#include <sys/queue.h>
-#endif
-#ifndef lint
-#if 0
-static const char *rcsid = "from FreeBSD Id: perform.c,v 1.44 1997/10/13 15:03:46 jkh Exp";
-#else
-__RCSID("$NetBSD: perform.c,v 1.73 2008/09/17 15:21:30 joerg Exp $");
-#endif
-#endif
-
-/*
- * FreeBSD install - a package for the installation and maintainance
- * of non-core utilities.
+__RCSID("$NetBSD: perform.c,v 1.74 2009/02/02 12:35:00 joerg Exp $");
+
+/*-
+ * Copyright (c) 2003 Grant Beattie <grant@NetBSD.org>
+ * Copyright (c) 2005 Dieter Baron <dillo@NetBSD.org>
+ * Copyright (c) 2007 Roland Illig <rillig@NetBSD.org>
+ * 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.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * This is the main body of the add module.
+ * 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_ASSERT_H
-#include <assert.h>
-#endif
+#include <sys/utsname.h>
#if HAVE_ERR_H
#include <err.h>
#endif
-#if HAVE_ERRNO_H
#include <errno.h>
-#endif
-#include "defs.h"
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <archive.h>
+#include <archive_entry.h>
+
#include "lib.h"
#include "add.h"
-#include "verify.h"
-#if HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-#if HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#if HAVE_STRING_H
-#include <string.h>
-#endif
-#if HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#if HAVE_SYS_UTSNAME_H
-#include <sys/utsname.h>
-#endif
+struct pkg_meta {
+ char *meta_contents;
+ char *meta_comment;
+ char *meta_desc;
+ char *meta_mtree;
+ char *meta_build_version;
+ char *meta_build_info;
+ char *meta_size_pkg;
+ char *meta_size_all;
+ char *meta_required_by;
+ char *meta_display;
+ char *meta_install;
+ char *meta_deinstall;
+ char *meta_preserve;
+ char *meta_views;
+ char *meta_installed_info;
+};
+
+struct pkg_task {
+ char *pkgname;
+
+ const char *prefix;
+ char *install_prefix;
+
+ char *logdir;
+ char *install_logdir;
+ char *other_version;
+
+ package_t plist;
-static char LogDir[MaxPathSize];
-static int zapLogDir; /* Should we delete LogDir? */
+ struct pkg_meta meta_data;
-static package_t Plist;
-static char *Home;
+ struct archive *archive;
+ struct archive_entry *entry;
-static lfile_head_t files;
+ char *buildinfo[BI_ENUM_COUNT];
-/* used in build information */
-enum {
- Good,
- Missing,
- Warning,
- Fatal
+ size_t dep_length, dep_allocated;
+ char **dependencies;
};
-static void
-normalise_platform(struct utsname *host_name)
-{
-#ifdef NUMERIC_VERSION_ONLY
- size_t span;
+static const struct pkg_meta_desc {
+ size_t entry_offset;
+ const char *entry_filename;
+ int required_file;
+ mode_t perm;
+} pkg_meta_descriptors[] = {
+ { offsetof(struct pkg_meta, meta_contents), CONTENTS_FNAME, 1, 0644 },
+ { offsetof(struct pkg_meta, meta_comment), COMMENT_FNAME, 1, 0444},
+ { offsetof(struct pkg_meta, meta_desc), DESC_FNAME, 1, 0444},
+ { offsetof(struct pkg_meta, meta_install), INSTALL_FNAME, 0, 0555 },
+ { offsetof(struct pkg_meta, meta_deinstall), DEINSTALL_FNAME, 0, 0555 },
+ { offsetof(struct pkg_meta, meta_display), DISPLAY_FNAME, 0, 0444 },
+ { offsetof(struct pkg_meta, meta_mtree), MTREE_FNAME, 0, 0444 },
+ { offsetof(struct pkg_meta, meta_build_version), BUILD_VERSION_FNAME, 0, 0444 },
+ { offsetof(struct pkg_meta, meta_build_info), BUILD_INFO_FNAME, 0, 0444 },
+ { offsetof(struct pkg_meta, meta_size_pkg), SIZE_PKG_FNAME, 0, 0444 },
+ { offsetof(struct pkg_meta, meta_size_all), SIZE_ALL_FNAME, 0, 0444 },
+ { offsetof(struct pkg_meta, meta_preserve), PRESERVE_FNAME, 0, 0444 },
+ { offsetof(struct pkg_meta, meta_views), VIEWS_FNAME, 0, 0444 },
+ { offsetof(struct pkg_meta, meta_required_by), REQUIRED_BY_FNAME, 0, 0644 },
+ { offsetof(struct pkg_meta, meta_installed_info), INSTALLED_INFO_FNAME, 0, 0644 },
+ { 0, NULL, 0 },
+};
- span = strspn(host_name->release, "0123456789.");
- host_name->release[span] = '\0';
-#endif
-}
+static int pkg_do(const char *, int);
-/* Read package build information */
static int
-read_buildinfo(char **buildinfo)
+mkdir_p(const char *path)
{
- char *key;
- char *line;
- size_t len;
- FILE *fp;
+ char *p, *cur_end;
+ int done;
- if ((fp = fopen(BUILD_INFO_FNAME, "r")) == NULL) {
- warnx("unable to open %s file.", BUILD_INFO_FNAME);
+ /*
+ * Handle the easy case of direct success or
+ * pre-existing directory first.
+ */
+ if (mkdir(path, 0777) == 0 || errno == EEXIST)
return 0;
- }
+ if (errno != ENOENT)
+ return -1;
- while ((line = fgetln(fp, &len)) != NULL) {
- if (line[len - 1] == '\n')
- line[len - 1] = '\0';
+ cur_end = p = xstrdup(path);
- if ((key = strsep(&line, "=")) == NULL)
- continue;
+ for (;;) {
+ /*
+ * First skip leading slashes either from / or
+ * from the last iteration.
+ */
+ cur_end += strspn(cur_end, "/");
+ /* Find end of actual directory name. */
+ cur_end += strcspn(cur_end, "/");
/*
- * pkgsrc used to create the BUILDINFO file using
- * "key= value", so skip the space if it's there.
+ * Remember if this is the last component and
+ * overwrite / if needed.
*/
- if (line == NULL)
- continue;
- if (line[0] == ' ')
- line += sizeof(char);
+ done = (*cur_end == '\0');
+ *cur_end = '\0';
/*
- * we only care about opsys, arch, version, and
- * dependency recommendations
+ * ENOENT can only happen if something else races us,
+ * in which case we should better give up.
*/
- if (line[0] != '\0') {
- if (strcmp(key, "OPSYS") == 0)
- buildinfo[BI_OPSYS] = strdup(line);
- else if (strcmp(key, "OS_VERSION") == 0)
- buildinfo[BI_OS_VERSION] = strdup(line);
- else if (strcmp(key, "MACHINE_ARCH") == 0)
- buildinfo[BI_MACHINE_ARCH] = strdup(line);
- else if (strcmp(key, "IGNORE_RECOMMENDED") == 0)
- buildinfo[BI_IGNORE_RECOMMENDED] = strdup(line);
- else if (strcmp(key, "USE_ABI_DEPENDS") == 0)
- buildinfo[BI_USE_ABI_DEPENDS] = strdup(line);
+ if (mkdir(p, 0777) == -1 && errno != EEXIST) {
+ free(p);
+ return -1;
}
+ if (done)
+ break;
+ *cur_end = '/';
}
- (void) fclose(fp);
- if (buildinfo[BI_OPSYS] == NULL ||
- buildinfo[BI_OS_VERSION] == NULL ||
- buildinfo[BI_MACHINE_ARCH] == NULL) {
- warnx("couldn't extract build information from package.");
- return 0;
+
+ free(p);
+ return 0;
+}
+
+/*
+ * Read meta data from archive.
+ * Bail out if a required entry is missing or entries are in the wrong order.
+ */
+static int
+read_meta_data(struct pkg_task *pkg)
+{
+ const struct pkg_meta_desc *descr, *last_descr;
+ const char *fname;
+ char **target;
+ int64_t size;
+ int r, found_required;
+
+ found_required = 0;
+
+ r = ARCHIVE_OK;
+ last_descr = 0;
+
+ if (pkg->entry != NULL)
+ goto skip_header;
+
+ for (;;) {
+ r = archive_read_next_header(pkg->archive, &pkg->entry);
+ if (r != ARCHIVE_OK)
+ break;
+skip_header:
+ fname = archive_entry_pathname(pkg->entry);
+
+ for (descr = pkg_meta_descriptors; descr->entry_filename;
+ ++descr) {
+ if (strcmp(descr->entry_filename, fname) == 0)
+ break;
+ }
+ if (descr->entry_filename == NULL)
+ break;
+
+ if (descr->required_file)
+ ++found_required;
+
+ target = (char **)((char *)&pkg->meta_data +
+ descr->entry_offset);
+ if (*target) {
+ warnx("duplicate entry, package corrupt");
+ return -1;
+ }
+ if (descr < last_descr) {
+ warnx("misordered package");
+ return -1;
+ }
+ last_descr = descr;
+
+ size = archive_entry_size(pkg->entry);
+ if (size > SSIZE_MAX - 1) {
+ warnx("package meta data too large to process");
+ return -1;
+ }
+ *target = xmalloc(size + 1);
+ if (archive_read_data(pkg->archive, *target, size) != size) {
+ warnx("cannot read package meta data");
+ return -1;
+ }
+ (*target)[size] = '\0';
+ }
+
+ if (r != ARCHIVE_OK)
+ pkg->entry = NULL;
+ if (r == ARCHIVE_EOF)
+ r = ARCHIVE_OK;
+
+ for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) {
+ if (descr->required_file)
+ --found_required;
+ }
+
+ return !found_required && r == ARCHIVE_OK ? 0 : -1;
+}
+
+/*
+ * Free meta data.
+ */
+static void
+free_meta_data(struct pkg_task *pkg)
+{
+ const struct pkg_meta_desc *descr;
+ char **target;
+
+ for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) {
+ target = (char **)((char *)&pkg->meta_data +
+ descr->entry_offset);
+ free(*target);
+ *target = NULL;
}
- return 1;
}
+/*
+ * Parse PLIST and populate pkg.
+ */
static int
-sanity_check(const char *pkg)
+pkg_parse_plist(struct pkg_task *pkg)
{
- int errc = 0;
-
- if (!fexists(CONTENTS_FNAME)) {
- warnx("package %s has no CONTENTS file!", pkg);
- errc = 1;
- } else if (!fexists(COMMENT_FNAME)) {
- warnx("package %s has no COMMENT file!", pkg);
- errc = 1;
- } else if (!fexists(DESC_FNAME)) {
- warnx("package %s has no DESC file!", pkg);
- errc = 1;
+ plist_t *p;
+
+ parse_plist(&pkg->plist, pkg->meta_data.meta_contents);
+ if ((p = find_plist(&pkg->plist, PLIST_NAME)) == NULL) {
+ warnx("Invalid PLIST: missing @name");
+ return -1;
}
- return errc;
+ if (pkg->pkgname == NULL)
+ pkg->pkgname = xstrdup(p->name);
+ else if (strcmp(pkg->pkgname, p->name) != 0) {
+ warnx("Signature and PLIST differ on package name");
+ return -1;
+ }
+ if ((p = find_plist(&pkg->plist, PLIST_CWD)) == NULL) {
+ warnx("Invalid PLIST: missing @cwd");
+ return -1;
+ }
+
+ if (Prefix != NULL &&
+ strcmp(p->name, Prefix) != 0) {
+ size_t len;
+
+ delete_plist(&pkg->plist, FALSE, PLIST_CWD, NULL);
+ add_plist_top(&pkg->plist, PLIST_CWD, Prefix);
+ free(pkg->meta_data.meta_contents);
+ stringify_plist(&pkg->plist, &pkg->meta_data.meta_contents, &len,
+ Prefix);
+ pkg->prefix = Prefix;
+ } else
+ pkg->prefix = p->name;
+
+ if (Destdir != NULL)
+ pkg->install_prefix = xasprintf("%s/%s", Destdir, pkg->prefix);
+ else
+ pkg->install_prefix = xstrdup(pkg->prefix);
+
+ return 0;
+}
+
+/*
+ * Helper function to extract value from a string of the
+ * form key=value ending at eol.
+ */
+static char *
+dup_value(const char *line, const char *eol)
+{
+ const char *key;
+ char *val;
+
+ key = strchr(line, '=');
+ val = xmalloc(eol - key);
+ memcpy(val, key + 1, eol - key - 1);
+ val[eol - key - 1] = '\0';
+ return val;
}
-/* install a pre-requisite package. Returns 1 if it installed it */
static int
-installprereq(const char *name, int *errc, int doupdate)
+check_already_installed(struct pkg_task *pkg)
{
- int ret;
- ret = 0;
+ char *filename;
+ int fd;
- if (Verbose)
- printf("Loading it from %s.\n", name);
- path_setenv("PKG_PATH");
-
- if (fexec_skipempty(BINDIR "/pkg_add", "-K", _pkgdb_getPKGDB_DIR(),
- "-s", get_verification(),
- doupdate > 1 ? "-uu" : (doupdate ? "-u" : ""),
- Fake ? "-n" : "",
- NoView ? "-L" : "",
- View ? "-w" : "", View ? View : "",
- Viewbase ? "-W" : "", Viewbase ? Viewbase : "",
- Force ? "-f" : "",
- Prefix ? "-p" : "", Prefix ? Prefix : "",
- Verbose ? "-v" : "",
- OverrideMachine ? "-m" : "",
- OverrideMachine ? OverrideMachine : "",
- NoInstall ? "-I" : "",
- "-A", name, NULL)) {
- warnx("autoload of dependency `%s' failed%s",
- name, Force ? " (proceeding anyway)" : "!");
- if (!Force)
- ++(*errc);
+ if (Force)
+ return -1;
+
+ filename = pkgdb_pkg_file(pkg->pkgname, CONTENTS_FNAME);
+ fd = open(filename, O_RDONLY);
+ free(filename);
+ if (fd == -1)
+ return -1;
+
+ /* We can only arrive here for explicitly requested packages. */
+ if (!Automatic && is_automatic_installed(pkg->pkgname)) {
+ if (Fake ||
+ mark_as_automatic_installed(pkg->pkgname, 0) == 0)
+ warnx("package `%s' was already installed as "
+ "dependency, now marked as installed "
+ "manually", pkg->pkgname);
} else {
- ret = 1;
+ warnx("package `%s' already recorded as installed",
+ pkg->pkgname);
}
+ return 0;
- return ret;
}
static int
-pkg_do_installed(int *replacing, char replace_via[MaxPathSize], char replace_to[MaxPathSize],
- Boolean is_depoted_pkg, const char *dbdir)
+check_other_installed(struct pkg_task *pkg)
{
- char replace_from[MaxPathSize];
- char *s;
- char buf[MaxPathSize];
- char *best_installed;
+ FILE *f, *f_pkg;
+ size_t len;
+ char *pkgbase, *iter, *filename;
+ package_t plist;
+ plist_t *p;
+ int status;
- const size_t replace_via_size = MaxPathSize;
- const size_t replace_to_size = MaxPathSize;
+ pkgbase = xstrdup(pkg->pkgname);
- if ((s = strrchr(PkgName, '-')) == NULL) {
- warnx("Package name %s does not contain a version, bailing out", PkgName);
+ if ((iter = strrchr(pkgbase, '-')) == NULL) {
+ free(pkgbase);
+ warnx("Invalid package name %s", pkg->pkgname);
return -1;
}
-
- /*
- * See if the pkg is already installed. If so, we might want to
- * upgrade/replace it. Otherwise, just return and let pkg_do work.
- */
- (void) snprintf(buf, sizeof(buf), "%.*s[0-9]*",
- (int)(s - PkgName) + 1, PkgName);
- best_installed = find_best_matching_installed_pkg(buf);
- if (best_installed == NULL)
+ *iter = '\0';
+ pkg->other_version = find_best_matching_installed_pkg(pkgbase);
+ free(pkgbase);
+ if (pkg->other_version == NULL)
return 0;
- if (!Replace || Fake) {
- if (is_depoted_pkg) {
- free(best_installed);
- return 0;
- } else {
- warnx("other version '%s' already installed", best_installed);
- free(best_installed);
- return 1; /* close enough for government work */
- }
+ if (!Replace) {
+ /* XXX This is redundant to the implicit conflict check. */
+ warnx("A different version of %s is already installed: %s",
+ pkg->pkgname, pkg->other_version);
+ return -1;
}
- /* XXX Should list the steps in Fake mode */
- snprintf(replace_from, sizeof(replace_from), "%s/%s/" REQUIRED_BY_FNAME,
- dbdir, best_installed);
- snprintf(replace_via, replace_via_size, "%s/.%s." REQUIRED_BY_FNAME,
- dbdir, best_installed);
- snprintf(replace_to, replace_to_size, "%s/%s/" REQUIRED_BY_FNAME,
- dbdir, PkgName);
-
- if (Verbose)
- printf("Upgrading %s to %s.\n", best_installed, PkgName);
+ filename = pkgdb_pkg_file(pkg->other_version, REQUIRED_BY_FNAME);
+ errno = 0;
+ f = fopen(filename, "r");
+ free(filename);
+ if (f == NULL) {
+ if (errno == ENOENT) {
+ /* No packages depend on this, so everything is well. */
+ return 0;
+ }
+ warnx("Can't open +REQUIRED_BY of %s", pkg->other_version);
+ return -1;
+ }
- if (fexists(replace_from)) { /* Are there any dependencies? */
- /*
- * Upgrade step 1/4: Check if the new version is ok with all pkgs
- * (from +REQUIRED_BY) that require this pkg
- */
- FILE *rb; /* +REQUIRED_BY file */
- char pkg2chk[MaxPathSize];
-
- rb = fopen(replace_from, "r");
- if (! rb) {
- warnx("Cannot open '%s' for reading%s", replace_from,
- Force ? " (proceeding anyways)" : "");
- if (Force)
- goto ignore_replace_depends_check;
- else
- return -1;
+ status = 0;
+
+ while ((iter = fgetln(f, &len)) != NULL) {
+ if (iter[len - 1] == '\n')
+ iter[len - 1] = '\0';
+ filename = pkgdb_pkg_file(iter, CONTENTS_FNAME);
+ if ((f_pkg = fopen(filename, "r")) == NULL) {
+ warnx("Can't open +CONTENTS of depending package %s",
+ iter);
+ fclose(f);
+ return -1;
}
- while (fgets(pkg2chk, sizeof(pkg2chk), rb)) {
- package_t depPlist;
- FILE *depf;
- plist_t *depp;
- char depC[MaxPathSize];
-
- s = strrchr(pkg2chk, '\n');
- if (s)
- *s = '\0'; /* strip trailing '\n' */
-
- /*
- * step into pkg2chk, read it's +CONTENTS file and see if
- * all @pkgdep lines agree with PkgName (using pkg_match())
+ read_plist(&plist, f_pkg);
+ fclose(f_pkg);
+ for (p = plist.head; p != NULL; p = p->next) {
+ if (p->type == PLIST_IGNORE) {
+ p = p->next;
+ continue;
+ } else if (p->type != PLIST_PKGDEP)
+ continue;
+ /*
+ * XXX This is stricter than necessary.
+ * XXX One pattern might be fulfilled by
+ * XXX a different package and still need this
+ * XXX one for a different pattern.
*/
- snprintf(depC, sizeof(depC), "%s/%s/%s", dbdir, pkg2chk, CONTENTS_FNAME);
- depf = fopen(depC , "r");
- if (depf == NULL) {
- warnx("Cannot check depends in '%s'%s", depC,
- Force ? " (proceeding anyways)" : "!" );
- if (Force)
- goto ignore_replace_depends_check;
- else
- return -1;
- }
- read_plist(&depPlist, depf);
- fclose(depf);
-
- for (depp = depPlist.head; depp; depp = depp->next) {
- char base_new[MaxPathSize];
- char base_exist[MaxPathSize];
- char *s2;
-
- if (depp->type != PLIST_PKGDEP)
- continue;
-
- /*
- * Prepare basename (no versions) of both pkgs,
- * to see if we want to compare against that
- * one at all.
- */
- strlcpy(base_new, PkgName, sizeof(base_new));
- s2 = strpbrk(base_new, "<>[]?*{"); /* } */
- if (s2)
- *s2 = '\0';
- else {
- s2 = strrchr(base_new, '-');
- if (s2)
- *s2 = '\0';
- }
- strlcpy(base_exist, depp->name, sizeof(base_exist));
- s2 = strpbrk(base_exist, "<>[]?*{"); /* } */
- if (s2)
- *s2 = '\0';
- else {
- s2 = strrchr(base_exist, '-');
- if (s2)
- *s2 = '\0';
- }
- if (strcmp(base_new, base_exist) == 0) {
- /* Same pkg, so do the interesting compare */
- if (pkg_match(depp->name, PkgName)) {
- if (Verbose)
- printf("@pkgdep check: %s is ok for %s (in %s pkg)\n",
- PkgName, depp->name, pkg2chk);
- } else {
- printf("Package %s requires %s, \n\tCannot replace with %s%s\n",
- pkg2chk, depp->name, PkgName,
- Force? " (proceeding anyways)" : "!");
- if (! Force)
- return -1;
- }
- }
- }
+ if (pkg_match(p->name, pkg->other_version) == 0)
+ continue;
+ if (pkg_match(p->name, pkg->pkgname) == 1)
+ continue; /* Both match, ok. */
+ warnx("Dependency of %s fulfilled by %s, but not by %s",
+ iter, pkg->other_version, pkg->pkgname);
+ if (!Force)
+ status = -1;
+ break;
}
- fclose(rb);
+ free_plist(&plist);
+ }
-ignore_replace_depends_check:
- /*
- * Upgrade step 2/4: Do the actual update by moving aside
- * the +REQUIRED_BY file, deinstalling the old pkg, adding
- * the new one and moving the +REQUIRED_BY file back
- * into place (finished in step 3/4)
- */
- if (Verbose)
- printf("mv %s %s\n", replace_from, replace_via);
- if (rename(replace_from, replace_via) != 0)
- err(EXIT_FAILURE, "renaming \"%s\" to \"%s\" failed", replace_from, replace_via);
+ fclose(f);
- *replacing = 1;
- }
+ return status;
+}
- if (Verbose) {
- printf("%s/pkg_delete -K %s '%s'\n",
- BINDIR, dbdir, best_installed);
+/*
+ * Read package build information from meta data.
+ */
+static int
+read_buildinfo(struct pkg_task *pkg)
+{
+ const char *data, *eol, *next_line;
+
+ data = pkg->meta_data.meta_build_info;
+
+ for (; *data != '\0'; data = next_line) {
+ if ((eol = strchr(data, '\n')) == NULL) {
+ eol = data + strlen(data);
+ next_line = eol;
+ } else
+ next_line = eol + 1;
+
+ if (strncmp(data, "OPSYS=", 6) == 0)
+ pkg->buildinfo[BI_OPSYS] = dup_value(data, eol);
+ else if (strncmp(data, "OS_VERSION=", 11) == 0)
+ pkg->buildinfo[BI_OS_VERSION] = dup_value(data, eol);
+ else if (strncmp(data, "MACHINE_ARCH=", 13) == 0)
+ pkg->buildinfo[BI_MACHINE_ARCH] = dup_value(data, eol);
+ else if (strncmp(data, "IGNORE_RECOMMENDED=", 19) == 0)
+ pkg->buildinfo[BI_IGNORE_RECOMMENDED] = dup_value(data,
+ eol);
+ else if (strncmp(data, "USE_ABI_DEPENDS=", 16) == 0)
+ pkg->buildinfo[BI_USE_ABI_DEPENDS] = dup_value(data,
+ eol);
+ }
+ if (pkg->buildinfo[BI_OPSYS] == NULL ||
+ pkg->buildinfo[BI_OS_VERSION] == NULL ||
+ pkg->buildinfo[BI_MACHINE_ARCH] == NULL) {
+ warnx("Not all required build information are present.");
+ return -1;
}
- fexec(BINDIR "/pkg_delete", "-K", dbdir, best_installed, NULL);
- free(best_installed);
+ if ((pkg->buildinfo[BI_USE_ABI_DEPENDS] != NULL &&
+ strcasecmp(pkg->buildinfo[BI_USE_ABI_DEPENDS], "YES") != 0) ||
+ (pkg->buildinfo[BI_IGNORE_RECOMMENDED] != NULL &&
+ strcasecmp(pkg->buildinfo[BI_IGNORE_RECOMMENDED], "NO") != 0)) {
+ warnx("%s was built to ignore ABI dependencies", pkg->pkgname);
+ }
return 0;
}
/*
- * Install a single package
- * Returns 0 if everything is ok, >0 else
+ * Free buildinfo.
*/
-static int
-pkg_do(const char *pkg, lpkg_head_t *pkgs)
+static void
+free_buildinfo(struct pkg_task *pkg)
{
- char playpen[MaxPathSize];
- char replace_via[MaxPathSize];
- char replace_to[MaxPathSize];
- char *buildinfo[BI_ENUM_COUNT];
- int replacing = 0;
- char dbdir[MaxPathSize];
- const char *tmppkg;
- FILE *cfile;
- int errc, err_prescan;
- plist_t *p;
- struct stat sb;
- struct utsname host_uname;
- uint64_t needed;
- Boolean is_depoted_pkg = FALSE;
- lfile_t *lfp;
- int result;
-
- errc = 0;
- zapLogDir = 0;
- LogDir[0] = '\0';
- strlcpy(playpen, FirstPen, sizeof(playpen));
- memset(buildinfo, '\0', sizeof(buildinfo));
-
- umask(DEF_UMASK);
-
- tmppkg = fileFindByPath(pkg);
- if (tmppkg == NULL) {
- warnx("no pkg found for '%s', sorry.", pkg);
- return 1;
+ size_t i;
+
+ for (i = 0; i < BI_ENUM_COUNT; ++i) {
+ free(pkg->buildinfo[i]);
+ pkg->buildinfo[i] = NULL;
}
+}
- pkg = tmppkg;
+/*
+ * Write meta data files to pkgdb after creating the directory.
+ */
+static int
+write_meta_data(struct pkg_task *pkg)
+{
+ const struct pkg_meta_desc *descr;
+ char *filename, **target;
+ size_t len;
+ ssize_t ret;
+ int fd;
- if (IS_URL(pkg)) {
- Home = fileGetURL(pkg);
- if (Home == NULL) {
- warnx("unable to fetch `%s' by URL", pkg);
- }
+ if (Fake)
+ return 0;
- /* make sure the pkg is verified */
- if (!verify(pkg)) {
- warnx("Package %s will not be extracted", pkg);
- goto bomb;
+ if (mkdir_p(pkg->install_logdir)) {
+ warn("Can't create pkgdb entry: %s", pkg->install_logdir);
+ return -1;
+ }
+
+ for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) {
+ target = (char **)((char *)&pkg->meta_data +
+ descr->entry_offset);
+ if (*target == NULL)
+ continue;
+ filename = xasprintf("%s/%s", pkg->install_logdir,
+ descr->entry_filename);
+ (void)unlink(filename);
+ fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, descr->perm);
+ if (fd == -1) {
+ warn("Can't open meta data file: %s", filename);
+ return -1;
}
- } else { /* local */
- if (!IS_STDIN(pkg)) {
- /* not stdin */
- if (!ispkgpattern(pkg)) {
- if (stat(pkg, &sb) == FAIL) {
- warnx("can't stat package file '%s'", pkg);
- goto bomb;
- }
- /* make sure the pkg is verified */
- if (!verify(pkg)) {
- warnx("Package %s will not be extracted", pkg);
- goto bomb;
- }
+ len = strlen(*target);
+ do {
+ ret = write(fd, *target, len);
+ if (ret == -1) {
+ warn("Can't write meta data file: %s",
+ filename);
+ free(filename);
+ return -1;
}
- LFILE_ADD(&files, lfp, CONTENTS_FNAME);
- } else {
- /* some values for stdin */
- sb.st_size = 100000; /* Make up a plausible average size */
+ len -= ret;
+ } while (ret > 0);
+ if (close(fd) == -1) {
+ warn("Can't close meta data file: %s", filename);
+ free(filename);
+ return -1;
}
- Home = make_playpen(playpen, sizeof(playpen), sb.st_size * 4);
- if (!Home)
- warnx("unable to make playpen for %ld bytes",
- (long) (sb.st_size * 4));
- result = unpack(pkg, &files);
- while ((lfp = TAILQ_FIRST(&files)) != NULL) {
- TAILQ_REMOVE(&files, lfp, lf_link);
- free(lfp);
+ free(filename);
+ }
+
+ return 0;
+}
+
+/*
+ * Helper function for extract_files.
+ */
+static int
+copy_data_to_disk(struct archive *reader, struct archive *writer,
+ const char *filename)
+{
+ int r;
+ const void *buff;
+ size_t size;
+ off_t offset;
+
+ for (;;) {
+ r = archive_read_data_block(reader, &buff, &size, &offset);
+ if (r == ARCHIVE_EOF)
+ return 0;
+ if (r != ARCHIVE_OK) {
+ warnx("Read error for %s: %s", filename,
+ archive_error_string(reader));
+ return -1;
}
- if (result) {
- warnx("unable to extract table of contents file from `%s' - not a package?",
- pkg);
- goto bomb;
+ r = archive_write_data_block(writer, buff, size, offset);
+ if (r != ARCHIVE_OK) {
+ warnx("Write error for %s: %s", filename,
+ archive_error_string(writer));
+ return -1;
}
}
+}
- cfile = fopen(CONTENTS_FNAME, "r");
- if (!cfile) {
- warnx("unable to open table of contents file `%s' - not a package?",
- CONTENTS_FNAME);
- goto bomb;
- }
- read_plist(&Plist, cfile);
- fclose(cfile);
+/*
+ * Extract package.
+ * Any misordered, missing or unlisted file in the package is an error.
+ */
- if (!IS_URL(pkg)) {
- /*
- * Apply a crude heuristic to see how much space the package will
- * take up once it's unpacked. I've noticed that most packages
- * compress an average of 75%, so multiply by 4 for good measure.
- */
+static const int extract_flags = /* ARCHIVE_EXTRACT_OWNER | */
+ ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_UNLINK |
+ ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR;
- needed = 4 * (uint64_t) sb.st_size;
- if (min_free(playpen) < needed) {
- warnx("projected size of %" MY_PRIu64 " bytes exceeds available free space\n"
- "in %s. Please set your PKG_TMPDIR variable to point\n"
- "to a location with more free space and try again.",
- needed, playpen);
- goto bomb;
- }
+static int
+extract_files(struct pkg_task *pkg)
+{
+ char cmd[MaxPathSize];
+ const char *owner, *group, *permissions;
+ struct archive *writer;
+ int r;
+ plist_t *p;
+ const char *last_file;
+ char *fullpath;
- /* Finally unpack the whole mess */
- if (unpack(pkg, NULL)) {
- warnx("unable to extract `%s'!", pkg);
- goto bomb;
- }
+ if (Fake)
+ return 0;
+
+ if (mkdir_p(pkg->install_prefix)) {
+ warn("Can't create prefix: %s", pkg->install_prefix);
+ return -1;
}
- /* Check for sanity */
- if (sanity_check(pkg))
- goto bomb;
+ if (!NoRecord && !pkgdb_open(ReadWrite)) {
+ warn("Can't open pkgdb for writing");
+ return -1;
+ }
- /* Read the OS, version and architecture from BUILD_INFO file */
- if (!read_buildinfo(buildinfo)) {
- warn("can't read build information from %s", BUILD_INFO_FNAME);
- if (!Force) {
- warnx("aborting.");
- goto bomb;
- }
+ if (chdir(pkg->install_prefix) == -1) {
+ warn("Can't change into prefix: %s", pkg->install_prefix);
+ return -1;
}
- if (uname(&host_uname) < 0) {
- warnx("uname() failed.");
- if (!Force) {
- warnx("aborting.");
- goto bomb;
- }
- } else {
- int status = Good;
+ writer = archive_write_disk_new();
+ archive_write_disk_set_options(writer, extract_flags);
+ archive_write_disk_set_standard_lookup(writer);
+
+ owner = NULL;
+ group = NULL;
+ permissions = NULL;
+ last_file = NULL;
+
+ r = -1;
+
+ for (p = pkg->plist.head; p != NULL; p = p->next) {
+ switch (p->type) {
+ case PLIST_FILE:
+ last_file = p->name;
+ if (pkg->entry == NULL) {
+ warnx("PLIST entry not in package (%s)",
+ archive_entry_pathname(pkg->entry));
+ goto out;
+ }
+ if (strcmp(p->name, archive_entry_pathname(pkg->entry))) {
+ warnx("PLIST entry and package don't match (%s vs %s)",
+ p->name, archive_entry_pathname(pkg->entry));
+ goto out;
+ }
+ fullpath = xasprintf("%s/%s", pkg->prefix, p->name);
+ pkgdb_store(fullpath, pkg->pkgname);
+ free(fullpath);
+ if (Verbose)
+ printf("%s", p->name);
+ break;
- normalise_platform(&host_uname);
+ case PLIST_CMD:
+ if (format_cmd(cmd, sizeof(cmd), p->name, pkg->prefix, last_file))
+ return -1;
+ printf("Executing '%s'\n", cmd);
+ if (!Fake && system(cmd))
+ warnx("command '%s' failed", cmd); /* XXX bail out? */
+ continue;
- /* check that we have read some values from buildinfo */
- if (buildinfo[BI_OPSYS] == NULL) {
- warnx("Missing operating system value from build information");
- status = Missing;
- }
- if (buildinfo[BI_MACHINE_ARCH] == NULL) {
- warnx("Missing machine architecture value from build information");
- status = Missing;
- }
- if (buildinfo[BI_OS_VERSION] == NULL) {
- warnx("Missing operating system version value from build information");
- status = Missing;
+ case PLIST_CHMOD:
+ permissions = p->name;
+ continue;
+
+ case PLIST_CHOWN:
+ owner = p->name;
+ continue;
+
+ case PLIST_CHGRP:
+ group = p->name;
+ continue;
+
+ case PLIST_IGNORE:
+ p = p->next;
+ continue;
+
+ default:
+ continue;
}
- if (status == Good) {
- const char *effective_arch;
-
- if (OverrideMachine != NULL)
- effective_arch = OverrideMachine;
- else
- effective_arch = MACHINE_ARCH;
-
- /* If either the OS or arch are different, bomb */
- if (strcmp(OPSYS_NAME, buildinfo[BI_OPSYS]) != 0)
- status = Fatal;
- if (strcmp(effective_arch, buildinfo[BI_MACHINE_ARCH]) != 0)
- status = Fatal;
-
- /* If OS and arch are the same, warn if version differs */
- if (status == Good &&
- strcmp(host_uname.release, buildinfo[BI_OS_VERSION]) != 0)
- status = Warning;
-
- if (status != Good) {
- warnx("Warning: package `%s' was built for a different version of the OS:", pkg);
- warnx("%s/%s %s (pkg) vs. %s/%s %s (this host)",
- buildinfo[BI_OPSYS],
- buildinfo[BI_MACHINE_ARCH],
- buildinfo[BI_OS_VERSION],
- OPSYS_NAME,
- effective_arch,
- host_uname.release);
- }
+ r = archive_write_header(writer, pkg->entry);
+ if (r != ARCHIVE_OK) {
+ warnx("Failed to write %s: %s",
+ archive_entry_pathname(pkg->entry),
+ archive_error_string(writer));
+ goto out;
}
- if (!Force && status == Fatal) {
- warnx("aborting.");
- goto bomb;
+ if (owner != NULL)
+ archive_entry_set_uname(pkg->entry, owner);
+ if (group != NULL)
+ archive_entry_set_uname(pkg->entry, group);
+ if (permissions != NULL) {
+ mode_t mode;
+
+ mode = archive_entry_mode(pkg->entry);
+ mode = getmode(setmode(permissions), mode);
+ archive_entry_set_mode(pkg->entry, mode);
}
- }
- /* Check if USE_ABI_DEPENDS or IGNORE_RECOMMENDED was set
- * when this package was built. IGNORE_RECOMMENDED is historical. */
+ r = copy_data_to_disk(pkg->archive, writer,
+ archive_entry_pathname(pkg->entry));
+ if (r)
+ goto out;
+ if (Verbose)
+ printf("\n");
- if ((buildinfo[BI_USE_ABI_DEPENDS] != NULL &&
- strcasecmp(buildinfo[BI_USE_ABI_DEPENDS], "YES") != 0) ||
- (buildinfo[BI_IGNORE_RECOMMENDED] != NULL &&
- strcasecmp(buildinfo[BI_IGNORE_RECOMMENDED], "NO") != 0)) {
- warnx("%s was built", pkg);
- warnx("\tto ignore recommended ABI dependencies, this may cause problems!\n");
+ r = archive_read_next_header(pkg->archive, &pkg->entry);
+ if (r == ARCHIVE_EOF) {
+ pkg->entry = NULL;
+ continue;
+ }
+ if (r != ARCHIVE_OK) {
+ warnx("Failed to read from archive: %s",
+ archive_error_string(pkg->archive));
+ goto out;
+ }
}
- /*
- * If we have a prefix, delete the first one we see and add this
- * one in place of it.
- */
- if (Prefix) {
- delete_plist(&Plist, FALSE, PLIST_CWD, NULL);
- add_plist_top(&Plist, PLIST_CWD, Prefix);
+ if (pkg->entry != NULL) {
+ warnx("Package contains entries not in PLIST: %s",
+ archive_entry_pathname(pkg->entry));
+ goto out;
}
- /* Protect against old packages with bogus @name fields */
- p = find_plist(&Plist, PLIST_NAME);
- if (p->name == NULL) {
- warnx("PLIST contains no @name field");
- goto bomb;
- }
- PkgName = p->name;
+ r = 0;
- if (fexists(VIEWS_FNAME))
- is_depoted_pkg = TRUE;
-
- /*
- * Depoted packages' dbdir is the same as DEPOTBASE. Non-depoted
- * packages' dbdir comes from the command-line or the environment.
- */
- if (is_depoted_pkg) {
- p = find_plist(&Plist, PLIST_CWD);
- if (p == NULL) {
- warn("no @cwd in +CONTENTS file?! aborting.");
- goto bomb;
- }
- (void) strlcpy(dbdir, dirname_of(p->name), sizeof(dbdir));
- (void) strlcpy(LogDir, p->name, sizeof(LogDir));
- } else {
- (void) strlcpy(dbdir, _pkgdb_getPKGDB_DIR(), sizeof(dbdir));
- (void) snprintf(LogDir, sizeof(LogDir), "%s/%s", dbdir, PkgName);
- }
+out:
+ if (!NoRecord)
+ pkgdb_close();
+ archive_write_close(writer);
+ archive_write_finish(writer);
- /* Set environment variables expected by the +INSTALL script. */
- setenv(PKG_PREFIX_VNAME, (p = find_plist(&Plist, PLIST_CWD)) ? p->name : ".", 1);
- setenv(PKG_METADATA_DIR_VNAME, LogDir, 1);
- setenv(PKG_REFCOUNT_DBDIR_VNAME, pkgdb_refcount_dir(), 1);
-
- /* make sure dbdir actually exists! */
- if (!(isdir(dbdir) || islinktodir(dbdir))) {
- if (fexec("mkdir", "-p", dbdir, NULL)) {
- errx(EXIT_FAILURE,
- "Database-dir %s cannot be generated, aborting.",
- dbdir);
- }
+ return r;
+}
+
+/*
+ * Register dependencies after sucessfully installing the package.
+ */
+static void
+pkg_register_depends(struct pkg_task *pkg)
+{
+ int fd;
+ size_t text_len, i;
+ char *required_by, *text;
+
+ if (Fake)
+ return;
+
+ if (pkg->other_version != NULL)
+ return; /* XXX It's using the old dependencies. */
+
+ text = xasprintf("%s\n", pkg->pkgname);
+ text_len = strlen(text);
+
+ for (i = 0; i < pkg->dep_length; ++i) {
+ required_by = pkgdb_pkg_file(pkg->dependencies[i], REQUIRED_BY_FNAME);
+
+ fd = open(required_by, O_WRONLY | O_APPEND | O_CREAT, 0644);
+ if (fd == -1)
+ warn("can't open dependency file '%s',"
+ "registration is incomplete!", required_by);
+ else if (write(fd, text, text_len) != text_len)
+ warn("can't write to dependency file `%s'", required_by);
+ else if (close(fd) == -1)
+ warn("cannot close file %s", required_by);
+
+ free(required_by);
}
- /* See if this package (exact version) is already registered */
- if (isdir(LogDir) && !Force) {
- if (!Automatic && is_automatic_installed(PkgName)) {
- if (mark_as_automatic_installed(PkgName, 0) == 0)
- warnx("package `%s' was already installed as "
- "dependency, now marked as installed "
- "manually", PkgName);
+ free(text);
+}
+
+/*
+ * Reduce the result from uname(3) to a canonical form.
+ */
+static void
+normalise_platform(struct utsname *host_name)
+{
+#ifdef NUMERIC_VERSION_ONLY
+ size_t span;
+
+ span = strspn(host_name->release, "0123456789.");
+ host_name->release[span] = '\0';
+#endif
+}
+
+/*
+ * Check build platform of the package against local host.
+ */
+static int
+check_platform(struct pkg_task *pkg)
+{
+ struct utsname host_uname;
+ const char *effective_arch;
+ int fatal;
+
+ if (uname(&host_uname) < 0) {
+ if (Force) {
+ warnx("uname() failed, continuing.");
+ return 0;
} else {
- warnx("package `%s' already recorded as installed",
- PkgName);
+ warnx("uname() failed, aborting.");
+ return -1;
}
- goto success; /* close enough for government work */
}
- /* See if some other version of us is already installed */
- switch (pkg_do_installed(&replacing, replace_via, replace_to, is_depoted_pkg, dbdir)) {
- case 0:
- break;
- case 1:
- errc = 1;
- goto success;
- case -1:
- goto bomb;
+ normalise_platform(&host_uname);
+
+ if (OverrideMachine != NULL)
+ effective_arch = OverrideMachine;
+ else
+ effective_arch = MACHINE_ARCH;
+
+ /* If either the OS or arch are different, bomb */
+ if (strcmp(OPSYS_NAME, pkg->buildinfo[BI_OPSYS]) ||
+ strcmp(effective_arch, pkg->buildinfo[BI_MACHINE_ARCH]) != 0)
+ fatal = 1;
+ else
+ fatal = 0;
+
+ if (fatal ||
+ strcmp(host_uname.release, pkg->buildinfo[BI_OS_VERSION]) != 0) {
+ warnx("Warning: package `%s' was built for a platform:",
+ pkg->pkgname);
+ warnx("%s/%s %s (pkg) vs. %s/%s %s (this host)",
+ pkg->buildinfo[BI_OPSYS],
+ pkg->buildinfo[BI_MACHINE_ARCH],
+ pkg->buildinfo[BI_OS_VERSION],
+ OPSYS_NAME,
+ effective_arch,
+ host_uname.release);
+ if (!Force && fatal)
+ return -1;
}
+ return 0;
+}
- /* See if there are conflicting packages installed */
- for (p = Plist.head; p; p = p->next) {
- char *best_installed;
+/*
+ * Run the install script.
+ */
+static int
+run_install_script(struct pkg_task *pkg, const char *argument)
+{
+ int ret;
+ char *filename;
+
+ if (pkg->meta_data.meta_install == NULL || NoInstall)
+ return 0;
+
+ if (Destdir != NULL)
+ setenv(PKG_DESTDIR_VNAME, Destdir, 1);
+ setenv(PKG_PREFIX_VNAME, pkg->prefix, 1);
+ setenv(PKG_METADATA_DIR_VNAME, pkg->logdir, 1);
+ setenv(PKG_REFCOUNT_DBDIR_VNAME, pkgdb_refcount_dir(), 1);
+
+ if (Verbose)
+ printf("Running install with PRE-INSTALL for %s.\n", pkg->pkgname);
+ if (Fake)
+ return 0;
- if (p->type != PLIST_PKGCFL)
+ filename = pkgdb_pkg_file(pkg->pkgname, INSTALL_FNAME);
+
+ ret = 0;
+ errno = 0;
+ if (fcexec(pkg->install_logdir, filename, pkg->pkgname, argument,
+ (void *)NULL)) {
+ if (errno != 0)
+ warn("exec of install script failed");
+ else
+ warnx("install script returned error status");
+ ret = -1;
+ }
+ free(filename);
+
+ return ret;
+}
+
+static int
+check_explicit_conflict(struct pkg_task *pkg)
+{
+ char *installed, *installed_pattern;
+ plist_t *p;
+ int status;
+
+ status = 0;
+
+ for (p = pkg->plist.head; p != NULL; p = p->next) {
+ if (p->type == PLIST_IGNORE) {
+ p = p->next;
continue;
- if (Verbose)
- printf("Package `%s' conflicts with `%s'.\n", PkgName, p->name);
- best_installed = find_best_matching_installed_pkg(p->name);
- if (best_installed) {
+ } else if (p->type != PLIST_PKGCFL)
+ continue;
+ installed = find_best_matching_installed_pkg(p->name);
+ if (installed) {
warnx("Package `%s' conflicts with `%s', and `%s' is installed.",
- PkgName, p->name, best_installed);
- free(best_installed);
- ++errc;
+ pkg->pkgname, p->name, installed);
+ free(installed);
+ status = -1;
}
}
- /* See if any of the installed packages conflicts with this one. */
- {
- char *inst_pkgname, *inst_pattern;
+ if (some_installed_package_conflicts_with(pkg->pkgname,
+ pkg->other_version, &installed, &installed_pattern)) {
+ warnx("Installed package `%s' conflicts with `%s' when trying to install `%s'.",
+ installed, installed_pattern, pkg->pkgname);
+ free(installed);
+ free(installed_pattern);
+ status = -1;
+ }
+
+ return status;
+}
- if (some_installed_package_conflicts_with(PkgName, &inst_pkgname, &inst_pattern)) {
- warnx("Installed package `%s' conflicts with `%s' when trying to install `%s'.",
- inst_pkgname, inst_pattern, PkgName);
- free(inst_pkgname);
- free(inst_pattern);
- errc++;
- }
+static int
+check_implicit_conflict(struct pkg_task *pkg)
+{
+ plist_t *p;
+ char *fullpath, *existing;
+ int status;
+
+ if (!pkgdb_open(ReadOnly)) {
+#if notyet /* XXX empty pkgdb without database? */
+ warn("Can't open pkgdb for reading");
+ return -1;
+#else
+ return 0;
+#endif
}
- /* Quick pre-check if any conflicting dependencies are installed
- * (e.g. version X is installed, but version Y is required)
- */
- err_prescan=0;
- for (p = Plist.head; p; p = p->next) {
- char *best_installed;
-
- if (p->type != PLIST_PKGDEP)
+ status = 0;
+
+ for (p = pkg->plist.head; p != NULL; p = p->next) {
+ if (p->type == PLIST_IGNORE) {
+ p = p->next;
continue;
- if (Verbose)
- printf("Depends pre-scan: `%s' required.\n", p->name);
- best_installed = find_best_matching_installed_pkg(p->name);
- if (best_installed == NULL) {
- /*
- * required pkg not found. look if it's available with a more liberal
- * pattern. If so, this will lead to problems later (check on "some
- * other version of us is already installed" will fail, see above),
- * and we better stop right now.
- */
- char *s;
- int skip = -1;
-
- /* doing this right required to parse the full version(s),
- * do a 99% solution here for now */
- if (strchr(p->name, '{'))
- continue; /* would remove trailing '}' else */
-
- if ((s = strpbrk(p->name, "<>")) != NULL) {
- skip = 0;
- } else if (((s = strstr(p->name, "-[0-9]*")) != NULL) &&
- (*(s + sizeof("-[0-9]*") - 1) == '\0')) {
- /* -[0-9]* already present so no need to */
- /* add it a second time */
- skip = -1;
- } else if ((s = strrchr(p->name, '-')) != NULL) {
- skip = 1;
- }
-
- if (skip >= 0) {
- char buf[MaxPathSize];
-
- (void) snprintf(buf, sizeof(buf),
- skip ? "%.*s[0-9]*" : "%.*s-[0-9]*",
- (int)(s - p->name) + skip, p->name);
- best_installed = find_best_matching_installed_pkg(buf);
- if (best_installed) {
- int done = 0;
-
- if (Replace > 1)
- {
- int errc0 = 0;
- char tmp[MaxPathSize];
-
- warnx("Attempting to update `%s' using binary package\n", p->name);
- /* Yes, append .tgz after the version so the */
- /* pattern can match a filename. */
- snprintf(tmp, sizeof(tmp), "%s.tgz", p->name);
- done = installprereq(tmp, &errc0, 2);
- }
- else if (Replace)
- {
- warnx("To perform necessary upgrades on required packages specify -u twice.\n");
- }
-
- if (!done)
- {
- warnx("pkg `%s' required, but `%s' found installed.",
- p->name, best_installed);
- if (Force) {
- warnx("Proceeding anyway.");
- } else {
- err_prescan++;
- }
- }
- free(best_installed);
- }
- }
- } else {
- free(best_installed);
+ } else if (p->type != PLIST_FILE)
+ continue;
+
+ fullpath = xasprintf("%s/%s", pkg->prefix, p->name);
+ existing = pkgdb_retrieve(fullpath);
+ free(fullpath);
+ if (existing == NULL)
+ continue;
+ if (pkg->other_version != NULL &&
+ strcmp(pkg->other_version, existing) == 0)
+ continue;
+
+ warnx("Conflicting PLIST with %s: %s", existing, p->name);
+ if (!Force) {
+ status = -1;
+ if (!Verbose)
+ break;
}
}
- if (err_prescan > 0) {
- warnx("Please resolve this conflict!");
- errc += err_prescan;
- goto success; /* close enough */
- }
-
-
- /* Now check the packing list for dependencies */
- for (p = Plist.head; p; p = p->next) {
- char *best_installed;
-
- if (p->type != PLIST_PKGDEP)
+
+ pkgdb_close();
+ return status;
+}
+
+static int
+check_dependencies(struct pkg_task *pkg)
+{
+ plist_t *p;
+ char *best_installed;
+ int status;
+ size_t i;
+
+ status = 0;
+
+ for (p = pkg->plist.head; p != NULL; p = p->next) {
+ if (p->type == PLIST_IGNORE) {
+ p = p->next;
+ continue;
+ } else if (p->type != PLIST_PKGDEP)
continue;
- if (Verbose)
- printf("Package `%s' depends on `%s'.\n", PkgName, p->name);
best_installed = find_best_matching_installed_pkg(p->name);
if (best_installed == NULL) {
- /* required pkg not found - need to pull in */
-
- if (Fake) {
- /* fake install (???) */
- if (Verbose)
- printf("Package dependency %s for %s not installed%s\n", p->name, pkg,
- Force ? " (proceeding anyway)" : "!");
- } else {
- int done = 0;
- int errc0 = 0;
-
- done = installprereq(p->name, &errc0, (Replace > 1) ? 2 : 0);
- if (!done && !Force) {
- errc += errc0;
+ /* XXX check cyclic dependencies? */
+ if (Fake || NoRecord) {
+ if (!Force) {
+ warnx("Missing dependency %s\n",
+ p->name);
+ status = -1;
+ break;
}
+ warnx("Missing dependency %s, continuing",
+ p->name);
+ continue;
}
- } else {
- if (Verbose)
- printf(" - %s already installed.\n", best_installed);
+ if (pkg_do(p->name, 1)) {
+ warnx("Can't install dependency %s", p->name);
+ status = -1;
+ break;
+ }
+ best_installed = find_best_matching_installed_pkg(p->name);
+ if (best_installed == NULL && Force) {
+ warnx("Missing dependency %s ignored", p->name);
+ continue;
+ } else if (best_installed == NULL) {
+ warnx("Just installed dependency %s disappeared", p->name);
+ status = -1;
+ break;
+ }
+ }
+ for (i = 0; i < pkg->dep_length; ++i) {
+ if (strcmp(best_installed, pkg->dependencies[i]) == 0)
+ break;
+ }
+ if (i < pkg->dep_length) {
+ /* Already used as dependency, so skip it. */
free(best_installed);
+ continue;
}
+ if (pkg->dep_length + 1 >= pkg->dep_allocated) {
+ char **tmp;
+ pkg->dep_allocated = 2 * pkg->dep_allocated + 1;
+ pkg->dependencies = xrealloc(pkg->dependencies,
+ pkg->dep_allocated * sizeof(*tmp));
+ }
+ pkg->dependencies[pkg->dep_length++] = best_installed;
}
- if (errc != 0)
- goto bomb;
+ return status;
+}
- /* If we're really installing, and have an installation file, run it */
- if (!NoInstall && fexists(INSTALL_FNAME)) {
- (void) fexec(CHMOD_CMD, "+x", INSTALL_FNAME, NULL); /* make sure */
- if (Verbose)
- printf("Running install with PRE-INSTALL for %s.\n", PkgName);
- errno = 0;
- if (!Fake && fexec("./" INSTALL_FNAME, PkgName, "PRE-INSTALL", NULL)) {
- if (errno != 0)
- warn("exec of install script failed");
- else
- warnx("install script returned error status");
- errc = 1;
- goto success; /* nothing to uninstall yet */
- }
+/*
+ * If this package uses pkg_views, register it in the default view.
+ */
+static void
+pkg_register_views(struct pkg_task *pkg)
+{
+ if (Fake || NoView || pkg->meta_data.meta_views == NULL)
+ return;
+
+ if (Verbose) {
+ printf("%s/pkg_view -d %s %s%s %s%s %sadd %s\n",
+ BINDIR, _pkgdb_getPKGDB_DIR(),
+ View ? "-w " : "", View ? View : "",
+ Viewbase ? "-W " : "", Viewbase ? Viewbase : "",
+ Verbose ? "-v " : "", pkg->pkgname);
}
- /*
- * Now finally extract the entire show if we're not going direct.
- * We need to reset the package dbdir so that extract_plist()
- * updates the correct pkgdb.byfile.db database.
- */
- if (!Fake) {
- _pkgdb_setPKGDB_DIR(dbdir);
- if (!extract_plist(".", &Plist)) {
- errc = 1;
- goto fail;
- }
+ fexec_skipempty(BINDIR "/pkg_view", "-d", _pkgdb_getPKGDB_DIR(),
+ View ? "-w " : "", View ? View : "",
+ Viewbase ? "-W " : "", Viewbase ? Viewbase : "",
+ Verbose ? "-v " : "", "add", pkg->pkgname,
+ (void *)NULL);
+}
+
+static int
+preserve_meta_data_file(struct pkg_task *pkg, const char *name)
+{
+ char *old_file, *new_file;
+ int rv;
+
+ if (Fake)
+ return 0;
+
+ old_file = pkgdb_pkg_file(pkg->other_version, name);
+ new_file = pkgdb_pkg_file(pkg->pkgname, name);
+ rv = 0;
+ if (rename(old_file, new_file) == -1 && errno != ENOENT) {
+ warn("Can't move %s from %s to %s", name, old_file, new_file);
+ rv = -1;
}
+ free(old_file);
+ free(new_file);
+ return rv;
+}
- if (!Fake && fexists(MTREE_FNAME)) {
- warnx("Mtree file ignored for package %s", PkgName);
+static int
+start_replacing(struct pkg_task *pkg)
+{
+ if (preserve_meta_data_file(pkg, REQUIRED_BY_FNAME))
+ return -1;
+
+ if (pkg->meta_data.meta_preserve == NULL &&
+ preserve_meta_data_file(pkg, PRESERVE_FNAME))
+ return -1;
+
+ if (pkg->meta_data.meta_installed_info == NULL &&
+ preserve_meta_data_file(pkg, INSTALLED_INFO_FNAME))
+ return -1;
+
+ if (Verbose || Fake) {
+ printf("%s/pkg_delete -K %s -p %s%s%s '%s'\n",
+ BINDIR, _pkgdb_getPKGDB_DIR(), pkg->prefix,
+ Destdir ? " -P ": "", Destdir ? Destdir : "",
+ pkg->other_version);
}
+ if (!Fake)
+ fexec_skipempty(BINDIR "/pkg_delete", "-K", _pkgdb_getPKGDB_DIR(),
+ "-p", pkg->prefix,
+ Destdir ? "-P": "", Destdir ? Destdir : "",
+ pkg->other_version, NULL);
- /* Run the installation script one last time? */
- if (!NoInstall && fexists(INSTALL_FNAME)) {
- if (Verbose)
- printf("Running install with POST-INSTALL for %s.\n", PkgName);
- if (!Fake && fexec("./" INSTALL_FNAME, PkgName, "POST-INSTALL", NULL)) {
- warnx("install script returned error status");
- errc = 1;
- goto fail;
- }
+ /* XXX Check return value and do what? */
+ return 0;
+}
+
+static int check_input(const char *line, size_t len)
+{
+ if (line == NULL || len == 0)
+ return 1;
+ switch (*line) {
+ case 'Y':
+ case 'y':
+ case 'T':
+ case 't':
+ case '1':
+ return 0;
+ default:
+ return 1;
}
+}
- /* Time to record the deed? */
- if (!NoRecord && !Fake) {
- char contents[MaxPathSize];
+static int
+check_signature(struct pkg_task *pkg, void *signature_cookie, int invalid_sig)
+{
+ char *line;
+ size_t len;
- if (!PkgName) {
- warnx("no package name! can't record package, sorry");
- errc = 1;
- goto success; /* well, partial anyway */
- }
- (void) snprintf(LogDir, sizeof(LogDir), "%s/%s", dbdir, PkgName);
- zapLogDir = 1; /* LogDir contains something valid now */
- if (Verbose)
- printf("Attempting to record package into %s.\n", LogDir);
- if (make_hierarchy(LogDir)) {
- warnx("can't record package into '%s', you're on your own!",
- LogDir);
- memset(LogDir, 0, sizeof(LogDir));
- errc = 1;
- goto success; /* close enough for government work */
+ if (strcasecmp(verified_installation, "never") == 0)
+ return 0;
+ if (strcasecmp(verified_installation, "always") == 0) {
+ if (invalid_sig)
+ warnx("No valid signature found, rejected");
+ return invalid_sig;
+ }
+ if (strcasecmp(verified_installation, "trusted") == 0) {
+ if (!invalid_sig)
+ return 0;
+ fprintf(stderr, "No valid signature found for %s.\n",
+ pkg->pkgname);
+ fprintf(stderr,
+ "Do you want to proceed with the installation [y/n]?\n");
+ line = fgetln(stdin, &len);
+ if (check_input(line, len)) {
+ fprintf(stderr, "Cancelling installation\n");
+ return 1;
}
- /* Make sure pkg_info can read the entry */
- (void) fexec(CHMOD_CMD, "a+rx", LogDir, NULL);
-
- /* Move all of the +-files into place */
- move_files(".", "+*", LogDir);
-
- /* Generate the +CONTENTS file in-place from the Plist */
- (void) snprintf(contents, sizeof(contents), "%s/%s", LogDir, CONTENTS_FNAME);
- cfile = fopen(contents, "w");
- if (!cfile) {
- warnx("can't open new contents file '%s'! can't register pkg",
- contents);
- goto success; /* can't log, but still keep pkg */
+ return 0;
+ }
+ if (strcasecmp(verified_installation, "interactive") == 0) {
+ fprintf(stderr, "Do you want to proceed with "
+ "the installation of %s [y/n]?\n", pkg->pkgname);
+ line = fgetln(stdin, &len);
+ if (check_input(line, len)) {
+ fprintf(stderr, "Cancelling installation\n");
+ return 1;
}
- write_plist(&Plist, cfile, NULL);
- fclose(cfile);
-
- /* register dependencies */
- /* we could save some cycles here if we remembered what we
- * installed above (in case we got a wildcard dependency) */
- /* XXX remembering in p->name would NOT be good! */
- for (p = Plist.head; p; p = p->next) {
- if (p->type != PLIST_PKGDEP)
- continue;
- if (Verbose)
- printf("Attempting to record dependency on package `%s'\n", p->name);
- (void) snprintf(contents, sizeof(contents), "%s/%s", dbdir,
- basename_of(p->name));
- if (ispkgpattern(p->name)) {
- char *s;
+ return 0;
+ }
+ warnx("Unknown value of configuration variable VERIFIED_INSTALLATION");
+ return 1;
+}
- s = find_best_matching_installed_pkg(p->name);
+static int
+check_vulnerable(struct pkg_task *pkg)
+{
+ static struct pkg_vulnerabilities *pv;
+ int require_check;
+ char *line;
+ size_t len;
- if (s == NULL)
- errx(EXIT_FAILURE, "Where did our dependency go?!");
+ if (strcasecmp(check_vulnerabilities, "never") == 0)
+ return 0;
+ else if (strcasecmp(check_vulnerabilities, "always"))
+ require_check = 1;
+ else if (strcasecmp(check_vulnerabilities, "interactive"))
+ require_check = 0;
+ else {
+ warnx("Unknown value of the configuration variable"
+ "CHECK_VULNERABILITIES");
+ return 1;
+ }
- (void) snprintf(contents, sizeof(contents), "%s/%s", dbdir, s);
- free(s);
- }
- strlcat(contents, "/", sizeof(contents));
- strlcat(contents, REQUIRED_BY_FNAME, sizeof(contents));
-
- cfile = fopen(contents, "a");
- if (!cfile)
- warnx("can't open dependency file '%s'!\n"
- "dependency registration is incomplete", contents);
- else {
- fprintf(cfile, "%s\n", PkgName);
- if (fclose(cfile) == EOF)
- warnx("cannot properly close file %s", contents);
- }
- }
- if (Automatic)
- mark_as_automatic_installed(PkgName, 1);
- if (Verbose)
- printf("Package %s registered in %s\n", PkgName, LogDir);
+ if (pv == NULL) {
+ pv = read_pkg_vulnerabilities(pkg_vulnerabilities_file,
+ require_check, 0);
+ if (pv == NULL)
+ return require_check;
}
- if ((p = find_plist(&Plist, PLIST_DISPLAY)) != NULL) {
- FILE *fp;
- char buf[BUFSIZ];
-
- (void) snprintf(buf, sizeof(buf), "%s/%s", LogDir, p->name);
- fp = fopen(buf, "r");
- if (fp) {
- putc('\n', stdout);
- while (fgets(buf, sizeof(buf), fp))
- fputs(buf, stdout);
- putc('\n', stdout);
- (void) fclose(fp);
- } else
- warnx("cannot open %s as display file", buf);
+ if (!audit_package(pv, pkg->pkgname, NULL, 0, 2))
+ return 0;
+
+ if (require_check)
+ return 1;
+
+ fprintf(stderr, "Do you want to proceed with the installation of %s"
+ " [y/n]?\n", pkg->pkgname);
+ line = fgetln(stdin, &len);
+ if (check_input(line, len)) {
+ fprintf(stderr, "Cancelling installation\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Install a single package.
+ */
+static int
+pkg_do(const char *pkgpath, int mark_automatic)
+{
+ int status, invalid_sig;
+ void *archive_cookie;
+ void *signature_cookie;
+ struct pkg_task *pkg;
+
+ pkg = xcalloc(1, sizeof(*pkg));
+
+ status = -1;
+
+ if ((pkg->archive = find_archive(pkgpath, &archive_cookie)) == NULL) {
+ warnx("no pkg found for '%s', sorry.", pkgpath);
+ goto clean_find_archive;
}
- /* Add the package to a default view. */
- if (!Fake && !NoView && is_depoted_pkg) {
- if (Verbose) {
- printf("%s/pkg_view -d %s %s%s %s%s %sadd %s\n",
- BINDIR, dbdir,
- View ? "-w " : "", View ? View : "",
- Viewbase ? "-W " : "", Viewbase ? Viewbase : "",
- Verbose ? "-v " : "", PkgName);
+#ifdef HAVE_SSL
+ invalid_sig = pkg_verify_signature(&pkg->archive, &pkg->entry,
+ &pkg->pkgname, &signature_cookie);
+#else
+ invalid_sig = 1;
+ signature_cookie = NULL;
+#endif
+
+ if (read_meta_data(pkg))
+ goto clean_memory;
+
+ /* Parse PLIST early, so that messages can use real package name. */
+ if (pkg_parse_plist(pkg))
+ goto clean_memory;
+
+ if (check_signature(pkg, &signature_cookie, invalid_sig))
+ goto clean_memory;
+
+ if (check_vulnerable(pkg))
+ goto clean_memory;
+
+ if (pkg->meta_data.meta_mtree != NULL)
+ warnx("mtree specification in pkg `%s' ignored", pkg->pkgname);
+
+ if (pkg->meta_data.meta_views != NULL) {
+ pkg->logdir = xstrdup(pkg->prefix);
+ _pkgdb_setPKGDB_DIR(dirname_of(pkg->logdir));
+ } else {
+ pkg->logdir = xasprintf("%s/%s", _pkgdb_getPKGDB_DIR(),
+ pkg->pkgname);
+ }
+
+ if (Destdir != NULL) {
+ pkg->install_logdir = xasprintf("%s/%s", Destdir, pkg->logdir);
+ _pkgdb_setPKGDB_DIR(dirname_of(pkg->install_logdir));
+ } else
+ pkg->install_logdir = xstrdup(pkg->logdir);
+
+ if (NoRecord && !Fake) {
+ const char *tmpdir;
+
+ tmpdir = getenv("TMPDIR");
+ if (tmpdir == NULL)
+ tmpdir = "/tmp";
+
+ free(pkg->install_logdir);
+ pkg->install_logdir = xasprintf("%s/pkg_install.XXXXXX", tmpdir);
+ /* XXX pkg_add -u... */
+ if (mkdtemp(pkg->install_logdir) == NULL) {
+ warn("mkdtemp failed");
+ goto clean_memory;
}
+ }
- fexec_skipempty(BINDIR "/pkg_view", "-d", dbdir,
- View ? "-w " : "", View ? View : "",
- Viewbase ? "-W " : "", Viewbase ? Viewbase : "",
- Verbose ? "-v " : "", "add", PkgName, NULL);
+ if (check_already_installed(pkg) == 0) {
+ status = 0;
+ goto clean_memory;
}
- goto success;
+ if (read_buildinfo(pkg))
+ goto clean_memory;
-bomb:
- errc = 1;
- goto success;
+ if (check_platform(pkg))
+ goto clean_memory;
-fail:
- /* Nuke the whole (installed) show, XXX but don't clean directories */
- if (!Fake)
- delete_package(FALSE, FALSE, &Plist, FALSE);
+ if (check_other_installed(pkg))
+ goto clean_memory;
-success:
- /* delete the packing list contents */
- free_plist(&Plist);
- leave_playpen(Home);
+ if (check_explicit_conflict(pkg))
+ goto clean_memory;
- if (replacing) {
+ if (check_implicit_conflict(pkg))
+ goto clean_memory;
+
+ if (pkg->other_version != NULL) {
/*
- * Upgrade step 3/4: move back +REQUIRED_BY file
- * (see also step 2/4)
+ * Replacing an existing package.
+ * Write meta-data, get rid of the old version,
+ * install/update dependencies and finally extract.
*/
- if (rename(replace_via, replace_to) != 0)
- err(EXIT_FAILURE, "renaming \"%s\" to \"%s\" failed", replace_via, replace_to);
-
+ if (write_meta_data(pkg))
+ goto nuke_pkgdb;
+
+ if (start_replacing(pkg))
+ goto nuke_pkgdb;
+
+ if (check_dependencies(pkg))
+ goto nuke_pkgdb;
+ } else {
/*
- * Upgrade step 4/4: Fix pkgs that depend on us to
- * depend on the new version instead of the old
- * one by fixing @pkgdep lines in +CONTENTS files.
- */
- /* TODO */
+ * Normal installation.
+ * Install/update dependencies first and
+ * write the current package to disk afterwards.
+ */
+ if (check_dependencies(pkg))
+ goto clean_memory;
+
+ if (write_meta_data(pkg))
+ goto nuke_pkgdb;
}
- return errc;
-}
+ if (run_install_script(pkg, "PRE-INSTALL"))
+ goto nuke_pkgdb;
-void
-cleanup(int signo)
-{
- static int alreadyCleaning;
- void (*oldint) (int);
- void (*oldhup) (int);
- int saved_errno;
-
- saved_errno = errno;
- oldint = signal(SIGINT, SIG_IGN);
- oldhup = signal(SIGHUP, SIG_IGN);
-
- if (!alreadyCleaning) {
- alreadyCleaning = 1;
- if (signo)
- printf("Signal %d received, cleaning up.\n", signo);
- if (!Fake && zapLogDir && LogDir[0])
- (void) fexec(REMOVE_CMD, "-fr", LogDir, NULL);
- leave_playpen(Home);
- if (signo)
- exit(1);
+ if (extract_files(pkg))
+ goto nuke_pkg;
+
+ if (run_install_script(pkg, "POST-INSTALL"))
+ goto nuke_pkgdb;
+
+ /* XXX keep +INSTALL_INFO for updates? */
+ /* XXX keep +PRESERVE for updates? */
+ if (mark_automatic)
+ mark_as_automatic_installed(pkg->pkgname, 1);
+
+ pkg_register_depends(pkg);
+
+ if (Verbose)
+ printf("Package %s registered in %s\n", pkg->pkgname, pkg->install_logdir);
+
+ if (pkg->meta_data.meta_display != NULL)
+ fputs(pkg->meta_data.meta_display, stdout);
+
+ pkg_register_views(pkg);
+
+ status = 0;
+ goto clean_memory;
+
+nuke_pkg:
+ if (!Fake) {
+ if (pkg->other_version) {
+ warnx("Updating of %s to %s failed.",
+ pkg->other_version, pkg->pkgname);
+ warnx("Remember to run pkg_admin rebuild-tree after fixing this.");
+ }
+ delete_package(FALSE, FALSE, &pkg->plist, FALSE, Destdir);
+ }
+
+nuke_pkgdb:
+ if (!Fake) {
+ if (recursive_remove(pkg->install_logdir, 1))
+ warn("Couldn't remove %s", pkg->install_logdir);
+ free(pkg->install_logdir);
+ free(pkg->logdir);
+ pkg->install_logdir = NULL;
+ pkg->logdir = NULL;
+ }
+
+clean_memory:
+ if (pkg->logdir != NULL && NoRecord && !Fake) {
+ if (recursive_remove(pkg->install_logdir, 1))
+ warn("Couldn't remove %s", pkg->install_logdir);
+ }
+ free(pkg->install_prefix);
+ free(pkg->install_logdir);
+ free(pkg->logdir);
+ free_buildinfo(pkg);
+ free_plist(&pkg->plist);
+ free_meta_data(pkg);
+ if (pkg->archive) {
+ archive_read_close(pkg->archive);
+ close_archive(archive_cookie);
}
- signal(SIGINT, oldint);
- signal(SIGHUP, oldhup);
- errno = saved_errno;
+ free(pkg->other_version);
+ free(pkg->pkgname);
+#ifdef HAVE_SSL
+ pkg_free_signature(signature_cookie);
+#endif
+clean_find_archive:
+ free(pkg);
+ return status;
}
int
pkg_perform(lpkg_head_t *pkgs)
{
- int err_cnt = 0;
+ int oldcwd, errors = 0;
lpkg_t *lpp;
- signal(SIGINT, cleanup);
- signal(SIGHUP, cleanup);
-
- TAILQ_INIT(&files);
+ if ((oldcwd = open(".", O_RDONLY, 0)) == -1)
+ err(EXIT_FAILURE, "unable to open cwd");
while ((lpp = TAILQ_FIRST(pkgs)) != NULL) {
path_prepend_from_pkgname(lpp->lp_name);
- err_cnt += pkg_do(lpp->lp_name, pkgs);
+ if (pkg_do(lpp->lp_name, Automatic))
+ ++errors;
path_prepend_clear();
TAILQ_REMOVE(pkgs, lpp, lp_link);
free_lpkg(lpp);
+
+ if (fchdir(oldcwd) == -1)
+ err(EXIT_FAILURE, "unable to restore cwd");
}
-
- ftp_stop();
-
- return err_cnt;
+
+ close(oldcwd);
+
+ return errors;
}
diff --git a/pkgtools/pkg_install/files/add/pkg_add.1 b/pkgtools/pkg_install/files/add/pkg_add.1
index ced8fd613c9..5472b414d13 100644
--- a/pkgtools/pkg_install/files/add/pkg_add.1
+++ b/pkgtools/pkg_install/files/add/pkg_add.1
@@ -1,4 +1,4 @@
-.\" $NetBSD: pkg_add.1,v 1.30 2008/04/26 17:40:01 joerg Exp $
+.\" $NetBSD: pkg_add.1,v 1.31 2009/02/02 12:35:00 joerg Exp $
.\"
.\" FreeBSD install - a package for the installation and maintenance
.\" of non-core utilities.
@@ -17,7 +17,7 @@
.\"
.\" @(#)pkg_add.1
.\"
-.Dd August 23, 2007
+.Dd October 10, 2008
.Dt PKG_ADD 1
.Os
.Sh NAME
@@ -28,9 +28,8 @@
.Op Fl AfILnRuVv
.Op Fl K Ar pkg_dbdir
.Op Fl m Ar machine
+.Op Fl P Ar destdir
.Op Fl p Ar prefix
-.Op Fl s Ar verification-type
-.Op Fl t Ar template
.Op Fl W Ar viewbase
.Op Fl w Ar view
.Ar \fR[[ftp|http]://[\fIuser\fR[:\fIpassword]\fR@]\fIhost\fR[:\fIport\fR]][/\fIpath/\fR]pkg-name ...
@@ -60,8 +59,8 @@ You are advised to verify the competence and identity of those who
provide installable package files.
For extra protection, use the digital signatures provided where possible
(see the
-.Fl s
-option), or, failing that, use
+.Xr pkg_install.conf 5 ) ,
+or, failing that, use
.Xr tar 1
to extract the package file, and inspect its contents and scripts
to ensure it poses no danger to your system's integrity.
@@ -143,6 +142,11 @@ Override the machine architecture returned by uname with
.It Fl n
Don't actually install a package, just report the steps that
would be taken if it was.
+.It Fl P Ar destdir
+Prefix all file and directory names with
+.Ar destdir .
+For packages without install scripts this has the same behavior as
+using chroot.
.It Fl p Ar prefix
Set
.Ar prefix
@@ -160,56 +164,14 @@ into
.Ar pkgdb .
.It Fl R
Do not record the installation of a package.
+This implies
+.Fl I .
This means that you cannot deinstall it later, so only use this option if
you know what you are doing!
-.It Fl s Ar verification-type
-Use a callout to an external program to verify the binary package
-being installed against an existing detached signature file.
-The signature file must reside in the same directory
-as the binary package.
-At the present time, the following verification types
-are defined: none, gpg and pgp5.
-The signature will be verified at install time, and the results
-will be displayed.
-If the signature type is anything other than none, the user will be asked if
-.Nm
-should proceed to install the binary package.
-The user must then take the decision whether to proceed or not, depending
-upon the amount of trust that is placed in the signatory of the binary
-package.
-Please note that, at the current time, it is not possible to use
-the verification feature when using
-.Nm
-to add a binary package via a URL - the package, and the related
-detached signature file, must be local
-for the verification to work.
-.It Fl t Ar template
-Use
-.Ar template
-as the input to
-.Xr mktemp 3
-when creating a
-.Dq staging area .
-By default, this is the string
-.Pa /var/tmp/instmp.XXXXXX ,
-but it may be necessary to override it in the situation where
-space in your
-.Pa /var/tmp
-directory is limited.
-Be sure to leave some number of
-.Sq X
-characters for
-.Xr mktemp 3
-to fill in with a unique ID.
-.Pp
-You can get a performance boost by setting the staging area
-.Ar template
-to reside on the same disk partition as target directories for package
-file installation; often this is
-.Pa /usr .
.It Fl u
-If the package that's being installed is already installed, either
-in the same or a different version, an update is performed.
+If the package that's being installed is already installed,
+an update is performed.
+It is currently not possible to update to an identical version.
If this is specified twice, then any dependant packages that are
too old will also be updated to fulfill the dependency.
See below for a more detailed description of the process.
@@ -275,11 +237,10 @@ passive mode
ftp.
.Sh TECHNICAL DETAILS
.Nm
-extracts each package's
-.Dq packing list
-into a special staging directory in /var/tmp (or $PKG_TMPDIR if set)
-and then runs through the following sequence to fully extract the contents
-of the package:
+extracts each package's meta data (including the
+.Dq packing list )
+to memory and then runs through the following sequence to fully extract
+the contents of the package:
.Bl -enum -offset indent
.It
A check is made to determine if the package or another version of it
@@ -305,13 +266,37 @@ was not installed, and restores the
.Pa +REQUIRED_BY
file afterwards.
.It
+The package build information is extracted from the
+.Pa +BUILD_INFO
+file and compared against the result of
+.Xr uname 3 .
+If the operating system or architecture of the package differ from
+that of the host, installation is aborted.
+This behavior is overridable with the
+.Fl f
+flag.
+.It
+The package build information from
+.Pa +BUILD_INFO
+is then checked for
+.Ev USE_ABI_DEPENDS=NO
+(or
+.Ev IGNORE_RECOMMENDED ) .
+If the package was built with ABI dependency recommendations ignored,
+a warning will be issued.
+.It
A check is made to determine if the package conflicts (from
.Cm @pkgcfl
directives, see
.Xr pkg_create 1 )
-with an already recorded as installed package.
+with an already recorded as installed package or if an installed package
+conflicts with the package.
If it is, installation is terminated.
.It
+The file list of the package is compared to the file lists of the
+installed packeges.
+If there is any overlap, the installation is terminated.
+.It
All package dependencies (from
.Cm @pkgdep
directives, see
@@ -330,34 +315,6 @@ The dependant packages are found according to the normal
.Ev PKG_PATH
rules.
.It
-A search is made for any
-.Cm @option
-directives which control how the package is added to the system.
-The only currently implemented option is
-.Cm @option preserve ,
-which tells pkg_add to move any existing files out of the way,
-preserving the previous contents (which are also resurrected on
-pkg_delete, so caveat emptor).
-.It
-The package build information is extracted from the
-.Pa +BUILD_INFO
-file and compared against the result of
-.Xr uname 3 .
-If the operating system or architecture of the package differ from
-that of the host, installation is aborted.
-This behavior is overridable with the
-.Fl f
-flag.
-.It
-The package build information from
-.Pa +BUILD_INFO
-is then checked for
-.Ev USE_ABI_DEPENDS=NO
-(or
-.Ev IGNORE_RECOMMENDED ) .
-If the package was built with ABI dependency recommendations ignored,
-a warning will be issued.
-.It
If the package contains an
.Ar install
script, it is executed with the following arguments:
@@ -373,8 +330,7 @@ If the
.Ar install
script exits with a non-zero status code, the installation is terminated.
.It
-It is used as a guide for moving (or copying, as necessary) files from
-the staging area into their final locations.
+The files from the file list are extracted to the choosen prefix.
.It
If an
.Ar install
@@ -403,8 +359,6 @@ path shown above).
.It
If the package is a depoted package, then add it to the default view.
.It
-The staging area is deleted and the program terminates.
-.It
Finally, if we were upgrading a package, any
.Pa +REQUIRED_BY
file that was moved aside before upgrading was started is now moved
@@ -432,6 +386,13 @@ meta-data files, and with the
.Ev PKG_REFCOUNT_DBDIR
environment variable set to the location of the package reference counts
database directory.
+If the
+.Fl P
+flag was given to
+.Nm ,
+.Ev PKG_DESTDIR
+will be set to
+.Ar destdir .
.Sh ENVIRONMENT
.Bl -tag -width PKG_TMPDIR
.It Ev LOCALBASE
@@ -467,10 +428,6 @@ The default location is the path to the package database directory with
.Dq .refcount
appended to the path, e.g.
.Pa /var/db/pkg.refcount .
-.It Ev PKG_TMPDIR
-Staging directory for installing packages, defaults to /var/tmp.
-Set to directory with lots of free disk if you run out of
-space when installing a binary package.
.It Ev PKG_VIEW
The default view can be specified in the
.Ev PKG_VIEW
@@ -532,6 +489,16 @@ If you do this, consider installing and using the
.Pa security/audit-packages
package and running it after every
.Nm .
+.Sh CONFIGURATION VARIABLES
+The following variables change the behaviour of
+.Nm
+and are described in
+.Xr pkg_install.conf 5 :
+.Bl -tag -width CERTIFICATE_ANCHOR_PKGS
+.It Ev CERTIFICATE_ANCHOR_PKGS
+.It Ev CERTIFICATE_CHAIN
+.It Ev VERIFIED_INSTALLATION
+.El
.Sh SEE ALSO
.Xr pkg_admin 1 ,
.Xr pkg_create 1 ,
@@ -540,6 +507,7 @@ package and running it after every
.Xr tar 1 ,
.Xr mktemp 3 ,
.Xr sysconf 3 ,
+.Xr pkg_install.conf 5 ,
.Xr pkgsrc 7
.Sh AUTHORS
.Bl -tag -width indent -compact
@@ -553,21 +521,10 @@ refinements.
wildcard dependency processing, pkgdb, upgrading, etc.
.It Thomas Klausner
HTTP support.
+.It Joerg Sonnenberger
+Rewrote most of the code base to work without external commands.
.El
.Sh BUGS
-Hard links between files in a distribution are only preserved if either
-(1) the staging area is on the same file system as the target directory of
-all the links to the file, or (2) all the links to the file are bracketed by
-.Cm @cwd
-directives in the contents file,
-.Em and
-and the link names are extracted with a single
-.Cm tar
-command (not split between
-invocations due to exec argument-space limitations--this depends on the
-value returned by
-.Fn sysconf _SC_ARG_MAX ) .
-.Pp
Package upgrading needs a lot more work to be really universal.
.Pp
Sure to be others.
diff --git a/pkgtools/pkg_install/files/add/pkg_add.cat1 b/pkgtools/pkg_install/files/add/pkg_add.cat1
index 6ff5af89037..299b76c5f9d 100644
--- a/pkgtools/pkg_install/files/add/pkg_add.cat1
+++ b/pkgtools/pkg_install/files/add/pkg_add.cat1
@@ -5,8 +5,8 @@ NNAAMMEE
tributions
SSYYNNOOPPSSIISS
- ppkkgg__aadddd [--AAffIILLnnRRuuVVvv] [--KK _p_k_g___d_b_d_i_r] [--mm _m_a_c_h_i_n_e] [--pp _p_r_e_f_i_x]
- [--ss _v_e_r_i_f_i_c_a_t_i_o_n_-_t_y_p_e] [--tt _t_e_m_p_l_a_t_e] [--WW _v_i_e_w_b_a_s_e] [--ww _v_i_e_w]
+ ppkkgg__aadddd [--AAffIILLnnRRuuVVvv] [--KK _p_k_g___d_b_d_i_r] [--mm _m_a_c_h_i_n_e] [--PP _d_e_s_t_d_i_r] [--pp _p_r_e_f_i_x]
+ [--WW _v_i_e_w_b_a_s_e] [--ww _v_i_e_w]
[[ftp|http]://[_u_s_e_r[:_p_a_s_s_w_o_r_d_]@]_h_o_s_t[:_p_o_r_t]][/_p_a_t_h_/]pkg-name ...
DDEESSCCRRIIPPTTIIOONN
@@ -25,13 +25,13 @@ WWAARRNNIINNGG
_Y_o_u _a_r_e _a_d_v_i_s_e_d _t_o _v_e_r_i_f_y _t_h_e _c_o_m_p_e_t_e_n_c_e _a_n_d _i_d_e_n_t_i_t_y _o_f _t_h_o_s_e _w_h_o _p_r_o_-
_v_i_d_e _i_n_s_t_a_l_l_a_b_l_e _p_a_c_k_a_g_e _f_i_l_e_s_. _F_o_r _e_x_t_r_a _p_r_o_t_e_c_t_i_o_n_, _u_s_e _t_h_e _d_i_g_i_t_a_l
- _s_i_g_n_a_t_u_r_e_s _p_r_o_v_i_d_e_d _w_h_e_r_e _p_o_s_s_i_b_l_e _(_s_e_e _t_h_e --ss _o_p_t_i_o_n_)_, _o_r_, _f_a_i_l_i_n_g _t_h_a_t_,
- _u_s_e tar(_1) _t_o _e_x_t_r_a_c_t _t_h_e _p_a_c_k_a_g_e _f_i_l_e_, _a_n_d _i_n_s_p_e_c_t _i_t_s _c_o_n_t_e_n_t_s _a_n_d
- _s_c_r_i_p_t_s _t_o _e_n_s_u_r_e _i_t _p_o_s_e_s _n_o _d_a_n_g_e_r _t_o _y_o_u_r _s_y_s_t_e_m_'_s _i_n_t_e_g_r_i_t_y_. _P_a_y
- _p_a_r_t_i_c_u_l_a_r _a_t_t_e_n_t_i_o_n _t_o _a_n_y _+_I_N_S_T_A_L_L _o_r _+_D_E_I_N_S_T_A_L_L _f_i_l_e_s_, _a_n_d _i_n_s_p_e_c_t _t_h_e
- _+_C_O_N_T_E_N_T_S _f_i_l_e _f_o_r @@ccwwdd_, @@mmooddee _(_c_h_e_c_k _f_o_r _s_e_t_u_i_d_)_, @@ddiirrrrmm_, @@eexxeecc_, _a_n_d
- @@uunneexxeecc _d_i_r_e_c_t_i_v_e_s_, _a_n_d_/_o_r _u_s_e _t_h_e pkg_info(_1) _c_o_m_m_a_n_d _t_o _e_x_a_m_i_n_e _t_h_e
- _p_a_c_k_a_g_e _f_i_l_e_.
+ _s_i_g_n_a_t_u_r_e_s _p_r_o_v_i_d_e_d _w_h_e_r_e _p_o_s_s_i_b_l_e _(_s_e_e _t_h_e pkg_install.conf(_5)_)_, _o_r_,
+ _f_a_i_l_i_n_g _t_h_a_t_, _u_s_e tar(_1) _t_o _e_x_t_r_a_c_t _t_h_e _p_a_c_k_a_g_e _f_i_l_e_, _a_n_d _i_n_s_p_e_c_t _i_t_s
+ _c_o_n_t_e_n_t_s _a_n_d _s_c_r_i_p_t_s _t_o _e_n_s_u_r_e _i_t _p_o_s_e_s _n_o _d_a_n_g_e_r _t_o _y_o_u_r _s_y_s_t_e_m_'_s
+ _i_n_t_e_g_r_i_t_y_. _P_a_y _p_a_r_t_i_c_u_l_a_r _a_t_t_e_n_t_i_o_n _t_o _a_n_y _+_I_N_S_T_A_L_L _o_r _+_D_E_I_N_S_T_A_L_L _f_i_l_e_s_,
+ _a_n_d _i_n_s_p_e_c_t _t_h_e _+_C_O_N_T_E_N_T_S _f_i_l_e _f_o_r @@ccwwdd_, @@mmooddee _(_c_h_e_c_k _f_o_r _s_e_t_u_i_d_)_,
+ @@ddiirrrrmm_, @@eexxeecc_, _a_n_d @@uunneexxeecc _d_i_r_e_c_t_i_v_e_s_, _a_n_d_/_o_r _u_s_e _t_h_e pkg_info(_1) _c_o_m_m_a_n_d
+ _t_o _e_x_a_m_i_n_e _t_h_e _p_a_c_k_a_g_e _f_i_l_e_.
OOPPTTIIOONNSS
The following command line arguments are supported:
@@ -77,6 +77,11 @@ OOPPTTIIOONNSS
--nn Don't actually install a package, just report the steps that
would be taken if it was.
+ --PP _d_e_s_t_d_i_r
+ Prefix all file and directory names with _d_e_s_t_d_i_r. For packages
+ without install scripts this has the same behavior as using
+ chroot.
+
--pp _p_r_e_f_i_x
Set _p_r_e_f_i_x as the directory in which to extract files from a
package. If a package has set its default directory, it will be
@@ -86,44 +91,16 @@ OOPPTTIIOONNSS
directory transition is supported and the second one is expected
to go into _p_k_g_d_b.
- --RR Do not record the installation of a package. This means that you
- cannot deinstall it later, so only use this option if you know
- what you are doing!
-
- --ss _v_e_r_i_f_i_c_a_t_i_o_n_-_t_y_p_e
- Use a callout to an external program to verify the binary package
- being installed against an existing detached signature file. The
- signature file must reside in the same directory as the binary
- package. At the present time, the following verification types
- are defined: none, gpg and pgp5. The signature will be verified
- at install time, and the results will be displayed. If the sig-
- nature type is anything other than none, the user will be asked
- if ppkkgg__aadddd should proceed to install the binary package. The
- user must then take the decision whether to proceed or not,
- depending upon the amount of trust that is placed in the signa-
- tory of the binary package. Please note that, at the current
- time, it is not possible to use the verification feature when
- using ppkkgg__aadddd to add a binary package via a URL - the package,
- and the related detached signature file, must be local for the
- verification to work.
-
- --tt _t_e_m_p_l_a_t_e
- Use _t_e_m_p_l_a_t_e as the input to mktemp(3) when creating a ``staging
- area''. By default, this is the string _/_v_a_r_/_t_m_p_/_i_n_s_t_m_p_._X_X_X_X_X_X,
- but it may be necessary to override it in the situation where
- space in your _/_v_a_r_/_t_m_p directory is limited. Be sure to leave
- some number of `X' characters for mktemp(3) to fill in with a
- unique ID.
-
- You can get a performance boost by setting the staging area
- _t_e_m_p_l_a_t_e to reside on the same disk partition as target directo-
- ries for package file installation; often this is _/_u_s_r.
-
- --uu If the package that's being installed is already installed,
- either in the same or a different version, an update is per-
- formed. If this is specified twice, then any dependant packages
- that are too old will also be updated to fulfill the dependency.
- See below for a more detailed description of the process.
+ --RR Do not record the installation of a package. This implies --II.
+ This means that you cannot deinstall it later, so only use this
+ option if you know what you are doing!
+
+ --uu If the package that's being installed is already installed, an
+ update is performed. It is currently not possible to update to
+ an identical version. If this is specified twice, then any
+ dependant packages that are too old will also be updated to ful-
+ fill the dependency. See below for a more detailed description
+ of the process.
--VV Print version number and exit.
@@ -153,9 +130,9 @@ OOPPTTIIOONNSS
a firewall that demands the usage of _p_a_s_s_i_v_e _m_o_d_e ftp.
TTEECCHHNNIICCAALL DDEETTAAIILLSS
- ppkkgg__aadddd extracts each package's ``packing list'' into a special staging
- directory in /var/tmp (or $PKG_TMPDIR if set) and then runs through the
- following sequence to fully extract the contents of the package:
+ ppkkgg__aadddd extracts each package's meta data (including the ``packing
+ list'') to memory and then runs through the following sequence to fully
+ extract the contents of the package:
1. A check is made to determine if the package or another version
of it is already recorded as installed. If it is, installa-
@@ -171,12 +148,28 @@ TTEECCHHNNIICCAALL DDEETTAAIILLSS
age was not installed, and restores the _+_R_E_Q_U_I_R_E_D___B_Y file
afterwards.
- 2. A check is made to determine if the package conflicts (from
+ 2. The package build information is extracted from the
+ _+_B_U_I_L_D___I_N_F_O file and compared against the result of uname(3).
+ If the operating system or architecture of the package differ
+ from that of the host, installation is aborted. This behavior
+ is overridable with the --ff flag.
+
+ 3. The package build information from _+_B_U_I_L_D___I_N_F_O is then checked
+ for USE_ABI_DEPENDS=NO (or IGNORE_RECOMMENDED). If the pack-
+ age was built with ABI dependency recommendations ignored, a
+ warning will be issued.
+
+ 4. A check is made to determine if the package conflicts (from
@@ppkkggccffll directives, see pkg_create(1)) with an already
- recorded as installed package. If it is, installation is ter-
- minated.
+ recorded as installed package or if an installed package con-
+ flicts with the package. If it is, installation is termi-
+ nated.
+
+ 5. The file list of the package is compared to the file lists of
+ the installed packeges. If there is any overlap, the instal-
+ lation is terminated.
- 3. All package dependencies (from @@ppkkggddeepp directives, see
+ 6. All package dependencies (from @@ppkkggddeepp directives, see
pkg_create(1)) are read from the packing list. If any of
these required packages are not currently installed, an
attempt is made to find and install it; if the missing package
@@ -186,24 +179,6 @@ TTEECCHHNNIICCAALL DDEETTAAIILLSS
considered to be too old, are also updated. The dependant
packages are found according to the normal PKG_PATH rules.
- 4. A search is made for any @@ooppttiioonn directives which control how
- the package is added to the system. The only currently imple-
- mented option is @@ooppttiioonn pprreesseerrvvee, which tells pkg_add to move
- any existing files out of the way, preserving the previous
- contents (which are also resurrected on pkg_delete, so caveat
- emptor).
-
- 5. The package build information is extracted from the
- _+_B_U_I_L_D___I_N_F_O file and compared against the result of uname(3).
- If the operating system or architecture of the package differ
- from that of the host, installation is aborted. This behavior
- is overridable with the --ff flag.
-
- 6. The package build information from _+_B_U_I_L_D___I_N_F_O is then checked
- for USE_ABI_DEPENDS=NO (or IGNORE_RECOMMENDED). If the pack-
- age was built with ABI dependency recommendations ignored, a
- warning will be issued.
-
7. If the package contains an _i_n_s_t_a_l_l script, it is executed with
the following arguments:
@@ -216,8 +191,8 @@ TTEECCHHNNIICCAALL DDEETTAAIILLSS
If the _i_n_s_t_a_l_l script exits with a non-zero status code, the
installation is terminated.
- 8. It is used as a guide for moving (or copying, as necessary)
- files from the staging area into their final locations.
+ 8. The files from the file list are extracted to the choosen pre-
+ fix.
9. If an _i_n_s_t_a_l_l script exists for the package, it is executed
with the following arguments:
@@ -239,9 +214,7 @@ TTEECCHHNNIICCAALL DDEETTAAIILLSS
11. If the package is a depoted package, then add it to the
default view.
- 12. The staging area is deleted and the program terminates.
-
- 13. Finally, if we were upgrading a package, any _+_R_E_Q_U_I_R_E_D___B_Y file
+ 12. Finally, if we were upgrading a package, any _+_R_E_Q_U_I_R_E_D___B_Y file
that was moved aside before upgrading was started is now moved
back into place.
@@ -252,7 +225,8 @@ TTEECCHHNNIICCAALL DDEETTAAIILLSS
change it with the --pp flag to ppkkgg__aadddd. The scripts are also called with
the PKG_METADATA_DIR environment variable set to the location of the _+_*
meta-data files, and with the PKG_REFCOUNT_DBDIR environment variable set
- to the location of the package reference counts database directory.
+ to the location of the package reference counts database directory. If
+ the --PP flag was given to ppkkgg__aadddd, PKG_DESTDIR will be set to _d_e_s_t_d_i_r.
EENNVVIIRROONNMMEENNTT
LOCALBASE This is the location of the _v_i_e_w_b_a_s_e directory in which all
@@ -277,10 +251,6 @@ EENNVVIIRROONNMMEENNTT
directory with ``.refcount'' appended to the path, e.g.
_/_v_a_r_/_d_b_/_p_k_g_._r_e_f_c_o_u_n_t.
- PKG_TMPDIR Staging directory for installing packages, defaults to
- /var/tmp. Set to directory with lots of free disk if you run
- out of space when installing a binary package.
-
PKG_VIEW The default view can be specified in the PKG_VIEW environment
variable.
@@ -316,9 +286,19 @@ EEXXAAMMPPLLEESS
ter.) If you do this, consider installing and using the
_s_e_c_u_r_i_t_y_/_a_u_d_i_t_-_p_a_c_k_a_g_e_s package and running it after every ppkkgg__aadddd.
+CCOONNFFIIGGUURRAATTIIOONN VVAARRIIAABBLLEESS
+ The following variables change the behaviour of ppkkgg__aadddd and are described
+ in pkg_install.conf(5):
+
+ CERTIFICATE_ANCHOR_PKGS
+
+ CERTIFICATE_CHAIN
+
+ VERIFIED_INSTALLATION
+
SSEEEE AALLSSOO
pkg_admin(1), pkg_create(1), pkg_delete(1), pkg_info(1), tar(1),
- mktemp(3), sysconf(3), pkgsrc(7)
+ mktemp(3), sysconf(3), pkg_install.conf(5), pkgsrc(7)
AAUUTTHHOORRSS
Jordan Hubbard
@@ -329,18 +309,12 @@ AAUUTTHHOORRSS
NetBSD wildcard dependency processing, pkgdb, upgrading, etc.
Thomas Klausner
HTTP support.
+ Joerg Sonnenberger
+ Rewrote most of the code base to work without external commands.
BBUUGGSS
- Hard links between files in a distribution are only preserved if either
- (1) the staging area is on the same file system as the target directory
- of all the links to the file, or (2) all the links to the file are brack-
- eted by @@ccwwdd directives in the contents file, _a_n_d and the link names are
- extracted with a single ttaarr command (not split between invocations due to
- exec argument-space limitations--this depends on the value returned by
- ssyyssccoonnff(___S_C___A_R_G___M_A_X)).
-
Package upgrading needs a lot more work to be really universal.
Sure to be others.
-NetBSD 4.0 August 23, 2007 NetBSD 4.0
+NetBSD 5.0 October 10, 2008 NetBSD 5.0
diff --git a/pkgtools/pkg_install/files/add/verify.c b/pkgtools/pkg_install/files/add/verify.c
deleted file mode 100644
index 00fb8f2770c..00000000000
--- a/pkgtools/pkg_install/files/add/verify.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/* $NetBSD: verify.c,v 1.7 2004/12/29 12:16:56 agc Exp $ */
-
-/*
- * Copyright (c) 2001 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. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Alistair G. Crooks.
- * 4. 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_SYS_CDEFS_H
-#include <sys/cdefs.h>
-#endif
-
-#ifndef lint
-__COPYRIGHT("@(#) Copyright (c) 1999 \
- The NetBSD Foundation, Inc. All rights reserved.");
-__RCSID("$NetBSD: verify.c,v 1.7 2004/12/29 12:16:56 agc Exp $");
-#endif
-
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#if HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-
-#if HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#if HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#if HAVE_STRING_H
-#include <string.h>
-#endif
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "verify.h"
-#include "lib.h"
-
-enum {
- MaxExtensions = 10
-};
-
-/* this struct defines a verification type */
-typedef struct ver_t {
- const char *name; /* name of type */
- const char *command1; /* command to execute to verify */
- const char *command2; /* command to execute to verify */
- const char *extensions[MaxExtensions]; /* signature file extensions */
-} ver_t;
-
-static char *verification_type; /* the verification type which has been selected */
-
-/* called when gpg verification type is selected */
-static int
-do_verify(const char *pkgname, const char *cmd1, const char *cmd2, const char *const *extensions)
-{
- struct stat st;
- const char *const *ep;
- char buf[BUFSIZ];
- char f[MaxPathSize];
- int ret;
- int i;
-
- if (cmd1 == NULL) {
- return 1;
- }
- for (i = 0, ep = extensions ; i < MaxExtensions && *ep ; ep++, i++) {
- (void) snprintf(f, sizeof(f), "%s%s", pkgname, *ep);
- if (stat(f, &st) == 0) {
- (void) fprintf(stderr, "pkg_add: Using signature file: %s\n", f);
- ret = (cmd2 == NULL) ? fexec(cmd1, f, NULL) : fexec(cmd1, cmd2, f, NULL);
- if (ret != 0) {
- (void) fprintf(stderr, "*** WARNING ***: `%s' has a bad signature\n", f);
- return 0;
- }
- (void) fprintf(stderr, "Proceed with addition of %s: [y/n]? ", pkgname);
- if (fgets(buf, sizeof(buf), stdin) == NULL) {
- (void) fprintf(stderr, "Exiting now...");
- exit(EXIT_FAILURE);
- }
- switch(buf[0]) {
- case 'Y':
- case 'y':
- case '1':
- return 1;
- }
- (void) fprintf(stderr, "Package `%s' will not be added\n", pkgname);
- return 0;
- }
- }
- (void) fprintf(stderr, "No valid signature file found for `%s'\n", pkgname);
- return 0;
-}
-
-/* table holding possible verifications which can be made */
-static const ver_t vertab[] = {
- { "none", NULL, NULL, { NULL } },
- { "gpg", "gpg", "--verify", { ".sig", ".asc", NULL } },
- { "pgp5", "pgpv", NULL, { ".sig", ".asc", ".pgp", NULL } },
- { NULL }
-};
-
-/* set the verification type - usually called during command line processing */
-void
-set_verification(const char *type)
-{
- if (verification_type) {
- (void) free(verification_type);
- }
- verification_type = strdup(type);
-}
-
-/* return the type of verification that is being used */
-char *
-get_verification(void)
-{
- const ver_t *vp;
-
- if (verification_type != NULL) {
- for (vp = vertab ; vp->name ; vp++) {
- if (strcasecmp(verification_type, vp->name) == 0) {
- return verification_type;
- }
- }
- }
- return "none";
-}
-
-/* verify the digital signature (if any) on a package */
-int
-verify(const char *pkg)
-{
- const ver_t *vp;
-
- if (verification_type == NULL) {
- return do_verify(pkg, NULL, NULL, NULL);
- }
- for (vp = vertab ; vp->name ; vp++) {
- if (strcasecmp(verification_type, vp->name) == 0) {
- return do_verify(pkg, vp->command1, vp->command2, vp->extensions);
- }
- }
- (void) fprintf(stderr, "Can't find `%s' verification details\n", verification_type);
- return 0;
-}
diff --git a/pkgtools/pkg_install/files/add/verify.h b/pkgtools/pkg_install/files/add/verify.h
deleted file mode 100644
index 52a4c07d81d..00000000000
--- a/pkgtools/pkg_install/files/add/verify.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* $NetBSD: verify.h,v 1.3 2003/09/23 07:13:47 grant Exp $ */
-
-/*
- * Copyright (c) 2001 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. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Alistair G. Crooks.
- * 4. 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.
- */
-#ifndef VERIFY_H_
-#define VERIFY_H_
-
-void set_verification(const char *);
-char *get_verification(void);
-int verify(const char *);
-
-#endif /* VERIFY_H_ */