コード例 #1
0
ファイル: util.c プロジェクト: bougyman/xbps
char *
xbps_repository_pkg_path(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod)
{
	const char *pkgver, *arch, *repoloc;
	char *lbinpkg = NULL;

	assert(xhp);
	assert(xbps_object_type(pkg_repod) == XBPS_TYPE_DICTIONARY);

	if (!xbps_dictionary_get_cstring_nocopy(pkg_repod,
	    "pkgver", &pkgver))
		return NULL;
	if (!xbps_dictionary_get_cstring_nocopy(pkg_repod,
	    "architecture", &arch))
		return NULL;
	if (!xbps_dictionary_get_cstring_nocopy(pkg_repod,
	    "repository", &repoloc))
		return NULL;

	if (xbps_repository_is_remote(repoloc)) {
		/*
		 * First check if binpkg is available in cachedir.
		 */
		lbinpkg = xbps_xasprintf("%s/%s.%s.xbps", xhp->cachedir,
				pkgver, arch);
		if (access(lbinpkg, R_OK) == 0)
			return lbinpkg;

		free(lbinpkg);
	}
	/*
	 * Local and remote repositories use the same path.
	 */
	return xbps_xasprintf("%s/%s.%s.xbps", repoloc, pkgver, arch);
}
コード例 #2
0
ファイル: repo_sync.c プロジェクト: bougyman/xbps
char HIDDEN *
xbps_get_remote_repo_string(const char *uri)
{
	struct url *url;
	size_t i;
	char *p;

	if ((url = fetchParseURL(uri)) == NULL)
		return NULL;

	/*
	 * Replace '.' ':' and '/' characters with underscores, so that
	 * provided URL:
	 *
	 * 	http://nocturno.local:8080/repo/x86_64
	 *
	 * becomes:
	 *
	 * 	http___nocturno_local_8080_repo_x86_64
	 */
	if (url->port != 0)
		p = xbps_xasprintf("%s://%s:%u%s", url->scheme,
		    url->host, url->port, url->doc);
	else
		p = xbps_xasprintf("%s://%s%s", url->scheme,
		    url->host, url->doc);

	fetchFreeURL(url);
	for (i = 0; i < strlen(p); i++) {
		if (p[i] == '.' || p[i] == '/' || p[i] == ':')
			p[i] = '_';
	}

	return p;
}
コード例 #3
0
static int
remove_symlinks(struct xbps_handle *xhp, xbps_array_t a, const char *grname)
{
	unsigned int i, cnt;

	cnt = xbps_array_count(a);
	for (i = 0; i < cnt; i++) {
		xbps_string_t str;
		char *l, *lnk;

		str = xbps_array_get(a, i);
		l = left(xbps_string_cstring_nocopy(str));
		assert(l);
		if (l[0] != '/') {
			const char *tgt;
			char *tgt_dup, *tgt_dir;
			tgt = right(xbps_string_cstring_nocopy(str));
			tgt_dup = strdup(tgt);
			assert(tgt_dup);
			tgt_dir = dirname(tgt_dup);
			lnk = xbps_xasprintf("%s%s/%s", xhp->rootdir, tgt_dir, l);
			free(tgt_dup);
		} else {
			lnk = xbps_xasprintf("%s%s", xhp->rootdir, l);
		}
		xbps_set_cb_state(xhp, XBPS_STATE_ALTGROUP_LINK_REMOVED, 0, NULL,
		    "Removing '%s' alternatives group symlink: %s", grname, l);
		unlink(lnk);
		free(lnk);
		free(l);
	}

	return 0;
}
コード例 #4
0
ファイル: initend.c プロジェクト: xdave/xbps
static char *
set_metadir(struct xbps_handle *xh)
{
    if (xh->metadir == NULL) {
        if (strcmp(xh->rootdir, "/") == 0)
            return xbps_xasprintf("/%s", XBPS_META_PATH);
        else
            return xbps_xasprintf("%s/%s", xh->rootdir, XBPS_META_PATH);
    } else {
        return strdup(xh->metadir);
    }
}
コード例 #5
0
ファイル: initend.c プロジェクト: xdave/xbps
/**
 * @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 char *
set_cachedir(struct xbps_handle *xh)
{
    if (xh->cachedir[0] == '/') {
        /* full path */
        return strdup(xh->cachedir);
    } else {
        /* relative to rootdir */
        if (strcmp(xh->rootdir, "/") == 0)
            return xbps_xasprintf("/%s", xh->cachedir);
        else
            return xbps_xasprintf("%s/%s", xh->rootdir,
                                  xh->cachedir);
    }
}
コード例 #6
0
ファイル: package_conflicts.c プロジェクト: xdave/xbps
void HIDDEN
xbps_pkg_find_conflicts(struct xbps_handle *xhp, prop_dictionary_t pkg_repod)
{
	prop_array_t pkg_cflicts, trans_cflicts;
	prop_dictionary_t pkgd;
	const char *cfpkg, *repopkgver, *pkgver;
	char *buf;
	size_t i;

	pkg_cflicts = prop_dictionary_get(pkg_repod, "conflicts");
	if (pkg_cflicts == NULL || prop_array_count(pkg_cflicts) == 0)
		return;

	trans_cflicts = prop_dictionary_get(xhp->transd, "conflicts");
	prop_dictionary_get_cstring_nocopy(pkg_repod, "pkgver", &repopkgver);

	for (i = 0; i < prop_array_count(pkg_cflicts); i++) {
		prop_array_get_cstring_nocopy(pkg_cflicts, i, &cfpkg);
		/*
		 * Check if current pkg conflicts with an installed package.
		 */
		if ((pkgd = xbps_pkgdb_get_pkgd(xhp, cfpkg, true))) {
			prop_dictionary_get_cstring_nocopy(pkgd,
			    "pkgver", &pkgver);
			buf = xbps_xasprintf("%s conflicts with "
			    "installed pkg %s", repopkgver, pkgver);
			assert(buf != NULL);
			prop_array_add_cstring(trans_cflicts, buf);
			free(buf);
			continue;
		}
		/*
		 * Check if current pkg conflicts with any pkg in transaction.
		 */
		pkgd = xbps_find_pkg_in_dict_by_pattern(xhp, xhp->transd,
		    "unsorted_deps", cfpkg);
		if (pkgd != NULL) {
			prop_dictionary_get_cstring_nocopy(pkgd,
			    "pkgver", &pkgver);
			buf = xbps_xasprintf("%s conflicts with "
			   "%s in transaction", repopkgver, pkgver);
			assert(buf != NULL);
			prop_array_add_cstring(trans_cflicts, buf);
			free(buf);
			continue;
		}
	}
}
コード例 #7
0
int HIDDEN
xbps_pkgdb_init(struct xbps_handle *xhp)
{
	int rv;

	assert(xhp != NULL);

	if (xhp->pkgdb_plist == NULL)
		xhp->pkgdb_plist = xbps_xasprintf("%s/%s", xhp->metadir, XBPS_PKGDB);

#if 0
	if ((rv = xbps_pkgdb_conversion(xhp)) != 0)
		return rv;
#endif

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

	if ((rv = xbps_pkgdb_update(xhp, false, true)) != 0) {
		if (rv != ENOENT)
			xbps_dbg_printf(xhp, "[pkgdb] cannot internalize "
			    "pkgdb array: %s\n", strerror(rv));

		return rv;
	}
	if ((rv = pkgdb_map_vpkgs(xhp)) != 0) {
		xbps_dbg_printf(xhp, "[pkgdb] pkgdb_map_vpkgs %s\n", strerror(rv));
		return rv;
	}
	assert(xhp->pkgdb);
	xbps_dbg_printf(xhp, "[pkgdb] initialized ok.\n");

	return 0;
}
コード例 #8
0
xbps_dictionary_t
xbps_pkgdb_get_pkg_files(struct xbps_handle *xhp, const char *pkg)
{
	xbps_dictionary_t pkgd, pkgfilesd;
	const char *pkgver;
	char *pkgname, *plist;

	if (pkg == NULL)
		return NULL;

	pkgd = xbps_pkgdb_get_pkg(xhp, pkg);
	if (pkgd == NULL)
		return NULL;

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

	plist = xbps_xasprintf("%s/.%s-files.plist", xhp->metadir, pkgname);
	free(pkgname);
	pkgfilesd = xbps_plist_dictionary_from_file(xhp, plist);
	free(plist);

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

	return pkgfilesd;
}
コード例 #9
0
ファイル: pkgdb.c プロジェクト: prodigeni/xbps
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;
}
コード例 #10
0
ファイル: sign.c プロジェクト: uggedal/xbps
static RSA *
load_rsa_key(const char *privkey)
{
	RSA *rsa = NULL;
	char *defprivkey;

	/*
	 * 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);
		exit(EXIT_FAILURE);
	}

	return rsa;
}
コード例 #11
0
ファイル: repo.c プロジェクト: niamtokik/xbps
/**
 * @file lib/repo.c
 * @brief Repository functions
 * @defgroup repo Repository functions
 */
char *
xbps_repo_path(struct xbps_handle *xhp, const char *url)
{
	assert(xhp);
	assert(url);

	return xbps_xasprintf("%s/%s-repodata",
	    url, xhp->target_arch ? xhp->target_arch : xhp->native_arch);
}
コード例 #12
0
ファイル: transaction_revdeps.c プロジェクト: DirectorX/xbps
static void
broken_pkg(xbps_array_t mdeps, const char *dep, const char *pkg, const char *trans)
{
	char *str;

	str = xbps_xasprintf("%s (%s) breaks installed pkg `%s'", pkg, trans, dep);
	xbps_array_add_cstring(mdeps, str);
	free(str);
}
コード例 #13
0
ファイル: repoflush.c プロジェクト: prodigeni/xbps
int
repodata_flush(struct xbps_handle *xhp, const char *repodir,
	xbps_dictionary_t idx, xbps_dictionary_t idxfiles)
{
	struct archive *ar;
	mode_t myumask;
	char *repofile, *tname, *xml;
	int repofd;

	/* Create a tempfile for our repository archive */
	repofile = xbps_repo_path(xhp, repodir);
	tname = xbps_xasprintf("%s.XXXXXXXXXX", repofile);
	if ((repofd = mkstemp(tname)) == -1)
		return errno;

	/* Create and write our repository archive */
	ar = archive_write_new();
	assert(ar);
	archive_write_set_compression_gzip(ar);
	archive_write_set_format_pax_restricted(ar);
	archive_write_set_options(ar, "compression-level=9");
	archive_write_open_fd(ar, repofd);

	xml = xbps_dictionary_externalize(idx);
	assert(xml);
	if (xbps_archive_append_buf(ar, xml, strlen(xml),
	    XBPS_PKGINDEX, 0644, "root", "root") != 0) {
		free(xml);
		return -1;
	}
	free(xml);

	xml = xbps_dictionary_externalize(idxfiles);
	assert(xml);
	if (xbps_archive_append_buf(ar, xml, strlen(xml),
	    XBPS_PKGINDEX_FILES, 0644, "root", "root") != 0) {
		free(xml);
		return -1;
	}
	free(xml);

	archive_write_finish(ar);

	/* Write data to tempfile and rename */
	fdatasync(repofd);
	myumask = umask(0);
	(void)umask(myumask);
	assert(fchmod(repofd, 0666 & ~myumask) != -1);
	close(repofd);
	rename(tname, repofile);
	free(repofile);
	free(tname);

	return 0;
}
コード例 #14
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;
}
コード例 #15
0
ファイル: transaction_revdeps.c プロジェクト: DirectorX/xbps
/*
 * 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;
}
コード例 #16
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;
}
コード例 #17
0
ファイル: pkgdb.c プロジェクト: prodigeni/xbps
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;
}
コード例 #18
0
ファイル: transaction.c プロジェクト: uggedal/xbps
static void
show_package_list(struct transaction *trans, const char *match, int cols)
{
	xbps_object_t obj;

	while ((obj = xbps_object_iterator_next(trans->iter)) != NULL) {
		const char *pkgver, *tract;
		char *buf = NULL;
		bool dload = false;

		xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
		xbps_dictionary_get_cstring_nocopy(obj, "transaction", &tract);
		xbps_dictionary_get_bool(obj, "download", &dload);

		if (match && strcmp(tract, "update") == 0) {
			xbps_dictionary_t ipkgd;
			const char *ipkgver, *iversion, *version;
			char *pkgname;

			/* get installed pkgver */
			pkgname = xbps_pkg_name(pkgver);
			assert(pkgname);
			ipkgd = xbps_pkgdb_get_pkg(trans->xhp, pkgname);
			assert(ipkgd);
			xbps_dictionary_get_cstring_nocopy(ipkgd, "pkgver", &ipkgver);
			version = xbps_pkg_version(pkgver);
			iversion = xbps_pkg_version(ipkgver);
			buf = xbps_xasprintf("%s (%s -> %s)", pkgname, iversion, version);
			free(pkgname);
		}
		if ((match && (strcmp(match, tract) == 0)) || (!match && dload)) {
			if (buf) {
				print_package_line(buf, cols, false);
				free(buf);
			} else {
				print_package_line(pkgver, cols, false);
			}
		}
	}
	xbps_object_iterator_reset(trans->iter);
	print_package_line(NULL, cols, true);
}
コード例 #19
0
ファイル: initend.c プロジェクト: indianpoptart/xbps
static void
store_preserved_file(struct xbps_handle *xhp, const char *file)
{
	glob_t globbuf;
	char *p = NULL, *rfile = NULL;
	size_t len;
	int rv = 0;

	if (xhp->preserved_files == NULL) {
		xhp->preserved_files = xbps_array_create();
		assert(xhp->preserved_files);
	}

	rfile = xbps_xasprintf("%s%s", xhp->rootdir, file);

	rv = glob(rfile, 0, NULL, &globbuf);
	if (rv == GLOB_NOMATCH) {
		if (xbps_match_string_in_array(xhp->preserved_files, file))
			goto out;
		xbps_array_add_cstring(xhp->preserved_files, file);
		xbps_dbg_printf(xhp, "Added preserved file: %s\n", file);
		goto out;
	} else if (rv != 0) {
		goto out;
	}
	for (size_t i = 0; i < globbuf.gl_pathc; i++) {
		if (xbps_match_string_in_array(xhp->preserved_files, globbuf.gl_pathv[i]))
			continue;

		len = strlen(globbuf.gl_pathv[i]) - strlen(xhp->rootdir) + 1;
		p = malloc(len);
		assert(p);
		strlcpy(p, globbuf.gl_pathv[i] + strlen(xhp->rootdir), len);
		xbps_array_add_cstring(xhp->preserved_files, p);
		xbps_dbg_printf(xhp, "Added preserved file: %s (expanded from %s)\n", p, file);
		free(p);
	}
out:
	globfree(&globbuf);
	free(rfile);
}
コード例 #20
0
ファイル: sign.c プロジェクト: ebfe/xbps
static RSA *
load_rsa_key(const char *privkey)
{
	RSA *rsa = NULL;
	char *defprivkey;

	/*
	 * 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);

	if ((rsa = load_rsa_privkey(defprivkey)) == NULL) {
		fprintf(stderr, "%s: failed to read the RSA privkey\n", _XBPS_RINDEX);
		exit(EXIT_FAILURE);
	}
	free(defprivkey);
	defprivkey = NULL;

	return rsa;
}
コード例 #21
0
ファイル: repo.c プロジェクト: niamtokik/xbps
bool
xbps_repo_lock(struct xbps_handle *xhp, const char *repodir,
		int *lockfd, char **lockfname)
{
	char *repofile, *lockfile;
	int fd, rv;

	assert(repodir);
	assert(lockfd);
	assert(lockfname);

	repofile = xbps_repo_path(xhp, repodir);
	assert(repofile);

	lockfile = xbps_xasprintf("%s.lock", repofile);
	free(repofile);

	for (;;) {
		fd = open(lockfile, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0660);
		rv = errno;
		if (fd != -1)
			break;
		if (rv != EEXIST) {
			xbps_dbg_printf(xhp, "[repo] `%s' failed to "
			    "create lock file %s\n", lockfile, strerror(rv));
			free(lockfile);
			return false;
		} else {
			xbps_dbg_printf(xhp, "[repo] `%s' lock file exists,"
			    "waiting for 1s...\n", lockfile);
			sleep(1);
		}
	}
	*lockfname = lockfile;
	*lockfd = fd;
	return true;
}
コード例 #22
0
ファイル: verifysig.c プロジェクト: DirectorX/xbps
bool
xbps_verify_file_signature(struct xbps_repo *repo, const char *fname)
{
	xbps_dictionary_t repokeyd = NULL;
	xbps_data_t pubkey;
	char *hexfp = NULL;
	unsigned char *digest = NULL, *sig_buf = NULL;
	size_t sigbuflen, sigfilelen;
	char *rkeyfile = NULL, *sig = NULL;
	bool val = false;

	if (!xbps_dictionary_count(repo->idxmeta)) {
		xbps_dbg_printf(repo->xhp, "%s: unsigned repository\n", repo->uri);
		return false;
	}
	hexfp = xbps_pubkey2fp(repo->xhp,
	    xbps_dictionary_get(repo->idxmeta, "public-key"));
	if (hexfp == NULL) {
		xbps_dbg_printf(repo->xhp, "%s: incomplete signed repo, missing hexfp obj\n", repo->uri);
		return false;
	}
	/*
	 * Prepare repository RSA public key to verify fname signature.
	 */
	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, "cannot read rkey data at %s: %s\n",
		    rkeyfile, strerror(errno));
		goto out;
	}

	pubkey = xbps_dictionary_get(repokeyd, "public-key");
	if (xbps_object_type(pubkey) != XBPS_TYPE_DATA)
		goto out;

	/*
	 * Prepare fname and signature data buffers.
	 */
	if (!(digest = xbps_file_hash_raw(fname))) {
		xbps_dbg_printf(repo->xhp, "can't open file %s: %s\n", fname, strerror(errno));
		goto out;
	}
	sig = xbps_xasprintf("%s.sig", fname);
	if (!xbps_mmap_file(sig, (void *)&sig_buf, &sigbuflen, &sigfilelen)) {
		xbps_dbg_printf(repo->xhp, "can't open signature file %s: %s\n", sig, strerror(errno));
		goto out;
	}
	/*
	 * Verify fname RSA signature.
	 */
	if (rsa_verify_hash(repo, pubkey, sig_buf, sigfilelen, digest))
		val = true;

out:
	if (hexfp)
		free(hexfp);
	if (rkeyfile)
		free(rkeyfile);
	if (digest)
		free(digest);
	if (sig_buf)
		(void)munmap(sig_buf, sigbuflen);
	if (sig)
		free(sig);
	if (repokeyd)
		xbps_object_release(repokeyd);

	return val;
}
コード例 #23
0
ファイル: package_remove.c プロジェクト: prodigeni/xbps
int HIDDEN
xbps_remove_pkg_files(struct xbps_handle *xhp,
		      xbps_dictionary_t dict,
		      const char *key,
		      const char *pkgver)
{
	struct stat st;
	xbps_array_t array;
	xbps_object_iterator_t iter;
	xbps_object_t obj;
	const char *file, *sha256, *curobj = NULL;
	char *path = NULL, *pkgname = NULL;
	char buf[PATH_MAX];
	int rv = 0;

	assert(xbps_object_type(dict) == XBPS_TYPE_DICTIONARY);
	assert(key != NULL);

	array = xbps_dictionary_get(dict, key);
	if (xbps_array_count(array) == 0)
		return 0;

	iter = xbps_array_iter_from_dict(dict, key);
	if (iter == NULL)
		return ENOMEM;

	if (strcmp(key, "files") == 0)
		curobj = "file";
	else if (strcmp(key, "conf_files") == 0)
		curobj = "configuration file";
	else if (strcmp(key, "links") == 0)
		curobj = "link";
	else if (strcmp(key, "dirs") == 0)
		curobj = "directory";

	pkgname = xbps_pkg_name(pkgver);
	assert(pkgname);

	while ((obj = xbps_object_iterator_next(iter))) {
		xbps_dictionary_get_cstring_nocopy(obj, "file", &file);
		path = xbps_xasprintf("%s/%s", xhp->rootdir, file);

		if ((strcmp(key, "files") == 0) ||
		    (strcmp(key, "conf_files") == 0)) {
			/*
			 * Check SHA256 hash in regular files and
			 * configuration files.
			 */
			xbps_dictionary_get_cstring_nocopy(obj,
			    "sha256", &sha256);
			rv = xbps_file_hash_check(path, sha256);
			if (rv == ENOENT) {
				/* missing file, ignore it */
				xbps_set_cb_state(xhp,
				    XBPS_STATE_REMOVE_FILE_HASH_FAIL,
				    rv, pkgver,
				    "%s: failed to check hash for %s `%s': %s",
				    pkgver, curobj, file, strerror(rv));
				free(path);
				rv = 0;
				continue;
			} else if (rv == ERANGE) {
				rv = 0;
				if ((xhp->flags &
				    XBPS_FLAG_FORCE_REMOVE_FILES) == 0) {
					xbps_set_cb_state(xhp,
					    XBPS_STATE_REMOVE_FILE_HASH_FAIL,
					    0, pkgver,
					    "%s: %s `%s' SHA256 mismatch, "
					    "preserving file", pkgver,
					    curobj, file);
					free(path);
					continue;
				} else {
					xbps_set_cb_state(xhp,
					    XBPS_STATE_REMOVE_FILE_HASH_FAIL,
					    0, pkgver,
					    "%s: %s `%s' SHA256 mismatch, "
					    "forcing removal", pkgver,
					    curobj, file);
				}
			} else if (rv != 0 && rv != ERANGE) {
				xbps_set_cb_state(xhp,
				    XBPS_STATE_REMOVE_FILE_HASH_FAIL,
				    rv, pkgver,
				    "%s: [remove] failed to check hash for "
				    "%s `%s': %s", pkgver, curobj, file,
				    strerror(rv));
				free(path);
				break;
			}
		} else if (strcmp(key, "links") == 0) {
			/*
			 * All regular files from package were removed at this
			 * point, so we will only remove dangling symlinks.
			 */
			if (realpath(path, buf) == NULL) {
				if (errno != ENOENT && errno != ELOOP) {
					free(path);
					rv = errno;
					break;
				}
			}
			if (stat(buf, &st) == 0) {
				free(path);
				continue;
			}
		}
		/*
		 * Remove the object if possible.
		 */
		if (remove(path) == -1) {
			xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FILE_FAIL,
			    errno, pkgver,
			    "%s: failed to remove %s `%s': %s", pkgver,
			    curobj, file, strerror(errno));
			errno = 0;
		} else {
			/* success */
			xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FILE,
			    0, pkgver, "Removed %s `%s'", curobj, file);
		}
		free(path);
	}
	xbps_object_iterator_release(iter);
	free(pkgname);

	return rv;
}
コード例 #24
0
ファイル: package_remove.c プロジェクト: prodigeni/xbps
int HIDDEN
xbps_remove_pkg(struct xbps_handle *xhp,
		const char *pkgver,
		bool update,
		bool soft_replace)
{
	xbps_dictionary_t pkgd = NULL;
	char *pkgname, *buf = NULL;
	int rv = 0;
	pkg_state_t state = 0;

	assert(xhp);
	assert(pkgver);

	pkgname = xbps_pkg_name(pkgver);
	assert(pkgname);

	if ((rv = xbps_pkg_state_installed(xhp, pkgname, &state)) != 0)
		goto out;

	xbps_dbg_printf(xhp, "attempting to remove %s state %d\n",
	    pkgver, state);

	if (!update)
		xbps_set_cb_state(xhp, XBPS_STATE_REMOVE, 0, pkgver, NULL);

	if (chdir(xhp->rootdir) == -1) {
		rv = errno;
		xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FAIL,
		    rv, pkgver,
		   "%s: [remove] failed to chdir to rootdir `%s': %s",
		    pkgver, xhp->rootdir, strerror(rv));
		goto out;
	}

	/* internalize pkg dictionary from metadir */
	buf = xbps_xasprintf("%s/.%s.plist", xhp->metadir, pkgname);
	pkgd = xbps_dictionary_internalize_from_file(buf);
	free(buf);
	if (pkgd == NULL)
		xbps_dbg_printf(xhp, "WARNING: metaplist for %s "
		    "doesn't exist!\n", pkgver);

	/* If package was "half-removed", remove it fully. */
	if (state == XBPS_PKG_STATE_HALF_REMOVED)
		goto purge;
	/*
	 * Run the pre remove action.
	 */
	if (pkgd) {
		rv = xbps_pkg_exec_script(xhp, pkgd, "remove-script",
		    "pre", update);
		if (rv != 0) {
			xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FAIL,
			    errno, pkgver,
			    "%s: [remove] REMOVE script failed to "
			    "execute pre ACTION: %s",
			    pkgver, strerror(rv));
			goto out;
		}
	}
	/*
	 * If updating a package, we just need to execute the current
	 * pre-remove action target and we are done. Its files will be
	 * overwritten later in unpack phase.
	 */
	if (update) {
		if (pkgd)
			xbps_object_release(pkgd);
		free(pkgname);
		return 0;
	} else if (soft_replace) {
		/*
		 * Soft replace a package. Do not remove its files, but
		 * execute PURGE action, remove metadata files and unregister
		 * from pkgdb.
		 */
		goto softreplace;
	}

	if (pkgd) {
		/* Remove regular files */
		if ((rv = xbps_remove_pkg_files(xhp, pkgd, "files", pkgver)) != 0)
			goto out;
		/* Remove configuration files */
		if ((rv = xbps_remove_pkg_files(xhp, pkgd, "conf_files", pkgver)) != 0)
			goto out;
		/* Remove links */
		if ((rv = xbps_remove_pkg_files(xhp, pkgd, "links", pkgver)) != 0)
			goto out;
		/* Remove dirs */
		if ((rv = xbps_remove_pkg_files(xhp, pkgd, "dirs", pkgver)) != 0)
			goto out;
		/*
		 * Execute the post REMOVE action if file exists and we aren't
		 * updating the package.
		 */
		rv = xbps_pkg_exec_script(xhp, pkgd, "remove-script", "post", false);
		if (rv != 0) {
			xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FAIL,
			    rv, pkgver,
			    "%s: [remove] REMOVE script failed to execute "
			    "post ACTION: %s", pkgver, strerror(rv));
			goto out;
		}
	}

softreplace:
	/*
	 * Set package state to "half-removed".
	 */
	rv = xbps_set_pkg_state_installed(xhp, pkgver,
	     XBPS_PKG_STATE_HALF_REMOVED);
	if (rv != 0) {
		xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FAIL,
		    rv, pkgver,
		    "%s: [remove] failed to set state to half-removed: %s",
		    pkgver, strerror(rv));
		goto out;
	}

purge:
	/*
	 * Execute the purge REMOVE action if file exists.
	 */
	if (pkgd) {
		rv = xbps_pkg_exec_script(xhp, pkgd, "remove-script", "purge", false);
		if (rv != 0) {
			xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FAIL,
			    rv, pkgver,
			    "%s: REMOVE script failed to execute "
			    "purge ACTION: %s", pkgver, strerror(rv));
			goto out;
		}
		xbps_object_release(pkgd);
	}
	/*
	 * Remove package metadata plist.
	 */
	buf = xbps_xasprintf("%s/.%s.plist", xhp->metadir, pkgname);
	if (remove(buf) == -1) {
		if (errno != ENOENT) {
			xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FAIL,
			    rv, pkgver,
			    "%s: failed to remove metadata file: %s",
			    pkgver, strerror(errno));
		}
	}
	free(buf);
	/*
	 * Unregister package from pkgdb.
	 */
	xbps_dictionary_remove(xhp->pkgdb, pkgname);
	if ((rv = xbps_pkgdb_update(xhp, true)) != 0)
		goto out;

	xbps_dbg_printf(xhp, "[remove] unregister %s returned %d\n", pkgver, rv);

	xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_DONE, 0, pkgver, NULL);
out:
	if (pkgname != NULL)
		free(pkgname);

	return rv;
}
コード例 #25
0
ファイル: sign.c プロジェクト: chneukirchen/xbps
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;
}
コード例 #26
0
ファイル: package_config_files.c プロジェクト: prodigeni/xbps
/*
 * Returns 1 if entry should be installed, 0 if don't or -1 on error.
 */
int HIDDEN
xbps_entry_install_conf_file(struct xbps_handle *xhp,
			     xbps_dictionary_t filesd,
			     struct archive_entry *entry,
			     const char *entry_pname,
			     const char *pkgver,
			     const char *pkgname)
{
	xbps_dictionary_t forigd;
	xbps_object_t obj, obj2;
	xbps_object_iterator_t iter, iter2;
	const char *cffile, *sha256_new = NULL;
	char *buf, *sha256_cur = NULL, *sha256_orig = NULL;
	int rv = 0;

	assert(xbps_object_type(filesd) == XBPS_TYPE_DICTIONARY);
	assert(entry != NULL);
	assert(entry_pname != NULL);
	assert(pkgver != NULL);

	iter = xbps_array_iter_from_dict(filesd, "conf_files");
	if (iter == NULL)
		return -1;

	/*
	 * Get original hash for the file from current
	 * installed package.
	 */
	xbps_dbg_printf(xhp, "%s: processing conf_file %s\n",
	    pkgver, entry_pname);

	forigd = xbps_pkgdb_get_pkg_metadata(xhp, pkgname);
	if (forigd == NULL) {
		xbps_dbg_printf(xhp, "%s: conf_file %s not currently "
		    "installed\n", pkgver, entry_pname);
		rv = 1;
		goto out;
	}

	iter2 = xbps_array_iter_from_dict(forigd, "conf_files");
	if (iter2 != NULL) {
		while ((obj2 = xbps_object_iterator_next(iter2))) {
			xbps_dictionary_get_cstring_nocopy(obj2,
			    "file", &cffile);
			buf = xbps_xasprintf(".%s", cffile);
			if (strcmp(entry_pname, buf) == 0) {
				xbps_dictionary_get_cstring(obj2, "sha256",
				    &sha256_orig);
				free(buf);
				break;
			}
			free(buf);
			buf = NULL;
		}
		xbps_object_iterator_release(iter2);
	}
	/*
	 * First case: original hash not found, install new file.
	 */
	if (sha256_orig == NULL) {
		xbps_dbg_printf(xhp, "%s: conf_file %s not installed\n",
		    pkgver, entry_pname);
		rv = 1;
		goto out;
	}

	/*
	 * Compare original, installed and new hash for current file.
	 */
	while ((obj = xbps_object_iterator_next(iter))) {
		xbps_dictionary_get_cstring_nocopy(obj, "file", &cffile);
		buf = xbps_xasprintf(".%s", cffile);
		if (strcmp(entry_pname, buf)) {
			free(buf);
			buf = NULL;
			continue;
		}
		sha256_cur = xbps_file_hash(buf);
		free(buf);
		xbps_dictionary_get_cstring_nocopy(obj, "sha256", &sha256_new);
		if (sha256_cur == NULL) {
			if (errno == ENOENT) {
				/*
				 * File not installed, install new one.
				 */
				xbps_dbg_printf(xhp, "%s: conf_file %s not "
				    "installed\n", pkgver, entry_pname);
				rv = 1;
				break;
			} else {
				rv = -1;
				break;
			}
		}
		/*
		 * Orig = X, Curr = X, New = X
		 *
		 * Keep file as is (no changes).
		 */
		if ((strcmp(sha256_orig, sha256_cur) == 0) &&
		    (strcmp(sha256_orig, sha256_new) == 0) &&
		    (strcmp(sha256_cur, sha256_new) == 0)) {
			xbps_dbg_printf(xhp, "%s: conf_file %s orig = X, "
			    "cur = X, new = X\n", pkgver, entry_pname);
			rv = 0;
			break;
		/*
		 * Orig = X, Curr = X, New = Y
		 *
		 * Install new file (installed file hasn't been modified).
		 */
		} else if ((strcmp(sha256_orig, sha256_cur) == 0) &&
			   (strcmp(sha256_orig, sha256_new)) &&
			   (strcmp(sha256_cur, sha256_new))) {
			xbps_set_cb_state(xhp, XBPS_STATE_CONFIG_FILE,
			    0, pkgver,
			    "Updating configuration file `%s' provided "
			    "by `%s'.", cffile, pkgver);
			rv = 1;
			break;
		/*
		 * Orig = X, Curr = Y, New = X
		 *
		 * Keep installed file as is because it has been modified,
		 * but new package doesn't contain new changes compared
		 * to the original version.
		 */
		} else if ((strcmp(sha256_orig, sha256_new) == 0) &&
			   (strcmp(sha256_cur, sha256_new)) &&
			   (strcmp(sha256_orig, sha256_cur))) {
			xbps_set_cb_state(xhp, XBPS_STATE_CONFIG_FILE,
			    0, pkgver,
			    "Keeping modified configuration file `%s'.",
			    cffile);
			rv = 0;
			break;
		/*
		 * Orig = X, Curr = Y, New = Y
		 *
		 * Keep file as is because changes made are compatible
		 * with new version.
		 */
		} else if ((strcmp(sha256_cur, sha256_new) == 0) &&
			   (strcmp(sha256_orig, sha256_new)) &&
			   (strcmp(sha256_orig, sha256_cur))) {
			xbps_dbg_printf(xhp, "%s: conf_file %s orig = X, "
			    "cur = Y, new = Y\n", pkgver, entry_pname);
			rv = 0;
			break;
		/*
		 * Orig = X, Curr = Y, New = Z
		 *
		 * Install new file as <file>.new-<version>
		 */
		} else  if ((strcmp(sha256_orig, sha256_cur)) &&
			    (strcmp(sha256_cur, sha256_new)) &&
			    (strcmp(sha256_orig, sha256_new))) {
			const char *version;

			version = xbps_pkg_version(pkgver);
			assert(version);
			buf = xbps_xasprintf(".%s.new-%s",
			    cffile, version);
			xbps_set_cb_state(xhp, XBPS_STATE_CONFIG_FILE,
			    0, pkgver,
			    "Installing new configuration file to "
			    "`%s.new-%s'.", cffile, version);
			archive_entry_set_pathname(entry, buf);
			free(buf);
			rv = 1;
			break;
		}
	}

out:
	if (sha256_orig)
		free(sha256_orig);
	if (sha256_cur)
		free(sha256_cur);

	xbps_object_iterator_release(iter);

	xbps_dbg_printf(xhp, "%s: conf_file %s returned %d\n",
	    pkgver, entry_pname, rv);

	return rv;
}
コード例 #27
0
ファイル: transaction_revdeps.c プロジェクト: prodigeni/xbps
/*
 * 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;
}
コード例 #28
0
ファイル: transaction_revdeps.c プロジェクト: prodigeni/xbps
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);
		}

	}
}
コード例 #29
0
ファイル: repo_sync.c プロジェクト: bougyman/xbps
/*
 * Returns -1 on error, 0 if transfer was not necessary (local/remote
 * size and/or mtime match) and 1 if downloaded successfully.
 */
int HIDDEN
xbps_repo_sync(struct xbps_handle *xhp, const char *uri)
{
	const char *arch, *fetchstr = NULL;
	char *repodata, *lrepodir, *uri_fixedp;
	int rv = 0;

	assert(uri != NULL);

	/* ignore non remote repositories */
	if (!xbps_repository_is_remote(uri))
		return 0;

	uri_fixedp = xbps_get_remote_repo_string(uri);
	if (uri_fixedp == NULL)
		return -1;

	if (xhp->target_arch)
		arch = xhp->target_arch;
	else
		arch = xhp->native_arch;

	/*
	 * Full path to repository directory to store the plist
	 * index file.
	 */
	lrepodir = xbps_xasprintf("%s/%s", xhp->metadir, uri_fixedp);
	free(uri_fixedp);
	/*
	 * Create repodir in metadir.
	 */
	if ((rv = xbps_mkpath(lrepodir, 0755)) == -1) {
		if (errno != EEXIST) {
			xbps_set_cb_state(xhp, XBPS_STATE_REPOSYNC_FAIL,
			    errno, NULL, "[reposync] failed "
			    "to create repodir `%s': %s", lrepodir,
			strerror(errno));
			free(lrepodir);
			return rv;
		}
	}
	if (chdir(lrepodir) == -1) {
		xbps_set_cb_state(xhp, XBPS_STATE_REPOSYNC_FAIL, errno, NULL,
		    "[reposync] failed to change dir to repodir `%s': %s",
		    lrepodir, strerror(errno));
		free(lrepodir);
		return -1;
	}
	free(lrepodir);
	/*
	 * Remote repository plist index full URL.
	 */
	repodata = xbps_xasprintf("%s/%s-repodata", uri, arch);

	/* reposync start cb */
	xbps_set_cb_state(xhp, XBPS_STATE_REPOSYNC, 0, repodata, NULL);
	/*
	 * Download plist index file from repository.
	 */
	if ((rv = xbps_fetch_file(xhp, repodata, NULL)) == -1) {
		/* reposync error cb */
		fetchstr = xbps_fetch_error_string();
		xbps_set_cb_state(xhp, XBPS_STATE_REPOSYNC_FAIL,
		    fetchLastErrCode != 0 ? fetchLastErrCode : errno, NULL,
		    "[reposync] failed to fetch file `%s': %s",
		    repodata, fetchstr ? fetchstr : strerror(errno));
	} else if (rv == 1)
		rv = 0;

	free(repodata);

	return rv;
}
コード例 #30
0
ファイル: sign.c プロジェクト: uggedal/xbps
static int
sign_pkg(struct xbps_handle *xhp, const char *binpkg, const char *privkey, bool force)
{
	RSA *rsa = NULL;
	struct stat st;
	unsigned char *sig = NULL;
	unsigned int siglen = 0;
	char *buf = NULL, *sigfile = NULL;
	int rv = 0, sigfile_fd = -1, binpkg_fd = -1;

	sigfile = xbps_xasprintf("%s.sig", binpkg);
	/*
	 * Skip pkg if file signature exists
	 */
	if (!force && ((sigfile_fd = access(sigfile, R_OK)) == 0)) {
		if (xhp->flags & XBPS_FLAG_VERBOSE)
			fprintf(stderr, "skipping %s, file signature found.\n", binpkg);

		sigfile_fd = -1;
		goto out;
	}
	/*
	 * Generate pkg file signature.
	 */
	if ((binpkg_fd = open(binpkg, O_RDONLY)) == -1) {
		fprintf(stderr, "cannot read %s: %s\n", binpkg, strerror(errno));
		rv = EINVAL;
		goto out;
	}
	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));
		rv = EINVAL;
		goto out;
	}
	close(binpkg_fd);

	rsa = load_rsa_key(privkey);
	if (!rsa_sign_buf(rsa, buf, st.st_size, &sig, &siglen)) {
		fprintf(stderr, "failed to sign %s: %s\n", binpkg, strerror(errno));
		rv = EINVAL;
		goto out;
	}
	free(buf);
	buf = NULL;
	/*
	 * Write pkg file signature.
	 */
	if (force)
		sigfile_fd = open(sigfile, O_WRONLY|O_TRUNC, 0644);
	else
		sigfile_fd = creat(sigfile, 0644);

	if (sigfile_fd == -1) {
		fprintf(stderr, "failed to create %s: %s\n", sigfile, strerror(errno));
		rv = EINVAL;
		goto out;
	}
	if (write(sigfile_fd, sig, siglen) != (ssize_t)siglen) {
		fprintf(stderr, "failed to write %s: %s\n", sigfile, strerror(errno));
		rv = EINVAL;
		goto out;
	}
	printf("signed successfully %s\n", binpkg);

out:
	if (rsa) {
		RSA_free(rsa);
		rsa = NULL;
	}
	if (buf)
		free(buf);
	if (sigfile)
		free(sigfile);
	if (sigfile_fd != -1)
		close(sigfile_fd);
	if (binpkg_fd != -1)
		close(binpkg_fd);

	return rv;
}