diff options
author | Lennart Poettering <lennart@poettering.net> | 2019-04-01 18:51:49 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2019-07-11 12:18:51 +0200 |
commit | 4d3bac5645b7451e23785358e80f4b320c7fde33 (patch) | |
tree | 6d139db074ba5a39f87ff2cddcaf1c94bbb2ae66 | |
parent | 6b7b2ed96b443be7076d599c43b719a608829a67 (diff) | |
download | systemd-4d3bac5645b7451e23785358e80f4b320c7fde33.tar.gz |
core: expose new clean operation on the bus
This adds CanClean() and Clean() as new methods on the Unit object that
initiate the cleaning operation.
-rw-r--r-- | src/core/dbus-manager.c | 7 | ||||
-rw-r--r-- | src/core/dbus-unit.c | 106 | ||||
-rw-r--r-- | src/core/dbus-unit.h | 1 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-common-errors.h | 2 |
4 files changed, 116 insertions, 0 deletions
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index cdd312b9ca..9fb3ed516a 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -634,6 +634,12 @@ static int method_kill_unit(sd_bus_message *message, void *userdata, sd_bus_erro return method_generic_unit_operation(message, userdata, error, bus_unit_method_kill, 0); } +static int method_clean_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + /* Load the unit if necessary, in order to load it, and insist on the unit being loaded to be + * cleaned */ + return method_generic_unit_operation(message, userdata, error, bus_unit_method_clean, GENERIC_UNIT_LOAD|GENERIC_UNIT_VALIDATE_LOADED); +} + static int method_reset_failed_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { /* Don't load the unit (because unloaded units can't be in failed state), and don't insist on the * unit to be loaded properly (since a failed unit might have its unit file disappeared) */ @@ -2473,6 +2479,7 @@ const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("EnqueueUnitJob", "sss", "uososa(uosos)", method_enqueue_unit_job, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CleanUnit", "sas", NULL, method_clean_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetUnitProperties", "sba(sv)", NULL, method_set_unit_properties, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("RefUnit", "s", NULL, method_ref_unit, SD_BUS_VTABLE_UNPRIVILEGED), diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 0dac290bc1..53daa9c2ec 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -52,6 +52,42 @@ static BUS_DEFINE_PROPERTY_GET(property_get_can_isolate, "b", Unit, unit_can_iso static BUS_DEFINE_PROPERTY_GET(property_get_need_daemon_reload, "b", Unit, unit_need_daemon_reload); static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_empty_strv, "as", 0); +static int property_get_can_clean( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Unit *u = userdata; + ExecCleanMask mask; + int r; + + assert(bus); + assert(reply); + + r = unit_can_clean(u, &mask); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "s"); + if (r < 0) + return r; + + for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { + if (!FLAGS_SET(mask, 1U << t)) + continue; + + r = sd_bus_message_append(reply, "s", exec_resource_type_to_string(t)); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + static int property_get_names( sd_bus *bus, const char *path, @@ -617,6 +653,74 @@ int bus_unit_method_unref(sd_bus_message *message, void *userdata, sd_bus_error return sd_bus_reply_method_return(message, NULL); } +int bus_unit_method_clean(sd_bus_message *message, void *userdata, sd_bus_error *error) { + ExecCleanMask mask = 0; + Unit *u = userdata; + int r; + + assert(message); + assert(u); + + r = mac_selinux_unit_access_check(u, message, "stop", error); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(message, 'a', "s"); + if (r < 0) + return r; + + for (;;) { + const char *i; + + r = sd_bus_message_read(message, "s", &i); + if (r < 0) + return r; + if (r == 0) + break; + + if (streq(i, "all")) + mask |= EXEC_CLEAN_ALL; + else { + ExecDirectoryType t; + + t = exec_resource_type_from_string(i); + if (t < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid resource type: %s", i); + + mask |= 1U << t; + } + } + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + r = bus_verify_manage_units_async_full( + u, + "clean", + CAP_DAC_OVERRIDE, + N_("Authentication is required to delete files and directories associated with '$(unit)'."), + true, + message, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = unit_clean(u, mask); + if (r == -EOPNOTSUPP) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Unit '%s' does not supporting cleaning.", u->id); + if (r == -EUNATCH) + return sd_bus_error_setf(error, BUS_ERROR_NOTHING_TO_CLEAN, "No matching resources found."); + if (r == -EBUSY) + return sd_bus_error_setf(error, BUS_ERROR_UNIT_BUSY, "Unit is not inactive or has pending job."); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + static int property_get_refs( sd_bus *bus, const char *path, @@ -701,6 +805,7 @@ const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_PROPERTY("CanStop", "b", property_get_can_stop, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("CanReload", "b", property_get_can_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("CanIsolate", "b", property_get_can_isolate, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("CanClean", "as", property_get_can_clean, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Job", "(uo)", property_get_job, offsetof(Unit, job), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("StopWhenUnneeded", "b", bus_property_get_bool, offsetof(Unit, stop_when_unneeded), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RefuseManualStart", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_start), SD_BUS_VTABLE_PROPERTY_CONST), @@ -748,6 +853,7 @@ const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_METHOD("SetProperties", "ba(sv)", NULL, bus_unit_method_set_properties, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Ref", NULL, NULL, bus_unit_method_ref, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Unref", NULL, NULL, bus_unit_method_unref, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Clean", "as", NULL, bus_unit_method_clean, SD_BUS_VTABLE_UNPRIVILEGED), /* For dependency types we don't support anymore always return an empty array */ SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN), diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h index 740bb1c86b..24abf3c088 100644 --- a/src/core/dbus-unit.h +++ b/src/core/dbus-unit.h @@ -25,6 +25,7 @@ int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bu int bus_unit_method_attach_processes(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_unit_method_ref(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_unit_method_unref(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_unit_method_clean(sd_bus_message *message, void *userdata, sd_bus_error *error); typedef enum BusUnitQueueFlags { BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE = 1 << 0, diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h index 296579116c..4a29b3bea8 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.h +++ b/src/libsystemd/sd-bus/bus-common-errors.h @@ -27,6 +27,8 @@ #define BUS_ERROR_NO_SUCH_DYNAMIC_USER "org.freedesktop.systemd1.NoSuchDynamicUser" #define BUS_ERROR_NOT_REFERENCED "org.freedesktop.systemd1.NotReferenced" #define BUS_ERROR_DISK_FULL "org.freedesktop.systemd1.DiskFull" +#define BUS_ERROR_NOTHING_TO_CLEAN "org.freedesktop.systemd1.NothingToClean" +#define BUS_ERROR_UNIT_BUSY "org.freedesktop.systemd1.UnitBusy" #define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine" #define BUS_ERROR_NO_SUCH_IMAGE "org.freedesktop.machine1.NoSuchImage" |