machine-dbus.c revision 40e1f4ea7458a0a80eaf1ef356e52bfe0835412e
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering This file is part of systemd.
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering Copyright 2011 Lennart Poettering
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering systemd is free software; you can redistribute it and/or modify it
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering under the terms of the GNU Lesser General Public License as published by
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering (at your option) any later version.
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering systemd is distributed in the hope that it will be useful, but
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering Lesser General Public License for more details.
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering You should have received a copy of the GNU Lesser General Public License
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
a0f29c767a3bb3d621c658fa5b87063e1f44e24aLennart Poettering/* When we include libgen.h because we need dirname() we immediately
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering * undefine basename() since libgen.h defines it as a macro to the POSIX
874ff7bf4d6fe693542209f127d23cd89adc499bLennart Poettering * version which is really broken. We prefer GNU basename(). */
874ff7bf4d6fe693542209f127d23cd89adc499bLennart Poettering return sd_bus_message_append_array(reply, 'y', &m->id, 16);
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering state = machine_state_to_string(machine_get_state(m));
84e51726a38e133ca42d2f30f0668d3921b210cbLennart Poettering r = sd_bus_message_append_basic(reply, 's', state);
assert(m);
NULL,
error);
r = machine_stop(m);
const char *swho;
assert(m);
if (who < 0)
NULL,
error);
int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd_bus_error *error) {
assert(m);
switch (m->class) {
case MACHINE_HOST: {
struct local_address *a;
for (a = addresses, i = 0; i < n; a++, i++) {
r = sd_bus_message_append_array(reply, 'y', &addresses[i].address, FAMILY_ADDRESS_SIZE(addresses[i].family));
case MACHINE_CONTAINER: {
return sd_bus_error_setf(error, BUS_ERROR_NO_PRIVATE_NETWORKING, "Machine %s does not use private networking", m->name);
return -errno;
if (child < 0)
if (child == 0) {
struct local_address *a;
for (a = addresses, i = 0; i < n; a++, i++) {
int family;
ssize_t n;
return -errno;
switch (family) {
case AF_INET:
return -EIO;
case AF_INET6:
return -EIO;
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting IP address data is only supported on container machines.");
int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) {
assert(m);
switch (m->class) {
case MACHINE_HOST:
case MACHINE_CONTAINER: {
return -errno;
if (child < 0)
if (child == 0) {
if (fd < 0) {
if (fd < 0)
return -errno;
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting OS release data is only supported on container machines.");
STRV_FOREACH_PAIR(k, v, l) {
assert(m);
m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-open-pty" : "org.freedesktop.machine1.open-pty",
NULL,
error);
if (master < 0)
return master;
assert(m);
switch (m->class) {
case MACHINE_HOST:
case MACHINE_CONTAINER: {
char *address;
if (asprintf(&address, "x-machine-kernel:pid=%1$" PID_PRI ";x-machine-unix:pid=%1$" PID_PRI, m->leader) < 0)
return -ENOMEM;
if (r == -ENOENT)
return -EOPNOTSUPP;
const char *p, *getty;
assert(m);
m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-login" : "org.freedesktop.machine1.login",
NULL,
error);
if (master < 0)
return master;
r = sd_bus_call_method(
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
assert(m);
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified path '%s' is not absolute", path);
if (!args)
return -ENOMEM;
m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-shell" : "org.freedesktop.machine1.shell",
NULL,
error);
if (master < 0)
return master;
assert(p);
if (slave < 0)
return slave;
&tm,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
assert(m);
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Bind mounting is only supported on container machines.");
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute and not contain ../.");
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and not contain ../.");
NULL,
error);
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Container does not allow propagation of mount points.");
mount_slave_created = true;
goto finish;
mount_slave_mounted = true;
goto finish;
r = sd_bus_error_set_errnof(error, errno, "Failed to create temporary mount point %s: %m", mount_tmp);
goto finish;
mount_tmp_created = true;
goto finish;
mount_tmp_mounted = true;
if (read_only)
goto finish;
r = sd_bus_error_set_errnof(error, errno, "Cannot create propagation directory %s: %m", mount_outside);
goto finish;
mount_outside_created = true;
goto finish;
mount_outside_mounted = true;
mount_tmp_mounted = false;
mount_tmp_created = false;
mount_slave_mounted = false;
mount_slave_created = false;
goto finish;
if (child < 0) {
goto finish;
if (child == 0) {
const char *mount_inside;
int mntfd;
if (mntfd < 0) {
goto child_fail;
goto child_fail;
if (make_directory)
goto child_fail;
goto finish;
goto finish;
goto finish;
if (mount_tmp_mounted)
if (mount_tmp_created)
if (mount_slave_mounted)
if (mount_slave_created)
assert(o);
o->pid = 0;
goto fail;
goto fail;
fail:
const char *src, *dest, *host_path, *container_path, *host_basename, *host_dirname, *container_basename, *container_dirname;
MachineOperation *o;
bool copy_from;
assert(m);
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Copying files is only supported on container machines.");
NULL,
error);
if (copy_from) {
if (hostfd < 0)
if (child < 0)
if (child == 0) {
int containerfd;
int mntfd;
if (mntfd < 0) {
goto child_fail;
goto child_fail;
if (containerfd < 0) {
goto child_fail;
if (copy_from)
goto child_fail;
return log_oom();
r = sd_event_add_child(m->manager->event, &o->event_source, child, WEXITED, machine_operation_done, o);
return log_oom();
m->n_operations++;
o->machine = m;
BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Machine, timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Machine, unit), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Machine, class), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(Machine, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_METHOD("GetAddresses", NULL, "a(iay)", bus_machine_method_get_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetOSRelease", NULL, "a{ss}", bus_machine_method_get_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("OpenShell", "ssasas", "hs", bus_machine_method_open_shell, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("BindMount", "ssbb", NULL, bus_machine_method_bind_mount, SD_BUS_VTABLE_UNPRIVILEGED),
int machine_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
assert(m);
if (!message)
e = bus_label_unescape(p);
return -ENOMEM;
if (!machine)
assert(m);
return NULL;
int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
Iterator i;
return -ENOMEM;
r = strv_consume(&l, p);
*nodes = l;
l = NULL;
assert(m);
p = machine_bus_path(m);
return -ENOMEM;
return sd_bus_emit_signal(
"/org/freedesktop/machine1",
assert(m);
if (!m->create_message)
c = m->create_message;
if (error)
machine_save(m);
p = machine_bus_path(m);
return -ENOMEM;