diff options
Diffstat (limited to 'src/core/dbus-unit.c')
-rw-r--r-- | src/core/dbus-unit.c | 316 |
1 files changed, 78 insertions, 238 deletions
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 50a5ab9819..ae0410414e 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2010 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ #include "sd-bus.h" @@ -42,10 +24,32 @@ #include "user-util.h" #include "web-util.h" +static bool unit_can_start_refuse_manual(Unit *u) { + return unit_can_start(u) && !u->refuse_manual_start; +} + +static bool unit_can_stop_refuse_manual(Unit *u) { + return unit_can_stop(u) && !u->refuse_manual_stop; +} + +static bool unit_can_isolate_refuse_manual(Unit *u) { + return unit_can_isolate(u) && !u->refuse_manual_start; +} + static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_collect_mode, collect_mode, CollectMode); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_job_mode, job_mode, JobMode); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction); +static BUS_DEFINE_PROPERTY_GET(property_get_description, "s", Unit, unit_description); +static BUS_DEFINE_PROPERTY_GET2(property_get_active_state, "s", Unit, unit_active_state, unit_active_state_to_string); +static BUS_DEFINE_PROPERTY_GET(property_get_sub_state, "s", Unit, unit_sub_state_to_string); +static BUS_DEFINE_PROPERTY_GET2(property_get_unit_file_state, "s", Unit, unit_get_unit_file_state, unit_file_state_to_string); +static BUS_DEFINE_PROPERTY_GET(property_get_can_reload, "b", Unit, unit_can_reload); +static BUS_DEFINE_PROPERTY_GET(property_get_can_start, "b", Unit, unit_can_start_refuse_manual); +static BUS_DEFINE_PROPERTY_GET(property_get_can_stop, "b", Unit, unit_can_stop_refuse_manual); +static BUS_DEFINE_PROPERTY_GET(property_get_can_isolate, "b", Unit, unit_can_isolate_refuse_manual); +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_names( sd_bus *bus, @@ -56,20 +60,20 @@ static int property_get_names( void *userdata, sd_bus_error *error) { - Unit *u = userdata; + Set **s = userdata; Iterator i; const char *t; int r; assert(bus); assert(reply); - assert(u); + assert(s); r = sd_bus_message_open_container(reply, 'a', "s"); if (r < 0) return r; - SET_FOREACH(t, u->names, i) { + SET_FOREACH(t, *s, i) { r = sd_bus_message_append(reply, "s", t); if (r < 0) return r; @@ -94,7 +98,7 @@ static int property_get_following( assert(u); f = unit_following(u); - return sd_bus_message_append(reply, "s", f ? f->id : ""); + return sd_bus_message_append(reply, "s", f ? f->id : NULL); } static int property_get_dependencies( @@ -106,7 +110,7 @@ static int property_get_dependencies( void *userdata, sd_bus_error *error) { - Hashmap *h = *(Hashmap**) userdata; + Hashmap **h = userdata; Iterator j; Unit *u; void *v; @@ -114,12 +118,13 @@ static int property_get_dependencies( assert(bus); assert(reply); + assert(h); r = sd_bus_message_open_container(reply, 'a', "s"); if (r < 0) return r; - HASHMAP_FOREACH_KEY(v, u, h, j) { + HASHMAP_FOREACH_KEY(v, u, *h, j) { r = sd_bus_message_append(reply, "s", u->id); if (r < 0) return r; @@ -128,22 +133,6 @@ static int property_get_dependencies( return sd_bus_message_close_container(reply); } -static int property_get_obsolete_dependencies( - sd_bus *bus, - const char *path, - const char *interface, - const char *property, - sd_bus_message *reply, - void *userdata, - sd_bus_error *error) { - - assert(bus); - assert(reply); - - /* For dependency types we don't support anymore always return an empty array */ - return sd_bus_message_append(reply, "as", 0); -} - static int property_get_requires_mounts_for( sd_bus *bus, const char *path, @@ -153,7 +142,7 @@ static int property_get_requires_mounts_for( void *userdata, sd_bus_error *error) { - Hashmap *h = *(Hashmap**) userdata; + Hashmap **h = userdata; const char *p; Iterator j; void *v; @@ -161,12 +150,13 @@ static int property_get_requires_mounts_for( assert(bus); assert(reply); + assert(h); r = sd_bus_message_open_container(reply, 'a', "s"); if (r < 0) return r; - HASHMAP_FOREACH_KEY(v, p, h, j) { + HASHMAP_FOREACH_KEY(v, p, *h, j) { r = sd_bus_message_append(reply, "s", p); if (r < 0) return r; @@ -175,60 +165,6 @@ static int property_get_requires_mounts_for( return sd_bus_message_close_container(reply); } -static int property_get_description( - 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; - - assert(bus); - assert(reply); - assert(u); - - return sd_bus_message_append(reply, "s", unit_description(u)); -} - -static int property_get_active_state( - 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; - - assert(bus); - assert(reply); - assert(u); - - return sd_bus_message_append(reply, "s", unit_active_state_to_string(unit_active_state(u))); -} - -static int property_get_sub_state( - 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; - - assert(bus); - assert(reply); - assert(u); - - return sd_bus_message_append(reply, "s", unit_sub_state_to_string(u)); -} - static int property_get_unit_file_preset( sd_bus *bus, const char *path, @@ -248,100 +184,10 @@ static int property_get_unit_file_preset( r = unit_get_unit_file_preset(u); return sd_bus_message_append(reply, "s", - r < 0 ? "": + r < 0 ? NULL: r > 0 ? "enabled" : "disabled"); } -static int property_get_unit_file_state( - 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; - - assert(bus); - assert(reply); - assert(u); - - return sd_bus_message_append(reply, "s", unit_file_state_to_string(unit_get_unit_file_state(u))); -} - -static int property_get_can_start( - 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; - - assert(bus); - assert(reply); - assert(u); - - return sd_bus_message_append(reply, "b", unit_can_start(u) && !u->refuse_manual_start); -} - -static int property_get_can_stop( - 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; - - assert(bus); - assert(reply); - assert(u); - - return sd_bus_message_append(reply, "b", unit_can_stop(u) && !u->refuse_manual_stop); -} - -static int property_get_can_reload( - 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; - - assert(bus); - assert(reply); - assert(u); - - return sd_bus_message_append(reply, "b", unit_can_reload(u)); -} - -static int property_get_can_isolate( - 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; - - assert(bus); - assert(reply); - assert(u); - - return sd_bus_message_append(reply, "b", unit_can_isolate(u) && !u->refuse_manual_start); -} - static int property_get_job( sd_bus *bus, const char *path, @@ -352,38 +198,20 @@ static int property_get_job( sd_bus_error *error) { _cleanup_free_ char *p = NULL; - Unit *u = userdata; + Job **j = userdata; assert(bus); assert(reply); - assert(u); + assert(j); - if (!u->job) + if (!*j) return sd_bus_message_append(reply, "(uo)", 0, "/"); - p = job_dbus_path(u->job); + p = job_dbus_path(*j); if (!p) return -ENOMEM; - return sd_bus_message_append(reply, "(uo)", u->job->id, p); -} - -static int property_get_need_daemon_reload( - 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; - - assert(bus); - assert(reply); - assert(u); - - return sd_bus_message_append(reply, "b", unit_need_daemon_reload(u)); + return sd_bus_message_append(reply, "(uo)", (*j)->id, p); } static int property_get_conditions( @@ -439,15 +267,17 @@ static int property_get_load_error( _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL; Unit *u = userdata; + int r; assert(bus); assert(reply); assert(u); - if (u->load_error != 0) - sd_bus_error_set_errno(&e, u->load_error); + r = bus_unit_validate_load_state(u, &e); + if (r < 0) + return sd_bus_message_append(reply, "(ss)", e.name, e.message); - return sd_bus_message_append(reply, "(ss)", e.name, e.message); + return sd_bus_message_append(reply, "(ss)", NULL, NULL); } static int bus_verify_manage_units_async_full( @@ -735,7 +565,7 @@ const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Unit, id), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Names", "as", property_get_names, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Names", "as", property_get_names, offsetof(Unit, names), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Following", "s", property_get_following, 0, 0), SD_BUS_PROPERTY("Requires", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Requisite", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE]), SD_BUS_VTABLE_PROPERTY_CONST), @@ -777,7 +607,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("Job", "(uo)", property_get_job, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + 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), SD_BUS_PROPERTY("RefuseManualStop", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_stop), SD_BUS_VTABLE_PROPERTY_CONST), @@ -821,11 +651,12 @@ const sd_bus_vtable bus_unit_vtable[] = { 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), - /* Obsolete properties or obsolete alias names */ - SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN), - SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN), - SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN), - SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN), + /* 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), + SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN), + /* Obsolete alias names */ SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), SD_BUS_VTABLE_END @@ -931,7 +762,7 @@ static int property_get_cgroup( sd_bus_error *error) { Unit *u = userdata; - const char *t; + const char *t = NULL; assert(bus); assert(reply); @@ -944,9 +775,7 @@ static int property_get_cgroup( * other cases we report as-is. */ if (u->cgroup_path) - t = isempty(u->cgroup_path) ? "/" : u->cgroup_path; - else - t = ""; + t = empty_to_root(u->cgroup_path); return sd_bus_message_append(reply, "s", t); } @@ -992,7 +821,7 @@ static int append_cgroup(sd_bus_message *reply, const char *p, Set *pids) { assert(p); r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, p, &f); - if (r == ENOENT) + if (r == -ENOENT) return 0; if (r < 0) return r; @@ -1043,7 +872,7 @@ static int append_cgroup(sd_bus_message *reply, const char *p, Set *pids) { int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - _cleanup_(set_freep) Set *pids = NULL; + _cleanup_set_free_ Set *pids = NULL; Unit *u = userdata; pid_t pid; int r; @@ -1130,7 +959,7 @@ static int property_get_ip_counter( int bus_unit_method_attach_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; - _cleanup_(set_freep) Set *pids = NULL; + _cleanup_set_free_ Set *pids = NULL; Unit *u = userdata; const char *path; int r; @@ -1408,7 +1237,7 @@ int bus_unit_queue_job( } if (type == JOB_STOP && - (IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_ERROR)) && + IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_ERROR, UNIT_BAD_SETTING) && unit_active_state(u) == UNIT_INACTIVE) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id); @@ -1880,22 +1709,33 @@ int bus_unit_set_properties( return n; } -int bus_unit_check_load_state(Unit *u, sd_bus_error *error) { +int bus_unit_validate_load_state(Unit *u, sd_bus_error *error) { assert(u); - if (u->load_state == UNIT_LOADED) - return 0; + /* Generates a pretty error if a unit isn't properly loaded. */ - /* Give a better description of the unit error when - * possible. Note that in the case of UNIT_MASKED, load_error - * is not set. */ - if (u->load_state == UNIT_MASKED) - return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit %s is masked.", u->id); + switch (u->load_state) { + + case UNIT_LOADED: + return 0; - if (u->load_state == UNIT_NOT_FOUND) + case UNIT_NOT_FOUND: return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not found.", u->id); - return sd_bus_error_set_errnof(error, u->load_error, "Unit %s is not loaded properly: %m.", u->id); + case UNIT_BAD_SETTING: + return sd_bus_error_setf(error, BUS_ERROR_BAD_UNIT_SETTING, "Unit %s has a bad unit file setting.", u->id); + + case UNIT_ERROR: /* Only show .load_error in UNIT_ERROR state */ + return sd_bus_error_set_errnof(error, u->load_error, "Unit %s failed to loaded properly: %m.", u->id); + + case UNIT_MASKED: + return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit %s is masked.", u->id); + + case UNIT_STUB: + case UNIT_MERGED: + default: + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unexpected load state of unit %s", u->id); + } } static int bus_unit_track_handler(sd_bus_track *t, void *userdata) { |