mirror of
https://github.com/systemd/systemd.git
synced 2025-01-25 10:04:04 +03:00
machine: generalise logic GetOSRelease to later use it in varlink interface
This commit is contained in:
parent
f1daf9fb74
commit
31f9f589a8
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user