Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Add users/groups to the database and manifest: /!\ This need testing
Baptiste Daroussin committed 14 years ago
commit 47ddb170063c421b4b96be714e991ffc46c0174b
parent d9d4aa9
8 files changed +432 -3
modified libpkg/db_upgrades.h
@@ -82,7 +82,32 @@ static struct db_upgrades {
	"ALTER TABLE pkg_categories_assoc RENAME TO pkg_categories;"
	"DROP VIEW pkg_licenses;"
	"DROP TRIGGER licenses_insert;"
-
	"ALTER TABLE pkg_licenses_assoc RENAME TO pkg_licenses;"	
+
	"ALTER TABLE pkg_licenses_assoc RENAME TO pkg_licenses;"
+
	},
+

+
	{5,
+
	"CREATE TABLE users ("
+
		"id INTEGER PRIMATY KEY, "
+
		"name TEXT NOT NULL UNIQUE "
+
	");"
+
	"CREATE TABLE pkg_users ("
+
		"package_id INTEGER REFERECES packages(id) ON DELETE CASCADE"
+
			" ON UPDATE CASCADE, "
+
		"user_id INTEGER REFERENCES users(id) ON DELETE RESTRICT"
+
			" ON UPDATE RESTRICT, "
+
		"UNIQUE(package_id, user_id)"
+
	");"
+
	"CREATE TABLE groups ("
+
		"id INTEGER PRIMATY KEY, "
+
		"name TEXT NOT NULL UNIQUE "
+
	");"
+
	"CREATE TABLE pkg_groups ("
+
		"package_id INTEGER REFERECES packages(id) ON DELETE CASCADE"
+
			" ON UPDATE CASCADE, "
+
		"group_id INTEGER REFERENCES groups(id) ON DELETE RESTRICT"
+
			" ON UPDATE RESTRICT, "
+
		"UNIQUE(package_id, group_id)"
+
	");"
	},

	/* Mark the end of the array */
modified libpkg/pkg.c
@@ -301,6 +301,38 @@ pkg_licenses(struct pkg *pkg, struct pkg_license **l)
}

int
+
pkg_users(struct pkg *pkg, struct pkg_user **u)
+
{
+
	assert(pkg != NULL);
+

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

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

+
int
+
pkg_groups(struct pkg *pkg, struct pkg_group **g)
+
{
+
	assert(pkg != NULL);
+

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

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

+
int
pkg_deps(struct pkg *pkg, struct pkg_dep **d)
{
	assert(pkg != NULL);
@@ -451,6 +483,36 @@ pkg_addlicense(struct pkg *pkg, const char *name)
}

int
+
pkg_adduser(struct pkg *pkg, const char *name)
+
{
+
	struct pkg_user *u;
+

+
	assert(pkg != NULL);
+
	assert(name != NULL && name[0] != '\0');
+

+
	pkg_user_new(&u);
+

+
	strlcpy(u->name, name, MAXLOGNAME);
+

+
	return (EPKG_OK);
+
}
+

+
int
+
pkg_addgroup(struct pkg *pkg, const char *name)
+
{
+
	struct pkg_group *g;
+

+
	assert(pkg != NULL);
+
	assert(name != NULL && name[0] != '\0');
+

+
	pkg_group_new(&g);
+

+
	strlcpy(g->name, name, MAXLOGNAME);
+

+
	return (EPKG_OK);
+
}
+

+
int
pkg_adddep(struct pkg *pkg, const char *name, const char *origin, const char *version)
{
	struct pkg_dep *d;
@@ -781,6 +843,34 @@ pkg_freelicenses(struct pkg *pkg)
}

void
+
pkg_freeusers(struct pkg *pkg)
+
{
+
	struct pkg_user *u;
+

+
	while (!STAILQ_EMPTY(&pkg->users)) {
+
		u = STAILQ_FIRST(&pkg->users);
+
		STAILQ_REMOVE_HEAD(&pkg->users, next);
+
		pkg_user_free(u);
+
	}
+

+
	pkg->flags &= ~PKG_LOAD_USERS;
+
}
+

+
void
+
pkg_freegroups(struct pkg *pkg)
+
{
+
	struct pkg_group *g;
+

+
	while (!STAILQ_EMPTY(&pkg->groups)) {
+
		g = STAILQ_FIRST(&pkg->groups);
+
		STAILQ_REMOVE_HEAD(&pkg->groups, next);
+
		pkg_group_free(g);
+
	}
+

+
	pkg->flags &= ~PKG_LOAD_GROUPS;
+
}
+

+
void
pkg_freecategories(struct pkg *pkg)
{
	struct pkg_category *c;
modified libpkg/pkg.h
@@ -14,6 +14,8 @@ struct pkg_conflict;
struct pkg_script;
struct pkg_option;
struct pkg_license;
+
struct pkg_user;
+
struct pkg_group;

struct pkgdb;
struct pkgdb_it;
@@ -276,6 +278,20 @@ int pkg_categories(struct pkg *pkg, struct pkg_category **category);
int pkg_licenses(struct pkg *pkg, struct pkg_license **license);

/**
+
 * Iterates over the users of the package.
+
 * @param Must be set to NULL for the first call.
+
 * @return An error code.
+
 */
+
int pkg_users(struct pkg *pkg, struct pkg_user **user);
+

+
/**
+
 * Iterates over the groups of the package.
+
 * @param Must be set to NULL for the first call.
+
 * @return An error code.
+
 */
+
int pkg_groups(struct pkg *pkg, struct pkg_group **group);
+

+
/**
 * Iterates over the conflicts of the package.
 * @param conflict Must be set to NULL for the first call.
 * @return An error code.
@@ -399,6 +415,18 @@ int pkg_addcategory(struct pkg *pkg, const char *name);
int pkg_addlicense(struct pkg *pkg, const char *name);

/**
+
 * Add a user
+
 * @return An error code.
+
 */
+
int pkg_adduser(struct pkg *pkg, const char *name);
+

+
/**
+
 * Add a group
+
 * @return An error code.
+
 */
+
int pkg_addgroup(struct pkg *pkg, const char *group);
+

+
/**
 * Allocate a new struct pkg_conflict and add it to the conflicts of pkg.
 * @return An error code.
 */
@@ -455,6 +483,9 @@ const char *pkg_category_name(struct pkg_category *);

const char *pkg_license_name(struct pkg_license *);

+
const char *pkg_user_name(struct pkg_user *);
+
const char *pkg_group_name(struct pkg_group *);
+

/* pkg_conflict */
const char * pkg_conflict_glob(struct pkg_conflict *);

@@ -562,6 +593,8 @@ struct pkgdb_it * pkgdb_query_which(struct pkgdb *db, const char *path);
#define PKG_LOAD_DIRS (1<<8)
#define PKG_LOAD_CATEGORIES (1<<9)
#define PKG_LOAD_LICENSES (1<<10)
+
#define PKG_LOAD_USERS (1<<11)
+
#define PKG_LOAD_GROUPS (1<<12)

/**
 * Get the next pkg.
@@ -587,6 +620,8 @@ int pkgdb_loadoptions(struct pkgdb *db, struct pkg *pkg);
int pkgdb_loadmtree(struct pkgdb *db, struct pkg *pkg);
int pkgdb_loadcategory(struct pkgdb *db, struct pkg *pkg);
int pkgdb_loadlicense(struct pkgdb *db, struct pkg *pkg);
+
int pkgdb_loaduser(struct pkgdb *db, struct pkg *pkg);
+
int pkgdb_loadgroup(struct pkgdb *db, struct pkg *pkg);

/**
 * Compact the database to save space.
modified libpkg/pkg_attributes.c
@@ -188,6 +188,66 @@ pkg_license_name(struct pkg_license *l)
	return (sbuf_get(l->name));
}

+
/*
+
 * user
+
 */
+

+
int
+
pkg_user_new(struct pkg_user **u)
+
{
+
	if ((*u = calloc(1, sizeof(struct pkg_user))) == NULL) {
+
		EMIT_ERRNO("calloc", "pkg_user");
+
		return (EPKG_FATAL);
+
	}
+

+
	return (EPKG_OK);
+
}
+

+
void
+
pkg_user_free(struct pkg_user *u)
+
{
+
	if (u == NULL)
+
		return;
+

+
	free(u);
+
}
+

+
const char *
+
pkg_user_name(struct pkg_user *u)
+
{
+
	return (u->name);
+
}
+

+
/*
+
 * group
+
 */
+

+
int
+
pkg_group_new(struct pkg_group **g)
+
{
+
	if ((*g = calloc(1, sizeof(struct pkg_group))) == NULL) {
+
		EMIT_ERRNO("calloc", "pkg_group");
+
		return (EPKG_FATAL);
+
	}
+

+
	return (EPKG_OK);
+
}
+

+
void
+
pkg_group_free(struct pkg_group *g)
+
{
+
	if (g == NULL)
+
		return;
+

+
	free(g);
+
}
+

+
const char *
+
pkg_group_name(struct pkg_group *g)
+
{
+
	return (g->name);
+
}
+


/*
 * Script
modified libpkg/pkg_manifest.c
@@ -26,6 +26,8 @@
#define PKG_LICENSELOGIC -9
#define PKG_LICENSES -10
#define PKG_OPTIONS -11
+
#define PKG_USERS -12
+
#define PKG_GROUPS -13

static void parse_mapping(struct pkg *, yaml_node_pair_t *, yaml_document_t *, int);
static void parse_node(struct pkg *, yaml_node_t *, yaml_document_t *, int);
@@ -55,6 +57,8 @@ static struct manifest_key {
	{ "message", PKG_MESSAGE},
	{ "categories", PKG_CATEGORIES},
	{ "options", PKG_OPTIONS},
+
	{ "users", PKG_USERS},
+
	{ "groups", PKG_GROUPS}
};

#define manifest_key_len (int)(sizeof(manifest_key)/sizeof(manifest_key[0]))
@@ -314,6 +318,23 @@ parse_node(struct pkg *pkg, yaml_node_t *node, yaml_document_t *document, int pk
						pkg_addlicense(pkg, nd->data.scalar.value);
						++item;
					}
+
					break;
+
				case PKG_USERS:
+
					item = node->data.sequence.items.start;
+
					while (item < node->data.sequence.items.top) {
+
						nd = yaml_document_get_node(document, *item);
+
						pkg_adduser(pkg, nd->data.scalar.value);
+
						++item;
+
					}
+
					break;
+
				case PKG_GROUPS:
+
					item = node->data.sequence.items.start;
+
					while (item < node->data.sequence.items.top) {
+
						nd = yaml_document_get_node(document, *item);
+
						pkg_adduser(pkg, nd->data.scalar.value);
+
						++item;
+
					}
+
					break;
			}
			break;
		case YAML_MAPPING_NODE:
@@ -377,6 +398,8 @@ pkg_emit_manifest(struct pkg *pkg, char **dest)
	struct pkg_script *script = NULL;
	struct pkg_category *category = NULL;
	struct pkg_license *license = NULL;
+
	struct pkg_user *user = NULL;
+
	struct pkg_group *group = NULL;
	int rc = EPKG_OK;
	int mapping;
	int depsmap = -1;
@@ -388,6 +411,8 @@ pkg_emit_manifest(struct pkg *pkg, char **dest)
	int scripts = -1;
	int categories = -1;
	int licenses = -1;
+
	int groups = -1;
+
	int users = -1;
	const char *script_types;
	struct sbuf *destbuf = sbuf_new_auto();

@@ -468,6 +493,28 @@ pkg_emit_manifest(struct pkg *pkg, char **dest)
				yaml_document_add_scalar(&doc, NULL, __DECONST(yaml_char_t*, pkg_category_name(category)), strlen(pkg_category_name(category)), YAML_PLAIN_SCALAR_STYLE));
	}

+
	while (pkg_users(pkg, &user) == EPKG_OK) {
+
		if ( users  == -1 ) {
+
			users = yaml_document_add_sequence(&doc, NULL, YAML_FLOW_SEQUENCE_STYLE);
+
			yaml_document_append_mapping_pair(&doc, mapping,
+
					yaml_document_add_scalar(&doc, NULL, __DECONST(yaml_char_t *, "users"), 5, YAML_PLAIN_SCALAR_STYLE),
+
					users);
+
		}
+
		yaml_document_append_sequence_item(&doc, users,
+
				yaml_document_add_scalar(&doc, NULL, __DECONST(yaml_char_t*, pkg_user_name(user)), strlen(pkg_user_name(user)), YAML_PLAIN_SCALAR_STYLE));
+
	}
+

+
	while (pkg_groups(pkg, &group) == EPKG_OK) {
+
		if ( groups  == -1 ) {
+
			groups = yaml_document_add_sequence(&doc, NULL, YAML_FLOW_SEQUENCE_STYLE);
+
			yaml_document_append_mapping_pair(&doc, mapping,
+
					yaml_document_add_scalar(&doc, NULL, __DECONST(yaml_char_t *, "groups"), 6, YAML_PLAIN_SCALAR_STYLE),
+
					groups);
+
		}
+
		yaml_document_append_sequence_item(&doc, groups,
+
				yaml_document_add_scalar(&doc, NULL, __DECONST(yaml_char_t*, pkg_group_name(group)), strlen(pkg_group_name(group)), YAML_PLAIN_SCALAR_STYLE));
+
	}
+

	while (pkg_conflicts(pkg, &conflict) == EPKG_OK) {
		if (conflicts == -1) {
			conflicts = yaml_document_add_sequence(&doc, NULL, YAML_FLOW_SEQUENCE_STYLE);
modified libpkg/pkg_private.h
@@ -36,6 +36,8 @@ struct pkg {
	STAILQ_HEAD(conflicts, pkg_conflict) conflicts;
	STAILQ_HEAD(scripts, pkg_script) scripts;
	STAILQ_HEAD(options, pkg_option) options;
+
	STAILQ_HEAD(users, pkg_user) users;
+
	STAILQ_HEAD(groups, pkg_group) groups;
	int flags;
	int64_t rowid;
	lic_t licenselogic;
@@ -117,6 +119,16 @@ struct pkg_remote_repo {
	STAILQ_ENTRY(pkg_remote_repo) entries;
};

+
struct pkg_user {
+
	char name[MAXLOGNAME];
+
	STAILQ_ENTRY(pkg_user) next;
+
};
+

+
struct pkg_group {
+
	char name[MAXLOGNAME];
+
	STAILQ_ENTRY(pkg_group) next;
+
};
+

int pkg_open2(struct pkg **p, struct archive **a, struct archive_entry **ae, const char *path);
void pkg_freelicenses(struct pkg *pkg);
void pkg_freecategories(struct pkg *pkg);
@@ -127,6 +139,8 @@ void pkg_freedirs(struct pkg *pkg);
void pkg_freeconflicts(struct pkg *pkg);
void pkg_freescripts(struct pkg *pkg);
void pkg_freeoptions(struct pkg *pkg);
+
void pkg_freeusers(struct pkg *pkg);
+
void pkg_freegroups(struct pkg *pkg);

int pkg_dep_new(struct pkg_dep **);
void pkg_dep_free(struct pkg_dep *);
@@ -152,6 +166,12 @@ void pkg_script_free(struct pkg_script *);
int pkg_option_new(struct pkg_option **);
void pkg_option_free(struct pkg_option *);

+
int pkg_user_new(struct pkg_user **);
+
void pkg_user_free(struct pkg_user *);
+

+
int pkg_group_new(struct pkg_group **);
+
void pkg_group_free(struct pkg_group *);
+

int pkg_jobs_resolv(struct pkg_jobs *jobs);

struct packing;
modified libpkg/pkgdb.c
@@ -18,7 +18,7 @@
#include "pkg_util.h"

#include "db_upgrades.h"
-
#define DBVERSION 4
+
#define DBVERSION 5

static struct pkgdb_it * pkgdb_it_new(struct pkgdb *, sqlite3_stmt *, int);
static void pkgdb_regex(sqlite3_context *, int, sqlite3_value **, int);
@@ -374,7 +374,29 @@ pkgdb_init(sqlite3 *sdb)
			" ON UPDATE RESTRICT, "
		"PRIMARY KEY (package_id, license_id)"
	");"
-
	"PRAGMA user_version = 4;"
+
	"CREATE TABLE users ("
+
		"id INTEGER PRIMATY KEY, "
+
		"name TEXT NOT NULL UNIQUE "
+
	");"
+
	"CREATE TABLE pkg_users ("
+
		"package_id INTEGER REFERECES packages(id) ON DELETE CASCADE"
+
			" ON UPDATE CASCADE, "
+
		"user_id INTEGER REFERENCES users(id) ON DELETE RESTRICT"
+
			" ON UPDATE RESTRICT, "
+
		"UNIQUE(package_id, user_id)"
+
	");"
+
	"CREATE TABLE groups ("
+
		"id INTEGER PRIMATY KEY, "
+
		"name TEXT NOT NULL UNIQUE "
+
	");"
+
	"CREATE TABLE pkg_groups ("
+
		"package_id INTEGER REFERECES packages(id) ON DELETE CASCADE"
+
			" ON UPDATE CASCADE, "
+
		"group_id INTEGER REFERENCES groups(id) ON DELETE RESTRICT"
+
			" ON UPDATE RESTRICT, "
+
		"UNIQUE(package_id, group_id)"
+
	");"
+
	"PRAGMA user_version = 5;"
	;

	return (sql_exec(sdb, sql));
@@ -560,6 +582,14 @@ pkgdb_it_next(struct pkgdb_it *it, struct pkg **pkg_p, int flags)
			if ((ret = pkgdb_loadlicense(it->db, pkg)) != EPKG_OK)
				return (ret);

+
		if (flags & PKG_LOAD_USERS)
+
			if ((ret = pkgdb_loaduser(it->db, pkg)) != EPKG_OK)
+
				return (ret);
+

+
		if (flags & PKG_LOAD_GROUPS)
+
			if ((ret = pkgdb_loadgroup(it->db, pkg)) != EPKG_OK)
+
				return (ret);
+

		return (EPKG_OK);
	case SQLITE_DONE:
		return (EPKG_END);
@@ -914,6 +944,32 @@ pkgdb_loadcategory(struct pkgdb *db, struct pkg *pkg)
}

int
+
pkgdb_loaduser(struct pkgdb *db, struct pkg *pkg)
+
{
+
	const char sql[] = ""
+
		"SELECT users.name "
+
		"FROM pkg_users, users "
+
		"WHERE packagd_id ?1 "
+
		"AND user_id = users.id "
+
		"ORDER by name DESC";
+

+
	return (loadval(db->sqlite, pkg, sql, PKG_LOAD_USERS, pkg_adduser, pkg_freeusers));
+
}
+

+
int
+
pkgdb_loadgroup(struct pkgdb *db, struct pkg *pkg)
+
{
+
	const char sql[] = ""
+
		"SELECT groups.name "
+
		"FROM pkg_groups, groups "
+
		"WHERE packagd_id ?1 "
+
		"AND group_id = groups.id "
+
		"ORDER by name DESC";
+

+
	return (loadval(db->sqlite, pkg, sql, PKG_LOAD_GROUPS, pkg_addgroup, pkg_freegroups));
+
}
+

+
int
pkgdb_loadconflicts(struct pkgdb *db, struct pkg *pkg)
{
	const char sql[] = ""
@@ -1037,6 +1093,8 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
	struct pkg_option *option = NULL;
	struct pkg_category *category = NULL;
	struct pkg_license *license = NULL;
+
	struct pkg_user *user = NULL;
+
	struct pkg_group *group = NULL;

	sqlite3 *s;
	sqlite3_stmt *stmt_pkg = NULL;
@@ -1052,6 +1110,10 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
	sqlite3_stmt *stmt_cat = NULL;
	sqlite3_stmt *stmt_licenses = NULL;
	sqlite3_stmt *stmt_lic = NULL;
+
	sqlite3_stmt *stmt_user = NULL;
+
	sqlite3_stmt *stmt_users = NULL;
+
	sqlite3_stmt *stmt_groups = NULL;
+
	sqlite3_stmt *stmt_group = NULL;

	int ret;
	int retcode = EPKG_FATAL;
@@ -1094,6 +1156,14 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
	const char sql_license[] = ""
		"INSERT OR ROLLBACK INTO pkg_licenses(package_id, license_id) "
		"VALUES (?1, (SELECT id FROM licenses WHERE name = ?2));";
+
	const char sql_user[] = "INSERT OR IGNORE INTO users(name) VALUES(?1);";
+
	const char sql_users[] = ""
+
		"INSERT OR ROLLBACK INTO pkg_users(package_id, user_id) "
+
		"VALUES (?1, (SELECT id FROM users WHERE name = ?2));";
+
	const char sql_group[] = "INSERT OR IGNORE INTO groups(name) VALUES(?1);";
+
	const char sql_groups[] = ""
+
		"INSERT OR ROLLBACK INTO pkg_groups(package_id, group_id) "
+
		"VALUES (?1, (SELECT id FROM groups WHERE name = ?2));";

	if (pkgdb_has_flag(db, PKGDB_FLAG_IN_FLIGHT)) {
		EMIT_PKG_ERROR("%s", "tried to register a package with an in-flight SQL command");
@@ -1320,6 +1390,72 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
	}

	/*
+
	 * Insert users
+
	 */
+
	if (sqlite3_prepare_v2(s, sql_user, -1, &stmt_user, NULL) != SQLITE_OK) {
+
		ERROR_SQLITE(s);
+
		goto cleanup;
+
	}
+
	if (sqlite3_prepare_v2(s, sql_users, -1, &stmt_users, NULL) != SQLITE_OK) {
+
		ERROR_SQLITE(s);
+
		goto cleanup;
+
	}
+

+
	while (pkg_users(pkg, &user) == EPKG_OK) {
+
		sqlite3_bind_text(stmt_user, 1, pkg_user_name(user), -1, SQLITE_STATIC);
+
		sqlite3_bind_int64(stmt_users, 1, package_id);
+
		sqlite3_bind_text(stmt_users, 2, pkg_user_name(user), -1, SQLITE_STATIC);
+

+
		if ((ret = sqlite3_step(stmt_user)) != SQLITE_DONE) {
+
			if (ret == SQLITE_CONSTRAINT) {
+
				EMIT_PKG_ERROR("sqlite: constraint violation on users.name: %s",
+
						pkg_user_name(user));
+
			} else
+
				ERROR_SQLITE(s);
+
			goto cleanup;
+
		}
+
		if (( ret = sqlite3_step(stmt_users)) != SQLITE_DONE) {
+
			ERROR_SQLITE(s);
+
			goto cleanup;
+
		}
+
		sqlite3_reset(stmt_user);
+
		sqlite3_reset(stmt_users);
+
	}
+

+
	/*
+
	 * Insert groups
+
	 */
+
	if (sqlite3_prepare_v2(s, sql_group, -1, &stmt_group, NULL) != SQLITE_OK) {
+
		ERROR_SQLITE(s);
+
		goto cleanup;
+
	}
+
	if (sqlite3_prepare_v2(s, sql_groups, -1, &stmt_groups, NULL) != SQLITE_OK) {
+
		ERROR_SQLITE(s);
+
		goto cleanup;
+
	}
+

+
	while (pkg_groups(pkg, &group) == EPKG_OK) {
+
		sqlite3_bind_text(stmt_group, 1, pkg_group_name(group), -1, SQLITE_STATIC);
+
		sqlite3_bind_int64(stmt_groups, 1, package_id);
+
		sqlite3_bind_text(stmt_groups, 2, pkg_group_name(group), -1, SQLITE_STATIC);
+

+
		if ((ret = sqlite3_step(stmt_group)) != SQLITE_DONE) {
+
			if (ret == SQLITE_CONSTRAINT) {
+
				EMIT_PKG_ERROR("sqlite: constraint violation on groups.name: %s",
+
						pkg_group_name(group));
+
			} else
+
				ERROR_SQLITE(s);
+
			goto cleanup;
+
		}
+
		if (( ret = sqlite3_step(stmt_groups)) != SQLITE_DONE) {
+
			ERROR_SQLITE(s);
+
			goto cleanup;
+
		}
+
		sqlite3_reset(stmt_group);
+
		sqlite3_reset(stmt_groups);
+
	}
+

+
	/*
	 * Insert scripts
	 */

@@ -1404,6 +1540,12 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
	if (stmt_licenses != NULL)
		sqlite3_finalize(stmt_licenses);

+
	if (stmt_groups != NULL)
+
		sqlite3_finalize(stmt_groups);
+

+
	if (stmt_users != NULL)
+
		sqlite3_finalize(stmt_users);
+

	return (retcode);
}

modified ports/bsd.pkgng.mk
@@ -74,6 +74,16 @@ fake-pkg:
.endfor
	@${ECHO_CMD} "]" >> ${MANIFESTF}
.endif
+
	@${ECHO_CMD} -n "users: [" >> ${MANIFESTF}
+
.for user in ${USERS:u}
+
	@${ECHO_CMD} -n "${user}, " >> ${MANIFESTF}
+
.endfor
+
	@${ECHO_CMD} "]"
+
	@${ECHO_CMD} -n "groups: [" >> ${MANIFESTF}
+
.for group in ${GROUPS:u}
+
	@${ECHO_CMD} -n "${group}, " >> ${MANIFESTF}
+
.endfor
+
	@${ECHO_CMD} "]"
	@[ -f ${PKGINSTALL} ] && ${CP} ${PKGINSTALL} ${METADIR}/+INSTALL; \
	[ -f ${PKGPREINSTALL} ] && ${CP} ${PKGPREINSTALL} ${METADIR}/+PRE_INSTALL; \
	[ -f ${PKGPOSTINSTALL} ] && ${CP} ${PKGPOSTINSTALL} ${METADIR}/+POST_INSTALL; \