diff options
Diffstat (limited to 'src/machine')
-rw-r--r-- | src/machine/machine-dbus.c | 96 | ||||
-rw-r--r-- | src/machine/machine.h | 1 | ||||
-rw-r--r-- | src/machine/machinectl.c | 44 | ||||
-rw-r--r-- | src/machine/machined-dbus.c | 22 | ||||
-rw-r--r-- | src/machine/org.freedesktop.machine1.conf | 4 |
5 files changed, 165 insertions, 2 deletions
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c index c9c3de0d04..14dae0a033 100644 --- a/src/machine/machine-dbus.c +++ b/src/machine/machine-dbus.c @@ -28,9 +28,11 @@ #include "bus-util.h" #include "bus-label.h" #include "strv.h" -#include "machine.h" #include "rtnl-util.h" #include "bus-errors.h" +#include "copy.h" +#include "fileio.h" +#include "machine.h" static int property_get_id( sd_bus *bus, @@ -333,6 +335,95 @@ int bus_machine_method_get_addresses(sd_bus *bus, sd_bus_message *message, void return sd_bus_send(bus, reply, NULL); } +int bus_machine_method_get_os_release(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_close_ int mntns_fd = -1, root_fd = -1; + _cleanup_close_pair_ int pair[2] = { -1, -1 }; + _cleanup_strv_free_ char **l = NULL; + _cleanup_fclose_ FILE *f = NULL; + Machine *m = userdata; + char **k, **v; + siginfo_t si; + pid_t child; + int r; + + assert(bus); + assert(message); + assert(m); + + r = namespace_open(m->leader, NULL, &mntns_fd, NULL, &root_fd); + if (r < 0) + return sd_bus_error_set_errno(error, r); + + if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0) + return sd_bus_error_set_errno(error, -errno); + + child = fork(); + if (child < 0) + return sd_bus_error_set_errno(error, -errno); + + if (child == 0) { + _cleanup_close_ int fd = -1; + + pair[0] = safe_close(pair[0]); + + r = namespace_enter(-1, mntns_fd, -1, root_fd); + if (r < 0) + _exit(EXIT_FAILURE); + + fd = open("/etc/os-release", O_RDONLY|O_CLOEXEC); + if (fd < 0) { + fd = open("/usr/lib/os-release", O_RDONLY|O_CLOEXEC); + if (fd < 0) + _exit(EXIT_FAILURE); + } + + r = copy_bytes(fd, pair[1], (off_t) -1); + if (r < 0) + _exit(EXIT_FAILURE); + + _exit(EXIT_SUCCESS); + } + + pair[1] = safe_close(pair[1]); + + f = fdopen(pair[0], "re"); + if (!f) + return sd_bus_error_set_errno(error, -errno); + + pair[0] = -1; + + r = load_env_file_pairs(f, "/etc/os-release", NULL, &l); + if (r < 0) + return sd_bus_error_set_errno(error, r); + + r = wait_for_terminate(child, &si); + if (r < 0) + return sd_bus_error_set_errno(error, r); + if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS) + return sd_bus_error_set_errno(error, EIO); + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return sd_bus_error_set_errno(error, r); + + r = sd_bus_message_open_container(reply, 'a', "{ss}"); + if (r < 0) + return sd_bus_error_set_errno(error, r); + + STRV_FOREACH_PAIR(k, v, l) { + r = sd_bus_message_append(reply, "{ss}", *k, *v); + if (r < 0) + return sd_bus_error_set_errno(error, r); + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return sd_bus_error_set_errno(error, r); + + return sd_bus_send(bus, reply, NULL); +} + 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), @@ -348,7 +439,8 @@ const sd_bus_vtable machine_vtable[] = { 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(yay)", bus_machine_method_get_addresses, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_VTABLE_END + SD_BUS_METHOD("GetOSRelease", NULL, "a{ss}", bus_machine_method_get_os_release, SD_BUS_VTABLE_UNPRIVILEGED), + 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) { diff --git a/src/machine/machine.h b/src/machine/machine.h index ed1c81c4f4..fa9262d52c 100644 --- a/src/machine/machine.h +++ b/src/machine/machine.h @@ -100,6 +100,7 @@ int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata, char int bus_machine_method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_machine_method_kill(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_machine_method_get_addresses(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_machine_method_get_os_release(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error); int machine_send_signal(Machine *m, bool new_machine); int machine_send_create_reply(Machine *m, sd_bus_error *error); diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index c2bf7e5197..022a4ebe50 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -224,6 +224,48 @@ static int print_addresses(sd_bus *bus, const char *name, const char *prefix, co return 0; } +static int print_os_release(sd_bus *bus, const char *name, const char *prefix) { + _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + const char *k, *v, *pretty = NULL; + int r; + + assert(bus); + assert(name); + assert(prefix); + + r = sd_bus_call_method(bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "GetMachineOSRelease", + NULL, + &reply, + "s", name); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(reply, 'a', "{ss}"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(reply, "{ss}", &k, &v)) > 0) { + if (streq(k, "PRETTY_NAME")) + pretty = v; + + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + if (pretty) + printf("%s%s\n", prefix, pretty); + + return 0; +} + typedef struct MachineStatusInfo { char *name; sd_id128_t id; @@ -284,6 +326,8 @@ static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) { "\t Address: ", "\t "); + print_os_release(bus, i->name, "\t OS: "); + if (i->unit) { printf("\t Unit: %s\n", i->unit); show_unit_cgroup(bus, i->unit, i->leader); diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c index 7c1802ce2a..ffcd7c026a 100644 --- a/src/machine/machined-dbus.c +++ b/src/machine/machined-dbus.c @@ -371,6 +371,27 @@ static int method_get_machine_addresses(sd_bus *bus, sd_bus_message *message, vo return bus_machine_method_get_addresses(bus, message, machine, error); } +static int method_get_machine_os_release(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + Machine *machine; + const char *name; + int r; + + assert(bus); + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return sd_bus_error_set_errno(error, r); + + machine = hashmap_get(m->machines, name); + if (!machine) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name); + + return bus_machine_method_get_os_release(bus, message, machine, error); +} + const sd_bus_vtable manager_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, SD_BUS_VTABLE_UNPRIVILEGED), @@ -381,6 +402,7 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)), SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)), SD_BUS_METHOD("GetMachineAddresses", "s", "a(yay)", method_get_machine_addresses, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_SIGNAL("MachineNew", "so", 0), SD_BUS_SIGNAL("MachineRemoved", "so", 0), SD_BUS_VTABLE_END diff --git a/src/machine/org.freedesktop.machine1.conf b/src/machine/org.freedesktop.machine1.conf index ab349a536d..3a77c70bf1 100644 --- a/src/machine/org.freedesktop.machine1.conf +++ b/src/machine/org.freedesktop.machine1.conf @@ -56,6 +56,10 @@ send_interface="org.freedesktop.machine1.Machine" send_member="GetAddresses"/> + <allow send_destination="org.freedesktop.machine1" + send_interface="org.freedesktop.machine1.Machine" + send_member="GetMachineOSRelease"/> + <allow receive_sender="org.freedesktop.machine1"/> </policy> |