summaryrefslogtreecommitdiff
path: root/src/core/dbus-unit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/dbus-unit.c')
-rw-r--r--src/core/dbus-unit.c316
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) {