Exemplo n.º 1
0
ATF_TC_BODY(pkgdb_get_pkg_revdeps_test, tc)
{
	struct xbps_handle xh;
	xbps_array_t res;
	xbps_string_t pstr;
	const char *tcsdir, *str;
	const char *eout = "four-0.1_1\ntwo-0.1_1\n";
	unsigned int i;

	/* get test source dir */
	tcsdir = atf_tc_get_config_var(tc, "srcdir");

	memset(&xh, 0, sizeof(xh));
	strncpy(xh.rootdir, tcsdir, sizeof(xh.rootdir));
	strncpy(xh.metadir, tcsdir, sizeof(xh.metadir));
	xh.flags = XBPS_FLAG_DEBUG;
	ATF_REQUIRE_EQ(xbps_init(&xh), 0);

	res = xbps_pkgdb_get_pkg_revdeps(&xh, "mixed");
	ATF_REQUIRE_EQ(xbps_object_type(res), XBPS_TYPE_ARRAY);

	pstr = xbps_string_create();
	for (i = 0; i < xbps_array_count(res); i++) {
		xbps_array_get_cstring_nocopy(res, i, &str);
		xbps_string_append_cstring(pstr, str);
		xbps_string_append_cstring(pstr, "\n");
	}
	ATF_REQUIRE_STREQ(xbps_string_cstring_nocopy(pstr), eout);
}
Exemplo n.º 2
0
static void
generate_full_revdeps_tree(struct xbps_handle *xhp)
{
	xbps_object_t obj;
	xbps_object_iterator_t iter;

	if (xhp->pkgdb_revdeps)
		return;

	xhp->pkgdb_revdeps = xbps_dictionary_create();
	assert(xhp->pkgdb_revdeps);

	iter = xbps_dictionary_iterator(xhp->pkgdb);
	assert(iter);

	while ((obj = xbps_object_iterator_next(iter))) {
		xbps_array_t rundeps;
		xbps_dictionary_t pkgd;
		const char *pkgver;

		pkgd = xbps_dictionary_get_keysym(xhp->pkgdb, obj);
		rundeps = xbps_dictionary_get(pkgd, "run_depends");
		if (!xbps_array_count(rundeps))
			continue;

		xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver);
		for (unsigned int i = 0; i < xbps_array_count(rundeps); i++) {
			xbps_array_t pkg;
			const char *pkgdep, *vpkgname;
			char *curpkgname;
			bool alloc = false;

			xbps_array_get_cstring_nocopy(rundeps, i, &pkgdep);
			curpkgname = xbps_pkgpattern_name(pkgdep);
			if (curpkgname == NULL)
				curpkgname = xbps_pkg_name(pkgdep);
			assert(curpkgname);
			vpkgname = vpkg_user_conf(xhp, curpkgname);
			if (vpkgname == NULL)
				vpkgname = curpkgname;

			pkg = xbps_dictionary_get(xhp->pkgdb_revdeps, vpkgname);
			if (pkg == NULL) {
				alloc = true;
				pkg = xbps_array_create();
			}
			if (!xbps_match_string_in_array(pkg, pkgver)) {
				xbps_array_add_cstring_nocopy(pkg, pkgver);
				xbps_dictionary_set(xhp->pkgdb_revdeps, vpkgname, pkg);
			}
			free(curpkgname);
			if (alloc)
				xbps_object_release(pkg);
		}
	}
	xbps_object_iterator_release(iter);
}
Exemplo n.º 3
0
static void
print_array(xbps_array_t a)
{
	const char *str;

	for (unsigned int i = 0; i < xbps_array_count(a); i++) {
		xbps_array_get_cstring_nocopy(a, i, &str);
		fprintf(stderr, "%s\n", str);
	}
}
Exemplo n.º 4
0
static void
show_conflicts(xbps_array_t a)
{
	unsigned int i;
	const char *str;

	for (i = 0; i < xbps_array_count(a); i++) {
		xbps_array_get_cstring_nocopy(a, i, &str);
		fprintf(stderr, "%s\n", str);
	}
}
Exemplo n.º 5
0
Arquivo: search.c Projeto: Gottox/xbps
static void
print_results(struct xbps_handle *xhp, struct search_data *sd)
{
	const char *pkgver, *desc, *inststr;
	char tmp[256], *out;
	unsigned int j, tlen = 0, len = 0;

	/* Iterate over results array and find out largest pkgver string */
	for (unsigned int i = 0; i < xbps_array_count(sd->results); i+=2) {
		xbps_array_get_cstring_nocopy(sd->results, i, &pkgver);
		len = strlen(pkgver);
		if (tlen == 0 || len > tlen)
			tlen = len;
	}
	for (unsigned int i = 0; i < xbps_array_count(sd->results); i+=2) {
		xbps_array_get_cstring_nocopy(sd->results, i, &pkgver);
		xbps_array_get_cstring_nocopy(sd->results, i+1, &desc);
		xbps_strlcpy(tmp, pkgver, sizeof(tmp));
		for (j = strlen(tmp); j < tlen; j++)
			tmp[j] = ' ';

		tmp[j] = '\0';
		if (xbps_pkgdb_get_pkg(xhp, pkgver))
			inststr = "[*]";
		else
			inststr = "[-]";

		len = strlen(inststr) + strlen(tmp) + strlen(desc) + 3;
		if (sd->maxcols && (int)len > sd->maxcols) {
			out = malloc(sd->maxcols+1);
			assert(out);
			snprintf(out, sd->maxcols-3, "%s %s %s",
			    inststr, tmp, desc);
			xbps_strlcat(out, "...\n", sd->maxcols+1);
			printf("%s", out);
			free(out);
		} else {
			printf("%s %s %s\n", inststr, tmp, desc);
		}
	}
}
Exemplo n.º 6
0
static int
pkgdb_map_vpkgs(struct xbps_handle *xhp)
{
	xbps_object_iterator_t iter;
	xbps_object_t obj;
	int rv = 0;

	if (!xbps_dictionary_count(xhp->pkgdb))
		return 0;

	if (xhp->vpkgd == NULL) {
		xhp->vpkgd = xbps_dictionary_create();
		assert(xhp->vpkgd);
	}
	/*
	 * This maps all pkgs that have virtualpkgs in pkgdb.
	 */
	iter = xbps_dictionary_iterator(xhp->pkgdb);
	assert(iter);

	while ((obj = xbps_object_iterator_next(iter))) {
		xbps_array_t provides;
		xbps_dictionary_t pkgd;
		const char *pkgver;
		char *pkgname;

		pkgd = xbps_dictionary_get_keysym(xhp->pkgdb, obj);
		provides = xbps_dictionary_get(pkgd, "provides");
		if (provides == NULL)
			continue;

		xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver);
		pkgname = xbps_pkg_name(pkgver);
		assert(pkgname);

		for (unsigned int i = 0; i < xbps_array_count(provides); i++) {
			const char *vpkg;

			xbps_array_get_cstring_nocopy(provides, i, &vpkg);
			if (!xbps_dictionary_set_cstring(xhp->vpkgd, vpkg, pkgname)) {
				xbps_dbg_printf(xhp, "%s: set_cstring vpkg "
				    "%s pkgname %s\n", __func__, vpkg, pkgname);
				rv = EINVAL;
			} else {
				xbps_dbg_printf(xhp, "[pkgdb] added vpkg %s for %s\n",
				    vpkg, pkgname);
			}
		}
		free(pkgname);
	}
	xbps_object_iterator_release(iter);
	return rv;
}
Exemplo n.º 7
0
/*
 * Verify reverse dependencies for packages in transaction.
 * This will catch cases where a package update would break its reverse dependencies:
 *
 * 	- foo-1.0 is being updated to 2.0.
 * 	- baz-1.1 depends on foo<2.0.
 * 	- foo is updated to 2.0, hence baz-1.1 is currently broken.
 *
 * Abort transaction if such case is found.
 */
static bool
check_virtual_pkgs(xbps_array_t mdeps,
		   xbps_dictionary_t trans_pkgd,
		   xbps_dictionary_t rev_pkgd)
{
	xbps_array_t provides;
	bool matched = false;

	provides = xbps_dictionary_get(trans_pkgd, "provides");
	for (unsigned int i = 0; i < xbps_array_count(provides); i++) {
		xbps_array_t rundeps;
		const char *pkgver, *revpkgver, *pkgpattern;
		char *pkgname, *vpkgname, *vpkgver, *str;

		pkgver = revpkgver = pkgpattern = NULL;
		pkgname = vpkgname = vpkgver = str = NULL;

		xbps_dictionary_get_cstring_nocopy(trans_pkgd, "pkgver", &pkgver);
		xbps_dictionary_get_cstring_nocopy(rev_pkgd, "pkgver", &revpkgver);
		xbps_array_get_cstring(provides, i, &vpkgver);
		vpkgname = xbps_pkg_name(vpkgver);
		assert(vpkgname);
		rundeps = xbps_dictionary_get(rev_pkgd, "run_depends");
		for (unsigned int x = 0; x < xbps_array_count(rundeps); x++) {
			xbps_array_get_cstring_nocopy(rundeps, x, &pkgpattern);
			if (((pkgname = xbps_pkgpattern_name(pkgpattern)) == NULL) &&
			    ((pkgname = xbps_pkg_name(pkgpattern)) == NULL))
				continue;

			if (strcmp(vpkgname, pkgname)) {
				free(pkgname);
				continue;
			}
			free(pkgname);
			if (!strcmp(vpkgver, pkgpattern) ||
			    xbps_pkgpattern_match(vpkgver, pkgpattern)) {
				continue;
			}

			str = xbps_xasprintf("%s broken, needs '%s' virtual pkg (got `%s')",
			    revpkgver, pkgpattern, vpkgver);
			xbps_array_add_cstring(mdeps, str);
			free(str);
			matched = true;
		}
		free(vpkgname);
		free(vpkgver);
	}
	return matched;
}
Exemplo n.º 8
0
int
show_pkg_revdeps(struct xbps_handle *xhp, const char *pkg)
{
	xbps_array_t reqby;
	const char *pkgdep;
	unsigned int i;

	if ((reqby = xbps_pkgdb_get_pkg_revdeps(xhp, pkg)) != NULL) {
		for (i = 0; i < xbps_array_count(reqby); i++) {
			xbps_array_get_cstring_nocopy(reqby, i, &pkgdep);
			printf("%s\n", pkgdep);
		}
	}
	return 0;
}
Exemplo n.º 9
0
int
repo_show_pkg_revdeps(struct xbps_handle *xhp, const char *pkg)
{
	xbps_array_t revdeps;
	const char *pkgver;
	unsigned int i;
	int rv;

	revdeps = xbps_rpool_get_pkg_revdeps(xhp, pkg);
	rv = errno;

	for (i = 0; i < xbps_array_count(revdeps); i++) {
		xbps_array_get_cstring_nocopy(revdeps, i, &pkgver);
		printf("%s\n", pkgver);
	}

	return rv;
}
Exemplo n.º 10
0
bool HIDDEN
xbps_transaction_shlibs(struct xbps_handle *xhp, xbps_array_t pkgs, xbps_array_t mshlibs)
{
	xbps_object_t obj;
	xbps_object_iterator_t iter;
	xbps_dictionary_t shrequires, shprovides;
	bool unmatched = false;

	shrequires = collect_shlibs(xhp, pkgs, true);
	shprovides = collect_shlibs(xhp, pkgs, false);

	/* iterate over shlib-requires to find unmatched shlibs */
	iter = xbps_dictionary_iterator(shrequires);
	assert(iter);

	while ((obj = xbps_object_iterator_next(iter))) {
		xbps_array_t array;
		const char *pkgver, *shlib;
		char *buf;

		shlib = xbps_dictionary_keysym_cstring_nocopy(obj);
		xbps_dbg_printf(xhp, "%s: checking for `%s': ", __func__, shlib);
		if (xbps_dictionary_get(shprovides, shlib)) {
			xbps_dbg_printf_append(xhp, "found\n");
			continue;
		}
		xbps_dbg_printf_append(xhp, "not found\n");

		unmatched = true;
		array = xbps_dictionary_get_keysym(shrequires, obj);
		for (unsigned int i = 0; i < xbps_array_count(array); i++) {
			xbps_array_get_cstring_nocopy(array, i, &pkgver);
			buf = xbps_xasprintf("%s: broken, unresolvable "
			    "shlib `%s'", pkgver, shlib);
			xbps_array_add_cstring(mshlibs, buf);
			free(buf);
		}
		xbps_object_release(array);
	}
	xbps_object_iterator_release(iter);
	xbps_object_release(shprovides);

	return unmatched;
}
Exemplo n.º 11
0
xbps_array_t
xbps_repo_get_pkg_revdeps(struct xbps_repo *repo, const char *pkg)
{
	xbps_array_t revdeps = NULL, vdeps = NULL;
	xbps_dictionary_t pkgd;
	const char *vpkg;
	bool match = false;

	if (repo->idx == NULL)
		return NULL;

	if (((pkgd = xbps_repo_get_pkg(repo, pkg)) == NULL) &&
	    ((pkgd = xbps_repo_get_virtualpkg(repo, pkg)) == NULL)) {
		errno = ENOENT;
		return NULL;
	}
	/*
	 * If pkg is a virtual pkg let's match it instead of the real pkgver.
	 */
	if ((vdeps = xbps_dictionary_get(pkgd, "provides"))) {
		for (unsigned int i = 0; i < xbps_array_count(vdeps); i++) {
			char *vpkgn;

			xbps_array_get_cstring_nocopy(vdeps, i, &vpkg);
			vpkgn = xbps_pkg_name(vpkg);
			assert(vpkgn);
			if (strcmp(vpkgn, pkg) == 0) {
				free(vpkgn);
				match = true;
				break;
			}
			free(vpkgn);
			vpkg = NULL;
		}
		if (match)
			revdeps = revdeps_match(repo, pkgd, vpkg);
	}
	if (!match)
		revdeps = revdeps_match(repo, pkgd, NULL);

	return revdeps;
}
Exemplo n.º 12
0
static bool
entry_is_conf_file(const char *file)
{
	xbps_array_t a;
	const char *curfile;
	unsigned int i;

	assert(file);

	a = xbps_dictionary_get(pkg_propsd, "conf_files");
	if (a == NULL || xbps_array_count(a) == 0)
		return false;

	for (i = 0; i < xbps_array_count(a); i++) {
		xbps_array_get_cstring_nocopy(a, i, &curfile);
		if (strcmp(file, curfile) == 0)
			return true;
	}
	return false;
}
Exemplo n.º 13
0
Arquivo: util.c Projeto: bougyman/xbps
/*
 * Check if pkg is explicitly marked to replace a specific installed version.
 */
bool
xbps_pkg_reverts(xbps_dictionary_t pkg, const char *pkgver)
{
	unsigned int i;
	xbps_array_t reverts;
	const char *version = xbps_pkg_version(pkgver);
	const char *revertver;

	if ((reverts = xbps_dictionary_get(pkg, "reverts")) == NULL)
		return false;

	for (i = 0; i < xbps_array_count(reverts); i++) {
		xbps_array_get_cstring_nocopy(reverts, i, &revertver);
		if (strcmp(version, revertver) == 0) {
			return true;
		}
	}

	return false;
}
Exemplo n.º 14
0
static void
print_rdeps(struct xbps_handle *xhp, xbps_array_t rdeps,
	    bool full, bool repo, bool origin, int *indent)
{
	xbps_array_t currdeps;
	xbps_dictionary_t pkgd;
	const char *pkgdep;
	unsigned int i;
	int j;

	if (!origin)
		(*indent)++;

	for (i = 0; i < xbps_array_count(rdeps); i++) {
		xbps_array_get_cstring_nocopy(rdeps, i, &pkgdep);
		if (!origin || !full)
			for (j = 0; j < *indent; j++)
				putchar(' ');

		printf("%s\n", pkgdep);
		if (!full)
			continue;

		if (repo) {
			pkgd = xbps_rpool_get_pkg(xhp, pkgdep);
			if (pkgd == NULL)
				pkgd = xbps_rpool_get_virtualpkg(xhp, pkgdep);
		} else {
			pkgd = xbps_pkgdb_get_pkg(xhp, pkgdep);
			if (pkgd == NULL)
				pkgd = xbps_pkgdb_get_virtualpkg(xhp, pkgdep);
		}
		if (pkgd != NULL) {
			currdeps = xbps_dictionary_get(pkgd, "run_depends");
			if (currdeps != NULL)
				print_rdeps(xhp, currdeps,
				    full, repo, false, indent);
		}
	}
	(*indent)--;
}
Exemplo n.º 15
0
/*
 * Returns true if entry is a configuration file, false otherwise.
 */
int HIDDEN
xbps_entry_is_a_conf_file(xbps_dictionary_t propsd,
			  const char *entry_pname)
{
	xbps_array_t array;
	const char *cffile;
	unsigned int i;

	assert(xbps_object_type(propsd) == XBPS_TYPE_DICTIONARY);
	assert(entry_pname != NULL);

	array = xbps_dictionary_get(propsd, "conf_files");
	if (xbps_array_count(array) == 0)
		return false;

	for (i = 0; i < xbps_array_count(array); i++) {
		xbps_array_get_cstring_nocopy(array, i, &cffile);
		if (strcmp(cffile, entry_pname) == 0)
			return true;
	}
	return false;
}
Exemplo n.º 16
0
void HIDDEN
xbps_transaction_revdeps(struct xbps_handle *xhp, xbps_array_t pkgs)
{
	xbps_array_t mdeps;

	mdeps = xbps_dictionary_get(xhp->transd, "missing_deps");

	for (unsigned int i = 0; i < xbps_array_count(pkgs); i++) {
		xbps_array_t pkgrdeps;
		xbps_object_t obj;
		const char *pkgver, *tract;
		char *pkgname;

		obj = xbps_array_get(pkgs, i);
		/*
		 * if pkg in transaction is not installed,
		 * pass to next one.
		 */
		xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
		xbps_dictionary_get_cstring_nocopy(obj, "transaction", &tract);

		pkgname = xbps_pkg_name(pkgver);
		assert(pkgname);
		if (xbps_pkg_is_installed(xhp, pkgname) == 0) {
			free(pkgname);
			continue;
		}
		/*
		 * If pkg is installed but does not have revdeps,
		 * pass to next one.
		 */
		pkgrdeps = xbps_pkgdb_get_pkg_revdeps(xhp, pkgname);
		if (!xbps_array_count(pkgrdeps)) {
			free(pkgname);
			continue;
		}
		free(pkgname);
		/*
		 * Time to validate revdeps for current pkg.
		 */
		for (unsigned int x = 0; x < xbps_array_count(pkgrdeps); x++) {
			xbps_array_t rundeps;
			xbps_dictionary_t revpkgd;
			const char *curpkgver, *revpkgver, *curdep, *curtract;
			char *curpkgname, *curdepname;
			bool found = false;

			xbps_array_get_cstring_nocopy(pkgrdeps, x, &curpkgver);
			pkgname = xbps_pkg_name(curpkgver);
			assert(pkgname);
			if ((revpkgd = xbps_find_pkg_in_array(pkgs, pkgname, NULL))) {
				xbps_dictionary_get_cstring_nocopy(revpkgd, "transaction", &curtract);
				if (strcmp(curtract, "remove") == 0)
					revpkgd = NULL;
			}
			if (revpkgd == NULL)
				revpkgd = xbps_pkgdb_get_pkg(xhp, curpkgver);

			xbps_dictionary_get_cstring_nocopy(revpkgd, "pkgver", &revpkgver);
			/*
			 * If target pkg is being removed, all its revdeps
			 * will be broken unless those revdeps are also in
			 * the transaction.
			 */
			if (strcmp(tract, "remove") == 0) {
				if (xbps_dictionary_get(obj, "replaced")) {
					free(pkgname);
					continue;
				}
				if (xbps_find_pkg_in_array(pkgs, pkgname, "remove")) {
					free(pkgname);
					continue;
				}
				free(pkgname);
				broken_pkg(mdeps, curpkgver, pkgver, tract);
				continue;
			}
			/*
			 * First try to match any supported virtual package.
			 */
			if (check_virtual_pkgs(mdeps, obj, revpkgd)) {
				free(pkgname);
				continue;
			}
			/*
			 * Try to match real dependencies.
			 */
			rundeps = xbps_dictionary_get(revpkgd, "run_depends");
			/*
			 * Find out what dependency is it.
			 */
			curpkgname = xbps_pkg_name(pkgver);
			assert(curpkgname);

			for (unsigned int j = 0; j < xbps_array_count(rundeps); j++) {
				xbps_array_get_cstring_nocopy(rundeps, j, &curdep);
				if (((curdepname = xbps_pkg_name(curdep)) == NULL) &&
				    ((curdepname = xbps_pkgpattern_name(curdep)) == NULL))
					abort();

				if (strcmp(curdepname, curpkgname) == 0) {
					free(curdepname);
					found = true;
					break;
				}
				free(curdepname);
			}
			free(curpkgname);

			if (!found) {
				free(pkgname);
				continue;
			}
			if (xbps_match_pkgdep_in_array(rundeps, pkgver)) {
				free(pkgname);
				continue;
			}
			/*
			 * Installed package conflicts with package
			 * in transaction being updated, check
			 * if a new version of this conflicting package
			 * is in the transaction.
			 */
			if (xbps_find_pkg_in_array(pkgs, pkgname, "update")) {
				free(pkgname);
				continue;
			}
			free(pkgname);
			broken_pkg(mdeps, curpkgver, pkgver, tract);
		}

	}
}
Exemplo n.º 17
0
int
xbps_transaction_prepare(struct xbps_handle *xhp)
{
	xbps_array_t array, pkgs, edges;
	unsigned int i, cnt;
	int rv = 0;

	if (xhp->transd == NULL)
		return ENXIO;

	/*
	 * Collect dependencies for pkgs in transaction.
	 */
	if ((edges = xbps_array_create()) == NULL)
		return ENOMEM;
	/*
	 * The edges are also appended after its dependencies have been
	 * collected; the edges at the original array are removed later.
	 */
	pkgs = xbps_dictionary_get(xhp->transd, "packages");
	assert(xbps_object_type(pkgs) == XBPS_TYPE_ARRAY);
	cnt = xbps_array_count(pkgs);
	for (i = 0; i < cnt; i++) {
		xbps_dictionary_t pkgd;
		xbps_string_t str;
		const char *tract = NULL;

		pkgd = xbps_array_get(pkgs, i);
		str = xbps_dictionary_get(pkgd, "pkgver");
		xbps_dictionary_get_cstring_nocopy(pkgd, "transaction", &tract);
		if ((strcmp(tract, "remove") == 0) || strcmp(tract, "hold") == 0)
			continue;

		assert(xbps_object_type(str) == XBPS_TYPE_STRING);

		if (!xbps_array_add(edges, str))
			return ENOMEM;

		if ((rv = xbps_repository_find_deps(xhp, pkgs, pkgd)) != 0)
			return rv;

		if (!xbps_array_add(pkgs, pkgd))
			return ENOMEM;
	}
	/* ... remove dup edges at head */
	for (i = 0; i < xbps_array_count(edges); i++) {
		const char *pkgver;
		xbps_array_get_cstring_nocopy(edges, i, &pkgver);
		xbps_remove_pkg_from_array_by_pkgver(pkgs, pkgver);
	}
	xbps_object_release(edges);

	/*
	 * Check for packages to be replaced.
	 */
	if ((rv = xbps_transaction_package_replace(xhp, pkgs)) != 0) {
		xbps_object_release(xhp->transd);
		xhp->transd = NULL;
		return rv;
	}
	/*
	 * If there are missing deps or revdeps bail out.
	 */
	xbps_transaction_revdeps(xhp, pkgs);
	array = xbps_dictionary_get(xhp->transd, "missing_deps");
	if (xbps_array_count(array)) {
		if (xhp->flags & XBPS_FLAG_FORCE_REMOVE_REVDEPS) {
			xbps_dbg_printf(xhp, "[trans] continuing with broken reverse dependencies!");
		} else {
			return ENODEV;
		}
	}
	/*
	 * If there are package conflicts bail out.
	 */
	xbps_transaction_conflicts(xhp, pkgs);
	array = xbps_dictionary_get(xhp->transd, "conflicts");
	if (xbps_array_count(array))
		return EAGAIN;
	/*
	 * Check for unresolved shared libraries.
	 */
	if (xbps_transaction_shlibs(xhp, pkgs,
	    xbps_dictionary_get(xhp->transd, "missing_shlibs"))) {
		if (xhp->flags & XBPS_FLAG_FORCE_REMOVE_REVDEPS) {
			xbps_dbg_printf(xhp, "[trans] continuing with unresolved shared libraries!");
		} else {
			return ENOEXEC;
		}
	}
	/*
	 * Add transaction stats for total download/installed size,
	 * number of packages to be installed, updated, configured
	 * and removed to the transaction dictionary.
	 */
	if ((rv = compute_transaction_stats(xhp)) != 0) {
		return rv;
	}
	/*
	 * Remove now unneeded objects.
	 */
	xbps_dictionary_remove(xhp->transd, "missing_shlibs");
	xbps_dictionary_remove(xhp->transd, "missing_deps");
	xbps_dictionary_remove(xhp->transd, "conflicts");
	xbps_dictionary_make_immutable(xhp->transd);

	return 0;
}
Exemplo n.º 18
0
int
xbps_init(struct xbps_handle *xhp)
{
	struct utsname un;
	char cwd[PATH_MAX-1], *buf;
	const char *repodir, *native_arch;
	int rv;

	assert(xhp != NULL);

	/* get cwd */
	if (getcwd(cwd, sizeof(cwd)) == NULL)
		return ENOTSUP;

	/* set conffile */
	if (xhp->conffile[0] == '\0') {
		snprintf(xhp->conffile, sizeof(xhp->conffile), XBPS_CONF_DEF);
	} else {
		buf = strdup(xhp->conffile);
		snprintf(xhp->conffile, sizeof(xhp->conffile), "%s/%s", cwd, buf);
		free(buf);
	}
	/* Set rootdir */
	if (xhp->rootdir[0] == '\0') {
		xhp->rootdir[0] = '/';
		xhp->rootdir[1] = '\0';
	} else if (xhp->rootdir[0] != '/') {
		buf = strdup(xhp->rootdir);
		snprintf(xhp->rootdir, sizeof(xhp->rootdir), "%s/%s", cwd, buf);
		free(buf);
	}
	/* parse configuration file */
	xbps_dbg_printf(xhp, "%s\n", XBPS_RELVER);
	if ((rv = parse_file(xhp, cwd, xhp->conffile, false, false)) != 0) {
		xbps_dbg_printf(xhp, "Using built-in defaults\n");
	}
	/* Set cachedir */
	if (xhp->cachedir[0] == '\0') {
		snprintf(xhp->cachedir, sizeof(xhp->cachedir),
		    "%s/%s", strcmp(xhp->rootdir, "/") ? xhp->rootdir : "",
		    XBPS_CACHE_PATH);
	} else if (xhp->cachedir[0] != '/') {
		/* relative path */
		buf = strdup(xhp->cachedir);
		snprintf(xhp->cachedir, sizeof(xhp->cachedir),
		    "%s/%s", strcmp(xhp->rootdir, "/") ? xhp->rootdir : "", buf);
		free(buf);
	}
	/* Set metadir */
	if (xhp->metadir[0] == '\0') {
		snprintf(xhp->metadir, sizeof(xhp->metadir),
		    "%s/%s", strcmp(xhp->rootdir, "/") ? xhp->rootdir : "",
		    XBPS_META_PATH);
	} else if (xhp->metadir[0] != '/') {
		/* relative path */
		buf = strdup(xhp->metadir);
		snprintf(xhp->metadir, sizeof(xhp->metadir),
		    "%s/%s", strcmp(xhp->rootdir, "/") ? xhp->rootdir : "", buf);
		free(buf);
	}
	/* process virtualpkg.d dirs */
	if ((rv = parse_dir(xhp, cwd, XBPS_SYS_VPKG_PATH, XBPS_VPKG_PATH, true)) != 0)
		return rv;

	/* process repo.d dirs */
	if ((rv = parse_dir(xhp, cwd, XBPS_SYS_REPOD_PATH, XBPS_REPOD_PATH, false)) != 0)
		return rv;

	/* process preserve.d dirs */
	if ((rv = parse_dir(xhp, cwd, XBPS_SYS_PRESERVED_PATH, XBPS_PRESERVED_PATH, false)) != 0)
		return rv;

	xhp->target_arch = getenv("XBPS_TARGET_ARCH");
	if ((native_arch = getenv("XBPS_ARCH")) != NULL) {
		strlcpy(xhp->native_arch, native_arch, sizeof(xhp->native_arch));
	} else {
		uname(&un);
		strlcpy(xhp->native_arch, un.machine, sizeof(xhp->native_arch));
	}
	assert(xhp->native_arch);

	xbps_fetch_set_cache_connection(XBPS_FETCH_CACHECONN, XBPS_FETCH_CACHECONN_HOST);

	xbps_dbg_printf(xhp, "rootdir=%s\n", xhp->rootdir);
	xbps_dbg_printf(xhp, "metadir=%s\n", xhp->metadir);
	xbps_dbg_printf(xhp, "cachedir=%s\n", xhp->cachedir);
	xbps_dbg_printf(xhp, "syslog=%s\n", xhp->flags & XBPS_FLAG_DISABLE_SYSLOG ? "false" : "true");
	xbps_dbg_printf(xhp, "Architecture: %s\n", xhp->native_arch);
	xbps_dbg_printf(xhp, "Target Architecture: %s\n", xhp->target_arch);

	if (xhp->flags & XBPS_FLAG_DEBUG) {
		for (unsigned int i = 0; i < xbps_array_count(xhp->repositories); i++) {
			xbps_array_get_cstring_nocopy(xhp->repositories, i, &repodir);
			xbps_dbg_printf(xhp, "Repository[%u]=%s\n", i, repodir);
		}
	}
	/* Going back to old working directory */
	if (chdir(cwd) == -1)
		xbps_dbg_printf(xhp, "%s: cannot chdir to %s: %s\n", __func__, cwd, strerror(errno));

	return 0;
}
Exemplo n.º 19
0
/*
 * Verify reverse dependencies for packages in transaction.
 * This will catch cases where a package update would break its reverse dependencies:
 *
 * 	- foo-1.0 is being updated to 2.0.
 * 	- baz-1.1 depends on foo<2.0.
 * 	- foo is updated to 2.0, hence baz-1.1 is currently broken.
 *
 * Abort transaction if such case is found.
 */
static bool
check_virtual_pkgs(struct xbps_handle *xhp,
		   xbps_dictionary_t trans_pkgd,
		   xbps_dictionary_t rev_pkgd)
{
	xbps_array_t unsorted, provides, rundeps, mdeps;
	const char *pkgver, *revpkgver, *pkgpattern;
	char *pkgname, *pkgdepname, *vpkgname, *vpkgver, *str;
	unsigned int i, x;
	bool matched = false;

	unsorted = xbps_dictionary_get(xhp->transd, "unsorted_deps");
	provides = xbps_dictionary_get(trans_pkgd, "provides");
	for (i = 0; i < xbps_array_count(provides); i++) {
		char *tmp = NULL;

		xbps_array_get_cstring(provides, i, &vpkgver);
		if (strchr(vpkgver, '_') == NULL) {
			tmp = xbps_xasprintf("%s_1", vpkgver);
			vpkgver = strdup(tmp);
		}
		vpkgname = xbps_pkg_name(vpkgver);
		assert(vpkgname);
		rundeps = xbps_dictionary_get(rev_pkgd, "run_depends");
		for (x = 0; x < xbps_array_count(rundeps); x++) {
			xbps_array_get_cstring_nocopy(rundeps, x, &pkgpattern);
			if (((pkgname = xbps_pkgpattern_name(pkgpattern)) == NULL) &&
			    ((pkgname = xbps_pkg_name(pkgpattern)) == NULL))
				continue;

			if (strcmp(vpkgname, pkgname)) {
				free(pkgname);
				continue;
			}
			free(pkgname);
			if (xbps_pkgpattern_match(vpkgver, pkgpattern))
				continue;

			/*
			 * Installed package conflicts with package
			 * in transaction being updated, check
			 * if a new version of this conflicting package
			 * is in the transaction.
			 */
			xbps_dictionary_get_cstring_nocopy(trans_pkgd, "pkgver", &pkgver);
			pkgdepname = xbps_pkg_name(pkgver);
			assert(pkgdepname);
			if (xbps_find_pkg_in_array(unsorted, pkgdepname)) {
				free(pkgdepname);
				continue;
			}
			free(pkgdepname);

			mdeps = xbps_dictionary_get(xhp->transd, "missing_deps");
			xbps_dictionary_get_cstring_nocopy(trans_pkgd, "pkgver", &pkgver);
			xbps_dictionary_get_cstring_nocopy(rev_pkgd, "pkgver", &revpkgver);
			str = xbps_xasprintf("CONFLICT: `%s' update "
			    "breaks `%s', needs `%s' virtual pkg (got `%s`)",
			    pkgver, revpkgver, pkgpattern, vpkgver);
			xbps_array_add_cstring(mdeps, str);
			free(str);
			matched = true;
		}
		free(vpkgname);
		free(vpkgver);
	}
	return matched;
}
Exemplo n.º 20
0
void HIDDEN
xbps_transaction_revdeps(struct xbps_handle *xhp)
{
	xbps_array_t mdeps, unsorted, pkgrdeps, rundeps;
	xbps_dictionary_t revpkgd;
	xbps_object_t obj;
	const char *pkgver, *curdep, *revpkgver, *curpkgver, *tract;
	char *pkgname, *curdepname, *curpkgname, *str;
	unsigned int i, j, x;

	unsorted = xbps_dictionary_get(xhp->transd, "unsorted_deps");

	for (i = 0; i < xbps_array_count(unsorted); i++) {
		obj = xbps_array_get(unsorted, i);
		/*
		 * Only check packages in transaction being updated.
		 */
		xbps_dictionary_get_cstring_nocopy(obj, "transaction", &tract);
		if (strcmp(tract, "update"))
			continue;
		/*
		 * if pkg in transaction is not installed,
		 * pass to next one.
		 */
		xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
		pkgname = xbps_pkg_name(pkgver);
		assert(pkgname);
		if (xbps_pkg_is_installed(xhp, pkgname) == 0) {
			free(pkgname);
			continue;
		}
		/*
		 * If pkg is installed but does not have revdeps,
		 * pass to next one.
		 */
		pkgrdeps = xbps_pkgdb_get_pkg_revdeps(xhp, pkgname);
		if (!xbps_array_count(pkgrdeps)) {
			free(pkgname);
			continue;
		}
		free(pkgname);
		/*
		 * Time to validate revdeps for current pkg.
		 */
		for (x = 0; x < xbps_array_count(pkgrdeps); x++) {
			bool found = false;

			xbps_array_get_cstring_nocopy(pkgrdeps, x, &curpkgver);
			revpkgd = xbps_pkgdb_get_pkg(xhp, curpkgver);
			/*
			 * First try to match any supported virtual package.
			 */
			if (check_virtual_pkgs(xhp, obj, revpkgd))
				continue;
			/*
			 * Try to match real dependencies.
			 */
			rundeps = xbps_dictionary_get(revpkgd, "run_depends");
			/*
			 * Find out what dependency is it.
			 */
			curpkgname = xbps_pkg_name(pkgver);
			assert(curpkgname);

			for (j = 0; j < xbps_array_count(rundeps); j++) {
				xbps_array_get_cstring_nocopy(rundeps, j, &curdep);
				if (((curdepname = xbps_pkg_name(curdep)) == NULL) &&
				    ((curdepname = xbps_pkgpattern_name(curdep)) == NULL))
					abort();

				if (strcmp(curdepname, curpkgname) == 0) {
					free(curdepname);
					found = true;
					break;
				}
				free(curdepname);
			}
			if (!found)
				continue;

			if (xbps_match_pkgdep_in_array(rundeps, pkgver))
				continue;
			/*
			 * Installed package conflicts with package
			 * in transaction being updated, check
			 * if a new version of this conflicting package
			 * is in the transaction.
			 */
			pkgname = xbps_pkg_name(curpkgver);
			if (xbps_find_pkg_in_array(unsorted, pkgname)) {
				free(pkgname);
				continue;
			}
			free(pkgname);
			mdeps = xbps_dictionary_get(xhp->transd, "missing_deps");
			xbps_dictionary_get_cstring_nocopy(revpkgd,
			    "pkgver", &revpkgver);
			str = xbps_xasprintf("CONFLICT: `%s' "
			    "update breaks `%s', needs `%s'",
			    pkgver, revpkgver, curdep);
			xbps_array_add_cstring(mdeps, str);
			free(str);
		}

	}
}
Exemplo n.º 21
0
int
xbps_alternatives_unregister(struct xbps_handle *xhp, xbps_dictionary_t pkgd)
{
	xbps_array_t allkeys;
	xbps_dictionary_t alternatives, pkg_alternatives;
	const char *pkgver;
	char *pkgname;
	bool update = false;
	int rv = 0;

	assert(xhp);

	alternatives = xbps_dictionary_get(xhp->pkgdb, "_XBPS_ALTERNATIVES_");
	if (alternatives == NULL)
		return 0;

	pkg_alternatives = xbps_dictionary_get(pkgd, "alternatives");
	if (!xbps_dictionary_count(pkg_alternatives))
		return 0;

	xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver);
	if ((pkgname = xbps_pkg_name(pkgver)) == NULL)
		return EINVAL;

	xbps_dictionary_get_bool(pkgd, "alternatives-update", &update);

	allkeys = xbps_dictionary_all_keys(pkg_alternatives);
	for (unsigned int i = 0; i < xbps_array_count(allkeys); i++) {
		xbps_array_t array;
		xbps_object_t keysym;
		const char *first = NULL, *keyname;

		keysym = xbps_array_get(allkeys, i);
		keyname = xbps_dictionary_keysym_cstring_nocopy(keysym);

		array = xbps_dictionary_get(alternatives, keyname);
		if (array == NULL)
			continue;

		xbps_array_get_cstring_nocopy(array, 0, &first);
		if (strcmp(pkgname, first) == 0) {
			/* this pkg is the current alternative for this group */
			rv = remove_symlinks(xhp,
				xbps_dictionary_get(pkg_alternatives, keyname),
				keyname);
			if (rv != 0)
				break;
		}

		xbps_set_cb_state(xhp, XBPS_STATE_ALTGROUP_REMOVED, 0, NULL,
		    "%s: unregistered '%s' alternatives group", pkgver, keyname);
		if (!update)
			xbps_remove_string_from_array(array, pkgname);

		if (xbps_array_count(array) == 0) {
			xbps_dictionary_remove(alternatives, keyname);
		} else {
			xbps_dictionary_t curpkgd;

			first = NULL;
			xbps_array_get_cstring_nocopy(array, 0, &first);
			curpkgd = xbps_pkgdb_get_pkg(xhp, first);
			assert(curpkgd);
			xbps_set_cb_state(xhp, XBPS_STATE_ALTGROUP_SWITCHED, 0, NULL,
			    "Switched '%s' alternatives group to '%s'", keyname, first);
			pkg_alternatives = xbps_dictionary_get(curpkgd, "alternatives");
			rv = create_symlinks(xhp,
				xbps_dictionary_get(pkg_alternatives, keyname),
				keyname);
			if (rv != 0)
				break;
		}

	}
	xbps_object_release(allkeys);
	free(pkgname);

	return rv;
}
Exemplo n.º 22
0
static xbps_array_t
revdeps_match(struct xbps_repo *repo, xbps_dictionary_t tpkgd, const char *str)
{
	xbps_dictionary_t pkgd;
	xbps_array_t revdeps = NULL, pkgdeps, provides;
	xbps_object_iterator_t iter;
	xbps_object_t obj;
	const char *pkgver, *tpkgver, *arch, *vpkg;

	iter = xbps_dictionary_iterator(repo->idx);
	assert(iter);

	while ((obj = xbps_object_iterator_next(iter))) {
		pkgd = xbps_dictionary_get_keysym(repo->idx, obj);
		if (xbps_dictionary_equals(pkgd, tpkgd))
			continue;

		pkgdeps = xbps_dictionary_get(pkgd, "run_depends");
		if (!xbps_array_count(pkgdeps))
			continue;
		/*
		 * Try to match passed in string.
		 */
		if (str) {
			if (!xbps_match_pkgdep_in_array(pkgdeps, str))
				continue;
			xbps_dictionary_get_cstring_nocopy(pkgd,
			    "architecture", &arch);
			if (!xbps_pkg_arch_match(repo->xhp, arch, NULL))
				continue;

			xbps_dictionary_get_cstring_nocopy(pkgd,
			    "pkgver", &tpkgver);
			/* match */
			if (revdeps == NULL)
				revdeps = xbps_array_create();

			if (!xbps_match_string_in_array(revdeps, tpkgver))
				xbps_array_add_cstring_nocopy(revdeps, tpkgver);

			continue;
		}
		/*
		 * Try to match any virtual package.
		 */
		provides = xbps_dictionary_get(tpkgd, "provides");
		for (unsigned int i = 0; i < xbps_array_count(provides); i++) {
			xbps_array_get_cstring_nocopy(provides, i, &vpkg);
			if (!xbps_match_pkgdep_in_array(pkgdeps, vpkg))
				continue;

			xbps_dictionary_get_cstring_nocopy(pkgd,
			    "architecture", &arch);
			if (!xbps_pkg_arch_match(repo->xhp, arch, NULL))
				continue;

			xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver",
			    &tpkgver);
			/* match */
			if (revdeps == NULL)
				revdeps = xbps_array_create();

			if (!xbps_match_string_in_array(revdeps, tpkgver))
				xbps_array_add_cstring_nocopy(revdeps, tpkgver);
		}
		/*
		 * Try to match by pkgver.
		 */
		xbps_dictionary_get_cstring_nocopy(tpkgd, "pkgver", &pkgver);
		if (!xbps_match_pkgdep_in_array(pkgdeps, pkgver))
			continue;

		xbps_dictionary_get_cstring_nocopy(pkgd,
		    "architecture", &arch);
		if (!xbps_pkg_arch_match(repo->xhp, arch, NULL))
			continue;

		xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &tpkgver);
		/* match */
		if (revdeps == NULL)
			revdeps = xbps_array_create();

		if (!xbps_match_string_in_array(revdeps, tpkgver))
			xbps_array_add_cstring_nocopy(revdeps, tpkgver);
	}
	xbps_object_iterator_release(iter);
	return revdeps;
}
Exemplo n.º 23
0
static bool
repodata_commit(struct xbps_handle *xhp, const char *repodir,
	xbps_dictionary_t idx, xbps_dictionary_t meta, xbps_dictionary_t stage) {
	const char *pkgname;
	xbps_object_iterator_t iter;
	xbps_object_t keysym;
	int rv;

	if(xbps_dictionary_count(stage) == 0) {
		// Nothing to do.
		return true;
	}

	/*
	 * Find old shlibs-provides
	 */
	xbps_dictionary_t oldshlibs = xbps_dictionary_create();
	xbps_dictionary_t usedshlibs = xbps_dictionary_create();

	iter = xbps_dictionary_iterator(stage);
	while ((keysym = xbps_object_iterator_next(iter))) {
		pkgname = xbps_dictionary_keysym_cstring_nocopy(keysym);
		xbps_dictionary_t oldpkg = xbps_dictionary_get(idx, pkgname);

		xbps_array_t pkgshlibs = xbps_dictionary_get(oldpkg, "shlib-provides");
		for(unsigned int i = 0; i < xbps_array_count(pkgshlibs); i++) {
			const char *shlib = NULL;
			xbps_array_get_cstring_nocopy(pkgshlibs, i, &shlib);
			xbps_dictionary_set_cstring(oldshlibs, shlib, pkgname);
		}
	}
	xbps_object_iterator_release(iter);

	/*
	 * throw away all unused shlibs
	 */
	iter = xbps_dictionary_iterator(idx);
	while ((keysym = xbps_object_iterator_next(iter))) {
		pkgname = xbps_dictionary_keysym_cstring_nocopy(keysym);
		xbps_dictionary_t pkg = xbps_dictionary_get(stage, pkgname);
		if(!pkg)
			pkg = xbps_dictionary_get_keysym(idx, keysym);
		xbps_array_t pkgshlibs = xbps_dictionary_get(pkg, "shlib-requires");

		for(unsigned int i = 0; i < xbps_array_count(pkgshlibs); i++) {
			const char *shlib = NULL, *user = NULL;
			xbps_array_get_cstring_nocopy(pkgshlibs, i, &shlib);
			xbps_dictionary_get_cstring_nocopy(pkg, shlib, &user);
			if(!user)
				continue;
			xbps_array_t users = xbps_dictionary_get(usedshlibs, shlib);
			if(!users) {
				users = xbps_array_create();
				xbps_dictionary_set(usedshlibs, shlib, users);
			}
			xbps_array_add_cstring(users, user);
		}
	}
	xbps_object_iterator_release(iter);

	/*
	 * purge all packages that are fullfilled by the stage
	 */
	iter = xbps_dictionary_iterator(stage);
	while ((keysym = xbps_object_iterator_next(iter))) {
		pkgname = xbps_dictionary_keysym_cstring_nocopy(keysym);
		xbps_dictionary_t newpkg = xbps_dictionary_get(idx, pkgname);

		xbps_array_t pkgshlibs = xbps_dictionary_get(newpkg, "shlib-provides");
		for(unsigned int i = 0; i < xbps_array_count(pkgshlibs); i++) {
			const char *shlib;
			xbps_array_get_cstring_nocopy(pkgshlibs, i, &shlib);
			xbps_dictionary_remove(usedshlibs, shlib);
		}
	}
	xbps_object_iterator_release(iter);

	if(xbps_dictionary_count(usedshlibs) != 0) {
		puts("Unfullfilled shlibs:");
		iter = xbps_dictionary_iterator(usedshlibs);
		while ((keysym = xbps_object_iterator_next(iter))) {
			const char *shlib = xbps_dictionary_keysym_cstring_nocopy(keysym), *provider = NULL;
			xbps_array_t users = xbps_dictionary_get(usedshlibs, shlib);
			xbps_dictionary_get_cstring_nocopy(usedshlibs, shlib, &provider);

			printf(" %s (provided by: %s; used by: ", shlib, provider);
			const char *pre = "";
			for(unsigned int i = 0; i < xbps_array_count(users); i++) {
				const char *user;
				xbps_array_get_cstring_nocopy(users, i, &user);
				xbps_dictionary_remove(usedshlibs, shlib);
				printf("%s%s",pre, user);
				pre = ", ";
			}
			puts(")");
		}
		puts("Changes are commit to stage.");
		xbps_object_iterator_release(iter);
		// TODO FLUSH STAGE
		rv = true;
	}
	else {
		iter = xbps_dictionary_iterator(stage);
		while ((keysym = xbps_object_iterator_next(iter))) {
			pkgname = xbps_dictionary_keysym_cstring_nocopy(keysym);
			xbps_dictionary_t newpkg = xbps_dictionary_get_keysym(stage, keysym);
			xbps_dictionary_set(idx, pkgname, newpkg);
		}
		xbps_object_iterator_release(iter);
		rv = repodata_flush(xhp, repodir, idx, meta);
	}
	xbps_object_release(usedshlibs);
	xbps_object_release(oldshlibs);
	return rv;
}
Exemplo n.º 24
0
static xbps_dictionary_t
collect_shlibs(struct xbps_handle *xhp, xbps_array_t pkgs, bool req)
{
	xbps_object_t obj;
	xbps_object_iterator_t iter;
	xbps_dictionary_t d, pd;
	const char *pkgver;

	d = xbps_dictionary_create();
	assert(d);

	/* copy pkgdb to out temporary dictionary */
	pd = xbps_dictionary_copy(xhp->pkgdb);
	assert(pd);

	/*
	 * copy pkgs from transaction to our dictionary, overriding them
	 * if they were there from pkgdb.
	 */
	iter = xbps_array_iterator(pkgs);
	assert(iter);
	while ((obj = xbps_object_iterator_next(iter))) {
		char *pkgname;

		if (!xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver))
			continue;

		pkgname = xbps_pkg_name(pkgver);
		assert(pkgname);
		xbps_dictionary_set(pd, pkgname, obj);
		free(pkgname);
	}
	xbps_object_iterator_release(iter);

	/*
	 * iterate over our dictionary to collect shlib-{requires,provides}.
	 */
	iter = xbps_dictionary_iterator(pd);
	assert(iter);

	while ((obj = xbps_object_iterator_next(iter))) {
		xbps_array_t shobjs;
		xbps_dictionary_t pkgd;
		const char *trans;

		pkgd = xbps_dictionary_get_keysym(pd, obj);
		if (xbps_dictionary_get_cstring_nocopy(pkgd, "transaction", &trans)) {
			if (!strcmp(trans, "remove"))
				continue;
		}
		/*
		 * If pkg does not have the required obj, pass to next one.
		 */
		xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver);
		shobjs = xbps_dictionary_get(pkgd,
				req ? "shlib-requires" : "shlib-provides");
		if (shobjs == NULL)
			continue;

		for (unsigned int i = 0; i < xbps_array_count(shobjs); i++) {
			const char *shlib;

			xbps_array_get_cstring_nocopy(shobjs, i, &shlib);
			xbps_dbg_printf(xhp, "%s: registering %s for %s\n",
			    pkgver, shlib, req ? "shlib-requires" : "shlib-provides");
			if (req)
				shlib_register(d, shlib, pkgver);
			else
				xbps_dictionary_set_cstring_nocopy(d, shlib, pkgver);
		}
	}
	xbps_object_iterator_release(iter);
	return d;
}