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>
This commit is contained in:
Andrew Gregory 2017-04-16 00:31:57 -04:00
parent 6a4c6a02de
commit fae33a1faf
4 changed files with 32 additions and 8 deletions

View file

@ -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')
--------------------------------------------------

View file

@ -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,

View file

@ -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));

View file

@ -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;