Ejemplo n.º 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);
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
static int
repo_find_best_pkg_cb(struct xbps_handle *xhp,
		      struct xbps_rpool_index *rpi,
		      void *arg,
		      bool *done)
{
	struct repo_pool_fpkg *rpf = arg;
	const char *repopkgver;
	prop_dictionary_t pkgd;

	(void)done;
	(void)xhp;

	if (rpf->bypattern) {
		pkgd = xbps_find_pkg_in_array_by_pattern(xhp, rpi->repo,
		    rpf->pattern, NULL);
	} else {
		pkgd = xbps_find_pkg_in_array_by_name(xhp, rpi->repo,
		    rpf->pattern, NULL);
	}
	if (pkgd == NULL) {
		if (errno && errno != ENOENT)
			return errno;

		xbps_dbg_printf(xhp,
		    "[rpool] Package '%s' not found in repository "
		    "'%s'.\n", rpf->pattern, rpi->uri);
		return 0;
	}
	prop_dictionary_get_cstring_nocopy(pkgd,
	    "pkgver", &repopkgver);
	if (rpf->bestpkgver == NULL) {
		xbps_dbg_printf(xhp,
		    "[rpool] Found best match '%s' (%s).\n",
		    repopkgver, rpi->uri);
		rpf->pkgd = pkgd;
		prop_dictionary_set_cstring_nocopy(rpf->pkgd,
		    "repository", rpi->uri);
		rpf->bestpkgver = repopkgver;
		return 0;
	}
	/*
	 * Compare current stored version against new
	 * version from current package in repository.
	 */
	if (xbps_cmpver(repopkgver, rpf->bestpkgver) == 1) {
		xbps_dbg_printf(xhp,
		    "[rpool] Found best match '%s' (%s).\n",
		    repopkgver, rpi->uri);
		rpf->pkgd = pkgd;
		prop_dictionary_set_cstring_nocopy(rpf->pkgd,
		    "repository", rpi->uri);
		rpf->bestpkgver = repopkgver;
	}
	return 0;
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
static bool
rsa_verify_hash(struct xbps_repo *repo, xbps_data_t pubkey,
		unsigned char *sig, unsigned int siglen,
		unsigned char *sha256)
{
	BIO *bio;
	RSA *rsa;
	int rv;

	ERR_load_crypto_strings();
	SSL_load_error_strings();

	bio = BIO_new_mem_buf(__UNCONST(xbps_data_data_nocopy(pubkey)),
			xbps_data_size(pubkey));
	assert(bio);

	rsa = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL);
	if (rsa == NULL) {
		xbps_dbg_printf(repo->xhp, "`%s' error reading public key: %s\n",
		    repo->uri, ERR_error_string(ERR_get_error(), NULL));
		return false;
	}

	rv = RSA_verify(NID_sha1, sha256, SHA256_DIGEST_LENGTH, sig, siglen, rsa);
	RSA_free(rsa);
	BIO_free(bio);
	ERR_free_strings();

	return rv ? true : false;
}
Ejemplo n.º 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;
}
Ejemplo n.º 9
0
static int
pfcexec(struct xbps_handle *xhp, const char *file, const char **argv)
{
	pid_t child;
	int status;

	child = vfork();
	switch (child) {
	case 0:
		/*
		 * If rootdir != / and uid==0 and bin/sh exists,
		 * change root directory and exec command.
		 */
		if (strcmp(xhp->rootdir, "/")) {
			if ((geteuid() == 0) && (access("bin/sh", X_OK) == 0)) {
				if (chroot(xhp->rootdir) == -1) {
					xbps_dbg_printf(xhp, "%s: chroot() "
					    "failed: %s\n", *argv, strerror(errno));
					_exit(errno);
				}
				if (chdir("/") == -1) {
					xbps_dbg_printf(xhp, "%s: chdir() "
					    "failed: %s\n", *argv, strerror(errno));
					_exit(errno);
				}
			}
		}
		(void)execv(file, __UNCONST(argv));
		_exit(errno);
		/* NOTREACHED */
	case -1:
		return -1;
	}

	while (waitpid(child, &status, 0) < 0) {
		if (errno != EINTR)
			return -1;
	}

	if (!WIFEXITED(status))
		return -1;

	return WEXITSTATUS(status);
}
Ejemplo n.º 10
0
void
xbps_pkgdb_unlock(struct xbps_handle *xhp)
{
	if (pkgdb_fd != -1) {
		if (lockf(pkgdb_fd, F_ULOCK, 0) == -1)
			xbps_dbg_printf(xhp, "[pkgdb] failed to unlock pkgdb: %s\n", strerror(errno));

		(void)close(pkgdb_fd);
		pkgdb_fd = -1;
	}
}
Ejemplo n.º 11
0
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);
}
Ejemplo n.º 12
0
static bool
repo_open_local(struct xbps_repo *repo, const char *repofile)
{
	struct stat st;
	int rv = 0;

	if (fstat(repo->fd, &st) == -1) {
		rv = errno;
		xbps_dbg_printf(repo->xhp, "[repo] `%s' fstat repodata %s\n",
		    repofile, strerror(rv));
		return false;
	}

	repo->ar = archive_read_new();
	archive_read_support_compression_gzip(repo->ar);
	archive_read_support_format_tar(repo->ar);

	if (archive_read_open_fd(repo->ar, repo->fd, st.st_blksize) == ARCHIVE_FATAL) {
		rv = archive_errno(repo->ar);
		xbps_dbg_printf(repo->xhp,
		    "[repo] `%s' failed to open repodata archive %s\n",
		    repofile, strerror(rv));
		return false;
	}
	if ((repo->idx = repo_get_dict(repo)) == NULL) {
		rv = archive_errno(repo->ar);
		xbps_dbg_printf(repo->xhp, "[repo] `%s' failed to internalize "
		    " index on archive, removing file.\n", repofile);
		/* broken archive, remove it */
		(void)unlink(repofile);
		return false;
	}
	xbps_dictionary_make_immutable(repo->idx);
	repo->idxmeta = repo_get_dict(repo);
	if (repo->idxmeta != NULL) {
		repo->is_signed = true;
		xbps_dictionary_make_immutable(repo->idxmeta);
	}

	return true;
}
Ejemplo n.º 13
0
void HIDDEN
xbps_pkgdb_release(struct xbps_handle *xhp)
{
	assert(xhp != NULL);

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

	xbps_pkgdb_unlock(xhp);
	xbps_object_release(xhp->pkgdb);
	xbps_dbg_printf(xhp, "[pkgdb] released ok.\n");
}
Ejemplo n.º 14
0
/**
 * @file lib/pkgdb.c
 * @brief Package database handling routines
 * @defgroup pkgdb Package database handling functions
 *
 * Functions to manipulate the main package database plist file (pkgdb).
 *
 * The following image shown below shows the proplib structure used
 * by the main package database plist:
 *
 * @image html images/xbps_pkgdb_array.png
 *
 * Legend:
 *  - <b>Salmon filled box</b>: \a XBPS_PKGDB file internalized.
 *  - <b>White filled box</b>: mandatory objects.
 *  - <b>Grey filled box</b>: optional objects.
 *  - <b>Green filled box</b>: possible value set in the object, only one
 *    of them is set.
 *
 * Text inside of white boxes are the key associated with the object, its
 * data type is specified on its edge, i.e array, bool, integer, string,
 * dictionary.
 */
int HIDDEN
xbps_pkgdb_init(struct xbps_handle *xhp)
{
	int rv;

	assert(xhp != NULL);

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

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

		return rv;
	}
	xbps_dbg_printf(xhp, "[pkgdb] initialized ok.\n");

	return 0;
}
Ejemplo n.º 15
0
bool
xbps_repo_store(struct xbps_handle *xhp, const char *repo)
{
	char *url = NULL;

	assert(xhp);
	assert(repo);

	if (xhp->repositories == NULL) {
		xhp->repositories = xbps_array_create();
		assert(xhp->repositories);
	}
	/*
	 * If it's a local repo and path is relative, make it absolute.
	 */
	if (!xbps_repository_is_remote(repo)) {
		if (repo[0] != '/' && repo[0] != '\0') {
			if ((url = realpath(repo, NULL)) == NULL)
				xbps_dbg_printf(xhp, "[repo] %s: realpath %s\n", __func__, repo);
		}
	}
	if (xbps_match_string_in_array(xhp->repositories, url ? url : repo)) {
		xbps_dbg_printf(xhp, "[repo] `%s' already stored\n", url ? url : repo);
		if (url)
			free(url);
		return false;
	}
	if (xbps_array_add_cstring(xhp->repositories, url ? url : repo)) {
		xbps_dbg_printf(xhp, "[repo] `%s' stored successfully\n", url ? url : repo);
		if (url)
			free(url);
		return true;
	}
	if (url)
		free(url);

	return false;
}
Ejemplo n.º 16
0
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;
}
Ejemplo n.º 17
0
void HIDDEN
xbps_pkgdb_release(struct xbps_handle *xhp)
{
	assert(xhp != NULL);

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

	if (xbps_object_type(xhp->pkg_metad) == XBPS_TYPE_DICTIONARY)
	       xbps_object_release(xhp->pkg_metad);

	xbps_object_release(xhp->pkgdb);
	xhp->pkgdb = NULL;
	xbps_dbg_printf(xhp, "[pkgdb] released ok.\n");
}
Ejemplo n.º 18
0
static bool
repo_open_remote(struct xbps_repo *repo)
{
	char *rpath;
	bool rv;

	rpath = xbps_repo_path(repo->xhp, repo->uri);
	rv = xbps_repo_fetch_remote(repo, rpath);
	free(rpath);
	if (rv) {
		xbps_dbg_printf(repo->xhp, "[repo] `%s' used remotely (kept in memory).\n", repo->uri);
		if (repo->xhp->state_cb && xbps_repo_key_import(repo) != 0)
			rv = false;
	}
	return rv;
}
Ejemplo n.º 19
0
static xbps_dictionary_t
repo_get_dict(struct xbps_repo *repo)
{
	struct archive_entry *entry;
	int rv;

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

	rv = archive_read_next_header(repo->ar, &entry);
	if (rv != ARCHIVE_OK) {
		xbps_dbg_printf(repo->xhp,
		    "%s: read_next_header %s\n", repo->uri,
		    archive_error_string(repo->ar));
		return NULL;
	}
	return xbps_archive_get_dictionary(repo->ar, entry);
}
Ejemplo n.º 20
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;
}
Ejemplo n.º 21
0
int HIDDEN
xbps_repository_find_deps(struct xbps_handle *xhp,
			  xbps_array_t unsorted,
			  xbps_dictionary_t repo_pkgd)
{
	xbps_array_t pkg_rdeps, pkg_provides = NULL;
	const char *pkgver;
	unsigned short depth = 0;

	pkg_rdeps = xbps_dictionary_get(repo_pkgd, "run_depends");
	if (xbps_array_count(pkg_rdeps) == 0)
		return 0;

	xbps_dictionary_get_cstring_nocopy(repo_pkgd, "pkgver", &pkgver);
	xbps_dbg_printf(xhp, "Finding required dependencies for '%s':\n", pkgver);
	/*
	 * This will find direct and indirect deps, if any of them is not
	 * there it will be added into the missing_deps array.
	 */
	pkg_provides = xbps_dictionary_get(repo_pkgd, "provides");
	return find_repo_deps(xhp, unsorted, pkg_rdeps, pkg_provides, pkgver, &depth);
}
Ejemplo n.º 22
0
int HIDDEN
xbps_transaction_package_replace(struct xbps_handle *xhp, xbps_array_t pkgs)
{
	for (unsigned int i = 0; i < xbps_array_count(pkgs); i++) {
		xbps_array_t replaces;
		xbps_object_t obj, obj2;
		xbps_object_iterator_t iter;
		const char *pkgver;
		char *pkgname;

		obj = xbps_array_get(pkgs, i);
		replaces = xbps_dictionary_get(obj, "replaces");
		if (replaces == NULL || xbps_array_count(replaces) == 0)
			continue;

		iter = xbps_array_iterator(replaces);
		assert(iter);

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

		while ((obj2 = xbps_object_iterator_next(iter)) != NULL) {
			xbps_dictionary_t instd, reppkgd;
			const char *tract, *pattern, *curpkgver;
			char *curpkgname;
			bool instd_auto = false;

			pattern = xbps_string_cstring_nocopy(obj2);
			/*
			 * Find the installed package that matches the pattern
			 * to be replaced.
			 */
			if (((instd = xbps_pkgdb_get_pkg(xhp, pattern)) == NULL) &&
			    ((instd = xbps_pkgdb_get_virtualpkg(xhp, pattern)) == NULL))
				continue;

			xbps_dictionary_get_cstring_nocopy(instd,
			    "pkgver", &curpkgver);
			curpkgname = xbps_pkg_name(curpkgver);
			assert(curpkgname);
			/*
			 * Check that we are not replacing the same package,
			 * due to virtual packages.
			 */
			if (strcmp(pkgname, curpkgname) == 0) {
				free(curpkgname);
				continue;
			}
			/*
			 * Make sure to not add duplicates.
			 */
			xbps_dictionary_get_bool(instd, "automatic-install", &instd_auto);
			reppkgd = xbps_find_pkg_in_array(pkgs, curpkgname, NULL);
			if (reppkgd) {
				xbps_dictionary_get_cstring_nocopy(reppkgd,
				    "transaction", &tract);
				if (strcmp(tract, "remove") == 0)
					continue;
				/*
				 * Package contains replaces="pkgpattern", but the
				 * package that should be replaced is also in the
				 * transaction and it's going to be updated.
				 */
				xbps_dictionary_set_bool(reppkgd,
				    "automatic-install", instd_auto);
				xbps_array_replace_dict_by_name(pkgs,
				    reppkgd, curpkgname);
				continue;
			}
			/*
			 * If new package is providing a virtual package to the
			 * package that we want to replace we should respect
			 * the automatic-install object.
			 */
			if (xbps_match_virtual_pkg_in_dict(obj, pattern)) {
				xbps_dictionary_set_bool(obj,
				    "automatic-install", instd_auto);
			}
			xbps_dbg_printf(xhp,
			    "Package `%s' will be replaced by `%s', "
			    "matched with `%s'\n", curpkgver, pkgver, pattern);
			/*
			 * Add package dictionary into the transaction and mark
			 * it as to be "removed".
			 */
			xbps_dictionary_set_cstring_nocopy(instd,
			    "transaction", "remove");
			if (!xbps_array_add_first(pkgs, instd))
				return EINVAL;
			free(curpkgname);
		}
		xbps_object_iterator_release(iter);
		free(pkgname);
	}

	return 0;
}
Ejemplo n.º 23
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;
}
Ejemplo n.º 24
0
static int
create_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 *tgt_dup, *tgt_dir, *lnk_dup, *lnk_dir;
		char *l, *lnk, *tgt = NULL;
		const char *tgt0;
		int rv;

		str = xbps_array_get(a, i);
		l = left(xbps_string_cstring_nocopy(str));
		assert(l);
		tgt0 = right(xbps_string_cstring_nocopy(str));
		assert(tgt0);
		/* always create target dir, for dangling symlinks */
		tgt_dup = strdup(tgt0);
		assert(tgt_dup);
		tgt_dir = dirname(tgt_dup);
		if (strcmp(tgt_dir, ".")) {
			tgt = xbps_xasprintf("%s%s", xhp->rootdir, tgt_dir);
			if (xbps_mkpath(tgt, 0755) != 0) {
				if (errno != EEXIST) {
					rv = errno;
					xbps_dbg_printf(xhp, "failed to create "
					    "target dir '%s' for group '%s': %s\n",
					    tgt, grname, strerror(errno));
					free(tgt_dup);
					free(tgt);
					free(l);
					return rv;
				}
			}
			free(tgt);
		}
		/* always create link dir, for dangling symlinks */
		lnk_dup = strdup(l);
		assert(lnk_dup);
		lnk_dir = dirname(lnk_dup);
		if (strcmp(lnk_dir, ".")) {
			lnk = xbps_xasprintf("%s%s", xhp->rootdir, lnk_dir);
			if (xbps_mkpath(lnk, 0755) != 0) {
				if (errno != EEXIST) {
					rv = errno;
					xbps_dbg_printf(xhp, "failed to create symlink"
					    "dir '%s' for group '%s': %s\n",
					    lnk, grname, strerror(errno));
					free(tgt_dup);
					free(lnk_dup);
					free(lnk);
					free(l);
					return rv;
				}
			}
			free(lnk);
		}
		free(lnk_dup);

		if (l[0] != '/') {
			lnk = xbps_xasprintf("%s%s/%s", xhp->rootdir, tgt_dir, l);
			free(tgt_dup);
			tgt_dup = strdup(tgt0);
			assert(tgt_dup);
			tgt = strdup(basename(tgt_dup));
			free(tgt_dup);
		} else {
			free(tgt_dup);
			tgt = strdup(tgt0);
			lnk = xbps_xasprintf("%s%s", xhp->rootdir, l);
		}
		xbps_set_cb_state(xhp, XBPS_STATE_ALTGROUP_LINK_ADDED, 0, NULL,
		    "Creating '%s' alternatives group symlink: %s -> %s", grname, l, tgt);
		unlink(lnk);
		if (tgt[0] == '/') {
			tgt_dup = relpath(lnk + strlen(xhp->rootdir), tgt);
			free(tgt);
			tgt = tgt_dup;
		}
		if ((rv = symlink(tgt, lnk)) != 0) {
			xbps_dbg_printf(xhp, "failed to create alt symlink '%s'"
			    "for group '%s': %s\n", lnk, grname,
			    strerror(errno));
			free(tgt);
			free(lnk);
			free(l);
			return rv;
		}
		free(tgt);
		free(lnk);
		free(l);
	}

	return 0;
}
Ejemplo n.º 25
0
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;
}
Ejemplo n.º 26
0
/*
 * 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;
}
Ejemplo n.º 27
0
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;
}
Ejemplo n.º 28
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;
}
Ejemplo n.º 29
0
static int
parse_dir(struct xbps_handle *xhp, const char *cwd, const char *dir, const char *confdir, bool vpkg)
{
	struct dirent **namelist;
	char *ext, ldir[PATH_MAX], conf[PATH_MAX];
	int i, n, rv = 0;

	/*
	 * Read all configuration files stored in the system
	 * foo.d directory.
	 */
	snprintf(ldir, sizeof(ldir), "%s/%s",
		strcmp(xhp->rootdir, "/") ? xhp->rootdir : "", dir);
	xbps_dbg_printf(xhp, "Processing system directory: %s\n", ldir);

	if ((n = scandir(ldir, &namelist, 0, alphasort)) < 0)
		goto stage2;

	for (i = 0; i < n; i++) {
		if ((strcmp(namelist[i]->d_name, "..") == 0) ||
		    (strcmp(namelist[i]->d_name, ".") == 0)) {
			free(namelist[i]);
			continue;
		}
		/* only process .vpkg/.conf files, ignore something else */
		if ((ext = strrchr(namelist[i]->d_name, '.')) == NULL) {
			free(namelist[i]);
			continue;
		}
		if (strcmp(ext, ".conf") && strcmp(ext, ".vpkg")) {
			xbps_dbg_printf(xhp, "%s: ignoring %s\n", ldir, namelist[i]->d_name);
			free(namelist[i]);
			continue;
		}
		/* if the same file exists in configuration directory, ignore it */
		snprintf(conf, sizeof(conf), "%s/%s/%s", xhp->rootdir, confdir, namelist[i]->d_name);
		if (access(conf, R_OK) == 0) {
			xbps_dbg_printf(xhp, "%s: ignoring %s (exists in confdir)\n", ldir, namelist[i]->d_name);
			free(namelist[i]);
			continue;
		}
		/* parse conf file */
		snprintf(conf, sizeof(conf), "%s/%s", ldir, namelist[i]->d_name);
		if ((rv = parse_file(xhp, cwd, conf, false, vpkg)) != 0) {
			free(namelist[i]);
			break;
		}
	}
	free(namelist);
	if (rv != 0)
		return rv;

stage2:
	/*
	 * Read all configuration files stored in the configuration foo.d directory.
	 */
	snprintf(ldir, sizeof(ldir), "%s%s",
		strcmp(xhp->rootdir, "/") ? xhp->rootdir : "", confdir);
	xbps_dbg_printf(xhp, "Processing configuration directory: %s\n", ldir);

	if ((n = scandir(ldir, &namelist, 0, alphasort)) < 0)
		return 0;

	for (i = 0; i < n; i++) {
		if ((strcmp(namelist[i]->d_name, "..") == 0) ||
		    (strcmp(namelist[i]->d_name, ".") == 0)) {
			free(namelist[i]);
			continue;
		}
		/* only process .vpkg/.conf files, ignore something else */
		if ((ext = strrchr(namelist[i]->d_name, '.')) == NULL) {
			free(namelist[i]);
			continue;
		}
		if (strcmp(ext, ".conf") && strcmp(ext, ".vpkg")) {
			xbps_dbg_printf(xhp, "%s: ignoring %s\n", ldir, namelist[i]->d_name);
			free(namelist[i]);
			continue;
		}
		/* parse conf file */
		snprintf(conf, sizeof(conf), "%s/%s", ldir, namelist[i]->d_name);
		if ((rv = parse_file(xhp, cwd, conf, false, vpkg)) != 0) {
			free(namelist[i]);
			break;
		}
	}
	free(namelist);

	return rv;
}
Ejemplo n.º 30
0
static int
parse_file(struct xbps_handle *xhp, const char *cwd, const char *path, bool nested, bool vpkgconf)
{
	FILE *fp;
	char tmppath[XBPS_MAXPATH] = {0};
	size_t len, nlines = 0;
	ssize_t nread;
	char *cfcwd, *line = NULL;
	int rv = 0;

	if ((fp = fopen(path, "r")) == NULL) {
		rv = errno;
		xbps_dbg_printf(xhp, "cannot read configuration file %s: %s\n", path, strerror(rv));
		return rv;
	}

	if (!vpkgconf) {
		xbps_dbg_printf(xhp, "Parsing configuration file: %s\n", path);
	}

	while ((nread = getline(&line, &len, fp)) != -1) {
		char *p, *k, *v;

		nlines++;
		p = line;
		/* eat blanks */
		while (isblank((unsigned char)*p))
			p++;
		/* ignore comments or empty lines */
		if (*p == '#' || *p == '\n')
			continue;
		if (!parse_option(p, &k, &v)) {
			xbps_dbg_printf(xhp, "%s: ignoring invalid option at "
			    "line %zu\n", path, nlines);
			continue;
		}
		if (strcmp(k, "rootdir") == 0) {
			xbps_dbg_printf(xhp, "%s: rootdir set to %s\n",
			    path, v);
			snprintf(xhp->rootdir, sizeof(xhp->rootdir), "%s", v);
		} else if (strcmp(k, "cachedir") == 0) {
			xbps_dbg_printf(xhp, "%s: cachedir set to %s\n",
			    path, v);
			snprintf(xhp->cachedir, sizeof(xhp->cachedir), "%s", v);
		} else if (strcmp(k, "syslog") == 0) {
			if (strcasecmp(v, "true") == 0) {
				xhp->flags &= ~XBPS_FLAG_DISABLE_SYSLOG;
				xbps_dbg_printf(xhp, "%s: syslog enabled\n", path);
			} else {
				xhp->flags |= XBPS_FLAG_DISABLE_SYSLOG;
				xbps_dbg_printf(xhp, "%s: syslog disabled\n", path);
			}
		} else if (strcmp(k, "repository") == 0) {
			if (store_repo(xhp, v))
				xbps_dbg_printf(xhp, "%s: added repository %s\n", path, v);
		} else if (strcmp(k, "virtualpkg") == 0) {
			store_vpkg(xhp, path, nlines, v);
		} else if (strcmp(k, "preserve") == 0) {
			store_preserved_file(xhp, v);
		}
		/* Avoid double-nested parsing, only allow it once */
		if (nested)
			continue;

		if (strcmp(k, "include"))
			continue;

		/* cwd to the dir containing the config file */
		strlcpy(tmppath, path, sizeof(tmppath));
		cfcwd = dirname(tmppath);
		if (chdir(cfcwd) == -1) {
			rv = errno;
			xbps_dbg_printf(xhp, "cannot chdir to %s: %s\n", cfcwd, strerror(rv));
			return rv;
		}
		if ((rv = parse_files_glob(xhp, cwd, v, true, false)) != 0)
			break;

	}
	free(line);
	fclose(fp);

	return rv;
}