summaryrefslogtreecommitdiffstats
path: root/src/portable/portablectl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/portable/portablectl.c')
-rw-r--r--src/portable/portablectl.c77
1 files changed, 66 insertions, 11 deletions
diff --git a/src/portable/portablectl.c b/src/portable/portablectl.c
index 1588b17..57b930d 100644
--- a/src/portable/portablectl.c
+++ b/src/portable/portablectl.c
@@ -50,6 +50,7 @@ static bool arg_now = false;
static bool arg_no_block = false;
static char **arg_extension_images = NULL;
static bool arg_force = false;
+static bool arg_clean = false;
STATIC_DESTRUCTOR_REGISTER(arg_extension_images, strv_freep);
@@ -769,13 +770,49 @@ static int maybe_stop_enable_restart(sd_bus *bus, sd_bus_message *reply) {
return 0;
}
-static int maybe_stop_disable(sd_bus *bus, char *image, char *argv[]) {
+static int maybe_clean_units(sd_bus *bus, char **units) {
+ int r;
+
+ assert(bus);
+
+ if (!arg_clean)
+ return 0;
+
+ STRV_FOREACH(name, units) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+
+ r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "CleanUnit");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(m, "s", *name);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append_strv(m, STRV_MAKE("all", "fdstore"));
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_call(bus, m, 0, &error, NULL);
+ if (r < 0)
+ return log_error_errno(
+ r,
+ "Failed to call CleanUnit on portable service %s: %s",
+ *name,
+ bus_error_message(&error, r));
+ }
+
+ return 0;
+}
+
+static int maybe_stop_disable_clean(sd_bus *bus, char *image, char *argv[]) {
_cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *wait = NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_strv_free_ char **matches = NULL;
+ _cleanup_strv_free_ char **matches = NULL, **units = NULL;
int r;
- if (!arg_enable && !arg_now)
+ if (!arg_enable && !arg_now && !arg_clean)
return 0;
r = determine_matches(argv[1], argv + 2, true, &matches);
@@ -829,6 +866,10 @@ static int maybe_stop_disable(sd_bus *bus, char *image, char *argv[]) {
(void) maybe_start_stop_restart(bus, name, "StopUnit", wait);
(void) maybe_enable_disable(bus, name, false);
+
+ r = strv_extend(&units, name);
+ if (r < 0)
+ return log_oom();
}
r = sd_bus_message_exit_container(reply);
@@ -840,6 +881,9 @@ static int maybe_stop_disable(sd_bus *bus, char *image, char *argv[]) {
if (r < 0)
return r;
+ /* Need to ensure all units are stopped before calling CleanUnit, as files might be in use. */
+ (void) maybe_clean_units(bus, units);
+
return 0;
}
@@ -942,7 +986,7 @@ static int detach_image(int argc, char *argv[], void *userdata) {
(void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
- (void) maybe_stop_disable(bus, image, argv);
+ (void) maybe_stop_disable_clean(bus, image, argv);
method = strv_isempty(arg_extension_images) && !arg_force ? "DetachImage" : "DetachImageWithExtensions";
@@ -1030,7 +1074,7 @@ static int list_images(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_parse_error(r);
- if (table_get_rows(table) > 1) {
+ if (!table_isempty(table)) {
r = table_set_sort(table, (size_t) 0);
if (r < 0)
return table_log_sort_error(r);
@@ -1043,10 +1087,10 @@ static int list_images(int argc, char *argv[], void *userdata) {
}
if (arg_legend) {
- if (table_get_rows(table) > 1)
- printf("\n%zu images listed.\n", table_get_rows(table) - 1);
- else
+ if (table_isempty(table))
printf("No images.\n");
+ else
+ printf("\n%zu images listed.\n", table_get_rows(table) - 1);
}
return 0;
@@ -1251,7 +1295,8 @@ static int help(int argc, char *argv[], void *userdata) {
" -M --machine=CONTAINER Operate on local container\n"
" -q --quiet Suppress informational messages\n"
" -p --profile=PROFILE Pick security profile for portable service\n"
- " --copy=copy|auto|symlink Prefer copying or symlinks if possible\n"
+ " --copy=copy|auto|symlink|mixed\n"
+ " Pick copying or symlinking of resources\n"
" --runtime Attach portable service until next reboot only\n"
" --no-reload Don't reload the system and service manager\n"
" --cat When inspecting include unit and os-release file\n"
@@ -1264,6 +1309,9 @@ static int help(int argc, char *argv[], void *userdata) {
" --extension=PATH Extend the image with an overlay\n"
" --force Skip 'already active' check when attaching or\n"
" detaching an image (with extensions)\n"
+ " --clean When detaching, also remove configuration, state,\n"
+ " cache, logs or runtime data of the portable\n"
+ " service(s)\n"
"\nSee the %s for details.\n",
program_invocation_short_name,
ansi_highlight(),
@@ -1290,6 +1338,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_NO_BLOCK,
ARG_EXTENSION,
ARG_FORCE,
+ ARG_CLEAN,
};
static const struct option options[] = {
@@ -1311,6 +1360,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "no-block", no_argument, NULL, ARG_NO_BLOCK },
{ "extension", required_argument, NULL, ARG_EXTENSION },
{ "force", no_argument, NULL, ARG_FORCE },
+ { "clean", no_argument, NULL, ARG_CLEAN },
{}
};
@@ -1372,12 +1422,13 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_COPY:
if (streq(optarg, "auto"))
arg_copy_mode = NULL;
- else if (STR_IN_SET(optarg, "copy", "symlink"))
+ else if (STR_IN_SET(optarg, "copy", "symlink", "mixed"))
arg_copy_mode = optarg;
else if (streq(optarg, "help")) {
puts("auto\n"
"copy\n"
- "symlink");
+ "symlink\n"
+ "mixed\n");
return 0;
} else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
@@ -1419,6 +1470,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_force = true;
break;
+ case ARG_CLEAN:
+ arg_clean = true;
+ break;
+
case '?':
return -EINVAL;