From fae33a1faf3f94ea46049664ef483b2a3e0d3f01 Mon Sep 17 00:00:00 2001 From: Andrew Gregory Date: Sun, 16 Apr 2017 00:31:57 -0400 Subject: 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 --- doc/pacman.8.txt | 11 +++++++++-- src/pacman/conf.h | 2 ++ src/pacman/pacman.c | 24 ++++++++++++++++++------ src/pacman/util.c | 3 +++ 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* :: 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* :: + 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 set an alternate installation root\n")); addlist(_(" -v, --verbose be verbose\n")); addlist(_(" --arch set an alternate architecture\n")); + addlist(_(" --sysroot operate on a mounted guest system (root-only)\n")); addlist(_(" --cachedir set an alternate package cache location\n")); addlist(_(" --hookdir set an alternate hook location\n")); addlist(_(" --color 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; -- cgit v1.2.3-24-g4f1b