Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Introduce new API \o/
jlaffaye committed 15 years ago
commit 4ee116d58059e607e3e58ecf7cdab1617a0eb1ca
parent dff127f
15 files changed +548 -250
modified libpkg/Makefile
@@ -9,7 +9,9 @@ SHLIB_MAJOR= 0
SRCS=		pkg.c \
		pkgdb.c \
		pkg_compat.c \
+
		pkg_conflict.c \
		pkg_create.c \
+
		pkg_file.c \
		pkg_manifest.c \
		util.c

@@ -19,7 +21,6 @@ CFLAGS+= -I${.CURDIR} \
		-I${.CURDIR}/../external/sqlite
LDADD+=		-L${.CURDIR}/../external/jansson \
		-L${.CURDIR}/../external/sqlite \
-
		-L${.CURDIR}/../external/tinycdb \
		-L/usr/local/lib \
		-ljansson \
		-lsqlite3 \
modified libpkg/pkg.c
@@ -5,8 +5,10 @@

#include "pkg.h"
#include "pkg_private.h"
-
#include "pkg_manifest.h"
#include "pkgdb.h"
+
#include "util.h"
+

+
static void pkg_free_void(void*);

const char *
pkg_name(struct pkg *pkg)
@@ -38,31 +40,28 @@ pkg_origin(struct pkg *pkg)
	return (pkg->origin);
}

-
int
-
pkg_dep(struct pkg *pkg, struct pkg *dep)
+
struct pkg **
+
pkg_deps(struct pkg *pkg)
{
-
	pkg_reset(dep);
-
	return (pkgdb_query_dep(pkg, dep));
+
	return ((struct pkg **)pkg->deps.data);
}

-
int
-
pkg_rdep(struct pkg *pkg, struct pkg *rdep)
+
struct pkg **
+
pkg_rdeps(struct pkg *pkg)
{
-
	pkg_reset(rdep);
-
	return (pkgdb_query_rdep(pkg, rdep));
+
	return ((struct pkg **)pkg->rdeps.data);
}

-
int
-
pkg_conflicts(struct pkg *pkg, struct pkg *conflict)
+
struct pkg_file **
+
pkg_files(struct pkg *pkg)
{
-
	pkg_reset(conflict);
-
	return (pkgdb_query_rdep(pkg, conflict));
+
	return ((struct pkg_file **)pkg->files.data);
}

-
int
-
pkg_files(struct pkg *pkg, const char **path, const char **md5)
+
struct pkg_conflict **
+
pkg_conflicts(struct pkg *pkg)
{
-
	return (pkgdb_query_files(pkg, path, md5));
+
	return ((struct pkg_conflict **)pkg->conflicts.data);
}

int
@@ -76,48 +75,42 @@ pkg_new(struct pkg **pkg)
void
pkg_reset(struct pkg *pkg)
{
-
	free(pkg->name);
-
	pkg->name = NULL;
-
	free(pkg->version);
-
	pkg->version = NULL;
-
	free(pkg->origin);
-
	pkg->origin = NULL;
-
	free(pkg->comment);
-
	pkg->comment = NULL;
+
	if (pkg == NULL)
+
		return;
+

+
	pkg->name[0] = '\0';
+
	pkg->version[0] = '\0';
+
	pkg->origin[0] = '\0';
+
	pkg->comment[0] = '\0';
+

	free(pkg->desc);
	pkg->desc = NULL;
-
	pkg->pdb = NULL;
-
	if (pkg->deps_stmt != NULL) {
-
		sqlite3_finalize(pkg->deps_stmt);
-
		pkg->deps_stmt = NULL;
-
	}
-
	if (pkg->rdeps_stmt != NULL) {
-
		sqlite3_finalize(pkg->rdeps_stmt);
-
		pkg->rdeps_stmt = NULL;
-
	}
-
	if (pkg->which_stmt != NULL) {
-
		sqlite3_finalize(pkg->which_stmt);
-
		pkg->which_stmt = NULL;
-
	}
-
	if (pkg->files_stmt != NULL) {
-
		sqlite3_finalize(pkg->files_stmt);
-
		pkg->files_stmt = NULL;
-
	}
-
	if (pkg->m != NULL) {
-
		pkg_manifest_free(pkg->m);
-
		pkg->m = NULL;
-
	}
+

+
	array_reset(&pkg->deps, &pkg_free_void);
+
	array_reset(&pkg->rdeps, &pkg_free_void);
+
	array_reset(&pkg->conflicts, &free);
+
	array_reset(&pkg->files, &free);
}

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

+
	free(pkg->desc);
+

+
	array_free(&pkg->deps, &pkg_free_void);
+
	array_free(&pkg->rdeps, &pkg_free_void);
+
	array_free(&pkg->conflicts, &free);
+
	array_free(&pkg->files, &free);
+

	free(pkg);
}

-
void
-
pkg_from_manifest(struct pkg *pkg, struct pkg_manifest *m)
+
static void
+
pkg_free_void(void *p)
{
-
	pkg->m = m;
+
	if (p != NULL)
+
		pkg_free((struct pkg*) p);
}
modified libpkg/pkg.h
@@ -2,7 +2,11 @@
#define _PKG_H

struct pkg;
+
struct pkg_file;
+
struct pkg_conflict;
+

struct pkgdb;
+
struct pkgdb_it;

typedef enum _match_t {
	MATCH_ALL,
@@ -21,19 +25,48 @@ const char *pkg_version(struct pkg *);
const char *pkg_comment(struct pkg *);
const char *pkg_desc(struct pkg *);
const char *pkg_origin(struct pkg *);
-
int pkg_dep(struct pkg *, struct pkg *);
-
int pkg_rdep(struct pkg *, struct pkg *);
-
int pkg_conflicts(struct pkg*, struct pkg*);
-
int pkg_files(struct pkg *, const char **, const char **);
+
struct pkg ** pkg_deps(struct pkg *);
+
struct pkg ** pkg_rdeps(struct pkg *);
+
struct pkg_file ** pkg_files(struct pkg *);
+
struct pkg_conflict ** pkg_conflicts(struct pkg *);
+

+
/* 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_md5(struct pkg_file *);
+

+
/* 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_origin(struct pkg_conflict *);
+
const char * pkg_conflict_version(struct pkg_conflict *);
+
const char * pkg_conflict_name(struct pkg_conflict *);

/* pkgdb */
int pkgdb_open(struct pkgdb **);
void pkgdb_close(struct pkgdb *);

-
int pkgdb_query_init(struct pkgdb *, const char *, match_t);
-
int pkgdb_query(struct pkgdb *, struct pkg *);
-
void pkgdb_query_free(struct pkgdb *);
-
int pkgdb_query_which(struct pkgdb *, const char *, struct pkg *);
+
struct pkgdb_it * pkgdb_query(struct pkgdb *, const char *, match_t);
+
struct pkgdb_it * pkgdb_query_which(struct pkgdb *, const char *);
+
struct pkgdb_it * pkgdb_query_dep(struct pkgdb *, const char *);
+
struct pkgdb_it * pkgdb_query_rdep(struct pkgdb *, const char *);
+
struct pkgdb_it * pkgdb_query_conflicts(struct pkgdb *, const char *);
+
struct pkgdb_it * pkgdb_query_files(struct pkgdb *, const char *);
+

+
#define PKG_BASIC 0
+
#define PKG_DEPS (1<<0)
+
#define PKG_RDEPS (1<<1)
+
#define PKG_CONFLICTS (1<<2)
+
#define PKG_FILES (1<<3)
+
#define PKG_ALL PKG_BASIC|PKG_DEPS|PKG_RDEPS|PKG_CONFLICTS|PKG_FILES
+

+
int pkgdb_it_next_pkg(struct pkgdb_it *, struct pkg **, int);
+
int pkgdb_it_next_conflict(struct pkgdb_it *, struct pkg_conflict **);
+
int pkgdb_it_next_file(struct pkgdb_it *, struct pkg_file **);
+
void pkgdb_it_free(struct pkgdb_it *);

const char *pkgdb_get_dir(void);
void pkgdb_warn(struct pkgdb *);
added libpkg/pkg_conflict.c
@@ -0,0 +1,44 @@
+
#include <stdlib.h>
+

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

+
const char *
+
pkg_conflict_origin(struct pkg_conflict *c)
+
{
+
	return (c->origin);
+
}
+

+
const char *
+
pkg_conflict_version(struct pkg_conflict *c)
+
{
+
	return (c->version);
+
}
+

+
const char *
+
pkg_conflict_name(struct pkg_conflict *c)
+
{
+
	return (c->name);
+
}
+

+
int
+
pkg_conflict_new(struct pkg_conflict **c)
+
{
+
	if ((*c = calloc(1, sizeof(struct pkg_conflict))))
+
		return (-1);
+
	return (0);
+
}
+

+
void
+
pkg_conflict_reset(struct pkg_conflict *c)
+
{
+
	c->origin[0] = '\0';
+
	c->version[0] = '\0';
+
	c->name[0] = '\0';
+
}
+

+
void
+
pkg_conflict_free(struct pkg_conflict *c)
+
{
+
	free(c);
+
}
modified libpkg/pkg_create.c
@@ -136,7 +136,6 @@ pkg_create(const char *mpath, pkg_formats format, const char *outdir, const char

	snprintf(namever, sizeof(namever), "%s-%s", pkg_manifest_value(m, "name"),
			 pkg_manifest_value(m, "version"));
-
	printf("Creating package %s/%s.%s\n", outdir, namever, ext);
	snprintf(archive_path, sizeof(archive_path), "%s/%s.%s", outdir, namever, ext);

	archive_write_set_format_pax_restricted(pkg_archive);
added libpkg/pkg_file.c
@@ -0,0 +1,37 @@
+
#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_md5(struct pkg_file *file)
+
{
+
	return (file->md5);
+
}
+

+
int
+
pkg_file_new(struct pkg_file **file)
+
{
+
	if ((*file = calloc(1, sizeof(struct pkg_file))))
+
		return (-1);
+
	return (0);
+
}
+

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

+
void
+
pkg_file_free(struct pkg_file *file)
+
{
+
	free(file);
+
}
modified libpkg/pkg_manifest.c
@@ -391,10 +391,9 @@ pkg_manifest_load_file(const char *path)
int
pkg_manifest_from_pkg(struct pkg *pkg, struct pkg_manifest **m)
{
-
	struct pkg *dep;
-
	const char *path;
-
	const char *md5;
-

+
	size_t i;
+
	struct pkg **deps;
+
	struct pkg_file **files;
	*m = pkg_manifest_new();

	pkg_manifest_add_value(*m, "name", pkg_name(pkg));
@@ -403,14 +402,23 @@ pkg_manifest_from_pkg(struct pkg *pkg, struct pkg_manifest **m)
	pkg_manifest_add_value(*m, "comment", pkg_comment(pkg));
	pkg_manifest_add_value(*m, "desc", pkg_desc(pkg));

-
	pkg_new(&dep);
-
	while (pkg_dep(pkg, dep) == 0) {
-
		pkg_manifest_add_dep(*m, pkg_name(dep), pkg_origin(dep), pkg_version(dep));
+
	deps = pkg_deps(pkg);
+
	if (deps == NULL) {
+
		warnx("Mising deps informations in pkg %s", pkg_origin(pkg));
+
		return (-1);
+
	}
+
	for (i = 0; deps[i] != NULL; i++) {
+
		pkg_manifest_add_dep(*m, pkg_name(deps[i]), pkg_origin(deps[i]),
+
							 pkg_version(deps[i]));
	}
-
	pkg_free(dep);

-
	while (pkg_files(pkg, &path, &md5) == 0) {
-
		pkg_manifest_add_file(*m, path, md5);
+
	files = pkg_files(pkg);
+
	if (files == NULL) {
+
		warnx("Missing files informations in pkg %s", pkg_origin(pkg));
+
		return (-1);
+
	}
+
	for (i = 0; files[i] != NULL; i++) {
+
		pkg_manifest_add_file(*m, pkg_file_path(files[i]), pkg_file_md5(files[i]));
	}

	/* TODO: conflicts, exec, unexec */
modified libpkg/pkg_private.h
@@ -1,21 +1,29 @@
#ifndef _PKG_PRIVATE_H
#define _PKG_PRIVATE_H

-
#include "pkg_manifest.h"
+
#include "util.h"

struct pkg {
-
	char *name;
-
	char *version;
-
	char *origin;
-
	char *comment;
+
	char name[100];
+
	char version[10];
+
	char origin[100];
+
	char comment[150];
	char *desc;
-
	struct pkgdb *pdb;
-
	sqlite3_stmt *deps_stmt;
-
	sqlite3_stmt *rdeps_stmt;
-
	sqlite3_stmt *conflicts_stmt;
-
	sqlite3_stmt *which_stmt;
-
	sqlite3_stmt *files_stmt;
-
	struct pkg_manifest *m;
+
	struct array deps;
+
	struct array rdeps;
+
	struct array conflicts;
+
	struct array files;
+
};
+

+
struct pkg_conflict {
+
	char name[100];
+
	char version[10];
+
	char origin[100];
+
};
+

+
struct pkg_file {
+
	char path[MAXPATHLEN];
+
	char md5[33];
};

#endif
modified libpkg/pkgdb.c
@@ -1,6 +1,7 @@
#include <sys/param.h>
#include <sys/stat.h>

+
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <regex.h>
@@ -13,16 +14,16 @@
#include "pkg.h"
#include "pkg_private.h"
#include "pkgdb.h"
+
#include "util.h"

#ifdef DEBUG
#include <dirent.h>
#include "pkg_compat.h"
-
#include "util.h"
#endif

#define PKG_DBDIR "/var/db/pkg"

-
static void pkgdb_stmt_to_pkg(sqlite3_stmt *, struct pkg *);
+
static struct pkgdb_it * pkgdb_it_new(struct pkgdb *, sqlite3_stmt *, pkgdb_it_t);
static void pkgdb_regex(sqlite3_context *, int, sqlite3_value **, int);
static void pkgdb_regex_basic(sqlite3_context *, int, sqlite3_value **);
static void pkgdb_regex_extended(sqlite3_context *, int, sqlite3_value **);
@@ -276,15 +277,178 @@ pkgdb_close(struct pkgdb *db)
	free(db);
}

+
static struct pkgdb_it *
+
pkgdb_it_new(struct pkgdb *db, sqlite3_stmt *s, pkgdb_it_t t)
+
{
+
	struct pkgdb_it *it = malloc(sizeof(struct pkgdb_it));
+
	if (it == NULL)
+
		return (NULL);
+

+
	it->db = db;
+
	it->stmt = s;
+
	it->type = t;
+
	return (it);
+
}
+

+
int
+
pkgdb_it_next_pkg(struct pkgdb_it *it, struct pkg **pkg_p, int flags)
+
{
+
	struct pkg *pkg;
+
	struct pkg *p;
+
	struct pkg_conflict *c;
+
	struct pkg_file *f;
+
	struct pkgdb_it *i;
+

+
	assert(it->type == IT_PKG);
+

+
	switch (sqlite3_step(it->stmt)) {
+
	case SQLITE_ROW:
+
		if (*pkg_p == NULL)
+
			pkg_new(pkg_p);
+
		else
+
			pkg_reset(*pkg_p);
+
		pkg = *pkg_p;
+

+
		strlcpy(pkg->origin, sqlite3_column_text(it->stmt, 0), sizeof(pkg->origin));
+
		strlcpy(pkg->name, sqlite3_column_text(it->stmt, 1), sizeof(pkg->name));
+
		strlcpy(pkg->version, sqlite3_column_text(it->stmt, 2), sizeof(pkg->version));
+
		strlcpy(pkg->comment, sqlite3_column_text(it->stmt, 3), sizeof(pkg->comment));
+
		pkg->desc = strdup(sqlite3_column_text(it->stmt, 4));
+

+
		if (flags & PKG_DEPS) {
+
			array_init(&pkg->deps, 10);
+

+
			i = pkgdb_query_dep(it->db, pkg->origin);
+
			p = NULL;
+
			while (pkgdb_it_next_pkg(i, &p, PKG_BASIC) == 0) {
+
				array_append(&pkg->deps, p);
+
				p = NULL;
+
			}
+
			pkgdb_it_free(i);
+

+
			array_append(&pkg->deps, NULL);
+
		}
+

+
		if (flags & PKG_RDEPS) {
+
			array_init(&pkg->rdeps, 5);
+

+
			i = pkgdb_query_rdep(it->db, pkg->origin);
+
			p = NULL;
+
			while (pkgdb_it_next_pkg(i, &p, PKG_BASIC) == 0) {
+
				array_append(&pkg->rdeps, p);
+
				p = NULL;
+
			}
+
			pkgdb_it_free(i);
+

+
			array_append(&pkg->rdeps, NULL);
+
		}
+

+
		if (flags & PKG_CONFLICTS) {
+
			array_init(&pkg->conflicts, 5);
+

+
			i = pkgdb_query_conflicts(it->db, pkg->origin);
+
			c = NULL;
+
			while (pkgdb_it_next_conflict(i, &c) == 0) {
+
				array_append(&pkg->conflicts, c);
+
				c = NULL;
+
			}
+
			pkgdb_it_free(i);
+

+
			array_append(&pkg->conflicts, NULL);
+
		}
+

+
		if (flags & PKG_FILES) {
+
			array_init(&pkg->files, 10);
+

+
			i = pkgdb_query_files(it->db, pkg->origin);
+
			f = NULL;
+
			while (pkgdb_it_next_file(i, &f) == 0) {
+
				array_append(&pkg->files, f);
+
				f = NULL;
+
			}
+
			pkgdb_it_free(i);
+

+
			array_append(&pkg->files, NULL);
+
		}
+
		return (0);
+
	case SQLITE_DONE:
+
		return (1);
+
	default:
+
		pkgdb_set_error(it->db, 0, "sqlite3_step(): %s", sqlite3_errmsg(it->db->sqlite));
+
		return (-1);
+
	}
+
}
+

+
int
+
pkgdb_it_next_conflict(struct pkgdb_it *it, struct pkg_conflict **c_p)
+
{
+
	struct pkg_conflict *c;
+

+
	assert(it->type == IT_CONFLICT);
+

+
	switch (sqlite3_step(it->stmt)) {
+
	case SQLITE_ROW:
+
		if (*c_p == NULL)
+
			pkg_conflict_new(c_p);
+
		else
+
			pkg_conflict_reset(*c_p);
+
		c = *c_p;
+

+
		strlcpy(c->origin, sqlite3_column_text(it->stmt, 0), sizeof(c->origin));
+
		strlcpy(c->name, sqlite3_column_text(it->stmt, 1), sizeof(c->name));
+
		strlcpy(c->version, sqlite3_column_text(it->stmt, 2), sizeof(c->version));
+
		return (0);
+
	case SQLITE_DONE:
+
		return (1);
+
	default:
+
		pkgdb_set_error(it->db, 0, "sqlite3_step(): %s", sqlite3_errmsg(it->db->sqlite));
+
		return (-1);
+
	}
+
}
+

int
-
pkgdb_query_init(struct pkgdb *db, const char *pattern, match_t match)
+
pkgdb_it_next_file(struct pkgdb_it *it, struct pkg_file **file_p)
+
{
+
	struct pkg_file *file;
+

+
	assert(it->type == IT_FILE);
+

+
	switch (sqlite3_step(it->stmt)) {
+
	case SQLITE_ROW:
+
		if (*file_p == NULL)
+
			pkg_file_new(file_p);
+
		else
+
			pkg_file_reset(*file_p);
+
		file = *file_p;
+

+
		strlcpy(file->path, sqlite3_column_text(it->stmt, 0), sizeof(file->path));
+
		strlcpy(file->md5, sqlite3_column_text(it->stmt, 1), sizeof(file->md5));
+
		return (0);
+
	case SQLITE_DONE:
+
		return (1);
+
	default:
+
		pkgdb_set_error(it->db, 0, "sqlite3_step(): %s", sqlite3_errmsg(it->db->sqlite));
+
		return (-1);
+
	}
+
}
+

+
void
+
pkgdb_it_free(struct pkgdb_it *it)
+
{
+
	sqlite3_finalize(it->stmt);
+
	free(it);
+
}
+

+
struct pkgdb_it *
+
pkgdb_query(struct pkgdb *db, const char *pattern, match_t match)
{
	char sql[BUFSIZ];
+
	sqlite3_stmt *stmt;
	const char *comp = NULL;

	if (match != MATCH_ALL && pattern == NULL) {
		pkgdb_set_error(db, 0, "missing pattern");
-
		return (-1);
+
		return (NULL);
	}

	switch (match) {
@@ -308,169 +472,81 @@ pkgdb_query_init(struct pkgdb *db, const char *pattern, match_t match)
	snprintf(sql, sizeof(sql),
			"SELECT origin, name, version, comment, desc FROM packages%s;", comp);

-
	sqlite3_prepare(db->sqlite, sql, -1, &db->stmt, NULL);
+
	sqlite3_prepare(db->sqlite, sql, -1, &stmt, NULL);

	if (match != MATCH_ALL)
-
		sqlite3_bind_text(db->stmt, 1, pattern, -1, SQLITE_TRANSIENT);
+
		sqlite3_bind_text(stmt, 1, pattern, -1, SQLITE_TRANSIENT);

-
	return (0);
+
	return (pkgdb_it_new(db, stmt, IT_PKG));
}

-
void
-
pkgdb_query_free(struct pkgdb *db)
+
struct pkgdb_it *
+
pkgdb_query_which(struct pkgdb *db, const char *path)
{
-
	sqlite3_finalize(db->stmt);
-
	db->stmt = NULL;
-
}
-

-
int
-
pkgdb_query(struct pkgdb *db, struct pkg *pkg)
-
{
-
	int retcode;
-

-
	pkg_reset(pkg);
-
	retcode = sqlite3_step(db->stmt);
-

-
	if (retcode == SQLITE_ROW) {
-
		pkgdb_stmt_to_pkg(db->stmt, pkg);
-
		pkg->pdb = db;
-
		return (0);
-
	} else if (retcode == SQLITE_DONE) {
-
		sqlite3_reset(db->stmt);
-
		return (1);
-
	} else {
-
		pkgdb_set_error(db, 0, "sqlite3_step(): %s", sqlite3_errmsg(db->sqlite));
-
		return (-1);
-
	}
-
}
+
	sqlite3_stmt *stmt;

-
int
-
pkgdb_query_which(struct pkgdb *db, const char *path, struct pkg *pkg)
-
{
-
	int retcode;
-

-
	pkg_reset(pkg);
	sqlite3_prepare(db->sqlite,
					"SELECT origin, name, version, comment, desc FROM packages, files "
					"WHERE origin = files.package_id "
-
					"AND files.path = ?1;", -1, &pkg->which_stmt, NULL);
-
	sqlite3_bind_text(pkg->which_stmt, 1, path, -1, SQLITE_STATIC);
-

-
	retcode = sqlite3_step(pkg->which_stmt);
-
	if (retcode == SQLITE_ROW) {
-
		pkgdb_stmt_to_pkg(pkg->which_stmt, pkg);
-
		pkg->pdb = db;
-
	}
+
					"AND files.path = ?1;", -1, &stmt, NULL);
+
	sqlite3_bind_text(stmt, 1, path, -1, SQLITE_TRANSIENT);

-
	return ((retcode == SQLITE_ROW) ? 0 : 1);
+
	return (pkgdb_it_new(db, stmt, IT_PKG));
}

-
int
-
pkgdb_query_dep(struct pkg *pkg, struct pkg *dep) {
-
	int retcode;
+
struct pkgdb_it *
+
pkgdb_query_dep(struct pkgdb *db, const char *origin) {
+
	sqlite3_stmt *stmt;

-
	if (pkg->deps_stmt == NULL) {
-
		sqlite3_prepare(pkg->pdb->sqlite,
-
						"SELECT p.origin, p.name, p.version, p.comment, p.desc FROM packages AS p, deps AS d "
-
						"WHERE p.origin = d.origin "
-
						"AND d.package_id = ?1;", -1, &pkg->deps_stmt, NULL);
-
		sqlite3_bind_text(pkg->deps_stmt, 1, pkg->origin, -1, SQLITE_STATIC);
-
	}
+
	sqlite3_prepare(db->sqlite,
+
					"SELECT p.origin, p.name, p.version, p.comment, p.desc "
+
					"FROM packages AS p, deps AS d "
+
					"WHERE p.origin = d.origin "
+
					"AND d.package_id = ?1;", -1, &stmt, NULL);
+
	sqlite3_bind_text(stmt, 1, origin, -1, SQLITE_TRANSIENT);

-
	retcode = sqlite3_step(pkg->deps_stmt);
-
	if (retcode == SQLITE_ROW) {
-
		pkgdb_stmt_to_pkg(pkg->deps_stmt, dep);
-
		dep->pdb = pkg->pdb;
-
		return (0);
-
	} else if (retcode == SQLITE_DONE) {
-
		sqlite3_reset(pkg->deps_stmt);
-
		return (1);
-
	} else {
-
		return (-1);
-
	}
+
	return (pkgdb_it_new(db, stmt, IT_PKG));
}

-
int
-
pkgdb_query_rdep(struct pkg *pkg, struct pkg *rdep) {
-
	int retcode;
+
struct pkgdb_it *
+
pkgdb_query_rdep(struct pkgdb *db, const char *origin) {
+
	sqlite3_stmt *stmt;

-
	if (pkg->rdeps_stmt == NULL) {
-
		sqlite3_prepare(pkg->pdb->sqlite,
-
						"SELECT p.origin, p.name, p.version, p.comment, p.desc FROM packages AS p, deps AS d "
-
						"WHERE p.origin = d.package_id "
-
						"AND d.origin = ?1;", -1, &pkg->rdeps_stmt, NULL);
-
		sqlite3_bind_text(pkg->rdeps_stmt, 1, pkg->origin, -1, SQLITE_STATIC);
-
	}
+
	sqlite3_prepare(db->sqlite,
+
					"SELECT p.origin, p.name, p.version, p.comment, p.desc "
+
					"FROM packages AS p, deps AS d "
+
					"WHERE p.origin = d.package_id "
+
					"AND d.origin = ?1;", -1, &stmt, NULL);
+
	sqlite3_bind_text(stmt, 1, origin, -1, SQLITE_TRANSIENT);

-
	retcode = sqlite3_step(pkg->rdeps_stmt);
-
	if (retcode == SQLITE_ROW) {
-
		pkgdb_stmt_to_pkg(pkg->rdeps_stmt, rdep);
-
		rdep->pdb = pkg->pdb;
-
		return (0);
-
	} else if (retcode == SQLITE_DONE) {
-
		sqlite3_reset(pkg->rdeps_stmt);
-
		return (1);
-
	} else {
-
		return (-1);
-
	}
+
	return (pkgdb_it_new(db, stmt, IT_PKG));
}

-
int
-
pkgdb_query_conflicts(struct pkg *pkg, struct pkg *conflict) {
-
	int retcode;
+
struct pkgdb_it *
+
pkgdb_query_conflicts(struct pkgdb *db, const char *origin) {
+
	sqlite3_stmt *stmt;

-
	if (pkg->conflicts_stmt == NULL) {
-
		sqlite3_prepare(pkg->pdb->sqlite,
-
						"SELECT name, origin, version FROM conflicts "
-
						"WHERE package_id = ?1;", -1, &pkg->files_stmt, NULL);
-
		sqlite3_bind_text(pkg->files_stmt, 1, pkg->origin, -1, SQLITE_STATIC);
-
	}
+
	sqlite3_prepare(db->sqlite,
+
					"SELECT name, origin, version "
+
					"FROM conflicts "
+
					"WHERE package_id = ?1;", -1, &stmt, NULL);
+
	sqlite3_bind_text(stmt, 1, origin, -1, SQLITE_TRANSIENT);

-
	retcode = sqlite3_step(pkg->files_stmt);
-
	if (retcode == SQLITE_ROW) {
-
		conflict->name = strdup(sqlite3_column_text(pkg->files_stmt, 0));
-
		conflict->origin = strdup(sqlite3_column_text(pkg->files_stmt, 1));
-
		conflict->version = strdup(sqlite3_column_text(pkg->files_stmt, 2));
-
		return (0);
-
	} else if (retcode == SQLITE_DONE) {
-
		sqlite3_reset(pkg->files_stmt);
-
		return (1);
-
	} else {
-
		return (-1);
-
	}
+
	return (pkgdb_it_new(db, stmt, IT_CONFLICT));
}

-
int
-
pkgdb_query_files(struct pkg *pkg, const char **path, const char **md5) {
-
	int retcode;
+
struct pkgdb_it *
+
pkgdb_query_files(struct pkgdb *db, const char *origin) {
+
	sqlite3_stmt *stmt;

-
	if (pkg->files_stmt == NULL) {
-
		sqlite3_prepare(pkg->pdb->sqlite,
-
						"SELECT path, md5 FROM files WHERE package_id = ?1;", -1, &pkg->files_stmt, NULL);
-
		sqlite3_bind_text(pkg->files_stmt, 1, pkg->origin, -1, SQLITE_STATIC);
-
	}
+
	sqlite3_prepare(db->sqlite,
+
					"SELECT path, md5 "
+
					"FROM files "
+
					"WHERE package_id = ?1;", -1, &stmt, NULL);
+
	sqlite3_bind_text(stmt, 1, origin, -1, SQLITE_TRANSIENT);

-
	retcode = sqlite3_step(pkg->files_stmt);
-
	if (retcode == SQLITE_ROW) {
-
		*path = sqlite3_column_text(pkg->files_stmt, 0);
-
		*md5 = sqlite3_column_text(pkg->files_stmt, 1);
-
		return (0);
-
	} else if (retcode == SQLITE_DONE) {
-
		sqlite3_reset(pkg->files_stmt);
-
		return (1);
-
	} else {
-
		return (-1);
-
	}
-
}
+
	return (pkgdb_it_new(db, stmt, IT_FILE));

-
static void
-
pkgdb_stmt_to_pkg(sqlite3_stmt *stmt, struct pkg *pkg)
-
{
-
		pkg->origin = strdup(sqlite3_column_text(stmt, 0));
-
		pkg->name = strdup(sqlite3_column_text(stmt, 1));
-
		pkg->version = strdup(sqlite3_column_text(stmt, 2));
-
		pkg->comment = strdup(sqlite3_column_text(stmt, 3));
-
		pkg->desc = strdup(sqlite3_column_text(stmt, 4));
}

void
modified libpkg/pkgdb.h
@@ -1,6 +1,10 @@
#ifndef _PKGDB_H
#define _PKGDB_H

+
#include "pkg.h"
+

+
#include "sqlite3.h"
+

struct pkgdb {
	sqlite3 *sqlite;
	sqlite3_stmt *stmt;
@@ -8,10 +12,17 @@ struct pkgdb {
	char errstring[1024];
};

-
int pkgdb_query_dep(struct pkg *, struct pkg *);
-
int pkgdb_query_rdep(struct pkg *, struct pkg *);
-
int pkgdb_query_conflicts(struct pkg *, struct pkg *);
-
int pkgdb_query_files(struct pkg *, const char **, const char **);
+
typedef enum _pkgdb_it_t {
+
	IT_PKG,
+
	IT_CONFLICT,
+
	IT_FILE
+
} pkgdb_it_t;
+
struct pkgdb_it {
+
	struct pkgdb *db;
+
	sqlite3_stmt *stmt;
+
	pkgdb_it_t type;
+
};
+

void pkgdb_set_error(struct pkgdb *, int, const char *, ...);

#endif
modified libpkg/util.c
@@ -10,6 +10,61 @@

#include "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);
+
}
+

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

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

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

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

off_t
file_to_buffer(const char *path, char **buffer)
{
modified libpkg/util.h
@@ -1,8 +1,20 @@
#ifndef _PKG_UTIL_H
#define _PKG_UTIL_H

+
#include <sys/param.h>
#include <dirent.h>

+
struct array {
+
	size_t cap;
+
	size_t len;
+
	void **data;
+
};
+

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

off_t file_to_buffer(const char *path, char **buffer);
char *str_replace(char *string, const char *find, char *replace);
int select_dir(const struct dirent *);
modified pkg/create.c
@@ -31,6 +31,7 @@ int
exec_create(int argc, char **argv)
{
	struct pkgdb *db;
+
	struct pkgdb_it *it;
	struct pkg *pkg;

	match_t match = MATCH_EXACT;
@@ -108,18 +109,20 @@ exec_create(int argc, char **argv)
			return (-1);
		}

-
		if (pkgdb_query_init(db, argv[0], match) == -1) {
+
		if ((it = pkgdb_query(db, argv[0], match)) == NULL) {
			pkgdb_warn(db);
			return (-1);
		}

		pkg_new(&pkg);
-
		while (pkgdb_query(db, pkg) == 0) {
-
			snprintf(mpath, sizeof(mpath), "%s/%s-%s/+MANIFEST", pkgdb_get_dir(), pkg_name(pkg), pkg_version(pkg));
+
		while (pkgdb_it_next_pkg(it, &pkg, PKG_ALL) == 0) {
+
			snprintf(mpath, sizeof(mpath), "%s/%s-%s/+MANIFEST", pkgdb_get_dir(),
+
					 pkg_name(pkg), pkg_version(pkg));
+
			printf("Creating package for %s-%s\n", pkg_name(pkg), pkg_version(pkg));
			pkg_create(mpath, fmt, outdir, rootdir, pkg);
		}
		pkg_free(pkg);
-
		pkgdb_query_free(db);
+
		pkgdb_it_free(it);
		pkgdb_close(db);
	} else {
		snprintf(mpath, sizeof(mpath), "%s/+MANIFEST", manifestdir);
modified pkg/info.c
@@ -11,18 +11,21 @@

#include "info.h"

-

static int64_t
pkg_size(struct pkg *pkg)
{
+
	struct pkg_file **files;
	struct stat st;
-
	const char *path;
-
	const char *md5;
	int64_t size = 0;

-
	while(pkg_files(pkg, &path, &md5) == 0) {
-
		if (stat(path, &st) != 0) {
-
			warn("stat(%s)", path);
+
	files = pkg_files(pkg);
+
	if (files == NULL) {
+
		warnx("Missing files informations for %s", pkg_origin(pkg));
+
		return (0);
+
	}
+
	for (size_t i = 0; files[i] != NULL; i++) {
+
		if (stat(pkg_file_path(files[i]), &st) != 0) {
+
			warn("stat(%s)", pkg_file_path(files[i]));
			continue;
		}
		size += st.st_size;
@@ -46,14 +49,16 @@ int
exec_info(int argc, char **argv)
{
	struct pkgdb *db;
+
	struct pkgdb_it *it;
+
	int query_flags = PKG_BASIC;
	struct pkg *pkg;
-
	struct pkg *dep;
-
	const char *path;
-
	const char *md5;
+
	struct pkg **deps;
+
	struct pkg_file **files;
	unsigned char opt = 0;
	char size[7];
	match_t match = MATCH_EXACT;
	char ch;
+
	size_t i;
	int retcode = 0;

	/* TODO: exclusive opts ? */
@@ -73,15 +78,19 @@ exec_info(int argc, char **argv)
				break;
			case 'd':
				opt |= INFO_PRINT_DEP;
+
				query_flags |= PKG_DEPS;
				break;
			case 'r':
				opt |= INFO_PRINT_RDEP;
+
				query_flags |= PKG_RDEPS;
				break;
			case 'l':
				opt |= INFO_LIST_FILES;
+
				query_flags = PKG_FILES;
				break;
			case 's':
				opt |= INFO_SIZE;
+
				query_flags = PKG_FILES;
				break;
		}
	}
@@ -96,36 +105,41 @@ exec_info(int argc, char **argv)
		return (-1);
	}

-
	if (pkgdb_query_init(db, argv[0], match) == -1) {
+
	if ((it = pkgdb_query(db, argv[0], match)) == NULL) {
		pkgdb_warn(db);
		return (-1);
	}

	pkg_new(&pkg);
-
	pkg_new(&dep);

-
	while (pkgdb_query(db, pkg) == 0) {
+
	while (pkgdb_it_next_pkg(it, &pkg, query_flags) == 0) {
+

		if (opt & INFO_EXISTS) {
			retcode = 0;
		} else if (opt & INFO_PRINT_DEP) {

			printf("%s-%s depends on:\n", pkg_name(pkg), pkg_version(pkg));

-
			while (pkg_dep(pkg, dep) == 0) {
-
				printf("%s-%s\n", pkg_name(dep), pkg_version(pkg));
+
			deps = pkg_deps(pkg);
+
			for (i = 0; deps[i] != NULL; i++) {
+
				printf("%s-%s\n", pkg_name(deps[i]), pkg_version(deps[i]));
			}

			printf("\n");
		} else if (opt & INFO_PRINT_RDEP) {
			printf("%s-%s is required by:\n", pkg_name(pkg), pkg_version(pkg));
-
			while (pkg_rdep(pkg, dep) == 0) {
-
				printf("%s-%s\n", pkg_name(dep), pkg_version(dep));
+

+
			deps = pkg_rdeps(pkg);
+
			for (i = 0; deps[i] != NULL; i++) {
+
				printf("%s-%s\n", pkg_name(deps[i]), pkg_version(deps[i]));
			}
+

			printf("\n");
		} else if (opt & INFO_LIST_FILES) {
			printf("%s-%s owns the following files:\n", pkg_name(pkg), pkg_version(pkg));
-
			while (pkg_files(pkg, &path, &md5) == 0) {
-
				printf("%s\n", path);
+
			files = pkg_files(pkg);
+
			for (i = 0; files[i] != NULL; i++) {
+
				printf("%s\n", pkg_file_path(files[i]));
			}
		} else if (opt & INFO_SIZE) {
			humanize_number(size, sizeof(size), pkg_size(pkg), "B", HN_AUTOSCALE, 0);
@@ -134,16 +148,14 @@ exec_info(int argc, char **argv)
			printf("%s-%s: %s\n", pkg_name(pkg), pkg_version(pkg), pkg_comment(pkg));
		}
	}
-

	pkg_free(pkg);
-
	pkg_free(dep);

	if (pkgdb_errnum(db) > 0) {
		pkgdb_warn(db);
		retcode = -1;
	}

-
	pkgdb_query_free(db);
+
	pkgdb_it_free(it);
	pkgdb_close(db);
	return (retcode);
}
modified pkg/which.c
@@ -21,6 +21,7 @@ int
exec_which(int argc, char **argv)
{
	struct pkgdb *db;
+
	struct pkgdb_it *it;
	struct pkg *pkg;
	char pathabs[MAXPATHLEN];
	char pathabsdir[MAXPATHLEN];
@@ -39,8 +40,13 @@ exec_which(int argc, char **argv)
	realpath(dirname(argv[1]), pathabsdir);
	snprintf(pathabs, sizeof(pathabs), "%s/%s", pathabsdir, basename(argv[1]));

+
	if ((it = pkgdb_query_which(db, pathabs)) == NULL) {
+
		pkgdb_warn(db);
+
		return (-1);
+
	}
+

	pkg_new(&pkg);
-
	if (pkgdb_query_which(db, pathabs, pkg) == 0) {
+
	if (pkgdb_it_next_pkg(it, &pkg, PKG_BASIC) == 0) {
		retcode = 0;
		printf("%s was installed by package %s-%s\n", pathabs, pkg_name(pkg),
			   pkg_version(pkg));