Example #1
0
/**
 * @file lib/initend.c
 * @brief Initialization and finalization routines
 * @defgroup initend Initialization and finalization functions
 *
 * Use these functions to initialize some parameters before start
 * using libxbps and finalize usage to release resources at the end.
 */
static void
store_vpkg(struct xbps_handle *xhp, const char *path, size_t line, char *vpkg_s)
{
	/*
	 * Append virtual package overrides to our vpkgd dictionary:
	 *
	 * <key>vpkgver</key>
	 * <string>realpkgname</string>
	 */
	char *vpkg, *rpkg, *tc;
	size_t vpkglen;

	if (xhp->vpkgd == NULL)
		xhp->vpkgd = xbps_dictionary_create();

	/* real pkg after ':' */
	vpkg = vpkg_s;
	rpkg = strchr(vpkg_s, ':');
	if (rpkg == NULL || *rpkg == '\0') {
		xbps_dbg_printf(xhp, "%s: ignoring invalid "
		    "virtualpkg option at line %zu\n", path, line);
		return;
	}
	/* vpkg until ':' */
	tc = strchr(vpkg_s, ':');
	vpkglen = strlen(vpkg_s) - strlen(tc);
	vpkg[vpkglen] = '\0';

	/* skip ':' */
	rpkg++;
	xbps_dictionary_set_cstring(xhp->vpkgd, vpkg, rpkg);
	xbps_dbg_printf(xhp, "%s: added vpkg %s for %s\n", path, vpkg, rpkg);
}
Example #2
0
static void
process_one_alternative(const char *altgrname, const char *val)
{
	xbps_dictionary_t d;
	xbps_array_t a;
	char *altfiles;
	bool alloc = false;

	if ((d = xbps_dictionary_get(pkg_propsd, "alternatives")) == NULL) {
		d = xbps_dictionary_create();
		assert(d);
		alloc = true;
	}
	if ((a = xbps_dictionary_get(d, altgrname)) == NULL) {
		a = xbps_array_create();
		assert(a);
	}
	altfiles = strchr(val, ':') + 1;
	assert(altfiles);

	xbps_array_add_cstring(a, altfiles);
	xbps_dictionary_set(d, altgrname, a);
	xbps_dictionary_set(pkg_propsd, "alternatives", d);

	if (alloc) {
		xbps_object_release(a);
		xbps_object_release(d);
	}
}
Example #3
0
static xbps_dictionary_t
get_pkg_metadata(struct xbps_handle *xhp, xbps_dictionary_t pkgd)
{
	xbps_dictionary_t pkg_metad;
	const char *pkgver;
	char *pkgname, *plist;

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

	if ((pkg_metad = xbps_dictionary_get(xhp->pkg_metad, pkgname)) != NULL) {
		free(pkgname);
		return pkg_metad;
	}
	plist = xbps_xasprintf("%s/.%s.plist", xhp->metadir, pkgname);
	pkg_metad = xbps_dictionary_internalize_from_file(plist);
	free(plist);

	if (pkg_metad == NULL) {
		xbps_dbg_printf(xhp, "[pkgdb] cannot read %s metadata: %s\n",
		    pkgver, strerror(errno));
		free(pkgname);
		return NULL;
	}

	if (xhp->pkg_metad == NULL)
		xhp->pkg_metad = xbps_dictionary_create();

	xbps_dictionary_set(xhp->pkg_metad, pkgname, pkg_metad);
	xbps_object_release(pkg_metad);
	free(pkgname);

	return pkg_metad;
}
Example #4
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);
}
Example #5
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;
}
Example #6
0
int
xbps_pkgdb_lock(struct xbps_handle *xhp)
{
	mode_t prev_umask;
	int rv;
	/*
	 * Use a mandatory file lock to only allow one writer to pkgdb,
	 * other writers will block.
	 */
	xhp->pkgdb_plist = xbps_xasprintf("%s/%s", xhp->metadir, XBPS_PKGDB);
	if (xbps_pkgdb_init(xhp) == ENOENT) {
		/* if metadir does not exist, create it */
		if (access(xhp->metadir, R_OK|X_OK) == -1) {
			if (errno != ENOENT)
				return errno;

			if (xbps_mkpath(xhp->metadir, 0755) == -1) {
				rv = errno;
				xbps_dbg_printf(xhp, "[pkgdb] failed to create metadir "
				    "%s: %s\n", xhp->metadir, strerror(rv));
				return rv;
			}
		}
		/* if pkgdb is unexistent, create it with an empty dictionary */
		xhp->pkgdb = xbps_dictionary_create();
		if (!xbps_dictionary_externalize_to_file(xhp->pkgdb, xhp->pkgdb_plist)) {
			rv = errno;
			xbps_dbg_printf(xhp, "[pkgdb] failed to create pkgdb "
			    "%s: %s\n", xhp->pkgdb_plist, strerror(rv));
			return rv;
		}
	}

	prev_umask = umask(022);
	if ((pkgdb_fd = open(xhp->pkgdb_plist, O_CREAT|O_RDWR|O_CLOEXEC, 0664)) == -1) {
		rv = errno;
		xbps_dbg_printf(xhp, "[pkgdb] cannot open pkgdb for locking "
		    "%s: %s\n", xhp->pkgdb_plist, strerror(rv));
		free(xhp->pkgdb_plist);
		umask(prev_umask);
		return rv;
	}
	umask(prev_umask);

	if (lockf(pkgdb_fd, F_TLOCK, 0) == -1) {
		rv = errno;
		xbps_dbg_printf(xhp, "[pkgdb] cannot lock pkgdb: %s\n", strerror(rv));
		return rv;
	}
	return 0;
}
Example #7
0
int
xbps_set_pkg_state_installed(struct xbps_handle *xhp,
			     const char *pkgver,
			     pkg_state_t state)
{
	xbps_dictionary_t pkgd;
	char *pkgname;
	int rv = 0;

	assert(pkgver != NULL);

	pkgd = xbps_pkgdb_get_pkg(xhp, pkgver);
	if (pkgd == NULL) {
		pkgd = xbps_dictionary_create();
		if (pkgd == NULL)
			return ENOMEM;

		if (!xbps_dictionary_set_cstring_nocopy(pkgd,
		    "pkgver", pkgver)) {
			xbps_object_release(pkgd);
			return EINVAL;
		}
		if ((rv = set_new_state(pkgd, state)) != 0) {
			xbps_object_release(pkgd);
			return rv;
		}
		pkgname = xbps_pkg_name(pkgver);
		assert(pkgname);
		if (!xbps_dictionary_set(xhp->pkgdb, pkgname, pkgd)) {
			xbps_object_release(pkgd);
			free(pkgname);
			return EINVAL;
		}
		free(pkgname);
		xbps_object_release(pkgd);
	} else {
		if ((rv = set_new_state(pkgd, state)) != 0)
			return rv;

		pkgname = xbps_pkg_name(pkgver);
		assert(pkgname);
		if (!xbps_dictionary_set(xhp->pkgdb, pkgname, pkgd)) {
			free(pkgname);
			return EINVAL;
		}
		free(pkgname);
	}

	return rv;
}
Example #8
0
int
xbps_pkgdb_update(struct xbps_handle *xhp, bool flush, bool update)
{
	xbps_dictionary_t pkgdb_storage;
	static int cached_rv;
	int rv = 0;

	if (cached_rv && !flush)
		return cached_rv;

	if (xhp->pkgdb && update) {
		pkgdb_storage = xbps_dictionary_internalize_from_file(xhp->pkgdb_plist);
		if (pkgdb_storage == NULL ||
		    !xbps_dictionary_equals(xhp->pkgdb, pkgdb_storage)) {
			/* flush dictionary to storage */
			if (!xbps_dictionary_externalize_to_file(xhp->pkgdb, xhp->pkgdb_plist))
				return errno;
		}
		if (pkgdb_storage)
			xbps_object_release(pkgdb_storage);

		xbps_object_release(xhp->pkgdb);
		xhp->pkgdb = NULL;
		cached_rv = 0;
	}
	if (!update)
		return rv;

	/* update copy in memory */
	if ((xhp->pkgdb = xbps_dictionary_internalize_from_file(xhp->pkgdb_plist)) == NULL) {
		rv = errno;
		if (!rv)
			rv = EINVAL;

		if (rv == ENOENT)
			xhp->pkgdb = xbps_dictionary_create();
		else
			xbps_error_printf("cannot access to pkgdb: %s\n", strerror(rv));

		cached_rv = rv = errno;
	}

	return rv;
}
Example #9
0
int
xbps_pkgdb_update(struct xbps_handle *xhp, bool flush)
{
	xbps_dictionary_t pkgdb_storage;
	char *plist;
	static int cached_rv;
	int rv = 0;

	if (cached_rv && !flush)
		return cached_rv;

	plist = xbps_xasprintf("%s/%s", xhp->metadir, XBPS_PKGDB);
	if (xhp->pkgdb && flush) {
		pkgdb_storage = xbps_dictionary_internalize_from_file(plist);
		if (pkgdb_storage == NULL ||
		    !xbps_dictionary_equals(xhp->pkgdb, pkgdb_storage)) {
			/* flush dictionary to storage */
			if (!xbps_dictionary_externalize_to_file(xhp->pkgdb, plist)) {
				free(plist);
				return errno;
			}
		}
		if (pkgdb_storage)
			xbps_object_release(pkgdb_storage);

		xbps_object_release(xhp->pkgdb);
		xhp->pkgdb = NULL;
		cached_rv = 0;
	}
	/* update copy in memory */
	if ((xhp->pkgdb = xbps_dictionary_internalize_from_file(plist)) == NULL) {
		if (errno == ENOENT)
			xhp->pkgdb = xbps_dictionary_create();
		else
			xbps_error_printf("cannot access to pkgdb: %s\n", strerror(errno));

		cached_rv = rv = errno;
	}
	free(plist);

	return rv;
}
Example #10
0
int
xbps_alternatives_register(struct xbps_handle *xhp, xbps_dictionary_t pkgd)
{
	xbps_array_t allkeys;
	xbps_dictionary_t alternatives, pkg_alternatives;
	const char *pkgver;
	char *pkgname;
	int rv = 0;

	assert(xhp);

	if (xhp->pkgdb == NULL)
		return EINVAL;

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

	alternatives = xbps_dictionary_get(xhp->pkgdb, "_XBPS_ALTERNATIVES_");
	if (alternatives == NULL) {
		alternatives = xbps_dictionary_create();
		xbps_dictionary_set(xhp->pkgdb, "_XBPS_ALTERNATIVES_", alternatives);
		xbps_object_release(alternatives);
	}
	alternatives = xbps_dictionary_get(xhp->pkgdb, "_XBPS_ALTERNATIVES_");
	assert(alternatives);

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

	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 *keyname;
		bool alloc = false;

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

		array = xbps_dictionary_get(alternatives, keyname);
		if (array == NULL) {
			alloc = true;
			array = xbps_array_create();
		} else {
			/* already registered */
			if (xbps_match_string_in_array(array, pkgname))
				continue;
		}

		xbps_array_add_cstring(array, pkgname);
		xbps_dictionary_set(alternatives, keyname, array);
		xbps_set_cb_state(xhp, XBPS_STATE_ALTGROUP_ADDED, 0, NULL,
		    "%s: registered '%s' alternatives group", pkgver, keyname);
		if (alloc) {
			/* apply alternatives for this group */
			rv = create_symlinks(xhp,
				xbps_dictionary_get(pkg_alternatives, keyname),
				keyname);
			xbps_object_release(array);
			if (rv != 0)
				break;
		}
	}
	xbps_object_release(allkeys);
	free(pkgname);

	return rv;
}
Example #11
0
int HIDDEN
xbps_transaction_init(struct xbps_handle *xhp)
{
	xbps_array_t array;

	if (xhp->transd != NULL)
		return 0;

	if ((xhp->transd = xbps_dictionary_create()) == NULL)
		return ENOMEM;

        if ((array = xbps_array_create()) == NULL) {
		xbps_object_release(xhp->transd);
		xhp->transd = NULL;
		return ENOMEM;
	}
	if (!xbps_dictionary_set(xhp->transd, "packages", array)) {
		xbps_object_release(xhp->transd);
		xhp->transd = NULL;
		return EINVAL;
	}
	xbps_object_release(array);

	if ((array = xbps_array_create()) == NULL) {
		xbps_object_release(xhp->transd);
		xhp->transd = NULL;
		return ENOMEM;
	}
	if (!xbps_dictionary_set(xhp->transd, "missing_deps", array)) {
		xbps_object_release(xhp->transd);
		xhp->transd = NULL;
		return EINVAL;
	}
	xbps_object_release(array);

	if ((array = xbps_array_create()) == NULL) {
		xbps_object_release(xhp->transd);
		xhp->transd = NULL;
		return ENOMEM;
	}
	if (!xbps_dictionary_set(xhp->transd, "missing_shlibs", array)) {
		xbps_object_release(xhp->transd);
		xhp->transd = NULL;
		return EINVAL;
	}
	xbps_object_release(array);

	if ((array = xbps_array_create()) == NULL) {
		xbps_object_release(xhp->transd);
		xhp->transd = NULL;
		return ENOMEM;
	}
	if (!xbps_dictionary_set(xhp->transd, "conflicts", array)) {
		xbps_object_release(xhp->transd);
		xhp->transd = NULL;
		return EINVAL;
	}
	xbps_object_release(array);

	return 0;
}
Example #12
0
int
index_add(struct xbps_handle *xhp, int args, int argmax, char **argv, bool force)
{
	xbps_dictionary_t idx, idxmeta, idxstage, binpkgd, curpkgd;
	struct xbps_repo *repo = NULL;
	struct stat st;
	char *tmprepodir = NULL, *repodir = NULL, *rlockfname = NULL;
	int rv = 0, ret = 0, rlockfd = -1;

	assert(argv);
	/*
	 * Read the repository data or create index dictionaries otherwise.
	 */
	if ((tmprepodir = strdup(argv[args])) == NULL)
		return ENOMEM;

	repodir = dirname(tmprepodir);
	if (!xbps_repo_lock(xhp, repodir, &rlockfd, &rlockfname)) {
		fprintf(stderr, "xbps-rindex: cannot lock repository "
		    "%s: %s\n", repodir, strerror(errno));
		rv = -1;
		goto out;
	}
	repo = xbps_repo_public_open(xhp, repodir);
	if (repo == NULL && errno != ENOENT) {
		fprintf(stderr, "xbps-rindex: cannot open/lock repository "
		    "%s: %s\n", repodir, strerror(errno));
		rv = -1;
		goto out;
	}
	if (repo) {
		idx = xbps_dictionary_copy_mutable(repo->idx);
		idxmeta = xbps_dictionary_copy_mutable(repo->idxmeta);
	} else {
		idx = xbps_dictionary_create();
		idxmeta = NULL;
	}
	// TODO: load data from stage repository
	idxstage = xbps_dictionary_create();
	/*
	 * Process all packages specified in argv.
	 */
	for (int i = args; i < argmax; i++) {
		const char *arch = NULL, *pkg = argv[i];
		char *sha256 = NULL, *pkgver = NULL, *pkgname = NULL;

		assert(pkg);
		/*
		 * Read metadata props plist dictionary from binary package.
		 */
		binpkgd = xbps_archive_fetch_plist(pkg, "/props.plist");
		if (binpkgd == NULL) {
			fprintf(stderr, "index: failed to read %s metadata for "
			    "`%s', skipping!\n", XBPS_PKGPROPS, pkg);
			continue;
		}
		xbps_dictionary_get_cstring_nocopy(binpkgd, "architecture", &arch);
		xbps_dictionary_get_cstring(binpkgd, "pkgver", &pkgver);
		if (!xbps_pkg_arch_match(xhp, arch, NULL)) {
			fprintf(stderr, "index: ignoring %s, unmatched arch (%s)\n", pkgver, arch);
			xbps_object_release(binpkgd);
			free(pkgver);
			continue;
		}
		pkgname = xbps_pkg_name(pkgver);
		assert(pkgname);
		/*
		 * Check if this package exists already in the index, but first
		 * checking the version. If current package version is greater
		 * than current registered package, update the index; otherwise
		 * pass to the next one.
		 */
		curpkgd = xbps_dictionary_get(idxstage, pkgname);
		if(curpkgd == NULL)
			curpkgd = xbps_dictionary_get(idx, pkgname);
		if (curpkgd == NULL) {
			if (errno && errno != ENOENT) {
				rv = errno;
				free(pkgver);
				free(pkgname);
				goto out;
			}
		} else if (!force) {
			char *opkgver = NULL, *oarch = NULL;

			/* Only check version if !force */
			xbps_dictionary_get_cstring(curpkgd, "pkgver", &opkgver);
			xbps_dictionary_get_cstring(curpkgd, "architecture", &oarch);
			ret = xbps_cmpver(pkgver, opkgver);

			/*
			 * If the considered package reverts the package in the index,
			 * consider the current package as the newer one.
			 */
			if (ret < 0 && xbps_pkg_reverts(binpkgd, opkgver)) {
				ret = 1;
			/*
			 * If package in the index reverts considered package, consider the
			 * package in the index as the newer one.
			 */
			} else if (ret > 0 && xbps_pkg_reverts(curpkgd, pkgver)) {
				ret = -1;
			}

			if (ret <= 0) {
				/* Same version or index version greater */
				fprintf(stderr, "index: skipping `%s' (%s), already registered.\n", pkgver, arch);
				xbps_object_release(binpkgd);
				free(opkgver);
				free(oarch);
				free(pkgver);
				free(pkgname);
				continue;
			}
			/*
			 * Current package version is greater than
			 * index version.
			 */
			printf("index: removed obsolete entry `%s' (%s).\n", opkgver, oarch);
			xbps_dictionary_remove(idx, pkgname);
			free(opkgver);
			free(oarch);
		}
		/*
		 * Add additional objects for repository ops:
		 * 	- filename-size
		 * 	- filename-sha256
		 */
		if ((sha256 = xbps_file_hash(pkg)) == NULL) {
			free(pkgver);
			free(pkgname);
			rv = EINVAL;
			goto out;
		}
		if (!xbps_dictionary_set_cstring(binpkgd, "filename-sha256", sha256)) {
			free(sha256);
			free(pkgver);
			free(pkgname);
			rv = EINVAL;
			goto out;
		}
		free(sha256);
		if (stat(pkg, &st) == -1) {
			free(pkgver);
			free(pkgname);
			rv = EINVAL;
			goto out;
		}
		if (!xbps_dictionary_set_uint64(binpkgd, "filename-size", (uint64_t)st.st_size)) {
			free(pkgver);
			free(pkgname);
			rv = EINVAL;
			goto out;
		}
		if (set_build_date(binpkgd, st.st_mtime) < 0) {
			free(pkgver);
			free(pkgname);
			rv = EINVAL;
			goto out;
		}
		/* Remove unneeded objects */
		xbps_dictionary_remove(binpkgd, "pkgname");
		xbps_dictionary_remove(binpkgd, "version");
		xbps_dictionary_remove(binpkgd, "packaged-with");

		/*
		 * Add new pkg dictionary into the index.
		 */
		if (!xbps_dictionary_set(idxstage, pkgname, binpkgd)) {
			free(pkgname);
			free(pkgver);
			rv = EINVAL;
			goto out;
		}
		printf("index: added `%s' (%s).\n", pkgver, arch);
		xbps_object_release(binpkgd);
		free(pkgname);
		free(pkgver);
	}
	/*
	 * Generate repository data files.
	 */
	if (!repodata_commit(xhp, repodir, idx, idxmeta, idxstage)) {
		fprintf(stderr, "%s: failed to write repodata: %s\n",
				_XBPS_RINDEX, strerror(errno));
		goto out;
	}
	printf("index: %u packages registered.\n", xbps_dictionary_count(idx));

out:
	if (repo)
		xbps_repo_close(repo);

	xbps_repo_unlock(rlockfd, rlockfname);

	if (tmprepodir)
		free(tmprepodir);

	return rv;
}
Example #13
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;
}
Example #14
0
int
sign_repo(struct xbps_handle *xhp, const char *repodir,
	const char *privkey, const char *signedby)
{
	struct stat st;
	struct xbps_repo *repo;
	xbps_dictionary_t pkgd, meta = NULL;
	xbps_data_t data = NULL, rpubkey = NULL;
	xbps_object_iterator_t iter = NULL;
	xbps_object_t obj;
	RSA *rsa = NULL;
	unsigned char *sig;
	unsigned int siglen;
	uint16_t rpubkeysize, pubkeysize;
	const char *arch, *pkgver, *rsignedby = NULL;
	char *binpkg = NULL, *binpkg_sig = NULL, *buf = NULL, *defprivkey = NULL;
	int binpkg_fd, binpkg_sig_fd, rv = 0;
	bool flush = false;

	if (signedby == NULL) {
		fprintf(stderr, "--signedby unset! cannot sign repository\n");
		return -1;
	}

	/*
	 * Check that repository index exists and not empty, otherwise bail out.
	 */
	repo = xbps_repo_open(xhp, repodir, true);
	if (repo == NULL) {
		rv = errno;
		fprintf(stderr, "%s: cannot read repository data: %s\n",
		    _XBPS_RINDEX, strerror(errno));
		goto out;
	}
	if (xbps_dictionary_count(repo->idx) == 0) {
		fprintf(stderr, "%s: invalid repository, existing!\n", _XBPS_RINDEX);
		rv = EINVAL;
		goto out;
	}
	/*
	 * If privkey not set, default to ~/.ssh/id_rsa.
	 */
	if (privkey == NULL)
		defprivkey = xbps_xasprintf("%s/.ssh/id_rsa", getenv("HOME"));
	else
		defprivkey = strdup(privkey);

	ERR_load_crypto_strings();
	OpenSSL_add_all_algorithms();
	OpenSSL_add_all_ciphers();
	OpenSSL_add_all_digests();

	if ((rsa = load_rsa_privkey(defprivkey)) == NULL) {
		fprintf(stderr, "%s: failed to read the RSA privkey\n", _XBPS_RINDEX);
		rv = EINVAL;
		goto out;
	}
	/*
	 * Iterate over the idx dictionary and then sign all binary
	 * packages in this repository.
	 */
	iter = xbps_dictionary_iterator(repo->idx);
	assert(iter);

	while ((obj = xbps_object_iterator_next(iter))) {
		pkgd = xbps_dictionary_get_keysym(repo->idx, obj);
		xbps_dictionary_get_cstring_nocopy(pkgd, "architecture", &arch);
		xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver);

		binpkg = xbps_xasprintf("%s/%s.%s.xbps", repodir, pkgver, arch);
		binpkg_sig = xbps_xasprintf("%s.sig", binpkg);
		/*
		 * Skip pkg if file signature exists
		 */
		if ((binpkg_sig_fd = access(binpkg_sig, R_OK)) == 0) {
			if (xhp->flags & XBPS_FLAG_VERBOSE)
				fprintf(stderr, "skipping %s, file signature found.\n", pkgver);
			free(binpkg);
			free(binpkg_sig);
			close(binpkg_sig_fd);
			continue;
		}
		/*
		 * Generate pkg file signature.
		 */
		if ((binpkg_fd = open(binpkg, O_RDONLY)) == -1) {
			fprintf(stderr, "cannot read %s: %s\n", binpkg, strerror(errno));
			free(binpkg);
			free(binpkg_sig);
			continue;
		}
		fstat(binpkg_fd, &st);
		buf = malloc(st.st_size);
		assert(buf);
		if (read(binpkg_fd, buf, st.st_size) != st.st_size) {
			fprintf(stderr, "failed to read %s: %s\n", binpkg, strerror(errno));
			close(binpkg_fd);
			free(buf);
			free(binpkg);
			free(binpkg_sig);
			continue;
		}
		close(binpkg_fd);
		if (!rsa_sign_buf(rsa, buf, st.st_size, &sig, &siglen)) {
			fprintf(stderr, "failed to sign %s: %s\n", binpkg, strerror(errno));
			free(buf);
			free(binpkg);
			free(binpkg_sig);
			continue;
		}
		free(buf);
		free(binpkg);
		/*
		 * Write pkg file signature.
		 */
		binpkg_sig_fd = creat(binpkg_sig, 0644);
		if (binpkg_sig_fd == -1) {
			fprintf(stderr, "failed to create %s: %s\n", binpkg_sig, strerror(errno));
			free(sig);
			free(binpkg_sig);
			continue;
		}
		if (write(binpkg_sig_fd, sig, siglen) != (ssize_t)siglen) {
			fprintf(stderr, "failed to write %s: %s\n", binpkg_sig, strerror(errno));
			free(sig);
			free(binpkg_sig);
			close(binpkg_sig_fd);
			continue;
		}
		free(sig);
		free(binpkg_sig);
		close(binpkg_sig_fd);
		printf("signed successfully %s\n", pkgver);
	}
	xbps_object_iterator_release(iter);
	/*
	 * Check if repository index-meta contains changes compared to its
	 * current state.
	 */
	if ((buf = pubkey_from_privkey(rsa)) == NULL) {
		rv = EINVAL;
		goto out;
	}
	meta = xbps_dictionary_create();

	data = xbps_data_create_data(buf, strlen(buf));
	rpubkey = xbps_dictionary_get(repo->idxmeta, "public-key");
	if (!xbps_data_equals(rpubkey, data))
		flush = true;

	free(buf);

	pubkeysize = RSA_size(rsa) * 8;
	xbps_dictionary_get_uint16(repo->idxmeta, "public-key-size", &rpubkeysize);
	if (rpubkeysize != pubkeysize)
		flush = true;

	xbps_dictionary_get_cstring_nocopy(repo->idxmeta, "signature-by", &rsignedby);
	if (rsignedby == NULL || strcmp(rsignedby, signedby))
		flush = true;

	if (!flush)
		goto out;

	xbps_dictionary_set(meta, "public-key", data);
	xbps_dictionary_set_uint16(meta, "public-key-size", pubkeysize);
	xbps_dictionary_set_cstring_nocopy(meta, "signature-by", signedby);
	xbps_dictionary_set_cstring_nocopy(meta, "signature-type", "rsa");
	xbps_object_release(data);
	data = NULL;

	if (!repodata_flush(xhp, repodir, repo->idx, meta)) {
		fprintf(stderr, "failed to write repodata: %s\n", strerror(errno));
		goto out;
	}
	printf("Signed repository (%u package%s)\n",
	    xbps_dictionary_count(repo->idx),
	    xbps_dictionary_count(repo->idx) == 1 ? "" : "s");

out:
	if (defprivkey) {
		free(defprivkey);
	}
	if (rsa) {
		RSA_free(rsa);
		rsa = NULL;
	}
	if (repo) {
		xbps_repo_close(repo);
	}
	return rv ? -1 : 0;
}
Example #15
0
File: sign.c Project: uggedal/xbps
int
sign_repo(struct xbps_handle *xhp, const char *repodir,
	const char *privkey, const char *signedby)
{
	struct xbps_repo *repo = NULL;
	xbps_dictionary_t meta = NULL;
	xbps_data_t data = NULL, rpubkey = NULL;
	RSA *rsa = NULL;
	uint16_t rpubkeysize, pubkeysize;
	const char *rsignedby = NULL;
	char *buf = NULL, *rlockfname = NULL;
	int rlockfd = -1, rv = 0;
	bool flush_failed = false, flush = false;

	if (signedby == NULL) {
		fprintf(stderr, "--signedby unset! cannot initialize signed repository\n");
		return -1;
	}

	/*
	 * Check that repository index exists and not empty, otherwise bail out.
	 */
	repo = xbps_repo_open(xhp, repodir);
	if (repo == NULL) {
		rv = errno;
		fprintf(stderr, "%s: cannot read repository data: %s\n",
		    _XBPS_RINDEX, strerror(errno));
		goto out;
	}
	if (xbps_dictionary_count(repo->idx) == 0) {
		fprintf(stderr, "%s: invalid repository, existing!\n", _XBPS_RINDEX);
		rv = EINVAL;
		goto out;
	}

	rsa = load_rsa_key(privkey);
	/*
	 * Check if repository index-meta contains changes compared to its
	 * current state.
	 */
	if ((buf = pubkey_from_privkey(rsa)) == NULL) {
		rv = EINVAL;
		goto out;
	}
	meta = xbps_dictionary_create();

	data = xbps_data_create_data(buf, strlen(buf));
	rpubkey = xbps_dictionary_get(repo->idxmeta, "public-key");
	if (!xbps_data_equals(rpubkey, data))
		flush = true;

	free(buf);

	pubkeysize = RSA_size(rsa) * 8;
	xbps_dictionary_get_uint16(repo->idxmeta, "public-key-size", &rpubkeysize);
	if (rpubkeysize != pubkeysize)
		flush = true;

	xbps_dictionary_get_cstring_nocopy(repo->idxmeta, "signature-by", &rsignedby);
	if (rsignedby == NULL || strcmp(rsignedby, signedby))
		flush = true;

	if (!flush)
		goto out;

	xbps_dictionary_set(meta, "public-key", data);
	xbps_dictionary_set_uint16(meta, "public-key-size", pubkeysize);
	xbps_dictionary_set_cstring_nocopy(meta, "signature-by", signedby);
	xbps_dictionary_set_cstring_nocopy(meta, "signature-type", "rsa");
	xbps_object_release(data);
	data = NULL;

	/* lock repository to write repodata file */
	if (!xbps_repo_lock(xhp, repodir, &rlockfd, &rlockfname)) {
		rv = errno;
		fprintf(stderr, "%s: cannot lock repository: %s\n",
		    _XBPS_RINDEX, strerror(errno));
		goto out;
	}
	flush_failed = repodata_flush(xhp, repodir, repo->idx, meta);
	xbps_repo_unlock(rlockfd, rlockfname);
	if (!flush_failed) {
		fprintf(stderr, "failed to write repodata: %s\n", strerror(errno));
		goto out;
	}
	printf("Initialized signed repository (%u package%s)\n",
	    xbps_dictionary_count(repo->idx),
	    xbps_dictionary_count(repo->idx) == 1 ? "" : "s");

out:
	if (rsa) {
		RSA_free(rsa);
		rsa = NULL;
	}
	if (repo)
		xbps_repo_close(repo);

	return rv ? -1 : 0;
}
Example #16
0
int
xbps_repo_key_import(struct xbps_repo *repo)
{
	xbps_dictionary_t repokeyd = NULL;
	xbps_data_t pubkey = NULL;
	uint16_t pubkey_size = 0;
	const char *signedby = NULL;
	char *hexfp = NULL;
	char *p, *dbkeyd, *rkeyfile = NULL;
	int import, rv = 0;

	assert(repo);
	/*
	 * If repository does not have required metadata plist, ignore it.
	 */
	if (!xbps_dictionary_count(repo->idxmeta)) {
		xbps_dbg_printf(repo->xhp,
		    "[repo] `%s' unsigned repository!\n", repo->uri);
		return 0;
	}
	/*
	 * Check for required objects in index-meta:
	 * 	- signature-by (string)
	 * 	- public-key (data)
	 * 	- public-key-size (number)
	 */
	xbps_dictionary_get_cstring_nocopy(repo->idxmeta, "signature-by", &signedby);
	xbps_dictionary_get_uint16(repo->idxmeta, "public-key-size", &pubkey_size);
	pubkey = xbps_dictionary_get(repo->idxmeta, "public-key");

	if (signedby == NULL || pubkey_size == 0 ||
	    xbps_object_type(pubkey) != XBPS_TYPE_DATA) {
		xbps_dbg_printf(repo->xhp,
		    "[repo] `%s': incomplete signed repository "
		    "(missing objs)\n", repo->uri);
		rv = EINVAL;
		goto out;
	}
	hexfp = xbps_pubkey2fp(repo->xhp, pubkey);
	/*
	 * Check if the public key is alredy stored.
	 */
	rkeyfile = xbps_xasprintf("%s/keys/%s.plist", repo->xhp->metadir, hexfp);
	repokeyd = xbps_plist_dictionary_from_file(repo->xhp, rkeyfile);
	if (xbps_object_type(repokeyd) == XBPS_TYPE_DICTIONARY) {
		xbps_dbg_printf(repo->xhp,
		    "[repo] `%s' public key already stored.\n", repo->uri);
		goto out;
	}
	/*
	 * Notify the client and take appropiate action to import
	 * the repository public key. Pass back the public key openssh fingerprint
	 * to the client.
	 */
	import = xbps_set_cb_state(repo->xhp, XBPS_STATE_REPO_KEY_IMPORT, 0,
			hexfp, "`%s' repository has been RSA signed by \"%s\"",
			repo->uri, signedby);
	if (import <= 0) {
		rv = EAGAIN;
		goto out;
	}

	p = strdup(rkeyfile);
	dbkeyd = dirname(p);
	assert(dbkeyd);
	if (access(dbkeyd, R_OK|W_OK) == -1) {
		rv = errno;
		if (rv == ENOENT)
			rv = xbps_mkpath(dbkeyd, 0755);
		if (rv != 0) {
			rv = errno;
			xbps_dbg_printf(repo->xhp,
			    "[repo] `%s' cannot create %s: %s\n",
			    repo->uri, dbkeyd, strerror(errno));
			free(p);
			goto out;
		}
	}
	free(p);

	repokeyd = xbps_dictionary_create();
	xbps_dictionary_set(repokeyd, "public-key", pubkey);
	xbps_dictionary_set_uint16(repokeyd, "public-key-size", pubkey_size);
	xbps_dictionary_set_cstring_nocopy(repokeyd, "signature-by", signedby);

	if (!xbps_dictionary_externalize_to_file(repokeyd, rkeyfile)) {
		rv = errno;
		xbps_dbg_printf(repo->xhp,
		    "[repo] `%s' failed to externalize %s: %s\n",
		    repo->uri, rkeyfile, strerror(rv));
	}

out:
	if (hexfp)
		free(hexfp);
	if (repokeyd)
		xbps_object_release(repokeyd);
	if (rkeyfile)
		free(rkeyfile);
	return rv;
}
Example #17
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;
}