Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Initial cut at adding in events, starting with errors.
Will Andrews committed 14 years ago
commit 653e68cf7d86ffdf83a34ef3f67a0a990138d103
parent e27b4ca
16 files changed +307 -165
modified libpkg/Makefile
@@ -13,6 +13,7 @@ SRCS= pkg.c \
		pkg_create.c \
		pkg_delete.c \
		pkg_elf.c \
+
		pkg_event.c \
		pkg_error.c \
		pkg_handle.c \
		pkg_manifest.c \
modified libpkg/fetch.c
@@ -29,8 +29,9 @@ pkg_fetch_file(const char *url, const char *dest, void *data, fetch_cb cb)
	int retcode = EPKG_OK;

	if ((fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) {
-
		retcode = pkg_error_set(EPKG_FATAL, "open(%s): %s", dest,
-
								strerror(errno));
+
		pkg_emit_event(PKG_EVENT_OPEN_FAILED, /*argc*/2, dest,
+
		    strerror(errno));
+
		retcode = EPKG_FATAL;
		goto cleanup;
	}

@@ -39,7 +40,9 @@ pkg_fetch_file(const char *url, const char *dest, void *data, fetch_cb cb)
		if (remote == NULL) {
			--retry;
			if (retry == 0) {
-
				retcode = pkg_error_set(EPKG_FATAL, "%s", fetchLastErrString);
+
				pkg_emit_event(PKG_EVENT_FETCH_FAILED,
+
				    /*argc*/1, fetchLastErrString);
+
				retcode = EPKG_FATAL;
				goto cleanup;
			}
			sleep(1);
@@ -52,8 +55,9 @@ pkg_fetch_file(const char *url, const char *dest, void *data, fetch_cb cb)
			break;

		if (write(fd, buf, r) != r) {
-
			retcode = pkg_error_set(EPKG_FATAL, "write(%s): %s", dest,
-
									strerror(errno));
+
			pkg_emit_event(PKG_EVENT_WRITE_FAILED, /*argc*/2,
+
			    dest, strerror(errno));
+
			retcode = EPKG_FATAL;
			goto cleanup;
		}

@@ -67,7 +71,9 @@ pkg_fetch_file(const char *url, const char *dest, void *data, fetch_cb cb)
	}

	if (ferror(remote)) {
-
		retcode = pkg_error_set(EPKG_FATAL, "%s", fetchLastErrString);
+
		pkg_emit_event(PKG_EVENT_FETCH_FAILED, /*argc*/1,
+
		    fetchLastErrString);
+
		retcode = EPKG_FATAL;
		goto cleanup;
	}

@@ -104,7 +110,9 @@ pkg_fetch_buffer(const char *url, char **buffer, void *data, fetch_cb cb)
		if (remote == NULL) {
			--retry;
			if (retry == 0) {
-
				pkg_error_set(EPKG_FATAL, "%s", fetchLastErrString);
+
				pkg_emit_event(PKG_EVENT_FETCH_FAILED,
+
				    /*argc*/1, fetchLastErrString);
+
				retcode = EPKG_FATAL;
				goto cleanup;
			}
			sleep(1);
@@ -130,7 +138,8 @@ pkg_fetch_buffer(const char *url, char **buffer, void *data, fetch_cb cb)
	}

	if (ferror(remote)) {
-
		retcode = pkg_error_set(EPKG_FATAL, "%s", fetchLastErrString);
+
		pkg_emit_event(PKG_EVENT_FETCH_FAILED, /*argc*/1,
+
		    fetchLastErrString);
		goto cleanup;
	}

modified libpkg/packing.c
@@ -15,7 +15,6 @@
#include <stdlib.h>

#include <pkg.h>
-
#include <pkg_error.h>
#include <pkg_private.h>

static const char *packing_set_format(struct archive *a, pkg_formats format);
@@ -32,8 +31,10 @@ packing_init(struct packing **pack, const char *path, pkg_formats format)
	char archive_path[MAXPATHLEN];
	const char *ext;

-
	if ((*pack = calloc(1, sizeof(struct packing))) == NULL)
-
		return(pkg_error_set(EPKG_FATAL, "%s", strerror(errno)));
+
	if ((*pack = calloc(1, sizeof(struct packing))) == NULL) {
+
		pkg_emit_event(PKG_EVENT_MALLOC_FAILED, /*argc*/1,
+
		    strerror(errno));
+
	}

	(*pack)->aread = archive_read_disk_new();
	archive_read_disk_set_standard_lookup((*pack)->aread);
@@ -48,7 +49,7 @@ packing_init(struct packing **pack, const char *path, pkg_formats format)
			archive_read_finish((*pack)->aread);
			archive_write_finish((*pack)->awrite);
			archive_entry_free((*pack)->entry);
-
			return (pkg_error_set(EPKG_FATAL, "Unsupported format"));
+
			return EPKG_FATAL; /* error set by _set_format() */
		}
		snprintf(archive_path, sizeof(archive_path), "%s.%s", path, ext);

@@ -93,10 +94,9 @@ packing_append_file(struct packing *pack, const char *filepath, const char *newp

	retcode = archive_read_disk_entry_from_file(pack->aread, pack->entry, -1, NULL);
	if (retcode != ARCHIVE_OK) {
-
		pkg_emit_event(PKG_EVENT_ARCHIVE_ERROR, 2, filepath, pack->aread);
-
		retcode = pkg_error_set(EPKG_FATAL,
-
								"archive_read_disk_entry_from_file(%s): %s",
-
								filepath, archive_error_string(pack->aread));
+
		pkg_emit_event(PKG_EVENT_ARCHIVE_ERROR, /*argc*/2,
+
		    filepath, pack->aread);
+
		retcode = EPKG_FATAL;
		goto cleanup;
	}
	retcode = EPKG_OK;
@@ -121,8 +121,9 @@ packing_append_file(struct packing *pack, const char *filepath, const char *newp

	if (archive_entry_size(pack->entry) > 0) {
		if ((fd = open(filepath, O_RDONLY)) < 0) {
-
			retcode = pkg_error_set(EPKG_FATAL, "open(%s): %s", filepath,
-
									 strerror(errno));
+
			pkg_emit_event(PKG_EVENT_OPEN_FAILED, /*argc*/2,
+
			    filepath, strerror(errno));
+
			retcode = EPKG_FATAL;
			goto cleanup;
		}

@@ -202,19 +203,22 @@ packing_set_format(struct archive *a, pkg_formats format)
			if (archive_write_set_compression_xz(a) == ARCHIVE_OK) {
				return ("txz");
			} else {
-
				warnx("xz compression is not supported, trying bzip2");
+
				pkg_emit_event(PKG_EVENT_ARCHIVE_COMP_UNSUP,
+
				    /*argc*/2, "xz", "bzip2");
			}
		case TBZ:
			if (archive_write_set_compression_bzip2(a) == ARCHIVE_OK) {
				return ("tbz");
			} else {
-
				warnx("bzip2 compression is not supported, trying gzip");
+
				pkg_emit_event(PKG_EVENT_ARCHIVE_COMP_UNSUP,
+
				    /*argc*/2, "bzip2", "gzip");
			}
		case TGZ:
			if (archive_write_set_compression_gzip(a) == ARCHIVE_OK) {
				return ("tgz");
			} else {
-
				warnx("gzip compression is not supported, trying plain tar");
+
				pkg_emit_event(PKG_EVENT_ARCHIVE_COMP_UNSUP,
+
				    /*argc*/2, "gzip", "plain tar");
			}
		case TAR:
			archive_write_set_compression_none(a);
modified libpkg/pkg.c
@@ -14,8 +14,11 @@
int
pkg_new(struct pkg **pkg, pkg_t type)
{
-
	if ((*pkg = calloc(1, sizeof(struct pkg))) == NULL)
-
		return(pkg_error_set(EPKG_FATAL, "%s", strerror(errno)));
+
	if ((*pkg = calloc(1, sizeof(struct pkg))) == NULL) {
+
		pkg_emit_event(PKG_EVENT_MALLOC_FAILED, /*argc*/1,
+
		    strerror(errno));
+
		return EPKG_FATAL;
+
	}

	struct _fields {
		int id;
@@ -566,7 +569,8 @@ pkg_addscript_file(struct pkg *pkg, const char *path)
			strcmp(filename, "+UPGRADE") == 0) {
		type = PKG_SCRIPT_UPGRADE;
	} else {
-
		return (pkg_error_set(EPKG_FATAL, "unknown script"));
+
		pkg_emit_event(PKG_EVENT_UNKNOWN_SCRIPT, /*argc*/1, filename);
+
		return EPKG_FATAL;
	}

	ret = pkg_addscript(pkg, data, type);
@@ -778,7 +782,9 @@ pkg_open2(struct pkg **pkg_p, struct archive **a, struct archive_entry **ae, con
	archive_read_support_format_tar(*a);

	if (archive_read_open_filename(*a, path, 4096) != ARCHIVE_OK) {
-
		retcode = pkg_error_set(EPKG_FATAL, "%s", archive_error_string(*a));
+
		pkg_emit_event(PKG_EVENT_ARCHIVE_ERROR, /*argc*/2,
+
		    archive_entry_pathname(*ae), *a);
+
		retcode = EPKG_FATAL;
		goto cleanup;
	}

@@ -838,8 +844,11 @@ pkg_open2(struct pkg **pkg_p, struct archive **a, struct archive_entry **ae, con
		}
	}

-
	if (ret != ARCHIVE_OK && ret != ARCHIVE_EOF)
-
		retcode = pkg_error_set(EPKG_FATAL, "%s", archive_error_string(*a));
+
	if (ret != ARCHIVE_OK && ret != ARCHIVE_EOF) {
+
		pkg_emit_event(PKG_EVENT_ARCHIVE_ERROR, /*argc*/2,
+
		    archive_entry_pathname(*ae), *a);
+
		retcode = EPKG_FATAL;
+
	}

	if (ret == ARCHIVE_EOF)
		retcode = EPKG_END;
@@ -865,7 +874,7 @@ pkg_copy_tree(struct pkg *pkg, const char *src, const char *dest)

	if (packing_init(&pack, dest, 0) != EPKG_OK) {
		/* TODO */
-
		return (pkg_error_set(EPKG_FATAL, "unable to create archive"));
+
		return EPKG_FATAL;
	}

	while (pkg_files(pkg, &file) == EPKG_OK) {
modified libpkg/pkg.h
@@ -581,7 +581,33 @@ typedef enum {
	PKG_EVENT_INSTALL_BEGIN = 0,

	/* errors */
-
	PKG_EVENT_ARCHIVE_ERROR = 65536,
+
	PKG_EVENT_ARCHIVE_COMP_UNSUP = 65536,
+
	PKG_EVENT_ARCHIVE_ERROR,
+
	PKG_EVENT_ACCESS_ERROR,
+
	PKG_EVENT_ALREADY_INSTALLED,
+
	PKG_EVENT_CKSUM_FAILED,
+
	PKG_EVENT_CONFIG_KEY_NOTFOUND,
+
	PKG_EVENT_CREATEDB_FAILED,
+
	PKG_EVENT_CREATEDB_FAILED_ERRNO,
+
	PKG_EVENT_DB_OPEN_FAILED,
+
	PKG_EVENT_DELETE_DEP_EXISTS,
+
	PKG_EVENT_ERROR_INSTALLING_DEP,
+
	PKG_EVENT_FETCH_FAILED,
+
	PKG_EVENT_FSTAT_ERROR,
+
	PKG_EVENT_INVALID_DB_STATE,
+
	PKG_EVENT_MALLOC_FAILED,
+
	PKG_EVENT_MISSING_DEP,
+
	PKG_EVENT_OPEN_DB_FAILED,
+
	PKG_EVENT_OPEN_ERROR,
+
	PKG_EVENT_OPEN_FAILED,
+
	PKG_EVENT_PARSE_ERROR,
+
	PKG_EVENT_READ_ERROR,
+
	PKG_EVENT_REPO_KEY_UNAVAIL,
+
	PKG_EVENT_REPO_KEY_UNUSABLE,
+
	PKG_EVENT_SQLITE_CONSTRAINT,
+
	PKG_EVENT_SQLITE_ERROR,
+
	PKG_EVENT_UNKNOWN_SCRIPT,
+
	PKG_EVENT_WRITE_FAILED,
} pkg_event_t;

/**
modified libpkg/pkg_add.c
@@ -41,7 +41,9 @@ do_extract(struct archive *a, struct archive_entry *ae)

	do {
		if (archive_read_extract(a, ae, EXTRACT_ARCHIVE_FLAGS) != ARCHIVE_OK) {
-
			retcode = pkg_error_set(EPKG_FATAL, "%s", archive_error_string(a));
+
			pkg_emit_event(PKG_EVENT_ARCHIVE_ERROR, /*argc*/2,
+
			    archive_entry_pathname(ae), a);
+
			retcode = EPKG_FATAL;
			break;
		}

@@ -57,14 +59,19 @@ do_extract(struct archive *a, struct archive_entry *ae)
		    && lstat(path, &st) == ENOENT) {
			archive_entry_set_pathname(ae, path);
			if (archive_read_extract(a, ae, EXTRACT_ARCHIVE_FLAGS) != ARCHIVE_OK) {
-
				retcode = pkg_error_set(EPKG_FATAL, "%s", archive_error_string(a));
+
				pkg_emit_event(PKG_EVENT_ARCHIVE_ERROR, /*argc*/2,
+
				    archive_entry_pathname(ae), a);
+
				retcode = EPKG_FATAL;
				break;
			}
		}
	} while ((ret = archive_read_next_header(a, &ae)) == ARCHIVE_OK);

-
	if (ret != ARCHIVE_EOF)
-
		retcode = pkg_error_set(EPKG_FATAL, "%s", archive_error_string(a));
+
	if (ret != ARCHIVE_EOF) {
+
		pkg_emit_event(PKG_EVENT_ARCHIVE_ERROR, /*argc*/2,
+
		    archive_entry_pathname(ae), a);
+
		retcode = EPKG_FATAL;
+
	}

	return (retcode);
}
@@ -112,15 +119,17 @@ pkg_add(struct pkgdb *db, const char *path, struct pkg **pkg_p)

	ret = pkgdb_it_next(it, &p, PKG_LOAD_BASIC);
	pkgdb_it_free(it);
-
	pkg_free(p);

	if (ret == EPKG_OK) {
-
		retcode = pkg_error_set(EPKG_INSTALLED, "package already installed");
+
		pkg_emit_event(PKG_EVENT_ALREADY_INSTALLED, /*argc*/1, p);
+
		retcode = EPKG_INSTALLED;
		goto cleanup;
	} else if (ret != EPKG_END) {
		retcode = ret;
		goto cleanup;
	}
+
	pkg_free(p);
+
	p = NULL;

	/*
	 * Check for dependencies
@@ -140,16 +149,18 @@ pkg_add(struct pkgdb *db, const char *path, struct pkg **pkg_p)

			if (access(dpath, F_OK) == 0) {
				if (pkg_add(db, dpath, NULL) != EPKG_OK) {
-
					retcode = pkg_error_set(EPKG_FATAL, "error while "
-
											"installing %s (dependency): %s",
-
											dpath,
-
											pkg_error_string());
+
					/* XXX: maybe the pkg_error_string()
+
					 * should be handled in the event
+
					 * handler */
+
					pkg_emit_event(PKG_EVENT_ERROR_INSTALLING_DEP,
+
					    /*argc*/2, dpath, pkg_error_string());
+
					retcode = EPKG_FATAL;
					goto cleanup;
				}
			} else {
-
				retcode = pkg_error_set(EPKG_DEPENDENCY, "missing %s-%s dependency",
-
										pkg_dep_name(dep),
-
										pkg_dep_version(dep));
+
				retcode = EPKG_FATAL;
+
				pkg_emit_event(PKG_EVENT_MISSING_DEP, /*argc*/2,
+
				    pkg_dep_name(dep), pkg_dep_version(dep));
				goto cleanup;
			}
		}
@@ -161,7 +172,7 @@ pkg_add(struct pkgdb *db, const char *path, struct pkg **pkg_p)
	if (retcode != EPKG_OK || pkgdb_has_flag(db, PKGDB_FLAG_IN_FLIGHT) == 0)
		goto cleanup_reg;

-
	pkg_emit_event(PKG_EVENT_INSTALL_BEGIN, 1, pkg);
+
	pkg_emit_event(PKG_EVENT_INSTALL_BEGIN, /*argc*/1, pkg);

	/*
	 * Execute pre-install scripts
@@ -190,6 +201,9 @@ pkg_add(struct pkgdb *db, const char *path, struct pkg **pkg_p)
	if (a != NULL)
		archive_read_finish(a);

+
	if (p != NULL)
+
		pkg_free(p);
+

	if (pkg_p != NULL)
		*pkg_p = (retcode == EPKG_OK) ? pkg : NULL;
	else
modified libpkg/pkg_config.c
@@ -71,6 +71,6 @@ pkg_config(const char *key)
		}
	}

-
	pkg_error_set(EPKG_FATAL, "unknown configuration key `%s'", key);
+
	pkg_emit_event(PKG_EVENT_CONFIG_KEY_NOTFOUND, /*argc*/1, key);
	return (NULL);
}
modified libpkg/pkg_create_repo.c
@@ -76,8 +76,11 @@ pkg_create_repo(char *path, void (progress)(struct pkg *pkg, void *data), void *
		"INSERT INTO deps (origin, name, version, package_id) "
		"VALUES (?1, ?2, ?3, ?4);";

-
	if (!is_dir(path))
-
		return (pkg_error_set(EPKG_FATAL, "%s is not a directory", path));
+
	if (!is_dir(path)) {
+
		pkg_emit_event(PKG_EVENT_CREATEDB_FAILED, /*argc*/2,
+
		    path, "not a directory");
+
		return EPKG_FATAL;
+
	}

	repopath[0] = path;
	repopath[1] = NULL;
@@ -85,21 +88,25 @@ pkg_create_repo(char *path, void (progress)(struct pkg *pkg, void *data), void *
	snprintf(repodb, MAXPATHLEN, "%s/repo.sqlite", path);

	if (stat(repodb, &st) != -1)
-
		if (unlink(repodb) != 0)
-
			return (pkg_error_set(EPKG_FATAL, "can not unlink %s: %s", repodb,
-
								  strerror(errno)));
+
		if (unlink(repodb) != 0) {
+
			pkg_emit_event(PKG_EVENT_CREATEDB_FAILED_ERRNO,
+
			    /*argc*/3, path, repodb, strerror(errno));
+
			return EPKG_FATAL;
+
		}

	if (sqlite3_open(repodb, &sqlite) != SQLITE_OK)
		return (EPKG_FATAL);

	if (sqlite3_exec(sqlite, initsql, NULL, NULL, &errmsg) != SQLITE_OK) {
-
		retcode = pkg_error_set(EPKG_FATAL, "%s", errmsg);
+
		pkg_emit_event(PKG_EVENT_SQLITE_ERROR, /*argc*/1, errmsg);
+
		retcode = EPKG_FATAL;
		goto cleanup;
	}

	if (sqlite3_exec(sqlite, "BEGIN TRANSACTION;", NULL, NULL, &errmsg) !=
		SQLITE_OK) {
-
		retcode = pkg_error_set(EPKG_FATAL, "%s", errmsg);
+
		pkg_emit_event(PKG_EVENT_SQLITE_ERROR, /*argc*/1, errmsg);
+
		retcode = EPKG_FATAL;
		goto cleanup;
	}

@@ -114,8 +121,9 @@ pkg_create_repo(char *path, void (progress)(struct pkg *pkg, void *data), void *
	}

	if ((fts = fts_open(repopath, FTS_PHYSICAL, NULL)) == NULL) {
-
		retcode = pkg_error_set(EPKG_FATAL, "can not open %s: %s", repopath,
-
								strerror(errno));
+
		pkg_emit_event(PKG_EVENT_OPEN_DB_FAILED, /*argc*/2,
+
		    repopath, strerror(errno));
+
		retcode = EPKG_FATAL;
		goto cleanup;
	}

@@ -143,8 +151,10 @@ pkg_create_repo(char *path, void (progress)(struct pkg *pkg, void *data), void *

		if (pkg_open(&pkg, ent->fts_accpath) != EPKG_OK) {
			if (progress != NULL) {
-
				pkg_error_set(EPKG_WARN, "can not open %s: %s", ent->fts_name,
-
							  pkg_error_string());
+
				pkg_emit_event(PKG_EVENT_DB_OPEN_FAILED,
+
				    /*argc*/2, ent->fts_name,
+
				    pkg_error_string());
+
				retcode = EPKG_WARN;
				progress(NULL, data);
			}
			continue;
@@ -191,8 +201,10 @@ pkg_create_repo(char *path, void (progress)(struct pkg *pkg, void *data), void *

	}

-
	if (sqlite3_exec(sqlite, "COMMIT;", NULL, NULL, &errmsg) != SQLITE_OK)
-
		retcode = pkg_error_set(EPKG_FATAL, "%s", errmsg);
+
	if (sqlite3_exec(sqlite, "COMMIT;", NULL, NULL, &errmsg) != SQLITE_OK) {
+
		pkg_emit_event(PKG_EVENT_SQLITE_ERROR, /*argc*/1, errmsg);
+
		retcode = EPKG_FATAL;
+
	}

	cleanup:
	if (fts != NULL)
@@ -256,8 +268,11 @@ pkg_finish_repo(char *path, pem_password_cb *password_cb, char *rsa_key_path)

	packing_init(&pack, repo_archive, TXZ);
	if (rsa_key_path != NULL) {
-
		if (access(rsa_key_path, R_OK) == -1)
-
			return pkg_error_set(EPKG_FATAL, "RSA key invalid: %s", strerror(errno));
+
		if (access(rsa_key_path, R_OK) == -1) {
+
			pkg_emit_event(PKG_EVENT_REPO_KEY_UNAVAIL, /*argc*/2,
+
			    rsa_key_path, strerror(errno));
+
			return EPKG_FATAL;
+
		}

		SSL_load_error_strings();

@@ -271,8 +286,11 @@ pkg_finish_repo(char *path, pem_password_cb *password_cb, char *rsa_key_path)

		sha256_file(repo_path, sha256);

-
		if (RSA_sign(NID_sha1, sha256, 65, sigret, &siglen, rsa) == 0)
-
			return pkg_error_set(EPKG_FATAL, "Unable to sign the repository");
+
		if (RSA_sign(NID_sha1, sha256, 65, sigret, &siglen, rsa) == 0) {
+
			pkg_emit_event(PKG_EVENT_REPO_KEY_UNUSABLE, /*argc*/2,
+
			    rsa_key_path, ERR_get_error()); /* XXX pass back RSA errors correctly */
+
			return EPKG_FATAL;
+
		}

		packing_append_buffer(pack, sigret, "signature", max_len);

modified libpkg/pkg_delete.c
@@ -50,7 +50,9 @@ pkg_delete(struct pkg *pkg, struct pkgdb *db, int force)
	if (rdep_msg != NULL) {
		if (!force) {
			sbuf_finish(rdep_msg);
-
			ret = pkg_error_set(EPKG_REQUIRED, "%s", sbuf_get(rdep_msg));
+
			pkg_emit_event(PKG_EVENT_DELETE_DEP_EXISTS, /*argc*/1,
+
			    sbuf_get(rdep_msg));
+
			ret = EPKG_REQUIRED;
			sbuf_free(rdep_msg);
			return ret;
		}
added libpkg/pkg_event.c
@@ -0,0 +1,65 @@
+
#include <assert.h>
+
#include <archive.h>
+
#include "pkg.h"
+
#include "pkg_error.h"
+

+
/* Guard-rail against incorrect number of arguments */
+
static void
+
pkg_event_argument_check(pkg_event_t ev, int argc)
+
{
+

+
	switch(ev) {
+
	case PKG_EVENT_INSTALL_BEGIN:
+
		assert(argc == 1);
+
		break;
+
	case PKG_EVENT_ARCHIVE_ERROR:
+
		assert(argc == 2);
+
		break;
+
	default:
+
		break;
+
	}
+
}
+

+
/**
+
 * This function's purpose is to perform global event handling.
+
 */
+
static void
+
libpkg_handle_event(pkg_event_t ev, void **argv)
+
{
+
	switch(ev) {
+
	case PKG_EVENT_ARCHIVE_ERROR:
+
		pkg_error_set(EPKG_FATAL, "archive_read_disk_entry_from_file(%s): %s",
+
		    argv[0], archive_error_string(argv[1]));
+
		break;
+
	case PKG_EVENT_OPEN_FAILED:
+
		pkg_error_set(EPKG_FATAL, "open of %s failed: %s", argv[0], argv[1]);
+
		break;
+
	default:
+
		break;
+
	}
+
}
+

+
void
+
__pkg_emit_event(struct pkg_handle *hdl, pkg_event_t ev, int argc, ...)
+
{
+
	va_list ap;
+
	void **argv;
+
	int i;
+

+
	if (hdl == NULL || hdl->event_cb == NULL)
+
		return;
+

+
	pkg_event_argument_check(ev, argc);
+

+
	/* Generate the argument vector to pass in. */
+
	argv = calloc(argc, sizeof(void *));
+
	va_start(ap, argc);
+
	for (i = 0;i < argc; i++)
+
		argv[i] = va_arg(ap, void *);
+
	va_end(ap);
+

+
	libpkg_handle_event(ev, argv);
+

+
	if (hdl->event_cb != NULL)
+
		hdl->event_cb(ev, argv);
+
}
modified libpkg/pkg_handle.c
@@ -1,4 +1,3 @@
-
#include <assert.h>
#include "pkg.h"

struct pkg_handle __pkg_handle_singleton;
@@ -20,42 +19,3 @@ pkg_handle_get_event_callback(struct pkg_handle *hdl)
{
	return hdl->event_cb;
}
-

-
/* Guard-rail against incorrect number of arguments */
-
static void
-
pkg_event_argument_check(pkg_event_t ev, int argc)
-
{
-

-
	switch(ev) {
-
	case PKG_EVENT_INSTALL_BEGIN:
-
		assert(argc == 1);
-
		break;
-
	case PKG_EVENT_ARCHIVE_ERROR:
-
		assert(argc == 2);
-
		break;
-
	default:
-
		break;
-
	}
-
}
-

-
void
-
__pkg_emit_event(struct pkg_handle *hdl, pkg_event_t ev, int argc, ...)
-
{
-
	va_list ap;
-
	void **argv;
-
	int i;
-

-
	if (hdl == NULL || hdl->event_cb == NULL)
-
		return;
-

-
	pkg_event_argument_check(ev, argc);
-

-
	/* Generate the argument vector to pass in. */
-
	argv = calloc(argc, sizeof(void *));
-
	va_start(ap, argc);
-
	for (i = 0;i < argc; i++)
-
		argv[i] = va_arg(ap, void *);
-
	va_end(ap);
-

-
	hdl->event_cb(ev, argv);
-
}
modified libpkg/pkg_manifest.c
@@ -133,9 +133,11 @@ m_parse_flatsize(struct pkg *pkg, char *buf)
	errno = 0;
	size = strtoimax(buf, NULL, 10);

-
	if (errno == EINVAL || errno == ERANGE)
-
		return (pkg_error_set(EPKG_FATAL, "m_parse_flatsize(): %s",
-
				strerror(errno)));
+
	if (errno == EINVAL || errno == ERANGE) {
+
		pkg_emit_event(PKG_EVENT_PARSE_ERROR, /*argc*/2,
+
		    "flatsize", strerror(errno));
+
		return EPKG_FATAL;
+
	}

	pkg_setflatsize(pkg, size);
	return (EPKG_OK);
modified libpkg/pkg_repo.c
@@ -31,8 +31,10 @@ pkg_repo_fetch(struct pkg *pkg, void *data, fetch_cb cb)
	checksum:
	retcode = sha256_file(dest, cksum);
	if (retcode == EPKG_OK)
-
		if (strcmp(cksum, pkg_get(pkg, PKG_CKSUM)))
-
			retcode = pkg_error_set(EPKG_FATAL, "failed checksum");
+
		if (strcmp(cksum, pkg_get(pkg, PKG_CKSUM))) {
+
			pkg_emit_event(PKG_EVENT_CKSUM_FAILED, /*argc*/1, pkg);
+
			retcode = EPKG_FATAL;
+
		}

	return (retcode);
}
modified libpkg/pkg_util.c
@@ -70,23 +70,30 @@ file_to_buffer(const char *path, char **buffer, off_t *sz)
		return (ERROR_BAD_ARG("buffer"));

	if ((fd = open(path, O_RDONLY)) == -1) {
-
		return (pkg_error_set(EPKG_FATAL, "can not open %s: %s", path,
-
				strerror(errno)));
+
		pkg_emit_event(PKG_EVENT_OPEN_ERROR, /*argc*/2, path,
+
		    strerror(errno));
+
		return EPKG_FATAL;
	}

	if (fstat(fd, &st) == -1) {
		close(fd);
-
		return (pkg_error_set(EPKG_FATAL, "fstat(): %s", strerror(errno)));
+
		pkg_emit_event(PKG_EVENT_FSTAT_ERROR, /*argc*/2, path,
+
		    strerror(errno));
+
		return EPKG_FATAL;
	}

	if ((*buffer = malloc(st.st_size + 1)) == NULL) {
		close(fd);
-
		return (pkg_error_set(EPKG_FATAL, "malloc(): %s", strerror(errno)));
+
		pkg_emit_event(PKG_EVENT_MALLOC_FAILED, /*argc*/1,
+
		    strerror(errno));
+
		return EPKG_FATAL;
	}

	if (read(fd, *buffer, st.st_size) == -1) {
		close(fd);
-
		return (pkg_error_set(EPKG_FATAL, "read(%s): %s", path, strerror(errno)));
+
		pkg_emit_event(PKG_EVENT_READ_ERROR, /*argc*/2,
+
		    path, strerror(errno));
+
		return EPKG_FATAL;
	}

	close(fd);
@@ -206,9 +213,11 @@ sha256_file(const char *path, char out[65])
	size_t r = 0;
	SHA256_CTX sha256;

-
	if ((fp = fopen(path, "rb")) == NULL)
-
		return (pkg_error_set(EPKG_FATAL, "fopen(%s): %s", path,
-
							  strerror(errno)));
+
	if ((fp = fopen(path, "rb")) == NULL) {
+
		pkg_emit_event(PKG_EVENT_OPEN_FAILED, /*argc*/2,
+
		    path, strerror(errno));
+
		return EPKG_FATAL;
+
	}

	SHA256_Init(&sha256);

@@ -218,9 +227,9 @@ sha256_file(const char *path, char out[65])
	if (ferror(fp) != 0) {
		fclose(fp);
		out[0] = '\0';
-
		return (pkg_error_set(EPKG_FATAL, "fread(%s): %s", path,
-
							  strerror(errno)));
-

+
		pkg_emit_event(PKG_EVENT_READ_ERROR, /*argc*/2,
+
		    path, strerror(errno));
+
		return EPKG_FATAL;
	}

	fclose(fp);
modified libpkg/pkgdb.c
@@ -231,7 +231,7 @@ pkgdb_init(sqlite3 *sdb)
	;

	if (sqlite3_exec(sdb, sql, NULL, NULL, &errmsg) != SQLITE_OK) {
-
		pkg_error_set(EPKG_FATAL, "sqlite: %s", errmsg);
+
		pkg_emit_event(PKG_EVENT_SQLITE_ERROR, /*argc*/1, errmsg);
		sqlite3_free(errmsg);
		return (EPKG_FATAL);
	}
@@ -251,20 +251,27 @@ pkgdb_open(struct pkgdb **db, pkgdb_t type)

	dbdir = pkg_config("PKG_DBDIR");

-
	if ((*db = calloc(1, sizeof(struct pkgdb))) == NULL)
-
		return (pkg_error_set(EPKG_FATAL, "calloc(): %s", strerror(errno)));
+
	if ((*db = calloc(1, sizeof(struct pkgdb))) == NULL) {
+
		pkg_emit_event(PKG_EVENT_MALLOC_FAILED, /*argc*/1,
+
		    strerror(errno));
+
		return EPKG_FATAL;
+
	}

	(*db)->type = type;

	snprintf(localpath, sizeof(localpath), "%s/local.sqlite", dbdir);
	retcode = access(localpath, R_OK);
	if (retcode == -1) {
-
		if (errno != ENOENT)
-
			return (pkg_error_set(EPKG_FATAL, "%s: %s", localpath,
-
								  strerror(errno)));
-
		else if (eaccess(dbdir, W_OK) != 0)
-
			return (pkg_error_set(EPKG_FATAL, "can not initialize database in "
-
								 "%s: %s", dbdir, strerror(errno)));
+
		if (errno != ENOENT) {
+
			pkg_emit_event(PKG_EVENT_ACCESS_ERROR, /*argc*/2,
+
			    localpath, strerror(errno));
+
			return EPKG_FATAL;
+
		}
+
		else if (eaccess(dbdir, W_OK) != 0) {
+
			pkg_emit_event(PKG_EVENT_ACCESS_ERROR, /*argc*/2,
+
			    dbdir, strerror(errno));
+
			return EPKG_FATAL;
+
		}
	}

	if (sqlite3_open(localpath, &(*db)->sqlite) != SQLITE_OK)
@@ -273,14 +280,16 @@ pkgdb_open(struct pkgdb **db, pkgdb_t type)
	if (type == PKGDB_REMOTE) {
		snprintf(remotepath, sizeof(remotepath), "%s/repo.sqlite", dbdir);

-
		if (access(remotepath, R_OK) != 0)
-
			return (pkg_error_set(EPKG_FATAL, "repo.sqlite: %s",
-
								  strerror(errno)));
+
		if (access(remotepath, R_OK) != 0) {
+
			pkg_emit_event(PKG_EVENT_ACCESS_ERROR, /*argc*/2,
+
			    remotepath, strerror(errno));
+
			return EPKG_FATAL;
+
		}

		sqlite3_snprintf(sizeof(sql), sql, "ATTACH \"%s\" as remote;", remotepath);

		if (sqlite3_exec((*db)->sqlite, sql, NULL, NULL, &errmsg) != SQLITE_OK) {
-
			pkg_error_set(EPKG_FATAL, "%s", errmsg);
+
			pkg_emit_event(PKG_EVENT_SQLITE_ERROR, /*argc*/1, errmsg);
			sqlite3_free(errmsg);
			return (EPKG_FATAL);
		}
@@ -306,7 +315,7 @@ pkgdb_open(struct pkgdb **db, pkgdb_t type)
	 */
	if (sqlite3_exec((*db)->sqlite, "PRAGMA foreign_keys = ON;", NULL, NULL,
		&errmsg) != SQLITE_OK) {
-
		pkg_error_set(EPKG_FATAL, "sqlite: %s", errmsg);
+
		pkg_emit_event(PKG_EVENT_SQLITE_ERROR, /*argc*/1, errmsg);
		sqlite3_free(errmsg);
		return (EPKG_FATAL);
	}
@@ -336,7 +345,8 @@ pkgdb_it_new(struct pkgdb *db, sqlite3_stmt *s, int type)
	struct pkgdb_it *it;

	if ((it = malloc(sizeof(struct pkgdb_it))) == NULL) {
-
		pkg_error_set(EPKG_FATAL, "malloc(): %s", strerror(errno));
+
		pkg_emit_event(PKG_EVENT_MALLOC_FAILED, /*argc*/1,
+
		    strerror(errno));
		sqlite3_finalize(s);
		return (NULL);
	}
@@ -880,14 +890,15 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
		"VALUES (?1, ?2);";

	if (pkgdb_has_flag(db, PKGDB_FLAG_IN_FLIGHT)) {
-
		pkg_error_set(EPKG_FATAL, "tried to register a package with an in-flight SQL command");
+
		pkg_emit_event(PKG_EVENT_INVALID_DB_STATE, /*argc*/1,
+
		    "tried to register a package with an in-flight SQL command");
		return (EPKG_FATAL);
	}

	s = db->sqlite;

	if (sqlite3_exec(s, sql_begin, NULL, NULL, &errmsg) != SQLITE_OK) {
-
		pkg_error_set(EPKG_FATAL, "sqlite: %s", errmsg);
+
		pkg_emit_event(PKG_EVENT_SQLITE_ERROR, /*argc*/1, errmsg);
		sqlite3_free(errmsg);
		return (EPKG_FATAL);
	}
@@ -916,10 +927,10 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
	sqlite3_bind_int(stmt_pkg, 14, pkg_isautomatic(pkg));

	if ((ret = sqlite3_step(stmt_pkg)) != SQLITE_DONE) {
-
		if ( ret == SQLITE_CONSTRAINT)
-
			retcode = pkg_error_set(EPKG_FATAL, "constraint violation on "
-
					"pkg with %s", pkg_get(pkg, PKG_ORIGIN));
-
		else
+
		if ( ret == SQLITE_CONSTRAINT) {
+
			pkg_emit_event(PKG_EVENT_SQLITE_CONSTRAINT, /*argc*/1, pkg);
+
			retcode = EPKG_FATAL;
+
		} else
			retcode = ERROR_SQLITE(s);
		goto cleanup;
	}
@@ -959,10 +970,10 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
		sqlite3_bind_int64(stmt_dep, 4, package_id);

		if ((ret = sqlite3_step(stmt_dep)) != SQLITE_DONE) {
-
			if ( ret == SQLITE_CONSTRAINT)
-
				retcode = pkg_error_set(EPKG_FATAL, "constraint violation on "
-
						"deps with %s", pkg_dep_origin(dep));
-
			else
+
			if ( ret == SQLITE_CONSTRAINT) {
+
				pkg_emit_event(PKG_EVENT_SQLITE_CONSTRAINT, /*argc*/1,dep);
+
				retcode = EPKG_FATAL;
+
			} else
				retcode = ERROR_SQLITE(s);
			goto cleanup;
		}
@@ -984,10 +995,10 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
		sqlite3_bind_int64(stmt_conflict, 2, package_id);

		if ((ret = sqlite3_step(stmt_conflict)) != SQLITE_DONE) {
-
			if ( ret == SQLITE_CONSTRAINT)
-
				retcode = pkg_error_set(EPKG_FATAL, "constraint violation on "
-
						"conflicts with %s", pkg_conflict_glob(conflict));
-
			else
+
			if ( ret == SQLITE_CONSTRAINT) {
+
				pkg_emit_event(PKG_EVENT_SQLITE_CONSTRAINT, /*argc*/1, conflict);
+
				retcode = EPKG_FATAL;
+
			} else
				retcode = ERROR_SQLITE(s);
			goto cleanup;
		}
@@ -1011,10 +1022,10 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
		sqlite3_bind_int64(stmt_file, 3, package_id);

		if ((ret = sqlite3_step(stmt_file)) != SQLITE_DONE) {
-
			if (ret == SQLITE_CONSTRAINT)
-
				retcode = pkg_error_set(EPKG_FATAL, "constraint violation on "
-
						"path with %s", pkg_file_path(file));
-
			else
+
			if (ret == SQLITE_CONSTRAINT) {
+
				pkg_emit_event(PKG_EVENT_SQLITE_CONSTRAINT, /*argc*/1, file);
+
				retcode = EPKG_FATAL;
+
			} else
				retcode = ERROR_SQLITE(s);
			goto cleanup;
		}
@@ -1035,10 +1046,10 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
		sqlite3_bind_text(stmt_dirs, 2, pkg_dir_path(dir), -1, SQLITE_STATIC);
			
		if ((ret = sqlite3_step(stmt_dirs)) != SQLITE_DONE) {
-
			if ( ret == SQLITE_CONSTRAINT)
-
				retcode = pkg_error_set(EPKG_FATAL, "constraint violation on "
-
						"dirs with %s", pkg_dir_path(dir));
-
			else
+
			if ( ret == SQLITE_CONSTRAINT) {
+
				pkg_emit_event(PKG_EVENT_SQLITE_CONSTRAINT, /*argc*/1, dir);
+
				retcode = EPKG_FATAL;
+
			} else
				retcode = ERROR_SQLITE(s);
			goto cleanup;
		}
@@ -1060,10 +1071,10 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
		sqlite3_bind_int64(stmt_script, 3, package_id);

		if (sqlite3_step(stmt_script) != SQLITE_DONE) {
-
			if ( ret == SQLITE_CONSTRAINT)
-
				retcode = pkg_error_set(EPKG_FATAL, "constraint violation on "
-
						"scripts with %s", pkg_script_data(script));
-
			else
+
			if ( ret == SQLITE_CONSTRAINT) {
+
				pkg_emit_event(PKG_EVENT_SQLITE_CONSTRAINT, /*argc*/1, script);
+
				retcode = EPKG_FATAL;
+
			} else
				retcode = ERROR_SQLITE(s);
			goto cleanup;
		}
@@ -1131,13 +1142,15 @@ pkgdb_register_finale(struct pkgdb *db, int retcode)
	char *errmsg;

	if (!pkgdb_has_flag(db, PKGDB_FLAG_IN_FLIGHT)) {
-
		ret = pkg_error_set(EPKG_FATAL, "database command not in flight");
-
		return ret;
+
		pkg_emit_event(PKG_EVENT_INVALID_DB_STATE, /*argc*/1,
+
		    "database command not in flight");
+
		return EPKG_FATAL;
	}

	command = (retcode == EPKG_OK) ? commands[0] : commands[1];
	if (sqlite3_exec(db->sqlite, command, NULL, NULL, &errmsg) != SQLITE_OK) {
-
		ret = pkg_error_set(EPKG_FATAL, "sqlite: %s", errmsg);
+
		pkg_emit_event(PKG_EVENT_SQLITE_ERROR, /*argc*/1, errmsg);
+
		ret = EPKG_FATAL;
		sqlite3_free(errmsg);
	}
	PKGDB_UNSET_FLAG(db, PKGDB_FLAG_IN_FLIGHT);
@@ -1217,7 +1230,8 @@ pkgdb_compact(struct pkgdb *db)
		return (EPKG_OK);

	if (sqlite3_exec(db->sqlite, "VACUUM;", NULL, NULL, &errmsg) != SQLITE_OK){
-
		retcode = pkg_error_set(EPKG_FATAL, "%s", errmsg);
+
		pkg_emit_event(PKG_EVENT_SQLITE_ERROR, /*argc*/1, errmsg);
+
		retcode = EPKG_FATAL;
		sqlite3_free(errmsg);
	}

@@ -1230,7 +1244,8 @@ pkgdb_query_upgrades(struct pkgdb *db)
	sqlite3_stmt *stmt;

	if (db->type != PKGDB_REMOTE) {
-
		pkg_error_set(EPKG_FATAL, "remote database not attached");
+
		pkg_emit_event(PKG_EVENT_INVALID_DB_STATE, /*argc*/1,
+
		    "remote database not attached");
		return (NULL);
	}

@@ -1258,7 +1273,8 @@ pkgdb_query_downgrades(struct pkgdb *db)
	sqlite3_stmt *stmt;

	if (db->type != PKGDB_REMOTE) {
-
		pkg_error_set(EPKG_FATAL, "remote database not attached");
+
		pkg_emit_event(PKG_EVENT_INVALID_DB_STATE, /*argc*/1,
+
		    "remote database not attached");
		return (NULL);
	}

modified pkg/event.c
@@ -1,4 +1,5 @@
#include <archive.h>
+
#include <err.h>

#include "pkg.h"
#include "event.h"
@@ -15,6 +16,10 @@ event_callback(pkg_event_t ev, void **argv)
		fprintf(stderr, "archive error on %s: %s\n",
		    (const char *)argv[0], archive_error_string(argv[1]));
		break;
+
	case PKG_EVENT_ARCHIVE_COMP_UNSUP:
+
		warnx("%s is not supported, trying %s",
+
		    (const char *)argv[0], (const char *)argv[1]);
+
		break;
	default:
		break;
	}