Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Merge remote branch 'pkgng/master'
Will Andrews committed 14 years ago
commit ce2dd24788e7773f6098292799c5c43e317a71b5
parent cda9b80
23 files changed +520 -548
modified README
@@ -62,3 +62,8 @@ Deletion of a package
---------------------

Directory leftovers are automatically removed if they are not in the MTREE.
+

+
Using from ports
+
----------------
+
To use pkgng from ports currently we need to include bsd.pkgng.mk in bsd.port.mk
+
the line before .if !defined(PKG_ARGS)
modified libpkg/Makefile
@@ -25,7 +25,8 @@ SRCS= pkg.c \
		pkg_version.c \
		pkgdb.c \
		fetch.c \
-
		packing.c
+
		packing.c \
+
		scripts.c

CFLAGS+=	-std=c99
CFLAGS+=	-I${.CURDIR} \
modified libpkg/packing.c
@@ -83,8 +83,10 @@ packing_append_file(struct packing *pack, const char *filepath, const char *newp
{
	int fd;
	int len;
+
	char linkdest[MAXPATHLEN];
	char buf[BUFSIZ];
	int retcode = EPKG_OK;
+
	struct stat st;

	archive_entry_clear(pack->entry);
	archive_entry_copy_sourcepath(pack->entry, filepath);
@@ -97,6 +99,14 @@ packing_append_file(struct packing *pack, const char *filepath, const char *newp
		goto cleanup;
	}

+
	lstat(filepath, &st);
+
	archive_entry_copy_stat(pack->entry, &st);
+

+
	if (S_ISLNK(st.st_mode)) {
+
		readlink(filepath, linkdest, MAXPATHLEN);
+
		archive_entry_set_symlink(pack->entry, linkdest);
+
	}
+

	if (newpath != NULL)
		archive_entry_set_pathname(pack->entry, newpath);

modified libpkg/pkg.c
@@ -143,18 +143,6 @@ pkg_scripts(struct pkg *pkg)
	return ((struct pkg_script **)pkg->scripts.data);
}

-
struct pkg_exec **
-
pkg_execs(struct pkg *pkg)
-
{
-
	if (pkg == NULL) {
-
		ERROR_BAD_ARG("pkg");
-
		return (NULL);
-
	}
-

-
	array_init(&pkg->exec, 1);
-
	return (struct pkg_exec **) pkg->exec.data;
-
}
-

struct pkg **
pkg_deps(struct pkg *pkg)
{
@@ -181,18 +169,17 @@ pkg_options(struct pkg *pkg)

int
pkg_resolvdeps(struct pkg *pkg, struct pkgdb *db) {
-
	struct pkg *p;
+
	struct pkg *p = NULL;
	struct pkgdb_it *it;
	struct pkg **deps;
	int i;

	deps = pkg_deps(pkg);
-
	pkg_new(&p);
	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 (pkgdb_it_next(it, &p, PKG_LOAD_BASIC) == 0) {
+
			if (pkgdb_it_next(it, &p, PKG_LOAD_BASIC) == EPKG_OK) {
				deps[i]->type = PKG_INSTALLED;
			} else {
				deps[i]->type = PKG_NOTFOUND;
@@ -309,9 +296,9 @@ pkg_open2(struct pkg **pkg_p, struct archive **a, struct archive_entry **ae, con
	}

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

	pkg = *pkg_p;
	pkg->type = PKG_FILE;
@@ -384,7 +371,7 @@ pkg_open2(struct pkg **pkg_p, struct archive **a, struct archive_entry **ae, con
}

int
-
pkg_new(struct pkg **pkg)
+
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)));
@@ -416,11 +403,13 @@ pkg_new(struct pkg **pkg)
		(*pkg)->fields[fields[i].id].optional = fields[i].optional;
	}

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

	return (EPKG_OK);
}

void
-
pkg_reset(struct pkg *pkg)
+
pkg_reset(struct pkg *pkg, pkg_t type)
{
	if (pkg == NULL)
		return;
@@ -439,8 +428,9 @@ pkg_reset(struct pkg *pkg)
	array_reset(&pkg->conflicts, &pkg_conflict_free_void);
	array_reset(&pkg->files, &free);
	array_reset(&pkg->scripts, &pkg_script_free_void);
-
	array_reset(&pkg->exec, &pkg_exec_free_void);
	array_reset(&pkg->options, &pkg_option_free_void);
+

+
	pkg->type = type;
}

void
@@ -457,7 +447,6 @@ pkg_free(struct pkg *pkg)
	array_free(&pkg->conflicts, &pkg_conflict_free_void);
	array_free(&pkg->files, &free);
	array_free(&pkg->scripts, &pkg_script_free_void);
-
	array_free(&pkg->exec, &pkg_exec_free_void);
	array_free(&pkg->options, &pkg_option_free_void);

	free(pkg);
@@ -566,9 +555,11 @@ pkg_addscript(struct pkg *pkg, const char *path)
}

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

	if (pkg == NULL)
		return (ERROR_BAD_ARG("pkg"));
@@ -576,13 +567,28 @@ pkg_addexec(struct pkg *pkg, const char *cmd, pkg_exec_t type)
	if (cmd == NULL || cmd[0] == '\0')
		return (ERROR_BAD_ARG("cmd"));

-
	pkg_exec_new(&exec);
+
	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;
+
			}
+
		}
+
	}
+

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

-
	sbuf_set(&exec->cmd, cmd);
-
	exec->type = type;
+
	pkg_script_new(&p_i_script);
+
	sbuf_set(&p_i_script->data, cmd);

-
	array_init(&pkg->exec, 5);
-
	array_append(&pkg->exec, exec);
+
	p_i_script->type = type;
+

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

	return (EPKG_OK);
}
@@ -629,12 +635,11 @@ pkg_adddep(struct pkg *pkg, const char *name, const char *origin, const char *ve
	if (version == NULL || version[0] == '\0')
		return (ERROR_BAD_ARG("version"));

-
	pkg_new(&dep);
+
	pkg_new(&dep, PKG_NOTFOUND);

	pkg_set(dep, PKG_NAME, name);
	pkg_set(dep, PKG_ORIGIN, origin);
	pkg_set(dep, PKG_VERSION, version);
-
	dep->type = PKG_NOTFOUND;

	array_init(&pkg->deps, 5);
	array_append(&pkg->deps, dep);
modified libpkg/pkg.h
@@ -7,7 +7,6 @@
struct pkg;
struct pkg_file;
struct pkg_conflict;
-
struct pkg_exec;
struct pkg_script;

struct pkgdb;
@@ -118,15 +117,6 @@ typedef enum _pkg_script_t {
} pkg_script_t;

/**
-
 * Determine the type of a pkg_exec.
-
 * @warning Legacy interface, may be removed later.
-
 */
-
typedef enum {
-
	PKG_EXEC = 0,
-
	PKG_UNEXEC
-
} pkg_exec_t;
-

-
/**
 * Error type used everywhere by libpkg.
 */
typedef enum {
@@ -165,13 +155,13 @@ typedef void (*fetch_cb)(void *data, const char *url, off_t total, off_t done,
 * Allocate a new pkg.
 * Allocated pkg must be deallocated by pkg_free().
 */
-
int pkg_new(struct pkg **);
+
int pkg_new(struct pkg **, pkg_t type);

/**
 * Reset a pkg to its initial state.
 * Useful to avoid sequences of pkg_new() and pkg_free().
 */
-
void pkg_reset(struct pkg *);
+
void pkg_reset(struct pkg *, pkg_t type);

/**
 * Deallocate a pkg
@@ -242,12 +232,6 @@ struct pkg_conflict ** pkg_conflicts(struct pkg *);
struct pkg_script ** pkg_scripts(struct pkg *);

/**
-
 * @return NULL-terminated array of pkg_exec.
-
 * @warning Legacy interface, may be removed later.
-
 */
-
struct pkg_exec ** pkg_execs(struct pkg *);
-

-
/**
 * @return NULL-terminated array of pkg_option
 */
struct pkg_option ** pkg_options(struct pkg *);
@@ -314,11 +298,6 @@ int pkg_addfile(struct pkg *pkg, const char *path, const char *sha256);
 */
int pkg_addconflict(struct pkg *pkg, const char *glob);

-
/**
-
 * Allocate a new struct pkg_exec and add it to the execs of pkg.
-
 * @return An error code.
-
 */
-
int pkg_addexec(struct pkg *pkg, const char *cmd, pkg_exec_t type);

/**
 * Allocate a new struct pkg_script and add it to the scripts of pkg.
@@ -326,6 +305,7 @@ int pkg_addexec(struct pkg *pkg, const char *cmd, pkg_exec_t type);
 @ @return An error code.
 */
int pkg_addscript(struct pkg *pkg, const char *path);
+
int pkg_appendscript(struct pkg *pkg, const char *cmd, pkg_script_t type);

/**
 * Allocate a new struct pkg_option and add it to the options of pkg.
@@ -368,12 +348,6 @@ void pkg_script_free(struct pkg_script *);
const char *pkg_script_data(struct pkg_script *);
pkg_script_t pkg_script_type(struct pkg_script *);

-
int pkg_exec_new(struct pkg_exec **);
-
void pkg_exec_reset(struct pkg_exec *);
-
void pkg_exec_free(struct pkg_exec *);
-
const char *pkg_exec_cmd(struct pkg_exec *);
-
pkg_exec_t pkg_exec_type(struct pkg_exec *);
-

/* pkg_option */
int pkg_option_new(struct pkg_option **);
void pkg_option_reset(struct pkg_option *);
@@ -453,7 +427,6 @@ struct pkgdb_it * pkgdb_query_which(struct pkgdb *db, const char *path);
#define PKG_LOAD_RDEPS (1<<1)
#define PKG_LOAD_CONFLICTS (1<<2)
#define PKG_LOAD_FILES (1<<3)
-
#define PKG_LOAD_EXECS (1<<4)
#define PKG_LOAD_SCRIPTS (1<<5)
#define PKG_LOAD_OPTIONS (1<<6)
#define PKG_LOAD_MTREE (1<<7)
@@ -476,7 +449,6 @@ int pkgdb_loaddeps(struct pkgdb *db, struct pkg *pkg);
int pkgdb_loadrdeps(struct pkgdb *db, struct pkg *pkg);
int pkgdb_loadconflicts(struct pkgdb *db, struct pkg *pkg);
int pkgdb_loadfiles(struct pkgdb *db, struct pkg *pkg);
-
int pkgdb_loadexecs(struct pkgdb *db, struct pkg *pkg);
int pkgdb_loadscripts(struct pkgdb *db, struct pkg *pkg);
int pkgdb_loadoptions(struct pkgdb *db, struct pkg *pkg);
int pkgdb_loadmtree(struct pkgdb *db, struct pkg *pkg);
@@ -530,10 +502,7 @@ int pkg_repo_fetch(struct pkg *pkg, void *data, fetch_cb cb);
 * Generally speaking, external consumers should not use these.
 * @return An error code on failure, or EPKG_OK.
 */
-
int pkg_pre_deinstall(struct pkg *pkg);
int pkg_delete_files(struct pkg *pkg, int force);
-
int pkg_post_deinstall(struct pkg *pkg);
-
int pkg_run_unexecs(struct pkg *pkg);

/**
 * Get the value of a configuration key
@@ -584,4 +553,13 @@ void pkg_error_warn(const char *fmt, ...);
 */
int pkg_copy_tree(struct pkg *, const char *src, const char *dest);

+
/**
+
 * scripts handling
+
 */
+
int pkg_script_pre_install(struct pkg *);
+
int pkg_script_post_install(struct pkg *);
+
int pkg_script_pre_upgrade(struct pkg *);
+
int pkg_script_post_upgrade(struct pkg *);
+
int pkg_script_pre_deinstall(struct pkg *);
+
int pkg_script_post_deinstall(struct pkg *);
#endif
modified libpkg/pkg_add.c
@@ -58,9 +58,6 @@ pkg_add(struct pkgdb *db, const char *path, struct pkg **pkg_p)
	struct pkg *p = NULL;
	struct pkg *pkg = NULL;
	struct pkg **deps;
-
	struct pkg_exec **execs;
-
	struct pkg_script **scripts;
-
	struct sbuf *script_cmd;
	bool extract = true;
	char dpath[MAXPATHLEN];
	const char *basedir;
@@ -156,75 +153,25 @@ pkg_add(struct pkgdb *db, const char *path, struct pkg **pkg_p)
	/*
	 * Execute pre-install scripts
	 */
-
	script_cmd = sbuf_new_auto();
-

-
	if ((scripts = pkg_scripts(pkg)) != NULL)
-
		for (i= 0; scripts[i] != NULL; i++) {
-
			switch (pkg_script_type(scripts[i])) {
-
				case PKG_SCRIPT_INSTALL:
-
					sbuf_reset(script_cmd);
-
					sbuf_printf(script_cmd, "set -- %s-%s INSTALL\n%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
-
					sbuf_finish(script_cmd);
-
					system(sbuf_data(script_cmd));
-
					break;
-
				case PKG_SCRIPT_PRE_INSTALL:
-
					sbuf_reset(script_cmd);
-
					sbuf_printf(script_cmd, "set -- %s-%s\n%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
-
					sbuf_finish(script_cmd);
-
					system(sbuf_data(script_cmd));
-
					break;
-
				default:
-
					/* just ignore */
-
					break;
-
			}
-
		}
+
	pkg_script_pre_install(pkg);

	/*
	 * Extract the files on disk.
	 */
-
	if (extract == true && (retcode = do_extract(a, ae)) != EPKG_OK)
+
	if (extract == true && (retcode = do_extract(a, ae)) != EPKG_OK) {
+
		/* If the add failed, clean up */
+
		(void) pkg_delete_files(pkg, 1);
		goto cleanup;
+
	}

	/*
	 * Execute post install scripts
	 */
-
	if (scripts != NULL)
-
		for (i= 0; scripts[i] != NULL; i++) {
-
			switch (pkg_script_type(scripts[i])) {
-
				case PKG_SCRIPT_INSTALL:
-
					sbuf_reset(script_cmd);
-
					sbuf_printf(script_cmd, "set -- %s-%s POST-INSTALL\n%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
-
					sbuf_finish(script_cmd);
-
					system(sbuf_data(script_cmd));
-
					break;
-
				case PKG_SCRIPT_POST_INSTALL:
-
					sbuf_reset(script_cmd);
-
					sbuf_printf(script_cmd, "set -- %s-%s\n%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
-
					sbuf_finish(script_cmd);
-
					system(sbuf_data(script_cmd));
-
					break;
-
				default:
-
					/* just ignore */
-
					break;
-
			}
-
		}
-

-
	sbuf_free(script_cmd);
-

-
	/*
-
	 * Execute @exec
-
	 */
-
	if ((execs = pkg_execs(pkg)) != NULL)
-
		for (i = 0; execs[i] != NULL; i++)
-
			if (pkg_exec_type(execs[i]) == PKG_EXEC)
-
				system(pkg_exec_cmd(execs[i]));
+
	pkg_script_post_install(pkg);

	cleanup:

	pkgdb_register_finale(db, retcode);
-
	/* If the add failed, clean up */
-
	if (retcode != EPKG_OK)
-
		(void) pkg_delete_files(pkg, 1);

	if (a != NULL)
		archive_read_finish(a);
modified libpkg/pkg_create.c
@@ -125,13 +125,15 @@ pkg_create_fakeroot(const char *outdir, pkg_formats format, const char *rootdir,
	/* Load the manifest from the metadata directory */
	if (asprintf(&manifest_path, "%s/+MANIFEST", metadatadir) == -1)
		goto cleanup;
-
	pkg_new(&pkg);
-
	pkg->type = PKG_FILE;
+

+
	pkg_new(&pkg, PKG_FILE);
	if (pkg == NULL)
		goto cleanup;
+

	ret = file_to_buffer(manifest_path, &manifest, &sz);
	if (ret != EPKG_OK)
		goto cleanup;
+

	ret = pkg_parse_manifest(pkg, manifest);

	/* Create the archive */
@@ -163,7 +165,7 @@ pkg_create_installed(const char *outdir, pkg_formats format, const char *rootdir
{
	struct packing *pkg_archive;
	int required_flags = PKG_LOAD_DEPS | PKG_LOAD_CONFLICTS | PKG_LOAD_FILES |
-
						 PKG_LOAD_EXECS | PKG_LOAD_SCRIPTS | PKG_LOAD_OPTIONS |
+
						 PKG_LOAD_SCRIPTS | PKG_LOAD_OPTIONS |
						 PKG_LOAD_MTREE;

	if (pkg->type != PKG_INSTALLED)
modified libpkg/pkg_delete.c
@@ -32,8 +32,6 @@ pkg_delete(struct pkg *pkg, struct pkgdb *db, int force)
		return (ret);
	if ((ret = pkgdb_loadscripts(db, pkg)) != EPKG_OK)
		return (ret);
-
	if ((ret = pkgdb_loadexecs(db, pkg)) != EPKG_OK)
-
		return (ret);
	if ((ret = pkgdb_loadmtree(db, pkg)) != EPKG_OK)
		return (ret);

@@ -48,7 +46,7 @@ pkg_delete(struct pkg *pkg, struct pkgdb *db, int force)
		}
		if (!force) {
			sbuf_finish(rdep_msg);
-
			ret = pkg_error_set(EPKG_REQUIRED, sbuf_get(rdep_msg));
+
			ret = pkg_error_set(EPKG_REQUIRED, "%s", sbuf_get(rdep_msg));
			sbuf_free(rdep_msg);
			return ret;
		}
@@ -58,39 +56,19 @@ pkg_delete(struct pkg *pkg, struct pkgdb *db, int force)
		sbuf_free(rdep_msg);
	}

-
	if ((ret = pkg_pre_deinstall(pkg)) != EPKG_OK)
+
	if ((ret = pkg_script_pre_deinstall(pkg)) != EPKG_OK)
		return (ret);

	if ((ret = pkg_delete_files(pkg, force)) != EPKG_OK)
		return (ret);

-
	if ((ret = pkg_post_deinstall(pkg)) != EPKG_OK)
-
		return (ret);
-

-
	if ((ret = pkg_run_unexecs(pkg)) != EPKG_OK)
+
	if ((ret = pkg_script_post_deinstall(pkg)) != EPKG_OK)
		return (ret);

	return (pkgdb_unregister_pkg(db, pkg_get(pkg, PKG_ORIGIN)));
}

int
-
pkg_run_unexecs(struct pkg *pkg)
-
{
-
	int ret = EPKG_OK;
-
	int i;
-
	struct pkg_exec **execs;
-

-
	execs = pkg_execs(pkg);
-

-
	/* run the @unexec */
-
	for (i = 0; execs[i] != NULL; i++)
-
		if (pkg_exec_type(execs[i]) == PKG_UNEXEC)
-
			system(pkg_exec_cmd(execs[i]));
-

-
	return (ret);
-
}
-

-
int
pkg_delete_files(struct pkg *pkg, int force)
{
	int do_remove, i;
@@ -110,6 +88,18 @@ pkg_delete_files(struct pkg *pkg, int force)
				warn("%s", path);
			continue;
		}
+
		/* Directories */
+

+
		if (path[strlen(path) - 1] == '/') {
+
			/*
+
			 * currently do not warn on this because multiple
+
			 * packages can own the same directory
+
			 */
+
			rmdir(path);
+
			continue;
+
		}
+

+
		/* Regular files and links */
		/* check sha256 */
		do_remove = 1;
		if (pkg_file_sha256(files[i])[0] != '\0') {
@@ -127,85 +117,12 @@ pkg_delete_files(struct pkg *pkg, int force)
				}
			}
		}
-
		if (do_remove && unlink(pkg_file_path(files[i])) == -1) {
-
			if (is_dir(pkg_file_path(files[i]))) {
-
				rmdir(pkg_file_path(files[i]));
-
			} else {
-
				warn("unlink(%s)", pkg_file_path(files[i]));
-
				continue;
-
			}
-
		}
-
	}
-

-
	return (ret);
-
}
-

-
int
-
pkg_pre_deinstall(struct pkg *pkg)
-
{
-
	int ret = EPKG_OK;
-
	int i;
-
	struct sbuf *script_cmd;
-
	struct pkg_script **scripts;
-

-
	script_cmd = sbuf_new_auto();
-
	scripts = pkg_scripts(pkg);
-
	/* execute PRE_DEINSTALL */
-
	for (i = 0; scripts[i] != NULL; i++) {
-
		switch (pkg_script_type(scripts[i])) {
-
			case PKG_SCRIPT_DEINSTALL:
-
				sbuf_reset(script_cmd);
-
				sbuf_printf(script_cmd, "set -- %s-%s DEINSTALL\n%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
-
				sbuf_finish(script_cmd);
-
				system(sbuf_data(script_cmd));
-
				break;
-
			case PKG_SCRIPT_PRE_DEINSTALL:
-
				sbuf_reset(script_cmd);
-
				sbuf_printf(script_cmd, "set -- %s-%s\n%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
-
				sbuf_finish(script_cmd);
-
				system(sbuf_data(script_cmd));
-
				break;
-
			default:
-
				/* just ignore */
-
				break;
-
		}
-
	}
-
	sbuf_free(script_cmd);

-
	return (ret);
-
}
-

-
int
-
pkg_post_deinstall(struct pkg *pkg)
-
{
-
	int i;
-
	int ret = EPKG_OK;
-
	struct sbuf *script_cmd;
-
	struct pkg_script **scripts;
-

-
	script_cmd = sbuf_new_auto();
-
	scripts = pkg_scripts(pkg);
-

-
	for (i = 0; scripts[i] != NULL; i++) {
-
		switch (pkg_script_type(scripts[i])) {
-
			case PKG_SCRIPT_DEINSTALL:
-
				sbuf_reset(script_cmd);
-
				sbuf_printf(script_cmd, "set -- %s-%s POST-DEINSTALL\n%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
-
				sbuf_finish(script_cmd);
-
				system(sbuf_data(script_cmd));
-
				break;
-
			case PKG_SCRIPT_POST_DEINSTALL:
-
				sbuf_reset(script_cmd);
-
				sbuf_printf(script_cmd, "set -- %s-%s\n%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
-
				sbuf_finish(script_cmd);
-
				system(sbuf_data(script_cmd));
-
				break;
-
			default:
-
				/* just ignore */
-
				break;
+
		if (do_remove && unlink(pkg_file_path(files[i])) == -1) {
+
			warn("unlink(%s)", pkg_file_path(files[i]));
+
			continue;
		}
	}
-
	sbuf_free(script_cmd);

	return (ret);
}
modified libpkg/pkg_elf.c
@@ -14,7 +14,7 @@ static int
analyse_elf(struct pkgdb *db, struct pkg *pkg, const char *fpath)
{
	struct pkg **deps;
-
	struct pkg *p;
+
	struct pkg *p = NULL;
	struct pkgdb_it *it = NULL;
	Elf *e;
	Elf_Scn *scn = NULL;
@@ -50,7 +50,6 @@ analyse_elf(struct pkgdb *db, struct pkg *pkg, const char *fpath)
	data = elf_getdata(scn, NULL);
	numdyn = shdr.sh_size / shdr.sh_entsize;

-
	pkg_new(&p);
	for (dynidx = 0; dynidx < numdyn; dynidx++) {
		if ((dyn = gelf_getdyn(data, dynidx, &dyn_mem)) == NULL)
			return (EPKG_FATAL);
@@ -66,7 +65,7 @@ analyse_elf(struct pkgdb *db, struct pkg *pkg, const char *fpath)
			if ((it = pkgdb_query_which(db, map->l_name)) == NULL)
				return (EPKG_FATAL);

-
			if (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC) == 0) {
+
			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++) {
@@ -81,7 +80,6 @@ analyse_elf(struct pkgdb *db, struct pkg *pkg, const char *fpath)
			}
			dlclose(handle);
		}
-
		pkg_reset(p);
		pkgdb_it_free(it);
	}
	pkg_free(p);
modified libpkg/pkg_exec.c
@@ -47,47 +47,3 @@ pkg_script_free_void(void *s)
	if (s != NULL)
		pkg_script_free((struct pkg_script *)s);
}
-

-
const char *
-
pkg_exec_cmd(struct pkg_exec *exec)
-
{
-
	return (sbuf_get(exec->cmd));
-
}
-

-
pkg_exec_t
-
pkg_exec_type(struct pkg_exec *exec)
-
{
-
	return (exec->type);
-
}
-

-
int
-
pkg_exec_new(struct pkg_exec **exec)
-
{
-
	if ((*exec = calloc(1, sizeof(struct pkg_exec))) == NULL)
-
		err(EXIT_FAILURE, "calloc()");
-

-
	return (0);
-
}
-

-
void
-
pkg_exec_reset(struct pkg_exec *exec)
-
{
-
	sbuf_reset(exec->cmd);
-
}
-

-
void
-
pkg_exec_free(struct pkg_exec *exec)
-
{
-
	if (exec == NULL)
-
		return;
-

-
	sbuf_free(exec->cmd);
-
	free(exec);
-
}
-

-
void
-
pkg_exec_free_void(void *e)
-
{
-
	if (e != NULL)
-
		pkg_exec_free((struct pkg_exec *)e);
-
}
modified libpkg/pkg_manifest.c
@@ -27,8 +27,6 @@ static int m_parse_option(struct pkg *pkg, char *buf);
static int m_parse_dep(struct pkg *pkg, char *buf);
static int m_parse_conflict(struct pkg *pkg, char *buf);
static int m_parse_maintainer(struct pkg *pkg, char *buf);
-
static int m_parse_exec(struct pkg *pkg, char *buf);
-
static int m_parse_unexec(struct pkg *pkg, char *buf);
static int m_parse_prefix(struct pkg *pkg, char *buf);
static int m_parse_file(struct pkg *pkg, char *buf);
static int m_parse_set_string(struct pkg *pkg, char *buf, pkg_attr attr);
@@ -51,8 +49,6 @@ static struct manifest_key {
	{ "@dep", m_parse_dep},
	{ "@conflict", m_parse_conflict},
	{ "@maintainer", m_parse_maintainer},
-
	{ "@exec", m_parse_exec},
-
	{ "@unexec", m_parse_unexec},
	{ "@prefix", m_parse_prefix},
	{ "@file", m_parse_file},
};
@@ -144,34 +140,6 @@ m_parse_flatsize(struct pkg *pkg, char *buf)
}

static int
-
m_parse_exec(struct pkg *pkg, char *buf)
-
{
-
	while (isspace(*buf))
-
		buf++;
-

-
	if (*buf == '\0')
-
		return (EPKG_FATAL);
-

-
	pkg_addexec(pkg, buf, PKG_EXEC);
-

-
	return (EPKG_OK);
-
}
-

-
static int
-
m_parse_unexec(struct pkg *pkg, char *buf)
-
{
-
	while (isspace(*buf))
-
		buf++;
-

-
	if (*buf == '\0')
-
		return (EPKG_FATAL);
-

-
	pkg_addexec(pkg, buf, PKG_UNEXEC);
-

-
	return (EPKG_OK);
-
}
-

-
static int
m_parse_option(struct pkg *pkg, char *buf)
{
	char *value;
@@ -316,7 +284,6 @@ pkg_emit_manifest(struct pkg *pkg, char **dest)
	struct sbuf *manifest;
	struct pkg **deps;
	struct pkg_conflict **conflicts;
-
	struct pkg_exec **execs;
	struct pkg_option **options;
	struct pkg_file **files;
	int i;
@@ -362,14 +329,6 @@ pkg_emit_manifest(struct pkg *pkg, char **dest)
		}
	}

-
	if ((execs = pkg_execs(pkg)) != NULL) {
-
		for (i = 0; execs[i] != NULL; i++) {
-
			sbuf_printf(manifest, "@%s %s\n",
-
					pkg_exec_type(execs[i]) == PKG_EXEC ? "exec" : "unexec",
-
					pkg_exec_cmd(execs[i]));
-
		}
-
	}
-

	if ((options = pkg_options(pkg)) != NULL)  {
		for (i = 0; options[i] != NULL; i++) {
			sbuf_printf(manifest, "@option %s %s\n",
modified libpkg/pkg_ports.c
@@ -25,6 +25,8 @@ ports_parse_plist(struct pkg *pkg, char *plist)
	int ret = EPKG_OK;
	off_t sz = 0;
	int64_t flatsize = 0;
+
	struct sbuf *exec_scripts = sbuf_new_auto();
+
	struct sbuf *unexec_scripts = sbuf_new_auto();

	buf = NULL;
	p = NULL;
@@ -71,9 +73,9 @@ ports_parse_plist(struct pkg *pkg, char *plist)
					continue;

				if (plist_p[1] == 'u')
-
					pkg_addexec(pkg, cmd, PKG_UNEXEC);
+
					sbuf_printf(unexec_scripts, "%s\n", cmd);
				else
-
					pkg_addexec(pkg, cmd, PKG_EXEC);
+
					sbuf_printf(exec_scripts, "%s\n", cmd);

				free(cmd);

@@ -89,9 +91,9 @@ ports_parse_plist(struct pkg *pkg, char *plist)
					buf++;

				if (prefix[strlen(prefix) -1 ] == '/')
-
					snprintf(path, MAXPATHLEN, "%s%s", prefix, buf);
+
					snprintf(path, MAXPATHLEN, "%s%s/", prefix, buf);
				else
-
					snprintf(path, MAXPATHLEN, "%s/%s", prefix, buf);
+
					snprintf(path, MAXPATHLEN, "%s/%s/", prefix, buf);

				if (lstat(path, &st) >= 0)
					flatsize += st.st_size;
@@ -130,6 +132,17 @@ ports_parse_plist(struct pkg *pkg, char *plist)
	}

	pkg_setflatsize(pkg, flatsize);
+
	if (sbuf_len(exec_scripts) > 0) {
+
		sbuf_done(exec_scripts);
+
		pkg_appendscript(pkg, sbuf_data(exec_scripts), PKG_SCRIPT_POST_INSTALL);
+
	}
+
	if (sbuf_len(unexec_scripts) > 0) {
+
		sbuf_done(unexec_scripts);
+
		pkg_appendscript(pkg, sbuf_data(unexec_scripts), PKG_SCRIPT_POST_DEINSTALL);
+
	}
+

+
	sbuf_delete(exec_scripts);
+
	sbuf_delete(unexec_scripts);

	free(plist_buf);

modified libpkg/pkg_private.h
@@ -29,7 +29,6 @@ struct pkg {
	struct array conflicts;
	struct array files;
	struct array scripts;
-
	struct array exec;
	struct array options;
	int flags;
	int64_t rowid;
@@ -45,11 +44,6 @@ struct pkg_script {
	pkg_script_t type;
};

-
struct pkg_exec {
-
	struct sbuf *cmd;
-
	pkg_exec_t type;
-
};
-

struct pkg_file {
	char path[MAXPATHLEN];
	char sha256[65];
@@ -62,7 +56,6 @@ struct pkg_option {

void pkg_conflict_free_void(void *);
void pkg_script_free_void(void *);
-
void pkg_exec_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);
modified libpkg/pkgdb.c
@@ -117,10 +117,6 @@ pkgdb_pkggt(sqlite3_context *ctx, int argc, sqlite3_value **argv)
 * - 7: DEINSTALL
 * - 8: UPGRADE
 * 
-
 * exec.type can be:
-
 * - 0: exec
-
 * - 1: unexec
-
 *
 */

static int
@@ -147,6 +143,27 @@ pkgdb_init(sqlite3 *sdb)
		"automatic INTEGER,"
		"pkg_format_version INTEGER"
	");"
+
	"CREATE TABLE mtree ("
+
		"id INTEGER PRIMARY KEY,"
+
		"content TEXT UNIQUE"
+
	");"
+
	"CREATE TRIGGER clean_mtree AFTER DELETE ON packages BEGIN "
+
		"DELETE FROM mtree WHERE id NOT IN (SELECT DISTINCT mtree_id FROM packages);"
+
	"END;"
+
	"CREATE VIEW pkg_mtree AS "
+
	"SELECT origin, name, version, comment, desc, mtree.content AS mtree, message, arch, osversion, "
+
	"maintainer, www, prefix, flatsize, automatic, pkg_format_version FROM packages "
+
	"INNER JOIN mtree ON packages.mtree_id = mtree.id;"
+
	"CREATE TRIGGER pkg_insert INSTEAD OF INSERT ON pkg_mtree "
+
	"FOR EACH ROW BEGIN "
+
		"INSERT OR IGNORE INTO mtree (content) VALUES (NEW.mtree);"
+
		"INSERT OR REPLACE INTO packages(origin, name, version, comment, desc, mtree_id, "
+
		"message, arch, osversion, maintainer, www, prefix, flatsize) "
+
		"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);"
+
	"END;"
	"CREATE TABLE scripts ("
		"package_id INTEGER REFERENCES packages(id) ON DELETE CASCADE"
			" ON UPDATE CASCADE,"
@@ -155,13 +172,6 @@ pkgdb_init(sqlite3 *sdb)
		"PRIMARY KEY (package_id, type)"
	");"
	"CREATE INDEX scripts_package ON scripts(package_id);"
-
	"CREATE TABLE exec ("
-
		"package_id INTEGER REFERENCES packages(id) ON DELETE CASCADE"
-
			" ON UPDATE CASCADE,"
-
		"cmd TEXT,"
-
		"type INTEGER"
-
	");"
-
	"CREATE INDEX exec_package ON exec(package_id);"
	"CREATE TABLE options ("
		"package_id INTEGER REFERENCES packages(id) ON DELETE CASCADE"
			" ON UPDATE CASCADE,"
@@ -194,14 +204,31 @@ pkgdb_init(sqlite3 *sdb)
		"PRIMARY KEY (package_id,name)"
	");"
	"CREATE INDEX conflicts_package ON conflicts(package_id);"
-
	"CREATE TABLE mtree ("
-
		"id INTEGER PRIMARY KEY,"
-
		"sha256 TEXT UNIQUE,"
-
		"content TEXT"
+
	"CREATE TABLE directories ("
+
		"id INTEGER PRIMARY KEY, "
+
		"path TEXT "
	");"
-
	"CREATE TRIGGER clean_mtree AFTER DELETE ON packages BEGIN "
-
		"DELETE FROM mtree WHERE rowid NOT IN (SELECT DISTINCT mtree_id FROM packages);"
-
	"END;";
+
	"CREATE TABLE pkg_dirs_assoc ("
+
		"package_id INTEGER REFERENCES packages(id) ON DELETE CASCADE"
+
			" ON UPDATE CASCADE, "
+
		"directory_id INTEGER REFERENCES directories(id) ON DELETE RESTRICT"
+
			" ON UPDATE RESTRICT, "
+
		"PRIMARY KEY (package_id, directory_id)"
+
	");"
+
	"CREATE VIEW pkg_dirs AS SELECT origin, path FROM packages "
+
	"INNER JOIN pkg_dirs_assoc ON packages.id = pkg_dirs_assoc.package_id "
+
	"INNER JOIN directories ON pkg_dirs_assoc.directory_id = directories.id;"
+
	"CREATE TRIGGER pkg_dirs_clean AFTER DELETE ON packages BEGIN "
+
		"DELETE from directories WHERE id NOT IN (SELECT DISTINCT directory_id FROM pkg_dirs_assoc);"
+
	"END;"
+
	"CREATE TRIGGER dir_insert INSTEAD OF INSERT ON pkg_dirs "
+
	"FOR EACH ROW BEGIN "
+
		"INSERT OR IGNORE INTO directories (path) VALUES (NEW.path);"
+
		"INSERT INTO pkg_dirs_assoc (package_id, directory_id) VALUES "
+
			"((SELECT id FROM packages WHERE origin = NEW.origin), "
+
			"(SELECT id FROM directories WHERE path = NEW.path));"
+
	"END;"
+
	;

	if (sqlite3_exec(sdb, sql, NULL, NULL, &errmsg) != SQLITE_OK) {
		pkg_error_set(EPKG_FATAL, "sqlite: %s", errmsg);
@@ -275,7 +302,7 @@ pkgdb_open(struct pkgdb **db, pkgdb_t remote, int mode)
	sqlite3_create_function((*db)->sqlite, "pkggt", 2, SQLITE_ANY, NULL,
			pkgdb_pkggt, NULL, NULL);

-
	/* 
+
	/*
	 * allow forign key option which will allow to have clean support for
	 * reinstalling
	 */
@@ -334,12 +361,11 @@ pkgdb_it_next(struct pkgdb_it *it, struct pkg **pkg_p, int flags)
	switch (sqlite3_step(it->stmt)) {
	case SQLITE_ROW:
		if (*pkg_p == NULL)
-
			pkg_new(pkg_p);
+
			pkg_new(pkg_p, PKG_INSTALLED);
		else
-
			pkg_reset(*pkg_p);
+
			pkg_reset(*pkg_p, PKG_INSTALLED);
		pkg = *pkg_p;

-
		pkg->type = PKG_INSTALLED;
		pkg->rowid = sqlite3_column_int64(it->stmt, 0);
		pkg_set(pkg, PKG_ORIGIN, sqlite3_column_text(it->stmt, 1));
		pkg_set(pkg, PKG_NAME, sqlite3_column_text(it->stmt, 2));
@@ -379,10 +405,6 @@ pkgdb_it_next(struct pkgdb_it *it, struct pkg **pkg_p, int flags)
			if ((ret = pkgdb_loadfiles(it->db, pkg)) != EPKG_OK)
				return (ret);

-
		if (flags & PKG_LOAD_EXECS)
-
			if ((ret = pkgdb_loadexecs(it->db, pkg)) != EPKG_OK)
-
				return (ret);
-

		if (flags & PKG_LOAD_SCRIPTS)
			if ((ret = pkgdb_loadscripts(it->db, pkg)) != EPKG_OK)
				return (ret);
@@ -638,13 +660,19 @@ int
pkgdb_loadfiles(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 DESC";
+
		"ORDER BY PATH ASC";
+
	const char sqldir[] = ""
+
		"SELECT path "
+
		"FROM pkg_dirs "
+
		"WHERE origin = ?1 "
+
		"ORDER by path DESC";

	if (pkg->type != PKG_INSTALLED)
		return (ERROR_BAD_ARG("pkg"));
@@ -672,48 +700,19 @@ pkgdb_loadfiles(struct pkgdb *db, struct pkg *pkg)
		return (ERROR_SQLITE(db->sqlite));
	}

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

-
int
-
pkgdb_loadexecs(struct pkgdb *db, struct pkg *pkg)
-
{
-
	sqlite3_stmt *stmt;
-
	struct pkg_exec *e;
-
	int ret;
-
	const char sql[] = ""
-
		"SELECT cmd, type "
-
		"FROM exec "
-
		"WHERE package_id = ?1";
-

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

-
	if (pkg->flags & PKG_LOAD_EXECS)
-
		return (EPKG_OK);
-

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

-
	if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK)
+
	if (sqlite3_prepare_v2(db->sqlite, sqldir, -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_exec_new(&e);
-
		sbuf_set(&e->cmd, sqlite3_column_text(stmt, 0));
-
		e->type = sqlite3_column_int(stmt, 1);
-
		array_append(&pkg->exec, e);
+
		pkg_file_new(&f);
+
		strlcpy(f->path, sqlite3_column_text(stmt, 0), sizeof(f->path));
+
		array_append(&pkg->files, f);
	}
	sqlite3_finalize(stmt);

-
	if (ret != SQLITE_DONE) {
-
		array_reset(&pkg->exec, &pkg_exec_free_void);
-
		return (ERROR_SQLITE(db->sqlite));
-
	}
-

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

@@ -854,43 +853,35 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
	struct pkg **deps;
	struct pkg_file **files;
	struct pkg_conflict **conflicts;
-
	struct pkg_exec **execs;
	struct pkg_script **scripts;
	struct pkg_option **options;

	sqlite3 *s;
-
	sqlite3_stmt *stmt_sel_mtree = NULL;
-
	sqlite3_stmt *stmt_mtree = NULL;
	sqlite3_stmt *stmt_pkg = NULL;
+
	sqlite3_stmt *stmt_sel_pkg = NULL;
	sqlite3_stmt *stmt_dep = NULL;
	sqlite3_stmt *stmt_conflict = NULL;
	sqlite3_stmt *stmt_file = NULL;
-
	sqlite3_stmt *stmt_exec = NULL;
	sqlite3_stmt *stmt_script = NULL;
	sqlite3_stmt *stmt_option = NULL;
+
	sqlite3_stmt *stmt_dirs = NULL;

	int i;
	int ret;
	int retcode = EPKG_OK;
+
	const char *path;
	int64_t package_id;
-
	int64_t mtree_id;
-
	char mtree_sha256[65];
	char *errmsg;
-
	const char *mtree;

	const char sql_begin[] = "BEGIN TRANSACTION;";
-
	const char sql_sel_mtree[] = ""
-
		"SELECT id "
-
		"FROM mtree "
-
		"WHERE sha256 = ?1;";
-
	const char sql_mtree[] = ""
-
		"INSERT INTO mtree (sha256, content) "
-
		"VALUES (?1, ?2);";
	const char sql_pkg[] = ""
-
		"INSERT OR REPLACE INTO packages( "
-
			"origin, name, version, comment, desc, mtree_id, message, arch, "
+
		"INSERT INTO pkg_mtree( "
+
			"origin, name, version, comment, desc, mtree, message, arch, "
			"osversion, maintainer, www, prefix, flatsize) "
		"VALUES( ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13);";
+
	const char sql_sel_pkg[] = ""
+
		"SELECT id FROM packages "
+
		"WHERE origin = ?1;";
	const char sql_dep[] = ""
		"INSERT INTO deps (origin, name, version, package_id) "
		"VALUES (?1, ?2, ?3, ?4);";
@@ -903,12 +894,12 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
	const char sql_script[] = ""
		"INSERT INTO scripts (script, type, package_id) "
		"VALUES (?1, ?2, ?3);";
-
	const char sql_exec[] = ""
-
		"INSERT INTO exec (cmd, type, package_id) "
-
		"VALUES (?1, ?2, ?3);";
	const char sql_option[] = ""
		"INSERT INTO options (option, value, package_id) "
		"VALUES (?1, ?2, ?3);";
+
	const char sql_dir[] = ""
+
		"INSERT INTO pkg_dirs(origin, path) "
+
		"VALUES (?1, ?2);";

	if (pkgdb_has_flag(db, PKGDB_FLAG_IN_FLIGHT)) {
		pkg_error_set(EPKG_FATAL, "tried to register a package with an in-flight SQL command");
@@ -925,60 +916,6 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
	PKGDB_SET_FLAG(db, PKGDB_FLAG_IN_FLIGHT);

	/*
-
	 * If this package has a mtree, insert it in the database.
-
	 * Compute the sha256 of the mtree.
-
	 * If there is no mtree, mtree_id is set to zero (NULL in the database).
-
	 */
-
	mtree = pkg_get(pkg, PKG_MTREE);
-
	if (mtree != NULL) {
-
		sha256_str(mtree, mtree_sha256);
-

-
		/* Try to find the mtree in the database */
-
		if (sqlite3_prepare_v2(s, sql_sel_mtree, -1, &stmt_sel_mtree, NULL)
-
			!= SQLITE_OK) {
-
			retcode = ERROR_SQLITE(s);
-
			goto cleanup;
-
		}
-

-
		sqlite3_bind_text(stmt_sel_mtree, 1, mtree_sha256, -1, SQLITE_STATIC);
-

-
		ret = sqlite3_step(stmt_sel_mtree);
-
		if (ret == SQLITE_ROW) {
-
			mtree_id = sqlite3_column_int64(stmt_sel_mtree, 0);
-
			ret = SQLITE_DONE;
-
		} else if (ret == SQLITE_DONE)
-
			/* no result found */
-
			mtree_id = 0;
-

-
		if (ret != SQLITE_DONE) {
-
			retcode = ERROR_SQLITE(s);
-
			goto cleanup;
-
		}
-

-
		/* if the mtree is not into the dabase, insert it */
-
		if (mtree_id == 0) {
-
			if (sqlite3_prepare_v2(s, sql_mtree, -1, &stmt_mtree, NULL) !=
-
								SQLITE_OK) {
-
				retcode = ERROR_SQLITE(s);
-
				goto cleanup;
-
			}
-

-
			sqlite3_bind_text(stmt_mtree, 1, mtree_sha256, -1, SQLITE_STATIC);
-
			sqlite3_bind_text(stmt_mtree, 2, mtree, -1, SQLITE_STATIC);
-

-
			ret = sqlite3_step(stmt_mtree);
-
			if (ret != SQLITE_DONE) {
-
				retcode = ERROR_SQLITE(s);
-
				goto cleanup;
-
			}
-

-
			mtree_id = sqlite3_last_insert_rowid(s);
-
		}
-
	} else {
-
		mtree_id = 0;
-
	}
-

-
	/*
	 * Insert package record
	 */
	if (sqlite3_prepare_v2(s, sql_pkg, -1, &stmt_pkg, NULL) != SQLITE_OK) {
@@ -990,10 +927,7 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
	sqlite3_bind_text(stmt_pkg, 3, pkg_get(pkg, PKG_VERSION), -1, SQLITE_STATIC);
	sqlite3_bind_text(stmt_pkg, 4, pkg_get(pkg, PKG_COMMENT), -1, SQLITE_STATIC);
	sqlite3_bind_text(stmt_pkg, 5, pkg_get(pkg, PKG_DESC), -1, SQLITE_STATIC);
-
	if (mtree_id > 0)
-
		sqlite3_bind_int64(stmt_pkg, 6, mtree_id);
-
	else
-
		sqlite3_bind_null(stmt_pkg, 6);
+
	sqlite3_bind_text(stmt_pkg, 6, pkg_get(pkg, PKG_MTREE), -1, SQLITE_STATIC);
	sqlite3_bind_text(stmt_pkg, 7, pkg_get(pkg, PKG_MESSAGE), -1, SQLITE_STATIC);
	sqlite3_bind_text(stmt_pkg, 8, pkg_get(pkg, PKG_ARCH), -1, SQLITE_STATIC);
	sqlite3_bind_text(stmt_pkg, 9, pkg_get(pkg, PKG_OSVERSION), -1, SQLITE_STATIC);
@@ -1002,21 +936,39 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
	sqlite3_bind_text(stmt_pkg, 12, pkg_get(pkg, PKG_PREFIX), -1, SQLITE_STATIC);
	sqlite3_bind_int64(stmt_pkg, 13, pkg_flatsize(pkg));

-
	if (sqlite3_step(stmt_pkg) != SQLITE_DONE) {
-
		retcode = ERROR_SQLITE(s);
+
	if ((ret = sqlite3_step(stmt_pkg)) != SQLITE_DONE) {
+
		if ( ret == SQLITE_CONSTRAINT)
+
			retcode = pkg_error_set(EPKG_FATAL, "constraint violation on "
+
					"pkg with %s", pkg_get(pkg, PKG_ORIGIN));
+
		else
+
			retcode = ERROR_SQLITE(s);
		goto cleanup;
	}

	/*
	 * Get the generated package_id
	 */
-
	package_id = sqlite3_last_insert_rowid(s);
+

+
	if (sqlite3_prepare_v2(s, sql_sel_pkg, -1, &stmt_sel_pkg, NULL) != SQLITE_OK) {
+
		retcode = ERROR_SQLITE(s);
+
		goto cleanup;
+
	}
+
	sqlite3_bind_text(stmt_sel_pkg, 1, pkg_get(pkg, PKG_ORIGIN), -1, SQLITE_STATIC);
+
	ret = sqlite3_step(stmt_sel_pkg);
+
	if (ret == SQLITE_ROW) {
+
		package_id = sqlite3_column_int64(stmt_sel_pkg, 0);
+
		ret = SQLITE_DONE;
+
	} else {
+
		retcode = ERROR_SQLITE(s);
+
		goto cleanup;
+
	}

	/*
	 * Insert dependencies list
	 */

	if (sqlite3_prepare_v2(s, sql_dep, -1, &stmt_dep, NULL) != SQLITE_OK) {
+

		retcode = ERROR_SQLITE(s);
		goto cleanup;
	}
@@ -1028,8 +980,12 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
		sqlite3_bind_text(stmt_dep, 3, pkg_get(deps[i], PKG_VERSION), -1, SQLITE_STATIC);
		sqlite3_bind_int64(stmt_dep, 4, package_id);

-
		if (sqlite3_step(stmt_dep) != SQLITE_DONE) {
-
			retcode = ERROR_SQLITE(s);
+
		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));
+
			else
+
				retcode = ERROR_SQLITE(s);
			goto cleanup;
		}

@@ -1040,8 +996,7 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
	 * Insert conflicts list
	 */

-
	if (sqlite3_prepare_v2(s, sql_conflict, -1, &stmt_conflict, NULL) !=
-
						SQLITE_OK) {
+
	if (sqlite3_prepare_v2(s, sql_conflict, -1, &stmt_conflict, NULL) != SQLITE_OK) {
		retcode = ERROR_SQLITE(s);
		goto cleanup;
	}
@@ -1052,7 +1007,11 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
		sqlite3_bind_int64(stmt_conflict, 2, package_id);

		if (sqlite3_step(stmt_conflict) != SQLITE_DONE) {
-
			retcode = ERROR_SQLITE(s);
+
			if ( ret == SQLITE_CONSTRAINT)
+
				retcode = pkg_error_set(EPKG_FATAL, "constraint violation on "
+
						"conflicts with %s", pkg_conflict_glob(conflicts[i]));
+
			else
+
				retcode = ERROR_SQLITE(s);
			goto cleanup;
		}

@@ -1061,6 +1020,7 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)

	/*
	 * Insert file
+
	 * and dirs
	 */

	if (sqlite3_prepare_v2(s, sql_file, -1, &stmt_file, NULL) != SQLITE_OK) {
@@ -1068,22 +1028,43 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
		goto cleanup;
	}

+
	if (sqlite3_prepare_v2(s, sql_dir, -1, &stmt_dirs, NULL) != SQLITE_OK) {
+
		retcode = ERROR_SQLITE(s);
+
		goto cleanup;
+
	}
+

	files = pkg_files(pkg);
	for (i = 0; files[i] != NULL; 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);
-
		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]));
-
			else
-
				retcode = ERROR_SQLITE(s);
-
			goto cleanup;
+
		path = pkg_file_path(files[i]);
+
		if (path[strlen(path) - 1 ] != '/') {
+
			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);
+
			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]));
+
				else
+
					retcode = ERROR_SQLITE(s);
+
				goto cleanup;
+
			}
+
			sqlite3_reset(stmt_file);
+
		} else {
+
			sqlite3_bind_text(stmt_dirs, 1, pkg_get(pkg, PKG_ORIGIN), -1, SQLITE_STATIC);
+
			sqlite3_bind_text(stmt_dirs, 2, pkg_file_path(files[i]), -1, SQLITE_STATIC);
+
			
+
			if ((ret = sqlite3_step(stmt_dirs)) != SQLITE_DONE) {
+
				if ( ret == SQLITE_CONSTRAINT)
+
					retcode = pkg_error_set(EPKG_FATAL, "constraint violation on "
+
							"dirs with %s", pkg_file_path(files[i]));
+
				else
+
					retcode = ERROR_SQLITE(s);
+
				goto cleanup;
+
			}
+
			sqlite3_reset(stmt_dirs);
		}

-
		sqlite3_reset(stmt_file);
	}

	/*
@@ -1102,7 +1083,11 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
		sqlite3_bind_int64(stmt_script, 3, package_id);

		if (sqlite3_step(stmt_script) != SQLITE_DONE) {
-
			retcode = ERROR_SQLITE(s);
+
			if ( ret == SQLITE_CONSTRAINT)
+
				retcode = pkg_error_set(EPKG_FATAL, "constraint violation on "
+
						"scripts with %s", pkg_script_data(scripts[i]));
+
			else
+
				retcode = ERROR_SQLITE(s);
			goto cleanup;
		}

@@ -1110,29 +1095,6 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
	}

	/*
-
	 * Insert execs
-
	 */
-

-
	if (sqlite3_prepare_v2(s, sql_exec, -1, &stmt_exec, NULL) != SQLITE_OK) {
-
		retcode = ERROR_SQLITE(s);
-
		goto cleanup;
-
	}
-

-
	execs = pkg_execs(pkg);
-
	for (i = 0; execs[i] != NULL; i++) {
-
		sqlite3_bind_text(stmt_exec, 1, pkg_exec_cmd(execs[i]), -1, SQLITE_STATIC);
-
		sqlite3_bind_int(stmt_exec, 2, pkg_exec_type(execs[i]));
-
		sqlite3_bind_int64(stmt_exec, 3, package_id);
-

-
		if (sqlite3_step(stmt_exec) != SQLITE_DONE) {
-
			retcode = ERROR_SQLITE(s);
-
			goto cleanup;
-
		}
-

-
		sqlite3_reset(stmt_exec);
-
	}
-

-
	/*
	 * Insert options
	 */

@@ -1157,15 +1119,12 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)

	cleanup:

-
	if (stmt_sel_mtree != NULL)
-
		sqlite3_finalize(stmt_sel_mtree);
-

-
	if (stmt_mtree != NULL)
-
		sqlite3_finalize(stmt_mtree);
-

	if (stmt_pkg != NULL)
		sqlite3_finalize(stmt_pkg);

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

	if (stmt_dep != NULL)
		sqlite3_finalize(stmt_dep);

@@ -1178,11 +1137,11 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
	if (stmt_script != NULL)
		sqlite3_finalize(stmt_script);

-
	if (stmt_exec != NULL)
-
		sqlite3_finalize(stmt_exec);
-

	if (stmt_option != NULL)
		sqlite3_finalize(stmt_option);
+
	
+
	if (stmt_dirs != NULL)
+
		sqlite3_finalize(stmt_dirs);

	return (retcode);
}
added libpkg/scripts.c
@@ -0,0 +1,214 @@
+
#include <pkg.h>
+
#include <pkg_private.h>
+
#include <pkg_error.h>
+

+
int
+
pkg_script_pre_install(struct pkg *pkg)
+
{
+
	int i;
+
	struct pkg_script **scripts;
+
	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])) {
+
			case PKG_SCRIPT_INSTALL:
+
				sbuf_reset(script_cmd);
+
				sbuf_printf(script_cmd, "set -- %s-%s PRE-INSTALL\n%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
				sbuf_finish(script_cmd);
+
				system(sbuf_data(script_cmd));
+
				break;
+
			case PKG_SCRIPT_PRE_INSTALL:
+
				sbuf_reset(script_cmd);
+
				sbuf_printf(script_cmd, "set -- %s-%s\n%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
				sbuf_finish(script_cmd);
+
				system(sbuf_data(script_cmd));
+
				break;
+
			default:
+
				/* ignored to prevent warning */
+
				break;
+
		}
+
	}
+

+
	sbuf_delete(script_cmd);
+

+
	return (EPKG_OK);
+
}
+

+
int
+
pkg_script_post_install(struct pkg *pkg)
+
{
+
	int i;
+
	struct pkg_script **scripts;
+
	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])) {
+
			case PKG_SCRIPT_INSTALL:
+
				sbuf_reset(script_cmd);
+
				sbuf_printf(script_cmd, "set -- %s-%s POST-INSTALL\n%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
				sbuf_finish(script_cmd);
+
				system(sbuf_data(script_cmd));
+
				break;
+
			case PKG_SCRIPT_POST_INSTALL:
+
				sbuf_reset(script_cmd);
+
				sbuf_printf(script_cmd, "set -- %s-%s\n%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
				sbuf_finish(script_cmd);
+
				system(sbuf_data(script_cmd));
+
				break;
+
			default:
+
				/* ignored to prevent warning */
+
				break;
+
		}
+
	}
+

+
	sbuf_delete(script_cmd);
+

+
	return (EPKG_OK);
+
}
+

+
int
+
pkg_script_pre_upgrade(struct pkg *pkg)
+
{
+
	int i;
+
	struct pkg_script **scripts;
+
	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])) {
+
			case PKG_SCRIPT_UPGRADE:
+
				sbuf_reset(script_cmd);
+
				sbuf_printf(script_cmd, "set -- %s-%s PRE-UPGRADE\n%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
				sbuf_finish(script_cmd);
+
				system(sbuf_data(script_cmd));
+
				break;
+
			case PKG_SCRIPT_PRE_UPGRADE:
+
				sbuf_reset(script_cmd);
+
				sbuf_printf(script_cmd, "set -- %s-%s\n%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
				sbuf_finish(script_cmd);
+
				system(sbuf_data(script_cmd));
+
				break;
+
			default:
+
				/* ignored to prevent warning */
+
				break;
+
		}
+
	}
+

+
	sbuf_delete(script_cmd);
+

+
	return (EPKG_OK);
+
}
+

+
int
+
pkg_script_post_upgrade(struct pkg *pkg)
+
{
+
	int i;
+
	struct pkg_script **scripts;
+
	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])) {
+
			case PKG_SCRIPT_UPGRADE:
+
				sbuf_reset(script_cmd);
+
				sbuf_printf(script_cmd, "set -- %s-%s POST-UPGRADE\n%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
				sbuf_finish(script_cmd);
+
				system(sbuf_data(script_cmd));
+
				break;
+
			case PKG_SCRIPT_POST_UPGRADE:
+
				sbuf_reset(script_cmd);
+
				sbuf_printf(script_cmd, "set -- %s-%s\n%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
				sbuf_finish(script_cmd);
+
				system(sbuf_data(script_cmd));
+
				break;
+
			default:
+
				/* ignored to prevent warning */
+
				break;
+
		}
+
	}
+

+
	sbuf_delete(script_cmd);
+

+
	return (EPKG_OK);
+
}
+

+
int
+
pkg_script_pre_deinstall(struct pkg *pkg)
+
{
+
	int i;
+
	struct pkg_script **scripts;
+
	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])) {
+
			case PKG_SCRIPT_DEINSTALL:
+
				sbuf_reset(script_cmd);
+
				sbuf_printf(script_cmd, "set -- %s-%s PRE-DEINSTALL\n%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
				sbuf_finish(script_cmd);
+
				system(sbuf_data(script_cmd));
+
				break;
+
			case PKG_SCRIPT_PRE_DEINSTALL:
+
				sbuf_reset(script_cmd);
+
				sbuf_printf(script_cmd, "set -- %s-%s\n%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
				sbuf_finish(script_cmd);
+
				system(sbuf_data(script_cmd));
+
				break;
+
			default:
+
				/* ignored to prevent warning */
+
				break;
+
		}
+
	}
+

+
	sbuf_delete(script_cmd);
+

+
	return (EPKG_OK);
+
}
+

+
int
+
pkg_script_post_deinstall(struct pkg *pkg)
+
{
+
	int i;
+
	struct pkg_script **scripts;
+
	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])) {
+
			case PKG_SCRIPT_DEINSTALL:
+
				sbuf_reset(script_cmd);
+
				sbuf_printf(script_cmd, "set -- %s-%s POST-DEINSTALL\n%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
				sbuf_finish(script_cmd);
+
				system(sbuf_data(script_cmd));
+
				break;
+
			case PKG_SCRIPT_POST_DEINSTALL:
+
				sbuf_reset(script_cmd);
+
				sbuf_printf(script_cmd, "set -- %s-%s\n%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_script_data(scripts[i]));
+
				sbuf_finish(script_cmd);
+
				system(sbuf_data(script_cmd));
+
				break;
+
			default:
+
				/* ignored to prevent warning */
+
				break;
+
		}
+
	}
+

+
	sbuf_delete(script_cmd);
+

+
	return (EPKG_OK);
+
}
+

modified pkg/create.c
@@ -26,7 +26,7 @@ pkg_create_matches(int argc, char **argv, match_t match, pkg_formats fmt, const
	struct pkgdb_it *it = NULL;
	struct pkg *pkg = NULL;
	int query_flags = PKG_LOAD_DEPS | PKG_LOAD_CONFLICTS | PKG_LOAD_FILES |
-
					  PKG_LOAD_EXECS | PKG_LOAD_SCRIPTS | PKG_LOAD_OPTIONS |
+
					  PKG_LOAD_SCRIPTS | PKG_LOAD_OPTIONS |
					  PKG_LOAD_MTREE;

	if (pkgdb_open(&db, PKGDB_DEFAULT, R_OK) != EPKG_OK) {
@@ -34,15 +34,30 @@ pkg_create_matches(int argc, char **argv, match_t match, pkg_formats fmt, const
		pkgdb_close(db);
		return (-1);
	}
-
	pkg_new(&pkg);
-
	for (i = 0;i < argc; i++) {
-
		if ((it = pkgdb_query(db, argv[i], match)) == NULL) {
+

+
	if (match != MATCH_ALL) {
+
		for (i = 0;i < argc; i++) {
+
			if ((it = pkgdb_query(db, argv[i], match)) == NULL) {
+
				pkg_error_warn("can not query database");
+
				goto cleanup;
+
			}
+
			while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) {
+
				printf("Creating package for %s-%s\n", pkg_get(pkg, PKG_NAME),
+
				    pkg_get(pkg, PKG_VERSION));
+
				if (pkg_create_installed(outdir, fmt, rootdir, pkg) != EPKG_OK) {
+
					pkg_error_warn("can not create package");
+
					retcode++;
+
				}
+
			}
+
		}
+
	} else {
+
		if ((it = pkgdb_query(db, NULL, match)) == NULL) {
			pkg_error_warn("can not query database");
			goto cleanup;
		}
		while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) {
			printf("Creating package for %s-%s\n", pkg_get(pkg, PKG_NAME),
-
			    pkg_get(pkg, PKG_VERSION));
+
					pkg_get(pkg, PKG_VERSION));
			if (pkg_create_installed(outdir, fmt, rootdir, pkg) != EPKG_OK) {
				pkg_error_warn("can not create package");
				retcode++;
modified pkg/delete.c
@@ -20,7 +20,7 @@ usage_delete(void)
int
exec_delete(int argc, char **argv)
{
-
	struct pkg *pkg;
+
	struct pkg *pkg = NULL;
	struct pkgdb *db;
	struct pkgdb_it *it;
	match_t match = MATCH_EXACT;
@@ -69,7 +69,6 @@ exec_delete(int argc, char **argv)
		return (1);
	}

-
	pkg_new(&pkg);
	while ((ret = pkgdb_it_next(it, &pkg, flags)) == EPKG_OK) {
		if (pkg_delete(pkg, db, force) != EPKG_OK) {
			retcode++;
modified pkg/info.c
@@ -166,8 +166,6 @@ exec_info(int argc, char **argv)
	if (argc == 0)
		match = MATCH_ALL;

-
	pkg_new(&pkg);
-

	if (pkgdb_open(&db, PKGDB_DEFAULT, R_OK) != EPKG_OK) {
		pkg_error_warn("can not open database");
		return (-1);
modified pkg/register.c
@@ -35,7 +35,8 @@ usage_register(void)
	fprintf(stderr, "usage: pkg register -c comment -d desc -f plist_file -p prefix\n");
	fprintf(stderr, "                    -m mtree_file -n pkgname -o origin -r maintainer\n");
	fprintf(stderr, "                    [-P depends] [-C conflicts] [-M message_file] [-s scripts]\n");
-
	fprintf(stderr, "                    [-a arch] [-w www] [-O options] [-H] [-i input_dir]\n\n");
+
	fprintf(stderr, "                    [-a arch] [-w www] [-O options] [-H] [-i input_dir]\n");
+
	fprintf(stderr, "                    [-l]\n\n");
	fprintf(stderr, "For more information see 'pkg help register'.\n");
}

@@ -60,6 +61,7 @@ exec_register(int argc, char **argv)
	size_t size;

	bool heuristic = false;
+
	bool legacy = false;

	int retcode = 0;
	int ret = 0;
@@ -69,8 +71,8 @@ exec_register(int argc, char **argv)
		return (EX_NOPERM);
	}

-
	pkg_new(&pkg);
-
	while ((ch = getopt(argc, argv, "vHc:d:f:p:P:m:o:C:n:M:s:a:r:w:O:i:")) != -1) {
+
	pkg_new(&pkg, PKG_INSTALLED);
+
	while ((ch = getopt(argc, argv, "vHc:d:f:p:P:m:o:C:n:M:s:a:r:w:O:i:l")) != -1) {
		switch (ch) {
			case 'v':
				/* IGNORE */
@@ -139,6 +141,9 @@ exec_register(int argc, char **argv)
				if ((input_path = strdup(optarg)) == NULL)
					errx(1, "cannot allocate memory");
				break;
+
			case 'l':
+
				legacy = true;
+
				break;
			default:
				printf("%c\n", ch);
				usage_register();
@@ -221,7 +226,13 @@ exec_register(int argc, char **argv)
		retcode = 1;
	}

-
	if (pkg_get(pkg, PKG_MESSAGE) != NULL)
+
	pkgdb_register_finale(db, ret);
+
	if (ret != EPKG_OK) {
+
		pkg_error_warn("can not register package");
+
		retcode = 1;
+
	}
+

+
	if (pkg_get(pkg, PKG_MESSAGE) != NULL && !legacy)
		printf("%s\n", pkg_get(pkg, PKG_MESSAGE));

	pkgdb_close(db);
modified pkg/which.c
@@ -23,7 +23,7 @@ exec_which(int argc, char **argv)
{
	struct pkgdb *db;
	struct pkgdb_it *it;
-
	struct pkg *pkg;
+
	struct pkg *pkg = NULL;
	char pathabs[MAXPATHLEN];
	char pathabsdir[MAXPATHLEN];
	int retcode = 1;
@@ -48,7 +48,6 @@ exec_which(int argc, char **argv)
		return (-1);
	}

-
	pkg_new(&pkg);
	if (( ret = pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC)) == EPKG_OK) {
		retcode = 0;
		printf("%s was installed by package %s-%s\n", pathabs, pkg_get(pkg, PKG_NAME),
modified pkg2legacy/pkg2legacy.c
@@ -35,7 +35,7 @@ main(int argc, char **argv)
	char destpath[MAXPATHLEN];
	char relativepath[MAXPATHLEN];
	char linkpath[MAXPATHLEN];
-
	char *newpath;
+
	const char *newpath;
	BZFILE *bz;
	int bzError;
	struct pkg **deps;
@@ -157,11 +157,10 @@ main(int argc, char **argv)
		sbuf_printf(sbuf, "@comment PKG_FORMAT_REVISION:1.1\n"
				"@name %s-%s\n"
				"@comment ORIGIN:%s\n"
-
				"@cwd %s\n",
+
				"@cwd /\n",
				pkg_get(pkg, PKG_NAME),
				pkg_get(pkg, PKG_VERSION),
-
				pkg_get(pkg, PKG_ORIGIN),
-
				pkg_get(pkg, PKG_PREFIX));
+
				pkg_get(pkg, PKG_ORIGIN));

		if ((deps = pkg_deps(pkg)) != NULL) {
			for (i = 0; deps[i] != NULL; i++) {
@@ -198,13 +197,7 @@ main(int argc, char **argv)

			size = archive_entry_size(ae);

-
			strlcpy(destpath, archive_entry_pathname(ae), MAXPATHLEN);
-
			if (strncmp(destpath, pkg_get(pkg, PKG_PREFIX), strlen(pkg_get(pkg, PKG_PREFIX))) == 0)
-
				newpath = destpath + strlen(pkg_get(pkg, PKG_PREFIX));
-
			else {
-
				sbuf_cat(sbuf, "@cwd /");
-
				newpath = destpath;
-
			}
+
			newpath = archive_entry_pathname(ae);

			if (newpath[0] == '/')
				newpath++;
modified ports/bsd.pkgng.mk
@@ -24,7 +24,7 @@ ACTUAL-PACKAGE-DEPENDS?= \
	fi

.if !defined(PKG_ARGS)
-
PKG_ARGS=		-v -c -${COMMENT:Q} -d ${DESCR} -f ${TMPPLIST} -p ${PREFIX} -P "`cd ${.CURDIR} && ${MAKE} actual-package-depends | ${GREP} -v -E ${PKG_IGNORE_DEPENDS} | ${SORT} -u -t : -k 2`" ${EXTRA_PKG_ARGS} $${_LATE_PKG_ARGS}
+
PKG_ARGS=		-l -v -c -${COMMENT:Q} -d ${DESCR} -f ${TMPPLIST} -p ${PREFIX} -P "`cd ${.CURDIR} && ${MAKE} actual-package-depends | ${GREP} -v -E ${PKG_IGNORE_DEPENDS} | ${SORT} -u -t : -k 2`" ${EXTRA_PKG_ARGS} $${_LATE_PKG_ARGS}
.if !defined(NO_MTREE)
PKG_ARGS+=		-m ${MTREE_FILE}
.endif
modified ports/pkg2ng
@@ -64,7 +64,7 @@ do

	MAINTAINER=$( make -C /usr/ports/${ORIGIN} -V MAINTAINER )

-
	CMD_ARGS=""
+
	CMD_ARGS="-l"
	test -f ${DB}/+MTREE_DIRS && CMD_ARGS="${CMD_ARGS} -m ${DB}/+MTREE_DIRS"
	test -f ${DB}/+DISPLAY && CMD_ARGS="${CMD_ARGS} -M ${DB}/+DISPLAY"
	test -n "${CONFLICTS}" && CMD_ARGS="${CMD_ARGS} -C ${CONFLICTS}"