1
0
mirror of https://github.com/systemd/systemd.git synced 2025-08-03 08:22:21 +03:00

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.
This commit is contained in:
Lennart Poettering
2019-04-01 18:51:49 +02:00
parent 6b7b2ed96b
commit 4d3bac5645
4 changed files with 116 additions and 0 deletions

View File

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

View File

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

View File

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

View File

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