Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Early support for pkg -r <rootdir> (no chroot involved)
Baptiste Daroussin committed 11 years ago
commit 4f6eb5b79785b7eca2ed82b91c6f956791998046
parent e1bb844
12 files changed +90 -11
modified libpkg/libpkg.ver
@@ -134,6 +134,7 @@ global:
	pkg_set_debug_level;
	pkg_set_from_file;
	pkg_set_from_fileat;
+
	pkg_set_rootdir;
	pkg_shlibs_provided;
	pkg_shlibs_required;
	pkg_shutdown;
modified libpkg/pkg.c
@@ -1923,6 +1923,8 @@ pkg_open_root_fd(struct pkg *pkg)
		return (EPKG_OK);

	path = pkg_kv_get(&pkg->annotations, "relocated");
+
	if (pkg_rootdir != NULL)
+
		path = pkg_rootdir;
	if (path == NULL)
		path = "/";

modified libpkg/pkg.h.in
@@ -717,6 +717,7 @@ int pkg_set_from_fileat(int fd, struct pkg *pkg, pkg_attr attr, const char *file
 * @return Previous debug level.
 */
int64_t pkg_set_debug_level(int64_t debug_level);
+
void pkg_set_rootdir(const char *rootdir);

/**
 * Allocate a new struct pkg and add it to the deps of pkg.
modified libpkg/pkg_add.c
@@ -463,12 +463,13 @@ pkg_add_cleanup_old(struct pkgdb *db, struct pkg *old, struct pkg *new, int flag

static int
pkg_add_common(struct pkgdb *db, const char *path, unsigned flags,
-
    struct pkg_manifest_key *keys, const char *location, struct pkg *remote,
+
    struct pkg_manifest_key *keys, const char *reloc, struct pkg *remote,
    struct pkg *local)
{
	struct archive	*a;
	struct archive_entry *ae;
	struct pkg	*pkg = NULL;
+
	const char	*location;
	bool		 extract = true;
	bool		 handle_rc = false;
	int		 retcode = EPKG_OK;
@@ -480,6 +481,10 @@ pkg_add_common(struct pkgdb *db, const char *path, unsigned flags,
	if (local != NULL)
		flags |= PKG_ADD_UPGRADE;

+
	location = reloc;
+
	if (pkg_rootdir != NULL)
+
		location = pkg_rootdir;
+

	/*
	 * Open the package archive file, read all the meta files and set the
	 * current archive_entry to the first non-meta file.
@@ -513,7 +518,8 @@ pkg_add_common(struct pkgdb *db, const char *path, unsigned flags,
	 * Additional checks for non-remote package
	 */
	if (remote == NULL) {
-
		ret = pkg_add_check_pkg_archive(db, pkg, path, flags, keys, location);
+
		ret = pkg_add_check_pkg_archive(db, pkg, path, flags, keys,
+
		    location);
		if (ret != EPKG_OK) {
			/* Do not return error on installed package */
			retcode = (ret == EPKG_INSTALLED ? EPKG_OK : ret);
@@ -534,7 +540,7 @@ pkg_add_common(struct pkgdb *db, const char *path, unsigned flags,
			pkg->automatic = remote->automatic;
	}

-
	if (location != NULL)
+
	if (pkg_rootdir == NULL && location != NULL)
		pkg_kv_add(&pkg->annotations, "relocated", location, "annotation");

	/* register the package before installing it in case there are
modified libpkg/pkg_config.c
@@ -65,6 +65,7 @@
int eventpipe = -1;
int64_t debug_level = 0;
bool developer_mode = false;
+
const char *pkg_rootdir = NULL;

struct config_entry {
	uint8_t type;
@@ -766,6 +767,8 @@ pkg_ini(const char *path, const char *reposdir, pkg_init_flags flags)
	ucl_object_iter_t it = NULL;
	struct sbuf *ukey = NULL;
	bool fatal_errors = false;
+
	char *rootedpath = NULL;
+
	char *tmp = NULL;

	k = NULL;
	o = NULL;
@@ -788,8 +791,14 @@ pkg_ini(const char *path, const char *reposdir, pkg_init_flags flags)
	for (i = 0; i < c_size; i++) {
		switch (c[i].type) {
		case PKG_STRING:
+
			tmp = NULL;
+
			if (c[i].def != NULL && c[i].def[0] == '/' &&
+
			    pkg_rootdir != NULL) {
+
				asprintf(&tmp, "%s%s", pkg_rootdir, c[i].def);
+
			}
			obj = ucl_object_fromstring_common(
-
			    c[i].def != NULL ? c[i].def : "", 0, UCL_STRING_TRIM);
+
			    c[i].def != NULL ? tmp != NULL ? tmp : c[i].def : "", 0, UCL_STRING_TRIM);
+
			free(tmp);
			ucl_object_insert_key(config, obj,
			    c[i].key, strlen(c[i].key), false);
			break;
@@ -859,11 +868,14 @@ pkg_ini(const char *path, const char *reposdir, pkg_init_flags flags)
	if (path == NULL)
		path = PREFIX"/etc/pkg.conf";

+
	if (pkg_rootdir != NULL)
+
		asprintf(&rootedpath, "%s/%s", pkg_rootdir, path);
+

	p = ucl_parser_new(0);

	errno = 0;
	obj = NULL;
-
	if (!ucl_parser_add_file(p, path)) {
+
	if (!ucl_parser_add_file(p, rootedpath != NULL ? rootedpath : path)) {
		if (errno != ENOENT)
			pkg_emit_error("Invalid configuration file: %s", ucl_parser_get_error(p));
	} else {
@@ -908,6 +920,7 @@ pkg_ini(const char *path, const char *reposdir, pkg_init_flags flags)
	if (fatal_errors) {
		ucl_object_unref(ncfg);
		ucl_parser_free(p);
+
		free(rootedpath);
		return (EPKG_FATAL);
	}

@@ -1017,6 +1030,7 @@ pkg_ini(const char *path, const char *reposdir, pkg_init_flags flags)
	parsed = true;
	ucl_object_unref(obj);
	ucl_parser_free(p);
+
	free(rootedpath);

	if (strcmp(pkg_object_string(pkg_config_get("ABI")), "unknown") == 0) {
		pkg_emit_error("Unable to determine ABI");
@@ -1236,3 +1250,11 @@ pkg_set_debug_level(int64_t new_debug_level) {
	debug_level = new_debug_level;
	return old_debug_level;
}
+

+
void
+
pkg_set_rootdir(const char *rootdir) {
+
	if (pkg_initialized())
+
		return;
+

+
	pkg_rootdir = rootdir;
+
}
modified libpkg/pkg_create.c
@@ -69,6 +69,8 @@ pkg_create_from_dir(struct pkg *pkg, const char *root,
	relocation = pkg_kv_get(&pkg->annotations, "relocated");
	if (relocation == NULL)
		relocation = "";
+
	if (pkg_rootdir != NULL)
+
		relocation = pkg_rootdir;

	/*
	 * Get / compute size / checksum if not provided in the manifest
modified libpkg/pkg_ports.c
@@ -1284,11 +1284,16 @@ ports_parse_plist(struct pkg *pkg, const char *plist, const char *stage)

int
pkg_add_port(struct pkgdb *db, struct pkg *pkg, const char *input_path,
-
    const char *location, bool testing)
+
    const char *reloc, bool testing)
{
+
	const char *location;
	int rc = EPKG_OK;

-
	if (location != NULL)
+
	location = reloc;
+
	if (pkg_rootdir != NULL)
+
		location = pkg_rootdir;
+

+
	if (pkg_rootdir == NULL && location != NULL)
		pkg_kv_add(&pkg->annotations, "relocated", location, "annotation");

	pkg_emit_install_begin(pkg);
modified libpkg/private/pkg.h
@@ -125,6 +125,7 @@
extern int eventpipe;
extern int64_t debug_level;
extern bool developer_mode;
+
extern const char *pkg_rootdir;

struct pkg_repo_it;
struct pkg_repo;
modified src/main.c
@@ -169,13 +169,14 @@ usage(const char *conffile, const char *reposdir, FILE *out, enum pkg_usage_reas
#else
#define JAIL_ARG
#endif
-
	fprintf(out, "Usage: pkg [-v] [-d] [-l] [-N] ["JAIL_ARG"-c <chroot path>] [-C <configuration file>] [-R <repo config dir>] [-o var=value] [-4|-6] <command> [<args>]\n");
+
	fprintf(out, "Usage: pkg [-v] [-d] [-l] [-N] ["JAIL_ARG"-c <chroot path>|-r <rootdir>] [-C <configuration file>] [-R <repo config dir>] [-o var=value] [-4|-6] <command> [<args>]\n");
	if (reason == PKG_USAGE_HELP) {
		fprintf(out, "Global options supported:\n");
		fprintf(out, "\t%-15s%s\n", "-d", "Increment debug level");
#ifdef HAVE_LIBJAIL
		fprintf(out, "\t%-15s%s\n", "-j", "Execute pkg(8) inside a jail(8)");
#endif
+
		fprintf(out, "\t%-15s%s\n", "-R", "Execute pkg(8) using relocating installation to <rootdir>");
		fprintf(out, "\t%-15s%s\n", "-c", "Execute pkg(8) inside a chroot(8)");
		fprintf(out, "\t%-15s%s\n", "-C", "Use the specified configuration file");
		fprintf(out, "\t%-15s%s\n", "-R", "Directory to search for individual repository configurations");
@@ -553,6 +554,7 @@ main(int argc, char **argv)
	struct commands	 *command = NULL;
	unsigned int	  ambiguous = 0;
	const char	 *chroot_path = NULL;
+
	const char	 *rootdir = NULL;
#ifdef HAVE_LIBJAIL
	int		  jid;
#endif
@@ -581,6 +583,7 @@ main(int argc, char **argv)
		{ "chroot",		required_argument,	NULL,	'c' },
		{ "config",		required_argument,	NULL,	'C' },
		{ "repo-conf-dir",	required_argument,	NULL,	'R' },
+
		{ "rootdir",		required_argument,	NULL,	'r' },
		{ "list",		no_argument,		NULL,	'l' },
		{ "version",		no_argument,		NULL,	'v' },
		{ "option",		required_argument,	NULL,	'o' },
@@ -614,7 +617,7 @@ main(int argc, char **argv)
#else
#define JAIL_OPT
#endif
-
	while ((ch = getopt_long(argc, argv, "+d"JAIL_OPT"c:C:R:lNvo:46", longopts, NULL)) != -1) {
+
	while ((ch = getopt_long(argc, argv, "+d"JAIL_OPT"c:C:R:r:lNvo:46", longopts, NULL)) != -1) {
		switch (ch) {
		case 'd':
			debug++;
@@ -628,6 +631,9 @@ main(int argc, char **argv)
		case 'R':
			reposdir = optarg;
			break;
+
		case 'r':
+
			rootdir = optarg;
+
			break;
#ifdef HAVE_LIBJAIL
		case 'j':
			jail_str = optarg;
@@ -686,9 +692,11 @@ main(int argc, char **argv)
	arc4random_stir();
#endif

-
	if (jail_str != NULL && chroot_path != NULL) {
+
	if ((jail_str != NULL && (chroot_path != NULL || rootdir != NULL)) ||
+
	    (chroot_path != NULL && (jail_str != NULL || rootdir != NULL)) ||
+
	    (rootdir != NULL && (jail_str != NULL || chroot_path != NULL)))  {
		usage(conffile, reposdir, stderr, PKG_USAGE_INVALID_ARGUMENTS,
-
				"-j and -c cannot be used at the same time!\n");
+
		    "-j, -c and/or -r cannot be used at the same time!\n");
	}

	if (chroot_path != NULL)
@@ -710,6 +718,12 @@ main(int argc, char **argv)
			errx(EX_SOFTWARE, "chdir() failed");
#endif

+
	if (rootdir != NULL) {
+
		if (chdir(rootdir) == -1)
+
			errx(EX_SOFTWARE, "chdir() failed");
+
		pkg_set_rootdir(rootdir);
+
	}
+

	if (pkg_ini(conffile, reposdir, init_flags) != EPKG_OK)
		errx(EX_SOFTWARE, "Cannot parse configuration file!");

modified tests/Makefile.am
@@ -78,6 +78,7 @@ EXTRA_DIST= frontend/png.uclin \
		frontend/pkg.shin \
		frontend/register.shin \
		frontend/requires.shin \
+
		frontend/rootdir.shin \
		frontend/rubypuppet.shin \
		frontend/search.shin \
		frontend/set.shin \
@@ -104,6 +105,7 @@ check_SCRIPTS= frontend/pkg.sh \
		frontend/packagesplit.sh \
		frontend/register.sh \
		frontend/requires.sh \
+
		frontend/rootdir.sh \
		frontend/rubypuppet.sh \
		frontend/search.sh \
		frontend/set.sh \
modified tests/frontend/Kyuafile
@@ -14,6 +14,7 @@ atf_test_program{name='packagesplit.sh'}
atf_test_program{name='pkg.sh'}
atf_test_program{name='register.sh'}
atf_test_program{name='requires.sh'}
+
atf_test_program{name='rootdir.sh'}
atf_test_program{name='rubypuppet.sh'}
atf_test_program{name='search.sh'}
atf_test_program{name='set.sh'}
added tests/frontend/rootdir.shin
@@ -0,0 +1,22 @@
+
#!/usr/bin/env atf-sh
+

+
atf_test_case rootdir
+
rootdir_head() {
+
	atf_set "descr" "pkg -r <rootdir>"
+
}
+

+
rootdir_body() {
+
	unset PKG_DBDIR
+

+
	atf_check \
+
		-o inline:"${TMPDIR}/var/db/pkg\n" \
+
		-e empty \
+
		-s exit:0 \
+
		pkg -r "${TMPDIR}" config pkg_dbdir
+
}
+

+
atf_init_test_cases() {
+
	. $(atf_get_srcdir)/test_environment.sh
+

+
	atf_add_test_case rootdir
+
}