dbus-manager.c revision da927ba997d68401563b927f92e6e40e021a8e5c
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
#include <unistd.h>
#include "log.h"
#include "strv.h"
#include "build.h"
#include "install.h"
#include "selinux-access.h"
#include "watchdog.h"
#include "clock-util.h"
#include "path-util.h"
#include "virt.h"
#include "architecture.h"
#include "env-util.h"
#include "dbus.h"
#include "dbus-job.h"
#include "dbus-manager.h"
#include "dbus-unit.h"
#include "dbus-snapshot.h"
#include "dbus-execute.h"
#include "bus-errors.h"
static int property_get_version(
const char *path,
const char *interface,
const char *property,
void *userdata,
sd_bus_error *error) {
}
static int property_get_features(
const char *path,
const char *interface,
const char *property,
void *userdata,
sd_bus_error *error) {
}
static int property_get_virtualization(
const char *path,
const char *interface,
const char *property,
void *userdata,
sd_bus_error *error) {
}
static int property_get_architecture(
const char *path,
const char *interface,
const char *property,
void *userdata,
sd_bus_error *error) {
}
static int property_get_tainted(
const char *path,
const char *interface,
const char *property,
void *userdata,
sd_bus_error *error) {
_cleanup_free_ char *p = NULL;
assert(m);
if (m->taint_usr)
e = stpcpy(e, "split-usr:");
if (readlink_malloc("/etc/mtab", &p) < 0)
e = stpcpy(e, "mtab-not-symlink:");
e = stpcpy(e, "cgroups-missing:");
if (clock_is_localtime() > 0)
e = stpcpy(e, "local-hwclock:");
/* remove the last ':' */
if (e != buf)
e[-1] = 0;
}
static int property_get_log_target(
const char *path,
const char *interface,
const char *property,
void *userdata,
sd_bus_error *error) {
}
static int property_set_log_target(
const char *path,
const char *interface,
const char *property,
void *userdata,
sd_bus_error *error) {
const char *t;
int r;
if (r < 0)
return r;
return log_set_target_from_string(t);
}
static int property_get_log_level(
const char *path,
const char *interface,
const char *property,
void *userdata,
sd_bus_error *error) {
_cleanup_free_ char *t = NULL;
int r;
r = log_level_to_string_alloc(log_get_max_level(), &t);
if (r < 0)
return r;
}
static int property_set_log_level(
const char *path,
const char *interface,
const char *property,
void *userdata,
sd_bus_error *error) {
const char *t;
int r;
if (r < 0)
return r;
return log_set_max_level_from_string(t);
}
static int property_get_n_names(
const char *path,
const char *interface,
const char *property,
void *userdata,
sd_bus_error *error) {
assert(m);
}
static int property_get_n_failed_units(
const char *path,
const char *interface,
const char *property,
void *userdata,
sd_bus_error *error) {
assert(m);
}
static int property_get_n_jobs(
const char *path,
const char *interface,
const char *property,
void *userdata,
sd_bus_error *error) {
assert(m);
}
static int property_get_progress(
const char *path,
const char *interface,
const char *property,
void *userdata,
sd_bus_error *error) {
double d;
assert(m);
if (dual_timestamp_is_set(&m->finish_timestamp))
d = 1.0;
else
}
static int property_get_system_state(
const char *path,
const char *interface,
const char *property,
void *userdata,
sd_bus_error *error) {
assert(m);
}
static int property_set_runtime_watchdog(
const char *path,
const char *interface,
const char *property,
void *userdata,
sd_bus_error *error) {
int r;
if (r < 0)
return r;
return watchdog_set_timeout(t);
}
static int method_get_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *name;
Unit *u;
int r;
assert(m);
/* Anyone can call this method */
if (r < 0)
return r;
u = manager_get_unit(m, name);
if (!u)
if (r < 0)
return r;
path = unit_dbus_path(u);
if (!path)
return -ENOMEM;
}
static int method_get_unit_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Unit *u;
int r;
assert(m);
/* Anyone can call this method */
if (r < 0)
return r;
if (pid == 0) {
if (r < 0)
return r;
if (r < 0)
return r;
}
u = manager_get_unit_by_pid(m, pid);
if (!u)
return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_PID, "PID %u does not belong to any loaded unit.", pid);
if (r < 0)
return r;
path = unit_dbus_path(u);
if (!path)
return -ENOMEM;
}
static int method_load_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *name;
Unit *u;
int r;
assert(m);
/* Anyone can call this method */
if (r < 0)
return r;
if (r < 0)
return r;
if (r < 0)
return r;
path = unit_dbus_path(u);
if (!path)
return -ENOMEM;
}
static 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) {
const char *name;
Unit *u;
int r;
assert(m);
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 */
if (r < 0)
return r;
if (r < 0)
return r;
}
static int method_start_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
}
static int method_stop_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
}
static int method_reload_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
}
static int method_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
}
static int method_try_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
}
static int method_reload_or_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
}
static int method_reload_or_try_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
}
static int method_start_unit_replace(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *old_name;
Unit *u;
int r;
assert(m);
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 */
if (r < 0)
return r;
u = manager_get_unit(m, old_name);
}
static int method_kill_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *name;
Unit *u;
int r;
assert(m);
/* Like bus_verify_manage_unit_async(), but uses CAP_SYS_KILL */
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 */
if (r < 0)
return r;
u = manager_get_unit(m, name);
if (!u)
}
static int method_reset_failed_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *name;
Unit *u;
int r;
assert(m);
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 */
if (r < 0)
return r;
u = manager_get_unit(m, name);
if (!u)
}
static int method_set_unit_properties(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *name;
Unit *u;
int r;
assert(m);
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 */
if (r < 0)
return r;
u = manager_get_unit(m, name);
if (!u)
}
static int method_start_transient_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
UnitType t;
Unit *u;
int r;
assert(m);
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 */
if (r < 0)
return r;
t = unit_name_to_type(name);
if (t < 0)
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.", unit_type_to_string(t));
if (mode < 0)
if (r < 0)
return r;
if (r < 0)
return r;
/* 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 */
if (r < 0)
return r;
/* And load this stub fully */
r = unit_load(u);
if (r < 0)
return r;
/* Finally, start it */
}
static int method_get_job(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Job *j;
int r;
assert(m);
/* Anyone can call this method */
if (r < 0)
return r;
j = manager_get_job(m, id);
if (!j)
if (r < 0)
return r;
path = job_dbus_path(j);
if (!path)
return -ENOMEM;
}
static int method_cancel_job(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Job *j;
int r;
assert(m);
if (r < 0)
return r;
j = manager_get_job(m, id);
if (!j)
}
static int method_clear_jobs(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
int r;
assert(m);
if (r < 0)
return r;
}
static int method_reset_failed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
int r;
assert(m);
if (r < 0)
return r;
}
static int list_units_filtered(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error, char **states) {
const char *k;
Iterator i;
Unit *u;
int r;
assert(m);
/* Anyone can call this method */
if (r < 0)
return r;
if (r < 0)
return r;
if (r < 0)
return r;
HASHMAP_FOREACH_KEY(u, k, m->units, i) {
if (k != u->id)
continue;
following = unit_following(u);
if (!strv_isempty(states) &&
continue;
unit_path = unit_dbus_path(u);
if (!unit_path)
return -ENOMEM;
if (u->job) {
if (!job_path)
return -ENOMEM;
}
reply, "(ssssssouso)",
u->id,
unit_description(u),
if (r < 0)
return r;
}
if (r < 0)
return r;
}
static int method_list_units(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
}
static int method_list_units_filtered(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
int r;
if (r < 0)
return r;
}
static int method_list_jobs(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Iterator i;
Job *j;
int r;
assert(m);
/* Anyone can call this method */
if (r < 0)
return r;
if (r < 0)
return r;
if (r < 0)
return r;
HASHMAP_FOREACH(j, m->jobs, i) {
job_path = job_dbus_path(j);
if (!job_path)
return -ENOMEM;
if (!unit_path)
return -ENOMEM;
reply, "(usssoo)",
j->id,
job_type_to_string(j->type),
job_state_to_string(j->state),
if (r < 0)
return r;
}
if (r < 0)
return r;
}
static int method_subscribe(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
int r;
assert(m);
/* Anyone can call this method */
if (r < 0)
return r;
/* Note that direct bus connection subscribe by
* default, we only track peers on the API bus here */
if (!m->subscribed) {
if (r < 0)
return r;
}
if (r < 0)
return r;
if (r == 0)
}
}
static int method_unsubscribe(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
int r;
assert(m);
/* Anyone can call this method */
if (r < 0)
return r;
if (r < 0)
return r;
if (r == 0)
}
}
int r;
assert(m);
/* Anyone can call this method */
if (r < 0)
return r;
if (!f)
return -ENOMEM;
manager_dump_units(m, f, NULL);
manager_dump_jobs(m, f, NULL);
fflush(f);
if (ferror(f))
return -ENOMEM;
}
static int method_create_snapshot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *name;
int cleanup;
int r;
assert(m);
if (r < 0)
return r;
if (r < 0)
return r;
if (r < 0)
return r;
if (!path)
return -ENOMEM;
}
static int method_remove_snapshot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *name;
Unit *u;
int r;
assert(m);
if (r < 0)
return r;
if (r < 0)
return r;
u = manager_get_unit(m, name);
if (!u)
if (u->type != UNIT_SNAPSHOT)
}
static int method_reload(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
int r;
assert(m);
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 */
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);
if (r < 0)
return r;
m->exit_code = MANAGER_RELOAD;
return 1;
}
static int method_reexecute(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
int r;
assert(m);
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 */
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;
}
int r;
assert(m);
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;
}
static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
int r;
assert(m);
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;
}
static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
int r;
assert(m);
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;
}
int r;
assert(m);
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;
}
static int method_kexec(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
int r;
assert(m);
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;
}
static int method_switch_root(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
int r;
assert(m);
if (r < 0)
return r;
if (m->running_as != SYSTEMD_SYSTEM)
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Root switching is only supported by system manager.");
if (r < 0)
return r;
/* Safety check */
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. os-release file is missing.", root);
} else {
_cleanup_free_ char *p = NULL;
if (!path_is_absolute(init))
if (!p)
return -ENOMEM;
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified init binary %s does not exist.", p);
}
if (!rt)
return -ENOMEM;
if (!ri) {
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;
}
static int method_set_environment(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
int r;
assert(m);
if (r < 0)
return r;
if (r < 0)
return r;
if (!strv_env_is_valid(plus))
if (r < 0)
return r;
}
static int method_unset_environment(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
int r;
assert(m);
if (r < 0)
return r;
if (r < 0)
return r;
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
if (r < 0)
return r;
}
static int method_unset_and_set_environment(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
int r;
assert(m);
if (r < 0)
return r;
if (r < 0)
return r;
if (r < 0)
return r;
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
if (!strv_env_is_valid(plus))
if (r < 0)
return r;
}
static int method_list_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Hashmap *h;
Iterator i;
int r;
assert(m);
/* Anyone can call this method */
if (r < 0)
return r;
if (r < 0)
return r;
h = hashmap_new(&string_hash_ops);
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;
if (r < 0)
goto fail;
HASHMAP_FOREACH(item, h, i) {
if (r < 0)
goto fail;
}
if (r < 0)
return r;
fail:
return r;
}
static int method_get_unit_file_state(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *name;
int r;
assert(m);
/* Anyone can call this method */
if (r < 0)
return r;
if (r < 0)
return r;
if (state < 0)
return state;
}
static int method_get_default_target(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
int r;
assert(m);
/* Anyone can call this method */
if (r < 0)
return r;
if (r < 0)
return r;
}
int r;
r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
if (r < 0)
return r;
}
static int reply_unit_file_changes_and_free(
Manager *m,
int carries_install_info,
unsigned n_changes) {
unsigned i;
int r;
if (n_changes > 0) {
if (r < 0)
log_debug_errno(r, "Failed to send UnitFilesChanged signal: %m");
}
if (r < 0)
goto fail;
if (carries_install_info >= 0) {
if (r < 0)
goto fail;
}
if (r < 0)
goto fail;
for (i = 0; i < n_changes; i++) {
reply, "(sss)",
if (r < 0)
goto fail;
}
if (r < 0)
goto fail;
fail:
return r;
}
static int method_enable_unit_files_generic(
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;
unsigned n_changes = 0;
assert(m);
if (r < 0)
return r;
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
r = sd_bus_message_read_strv(message, &l);
if (r < 0)
return r;
if (r < 0)
return r;
if (r < 0)
return r;
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 unit_file_preset_without_mode(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes) {
return unit_file_preset(scope, runtime, root_dir, files, UNIT_FILE_PRESET_FULL, force, changes, n_changes);
}
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_without_mode, 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_preset_unit_files_with_mode(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_strv_free_ char **l = NULL;
unsigned n_changes = 0;
const char *mode;
assert(m);
if (r < 0)
return r;
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
r = sd_bus_message_read_strv(message, &l);
if (r < 0)
return r;
if (r < 0)
return r;
else {
if (mm < 0)
return -EINVAL;
}
if (r < 0)
return r;
if (r < 0)
return r;
}
static int method_disable_unit_files_generic(
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;
unsigned n_changes = 0;
int r, runtime;
assert(m);
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 */
if (r < 0)
return r;
r = sd_bus_message_read_strv(message, &l);
if (r < 0)
return r;
if (r < 0)
return r;
if (r < 0)
return r;
}
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) {
unsigned n_changes = 0;
const char *name;
int force, r;
assert(m);
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 */
if (r < 0)
return r;
if (r < 0)
return r;
if (r < 0)
return r;
}
static int method_preset_all_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
unsigned n_changes = 0;
const char *mode;
assert(m);
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 */
if (r < 0)
return r;
if (r < 0)
return r;
else {
if (mm < 0)
return -EINVAL;
}
if (r < 0)
return r;
}
static int method_add_dependency_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_strv_free_ char **l = NULL;
unsigned n_changes = 0;
char *target;
char *type;
assert(m);
if (r < 0)
return r;
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
r = sd_bus_message_read_strv(message, &l);
if (r < 0)
return r;
if (r < 0)
return r;
if (dep < 0)
return -EINVAL;
if (r < 0)
return r;
if (r < 0)
return r;
}
const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_PROPERTY("Virtualization", "s", property_get_virtualization, 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_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("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), 0),
SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, shutdown_watchdog), 0),
SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ReloadOrRestartUnit", "ss", "o", method_reload_or_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetUnitProperties", "sba(sv)", NULL, method_set_unit_properties, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ListUnitsFiltered", "as", "a(ssssssouso)", method_list_units_filtered, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SwitchRoot", "ss", NULL, method_switch_root, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
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, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("DisableUnitFiles", "asb", "a(sss)", method_disable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ReenableUnitFiles", "asbb", "ba(sss)", method_reenable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("LinkUnitFiles", "asbb", "a(sss)", method_link_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("PresetUnitFiles", "asbb", "ba(sss)", method_preset_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("PresetUnitFilesWithMode", "assbb", "ba(sss)", method_preset_unit_files_with_mode, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("MaskUnitFiles", "asbb", "a(sss)", method_mask_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("UnmaskUnitFiles", "asb", "a(sss)", method_unmask_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetDefaultTarget", "sb", "a(sss)", method_set_default_target, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("PresetAllUnitFiles", "sbb", "a(sss)", method_preset_all_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("AddDependencyUnitFiles", "asssbb", "a(sss)", method_add_dependency_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
};
int r;
r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
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;
}
Manager *m,
usec_t total_usec) {
int r;
assert(m);
r = bus_foreach_bus(
m,
NULL,
(usec_t[6]) {
});
if (r < 0)
log_debug_errno(r, "Failed to send finished signal: %m");
}
int r;
r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading");
if (r < 0)
return r;
if (r < 0)
return r;
}
int r;
assert(m);
if (r < 0)
log_debug_errno(r, "Failed to send reloading signal: %m");
}