2010-08-14 19:59:25 +02:00
|
|
|
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
2010-02-01 03:33:24 +01:00
|
|
|
|
2010-02-03 13:03:47 +01:00
|
|
|
/***
|
|
|
|
This file is part of systemd.
|
|
|
|
|
|
|
|
Copyright 2010 Lennart Poettering
|
|
|
|
|
|
|
|
systemd is free software; you can redistribute it and/or modify it
|
2012-04-12 00:20:58 +02:00
|
|
|
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
|
2010-02-03 13:03:47 +01:00
|
|
|
(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
|
2012-04-12 00:20:58 +02:00
|
|
|
Lesser General Public License for more details.
|
2010-02-03 13:03:47 +01:00
|
|
|
|
2012-04-12 00:20:58 +02:00
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
2010-02-03 13:03:47 +01:00
|
|
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
***/
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
#include "sd-bus.h"
|
2010-02-01 03:33:24 +01:00
|
|
|
#include "log.h"
|
2012-09-06 22:23:11 +02:00
|
|
|
#include "selinux-access.h"
|
2013-01-12 04:24:12 +01:00
|
|
|
#include "cgroup-util.h"
|
|
|
|
#include "strv.h"
|
2014-12-10 19:00:46 +01:00
|
|
|
#include "bus-common-errors.h"
|
2014-03-03 01:33:45 +01:00
|
|
|
#include "dbus.h"
|
|
|
|
#include "dbus-unit.h"
|
2013-11-19 21:12:59 +01:00
|
|
|
|
|
|
|
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState);
|
2013-11-26 01:39:53 +01:00
|
|
|
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_job_mode, job_mode, JobMode);
|
2014-10-28 01:49:07 +01:00
|
|
|
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_failure_action, failure_action, FailureAction);
|
2013-11-19 21:12:59 +01:00
|
|
|
|
|
|
|
static int property_get_names(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2013-11-19 21:12:59 +01:00
|
|
|
|
|
|
|
Unit *u = userdata;
|
|
|
|
Iterator i;
|
|
|
|
const char *t;
|
|
|
|
int r;
|
2010-02-01 03:33:24 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
|
|
|
assert(u);
|
2010-04-18 03:08:16 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_open_container(reply, 'a', "s");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2010-04-18 03:08:16 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
SET_FOREACH(t, u->names, i) {
|
|
|
|
r = sd_bus_message_append(reply, "s", t);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
}
|
2010-04-18 03:08:16 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
return sd_bus_message_close_container(reply);
|
2010-04-18 03:08:16 +02:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int property_get_following(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2013-11-19 21:12:59 +01:00
|
|
|
|
|
|
|
Unit *u = userdata, *f;
|
2010-07-20 20:33:19 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
2010-07-20 20:33:19 +02:00
|
|
|
assert(u);
|
|
|
|
|
2010-07-21 05:00:29 +02:00
|
|
|
f = unit_following(u);
|
2013-11-19 21:12:59 +01:00
|
|
|
return sd_bus_message_append(reply, "s", f ? f->id : "");
|
2010-07-20 20:33:19 +02:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int property_get_dependencies(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2013-06-18 01:00:13 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
Set *s = *(Set**) userdata;
|
2010-05-16 16:20:24 +02:00
|
|
|
Iterator j;
|
2013-11-19 21:12:59 +01:00
|
|
|
Unit *u;
|
|
|
|
int r;
|
2010-05-16 16:20:24 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
2010-05-16 16:20:24 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_open_container(reply, 'a', "s");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2010-05-16 16:20:24 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
SET_FOREACH(u, s, j) {
|
|
|
|
r = sd_bus_message_append(reply, "s", u->id);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
}
|
2010-05-16 16:20:24 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
return sd_bus_message_close_container(reply);
|
2010-05-16 16:20:24 +02:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int property_get_description(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2010-02-01 03:33:24 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
Unit *u = userdata;
|
2010-02-01 03:33:24 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
|
|
|
assert(u);
|
2010-02-01 03:33:24 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
return sd_bus_message_append(reply, "s", unit_description(u));
|
2010-02-01 03:33:24 +01:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int property_get_active_state(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2010-02-01 03:33:24 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
Unit *u = userdata;
|
2010-02-01 03:33:24 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
2010-02-01 03:33:24 +01:00
|
|
|
assert(u);
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
return sd_bus_message_append(reply, "s", unit_active_state_to_string(unit_active_state(u)));
|
2010-02-01 03:33:24 +01:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int property_get_sub_state(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2010-04-13 20:59:01 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
Unit *u = userdata;
|
2010-04-13 20:59:01 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
|
|
|
assert(u);
|
2010-04-13 20:59:01 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
return sd_bus_message_append(reply, "s", unit_sub_state_to_string(u));
|
2010-04-13 20:59:01 +02:00
|
|
|
}
|
|
|
|
|
2014-12-02 02:38:18 +01:00
|
|
|
static int property_get_unit_file_preset(
|
|
|
|
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;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
|
|
|
assert(u);
|
|
|
|
|
|
|
|
r = unit_get_unit_file_preset(u);
|
|
|
|
|
|
|
|
return sd_bus_message_append(reply, "s",
|
|
|
|
r < 0 ? "":
|
|
|
|
r > 0 ? "enabled" : "disabled");
|
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int property_get_unit_file_state(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2011-07-31 18:28:02 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
Unit *u = userdata;
|
2011-07-31 18:28:02 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
|
|
|
assert(u);
|
2011-07-31 18:28:02 +02:00
|
|
|
|
2014-12-10 19:57:45 +01:00
|
|
|
return sd_bus_message_append(reply, "s", unit_file_state_to_string(unit_get_unit_file_state(u)));
|
2011-07-31 18:28:02 +02:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int property_get_can_start(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2010-02-02 12:22:59 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
Unit *u = userdata;
|
2010-08-10 20:57:21 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
|
|
|
assert(u);
|
2010-08-10 20:57:21 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
return sd_bus_message_append(reply, "b", unit_can_start(u) && !u->refuse_manual_start);
|
2010-08-10 20:57:21 +02:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int property_get_can_stop(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2013-11-19 21:12:59 +01:00
|
|
|
|
|
|
|
Unit *u = userdata;
|
2010-08-10 20:57:21 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
2010-08-10 20:57:21 +02:00
|
|
|
assert(u);
|
|
|
|
|
|
|
|
/* On the lower levels we assume that every unit we can start
|
|
|
|
* we can also stop */
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
return sd_bus_message_append(reply, "b", unit_can_start(u) && !u->refuse_manual_stop);
|
2010-02-02 12:22:59 +01:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int property_get_can_reload(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2010-02-02 12:22:59 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
Unit *u = userdata;
|
2010-02-02 12:22:59 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
|
|
|
assert(u);
|
2010-02-02 12:22:59 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
return sd_bus_message_append(reply, "b", unit_can_reload(u));
|
2010-02-02 12:22:59 +01:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int property_get_can_isolate(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2010-08-30 22:45:46 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
Unit *u = userdata;
|
2010-08-30 22:45:46 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
|
|
|
assert(u);
|
2010-08-30 22:45:46 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
return sd_bus_message_append(reply, "b", unit_can_isolate(u) && !u->refuse_manual_start);
|
2010-08-30 22:45:46 +02:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int property_get_job(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2013-11-19 21:12:59 +01:00
|
|
|
|
2013-01-02 22:19:07 +01:00
|
|
|
_cleanup_free_ char *p = NULL;
|
2013-11-19 21:12:59 +01:00
|
|
|
Unit *u = userdata;
|
2010-02-02 12:22:59 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
2010-02-02 12:22:59 +01:00
|
|
|
assert(u);
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
if (!u->job)
|
|
|
|
return sd_bus_message_append(reply, "(uo)", 0, "/");
|
2010-02-02 12:22:59 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
p = job_dbus_path(u->job);
|
|
|
|
if (!p)
|
|
|
|
return -ENOMEM;
|
2010-02-02 12:22:59 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
return sd_bus_message_append(reply, "(uo)", u->job->id, p);
|
|
|
|
}
|
2010-02-02 12:22:59 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int property_get_need_daemon_reload(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2010-02-02 12:22:59 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
Unit *u = userdata;
|
2010-02-02 12:22:59 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
|
|
|
assert(u);
|
2010-02-02 12:22:59 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
return sd_bus_message_append(reply, "b", unit_need_daemon_reload(u));
|
2010-02-02 12:22:59 +01:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int property_get_conditions(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2010-07-17 00:57:51 +02:00
|
|
|
|
2014-11-06 13:43:45 +01:00
|
|
|
const char *(*to_string)(ConditionType type) = NULL;
|
|
|
|
Condition **list = userdata, *c;
|
2013-11-19 21:12:59 +01:00
|
|
|
int r;
|
2010-07-17 00:57:51 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
2014-11-06 13:43:45 +01:00
|
|
|
assert(list);
|
|
|
|
|
|
|
|
to_string = streq(property, "Asserts") ? assert_type_to_string : condition_type_to_string;
|
2010-07-17 00:57:51 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_open_container(reply, 'a', "(sbbsi)");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2010-07-17 00:57:51 +02:00
|
|
|
|
2014-11-06 13:43:45 +01:00
|
|
|
LIST_FOREACH(conditions, c, *list) {
|
2014-11-06 02:27:10 +01:00
|
|
|
int tristate;
|
|
|
|
|
|
|
|
tristate =
|
|
|
|
c->result == CONDITION_UNTESTED ? 0 :
|
|
|
|
c->result == CONDITION_SUCCEEDED ? 1 : -1;
|
|
|
|
|
2013-11-25 17:18:38 +01:00
|
|
|
r = sd_bus_message_append(reply, "(sbbsi)",
|
2014-11-06 13:43:45 +01:00
|
|
|
to_string(c->type),
|
2013-11-25 17:18:38 +01:00
|
|
|
c->trigger, c->negate,
|
2014-11-06 02:27:10 +01:00
|
|
|
c->parameter, tristate);
|
2013-11-19 21:12:59 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2010-07-17 00:57:51 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
}
|
systemd,systemctl: export condition status and show failing condition
$ systemctl --user status hoohoo
hoohoo.service
Loaded: loaded (/home/zbyszek/.config/systemd/user/hoohoo.service; static)
Active: inactive (dead)
start condition failed at Tue 2013-06-25 18:08:42 EDT; 1s ago
ConditionPathExists=/tmp/hoo was not met
Full information is exported over D-Bus:
[(condition, trigger, negate, param, state),...]
where state is one of "failed" (<0), "untested" (0), "OK" (>0).
I've decided to use 0 for "untested", because it might be useful to
differentiate different types of failure later on, without breaking
compatibility.
systemctl shows the failing condition, if there was a non-trigger
failing condition, or says "none of the trigger conditions were met",
because there're often many trigger conditions, and they must all
fail for the condition to fail, so printing them all would consume
a lot of space, and bring unnecessary attention to something that is
quite low-level.
2013-06-25 22:09:07 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
return sd_bus_message_close_container(reply);
|
systemd,systemctl: export condition status and show failing condition
$ systemctl --user status hoohoo
hoohoo.service
Loaded: loaded (/home/zbyszek/.config/systemd/user/hoohoo.service; static)
Active: inactive (dead)
start condition failed at Tue 2013-06-25 18:08:42 EDT; 1s ago
ConditionPathExists=/tmp/hoo was not met
Full information is exported over D-Bus:
[(condition, trigger, negate, param, state),...]
where state is one of "failed" (<0), "untested" (0), "OK" (>0).
I've decided to use 0 for "untested", because it might be useful to
differentiate different types of failure later on, without breaking
compatibility.
systemctl shows the failing condition, if there was a non-trigger
failing condition, or says "none of the trigger conditions were met",
because there're often many trigger conditions, and they must all
fail for the condition to fail, so printing them all would consume
a lot of space, and bring unnecessary attention to something that is
quite low-level.
2013-06-25 22:09:07 +02:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int property_get_load_error(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
systemd,systemctl: export condition status and show failing condition
$ systemctl --user status hoohoo
hoohoo.service
Loaded: loaded (/home/zbyszek/.config/systemd/user/hoohoo.service; static)
Active: inactive (dead)
start condition failed at Tue 2013-06-25 18:08:42 EDT; 1s ago
ConditionPathExists=/tmp/hoo was not met
Full information is exported over D-Bus:
[(condition, trigger, negate, param, state),...]
where state is one of "failed" (<0), "untested" (0), "OK" (>0).
I've decided to use 0 for "untested", because it might be useful to
differentiate different types of failure later on, without breaking
compatibility.
systemctl shows the failing condition, if there was a non-trigger
failing condition, or says "none of the trigger conditions were met",
because there're often many trigger conditions, and they must all
fail for the condition to fail, so printing them all would consume
a lot of space, and bring unnecessary attention to something that is
quite low-level.
2013-06-25 22:09:07 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
_cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
|
|
|
|
Unit *u = userdata;
|
systemd,systemctl: export condition status and show failing condition
$ systemctl --user status hoohoo
hoohoo.service
Loaded: loaded (/home/zbyszek/.config/systemd/user/hoohoo.service; static)
Active: inactive (dead)
start condition failed at Tue 2013-06-25 18:08:42 EDT; 1s ago
ConditionPathExists=/tmp/hoo was not met
Full information is exported over D-Bus:
[(condition, trigger, negate, param, state),...]
where state is one of "failed" (<0), "untested" (0), "OK" (>0).
I've decided to use 0 for "untested", because it might be useful to
differentiate different types of failure later on, without breaking
compatibility.
systemctl shows the failing condition, if there was a non-trigger
failing condition, or says "none of the trigger conditions were met",
because there're often many trigger conditions, and they must all
fail for the condition to fail, so printing them all would consume
a lot of space, and bring unnecessary attention to something that is
quite low-level.
2013-06-25 22:09:07 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
|
|
|
assert(u);
|
systemd,systemctl: export condition status and show failing condition
$ systemctl --user status hoohoo
hoohoo.service
Loaded: loaded (/home/zbyszek/.config/systemd/user/hoohoo.service; static)
Active: inactive (dead)
start condition failed at Tue 2013-06-25 18:08:42 EDT; 1s ago
ConditionPathExists=/tmp/hoo was not met
Full information is exported over D-Bus:
[(condition, trigger, negate, param, state),...]
where state is one of "failed" (<0), "untested" (0), "OK" (>0).
I've decided to use 0 for "untested", because it might be useful to
differentiate different types of failure later on, without breaking
compatibility.
systemctl shows the failing condition, if there was a non-trigger
failing condition, or says "none of the trigger conditions were met",
because there're often many trigger conditions, and they must all
fail for the condition to fail, so printing them all would consume
a lot of space, and bring unnecessary attention to something that is
quite low-level.
2013-06-25 22:09:07 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
if (u->load_error != 0)
|
|
|
|
sd_bus_error_set_errno(&e, u->load_error);
|
systemd,systemctl: export condition status and show failing condition
$ systemctl --user status hoohoo
hoohoo.service
Loaded: loaded (/home/zbyszek/.config/systemd/user/hoohoo.service; static)
Active: inactive (dead)
start condition failed at Tue 2013-06-25 18:08:42 EDT; 1s ago
ConditionPathExists=/tmp/hoo was not met
Full information is exported over D-Bus:
[(condition, trigger, negate, param, state),...]
where state is one of "failed" (<0), "untested" (0), "OK" (>0).
I've decided to use 0 for "untested", because it might be useful to
differentiate different types of failure later on, without breaking
compatibility.
systemctl shows the failing condition, if there was a non-trigger
failing condition, or says "none of the trigger conditions were met",
because there're often many trigger conditions, and they must all
fail for the condition to fail, so printing them all would consume
a lot of space, and bring unnecessary attention to something that is
quite low-level.
2013-06-25 22:09:07 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
return sd_bus_message_append(reply, "(ss)", e.name, e.message);
|
systemd,systemctl: export condition status and show failing condition
$ systemctl --user status hoohoo
hoohoo.service
Loaded: loaded (/home/zbyszek/.config/systemd/user/hoohoo.service; static)
Active: inactive (dead)
start condition failed at Tue 2013-06-25 18:08:42 EDT; 1s ago
ConditionPathExists=/tmp/hoo was not met
Full information is exported over D-Bus:
[(condition, trigger, negate, param, state),...]
where state is one of "failed" (<0), "untested" (0), "OK" (>0).
I've decided to use 0 for "untested", because it might be useful to
differentiate different types of failure later on, without breaking
compatibility.
systemctl shows the failing condition, if there was a non-trigger
failing condition, or says "none of the trigger conditions were met",
because there're often many trigger conditions, and they must all
fail for the condition to fail, so printing them all would consume
a lot of space, and bring unnecessary attention to something that is
quite low-level.
2013-06-25 22:09:07 +02:00
|
|
|
}
|
|
|
|
|
2015-02-18 17:40:57 +01:00
|
|
|
int bus_unit_method_start_generic(
|
|
|
|
sd_bus *bus,
|
|
|
|
sd_bus_message *message,
|
|
|
|
Unit *u,
|
|
|
|
JobType job_type,
|
|
|
|
bool reload_if_possible,
|
|
|
|
sd_bus_error *error) {
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
const char *smode;
|
|
|
|
JobMode mode;
|
|
|
|
int r;
|
2011-07-31 18:13:03 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(message);
|
2011-07-31 18:13:03 +02:00
|
|
|
assert(u);
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(job_type >= 0 && job_type < _JOB_TYPE_MAX);
|
2011-07-31 18:13:03 +02:00
|
|
|
|
2015-02-18 17:40:57 +01:00
|
|
|
r = mac_selinux_unit_access_check(u, message, job_type == JOB_STOP ? "stop" : "start", error);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_read(message, "s", &smode);
|
|
|
|
if (r < 0)
|
2013-11-21 19:34:37 +01:00
|
|
|
return r;
|
2011-07-31 18:13:03 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
mode = job_mode_from_string(smode);
|
|
|
|
if (mode < 0)
|
2013-11-21 19:34:37 +01:00
|
|
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s invalid", smode);
|
2011-07-31 18:13:03 +02:00
|
|
|
|
2015-02-18 17:40:57 +01:00
|
|
|
r = bus_verify_manage_units_async(u->manager, 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 */
|
|
|
|
|
2013-11-21 19:34:37 +01:00
|
|
|
return bus_unit_queue_job(bus, message, u, job_type, mode, reload_if_possible, error);
|
2011-07-31 18:13:03 +02:00
|
|
|
}
|
|
|
|
|
2013-11-21 19:34:37 +01:00
|
|
|
static int method_start(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
|
|
|
return bus_unit_method_start_generic(bus, message, userdata, JOB_START, false, error);
|
2013-11-19 21:12:59 +01:00
|
|
|
}
|
2010-02-03 12:37:42 +01:00
|
|
|
|
2013-11-21 19:34:37 +01:00
|
|
|
static int method_stop(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
|
|
|
return bus_unit_method_start_generic(bus, message, userdata, JOB_STOP, false, error);
|
2013-11-19 21:12:59 +01:00
|
|
|
}
|
|
|
|
|
2013-11-21 19:34:37 +01:00
|
|
|
static int method_reload(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
|
|
|
return bus_unit_method_start_generic(bus, message, userdata, JOB_RELOAD, false, error);
|
2013-11-19 21:12:59 +01:00
|
|
|
}
|
2011-07-13 19:56:40 +02:00
|
|
|
|
2013-11-21 19:34:37 +01:00
|
|
|
static int method_restart(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
|
|
|
return bus_unit_method_start_generic(bus, message, userdata, JOB_RESTART, false, error);
|
2013-11-19 21:12:59 +01:00
|
|
|
}
|
2010-10-22 16:11:50 +02:00
|
|
|
|
2013-11-21 19:34:37 +01:00
|
|
|
static int method_try_restart(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
|
|
|
return bus_unit_method_start_generic(bus, message, userdata, JOB_TRY_RESTART, false, error);
|
2013-11-19 21:12:59 +01:00
|
|
|
}
|
2012-10-02 23:07:00 +02:00
|
|
|
|
2013-11-21 19:34:37 +01:00
|
|
|
static int method_reload_or_restart(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
|
|
|
return bus_unit_method_start_generic(bus, message, userdata, JOB_RESTART, true, error);
|
2013-11-19 21:12:59 +01:00
|
|
|
}
|
2010-10-22 16:11:50 +02:00
|
|
|
|
2013-11-21 19:34:37 +01:00
|
|
|
static int method_reload_or_try_restart(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
|
|
|
return bus_unit_method_start_generic(bus, message, userdata, JOB_TRY_RESTART, true, error);
|
2013-11-19 21:12:59 +01:00
|
|
|
}
|
2010-10-22 16:11:50 +02:00
|
|
|
|
2013-11-21 19:34:37 +01:00
|
|
|
int bus_unit_method_kill(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
2013-11-19 21:12:59 +01:00
|
|
|
Unit *u = userdata;
|
|
|
|
const char *swho;
|
|
|
|
int32_t signo;
|
|
|
|
KillWho who;
|
|
|
|
int r;
|
2010-07-18 04:58:01 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(message);
|
|
|
|
assert(u);
|
2012-10-02 23:07:00 +02:00
|
|
|
|
2015-02-18 17:40:57 +01:00
|
|
|
r = mac_selinux_unit_access_check(u, message, "stop", error);
|
2014-08-06 11:45:36 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_read(message, "si", &swho, &signo);
|
|
|
|
if (r < 0)
|
2013-11-21 19:34:37 +01:00
|
|
|
return r;
|
2013-11-19 21:12:59 +01:00
|
|
|
|
|
|
|
if (isempty(swho))
|
|
|
|
who = KILL_ALL;
|
|
|
|
else {
|
|
|
|
who = kill_who_from_string(swho);
|
|
|
|
if (who < 0)
|
2013-11-21 19:34:37 +01:00
|
|
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid who argument %s", swho);
|
2013-11-19 21:12:59 +01:00
|
|
|
}
|
2010-07-18 04:58:01 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
if (signo <= 0 || signo >= _NSIG)
|
2013-11-21 19:34:37 +01:00
|
|
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Signal number out of range.");
|
2013-06-27 21:14:56 +02:00
|
|
|
|
2015-02-18 17:40:57 +01:00
|
|
|
r = bus_verify_manage_units_async_for_kill(u->manager, message, error);
|
2013-11-21 19:34:37 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2015-02-18 17:40:57 +01:00
|
|
|
if (r == 0)
|
|
|
|
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
2013-06-27 21:14:56 +02:00
|
|
|
|
2013-11-21 19:34:37 +01:00
|
|
|
r = unit_kill(u, who, signo, error);
|
2013-11-19 21:12:59 +01:00
|
|
|
if (r < 0)
|
2013-11-21 19:34:37 +01:00
|
|
|
return r;
|
2013-06-27 21:14:56 +02:00
|
|
|
|
2013-11-21 01:51:16 +01:00
|
|
|
return sd_bus_reply_method_return(message, NULL);
|
2013-11-19 21:12:59 +01:00
|
|
|
}
|
2013-06-27 21:14:56 +02:00
|
|
|
|
2013-11-21 19:34:37 +01:00
|
|
|
int bus_unit_method_reset_failed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
2013-11-19 21:12:59 +01:00
|
|
|
Unit *u = userdata;
|
2013-11-21 19:34:37 +01:00
|
|
|
int r;
|
2010-02-03 12:37:42 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(message);
|
|
|
|
assert(u);
|
2010-02-03 12:37:42 +01:00
|
|
|
|
2015-02-18 17:40:57 +01:00
|
|
|
r = mac_selinux_unit_access_check(u, message, "reload", error);
|
2014-08-06 11:45:36 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2015-02-18 17:40:57 +01:00
|
|
|
r = bus_verify_manage_units_async(u->manager, message, error);
|
2013-11-21 19:34:37 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2015-02-18 17:40:57 +01:00
|
|
|
if (r == 0)
|
|
|
|
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
2010-02-03 12:37:42 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
unit_reset_failed(u);
|
2010-02-03 12:37:42 +01:00
|
|
|
|
2013-11-21 01:51:16 +01:00
|
|
|
return sd_bus_reply_method_return(message, NULL);
|
2010-02-01 03:33:24 +01:00
|
|
|
}
|
|
|
|
|
2013-11-21 19:34:37 +01:00
|
|
|
int bus_unit_method_set_properties(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
2013-11-19 21:12:59 +01:00
|
|
|
Unit *u = userdata;
|
|
|
|
int runtime, r;
|
2010-02-01 03:33:24 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
2010-02-01 03:33:24 +01:00
|
|
|
assert(message);
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(u);
|
2012-05-21 12:54:34 +02:00
|
|
|
|
2015-02-18 17:40:57 +01:00
|
|
|
r = mac_selinux_unit_access_check(u, message, "start", error);
|
2014-08-06 11:45:36 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_read(message, "b", &runtime);
|
|
|
|
if (r < 0)
|
2013-11-21 19:34:37 +01:00
|
|
|
return r;
|
2010-10-13 03:03:31 +02:00
|
|
|
|
2015-02-18 17:40:57 +01:00
|
|
|
r = bus_verify_manage_units_async(u->manager, message, error);
|
2013-11-21 19:34:37 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2015-02-18 17:40:57 +01:00
|
|
|
if (r == 0)
|
|
|
|
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
2012-10-02 23:07:00 +02:00
|
|
|
|
2013-11-21 19:34:37 +01:00
|
|
|
r = bus_unit_set_properties(u, message, runtime ? UNIT_RUNTIME : UNIT_PERSISTENT, true, error);
|
2013-11-19 21:12:59 +01:00
|
|
|
if (r < 0)
|
2013-11-21 19:34:37 +01:00
|
|
|
return r;
|
2010-10-13 03:03:31 +02:00
|
|
|
|
2013-11-21 01:51:16 +01:00
|
|
|
return sd_bus_reply_method_return(message, NULL);
|
2013-11-19 21:12:59 +01:00
|
|
|
}
|
2010-10-13 03:03:31 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
const sd_bus_vtable bus_unit_vtable[] = {
|
|
|
|
SD_BUS_VTABLE_START(0),
|
|
|
|
|
2013-12-22 02:24:05 +01:00
|
|
|
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),
|
2013-11-19 21:12:59 +01:00
|
|
|
SD_BUS_PROPERTY("Following", "s", property_get_following, 0, 0),
|
2013-12-22 02:24:05 +01:00
|
|
|
SD_BUS_PROPERTY("Requires", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES_OVERRIDABLE]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("Requisite", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE_OVERRIDABLE]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("Wants", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTS]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("BindsTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BINDS_TO]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("PartOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PART_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("RequiredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY_OVERRIDABLE]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("WantedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("BoundBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BOUND_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("ConsistsOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("Conflicts", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTS]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("ConflictedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("Before", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BEFORE]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("After", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_AFTER]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("OnFailure", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_ON_FAILURE]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("Triggers", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERS]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("TriggeredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("PropagatesReloadTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("ReloadPropagatedFrom", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("JoinsNamespaceOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_JOINS_NAMESPACE_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("RequiresMountsFor", "as", NULL, offsetof(Unit, requires_mounts_for), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("Documentation", "as", NULL, offsetof(Unit, documentation), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("Description", "s", property_get_description, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("LoadState", "s", property_get_load_state, offsetof(Unit, load_state), SD_BUS_VTABLE_PROPERTY_CONST),
|
2013-11-19 21:12:59 +01:00
|
|
|
SD_BUS_PROPERTY("ActiveState", "s", property_get_active_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
|
|
|
SD_BUS_PROPERTY("SubState", "s", property_get_sub_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
2013-12-22 02:24:05 +01:00
|
|
|
SD_BUS_PROPERTY("FragmentPath", "s", NULL, offsetof(Unit, fragment_path), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Unit, source_path), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("DropInPaths", "as", NULL, offsetof(Unit, dropin_paths), SD_BUS_VTABLE_PROPERTY_CONST),
|
2013-11-19 21:12:59 +01:00
|
|
|
SD_BUS_PROPERTY("UnitFileState", "s", property_get_unit_file_state, 0, 0),
|
2014-12-02 02:38:18 +01:00
|
|
|
SD_BUS_PROPERTY("UnitFilePreset", "s", property_get_unit_file_preset, 0, 0),
|
2013-11-19 21:12:59 +01:00
|
|
|
BUS_PROPERTY_DUAL_TIMESTAMP("InactiveExitTimestamp", offsetof(Unit, inactive_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
|
|
|
BUS_PROPERTY_DUAL_TIMESTAMP("ActiveEnterTimestamp", offsetof(Unit, active_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
|
|
|
BUS_PROPERTY_DUAL_TIMESTAMP("ActiveExitTimestamp", offsetof(Unit, active_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
|
|
|
BUS_PROPERTY_DUAL_TIMESTAMP("InactiveEnterTimestamp", offsetof(Unit, inactive_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
2013-12-22 02:24:05 +01:00
|
|
|
SD_BUS_PROPERTY("CanStart", "b", property_get_can_start, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
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),
|
2013-11-19 21:12:59 +01:00
|
|
|
SD_BUS_PROPERTY("Job", "(uo)", property_get_job, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
2013-12-22 02:24:05 +01:00
|
|
|
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),
|
|
|
|
SD_BUS_PROPERTY("AllowIsolate", "b", bus_property_get_bool, offsetof(Unit, allow_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("DefaultDependencies", "b", bus_property_get_bool, offsetof(Unit, default_dependencies), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("OnFailureJobMode", "s", property_get_job_mode, offsetof(Unit, on_failure_job_mode), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("IgnoreOnSnapshot", "b", bus_property_get_bool, offsetof(Unit, ignore_on_snapshot), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_timeout), SD_BUS_VTABLE_PROPERTY_CONST),
|
2014-10-28 01:49:07 +01:00
|
|
|
SD_BUS_PROPERTY("JobTimeoutAction", "s", property_get_failure_action, offsetof(Unit, job_timeout_action), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("JobTimeoutRebootArgument", "s", NULL, offsetof(Unit, job_timeout_reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
|
2013-11-19 21:12:59 +01:00
|
|
|
SD_BUS_PROPERTY("ConditionResult", "b", bus_property_get_bool, offsetof(Unit, condition_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
2014-11-06 13:43:45 +01:00
|
|
|
SD_BUS_PROPERTY("AssertResult", "b", bus_property_get_bool, offsetof(Unit, assert_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
2013-11-19 21:12:59 +01:00
|
|
|
BUS_PROPERTY_DUAL_TIMESTAMP("ConditionTimestamp", offsetof(Unit, condition_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
2014-11-06 13:43:45 +01:00
|
|
|
BUS_PROPERTY_DUAL_TIMESTAMP("AssertTimestamp", offsetof(Unit, assert_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
|
|
|
SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions, offsetof(Unit, conditions), 0),
|
|
|
|
SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), 0),
|
2013-12-22 02:24:05 +01:00
|
|
|
SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST),
|
2013-11-19 21:12:59 +01:00
|
|
|
|
2015-02-18 17:40:57 +01:00
|
|
|
SD_BUS_METHOD("Start", "s", "o", method_start, SD_BUS_VTABLE_UNPRIVILEGED),
|
|
|
|
SD_BUS_METHOD("Stop", "s", "o", method_stop, SD_BUS_VTABLE_UNPRIVILEGED),
|
|
|
|
SD_BUS_METHOD("Reload", "s", "o", method_reload, SD_BUS_VTABLE_UNPRIVILEGED),
|
|
|
|
SD_BUS_METHOD("Restart", "s", "o", method_restart, SD_BUS_VTABLE_UNPRIVILEGED),
|
|
|
|
SD_BUS_METHOD("TryRestart", "s", "o", method_try_restart, SD_BUS_VTABLE_UNPRIVILEGED),
|
|
|
|
SD_BUS_METHOD("ReloadOrRestart", "s", "o", method_reload_or_restart, SD_BUS_VTABLE_UNPRIVILEGED),
|
|
|
|
SD_BUS_METHOD("ReloadOrTryRestart", "s", "o", method_reload_or_try_restart, SD_BUS_VTABLE_UNPRIVILEGED),
|
|
|
|
SD_BUS_METHOD("Kill", "si", NULL, bus_unit_method_kill, SD_BUS_VTABLE_UNPRIVILEGED),
|
|
|
|
SD_BUS_METHOD("ResetFailed", NULL, NULL, bus_unit_method_reset_failed, SD_BUS_VTABLE_UNPRIVILEGED),
|
|
|
|
SD_BUS_METHOD("SetProperties", "ba(sv)", NULL, bus_unit_method_set_properties, SD_BUS_VTABLE_UNPRIVILEGED),
|
2013-11-19 21:12:59 +01:00
|
|
|
|
|
|
|
SD_BUS_VTABLE_END
|
|
|
|
};
|
2010-10-13 03:03:31 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int property_get_slice(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2010-10-13 03:03:31 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
Unit *u = userdata;
|
2010-10-13 03:03:31 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
|
|
|
assert(u);
|
2010-10-13 03:03:31 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
return sd_bus_message_append(reply, "s", unit_slice_name(u));
|
|
|
|
}
|
2010-10-13 03:03:31 +02:00
|
|
|
|
2015-01-23 02:58:02 +01:00
|
|
|
static int property_get_current_memory(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
|
|
|
|
|
|
|
uint64_t sz = (uint64_t) -1;
|
2015-03-01 16:24:19 +01:00
|
|
|
Unit *u = userdata;
|
2015-01-23 02:58:02 +01:00
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
|
|
|
assert(u);
|
|
|
|
|
2015-03-01 16:24:19 +01:00
|
|
|
r = unit_get_memory_current(u, &sz);
|
|
|
|
if (r < 0 && r != -ENODATA)
|
|
|
|
log_unit_warning_errno(u->id, r, "Failed to get memory.usage_in_bytes attribute: %m");
|
2015-01-23 02:58:02 +01:00
|
|
|
|
2015-03-01 16:24:19 +01:00
|
|
|
return sd_bus_message_append(reply, "t", sz);
|
|
|
|
}
|
2015-01-23 02:58:02 +01:00
|
|
|
|
2015-03-01 16:24:19 +01:00
|
|
|
static int property_get_cpu_usage(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2015-01-23 02:58:02 +01:00
|
|
|
|
2015-03-01 16:24:19 +01:00
|
|
|
nsec_t ns = (nsec_t) -1;
|
|
|
|
Unit *u = userdata;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
|
|
|
assert(u);
|
|
|
|
|
|
|
|
r = unit_get_cpu_usage(u, &ns);
|
|
|
|
if (r < 0 && r != -ENODATA)
|
|
|
|
log_unit_warning_errno(u->id, r, "Failed to get cpuacct.usage attribute: %m");
|
|
|
|
|
|
|
|
return sd_bus_message_append(reply, "t", ns);
|
2015-01-23 02:58:02 +01:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
const sd_bus_vtable bus_unit_cgroup_vtable[] = {
|
|
|
|
SD_BUS_VTABLE_START(0),
|
|
|
|
SD_BUS_PROPERTY("Slice", "s", property_get_slice, 0, 0),
|
|
|
|
SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Unit, cgroup_path), 0),
|
2015-01-23 02:58:02 +01:00
|
|
|
SD_BUS_PROPERTY("MemoryCurrent", "t", property_get_current_memory, 0, 0),
|
2015-03-01 16:24:19 +01:00
|
|
|
SD_BUS_PROPERTY("CPUUsageNSec", "t", property_get_cpu_usage, 0, 0),
|
2013-11-19 21:12:59 +01:00
|
|
|
SD_BUS_VTABLE_END
|
|
|
|
};
|
2010-10-13 03:03:31 +02:00
|
|
|
|
2014-03-03 01:33:45 +01:00
|
|
|
static int send_new_signal(sd_bus *bus, void *userdata) {
|
2013-11-19 21:12:59 +01:00
|
|
|
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
|
|
|
|
_cleanup_free_ char *p = NULL;
|
|
|
|
Unit *u = userdata;
|
|
|
|
int r;
|
2010-10-13 03:03:31 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(u);
|
2010-10-13 03:03:31 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
p = unit_dbus_path(u);
|
|
|
|
if (!u)
|
|
|
|
return -ENOMEM;
|
2010-10-13 03:03:31 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_new_signal(
|
|
|
|
bus,
|
2014-02-19 23:54:58 +01:00
|
|
|
&m,
|
2013-11-19 21:12:59 +01:00
|
|
|
"/org/freedesktop/systemd1",
|
|
|
|
"org.freedesktop.systemd1.Manager",
|
2014-02-19 23:54:58 +01:00
|
|
|
"UnitNew");
|
2013-11-19 21:12:59 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2010-10-13 03:03:31 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_append(m, "so", u->id, p);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2010-10-13 03:03:31 +02:00
|
|
|
|
2014-03-03 01:33:45 +01:00
|
|
|
return sd_bus_send(bus, m, NULL);
|
2013-11-19 21:12:59 +01:00
|
|
|
}
|
2010-10-13 03:03:31 +02:00
|
|
|
|
2014-03-03 01:33:45 +01:00
|
|
|
static int send_changed_signal(sd_bus *bus, void *userdata) {
|
2013-11-19 21:12:59 +01:00
|
|
|
_cleanup_free_ char *p = NULL;
|
|
|
|
Unit *u = userdata;
|
|
|
|
int r;
|
2010-10-13 03:03:31 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(u);
|
2010-10-13 03:03:31 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
p = unit_dbus_path(u);
|
2014-01-31 17:47:22 +01:00
|
|
|
if (!p)
|
2013-11-19 21:12:59 +01:00
|
|
|
return -ENOMEM;
|
2010-10-13 03:03:31 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
/* Send a properties changed signal. First for the specific
|
|
|
|
* type, then for the generic unit. The clients may rely on
|
|
|
|
* this order to get atomic behavior if needed. */
|
2010-02-01 03:33:24 +01:00
|
|
|
|
2013-12-22 03:43:03 +01:00
|
|
|
r = sd_bus_emit_properties_changed_strv(
|
|
|
|
bus, p,
|
|
|
|
UNIT_VTABLE(u)->bus_interface,
|
|
|
|
NULL);
|
2014-03-11 04:10:19 +01:00
|
|
|
if (r < 0)
|
2013-12-22 03:43:03 +01:00
|
|
|
return r;
|
2012-05-21 12:54:34 +02:00
|
|
|
|
2014-03-11 04:10:19 +01:00
|
|
|
return sd_bus_emit_properties_changed_strv(
|
2013-11-19 21:12:59 +01:00
|
|
|
bus, p,
|
|
|
|
"org.freedesktop.systemd1.Unit",
|
|
|
|
NULL);
|
2010-02-01 03:33:24 +01:00
|
|
|
}
|
|
|
|
|
2010-02-05 00:38:41 +01:00
|
|
|
void bus_unit_send_change_signal(Unit *u) {
|
2013-07-10 20:33:11 +02:00
|
|
|
int r;
|
2010-02-05 00:38:41 +01:00
|
|
|
assert(u);
|
|
|
|
|
2012-01-15 12:04:08 +01:00
|
|
|
if (u->in_dbus_queue) {
|
2013-10-14 06:10:14 +02:00
|
|
|
LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u);
|
2012-01-15 12:04:08 +01:00
|
|
|
u->in_dbus_queue = false;
|
2010-07-11 03:59:49 +02:00
|
|
|
}
|
2010-02-05 00:38:41 +01:00
|
|
|
|
2012-01-15 12:04:08 +01:00
|
|
|
if (!u->id)
|
2010-08-09 17:02:09 +02:00
|
|
|
return;
|
|
|
|
|
2014-03-03 01:33:45 +01:00
|
|
|
r = bus_foreach_bus(u->manager, NULL, u->sent_dbus_new_signal ? send_changed_signal : send_new_signal, u);
|
2013-11-19 21:12:59 +01:00
|
|
|
if (r < 0)
|
2014-11-28 13:19:16 +01:00
|
|
|
log_debug_errno(r, "Failed to send unit change signal for %s: %m", u->id);
|
2010-02-05 00:38:41 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
u->sent_dbus_new_signal = true;
|
|
|
|
}
|
2010-08-20 02:26:05 +02:00
|
|
|
|
2014-03-03 01:33:45 +01:00
|
|
|
static int send_removed_signal(sd_bus *bus, void *userdata) {
|
2013-11-19 21:12:59 +01:00
|
|
|
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
|
|
|
|
_cleanup_free_ char *p = NULL;
|
|
|
|
Unit *u = userdata;
|
|
|
|
int r;
|
2010-08-20 02:26:05 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(u);
|
2010-02-05 00:38:41 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
p = unit_dbus_path(u);
|
|
|
|
if (!u)
|
|
|
|
return -ENOMEM;
|
2010-02-05 00:38:41 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_new_signal(
|
|
|
|
bus,
|
2014-02-19 23:54:58 +01:00
|
|
|
&m,
|
2013-11-19 21:12:59 +01:00
|
|
|
"/org/freedesktop/systemd1",
|
|
|
|
"org.freedesktop.systemd1.Manager",
|
2014-02-19 23:54:58 +01:00
|
|
|
"UnitRemoved");
|
2013-11-19 21:12:59 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2010-02-05 00:38:41 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_append(m, "so", u->id, p);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2010-02-05 00:38:41 +01:00
|
|
|
|
2014-03-03 01:33:45 +01:00
|
|
|
return sd_bus_send(bus, m, NULL);
|
2010-02-05 00:38:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void bus_unit_send_removed_signal(Unit *u) {
|
2013-11-19 21:12:59 +01:00
|
|
|
int r;
|
2010-02-05 00:38:41 +01:00
|
|
|
assert(u);
|
|
|
|
|
2012-01-15 12:04:08 +01:00
|
|
|
if (!u->sent_dbus_new_signal)
|
2010-05-22 04:27:24 +02:00
|
|
|
bus_unit_send_change_signal(u);
|
|
|
|
|
2012-01-15 12:04:08 +01:00
|
|
|
if (!u->id)
|
2010-08-09 17:02:09 +02:00
|
|
|
return;
|
|
|
|
|
2014-03-03 01:33:45 +01:00
|
|
|
r = bus_foreach_bus(u->manager, NULL, send_removed_signal, u);
|
2013-11-19 21:12:59 +01:00
|
|
|
if (r < 0)
|
2014-11-28 13:19:16 +01:00
|
|
|
log_debug_errno(r, "Failed to send unit remove signal for %s: %m", u->id);
|
2010-02-05 00:38:41 +01:00
|
|
|
}
|
2012-01-17 09:20:32 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
int bus_unit_queue_job(
|
|
|
|
sd_bus *bus,
|
|
|
|
sd_bus_message *message,
|
2012-10-02 23:07:00 +02:00
|
|
|
Unit *u,
|
|
|
|
JobType type,
|
|
|
|
JobMode mode,
|
2013-11-21 19:34:37 +01:00
|
|
|
bool reload_if_possible,
|
|
|
|
sd_bus_error *error) {
|
2012-10-02 23:07:00 +02:00
|
|
|
|
|
|
|
_cleanup_free_ char *path = NULL;
|
|
|
|
Job *j;
|
|
|
|
int r;
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
2012-10-02 23:07:00 +02:00
|
|
|
assert(message);
|
|
|
|
assert(u);
|
|
|
|
assert(type >= 0 && type < _JOB_TYPE_MAX);
|
|
|
|
assert(mode >= 0 && mode < _JOB_MODE_MAX);
|
|
|
|
|
|
|
|
if (reload_if_possible && unit_can_reload(u)) {
|
|
|
|
if (type == JOB_RESTART)
|
|
|
|
type = JOB_RELOAD_OR_START;
|
|
|
|
else if (type == JOB_TRY_RESTART)
|
|
|
|
type = JOB_RELOAD;
|
|
|
|
}
|
|
|
|
|
2014-10-24 14:15:25 +02:00
|
|
|
r = mac_selinux_unit_access_check(
|
2014-05-14 22:44:45 +02:00
|
|
|
u, message,
|
2013-11-21 19:34:37 +01:00
|
|
|
(type == JOB_START || type == JOB_RESTART || type == JOB_TRY_RESTART) ? "start" :
|
|
|
|
type == JOB_STOP ? "stop" : "reload", error);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2012-10-02 23:07:00 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
if (type == JOB_STOP &&
|
|
|
|
(u->load_state == UNIT_NOT_FOUND || u->load_state == UNIT_ERROR) &&
|
|
|
|
unit_active_state(u) == UNIT_INACTIVE)
|
2013-11-21 19:34:37 +01:00
|
|
|
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
|
2012-10-02 23:07:00 +02:00
|
|
|
|
|
|
|
if ((type == JOB_START && u->refuse_manual_start) ||
|
|
|
|
(type == JOB_STOP && u->refuse_manual_stop) ||
|
2013-11-19 21:12:59 +01:00
|
|
|
((type == JOB_RESTART || type == JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)))
|
2013-11-21 19:34:37 +01:00
|
|
|
return sd_bus_error_setf(error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only.", u->id);
|
2012-10-02 23:07:00 +02:00
|
|
|
|
2013-11-21 19:34:37 +01:00
|
|
|
r = manager_add_job(u->manager, type, u, mode, true, error, &j);
|
2012-10-02 23:07:00 +02:00
|
|
|
if (r < 0)
|
2013-11-21 19:34:37 +01:00
|
|
|
return r;
|
2012-10-02 23:07:00 +02:00
|
|
|
|
2014-03-03 01:33:45 +01:00
|
|
|
if (bus == u->manager->api_bus) {
|
2014-08-06 11:53:00 +02:00
|
|
|
if (!j->clients) {
|
|
|
|
r = sd_bus_track_new(bus, &j->clients, NULL, NULL);
|
2014-03-03 01:33:45 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2014-08-06 11:53:00 +02:00
|
|
|
r = sd_bus_track_add_sender(j->clients, message);
|
2014-03-03 01:33:45 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
}
|
2012-10-02 23:07:00 +02:00
|
|
|
|
|
|
|
path = job_dbus_path(j);
|
|
|
|
if (!path)
|
2013-11-21 20:49:04 +01:00
|
|
|
return -ENOMEM;
|
2012-10-02 23:07:00 +02:00
|
|
|
|
2013-11-21 01:51:16 +01:00
|
|
|
return sd_bus_reply_method_return(message, "o", path);
|
2012-10-02 23:07:00 +02:00
|
|
|
}
|
|
|
|
|
2013-07-01 00:40:56 +02:00
|
|
|
static int bus_unit_set_transient_property(
|
|
|
|
Unit *u,
|
|
|
|
const char *name,
|
2013-11-19 21:12:59 +01:00
|
|
|
sd_bus_message *message,
|
2013-07-01 00:40:56 +02:00
|
|
|
UnitSetPropertiesMode mode,
|
2013-11-19 21:12:59 +01:00
|
|
|
sd_bus_error *error) {
|
2013-07-01 00:40:56 +02:00
|
|
|
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(u);
|
|
|
|
assert(name);
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(message);
|
2013-07-01 00:40:56 +02:00
|
|
|
|
|
|
|
if (streq(name, "Description")) {
|
2013-11-19 21:12:59 +01:00
|
|
|
const char *d;
|
2013-07-01 00:40:56 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_read(message, "s", &d);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-07-02 15:49:27 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
if (mode != UNIT_CHECK) {
|
|
|
|
r = unit_set_description(u, d);
|
2013-07-02 15:49:27 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-07-10 21:13:56 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
unit_write_drop_in_format(u, mode, name, "[Unit]\nDescription=%s\n", d);
|
2013-07-02 15:49:27 +02:00
|
|
|
}
|
2013-07-01 00:40:56 +02:00
|
|
|
|
|
|
|
return 1;
|
2015-02-03 19:07:40 +01:00
|
|
|
|
|
|
|
} else if (streq(name, "DefaultDependencies")) {
|
|
|
|
int b;
|
|
|
|
|
|
|
|
r = sd_bus_message_read(message, "b", &b);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
|
|
|
u->default_dependencies = b;
|
|
|
|
unit_write_drop_in_format(u, mode, name, "[Unit]\nDefaultDependencies=%s\n", yes_no(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
2013-07-01 03:02:42 +02:00
|
|
|
|
|
|
|
} else if (streq(name, "Slice") && unit_get_cgroup_context(u)) {
|
|
|
|
const char *s;
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_read(message, "s", &s);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-07-01 03:02:42 +02:00
|
|
|
|
2013-12-26 21:30:22 +01:00
|
|
|
if (!unit_name_is_valid(s, TEMPLATE_INVALID) || !endswith(s, ".slice"))
|
2013-11-19 21:12:59 +01:00
|
|
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid slice name %s", s);
|
2013-07-01 03:02:42 +02:00
|
|
|
|
2013-07-02 15:49:27 +02:00
|
|
|
if (isempty(s)) {
|
2013-07-11 21:29:33 +02:00
|
|
|
if (mode != UNIT_CHECK) {
|
2013-07-02 15:49:27 +02:00
|
|
|
unit_ref_unset(&u->slice);
|
2013-07-11 21:29:33 +02:00
|
|
|
unit_remove_drop_in(u, mode, name);
|
|
|
|
}
|
2013-07-02 15:49:27 +02:00
|
|
|
} else {
|
2013-07-11 21:29:33 +02:00
|
|
|
Unit *slice;
|
2013-07-10 21:13:56 +02:00
|
|
|
|
2013-07-02 15:49:27 +02:00
|
|
|
r = manager_load_unit(u->manager, s, NULL, error, &slice);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-07-01 03:02:42 +02:00
|
|
|
|
2013-07-02 15:49:27 +02:00
|
|
|
if (slice->type != UNIT_SLICE)
|
|
|
|
return -EINVAL;
|
2013-07-01 03:02:42 +02:00
|
|
|
|
2013-07-11 21:29:33 +02:00
|
|
|
if (mode != UNIT_CHECK) {
|
2013-07-02 15:49:27 +02:00
|
|
|
unit_ref_set(&u->slice, slice);
|
2013-07-11 21:29:33 +02:00
|
|
|
unit_write_drop_in_private_format(u, mode, name, "Slice=%s\n", s);
|
|
|
|
}
|
2013-07-02 15:49:27 +02:00
|
|
|
}
|
2013-07-11 21:29:33 +02:00
|
|
|
|
2013-07-01 03:02:42 +02:00
|
|
|
return 1;
|
2014-10-30 07:45:15 +01:00
|
|
|
} else if (STR_IN_SET(name,
|
|
|
|
"Requires", "RequiresOverridable",
|
|
|
|
"Requisite", "RequisiteOverridable",
|
|
|
|
"Wants",
|
|
|
|
"BindsTo",
|
|
|
|
"Conflicts",
|
|
|
|
"Before", "After",
|
|
|
|
"OnFailure",
|
|
|
|
"PropagatesReloadTo", "ReloadPropagatedFrom",
|
|
|
|
"PartOf")) {
|
2013-07-10 23:39:46 +02:00
|
|
|
|
|
|
|
UnitDependency d;
|
2013-11-19 21:12:59 +01:00
|
|
|
const char *other;
|
2013-07-10 23:39:46 +02:00
|
|
|
|
|
|
|
d = unit_dependency_from_string(name);
|
|
|
|
if (d < 0)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_enter_container(message, 'a', "s");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-07-10 23:39:46 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
while ((r = sd_bus_message_read(message, "s", &other)) > 0) {
|
2013-12-26 21:30:22 +01:00
|
|
|
if (!unit_name_is_valid(other, TEMPLATE_INVALID))
|
2013-11-19 21:12:59 +01:00
|
|
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name %s", other);
|
2013-07-10 23:39:46 +02:00
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
2013-07-11 21:29:33 +02:00
|
|
|
_cleanup_free_ char *label = NULL;
|
2013-07-10 23:39:46 +02:00
|
|
|
|
|
|
|
r = unit_add_dependency_by_name(u, d, other, NULL, true);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
label = strjoin(name, "-", other, NULL);
|
|
|
|
if (!label)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2013-07-11 21:29:33 +02:00
|
|
|
unit_write_drop_in_format(u, mode, label, "[Unit]\n%s=%s\n", name, other);
|
2013-07-10 23:39:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2013-11-19 21:12:59 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-07-10 23:39:46 +02:00
|
|
|
|
2013-11-21 20:49:04 +01:00
|
|
|
r = sd_bus_message_exit_container(message);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2013-07-10 23:39:46 +02:00
|
|
|
return 1;
|
2013-07-01 00:40:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-06-28 04:12:58 +02:00
|
|
|
int bus_unit_set_properties(
|
|
|
|
Unit *u,
|
2013-11-19 21:12:59 +01:00
|
|
|
sd_bus_message *message,
|
2013-06-28 04:12:58 +02:00
|
|
|
UnitSetPropertiesMode mode,
|
|
|
|
bool commit,
|
2013-11-19 21:12:59 +01:00
|
|
|
sd_bus_error *error) {
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2013-06-27 21:14:56 +02:00
|
|
|
bool for_real = false;
|
|
|
|
unsigned n = 0;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(u);
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(message);
|
2013-06-27 21:14:56 +02:00
|
|
|
|
|
|
|
/* We iterate through the array twice. First run we just check
|
|
|
|
* if all passed data is valid, second run actually applies
|
|
|
|
* it. This is to implement transaction-like behaviour without
|
|
|
|
* actually providing full transactions. */
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_enter_container(message, 'a', "(sv)");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-27 21:14:56 +02:00
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
const char *name;
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_enter_container(message, 'r', "sv");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
if (r == 0) {
|
2013-08-26 04:36:45 +02:00
|
|
|
if (for_real || mode == UNIT_CHECK)
|
2013-06-27 21:14:56 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* Reached EOF. Let's try again, and this time for realz... */
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_rewind(message, false);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-11-21 20:49:04 +01:00
|
|
|
|
2013-06-27 21:14:56 +02:00
|
|
|
for_real = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_read(message, "s", &name);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-27 21:14:56 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
if (!UNIT_VTABLE(u)->bus_set_property)
|
|
|
|
return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Objects of this type do not support setting properties.");
|
2013-06-27 21:14:56 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_enter_container(message, 'v', NULL);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-27 21:14:56 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = UNIT_VTABLE(u)->bus_set_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
|
2013-07-01 00:40:56 +02:00
|
|
|
if (r == 0 && u->transient && u->load_state == UNIT_STUB)
|
2013-11-19 21:12:59 +01:00
|
|
|
r = bus_unit_set_transient_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
if (r == 0)
|
|
|
|
return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Cannot set property %s, or unknown property.", name);
|
|
|
|
|
|
|
|
r = sd_bus_message_exit_container(message);
|
2013-06-27 21:14:56 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_exit_container(message);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-27 21:14:56 +02:00
|
|
|
|
|
|
|
n += for_real;
|
|
|
|
}
|
|
|
|
|
2013-11-21 20:49:04 +01:00
|
|
|
r = sd_bus_message_exit_container(message);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2013-06-28 04:12:58 +02:00
|
|
|
if (commit && n > 0 && UNIT_VTABLE(u)->bus_commit_properties)
|
2013-06-27 21:14:56 +02:00
|
|
|
UNIT_VTABLE(u)->bus_commit_properties(u);
|
|
|
|
|
2013-06-28 00:41:24 +02:00
|
|
|
return n;
|
2013-06-27 21:14:56 +02:00
|
|
|
}
|