]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
machine: generalise logic GetOSRelease to later use it in varlink interface 34546/head
authorIvan Kruglov <mail@ikruglov.com>
Wed, 25 Sep 2024 12:17:38 +0000 (14:17 +0200)
committerIvan Kruglov <mail@ikruglov.com>
Tue, 1 Oct 2024 17:00:25 +0000 (19:00 +0200)
src/machine/machine-dbus.c
src/machine/machined-core.c
src/machine/machined.h

index a8c376dee9713f94df2bb76c8334bfecfcead386..85cb00a8a6889596a6d54d31c9590841d5607632 100644 (file)
@@ -236,8 +236,6 @@ int bus_machine_method_get_ssh_info(sd_bus_message *message, void *userdata, sd_
         return sd_bus_send(NULL, reply, NULL);
 }
 
-#define EXIT_NOT_FOUND 2
-
 int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_strv_free_ char **l = NULL;
         Machine *m = ASSERT_PTR(userdata);
@@ -245,80 +243,13 @@ int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, s
 
         assert(message);
 
-        switch (m->class) {
-
-        case MACHINE_HOST:
-                r = load_os_release_pairs(NULL, &l);
-                if (r < 0)
-                        return r;
-
-                break;
-
-        case MACHINE_CONTAINER: {
-                _cleanup_close_ int mntns_fd = -EBADF, root_fd = -EBADF, pidns_fd = -EBADF;
-                _cleanup_close_pair_ int pair[2] = EBADF_PAIR;
-                _cleanup_fclose_ FILE *f = NULL;
-                pid_t child;
-
-                r = pidref_namespace_open(&m->leader,
-                                          &pidns_fd,
-                                          &mntns_fd,
-                                          /* ret_netns_fd = */ NULL,
-                                          /* ret_userns_fd = */ NULL,
-                                          &root_fd);
-                if (r < 0)
-                        return r;
-
-                if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
-                        return -errno;
-
-                r = namespace_fork("(sd-osrelns)", "(sd-osrel)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
-                                   pidns_fd, mntns_fd, -1, -1, root_fd,
-                                   &child);
-                if (r < 0)
-                        return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
-                if (r == 0) {
-                        int fd = -EBADF;
-
-                        pair[0] = safe_close(pair[0]);
-
-                        r = open_os_release(NULL, NULL, &fd);
-                        if (r == -ENOENT)
-                                _exit(EXIT_NOT_FOUND);
-                        if (r < 0)
-                                _exit(EXIT_FAILURE);
-
-                        r = copy_bytes(fd, pair[1], UINT64_MAX, 0);
-                        if (r < 0)
-                                _exit(EXIT_FAILURE);
-
-                        _exit(EXIT_SUCCESS);
-                }
-
-                pair[1] = safe_close(pair[1]);
-
-                f = take_fdopen(&pair[0], "r");
-                if (!f)
-                        return -errno;
-
-                r = load_env_file_pairs(f, "/etc/os-release", &l);
-                if (r < 0)
-                        return r;
-
-                r = wait_for_terminate_and_check("(sd-osrelns)", child, 0);
-                if (r < 0)
-                        return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m");
-                if (r == EXIT_NOT_FOUND)
-                        return sd_bus_error_set(error, SD_BUS_ERROR_FAILED, "Machine does not contain OS release information");
-                if (r != EXIT_SUCCESS)
-                        return sd_bus_error_set(error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
-
-                break;
-        }
-
-        default:
+        r = machine_get_os_release(m, &l);
+        if (r == -ENONET)
+                return sd_bus_error_set(error, SD_BUS_ERROR_FAILED, "Machine does not contain OS release information.");
+        if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
                 return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting OS release data is only supported on container machines.");
-        }
+        if (r < 0)
+                return sd_bus_error_set_errnof(error, r, "Failed to get OS release: %m");
 
         return bus_reply_pair_array(message, l);
 }
index df6e4378350d234106772da0af984338a9f23bd3..0045f75b0ca7d1651e08c2c66e563d9509ee8829 100644 (file)
@@ -1,7 +1,10 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include "cgroup-util.h"
+#include "copy.h"
+#include "env-file.h"
 #include "fd-util.h"
+#include "fileio.h"
 #include "iovec-util.h"
 #include "machined.h"
 #include "process-util.h"
@@ -299,3 +302,104 @@ int machine_get_addresses(Machine* machine, struct local_address **ret_addresses
                 return -EOPNOTSUPP;
         }
 }
+
+#define EXIT_NOT_FOUND 2
+
+int machine_get_os_release(Machine *machine, char ***ret_os_release) {
+        _cleanup_strv_free_ char **l = NULL;
+        int r;
+
+        assert(machine);
+        assert(ret_os_release);
+
+        switch (machine->class) {
+
+        case MACHINE_HOST:
+                r = load_os_release_pairs(/* root = */ NULL, &l);
+                if (r < 0)
+                        return log_debug_errno(r, "Failed to load OS release information: %m");
+
+                break;
+
+        case MACHINE_CONTAINER: {
+                _cleanup_close_ int mntns_fd = -EBADF, root_fd = -EBADF, pidns_fd = -EBADF;
+                _cleanup_close_pair_ int pair[2] = EBADF_PAIR;
+                _cleanup_fclose_ FILE *f = NULL;
+                pid_t child;
+
+                r = pidref_namespace_open(&machine->leader,
+                                          &pidns_fd,
+                                          &mntns_fd,
+                                          /* ret_netns_fd = */ NULL,
+                                          /* ret_userns_fd = */ NULL,
+                                          &root_fd);
+                if (r < 0)
+                        return log_debug_errno(r, "Failed to open namespace: %m");
+
+                if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
+                        return log_debug_errno(errno, "Failed to call socketpair(): %m");
+
+                r = namespace_fork("(sd-osrelns)",
+                                   "(sd-osrel)",
+                                   /* except_fds = */ NULL,
+                                   /* n_except_fds = */ 0,
+                                   FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
+                                   pidns_fd,
+                                   mntns_fd,
+                                   /* netns_fd = */ -1,
+                                   /* userns_fd = */ -1,
+                                   root_fd,
+                                   &child);
+                if (r < 0)
+                        return log_debug_errno(r, "Failed to fork(): %m");
+                if (r == 0) {
+                        _cleanup_close_ int fd = -EBADF;
+
+                        pair[0] = safe_close(pair[0]);
+
+                        r = open_os_release(/* root = */ NULL, /* ret_path = */ NULL, &fd);
+                        if (r == -ENOENT)
+                                _exit(EXIT_NOT_FOUND);
+                        if (r < 0) {
+                                log_debug_errno(r, "Failed to read OS release: %m");
+                                _exit(EXIT_FAILURE);
+                        }
+
+                        r = copy_bytes(fd, pair[1], UINT64_MAX, /* copy_flags = */ 0);
+                        if (r < 0) {
+                                log_debug_errno(r, "Failed to write to fd: %m");
+                                _exit(EXIT_FAILURE);
+                        }
+
+                        _exit(EXIT_SUCCESS);
+                }
+
+                pair[1] = safe_close(pair[1]);
+
+                f = take_fdopen(&pair[0], "r");
+                if (!f)
+                        return log_debug_errno(errno, "Failed to fdopen(): %m");
+
+                r = load_env_file_pairs(f, "/etc/os-release", &l);
+                if (r < 0)
+                        return log_debug_errno(r, "Failed to load OS release information: %m");
+
+                r = wait_for_terminate_and_check("(sd-osrelns)", child, /* flags = */ 0);
+                if (r < 0)
+                        return log_debug_errno(r, "Failed to wait for child: %m");
+                if (r == EXIT_NOT_FOUND)
+                        return -ENOENT;
+                if (r != EXIT_SUCCESS)
+                        return log_debug_errno(SYNTHETIC_ERRNO(ESHUTDOWN), "Child died abnormally");
+
+                break;
+        }
+
+        default:
+                return -EOPNOTSUPP;
+        }
+
+
+        *ret_os_release = TAKE_PTR(l);
+        return 0;
+}
index f1d0d157c8815a6ad76d47b2aa1d49beb8d9df87..4a718f94627d7faf7dc17151a82879711f1e2c30 100644 (file)
@@ -66,3 +66,4 @@ void manager_gc(Manager *m, bool drop_not_started);
 void manager_enqueue_gc(Manager *m);
 
 int machine_get_addresses(Machine* machine, struct local_address **ret_addresses);
+int machine_get_os_release(Machine *machine, char ***ret_os_release);