Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Merge remote branch 'pkgng/master'
Will Andrews committed 14 years ago
commit dc7f425163bd8782635faab61f1c1a115039d540
parent d2afb0f
24 files changed +1117 -1090
modified libpkg/Makefile
@@ -8,19 +8,16 @@ SHLIB_MAJOR= 0

SRCS=		pkg.c \
		pkg_add.c \
+
		pkg_attributes.c \
		pkg_config.c \
-
		pkg_conflict.c \
		pkg_create.c \
		pkg_delete.c \
		pkg_elf.c \
		pkg_error.c \
-
		pkg_file.c \
		pkg_handle.c \
		pkg_manifest.c \
-
		pkg_option.c \
		pkg_ports.c \
		pkg_repo.c \
-
		pkg_script.c \
		pkg_create_repo.c \
		pkg_util.c \
		pkg_version.c \
modified libpkg/pkg.c
@@ -11,6 +11,99 @@
#include "pkg_private.h"
#include "pkg_util.h"

+
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)));
+

+
	struct _fields {
+
		int id;
+
		int type;
+
		int optional;
+
	} fields[] = {
+
		{PKG_ORIGIN, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
+
		{PKG_NAME, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
+
		{PKG_VERSION, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
+
		{PKG_COMMENT, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
+
		{PKG_DESC, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
+
		{PKG_MTREE, PKG_FILE|PKG_INSTALLED|PKG_UPGRADE, 1},
+
		{PKG_MESSAGE, PKG_FILE|PKG_INSTALLED|PKG_UPGRADE, 1},
+
		{PKG_ARCH, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
+
		{PKG_OSVERSION, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
+
		{PKG_MAINTAINER, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
+
		{PKG_WWW, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 1},
+
		{PKG_PREFIX, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
+
		{PKG_REPOPATH, PKG_REMOTE|PKG_UPGRADE, 0},
+
		{PKG_CKSUM, PKG_REMOTE|PKG_UPGRADE, 0},
+
		{PKG_NEWVERSION, PKG_UPGRADE, 0},
+
	};
+

+
	for (int i = 0; i < PKG_NUM_FIELDS; i++) {
+
		(*pkg)->fields[fields[i].id].type = fields[i].type;
+
		(*pkg)->fields[fields[i].id].optional = fields[i].optional;
+
	}
+

+
	STAILQ_INIT(&(*pkg)->deps);
+
	STAILQ_INIT(&(*pkg)->rdeps);
+
	STAILQ_INIT(&(*pkg)->files);
+
	STAILQ_INIT(&(*pkg)->dirs);
+
	STAILQ_INIT(&(*pkg)->conflicts);
+
	STAILQ_INIT(&(*pkg)->scripts);
+
	STAILQ_INIT(&(*pkg)->options);
+

+
	(*pkg)->automatic = false;
+
	(*pkg)->type = type;
+

+
	return (EPKG_OK);
+
}
+

+
void
+
pkg_reset(struct pkg *pkg, pkg_t type)
+
{
+
	if (pkg == NULL)
+
		return;
+

+
	for (int i = 0; i < PKG_NUM_FIELDS; i++)
+
		sbuf_reset(pkg->fields[i].value);
+

+
	pkg->flatsize = 0;
+
	pkg->new_flatsize = 0;
+
	pkg->new_pkgsize = 0;
+
	pkg->flags = 0;
+
	pkg->rowid = 0;
+

+
	pkg_freedeps(pkg);
+
	pkg_freerdeps(pkg);
+
	pkg_freefiles(pkg);
+
	pkg_freedirs(pkg);
+
	pkg_freeconflicts(pkg);
+
	pkg_freescripts(pkg);
+
	pkg_freeoptions(pkg);
+

+
	pkg->type = type;
+
}
+

+
void
+
pkg_free(struct pkg *pkg)
+
{
+
	if (pkg == NULL)
+
		return;
+

+
	for (int i = 0; i < PKG_NUM_FIELDS; i++)
+
		sbuf_free(pkg->fields[i].value);
+

+
	pkg_freedeps(pkg);
+
	pkg_freerdeps(pkg);
+
	pkg_freefiles(pkg);
+
	pkg_freedirs(pkg);
+
	pkg_freeconflicts(pkg);
+
	pkg_freescripts(pkg);
+
	pkg_freeoptions(pkg);
+

+
	free(pkg);
+
}
+

pkg_t
pkg_type(struct pkg const * const pkg)
{
@@ -150,396 +243,285 @@ pkg_new_pkgsize(struct pkg *pkg)
	return (pkg->new_pkgsize);
}

-
struct pkg_script **
-
pkg_scripts(struct pkg *pkg)
+
int
+
pkg_setflatsize(struct pkg *pkg, int64_t size)
{
-
	if (pkg == NULL) {
-
		ERROR_BAD_ARG("pkg");
-
		return (NULL);
-
	}
+
	if (pkg == NULL)
+
		return (ERROR_BAD_ARG("pkg"));
+

+
	if (size < 0)
+
		return (ERROR_BAD_ARG("size"));

-
	array_init(&pkg->scripts, 1);
-
	return ((struct pkg_script **)pkg->scripts.data);
+
	pkg->flatsize = size;
+
	return (EPKG_OK);
}

-
struct pkg **
-
pkg_deps(struct pkg *pkg)
+
int
+
pkg_setnewflatsize(struct pkg *pkg, int64_t size)
{
-
	if (pkg == NULL) {
-
		ERROR_BAD_ARG("pkg");
-
		return (NULL);
-
	}
+
	if (pkg == NULL)
+
		return (ERROR_BAD_ARG("pkg"));

-
	array_init(&pkg->deps, 1);
-
	return ((struct pkg **)pkg->deps.data);
-
}
+
	if (size <0)
+
		return (ERROR_BAD_ARG("size"));

-
struct pkg_option **
-
pkg_options(struct pkg *pkg)
-
{
-
	if (pkg == NULL) {
-
		ERROR_BAD_ARG("pkg");
-
		return (NULL);
-
	}
+
	pkg->new_flatsize = size;

-
	array_init(&pkg->options, 1);
-
	return ((struct pkg_option **)pkg->options.data);
+
	return (EPKG_OK);
}

int
-
pkg_resolvdeps(struct pkg *pkg, struct pkgdb *db) {
-
	struct pkg *p = NULL;
-
	struct pkgdb_it *it;
-
	struct pkg **deps;
-
	int i;
+
pkg_setnewpkgsize(struct pkg *pkg, int64_t size)
+
{
+
	if (pkg == NULL)
+
		return (ERROR_BAD_ARG("pkg"));

-
	deps = pkg_deps(pkg);
-
	for (i = 0; deps[i] != NULL; i++) {
-
		if (deps[i]->type != PKG_INSTALLED) {
-
			it = pkgdb_query(db, pkg_get(deps[i], PKG_ORIGIN), MATCH_EXACT);
+
	if (size <0)
+
		return (ERROR_BAD_ARG("size"));

-
			if (pkgdb_it_next(it, &p, PKG_LOAD_BASIC) == EPKG_OK) {
-
				deps[i]->type = PKG_INSTALLED;
-
			} else {
-
				deps[i]->type = PKG_NOTFOUND;
-
			}
-
			pkgdb_it_free(it);
-
		}
-
	}
-
	pkg_free(p);
+
	pkg->new_pkgsize = size;

	return (EPKG_OK);
}

-
struct pkg **
-
pkg_rdeps(struct pkg *pkg)
+
int
+
pkg_deps(struct pkg *pkg, struct pkg_dep **d)
{
-
	if (pkg == NULL) {
-
		ERROR_BAD_ARG("pkg");
-
		return (NULL);
-
	}
+
	if (pkg == NULL)
+
		return (ERROR_BAD_ARG("pkg"));
+

+
	if (*d == NULL)
+
		*d = STAILQ_FIRST(&pkg->deps);
+
	else
+
		*d = STAILQ_NEXT(*d, next);

-
	array_init(&pkg->rdeps, 1);
-
	return ((struct pkg **)pkg->rdeps.data);
+
	if (*d == NULL)
+
		return (EPKG_END);
+
	else
+
		return (EPKG_OK);
}

-
struct pkg_file **
-
pkg_files(struct pkg *pkg)
+
int
+
pkg_rdeps(struct pkg *pkg, struct pkg_dep **d)
{
-
	if (pkg == NULL) {
-
		ERROR_BAD_ARG("pkg");
-
		return (NULL);
-
	}
+
	if (pkg == NULL)
+
		return (ERROR_BAD_ARG("pkg"));
+

+
	if (*d == NULL)
+
		*d = STAILQ_FIRST(&pkg->rdeps);
+
	else
+
		*d = STAILQ_NEXT(*d, next);

-
	array_init(&pkg->files, 1);
-
	return ((struct pkg_file **)pkg->files.data);
+
	if (*d == NULL)
+
		return (EPKG_END);
+
	else
+
		return (EPKG_OK);
}

-
const char **
-
pkg_dirs(struct pkg *pkg)
+
int
+
pkg_files(struct pkg *pkg, struct pkg_file **f)
{
-
	if (pkg == NULL) {
-
		ERROR_BAD_ARG("pkg");
-
		return (NULL);
-
	}
+
	if (pkg == NULL)
+
		return (ERROR_BAD_ARG("pkg"));

-
	array_init(&pkg->dirs, 1);
-
	return ((const char **)pkg->dirs.data);
+
	if (*f == NULL)
+
		*f = STAILQ_FIRST(&pkg->files);
+
	else
+
		*f = STAILQ_NEXT(*f, next);
+

+
	if (*f == NULL)
+
		return (EPKG_END);
+
	else
+
		return (EPKG_OK);
}

-
struct pkg_conflict **
-
pkg_conflicts(struct pkg *pkg)
+
int
+
pkg_dirs(struct pkg *pkg, struct pkg_dir **d)
{
-
	if (pkg == NULL) {
-
		ERROR_BAD_ARG("pkg");
-
		return (NULL);
-
	}
+
	if (pkg == NULL)
+
		return (ERROR_BAD_ARG("pkg"));
+

+
	if (*d == NULL)
+
		*d = STAILQ_FIRST(&pkg->dirs);
+
	else
+
		*d = STAILQ_NEXT(*d, next);

-
	array_init(&pkg->conflicts, 1);
-
	return ((struct pkg_conflict **)pkg->conflicts.data);
+
	if (*d == NULL)
+
		return (EPKG_END);
+
	else
+
		return (EPKG_OK);
}

int
-
pkg_open(struct pkg **pkg_p, const char *path)
+
pkg_conflicts(struct pkg *pkg, struct pkg_conflict **c)
{
-
	struct archive *a;
-
	struct archive_entry *ae;
-
	int ret;
+
	if (pkg == NULL)
+
		return (ERROR_BAD_ARG("pkg"));

-
	ret = pkg_open2(pkg_p, &a, &ae, path);
+
	if (*c == NULL)
+
		*c = STAILQ_FIRST(&pkg->conflicts);
+
	else
+
		*c = STAILQ_NEXT(*c, next);

-
	if (ret != EPKG_OK && ret != EPKG_END)
-
		return (EPKG_FATAL);
+
	if (*c == NULL)
+
		return (EPKG_END);
+
	else
+
		return (EPKG_OK);
+
}

-
	archive_read_finish(a);
+
int
+
pkg_scripts(struct pkg *pkg, struct pkg_script **s)
+
{
+
	if (pkg == NULL)
+
		return (ERROR_BAD_ARG("pkg"));

-
	return (EPKG_OK);
+
	if (*s == NULL)
+
		*s = STAILQ_FIRST(&pkg->scripts);
+
	else
+
		*s = STAILQ_NEXT(*s, next);
+

+
	if (*s == NULL)
+
		return (EPKG_END);
+
	else
+
		return (EPKG_OK);
}

int
-
pkg_open2(struct pkg **pkg_p, struct archive **a, struct archive_entry **ae, const char *path)
+
pkg_options(struct pkg *pkg, struct pkg_option **o)
{
-
	struct pkg *pkg;
-
	struct pkg_script *script;
-
	pkg_error_t retcode = EPKG_OK;
-
	int ret;
-
	int64_t size;
-
	char *manifest;
-
	const char *fpath;
-
	char buf[2048];
-
	struct sbuf **sbuf;
-
	int i;
+
	if (pkg == NULL)
+
		return (ERROR_BAD_ARG("pkg"));

-
	struct {
-
		const char *name;
-
		pkg_attr attr;
-
	} files[] = {
-
		{ "+DESC", PKG_DESC },
-
		{ "+MTREE_DIRS", PKG_MTREE },
-
		{ NULL, 0 }
-
	};
-
	struct {
-
		const char *name;
-
		pkg_script_t type;
-
	} scripts[] = {
-
		{ "+PRE_INSTALL", PKG_SCRIPT_PRE_INSTALL },
-
		{ "+POST_INSTALL", PKG_SCRIPT_POST_INSTALL },
-
		{ "+PRE_DEINSTALL", PKG_SCRIPT_PRE_DEINSTALL },
-
		{ "+POST_DEINSTALL", PKG_SCRIPT_POST_DEINSTALL },
-
		{ "+PRE_UPGRADE", PKG_SCRIPT_PRE_UPGRADE },
-
		{ "+POST_UPGRADE", PKG_SCRIPT_POST_UPGRADE },
-
		{ "+INSTALL", PKG_SCRIPT_INSTALL },
-
		{ "+DEINSTALL", PKG_SCRIPT_DEINSTALL },
-
		{ "+UPGRADE", PKG_SCRIPT_UPGRADE },
-
		{ NULL, 0 }
-
	};
+
	if (*o == NULL)
+
		*o = STAILQ_FIRST(&pkg->options);
+
	else
+
		*o = STAILQ_NEXT(*o, next);

-
	if (path == NULL)
-
		return (ERROR_BAD_ARG("path"));
+
	if (*o == NULL)
+
		return (EPKG_END);
+
	else
+
		return (EPKG_OK);
+
}

-
	*a = archive_read_new();
-
	archive_read_support_compression_all(*a);
-
	archive_read_support_format_tar(*a);
+
int
+
pkg_adddep(struct pkg *pkg, const char *name, const char *origin, const char *version)
+
{
+
	struct pkg_dep *d;

-
	if (archive_read_open_filename(*a, path, 4096) != ARCHIVE_OK) {
-
		retcode = pkg_error_set(EPKG_FATAL, "%s", archive_error_string(*a));
-
		goto cleanup;
-
	}
+
	if (pkg == NULL)
+
		return (ERROR_BAD_ARG("pkg"));

-
	if (*pkg_p == NULL)
-
		pkg_new(pkg_p, PKG_FILE);
-
	else
-
		pkg_reset(*pkg_p, PKG_FILE);
+
	if (name == NULL || name[0] == '\0')
+
		return (ERROR_BAD_ARG("name"));

-
	pkg = *pkg_p;
-
	pkg->type = PKG_FILE;
+
	if (origin == NULL || origin[0] == '\0')
+
		return (ERROR_BAD_ARG("origin"));

-
	array_init(&pkg->scripts, 10);
-
	array_init(&pkg->files, 10);
+
	if (version == NULL || version[0] == '\0')
+
		return (ERROR_BAD_ARG("version"));

-
	while ((ret = archive_read_next_header(*a, ae)) == ARCHIVE_OK) {
-
		fpath = archive_entry_pathname(*ae);
+
	pkg_dep_new(&d);

-
		if (fpath[0] != '+')
-
			break;
+
	sbuf_set(&d->origin, origin);
+
	sbuf_set(&d->name, name);
+
	sbuf_set(&d->version, version);

-
		if (strcmp(fpath, "+MANIFEST") == 0) {
-
			size = archive_entry_size(*ae);
-
			manifest = calloc(1, size + 1);
-
			archive_read_data(*a, manifest, size);
-
			ret = pkg_parse_manifest(pkg, manifest);
-
			free(manifest);
-
			if (ret != EPKG_OK) {
-
				retcode = EPKG_FATAL;
-
				goto cleanup;
-
			}
-
		}
-

-
		for (i = 0; files[i].name != NULL; i++) {
-
			if (strcmp(fpath, files[i].name) == 0) {
-
				sbuf = &pkg->fields[files[i].attr].value;
-
				if (*sbuf == NULL)
-
					*sbuf = sbuf_new_auto();
-
				else
-
					sbuf_reset(*sbuf);
-
				while ((size = archive_read_data(*a, buf, sizeof(buf))) > 0 ) {
-
					sbuf_bcat(*sbuf, buf, size);
-
				}
-
				sbuf_finish(*sbuf);
-
			}
-
		}
-

-
		for (i = 0; scripts[i].name != NULL; i++) {
-
			if (strcmp(fpath, scripts[i].name) == 0) {
-
				pkg_script_new(&script);
-
				script->type = scripts[i].type;
-
				script->data = sbuf_new_auto();
-
				while ((size = archive_read_data(*a, buf, sizeof(buf))) > 0 ) {
-
					sbuf_bcat(script->data, buf, size);
-
				}
-
				sbuf_finish(script->data);
-
				array_append(&pkg->scripts, script);
-
				break;
-
			}
-
		}
-
	}
+
	STAILQ_INSERT_TAIL(&pkg->deps, d, next);

-
	if (ret != ARCHIVE_OK && ret != ARCHIVE_EOF)
-
		retcode = pkg_error_set(EPKG_FATAL, "%s", archive_error_string(*a));
-

-
	if (ret == ARCHIVE_EOF)
-
		retcode = EPKG_END;
-

-
	cleanup:
-
	if (retcode != EPKG_OK && retcode != EPKG_END) {
-
		if (*a != NULL)
-
			archive_read_finish(*a);
-
		*a = NULL;
-
		*ae = NULL;
-
	}
-

-
	return (retcode);
+
	return (EPKG_OK);
}

int
-
pkg_new(struct pkg **pkg, pkg_t type)
+
pkg_addfile(struct pkg *pkg, const char *path, const char *sha256)
{
-
	if ((*pkg = calloc(1, sizeof(struct pkg))) == NULL)
-
		return(pkg_error_set(EPKG_FATAL, "%s", strerror(errno)));
+
	struct pkg_file *f;

-
	struct _fields {
-
		int id;
-
		int type;
-
		int optional;
-
	} fields[] = {
-
		{PKG_ORIGIN, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE|PKG_NOTFOUND, 0},
-
		{PKG_NAME, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE|PKG_NOTFOUND, 0},
-
		{PKG_VERSION, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE|PKG_NOTFOUND, 0},
-
		{PKG_COMMENT, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
-
		{PKG_DESC, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
-
		{PKG_MTREE, PKG_FILE|PKG_INSTALLED|PKG_UPGRADE, 1},
-
		{PKG_MESSAGE, PKG_FILE|PKG_INSTALLED|PKG_UPGRADE, 1},
-
		{PKG_ARCH, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
-
		{PKG_OSVERSION, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
-
		{PKG_MAINTAINER, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
-
		{PKG_WWW, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 1},
-
		{PKG_PREFIX, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
-
		{PKG_REPOPATH, PKG_REMOTE|PKG_UPGRADE, 0},
-
		{PKG_CKSUM, PKG_REMOTE|PKG_UPGRADE, 0},
-
		{PKG_NEWVERSION, PKG_UPGRADE, 0},
-
	};
-

-
	for (int i = 0; i < PKG_NUM_FIELDS; i++) {
-
		(*pkg)->fields[fields[i].id].type = fields[i].type;
-
		(*pkg)->fields[fields[i].id].optional = fields[i].optional;
-
	}
-

-
	(*pkg)->automatic = false;
-
	(*pkg)->type = type;
-

-
	return (EPKG_OK);
-
}
-

-
void
-
pkg_reset(struct pkg *pkg, pkg_t type)
-
{
	if (pkg == NULL)
-
		return;
-

-
	for (int i = 0; i < PKG_NUM_FIELDS; i++)
-
		sbuf_reset(pkg->fields[i].value);
-

-
	pkg->flatsize = 0;
-
	pkg->new_flatsize = 0;
-
	pkg->new_pkgsize = 0;
-
	pkg->flags = 0;
-
	pkg->rowid = 0;
-

-
	array_reset(&pkg->deps, &pkg_free_void);
-
	array_reset(&pkg->rdeps, &pkg_free_void);
-
	array_reset(&pkg->conflicts, &pkg_conflict_free_void);
-
	array_reset(&pkg->files, &free);
-
	array_reset(&pkg->dirs, &free);
-
	array_reset(&pkg->scripts, &pkg_script_free_void);
-
	array_reset(&pkg->options, &pkg_option_free_void);
+
		return (ERROR_BAD_ARG("pkg"));

-
	pkg->type = type;
-
}
+
	if (path == NULL || path[0] == '\0')
+
		return (ERROR_BAD_ARG("path"));

-
void
-
pkg_free(struct pkg *pkg)
-
{
-
	if (pkg == NULL)
-
		return;
+
	pkg_file_new(&f);

-
	for (int i = 0; i < PKG_NUM_FIELDS; i++)
-
		sbuf_free(pkg->fields[i].value);
+
	strlcpy(f->path, path, sizeof(f->path));

-
	array_free(&pkg->deps, &pkg_free_void);
-
	array_free(&pkg->rdeps, &pkg_free_void);
-
	array_free(&pkg->conflicts, &pkg_conflict_free_void);
-
	array_free(&pkg->files, &free);
-
	array_free(&pkg->dirs, &free);
-
	array_free(&pkg->scripts, &pkg_script_free_void);
-
	array_free(&pkg->options, &pkg_option_free_void);
+
	if (sha256 != NULL)
+
		strlcpy(f->sha256, sha256, sizeof(f->sha256));

-
	free(pkg);
-
}
+
	STAILQ_INSERT_TAIL(&pkg->files, f, next);

-
void
-
pkg_free_void(void *p)
-
{
-
	if (p != NULL)
-
		pkg_free((struct pkg*) p);
+
	return (EPKG_OK);
}

int
-
pkg_setflatsize(struct pkg *pkg, int64_t size)
+
pkg_adddir(struct pkg *pkg, const char *path)
{
+
	struct pkg_dir *d = NULL;
+

	if (pkg == NULL)
		return (ERROR_BAD_ARG("pkg"));

-
	if (size < 0)
-
		return (ERROR_BAD_ARG("size"));
+
	if (path == NULL || path[0] == '\0')
+
		return (ERROR_BAD_ARG("path"));
+

+
	while (pkg_dirs(pkg, &d) == EPKG_OK) {
+
		if (strcmp(path, pkg_dir_path(d)) == 0) {
+
			warnx("Duplicate directory listing: %s, ignoring", path);
+
			return (EPKG_OK);
+
		}
+
	}
+

+
	pkg_dir_new(&d);
+
	strlcpy(d->path, path, sizeof(d->path));
+

+
	STAILQ_INSERT_TAIL(&pkg->dirs, d, next);

-
	pkg->flatsize = size;
	return (EPKG_OK);
}

int
-
pkg_setnewflatsize(struct pkg *pkg, int64_t size)
+
pkg_addconflict(struct pkg *pkg, const char *glob)
{
+
	struct pkg_conflict *c;
+

	if (pkg == NULL)
		return (ERROR_BAD_ARG("pkg"));

-
	if (size <0)
-
		return (ERROR_BAD_ARG("size"));
+
	if (glob == NULL || glob[0] == '\0')
+
		return (ERROR_BAD_ARG("glob"));

-
	pkg->new_flatsize = size;
+
	pkg_conflict_new(&c);
+
	sbuf_set(&c->glob, glob);
+

+
	STAILQ_INSERT_TAIL(&pkg->conflicts, c, next);

	return (EPKG_OK);
}

int
-
pkg_setnewpkgsize(struct pkg *pkg, int64_t size)
+
pkg_addscript(struct pkg *pkg, const char *data, pkg_script_t type)
{
+
	struct pkg_script *s;
+

	if (pkg == NULL)
		return (ERROR_BAD_ARG("pkg"));

-
	if (size <0)
-
		return (ERROR_BAD_ARG("size"));
+
	pkg_script_new(&s);
+
	sbuf_set(&s->data, data);
+
	s->type = type;

-
	pkg->new_pkgsize = size;
+
	STAILQ_INSERT_TAIL(&pkg->scripts, s, next);

	return (EPKG_OK);
}

int
-
pkg_addscript(struct pkg *pkg, const char *path)
+
pkg_addscript_file(struct pkg *pkg, const char *path)
{
-
	struct pkg_script *script;
	char *filename;
-
	char *raw_script;
+
	char *data;
+
	pkg_script_t type;
	int ret = EPKG_OK;
	off_t sz = 0;

@@ -549,60 +531,53 @@ pkg_addscript(struct pkg *pkg, const char *path)
	if (path == NULL)
		return (ERROR_BAD_ARG("path"));

-
	if ((ret = file_to_buffer(path, &raw_script, &sz)) != EPKG_OK)
+
	if ((ret = file_to_buffer(path, &data, &sz)) != EPKG_OK)
		return (ret);

-
	pkg_script_new(&script);
-

-
	sbuf_set(&script->data, raw_script);
-

	filename = strrchr(path, '/');
	filename[0] = '\0';
	filename++;

	if (strcmp(filename, "pkg-pre-install") == 0 || 
			strcmp(filename, "+PRE_INSTALL") == 0) {
-
		script->type = PKG_SCRIPT_PRE_INSTALL;
+
		type = PKG_SCRIPT_PRE_INSTALL;
	} else if (strcmp(filename, "pkg-post-install") == 0 ||
			strcmp(filename, "+POST_INSTALL") == 0) {
-
		script->type = PKG_SCRIPT_POST_INSTALL;
+
		type = PKG_SCRIPT_POST_INSTALL;
	} else if (strcmp(filename, "pkg-install") == 0 ||
			strcmp(filename, "+INSTALL") == 0) {
-
		script->type = PKG_SCRIPT_INSTALL;
+
		type = PKG_SCRIPT_INSTALL;
	} else if (strcmp(filename, "pkg-pre-deinstall") == 0 ||
			strcmp(filename, "+PRE_DEINSTALL") == 0) {
-
		script->type = PKG_SCRIPT_PRE_DEINSTALL;
+
		type = PKG_SCRIPT_PRE_DEINSTALL;
	} else if (strcmp(filename, "pkg-post-deinstall") == 0 ||
			strcmp(filename, "+POST_DEINSTALL") == 0) {
-
		script->type = PKG_SCRIPT_POST_DEINSTALL;
+
		type = PKG_SCRIPT_POST_DEINSTALL;
	} else if (strcmp(filename, "pkg-deinstall") == 0 ||
			strcmp(filename, "+DEINSTALL") == 0) {
-
		script->type = PKG_SCRIPT_DEINSTALL;
+
		type = PKG_SCRIPT_DEINSTALL;
	} else if (strcmp(filename, "pkg-pre-upgrade") == 0 ||
			strcmp(filename, "+PRE_UPGRADE") == 0) {
-
		script->type = PKG_SCRIPT_PRE_UPGRADE;
+
		type = PKG_SCRIPT_PRE_UPGRADE;
	} else if (strcmp(filename, "pkg-post-upgrade") == 0 ||
			strcmp(filename, "+POST_UPGRADE") == 0) {
-
		script->type = PKG_SCRIPT_POST_UPGRADE;
+
		type = PKG_SCRIPT_POST_UPGRADE;
	} else if (strcmp(filename, "pkg-upgrade") == 0 ||
			strcmp(filename, "+UPGRADE") == 0) {
-
		script->type = PKG_SCRIPT_UPGRADE;
+
		type = PKG_SCRIPT_UPGRADE;
	} else {
		return (pkg_error_set(EPKG_FATAL, "unknown script"));
	}

-
	array_init(&pkg->scripts, 6);
-
	array_append(&pkg->scripts, script);
-

-
	return (EPKG_OK);
+
	ret = pkg_addscript(pkg, data, type);
+
	free(data);
+
	return (ret);
}

int
pkg_appendscript(struct pkg *pkg, const char *cmd, pkg_script_t type)
{
-
	int i;
-
	struct pkg_script **scripts;
-
	struct pkg_script *p_i_script = NULL;
+
	struct pkg_script *s = NULL;

	if (pkg == NULL)
		return (ERROR_BAD_ARG("pkg"));
@@ -610,176 +585,296 @@ pkg_appendscript(struct pkg *pkg, const char *cmd, pkg_script_t type)
	if (cmd == NULL || cmd[0] == '\0')
		return (ERROR_BAD_ARG("cmd"));

-
	if ((scripts = pkg_scripts(pkg)) != NULL) {
-
		for (i = 0; scripts[i] != NULL; i++) {
-
			if (pkg_script_type(scripts[i]) == type) {
-
				p_i_script = scripts[i];
-
				break;
-
			}
+
	while (pkg_scripts(pkg, &s) == EPKG_OK) {
+
		if (pkg_script_type(s) == type) {
+
			break;
		}
	}

-
	if (p_i_script != NULL) {
-
		sbuf_cat(p_i_script->data, cmd);
-
		sbuf_done(p_i_script->data);
+
	if (s != NULL) {
+
		sbuf_cat(s->data, cmd);
+
		sbuf_done(s->data);
		return (EPKG_OK);
	}

-
	pkg_script_new(&p_i_script);
-
	sbuf_set(&p_i_script->data, cmd);
+
	pkg_script_new(&s);
+
	sbuf_set(&s->data, cmd);

-
	p_i_script->type = type;
+
	s->type = type;

-
	array_init(&pkg->scripts, 6);
-
	array_append(&pkg->scripts, p_i_script);
+
	STAILQ_INSERT_TAIL(&pkg->scripts, s, next);

	return (EPKG_OK);
}

int
-
pkg_addoption(struct pkg *pkg, const char *opt, const char *value)
+
pkg_addoption(struct pkg *pkg, const char *key, const char *value)
{
-
	struct pkg_option *option;
+
	struct pkg_option *o;

	if (pkg == NULL)
		return (ERROR_BAD_ARG("pkg"));

-
	if (opt == NULL || opt[0] == '\0')
+
	if (key == NULL || key[0] == '\0')
		return (ERROR_BAD_ARG("opt"));

	if (value == NULL || value[0] == '\0')
		return (ERROR_BAD_ARG("value"));

-
	pkg_option_new(&option);
+
	pkg_option_new(&o);

-
	sbuf_set(&option->opt, opt);
-
	sbuf_set(&option->value, value);
+
	sbuf_set(&o->key, key);
+
	sbuf_set(&o->value, value);

-
	array_init(&pkg->options, 5);
-
	array_append(&pkg->options, option);
+
	STAILQ_INSERT_TAIL(&pkg->options, o, next);

	return (EPKG_OK);
}

-
int
-
pkg_adddep(struct pkg *pkg, const char *name, const char *origin, const char *version)
+
void
+
pkg_freedeps(struct pkg *pkg)
{
-
	struct pkg *dep;
+
	struct pkg_dep *d;

-
	if (pkg == NULL)
-
		return (ERROR_BAD_ARG("pkg"));
+
	while (!STAILQ_EMPTY(&pkg->deps)) {
+
		d = STAILQ_FIRST(&pkg->deps);
+
		STAILQ_REMOVE_HEAD(&pkg->deps, next);
+
		pkg_dep_free(d);
+
	}
+
}

-
	if (name == NULL || name[0] == '\0')
-
		return (ERROR_BAD_ARG("name"));
+
void
+
pkg_freerdeps(struct pkg *pkg)
+
{
+
	struct pkg_dep *d;

-
	if (origin == NULL || origin[0] == '\0')
-
		return (ERROR_BAD_ARG("origin"));
+
	while (!STAILQ_EMPTY(&pkg->rdeps)) {
+
		d = STAILQ_FIRST(&pkg->rdeps);
+
		STAILQ_REMOVE_HEAD(&pkg->rdeps, next);
+
		pkg_dep_free(d);
+
	}
+
}

-
	if (version == NULL || version[0] == '\0')
-
		return (ERROR_BAD_ARG("version"));
+
void
+
pkg_freefiles(struct pkg *pkg)
+
{
+
	struct pkg_file *f;

-
	pkg_new(&dep, PKG_NOTFOUND);
+
	while (!STAILQ_EMPTY(&pkg->files)) {
+
		f = STAILQ_FIRST(&pkg->files);
+
		STAILQ_REMOVE_HEAD(&pkg->files, next);
+
		pkg_file_free(f);
+
	}
+
}

-
	pkg_set(dep, PKG_NAME, name);
-
	pkg_set(dep, PKG_ORIGIN, origin);
-
	pkg_set(dep, PKG_VERSION, version);
+
void
+
pkg_freedirs(struct pkg *pkg)
+
{
+
	struct pkg_dir *d;

-
	array_init(&pkg->deps, 5);
-
	array_append(&pkg->deps, dep);
+
	while (!STAILQ_EMPTY(&pkg->dirs)) {
+
		d = STAILQ_FIRST(&pkg->dirs);
+
		STAILQ_REMOVE_HEAD(&pkg->dirs, next);
+
		pkg_dir_free(d);
+
	}
+
}

-
	return (EPKG_OK);
+
void
+
pkg_freeconflicts(struct pkg *pkg)
+
{
+
	struct pkg_conflict *c;
+

+
	while (!STAILQ_EMPTY(&pkg->conflicts)) {
+
		c = STAILQ_FIRST(&pkg->conflicts);
+
		STAILQ_REMOVE_HEAD(&pkg->conflicts, next);
+
		pkg_conflict_free(c);
+
	}
}

-
int
-
pkg_addfile(struct pkg *pkg, const char *path, const char *sha256)
+
void
+
pkg_freescripts(struct pkg *pkg)
{
-
	struct pkg_file *file;
+
	struct pkg_script *s;

-
	if (pkg == NULL)
-
		return (ERROR_BAD_ARG("pkg"));
+
	while (!STAILQ_EMPTY(&pkg->scripts)) {
+
		s = STAILQ_FIRST(&pkg->scripts);
+
		STAILQ_REMOVE_HEAD(&pkg->scripts, next);
+
		pkg_script_free(s);
+
	}
+
}

-
	if (path == NULL || path[0] == '\0')
-
		return (ERROR_BAD_ARG("path"));
+
void
+
pkg_freeoptions(struct pkg *pkg)
+
{
+
	struct pkg_option *o;

-
	pkg_file_new(&file);
+
	while (!STAILQ_EMPTY(&pkg->options)) {
+
		o = STAILQ_FIRST(&pkg->options);
+
		STAILQ_REMOVE_HEAD(&pkg->options, next);
+
		pkg_option_free(o);
+
	}
+
}

-
	strlcpy(file->path, path, sizeof(file->path));
+
int
+
pkg_open(struct pkg **pkg_p, const char *path)
+
{
+
	struct archive *a;
+
	struct archive_entry *ae;
+
	int ret;

-
	if (sha256 != NULL)
-
		strlcpy(file->sha256, sha256, sizeof(file->sha256));
+
	ret = pkg_open2(pkg_p, &a, &ae, path);

-
	array_init(&pkg->files, 10);
-
	array_append(&pkg->files, file);
+
	if (ret != EPKG_OK && ret != EPKG_END)
+
		return (EPKG_FATAL);
+

+
	archive_read_finish(a);

	return (EPKG_OK);
}

int
-
pkg_adddir(struct pkg *pkg, const char *path)
+
pkg_open2(struct pkg **pkg_p, struct archive **a, struct archive_entry **ae, const char *path)
{
-
	char **dirs;
+
	struct pkg *pkg;
+
	struct pkg_script *script;
+
	pkg_error_t retcode = EPKG_OK;
+
	int ret;
+
	int64_t size;
+
	char *manifest;
+
	const char *fpath;
+
	char buf[2048];
+
	struct sbuf **sbuf;
	int i;

-
	if (pkg == NULL)
-
		return (ERROR_BAD_ARG("pkg"));
+
	struct {
+
		const char *name;
+
		pkg_attr attr;
+
	} files[] = {
+
		{ "+DESC", PKG_DESC },
+
		{ "+MTREE_DIRS", PKG_MTREE },
+
		{ NULL, 0 }
+
	};
+
	struct {
+
		const char *name;
+
		pkg_script_t type;
+
	} scripts[] = {
+
		{ "+PRE_INSTALL", PKG_SCRIPT_PRE_INSTALL },
+
		{ "+POST_INSTALL", PKG_SCRIPT_POST_INSTALL },
+
		{ "+PRE_DEINSTALL", PKG_SCRIPT_PRE_DEINSTALL },
+
		{ "+POST_DEINSTALL", PKG_SCRIPT_POST_DEINSTALL },
+
		{ "+PRE_UPGRADE", PKG_SCRIPT_PRE_UPGRADE },
+
		{ "+POST_UPGRADE", PKG_SCRIPT_POST_UPGRADE },
+
		{ "+INSTALL", PKG_SCRIPT_INSTALL },
+
		{ "+DEINSTALL", PKG_SCRIPT_DEINSTALL },
+
		{ "+UPGRADE", PKG_SCRIPT_UPGRADE },
+
		{ NULL, 0 }
+
	};

-
	if (path == NULL || path[0] == '\0')
+
	if (path == NULL)
		return (ERROR_BAD_ARG("path"));

-
	array_init(&pkg->dirs, 10);
-
	dirs = (char **)pkg->dirs.data;
-
	for (i = 0; dirs[i] != NULL; i++) {
-
		if (strcmp(path, dirs[i]) == 0) {
-
			warnx("Duplicate directory listing: %s, ignoring", path);
-
			return (EPKG_OK);
-
		}
+
	*a = archive_read_new();
+
	archive_read_support_compression_all(*a);
+
	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));
+
		goto cleanup;
	}
-
	array_append(&pkg->dirs, strdup(path));

-
	return (EPKG_OK);
-
}
+
	if (*pkg_p == NULL)
+
		pkg_new(pkg_p, PKG_FILE);
+
	else
+
		pkg_reset(*pkg_p, PKG_FILE);

-
int
-
pkg_addconflict(struct pkg *pkg, const char *glob)
-
{
-
	struct pkg_conflict *conflict;
+
	pkg = *pkg_p;
+
	pkg->type = PKG_FILE;

-
	if (pkg == NULL)
-
		return (ERROR_BAD_ARG("pkg"));
+
	while ((ret = archive_read_next_header(*a, ae)) == ARCHIVE_OK) {
+
		fpath = archive_entry_pathname(*ae);

-
	if (glob == NULL || glob[0] == '\0')
-
		return (ERROR_BAD_ARG("glob"));
+
		if (fpath[0] != '+')
+
			break;
+

+
		if (strcmp(fpath, "+MANIFEST") == 0) {
+
			size = archive_entry_size(*ae);
+
			manifest = calloc(1, size + 1);
+
			archive_read_data(*a, manifest, size);
+
			ret = pkg_parse_manifest(pkg, manifest);
+
			free(manifest);
+
			if (ret != EPKG_OK) {
+
				retcode = EPKG_FATAL;
+
				goto cleanup;
+
			}
+
		}
+

+
		for (i = 0; files[i].name != NULL; i++) {
+
			if (strcmp(fpath, files[i].name) == 0) {
+
				sbuf = &pkg->fields[files[i].attr].value;
+
				if (*sbuf == NULL)
+
					*sbuf = sbuf_new_auto();
+
				else
+
					sbuf_reset(*sbuf);
+
				while ((size = archive_read_data(*a, buf, sizeof(buf))) > 0 ) {
+
					sbuf_bcat(*sbuf, buf, size);
+
				}
+
				sbuf_finish(*sbuf);
+
			}
+
		}

-
	pkg_conflict_new(&conflict);
-
	sbuf_set(&conflict->glob, glob);
+
		for (i = 0; scripts[i].name != NULL; i++) {
+
			if (strcmp(fpath, scripts[i].name) == 0) {
+
				pkg_script_new(&script);
+
				script->type = scripts[i].type;
+
				script->data = sbuf_new_auto();
+
				while ((size = archive_read_data(*a, buf, sizeof(buf))) > 0 ) {
+
					sbuf_bcat(script->data, buf, size);
+
				}
+
				sbuf_finish(script->data);

-
	array_init(&pkg->conflicts, 5);
-
	array_append(&pkg->conflicts, conflict);
+
				STAILQ_INSERT_TAIL(&pkg->scripts, script, next);
+
				break;
+
			}
+
		}
+
	}

-
	return (EPKG_OK);
+
	if (ret != ARCHIVE_OK && ret != ARCHIVE_EOF)
+
		retcode = pkg_error_set(EPKG_FATAL, "%s", archive_error_string(*a));
+

+
	if (ret == ARCHIVE_EOF)
+
		retcode = EPKG_END;
+

+
	cleanup:
+
	if (retcode != EPKG_OK && retcode != EPKG_END) {
+
		if (*a != NULL)
+
			archive_read_finish(*a);
+
		*a = NULL;
+
		*ae = NULL;
+
	}
+

+
	return (retcode);
}

int
pkg_copy_tree(struct pkg *pkg, const char *src, const char *dest)
{
	struct packing *pack;
-
	struct pkg_file **files;
+
	struct pkg_file *file = NULL;
	char spath[MAXPATHLEN];
	char dpath[MAXPATHLEN];
-
	int i;

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

-
	files = pkg_files(pkg);
-
	for (i = 0; files[i] != NULL; i++) {
-
		snprintf(spath, MAXPATHLEN, "%s%s", src, pkg_file_path(files[i]));
-
		snprintf(dpath, MAXPATHLEN, "%s%s", dest, pkg_file_path(files[i]));
+
	while (pkg_files(pkg, &file) == EPKG_OK) {
+
		snprintf(spath, MAXPATHLEN, "%s%s", src, pkg_file_path(file));
+
		snprintf(dpath, MAXPATHLEN, "%s%s", dest, pkg_file_path(file));
		printf("%s -> %s\n", spath, dpath);
		packing_append_file(pack, spath, dpath);
	}

	return (packing_finish(pack));
}
+

modified libpkg/pkg.h
@@ -5,9 +5,12 @@
#include <openssl/pem.h>

struct pkg;
+
struct pkg_dep;
struct pkg_file;
+
struct pkg_dir;
struct pkg_conflict;
struct pkg_script;
+
struct pkg_option;

struct pkgdb;
struct pkgdb_it;
@@ -69,14 +72,6 @@ typedef enum {
	 * A package to be upgraded.
	 */
	PKG_UPGRADE = 1 << 3,
-
	/**
-
	 * The pkg refers to a non installed package.
-
	 * @warning That means that the pkg contains only few attributes:
-
	 *   - origin
-
	 *   - name
-
	 *   - version
-
	 */
-
	PKG_NOTFOUND = 1 << 4,
} pkg_t;

/**
@@ -204,49 +199,56 @@ int64_t pkg_new_flatsize(struct pkg *);
 */
int64_t pkg_new_pkgsize(struct pkg *);

-
/**
-
 * @return NULL-terminated array of pkg.
-
 */
-
struct pkg ** pkg_deps(struct pkg *);

/**
-
 * Returns the reverse dependencies.
-
 * That is, the packages which require this package.
-
 * @return NULL-terminated array of pkg.
+
 * Iterates over the dependencies of the package.
+
 * @param dep Must be set to NULL for the first call.
+
 * @return An error code.
 */
-
struct pkg ** pkg_rdeps(struct pkg *);
+
int pkg_deps(struct pkg *, struct pkg_dep **dep);

/**
-
 * @return NULL-terminated array of pkg_file.
+
 * Iterates over the reverse dependencies of the package.
+
 * That is, the packages which require this package.
+
 * @param dep Must be set to NULL for the first call.
+
 * @return An error code.
 */
-
struct pkg_file ** pkg_files(struct pkg *);
+
int pkg_rdeps(struct pkg *, struct pkg_dep **dep);

/**
-
 * @return NULL-terminated array of C strings.
+
 * Iterates over the files of the package.
+
 * @param file Must be set to NULL for the first call.
+
 * @return An error code.
 */
-
const char ** pkg_dirs(struct pkg *pkg);
+
int pkg_files(struct pkg *, struct pkg_file **file);

/**
-
 * @return NULL-terminated array of pkg_conflict.
+
 * Iterates over the directories of the package.
+
 * @param Must be set to NULL for the first call.
+
 * @return An error code.
 */
-
struct pkg_conflict ** pkg_conflicts(struct pkg *);
+
int pkg_dirs(struct pkg *pkg, struct pkg_dir **dir);

/**
-
 * @return NULL-terminated array of pkg_script.
+
 * Iterates over the conflicts of the package.
+
 * @param conflict Must be set to NULL for the first call.
+
 * @return An error code.
 */
-
struct pkg_script ** pkg_scripts(struct pkg *);
+
int pkg_conflicts(struct pkg *, struct pkg_conflict **conflict);

/**
-
 * @return NULL-terminated array of pkg_option
+
 * Iterates over the scripts of the package.
+
 * @param script Must be set to NULL for the first call.
+
 * @return An error code.
 */
-
struct pkg_option ** pkg_options(struct pkg *);
+
int pkg_scripts(struct pkg *, struct pkg_script **script);

/**
-
 * Resolve the dependencies of the package.
-
 * Check if the dependencies are registered into the local database and set
-
 * their type to #PKG_INSTALLED or #PKG_NOTFOUND.
+
 * Iterates over the options of the package.
+
 * @param  option Must be set to NULL for the first call.
+
 * @return An error code.
 */
-
int pkg_resolvdeps(struct pkg *, struct pkgdb *db);
+
int pkg_options(struct pkg *, struct pkg_option **option);

/**
 * @todo Document
@@ -318,7 +320,13 @@ int pkg_addconflict(struct pkg *pkg, const char *glob);
 * @param path The path to the script on disk.
 @ @return An error code.
 */
-
int pkg_addscript(struct pkg *pkg, const char *path);
+
int pkg_addscript(struct pkg *pkg, const char *data, pkg_script_t type);
+

+
/**
+
 * Helper which call pkg_addscript() with the content of the file and
+
 * with the correct type.
+
 */
+
int pkg_addscript_file(struct pkg *pkg, const char *path);
int pkg_appendscript(struct pkg *pkg, const char *cmd, pkg_script_t type);

/**
@@ -343,30 +351,24 @@ int pkg_load_manifest_file(struct pkg *pkg, const char *fpath);
 */
int pkg_emit_manifest(struct pkg *pkg, char **buf);

+
const char *pkg_dep_origin(struct pkg_dep *dep);
+
const char *pkg_dep_name(struct pkg_dep *dep);
+
const char *pkg_dep_version(struct pkg_dep *dep);
+

/* pkg_file */
-
int pkg_file_new(struct pkg_file **);
-
void pkg_file_reset(struct pkg_file *);
-
void pkg_file_free(struct pkg_file *);
const char * pkg_file_path(struct pkg_file *);
const char * pkg_file_sha256(struct pkg_file *);

+
const char *pkg_dir_path(struct pkg_dir *);
+

/* pkg_conflict */
-
int pkg_conflict_new(struct pkg_conflict **);
-
void pkg_conflict_reset(struct pkg_conflict *);
-
void pkg_conflict_free(struct pkg_conflict *);
const char * pkg_conflict_glob(struct pkg_conflict *);

/* pkg_script */
-
int pkg_script_new(struct pkg_script **);
-
void pkg_script_reset(struct pkg_script *);
-
void pkg_script_free(struct pkg_script *);
const char *pkg_script_data(struct pkg_script *);
pkg_script_t pkg_script_type(struct pkg_script *);

/* pkg_option */
-
int pkg_option_new(struct pkg_option **);
-
void pkg_option_reset(struct pkg_option *);
-
void pkg_option_free(struct pkg_option *);
const char *pkg_option_opt(struct pkg_option *);
const char *pkg_option_value(struct pkg_option *);

modified libpkg/pkg_add.c
@@ -12,6 +12,26 @@
#include "pkg_private.h"

static int
+
dep_installed(struct pkg_dep *dep, struct pkgdb *db) {
+
	struct pkg *p = NULL;
+
	struct pkgdb_it *it;
+
	int ret;
+

+
	it = pkgdb_query(db, pkg_dep_origin(dep), MATCH_EXACT);
+

+
	if (pkgdb_it_next(it, &p, PKG_LOAD_BASIC) == EPKG_OK) {
+
		ret = EPKG_OK;
+
	} else {
+
		ret = EPKG_FATAL;
+
	}
+

+
	pkgdb_it_free(it);
+
	pkg_free(p);
+

+
	return (ret);
+
}
+

+
static int
do_extract(struct archive *a, struct archive_entry *ae)
{
	int retcode = EPKG_OK;
@@ -57,14 +77,13 @@ pkg_add(struct pkgdb *db, const char *path, struct pkg **pkg_p)
	struct pkgdb_it *it;
	struct pkg *p = NULL;
	struct pkg *pkg = NULL;
-
	struct pkg **deps;
+
	struct pkg_dep *dep = NULL;
	bool extract = true;
	char dpath[MAXPATHLEN];
	const char *basedir;
	const char *ext;
	int retcode = EPKG_OK;
	int ret;
-
	int i;

	if (path == NULL)
		return (ERROR_BAD_ARG("path"));
@@ -106,28 +125,21 @@ pkg_add(struct pkgdb *db, const char *path, struct pkg **pkg_p)
	/*
	 * Check for dependencies
	 */
-
	deps = pkg_deps(pkg);
+

	basedir = dirname(path);
	if ((ext = strrchr(path, '.')) == NULL) {
		retcode = pkg_error_set(EPKG_FATAL, "%s has no extension", path);
		goto cleanup;
	}
-
	pkg_resolvdeps(pkg, db);
-
	for (i = 0; deps[i] != NULL; i++) {
-
		if (pkg_type(deps[i]) == PKG_NOTFOUND) {
+

+
	while (pkg_deps(pkg, &dep) == EPKG_OK) {
+
		if (dep_installed(dep, db) != EPKG_OK) {
			snprintf(dpath, sizeof(dpath), "%s/%s-%s%s", basedir,
-
					 pkg_get(deps[i], PKG_NAME), pkg_get(deps[i], PKG_VERSION),
+
					 pkg_dep_name(dep), pkg_dep_version(dep),
					 ext);

			if (access(dpath, F_OK) == 0) {
-
				if (pkg_add(db, dpath, NULL) == EPKG_OK) {
-
					/*
-
					 * Recheck the deps because the last installed package may
-
					 * have installed our deps too.
-
					 * TODO: do not it database here.
-
					 */
-
					pkg_resolvdeps(pkg, db);
-
				} else {
+
				if (pkg_add(db, dpath, NULL) != EPKG_OK) {
					retcode = pkg_error_set(EPKG_FATAL, "error while "
											"installing %s (dependency): %s",
											dpath,
@@ -136,11 +148,10 @@ pkg_add(struct pkgdb *db, const char *path, struct pkg **pkg_p)
				}
			} else {
				retcode = pkg_error_set(EPKG_DEPENDENCY, "missing %s-%s dependency",
-
										pkg_get(deps[i], PKG_NAME),
-
										pkg_get(deps[i], PKG_VERSION));
+
										pkg_dep_name(dep),
+
										pkg_dep_version(dep));
				goto cleanup;
			}
-

		}
	}

added libpkg/pkg_attributes.c
@@ -0,0 +1,195 @@
+
#include <err.h>
+
#include <stdlib.h>
+

+
#include "pkg.h"
+
#include "pkg_private.h"
+

+
/*
+
 * Dep
+
 */
+
int
+
pkg_dep_new(struct pkg_dep **d)
+
{
+
	if ((*d = calloc(1, sizeof(struct pkg_dep))) == NULL)
+
		return (EPKG_FATAL);
+

+
	return (EPKG_OK);
+
}
+

+
void
+
pkg_dep_free(struct pkg_dep *d)
+
{
+
	sbuf_free(d->origin);
+
	sbuf_free(d->name);
+
	sbuf_free(d->version);
+
	free(d);
+
}
+

+
const char *
+
pkg_dep_origin(struct pkg_dep *d)
+
{
+
	return (sbuf_get(d->origin));
+
}
+

+
const char *
+
pkg_dep_name(struct pkg_dep *d)
+
{
+
	return (sbuf_get(d->name));
+
}
+

+
const char *
+
pkg_dep_version(struct pkg_dep *d)
+
{
+
	return (sbuf_get(d->version));
+
}
+

+
/*
+
 * File
+
 */
+

+
int
+
pkg_file_new(struct pkg_file **file)
+
{
+
	if ((*file = calloc(1, sizeof(struct pkg_file))) == NULL)
+
		return (EPKG_FATAL);
+

+
	return (EPKG_OK);
+
}
+

+
void
+
pkg_file_free(struct pkg_file *file)
+
{
+
	free(file);
+
}
+

+
const char *
+
pkg_file_path(struct pkg_file *file)
+
{
+
	return (file->path);
+
}
+

+
const char *
+
pkg_file_sha256(struct pkg_file *file)
+
{
+
	return (file->sha256);
+
}
+

+
/*
+
 * Dir
+
 */
+

+
int
+
pkg_dir_new(struct pkg_dir **d)
+
{
+
	if ((*d = calloc(1, sizeof(struct pkg_dir))) == NULL)
+
		return (EPKG_FATAL);
+

+
	return (EPKG_OK);
+
}
+

+
void
+
pkg_dir_free(struct pkg_dir *d)
+
{
+
	free(d);
+
}
+

+
const char *
+
pkg_dir_path(struct pkg_dir *d)
+
{
+
	return (d->path);
+
}
+

+
/*
+
 * Conflict
+
 */
+

+
int
+
pkg_conflict_new(struct pkg_conflict **c)
+
{
+
	if ((*c = calloc(1, sizeof(struct pkg_conflict))) == NULL)
+
		err(EXIT_FAILURE, "calloc()");
+

+
	return (0);
+
}
+

+
void
+
pkg_conflict_free(struct pkg_conflict *c)
+
{
+
	if (c == NULL)
+
		return;
+

+
	sbuf_free(c->glob);
+
	free(c);
+
}
+

+
const char *
+
pkg_conflict_glob(struct pkg_conflict *c)
+
{
+
	return (sbuf_get(c->glob));
+
}
+

+
/*
+
 * Script
+
 */
+

+
int
+
pkg_script_new(struct pkg_script **script)
+
{
+
	if ((*script = calloc(1, sizeof(struct pkg_script))) == NULL)
+
		err(EXIT_FAILURE, "calloc()");
+

+
	return (0);
+
}
+

+
void
+
pkg_script_free(struct pkg_script *script)
+
{
+
	if (script == NULL)
+
		return;
+

+
	sbuf_free(script->data);
+
	free(script);
+
}
+

+
const char *
+
pkg_script_data(struct pkg_script *s)
+
{
+
	return (sbuf_get(s->data));
+
}
+

+
pkg_script_t
+
pkg_script_type(struct pkg_script *s)
+
{
+
	return (s->type);
+
}
+

+
/*
+
 * Option
+
 */
+

+
int
+
pkg_option_new(struct pkg_option **option)
+
{
+
	if ((*option = calloc(1, sizeof(struct pkg_option))))
+
		return (-1);
+
	return (0);
+
}
+

+
void
+
pkg_option_free(struct pkg_option *option)
+
{
+
	sbuf_free(option->key);
+
	sbuf_free(option->value);
+
}
+

+
const char *
+
pkg_option_opt(struct pkg_option *option)
+
{
+
	return (sbuf_get(option->key));
+
}
+

+
const char *
+
pkg_option_value(struct pkg_option *option)
+
{
+
	return (sbuf_get(option->value));
+
}
deleted libpkg/pkg_conflict.c
@@ -1,43 +0,0 @@
-
#include <stdlib.h>
-
#include <err.h>
-

-
#include "pkg.h"
-
#include "pkg_private.h"
-

-
const char *
-
pkg_conflict_glob(struct pkg_conflict *c)
-
{
-
	return (sbuf_get(c->glob));
-
}
-

-
int
-
pkg_conflict_new(struct pkg_conflict **c)
-
{
-
	if ((*c = calloc(1, sizeof(struct pkg_conflict))) == NULL)
-
		err(EXIT_FAILURE, "calloc()");
-

-
	return (0);
-
}
-

-
void
-
pkg_conflict_reset(struct pkg_conflict *c)
-
{
-
	sbuf_reset(c->glob);
-
}
-

-
void
-
pkg_conflict_free(struct pkg_conflict *c)
-
{
-
	if (c == NULL)
-
		return;
-

-
	sbuf_free(c->glob);
-
	free(c);
-
}
-

-
void
-
pkg_conflict_free_void(void *c)
-
{
-
	if (c != NULL)
-
		pkg_conflict_free((struct pkg_conflict *)c);
-
}
modified libpkg/pkg_create.c
@@ -20,11 +20,10 @@ static int
pkg_create_from_dir(struct pkg *pkg, const char *root, struct packing *pkg_archive)
{
	char fpath[MAXPATHLEN];
-
	struct pkg_file **files;
-
	struct pkg_script **scripts;
+
	struct pkg_file *file = NULL;
+
	struct pkg_script *script = NULL;
	char *m;
	const char *mtree;
-
	int i;
	const char *scriptname = NULL;

	pkg_emit_manifest(pkg, &m);
@@ -37,52 +36,48 @@ pkg_create_from_dir(struct pkg *pkg, const char *root, struct packing *pkg_archi
	if (mtree != NULL)
		packing_append_buffer(pkg_archive, mtree, "+MTREE_DIRS", strlen(mtree));

-
	if ((scripts = pkg_scripts(pkg)) != NULL) {
-
		for (i = 0; scripts[i] != NULL; i++) {
-
			switch (pkg_script_type(scripts[i])) {
-
				case PKG_SCRIPT_PRE_INSTALL:
-
					scriptname = "+PRE_INSTALL";
-
					break;
-
				case PKG_SCRIPT_POST_INSTALL:
-
					scriptname = "+POST_INSTALL";
-
					break;
-
				case PKG_SCRIPT_INSTALL:
-
					scriptname = "+INSTALL";
-
					break;
-
				case PKG_SCRIPT_PRE_DEINSTALL:
-
					scriptname = "+PRE_DEINSTALL";
-
					break;
-
				case PKG_SCRIPT_POST_DEINSTALL:
-
					scriptname = "+POST_DEINSTALL";
-
					break;
-
				case PKG_SCRIPT_DEINSTALL:
-
					scriptname = "+DEINSTALL";
-
					break;
-
				case PKG_SCRIPT_PRE_UPGRADE:
-
					scriptname = "+PRE_UPGRADE";
-
					break;
-
				case PKG_SCRIPT_POST_UPGRADE:
-
					scriptname = "+POST_UPGRADE";
-
					break;
-
				case PKG_SCRIPT_UPGRADE:
-
					scriptname = "+UPGRADE";
-
					break;
-
			}
-
			packing_append_buffer(pkg_archive, pkg_script_data(scripts[i]),
-
								  scriptname, strlen(pkg_script_data(scripts[i])));
+
	while (pkg_scripts(pkg, &script) == EPKG_OK) {
+
		switch (pkg_script_type(script)) {
+
			case PKG_SCRIPT_PRE_INSTALL:
+
				scriptname = "+PRE_INSTALL";
+
				break;
+
			case PKG_SCRIPT_POST_INSTALL:
+
				scriptname = "+POST_INSTALL";
+
				break;
+
			case PKG_SCRIPT_INSTALL:
+
				scriptname = "+INSTALL";
+
				break;
+
			case PKG_SCRIPT_PRE_DEINSTALL:
+
				scriptname = "+PRE_DEINSTALL";
+
				break;
+
			case PKG_SCRIPT_POST_DEINSTALL:
+
				scriptname = "+POST_DEINSTALL";
+
				break;
+
			case PKG_SCRIPT_DEINSTALL:
+
				scriptname = "+DEINSTALL";
+
				break;
+
			case PKG_SCRIPT_PRE_UPGRADE:
+
				scriptname = "+PRE_UPGRADE";
+
				break;
+
			case PKG_SCRIPT_POST_UPGRADE:
+
				scriptname = "+POST_UPGRADE";
+
				break;
+
			case PKG_SCRIPT_UPGRADE:
+
				scriptname = "+UPGRADE";
+
				break;
		}
+
		packing_append_buffer(pkg_archive, pkg_script_data(script),
+
							  scriptname, strlen(pkg_script_data(script)));
	}

-
	if ((files = pkg_files(pkg)) != NULL) {
-
		for (i = 0; files[i] != NULL; i++) {
+
	while (pkg_files(pkg, &file) == EPKG_OK) {

-
			if (root != NULL)
-
				snprintf(fpath, sizeof(MAXPATHLEN), "%s%s", root, pkg_file_path(files[i]));
-
			else
-
				strlcpy(fpath, pkg_file_path(files[i]), MAXPATHLEN);
+
		if (root != NULL)
+
			snprintf(fpath, sizeof(MAXPATHLEN), "%s%s", root, pkg_file_path(file));
+
		else
+
			strlcpy(fpath, pkg_file_path(file), MAXPATHLEN);

-
			packing_append_file(pkg_archive, fpath, pkg_file_path(files[i]));
-
		}
+
		packing_append_file(pkg_archive, fpath, pkg_file_path(file));
	}

	return (EPKG_OK);
modified libpkg/pkg_create_repo.c
@@ -26,7 +26,7 @@ pkg_create_repo(char *path, void (progress)(struct pkg *pkg, void *data), void *

	struct stat st;
	struct pkg *pkg = NULL;
-
	struct pkg **deps;
+
	struct pkg_dep *dep = NULL;
	char *ext = NULL;
	sqlite3 *sqlite = NULL;
	sqlite3_stmt *stmt_deps = NULL;
@@ -35,9 +35,7 @@ pkg_create_repo(char *path, void (progress)(struct pkg *pkg, void *data), void *
	char *errmsg = NULL;
	int retcode = EPKG_OK;
	char *pkg_path;
-
	char sum[65];
-

-
	int i;
+
	char cksum[65];

	char *repopath[2];
	char repodb[MAXPATHLEN];
@@ -54,10 +52,9 @@ pkg_create_repo(char *path, void (progress)(struct pkg *pkg, void *data), void *
			"osversion TEXT,"
			"maintainer TEXT,"
			"www TEXT,"
-
			"pkg_format_version INTEGER,"
			"pkgsize INTEGER,"
			"flatsize INTEGER,"
-
			"sum TEXT,"
+
			"cksum TEXT,"
			"path TEXT NOT NULL" /* relative path to the package in the repository */
		");"
		"CREATE TABLE deps ("
@@ -72,10 +69,9 @@ pkg_create_repo(char *path, void (progress)(struct pkg *pkg, void *data), void *
	const char pkgsql[] = ""
		"INSERT INTO packages ("
				"origin, name, version, comment, desc, arch, osversion, "
-
				"maintainer, www, pkg_format_version, pkgsize, flatsize, "
-
				"sum, path"
+
				"maintainer, www, pkgsize, flatsize, cksum, path"
		")"
-
		"VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14);";
+
		"VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13);";
	const char depssql[] = ""
		"INSERT INTO deps (origin, name, version, package_id) "
		"VALUES (?1, ?2, ?3, ?4);";
@@ -124,7 +120,7 @@ pkg_create_repo(char *path, void (progress)(struct pkg *pkg, void *data), void *
	}

	while ((ent = fts_read(fts)) != NULL) {
-
		sum[0] = '\0';
+
		cksum[0] = '\0';
		/* skip everything that is not a file */
		if (ent->fts_info != FTS_F)
			continue;
@@ -166,11 +162,11 @@ pkg_create_repo(char *path, void (progress)(struct pkg *pkg, void *data), void *
		sqlite3_bind_text(stmt_pkg, 7, pkg_get(pkg, PKG_OSVERSION), -1, SQLITE_STATIC);
		sqlite3_bind_text(stmt_pkg, 8, pkg_get(pkg, PKG_MAINTAINER), -1, SQLITE_STATIC);
		sqlite3_bind_text(stmt_pkg, 9, pkg_get(pkg, PKG_WWW), -1, SQLITE_STATIC);
-
		sqlite3_bind_int64(stmt_pkg, 11, ent->fts_statp->st_size);
-
		sqlite3_bind_int64(stmt_pkg, 12, pkg_flatsize(pkg));
-
		sha256_file(ent->fts_accpath, sum);
-
		sqlite3_bind_text(stmt_pkg, 13, sum, -1, SQLITE_STATIC);
-
		sqlite3_bind_text(stmt_pkg, 14, pkg_path, -1, SQLITE_STATIC);
+
		sqlite3_bind_int64(stmt_pkg, 10, ent->fts_statp->st_size);
+
		sqlite3_bind_int64(stmt_pkg, 11, pkg_flatsize(pkg));
+
		sha256_file(ent->fts_accpath, cksum);
+
		sqlite3_bind_text(stmt_pkg, 12, cksum, -1, SQLITE_STATIC);
+
		sqlite3_bind_text(stmt_pkg, 13, pkg_path, -1, SQLITE_STATIC);

		if (sqlite3_step(stmt_pkg) != SQLITE_DONE) {
			retcode = ERROR_SQLITE(sqlite);
@@ -180,11 +176,10 @@ pkg_create_repo(char *path, void (progress)(struct pkg *pkg, void *data), void *

		package_id = sqlite3_last_insert_rowid(sqlite);

-
		deps = pkg_deps(pkg);
-
		for (i = 0; deps[i] != NULL; i++) {
-
			sqlite3_bind_text(stmt_deps, 1, pkg_get(deps[i], PKG_ORIGIN), -1, SQLITE_STATIC);
-
			sqlite3_bind_text(stmt_deps, 2, pkg_get(deps[i], PKG_NAME), -1, SQLITE_STATIC);
-
			sqlite3_bind_text(stmt_deps, 3, pkg_get(deps[i], PKG_VERSION), -1, SQLITE_STATIC);
+
		while (pkg_deps(pkg, &dep) == EPKG_OK) {
+
			sqlite3_bind_text(stmt_deps, 1, pkg_dep_origin(dep), -1, SQLITE_STATIC);
+
			sqlite3_bind_text(stmt_deps, 2, pkg_dep_name(dep), -1, SQLITE_STATIC);
+
			sqlite3_bind_text(stmt_deps, 3, pkg_dep_version(dep), -1, SQLITE_STATIC);
			sqlite3_bind_int64(stmt_deps, 4, package_id);

			if (sqlite3_step(stmt_deps) != SQLITE_DONE) {
@@ -195,7 +190,6 @@ pkg_create_repo(char *path, void (progress)(struct pkg *pkg, void *data), void *
		}

	}
-
		sum[0] = '\0';

	if (sqlite3_exec(sqlite, "COMMIT;", NULL, NULL, &errmsg) != SQLITE_OK)
		retcode = pkg_error_set(EPKG_FATAL, "%s", errmsg);
modified libpkg/pkg_delete.c
@@ -14,9 +14,9 @@
int
pkg_delete(struct pkg *pkg, struct pkgdb *db, int force)
{
-
	struct pkg **rdeps;
-
	int i, ret;
-
	struct sbuf *rdep_msg;
+
	struct pkg_dep *rdep = NULL;
+
	int ret;
+
	struct sbuf *rdep_msg = NULL;

	if (pkg == NULL)
		return (ERROR_BAD_ARG("pkg"));
@@ -38,15 +38,16 @@ pkg_delete(struct pkg *pkg, struct pkgdb *db, int force)
	if ((ret = pkgdb_loadmtree(db, pkg)) != EPKG_OK)
		return (ret);

-
	rdeps = pkg_rdeps(pkg);
-

-
	if (rdeps[0] != NULL) {
-
		rdep_msg = sbuf_new_auto();
-
		sbuf_printf(rdep_msg, "%s-%s is required by other packages:", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION));
-
		for (i = 0;rdeps[i] != NULL; i++) {
-
			sbuf_cat(rdep_msg, " ");
-
			sbuf_printf(rdep_msg, "%s-%s", pkg_get(rdeps[i], PKG_NAME), pkg_get(rdeps[i], PKG_VERSION));
+
	while (pkg_rdeps(pkg, &rdep) == EPKG_OK) {
+
		if (rdep_msg == NULL) {
+
			rdep_msg = sbuf_new_auto();
+
			sbuf_printf(rdep_msg, "%s-%s is required by other packages:", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION));
		}
+
		sbuf_cat(rdep_msg, " ");
+
		sbuf_printf(rdep_msg, "%s-%s", pkg_dep_name(rdep), pkg_dep_version(rdep));
+
	}
+
	/* If there are dependencies */
+
	if (rdep_msg != NULL) {
		if (!force) {
			sbuf_finish(rdep_msg);
			ret = pkg_error_set(EPKG_REQUIRED, "%s", sbuf_get(rdep_msg));
@@ -77,22 +78,20 @@ pkg_delete(struct pkg *pkg, struct pkgdb *db, int force)
int
pkg_delete_files(struct pkg *pkg, int force)
{
-
	int i;
-
	struct pkg_file **files;
+
	struct pkg_file *file = NULL;
	char sha256[65];
	const char *path;

-
	files = pkg_files(pkg);
-
	for (i = 0; files[i] != NULL; i++) {
-
		path = pkg_file_path(files[i]);
+
	while (pkg_files(pkg, &file) == EPKG_OK) {
+
		path = pkg_file_path(file);

		/* Regular files and links */
		/* check sha256 */
-
		if (!force && pkg_file_sha256(files[i])[0] != '\0') {
+
		if (!force && pkg_file_sha256(file)[0] != '\0') {
			if (sha256_file(path, sha256) == -1) {
				warnx("sha256 calculation failed for '%s'",
					  path);
-
			} else if (strcmp(sha256, pkg_file_sha256(files[i])) != 0) {
+
			} else if (strcmp(sha256, pkg_file_sha256(file)) != 0) {
				warnx("%s fails original SHA256 checksum, not removing", path);
				continue;
			}
@@ -110,13 +109,11 @@ pkg_delete_files(struct pkg *pkg, int force)
int
pkg_delete_dirs(struct pkg *pkg, int force)
{
-
	int i;
-
	const char **dirs;
+
	struct pkg_dir *dir = NULL;

-
	dirs = pkg_dirs(pkg);
-
	for (i = 0; dirs[i] != NULL; i++) {
-
		if (rmdir(dirs[i]) == -1 && errno != ENOTEMPTY && force != 1) {
-
			warn("rmdir(%s)", dirs[i]);
+
	while (pkg_dirs(pkg, &dir) == EPKG_OK) {
+
		if (rmdir(pkg_dir_path(dir)) == -1 && errno != ENOTEMPTY && force != 1) {
+
			warn("rmdir(%s)", pkg_dir_path(dir));
		}
	}

modified libpkg/pkg_elf.c
@@ -13,7 +13,7 @@
static int
analyse_elf(struct pkgdb *db, struct pkg *pkg, const char *fpath)
{
-
	struct pkg **deps;
+
	struct pkg_dep *dep = NULL;
	struct pkg *p = NULL;
	struct pkgdb_it *it = NULL;
	Elf *e;
@@ -28,7 +28,7 @@ analyse_elf(struct pkgdb *db, struct pkg *pkg, const char *fpath)
	char *name;
	bool found=false;

-
	int fd, i;
+
	int fd;

	if ((fd = open(fpath, O_RDONLY, 0)) < 0)
		return (EPKG_FATAL);
@@ -67,11 +67,9 @@ analyse_elf(struct pkgdb *db, struct pkg *pkg, const char *fpath)

			if (pkgdb_it_next(it, &p, PKG_LOAD_BASIC) == EPKG_OK) {
				found = false;
-
				if (( deps = pkg_deps(pkg) ) != NULL) {
-
					for (i = 0; deps[i]; i++) {
-
						if (strcmp(pkg_get(deps[i], PKG_ORIGIN), pkg_get(p, PKG_ORIGIN)) == 0)
-
							found = true;
-
					}
+
				while (pkg_deps(pkg, &dep) == EPKG_OK) {
+
					if (strcmp(pkg_dep_origin(dep), pkg_get(p, PKG_ORIGIN)) == 0)
+
						found = true;
				}
				if (!found) {
					warnx("adding forgotten depends (%s): %s-%s", map->l_name, pkg_get(p, PKG_NAME), pkg_get(p, PKG_VERSION));
@@ -92,15 +90,13 @@ analyse_elf(struct pkgdb *db, struct pkg *pkg, const char *fpath)
int
pkg_analyse_files(struct pkgdb *db, struct pkg *pkg)
{
-
	struct pkg_file **files;
-
	int i;
+
	struct pkg_file *file = NULL;

	if (elf_version(EV_CURRENT) == EV_NONE)
		return (EPKG_FATAL);

-
	if ((files = pkg_files(pkg)) != NULL)
-
		for (i = 0; files[i] != NULL ; i++)
-
			analyse_elf(db, pkg, pkg_file_path(files[i]));
+
	while (pkg_files(pkg, &file) == EPKG_OK)
+
		analyse_elf(db, pkg, pkg_file_path(file));

	return (EPKG_OK);
}
deleted libpkg/pkg_file.c
@@ -1,38 +0,0 @@
-
#include <stdlib.h>
-

-
#include "pkg.h"
-
#include "pkg_private.h"
-

-
const char *
-
pkg_file_path(struct pkg_file *file)
-
{
-
	return (file->path);
-
}
-

-
const char *
-
pkg_file_sha256(struct pkg_file *file)
-
{
-
	return (file->sha256);
-
}
-

-
int
-
pkg_file_new(struct pkg_file **file)
-
{
-
	if ((*file = calloc(1, sizeof(struct pkg_file))) == NULL)
-
		return (EPKG_FATAL);
-

-
	return (EPKG_OK);
-
}
-

-
void
-
pkg_file_reset(struct pkg_file *file)
-
{
-
	file->path[0] = '\0';
-
	file->sha256[0] = '\0';
-
}
-

-
void
-
pkg_file_free(struct pkg_file *file)
-
{
-
	free(file);
-
}
modified libpkg/pkg_manifest.c
@@ -314,12 +314,11 @@ int
pkg_emit_manifest(struct pkg *pkg, char **dest)
{
	struct sbuf *manifest;
-
	struct pkg **deps;
-
	struct pkg_conflict **conflicts;
-
	struct pkg_option **options;
-
	struct pkg_file **files;
-
	const char **dirs;
-
	int i;
+
	struct pkg_dep *dep = NULL;
+
	struct pkg_conflict *conflict = NULL;
+
	struct pkg_option *option = NULL;
+
	struct pkg_file *file = NULL;
+
	struct pkg_dir *dir = NULL;
	int len = 0;

	manifest = sbuf_new_auto();
@@ -347,34 +346,30 @@ pkg_emit_manifest(struct pkg *pkg, char **dest)
			pkg_flatsize(pkg)
			);

-
	deps = pkg_deps(pkg);
-
	for (i = 0; deps[i] != NULL; i++) {
+
	while (pkg_deps(pkg, &dep) == EPKG_OK) {
		sbuf_printf(manifest, "@dep %s %s %s\n",
-
					pkg_get(deps[i], PKG_NAME),
-
					pkg_get(deps[i], PKG_ORIGIN),
-
					pkg_get(deps[i], PKG_VERSION));
+
					pkg_dep_name(dep),
+
					pkg_dep_origin(dep),
+
					pkg_dep_version(dep));
	}

-
	conflicts = pkg_conflicts(pkg);
-
	for (i = 0; conflicts[i] != NULL; i++) {
-
		sbuf_printf(manifest, "@conflict %s\n", pkg_conflict_glob(conflicts[i]));
+

+
	while (pkg_conflicts(pkg, &conflict) == EPKG_OK) {
+
		sbuf_printf(manifest, "@conflict %s\n", pkg_conflict_glob(conflict));
	}

-
	options = pkg_options(pkg);
-
	for (i = 0; options[i] != NULL; i++) {
-
		sbuf_printf(manifest, "@option %s %s\n", pkg_option_opt(options[i]),
-
					pkg_option_value(options[i]));
+
	while (pkg_options(pkg, &option) == EPKG_OK) {
+
		sbuf_printf(manifest, "@option %s %s\n", pkg_option_opt(option),
+
					pkg_option_value(option));
	}

-
	files = pkg_files(pkg);
-
	for (i = 0; files[i] != NULL; i++) {
-
		sbuf_printf(manifest, "@file %s %s\n", pkg_file_path(files[i]),
-
					pkg_file_sha256(files[i]));
+
	while (pkg_files(pkg, &file) == EPKG_OK) {
+
		sbuf_printf(manifest, "@file %s %s\n", pkg_file_path(file),
+
					pkg_file_sha256(file));
	}

-
	dirs = pkg_dirs(pkg);
-
	for (i = 0; dirs[i] != NULL; i++) {
-
		sbuf_printf(manifest, "@dir %s\n", dirs[i]);
+
	while (pkg_dirs(pkg, &dir) == EPKG_OK) {
+
		sbuf_printf(manifest, "@dir %s\n", pkg_dir_path(dir));
	}

	sbuf_finish(manifest);
deleted libpkg/pkg_option.c
@@ -1,45 +0,0 @@
-
#include <stdlib.h>
-

-
#include "pkg.h"
-
#include "pkg_private.h"
-

-
const char *
-
pkg_option_opt(struct pkg_option *option)
-
{
-
	return (sbuf_get(option->opt));
-
}
-

-
const char *
-
pkg_option_value(struct pkg_option *option)
-
{
-
	return (sbuf_get(option->value));
-
}
-

-
int
-
pkg_option_new(struct pkg_option **option)
-
{
-
	if ((*option = calloc(1, sizeof(struct pkg_option))))
-
		return (-1);
-
	return (0);
-
}
-

-
void
-
pkg_option_reset(struct pkg_option *option)
-
{
-
	sbuf_reset(option->opt);
-
	sbuf_reset(option->value);
-
}
-

-
void
-
pkg_option_free(struct pkg_option *option)
-
{
-
	sbuf_free(option->opt);
-
	sbuf_free(option->value);
-
}
-

-
void
-
pkg_option_free_void(void *o)
-
{
-
	if (o != NULL)
-
		pkg_option_free((struct pkg_option *)o);
-
}
modified libpkg/pkg_private.h
@@ -2,8 +2,9 @@
#define _PKG_PRIVATE_H

#include <sys/param.h>
-
#include <sys/types.h>
+
#include <sys/queue.h>
#include <sys/sbuf.h>
+
#include <sys/types.h>
#include <stdbool.h>

#include <archive.h>
@@ -26,42 +27,79 @@ struct pkg {
	int64_t flatsize;
	int64_t new_flatsize;
	int64_t new_pkgsize;
-
	struct array deps;
-
	struct array rdeps;
-
	struct array conflicts;
-
	struct array files;
-
	struct array dirs;
-
	struct array scripts;
-
	struct array options;
+
	STAILQ_HEAD(deps, pkg_dep) deps;
+
	STAILQ_HEAD(rdeps, pkg_dep) rdeps;
+
	STAILQ_HEAD(files, pkg_file) files;
+
	STAILQ_HEAD(dirs, pkg_dir) dirs;
+
	STAILQ_HEAD(conflicts, pkg_conflict) conflicts;
+
	STAILQ_HEAD(scripts, pkg_script) scripts;
+
	STAILQ_HEAD(options, pkg_option) options;
	int flags;
	int64_t rowid;
	pkg_t type;
};

+
struct pkg_dep {
+
	struct sbuf *origin;
+
	struct sbuf *name;
+
	struct sbuf *version;
+
	STAILQ_ENTRY(pkg_dep) next;
+
};
+

+
struct pkg_file {
+
	char path[MAXPATHLEN];
+
	char sha256[65];
+
	STAILQ_ENTRY(pkg_file) next;
+
};
+

+
struct pkg_dir {
+
	char path[MAXPATHLEN];
+
	STAILQ_ENTRY(pkg_dir) next;
+
};
+

struct pkg_conflict {
	struct sbuf *glob;
+
	STAILQ_ENTRY(pkg_conflict) next;
};

struct pkg_script {
	struct sbuf *data;
	pkg_script_t type;
-
};
-

-
struct pkg_file {
-
	char path[MAXPATHLEN];
-
	char sha256[65];
+
	STAILQ_ENTRY(pkg_script) next;
};

struct pkg_option {
-
	struct sbuf *opt;
+
	struct sbuf *key;
	struct sbuf *value;
+
	STAILQ_ENTRY(pkg_option) next;
};

-
void pkg_conflict_free_void(void *);
-
void pkg_script_free_void(void *);
-
void pkg_option_free_void(void *);
-

int pkg_open2(struct pkg **p, struct archive **a, struct archive_entry **ae, const char *path);
+
void pkg_freedeps(struct pkg *pkg);
+
void pkg_freerdeps(struct pkg *pkg);
+
void pkg_freefiles(struct pkg *pkg);
+
void pkg_freedirs(struct pkg *pkg);
+
void pkg_freeconflicts(struct pkg *pkg);
+
void pkg_freescripts(struct pkg *pkg);
+
void pkg_freeoptions(struct pkg *pkg);
+

+
int pkg_dep_new(struct pkg_dep **);
+
void pkg_dep_free(struct pkg_dep *);
+

+
int pkg_file_new(struct pkg_file **);
+
void pkg_file_free(struct pkg_file *);
+

+
int pkg_dir_new(struct pkg_dir **);
+
void pkg_dir_free(struct pkg_dir *);
+

+
int pkg_conflict_new(struct pkg_conflict **);
+
void pkg_conflict_free(struct pkg_conflict *);
+

+
int pkg_script_new(struct pkg_script **);
+
void pkg_script_free(struct pkg_script *);
+

+
int pkg_option_new(struct pkg_option **);
+
void pkg_option_free(struct pkg_option *);

struct packing;

@@ -72,8 +110,6 @@ int packing_append_tree(struct packing *pack, const char *treepath, const char *
int packing_finish(struct packing *pack);
pkg_formats packing_format_from_string(const char *str);

-
void pkg_free_void(void *);
-

int pkg_delete_files(struct pkg *pkg, int force);
int pkg_delete_dirs(struct pkg *pkg, int force);

deleted libpkg/pkg_script.c
@@ -1,49 +0,0 @@
-
#include <stdlib.h>
-
#include <err.h>
-

-
#include "pkg.h"
-
#include "pkg_private.h"
-

-
const char *
-
pkg_script_data(struct pkg_script *s)
-
{
-
	return (sbuf_get(s->data));
-
}
-

-
pkg_script_t
-
pkg_script_type(struct pkg_script *s)
-
{
-
	return (s->type);
-
}
-

-
int
-
pkg_script_new(struct pkg_script **script)
-
{
-
	if ((*script = calloc(1, sizeof(struct pkg_script))) == NULL)
-
		err(EXIT_FAILURE, "calloc()");
-

-
	return (0);
-
}
-

-
void
-
pkg_script_reset(struct pkg_script *script)
-
{
-
	sbuf_reset(script->data);
-
}
-

-
void
-
pkg_script_free(struct pkg_script *script)
-
{
-
	if (script == NULL)
-
		return;
-

-
	sbuf_free(script->data);
-
	free(script);
-
}
-

-
void
-
pkg_script_free_void(void *s)
-
{
-
	if (s != NULL)
-
		pkg_script_free((struct pkg_script *)s);
-
}
modified libpkg/pkg_util.c
@@ -18,63 +18,6 @@
#include "pkg_error.h"
#include "pkg_util.h"

-
void
-
array_init(struct array *a, size_t c)
-
{
-
	assert(c > 0);
-

-
	/* if the array is already initialized, do nothing */
-
	if (a->cap > 0 && a->data != NULL)
-
		return;
-

-
	a->cap = c;
-
	a->len = 0;
-
	a->data = malloc(sizeof(void*) * a->cap);
-
	a->data[0] = NULL;
-
}
-

-
void
-
array_append(struct array *a, void *d)
-
{
-
	assert(a->cap > 0);
-
	assert(a->data != NULL);
-

-
	if (a->cap <= a->len + 1) {
-
		a->cap *= 2;
-
		a->data = realloc(a->data, sizeof(void*) * a->cap);
-
	}
-
	a->data[a->len] = d;
-
	a->data[a->len+1] = NULL;
-
	a->len++;
-
}
-

-
void
-
array_reset(struct array *a, void (*free_elm)(void*))
-
{
-
	if (a->data == NULL)
-
		return;
-

-
	if (free_elm != NULL)
-
		for (size_t i = 0; i < a->len; i++)
-
			free_elm(a->data[i]);
-

-
	a->len = 0;
-
	a->data[0] = NULL;
-
}
-

-
void
-
array_free(struct array *a, void (*free_elm)(void*))
-
{
-
	if (a->data == NULL)
-
		return;
-

-
	array_reset(a, free_elm);
-

-
	free(a->data);
-
	a->data = NULL;
-
	a->cap = 0;
-
}
-

int
sbuf_set(struct sbuf **buf, const char *str)
{
modified libpkg/pkg_util.h
@@ -15,11 +15,6 @@ struct array {

#define STARTS_WITH(string, needle) (strncasecmp(string, needle, strlen(needle)) == 0)

-
void array_init(struct array *, size_t);
-
void array_append(struct array *, void *);
-
void array_reset(struct array *, void (*free_elm)(void*));
-
void array_free(struct array *, void (*free_elm)(void*));
-

int sbuf_set(struct sbuf **, const char *);
const char * sbuf_get(struct sbuf *);
void sbuf_reset(struct sbuf *);
modified libpkg/pkgdb.c
@@ -162,7 +162,7 @@ pkgdb_init(sqlite3 *sdb)
		"VALUES (NEW.origin, NEW.name, NEW.version, NEW.comment, NEW.desc, "
		"(SELECT id FROM mtree WHERE content = NEW.mtree), "
		"NEW.message, NEW.arch, NEW.osversion, NEW.maintainer, NEW.www, NEW.prefix, "
-
		"NEW.flatsize NEW.automatic);"
+
		"NEW.flatsize, NEW.automatic);"
	"END;"
	"CREATE TABLE scripts ("
		"package_id INTEGER REFERENCES packages(id) ON DELETE CASCADE"
@@ -530,13 +530,9 @@ int
pkgdb_loaddeps(struct pkgdb *db, struct pkg *pkg)
{
	sqlite3_stmt *stmt;
-
	struct pkgdb_it it;
-
	struct pkg *p;
	int ret;
	const char sql[] = ""
-
	"SELECT p.rowid, p.origin, p.name, p.version, p.comment, p.desc, "
-
		"p.message, p.arch, p.osversion, p.maintainer, p.www, "
-
		"p.prefix, p.flatsize "
+
	"SELECT p.name, p.origin, p.version "
	"FROM packages AS p, deps AS d "
	"WHERE p.origin = d.origin "
		"AND d.package_id = ?1;";
@@ -547,27 +543,20 @@ pkgdb_loaddeps(struct pkgdb *db, struct pkg *pkg)
	if (pkg->flags & PKG_LOAD_DEPS)
		return (EPKG_OK);

-
	array_init(&pkg->deps, 10);
-

	if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK)
		return (ERROR_SQLITE(db->sqlite));

	sqlite3_bind_int64(stmt, 1, pkg->rowid);

-
	it.stmt = stmt;
-
	it.db = db;
-

-
	p = NULL;
-
	while ((ret = pkgdb_it_next(&it, &p, PKG_LOAD_BASIC)) == EPKG_OK) {
-
		array_append(&pkg->deps, p);
-
		p = NULL;
+
	while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) {
+
		pkg_adddep(pkg, sqlite3_column_text(stmt, 0), sqlite3_column_text(stmt, 1),
+
				   sqlite3_column_text(stmt, 2));
	}
-

	sqlite3_finalize(stmt);

-
	if (ret != EPKG_END) {
-
		array_reset(&pkg->deps, &pkg_free_void);
-
		return (ret);
+
	if (ret != SQLITE_DONE) {
+
		pkg_freedeps(pkg);
+
		return (ERROR_SQLITE(db->sqlite));
	}

	pkg->flags |= PKG_LOAD_DEPS;
@@ -578,13 +567,9 @@ int
pkgdb_loadrdeps(struct pkgdb *db, struct pkg *pkg)
{
	sqlite3_stmt *stmt;
-
	struct pkgdb_it it;
-
	struct pkg *p;
	int ret;
	const char sql[] = ""
-
		"SELECT p.rowid, p.origin, p.name, p.version, p.comment, p.desc, "
-
			"p.message, p.arch, p.osversion, p.maintainer, p.www, "
-
			"p.prefix, p.flatsize "
+
		"SELECT p.name, p.origin, p.version "
		"FROM packages AS p, deps AS d "
		"WHERE p.rowid = d.package_id "
			"AND d.origin = ?1;";
@@ -595,26 +580,20 @@ pkgdb_loadrdeps(struct pkgdb *db, struct pkg *pkg)
	if (pkg->flags & PKG_LOAD_RDEPS)
		return (EPKG_OK);

-
	array_init(&pkg->rdeps, 5);
-

	if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK)
		return (ERROR_SQLITE(db->sqlite));

	sqlite3_bind_text(stmt, 1, pkg_get(pkg, PKG_ORIGIN), -1, SQLITE_STATIC);

-
	it.stmt = stmt;
-
	it.db = db;
-

-
	p = NULL;
-
	while ((ret = pkgdb_it_next(&it, &p, PKG_LOAD_BASIC)) == EPKG_OK) {
-
		array_append(&pkg->rdeps, p);
-
		p = NULL;
+
	while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) {
+
		pkg_adddep(pkg, sqlite3_column_text(stmt, 0), sqlite3_column_text(stmt, 1),
+
				   sqlite3_column_text(stmt, 2));
	}
	sqlite3_finalize(stmt);

-
	if (ret != EPKG_END) {
-
		array_reset(&pkg->rdeps, &pkg_free_void);
-
		return (ret);
+
	if (ret != SQLITE_DONE) {
+
		pkg_freerdeps(pkg);
+
		return (ERROR_SQLITE(db->sqlite));
	}

	pkg->flags |= PKG_LOAD_RDEPS;
@@ -622,124 +601,107 @@ pkgdb_loadrdeps(struct pkgdb *db, struct pkg *pkg)
}

int
-
pkgdb_loadconflicts(struct pkgdb *db, struct pkg *pkg)
+
pkgdb_loadfiles(struct pkgdb *db, struct pkg *pkg)
{
	sqlite3_stmt *stmt;
-
	struct pkg_conflict *c;
	int ret;
	const char sql[] = ""
-
		"SELECT name "
-
		"FROM conflicts "
-
		"WHERE package_id = ?1;";
+
		"SELECT path, sha256 "
+
		"FROM files "
+
		"WHERE package_id = ?1 "
+
		"ORDER BY PATH ASC";

	if (pkg->type != PKG_INSTALLED)
		return (ERROR_BAD_ARG("pkg"));

-
	if (pkg->flags & PKG_LOAD_CONFLICTS)
+
	if (pkg->flags & PKG_LOAD_FILES)
		return (EPKG_OK);

-
	array_init(&pkg->conflicts, 5);
-

	if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK)
		return (ERROR_SQLITE(db->sqlite));

	sqlite3_bind_int64(stmt, 1, pkg->rowid);

	while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) {
-
		pkg_conflict_new(&c);
-
		sbuf_set(&c->glob, sqlite3_column_text(stmt, 0));
-
		array_append(&pkg->conflicts, c);
+
		pkg_addfile(pkg, sqlite3_column_text(stmt, 0), sqlite3_column_text(stmt, 1));
	}
	sqlite3_finalize(stmt);

	if (ret != SQLITE_DONE) {
-
		array_reset(&pkg->conflicts, &pkg_conflict_free_void);
+
		pkg_freefiles(pkg);
		return (ERROR_SQLITE(db->sqlite));
	}

-
	pkg->flags |= PKG_LOAD_CONFLICTS;
-

+
	pkg->flags |= PKG_LOAD_FILES;
	return (EPKG_OK);
}

int
-
pkgdb_loadfiles(struct pkgdb *db, struct pkg *pkg)
+
pkgdb_loaddirs(struct pkgdb *db, struct pkg *pkg)
{
	sqlite3_stmt *stmt;
-

-
	struct pkg_file *f;
	int ret;
	const char sql[] = ""
-
		"SELECT path, sha256 "
-
		"FROM files "
-
		"WHERE package_id = ?1 "
-
		"ORDER BY PATH ASC";
-

-
	if (pkg->type != PKG_INSTALLED)
-
		return (ERROR_BAD_ARG("pkg"));
+
		"SELECT path "
+
		"FROM pkg_dirs "
+
		"WHERE origin = ?1 "
+
		"ORDER by path DESC";

-
	if (pkg->flags & PKG_LOAD_FILES)
+
	if (pkg->flags & PKG_LOAD_DIRS)
		return (EPKG_OK);

-
	array_init(&pkg->files, 10);
-

	if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK)
		return (ERROR_SQLITE(db->sqlite));

-
	sqlite3_bind_int64(stmt, 1, pkg->rowid);
+
	sqlite3_bind_text(stmt, 1, pkg_get(pkg, PKG_ORIGIN), -1, SQLITE_STATIC);

	while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) {
-
		pkg_file_new(&f);
-
		strlcpy(f->path, sqlite3_column_text(stmt, 0), sizeof(f->path));
-
		strlcpy(f->sha256, sqlite3_column_text(stmt, 1), sizeof(f->sha256));
-
		array_append(&pkg->files, f);
+
		pkg_adddir(pkg, sqlite3_column_text(stmt, 0));
	}
	sqlite3_finalize(stmt);

	if (ret != SQLITE_DONE) {
-
		array_reset(&pkg->files, &free);
+
		pkg_freedirs(pkg);
		return (ERROR_SQLITE(db->sqlite));
	}

-
	pkg->flags |= PKG_LOAD_FILES;
+
	pkg->flags |= PKG_LOAD_DIRS;
	return (EPKG_OK);
}

int
-
pkgdb_loaddirs(struct pkgdb *db, struct pkg *pkg)
+
pkgdb_loadconflicts(struct pkgdb *db, struct pkg *pkg)
{
	sqlite3_stmt *stmt;
-
	char *path;
	int ret;
-

	const char sql[] = ""
-
		"SELECT path "
-
		"FROM pkg_dirs "
-
		"WHERE origin = ?1 "
-
		"ORDER by path DESC";
+
		"SELECT name "
+
		"FROM conflicts "
+
		"WHERE package_id = ?1;";

-
	if (pkg->flags & PKG_LOAD_DIRS)
+
	if (pkg->type != PKG_INSTALLED)
+
		return (ERROR_BAD_ARG("pkg"));
+

+
	if (pkg->flags & PKG_LOAD_CONFLICTS)
		return (EPKG_OK);

	if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK)
		return (ERROR_SQLITE(db->sqlite));

-
	array_init(&pkg->dirs, 5);
-

-
	sqlite3_bind_text(stmt, 1, pkg_get(pkg, PKG_ORIGIN), -1, SQLITE_STATIC);
+
	sqlite3_bind_int64(stmt, 1, pkg->rowid);

	while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) {
-
		path = strdup(sqlite3_column_text(stmt, 0));
-
		array_append(&pkg->dirs, path);
+
		pkg_addconflict(pkg, sqlite3_column_text(stmt, 0));
	}
	sqlite3_finalize(stmt);

	if (ret != SQLITE_DONE) {
-
		array_reset(&pkg->dirs, &free);
+
		pkg_freeconflicts(pkg);
		return (ERROR_SQLITE(db->sqlite));
	}

-
	pkg->flags |= PKG_LOAD_DIRS;
+
	pkg->flags |= PKG_LOAD_CONFLICTS;
+

	return (EPKG_OK);
}

@@ -747,7 +709,6 @@ int
pkgdb_loadscripts(struct pkgdb *db, struct pkg *pkg)
{
	sqlite3_stmt *stmt;
-
	struct pkg_script *s;
	int ret;
	const char sql[] = ""
		"SELECT script, type "
@@ -760,23 +721,18 @@ pkgdb_loadscripts(struct pkgdb *db, struct pkg *pkg)
	if (pkg->flags & PKG_LOAD_SCRIPTS)
		return (EPKG_OK);

-
	array_init(&pkg->scripts, 6);
-

	if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK)
		return (ERROR_SQLITE(db->sqlite));

	sqlite3_bind_int64(stmt, 1, pkg->rowid);

	while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) {
-
		pkg_script_new(&s);
-
		sbuf_set(&s->data, sqlite3_column_text(stmt, 0));
-
		s->type = sqlite3_column_int(stmt, 1);
-
		array_append(&pkg->scripts, s);
+
		pkg_addscript(pkg, sqlite3_column_text(stmt, 0), sqlite3_column_int(stmt, 1));
	}
	sqlite3_finalize(stmt);

	if (ret != SQLITE_DONE) {
-
		array_reset(&pkg->scripts, &pkg_script_free_void);
+
		pkg_freescripts(pkg);
		return (ERROR_SQLITE(db->sqlite));
	}

@@ -788,7 +744,6 @@ int
pkgdb_loadoptions(struct pkgdb *db, struct pkg *pkg)
{
	sqlite3_stmt *stmt;
-
	struct pkg_option *o;
	int ret;
	const char sql[] = ""
		"SELECT option, value "
@@ -801,23 +756,19 @@ pkgdb_loadoptions(struct pkgdb *db, struct pkg *pkg)
	if (pkg->flags & PKG_LOAD_OPTIONS)
		return (EPKG_OK);

-
	array_init(&pkg->options, 5);
-

	if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK)
		return (ERROR_SQLITE(db->sqlite));

	sqlite3_bind_int64(stmt, 1, pkg->rowid);

	while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) {
-
		pkg_option_new(&o);
-
		sbuf_set(&o->opt, sqlite3_column_text(stmt, 0));
-
		sbuf_set(&o->value, sqlite3_column_text(stmt, 1));
-
		array_append(&pkg->options, o);
+
		pkg_addoption(pkg, sqlite3_column_text(stmt, 0),
+
					  sqlite3_column_text(stmt, 1));
	}
	sqlite3_finalize(stmt);

	if (ret != SQLITE_DONE) {
-
		array_reset(&pkg->options, &pkg_option_free_void);
+
		pkg_freeoptions(pkg);
		return (ERROR_SQLITE(db->sqlite));
	}

@@ -877,12 +828,12 @@ pkgdb_has_flag(struct pkgdb *db, int flag)
int
pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
{
-
	struct pkg **deps;
-
	struct pkg_file **files;
-
	const char **dirs;
-
	struct pkg_conflict **conflicts;
-
	struct pkg_script **scripts;
-
	struct pkg_option **options;
+
	struct pkg_dep *dep = NULL;
+
	struct pkg_file *file = NULL;
+
	struct pkg_dir *dir = NULL;
+
	struct pkg_conflict *conflict = NULL;
+
	struct pkg_script *script = NULL;
+
	struct pkg_option *option = NULL;

	sqlite3 *s;
	sqlite3_stmt *stmt_pkg = NULL;
@@ -894,7 +845,6 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
	sqlite3_stmt *stmt_option = NULL;
	sqlite3_stmt *stmt_dirs = NULL;

-
	int i;
	int ret;
	int retcode = EPKG_OK;
	const char *path;
@@ -1002,17 +952,16 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
		goto cleanup;
	}

-
	deps = pkg_deps(pkg);
-
	for (i = 0; deps[i] != NULL; i++) {
-
		sqlite3_bind_text(stmt_dep, 1, pkg_get(deps[i], PKG_ORIGIN), -1, SQLITE_STATIC);
-
		sqlite3_bind_text(stmt_dep, 2, pkg_get(deps[i], PKG_NAME), -1, SQLITE_STATIC);
-
		sqlite3_bind_text(stmt_dep, 3, pkg_get(deps[i], PKG_VERSION), -1, SQLITE_STATIC);
+
	while (pkg_deps(pkg, &dep) == EPKG_OK) {
+
		sqlite3_bind_text(stmt_dep, 1, pkg_dep_origin(dep), -1, SQLITE_STATIC);
+
		sqlite3_bind_text(stmt_dep, 2, pkg_dep_name(dep), -1, SQLITE_STATIC);
+
		sqlite3_bind_text(stmt_dep, 3, pkg_dep_version(dep), -1, SQLITE_STATIC);
		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_get(deps[i], PKG_ORIGIN));
+
						"deps with %s", pkg_dep_origin(dep));
			else
				retcode = ERROR_SQLITE(s);
			goto cleanup;
@@ -1030,15 +979,14 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
		goto cleanup;
	}

-
	conflicts = pkg_conflicts(pkg);
-
	for (i = 0; conflicts[i] != NULL; i++) {
-
		sqlite3_bind_text(stmt_conflict, 1, pkg_conflict_glob(conflicts[i]), -1, SQLITE_STATIC);
+
	while (pkg_conflicts(pkg, &conflict) == EPKG_OK) {
+
		sqlite3_bind_text(stmt_conflict, 1, pkg_conflict_glob(conflict), -1, SQLITE_STATIC);
		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(conflicts[i]));
+
						"conflicts with %s", pkg_conflict_glob(conflict));
			else
				retcode = ERROR_SQLITE(s);
			goto cleanup;
@@ -1056,17 +1004,16 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
		goto cleanup;
	}

-
	files = pkg_files(pkg);
-
	for (i = 0; files[i] != NULL; i++) {
-
		path = pkg_file_path(files[i]);
-
		sqlite3_bind_text(stmt_file, 1, pkg_file_path(files[i]), -1, SQLITE_STATIC);
-
		sqlite3_bind_text(stmt_file, 2, pkg_file_sha256(files[i]), -1, SQLITE_STATIC);
+
	while (pkg_files(pkg, &file) == EPKG_OK) {
+
		path = pkg_file_path(file);
+
		sqlite3_bind_text(stmt_file, 1, pkg_file_path(file), -1, SQLITE_STATIC);
+
		sqlite3_bind_text(stmt_file, 2, pkg_file_sha256(file), -1, SQLITE_STATIC);
		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(files[i]));
+
						"path with %s", pkg_file_path(file));
			else
				retcode = ERROR_SQLITE(s);
			goto cleanup;
@@ -1083,15 +1030,14 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
		goto cleanup;
	}

-
	dirs = pkg_dirs(pkg);
-
	for (i = 0; dirs[i] != NULL; i++) {
+
	while (pkg_dirs(pkg, &dir) == EPKG_OK) {
		sqlite3_bind_text(stmt_dirs, 1, pkg_get(pkg, PKG_ORIGIN), -1, SQLITE_STATIC);
-
		sqlite3_bind_text(stmt_dirs, 2, dirs[i], -1, SQLITE_STATIC);
+
		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", dirs[i]);
+
						"dirs with %s", pkg_dir_path(dir));
			else
				retcode = ERROR_SQLITE(s);
			goto cleanup;
@@ -1108,16 +1054,15 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
		goto cleanup;
	}

-
	scripts = pkg_scripts(pkg);
-
	for (i = 0; scripts[i] != NULL; i++) {
-
		sqlite3_bind_text(stmt_script, 1, pkg_script_data(scripts[i]), -1, SQLITE_STATIC);
-
		sqlite3_bind_int(stmt_script, 2, pkg_script_type(scripts[i]));
+
	while (pkg_scripts(pkg, &script) == EPKG_OK) {
+
		sqlite3_bind_text(stmt_script, 1, pkg_script_data(script), -1, SQLITE_STATIC);
+
		sqlite3_bind_int(stmt_script, 2, pkg_script_type(script));
		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(scripts[i]));
+
						"scripts with %s", pkg_script_data(script));
			else
				retcode = ERROR_SQLITE(s);
			goto cleanup;
@@ -1130,15 +1075,14 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
	 * Insert options
	 */

-
	options = pkg_options(pkg);
	if (sqlite3_prepare_v2(s, sql_option, -1, &stmt_option, NULL) != SQLITE_OK) {
		retcode = ERROR_SQLITE(s);
		goto cleanup;
	}

-
	for (i = 0; options[i] != NULL; i++) {
-
		sqlite3_bind_text(stmt_option, 1, pkg_option_opt(options[i]), -1, SQLITE_STATIC);
-
		sqlite3_bind_text(stmt_option, 2, pkg_option_value(options[i]), -1, SQLITE_STATIC);
+
	while (pkg_options(pkg, &option) == EPKG_OK) {
+
		sqlite3_bind_text(stmt_option, 1, pkg_option_opt(option), -1, SQLITE_STATIC);
+
		sqlite3_bind_text(stmt_option, 2, pkg_option_value(option), -1, SQLITE_STATIC);
		sqlite3_bind_int64(stmt_option, 3, package_id);

		if (sqlite3_step(stmt_option) != SQLITE_DONE) {
modified libpkg/scripts.c
@@ -5,20 +5,16 @@
int
pkg_script_pre_install(struct pkg *pkg)
{
-
	int i;
-
	struct pkg_script **scripts;
+
	struct pkg_script *script = NULL;
	struct sbuf *script_cmd = sbuf_new_auto();

-
	if ((scripts = pkg_scripts(pkg)) == NULL)
-
		return (EPKG_OK);
-

-
	for (i = 0; scripts[i] != NULL; i++) {
-
		switch (pkg_script_type(scripts[i])) {
+
	while (pkg_scripts(pkg, &script) == EPKG_OK) {
+
		switch (pkg_script_type(script)) {
			case PKG_SCRIPT_INSTALL:
				sbuf_reset(script_cmd);
				sbuf_printf(script_cmd, "PKG_PREFIX=%s\nset -- %s-%s PRE-INSTALL\n%s",
					pkg_get(pkg, PKG_PREFIX), pkg_get(pkg, PKG_NAME),
-
					pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
					pkg_get(pkg, PKG_VERSION), pkg_script_data(script));
				sbuf_finish(script_cmd);
				system(sbuf_data(script_cmd));
				break;
@@ -26,7 +22,7 @@ pkg_script_pre_install(struct pkg *pkg)
				sbuf_reset(script_cmd);
				sbuf_printf(script_cmd, "PKG_PREFIX=%s\nset -- %s-%s\n%s",
				  pkg_get(pkg, PKG_PREFIX), pkg_get(pkg, PKG_NAME),
-
				  pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
				  pkg_get(pkg, PKG_VERSION), pkg_script_data(script));
				sbuf_finish(script_cmd);
				system(sbuf_data(script_cmd));
				break;
@@ -44,20 +40,16 @@ pkg_script_pre_install(struct pkg *pkg)
int
pkg_script_post_install(struct pkg *pkg)
{
-
	int i;
-
	struct pkg_script **scripts;
+
	struct pkg_script *script = NULL;
	struct sbuf *script_cmd = sbuf_new_auto();

-
	if ((scripts = pkg_scripts(pkg)) == NULL)
-
		return (EPKG_OK);
-

-
	for (i = 0; scripts[i] != NULL; i++) {
-
		switch (pkg_script_type(scripts[i])) {
+
	while (pkg_scripts(pkg, &script) == EPKG_OK) {
+
		switch (pkg_script_type(script)) {
			case PKG_SCRIPT_INSTALL:
				sbuf_reset(script_cmd);
				sbuf_printf(script_cmd, "PKG_PREFIX=%s\nset -- %s-%s POST-INSTALL\n%s",
				  pkg_get(pkg, PKG_PREFIX), pkg_get(pkg, PKG_NAME),
-
				  pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
				  pkg_get(pkg, PKG_VERSION), pkg_script_data(script));
				sbuf_finish(script_cmd);
				system(sbuf_data(script_cmd));
				break;
@@ -65,7 +57,7 @@ pkg_script_post_install(struct pkg *pkg)
				sbuf_reset(script_cmd);
				sbuf_printf(script_cmd, "PKG_PREFIX=%s\nset -- %s-%s\n%s",
				  pkg_get(pkg, PKG_PREFIX), pkg_get(pkg, PKG_NAME),
-
				  pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
				  pkg_get(pkg, PKG_VERSION), pkg_script_data(script));
				sbuf_finish(script_cmd);
				system(sbuf_data(script_cmd));
				break;
@@ -83,20 +75,16 @@ pkg_script_post_install(struct pkg *pkg)
int
pkg_script_pre_upgrade(struct pkg *pkg)
{
-
	int i;
-
	struct pkg_script **scripts;
+
	struct pkg_script *script = NULL;
	struct sbuf *script_cmd = sbuf_new_auto();

-
	if ((scripts = pkg_scripts(pkg)) == NULL)
-
		return (EPKG_OK);
-

-
	for (i = 0; scripts[i] != NULL; i++) {
-
		switch (pkg_script_type(scripts[i])) {
+
	while (pkg_scripts(pkg, &script) == EPKG_OK) {
+
		switch (pkg_script_type(script)) {
			case PKG_SCRIPT_UPGRADE:
				sbuf_reset(script_cmd);
				sbuf_printf(script_cmd, "PKG_PREFIX=%s\nset -- %s-%s PRE-UPGRADE\n%s",
				  pkg_get(pkg, PKG_PREFIX), pkg_get(pkg, PKG_NAME),
-
				  pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
				  pkg_get(pkg, PKG_VERSION), pkg_script_data(script));
				sbuf_finish(script_cmd);
				system(sbuf_data(script_cmd));
				break;
@@ -104,7 +92,7 @@ pkg_script_pre_upgrade(struct pkg *pkg)
				sbuf_reset(script_cmd);
				sbuf_printf(script_cmd, "PKG_PREFIX=%s\nset -- %s-%s\n%s",
				  pkg_get(pkg, PKG_PREFIX), pkg_get(pkg, PKG_NAME),
-
				  pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
				  pkg_get(pkg, PKG_VERSION), pkg_script_data(script));
				sbuf_finish(script_cmd);
				system(sbuf_data(script_cmd));
				break;
@@ -122,20 +110,16 @@ pkg_script_pre_upgrade(struct pkg *pkg)
int
pkg_script_post_upgrade(struct pkg *pkg)
{
-
	int i;
-
	struct pkg_script **scripts;
+
	struct pkg_script *script = NULL;
	struct sbuf *script_cmd = sbuf_new_auto();

-
	if ((scripts = pkg_scripts(pkg)) == NULL)
-
		return (EPKG_OK);
-

-
	for (i = 0; scripts[i] != NULL; i++) {
-
		switch (pkg_script_type(scripts[i])) {
+
	while (pkg_scripts(pkg, &script) == EPKG_OK) {
+
		switch (pkg_script_type(script)) {
			case PKG_SCRIPT_UPGRADE:
				sbuf_reset(script_cmd);
				sbuf_printf(script_cmd, "PKG_PREFIX=%s\nset -- %s-%s POST-UPGRADE\n%s",
				  pkg_get(pkg, PKG_PREFIX), pkg_get(pkg, PKG_NAME),
-
				  pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
				  pkg_get(pkg, PKG_VERSION), pkg_script_data(script));
				sbuf_finish(script_cmd);
				system(sbuf_data(script_cmd));
				break;
@@ -143,7 +127,7 @@ pkg_script_post_upgrade(struct pkg *pkg)
				sbuf_reset(script_cmd);
				sbuf_printf(script_cmd, "PKG_PREFIX=%s\nset -- %s-%s\n%s",
				  pkg_get(pkg, PKG_PREFIX), pkg_get(pkg, PKG_NAME),
-
				  pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
				  pkg_get(pkg, PKG_VERSION), pkg_script_data(script));
				sbuf_finish(script_cmd);
				system(sbuf_data(script_cmd));
				break;
@@ -161,20 +145,16 @@ pkg_script_post_upgrade(struct pkg *pkg)
int
pkg_script_pre_deinstall(struct pkg *pkg)
{
-
	int i;
-
	struct pkg_script **scripts;
+
	struct pkg_script *script = NULL;
	struct sbuf *script_cmd = sbuf_new_auto();

-
	if ((scripts = pkg_scripts(pkg)) == NULL)
-
		return (EPKG_OK);
-

-
	for (i = 0; scripts[i] != NULL; i++) {
-
		switch (pkg_script_type(scripts[i])) {
+
	while (pkg_scripts(pkg, &script) == EPKG_OK) {
+
		switch (pkg_script_type(script)) {
			case PKG_SCRIPT_DEINSTALL:
				sbuf_reset(script_cmd);
				sbuf_printf(script_cmd, "PKG_PREFIX=%s\nset -- %s-%s DEINSTALL\n%s",
				  pkg_get(pkg, PKG_PREFIX), pkg_get(pkg, PKG_NAME),
-
				  pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
				  pkg_get(pkg, PKG_VERSION), pkg_script_data(script));
				sbuf_finish(script_cmd);
				system(sbuf_data(script_cmd));
				break;
@@ -182,7 +162,7 @@ pkg_script_pre_deinstall(struct pkg *pkg)
				sbuf_reset(script_cmd);
				sbuf_printf(script_cmd, "PKG_PREFIX=%s\nset -- %s-%s\n%s",
				  pkg_get(pkg, PKG_PREFIX), pkg_get(pkg, PKG_NAME),
-
				  pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
				  pkg_get(pkg, PKG_VERSION), pkg_script_data(script));
				sbuf_finish(script_cmd);
				system(sbuf_data(script_cmd));
				break;
@@ -200,31 +180,27 @@ pkg_script_pre_deinstall(struct pkg *pkg)
int
pkg_script_post_deinstall(struct pkg *pkg)
{
-
	int i;
-
	struct pkg_script **scripts;
+
	struct pkg_script *script = NULL;
	struct sbuf *script_cmd = sbuf_new_auto();

-
	if ((scripts = pkg_scripts(pkg)) == NULL)
-
		return (EPKG_OK);
-

	/* two loops because the order matters */
-
	for (i = 0; scripts[i] != NULL; i++) {
-
		if (pkg_script_type(scripts[i]) == PKG_SCRIPT_DEINSTALL) {
+
	while (pkg_scripts(pkg, &script) == EPKG_OK) {
+
		if (pkg_script_type(script) == PKG_SCRIPT_DEINSTALL) {
			sbuf_reset(script_cmd);
			sbuf_printf(script_cmd, "PKG_PREFIX=%s\nset -- %s-%s POST-DEINSTALL\n%s",
					pkg_get(pkg, PKG_PREFIX), pkg_get(pkg, PKG_NAME),
-
					pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
					pkg_get(pkg, PKG_VERSION), pkg_script_data(script));
			sbuf_finish(script_cmd);
			system(sbuf_data(script_cmd));
		}
	}

-
	for (i = 0; scripts[i] != NULL; i++) {
-
		if (pkg_script_type(scripts[i]) == PKG_SCRIPT_POST_DEINSTALL) {
+
	while (pkg_scripts(pkg, &script) == EPKG_OK) {
+
		if (pkg_script_type(script) == PKG_SCRIPT_POST_DEINSTALL) {
			sbuf_reset(script_cmd);
			sbuf_printf(script_cmd, "PKG_PREFIX=%s\nset -- %s-%s\n%s",
					pkg_get(pkg, PKG_PREFIX), pkg_get(pkg, PKG_NAME),
-
					pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
					pkg_get(pkg, PKG_VERSION), pkg_script_data(script));
			sbuf_finish(script_cmd);
			system(sbuf_data(script_cmd));
		}
modified pkg/autoremove.c
@@ -14,6 +14,25 @@

#include "autoremove.h"

+
static int
+
query_yesno(const char *msg)
+
{
+
	int c, r = 0;
+

+
	printf(msg);
+

+
	c = getchar();
+
	if (c == 'y' || c == 'Y')
+
		r = 1;
+
	else if (c == '\n' || c == EOF)
+
		return 0;
+

+
	while((c = getchar()) != '\n' && c != EOF)
+
		continue;
+

+
	return r;
+
}
+

void
usage_autoremove(void)
{
@@ -70,7 +89,24 @@ exec_autoremove(int argc, char **argv)
		printf("the autoremove will require %s more space\n", size);
	}

+
	if (query_yesno("Proceed (y|N): ")) {
+
		it = pkgdb_query_autoremove(db);
+
		while ((retcode = pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC)) == EPKG_OK) {
+
			if (pkg_delete(pkg, db, 0) != EPKG_OK) {
+
				retcode++;
+
				pkg_error_warn("can not delete %s-%s", pkg_get(pkg, PKG_ORIGIN));
+
			}
+
		}
+

+
	} else {
+
		printf("Aborted");
+
	}
+

+
	if (pkgdb_compact(db) != EPKG_OK)
+
		pkg_error_warn("can not compact database");
+

	cleanup:
+
	pkg_free(pkg);
	
	if (db != NULL)
		pkgdb_close(db);
modified pkg/info.c
@@ -23,18 +23,16 @@ enum sign {
static int
print_info(struct pkg *pkg, unsigned int opt)
{
-
	struct pkg **deps;
-
	struct pkg_file **files;
+
	struct pkg_dep *dep = NULL;
+
	struct pkg_file *file = NULL;
	char size[7];
-
	int i;

	if (opt & INFO_PRINT_DEP) {
		if (!(opt & INFO_QUIET))
			printf("%s-%s depends on:\n", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION));

-
		deps = pkg_deps(pkg);
-
		for (i = 0; deps[i] != NULL; i++) {
-
			printf("%s-%s\n", pkg_get(deps[i], PKG_NAME), pkg_get(deps[i], PKG_VERSION));
+
		while (pkg_deps(pkg, &dep) == EPKG_OK) {
+
			printf("%s-%s\n", pkg_dep_name(dep), pkg_dep_version(dep));
		}

		if (!(opt & INFO_QUIET))
@@ -43,9 +41,8 @@ print_info(struct pkg *pkg, unsigned int opt)
		if (!(opt & INFO_QUIET))
			printf("%s-%s is required by:\n", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION));

-
		deps = pkg_rdeps(pkg);
-
		for (i = 0; deps[i] != NULL; i++) {
-
			printf("%s-%s\n", pkg_get(deps[i], PKG_NAME), pkg_get(deps[i], PKG_VERSION));
+
		while (pkg_deps(pkg, &dep) == EPKG_OK) {
+
			printf("%s-%s\n", pkg_dep_name(dep), pkg_dep_version(dep));
		}

		if (!(opt & INFO_QUIET))
@@ -54,9 +51,8 @@ print_info(struct pkg *pkg, unsigned int opt)
		if (!(opt & INFO_QUIET))
			printf("%s-%s owns the following files:\n", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION));

-
		files = pkg_files(pkg);
-
		for (i = 0; files[i] != NULL; i++) {
-
			printf("%s\n", pkg_file_path(files[i]));
+
		while (pkg_files(pkg, &file) == EPKG_OK) {
+
			printf("%s\n", pkg_file_path(file));
		}

		if (!(opt & INFO_QUIET))
modified pkg/register.c
@@ -149,7 +149,7 @@ exec_register(int argc, char **argv)

	for (i = 0; scripts[i] != NULL; i++) {
		snprintf(fpath, MAXPATHLEN, "%s/%s", mdir, scripts[i]);
-
		if (access(fpath, F_OK) == 0 && pkg_addscript(pkg, fpath) != EPKG_OK)
+
		if (access(fpath, F_OK) == 0 && pkg_addscript_file(pkg, fpath) != EPKG_OK)
			pkg_error_warn("");
	}

modified tests/manifest.c
@@ -118,10 +118,10 @@ char wrong_manifest5[] = ""
START_TEST(parse_manifest)
{
	struct pkg *p = NULL;
-
	struct pkg **deps;
-
	struct pkg_conflict **conflicts;
-
	struct pkg_option **options;
-
	struct pkg_file **files;
+
	struct pkg_dep *dep = NULL;
+
	struct pkg_conflict *conflict = NULL;
+
	struct pkg_option *option = NULL;
+
	struct pkg_file *file = NULL;
	int i;

	fail_unless(pkg_new(&p, PKG_FILE) == EPKG_OK);
@@ -136,50 +136,49 @@ START_TEST(parse_manifest)
	fail_unless(strcmp(pkg_get(p, PKG_WWW), "http://www.foobar.com") == 0);
	fail_unless(strcmp(pkg_get(p, PKG_MAINTAINER), "test@pkgng.lan") == 0);

-
	deps = pkg_deps(p);
-
	fail_if(deps == NULL);
-
	for (i = 0; deps[i] != NULL; i++) {
+
	i = 0;
+
	while (pkg_deps(p, &dep) == EPKG_OK) {
		if (i == 0) {
-
			fail_unless(strcmp(pkg_get(deps[i], PKG_NAME), "depfoo") == 0);
-
			fail_unless(strcmp(pkg_get(deps[i], PKG_ORIGIN), "dep/foo") == 0);
-
			fail_unless(strcmp(pkg_get(deps[i], PKG_VERSION), "1.2") == 0);
+
			fail_unless(strcmp(pkg_dep_name(dep), "depfoo") == 0);
+
			fail_unless(strcmp(pkg_dep_origin(dep), "dep/foo") == 0);
+
			fail_unless(strcmp(pkg_dep_version(dep), "1.2") == 0);
		} else if (i == 1) {
-
			fail_unless(strcmp(pkg_get(deps[i], PKG_NAME), "depbar") == 0);
-
			fail_unless(strcmp(pkg_get(deps[i], PKG_ORIGIN), "dep/bar") == 0);
-
			fail_unless(strcmp(pkg_get(deps[i], PKG_VERSION), "3.4") == 0);
+
			fail_unless(strcmp(pkg_dep_name(dep), "depbar") == 0);
+
			fail_unless(strcmp(pkg_dep_origin(dep), "dep/bar") == 0);
+
			fail_unless(strcmp(pkg_dep_version(dep), "3.4") == 0);
		}
+
		i++;
	}
	fail_unless(i == 2);

-
	conflicts = pkg_conflicts(p);
-
	fail_if(conflicts == NULL);
-
	for (i = 0; conflicts[i] != NULL; i++) {
+
	i = 0;
+
	while (pkg_conflicts(p, &conflict) == EPKG_OK) {
		if (i == 0) {
-
			fail_unless(strcmp(pkg_conflict_glob(conflicts[i]), "foo-*") == 0);
+
			fail_unless(strcmp(pkg_conflict_glob(conflict), "foo-*") == 0);
		} else if (i == 1) {
-
			fail_unless(strcmp(pkg_conflict_glob(conflicts[i]), "bar-*") == 0);
+
			fail_unless(strcmp(pkg_conflict_glob(conflict), "bar-*") == 0);
		}
+
		i++;
	}
	fail_unless(i == 2);

-
	options = pkg_options(p);
-
	fail_if(options == NULL);
-
	for (i = 0; options[i] != NULL; i++) {
+
	i = 0;
+
	while (pkg_options(p, &option) == EPKG_OK) {
		if (i == 0) {
-
			fail_unless(strcmp(pkg_option_opt(options[i]), "foo") == 0);
-
			fail_unless(strcmp(pkg_option_value(options[i]), "true") == 0);
+
			fail_unless(strcmp(pkg_option_opt(option), "foo") == 0);
+
			fail_unless(strcmp(pkg_option_value(option), "true") == 0);
		} else if (i == 1) {
-
			fail_unless(strcmp(pkg_option_opt(options[i]), "bar") == 0);
-
			fail_unless(strcmp(pkg_option_value(options[i]), "false") == 0);
+
			fail_unless(strcmp(pkg_option_opt(option), "bar") == 0);
+
			fail_unless(strcmp(pkg_option_value(option), "false") == 0);
		}
+
		i++;
	}
	fail_unless(i == 2);

-
	files = pkg_files(p);
-
	fail_if(files == NULL);
-
	fail_unless(strcmp(pkg_file_path(files[0]), "/usr/local/bin/foo") ==
+
	fail_unless(pkg_files(p, &file) == EPKG_OK);
+
	fail_unless(strcmp(pkg_file_path(file), "/usr/local/bin/foo") ==
				0);
-
	fail_unless(strcmp(pkg_file_sha256(files[0]),
+
	fail_unless(strcmp(pkg_file_sha256(file),
				"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b")
				== 0);

modified tests/pkg.c
@@ -9,13 +9,13 @@ START_TEST(pkg_null)
	fail_unless(pkg_set(p, PKG_NAME, "foobar") == EPKG_FATAL);
	fail_unless(pkg_type(p) == PKG_NONE);
	fail_unless(pkg_set_from_file(p, PKG_NAME, "path") == EPKG_FATAL);
-
	fail_unless(pkg_scripts(p) == NULL);
-
	fail_unless(pkg_deps(p) == NULL);
-
	fail_unless(pkg_options(p) == NULL);
-
	fail_unless(pkg_rdeps(p) == NULL);
-
	fail_unless(pkg_files(p) == NULL);
-
	fail_unless(pkg_conflicts(p) == NULL);
-
	fail_unless(pkg_addscript(p, "./bla") == EPKG_FATAL);
+
	fail_unless(pkg_scripts(p, NULL) == EPKG_FATAL);
+
	fail_unless(pkg_deps(p, NULL) == EPKG_FATAL);
+
	fail_unless(pkg_options(p, NULL) == EPKG_FATAL);
+
	fail_unless(pkg_rdeps(p, NULL) == EPKG_FATAL);
+
	fail_unless(pkg_files(p, NULL) == EPKG_FATAL);
+
	fail_unless(pkg_conflicts(p, NULL) == EPKG_FATAL);
+
	fail_unless(pkg_addscript_file(p, "./bla") == EPKG_FATAL);
	fail_unless(pkg_addoption(p, "foo", "bar") == EPKG_FATAL);
	fail_unless(pkg_adddep(p, "foo", "foo/bar", "123") == EPKG_FATAL);

@@ -24,8 +24,8 @@ START_TEST(pkg_null)
	fail_unless(pkg_set_from_file(p, PKG_NAME, NULL) == EPKG_FATAL);
	fail_unless(pkg_open(&p, NULL) == EPKG_FATAL);
	fail_unless(pkg_open(&p, "test") == EPKG_FATAL);
-
	fail_unless(pkg_addscript(p, NULL) == EPKG_FATAL);
-
	fail_unless(pkg_addscript(p, "./bla") == EPKG_FATAL);
+
	fail_unless(pkg_addscript_file(p, NULL) == EPKG_FATAL);
+
	fail_unless(pkg_addscript_file(p, "./bla") == EPKG_FATAL);
	fail_unless(pkg_addoption(p, NULL, "bar") == EPKG_FATAL);
	fail_unless(pkg_addoption(p, "foo", NULL) == EPKG_FATAL);
	fail_unless(pkg_adddep(p, NULL, "foo/bar", "123") == EPKG_FATAL);