dbus-manager.c revision 4f7385fa496242f06aaf358b66b28d71348607b3
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering/***
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering This file is part of systemd.
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering Copyright 2010 Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering systemd is free software; you can redistribute it and/or modify it
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering under the terms of the GNU Lesser General Public License as published by
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering (at your option) any later version.
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering systemd is distributed in the hope that it will be useful, but
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering Lesser General Public License for more details.
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering You should have received a copy of the GNU Lesser General Public License
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering***/
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering#include <errno.h>
4871690d9e32608bbd9b18505b5326c2079c9690Allin Cottrell#include <unistd.h>
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering#include "log.h"
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering#include "strv.h"
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering#include "build.h"
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering#include "install.h"
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering#include "selinux-access.h"
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek#include "watchdog.h"
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering#include "hwclock.h"
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering#include "path-util.h"
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering#include "virt.h"
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering#include "env-util.h"
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen#include "dbus.h"
a09abc4ae0bdc0200324eaa0416f23ff2170ec4eLennart Poettering#include "dbus-manager.h"
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering#include "dbus-unit.h"
d18d46ecea80a7f07415edb9264af6a254fd70bbZbigniew Jędrzejewski-Szmek#include "dbus-snapshot.h"
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering#include "dbus-client-track.h"
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering#include "dbus-execute.h"
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering#include "bus-errors.h"
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int property_get_version(
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus *bus,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *path,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *interface,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *property,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus_message *reply,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering void *userdata,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus_error *error) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(bus);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(reply);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return sd_bus_message_append(reply, "s", PACKAGE_VERSION);
d18d46ecea80a7f07415edb9264af6a254fd70bbZbigniew Jędrzejewski-Szmek}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int property_get_features(
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus *bus,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *path,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *interface,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *property,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus_message *reply,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering void *userdata,
d18d46ecea80a7f07415edb9264af6a254fd70bbZbigniew Jędrzejewski-Szmek sd_bus_error *error) {
d18d46ecea80a7f07415edb9264af6a254fd70bbZbigniew Jędrzejewski-Szmek
d18d46ecea80a7f07415edb9264af6a254fd70bbZbigniew Jędrzejewski-Szmek assert(bus);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(reply);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return sd_bus_message_append(reply, "s", SYSTEMD_FEATURES);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poetteringstatic int property_get_virtualization(
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek sd_bus *bus,
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek const char *path,
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek const char *interface,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *property,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus_message *reply,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering void *userdata,
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering sd_bus_error *error) {
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *id = NULL;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(bus);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek assert(reply);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
874bc134ac6504c45e94174e37af13ff21a6bfe2Zbigniew Jędrzejewski-Szmek detect_virtualization(&id);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return sd_bus_message_append(reply, "s", id);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int property_get_tainted(
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus *bus,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *path,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *interface,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *property,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus_message *reply,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering void *userdata,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus_error *error) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering char buf[sizeof("split-usr:mtab-not-symlink:cgroups-missing:local-hwclock:")] = "", *e = buf;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering _cleanup_free_ char *p = NULL;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering Manager *m = userdata;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(bus);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(reply);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(m);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (m->taint_usr)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering e = stpcpy(e, "split-usr:");
874bc134ac6504c45e94174e37af13ff21a6bfe2Zbigniew Jędrzejewski-Szmek
874bc134ac6504c45e94174e37af13ff21a6bfe2Zbigniew Jędrzejewski-Szmek if (readlink_malloc("/etc/mtab", &p) < 0)
8c0b803b97bb0ee6603d9be85fb6b69cd6081eafLennart Poettering e = stpcpy(e, "mtab-not-symlink:");
874bc134ac6504c45e94174e37af13ff21a6bfe2Zbigniew Jędrzejewski-Szmek
874bc134ac6504c45e94174e37af13ff21a6bfe2Zbigniew Jędrzejewski-Szmek if (access("/proc/cgroups", F_OK) < 0)
874bc134ac6504c45e94174e37af13ff21a6bfe2Zbigniew Jędrzejewski-Szmek e = stpcpy(e, "cgroups-missing:");
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (hwclock_is_localtime() > 0)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering e = stpcpy(e, "local-hwclock:");
874bc134ac6504c45e94174e37af13ff21a6bfe2Zbigniew Jędrzejewski-Szmek
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* remove the last ':' */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (e != buf)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering e[-1] = 0;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return sd_bus_message_append(reply, "s", buf);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int property_get_log_target(
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus *bus,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *path,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *interface,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *property,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus_message *reply,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering void *userdata,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus_error *error) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
12a717f8347f3daf0ae46a2b71c7d011d9c12feaZbigniew Jędrzejewski-Szmek assert(bus);
92ee6447b1deef7c79962a8121fdf8e58acb3a83Zbigniew Jędrzejewski-Szmek assert(reply);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek return sd_bus_message_append(reply, "s", log_target_to_string(log_get_target()));
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int property_set_log_target(
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus *bus,
d18d46ecea80a7f07415edb9264af6a254fd70bbZbigniew Jędrzejewski-Szmek const char *path,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *interface,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *property,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus_message *value,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering void *userdata,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus_error *error) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *t;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering int r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(bus);
874bc134ac6504c45e94174e37af13ff21a6bfe2Zbigniew Jędrzejewski-Szmek assert(value);
a174f94d529c7ae9be589867308b669ec9b4dcc0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering r = sd_bus_message_read(value, "s", &t);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (r < 0)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return log_set_target_from_string(t);
2a0e0692565f0435657c93498e09cbb2d3517152Shawn Landden}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int property_get_log_level(
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus *bus,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *path,
2a0e0692565f0435657c93498e09cbb2d3517152Shawn Landden const char *interface,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *property,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus_message *reply,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering void *userdata,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus_error *error) {
2a0e0692565f0435657c93498e09cbb2d3517152Shawn Landden
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering _cleanup_free_ char *t = NULL;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering int r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(bus);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(reply);
2a0e0692565f0435657c93498e09cbb2d3517152Shawn Landden
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering r = log_level_to_string_alloc(log_get_max_level(), &t);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (r < 0)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return sd_bus_message_append(reply, "s", t);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
1f6b411372076426c0faf0bb350437fb4d82931fLennart Poetteringstatic int property_set_log_level(
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus *bus,
2a0e0692565f0435657c93498e09cbb2d3517152Shawn Landden const char *path,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *interface,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *property,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus_message *value,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering void *userdata,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus_error *error) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *t;
1f6b411372076426c0faf0bb350437fb4d82931fLennart Poettering int r;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek assert(bus);
2a0e0692565f0435657c93498e09cbb2d3517152Shawn Landden assert(value);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek r = sd_bus_message_read(value, "s", &t);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek if (r < 0)
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek return r;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek return log_set_max_level_from_string(t);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int property_get_n_names(
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus *bus,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *path,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *interface,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *property,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus_message *reply,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering void *userdata,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus_error *error) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering Manager *m = userdata;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(bus);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(reply);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(m);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->units));
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
505b6a61c22d5565e9308045c7b9bf79f7d0517eLennart Poetteringstatic int property_get_n_jobs(
fa1c4b518ec7d8ec2d647213ee651cde4d6c9d7eZbigniew Jędrzejewski-Szmek sd_bus *bus,
505b6a61c22d5565e9308045c7b9bf79f7d0517eLennart Poettering const char *path,
505b6a61c22d5565e9308045c7b9bf79f7d0517eLennart Poettering const char *interface,
505b6a61c22d5565e9308045c7b9bf79f7d0517eLennart Poettering const char *property,
505b6a61c22d5565e9308045c7b9bf79f7d0517eLennart Poettering sd_bus_message *reply,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering void *userdata,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus_error *error) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering Manager *m = userdata;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(bus);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(reply);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(m);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->jobs));
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int property_get_progress(
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus *bus,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *path,
d18d46ecea80a7f07415edb9264af6a254fd70bbZbigniew Jędrzejewski-Szmek const char *interface,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *property,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus_message *reply,
874bc134ac6504c45e94174e37af13ff21a6bfe2Zbigniew Jędrzejewski-Szmek void *userdata,
a174f94d529c7ae9be589867308b669ec9b4dcc0Lennart Poettering sd_bus_error *error) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering Manager *m = userdata;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering double d;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(bus);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(reply);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(m);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (dual_timestamp_is_set(&m->finish_timestamp))
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering d = 1.0;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering else
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
874bc134ac6504c45e94174e37af13ff21a6bfe2Zbigniew Jędrzejewski-Szmek return sd_bus_message_append(reply, "d", d);
874bc134ac6504c45e94174e37af13ff21a6bfe2Zbigniew Jędrzejewski-Szmek}
874bc134ac6504c45e94174e37af13ff21a6bfe2Zbigniew Jędrzejewski-Szmek
874bc134ac6504c45e94174e37af13ff21a6bfe2Zbigniew Jędrzejewski-Szmekstatic int property_set_runtime_watchdog(
874bc134ac6504c45e94174e37af13ff21a6bfe2Zbigniew Jędrzejewski-Szmek sd_bus *bus,
874bc134ac6504c45e94174e37af13ff21a6bfe2Zbigniew Jędrzejewski-Szmek const char *path,
874bc134ac6504c45e94174e37af13ff21a6bfe2Zbigniew Jędrzejewski-Szmek const char *interface,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *property,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus_message *value,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering void *userdata,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_bus_error *error) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering usec_t *t = userdata;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering int r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(bus);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(value);
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen assert_cc(sizeof(usec_t) == sizeof(uint64_t));
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering r = sd_bus_message_read(value, "t", t);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (r < 0)
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek return r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return watchdog_set_timeout(t);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int method_get_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering _cleanup_free_ char *path = NULL;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering Manager *m = userdata;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *name;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering Unit *u;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering int r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(bus);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(message);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(m);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering r = sd_bus_message_read(message, "s", &name);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (r < 0)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering u = manager_get_unit(m, name);
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering if (!u)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", name);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering r = selinux_unit_access_check(u, bus, message, "status", error);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering if (r < 0)
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering return r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering path = unit_dbus_path(u);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering if (!path)
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering return -ENOMEM;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return sd_bus_reply_method_return(message, "o", path);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poetteringstatic int method_get_unit_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering _cleanup_free_ char *path = NULL;
73843b52585d42cc1a970a1c664818ece6942e9eLennart Poettering Manager *m = userdata;
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering pid_t pid;
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering Unit *u;
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering int r;
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering assert(bus);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering assert(message);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering assert(m);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering assert_cc(sizeof(pid_t) == sizeof(uint32_t));
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering r = sd_bus_message_read(message, "u", &pid);
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering if (r < 0)
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering return r;
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering if (pid == 0) {
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering if (r < 0)
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering return r;
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering r = sd_bus_creds_get_pid(creds, &pid);
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering if (r < 0)
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering return r;
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering }
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering u = manager_get_unit_by_pid(m, pid);
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering if (!u)
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_PID, "PID %u does not belong to any loaded unit.", pid);
ae6c3cc009a21df4b51851fb8fe3fde0b7d6d8f0Lennart Poettering
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering r = selinux_unit_access_check(u, bus, message, "status", error);
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering if (r < 0)
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering return r;
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering path = unit_dbus_path(u);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (!path)
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt return -ENOMEM;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return sd_bus_reply_method_return(message, "o", path);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int method_load_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering _cleanup_free_ char *path = NULL;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering Manager *m = userdata;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *name;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering Unit *u;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering int r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(bus);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(message);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(m);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering r = sd_bus_message_read(message, "s", &name);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering if (r < 0)
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering return r;
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering r = manager_load_unit(m, name, NULL, error, &u);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering if (r < 0)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return r;
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering r = selinux_unit_access_check(u, bus, message, "status", error);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering if (r < 0)
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt return r;
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering path = unit_dbus_path(u);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering if (!path)
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering return -ENOMEM;
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering return sd_bus_reply_method_return(message, "o", path);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering}
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poetteringstatic int method_start_unit_generic(sd_bus *bus, sd_bus_message *message, Manager *m, JobType job_type, bool reload_if_possible, sd_bus_error *error) {
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering const char *name;
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering Unit *u;
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering int r;
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering assert(bus);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering assert(message);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering assert(m);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering r = sd_bus_message_read(message, "s", &name);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering if (r < 0)
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering return r;
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt r = manager_load_unit(m, name, NULL, error, &u);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering if (r < 0)
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering return r;
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return bus_unit_method_start_generic(bus, message, u, job_type, reload_if_possible, error);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poetteringstatic int method_start_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering return method_start_unit_generic(bus, message, userdata, JOB_START, false, error);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int method_stop_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return method_start_unit_generic(bus, message, userdata, JOB_STOP, false, error);
f7a5bb2842037fa27dbc99d92c3fee7fe1bbbc2aZbigniew Jędrzejewski-Szmek}
f7a5bb2842037fa27dbc99d92c3fee7fe1bbbc2aZbigniew Jędrzejewski-Szmek
f7a5bb2842037fa27dbc99d92c3fee7fe1bbbc2aZbigniew Jędrzejewski-Szmekstatic int method_reload_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
f7a5bb2842037fa27dbc99d92c3fee7fe1bbbc2aZbigniew Jędrzejewski-Szmek return method_start_unit_generic(bus, message, userdata, JOB_RELOAD, false, error);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidtstatic int method_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt return method_start_unit_generic(bus, message, userdata, JOB_RESTART, false, error);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int method_try_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return method_start_unit_generic(bus, message, userdata, JOB_TRY_RESTART, false, error);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt}
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int method_reload_or_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
4a61c3e51e96a747c30598d78ee3a24e7c569e9fZbigniew Jędrzejewski-Szmek return method_start_unit_generic(bus, message, userdata, JOB_RESTART, true, error);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int method_reload_or_try_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return method_start_unit_generic(bus, message, userdata, JOB_TRY_RESTART, true, error);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt}
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int method_start_unit_replace(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering Manager *m = userdata;
6baa7db00812437bbc87e73faa1a11b6cf631958Lennart Poettering const char *old_name;
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering Unit *u;
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering int r;
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering assert(bus);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(message);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(m);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt r = sd_bus_message_read(message, "s", &old_name);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt if (r < 0)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return r;
8531ae707d4d0203e83304d4af948b8169a5fce1Lennart Poettering
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt u = manager_get_unit(m, old_name);
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt if (!u || !u->job || u->job->type != JOB_START)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return method_start_unit_generic(bus, message, m, JOB_START, false, error);
}
static int method_kill_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
const char *name;
Unit *u;
int r;
assert(bus);
assert(message);
assert(m);
r = sd_bus_message_read(message, "s", &name);
if (r < 0)
return r;
u = manager_get_unit(m, name);
if (!u)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
return bus_unit_method_kill(bus, message, u, error);
}
static int method_reset_failed_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
const char *name;
Unit *u;
int r;
assert(bus);
assert(message);
assert(m);
r = sd_bus_message_read(message, "s", &name);
if (r < 0)
return r;
u = manager_get_unit(m, name);
if (!u)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
return bus_unit_method_reset_failed(bus, message, u, error);
}
static int method_set_unit_properties(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
const char *name;
Unit *u;
int r;
assert(bus);
assert(message);
assert(m);
r = sd_bus_message_read(message, "s", &name);
if (r < 0)
return r;
u = manager_get_unit(m, name);
if (!u)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
return bus_unit_method_set_properties(bus, message, u, error);
}
static int method_start_transient_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *name, *smode;
Manager *m = userdata;
JobMode mode;
UnitType t;
Unit *u;
int r;
assert(bus);
assert(message);
assert(m);
r = sd_bus_message_read(message, "ss", &name, &smode);
if (r < 0)
return r;
t = unit_name_to_type(name);
if (t < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit type.");
if (!unit_vtable[t]->can_transient)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit type %s does not support transient units.");
mode = job_mode_from_string(smode);
if (mode < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s is invalid.", smode);
r = selinux_access_check(bus, message, "start", error);
if (r < 0)
return r;
r = manager_load_unit(m, name, NULL, error, &u);
if (r < 0)
return r;
if (u->load_state != UNIT_NOT_FOUND || set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0)
return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name);
/* OK, the unit failed to load and is unreferenced, now let's
* fill in the transient data instead */
r = unit_make_transient(u);
if (r < 0)
return r;
/* Set our properties */
r = bus_unit_set_properties(u, message, UNIT_RUNTIME, false, error);
if (r < 0)
return r;
/* And load this stub fully */
r = unit_load(u);
if (r < 0)
return r;
manager_dispatch_load_queue(m);
/* Finally, start it */
return bus_unit_queue_job(bus, message, u, JOB_START, mode, false, error);
}
static int method_get_job(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *path = NULL;
Manager *m = userdata;
uint32_t id;
Job *j;
int r;
assert(bus);
assert(message);
assert(m);
r = sd_bus_message_read(message, "u", &id);
if (r < 0)
return r;
j = manager_get_job(m, id);
if (!j)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
r = selinux_unit_access_check(j->unit, bus, message, "status", error);
if (r < 0)
return r;
path = job_dbus_path(j);
if (!path)
return -ENOMEM;
return sd_bus_reply_method_return(message, "o", path);
}
static int method_cancel_job(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
uint32_t id;
Job *j;
int r;
assert(bus);
assert(message);
assert(m);
r = sd_bus_message_read(message, "u", &id);
if (r < 0)
return r;
j = manager_get_job(m, id);
if (!j)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
r = selinux_unit_access_check(j->unit, bus, message, "stop", error);
if (r < 0)
return r;
job_finish_and_invalidate(j, JOB_CANCELED, true);
return sd_bus_reply_method_return(message, NULL);
}
static int method_clear_jobs(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "reboot", error);
if (r < 0)
return r;
manager_clear_jobs(m);
return sd_bus_reply_method_return(message, NULL);
}
static int method_reset_failed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "reload", error);
if (r < 0)
return r;
manager_reset_failed(m);
return sd_bus_reply_method_return(message, NULL);
}
static int method_list_units(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
Manager *m = userdata;
const char *k;
Iterator i;
Unit *u;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "status", error);
if (r < 0)
return r;
r = sd_bus_message_new_method_return(message, &reply);
if (r < 0)
return r;
r = sd_bus_message_open_container(reply, 'a', "(ssssssouso)");
if (r < 0)
return r;
HASHMAP_FOREACH_KEY(u, k, m->units, i) {
_cleanup_free_ char *unit_path = NULL, *job_path = NULL;
Unit *following;
if (k != u->id)
continue;
following = unit_following(u);
unit_path = unit_dbus_path(u);
if (!unit_path)
return -ENOMEM;
if (u->job) {
job_path = job_dbus_path(u->job);
if (!job_path)
return -ENOMEM;
}
r = sd_bus_message_append(
reply, "(ssssssouso)",
u->id,
unit_description(u),
unit_load_state_to_string(u->load_state),
unit_active_state_to_string(unit_active_state(u)),
unit_sub_state_to_string(u),
following ? following->id : "",
unit_path,
u->job ? u->job->id : 0,
u->job ? job_type_to_string(u->job->type) : "",
job_path ? job_path : "/");
if (r < 0)
return r;
}
r = sd_bus_message_close_container(reply);
if (r < 0)
return r;
return sd_bus_send(bus, reply, NULL);
}
static int method_list_jobs(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
Manager *m = userdata;
Iterator i;
Job *j;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "status", error);
if (r < 0)
return r;
r = sd_bus_message_new_method_return(message, &reply);
if (r < 0)
return r;
r = sd_bus_message_open_container(reply, 'a', "(usssoo)");
if (r < 0)
return r;
HASHMAP_FOREACH(j, m->jobs, i) {
_cleanup_free_ char *unit_path = NULL, *job_path = NULL;
job_path = job_dbus_path(j);
if (!job_path)
return -ENOMEM;
unit_path = unit_dbus_path(j->unit);
if (!unit_path)
return -ENOMEM;
r = sd_bus_message_append(
reply, "(usssoo)",
j->id,
j->unit->id,
job_type_to_string(j->type),
job_state_to_string(j->state),
job_path,
unit_path);
if (r < 0)
return r;
}
r = sd_bus_message_close_container(reply);
if (r < 0)
return r;
return sd_bus_send(bus, reply, NULL);
}
static int method_subscribe(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "status", error);
if (r < 0)
return r;
r = bus_client_track(&m->subscribed, bus, sd_bus_message_get_sender(message));
if (r < 0)
return r;
if (r == 0)
return sd_bus_error_setf(error, BUS_ERROR_ALREADY_SUBSCRIBED, "Client is already subscribed.");
return sd_bus_reply_method_return(message, NULL);
}
static int method_unsubscribe(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "status", error);
if (r < 0)
return r;
r = bus_client_untrack(m->subscribed, bus, sd_bus_message_get_sender(message));
if (r < 0)
return r;
if (r == 0)
return sd_bus_error_setf(error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
return sd_bus_reply_method_return(message, NULL);
}
static int method_dump(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *dump = NULL;
_cleanup_fclose_ FILE *f = NULL;
Manager *m = userdata;
size_t size;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "status", error);
if (r < 0)
return r;
f = open_memstream(&dump, &size);
if (!f)
return -ENOMEM;
manager_dump_units(m, f, NULL);
manager_dump_jobs(m, f, NULL);
fflush(f);
if (ferror(f))
return -ENOMEM;
return sd_bus_reply_method_return(message, "s", dump);
}
static int method_create_snapshot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *path = NULL;
Manager *m = userdata;
const char *name;
int cleanup;
Snapshot *s;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "start", error);
if (r < 0)
return r;
r = sd_bus_message_read(message, "sb", &name, &cleanup);
if (r < 0)
return r;
if (isempty(name))
name = NULL;
r = snapshot_create(m, name, cleanup, error, &s);
if (r < 0)
return r;
path = unit_dbus_path(UNIT(s));
if (!path)
return -ENOMEM;
return sd_bus_reply_method_return(message, "o", path);
}
static int method_remove_snapshot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
const char *name;
Unit *u;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "stop", error);
if (r < 0)
return r;
r = sd_bus_message_read(message, "s", &name);
if (r < 0)
return r;
u = manager_get_unit(m, name);
if (!u)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s does not exist.", name);
if (u->type != UNIT_SNAPSHOT)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not a snapshot", name);
return bus_snapshot_method_remove(bus, message, u, error);
}
static int method_reload(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "reload", error);
if (r < 0)
return r;
/* Instead of sending the reply back right away, we just
* remember that we need to and then send it after the reload
* is finished. That way the caller knows when the reload
* finished. */
assert(!m->queued_message);
r = sd_bus_message_new_method_return(message, &m->queued_message);
if (r < 0)
return r;
m->queued_message_bus = sd_bus_ref(bus);
m->exit_code = MANAGER_RELOAD;
return 1;
}
static int method_reexecute(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "reload", error);
if (r < 0)
return r;
/* We don't send a reply back here, the client should
* just wait for us disconnecting. */
m->exit_code = MANAGER_REEXECUTE;
return 1;
}
static int method_exit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "halt", error);
if (r < 0)
return r;
if (m->running_as == SYSTEMD_SYSTEM)
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
m->exit_code = MANAGER_EXIT;
return sd_bus_reply_method_return(message, NULL);
}
static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "reboot", error);
if (r < 0)
return r;
if (m->running_as != SYSTEMD_SYSTEM)
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
m->exit_code = MANAGER_REBOOT;
return sd_bus_reply_method_return(message, NULL);
}
static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "halt", error);
if (r < 0)
return r;
if (m->running_as != SYSTEMD_SYSTEM)
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
m->exit_code = MANAGER_POWEROFF;
return sd_bus_reply_method_return(message, NULL);
}
static int method_halt(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "halt", error);
if (r < 0)
return r;
if (m->running_as != SYSTEMD_SYSTEM)
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Halt is only supported for system managers.");
m->exit_code = MANAGER_HALT;
return sd_bus_reply_method_return(message, NULL);
}
static int method_kexec(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "reboot", error);
if (r < 0)
return r;
if (m->running_as != SYSTEMD_SYSTEM)
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers.");
m->exit_code = MANAGER_KEXEC;
return sd_bus_reply_method_return(message, NULL);
}
static int method_switch_root(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
char *ri = NULL, *rt = NULL;
const char *root, *init;
Manager *m = userdata;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "reboot", error);
if (r < 0)
return r;
if (m->running_as != SYSTEMD_SYSTEM)
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers.");
r = sd_bus_message_read(message, "ss", &root, &init);
if (r < 0)
return r;
if (path_equal(root, "/") || !path_is_absolute(root))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid switch root path %s", root);
/* Safety check */
if (isempty(init)) {
if (! path_is_os_tree(root))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified switch root path %s does not seem to be an OS tree. /etc/os-release is missing.", root);
} else {
_cleanup_free_ char *p = NULL;
if (!path_is_absolute(init))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid init path %s", init);
p = strappend(root, init);
if (!p)
return -ENOMEM;
if (access(p, X_OK) < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified init binary %s does not exist.", p);
}
rt = strdup(root);
if (!rt)
return -ENOMEM;
if (!isempty(init)) {
ri = strdup(init);
if (!ri) {
free(rt);
return -ENOMEM;
}
}
free(m->switch_root);
m->switch_root = rt;
free(m->switch_root_init);
m->switch_root_init = ri;
m->exit_code = MANAGER_SWITCH_ROOT;
return sd_bus_reply_method_return(message, NULL);
}
static int method_set_environment(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_strv_free_ char **plus = NULL;
Manager *m = userdata;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "reload", error);
if (r < 0)
return r;
r = sd_bus_message_read_strv(message, &plus);
if (r < 0)
return r;
if (!strv_env_is_valid(plus))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
r = manager_environment_add(m, NULL, plus);
if (r < 0)
return r;
return sd_bus_reply_method_return(message, NULL);
}
static int method_unset_environment(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_strv_free_ char **minus = NULL;
Manager *m = userdata;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "reload", error);
if (r < 0)
return r;
r = sd_bus_message_read_strv(message, &minus);
if (r < 0)
return r;
if (!strv_env_name_or_assignment_is_valid(minus))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
r = manager_environment_add(m, minus, NULL);
if (r < 0)
return r;
return sd_bus_reply_method_return(message, NULL);
}
static int method_unset_and_set_environment(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_strv_free_ char **minus = NULL, **plus = NULL;
Manager *m = userdata;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "reload", error);
if (r < 0)
return r;
r = sd_bus_message_read_strv(message, &plus);
if (r < 0)
return r;
r = sd_bus_message_read_strv(message, &minus);
if (r < 0)
return r;
if (!strv_env_is_valid(plus))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
if (!strv_env_name_or_assignment_is_valid(minus))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
r = manager_environment_add(m, minus, plus);
if (r < 0)
return r;
return sd_bus_reply_method_return(message, NULL);
}
static int method_list_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
Manager *m = userdata;
UnitFileList *item;
Hashmap *h;
Iterator i;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "status", error);
if (r < 0)
return r;
r = sd_bus_message_new_method_return(message, &reply);
if (r < 0)
return r;
h = hashmap_new(string_hash_func, string_compare_func);
if (!h)
return -ENOMEM;
r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
if (r < 0)
goto fail;
r = sd_bus_message_open_container(reply, 'a', "(ss)");
if (r < 0)
goto fail;
HASHMAP_FOREACH(item, h, i) {
r = sd_bus_message_append(reply, "(ss)", item->path, unit_file_state_to_string(item->state));
if (r < 0)
goto fail;
}
unit_file_list_free(h);
r = sd_bus_message_close_container(reply);
if (r < 0)
return r;
return sd_bus_send(bus, reply, NULL);
fail:
unit_file_list_free(h);
return r;
}
static int method_get_unit_file_state(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
const char *name;
UnitFileState state;
UnitFileScope scope;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "status", error);
if (r < 0)
return r;
r = sd_bus_message_read(message, "s", &name);
if (r < 0)
return r;
scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
state = unit_file_get_state(scope, NULL, name);
if (state < 0)
return state;
return sd_bus_reply_method_return(message, "s", unit_file_state_to_string(state));
}
static int method_get_default_target(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *default_target = NULL;
Manager *m = userdata;
UnitFileScope scope;
int r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "status", error);
if (r < 0)
return r;
scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
r = unit_file_get_default(scope, NULL, &default_target);
if (r < 0)
return r;
return sd_bus_reply_method_return(message, "s", default_target);
}
static int send_unit_files_changed(sd_bus *bus, const char *destination, void *userdata) {
_cleanup_bus_message_unref_ sd_bus_message *message = NULL;
int r;
assert(bus);
r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged", &message);
if (r < 0)
return r;
return sd_bus_send_to(bus, message, destination, NULL);
}
static int reply_unit_file_changes_and_free(
Manager *m,
sd_bus *bus,
sd_bus_message *message,
int carries_install_info,
UnitFileChange *changes,
unsigned n_changes) {
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
unsigned i;
int r;
if (n_changes > 0)
bus_manager_foreach_client(m, send_unit_files_changed, NULL);
r = sd_bus_message_new_method_return(message, &reply);
if (r < 0)
goto fail;
if (carries_install_info >= 0) {
r = sd_bus_message_append(reply, "b", carries_install_info);
if (r < 0)
goto fail;
}
r = sd_bus_message_open_container(reply, 'a', "(sss)");
if (r < 0)
goto fail;
for (i = 0; i < n_changes; i++) {
r = sd_bus_message_append(
reply, "(sss)",
unit_file_change_type_to_string(changes[i].type),
changes[i].path,
changes[i].source);
if (r < 0)
goto fail;
}
r = sd_bus_message_close_container(reply);
if (r < 0)
goto fail;
return sd_bus_send(bus, reply, NULL);
fail:
unit_file_changes_free(changes, n_changes);
return r;
}
static int method_enable_unit_files_generic(
sd_bus *bus,
sd_bus_message *message,
Manager *m, const
char *verb,
int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes),
bool carries_install_info,
sd_bus_error *error) {
_cleanup_strv_free_ char **l = NULL;
char **i;
UnitFileChange *changes = NULL;
unsigned n_changes = 0;
UnitFileScope scope;
int runtime, force, r;
assert(bus);
assert(message);
assert(m);
r = sd_bus_message_read_strv(message, &l);
if (r < 0)
return r;
#ifdef HAVE_SELINUX
STRV_FOREACH(i, l) {
Unit *u;
u = manager_get_unit(m, *i);
if (u) {
r = selinux_unit_access_check(u, bus, message, verb, error);
if (r < 0)
return r;
}
}
#endif
r = sd_bus_message_read(message, "bb", &runtime, &force);
if (r < 0)
return r;
scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
r = call(scope, runtime, NULL, l, force, &changes, &n_changes);
if (r < 0)
return r;
return reply_unit_file_changes_and_free(m, bus, message, carries_install_info ? r : -1, changes, n_changes);
}
static int method_enable_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_enable, true, error);
}
static int method_reenable_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_reenable, true, error);
}
static int method_link_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_link, false, error);
}
static int method_preset_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_preset, true, error);
}
static int method_mask_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
return method_enable_unit_files_generic(bus, message, userdata, "disable", unit_file_mask, false, error);
}
static int method_disable_unit_files_generic(
sd_bus *bus,
sd_bus_message *message,
Manager *m, const
char *verb,
int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes),
sd_bus_error *error) {
_cleanup_strv_free_ char **l = NULL;
UnitFileChange *changes = NULL;
unsigned n_changes = 0;
UnitFileScope scope;
int r, runtime;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, verb, error);
if (r < 0)
return r;
r = sd_bus_message_read_strv(message, &l);
if (r < 0)
return r;
r = sd_bus_message_read(message, "b", &runtime);
if (r < 0)
return r;
scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
r = call(scope, runtime, NULL, l, &changes, &n_changes);
if (r < 0)
return r;
return reply_unit_file_changes_and_free(m, bus, message, -1, changes, n_changes);
}
static int method_disable_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
return method_disable_unit_files_generic(bus, message, userdata, "disable", unit_file_disable, error);
}
static int method_unmask_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
return method_disable_unit_files_generic(bus, message, userdata, "enable", unit_file_unmask, error);
}
static int method_set_default_target(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
UnitFileChange *changes = NULL;
unsigned n_changes = 0;
Manager *m = userdata;
UnitFileScope scope;
const char *name;
int force, r;
assert(bus);
assert(message);
assert(m);
r = selinux_access_check(bus, message, "enable", error);
if (r < 0)
return r;
r = sd_bus_message_read(message, "sb", &name, &force);
if (r < 0)
return r;
scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
r = unit_file_set_default(scope, NULL, name, force, &changes, &n_changes);
if (r < 0)
return r;
return reply_unit_file_changes_and_free(m, bus, message, -1, changes, n_changes);
}
const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Version", "s", property_get_version, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Features", "s", property_get_features, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Virtualization", "s", property_get_virtualization, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Tainted", "s", property_get_tainted, 0, SD_BUS_VTABLE_PROPERTY_CONST),
BUS_PROPERTY_DUAL_TIMESTAMP("FirmwareTimestamp", offsetof(Manager, firmware_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
BUS_PROPERTY_DUAL_TIMESTAMP("LoaderTimestamp", offsetof(Manager, loader_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
BUS_PROPERTY_DUAL_TIMESTAMP("KernelTimestamp", offsetof(Manager, kernel_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
BUS_PROPERTY_DUAL_TIMESTAMP("InitRDTimestamp", offsetof(Manager, initrd_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
BUS_PROPERTY_DUAL_TIMESTAMP("UserspaceTimestamp", offsetof(Manager, userspace_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
BUS_PROPERTY_DUAL_TIMESTAMP("FinishTimestamp", offsetof(Manager, finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
BUS_PROPERTY_DUAL_TIMESTAMP("SecurityStartTimestamp", offsetof(Manager, security_start_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
BUS_PROPERTY_DUAL_TIMESTAMP("SecurityFinishTimestamp", offsetof(Manager, security_finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsStartTimestamp", offsetof(Manager, generators_start_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsFinishTimestamp", offsetof(Manager, generators_finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadStartTimestamp", offsetof(Manager, units_load_start_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadFinishTimestamp", offsetof(Manager, units_load_finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level, property_set_log_level, 0, 0),
SD_BUS_WRITABLE_PROPERTY("LogTarget", "s", property_get_log_target, property_set_log_target, 0, 0),
SD_BUS_PROPERTY("NNames", "u", property_get_n_names, 0, 0),
SD_BUS_PROPERTY("NJobs", "u", property_get_n_jobs, 0, 0),
SD_BUS_PROPERTY("NInstalledJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_installed_jobs), 0),
SD_BUS_PROPERTY("NFailedJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_failed_jobs), 0),
SD_BUS_PROPERTY("Progress", "d", property_get_progress, 0, 0),
SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(Manager, environment), 0),
SD_BUS_PROPERTY("ConfirmSpawn", "b", bus_property_get_bool, offsetof(Manager, confirm_spawn), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ShowStatus", "b", bus_property_get_bool, offsetof(Manager, show_status), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("UnitPath", "as", NULL, offsetof(Manager, lookup_paths.unit_path), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, shutdown_watchdog), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("LoadUnit", "s", "o", method_load_unit, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("StartUnit", "ss", "o", method_start_unit, 0),
SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, 0),
SD_BUS_METHOD("StopUnit", "ss", "o", method_stop_unit, 0),
SD_BUS_METHOD("ReloadUnit", "ss", "o", method_reload_unit, 0),
SD_BUS_METHOD("RestartUnit", "ss", "o", method_restart_unit, 0),
SD_BUS_METHOD("TryRestartUnit", "ss", "o", method_try_restart_unit, 0),
SD_BUS_METHOD("ReloadOrRestartUnit", "ss", "o", method_reload_or_restart_unit, 0),
SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit, 0),
SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, 0),
SD_BUS_METHOD("SetUnitProperties", "sba(sv)", NULL, method_set_unit_properties, 0),
SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, 0),
SD_BUS_METHOD("GetJob", "u", "o", method_get_job, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CancelJob", "u", NULL, method_cancel_job, 0),
SD_BUS_METHOD("ClearJobs", NULL, NULL, method_clear_jobs, 0),
SD_BUS_METHOD("ResetFailed", NULL, NULL, method_reset_failed, 0),
SD_BUS_METHOD("ListUnits", NULL, "a(ssssssouso)", method_list_units, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ListJobs", NULL, "a(usssoo)", method_list_jobs, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Dump", NULL, "s", method_dump, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_create_snapshot, 0),
SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_remove_snapshot, 0),
SD_BUS_METHOD("Reload", NULL, NULL, method_reload, 0),
SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute, 0),
SD_BUS_METHOD("Exit", NULL, NULL, method_exit, 0),
SD_BUS_METHOD("Reboot", NULL, NULL, method_reboot, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
SD_BUS_METHOD("PowerOff", NULL, NULL, method_poweroff, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
SD_BUS_METHOD("Halt", NULL, NULL, method_halt, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
SD_BUS_METHOD("KExec", NULL, NULL, method_kexec, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
SD_BUS_METHOD("SwitchRoot", "ss", NULL, method_switch_root, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
SD_BUS_METHOD("SetEnvironment", "as", NULL, method_set_environment, 0),
SD_BUS_METHOD("UnsetEnvironment", "as", NULL, method_unset_environment, 0),
SD_BUS_METHOD("UnsetAndSetEnvironment", "asas", NULL, method_unset_and_set_environment, 0),
SD_BUS_METHOD("ListUnitFiles", NULL, "a(ss)", method_list_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetUnitFileState", "s", "s", method_get_unit_file_state, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("EnableUnitFiles", "asbb", "ba(sss)", method_enable_unit_files, 0),
SD_BUS_METHOD("DisableUnitFiles", "asb", "a(sss)", method_disable_unit_files, 0),
SD_BUS_METHOD("ReenableUnitFiles", "asbb", "ba(sss)", method_reenable_unit_files, 0),
SD_BUS_METHOD("LinkUnitFiles", "asbb", "a(sss)", method_link_unit_files, 0),
SD_BUS_METHOD("PresetUnitFiles", "asbb", "ba(sss)", method_preset_unit_files, 0),
SD_BUS_METHOD("MaskUnitFiles", "asbb", "a(sss)", method_mask_unit_files, 0),
SD_BUS_METHOD("UnmaskUnitFiles", "asb", "a(sss)", method_unmask_unit_files, 0),
SD_BUS_METHOD("SetDefaultTarget", "sb", "a(sss)", method_set_default_target, 0),
SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_SIGNAL("UnitNew", "so", 0),
SD_BUS_SIGNAL("UnitRemoved", "so", 0),
SD_BUS_SIGNAL("JobNew", "uos", 0),
SD_BUS_SIGNAL("JobRemoved", "uoss", 0),
SD_BUS_SIGNAL("StartupFinished", "tttttt", 0),
SD_BUS_SIGNAL("UnitFilesChanged", NULL, 0),
SD_BUS_SIGNAL("Reloading", "b", 0),
SD_BUS_VTABLE_END
};
int bus_manager_foreach_client(Manager *m, int (*send_message)(sd_bus *bus, const char *destination, void *userdata), void *userdata) {
Iterator i;
sd_bus *b;
unsigned n;
int r, ret;
n = set_size(m->subscribed);
if (n <= 0)
return 0;
if (n == 1) {
BusTrackedClient *d;
assert_se(d = set_first(m->subscribed));
return send_message(d->bus, isempty(d->name) ? NULL : d->name, userdata);
}
ret = 0;
/* Send to everybody */
SET_FOREACH(b, m->private_buses, i) {
r = send_message(b, NULL, userdata);
if (r < 0)
ret = r;
}
if (m->api_bus) {
r = send_message(m->api_bus, NULL, userdata);
if (r < 0)
ret = r;
}
return ret;
}
static int send_finished(sd_bus *bus, const char *destination, void *userdata) {
_cleanup_bus_message_unref_ sd_bus_message *message = NULL;
usec_t *times = userdata;
int r;
assert(bus);
assert(times);
r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished", &message);
if (r < 0)
return r;
r = sd_bus_message_append(message, "tttttt", times[0], times[1], times[2], times[3], times[4], times[5]);
if (r < 0)
return r;
return sd_bus_send_to(bus, message, destination, NULL);
}
void bus_manager_send_finished(
Manager *m,
usec_t firmware_usec,
usec_t loader_usec,
usec_t kernel_usec,
usec_t initrd_usec,
usec_t userspace_usec,
usec_t total_usec) {
int r;
assert(m);
r = bus_manager_foreach_client(m, send_finished,
(usec_t[6]) { firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec });
if (r < 0)
log_debug("Failed to send finished signal: %s", strerror(-r));
}
static int send_reloading(sd_bus *bus, const char *destination, void *userdata) {
_cleanup_bus_message_unref_ sd_bus_message *message = NULL;
int r;
assert(bus);
r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading", &message);
if (r < 0)
return r;
r = sd_bus_message_append(message, "b", PTR_TO_INT(userdata));
if (r < 0)
return r;
return sd_bus_send_to(bus, message, destination, NULL);
}
void bus_manager_send_reloading(Manager *m, bool active) {
int r;
assert(m);
r = bus_manager_foreach_client(m, send_reloading, INT_TO_PTR(active));
if (r < 0)
log_debug("Failed to send reloading signal: %s", strerror(-r));
}