From 8aa3894eae1e4e4ee20777a684f2f77f73bbb69a Mon Sep 17 00:00:00 2001 From: Richard Phibel Date: Wed, 7 Sep 2022 03:53:09 -0700 Subject: systemctl: add support for --image option All tools that support --root= should also learn --image= so that they can operate on disk images directly. --- src/systemctl/systemctl.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) (limited to 'src/systemctl/systemctl.c') diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 56d26c43a0..430f59d496 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -7,8 +7,10 @@ #include "sd-daemon.h" #include "bus-util.h" +#include "dissect-image.h" #include "install.h" #include "main-func.h" +#include "mount-util.h" #include "output-mode.h" #include "pager.h" #include "parse-argument.h" @@ -92,6 +94,7 @@ char **arg_wall = NULL; const char *arg_kill_whom = NULL; int arg_signal = SIGTERM; char *arg_root = NULL; +char *arg_image = NULL; usec_t arg_when = 0; const char *arg_reboot_argument = NULL; enum action arg_action = ACTION_SYSTEMCTL; @@ -119,6 +122,7 @@ STATIC_DESTRUCTOR_REGISTER(_arg_job_mode, unsetp); STATIC_DESTRUCTOR_REGISTER(arg_wall, strv_freep); STATIC_DESTRUCTOR_REGISTER(arg_kill_whom, unsetp); STATIC_DESTRUCTOR_REGISTER(arg_root, freep); +STATIC_DESTRUCTOR_REGISTER(arg_image, freep); STATIC_DESTRUCTOR_REGISTER(arg_reboot_argument, unsetp); STATIC_DESTRUCTOR_REGISTER(arg_host, unsetp); STATIC_DESTRUCTOR_REGISTER(arg_boot_loader_entry, unsetp); @@ -288,6 +292,8 @@ static int systemctl_help(void) { " --preset-mode= Apply only enable, only disable, or all presets\n" " --root=PATH Edit/enable/disable/mask unit files in the specified\n" " root directory\n" + " --image=PATH Edit/enable/disable/mask unit files in the specified\n" + " image\n" " -n --lines=INTEGER Number of journal entries to show\n" " -o --output=STRING Change journal output mode (short, short-precise,\n" " short-iso, short-iso-precise, short-full,\n" @@ -402,6 +408,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { ARG_NO_PAGER, ARG_NO_WALL, ARG_ROOT, + ARG_IMAGE, ARG_NO_RELOAD, ARG_KILL_WHOM, ARG_NO_ASK_PASSWORD, @@ -457,6 +464,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { { "dry-run", no_argument, NULL, ARG_DRY_RUN }, { "quiet", no_argument, NULL, 'q' }, { "root", required_argument, NULL, ARG_ROOT }, + { "image", required_argument, NULL, ARG_IMAGE }, { "force", no_argument, NULL, 'f' }, { "no-reload", no_argument, NULL, ARG_NO_RELOAD }, { "kill-whom", required_argument, NULL, ARG_KILL_WHOM }, @@ -663,6 +671,12 @@ static int systemctl_parse_argv(int argc, char *argv[]) { return r; break; + case ARG_IMAGE: + r = parse_path_argument(optarg, false, &arg_image); + if (r < 0) + return r; + break; + case 'l': arg_full = true; break; @@ -959,6 +973,9 @@ static int systemctl_parse_argv(int argc, char *argv[]) { "List of units to restart/reload is required."); } + if (arg_image && arg_root) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --root= or --image=, the combination of both is not supported."); + return 1; } @@ -1106,13 +1123,15 @@ static int systemctl_main(int argc, char *argv[]) { const Verb *verb = verbs_find_verb(argv[optind], verbs); if (verb && (verb->flags & VERB_ONLINE_ONLY) && arg_root) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Verb '%s' cannot be used with --root=.", + "Verb '%s' cannot be used with --root= or --image=.", argv[optind] ?: verb->verb); return dispatch_verb(argc, argv, verbs, NULL); } static int run(int argc, char *argv[]) { + _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL; + _cleanup_(umount_and_rmdir_and_freep) char *mounted_dir = NULL; int r; setlocale(LC_ALL, ""); @@ -1136,6 +1155,25 @@ static int run(int argc, char *argv[]) { /* systemctl_main() will print an error message for the bus connection, but only if it needs to */ + if (arg_image) { + assert(!arg_root); + + r = mount_image_privately_interactively( + arg_image, + DISSECT_IMAGE_GENERIC_ROOT | + DISSECT_IMAGE_REQUIRE_ROOT | + DISSECT_IMAGE_RELAX_VAR_CHECK | + DISSECT_IMAGE_VALIDATE_OS, + &mounted_dir, + &loop_device); + if (r < 0) + return r; + + arg_root = strdup(mounted_dir); + if (!arg_root) + return log_oom(); + } + switch (arg_action) { case ACTION_SYSTEMCTL: -- cgit v1.2.3