machine-dbus.c revision 0370612e0522191f929e3feb7d4937fff3d421e2
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering/***
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering This file is part of systemd.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Copyright 2011 Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering systemd is free software; you can redistribute it and/or modify it
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering under the terms of the GNU Lesser General Public License as published by
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering (at your option) any later version.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering systemd is distributed in the hope that it will be useful, but
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Lesser General Public License for more details.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering You should have received a copy of the GNU Lesser General Public License
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
4871690d9e32608bbd9b18505b5326c2079c9690Allin Cottrell***/
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <errno.h>
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering#include <string.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <arpa/inet.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <sys/mount.h>
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering/* When we include libgen.h because we need dirname() we immediately
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering * undefine basename() since libgen.h defines it as a macro to the XDG
afc5dbf37fd2399d37976388d9dd9ab470ecf446Lennart Poettering * version which is really broken. */
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering#include <libgen.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#undef basename
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "bus-util.h"
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen#include "bus-label.h"
0b452006de98294d1690f045f6ea2f7f6630ec3bRonny Chevalier#include "strv.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "bus-common-errors.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "copy.h"
15a5e95075a7f6007dd97b2a165c8ed16fe683dfLennart Poettering#include "fileio.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "in-addr-util.h"
7ccbd1ae843d77275f2c542582a9a80e5e058a70Lennart Poettering#include "local-addresses.h"
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering#include "path-util.h"
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering#include "mkdir.h"
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering#include "bus-internal.h"
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering#include "machine.h"
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering#include "machine-dbus.h"
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek
46b131574fdd7d77c15a0919ca9010cad7aa6ac7Lennart Poetteringstatic int property_get_id(
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek sd_bus *bus,
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek const char *path,
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek const char *interface,
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek const char *property,
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek sd_bus_message *reply,
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek void *userdata,
46b131574fdd7d77c15a0919ca9010cad7aa6ac7Lennart Poettering sd_bus_error *error) {
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek
f8294e4175918117ca6c131720bcf287eadcd029Josh Triplett Machine *m = userdata;
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek int r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(bus);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(reply);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(m);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_message_append_array(reply, 'y', &m->id, 16);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 1;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int property_get_state(
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering sd_bus *bus,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering const char *path,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering const char *interface,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering const char *property,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering sd_bus_message *reply,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering void *userdata,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering sd_bus_error *error) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Machine *m = userdata;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering const char *state;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering int r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(bus);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(reply);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(m);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering state = machine_state_to_string(machine_get_state(m));
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_message_append_basic(reply, 's', state);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering if (r < 0)
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering return r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering return 1;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
ccf23ad5faf228d450d263d7291156a948b61af2Christian Seiler
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int property_get_netif(
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering sd_bus *bus,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering const char *path,
ccf23ad5faf228d450d263d7291156a948b61af2Christian Seiler const char *interface,
ccf23ad5faf228d450d263d7291156a948b61af2Christian Seiler const char *property,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering sd_bus_message *reply,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering void *userdata,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering sd_bus_error *error) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Machine *m = userdata;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering int r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(bus);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering assert(reply);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering assert(m);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering assert_cc(sizeof(int) == sizeof(int32_t));
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_message_append_array(reply, 'i', m->netif, m->n_netif * sizeof(int));
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt return r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 1;
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, machine_class, MachineClass);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringint bus_machine_method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Machine *m = userdata;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering int r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(bus);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(message);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(m);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = machine_stop(m);
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return r;
3b97fcbd28f92a1e51887fef5de8844a89bde523Lennart Poettering
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek return sd_bus_reply_method_return(message, NULL);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringint bus_machine_method_kill(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Machine *m = userdata;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering const char *swho;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering int32_t signo;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering KillWho who;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering int r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(bus);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(message);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(m);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_message_read(message, "si", &swho, &signo);
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (isempty(swho))
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering who = KILL_ALL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering else {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering who = kill_who_from_string(swho);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (who < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (signo <= 0 || signo >= _NSIG)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = machine_kill(m, who, signo);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return sd_bus_reply_method_return(message, NULL);
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringint bus_machine_method_get_addresses(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_close_pair_ int pair[2] = { -1, -1 };
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_free_ char *us = NULL, *them = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_close_ int netns_fd = -1;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Machine *m = userdata;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering const char *p;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering siginfo_t si;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering pid_t child;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering int r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(bus);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(message);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(m);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (m->class != MACHINE_CONTAINER)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting IP address data is only supported on container machines.");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = readlink_malloc("/proc/self/ns/net", &us);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering p = procfs_file_alloca(m->leader, "ns/net");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = readlink_malloc(p, &them);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
e88baee88fad8bc59d33b55a7a2d640ef9e16cd6Zbigniew Jędrzejewski-Szmek return r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (streq(us, them))
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_PRIVATE_NETWORKING, "Machine %s does not use private networking", m->name);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = namespace_open(m->leader, NULL, NULL, &netns_fd, NULL);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return -errno;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering child = fork();
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (child < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
e88baee88fad8bc59d33b55a7a2d640ef9e16cd6Zbigniew Jędrzejewski-Szmek if (child == 0) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_free_ struct local_address *addresses = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering struct local_address *a;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering int i, n;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering pair[0] = safe_close(pair[0]);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = namespace_enter(-1, -1, netns_fd, -1);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _exit(EXIT_FAILURE);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering n = local_addresses(NULL, 0, AF_UNSPEC, &addresses);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (n < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _exit(EXIT_FAILURE);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering for (a = addresses, i = 0; i < n; a++, i++) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering struct iovec iov[2] = {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering { .iov_base = &a->family, .iov_len = sizeof(a->family) },
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering { .iov_base = &a->address, .iov_len = FAMILY_ADDRESS_SIZE(a->family) },
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering };
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = writev(pair[1], iov, 2);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _exit(EXIT_FAILURE);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering pair[1] = safe_close(pair[1]);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _exit(EXIT_SUCCESS);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
ec5ff4445cca6a1d786b8da36cf6fe0acc0b94c8Filipe Brandenburger
ec5ff4445cca6a1d786b8da36cf6fe0acc0b94c8Filipe Brandenburger pair[1] = safe_close(pair[1]);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
e88baee88fad8bc59d33b55a7a2d640ef9e16cd6Zbigniew Jędrzejewski-Szmek r = sd_bus_message_new_method_return(message, &reply);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return r;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = sd_bus_message_open_container(reply, 'a', "(iay)");
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (r < 0)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return r;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering for (;;) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering int family;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering ssize_t n;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering union in_addr_union in_addr;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering struct iovec iov[2];
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering struct msghdr mh = {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering .msg_iov = iov,
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering .msg_iovlen = 2,
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering };
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering iov[0] = (struct iovec) { .iov_base = &family, .iov_len = sizeof(family) };
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering iov[1] = (struct iovec) { .iov_base = &in_addr, .iov_len = sizeof(in_addr) };
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering n = recvmsg(pair[0], &mh, 0);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (n < 0)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return -errno;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if ((size_t) n < sizeof(family))
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering break;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = sd_bus_message_open_container(reply, 'r', "iay");
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (r < 0)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return r;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = sd_bus_message_append(reply, "i", family);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (r < 0)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return r;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering switch (family) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering case AF_INET:
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (n != sizeof(struct in_addr) + sizeof(family))
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return -EIO;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = sd_bus_message_append_array(reply, 'y', &in_addr.in, sizeof(in_addr.in));
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering break;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering case AF_INET6:
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (n != sizeof(struct in6_addr) + sizeof(family))
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return -EIO;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = sd_bus_message_append_array(reply, 'y', &in_addr.in6, sizeof(in_addr.in6));
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering break;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering }
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (r < 0)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return r;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = sd_bus_message_close_container(reply);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (r < 0)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return r;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering }
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = wait_for_terminate(child, &si);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (r < 0)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return sd_bus_error_set_errnof(error, r, "Failed to wait for client: %m");
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Client died abnormally.");
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = sd_bus_message_close_container(reply);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (r < 0)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return r;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return sd_bus_send(bus, reply, NULL);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering}
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poetteringint bus_machine_method_get_os_release(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_close_ int mntns_fd = -1, root_fd = -1;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_close_pair_ int pair[2] = { -1, -1 };
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering _cleanup_strv_free_ char **l = NULL;
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering _cleanup_fclose_ FILE *f = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Machine *m = userdata;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering char **k, **v;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering siginfo_t si;
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering pid_t child;
13f5402c6b734ed4c2b3e8b7c3d3bf6d815e7661Aleksander Adamowski int r;
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(bus);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(message);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(m);
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (m->class != MACHINE_CONTAINER)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting OS release data is only supported on container machines.");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = namespace_open(m->leader, NULL, &mntns_fd, NULL, &root_fd);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return r;
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return -errno;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering child = fork();
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (child < 0)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (child == 0) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_close_ int fd = -1;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering pair[0] = safe_close(pair[0]);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = namespace_enter(-1, mntns_fd, -1, root_fd);
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen if (r < 0)
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen _exit(EXIT_FAILURE);
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fd = open("/etc/os-release", O_RDONLY|O_CLOEXEC);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (fd < 0) {
d054f0a4d451120c26494263fc4dc175bfd405b1Daniel Mack fd = open("/usr/lib/os-release", O_RDONLY|O_CLOEXEC);
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering if (fd < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _exit(EXIT_FAILURE);
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering }
d054f0a4d451120c26494263fc4dc175bfd405b1Daniel Mack
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering r = copy_bytes(fd, pair[1], (off_t) -1, false);
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _exit(EXIT_FAILURE);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering _exit(EXIT_SUCCESS);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering pair[1] = safe_close(pair[1]);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering f = fdopen(pair[0], "re");
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering if (!f)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return -errno;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering pair[0] = -1;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering r = load_env_file_pairs(f, "/etc/os-release", NULL, &l);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek r = wait_for_terminate(child, &si);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return sd_bus_error_set_errnof(error, r, "Failed to wait for client: %m");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Client died abnormally.");
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_message_new_method_return(message, &reply);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
46b131574fdd7d77c15a0919ca9010cad7aa6ac7Lennart Poettering r = sd_bus_message_open_container(reply, 'a', "{ss}");
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek if (r < 0)
03ee5c38cb0da193dd08733fb4c0c2809cee6a99Lennart Poettering return r;
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering STRV_FOREACH_PAIR(k, v, l) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_message_append(reply, "{ss}", *k, *v);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt if (r < 0)
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt return r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_message_close_container(reply);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt return r;
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return sd_bus_send(bus, reply, NULL);
4a61c3e51e96a747c30598d78ee3a24e7c569e9fZbigniew Jędrzejewski-Szmek}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringint bus_machine_method_open_pty(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_free_ char *pty_name = NULL;
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt _cleanup_close_ int master = -1;
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt Machine *m = userdata;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering int r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
6355e75610a8d47fc3ba5ab8bd442172a2cfe574Lennart Poettering assert(bus);
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering assert(message);
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering assert(m);
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering if (m->class != MACHINE_CONTAINER)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Opening pseudo TTYs is only supported on container machines.");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering master = openpt_in_namespace(m->leader, O_RDWR|O_NOCTTY|O_CLOEXEC);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt if (master < 0)
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt return master;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
8531ae707d4d0203e83304d4af948b8169a5fce1Lennart Poettering r = ptsname_malloc(master, &pty_name);
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt if (r < 0)
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt return r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
48cef29504b1ffc0df9929f2d8b2af2ad74d2b4aVito Caputo r = sd_bus_message_new_method_return(message, &reply);
48cef29504b1ffc0df9929f2d8b2af2ad74d2b4aVito Caputo if (r < 0)
48cef29504b1ffc0df9929f2d8b2af2ad74d2b4aVito Caputo return r;
48cef29504b1ffc0df9929f2d8b2af2ad74d2b4aVito Caputo
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_message_append(reply, "hs", master, pty_name);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering return r;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering return sd_bus_send(bus, reply, NULL);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering}
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poetteringint bus_machine_method_open_login(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering _cleanup_free_ char *pty_name = NULL, *getty = NULL;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering _cleanup_bus_unref_ sd_bus *container_bus = NULL;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering _cleanup_close_ int master = -1;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering Machine *m = userdata;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering const char *p;
8a03c9ef744e13dc700a7e7ca6cae8afdcf0d71cZbigniew Jędrzejewski-Szmek int r;
8a03c9ef744e13dc700a7e7ca6cae8afdcf0d71cZbigniew Jędrzejewski-Szmek
8a03c9ef744e13dc700a7e7ca6cae8afdcf0d71cZbigniew Jędrzejewski-Szmek if (m->class != MACHINE_CONTAINER)
8a03c9ef744e13dc700a7e7ca6cae8afdcf0d71cZbigniew Jędrzejewski-Szmek return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Opening logins is only supported on container machines.");
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering r = bus_verify_polkit_async(
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering message,
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering CAP_SYS_ADMIN,
"org.freedesktop.machine1.login",
false,
&m->manager->polkit_registry,
error);
if (r < 0)
return r;
if (r == 0)
return 1; /* Will call us back */
master = openpt_in_namespace(m->leader, O_RDWR|O_NOCTTY|O_CLOEXEC);
if (master < 0)
return master;
r = ptsname_malloc(master, &pty_name);
if (r < 0)
return r;
p = path_startswith(pty_name, "/dev/pts/");
if (!p)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "PTS name %s is invalid", pty_name);
if (unlockpt(master) < 0)
return -errno;
r = sd_bus_new(&container_bus);
if (r < 0)
return r;
#ifdef ENABLE_KDBUS
asprintf(&container_bus->address, "x-machine-kernel:pid=" PID_FMT ";x-machine-unix:pid=" PID_FMT, m->leader, m->leader);
#else
asprintf(&container_bus->address, "x-machine-kernel:pid=" PID_FMT, m->leader);
#endif
if (!container_bus->address)
return log_oom();
container_bus->bus_client = true;
container_bus->trusted = false;
container_bus->is_system = true;
r = sd_bus_start(container_bus);
if (r < 0)
return r;
getty = strjoin("container-getty@", p, ".service", NULL);
if (!getty)
return log_oom();
r = sd_bus_call_method(
container_bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"StartUnit",
error, NULL,
"ss", getty, "replace");
if (r < 0)
return r;
container_bus = sd_bus_unref(container_bus);
r = sd_bus_message_new_method_return(message, &reply);
if (r < 0)
return r;
r = sd_bus_message_append(reply, "hs", master, pty_name);
if (r < 0)
return r;
return sd_bus_send(bus, reply, NULL);
}
int bus_machine_method_bind_mount(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 };
char mount_slave[] = "/tmp/propagate.XXXXXX", *mount_tmp, *mount_outside, *p;
bool mount_slave_created = false, mount_slave_mounted = false,
mount_tmp_created = false, mount_tmp_mounted = false,
mount_outside_created = false, mount_outside_mounted = false;
const char *dest, *src;
Machine *m = userdata;
int read_only, make_directory;
pid_t child;
siginfo_t si;
int r;
if (m->class != MACHINE_CONTAINER)
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Bind mounting is only supported on container machines.");
r = sd_bus_message_read(message, "ssbb", &src, &dest, &read_only, &make_directory);
if (r < 0)
return r;
if (!path_is_absolute(src) || !path_is_safe(src))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute and not contain ../.");
if (isempty(dest))
dest = src;
else if (!path_is_absolute(dest) || !path_is_safe(dest))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and not contain ../.");
/* One day, when bind mounting /proc/self/fd/n works across
* namespace boundaries we should rework this logic to make
* use of it... */
p = strjoina("/run/systemd/nspawn/propagate/", m->name, "/");
if (laccess(p, F_OK) < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Container does not allow propagation of mount points.");
/* Our goal is to install a new bind mount into the container,
possibly read-only. This is irritatingly complex
unfortunately, currently.
First, we start by creating a private playground in /tmp,
that we can mount MS_SLAVE. (Which is necessary, since
MS_MOUNT cannot be applied to mounts with MS_SHARED parent
mounts.) */
if (!mkdtemp(mount_slave))
return sd_bus_error_set_errnof(error, errno, "Failed to create playground %s: %m", mount_slave);
mount_slave_created = true;
if (mount(mount_slave, mount_slave, NULL, MS_BIND, NULL) < 0) {
r = sd_bus_error_set_errnof(error, errno, "Failed to make bind mount %s: %m", mount_slave);
goto finish;
}
mount_slave_mounted = true;
if (mount(NULL, mount_slave, NULL, MS_SLAVE, NULL) < 0) {
r = sd_bus_error_set_errnof(error, errno, "Failed to remount slave %s: %m", mount_slave);
goto finish;
}
/* Second, we mount the source directory to a directory inside
of our MS_SLAVE playground. */
mount_tmp = strjoina(mount_slave, "/mount");
if (mkdir(mount_tmp, 0700) < 0) {
r = sd_bus_error_set_errnof(error, errno, "Failed to create temporary mount point %s: %m", mount_tmp);
goto finish;
}
mount_tmp_created = true;
if (mount(src, mount_tmp, NULL, MS_BIND, NULL) < 0) {
r = sd_bus_error_set_errnof(error, errno, "Failed to overmount %s: %m", mount_tmp);
goto finish;
}
mount_tmp_mounted = true;
/* Third, we remount the new bind mount read-only if requested. */
if (read_only)
if (mount(NULL, mount_tmp, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) {
r = sd_bus_error_set_errnof(error, errno, "Failed to remount read-only %s: %m", mount_tmp);
goto finish;
}
/* Fourth, we move the new bind mount into the propagation
* directory. This way it will appear there read-only
* right-away. */
mount_outside = strjoina("/run/systemd/nspawn/propagate/", m->name, "/XXXXXX");
if (!mkdtemp(mount_outside)) {
r = sd_bus_error_set_errnof(error, errno, "Cannot create propagation directory %s: %m", mount_outside);
goto finish;
}
mount_outside_created = true;
if (mount(mount_tmp, mount_outside, NULL, MS_MOVE, NULL) < 0) {
r = sd_bus_error_set_errnof(error, errno, "Failed to move %s to %s: %m", mount_tmp, mount_outside);
goto finish;
}
mount_outside_mounted = true;
mount_tmp_mounted = false;
(void) rmdir(mount_tmp);
mount_tmp_created = false;
(void) umount(mount_slave);
mount_slave_mounted = false;
(void) rmdir(mount_slave);
mount_slave_created = false;
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0) {
r = sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
goto finish;
}
child = fork();
if (child < 0) {
r = sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
goto finish;
}
if (child == 0) {
const char *mount_inside;
int mntfd;
const char *q;
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
q = procfs_file_alloca(m->leader, "ns/mnt");
mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
if (mntfd < 0) {
r = log_error_errno(errno, "Failed to open mount namespace of leader: %m");
goto child_fail;
}
if (setns(mntfd, CLONE_NEWNS) < 0) {
r = log_error_errno(errno, "Failed to join namespace of leader: %m");
goto child_fail;
}
if (make_directory)
(void) mkdir_p(dest, 0755);
/* Fifth, move the mount to the right place inside */
mount_inside = strjoina("/run/systemd/nspawn/incoming/", basename(mount_outside));
if (mount(mount_inside, dest, NULL, MS_MOVE, NULL) < 0) {
r = log_error_errno(errno, "Failed to mount: %m");
goto child_fail;
}
_exit(EXIT_SUCCESS);
child_fail:
(void) write(errno_pipe_fd[1], &r, sizeof(r));
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
_exit(EXIT_FAILURE);
}
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
r = wait_for_terminate(child, &si);
if (r < 0) {
r = sd_bus_error_set_errnof(error, r, "Failed to wait for client: %m");
goto finish;
}
if (si.si_code != CLD_EXITED) {
r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Client died abnormally.");
goto finish;
}
if (si.si_status != EXIT_SUCCESS) {
if (read(errno_pipe_fd[0], &r, sizeof(r)) == sizeof(r))
r = sd_bus_error_set_errnof(error, r, "Failed to mount: %m");
else
r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Client failed.");
goto finish;
}
r = sd_bus_reply_method_return(message, NULL);
finish:
if (mount_outside_mounted)
umount(mount_outside);
if (mount_outside_created)
rmdir(mount_outside);
if (mount_tmp_mounted)
umount(mount_tmp);
if (mount_tmp_created)
rmdir(mount_tmp);
if (mount_slave_mounted)
umount(mount_slave);
if (mount_slave_created)
rmdir(mount_slave);
return r;
}
static int machine_operation_done(sd_event_source *s, const siginfo_t *si, void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
MachineOperation *o = userdata;
int r;
assert(o);
assert(si);
o->pid = 0;
if (si->si_code != CLD_EXITED) {
r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Client died abnormally.");
goto fail;
}
if (si->si_status != EXIT_SUCCESS) {
if (read(o->errno_fd, &r, sizeof(r)) == sizeof(r))
r = sd_bus_error_set_errnof(&error, r, "%m");
else
r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Client failed.");
goto fail;
}
r = sd_bus_reply_method_return(o->message, NULL);
if (r < 0)
log_error_errno(r, "Failed to reply to message: %m");
machine_operation_unref(o);
return 0;
fail:
r = sd_bus_reply_method_error(o->message, &error);
if (r < 0)
log_error_errno(r, "Failed to reply to message: %m");
machine_operation_unref(o);
return 0;
}
int bus_machine_method_copy(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *src, *dest, *host_path, *container_path, *host_basename, *host_dirname, *container_basename, *container_dirname;
_cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 };
_cleanup_close_ int hostfd = -1;
Machine *m = userdata;
MachineOperation *o;
bool copy_from;
pid_t child;
char *t;
int r;
if (m->n_operations >= MACHINE_OPERATIONS_MAX)
return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing copies.");
if (m->class != MACHINE_CONTAINER)
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Copying files is only supported on container machines.");
r = sd_bus_message_read(message, "ss", &src, &dest);
if (r < 0)
return r;
if (!path_is_absolute(src) || !path_is_safe(src))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute and not contain ../.");
if (isempty(dest))
dest = src;
else if (!path_is_absolute(dest) || !path_is_safe(dest))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and not contain ../.");
copy_from = strstr(sd_bus_message_get_member(message), "CopyFrom");
if (copy_from) {
container_path = src;
host_path = dest;
} else {
host_path = src;
container_path = dest;
}
host_basename = basename(host_path);
t = strdupa(host_path);
host_dirname = dirname(t);
container_basename = basename(container_path);
t = strdupa(container_path);
container_dirname = dirname(t);
hostfd = open(host_dirname, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_DIRECTORY);
if (r < 0)
return sd_bus_error_set_errnof(error, errno, "Failed to open host directory %s: %m", host_dirname);
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
child = fork();
if (child < 0)
return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
if (child == 0) {
int containerfd;
const char *q;
int mntfd;
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
q = procfs_file_alloca(m->leader, "ns/mnt");
mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
if (mntfd < 0) {
r = log_error_errno(errno, "Failed to open mount namespace of leader: %m");
goto child_fail;
}
if (setns(mntfd, CLONE_NEWNS) < 0) {
r = log_error_errno(errno, "Failed to join namespace of leader: %m");
goto child_fail;
}
containerfd = open(container_dirname, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_DIRECTORY);
if (containerfd < 0) {
r = log_error_errno(errno, "Failed top open destination directory: %m");
goto child_fail;
}
if (copy_from)
r = copy_tree_at(containerfd, container_basename, hostfd, host_basename, true);
else
r = copy_tree_at(hostfd, host_basename, containerfd, container_basename, true);
hostfd = safe_close(hostfd);
containerfd = safe_close(containerfd);
if (r < 0) {
r = log_error_errno(r, "Failed to copy tree: %m");
goto child_fail;
}
_exit(EXIT_SUCCESS);
child_fail:
(void) write(errno_pipe_fd[1], &r, sizeof(r));
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
_exit(EXIT_FAILURE);
}
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
/* Copying might take a while, hence install a watch the
* child, and return */
o = new0(MachineOperation, 1);
if (!o)
return log_oom();
o->pid = child;
o->message = sd_bus_message_ref(message);
o->errno_fd = errno_pipe_fd[0];
errno_pipe_fd[0] = -1;
r = sd_event_add_child(m->manager->event, &o->event_source, child, WEXITED, machine_operation_done, o);
if (r < 0) {
machine_operation_unref(o);
return log_oom();
}
LIST_PREPEND(operations, m->operations, o);
m->n_operations++;
o->machine = m;
return 1;
}
const sd_bus_vtable machine_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Machine, name), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Id", "ay", property_get_id, 0, SD_BUS_VTABLE_PROPERTY_CONST),
BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Machine, timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Machine, service), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Unit", "s", NULL, offsetof(Machine, unit), 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("Leader", "u", NULL, offsetof(Machine, leader), SD_BUS_VTABLE_PROPERTY_CONST),
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_PROPERTY("NetworkInterfaces", "ai", property_get_netif, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
SD_BUS_METHOD("Terminate", NULL, NULL, bus_machine_method_terminate, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
SD_BUS_METHOD("Kill", "si", NULL, bus_machine_method_kill, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
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("OpenPTY", NULL, "hs", bus_machine_method_open_pty, 0),
SD_BUS_METHOD("OpenLogin", NULL, "hs", bus_machine_method_open_login, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("BindMount", "ssbb", NULL, bus_machine_method_bind_mount, 0),
SD_BUS_METHOD("CopyFrom", "ss", NULL, bus_machine_method_copy, 0),
SD_BUS_METHOD("CopyTo", "ss", NULL, bus_machine_method_copy, 0),
SD_BUS_VTABLE_END
};
int machine_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
Manager *m = userdata;
Machine *machine;
int r;
assert(bus);
assert(path);
assert(interface);
assert(found);
assert(m);
if (streq(path, "/org/freedesktop/machine1/machine/self")) {
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
sd_bus_message *message;
pid_t pid;
message = sd_bus_get_current_message(bus);
if (!message)
return 0;
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
if (r < 0)
return r;
r = sd_bus_creds_get_pid(creds, &pid);
if (r < 0)
return r;
r = manager_get_machine_by_pid(m, pid, &machine);
if (r <= 0)
return 0;
} else {
_cleanup_free_ char *e = NULL;
const char *p;
p = startswith(path, "/org/freedesktop/machine1/machine/");
if (!p)
return 0;
e = bus_label_unescape(p);
if (!e)
return -ENOMEM;
machine = hashmap_get(m->machines, e);
if (!machine)
return 0;
}
*found = machine;
return 1;
}
char *machine_bus_path(Machine *m) {
_cleanup_free_ char *e = NULL;
assert(m);
e = bus_label_escape(m->name);
if (!e)
return NULL;
return strappend("/org/freedesktop/machine1/machine/", e);
}
int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
_cleanup_strv_free_ char **l = NULL;
Machine *machine = NULL;
Manager *m = userdata;
Iterator i;
int r;
assert(bus);
assert(path);
assert(nodes);
HASHMAP_FOREACH(machine, m->machines, i) {
char *p;
p = machine_bus_path(machine);
if (!p)
return -ENOMEM;
r = strv_consume(&l, p);
if (r < 0)
return r;
}
*nodes = l;
l = NULL;
return 1;
}
int machine_send_signal(Machine *m, bool new_machine) {
_cleanup_free_ char *p = NULL;
assert(m);
p = machine_bus_path(m);
if (!p)
return -ENOMEM;
return sd_bus_emit_signal(
m->manager->bus,
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
new_machine ? "MachineNew" : "MachineRemoved",
"so", m->name, p);
}
int machine_send_create_reply(Machine *m, sd_bus_error *error) {
_cleanup_bus_message_unref_ sd_bus_message *c = NULL;
_cleanup_free_ char *p = NULL;
assert(m);
if (!m->create_message)
return 0;
c = m->create_message;
m->create_message = NULL;
if (error)
return sd_bus_reply_method_error(c, error);
/* Update the machine state file before we notify the client
* about the result. */
machine_save(m);
p = machine_bus_path(m);
if (!p)
return -ENOMEM;
return sd_bus_reply_method_return(c, "o", p);
}