Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
convert from khash to pkghash
Baptiste Daroussin committed 4 years ago
commit 438bcc6049b9c80e1010b2b63db3ec1140c4a81c
parent 8ca695f
27 files changed +566 -640
modified libpkg/backup_lib.c
@@ -39,10 +39,10 @@ register_backup(struct pkgdb *db, int fd, const char *path)
	time_t t;
	char buf[BUFSIZ];
	char *sum;
-
	khint_t k;
	struct pkg_file *f;
	char *lpath;
	struct stat st;
+
	pkghash_entry *e;

	sum = pkg_checksum_generate_fileat(fd, RELATIVE_PATH(path), PKG_HASH_TYPE_SHA256_HEX);

@@ -67,11 +67,10 @@ register_backup(struct pkgdb *db, int fd, const char *path)
	free(pkg->version);
	t = time(NULL);
	strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", localtime(&t));
-
	if (pkg->filehash != NULL && (k = kh_get_pkg_files(pkg->filehash, path)) != kh_end(pkg->filehash)) {
-
		f = kh_val(pkg->filehash, k);
-
		kh_del_pkg_files(pkg->filehash, k);
-
		DL_DELETE(pkg->files, f);
-
		pkg_file_free(f);
+
	if ((e = pkghash_get(pkg->filehash, path)) != NULL) {
+
		DL_DELETE(pkg->files, (struct pkg_file *)e->value);
+
		pkg_file_free(e->value);
+
		pkghash_del(pkg->filehash, path);
	}
	xasprintf(&lpath, "%s/%s", ctx.backup_library_path, path);
	pkg_addfile(pkg, lpath, sum, false);
modified libpkg/elfhints.c
@@ -55,11 +55,9 @@ struct shlib {
	char		 path[];
};

-
KHASH_MAP_INIT_STR(shlib, struct shlib *);
-

-
static int	shlib_list_add(kh_shlib_t **shlib_list,
+
static int	shlib_list_add(pkghash **shlib_list,
				const char *dir, const char *shlib_file);
-
static int	scan_dirs_for_shlibs(kh_shlib_t **shlib_list,
+
static int	scan_dirs_for_shlibs(pkghash **shlib_list,
				     int numdirs, const char **dirlist,
	                             bool strictnames);
static void	add_dir(const char *, const char *, int);
@@ -73,26 +71,26 @@ int insecure;

/* Known shlibs on the standard system search path.  Persistent,
   common to all applications */
-
static kh_shlib_t *shlibs = NULL;
+
static pkghash *shlibs = NULL;

/* Known shlibs on the specific RPATH or RUNPATH of one binary.
   Evanescent. */
-
static kh_shlib_t *rpath = NULL;
+
static pkghash *rpath = NULL;

void
shlib_list_init(void)
{
-
	assert(kh_count(shlibs) == 0);
+
	assert(pkghash_count(shlibs) == 0);
}

void
rpath_list_init(void)
{
-
	assert(kh_count(rpath) == 0);
+
	assert(pkghash_count(rpath) == 0);
}

static int
-
shlib_list_add(kh_shlib_t **shlib_list, const char *dir,
+
shlib_list_add(pkghash **shlib_list, const char *dir,
    const char *shlib_file)
{
	struct shlib	*sl;
@@ -100,7 +98,7 @@ shlib_list_add(kh_shlib_t **shlib_list, const char *dir,

	/* If shlib_file is already in the shlib_list table, don't try
	 * and add it again */
-
	if (kh_contains(shlib, *shlib_list, shlib_file))
+
	if (pkghash_get(*shlib_list, shlib_file) != NULL)
		return (EPKG_OK);

	path_len = strlen(dir) + strlen(shlib_file) + 2;
@@ -113,7 +111,7 @@ shlib_list_add(kh_shlib_t **shlib_list, const char *dir,
	
	sl->name = sl->path + dir_len;

-
	kh_add(shlib, *shlib_list, sl, sl->name, free);
+
	pkghash_safe_add(*shlib_list, sl->name, sl, free);

	return (EPKG_OK);
}
@@ -122,14 +120,19 @@ const char *
shlib_list_find_by_name(const char *shlib_file)
{
	struct shlib *sl;
+
	pkghash_entry *e;

-
	kh_find(shlib, rpath, shlib_file, sl);
-
	if (sl != NULL)
+
	e = pkghash_get(rpath, shlib_file);
+
	if (e != NULL) {
+
		sl = (struct shlib *)e->value;
		return (sl->path);
+
	}

-
	kh_find(shlib, shlibs, shlib_file, sl);
-
	if (sl != NULL)
+
	e = pkghash_get(shlibs, shlib_file);
+
	if (e != NULL) {
+
		sl = (struct shlib *)e->value;
		return (sl->path);
+
	}
		
	return (NULL);
}
@@ -138,7 +141,7 @@ void
shlib_list_free(void)
{

-
	kh_free(shlib, shlibs, struct shlib, free);
+
	pkghash_destroy(shlibs);
	shlibs = NULL;
}

@@ -146,7 +149,7 @@ void
rpath_list_free(void)
{

-
	kh_free(shlib, rpath, struct shlib, free);
+
	pkghash_destroy(rpath);
	rpath = NULL;
}

@@ -185,7 +188,7 @@ add_dir(const char *hintsfile, const char *name, int trusted)
}

static int
-
scan_dirs_for_shlibs(kh_shlib_t **shlib_list, int numdirs,
+
scan_dirs_for_shlibs(pkghash **shlib_list, int numdirs,
		     const char **dirlist, bool strictnames)
{
	int	i;
modified libpkg/pkg.c
@@ -503,40 +503,38 @@ pkg_each(deps, struct pkg_dep, depends);
pkg_each(rdeps, struct pkg_dep, rdepends);
pkg_each(options, struct pkg_option, options);
pkg_each(conflicts, struct pkg_conflict, conflicts);
-

-
#define pkg_each_hash(name, htype, type, attrib)	\
-
int							\
-
pkg_##name(const struct pkg *pkg, type **c) {		\
-
	assert(pkg != NULL);				\
-
	kh_next(htype, pkg->name, (*c), attrib);	\
-
}
-
pkg_each_hash(config_files, pkg_config_files, struct pkg_config_file, path);
-

-
#define pkg_each_strings(name)			\
-
int						\
-
pkg_##name(const struct pkg *pkg, char **c) {	\
-
	assert(pkg != NULL);			\
-
	kh_string_next(pkg->name, (*c));	\
+
pkg_each(config_files, struct pkg_config_file, config_files);
+

+
#define pkg_each_string_hash(name)                   \
+
int                                                  \
+
pkg_##name(const struct pkg *pkg, char **c) {        \
+
	if ((*c) == NULL)                            \
+
		pkghash_loopinit(pkg->name);         \
+
	pkghash_entry *e = pkghash_inext(pkg->name); \
+
	if (e == NULL) {                             \
+
		(*c) = NULL;                         \
+
		return (EPKG_END);                   \
+
	}                                            \
+
	(*c) = e->key;                               \
+
	return (EPKG_OK);                            \
}

-
pkg_each_strings(categories);
-
pkg_each_strings(licenses);
-
pkg_each_strings(requires);
-
pkg_each_strings(provides);
-
pkg_each_strings(shlibs_required);
-
pkg_each_strings(shlibs_provided);
-
pkg_each_strings(users);
-
pkg_each_strings(groups);
+
pkg_each_string_hash(categories);
+
pkg_each_string_hash(licenses);
+
pkg_each_string_hash(requires);
+
pkg_each_string_hash(provides);
+
pkg_each_string_hash(shlibs_required);
+
pkg_each_string_hash(shlibs_provided);
+
pkg_each_string_hash(users);
+
pkg_each_string_hash(groups);

int
pkg_adduser(struct pkg *pkg, const char *name)
{
-
	char *storename;
-

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

-
	if (kh_contains(strings, pkg->users, name)) {
+
	if (pkghash_get(pkg->users, name) != NULL) {
		if (ctx.developer_mode) {
			pkg_emit_error("duplicate user listing: %s, fatal (developer mode)", name);
			return (EPKG_FATAL);
@@ -546,8 +544,7 @@ pkg_adduser(struct pkg *pkg, const char *name)
		}
	}

-
	storename = xstrdup(name);
-
	kh_add(strings, pkg->users, storename, storename, free);
+
	pkghash_safe_add(pkg->users, name, NULL, NULL);

	return (EPKG_OK);
}
@@ -555,12 +552,10 @@ pkg_adduser(struct pkg *pkg, const char *name)
int
pkg_addgroup(struct pkg *pkg, const char *name)
{
-
	char *storename;
-

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

-
	if (kh_contains(strings, pkg->groups, name)) {
+
	if (pkghash_get(pkg->groups, name) != NULL) {
		if (ctx.developer_mode) {
			pkg_emit_error("duplicate group listing: %s, fatal (developer mode)", name);
			return (EPKG_FATAL);
@@ -570,8 +565,7 @@ pkg_addgroup(struct pkg *pkg, const char *name)
		}
	}

-
	storename = xstrdup(name);
-
	kh_add(strings, pkg->groups, storename, storename, free);
+
	pkghash_safe_add(pkg->groups, name, NULL, NULL);

	return (EPKG_OK);
}
@@ -600,7 +594,7 @@ pkg_adddep_chain(struct pkg_dep *chain,
	assert(origin != NULL && origin[0] != '\0');

	pkg_debug(3, "Pkg: add a new dependency origin: %s, name: %s", origin, name);
-
	if (kh_contains(pkg_deps, pkg->depshash, name)) {
+
	if (pkghash_get(pkg->depshash, name) != NULL) {
		pkg_emit_error("%s: duplicate dependency listing: %s",
		    pkg->name, name);
		return (NULL);
@@ -614,8 +608,7 @@ pkg_adddep_chain(struct pkg_dep *chain,
	d->uid = xstrdup(name);
	d->locked = locked;

-
	kh_add(pkg_deps, pkg->depshash, d, d->name, pkg_dep_free);
-

+
	pkghash_safe_add(pkg->depshash, d->name, d, NULL);
	if (chain == NULL) {
		DL_APPEND(pkg->depends, d);
		chain = pkg->depends;
@@ -646,7 +639,7 @@ pkg_addrdep(struct pkg *pkg, const char *name, const char *origin, const char *v
	d->uid = xstrdup(name);
	d->locked = locked;

-
	kh_add(pkg_deps, pkg->rdepshash, d, d->name, pkg_dep_free);
+
	pkghash_safe_add(pkg->rdepshash, d->name, d, NULL);
	LL_PREPEND(pkg->rdepends, d);

	return (EPKG_OK);
@@ -672,7 +665,7 @@ pkg_addfile_attr(struct pkg *pkg, const char *path, const char *sum,
	path = pkg_absolutepath(path, abspath, sizeof(abspath), false);
	pkg_debug(3, "Pkg: add new file '%s'", path);

-
	if (check_duplicates && kh_contains(pkg_files, pkg->filehash, path)) {
+
	if (check_duplicates && pkghash_get(pkg->filehash, path) != NULL) {
		if (ctx.developer_mode) {
			pkg_emit_error("duplicate file listing: %s, fatal (developer mode)", path);
			return (EPKG_FATAL);
@@ -700,7 +693,7 @@ pkg_addfile_attr(struct pkg *pkg, const char *path, const char *sum,
	if (fflags != 0)
		f->fflags = fflags;

-
	kh_safe_add(pkg_files, pkg->filehash, f, f->path);
+
	pkghash_safe_add(pkg->filehash, f->path, f, NULL);
	DL_APPEND(pkg->files, f);

	return (EPKG_OK);
@@ -715,7 +708,7 @@ pkg_addconfig_file(struct pkg *pkg, const char *path, const char *content)
	path = pkg_absolutepath(path, abspath, sizeof(abspath), false);
	pkg_debug(3, "Pkg: add new config file '%s'", path);

-
	if (kh_contains(pkg_config_files, pkg->config_files, path)) {
+
	if (pkghash_get(pkg->config_files_hash, path) != NULL) {
		if (ctx.developer_mode) {
			pkg_emit_error("duplicate file listing: %s, fatal (developer mode)", path);
			return (EPKG_FATAL);
@@ -729,20 +722,19 @@ pkg_addconfig_file(struct pkg *pkg, const char *path, const char *content)
	if (content != NULL)
		f->content = xstrdup(content);

-
	kh_add(pkg_config_files, pkg->config_files, f, f->path, pkg_config_file_free);
+
	pkghash_safe_add(pkg->config_files_hash, f->path, f, NULL);
+
	DL_APPEND(pkg->config_files, f);

	return (EPKG_OK);
}

int
-
pkg_addstring(kh_strings_t **list, const char *val, const char *title)
+
pkg_addstring(pkghash **list, const char *val, const char *title)
{
-
	char *store;
-

	assert(val != NULL);
	assert(title != NULL);

-
	if (kh_contains(strings, *list, val)) {
+
	if (pkghash_get(*list, val) != NULL) {
		if (ctx.developer_mode) {
			pkg_emit_error("duplicate %s listing: %s, fatal"
			    " (developer mode)", title, val);
@@ -754,8 +746,7 @@ pkg_addstring(kh_strings_t **list, const char *val, const char *title)
		}
	}

-
	store = xstrdup(val);
-
	kh_add(strings, *list, store, store, free);
+
	pkghash_safe_add(*list, val, NULL, NULL);

	return (EPKG_OK);
}
@@ -782,7 +773,7 @@ pkg_adddir_attr(struct pkg *pkg, const char *path, const char *uname,
	}
	path = pkg_absolutepath(path, abspath, sizeof(abspath), false);
	pkg_debug(3, "Pkg: add new directory '%s'", path);
-
	if (check_duplicates && kh_contains(pkg_dirs, pkg->dirhash, path)) {
+
	if (check_duplicates && pkghash_get(pkg->dirhash, path) != NULL) {
		if (ctx.developer_mode) {
			pkg_emit_error("duplicate directory listing: %s, fatal (developer mode)", path);
			return (EPKG_FATAL);
@@ -807,7 +798,7 @@ pkg_adddir_attr(struct pkg *pkg, const char *path, const char *uname,
	if (fflags != 0)
		d->fflags = fflags;

-
	kh_safe_add(pkg_dirs, pkg->dirhash, d, d->path);
+
	pkghash_safe_add(pkg->dirhash, d->path, d, NULL);
	DL_APPEND(pkg->dirs, d);

	return (EPKG_OK);
@@ -953,7 +944,7 @@ pkg_addoption(struct pkg *pkg, const char *key, const char *value)
	   value. */

	pkg_debug(2,"Pkg> adding options: %s = %s", key, value);
-
	if (kh_contains(pkg_options, pkg->optionshash, key)) {
+
	if (pkghash_get(pkg->optionshash, key) != NULL) {
		if (ctx.developer_mode) {
			pkg_emit_error("duplicate options listing: %s, fatal (developer mode)", key);
			return (EPKG_FATAL);
@@ -965,7 +956,7 @@ pkg_addoption(struct pkg *pkg, const char *key, const char *value)
	o = xcalloc(1, sizeof(*o));
	o->key = xstrdup(key);
	o->value = xstrdup(value);
-
	kh_safe_add(pkg_options, pkg->optionshash, o, o->key);
+
	pkghash_safe_add(pkg->optionshash, o->key, o, NULL);
	DL_APPEND(pkg->options, o);

	return (EPKG_OK);
@@ -987,7 +978,7 @@ pkg_addoption_default(struct pkg *pkg, const char *key,
	   could be a default value or description for an option but
	   no actual value. */

-
	if (kh_contains(pkg_options, pkg->optionshash, key)) {
+
	if (pkghash_get(pkg->optionshash, key) != NULL) {
		if (ctx.developer_mode) {
			pkg_emit_error("duplicate default value for option: %s, fatal (developer mode)", key);
			return (EPKG_FATAL);
@@ -999,7 +990,7 @@ pkg_addoption_default(struct pkg *pkg, const char *key,
	o = xcalloc(1, sizeof(*o));
	o->key = xstrdup(key);
	o->default_value = xstrdup(default_value);
-
	kh_safe_add(pkg_options, pkg->optionshash, o, o->key);
+
	pkghash_safe_add(pkg->optionshash, o->key, o, NULL);
	DL_APPEND(pkg->options, o);

	return (EPKG_OK);
@@ -1020,7 +1011,7 @@ pkg_addoption_description(struct pkg *pkg, const char *key,
	   is already set. Which implies there could be a default
	   value or description for an option but no actual value. */

-
	if (kh_contains(pkg_options, pkg->optionshash, key)) {
+
	if (pkghash_get(pkg->optionshash, key) != NULL) {
		if (ctx.developer_mode) {
			pkg_emit_error("duplicate description for option: %s, fatal (developer mode)", key);
			return (EPKG_FATAL);
@@ -1033,7 +1024,7 @@ pkg_addoption_description(struct pkg *pkg, const char *key,
	o = xcalloc(1, sizeof(*o));
	o->key = xstrdup(key);
	o->description = xstrdup(description);
-
	kh_safe_add(pkg_options, pkg->optionshash, o, o->key);
+
	pkghash_safe_add(pkg->optionshash, o->key, o, NULL);
	DL_APPEND(pkg->options, o);

	return (EPKG_OK);
@@ -1042,17 +1033,14 @@ pkg_addoption_description(struct pkg *pkg, const char *key,
int
pkg_addshlib_required(struct pkg *pkg, const char *name)
{
-
	char *storename;
-

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

	/* silently ignore duplicates in case of shlibs */
-
	if (kh_contains(strings, pkg->shlibs_required, name))
+
	if (pkghash_get(pkg->shlibs_required, name) != NULL)
		return (EPKG_OK);

-
	storename = xstrdup(name);
-
	kh_add(strings, pkg->shlibs_required, storename, storename, free);
+
	pkghash_safe_add(pkg->shlibs_required, name, NULL, NULL);

	pkg_debug(3, "added shlib deps for %s on %s", pkg->name, name);

@@ -1062,8 +1050,6 @@ pkg_addshlib_required(struct pkg *pkg, const char *name)
int
pkg_addshlib_provided(struct pkg *pkg, const char *name)
{
-
	char *storename;
-

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

@@ -1072,11 +1058,10 @@ pkg_addshlib_provided(struct pkg *pkg, const char *name)
		return (EPKG_OK);

	/* silently ignore duplicates in case of shlibs */
-
	if (kh_contains(strings, pkg->shlibs_provided, name))
+
	if (pkghash_get(pkg->shlibs_provided, name) != NULL)
		return (EPKG_OK);

-
	storename = xstrdup(name);
-
	kh_add(strings, pkg->shlibs_provided, storename, storename, free);
+
	pkghash_safe_add(pkg->shlibs_provided, name, NULL, NULL);

	pkg_debug(3, "added shlib provide %s for %s", name, pkg->name);

@@ -1091,7 +1076,7 @@ pkg_addconflict(struct pkg *pkg, const char *uniqueid)
	assert(pkg != NULL);
	assert(uniqueid != NULL && uniqueid[0] != '\0');

-
	if (kh_contains(pkg_conflicts, pkg->conflictshash, uniqueid)) {
+
	if (pkghash_get(pkg->conflictshash, uniqueid) != NULL) {
		/* silently ignore duplicates in case of conflicts */
		return (EPKG_OK);
	}
@@ -1100,7 +1085,7 @@ pkg_addconflict(struct pkg *pkg, const char *uniqueid)
	c->uid = xstrdup(uniqueid);
	pkg_debug(3, "Pkg: add a new conflict origin: %s, with %s", pkg->uid, uniqueid);

-
	kh_safe_add(pkg_conflicts, pkg->conflictshash, c, c->uid);
+
	pkghash_safe_add(pkg->conflictshash, c->uid, c, NULL);
	DL_APPEND(pkg->conflicts, c);

	return (EPKG_OK);
@@ -1109,18 +1094,14 @@ pkg_addconflict(struct pkg *pkg, const char *uniqueid)
int
pkg_addrequire(struct pkg *pkg, const char *name)
{
-
	char *storename;
-

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

	/* silently ignore duplicates in case of conflicts */
-
	if (kh_contains(strings, pkg->requires, name))
+
	if (pkghash_get(pkg->requires, name) != NULL)
		return (EPKG_OK);

-
	storename = xstrdup(name);
-

-
	kh_add(strings, pkg->requires, storename, storename, free);
+
	pkghash_safe_add(pkg->requires, name, NULL, NULL);

	return (EPKG_OK);
}
@@ -1128,18 +1109,14 @@ pkg_addrequire(struct pkg *pkg, const char *name)
int
pkg_addprovide(struct pkg *pkg, const char *name)
{
-
	char *storename;
-

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

	/* silently ignore duplicates in case of conflicts */
-
	if (kh_contains(strings, pkg->provides, name))
+
	if (pkghash_get(pkg->provides, name) != NULL)
		return (EPKG_OK);

-
	storename = xstrdup(name);
-

-
	kh_add(strings, pkg->provides, storename, storename, free);
+
	pkghash_safe_add(pkg->provides, name, NULL, NULL);

	return (EPKG_OK);
}
@@ -1192,35 +1169,35 @@ pkg_list_count(const struct pkg *pkg, pkg_list list)
{
	switch (list) {
	case PKG_DEPS:
-
		return (kh_count(pkg->depshash));
+
		return (pkghash_count(pkg->depshash));
	case PKG_RDEPS:
-
		return (kh_count(pkg->rdepshash));
+
		return (pkghash_count(pkg->rdepshash));
	case PKG_OPTIONS:
-
		return (kh_count(pkg->optionshash));
+
		return (pkghash_count(pkg->optionshash));
	case PKG_FILES:
-
		return (kh_count(pkg->filehash));
+
		return (pkghash_count(pkg->filehash));
	case PKG_DIRS:
-
		return (kh_count(pkg->dirhash));
+
		return (pkghash_count(pkg->dirhash));
	case PKG_USERS:
-
		return (kh_count(pkg->users));
+
		return (pkghash_count(pkg->users));
	case PKG_GROUPS:
-
		return (kh_count(pkg->groups));
+
		return (pkghash_count(pkg->groups));
	case PKG_SHLIBS_REQUIRED:
-
		return (kh_count(pkg->shlibs_required));
+
		return (pkghash_count(pkg->shlibs_required));
	case PKG_SHLIBS_PROVIDED:
-
		return (kh_count(pkg->shlibs_provided));
+
		return (pkghash_count(pkg->shlibs_provided));
	case PKG_CONFLICTS:
-
		return (kh_count(pkg->conflictshash));
+
		return (pkghash_count(pkg->conflictshash));
	case PKG_PROVIDES:
-
		return (kh_count(pkg->provides));
+
		return (pkghash_count(pkg->provides));
	case PKG_REQUIRES:
-
		return (kh_count(pkg->requires));
+
		return (pkghash_count(pkg->requires));
	case PKG_CONFIG_FILES:
-
		return (kh_count(pkg->config_files));
+
		return (pkghash_count(pkg->config_files_hash));
	case PKG_CATEGORIES:
-
		return (kh_count(pkg->categories));
+
		return (pkghash_count(pkg->categories));
	case PKG_LICENSES:
-
		return (kh_count(pkg->licenses));
+
		return (pkghash_count(pkg->licenses));
	}

	return (0);
@@ -1238,66 +1215,82 @@ pkg_list_free(struct pkg *pkg, pkg_list list) {
			}
		}
		DL_FREE(pkg->depends, pkg_dep_free);
-
		kh_destroy_pkg_deps(pkg->depshash);
+
		pkghash_destroy(pkg->depshash);
+
		pkg->depshash = NULL;
		pkg->flags &= ~PKG_LOAD_DEPS;
		break;
	case PKG_RDEPS:
		LL_FREE(pkg->rdepends, pkg_dep_free);
-
		kh_destroy_pkg_deps(pkg->rdepshash);
+
		pkghash_destroy(pkg->rdepshash);
+
		pkg->depshash = NULL;
		pkg->flags &= ~PKG_LOAD_RDEPS;
		break;
	case PKG_OPTIONS:
		DL_FREE(pkg->options, pkg_option_free);
-
		kh_destroy_pkg_options(pkg->optionshash);
+
		pkghash_destroy(pkg->optionshash);
+
		pkg->optionshash = NULL;
		pkg->flags &= ~PKG_LOAD_OPTIONS;
		break;
	case PKG_FILES:
	case PKG_CONFIG_FILES:
		DL_FREE(pkg->files, pkg_file_free);
-
		kh_destroy_pkg_files(pkg->filehash);
-
		kh_free(pkg_config_files, pkg->config_files, struct pkg_config_file, pkg_config_file_free);
+
		pkghash_destroy(pkg->filehash);
+
		pkg->filehash = NULL;
+
		DL_FREE(pkg->config_files, pkg_config_file_free);
+
		pkghash_destroy(pkg->config_files_hash);
+
		pkg->config_files_hash = NULL;
		pkg->flags &= ~PKG_LOAD_FILES;
		break;
	case PKG_DIRS:
		DL_FREE(pkg->dirs, free);
-
		kh_destroy_pkg_dirs(pkg->dirhash);
+
		pkghash_destroy(pkg->dirhash);
+
		pkg->dirhash = NULL;
		pkg->flags &= ~PKG_LOAD_DIRS;
		break;
	case PKG_USERS:
-
		kh_free(strings, pkg->users, char, free);
+
		pkghash_destroy(pkg->users);
+
		pkg->users = NULL;
		pkg->flags &= ~PKG_LOAD_USERS;
		break;
	case PKG_GROUPS:
-
		kh_free(strings, pkg->groups, char, free);
+
		pkghash_destroy(pkg->groups);
+
		pkg->groups = NULL;
		pkg->flags &= ~PKG_LOAD_GROUPS;
		break;
	case PKG_SHLIBS_REQUIRED:
-
		kh_free(strings, pkg->shlibs_required, char, free);
+
		pkghash_destroy(pkg->shlibs_required);
+
		pkg->shlibs_required = NULL;
		pkg->flags &= ~PKG_LOAD_SHLIBS_REQUIRED;
		break;
	case PKG_SHLIBS_PROVIDED:
-
		kh_free(strings, pkg->shlibs_provided, char, free);
+
		pkghash_destroy(pkg->shlibs_provided);
+
		pkg->shlibs_provided = NULL;
		pkg->flags &= ~PKG_LOAD_SHLIBS_PROVIDED;
		break;
	case PKG_CONFLICTS:
		DL_FREE(pkg->conflicts, pkg_conflict_free);
-
		kh_destroy_pkg_conflicts(pkg->conflictshash);
+
		pkghash_destroy(pkg->conflictshash);
+
		pkg->conflictshash = NULL;
		pkg->flags &= ~PKG_LOAD_CONFLICTS;
		break;
	case PKG_PROVIDES:
-
		kh_free(strings, pkg->provides, char, free);
+
		pkghash_destroy(pkg->provides);
+
		pkg->provides = NULL;
		pkg->flags &= ~PKG_LOAD_PROVIDES;
		break;
	case PKG_REQUIRES:
-
		kh_free(strings, pkg->requires, char, free);
+
		pkghash_destroy(pkg->requires);
+
		pkg->requires = NULL;
		pkg->flags &= ~PKG_LOAD_REQUIRES;
		break;
	case PKG_CATEGORIES:
-
		kh_free(strings, pkg->categories, char, free);
+
		pkghash_destroy(pkg->categories);
+
		pkg->categories = NULL;
		pkg->flags &= ~PKG_LOAD_CATEGORIES;
		break;
	case PKG_LICENSES:
-
		kh_free(strings, pkg->licenses, char, free);
+
		pkghash_destroy(pkg->licenses);
+
		pkg->licenses = NULL;
		pkg->flags &= ~PKG_LOAD_LICENSES;
		break;
	}
@@ -1618,22 +1611,24 @@ pkg_is_config_file(struct pkg *p, const char *path,
    const struct pkg_file **file,
    struct pkg_config_file **cfile)
{
-

	*file = NULL;
	*cfile = NULL;
+
	pkghash_entry *e;

-
	if (kh_count(p->config_files) == 0)
+
	if (pkghash_count(p->config_files_hash) == 0)
		return (false);

-
	kh_find(pkg_files, p->filehash, path, *file);
-
	if (*file == NULL)
+
	e = pkghash_get(p->filehash, path);
+
	if (e == NULL)
		return (false);
+
	*file = (struct pkg_file *)e->value;

-
	kh_find(pkg_config_files, p->config_files, path, *cfile);
-
	if (*cfile == NULL) {
+
	e = pkghash_get(p->config_files_hash, path);
+
	if (e == NULL) {
		*file = NULL;
		return (false);
	}
+
	*cfile = (struct pkg_config_file *)e->value;

	return (true);
}
@@ -1641,33 +1636,31 @@ pkg_is_config_file(struct pkg *p, const char *path,
struct pkg_dir *
pkg_get_dir(struct pkg *p, const char *path)
{
-
	struct pkg_dir *d;
-

-
	kh_find(pkg_dirs, p->dirhash, path, d);
-

-
	return (d);
+
	pkghash_entry *e = pkghash_get(p->dirhash, path);
+
	if (e == NULL)
+
		return (NULL);
+
	return ((struct pkg_dir *)e->value);
}

struct pkg_file *
pkg_get_file(struct pkg *p, const char *path)
{
-
	struct pkg_file *f;
-

-
	kh_find(pkg_files, p->filehash, path, f);
-

-
	return (f);
+
	pkghash_entry *e = pkghash_get(p->filehash, path);
+
	if (e == NULL)
+
		return (NULL);
+
	return ((struct pkg_file *)e->value);
}

bool
pkg_has_file(struct pkg *p, const char *path)
{
-
	return (kh_contains(pkg_files, p->filehash, path));
+
	return (pkghash_get(p->filehash, path) != NULL);
}

bool
pkg_has_dir(struct pkg *p, const char *path)
{
-
	return (kh_contains(pkg_dirs, p->dirhash, path));
+
	return (pkghash_get(p->dirhash, path) != NULL);
}

int
modified libpkg/pkg_add.c
@@ -568,8 +568,12 @@ retry:

	if (fromfd == -1) {
		/* check if this is a config file */
-
		kh_find(pkg_config_files, pkg->config_files, f->path,
-
		    f->config);
+
		pkghash_entry *e;
+
		e = pkghash_get(pkg->config_files_hash, f->path);
+
		if (e == NULL)
+
			f->config = NULL;
+
		else
+
			f->config = (struct pkg_config_file *)e->value;
		if (f->config) {
			const char *cfdata;
			bool merge = pkg_object_bool(pkg_config_get("AUTOMERGE"));
@@ -1011,7 +1015,7 @@ pkg_add_cleanup_old(struct pkgdb *db, struct pkg *old, struct pkg *new, int flag
					const char *libname;
					libname = strrchr(f->path, '/');
					if (libname != NULL &&
-
					    kh_contains(strings, old->shlibs_provided, libname+1)) {
+
					    pkghash_get(old->shlibs_provided, libname+1) != NULL) {
						backup_library(db, old, f->path);
					}
				}
@@ -1157,7 +1161,7 @@ pkg_add_common(struct pkgdb *db, const char *path, unsigned flags,

	/* add the user and group if necessary */

-
	nfiles = kh_count(pkg->filehash) + kh_count(pkg->dirhash);
+
	nfiles = pkghash_count(pkg->filehash) + pkghash_count(pkg->dirhash);
	/*
	 * Extract the files on disk.
	 */
modified libpkg/pkg_checksum.c
@@ -220,6 +220,7 @@ pkg_checksum_generate(struct pkg *pkg, char *dest, size_t destlen,
	struct pkg_option *option = NULL;
	struct pkg_dep *dep = NULL;
	struct pkg_file *f = NULL;
+
	pkghash_it	it;
	int i;

	if (pkg == NULL || type >= PKG_HASH_TYPE_UNKNOWN ||
@@ -237,23 +238,27 @@ pkg_checksum_generate(struct pkg *pkg, char *dest, size_t destlen,
	}

	buf = NULL;
-
	while (pkg_shlibs_required(pkg, &buf) == EPKG_OK) {
-
		pkg_checksum_add_entry("required_shlib", buf, &entries);
+
	it = pkghash_iterator(pkg->shlibs_required);
+
	while (pkghash_next(&it)) {
+
		pkg_checksum_add_entry("required_shlib", it.key, &entries);
	}

	buf = NULL;
-
	while (pkg_shlibs_provided(pkg, &buf) == EPKG_OK) {
-
		pkg_checksum_add_entry("provided_shlib", buf, &entries);
+
	it = pkghash_iterator(pkg->shlibs_provided);
+
	while (pkghash_next(&it)) {
+
		pkg_checksum_add_entry("provided_shlib", it.key, &entries);
	}

	buf = NULL;
-
	while (pkg_users(pkg, &buf) == EPKG_OK) {
-
		pkg_checksum_add_entry("user", buf, &entries);
+
	it = pkghash_iterator(pkg->users);
+
	while (pkghash_next(&it)) {
+
		pkg_checksum_add_entry("user", it.key, &entries);
	}

	buf = NULL;
-
	while (pkg_groups(pkg, &buf) == EPKG_OK) {
-
		pkg_checksum_add_entry("group", buf, &entries);
+
	it = pkghash_iterator(pkg->groups);
+
	while (pkghash_next(&it)) {
+
		pkg_checksum_add_entry("group", it.key, &entries);
	}

	while (pkg_deps(pkg, &dep) == EPKG_OK) {
@@ -263,13 +268,15 @@ pkg_checksum_generate(struct pkg *pkg, char *dest, size_t destlen,
	}

	buf = NULL;
-
	while (pkg_provides(pkg, &buf) == EPKG_OK) {
-
		pkg_checksum_add_entry("provide", buf, &entries);
+
	it = pkghash_iterator(pkg->provides);
+
	while (pkghash_next(&it)) {
+
		pkg_checksum_add_entry("provide", it.key, &entries);
	}

	buf = NULL;
-
	while (pkg_requires(pkg, &buf) == EPKG_OK) {
-
		pkg_checksum_add_entry("require", buf, &entries);
+
	it = pkghash_iterator(pkg->requires);
+
	while (pkghash_next(&it)) {
+
		pkg_checksum_add_entry("require", it.key, &entries);
	}

	if (inc_scripts) {
modified libpkg/pkg_create.c
@@ -79,7 +79,7 @@ pkg_create_from_dir(struct pkg *pkg, const char *root,
	 * Get / compute size / checksum if not provided in the manifest
	 */

-
	nfiles = kh_count(pkg->filehash);
+
	nfiles = pkghash_count(pkg->filehash);
	counter_init("file sizes/checksums", nfiles);

	hardlinks = kh_init_hardlinks();
@@ -160,7 +160,7 @@ pkg_create_from_dir(struct pkg *pkg, const char *root,

	counter_end();

-
	nfiles = kh_count(pkg->dirhash);
+
	nfiles = pkghash_count(pkg->dirhash);
	counter_init("packing directories", nfiles);

	while (pkg_dirs(pkg, &dir) == EPKG_OK) {
modified libpkg/pkg_cudf.c
@@ -113,7 +113,6 @@ cudf_emit_pkg(struct pkg *pkg, int version, FILE *f,
	struct pkg_dep *dep;
	struct pkg_conflict *conflict;
	struct pkg_job_universe_item *u;
-
	char *buf;
	int column = 0, ver;

	if (fprintf(f, "package: ") < 0)
@@ -125,31 +124,32 @@ cudf_emit_pkg(struct pkg *pkg, int version, FILE *f,
	if (fprintf(f, "\nversion: %d\n", version) < 0)
		return (EPKG_FATAL);

-
	if (kh_count(pkg->depshash) > 0) {
+
	if (pkghash_count(pkg->depshash) > 0) {
		if (fprintf(f, "depends: ") < 0)
			return (EPKG_FATAL);
		LL_FOREACH(pkg->depends, dep) {
			if (cudf_print_element(f, dep->name,
-
			    column + 1 == kh_count(pkg->depshash), &column) < 0) {
+
			    column + 1 == pkghash_count(pkg->depshash), &column) < 0) {
				return (EPKG_FATAL);
			}
		}
	}

	column = 0;
-
	if (kh_count(pkg->provides) > 0) {
+
	if (pkghash_count(pkg->provides) > 0) {
		if (fprintf(f, "provides: ") < 0)
			return (EPKG_FATAL);
-
		kh_each_value(pkg->provides, buf, {
-
			if (cudf_print_element(f, buf,
-
			    column + 1 == kh_count(pkg->provides), &column) < 0) {
+
		pkghash_it it = pkghash_iterator(pkg->provides);
+
		while (pkghash_next(&it)) {
+
			if (cudf_print_element(f, it.key,
+
			    column + 1 == pkghash_count(pkg->provides), &column) < 0) {
				return (EPKG_FATAL);
			}
-
		});
+
		}
	}

	column = 0;
-
	if (kh_count(pkg->conflictshash) > 0 ||
+
	if (pkghash_count(pkg->conflictshash) > 0 ||
			(conflicts_chain->next != NULL &&
			conflicts_chain->next->priority != INT_MIN)) {
		if (fprintf(f, "conflicts: ") < 0)
modified libpkg/pkg_delete.c
@@ -344,7 +344,7 @@ pkg_delete_files(struct pkg *pkg, unsigned force)

	int		nfiles, cur_file = 0;

-
	nfiles = kh_count(pkg->filehash);
+
	nfiles = pkghash_count(pkg->filehash);

	if (nfiles == 0)
		return (EPKG_OK);
modified libpkg/pkg_elf.c
@@ -468,16 +468,20 @@ pkg_analyse_files(struct pkgdb *db __unused, struct pkg *pkg, const char *stage)
{
	struct pkg_file *file = NULL;
	char *sh;
-
	khint_t k;
	int ret = EPKG_OK;
	char fpath[MAXPATHLEN +1];
	const char *lib;
	bool failures = false;

-
	if (kh_count(pkg->shlibs_required) != 0)
-
		pkg_list_free(pkg, PKG_SHLIBS_REQUIRED);
-
	if (kh_count(pkg->shlibs_provided) != 0)
-
		pkg_list_free(pkg, PKG_SHLIBS_PROVIDED);
+
	if (pkghash_count(pkg->shlibs_required) != 0) {
+
		pkghash_destroy(pkg->shlibs_required);
+
		pkg->shlibs_required = NULL;
+
	}
+

+
	if (pkghash_count(pkg->shlibs_provided) != 0) {
+
		pkghash_destroy(pkg->shlibs_provided);
+
		pkg->shlibs_provided = NULL;
+
	}

	if (elf_version(EV_CURRENT) == EV_NONE)
		return (EPKG_FATAL);
@@ -518,35 +522,37 @@ pkg_analyse_files(struct pkgdb *db __unused, struct pkg *pkg, const char *stage)
	/*
	 * Do not depend on libraries that a package provides itself
	 */
-
	kh_each_value(pkg->shlibs_required, sh, {
-
		if (kh_contains(strings, pkg->shlibs_provided, sh)) {
+
	pkghash_it it = pkghash_iterator(pkg->shlibs_required);
+
	while (pkghash_next(&it)) {
+
		if (pkghash_get(pkg->shlibs_provided, it.key)) {
			pkg_debug(2, "remove %s from required shlibs as the "
			    "package %s provides this library itself",
-
			    sh, pkg->name);
-
			k = kh_get_strings(pkg->shlibs_required, sh);
-
			kh_del_strings(pkg->shlibs_required, k);
+
			    it.key, pkg->name);
+
			pkghash_del(pkg->shlibs_required, it.key);
			continue;
		}
		file = NULL;
		while (pkg_files(pkg, &file) == EPKG_OK) {
-
			if ((lib = strstr(file->path, sh)) != NULL &&
+
			if ((lib = strstr(file->path, it.key)) != NULL &&
			    strlen(lib) == strlen(sh) && lib[-1] == '/') {
				pkg_debug(2, "remove %s from required shlibs as "
				    "the package %s provides this file itself",
-
				    sh, pkg->name);
-
				k = kh_get_strings(pkg->shlibs_required, sh);
-
				kh_del_strings(pkg->shlibs_required, k);
+
				    it.key, pkg->name);
+

+
				pkghash_del(pkg->shlibs_required, it.key);
				break;
			}
		}
-
	});
+
	}

	/*
	 * if the package is not supposed to provide share libraries then
	 * drop the provided one
	 */
-
	if (pkg_kv_get(&pkg->annotations, "no_provide_shlib") != NULL)
-
		kh_free(strings, pkg->shlibs_provided, char, free);
+
	if (pkg_kv_get(&pkg->annotations, "no_provide_shlib") != NULL) {
+
		pkghash_destroy(pkg->shlibs_provided);
+
		pkg->shlibs_provided = NULL;
+
	}

	if (failures)
		goto cleanup;
modified libpkg/pkg_jobs.c
@@ -1090,6 +1090,7 @@ pkg_jobs_need_upgrade(struct pkg *rp, struct pkg *lp)
	struct pkg_dep *ld = NULL, *rd = NULL;
	struct pkg_conflict *lc = NULL, *rc = NULL;
	char *lb, *rb;
+
	pkghash_it it1, it2;

	/* If no local package, then rp is obviously need to be added */
	if (lp == NULL)
@@ -1209,16 +1210,18 @@ pkg_jobs_need_upgrade(struct pkg *rp, struct pkg *lp)

	/* Provides */
	lb = rb = NULL;
+
	it1 = pkghash_iterator(rp->provides);
+
	it2 = pkghash_iterator(lp->provides);
	for (;;) {
-
		ret1 = pkg_provides(rp, &rb);
-
		ret2 = pkg_provides(lp, &lb);
+
		ret1 = pkghash_next(&it1);
+
		ret2 = pkghash_next(&it2);
		if (ret1 != ret2) {
			free(rp->reason);
			rp->reason = xstrdup("provides changed");
			return (true);
		}
-
		if (ret1 == EPKG_OK) {
-
			if (strcmp(rb, lb) != 0) {
+
		if (ret1) {
+
			if (strcmp(it1.key, it2.key) != 0) {
				free(rp->reason);
				rp->reason = xstrdup("provides changed");
				return (true);
@@ -1229,16 +1232,18 @@ pkg_jobs_need_upgrade(struct pkg *rp, struct pkg *lp)
	}
	/* Requires */
	lb = rb = NULL;
+
	it1 = pkghash_iterator(rp->requires);
+
	it2 = pkghash_iterator(lp->requires);
	for (;;) {
-
		ret1 = pkg_requires(rp, &rb);
-
		ret2 = pkg_requires(lp, &lb);
+
		ret1 = pkghash_next(&it1);
+
		ret2 = pkghash_next(&it2);
		if (ret1 != ret2) {
			free(rp->reason);
			rp->reason = xstrdup("requires changed");
			return (true);
		}
-
		if (ret1 == EPKG_OK) {
-
			if (strcmp(rb, lb) != 0) {
+
		if (ret1) {
+
			if (strcmp(it1.key, it2.key) != 0) {
				free(rp->reason);
				rp->reason = xstrdup("requires changed");
				return (true);
@@ -1250,20 +1255,22 @@ pkg_jobs_need_upgrade(struct pkg *rp, struct pkg *lp)

	/* Finish by the shlibs */
	lb = rb = NULL;
+
	it1 = pkghash_iterator(rp->shlibs_provided);
+
	it2 = pkghash_iterator(lp->shlibs_provided);
	for (;;) {
-
		ret1 = pkg_shlibs_provided(rp, &rb);
-
		ret2 = pkg_shlibs_provided(lp, &lb);
+
		ret1 = pkghash_next(&it1);
+
		ret2 = pkghash_next(&it2);
		if (ret1 != ret2) {
			free(rp->reason);
			rp->reason = xstrdup("provided shared library changed");
			return (true);
		}
-
		if (ret1 == EPKG_OK) {
-
			if (strcmp(rb, lb) != 0) {
+
		if (ret1) {
+
			if (strcmp(it1.key, it2.key) != 0) {
				free(rp->reason);
				rp->reason = xstrdup("provided shared library changed");
				pkg_debug(1, "provided shlib changed %s -> %s",
-
				    lb, rb);
+
				    it2.key, it1.key);
				return (true);
			}
		}
@@ -1272,20 +1279,22 @@ pkg_jobs_need_upgrade(struct pkg *rp, struct pkg *lp)
	}

	lb = rb = NULL;
+
	it1 = pkghash_iterator(rp->shlibs_required);
+
	it2 = pkghash_iterator(lp->shlibs_required);
	for (;;) {
-
		ret1 = pkg_shlibs_required(rp, &rb);
-
		ret2 = pkg_shlibs_required(lp, &lb);
+
		ret1 = pkghash_next(&it1);
+
		ret2 = pkghash_next(&it2);
		if (ret1 != ret2) {
			free(rp->reason);
			rp->reason = xstrdup("needed shared library changed");
			return (true);
		}
-
		if (ret1 == EPKG_OK) {
-
			if (strcmp(rb, lb) != 0) {
+
		if (ret1) {
+
			if (strcmp(it1.key, it2.key) != 0) {
				free(rp->reason);
				rp->reason = xstrdup("needed shared library changed");
				pkg_debug(1, "Required shlib changed %s -> %s",
-
				    lb, rb);
+
				    it2.key, it1.key);
				return (true);
			}
		}
modified libpkg/pkg_jobs_conflicts.c
@@ -168,9 +168,9 @@ pkg_conflicts_register(struct pkg *p1, struct pkg *p2, enum pkg_conflict_type ty
	c2 = xcalloc(1, sizeof(*c2));

	c1->type = c2->type = type;
-
	if (!kh_contains(pkg_conflicts, p1->conflictshash, p2->uid)) {
+
	if (pkghash_get(p1->conflictshash, p2->uid) == NULL) {
		c1->uid = xstrdup(p2->uid);
-
		kh_safe_add(pkg_conflicts, p1->conflictshash, c1, c1->uid);
+
		pkghash_safe_add(p1->conflictshash, c1->uid, c1, NULL);
		DL_APPEND(p1->conflicts, c1);
		pkg_debug(2, "registering conflict between %s(%s) and %s(%s)",
				p1->uid, p1->type == PKG_INSTALLED ? "l" : "r",
@@ -179,9 +179,9 @@ pkg_conflicts_register(struct pkg *p1, struct pkg *p2, enum pkg_conflict_type ty
		pkg_conflict_free(c1);
	}

-
	if (!kh_contains(pkg_conflicts, p2->conflictshash, p1->uid)) {
+
	if (pkghash_get(p2->conflictshash, p1->uid) == NULL) {
		c2->uid = xstrdup(p1->uid);
-
		kh_safe_add(pkg_conflicts, p2->conflictshash, c2, c2->uid);
+
		pkghash_safe_add(p2->conflictshash, c2->uid, c2, NULL);
		DL_APPEND(p2->conflicts, c2);
		pkg_debug(2, "registering conflict between %s(%s) and %s(%s)",
				p2->uid, p2->type == PKG_INSTALLED ? "l" : "r",
@@ -224,8 +224,8 @@ pkg_conflicts_need_conflict(struct pkg_jobs *j, struct pkg *p1, struct pkg *p2)
	/*
	 * Check if we already have this conflict registered
	 */
-
	if (kh_contains(pkg_conflicts, p1->conflictshash, p2->uid) &&
-
	    kh_contains(pkg_conflicts, p2->conflictshash, p1->uid))
+
	if (pkghash_get(p1->conflictshash, p2->uid) != NULL &&
+
	    pkghash_get(p2->conflictshash, p1->uid) != NULL)
		return false;

	/*
@@ -253,9 +253,15 @@ pkg_conflicts_register_unsafe(struct pkg *p1, struct pkg *p2,
	bool use_digest)
{
	struct pkg_conflict *c1, *c2;
-

-
	kh_find(pkg_conflicts, p1->conflictshash, p2->uid, c1);
-
	kh_find(pkg_conflicts, p2->conflictshash, p1->uid, c2);
+
	pkghash_entry *e;
+

+
	c1 = c2 = NULL;
+
	e = pkghash_get(p1->conflictshash, p2->uid);
+
	if (e != NULL)
+
		c1 = (struct pkg_conflict *)e->value;
+
	e = pkghash_get(p2->conflictshash, p1->uid);
+
	if (e != NULL)
+
		c2 = (struct pkg_conflict *)e->value;
	if (c1 == NULL) {
		c1 = xcalloc(1, sizeof(*c1));
		c1->type = type;
@@ -265,7 +271,7 @@ pkg_conflicts_register_unsafe(struct pkg *p1, struct pkg *p2,
			c1->digest = xstrdup(p2->digest);
		}

-
		kh_safe_add(pkg_conflicts, p1->conflictshash, c1, c1->uid);
+
		pkghash_safe_add(p1->conflictshash, c1->uid, c1, NULL);
		DL_APPEND(p1->conflicts, c1);
	}

@@ -281,7 +287,7 @@ pkg_conflicts_register_unsafe(struct pkg *p1, struct pkg *p2,
			c2->digest = xstrdup(p1->digest);
		}

-
		kh_safe_add(pkg_conflicts, p2->conflictshash, c2, c2->uid);
+
		pkghash_safe_add(p2->conflictshash, c2->uid, c2, NULL);
		DL_APPEND(p2->conflicts, c2);
	}

@@ -385,7 +391,7 @@ pkg_conflicts_check_local_path(const char *path, const char *uid,

		assert(strcmp(uid, p->uid) != 0);

-
		if (!kh_contains(pkg_conflicts, p->conflictshash, uid)) {
+
		if (pkghash_get(p->conflictshash, uid) == NULL) {
			/* We need to register the conflict between two universe chains */
			sqlite3_finalize(stmt);
			return (p);
@@ -404,6 +410,7 @@ pkg_conflicts_check_all_paths(struct pkg_jobs *j, const char *path,
	struct pkg_jobs_conflict_item *cit, test;
	struct pkg_conflict *c;
	uint64_t hv;
+
	pkghash_entry *e;

	hv = siphash24(path, strlen(path), k);
	test.hash = hv;
@@ -430,7 +437,10 @@ pkg_conflicts_check_all_paths(struct pkg_jobs *j, const char *path,
		}

		/* Here we can have either collision or a real conflict */
-
		kh_find(pkg_conflicts, it->pkg->conflictshash, uid2, c);
+
		c = NULL;
+
		e = pkghash_get(it->pkg->conflictshash, uid2);
+
		if (e != NULL)
+
			c = (struct pkg_conflict *)e->value;
		if (c != NULL || !pkg_conflicts_register_chain(j, it, cit->item, path)) {
			/*
			 * Collision found, change the key following the
modified libpkg/pkg_jobs_universe.c
@@ -157,6 +157,7 @@ pkg_jobs_universe_add_pkg(struct pkg_jobs_universe *universe, struct pkg *pkg,
		bool force __unused, struct pkg_job_universe_item **found)
{
	struct pkg_job_universe_item *item, *seen, *tmp = NULL;
+
	pkghash_entry *e;

	pkg_validate(pkg, universe->j->db);

@@ -169,7 +170,10 @@ pkg_jobs_universe_add_pkg(struct pkg_jobs_universe *universe, struct pkg *pkg,
		}
	}

-
	kh_find(pkg_jobs_seen, universe->seen, pkg->digest, seen);
+
	seen = NULL;
+
	e = pkghash_get(universe->seen, pkg->digest);
+
	if (e != NULL)
+
		seen = (struct pkg_job_universe_item *)e->value;
	if (seen) {
		bool same_package = false;

@@ -216,7 +220,7 @@ pkg_jobs_universe_add_pkg(struct pkg_jobs_universe *universe, struct pkg *pkg,
	DL_APPEND(tmp, item);

	if (seen == NULL)
-
		kh_safe_add(pkg_jobs_seen, universe->seen, item, item->pkg->digest);
+
		pkghash_safe_add(universe->seen, item->pkg->digest, item, NULL);

	universe->nitems++;

@@ -476,39 +480,40 @@ pkg_jobs_universe_process_shlibs(struct pkg_jobs_universe *universe,
{
	struct pkg_job_provide *pr;
	struct pkgdb_it *it;
-
	char *buf = NULL;
	int rc;
+
	pkghash_it hit;

-
	while (pkg_shlibs_required(pkg, &buf) == EPKG_OK) {
-
		HASH_FIND_STR(universe->provides, buf, pr);
+
	hit = pkghash_iterator(pkg->shlibs_required);
+
	while (pkghash_next(&hit)) {
+
		HASH_FIND_STR(universe->provides, hit.key, pr);
		if (pr != NULL)
			continue;

		/* Check for local provides */
-
		it = pkgdb_query_shlib_provide(universe->j->db, buf);
+
		it = pkgdb_query_shlib_provide(universe->j->db, hit.key);
		if (it != NULL) {
			rc = pkg_jobs_universe_handle_provide(universe, it,
-
			    buf, true, pkg);
+
			    hit.key, true, pkg);
			pkgdb_it_free(it);

			if (rc != EPKG_OK) {
				pkg_debug(1, "cannot find local packages that provide library %s "
						"required for %s",
-
						buf, pkg->name);
+
						hit.key, pkg->name);
			}
		}
		/* Not found, search in the repos */
		it = pkgdb_repo_shlib_provide(universe->j->db,
-
			buf, universe->j->reponame);
+
			hit.key, universe->j->reponame);

		if (it != NULL) {
-
			rc = pkg_jobs_universe_handle_provide(universe, it, buf, true, pkg);
+
			rc = pkg_jobs_universe_handle_provide(universe, it, hit.key, true, pkg);
			pkgdb_it_free(it);

			if (rc != EPKG_OK) {
				pkg_debug(1, "cannot find remote packages that provide library %s "
						"required for %s",
-
				    buf, pkg->name);
+
				    hit.key, pkg->name);
			}
		}
	}
@@ -522,39 +527,41 @@ pkg_jobs_universe_process_provides_requires(struct pkg_jobs_universe *universe,
{
	struct pkg_job_provide *pr;
	struct pkgdb_it *it;
-
	char *buf = NULL;
	int rc;
+
	pkghash_it hit;

-
	while (pkg_requires(pkg, &buf) == EPKG_OK) {
-
		HASH_FIND_STR(universe->provides, buf, pr);
+

+
	hit = pkghash_iterator(pkg->requires);
+
	while(pkghash_next(&hit)) {
+
		HASH_FIND_STR(universe->provides, hit.key, pr);
		if (pr != NULL)
			continue;

		/* Check for local provides */
-
		it = pkgdb_query_provide(universe->j->db, buf);
+
		it = pkgdb_query_provide(universe->j->db, hit.key);
		if (it != NULL) {
-
			rc = pkg_jobs_universe_handle_provide(universe, it, buf, false, pkg);
+
			rc = pkg_jobs_universe_handle_provide(universe, it, hit.key, false, pkg);
			pkgdb_it_free(it);

			if (rc != EPKG_OK) {
				pkg_debug(1, "cannot find local packages that provide %s "
						"required for %s",
-
						buf, pkg->name);
+
						hit.key, pkg->name);
			}
		}

		/* Not found, search in the repos */
		it = pkgdb_repo_provide(universe->j->db,
-
			buf, universe->j->reponame);
+
			hit.key, universe->j->reponame);

		if (it != NULL) {
-
			rc = pkg_jobs_universe_handle_provide(universe, it, buf, false, pkg);
+
			rc = pkg_jobs_universe_handle_provide(universe, it, hit.key, false, pkg);
			pkgdb_it_free(it);

			if (rc != EPKG_OK) {
				pkg_debug(1, "cannot find remote packages that provide %s "
						"required for %s",
-
				    buf, pkg->name);
+
				    hit.key, pkg->name);
				return (rc);
			}
		}
@@ -830,7 +837,8 @@ pkg_jobs_universe_free(struct pkg_jobs_universe *universe)
			free(cur);
		}
	}
-
	kh_destroy_pkg_jobs_seen(universe->seen);
+
	pkghash_destroy(universe->seen);
+
	universe->seen = NULL;
	HASH_FREE(universe->provides, pkg_jobs_universe_provide_free);
	LL_FREE(universe->uid_replaces, pkg_jobs_universe_replacement_free);
}
modified libpkg/pkg_manifest.c
@@ -985,6 +985,7 @@ pkg_emit_object(struct pkg *pkg, short flags)
	char legacyarch[BUFSIZ];
	ucl_object_t *map, *seq, *submap;
	ucl_object_t *top = ucl_object_typed_new(UCL_OBJECT);
+
	pkghash_it it;

	if (pkg->abi == NULL && pkg->arch != NULL)
		pkg->abi = xstrdup(pkg->arch);
@@ -1045,11 +1046,12 @@ pkg_emit_object(struct pkg *pkg, short flags)

	pkg_debug(4, "Emitting licenses");
	seq = NULL;
-
	kh_each_value(pkg->licenses, buf, {
+
	it = pkghash_iterator(pkg->licenses);
+
	while (pkghash_next(&it)) {
		if (seq == NULL)
			seq = ucl_object_typed_new(UCL_ARRAY);
-
		ucl_array_append(seq, ucl_object_fromstring(buf));
-
	});
+
		ucl_array_append(seq, ucl_object_fromstring(it.key));
+
	}
	if (seq)
		ucl_object_insert_key(top, seq, "licenses", 8, false);

@@ -1081,11 +1083,12 @@ pkg_emit_object(struct pkg *pkg, short flags)

	pkg_debug(4, "Emitting categories");
	seq = NULL;
-
	kh_each_value(pkg->categories, buf, {
+
	it = pkghash_iterator(pkg->categories);
+
	while (pkghash_next(&it)) {
		if (seq == NULL)
			seq = ucl_object_typed_new(UCL_ARRAY);
-
		ucl_array_append(seq, ucl_object_fromstring(buf));
-
	});
+
		ucl_array_append(seq, ucl_object_fromstring(it.key));
+
	}
	if (seq)
		ucl_object_insert_key(top, seq, "categories", 10, false);

@@ -1114,10 +1117,11 @@ pkg_emit_object(struct pkg *pkg, short flags)
	pkg_debug(4, "Emitting required");
	seq = NULL;
	buf = NULL;
-
	while (pkg_shlibs_required(pkg, &buf) == EPKG_OK) {
+
	it = pkghash_iterator(pkg->shlibs_required);
+
	while (pkghash_next(&it)) {
		if (seq == NULL)
			seq = ucl_object_typed_new(UCL_ARRAY);
-
		ucl_array_append(seq, ucl_object_fromstring(buf));
+
		ucl_array_append(seq, ucl_object_fromstring(it.key));
	}
	if (seq)
		ucl_object_insert_key(top, seq, "shlibs_required", 15, false);
@@ -1125,10 +1129,11 @@ pkg_emit_object(struct pkg *pkg, short flags)
	pkg_debug(4, "Emitting shlibs_provided");
	seq = NULL;
	buf = NULL;
-
	while (pkg_shlibs_provided(pkg, &buf) == EPKG_OK) {
+
	it = pkghash_iterator(pkg->shlibs_provided);
+
	while (pkghash_next(&it)) {
		if (seq == NULL)
			seq = ucl_object_typed_new(UCL_ARRAY);
-
		ucl_array_append(seq, ucl_object_fromstring(buf));
+
		ucl_array_append(seq, ucl_object_fromstring(it.key));
	}
	if (seq)
		ucl_object_insert_key(top, seq, "shlibs_provided", 15, false);
@@ -1146,10 +1151,11 @@ pkg_emit_object(struct pkg *pkg, short flags)
	pkg_debug(4, "Emitting provides");
	seq = NULL;
	buf = NULL;
-
	while (pkg_provides(pkg, &buf) == EPKG_OK) {
+
	it = pkghash_iterator(pkg->provides);
+
	while (pkghash_next(&it)) {
		if (seq == NULL)
			seq = ucl_object_typed_new(UCL_ARRAY);
-
		ucl_array_append(seq, ucl_object_fromstring(buf));
+
		ucl_array_append(seq, ucl_object_fromstring(it.key));
	}
	if (seq)
		ucl_object_insert_key(top, seq, "provides", 8, false);
@@ -1157,10 +1163,11 @@ pkg_emit_object(struct pkg *pkg, short flags)
	pkg_debug(4, "Emitting requires");
	seq = NULL;
	buf = NULL;
-
	while (pkg_requires(pkg, &buf) == EPKG_OK) {
+
	it = pkghash_iterator(pkg->requires);
+
	while (pkghash_next(&it)) {
		if (seq == NULL)
			seq = ucl_object_typed_new(UCL_ARRAY);
-
		ucl_array_append(seq, ucl_object_fromstring(buf));
+
		ucl_array_append(seq, ucl_object_fromstring(it.key));
	}
	if (seq)
		ucl_object_insert_key(top, seq, "requires", 8, false);
modified libpkg/pkg_printf.c
@@ -917,7 +917,7 @@ format_shlibs_required(xstring *buf, const void *data, struct percent_esc *p)
	if (p->flags & (PP_ALTERNATE_FORM1|PP_ALTERNATE_FORM2))
		return (list_count(buf, pkg_list_count(pkg, PKG_SHLIBS_REQUIRED), p));
	else {
-
		char	*buffer = NULL;
+
		pkghash_it it;
		int			 count;

		set_list_defaults(p, "%Bn\n", "");
@@ -925,13 +925,14 @@ format_shlibs_required(xstring *buf, const void *data, struct percent_esc *p)
		count = 1;
		fflush(p->sep_fmt->fp);
		fflush(p->item_fmt->fp);
-
		while (pkg_shlibs_required(pkg, &buffer) == EPKG_OK) {
+
		it = pkghash_iterator(pkg->shlibs_required);
+
		while (pkghash_next(&it)) {
			if (count > 1)
				iterate_item(buf, pkg, p->sep_fmt->buf,
-
					     buffer, count, PP_B);
+
					     it.key, count, PP_B);

			iterate_item(buf, pkg, p->item_fmt->buf,
-
				     buffer, count, PP_B);
+
				     it.key, count, PP_B);
			count++;
		}
	}
@@ -961,7 +962,6 @@ format_categories(xstring *buf, const void *data, struct percent_esc *p)
{
	const struct pkg	*pkg = data;
	int			 count = 0;
-
	char			*cat;

	if (p->flags & (PP_ALTERNATE_FORM1|PP_ALTERNATE_FORM2)) {
		return (list_count(buf, pkg_list_count(pkg, PKG_CATEGORIES), p));
@@ -971,15 +971,16 @@ format_categories(xstring *buf, const void *data, struct percent_esc *p)
		count = 1;
		fflush(p->sep_fmt->fp);
		fflush(p->item_fmt->fp);
-
		kh_each_value(pkg->categories, cat, {
+
		pkghash_it it = pkghash_iterator(pkg->categories);
+
		while (pkghash_next(&it)) {
			if (count > 1)
				iterate_item(buf, pkg, p->sep_fmt->buf,
-
				    cat, count, PP_C);
+
				    it.key, count, PP_C);

-
			iterate_item(buf, pkg, p->item_fmt->buf, cat,
+
			iterate_item(buf, pkg, p->item_fmt->buf, it.key,
			    count, PP_C);
			count++;
-
		});
+
		}
	}
	return (buf);
}
@@ -1233,7 +1234,6 @@ xstring *
format_licenses(xstring *buf, const void *data, struct percent_esc *p)
{
	const struct pkg	*pkg = data;
-
	char			*lic;
	int			 count = 0;

	if (p->flags & (PP_ALTERNATE_FORM1|PP_ALTERNATE_FORM2)) {
@@ -1244,15 +1244,16 @@ format_licenses(xstring *buf, const void *data, struct percent_esc *p)
		count = 1;
		fflush(p->sep_fmt->fp);
		fflush(p->item_fmt->fp);
-
		kh_each_value(pkg->licenses, lic, {
+
		pkghash_it it = pkghash_iterator(pkg->licenses);
+
		while (pkghash_next(&it)) {
			if (count > 1)
				iterate_item(buf, pkg, p->sep_fmt->buf,
-
				    lic, count, PP_L);
+
				    it.key, count, PP_L);

-
			iterate_item(buf, pkg, p->item_fmt->buf, lic,
+
			iterate_item(buf, pkg, p->item_fmt->buf, it.key,
			    count, PP_L);
			count++;
-
		});
+
		}
	}
	return (buf);
}
@@ -1536,7 +1537,6 @@ format_required(xstring *buf, const void *data, struct percent_esc *p)
	if (p->flags & (PP_ALTERNATE_FORM1|PP_ALTERNATE_FORM2))
		return (list_count(buf, pkg_list_count(pkg, PKG_REQUIRES), p));
	else {
-
		char	*provide = NULL;
		int	 count;

		set_list_defaults(p, "%Yn\n", "");
@@ -1544,13 +1544,14 @@ format_required(xstring *buf, const void *data, struct percent_esc *p)
		count = 1;
		fflush(p->sep_fmt->fp);
		fflush(p->item_fmt->fp);
-
		while (pkg_requires(pkg, &provide) == EPKG_OK) {
+
		pkghash_it it = pkghash_iterator(pkg->requires);
+
		while (pkghash_next(&it)) {
			if (count > 1)
				iterate_item(buf, pkg, p->sep_fmt->buf,
-
					     provide, count, PP_Y);
+
					     it.key, count, PP_Y);

			iterate_item(buf, pkg, p->item_fmt->buf,
-
				     provide, count, PP_Y);
+
				     it.key, count, PP_Y);
			count++;
		}
	}
@@ -1594,7 +1595,7 @@ format_shlibs_provided(xstring *buf, const void *data, struct percent_esc *p)
	if (p->flags & (PP_ALTERNATE_FORM1|PP_ALTERNATE_FORM2))
		return (list_count(buf, pkg_list_count(pkg, PKG_SHLIBS_PROVIDED), p));
	else {
-
		char	*shlib = NULL;
+
		pkghash_it it;
		int	 count;

		set_list_defaults(p, "%bn\n", "");
@@ -1602,13 +1603,14 @@ format_shlibs_provided(xstring *buf, const void *data, struct percent_esc *p)
		count = 1;
		fflush(p->sep_fmt->fp);
		fflush(p->item_fmt->fp);
-
		while (pkg_shlibs_provided(pkg, &shlib) == EPKG_OK) {
+
		it = pkghash_iterator(pkg->shlibs_provided);
+
		while (pkghash_next(&it)) {
			if (count > 1)
				iterate_item(buf, pkg, p->sep_fmt->buf,
-
					     shlib, count, PP_b);
+
					     it.key, count, PP_b);

			iterate_item(buf, pkg, p->item_fmt->buf,
-
				     shlib, count, PP_b);
+
				     it.key, count, PP_b);
			count++;
		}
	}
@@ -1936,7 +1938,7 @@ format_provided(xstring *buf, const void *data, struct percent_esc *p)
	if (p->flags & (PP_ALTERNATE_FORM1|PP_ALTERNATE_FORM2))
		return (list_count(buf, pkg_list_count(pkg, PKG_PROVIDES), p));
	else {
-
		char	*provide = NULL;
+
		pkghash_it it;
		int	 count;

		set_list_defaults(p, "%yn\n", "");
@@ -1944,13 +1946,14 @@ format_provided(xstring *buf, const void *data, struct percent_esc *p)
		count = 1;
		fflush(p->sep_fmt->fp);
		fflush(p->item_fmt->fp);
-
		while (pkg_provides(pkg, &provide) == EPKG_OK) {
+
		it = pkghash_iterator(pkg->provides);
+
		while (pkghash_next(&it)) {
			if (count > 1)
				iterate_item(buf, pkg, p->sep_fmt->buf,
-
					     provide, count, PP_y);
+
					     it.key, count, PP_y);

			iterate_item(buf, pkg, p->item_fmt->buf,
-
				     provide, count, PP_y);
+
				     it.key, count, PP_y);
			count++;
		}
	}
modified libpkg/pkg_repo_create.c
@@ -76,7 +76,7 @@ struct digest_list_entry {

struct pkg_conflict_bulk {
	struct pkg_conflict *conflicts;
-
	kh_pkg_conflicts_t *conflictshash;
+
	pkghash *conflictshash;
	char *file;
	UT_hash_handle hh;
};
@@ -830,7 +830,8 @@ cleanup:
		close(ffd);
	HASH_ITER (hh, conflicts, curcb, tmpcb) {
		DL_FREE(curcb->conflicts, pkg_conflict_free);
-
		kh_destroy_pkg_conflicts(curcb->conflictshash);
+
		pkghash_destroy(curcb->conflictshash);
+
		curcb->conflictshash = NULL;
		HASH_DEL(conflicts, curcb);
		free(curcb);
	}
modified libpkg/pkg_solve.c
@@ -308,7 +308,7 @@ pkg_solve_handle_provide (struct pkg_solve_problem *problem,
		pkg = curvar->unit->pkg;

		if (pr->is_shlib) {
-
			libfound = kh_contains(strings, pkg->shlibs_provided, pr->provide);
+
			libfound = (pkghash_get(pkg->shlibs_provided, pr->provide) != NULL);
			/* Skip incompatible ABI as well */
			if (libfound && strcmp(pkg->arch, orig->arch) != 0) {
				pkg_debug(2, "solver: require %s: package %s-%s(%c) provides wrong ABI %s, "
@@ -318,7 +318,7 @@ pkg_solve_handle_provide (struct pkg_solve_problem *problem,
			}
		}
		else {
-
			providefound = kh_contains(strings, pkg->provides, pr->provide);
+
			providefound = (pkghash_get(pkg->provides, pr->provide) != NULL);
		}

		if (!providefound && !libfound) {
@@ -737,7 +737,7 @@ pkg_solve_process_universe_variable(struct pkg_solve_problem *problem,
	struct pkg_solve_variable *cur_var;
	struct pkg_jobs *j = problem->j;
	struct pkg_job_request *jreq = NULL;
-
	char *buf;
+
	pkghash_it it;
	bool chain_added = false;

	LL_FOREACH(var, cur_var) {
@@ -773,17 +773,17 @@ pkg_solve_process_universe_variable(struct pkg_solve_problem *problem,
		}

		/* Shlibs */
-
		buf = NULL;
-
		while (pkg_shlibs_required(pkg, &buf) == EPKG_OK) {
+
		it = pkghash_iterator(pkg->shlibs_required);
+
		while (pkghash_next(&it)) {
			if (pkg_solve_add_require_rule(problem, cur_var,
-
					buf, cur_var->assumed_reponame) != EPKG_OK) {
+
			    it.key, cur_var->assumed_reponame) != EPKG_OK) {
				continue;
			}
		}
-
		buf = NULL;
-
		while (pkg_requires(pkg, &buf) == EPKG_OK) {
+
		it = pkghash_iterator(pkg->requires);
+
		while (pkghash_next(&it)) {
			if (pkg_solve_add_require_rule(problem, cur_var,
-
					buf, cur_var->assumed_reponame) != EPKG_OK) {
+
			    it.key, cur_var->assumed_reponame) != EPKG_OK) {
				continue;
			}
		}
modified libpkg/pkgdb.c
@@ -1754,6 +1754,7 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg, int forced,
	int64_t			 package_id;

	const char		*arch;
+
	pkghash_it		hit;

	assert(db != NULL);

@@ -1912,30 +1913,32 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg, int forced,
	 * Insert categories
	 */

-
	kh_each_value(pkg->categories, buf, {
-
		ret = run_prstmt(CATEGORY1, buf);
+
	hit = pkghash_iterator(pkg->categories);
+
	while (pkghash_next(&hit)) {
+
		ret = run_prstmt(CATEGORY1, hit.key);
		if (ret == SQLITE_DONE)
-
			ret = run_prstmt(CATEGORY2, package_id, buf);
+
			ret = run_prstmt(CATEGORY2, package_id, hit.key);
		if (ret != SQLITE_DONE) {
			ERROR_STMT_SQLITE(s, STMT(CATEGORY2));
			goto cleanup;
		}
-
	});
+
	}

	/*
	 * Insert licenses
	 */

-
	kh_each_value(pkg->licenses, buf, {
-
		if (run_prstmt(LICENSES1, buf)
+
	hit = pkghash_iterator(pkg->licenses);
+
	while (pkghash_next(&hit)) {
+
		if (run_prstmt(LICENSES1, hit.key)
		    != SQLITE_DONE
		    ||
-
		    run_prstmt(LICENSES2, package_id, buf)
+
		    run_prstmt(LICENSES2, package_id, hit.key)
		    != SQLITE_DONE) {
			ERROR_STMT_SQLITE(s, STMT(LICENSES2));
			goto cleanup;
		}
-
	});
+
	}

	/*
	 * Insert users
@@ -2085,13 +2088,13 @@ pkgdb_insert_lua_scripts(struct pkg *pkg, int64_t package_id, sqlite3 *s)
int
pkgdb_update_shlibs_required(struct pkg *pkg, int64_t package_id, sqlite3 *s)
{
-
	char	*shlib = NULL;
+
	pkghash_it it = pkghash_iterator(pkg->shlibs_required);

-
	while (pkg_shlibs_required(pkg, &shlib) == EPKG_OK) {
-
		if (run_prstmt(SHLIBS1, shlib)
+
	while (pkghash_next(&it)) {
+
		if (run_prstmt(SHLIBS1, it.key)
		    != SQLITE_DONE
		    ||
-
		    run_prstmt(SHLIBS_REQD, package_id, shlib)
+
		    run_prstmt(SHLIBS_REQD, package_id, it.key)
		    != SQLITE_DONE) {
			ERROR_STMT_SQLITE(s, STMT(SHLIBS_REQD));
			return (EPKG_FATAL);
@@ -2120,13 +2123,13 @@ pkgdb_update_config_file_content(struct pkg *p, sqlite3 *s)
int
pkgdb_update_shlibs_provided(struct pkg *pkg, int64_t package_id, sqlite3 *s)
{
-
	char	*shlib = NULL;
+
	pkghash_it it = pkghash_iterator(pkg->shlibs_provided);

-
	while (pkg_shlibs_provided(pkg, &shlib) == EPKG_OK) {
-
		if (run_prstmt(SHLIBS1, shlib)
+
	while (pkghash_next(&it)) {
+
		if (run_prstmt(SHLIBS1, it.key)
		    != SQLITE_DONE
		    ||
-
		    run_prstmt(SHLIBS_PROV, package_id, shlib)
+
		    run_prstmt(SHLIBS_PROV, package_id, it.key)
		    != SQLITE_DONE) {
			ERROR_STMT_SQLITE(s, STMT(SHLIBS_PROV));
			return (EPKG_FATAL);
@@ -2139,13 +2142,13 @@ pkgdb_update_shlibs_provided(struct pkg *pkg, int64_t package_id, sqlite3 *s)
int
pkgdb_update_requires(struct pkg *pkg, int64_t package_id, sqlite3 *s)
{
-
	char	*require = NULL;
+
	pkghash_it it = pkghash_iterator(pkg->requires);

-
	while (pkg_requires(pkg, &require) == EPKG_OK) {
-
		if (run_prstmt(REQUIRE, require)
+
	while (pkghash_next(&it)) {
+
		if (run_prstmt(REQUIRE, it.key)
		    != SQLITE_DONE
		    ||
-
		    run_prstmt(PKG_REQUIRE, package_id, require)
+
		    run_prstmt(PKG_REQUIRE, package_id, it.key)
		    != SQLITE_DONE) {
			ERROR_STMT_SQLITE(s, STMT(PKG_REQUIRE));
			return (EPKG_FATAL);
@@ -2158,13 +2161,13 @@ pkgdb_update_requires(struct pkg *pkg, int64_t package_id, sqlite3 *s)
int
pkgdb_update_provides(struct pkg *pkg, int64_t package_id, sqlite3 *s)
{
-
	char	*provide = NULL;
+
	pkghash_it it = pkghash_iterator(pkg->provides);

-
	while (pkg_provides(pkg, &provide) == EPKG_OK) {
-
		if (run_prstmt(PROVIDE, provide)
+
	while (pkghash_next(&it)) {
+
		if (run_prstmt(PROVIDE, it.key)
		    != SQLITE_DONE
		    ||
-
		    run_prstmt(PKG_PROVIDE, package_id, provide)
+
		    run_prstmt(PKG_PROVIDE, package_id, it.key)
		    != SQLITE_DONE) {
			ERROR_STMT_SQLITE(s, STMT(PKG_PROVIDE));
			return (EPKG_FATAL);
modified libpkg/pkghash.c
@@ -83,19 +83,15 @@ pkghash_get(pkghash *table, const char *key)
	return (NULL);
}

-
static const char *
+
static bool
pkghash_set_entry(pkghash_entry *entries, size_t capacity,
    const char *key, void *value, size_t *pcount, void (*free_func)(void *)) {
	uint64_t hash = mum_hash(key, strlen(key), 0);
	size_t index = (size_t)(hash & (uint64_t)(capacity - 1));

	while (entries[index].key != NULL) {
-
		if (strcmp(key, entries[index].key) == 0) {
-
			if (entries[index].free_func != NULL)
-
				entries[index].free_func(entries[index].value);
-
			entries[index].value = value;
-
			return (entries[index].key);
-
		}
+
		if (strcmp(key, entries[index].key) == 0)
+
			return (false);
		index++;
		if (index >= capacity)
			index = 0;
@@ -108,7 +104,7 @@ pkghash_set_entry(pkghash_entry *entries, size_t capacity,
	entries[index].key = (char *)key;
	entries[index].value = value;
	entries[index].free_func = free_func;
-
	return (key);
+
	return (true);
}

static bool
@@ -132,7 +128,7 @@ pkghash_expand(pkghash *table)
	return (true);
}

-
const char *
+
bool
pkghash_add(pkghash *table, const char *key, void *value, void (*free_func)(void *))
{
	if (table->count >= table->capacity / 2 && !pkghash_expand(table))
modified libpkg/pkghash.h
@@ -8,7 +8,7 @@ typedef struct pkghash pkghash;

pkghash *pkghash_new(void);
void pkghash_destroy(pkghash *table);
-
const char *pkghash_add(pkghash *table, const char *key, void *value, void (*free_func)(void *));
+
bool pkghash_add(pkghash *table, const char *key, void *value, void (*free_func)(void *));
size_t pkghash_count(pkghash *table);

typedef struct {
modified libpkg/private/pkg.h
@@ -44,6 +44,7 @@

#include "xmalloc.h"
#include "private/utils.h"
+
#include "pkghash.h"

#define UCL_COUNT(obj) ((obj)?((obj)->len):0)

@@ -147,67 +148,6 @@
			return (EPKG_OK);     \
	} while (0)

-
#define KHASH_MAP_INIT_STRING(name, khval_t)                                             \
-
	KHASH_INIT(name, kh_cstr_t, khval_t, 1, string_hash_func, kh_str_hash_equal)
-

-
#define kh_string_next(head, data) do {                  \
-
	khint_t k;                                       \
-
	if (head == NULL)                                \
-
		return (EPKG_END);                       \
-
	if (data == NULL) {                              \
-
		k = kh_begin(head);                      \
-
	} else {                                         \
-
		k = kh_get_strings(head, (data));        \
-
		k++;                                     \
-
	}                                                \
-
	while (k != kh_end(head) && !kh_exist(head, k))  \
-
		k++;                                     \
-
	if (k == kh_end(head))                           \
-
		return (EPKG_END);                       \
-
	data = kh_value(head, k);                        \
-
	return (EPKG_OK);                                \
-
} while (0)
-

-
#define kh_next(name, head, data, attrib) do {           \
-
	khint_t k;                                       \
-
	if (head == NULL)                                \
-
		return (EPKG_END);                       \
-
	if (data == NULL) {                              \
-
		k = kh_begin(head);                      \
-
	} else {                                         \
-
		k = kh_get_##name(head, (data)->attrib); \
-
		k++;                                     \
-
	}                                                \
-
	while (k != kh_end(head) && !kh_exist(head, k))  \
-
		k++;                                     \
-
	if (k == kh_end(head)) {                         \
-
		data = NULL;                             \
-
		return (EPKG_END);                       \
-
	}                                                \
-
	data = kh_value(head, k);                        \
-
	return (EPKG_OK);                                \
-
} while (0)
-

-
#define kh_free(name, head, type, free_func) do {			\
-
	if (head) {							\
-
		type *_todelete;					\
-
		kh_foreach_value(head, _todelete, free_func(_todelete));\
-
		kh_destroy_##name(head);				\
-
		head = NULL;						\
-
	}								\
-
} while (0)
-

-
#define kh_contains(name, h, v) ((h)?(kh_get_##name(h, v) != kh_end(h)):false)
-

-
#define kh_each_value(h, vvar, code)							\
-
	for (khint_t __i = kh_begin(h); h != NULL && __i != kh_end(h); __i++) {		\
-
		if (!kh_exist(h, __i)) continue;					\
-
		(vvar) = kh_val(h, __i);						\
-
		code;									\
-
	}
-

-
#define kh_count(h) ((h)?((h)->size):0)
-

#define kh_safe_add(name, h, val, k) do {		\
	int __ret;					\
	khint_t __i;					\
@@ -217,17 +157,6 @@
		kh_val(h, __i) = val;			\
} while (0)

-
#define kh_add(name, h, val, k, free_func) do {		\
-
	int __ret;					\
-
	khint_t __i;					\
-
	if (!h) h = kh_init_##name();			\
-
	__i = kh_put_##name(h, k, &__ret);		\
-
	if (__ret != 0)					\
-
		kh_val(h, __i) = val;			\
-
	else						\
-
		free_func(val);				\
-
} while (0)
-

#define kh_find(name, h, k, ret) do {			\
	khint_t __k;					\
	ret = NULL;					\
@@ -239,14 +168,6 @@
	}						\
} while (0)

-
KHASH_MAP_INIT_STR(pkg_deps, struct pkg_dep *);
-
KHASH_MAP_INIT_STR(pkg_files, struct pkg_file *);
-
KHASH_MAP_INIT_STR(pkg_dirs, struct pkg_dir *);
-
KHASH_MAP_INIT_STR(pkg_config_files, struct pkg_config_file *);
-
KHASH_MAP_INIT_STR(strings, char *);
-
KHASH_MAP_INIT_STR(pkg_options, struct pkg_option *);
-
KHASH_MAP_INIT_STR(pkg_conflicts, struct pkg_conflict *);
-

struct pkg_ctx {
	int eventpipe;
	int64_t debug_level;
@@ -265,7 +186,7 @@ struct pkg_ctx {
	const char *backup_library_path;
	bool triggers;
	const char *triggers_path;
-
	kh_strings_t *touched_dir_hash;
+
	pkghash *touched_dir_hash;
	bool defer_triggers;
	bool repo_accept_legacy_pkg;
};
@@ -311,27 +232,28 @@ struct pkg {
	int64_t			 flatsize;
	int64_t			 old_flatsize;
	int64_t			 timestamp;
-
	kh_pkg_deps_t		*depshash;
+
	pkghash			*depshash;
	struct pkg_dep		*depends;
-
	kh_pkg_deps_t		*rdepshash;
+
	pkghash			*rdepshash;
	struct pkg_dep		*rdepends;
-
	kh_strings_t		*categories;
-
	kh_strings_t		*licenses;
-
	kh_pkg_files_t		*filehash;
+
	pkghash			*categories;
+
	pkghash			*licenses;
+
	pkghash			*filehash;
	struct pkg_file		*files;
-
	kh_pkg_dirs_t		*dirhash;
+
	pkghash			*dirhash;
	struct pkg_dir		*dirs;
-
	kh_pkg_options_t	*optionshash;
+
	pkghash			*optionshash;
	struct pkg_option	*options;
-
	kh_strings_t		*users;
-
	kh_strings_t		*groups;
-
	kh_strings_t		*shlibs_required;
-
	kh_strings_t		*shlibs_provided;
-
	kh_pkg_conflicts_t	*conflictshash;
+
	pkghash			*users;
+
	pkghash			*groups;
+
	pkghash			*shlibs_required;
+
	pkghash			*shlibs_provided;
+
	pkghash			*conflictshash;
	struct pkg_conflict	*conflicts;
-
	kh_strings_t		*provides;
-
	kh_strings_t		*requires;
-
	kh_pkg_config_files_t	*config_files;
+
	pkghash			*provides;
+
	pkghash			*requires;
+
	pkghash			*config_files_hash;
+
	struct pkg_config_file	*config_files;
	struct pkg_kv		*annotations;
	unsigned			flags;
	int		rootfd;
@@ -364,7 +286,7 @@ struct trigger {
		int type;
		bool sandbox;
	} cleanup;
-
	kh_strings_t *matched;
+
	pkghash *matched;
	struct trigger *prev, *next;
};

@@ -440,6 +362,7 @@ struct pkg_config_file {
	char *content;
	char *newcontent;
	merge_status status;
+
	struct pkg_config_file *next, *prev;
};

struct pkg_file {
@@ -884,7 +807,7 @@ int pkg_adddir(struct pkg *pkg, const char *path, bool check_duplicates);
int pkg_adddir_attr(struct pkg *pkg, const char *path, const char *uname,
    const char *gname, mode_t perm, u_long fflags, bool check_duplicates);

-
int pkg_addstring(kh_strings_t **s, const char *value, const char *title);
+
int pkg_addstring(pkghash **s, const char *value, const char *title);
int pkg_kv_add(struct pkg_kv **kv, const char *key, const char *value, const char *title);
const char *pkg_kv_get(struct pkg_kv *const*kv, const char *key);
int pkg_adduser(struct pkg *pkg, const char *name);
modified libpkg/private/pkg_jobs.h
@@ -68,8 +68,6 @@ struct pkg_solved {
	struct pkg_solved *prev, *next;
};

-
KHASH_MAP_INIT_STR(pkg_jobs_seen, struct pkg_job_universe_item *);
-

struct pkg_job_provide {
	struct pkg_job_universe_item *un;
	const char *provide;
@@ -86,7 +84,7 @@ struct pkg_job_replace {

struct pkg_jobs_universe {
	struct pkg_job_universe_item *items;
-
	kh_pkg_jobs_seen_t *seen;
+
	pkghash *seen;
	struct pkg_job_provide *provides;
	struct pkg_job_replace *uid_replaces;
	struct pkg_jobs *j;
modified libpkg/repo/binary/update.c
@@ -134,10 +134,10 @@ pkg_repo_binary_add_pkg(struct pkg *pkg, const char *pkg_path,
	int			 ret;
	struct pkg_dep		*dep      = NULL;
	struct pkg_option	*option   = NULL;
-
	char			*buf;
	struct pkg_kv		*kv;
	const char		*arch;
	int64_t			 package_id;
+
	pkghash_it		it;

	arch = pkg->abi != NULL ? pkg->abi : pkg->arch;

@@ -178,27 +178,29 @@ try_again:
		}
	}

-
	kh_each_value(pkg->categories, buf, {
-
		ret = pkg_repo_binary_run_prstatement(CAT1, buf);
+
	it = pkghash_iterator(pkg->categories);
+
	while (pkghash_next(&it)) {
+
	ret = pkg_repo_binary_run_prstatement(CAT1, it.key);
		if (ret == SQLITE_DONE)
			ret = pkg_repo_binary_run_prstatement(CAT2, package_id,
-
			    buf);
+
			    it.key);
		if (ret != SQLITE_DONE) {
			ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(CAT2));
			return (EPKG_FATAL);
		}
-
	});
+
	}

-
	kh_each_value(pkg->licenses, buf, {
-
		ret = pkg_repo_binary_run_prstatement(LIC1, buf);
+
	it = pkghash_iterator(pkg->licenses);
+
	while (pkghash_next(&it)) {
+
		ret = pkg_repo_binary_run_prstatement(LIC1, it.key);
		if (ret == SQLITE_DONE)
			ret = pkg_repo_binary_run_prstatement(LIC2, package_id,
-
			    buf);
+
			    it.key);
		if (ret != SQLITE_DONE) {
			ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(LIC2));
			return (EPKG_FATAL);
		}
-
	});
+
	}

	option = NULL;
	while (pkg_options(pkg, &option) == EPKG_OK) {
@@ -212,48 +214,48 @@ try_again:
		}
	}

-
	buf = NULL;
-
	while (pkg_shlibs_required(pkg, &buf) == EPKG_OK) {
-
		ret = pkg_repo_binary_run_prstatement(SHLIB1, buf);
+
	it = pkghash_iterator(pkg->shlibs_required);
+
	while (pkghash_next(&it)) {
+
		ret = pkg_repo_binary_run_prstatement(SHLIB1, it.key);
		if (ret == SQLITE_DONE)
			ret = pkg_repo_binary_run_prstatement(SHLIB_REQD, package_id,
-
			    buf);
+
			    it.key);
		if (ret != SQLITE_DONE) {
			ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(SHLIB_REQD));
			return (EPKG_FATAL);
		}
	}

-
	buf = NULL;
-
	while (pkg_shlibs_provided(pkg, &buf) == EPKG_OK) {
-
		ret = pkg_repo_binary_run_prstatement(SHLIB1, buf);
+
	it = pkghash_iterator(pkg->shlibs_provided);
+
	while (pkghash_next(&it)) {
+
		ret = pkg_repo_binary_run_prstatement(SHLIB1, it.key);
		if (ret == SQLITE_DONE)
			ret = pkg_repo_binary_run_prstatement(SHLIB_PROV, package_id,
-
			    buf);
+
			    it.key);
		if (ret != SQLITE_DONE) {
			ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(SHLIB_PROV));
			return (EPKG_FATAL);
		}
	}

-
	buf = NULL;
-
	while (pkg_provides(pkg, &buf) == EPKG_OK) {
-
		ret = pkg_repo_binary_run_prstatement(PROVIDE, buf);
+
	it = pkghash_iterator(pkg->provides);
+
	while (pkghash_next(&it)) {
+
		ret = pkg_repo_binary_run_prstatement(PROVIDE, it.key);
		if (ret == SQLITE_DONE)
			ret = pkg_repo_binary_run_prstatement(PROVIDES, package_id,
-
			    buf);
+
			    it.key);
		if (ret != SQLITE_DONE) {
			ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(PROVIDES));
			return (EPKG_FATAL);
		}
	}

-
	buf = NULL;
-
	while (pkg_requires(pkg, &buf) == EPKG_OK) {
-
		ret = pkg_repo_binary_run_prstatement(REQUIRE, buf);
+
	it = pkghash_iterator(pkg->requires);
+
	while (pkghash_next(&it)) {
+
		ret = pkg_repo_binary_run_prstatement(REQUIRE, it.key);
		if (ret == SQLITE_DONE)
			ret = pkg_repo_binary_run_prstatement(REQUIRES, package_id,
-
			    buf);
+
			    it.key);
		if (ret != SQLITE_DONE) {
			ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(REQUIRES));
			return (EPKG_FATAL);
modified libpkg/triggers.c
@@ -350,10 +350,10 @@ get_random_name(char name[])
}

static void
-
save_trigger(const char *script, bool sandbox, kh_strings_t *args)
+
save_trigger(const char *script, bool sandbox, pkghash *args)
{
	int db = ctx.pkg_dbdirfd;
-
	const char *dir;
+
	pkghash_it it;

	if (!mkdirat_p(db, "triggers"))
		return;
@@ -386,19 +386,21 @@ save_trigger(const char *script, bool sandbox, kh_strings_t *args)
	if (sandbox)
		fputs("--sandbox\n", f);
	fputs("--begin args\n", f);
-
	kh_foreach_value(args, dir, {
-
		fprintf(f, "-- %s\n", dir);
-
	});
+
	it = pkghash_iterator(args);
+
	while (pkghash_next(&it)) {
+
		fprintf(f, "-- %s\n", (char *)it.value);
+
	}
	fputs("--end args\n--\n", f);
	fprintf(f, "%s\n", script);
	fclose(f);
}

static int
-
trigger_execute_lua(const char *script, bool sandbox, kh_strings_t *args)
+
trigger_execute_lua(const char *script, bool sandbox, pkghash *args)
{
	lua_State *L;
	int pstat;
+
	pkghash_it it;

	if (ctx.defer_triggers) {
		save_trigger(script, sandbox, args);
@@ -423,14 +425,14 @@ trigger_execute_lua(const char *script, bool sandbox, kh_strings_t *args)
		lua_setglobal(L, "pkg");
		lua_pushinteger(L, ctx.rootfd);
		lua_setglobal(L, "rootfd");
-
		char *dir;
		char **arguments = NULL;
		int i = 0;
		if (args != NULL) {
-
			arguments = xcalloc(kh_count(args), sizeof(char*));
-
			kh_foreach_value(args, dir, {
-
				arguments[i++] = dir;
-
			});
+
			arguments = xcalloc(pkghash_count(args), sizeof(char*));
+
			it = pkghash_iterator(args);
+
			while (pkghash_next(&it)) {
+
				arguments[i++] = it.value;
+
			}
		}
		lua_args_table(L, arguments, i);
#ifdef HAVE_CAPSICUM
@@ -479,14 +481,14 @@ trigger_check_match(struct trigger *t, char *dir)
		it = NULL;
		while ((cur = ucl_iterate_object(t->path, &it, true))) {
			if (strcmp(dir, ucl_object_tostring(cur)) == 0) {
-
				kh_safe_add(strings, t->matched, dir, dir);
+
				pkghash_safe_add(t->matched, dir, dir, NULL);
				return;
			}
		}
	}

	if (match_ucl_lists(dir, t->path_glob, t->path_regex))
-
		kh_safe_add(strings, t->matched, dir, dir);
+
		pkghash_safe_add(t->matched, dir, dir, NULL);
}

/*
@@ -498,8 +500,7 @@ int
triggers_execute(struct trigger *cleanup_triggers)
{
	struct trigger *triggers, *t, *trigger;
-
	kh_strings_t *th = NULL;
-
	char *dir;
+
	pkghash *th = NULL;
	int ret = EPKG_OK;

	triggers = triggers_load(false);
@@ -509,20 +510,22 @@ triggers_execute(struct trigger *cleanup_triggers)
	 */
	if (cleanup_triggers != NULL) {
		LL_FOREACH(triggers, t) {
-
			kh_add(strings, th, t->name, t->name, free);
+
			pkghash_safe_add(th, t->name, t->name, NULL);
		}
	}

	/*
	 * only keep from the cleanup the one that are not anymore in triggers
	 */
-
	LL_FOREACH_SAFE(cleanup_triggers, trigger, t) {
-
		if (kh_contains(strings, th, trigger->name)) {
-
			DL_DELETE(cleanup_triggers, trigger);
-
			trigger_free(trigger);
+
	if (th != NULL) {
+
		LL_FOREACH_SAFE(cleanup_triggers, trigger, t) {
+
			if (pkghash_get(th, trigger->name) != NULL) {
+
				DL_DELETE(cleanup_triggers, trigger);
+
				trigger_free(trigger);
+
			}
		}
+
		pkghash_destroy(th);
	}
-
	kh_destroy_strings(th);

	pkg_emit_triggers_begin();
	LL_FOREACH(cleanup_triggers, t) {
@@ -536,12 +539,13 @@ triggers_execute(struct trigger *cleanup_triggers)
	}

	if (ctx.touched_dir_hash) {
-
		kh_foreach_value(ctx.touched_dir_hash, dir, {
-
				LL_FOREACH(triggers, t) {
-
				trigger_check_match(t, dir);
-
				}
+
		pkghash_it it = pkghash_iterator(ctx.touched_dir_hash);
+
		while (pkghash_next(&it)) {
+
			LL_FOREACH(triggers, t) {
+
				trigger_check_match(t, (char *)it.value);
+
			}
				/* We need to check if that matches a trigger */
-
				});
+
		}
	}

	LL_FOREACH(triggers, t) {
@@ -581,14 +585,14 @@ append_touched_file(const char *path)
		return;
	*walk = '\0';

-
	kh_add(strings, ctx.touched_dir_hash, newpath, newpath, free);
+
	pkghash_safe_add(ctx.touched_dir_hash, newpath, newpath, free);
}

void
exec_deferred(int dfd, const char *name)
{
	bool sandbox = false;
-
	kh_strings_t *args = NULL;
+
	pkghash *args = NULL;
	xstring *script = NULL;

	int fd = openat(dfd, name, O_RDONLY);
@@ -628,7 +632,7 @@ exec_deferred(int dfd, const char *name)
			if (line[linelen -1] == '\n')
				line[linelen -1] = '\0';
			char *s = strdup(walk);
-
			kh_add(strings, args, s, s, free);
+
			pkghash_safe_add(args, s, s, free);
		}
		if (script != NULL)
			fputs(line, script->fp);
@@ -636,7 +640,7 @@ exec_deferred(int dfd, const char *name)
	free(line);
	fclose(f);
	if (script == NULL) {
-
		kh_destroy_strings(args);
+
		pkghash_destroy(args);
		return;
	}
	char *s = xstring_get(script);
@@ -644,7 +648,7 @@ exec_deferred(int dfd, const char *name)
		unlinkat(dfd, name, 0);
	}
	free(s);
-
	kh_destroy_strings(args);
+
	pkghash_destroy(args);
}

int
modified src/audit.c
@@ -43,7 +43,6 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
-
#include <khash.h>
#include <utlist.h>
#include <ucl.h>

@@ -59,6 +58,7 @@
#include <pkg/audit.h>
#include "pkgcli.h"
#include "xmalloc.h"
+
#include "pkghash.h"

static const char* vop_names[] = {
	[0] = "",
@@ -76,40 +76,31 @@ usage_audit(void)
	fprintf(stderr, "For more information see 'pkg help audit'.\n");
}

-
KHASH_MAP_INIT_STR(pkgs, struct pkg *);
-

static void
-
add_to_check(kh_pkgs_t *check, struct pkg *pkg)
+
add_to_check(pkghash *check, struct pkg *pkg)
{
	const char *uid;
-
	int ret;
-
	khint_t k;

	pkg_get(pkg, PKG_UNIQUEID, &uid);
-

-
	k = kh_put_pkgs(check, uid, &ret);
-
	if (ret != 0)
-
		kh_value(check, k) = pkg;
+
	pkghash_safe_add(check, uid, pkg, NULL);
}

static void
-
print_recursive_rdeps(kh_pkgs_t *head, struct pkg *p, kh_pkgs_t *seen, bool top, ucl_object_t *array)
+
print_recursive_rdeps(pkghash *head, struct pkg *p, pkghash *seen, bool top, ucl_object_t *array)
{
+
	pkghash_entry *e;
	struct pkg_dep *dep = NULL;
-
	int ret;
-
	khint_t k, h;

	while(pkg_rdeps(p, &dep) == EPKG_OK) {
		const char *name = pkg_dep_get(dep, PKG_DEP_NAME);

-
		k = kh_get_pkgs(seen, name);
-
		if (k != kh_end(seen))
+
		if (pkghash_get(seen, name) != NULL)
			continue;
-
		h = kh_get_pkgs(head, name);
-
		if (h == kh_end(head))
+

+
		if ((e = pkghash_get(head, name)) == NULL)
			continue;

-
		kh_put_pkgs(seen, name, &ret);
+
		pkghash_safe_add(seen, name, NULL, NULL);
		if (array == NULL) {
			if (!top)
				printf(", ");
@@ -119,7 +110,7 @@ print_recursive_rdeps(kh_pkgs_t *head, struct pkg *p, kh_pkgs_t *seen, bool top,
			ucl_array_append(array, ucl_object_fromstring(name));
		}

-
		print_recursive_rdeps(head, kh_val(head, h), seen, false, array);
+
		print_recursive_rdeps(head, (struct pkg *)e->value, seen, false, array);

		top = false;
	}
@@ -226,7 +217,8 @@ exec_audit(int argc, char **argv)
	int			 ch, i;
	int			 raw;
	int			 ret = EXIT_SUCCESS;
-
	kh_pkgs_t		*check = NULL;
+
	pkghash			*check = NULL;
+
	pkghash_it		hit;
	ucl_object_t		*top = NULL, *vuln_objs = NULL;
	ucl_object_t		*obj = NULL;

@@ -299,7 +291,7 @@ exec_audit(int argc, char **argv)
		return (EXIT_FAILURE);
	}

-
	check = kh_init_pkgs();
+
	check = pkghash_new();
	if (argc >= 1) {
		for (i = 0; i < argc; i ++) {
			name = argv[i];
@@ -330,30 +322,30 @@ exec_audit(int argc, char **argv)
		ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL);
		if (ret == EPKG_ENODB) {
			pkg_audit_free(audit);
-
			kh_destroy_pkgs(check);
+
			pkghash_destroy(check);
			return (EXIT_SUCCESS);
		} else if (ret == EPKG_ENOACCESS) {
			warnx("Insufficient privileges to read the package database");
			pkg_audit_free(audit);
-
			kh_destroy_pkgs(check);
+
			pkghash_destroy(check);
			return (EXIT_FAILURE);
		} else if (ret != EPKG_OK) {
			warnx("Error accessing the package database");
			pkg_audit_free(audit);
-
			kh_destroy_pkgs(check);
+
			pkghash_destroy(check);
			return (EXIT_FAILURE);
		}

		if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) {
			pkg_audit_free(audit);
-
			kh_destroy_pkgs(check);
+
			pkghash_destroy(check);
			return (EXIT_FAILURE);
		}

		if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) {
			pkgdb_close(db);
			pkg_audit_free(audit);
-
			kh_destroy_pkgs(check);
+
			pkghash_destroy(check);
			warnx("Cannot get a read lock on a database, it is locked by another process");
			return (EXIT_FAILURE);
		}
@@ -377,7 +369,7 @@ exec_audit(int argc, char **argv)
		}
		if (ret != EXIT_SUCCESS) {
			pkg_audit_free(audit);
-
			kh_destroy_pkgs(check);
+
			pkghash_destroy(check);
			return (ret);
		}
	}
@@ -389,14 +381,16 @@ exec_audit(int argc, char **argv)
	if (cap_enter() < 0 && errno != ENOSYS) {
		warn("cap_enter() failed");
		pkg_audit_free(audit);
-
		kh_destroy_pkgs(check);
+
		pkghash_destroy(check);
		return (EPKG_FATAL);
	}
#endif

	if (pkg_audit_process(audit) == EPKG_OK) {
-
		kh_foreach_value(check, pkg, {
+
		hit = pkghash_iterator(check);
+
		while (pkghash_next(&hit)) {
			issues = NULL;
+
			pkg = (struct pkg *) hit.value;
			if (pkg_audit_is_vulnerable(audit, pkg, &issues, quiet)) {
				const char *version;
				const char *name = NULL;
@@ -443,7 +437,7 @@ exec_audit(int argc, char **argv)
				array = NULL;

				if (top != NULL || recursive) {
-
					kh_pkgs_t *seen = kh_init_pkgs();
+
					pkghash *seen = pkghash_new();

					if (name == NULL)
						pkg_get(pkg, PKG_NAME, &name);
@@ -456,7 +450,7 @@ exec_audit(int argc, char **argv)
					if (top == NULL)
						printf("\n\n");

-
					kh_destroy_pkgs(seen);
+
					pkghash_destroy(seen);
				}
				if (top != NULL) {
					ucl_object_insert_key(obj, array, "reverse dependencies", 20, false);
@@ -465,8 +459,8 @@ exec_audit(int argc, char **argv)
			}
			pkg_audit_issues_free(issues);
			pkg_free(pkg);
-
		});
-
		kh_destroy_pkgs(check);
+
		}
+
		pkghash_destroy(check);

		if (ret == EPKG_END && vuln == 0)
			ret = EXIT_SUCCESS;
@@ -485,7 +479,7 @@ exec_audit(int argc, char **argv)
	} else {
		warnx("cannot process vulnxml");
		ret = EXIT_FAILURE;
-
		kh_destroy_pkgs(check);
+
		pkghash_destroy(check);
	}

	pkg_audit_free(audit);
modified src/clean.c
@@ -49,7 +49,6 @@
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
-
#include <khash.h>
#include <kvec.h>
#include <fcntl.h>
#include <dirent.h>
@@ -58,8 +57,8 @@
#include <bsd_compat.h>

#include "pkgcli.h"
+
#include "pkghash.h"

-
KHASH_MAP_INIT_STR(sum, char *);
typedef kvec_t(char *) dl_list;

#define OUT_OF_DATE	(1U<<0)
@@ -153,7 +152,7 @@ delete_dellist(int fd, const char *cachedir, dl_list *dl, int total)
	return (retcode);
}

-
static kh_sum_t *
+
static pkghash *
populate_sums(struct pkgdb *db)
{
	struct pkg *p = NULL;
@@ -161,19 +160,16 @@ populate_sums(struct pkgdb *db)
	const char *sum;
	char *cksum;
	size_t slen;
-
	kh_sum_t *suml = NULL;
-
	khint_t k;
-
	int ret;
+
	pkghash *suml = NULL;

-
	suml = kh_init_sum();
+
	suml = pkghash_new();
	it = pkgdb_repo_search(db, "*", MATCH_GLOB, FIELD_NAME, FIELD_NONE, NULL);
	while (pkgdb_it_next(it, &p, PKG_LOAD_BASIC) == EPKG_OK) {
		pkg_get(p, PKG_CKSUM, &sum);
		slen = MIN(strlen(sum), PKG_FILE_CKSUM_CHARS);
		cksum = strndup(sum, slen);
-
		k = kh_put_sum(suml, cksum, &ret);
-
		if (ret != 0)
-
			kh_value(suml, k) = cksum;
+
		pkghash_safe_add(suml, cksum, NULL, NULL);
+
		free(cksum);
	}

	return (suml);
@@ -209,7 +205,7 @@ extract_filename_sum(const char *fname, char sum[])

static int
recursive_analysis(int fd, struct pkgdb *db, const char *dir,
-
    const char *cachedir, dl_list *dl, kh_sum_t **sumlist, bool all,
+
    const char *cachedir, dl_list *dl, pkghash **sumlist, bool all,
    size_t *total)
{
	DIR *d;
@@ -220,7 +216,7 @@ recursive_analysis(int fd, struct pkgdb *db, const char *dir,
	const char *name;
	ssize_t link_len;
	size_t nbfiles = 0, added = 0;
-
	khint_t k;
+
	pkghash_entry *e;

	tmpfd = dup(fd);
	d = fdopendir(tmpfd);
@@ -273,10 +269,11 @@ recursive_analysis(int fd, struct pkgdb *db, const char *dir,
			name = link_buf;
		}

-
		k = kh_end(*sumlist);
-
		if (extract_filename_sum(name, csum))
-
			k = kh_get_sum(*sumlist, csum);
-
		if (k == kh_end(*sumlist)) {
+
		e = NULL;
+
		if (extract_filename_sum(name, csum)) {
+
			e = pkghash_get(*sumlist, csum);
+
		}
+
		if (e == NULL) {
			added++;
			*total += add_to_dellist(fd, dl, cachedir, path);
		}
@@ -296,7 +293,7 @@ int
exec_clean(int argc, char **argv)
{
	struct pkgdb	*db = NULL;
-
	kh_sum_t	*sumlist = NULL;
+
	pkghash		*sumlist = NULL;
	dl_list		 dl;
	const char	*cachedir;
	bool		 all = false;
@@ -305,7 +302,6 @@ exec_clean(int argc, char **argv)
	int		 cachefd = -1;
	size_t		 total = 0;
	char		 size[8];
-
	char		*cksum;
	struct pkg_manifest_key *keys = NULL;
#ifdef HAVE_CAPSICUM
	cap_rights_t rights;
@@ -400,10 +396,7 @@ exec_clean(int argc, char **argv)
	pkg_manifest_keys_new(&keys);
	recursive_analysis(cachefd, db, cachedir, cachedir, &dl, &sumlist, all,
	    &total);
-
	if (sumlist != NULL) {
-
		kh_foreach_value(sumlist, cksum, free(cksum));
-
		kh_destroy_sum(sumlist);
-
	}
+
	pkghash_destroy(sumlist);

	if (kv_size(dl) == 0) {
		if (!quiet)
modified src/upgrade.c
@@ -38,8 +38,8 @@
#include <unistd.h>
#include <errno.h>
#include <signal.h>
-
#include <khash.h>
#include <xstring.h>
+
#include <pkghash.h>
#include <pkg.h>

#ifdef HAVE_SYS_CAPSICUM_H
@@ -61,20 +61,13 @@ usage_upgrade(void)
	fprintf(stderr, "For more information see 'pkg help upgrade'.\n");
}

-
KHASH_MAP_INIT_STR(pkgs, struct pkg *);
-

static void
-
add_to_check(kh_pkgs_t *check, struct pkg *pkg)
+
add_to_check(pkghash *check, struct pkg *pkg)
{
	const char *uid;
-
	int ret;
-
	khint_t k;

	pkg_get(pkg, PKG_UNIQUEID, &uid);
-

-
	k = kh_put_pkgs(check, uid, &ret);
-
	if (ret != 0)
-
		kh_value(check, k) = pkg;
+
	pkghash_safe_add(check, uid, pkg, NULL);
}

static void
@@ -83,7 +76,8 @@ check_vulnerable(struct pkg_audit *audit, struct pkgdb *db, int sock)
	struct pkg_audit_issues	*issues;
	struct pkgdb_it	*it = NULL;
	struct pkg		*pkg = NULL;
-
	kh_pkgs_t		*check = NULL;
+
	pkghash			*check = NULL;
+
	pkghash_it		hit;
	const char		*uid;
	FILE			*out;

@@ -99,7 +93,7 @@ check_vulnerable(struct pkg_audit *audit, struct pkgdb *db, int sock)
		fclose(out);
		return;
	}
-
	check = kh_init_pkgs();
+
	check = pkghash_new();

	while (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC|PKG_LOAD_RDEPS) == EPKG_OK) {
		if (pkg_type(pkg) == PKG_INSTALLED) {
@@ -113,7 +107,7 @@ check_vulnerable(struct pkg_audit *audit, struct pkgdb *db, int sock)

	if (check == NULL) {
		pkg_audit_free(audit);
-
		kh_destroy_pkgs(check);
+
		pkghash_destroy(check);
		fclose(out);
		return;
	}
@@ -123,7 +117,7 @@ check_vulnerable(struct pkg_audit *audit, struct pkgdb *db, int sock)
		warn("unable to open vulnxml file");
		fclose(out);
		pkg_audit_free(audit);
-
		kh_destroy_pkgs(check);
+
		pkghash_destroy(check);
		return;
	}

@@ -133,15 +127,17 @@ check_vulnerable(struct pkg_audit *audit, struct pkgdb *db, int sock)
	if (cap_enter() < 0 && errno != ENOSYS) {
		warn("cap_enter() failed");
		pkg_audit_free(audit);
-
		kh_destroy_pkgs(check);
+
		pkghash_destroy(check);
		fclose(out);
		return;
	}
#endif

	if (pkg_audit_process(audit) == EPKG_OK) {
-
		kh_foreach_value(check, pkg, {
+
		hit = pkghash_iterator(check);
+
		while (pkghash_next(&hit)) {
				issues = NULL;
+
				pkg = (struct pkg *)hit.value;
				if (pkg_audit_is_vulnerable(audit, pkg, &issues, true)) {
					pkg_get(pkg, PKG_UNIQUEID, &uid);
					fprintf(out, "%s\n", uid);
@@ -149,18 +145,16 @@ check_vulnerable(struct pkg_audit *audit, struct pkgdb *db, int sock)
				}
				pkg_audit_issues_free(issues);
				pkg_free(pkg);
-
		});
+
		}

-
		kh_destroy_pkgs(check);
		fprintf(out, "%s\n", vuln_end_lit);
		fflush(out);
-
	}
-
	else {
+
	} else {
		warnx("cannot process vulnxml");
-
		kh_destroy_pkgs(check);
	}

	pkg_audit_free(audit);
+
	pkghash_destroy(check);
	fclose(out);
}

modified src/version.c
@@ -47,7 +47,8 @@
#include <spawn.h>
#include <sys/types.h>
#include <sys/stat.h>
-
#include <khash.h>
+
#include <pkghash.h>
+
#include <xmalloc.h>

#include "pkgcli.h"

@@ -58,15 +59,12 @@ struct index_entry {
	char *version;
};

-
KHASH_MAP_INIT_STR(index, struct index_entry *);
-
KHASH_MAP_INIT_STR(ports, char *);
struct category {
	char *name;
-
	kh_ports_t *ports;
+
	pkghash *ports;
};
-
KHASH_MAP_INIT_STR(categories, struct category *);

-
kh_categories_t *categories = NULL;
+
pkghash *categories = NULL;

void
usage_version(void)
@@ -278,17 +276,15 @@ indexfilename(char *filebuf, size_t filebuflen)
	return (filebuf);
}

-
static kh_index_t *
+
static pkghash *
hash_indexfile(const char *indexfilename)
{
	FILE			*indexfile;
-
	kh_index_t		*index = NULL;
+
	pkghash			*index = NULL;
	struct index_entry	*entry;
	char			*version, *name;
	char			*line = NULL, *l;
	size_t			 linecap = 0;
-
	int			 ret;
-
	khint_t			 k;


	/* Create a hash table of all the package names and port
@@ -312,23 +308,15 @@ hash_indexfile(const char *indexfilename)
		version[0] = '\0';
		version++;

-
		entry = malloc(sizeof(struct index_entry));
-
		if (entry != NULL) {
-
			entry->name = strdup(name);
-
			entry->version = strdup(version);
-
		}
-

-
		if (entry == NULL || entry->version == NULL ||
-
		    entry->name == NULL)
-
			err(EXIT_FAILURE, "Out of memory while reading %s",
-
			    indexfilename);
+
		entry = xmalloc(sizeof(struct index_entry));
+
		entry->name = xstrdup(name);
+
		entry->version = xstrdup(version);

+
		pkghash_safe_add(index, entry->name, entry, NULL);
		if (index == NULL)
-
			index = kh_init_index();
-
		k = kh_put_index(index, entry->name, &ret);
-
		if (ret != 0) {
-
			kh_value(index, k) = entry;
-
		} else {
+
			index = pkghash_new();
+

+
		if (!pkghash_add(index, entry->name, entry, NULL)) {
			free(entry->version);
			free(entry->name);
			free(entry);
@@ -348,35 +336,33 @@ hash_indexfile(const char *indexfilename)
static void
free_categories(void)
{
-
	char *v;
	struct category *cat;
+
	pkghash_it it;

-
	if (categories == NULL)
-
		return;
-

-
	kh_foreach_value(categories, cat, {
+
	it = pkghash_iterator(categories);
+
	while (pkghash_next(&it)) {
+
		cat = (struct category *) it.value;
		free(cat->name);
-
		kh_foreach_value(cat->ports, v, free(v));
-
		kh_destroy_ports(cat->ports);
+
		pkghash_destroy(cat->ports);
		free(cat);
-
	});
-
	kh_destroy_categories(categories);
+
	}
+
	pkghash_destroy(categories);
}

static void
-
free_index(kh_index_t *index)
+
free_index(pkghash *index)
{
+
	pkghash_it it;
	struct index_entry *entry;

-
	if (index == NULL)
-
		return;
-

-
	kh_foreach_value(index, entry, {
+
	it = pkghash_iterator(index);
+
	while (pkghash_next(&it)) {
+
		entry = (struct index_entry *)it.value;
		free(entry->version);
		free(entry->name);
		free(entry);
-
	});
-
	kh_destroy_index(index);
+
	}
+
	pkghash_destroy(index);
}

static bool
@@ -408,13 +394,13 @@ static int
do_source_index(unsigned int opt, char limchar, char *pattern, match_t match,
    const char *matchorigin, const char *matchname, const char *indexfile)
{
-
	kh_index_t	*index;
+
	pkghash		*index;
+
	pkghash_entry	*e;
	struct pkgdb	*db = NULL;
	struct pkgdb_it	*it = NULL;
	struct pkg	*pkg = NULL;
	const char	*name;
	const char	*origin;
-
	khint_t		 k;

	if ( (opt & VERSION_SOURCES) != VERSION_SOURCE_INDEX) {
		usage_version();
@@ -451,9 +437,9 @@ do_source_index(unsigned int opt, char limchar, char *pattern, match_t match,
		    strcmp(name, matchname) != 0)
			continue;

-
		k = kh_get_index(index, name);
+
		e = pkghash_get(index, name);
		print_version(pkg, "index",
-
		    k != kh_end(index) ? (kh_value(index, k))->version : NULL, limchar, opt);
+
		    e != NULL ? ((struct index_entry *)e->value)->version : NULL, limchar, opt);
	}

cleanup:
@@ -616,8 +602,6 @@ category_new(char *categorypath, const char *category)
	xstring		*makecmd;
	char		*results, *d, *key;
	char		*argv[5];
-
	int		 ret;
-
	khint_t		 k;

	makecmd = xstring_new();

@@ -634,25 +618,14 @@ category_new(char *categorypath, const char *category)
	results = makecmd->buf;

	if (categories == NULL)
-
		categories = kh_init_categories();
+
		categories = pkghash_new();

-
	cat = calloc(1, sizeof(*cat));
-
	if (cat == NULL)
-
		goto cleanup;
+
	cat = xcalloc(1, sizeof(*cat));
+
	cat->name = xstrdup(category);

-
	cat->name = strdup(category);
-
	cat->ports = kh_init_ports();
-

-
	k = kh_put_categories(categories, cat->name, &ret);
-
	kh_value(categories, k) = cat;
-
	while ((d = strsep(&results, " \n")) != NULL) {
-
		key = strdup(d);
-
		k = kh_put_ports(cat->ports, key, &ret);
-
		if (k != kh_end(cat->ports))
-
			kh_value(cat->ports, k) = key;
-
		else
-
			free(key);
-
	}
+
	pkghash_add(categories, cat->name, cat, NULL);
+
	while ((d = strsep(&results, " \n")) != NULL)
+
		pkghash_safe_add(cat->ports, key, NULL, NULL);

cleanup:
	xstring_free(makecmd);
@@ -666,7 +639,7 @@ validate_origin(const char *portsdir, const char *origin)
	struct category	*cat;
	char		*category, *buf;
	char		 categorypath[MAXPATHLEN];
-
	khint_t		 k;
+
	pkghash_entry	*e;

	/* If the origin does not contain a / ignore it like for
	 * "base"
@@ -681,13 +654,11 @@ validate_origin(const char *portsdir, const char *origin)
	category = strrchr(categorypath, '/');
	category++;

-
	if (categories != NULL)
-
		k = kh_get_categories(categories, category);
-
	if (categories == NULL || k == kh_end(categories)) {
+
	e = pkghash_get(categories, category);
+
	if (e == NULL)
		cat = category_new(categorypath, category);
-
	} else {
-
		cat = kh_value(categories, k);
-
	}
+
	else
+
		cat = (struct category *)e->value;

	if (cat == NULL)
		return (false);
@@ -698,9 +669,7 @@ validate_origin(const char *portsdir, const char *origin)
	if (strcmp(origin, "base") == 0)
		return (false);

-
	k = kh_get_ports(cat->ports, buf);
-

-
	return (k != kh_end(cat->ports));
+
	return (pkghash_get(cat->ports, buf) != NULL);
}

static const char *