Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Convert *provides/*requires to khash
Baptiste Daroussin committed 10 years ago
commit f4dcde2c56063d523d466063cefa8f75a6fadb2b
parent d691576
16 files changed +205 -298
modified libpkg/pkg.c
@@ -558,19 +558,19 @@ pkg_options(const struct pkg *pkg, struct pkg_option **o)
}

int
-
pkg_shlibs_required(const struct pkg *pkg, struct pkg_shlib **s)
+
pkg_shlibs_required(const struct pkg *pkg, char **s)
{
	assert(pkg != NULL);

-
	HASH_NEXT(pkg->shlibs_required, (*s));
+
	kh_string_next(pkg->shlibs_required, (*s));
}

int
-
pkg_shlibs_provided(const struct pkg *pkg, struct pkg_shlib **s)
+
pkg_shlibs_provided(const struct pkg *pkg, char **s)
{
	assert(pkg != NULL);

-
	HASH_NEXT(pkg->shlibs_provided, (*s));
+
	kh_string_next(pkg->shlibs_provided, (*s));
}

int
@@ -582,19 +582,19 @@ pkg_conflicts(const struct pkg *pkg, struct pkg_conflict **c)
}

int
-
pkg_provides(const struct pkg *pkg, struct pkg_provide **c)
+
pkg_provides(const struct pkg *pkg, char **c)
{
	assert(pkg != NULL);

-
	HASH_NEXT(pkg->provides, (*c));
+
	kh_string_next(pkg->provides, (*c));
}

int
-
pkg_requires(const struct pkg *pkg, struct pkg_provide **c)
+
pkg_requires(const struct pkg *pkg, char **c)
{
	assert(pkg != NULL);

-
	HASH_NEXT(pkg->requires, (*c));
+
	kh_string_next(pkg->requires, (*c));
}

int
@@ -1152,22 +1152,17 @@ pkg_addoption_description(struct pkg *pkg, const char *key,
int
pkg_addshlib_required(struct pkg *pkg, const char *name)
{
-
	struct pkg_shlib *s = NULL, *f;
+
	char *storename;

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

-
	pkg_shlib_new(&s);
-
	s->name = strdup(name);
-

-
	HASH_FIND_STR(pkg->shlibs_required, s->name, f);
	/* silently ignore duplicates in case of shlibs */
-
	if (f != NULL) {
-
		pkg_shlib_free(s);
+
	if (kh_contains(strings, pkg->shlibs_required, name))
		return (EPKG_OK);
-
	}

-
	HASH_ADD_KEYPTR(hh, pkg->shlibs_required, s->name, strlen(s->name), s);
+
	storename = strdup(name);
+
	kh_add(strings, pkg->shlibs_required, storename, storename);

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

@@ -1177,7 +1172,7 @@ pkg_addshlib_required(struct pkg *pkg, const char *name)
int
pkg_addshlib_provided(struct pkg *pkg, const char *name)
{
-
	struct pkg_shlib *s = NULL, *f;
+
	char *storename;

	assert(pkg != NULL);
	assert(name != NULL && name[0] != '\0');
@@ -1186,16 +1181,12 @@ pkg_addshlib_provided(struct pkg *pkg, const char *name)
	if (strncmp(name, "lib", 3) != 0)
		return (EPKG_OK);

-
	pkg_shlib_new(&s);
-
	s->name = strdup(name);
-
	HASH_FIND_STR(pkg->shlibs_provided, s->name, f);
	/* silently ignore duplicates in case of shlibs */
-
	if (f != NULL) {
-
		pkg_shlib_free(s);
+
	if (kh_contains(strings, pkg->shlibs_provided, name))
		return (EPKG_OK);
-
	}

-
	HASH_ADD_KEYPTR(hh, pkg->shlibs_provided, s->name, strlen(s->name), s);
+
	storename = strdup(name);
+
	kh_add(strings, pkg->shlibs_provided, storename, storename);

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

@@ -1227,20 +1218,18 @@ pkg_addconflict(struct pkg *pkg, const char *uniqueid)
int
pkg_addrequire(struct pkg *pkg, const char *name)
{
-
	struct pkg_provide *p = NULL;
+
	char *storename;

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

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

-
	pkg_provide_new(&p);
-
	p->provide = strdup(name);
+
	storename = strdup(name);

-
	HASH_ADD_KEYPTR(hh, pkg->requires, p->provide, strlen(p->provide), p);
+
	kh_add(strings, pkg->requires, storename, storename);

	return (EPKG_OK);
}
@@ -1248,20 +1237,18 @@ pkg_addrequire(struct pkg *pkg, const char *name)
int
pkg_addprovide(struct pkg *pkg, const char *name)
{
-
	struct pkg_provide *p = NULL;
+
	char *storename;

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

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

-
	pkg_provide_new(&p);
-
	p->provide = strdup(name);
+
	storename = strdup(name);

-
	HASH_ADD_KEYPTR(hh, pkg->provides, p->provide, strlen(p->provide), p);
+
	kh_add(strings, pkg->provides, storename, storename);

	return (EPKG_OK);
}
@@ -1328,15 +1315,15 @@ pkg_list_count(const struct pkg *pkg, pkg_list list)
	case PKG_GROUPS:
		return (HASH_COUNT(pkg->groups));
	case PKG_SHLIBS_REQUIRED:
-
		return (HASH_COUNT(pkg->shlibs_required));
+
		return (kh_count(pkg->shlibs_required));
	case PKG_SHLIBS_PROVIDED:
-
		return (HASH_COUNT(pkg->shlibs_provided));
+
		return (kh_count(pkg->shlibs_provided));
	case PKG_CONFLICTS:
		return (HASH_COUNT(pkg->conflicts));
	case PKG_PROVIDES:
-
		return (HASH_COUNT(pkg->provides));
+
		return (kh_count(pkg->provides));
	case PKG_REQUIRES:
-
		return (HASH_COUNT(pkg->requires));
+
		return (kh_count(pkg->requires));
	case PKG_CONFIG_FILES:
		return (HASH_COUNT(pkg->config_files));
	}
@@ -1378,11 +1365,11 @@ pkg_list_free(struct pkg *pkg, pkg_list list) {
		pkg->flags &= ~PKG_LOAD_GROUPS;
		break;
	case PKG_SHLIBS_REQUIRED:
-
		HASH_FREE(pkg->shlibs_required, pkg_shlib_free);
+
		kh_free(strings, pkg->shlibs_required, char, free);
		pkg->flags &= ~PKG_LOAD_SHLIBS_REQUIRED;
		break;
	case PKG_SHLIBS_PROVIDED:
-
		HASH_FREE(pkg->shlibs_provided, pkg_shlib_free);
+
		kh_free(strings, pkg->shlibs_provided, char, free);
		pkg->flags &= ~PKG_LOAD_SHLIBS_PROVIDED;
		break;
	case PKG_CONFLICTS:
@@ -1390,11 +1377,11 @@ pkg_list_free(struct pkg *pkg, pkg_list list) {
		pkg->flags &= ~PKG_LOAD_CONFLICTS;
		break;
	case PKG_PROVIDES:
-
		HASH_FREE(pkg->provides, pkg_provide_free);
+
		kh_free(strings, pkg->provides, char, free);
		pkg->flags &= ~PKG_LOAD_PROVIDES;
		break;
	case PKG_REQUIRES:
-
		HASH_FREE(pkg->requires, pkg_provide_free);
+
		kh_free(strings, pkg->requires, char, free);
		pkg->flags &= ~PKG_LOAD_REQUIRES;
		break;
	}
modified libpkg/pkg.h.in
@@ -101,8 +101,6 @@ struct pkg_option;
struct pkg_license;
struct pkg_user;
struct pkg_group;
-
struct pkg_shlib;
-
struct pkg_provide;
struct pkg_config_file;

struct pkgdb;
@@ -638,16 +636,14 @@ int pkg_options(const struct pkg *, struct pkg_option **option);
 * @param shlib must be set to NULL for the first call.
 * @return An error code
 */
-
int pkg_shlibs_required(const struct pkg *pkg, struct pkg_shlib **shlib);
+
int pkg_shlibs_required(const struct pkg *pkg, char **shlib);

/**
 * Iterates over the shared libraries provided by the package.
 * @param shlib must be set to NULL for the first call.
 * @return An error code
 */
-
int pkg_shlibs_provided(const struct pkg *pkg, struct pkg_shlib **shlib);
-

-
const char *pkg_shlib_name(const struct pkg_shlib *shlib);
+
int pkg_shlibs_provided(const struct pkg *pkg, char **shlib);

/**
 * Iterates over the conflicts registered in the package.
@@ -661,10 +657,8 @@ int pkg_conflicts(const struct pkg *pkg, struct pkg_conflict **conflict);
 * @param provide must be set to NULL for the first call.
 * @return An error code
 */
-
int pkg_provides(const struct pkg *pkg, struct pkg_provide **provide);
-
int pkg_requires(const struct pkg *pkg, struct pkg_provide **require);
-

-
const char *pkg_provide_name(const struct pkg_provide *provide);
+
int pkg_provides(const struct pkg *pkg, char **provide);
+
int pkg_requires(const struct pkg *pkg, char **require);

/**
 * Iterates over the config files registered in the package.
modified libpkg/pkg_attributes.c
@@ -217,37 +217,6 @@ pkg_option_free(struct pkg_option *option)
}

/*
-
 * Shared Libraries
-
 */
-
int
-
pkg_shlib_new(struct pkg_shlib **sl)
-
{
-
	if ((*sl = calloc(1, sizeof(struct pkg_shlib))) == NULL)
-
		return (EPKG_FATAL);
-

-
	return (EPKG_OK);
-
}
-

-
void
-
pkg_shlib_free(struct pkg_shlib *sl)
-
{
-
	if (sl == NULL)
-
		return;
-

-
	free(sl->name);
-
	free(sl);
-
}
-

-
const char *
-
pkg_shlib_name(const struct pkg_shlib *sl)
-
{
-
	if (sl == NULL)
-
		return (NULL);
-

-
	return (sl->name);
-
}
-

-
/*
 * Conflicts
 */

@@ -272,28 +241,6 @@ pkg_conflict_free(struct pkg_conflict *c)
}

/*
-
 * Provides
-
 */
-
int
-
pkg_provide_new(struct pkg_provide **c)
-
{
-
	if ((*c = calloc(1, sizeof(struct pkg_provide))) == NULL)
-
		return (EPKG_FATAL);
-

-
	return (EPKG_OK);
-
}
-

-
void
-
pkg_provide_free(struct pkg_provide *c)
-
{
-
	if (c == NULL)
-
		return;
-

-
	free(c->provide);
-
	free(c);
-
}
-

-
/*
 * Config files
 */
int
@@ -366,15 +313,3 @@ pkg_kv_free(struct pkg_kv *c)
	free(c->value);
	free(c);
}
-

-
/*
-
 * provide
-
 */
-
const char *
-
pkg_provide_name(const struct pkg_provide *provide)
-
{
-
	if (provide == NULL)
-
		return (NULL);
-

-
	return (provide->provide);
-
}
modified libpkg/pkg_checksum.c
@@ -189,15 +189,13 @@ pkg_checksum_generate(struct pkg *pkg, char *dest, size_t destlen,
	pkg_checksum_type_t type)
{
	unsigned char *bdigest;
-
	char *olduid;
+
	char *olduid, *buf;
	size_t blen;
	struct pkg_checksum_entry *entries = NULL;
	struct pkg_option *option = NULL;
-
	struct pkg_shlib *shlib = NULL;
	struct pkg_user *user = NULL;
	struct pkg_group *group = NULL;
	struct pkg_dep *dep = NULL;
-
	struct pkg_provide *p = NULL;
	int i;

	if (pkg == NULL || type >= PKG_HASH_TYPE_UNKNOWN ||
@@ -213,13 +211,14 @@ pkg_checksum_generate(struct pkg *pkg, char *dest, size_t destlen,
		pkg_checksum_add_entry(option->key, option->value, &entries);
	}

-
	while (pkg_shlibs_required(pkg, &shlib) == EPKG_OK) {
-
		pkg_checksum_add_entry("required_shlib", shlib->name, &entries);
+
	buf = NULL;
+
	while (pkg_shlibs_required(pkg, &buf) == EPKG_OK) {
+
		pkg_checksum_add_entry("required_shlib", buf, &entries);
	}

-
	shlib = NULL;
-
	while (pkg_shlibs_provided(pkg, &shlib) == EPKG_OK) {
-
		pkg_checksum_add_entry("provided_shlib", shlib->name, &entries);
+
	buf = NULL;
+
	while (pkg_shlibs_provided(pkg, &buf) == EPKG_OK) {
+
		pkg_checksum_add_entry("provided_shlib", buf, &entries);
	}

	while (pkg_users(pkg, &user) == EPKG_OK) {
@@ -236,13 +235,14 @@ pkg_checksum_generate(struct pkg *pkg, char *dest, size_t destlen,
		free(olduid);
	}

-
	while (pkg_provides(pkg, &p) == EPKG_OK) {
-
		pkg_checksum_add_entry("provide", p->provide, &entries);
+
	buf = NULL;
+
	while (pkg_provides(pkg, &buf) == EPKG_OK) {
+
		pkg_checksum_add_entry("provide", buf, &entries);
	}

-
	p = NULL;
-
	while (pkg_requires(pkg, &p) == EPKG_OK) {
-
		pkg_checksum_add_entry("require", p->provide, &entries);
+
	buf = NULL;
+
	while (pkg_requires(pkg, &buf) == EPKG_OK) {
+
		pkg_checksum_add_entry("require", buf, &entries);
	}

	/* Sort before hashing */
modified libpkg/pkg_cudf.c
@@ -112,9 +112,9 @@ cudf_emit_pkg(struct pkg *pkg, int version, FILE *f,
		struct pkg_job_universe_item *conflicts_chain)
{
	struct pkg_dep *dep;
-
	struct pkg_provide *prov, *ptmp;
	struct pkg_conflict *conflict, *ctmp;
	struct pkg_job_universe_item *u;
+
	char *buf;
	int column = 0, ver;

	if (fprintf(f, "package: ") < 0)
@@ -138,15 +138,15 @@ cudf_emit_pkg(struct pkg *pkg, int version, FILE *f,
	}

	column = 0;
-
	if (HASH_COUNT(pkg->provides) > 0) {
+
	if (kh_count(pkg->provides) > 0) {
		if (fprintf(f, "provides: ") < 0)
			return (EPKG_FATAL);
-
		HASH_ITER(hh, pkg->provides, prov, ptmp) {
-
			if (cudf_print_element(f, prov->provide,
-
					(prov->hh.next != NULL), &column) < 0) {
+
		kh_each_value(pkg->provides, buf, {
+
			if (cudf_print_element(f, buf,
+
			    column + 1 == kh_count(pkg->provides), &column) < 0) {
				return (EPKG_FATAL);
			}
-
		}
+
		});
	}

	column = 0;
modified libpkg/pkg_elf.c
@@ -439,14 +439,17 @@ int
pkg_analyse_files(struct pkgdb *db, struct pkg *pkg, const char *stage)
{
	struct pkg_file *file = NULL;
-
	struct pkg_shlib *sh, *shtmp, *found;
+
	char *sh;
+
	khint_t k;
	int ret = EPKG_OK;
	char fpath[MAXPATHLEN];
	const char *lib;
	bool failures = false;

-
	pkg_list_free(pkg, PKG_SHLIBS_REQUIRED);
-
	pkg_list_free(pkg, PKG_SHLIBS_PROVIDED);
+
	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 (elf_version(EV_CURRENT) == EV_NONE)
		return (EPKG_FATAL);
@@ -482,34 +485,35 @@ pkg_analyse_files(struct pkgdb *db, struct pkg *pkg, const char *stage)
	/*
	 * Do not depend on libraries that a package provides itself
	 */
-
	HASH_ITER(hh, pkg->shlibs_required, sh, shtmp) {
-
		HASH_FIND_STR(pkg->shlibs_provided, sh->name, found);
-
		if (found != NULL) {
+
	kh_each_value(pkg->shlibs_required, sh, {
+
		if (kh_contains(strings, pkg->shlibs_provided, sh)) {
			pkg_debug(2, "remove %s from required shlibs as the "
			    "package %s provides this library itself",
-
			    sh->name, pkg->name);
-
			HASH_DEL(pkg->shlibs_required, sh);
+
			    sh, pkg->name);
+
			k = kh_get_strings(pkg->shlibs_required, sh);
+
			kh_del_strings(pkg->shlibs_required, k);
			continue;
		}
		file = NULL;
		while (pkg_files(pkg, &file) == EPKG_OK) {
-
			if ((lib = strstr(file->path, sh->name)) != NULL &&
-
			    strlen(lib) == strlen(sh->name) && lib[-1] == '/') {
+
			if ((lib = strstr(file->path, sh)) != NULL &&
+
			    strlen(lib) == strlen(sh) && lib[-1] == '/') {
				pkg_debug(2, "remove %s from required shlibs as "
				    "the package %s provides this library itself",
-
				    sh->name, pkg->name);
-
				HASH_DEL(pkg->shlibs_required, sh);
+
				    sh, pkg->name);
+
				k = kh_get_strings(pkg->shlibs_required, sh);
+
				kh_del_strings(pkg->shlibs_required, k);
				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)
-
		HASH_FREE(pkg->shlibs_provided, pkg_shlib_free);
+
		kh_free(strings, pkg->shlibs_provided, char, free);

	if (failures)
		goto cleanup;
modified libpkg/pkg_jobs.c
@@ -1042,9 +1042,8 @@ pkg_jobs_need_upgrade(struct pkg *rp, struct pkg *lp)
	int ret, ret1, ret2;
	struct pkg_option *lo = NULL, *ro = NULL;
	struct pkg_dep *ld = NULL, *rd = NULL;
-
	struct pkg_shlib *ls = NULL, *rs = NULL;
	struct pkg_conflict *lc = NULL, *rc = NULL;
-
	struct pkg_provide *lpr = NULL, *rpr = NULL;
+
	char *lb, *rb;

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

	/* Provides */
+
	lb = rb = NULL;
	for (;;) {
-
		ret1 = pkg_provides(rp, &rpr);
-
		ret2 = pkg_provides(lp, &lpr);
+
		ret1 = pkg_provides(rp, &rb);
+
		ret2 = pkg_provides(lp, &lb);
		if (ret1 != ret2) {
			free(rp->reason);
			rp->reason = strdup("provides changed");
			return (true);
		}
		if (ret1 == EPKG_OK) {
-
			if (strcmp(rpr->provide, lpr->provide) != 0) {
+
			if (strcmp(rb, lb) != 0) {
				free(rp->reason);
				rp->reason = strdup("provides changed");
				return (true);
@@ -1182,18 +1182,17 @@ pkg_jobs_need_upgrade(struct pkg *rp, struct pkg *lp)
			break;
	}
	/* Requires */
-
	rpr = NULL;
-
	lpr = NULL;
+
	lb = rb = NULL;
	for (;;) {
-
		ret1 = pkg_requires(rp, &rpr);
-
		ret1 = pkg_requires(lp, &lpr);
+
		ret1 = pkg_requires(rp, &rb);
+
		ret1 = pkg_requires(lp, &lb);
		if (ret1 != ret2) {
			free(rp->reason);
			rp->reason = strdup("requires changed");
			return (true);
		}
		if (ret1 == EPKG_OK) {
-
			if (strcmp(rpr->provide, lpr->provide) != 0) {
+
			if (strcmp(rb, lb) != 0) {
				free(rp->reason);
				rp->reason = strdup("requires changed");
				return (true);
@@ -1204,20 +1203,21 @@ pkg_jobs_need_upgrade(struct pkg *rp, struct pkg *lp)
	}

	/* Finish by the shlibs */
+
	lb = rb = NULL;
	for (;;) {
-
		ret1 = pkg_shlibs_provided(rp, &rs);
-
		ret2 = pkg_shlibs_provided(lp, &ls);
+
		ret1 = pkg_shlibs_provided(rp, &rb);
+
		ret2 = pkg_shlibs_provided(lp, &lb);
		if (ret1 != ret2) {
			free(rp->reason);
			rp->reason = strdup("provided shared library changed");
			return (true);
		}
		if (ret1 == EPKG_OK) {
-
			if (strcmp(rs->name, ls->name) != 0) {
+
			if (strcmp(rb, lb) != 0) {
				free(rp->reason);
				rp->reason = strdup("provided shared library changed");
				pkg_debug(1, "provided shlib changed %s -> %s",
-
				    ls->name, rs->name);
+
				    lb, rb);
				return (true);
			}
		}
@@ -1225,20 +1225,21 @@ pkg_jobs_need_upgrade(struct pkg *rp, struct pkg *lp)
			break;
	}

+
	lb = rb = NULL;
	for (;;) {
-
		ret1 = pkg_shlibs_required(rp, &rs);
-
		ret2 = pkg_shlibs_required(lp, &ls);
+
		ret1 = pkg_shlibs_required(rp, &rb);
+
		ret2 = pkg_shlibs_required(lp, &lb);
		if (ret1 != ret2) {
			free(rp->reason);
			rp->reason = strdup("needed shared library changed");
			return (true);
		}
		if (ret1 == EPKG_OK) {
-
			if (strcmp(rs->name, ls->name) != 0) {
+
			if (strcmp(rb, lb) != 0) {
				free(rp->reason);
				rp->reason = strdup("needed shared library changed");
				pkg_debug(1, "Required shlib changed %s -> %s",
-
				    ls->name, rs->name);
+
				    lb, rb);
				return (true);
			}
		}
modified libpkg/pkg_jobs_universe.c
@@ -402,40 +402,41 @@ static int
pkg_jobs_universe_process_shlibs(struct pkg_jobs_universe *universe,
	struct pkg *pkg)
{
-
	struct pkg_shlib *shlib = NULL;
	struct pkg_job_provide *pr;
	struct pkgdb_it *it;
+
	char *buf;
	int rc;

-
	while (pkg_shlibs_required(pkg, &shlib) == EPKG_OK) {
-
		HASH_FIND_STR(universe->provides, shlib->name, pr);
+
	while (pkg_shlibs_required(pkg, &buf) == EPKG_OK) {
+
		HASH_FIND_STR(universe->provides, buf, pr);
		if (pr != NULL)
			continue;

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

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

		if (it != NULL) {
-
			rc = pkg_jobs_universe_handle_provide(universe, it, shlib->name, true);
+
			rc = pkg_jobs_universe_handle_provide(universe, it, buf, true);
			pkgdb_it_free(it);

			if (rc != EPKG_OK) {
				pkg_debug(1, "cannot find remote packages that provide library %s "
						"required for %s",
-
				    shlib->name, pkg->name);
+
				    buf, pkg->name);
			}
		}
	}
@@ -447,41 +448,41 @@ static int
pkg_jobs_universe_process_provides_requires(struct pkg_jobs_universe *universe,
	struct pkg *pkg)
{
-
	struct pkg_provide *p = NULL;
	struct pkg_job_provide *pr;
	struct pkgdb_it *it;
+
	char *buf = NULL;
	int rc;

-
	while (pkg_requires(pkg, &p) == EPKG_OK) {
-
		HASH_FIND_STR(universe->provides, p->provide, pr);
+
	while (pkg_requires(pkg, &buf) == EPKG_OK) {
+
		HASH_FIND_STR(universe->provides, buf, pr);
		if (pr != NULL)
			continue;

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

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

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

		if (it != NULL) {
-
			rc = pkg_jobs_universe_handle_provide(universe, it, p->provide, false);
+
			rc = pkg_jobs_universe_handle_provide(universe, it, buf, false);
			pkgdb_it_free(it);

			if (rc != EPKG_OK) {
				pkg_debug(1, "cannot find remote packages that provide %s "
						"required for %s",
-
				    p->provide, pkg->name);
+
				    buf, pkg->name);
				return (rc);
			}
		}
modified libpkg/pkg_manifest.c
@@ -928,12 +928,10 @@ pkg_emit_object(struct pkg *pkg, short flags)
	struct pkg_dir		*dir      = NULL;
	struct pkg_user		*user     = NULL;
	struct pkg_group	*group    = NULL;
-
	struct pkg_shlib	*shlib    = NULL;
	struct pkg_conflict	*conflict = NULL;
-
	struct pkg_provide	*provide  = NULL;
-
	struct pkg_provide	*require  = NULL;
	struct pkg_config_file	*cf       = NULL;
	struct sbuf		*tmpsbuf  = NULL;
+
	char			*buf;
	int i;
	const char *script_types = NULL;
	char legacyarch[BUFSIZ];
@@ -1055,20 +1053,22 @@ pkg_emit_object(struct pkg *pkg, short flags)

	pkg_debug(4, "Emitting required");
	seq = NULL;
-
	while (pkg_shlibs_required(pkg, &shlib) == EPKG_OK) {
+
	buf = NULL;
+
	while (pkg_shlibs_required(pkg, &buf) == EPKG_OK) {
		if (seq == NULL)
			seq = ucl_object_typed_new(UCL_ARRAY);
-
		ucl_array_append(seq, ucl_object_fromstring(shlib->name));
+
		ucl_array_append(seq, ucl_object_fromstring(buf));
	}
	if (seq)
		ucl_object_insert_key(top, seq, "shlibs_required", 15, false);

	pkg_debug(4, "Emitting shlibs_provided");
	seq = NULL;
-
	while (pkg_shlibs_provided(pkg, &shlib) == EPKG_OK) {
+
	buf = NULL;
+
	while (pkg_shlibs_provided(pkg, &buf) == EPKG_OK) {
		if (seq == NULL)
			seq = ucl_object_typed_new(UCL_ARRAY);
-
		ucl_array_append(seq, ucl_object_fromstring(shlib->name));
+
		ucl_array_append(seq, ucl_object_fromstring(buf));
	}
	if (seq)
		ucl_object_insert_key(top, seq, "shlibs_provided", 15, false);
@@ -1085,20 +1085,22 @@ pkg_emit_object(struct pkg *pkg, short flags)

	pkg_debug(4, "Emitting provides");
	seq = NULL;
-
	while (pkg_provides(pkg, &provide) == EPKG_OK) {
+
	buf = NULL;
+
	while (pkg_provides(pkg, &buf) == EPKG_OK) {
		if (seq == NULL)
			seq = ucl_object_typed_new(UCL_ARRAY);
-
		ucl_array_append(seq, ucl_object_fromstring(provide->provide));
+
		ucl_array_append(seq, ucl_object_fromstring(buf));
	}
	if (seq)
		ucl_object_insert_key(top, seq, "provides", 8, false);

	pkg_debug(4, "Emitting requires");
	seq = NULL;
-
	while (pkg_requires(pkg, &require) == EPKG_OK) {
+
	buf = NULL;
+
	while (pkg_requires(pkg, &buf) == EPKG_OK) {
		if (seq == NULL)
			seq = ucl_object_typed_new(UCL_ARRAY);
-
		ucl_array_append(seq, ucl_object_fromstring(require->provide));
+
		ucl_array_append(seq, ucl_object_fromstring(buf));
	}
	if (seq)
		ucl_object_insert_key(top, seq, "requires", 8, false);
modified libpkg/pkg_printf.c
@@ -912,19 +912,19 @@ format_shlibs_required(struct sbuf *sbuf, const void *data, struct percent_esc *
	if (p->flags & (PP_ALTERNATE_FORM1|PP_ALTERNATE_FORM2))
		return (list_count(sbuf, pkg_list_count(pkg, PKG_SHLIBS_REQUIRED), p));
	else {
-
		struct pkg_shlib	*shlib = NULL;
+
		char	*buf = NULL;
		int			 count;

		set_list_defaults(p, "%Bn\n", "");

		count = 1;
-
		while (pkg_shlibs_required(pkg, &shlib) == EPKG_OK) {
+
		while (pkg_shlibs_required(pkg, &buf) == EPKG_OK) {
			if (count > 1)
				iterate_item(sbuf, pkg, sbuf_data(p->sep_fmt),
-
					     shlib, count, PP_B);
+
					     buf, count, PP_B);

			iterate_item(sbuf, pkg, sbuf_data(p->item_fmt),
-
				     shlib, count, PP_B);
+
				     buf, count, PP_B);
			count++;
		}
	}
@@ -938,9 +938,9 @@ format_shlibs_required(struct sbuf *sbuf, const void *data, struct percent_esc *
struct sbuf *
format_shlib_name(struct sbuf *sbuf, const void *data, struct percent_esc *p)
{
-
	const struct pkg_shlib	*shlib = data;
+
	const char	*shlib = data;

-
	return (string_val(sbuf, shlib->name, p));
+
	return (string_val(sbuf, shlib, p));
}

/*
@@ -1470,8 +1470,8 @@ format_required(struct sbuf *sbuf, const void *data, struct percent_esc *p)
	if (p->flags & (PP_ALTERNATE_FORM1|PP_ALTERNATE_FORM2))
		return (list_count(sbuf, pkg_list_count(pkg, PKG_REQUIRES), p));
	else {
-
		struct pkg_provide	*provide = NULL;
-
		int			 count;
+
		char	*provide = NULL;
+
		int	 count;

		set_list_defaults(p, "%Yn\n", "");

@@ -1495,9 +1495,9 @@ format_required(struct sbuf *sbuf, const void *data, struct percent_esc *p)
struct sbuf *
format_provide_name(struct sbuf *sbuf, const void *data, struct percent_esc *p)
{
-
	const struct pkg_provide	*provide = data;
+
	const char	*provide = data;

-
	return (string_val(sbuf, provide->provide, p));
+
	return (string_val(sbuf, provide, p));
}
/*
 * %a -- Autoremove flag. boolean.  Accepts field-width, left-align.
@@ -1526,8 +1526,8 @@ format_shlibs_provided(struct sbuf *sbuf, const void *data, struct percent_esc *
	if (p->flags & (PP_ALTERNATE_FORM1|PP_ALTERNATE_FORM2))
		return (list_count(sbuf, pkg_list_count(pkg, PKG_SHLIBS_PROVIDED), p));
	else {
-
		struct pkg_shlib	*shlib = NULL;
-
		int			 count;
+
		char	*shlib = NULL;
+
		int	 count;

		set_list_defaults(p, "%bn\n", "");

@@ -1861,8 +1861,8 @@ format_provided(struct sbuf *sbuf, const void *data, struct percent_esc *p)
	if (p->flags & (PP_ALTERNATE_FORM1|PP_ALTERNATE_FORM2))
		return (list_count(sbuf, pkg_list_count(pkg, PKG_PROVIDES), p));
	else {
-
		struct pkg_provide	*provide = NULL;
-
		int			 count;
+
		char	*provide = NULL;
+
		int	 count;

		set_list_defaults(p, "%yn\n", "");

modified libpkg/pkg_solve.c
@@ -302,9 +302,8 @@ pkg_solve_handle_provide (struct pkg_solve_problem *problem,
	struct pkg_solve_item *it = NULL;
	struct pkg_solve_variable *var, *curvar;
	struct pkg_job_universe_item *un;
-
	struct pkg_shlib *shlp;
-
	struct pkg_provide *np;
	struct pkg *pkg;
+
	bool libfound, providefound;

	/* Find the first package in the universe list */
	un = pr->un;
@@ -320,14 +319,12 @@ pkg_solve_handle_provide (struct pkg_solve_problem *problem,
		 * For each provide we need to check whether this package
		 * actually provides this require
		 */
-
		shlp = NULL;
-
		np = NULL;
		pkg = curvar->unit->pkg;

		if (pr->is_shlib) {
-
			HASH_FIND_STR(pkg->shlibs_provided, pr->provide, shlp);
+
			libfound = kh_contains(strings, pkg->shlibs_provided, pr->provide);
			/* Skip incompatible ABI as well */
-
			if (shlp != NULL && strcmp(pkg->arch, orig->arch) != 0) {
+
			if (libfound && strcmp(pkg->arch, orig->arch) != 0) {
				pkg_debug(2, "require %s: package %s-%s(%c) provides wrong ABI %s, "
					"wanted %s", pr->provide, pkg->name, pkg->version,
					pkg->type == PKG_INSTALLED ? 'l' : 'r', orig->arch, pkg->arch);
@@ -335,10 +332,10 @@ pkg_solve_handle_provide (struct pkg_solve_problem *problem,
			}
		}
		else {
-
			HASH_FIND_STR(pkg->provides, pr->provide, np);
+
			providefound = kh_contains(strings, pkg->provides, pr->provide);
		}

-
		if (np == NULL && shlp == NULL) {
+
		if (!providefound && !libfound) {
			pkg_debug(4, "%s provide is not satisfied by %s-%s(%c)", pr->provide,
					pkg->name, pkg->version, pkg->type == PKG_INSTALLED ?
							'l' : 'r');
@@ -719,10 +716,9 @@ pkg_solve_process_universe_variable(struct pkg_solve_problem *problem,
	struct pkg_conflict *conflict, *ctmp;
	struct pkg *pkg;
	struct pkg_solve_variable *cur_var;
-
	struct pkg_shlib *shlib = NULL;
-
	struct pkg_provide *p = NULL;
	struct pkg_jobs *j = problem->j;
	struct pkg_job_request *jreq;
+
	char *buf;
	bool chain_added = false;

	LL_FOREACH(var, cur_var) {
@@ -742,16 +738,16 @@ pkg_solve_process_universe_variable(struct pkg_solve_problem *problem,
		}

		/* Shlibs */
-
		shlib = NULL;
-
		while (pkg_shlibs_required(pkg, &shlib) == EPKG_OK) {
+
		buf = NULL;
+
		while (pkg_shlibs_required(pkg, &buf) == EPKG_OK) {
			if (pkg_solve_add_require_rule(problem, cur_var,
-
					shlib->name) != EPKG_OK)
+
					buf) != EPKG_OK)
				continue;
		}
-
		p = NULL;
-
		while (pkg_requires(pkg, &p) == EPKG_OK) {
+
		buf = NULL;
+
		while (pkg_requires(pkg, &buf) == EPKG_OK) {
			if (pkg_solve_add_require_rule(problem, cur_var,
-
					p->provide) != EPKG_OK)
+
					buf) != EPKG_OK)
				continue;
		}

modified libpkg/pkgdb.c
@@ -1984,13 +1984,13 @@ pkgdb_insert_scripts(struct pkg *pkg, int64_t package_id, sqlite3 *s)
int
pkgdb_update_shlibs_required(struct pkg *pkg, int64_t package_id, sqlite3 *s)
{
-
	struct pkg_shlib	*shlib = NULL;
+
	char	*shlib = NULL;

	while (pkg_shlibs_required(pkg, &shlib) == EPKG_OK) {
-
		if (run_prstmt(SHLIBS1, shlib->name)
+
		if (run_prstmt(SHLIBS1, shlib)
		    != SQLITE_DONE
		    ||
-
		    run_prstmt(SHLIBS_REQD, package_id, shlib->name)
+
		    run_prstmt(SHLIBS_REQD, package_id, shlib)
		    != SQLITE_DONE) {
			ERROR_SQLITE(s, SQL(SHLIBS_REQD));
			return (EPKG_FATAL);
@@ -2019,13 +2019,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)
{
-
	struct pkg_shlib	*shlib = NULL;
+
	char	*shlib = NULL;

	while (pkg_shlibs_provided(pkg, &shlib) == EPKG_OK) {
-
		if (run_prstmt(SHLIBS1, shlib->name)
+
		if (run_prstmt(SHLIBS1, shlib)
		    != SQLITE_DONE
		    ||
-
		    run_prstmt(SHLIBS_PROV, package_id, shlib->name)
+
		    run_prstmt(SHLIBS_PROV, package_id, shlib)
		    != SQLITE_DONE) {
			ERROR_SQLITE(s, SQL(SHLIBS_PROV));
			return (EPKG_FATAL);
@@ -2038,13 +2038,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)
{
-
	struct pkg_provide	*provide = NULL;
+
	char	*require = NULL;

-
	while (pkg_requires(pkg, &provide) == EPKG_OK) {
-
		if (run_prstmt(REQUIRE, provide->provide)
+
	while (pkg_requires(pkg, &require) == EPKG_OK) {
+
		if (run_prstmt(REQUIRE, require)
		    != SQLITE_DONE
		    ||
-
		    run_prstmt(PKG_REQUIRE, package_id, provide->provide)
+
		    run_prstmt(PKG_REQUIRE, package_id, require)
		    != SQLITE_DONE) {
			ERROR_SQLITE(s, SQL(PKG_REQUIRE));
			return (EPKG_FATAL);
@@ -2057,13 +2057,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)
{
-
	struct pkg_provide	*provide = NULL;
+
	char	*provide = NULL;

	while (pkg_provides(pkg, &provide) == EPKG_OK) {
-
		if (run_prstmt(PROVIDE, provide->provide)
+
		if (run_prstmt(PROVIDE, provide)
		    != SQLITE_DONE
		    ||
-
		    run_prstmt(PKG_PROVIDE, package_id, provide->provide)
+
		    run_prstmt(PKG_PROVIDE, package_id, provide)
		    != SQLITE_DONE) {
			ERROR_SQLITE(s, SQL(PKG_PROVIDE));
			return (EPKG_FATAL);
modified libpkg/private/pkg.h
@@ -199,6 +199,7 @@ struct pkg_repo;

KHASH_MAP_INIT_STR(pkg_deps, struct pkg_dep *);
KHASH_MAP_INIT_STR(pkg_files, struct pkg_file *);
+
KHASH_MAP_INIT_STR(strings, char *);

struct pkg {
	bool		 direct;
@@ -241,11 +242,11 @@ struct pkg {
	struct pkg_option	*options;
	struct pkg_user		*users;
	struct pkg_group	*groups;
-
	struct pkg_shlib	*shlibs_required;
-
	struct pkg_shlib	*shlibs_provided;
+
	kh_strings_t		*shlibs_required;
+
	kh_strings_t		*shlibs_provided;
	struct pkg_conflict *conflicts;
-
	struct pkg_provide	*provides;
-
	struct pkg_provide	*requires;
+
	kh_strings_t		*provides;
+
	kh_strings_t		*requires;
	struct pkg_config_file	*config_files;
	struct pkg_kv		*annotations;
	unsigned			flags;
@@ -282,11 +283,6 @@ struct pkg_conflict {
	UT_hash_handle	hh;
};

-
struct pkg_provide {
-
	char	*provide;
-
	UT_hash_handle	hh;
-
};
-

struct pkg_file {
	char		 path[MAXPATHLEN];
	int64_t		 size;
@@ -326,11 +322,6 @@ struct pkg_group {
	UT_hash_handle	hh;
};

-
struct pkg_shlib {
-
	char *name;
-
	UT_hash_handle	hh;
-
};
-

struct http_mirror {
	struct url *url;
	struct http_mirror *next;
@@ -629,15 +620,9 @@ void pkg_group_free(struct pkg_group *);

int pkg_jobs_resolv(struct pkg_jobs *jobs);

-
int pkg_shlib_new(struct pkg_shlib **);
-
void pkg_shlib_free(struct pkg_shlib *);
-

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

-
int pkg_provide_new(struct pkg_provide **);
-
void pkg_provide_free(struct pkg_provide *);
-

int pkg_config_file_new(struct pkg_config_file **);
void pkg_config_file_free(struct pkg_config_file *);

modified libpkg/repo/binary/update.c
@@ -138,8 +138,7 @@ pkg_repo_binary_add_pkg(struct pkg *pkg, const char *pkg_path,
	int			 ret;
	struct pkg_dep		*dep      = NULL;
	struct pkg_option	*option   = NULL;
-
	struct pkg_shlib	*shlib    = NULL;
-
	struct pkg_provide	*provide  = NULL;
+
	char			*buf;
	struct pkg_strel	*el;
	struct pkg_kv		*kv;
	const char		*arch;
@@ -224,48 +223,48 @@ try_again:
		}
	}

-
	shlib = NULL;
-
	while (pkg_shlibs_required(pkg, &shlib) == EPKG_OK) {
-
		ret = pkg_repo_binary_run_prstatement(SHLIB1, shlib->name);
+
	buf = NULL;
+
	while (pkg_shlibs_required(pkg, &buf) == EPKG_OK) {
+
		ret = pkg_repo_binary_run_prstatement(SHLIB1, buf);
		if (ret == SQLITE_DONE)
			ret = pkg_repo_binary_run_prstatement(SHLIB_REQD, package_id,
-
					shlib->name);
+
			    buf);
		if (ret != SQLITE_DONE) {
			ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(SHLIB_REQD));
			return (EPKG_FATAL);
		}
	}

-
	shlib = NULL;
-
	while (pkg_shlibs_provided(pkg, &shlib) == EPKG_OK) {
-
		ret = pkg_repo_binary_run_prstatement(SHLIB1, shlib->name);
+
	buf = NULL;
+
	while (pkg_shlibs_provided(pkg, &buf) == EPKG_OK) {
+
		ret = pkg_repo_binary_run_prstatement(SHLIB1, buf);
		if (ret == SQLITE_DONE)
			ret = pkg_repo_binary_run_prstatement(SHLIB_PROV, package_id,
-
					shlib->name);
+
			    buf);
		if (ret != SQLITE_DONE) {
			ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(SHLIB_PROV));
			return (EPKG_FATAL);
		}
	}

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

-
	provide = NULL;
-
	while (pkg_requires(pkg, &provide) == EPKG_OK) {
-
		ret = pkg_repo_binary_run_prstatement(REQUIRE, provide->provide);
+
	buf = NULL;
+
	while (pkg_requires(pkg, &buf) == EPKG_OK) {
+
		ret = pkg_repo_binary_run_prstatement(REQUIRE, buf);
		if (ret == SQLITE_DONE)
			ret = pkg_repo_binary_run_prstatement(REQUIRES, package_id,
-
			    provide->provide);
+
			    buf);
		if (ret != SQLITE_DONE) {
			ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(REQUIRES));
			return (EPKG_FATAL);
modified src/check.c
@@ -63,9 +63,8 @@ static int
check_deps(struct pkgdb *db, struct pkg *p, struct deps_head *dh, bool noinstall, struct sbuf *out)
{
	struct pkg_dep *dep = NULL;
-
	struct pkg_shlib *shlib = NULL;
	struct pkgdb_it *it;
-
	struct pkg_provide *provide = NULL;
+
	char *buf = NULL;
	int nbpkgs = 0;

	assert(db != NULL);
@@ -85,33 +84,35 @@ check_deps(struct pkgdb *db, struct pkg *p, struct deps_head *dh, bool noinstall
	}

	/* checking libraries required */
-
	while (pkg_shlibs_required(p, &shlib) == EPKG_OK) {
-
		it = pkgdb_query_shlib_provide(db, pkg_shlib_name(shlib));
+
	buf = NULL;
+
	while (pkg_shlibs_required(p, & buf) == EPKG_OK) {
+
		it = pkgdb_query_shlib_provide(db, buf);
		if (it != NULL && pkgdb_it_count(it) > 0) {
			pkgdb_it_free(it);
			continue;
		}
		pkgdb_it_free(it);
		if (quiet)
-
			pkg_sbuf_printf(out, "%n\t%Bn\n", p, shlib);
+
			pkg_sbuf_printf(out, "%n\t%S\n", p, buf);
		else
-
			pkg_sbuf_printf(out, "%n has require a missing libraries: %Bn\n",
-
			    p, shlib);
+
			pkg_sbuf_printf(out, "%n has require a missing libraries: %S\n",
+
			    p, buf);
	}

	/* checking requires */
-
	while (pkg_requires(p, &provide) == EPKG_OK) {
-
		it = pkgdb_query_provide(db, pkg_provide_name(provide));
+
	buf = NULL;
+
	while (pkg_requires(p, &buf) == EPKG_OK) {
+
		it = pkgdb_query_provide(db, buf);
		if (it != NULL && pkgdb_it_count(it) > 0) {
			pkgdb_it_free(it);
			continue;
		}
		pkgdb_it_free(it);
		if (quiet)
-
			pkg_sbuf_printf(out, "%n\tYn\n", p, provide);
+
			pkg_sbuf_printf(out, "%n\tS\n", p, buf);
		else
-
			pkg_sbuf_printf(out, "%n has a missing requirement: %Yn\n",
-
			    p, provide);
+
			pkg_sbuf_printf(out, "%n has a missing requirement: %S\n",
+
			    p, buf);
	}

	return (nbpkgs);
modified src/query.c
@@ -336,7 +336,7 @@ print_query(struct pkg *pkg, char *qstr, char multiline)
	struct pkg_dir		*dir    = NULL;
	struct pkg_user		*user   = NULL;
	struct pkg_group	*group  = NULL;
-
	struct pkg_shlib	*shlib  = NULL;
+
	char			*buf;
	struct pkg_kv		*kv;
	struct pkg_strel	*list;

@@ -400,14 +400,16 @@ print_query(struct pkg *pkg, char *qstr, char multiline)
		}
		break;
	case 'B':
-
		while (pkg_shlibs_required(pkg, &shlib) == EPKG_OK) {
-
			format_str(pkg, output, qstr, shlib);
+
		buf = NULL;
+
		while (pkg_shlibs_required(pkg, &buf) == EPKG_OK) {
+
			format_str(pkg, output, qstr, buf);
			printf("%s\n", sbuf_data(output));
		}
		break;
	case 'b':
-
		while (pkg_shlibs_provided(pkg, &shlib) == EPKG_OK) {
-
			format_str(pkg, output, qstr, shlib);
+
		buf = NULL;
+
		while (pkg_shlibs_provided(pkg, &buf) == EPKG_OK) {
+
			format_str(pkg, output, qstr, buf);
			printf("%s\n", sbuf_data(output));
		}
		break;