summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Gregory <andrew.gregory.8@gmail.com>2017-04-16 00:31:57 -0400
committerAndrew Gregory <andrew.gregory.8@gmail.com>2017-04-16 19:41:35 -0400
commitfae33a1faf3f94ea46049664ef483b2a3e0d3f01 (patch)
treee33404cef3acbbf18b774a33eab3006a7b986c5e
parent6a4c6a02de9b45abe4c0f78c4f5d14d92d3359d6 (diff)
add --sysroot option
--root is not sufficient to properly operate on a mounted guest system. Using --root still uses the host system's configuration and there is no way to correctly use the guest configuration without manually modifying any Include directives. --sysroot provides an easier way to operate on a guest system by chrooting immediately after option parsing before configuration parsing or performing any operations. It is currently limited to the root user, but that's enough for restoring a guest system to a working state, which is the primary intended use case. Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
-rw-r--r--doc/pacman.8.txt11
-rw-r--r--src/pacman/conf.h2
-rw-r--r--src/pacman/pacman.c24
-rw-r--r--src/pacman/util.c3
4 files changed, 32 insertions, 8 deletions
diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt
index f01f4aa4..d670e82a 100644
--- a/doc/pacman.8.txt
+++ b/doc/pacman.8.txt
@@ -136,11 +136,12 @@ Options
*-r, \--root* <path>::
Specify an alternative installation root (default is `/`). This should
not be used as a way to install software into `/usr/local` instead of
- `/usr`. This option is used if you want to install a package on a
- temporarily mounted partition that is "owned" by another system.
+ `/usr`.
*NOTE*: If database path or log file are not specified on either the
command line or in linkman:pacman.conf[5], their default location will
be inside this root path.
+ *NOTE*: This option is not suitable for performing operations on a mounted
+ guest system. See '\--sysroot' instead.
*-v, \--verbose*::
Output paths such as as the Root, Conf File, DB Path, Cache Dirs, etc.
@@ -197,6 +198,12 @@ Options
Disable defaults for low speed limit and timeout on downloads. Use this
if you have issues downloading files with proxy and/or security gateway.
+*\--sysroot* <dir>::
+ Specify an alternative system root. Pacman will chroot and chdir into the
+ system root prior to running. This allows mounted guest systems to be
+ properly operated on. Any other paths given will be interpreted as relative
+ to the system root. Requires root privileges.
+
Transaction Options (apply to '-S', '-R' and '-U')
--------------------------------------------------
diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index e67f7c51..53b44be6 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -67,6 +67,7 @@ typedef struct __config_t {
char *dbpath;
char *logfile;
char *gpgdir;
+ char *sysroot;
alpm_list_t *hookdirs;
alpm_list_t *cachedirs;
@@ -195,6 +196,7 @@ enum {
OP_PRINT,
OP_QUIET,
OP_ROOT,
+ OP_SYSROOT,
OP_RECURSIVE,
OP_SEARCH,
OP_REGEX,
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index 9d1cf6bb..605aec3e 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -214,6 +214,7 @@ static void usage(int op, const char * const myname)
addlist(_(" -r, --root <path> set an alternate installation root\n"));
addlist(_(" -v, --verbose be verbose\n"));
addlist(_(" --arch <arch> set an alternate architecture\n"));
+ addlist(_(" --sysroot operate on a mounted guest system (root-only)\n"));
addlist(_(" --cachedir <dir> set an alternate package cache location\n"));
addlist(_(" --hookdir <dir> set an alternate hook location\n"));
addlist(_(" --color <when> colorize the output\n"));
@@ -447,6 +448,10 @@ static int parsearg_global(int opt)
free(config->rootdir);
config->rootdir = strdup(optarg);
break;
+ case OP_SYSROOT:
+ free(config->sysroot);
+ config->sysroot = strdup(optarg);
+ break;
case OP_DISABLEDLTIMEOUT:
config->disable_dl_timeout = 1;
break;
@@ -917,6 +922,7 @@ static int parseargs(int argc, char *argv[])
{"print", no_argument, 0, OP_PRINT},
{"quiet", no_argument, 0, OP_QUIET},
{"root", required_argument, 0, OP_ROOT},
+ {"sysroot", required_argument, 0, OP_SYSROOT},
{"recursive", no_argument, 0, OP_RECURSIVE},
{"search", no_argument, 0, OP_SEARCH},
{"regex", no_argument, 0, OP_REGEX},
@@ -1150,6 +1156,18 @@ int main(int argc, char *argv[])
cleanup(ret);
}
+ /* check if we have sufficient permission for the requested operation */
+ if(myuid > 0 && needs_root()) {
+ pm_printf(ALPM_LOG_ERROR, _("you cannot perform this operation unless you are root.\n"));
+ cleanup(EXIT_FAILURE);
+ }
+
+ if(config->sysroot && (chroot(config->sysroot) != 0 || chdir("/") != 0)) {
+ pm_printf(ALPM_LOG_ERROR,
+ _("chroot to '%s' failed: (%s)\n"), config->sysroot, strerror(errno));
+ cleanup(EXIT_FAILURE);
+ }
+
/* we support reading targets from stdin if a cmdline parameter is '-' */
if(alpm_list_find_str(pm_targets, "-")) {
if(!isatty(fileno(stdin))) {
@@ -1222,12 +1240,6 @@ int main(int argc, char *argv[])
config->logmask &= ~ALPM_LOG_WARNING;
}
- /* check if we have sufficient permission for the requested operation */
- if(myuid > 0 && needs_root()) {
- pm_printf(ALPM_LOG_ERROR, _("you cannot perform this operation unless you are root.\n"));
- cleanup(EXIT_FAILURE);
- }
-
if(config->verbose > 0) {
alpm_list_t *j;
printf("Root : %s\n", alpm_option_get_root(config->handle));
diff --git a/src/pacman/util.c b/src/pacman/util.c
index 64ea8c57..ae8a74d3 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -103,6 +103,9 @@ int trans_release(void)
int needs_root(void)
{
+ if(config->sysroot) {
+ return 1;
+ }
switch(config->op) {
case PM_OP_DATABASE:
return !config->op_q_check;