mirror of
https://github.com/systemd/systemd
synced 2026-04-24 07:55:12 +02:00
Compare commits
25 Commits
3b6288f6be
...
996e6d0d89
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
996e6d0d89 | ||
|
|
0f44a6c64a | ||
|
|
10b2d19219 | ||
|
|
e8a5cda471 | ||
|
|
13b0e7fc6d | ||
|
|
8b4ee3d68d | ||
|
|
b3243f4bee | ||
|
|
b97b8fd4e3 | ||
|
|
a925cea9f2 | ||
|
|
22fc89f54d | ||
|
|
5c60d3011f | ||
|
|
ba8801a076 | ||
|
|
055a5a236c | ||
|
|
e99f741cdf | ||
|
|
d9c5566c0f | ||
|
|
1966baf2d6 | ||
|
|
f5fa86f9f8 | ||
|
|
e1b3319b6c | ||
|
|
b7f6bdbbd3 | ||
|
|
0011ecd6fa | ||
|
|
abf518a8dc | ||
|
|
3fc44a0f68 | ||
|
|
f4c3c107d9 | ||
|
|
5730a400fd | ||
|
|
953c347fb6 |
@ -347,7 +347,7 @@
|
|||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--chrome=</option></term>
|
<term><option>--chrome=</option></term>
|
||||||
|
|
||||||
<listitem><para>Takes a boolean argument. By default the initial setup scren will show reverse color
|
<listitem><para>Takes a boolean argument. By default the initial setup screen will show reverse color
|
||||||
"chrome" bars at the top and and the bottom of the terminal screen, which may be disabled by setting
|
"chrome" bars at the top and and the bottom of the terminal screen, which may be disabled by setting
|
||||||
this option to false.</para>
|
this option to false.</para>
|
||||||
|
|
||||||
|
|||||||
@ -1149,7 +1149,7 @@ NFTSet=cgroup:inet:filter:my_service user:inet:filter:serviceuser
|
|||||||
one more restricted, depending on the use case.</para>
|
one more restricted, depending on the use case.</para>
|
||||||
|
|
||||||
<para>Note that these settings might not be supported on some systems (for example if eBPF control group
|
<para>Note that these settings might not be supported on some systems (for example if eBPF control group
|
||||||
support is not enabled in the underlying kernel or container manager). These settings will fail the service in
|
support is not enabled in the underlying kernel or container manager). These settings will have no effect in
|
||||||
that case. If compatibility with such systems is desired it is hence recommended to attach your filter manually
|
that case. If compatibility with such systems is desired it is hence recommended to attach your filter manually
|
||||||
(requires <varname>Delegate=</varname><constant>yes</constant>) instead of using this setting.</para>
|
(requires <varname>Delegate=</varname><constant>yes</constant>) instead of using this setting.</para>
|
||||||
|
|
||||||
|
|||||||
@ -1122,6 +1122,7 @@ libmount = dependency('mount',
|
|||||||
version : fuzzer_build ? '>= 0' : '>= 2.30',
|
version : fuzzer_build ? '>= 0' : '>= 2.30',
|
||||||
disabler : true,
|
disabler : true,
|
||||||
required : get_option('libmount'))
|
required : get_option('libmount'))
|
||||||
|
libmount_cflags = libmount.partial_dependency(includes: true, compile_args: true)
|
||||||
|
|
||||||
libfdisk = dependency('fdisk',
|
libfdisk = dependency('fdisk',
|
||||||
version : '>= 2.32',
|
version : '>= 2.32',
|
||||||
|
|||||||
@ -2446,8 +2446,6 @@ static int analyze_security_one(sd_bus *bus,
|
|||||||
|
|
||||||
/* Refactoring SecurityInfo so that it can make use of existing struct variables instead of reading from dbus */
|
/* Refactoring SecurityInfo so that it can make use of existing struct variables instead of reading from dbus */
|
||||||
static int get_security_info(Unit *u, ExecContext *c, CGroupContext *g, SecurityInfo **ret_info) {
|
static int get_security_info(Unit *u, ExecContext *c, CGroupContext *g, SecurityInfo **ret_info) {
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(ret_info);
|
assert(ret_info);
|
||||||
|
|
||||||
_cleanup_(security_info_freep) SecurityInfo *info = security_info_new();
|
_cleanup_(security_info_freep) SecurityInfo *info = security_info_new();
|
||||||
@ -2577,8 +2575,7 @@ static int get_security_info(Unit *u, ExecContext *c, CGroupContext *g, Security
|
|||||||
info->_umask = c->umask;
|
info->_umask = c->umask;
|
||||||
|
|
||||||
#if HAVE_SECCOMP
|
#if HAVE_SECCOMP
|
||||||
r = dlopen_libseccomp();
|
if (dlopen_libseccomp() >= 0) {
|
||||||
if (r >= 0) {
|
|
||||||
SET_FOREACH(key, c->syscall_archs) {
|
SET_FOREACH(key, c->syscall_archs) {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
|
|||||||
@ -15,3 +15,20 @@ const char* runtime_scope_to_string(RuntimeScope scope) _const_;
|
|||||||
RuntimeScope runtime_scope_from_string(const char *s) _const_;
|
RuntimeScope runtime_scope_from_string(const char *s) _const_;
|
||||||
|
|
||||||
const char* runtime_scope_cmdline_option_to_string(RuntimeScope scope) _const_;
|
const char* runtime_scope_cmdline_option_to_string(RuntimeScope scope) _const_;
|
||||||
|
|
||||||
|
static inline mode_t runtime_scope_to_socket_mode(RuntimeScope scope) {
|
||||||
|
/* Returns the right socket mode to use for binding AF_UNIX sockets intended for the specified
|
||||||
|
* scope. If system mode is selected the whole system can connect to it, if user mode is selected
|
||||||
|
* only the user can connect to it. */
|
||||||
|
|
||||||
|
switch (scope) {
|
||||||
|
case RUNTIME_SCOPE_SYSTEM:
|
||||||
|
return 0666;
|
||||||
|
|
||||||
|
case RUNTIME_SCOPE_USER:
|
||||||
|
return 0600;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return MODE_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -547,9 +547,9 @@ int bpf_firewall_compile(Unit *u) {
|
|||||||
if (!cc)
|
if (!cc)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
crt = unit_setup_cgroup_runtime(u);
|
crt = unit_get_cgroup_runtime(u);
|
||||||
if (!crt)
|
if (!crt)
|
||||||
return -ENOMEM;
|
return -ESTALE;
|
||||||
|
|
||||||
if (bpf_program_supported() <= 0)
|
if (bpf_program_supported() <= 0)
|
||||||
return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP),
|
return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||||
|
|||||||
@ -2204,12 +2204,6 @@ int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const char *suffix_path) {
|
|||||||
if (set_isempty(pids))
|
if (set_isempty(pids))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Load any custom firewall BPF programs here once to test if they are existing and actually loadable.
|
|
||||||
* Fail here early since later errors in the call chain unit_realize_cgroup to cgroup_context_apply are ignored. */
|
|
||||||
r = bpf_firewall_load_custom(u);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
r = unit_realize_cgroup(u);
|
r = unit_realize_cgroup(u);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -4283,6 +4277,15 @@ int cgroup_runtime_serialize(Unit *u, FILE *f, FDSet *fds) {
|
|||||||
if (!crt)
|
if (!crt)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (crt->cgroup_path)
|
||||||
|
(void) serialize_item(f, "cgroup", crt->cgroup_path);
|
||||||
|
if (crt->cgroup_id != 0)
|
||||||
|
(void) serialize_item_format(f, "cgroup-id", "%" PRIu64, crt->cgroup_id);
|
||||||
|
|
||||||
|
(void) serialize_cgroup_mask(f, "cgroup-realized-mask", crt->cgroup_realized_mask);
|
||||||
|
(void) serialize_cgroup_mask(f, "cgroup-enabled-mask", crt->cgroup_enabled_mask);
|
||||||
|
(void) serialize_cgroup_mask(f, "cgroup-invalidated-mask", crt->cgroup_invalidated_mask);
|
||||||
|
|
||||||
(void) serialize_item_format(f, "cpu-usage-base", "%" PRIu64, crt->cpu_usage_base);
|
(void) serialize_item_format(f, "cpu-usage-base", "%" PRIu64, crt->cpu_usage_base);
|
||||||
if (crt->cpu_usage_last != NSEC_INFINITY)
|
if (crt->cpu_usage_last != NSEC_INFINITY)
|
||||||
(void) serialize_item_format(f, "cpu-usage-last", "%" PRIu64, crt->cpu_usage_last);
|
(void) serialize_item_format(f, "cpu-usage-last", "%" PRIu64, crt->cpu_usage_last);
|
||||||
@ -4316,15 +4319,6 @@ int cgroup_runtime_serialize(Unit *u, FILE *f, FDSet *fds) {
|
|||||||
(void) serialize_item_format(f, io_accounting_metric_field_last_to_string(im), "%" PRIu64, crt->io_accounting_last[im]);
|
(void) serialize_item_format(f, io_accounting_metric_field_last_to_string(im), "%" PRIu64, crt->io_accounting_last[im]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (crt->cgroup_path)
|
|
||||||
(void) serialize_item(f, "cgroup", crt->cgroup_path);
|
|
||||||
if (crt->cgroup_id != 0)
|
|
||||||
(void) serialize_item_format(f, "cgroup-id", "%" PRIu64, crt->cgroup_id);
|
|
||||||
|
|
||||||
(void) serialize_cgroup_mask(f, "cgroup-realized-mask", crt->cgroup_realized_mask);
|
|
||||||
(void) serialize_cgroup_mask(f, "cgroup-enabled-mask", crt->cgroup_enabled_mask);
|
|
||||||
(void) serialize_cgroup_mask(f, "cgroup-invalidated-mask", crt->cgroup_invalidated_mask);
|
|
||||||
|
|
||||||
(void) bpf_socket_bind_serialize(u, f, fds);
|
(void) bpf_socket_bind_serialize(u, f, fds);
|
||||||
|
|
||||||
(void) bpf_program_serialize_attachment(f, fds, "ip-bpf-ingress-installed", crt->ip_bpf_ingress_installed);
|
(void) bpf_program_serialize_attachment(f, fds, "ip-bpf-ingress-installed", crt->ip_bpf_ingress_installed);
|
||||||
|
|||||||
@ -134,7 +134,7 @@ libcore_static = static_library(
|
|||||||
dependencies : [libaudit_cflags,
|
dependencies : [libaudit_cflags,
|
||||||
libdl,
|
libdl,
|
||||||
libm,
|
libm,
|
||||||
libmount,
|
libmount_cflags,
|
||||||
librt,
|
librt,
|
||||||
libseccomp_cflags,
|
libseccomp_cflags,
|
||||||
libselinux,
|
libselinux,
|
||||||
@ -222,7 +222,7 @@ executables += [
|
|||||||
libcore,
|
libcore,
|
||||||
libshared
|
libshared
|
||||||
],
|
],
|
||||||
'dependencies' : libmount,
|
'dependencies' : libmount_cflags,
|
||||||
},
|
},
|
||||||
fuzz_template + {
|
fuzz_template + {
|
||||||
'sources' : files('fuzz-manager-serialize.c'),
|
'sources' : files('fuzz-manager-serialize.c'),
|
||||||
|
|||||||
@ -1952,16 +1952,16 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
|
|||||||
struct libmnt_fs *fs;
|
struct libmnt_fs *fs;
|
||||||
const char *device, *path, *options, *fstype;
|
const char *device, *path, *options, *fstype;
|
||||||
|
|
||||||
r = mnt_table_next_fs(table, iter, &fs);
|
r = sym_mnt_table_next_fs(table, iter, &fs);
|
||||||
if (r == 1)
|
if (r == 1)
|
||||||
break;
|
break;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
|
return log_error_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
|
||||||
|
|
||||||
device = mnt_fs_get_source(fs);
|
device = sym_mnt_fs_get_source(fs);
|
||||||
path = mnt_fs_get_target(fs);
|
path = sym_mnt_fs_get_target(fs);
|
||||||
options = mnt_fs_get_options(fs);
|
options = sym_mnt_fs_get_options(fs);
|
||||||
fstype = mnt_fs_get_fstype(fs);
|
fstype = sym_mnt_fs_get_fstype(fs);
|
||||||
|
|
||||||
if (!device || !path)
|
if (!device || !path)
|
||||||
continue;
|
continue;
|
||||||
@ -1983,9 +1983,11 @@ static void mount_shutdown(Manager *m) {
|
|||||||
|
|
||||||
m->mount_event_source = sd_event_source_disable_unref(m->mount_event_source);
|
m->mount_event_source = sd_event_source_disable_unref(m->mount_event_source);
|
||||||
|
|
||||||
mnt_unref_monitor(m->mount_monitor);
|
if (m->mount_monitor) {
|
||||||
|
sym_mnt_unref_monitor(m->mount_monitor);
|
||||||
m->mount_monitor = NULL;
|
m->mount_monitor = NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void mount_handoff_timestamp(
|
static void mount_handoff_timestamp(
|
||||||
Unit *u,
|
Unit *u,
|
||||||
@ -2075,33 +2077,39 @@ static void mount_enumerate(Manager *m) {
|
|||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
mnt_init_debug(0);
|
r = dlopen_libmount();
|
||||||
|
if (r < 0) {
|
||||||
|
log_error_errno(r, "Cannot enumerate mounts, as libmount is not available: %m");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
sym_mnt_init_debug(0);
|
||||||
|
|
||||||
if (!m->mount_monitor) {
|
if (!m->mount_monitor) {
|
||||||
usec_t mount_rate_limit_interval = 1 * USEC_PER_SEC;
|
usec_t mount_rate_limit_interval = 1 * USEC_PER_SEC;
|
||||||
unsigned mount_rate_limit_burst = 5;
|
unsigned mount_rate_limit_burst = 5;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
m->mount_monitor = mnt_new_monitor();
|
m->mount_monitor = sym_mnt_new_monitor();
|
||||||
if (!m->mount_monitor) {
|
if (!m->mount_monitor) {
|
||||||
log_oom();
|
log_oom();
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = mnt_monitor_enable_kernel(m->mount_monitor, 1);
|
r = sym_mnt_monitor_enable_kernel(m->mount_monitor, 1);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_error_errno(r, "Failed to enable watching of kernel mount events: %m");
|
log_error_errno(r, "Failed to enable watching of kernel mount events: %m");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = mnt_monitor_enable_userspace(m->mount_monitor, 1, NULL);
|
r = sym_mnt_monitor_enable_userspace(m->mount_monitor, 1, NULL);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_error_errno(r, "Failed to enable watching of userspace mount events: %m");
|
log_error_errno(r, "Failed to enable watching of userspace mount events: %m");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mnt_unref_monitor() will close the fd */
|
/* mnt_unref_monitor() will close the fd */
|
||||||
fd = r = mnt_monitor_get_fd(m->mount_monitor);
|
fd = r = sym_mnt_monitor_get_fd(m->mount_monitor);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_error_errno(r, "Failed to acquire watch file descriptor: %m");
|
log_error_errno(r, "Failed to acquire watch file descriptor: %m");
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -2165,6 +2173,9 @@ static int drain_libmount(Manager *m) {
|
|||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
|
if (!m->mount_monitor)
|
||||||
|
return false;
|
||||||
|
|
||||||
/* Drain all events and verify that the event is valid.
|
/* Drain all events and verify that the event is valid.
|
||||||
*
|
*
|
||||||
* Note that libmount also monitors /run/mount mkdir if the directory does not exist yet. The mkdir
|
* Note that libmount also monitors /run/mount mkdir if the directory does not exist yet. The mkdir
|
||||||
@ -2172,7 +2183,7 @@ static int drain_libmount(Manager *m) {
|
|||||||
*
|
*
|
||||||
* error: r < 0; valid: r == 0, false positive: r == 1 */
|
* error: r < 0; valid: r == 0, false positive: r == 1 */
|
||||||
do {
|
do {
|
||||||
r = mnt_monitor_next_change(m->mount_monitor, NULL, NULL);
|
r = sym_mnt_monitor_next_change(m->mount_monitor, NULL, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to drain libmount events: %m");
|
return log_error_errno(r, "Failed to drain libmount events: %m");
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
|
|||||||
@ -664,8 +664,6 @@ static int timer_start(Unit *u) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
t->last_trigger = DUAL_TIMESTAMP_NULL;
|
|
||||||
|
|
||||||
/* Reenable all timers that depend on unit activation time */
|
/* Reenable all timers that depend on unit activation time */
|
||||||
LIST_FOREACH(value, v, t->values)
|
LIST_FOREACH(value, v, t->values)
|
||||||
if (v->base == TIMER_ACTIVE)
|
if (v->base == TIMER_ACTIVE)
|
||||||
|
|||||||
@ -5559,11 +5559,11 @@ int unit_fork_helper_process(Unit *u, const char *name, bool into_cgroup, PidRef
|
|||||||
* with the child's PID. */
|
* with the child's PID. */
|
||||||
|
|
||||||
if (into_cgroup) {
|
if (into_cgroup) {
|
||||||
(void) unit_realize_cgroup(u);
|
r = unit_realize_cgroup(u);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
crt = unit_setup_cgroup_runtime(u);
|
crt = unit_get_cgroup_runtime(u);
|
||||||
if (!crt)
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r = safe_fork(name, FORK_REOPEN_LOG|FORK_DEATHSIG_SIGTERM, &pid);
|
r = safe_fork(name, FORK_REOPEN_LOG|FORK_DEATHSIG_SIGTERM, &pid);
|
||||||
@ -6005,15 +6005,11 @@ int unit_prepare_exec(Unit *u) {
|
|||||||
|
|
||||||
assert(u);
|
assert(u);
|
||||||
|
|
||||||
/* Load any custom firewall BPF programs here once to test if they are existing and actually loadable.
|
|
||||||
* Fail here early since later errors in the call chain unit_realize_cgroup to cgroup_context_apply are ignored. */
|
|
||||||
r = bpf_firewall_load_custom(u);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
/* Prepares everything so that we can fork of a process for this unit */
|
/* Prepares everything so that we can fork of a process for this unit */
|
||||||
|
|
||||||
(void) unit_realize_cgroup(u);
|
r = unit_realize_cgroup(u);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
CGroupRuntime *crt = unit_get_cgroup_runtime(u);
|
CGroupRuntime *crt = unit_get_cgroup_runtime(u);
|
||||||
if (crt && crt->reset_accounting) {
|
if (crt && crt->reset_accounting) {
|
||||||
|
|||||||
@ -191,19 +191,23 @@ static int is_tmpfs_with_noswap(dev_t devno) {
|
|||||||
_cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
|
_cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
table = mnt_new_table();
|
r = dlopen_libmount();
|
||||||
if (!table)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
r = mnt_table_parse_mtab(table, /* filename= */ NULL);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
struct libmnt_fs *fs = mnt_table_find_devno(table, devno, MNT_ITER_FORWARD);
|
table = sym_mnt_new_table();
|
||||||
|
if (!table)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
r = sym_mnt_table_parse_mtab(table, /* filename= */ NULL);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
struct libmnt_fs *fs = sym_mnt_table_find_devno(table, devno, MNT_ITER_FORWARD);
|
||||||
if (!fs)
|
if (!fs)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
r = mnt_fs_get_option(fs, "noswap", /* value= */ NULL, /* valuesz= */ NULL);
|
r = sym_mnt_fs_get_option(fs, "noswap", /* value= */ NULL, /* valuesz= */ NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ executables += [
|
|||||||
'public' : true,
|
'public' : true,
|
||||||
'sources' : files('creds.c'),
|
'sources' : files('creds.c'),
|
||||||
'dependencies' : [
|
'dependencies' : [
|
||||||
libmount,
|
libmount_cflags,
|
||||||
libopenssl,
|
libopenssl,
|
||||||
threads,
|
threads,
|
||||||
],
|
],
|
||||||
|
|||||||
@ -753,12 +753,12 @@ static char* disk_mount_point(const char *label) {
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
struct libmnt_fs *fs;
|
struct libmnt_fs *fs;
|
||||||
|
|
||||||
r = mnt_table_next_fs(table, iter, &fs);
|
r = sym_mnt_table_next_fs(table, iter, &fs);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (path_equal(mnt_fs_get_source(fs), device)) {
|
if (path_equal(sym_mnt_fs_get_source(fs), device)) {
|
||||||
const char *target = mnt_fs_get_target(fs);
|
const char *target = sym_mnt_fs_get_target(fs);
|
||||||
if (target)
|
if (target)
|
||||||
return strdup(target);
|
return strdup(target);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ executables += [
|
|||||||
'sources' : systemd_cryptsetup_sources,
|
'sources' : systemd_cryptsetup_sources,
|
||||||
'dependencies' : [
|
'dependencies' : [
|
||||||
libcryptsetup,
|
libcryptsetup,
|
||||||
libmount,
|
libmount_cflags,
|
||||||
libopenssl,
|
libopenssl,
|
||||||
libp11kit_cflags,
|
libp11kit_cflags,
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1048,15 +1048,19 @@ static int parse_fstab(bool prefix_sysroot) {
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
struct libmnt_fs *fs;
|
struct libmnt_fs *fs;
|
||||||
|
|
||||||
r = mnt_table_next_fs(table, iter, &fs);
|
r = sym_mnt_table_next_fs(table, iter, &fs);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to get next entry from '%s': %m", fstab);
|
return log_error_errno(r, "Failed to get next entry from '%s': %m", fstab);
|
||||||
if (r > 0) /* EOF */
|
if (r > 0) /* EOF */
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
r = parse_fstab_one(fstab,
|
r = parse_fstab_one(
|
||||||
mnt_fs_get_source(fs), mnt_fs_get_target(fs),
|
fstab,
|
||||||
mnt_fs_get_fstype(fs), mnt_fs_get_options(fs), mnt_fs_get_passno(fs),
|
sym_mnt_fs_get_source(fs),
|
||||||
|
sym_mnt_fs_get_target(fs),
|
||||||
|
sym_mnt_fs_get_fstype(fs),
|
||||||
|
sym_mnt_fs_get_options(fs),
|
||||||
|
sym_mnt_fs_get_passno(fs),
|
||||||
prefix_sysroot,
|
prefix_sysroot,
|
||||||
/* accept_root = */ false,
|
/* accept_root = */ false,
|
||||||
/* use_swap_enabled = */ true);
|
/* use_swap_enabled = */ true);
|
||||||
@ -1445,15 +1449,19 @@ static int add_mounts_from_creds(bool prefix_sysroot) {
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
struct libmnt_fs *fs;
|
struct libmnt_fs *fs;
|
||||||
|
|
||||||
r = mnt_table_next_fs(table, iter, &fs);
|
r = sym_mnt_table_next_fs(table, iter, &fs);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to get next fstab entry from credential '%s': %m", cred);
|
return log_error_errno(r, "Failed to get next fstab entry from credential '%s': %m", cred);
|
||||||
if (r > 0) /* EOF */
|
if (r > 0) /* EOF */
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
RET_GATHER(ret, parse_fstab_one("/run/credentials",
|
RET_GATHER(ret, parse_fstab_one(
|
||||||
mnt_fs_get_source(fs), mnt_fs_get_target(fs),
|
"/run/credentials",
|
||||||
mnt_fs_get_fstype(fs), mnt_fs_get_options(fs), mnt_fs_get_passno(fs),
|
sym_mnt_fs_get_source(fs),
|
||||||
|
sym_mnt_fs_get_target(fs),
|
||||||
|
sym_mnt_fs_get_fstype(fs),
|
||||||
|
sym_mnt_fs_get_options(fs),
|
||||||
|
sym_mnt_fs_get_passno(fs),
|
||||||
prefix_sysroot,
|
prefix_sysroot,
|
||||||
/* accept_root = */ true,
|
/* accept_root = */ true,
|
||||||
/* use_swap_enabled = */ true));
|
/* use_swap_enabled = */ true));
|
||||||
|
|||||||
@ -4,7 +4,7 @@ executables += [
|
|||||||
generator_template + {
|
generator_template + {
|
||||||
'name' : 'systemd-fstab-generator',
|
'name' : 'systemd-fstab-generator',
|
||||||
'sources' : files('fstab-generator.c'),
|
'sources' : files('fstab-generator.c'),
|
||||||
'dependencies' : libmount,
|
'dependencies' : libmount_cflags,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
"A service to create, remove, change or inspect home areas.",
|
"A service to create, remove, change or inspect home areas.",
|
||||||
BUS_IMPLEMENTATIONS(&manager_object,
|
BUS_IMPLEMENTATIONS(&manager_object,
|
||||||
&log_control_object),
|
&log_control_object),
|
||||||
|
/* runtime_scope= */ NULL,
|
||||||
argc, argv);
|
argc, argv);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@ -1988,6 +1988,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
"Manage the system hostname and related metadata.",
|
"Manage the system hostname and related metadata.",
|
||||||
BUS_IMPLEMENTATIONS(&manager_object,
|
BUS_IMPLEMENTATIONS(&manager_object,
|
||||||
&log_control_object),
|
&log_control_object),
|
||||||
|
/* runtime_scope= */ NULL,
|
||||||
argc, argv);
|
argc, argv);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@ -2019,6 +2019,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
"VM and container image import and export service.",
|
"VM and container image import and export service.",
|
||||||
BUS_IMPLEMENTATIONS(&manager_object,
|
BUS_IMPLEMENTATIONS(&manager_object,
|
||||||
&log_control_object),
|
&log_control_object),
|
||||||
|
/* runtime_scope= */ NULL,
|
||||||
argc, argv);
|
argc, argv);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@ -33,32 +33,54 @@ int user_search_dirs(const char *suffix, char ***ret_config_dirs, char ***ret_da
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int runtime_directory(RuntimeScope scope, const char *suffix, char **ret) {
|
int runtime_directory_generic(RuntimeScope scope, const char *suffix, char **ret) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(IN_SET(scope, RUNTIME_SCOPE_SYSTEM, RUNTIME_SCOPE_USER));
|
|
||||||
assert(suffix);
|
|
||||||
assert(ret);
|
assert(ret);
|
||||||
|
|
||||||
/* Accept $RUNTIME_DIRECTORY as authoritative
|
/* This does not bother with $RUNTIME_DIRECTORY, and hence can be applied to get other service's
|
||||||
|
* runtime dir */
|
||||||
|
|
||||||
|
switch (scope) {
|
||||||
|
case RUNTIME_SCOPE_USER:
|
||||||
|
r = xdg_user_runtime_dir(suffix, ret);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RUNTIME_SCOPE_SYSTEM: {
|
||||||
|
char *d = path_join("/run", suffix);
|
||||||
|
if (!d)
|
||||||
|
return -ENOMEM;
|
||||||
|
*ret = d;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int runtime_directory(RuntimeScope scope, const char *fallback_suffix, char **ret) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(ret);
|
||||||
|
|
||||||
|
/* Accept $RUNTIME_DIRECTORY as authoritative, i.e. only works for our service's own runtime dir.
|
||||||
|
*
|
||||||
* If it's missing, apply the suffix to /run/, or $XDG_RUNTIME_DIR if we are in a user runtime scope.
|
* If it's missing, apply the suffix to /run/, or $XDG_RUNTIME_DIR if we are in a user runtime scope.
|
||||||
*
|
*
|
||||||
* Return value indicates whether the suffix was applied or not */
|
* Return value indicates whether the suffix was applied or not. */
|
||||||
|
|
||||||
const char *e = secure_getenv("RUNTIME_DIRECTORY");
|
const char *e = secure_getenv("RUNTIME_DIRECTORY");
|
||||||
if (e)
|
if (e)
|
||||||
return strdup_to(ret, e);
|
return strdup_to(ret, e);
|
||||||
|
|
||||||
if (scope == RUNTIME_SCOPE_USER) {
|
r = runtime_directory_generic(scope, fallback_suffix, ret);
|
||||||
r = xdg_user_runtime_dir(suffix, ret);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
} else {
|
|
||||||
char *d = path_join("/run", suffix);
|
|
||||||
if (!d)
|
|
||||||
return -ENOMEM;
|
|
||||||
*ret = d;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,7 +57,8 @@ int lookup_paths_init_or_warn(LookupPaths *lp, RuntimeScope scope, LookupPathsFl
|
|||||||
void lookup_paths_log(LookupPaths *p);
|
void lookup_paths_log(LookupPaths *p);
|
||||||
void lookup_paths_done(LookupPaths *p);
|
void lookup_paths_done(LookupPaths *p);
|
||||||
|
|
||||||
int runtime_directory(RuntimeScope scope, const char *suffix, char **ret);
|
int runtime_directory_generic(RuntimeScope scope, const char *suffix, char **ret);
|
||||||
|
int runtime_directory(RuntimeScope scope, const char *fallback_suffix, char **ret);
|
||||||
|
|
||||||
/* We don't treat /etc/xdg/systemd/ in these functions as the xdg base dir spec suggests because we assume
|
/* We don't treat /etc/xdg/systemd/ in these functions as the xdg base dir spec suggests because we assume
|
||||||
* that is a link to /etc/systemd/ anyway. */
|
* that is a link to /etc/systemd/ anyway. */
|
||||||
|
|||||||
@ -635,6 +635,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
"Manage system locale settings and key mappings.",
|
"Manage system locale settings and key mappings.",
|
||||||
BUS_IMPLEMENTATIONS(&manager_object,
|
BUS_IMPLEMENTATIONS(&manager_object,
|
||||||
&log_control_object),
|
&log_control_object),
|
||||||
|
/* runtime_scope= */ NULL,
|
||||||
argc, argv);
|
argc, argv);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@ -1340,6 +1340,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
"Manager for user logins and devices and privileged operations.",
|
"Manager for user logins and devices and privileged operations.",
|
||||||
BUS_IMPLEMENTATIONS(&manager_object,
|
BUS_IMPLEMENTATIONS(&manager_object,
|
||||||
&log_control_object),
|
&log_control_object),
|
||||||
|
/* runtime_scope= */ NULL,
|
||||||
argc, argv);
|
argc, argv);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@ -40,6 +40,7 @@ int bus_image_method_remove(
|
|||||||
if (m->n_operations >= OPERATIONS_MAX)
|
if (m->n_operations >= OPERATIONS_MAX)
|
||||||
return sd_bus_error_set(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing operations.");
|
return sd_bus_error_set(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing operations.");
|
||||||
|
|
||||||
|
if (m->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
const char *details[] = {
|
const char *details[] = {
|
||||||
"image", image->name,
|
"image", image->name,
|
||||||
"verb", "remove",
|
"verb", "remove",
|
||||||
@ -56,6 +57,7 @@ int bus_image_method_remove(
|
|||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return 1; /* Will call us back */
|
return 1; /* Will call us back */
|
||||||
|
}
|
||||||
|
|
||||||
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
||||||
return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
|
return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
|
||||||
@ -65,7 +67,7 @@ int bus_image_method_remove(
|
|||||||
return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
|
return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
|
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
|
||||||
r = image_remove(image);
|
r = image_remove(image, m->runtime_scope);
|
||||||
report_errno_and_exit(errno_pipe_fd[1], r);
|
report_errno_and_exit(errno_pipe_fd[1], r);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,6 +103,7 @@ int bus_image_method_rename(
|
|||||||
if (!image_name_is_valid(new_name))
|
if (!image_name_is_valid(new_name))
|
||||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", new_name);
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", new_name);
|
||||||
|
|
||||||
|
if (m->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
const char *details[] = {
|
const char *details[] = {
|
||||||
"image", image->name,
|
"image", image->name,
|
||||||
"verb", "rename",
|
"verb", "rename",
|
||||||
@ -118,6 +121,7 @@ int bus_image_method_rename(
|
|||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return 1; /* Will call us back */
|
return 1; /* Will call us back */
|
||||||
|
}
|
||||||
|
|
||||||
r = rename_image_and_update_cache(m, image, new_name);
|
r = rename_image_and_update_cache(m, image, new_name);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -150,6 +154,7 @@ int bus_image_method_clone(
|
|||||||
if (!image_name_is_valid(new_name))
|
if (!image_name_is_valid(new_name))
|
||||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", new_name);
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", new_name);
|
||||||
|
|
||||||
|
if (m->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
const char *details[] = {
|
const char *details[] = {
|
||||||
"image", image->name,
|
"image", image->name,
|
||||||
"verb", "clone",
|
"verb", "clone",
|
||||||
@ -167,6 +172,7 @@ int bus_image_method_clone(
|
|||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return 1; /* Will call us back */
|
return 1; /* Will call us back */
|
||||||
|
}
|
||||||
|
|
||||||
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
||||||
return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
|
return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
|
||||||
@ -199,7 +205,7 @@ int bus_image_method_mark_read_only(
|
|||||||
sd_bus_error *error) {
|
sd_bus_error *error) {
|
||||||
|
|
||||||
Image *image = userdata;
|
Image *image = userdata;
|
||||||
Manager *m = image->userdata;
|
Manager *m = ASSERT_PTR(image->userdata);
|
||||||
int read_only, r;
|
int read_only, r;
|
||||||
|
|
||||||
assert(message);
|
assert(message);
|
||||||
@ -208,6 +214,7 @@ int bus_image_method_mark_read_only(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
if (m->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
const char *details[] = {
|
const char *details[] = {
|
||||||
"image", image->name,
|
"image", image->name,
|
||||||
"verb", "mark_read_only",
|
"verb", "mark_read_only",
|
||||||
@ -225,8 +232,9 @@ int bus_image_method_mark_read_only(
|
|||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return 1; /* Will call us back */
|
return 1; /* Will call us back */
|
||||||
|
}
|
||||||
|
|
||||||
r = image_read_only(image, read_only);
|
r = image_read_only(image, read_only, m->runtime_scope);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -251,6 +259,7 @@ int bus_image_method_set_limit(
|
|||||||
if (!FILE_SIZE_VALID_OR_INFINITY(limit))
|
if (!FILE_SIZE_VALID_OR_INFINITY(limit))
|
||||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range");
|
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range");
|
||||||
|
|
||||||
|
if (m->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
const char *details[] = {
|
const char *details[] = {
|
||||||
"machine", image->name,
|
"machine", image->name,
|
||||||
"verb", "set_limit",
|
"verb", "set_limit",
|
||||||
@ -267,6 +276,7 @@ int bus_image_method_set_limit(
|
|||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return 1; /* Will call us back */
|
return 1; /* Will call us back */
|
||||||
|
}
|
||||||
|
|
||||||
r = image_set_limit(image, limit);
|
r = image_set_limit(image, limit);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -280,11 +290,12 @@ int bus_image_method_get_hostname(
|
|||||||
void *userdata,
|
void *userdata,
|
||||||
sd_bus_error *error) {
|
sd_bus_error *error) {
|
||||||
|
|
||||||
Image *image = userdata;
|
Image *image = ASSERT_PTR(userdata);
|
||||||
|
Manager *m = ASSERT_PTR(image->userdata);
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!image->metadata_valid) {
|
if (!image->metadata_valid) {
|
||||||
r = image_read_metadata(image, &image_policy_container);
|
r = image_read_metadata(image, &image_policy_container, m->runtime_scope);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m");
|
return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m");
|
||||||
}
|
}
|
||||||
@ -298,11 +309,12 @@ int bus_image_method_get_machine_id(
|
|||||||
sd_bus_error *error) {
|
sd_bus_error *error) {
|
||||||
|
|
||||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||||
Image *image = userdata;
|
Image *image = ASSERT_PTR(userdata);
|
||||||
|
Manager *m = ASSERT_PTR(image->userdata);
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!image->metadata_valid) {
|
if (!image->metadata_valid) {
|
||||||
r = image_read_metadata(image, &image_policy_container);
|
r = image_read_metadata(image, &image_policy_container, m->runtime_scope);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m");
|
return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m");
|
||||||
}
|
}
|
||||||
@ -326,11 +338,12 @@ int bus_image_method_get_machine_info(
|
|||||||
void *userdata,
|
void *userdata,
|
||||||
sd_bus_error *error) {
|
sd_bus_error *error) {
|
||||||
|
|
||||||
Image *image = userdata;
|
Image *image = ASSERT_PTR(userdata);
|
||||||
|
Manager *m = ASSERT_PTR(image->userdata);
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!image->metadata_valid) {
|
if (!image->metadata_valid) {
|
||||||
r = image_read_metadata(image, &image_policy_container);
|
r = image_read_metadata(image, &image_policy_container, m->runtime_scope);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m");
|
return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m");
|
||||||
}
|
}
|
||||||
@ -343,11 +356,12 @@ int bus_image_method_get_os_release(
|
|||||||
void *userdata,
|
void *userdata,
|
||||||
sd_bus_error *error) {
|
sd_bus_error *error) {
|
||||||
|
|
||||||
Image *image = userdata;
|
Image *image = ASSERT_PTR(userdata);
|
||||||
|
Manager *m = ASSERT_PTR(image->userdata);
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!image->metadata_valid) {
|
if (!image->metadata_valid) {
|
||||||
r = image_read_metadata(image, &image_policy_container);
|
r = image_read_metadata(image, &image_policy_container, m->runtime_scope);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m");
|
return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -66,15 +66,17 @@ int vl_method_update_image(sd_varlink *link, sd_json_variant *parameters, sd_var
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
r = varlink_verify_polkit_async(
|
r = varlink_verify_polkit_async(
|
||||||
link,
|
link,
|
||||||
manager->bus,
|
manager->system_bus,
|
||||||
"org.freedesktop.machine1.manage-images",
|
"org.freedesktop.machine1.manage-images",
|
||||||
(const char**) STRV_MAKE("image", image->name,
|
(const char**) STRV_MAKE("image", image->name,
|
||||||
"verb", "update"),
|
"verb", "update"),
|
||||||
&manager->polkit_registry);
|
&manager->polkit_registry);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
if (p.new_name) {
|
if (p.new_name) {
|
||||||
r = rename_image_and_update_cache(manager, image, p.new_name);
|
r = rename_image_and_update_cache(manager, image, p.new_name);
|
||||||
@ -83,7 +85,7 @@ int vl_method_update_image(sd_varlink *link, sd_json_variant *parameters, sd_var
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (p.read_only >= 0) {
|
if (p.read_only >= 0) {
|
||||||
r = image_read_only(image, p.read_only);
|
r = image_read_only(image, p.read_only, manager->runtime_scope);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
RET_GATHER(ret, log_debug_errno(r, "Failed to toggle image read only, ignoring: %m"));
|
RET_GATHER(ret, log_debug_errno(r, "Failed to toggle image read only, ignoring: %m"));
|
||||||
}
|
}
|
||||||
@ -139,9 +141,10 @@ int vl_method_clone_image(sd_varlink *link, sd_json_variant *parameters, sd_varl
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
r = varlink_verify_polkit_async(
|
r = varlink_verify_polkit_async(
|
||||||
link,
|
link,
|
||||||
manager->bus,
|
manager->system_bus,
|
||||||
"org.freedesktop.machine1.manage-images",
|
"org.freedesktop.machine1.manage-images",
|
||||||
(const char**) STRV_MAKE("image", image->name,
|
(const char**) STRV_MAKE("image", image->name,
|
||||||
"verb", "clone",
|
"verb", "clone",
|
||||||
@ -149,6 +152,7 @@ int vl_method_clone_image(sd_varlink *link, sd_json_variant *parameters, sd_varl
|
|||||||
&manager->polkit_registry);
|
&manager->polkit_registry);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
||||||
return log_debug_errno(errno, "Failed to open pipe: %m");
|
return log_debug_errno(errno, "Failed to open pipe: %m");
|
||||||
@ -207,15 +211,17 @@ int vl_method_remove_image(sd_varlink *link, sd_json_variant *parameters, sd_var
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
r = varlink_verify_polkit_async(
|
r = varlink_verify_polkit_async(
|
||||||
link,
|
link,
|
||||||
manager->bus,
|
manager->system_bus,
|
||||||
"org.freedesktop.machine1.manage-images",
|
"org.freedesktop.machine1.manage-images",
|
||||||
(const char**) STRV_MAKE("image", image->name,
|
(const char**) STRV_MAKE("image", image->name,
|
||||||
"verb", "remove"),
|
"verb", "remove"),
|
||||||
&manager->polkit_registry);
|
&manager->polkit_registry);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
||||||
return log_debug_errno(errno, "Failed to open pipe: %m");
|
return log_debug_errno(errno, "Failed to open pipe: %m");
|
||||||
@ -225,7 +231,7 @@ int vl_method_remove_image(sd_varlink *link, sd_json_variant *parameters, sd_var
|
|||||||
return log_debug_errno(r, "Failed to fork: %m");
|
return log_debug_errno(r, "Failed to fork: %m");
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
|
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
|
||||||
r = image_remove(image);
|
r = image_remove(image, manager->runtime_scope);
|
||||||
report_errno_and_exit(errno_pipe_fd[1], r);
|
report_errno_and_exit(errno_pipe_fd[1], r);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,21 +268,23 @@ int vl_method_set_pool_limit(sd_varlink *link, sd_json_variant *parameters, sd_v
|
|||||||
if (!FILE_SIZE_VALID_OR_INFINITY(limit))
|
if (!FILE_SIZE_VALID_OR_INFINITY(limit))
|
||||||
return sd_varlink_error_invalid_parameter_name(link, "limit");
|
return sd_varlink_error_invalid_parameter_name(link, "limit");
|
||||||
|
|
||||||
|
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
r = varlink_verify_polkit_async(
|
r = varlink_verify_polkit_async(
|
||||||
link,
|
link,
|
||||||
manager->bus,
|
manager->system_bus,
|
||||||
"org.freedesktop.machine1.manage-images",
|
"org.freedesktop.machine1.manage-images",
|
||||||
(const char**) STRV_MAKE("verb", "set_pool_limit"),
|
(const char**) STRV_MAKE("verb", "set_pool_limit"),
|
||||||
&manager->polkit_registry);
|
&manager->polkit_registry);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set up the machine directory if necessary */
|
/* Set up the machine directory if necessary */
|
||||||
r = setup_machine_directory(/* error = */ NULL, /* use_btrfs_subvol= */ true, /* use_btrfs_quota= */ true);
|
r = setup_machine_directory(/* error = */ NULL, /* use_btrfs_subvol= */ true, /* use_btrfs_quota= */ true);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = image_set_pool_limit(IMAGE_MACHINE, limit);
|
r = image_set_pool_limit(manager->runtime_scope, IMAGE_MACHINE, limit);
|
||||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
||||||
return sd_varlink_error(link, VARLINK_ERROR_MACHINE_IMAGE_NOT_SUPPORTED, NULL);
|
return sd_varlink_error(link, VARLINK_ERROR_MACHINE_IMAGE_NOT_SUPPORTED, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -394,15 +402,17 @@ int vl_method_clean_pool(sd_varlink *link, sd_json_variant *parameters, sd_varli
|
|||||||
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
|
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
|
||||||
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
|
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
|
||||||
|
|
||||||
|
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
r = varlink_verify_polkit_async(
|
r = varlink_verify_polkit_async(
|
||||||
link,
|
link,
|
||||||
manager->bus,
|
manager->system_bus,
|
||||||
"org.freedesktop.machine1.manage-images",
|
"org.freedesktop.machine1.manage-images",
|
||||||
(const char**) STRV_MAKE("mode", image_clean_pool_mode_to_string(mode),
|
(const char**) STRV_MAKE("mode", image_clean_pool_mode_to_string(mode),
|
||||||
"verb", "clean_pool"),
|
"verb", "clean_pool"),
|
||||||
&manager->polkit_registry);
|
&manager->polkit_registry);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
Operation *op;
|
Operation *op;
|
||||||
r = image_clean_pool_operation(manager, mode, &op);
|
r = image_clean_pool_operation(manager, mode, &op);
|
||||||
|
|||||||
@ -143,7 +143,7 @@ int image_clean_pool_operation(Manager *manager, ImageCleanPoolMode mode, Operat
|
|||||||
if (mode == IMAGE_CLEAN_POOL_REMOVE_HIDDEN && !image_is_hidden(image))
|
if (mode == IMAGE_CLEAN_POOL_REMOVE_HIDDEN && !image_is_hidden(image))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = image_remove(image);
|
r = image_remove(image, manager->runtime_scope);
|
||||||
if (r == -EBUSY) {
|
if (r == -EBUSY) {
|
||||||
log_debug("Keeping image '%s' because it's currently used.", image->name);
|
log_debug("Keeping image '%s' because it's currently used.", image->name);
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@ -55,6 +55,7 @@ int bus_machine_method_unregister(sd_bus_message *message, void *userdata, sd_bu
|
|||||||
|
|
||||||
assert(message);
|
assert(message);
|
||||||
|
|
||||||
|
if (m->manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
const char *details[] = {
|
const char *details[] = {
|
||||||
"machine", m->name,
|
"machine", m->name,
|
||||||
"verb", "unregister",
|
"verb", "unregister",
|
||||||
@ -73,6 +74,7 @@ int bus_machine_method_unregister(sd_bus_message *message, void *userdata, sd_bu
|
|||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return 1; /* Will call us back */
|
return 1; /* Will call us back */
|
||||||
|
}
|
||||||
|
|
||||||
r = machine_finalize(m);
|
r = machine_finalize(m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -87,6 +89,7 @@ int bus_machine_method_terminate(sd_bus_message *message, void *userdata, sd_bus
|
|||||||
|
|
||||||
assert(message);
|
assert(message);
|
||||||
|
|
||||||
|
if (m->manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
const char *details[] = {
|
const char *details[] = {
|
||||||
"machine", m->name,
|
"machine", m->name,
|
||||||
"verb", "terminate",
|
"verb", "terminate",
|
||||||
@ -105,6 +108,7 @@ int bus_machine_method_terminate(sd_bus_message *message, void *userdata, sd_bus
|
|||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return 1; /* Will call us back */
|
return 1; /* Will call us back */
|
||||||
|
}
|
||||||
|
|
||||||
r = machine_stop(m);
|
r = machine_stop(m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -137,6 +141,7 @@ int bus_machine_method_kill(sd_bus_message *message, void *userdata, sd_bus_erro
|
|||||||
if (!SIGNAL_VALID(signo))
|
if (!SIGNAL_VALID(signo))
|
||||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
|
||||||
|
|
||||||
|
if (m->manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
const char *details[] = {
|
const char *details[] = {
|
||||||
"machine", m->name,
|
"machine", m->name,
|
||||||
"verb", "kill",
|
"verb", "kill",
|
||||||
@ -155,6 +160,7 @@ int bus_machine_method_kill(sd_bus_message *message, void *userdata, sd_bus_erro
|
|||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return 1; /* Will call us back */
|
return 1; /* Will call us back */
|
||||||
|
}
|
||||||
|
|
||||||
r = machine_kill(m, whom, signo);
|
r = machine_kill(m, whom, signo);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -260,6 +266,7 @@ int bus_machine_method_open_pty(sd_bus_message *message, void *userdata, sd_bus_
|
|||||||
|
|
||||||
assert(message);
|
assert(message);
|
||||||
|
|
||||||
|
if (m->manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
const char *details[] = {
|
const char *details[] = {
|
||||||
"machine", m->name,
|
"machine", m->name,
|
||||||
NULL
|
NULL
|
||||||
@ -277,6 +284,7 @@ int bus_machine_method_open_pty(sd_bus_message *message, void *userdata, sd_bus_
|
|||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return 1; /* Will call us back */
|
return 1; /* Will call us back */
|
||||||
|
}
|
||||||
|
|
||||||
master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC, &pty_name);
|
master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC, &pty_name);
|
||||||
if (master < 0)
|
if (master < 0)
|
||||||
@ -302,6 +310,7 @@ int bus_machine_method_open_login(sd_bus_message *message, void *userdata, sd_bu
|
|||||||
|
|
||||||
assert(message);
|
assert(message);
|
||||||
|
|
||||||
|
if (m->manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
const char *details[] = {
|
const char *details[] = {
|
||||||
"machine", m->name,
|
"machine", m->name,
|
||||||
"verb", "login",
|
"verb", "login",
|
||||||
@ -320,6 +329,7 @@ int bus_machine_method_open_login(sd_bus_message *message, void *userdata, sd_bu
|
|||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return 1; /* Will call us back */
|
return 1; /* Will call us back */
|
||||||
|
}
|
||||||
|
|
||||||
master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC, &pty_name);
|
master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC, &pty_name);
|
||||||
if (master < 0)
|
if (master < 0)
|
||||||
@ -345,7 +355,6 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
|
|||||||
_cleanup_free_ char *pty_name = NULL;
|
_cleanup_free_ char *pty_name = NULL;
|
||||||
_cleanup_close_ int master = -EBADF;
|
_cleanup_close_ int master = -EBADF;
|
||||||
_cleanup_strv_free_ char **env = NULL, **args_wire = NULL, **args = NULL;
|
_cleanup_strv_free_ char **env = NULL, **args_wire = NULL, **args = NULL;
|
||||||
_cleanup_free_ char *command_line = NULL;
|
|
||||||
Machine *m = ASSERT_PTR(userdata);
|
Machine *m = ASSERT_PTR(userdata);
|
||||||
const char *user, *path;
|
const char *user, *path;
|
||||||
int r;
|
int r;
|
||||||
@ -402,9 +411,11 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
|
|||||||
if (!strv_env_is_valid(env))
|
if (!strv_env_is_valid(env))
|
||||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
|
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
|
||||||
|
|
||||||
command_line = strv_join(args, " ");
|
if (m->manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
|
_cleanup_free_ char *command_line = strv_join(args, " ");
|
||||||
if (!command_line)
|
if (!command_line)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
const char *details[] = {
|
const char *details[] = {
|
||||||
"machine", m->name,
|
"machine", m->name,
|
||||||
"user", user,
|
"user", user,
|
||||||
@ -425,6 +436,7 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
|
|||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return 1; /* Will call us back */
|
return 1; /* Will call us back */
|
||||||
|
}
|
||||||
|
|
||||||
master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC, &pty_name);
|
master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC, &pty_name);
|
||||||
if (master < 0)
|
if (master < 0)
|
||||||
@ -470,6 +482,7 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu
|
|||||||
else if (!path_is_absolute(dest) || !path_is_normalized(dest))
|
else if (!path_is_absolute(dest) || !path_is_normalized(dest))
|
||||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and normalized.");
|
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and normalized.");
|
||||||
|
|
||||||
|
if (m->manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
const char *details[] = {
|
const char *details[] = {
|
||||||
"machine", m->name,
|
"machine", m->name,
|
||||||
"verb", "bind",
|
"verb", "bind",
|
||||||
@ -489,6 +502,7 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu
|
|||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return 1; /* Will call us back */
|
return 1; /* Will call us back */
|
||||||
|
}
|
||||||
|
|
||||||
r = machine_get_uid_shift(m, &uid);
|
r = machine_get_uid_shift(m, &uid);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -556,6 +570,7 @@ int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_erro
|
|||||||
else if (!path_is_absolute(dest))
|
else if (!path_is_absolute(dest))
|
||||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute.");
|
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute.");
|
||||||
|
|
||||||
|
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
const char *details[] = {
|
const char *details[] = {
|
||||||
"machine", m->name,
|
"machine", m->name,
|
||||||
"verb", "copy",
|
"verb", "copy",
|
||||||
@ -575,6 +590,7 @@ int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_erro
|
|||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return 1; /* Will call us back */
|
return 1; /* Will call us back */
|
||||||
|
}
|
||||||
|
|
||||||
copy_from = strstr(sd_bus_message_get_member(message), "CopyFrom");
|
copy_from = strstr(sd_bus_message_get_member(message), "CopyFrom");
|
||||||
|
|
||||||
@ -602,6 +618,7 @@ int bus_machine_method_open_root_directory(sd_bus_message *message, void *userda
|
|||||||
|
|
||||||
assert(message);
|
assert(message);
|
||||||
|
|
||||||
|
if (m->manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
const char *details[] = {
|
const char *details[] = {
|
||||||
"machine", m->name,
|
"machine", m->name,
|
||||||
"verb", "open_root_directory",
|
"verb", "open_root_directory",
|
||||||
@ -619,6 +636,7 @@ int bus_machine_method_open_root_directory(sd_bus_message *message, void *userda
|
|||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return 1; /* Will call us back */
|
return 1; /* Will call us back */
|
||||||
|
}
|
||||||
|
|
||||||
fd = machine_open_root_directory(m);
|
fd = machine_open_root_directory(m);
|
||||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(fd))
|
if (ERRNO_IS_NEG_NOT_SUPPORTED(fd))
|
||||||
@ -862,7 +880,7 @@ int machine_send_signal(Machine *m, bool new_machine) {
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
return sd_bus_emit_signal(
|
return sd_bus_emit_signal(
|
||||||
m->manager->bus,
|
m->manager->api_bus,
|
||||||
"/org/freedesktop/machine1",
|
"/org/freedesktop/machine1",
|
||||||
"org.freedesktop.machine1.Manager",
|
"org.freedesktop.machine1.Manager",
|
||||||
new_machine ? "MachineNew" : "MachineRemoved",
|
new_machine ? "MachineNew" : "MachineRemoved",
|
||||||
|
|||||||
@ -155,15 +155,17 @@ int vl_method_register(sd_varlink *link, sd_json_variant *parameters, sd_varlink
|
|||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
r = varlink_verify_polkit_async(
|
r = varlink_verify_polkit_async(
|
||||||
link,
|
link,
|
||||||
manager->bus,
|
manager->system_bus,
|
||||||
machine->allocate_unit ? "org.freedesktop.machine1.create-machine" : "org.freedesktop.machine1.register-machine",
|
machine->allocate_unit ? "org.freedesktop.machine1.create-machine" : "org.freedesktop.machine1.register-machine",
|
||||||
(const char**) STRV_MAKE("name", machine->name,
|
(const char**) STRV_MAKE("name", machine->name,
|
||||||
"class", machine_class_to_string(machine->class)),
|
"class", machine_class_to_string(machine->class)),
|
||||||
&manager->polkit_registry);
|
&manager->polkit_registry);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
if (!pidref_is_set(&machine->leader)) {
|
if (!pidref_is_set(&machine->leader)) {
|
||||||
r = varlink_get_peer_pidref(link, &machine->leader);
|
r = varlink_get_peer_pidref(link, &machine->leader);
|
||||||
@ -306,9 +308,10 @@ int vl_method_unregister_internal(sd_varlink *link, sd_json_variant *parameters,
|
|||||||
Manager *manager = ASSERT_PTR(machine->manager);
|
Manager *manager = ASSERT_PTR(machine->manager);
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
r = varlink_verify_polkit_async_full(
|
r = varlink_verify_polkit_async_full(
|
||||||
link,
|
link,
|
||||||
manager->bus,
|
manager->system_bus,
|
||||||
"org.freedesktop.machine1.manage-machines",
|
"org.freedesktop.machine1.manage-machines",
|
||||||
(const char**) STRV_MAKE("name", machine->name,
|
(const char**) STRV_MAKE("name", machine->name,
|
||||||
"verb", "unregister"),
|
"verb", "unregister"),
|
||||||
@ -317,6 +320,7 @@ int vl_method_unregister_internal(sd_varlink *link, sd_json_variant *parameters,
|
|||||||
&manager->polkit_registry);
|
&manager->polkit_registry);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
r = machine_finalize(machine);
|
r = machine_finalize(machine);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -330,9 +334,10 @@ int vl_method_terminate_internal(sd_varlink *link, sd_json_variant *parameters,
|
|||||||
Manager *manager = ASSERT_PTR(machine->manager);
|
Manager *manager = ASSERT_PTR(machine->manager);
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
r = varlink_verify_polkit_async_full(
|
r = varlink_verify_polkit_async_full(
|
||||||
link,
|
link,
|
||||||
manager->bus,
|
manager->system_bus,
|
||||||
"org.freedesktop.machine1.manage-machines",
|
"org.freedesktop.machine1.manage-machines",
|
||||||
(const char**) STRV_MAKE("name", machine->name,
|
(const char**) STRV_MAKE("name", machine->name,
|
||||||
"verb", "terminate"),
|
"verb", "terminate"),
|
||||||
@ -341,6 +346,7 @@ int vl_method_terminate_internal(sd_varlink *link, sd_json_variant *parameters,
|
|||||||
&manager->polkit_registry);
|
&manager->polkit_registry);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
r = machine_stop(machine);
|
r = machine_stop(machine);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -400,9 +406,10 @@ int vl_method_kill(sd_varlink *link, sd_json_variant *parameters, sd_varlink_met
|
|||||||
return sd_varlink_error_invalid_parameter_name(link, "whom");
|
return sd_varlink_error_invalid_parameter_name(link, "whom");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
r = varlink_verify_polkit_async_full(
|
r = varlink_verify_polkit_async_full(
|
||||||
link,
|
link,
|
||||||
manager->bus,
|
manager->system_bus,
|
||||||
"org.freedesktop.machine1.manage-machines",
|
"org.freedesktop.machine1.manage-machines",
|
||||||
(const char**) STRV_MAKE("name", machine->name,
|
(const char**) STRV_MAKE("name", machine->name,
|
||||||
"verb", "kill"),
|
"verb", "kill"),
|
||||||
@ -411,6 +418,7 @@ int vl_method_kill(sd_varlink *link, sd_json_variant *parameters, sd_varlink_met
|
|||||||
&manager->polkit_registry);
|
&manager->polkit_registry);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
r = machine_kill(machine, whom, p.signo);
|
r = machine_kill(machine, whom, p.signo);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -509,8 +517,8 @@ int vl_method_open(sd_varlink *link, sd_json_variant *parameters, sd_varlink_met
|
|||||||
};
|
};
|
||||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
||||||
_cleanup_free_ char *ptmx_name = NULL, *command_line = NULL;
|
_cleanup_free_ char *ptmx_name = NULL, *command_line = NULL;
|
||||||
_cleanup_strv_free_ char **polkit_details = NULL, **args = NULL;
|
|
||||||
const char *user = NULL, *path = NULL; /* gcc complains about uninitialized variables */
|
const char *user = NULL, *path = NULL; /* gcc complains about uninitialized variables */
|
||||||
|
_cleanup_strv_free_ char **args = NULL;
|
||||||
Machine *machine;
|
Machine *machine;
|
||||||
int r, ptmx_fd_idx;
|
int r, ptmx_fd_idx;
|
||||||
|
|
||||||
@ -543,10 +551,13 @@ int vl_method_open(sd_varlink *link, sd_json_variant *parameters, sd_varlink_met
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
|
_cleanup_strv_free_ char **polkit_details = NULL;
|
||||||
|
|
||||||
polkit_details = machine_open_polkit_details(p.mode, machine->name, user, path, command_line);
|
polkit_details = machine_open_polkit_details(p.mode, machine->name, user, path, command_line);
|
||||||
r = varlink_verify_polkit_async_full(
|
r = varlink_verify_polkit_async_full(
|
||||||
link,
|
link,
|
||||||
manager->bus,
|
manager->system_bus,
|
||||||
machine_open_polkit_action(p.mode, machine->class),
|
machine_open_polkit_action(p.mode, machine->class),
|
||||||
(const char**) polkit_details,
|
(const char**) polkit_details,
|
||||||
machine->uid,
|
machine->uid,
|
||||||
@ -554,6 +565,7 @@ int vl_method_open(sd_varlink *link, sd_json_variant *parameters, sd_varlink_met
|
|||||||
&manager->polkit_registry);
|
&manager->polkit_registry);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
ptmx_fd = machine_openpt(machine, O_RDWR|O_NOCTTY|O_CLOEXEC, &ptmx_name);
|
ptmx_fd = machine_openpt(machine, O_RDWR|O_NOCTTY|O_CLOEXEC, &ptmx_name);
|
||||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(ptmx_fd))
|
if (ERRNO_IS_NEG_NOT_SUPPORTED(ptmx_fd))
|
||||||
@ -824,10 +836,11 @@ int vl_method_bind_mount(sd_varlink *link, sd_json_variant *parameters, sd_varli
|
|||||||
if (machine->class != MACHINE_CONTAINER)
|
if (machine->class != MACHINE_CONTAINER)
|
||||||
return sd_varlink_error(link, VARLINK_ERROR_MACHINE_NOT_SUPPORTED, NULL);
|
return sd_varlink_error(link, VARLINK_ERROR_MACHINE_NOT_SUPPORTED, NULL);
|
||||||
|
|
||||||
|
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
/* NB: For now not opened up to owner of machine without auth */
|
/* NB: For now not opened up to owner of machine without auth */
|
||||||
r = varlink_verify_polkit_async(
|
r = varlink_verify_polkit_async(
|
||||||
link,
|
link,
|
||||||
manager->bus,
|
manager->system_bus,
|
||||||
"org.freedesktop.machine1.manage-machines",
|
"org.freedesktop.machine1.manage-machines",
|
||||||
(const char**) STRV_MAKE("name", machine->name,
|
(const char**) STRV_MAKE("name", machine->name,
|
||||||
"verb", "bind",
|
"verb", "bind",
|
||||||
@ -836,6 +849,7 @@ int vl_method_bind_mount(sd_varlink *link, sd_json_variant *parameters, sd_varli
|
|||||||
&manager->polkit_registry);
|
&manager->polkit_registry);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
r = machine_get_uid_shift(machine, &uid_shift);
|
r = machine_get_uid_shift(machine, &uid_shift);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -936,10 +950,11 @@ int vl_method_copy_internal(sd_varlink *link, sd_json_variant *parameters, sd_va
|
|||||||
if (machine->class != MACHINE_CONTAINER)
|
if (machine->class != MACHINE_CONTAINER)
|
||||||
return sd_varlink_error(link, VARLINK_ERROR_MACHINE_NOT_SUPPORTED, NULL);
|
return sd_varlink_error(link, VARLINK_ERROR_MACHINE_NOT_SUPPORTED, NULL);
|
||||||
|
|
||||||
|
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
/* NB: For now not opened up to owner of machine without auth */
|
/* NB: For now not opened up to owner of machine without auth */
|
||||||
r = varlink_verify_polkit_async(
|
r = varlink_verify_polkit_async(
|
||||||
link,
|
link,
|
||||||
manager->bus,
|
manager->system_bus,
|
||||||
"org.freedesktop.machine1.manage-machines",
|
"org.freedesktop.machine1.manage-machines",
|
||||||
(const char**) STRV_MAKE("name", machine->name,
|
(const char**) STRV_MAKE("name", machine->name,
|
||||||
"verb", "copy",
|
"verb", "copy",
|
||||||
@ -948,6 +963,7 @@ int vl_method_copy_internal(sd_varlink *link, sd_json_variant *parameters, sd_va
|
|||||||
&manager->polkit_registry);
|
&manager->polkit_registry);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
Operation *op;
|
Operation *op;
|
||||||
r = machine_copy_from_to_operation(manager, machine, host_path, container_path, copy_from, copy_flags, &op);
|
r = machine_copy_from_to_operation(manager, machine, host_path, container_path, copy_from, copy_flags, &op);
|
||||||
@ -967,15 +983,17 @@ int vl_method_open_root_directory_internal(sd_varlink *link, sd_json_variant *pa
|
|||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* NB: For now not opened up to owner of machine without auth */
|
/* NB: For now not opened up to owner of machine without auth */
|
||||||
|
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
r = varlink_verify_polkit_async(
|
r = varlink_verify_polkit_async(
|
||||||
link,
|
link,
|
||||||
manager->bus,
|
manager->system_bus,
|
||||||
"org.freedesktop.machine1.manage-machines",
|
"org.freedesktop.machine1.manage-machines",
|
||||||
(const char**) STRV_MAKE("name", machine->name,
|
(const char**) STRV_MAKE("name", machine->name,
|
||||||
"verb", "open_root_directory"),
|
"verb", "open_root_directory"),
|
||||||
&manager->polkit_registry);
|
&manager->polkit_registry);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
fd = machine_open_root_directory(machine);
|
fd = machine_open_root_directory(machine);
|
||||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(fd))
|
if (ERRNO_IS_NEG_NOT_SUPPORTED(fd))
|
||||||
|
|||||||
@ -88,7 +88,7 @@ int machine_link(Manager *manager, Machine *machine) {
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (machine->class != MACHINE_HOST) {
|
if (machine->class != MACHINE_HOST) {
|
||||||
char *temp = path_join("/run/systemd/machines", machine->name);
|
char *temp = path_join(manager->state_dir, machine->name);
|
||||||
if (!temp)
|
if (!temp)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -170,14 +170,14 @@ int machine_save(Machine *m) {
|
|||||||
|
|
||||||
_cleanup_(unlink_and_freep) char *sl = NULL; /* auto-unlink! */
|
_cleanup_(unlink_and_freep) char *sl = NULL; /* auto-unlink! */
|
||||||
if (m->unit && !m->subgroup) {
|
if (m->unit && !m->subgroup) {
|
||||||
sl = strjoin("/run/systemd/machines/unit:", m->unit);
|
sl = strjoin(m->manager->state_dir, "/unit:", m->unit);
|
||||||
if (!sl)
|
if (!sl)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
}
|
}
|
||||||
|
|
||||||
r = mkdir_safe_label("/run/systemd/machines", 0755, 0, 0, MKDIR_WARN_MODE);
|
r = mkdir_safe_label(m->manager->state_dir, 0755, 0, 0, MKDIR_WARN_MODE);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to create /run/systemd/machines/: %m");
|
return log_error_errno(r, "Failed to create '%s': %m", m->manager->state_dir);
|
||||||
|
|
||||||
_cleanup_(unlink_and_freep) char *temp_path = NULL;
|
_cleanup_(unlink_and_freep) char *temp_path = NULL;
|
||||||
_cleanup_fclose_ FILE *f = NULL;
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
@ -267,7 +267,7 @@ static void machine_unlink(Machine *m) {
|
|||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
if (m->unit && !m->subgroup) {
|
if (m->unit && !m->subgroup) {
|
||||||
const char *sl = strjoina("/run/systemd/machines/unit:", m->unit);
|
const char *sl = strjoina(m->manager->state_dir, "/unit:", m->unit);
|
||||||
(void) unlink(sl);
|
(void) unlink(sl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,7 +438,7 @@ static int machine_start_scope(
|
|||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
r = bus_message_new_method_call(
|
r = bus_message_new_method_call(
|
||||||
machine->manager->bus,
|
machine->manager->api_bus,
|
||||||
&m,
|
&m,
|
||||||
bus_systemd_mgr,
|
bus_systemd_mgr,
|
||||||
"StartTransientUnit");
|
"StartTransientUnit");
|
||||||
@ -920,7 +920,7 @@ int machine_start_getty(Machine *m, const char *ptmx_name, sd_bus_error *error)
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to create DBus to machine: %m");
|
return log_debug_errno(r, "Failed to create DBus to machine: %m");
|
||||||
|
|
||||||
container_bus = allocated_bus ?: m->manager->bus;
|
container_bus = allocated_bus ?: m->manager->system_bus;
|
||||||
getty = strjoina("container-getty@", p, ".service");
|
getty = strjoina("container-getty@", p, ".service");
|
||||||
|
|
||||||
r = bus_call_method(container_bus, bus_systemd_mgr, "StartUnit", error, /* ret_reply = */ NULL, "ss", getty, "replace");
|
r = bus_call_method(container_bus, bus_systemd_mgr, "StartUnit", error, /* ret_reply = */ NULL, "ss", getty, "replace");
|
||||||
@ -966,7 +966,7 @@ int machine_start_shell(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to create DBus to machine: %m");
|
return log_debug_errno(r, "Failed to create DBus to machine: %m");
|
||||||
|
|
||||||
container_bus = allocated_bus ?: m->manager->bus;
|
container_bus = allocated_bus ?: m->manager->system_bus;
|
||||||
r = bus_message_new_method_call(container_bus, &tm, bus_systemd_mgr, "StartTransientUnit");
|
r = bus_message_new_method_call(container_bus, &tm, bus_systemd_mgr, "StartTransientUnit");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@ -104,6 +104,7 @@ static const char* arg_format = NULL;
|
|||||||
static const char *arg_uid = NULL;
|
static const char *arg_uid = NULL;
|
||||||
static char **arg_setenv = NULL;
|
static char **arg_setenv = NULL;
|
||||||
static unsigned arg_max_addresses = 1;
|
static unsigned arg_max_addresses = 1;
|
||||||
|
static RuntimeScope arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
|
||||||
|
|
||||||
STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep);
|
STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep);
|
||||||
STATIC_DESTRUCTOR_REGISTER(arg_setenv, strv_freep);
|
STATIC_DESTRUCTOR_REGISTER(arg_setenv, strv_freep);
|
||||||
@ -2099,6 +2100,8 @@ static int help(int argc, char *argv[], void *userdata) {
|
|||||||
" --no-ask-password Do not ask for system passwords\n"
|
" --no-ask-password Do not ask for system passwords\n"
|
||||||
" -H --host=[USER@]HOST Operate on remote host\n"
|
" -H --host=[USER@]HOST Operate on remote host\n"
|
||||||
" -M --machine=CONTAINER Operate on local container\n"
|
" -M --machine=CONTAINER Operate on local container\n"
|
||||||
|
" --system Connect to system machine manager\n"
|
||||||
|
" --user Connect to user machine manager\n"
|
||||||
" -p --property=NAME Show only properties by this name\n"
|
" -p --property=NAME Show only properties by this name\n"
|
||||||
" --value When showing properties, only print the value\n"
|
" --value When showing properties, only print the value\n"
|
||||||
" -P NAME Equivalent to --value --property=NAME\n"
|
" -P NAME Equivalent to --value --property=NAME\n"
|
||||||
@ -2152,6 +2155,8 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
ARG_FORMAT,
|
ARG_FORMAT,
|
||||||
ARG_UID,
|
ARG_UID,
|
||||||
ARG_MAX_ADDRESSES,
|
ARG_MAX_ADDRESSES,
|
||||||
|
ARG_SYSTEM,
|
||||||
|
ARG_USER,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct option options[] = {
|
static const struct option options[] = {
|
||||||
@ -2181,6 +2186,8 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
{ "uid", required_argument, NULL, ARG_UID },
|
{ "uid", required_argument, NULL, ARG_UID },
|
||||||
{ "setenv", required_argument, NULL, 'E' },
|
{ "setenv", required_argument, NULL, 'E' },
|
||||||
{ "max-addresses", required_argument, NULL, ARG_MAX_ADDRESSES },
|
{ "max-addresses", required_argument, NULL, ARG_MAX_ADDRESSES },
|
||||||
|
{ "user", no_argument, NULL, ARG_USER },
|
||||||
|
{ "system", no_argument, NULL, ARG_SYSTEM },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2404,6 +2411,14 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
"Invalid number of addresses: %s", optarg);
|
"Invalid number of addresses: %s", optarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ARG_USER:
|
||||||
|
arg_runtime_scope = RUNTIME_SCOPE_USER;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ARG_SYSTEM:
|
||||||
|
arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
|
||||||
|
break;
|
||||||
|
|
||||||
case '?':
|
case '?':
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@ -2488,9 +2503,9 @@ static int run(int argc, char *argv[]) {
|
|||||||
"list-transfers", "cancel-transfer"))
|
"list-transfers", "cancel-transfer"))
|
||||||
return chainload_importctl(argc, argv);
|
return chainload_importctl(argc, argv);
|
||||||
|
|
||||||
r = bus_connect_transport(arg_transport, arg_host, RUNTIME_SCOPE_SYSTEM, &bus);
|
r = bus_connect_transport(arg_transport, arg_host, arg_runtime_scope, &bus);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return bus_log_connect_error(r, arg_transport, RUNTIME_SCOPE_SYSTEM);
|
return bus_log_connect_error(r, arg_transport, arg_runtime_scope);
|
||||||
|
|
||||||
(void) sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
|
(void) sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
|
||||||
|
|
||||||
|
|||||||
@ -278,6 +278,7 @@ static int machine_add_from_params(
|
|||||||
return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Only root may register machines for other users");
|
return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Only root may register machines for other users");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
const char *details[] = {
|
const char *details[] = {
|
||||||
"name", name,
|
"name", name,
|
||||||
"class", machine_class_to_string(c),
|
"class", machine_class_to_string(c),
|
||||||
@ -294,6 +295,7 @@ static int machine_add_from_params(
|
|||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return 0; /* Will call us back */
|
return 0; /* Will call us back */
|
||||||
|
}
|
||||||
|
|
||||||
r = manager_add_machine(manager, name, &m);
|
r = manager_add_machine(manager, name, &m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -697,7 +699,18 @@ static int method_register_machine(sd_bus_message *message, void *userdata, sd_b
|
|||||||
if (r == 0)
|
if (r == 0)
|
||||||
return 1; /* Will call us back */
|
return 1; /* Will call us back */
|
||||||
|
|
||||||
|
switch (manager->runtime_scope) {
|
||||||
|
case RUNTIME_SCOPE_USER:
|
||||||
|
r = cg_pidref_get_user_unit_full(&m->leader, &m->unit, &m->subgroup);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RUNTIME_SCOPE_SYSTEM:
|
||||||
r = cg_pidref_get_unit_full(&m->leader, &m->unit, &m->subgroup);
|
r = cg_pidref_get_unit_full(&m->leader, &m->unit, &m->subgroup);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert_not_reached();
|
||||||
|
}
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
r = sd_bus_error_set_errnof(error, r,
|
r = sd_bus_error_set_errnof(error, r,
|
||||||
"Failed to determine unit of process "PID_FMT" : %m",
|
"Failed to determine unit of process "PID_FMT" : %m",
|
||||||
@ -983,6 +996,7 @@ static int method_clean_pool(sd_bus_message *message, void *userdata, sd_bus_err
|
|||||||
else
|
else
|
||||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mode '%s'.", mm);
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mode '%s'.", mm);
|
||||||
|
|
||||||
|
if (m->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
const char *details[] = {
|
const char *details[] = {
|
||||||
"verb", "clean_pool",
|
"verb", "clean_pool",
|
||||||
"mode", mm,
|
"mode", mm,
|
||||||
@ -999,6 +1013,7 @@ static int method_clean_pool(sd_bus_message *message, void *userdata, sd_bus_err
|
|||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return 1; /* Will call us back */
|
return 1; /* Will call us back */
|
||||||
|
}
|
||||||
|
|
||||||
r = image_clean_pool_operation(m, mode, &operation);
|
r = image_clean_pool_operation(m, mode, &operation);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -1022,6 +1037,7 @@ static int method_set_pool_limit(sd_bus_message *message, void *userdata, sd_bus
|
|||||||
if (!FILE_SIZE_VALID_OR_INFINITY(limit))
|
if (!FILE_SIZE_VALID_OR_INFINITY(limit))
|
||||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range");
|
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range");
|
||||||
|
|
||||||
|
if (m->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||||
const char *details[] = {
|
const char *details[] = {
|
||||||
"verb", "set_pool_limit",
|
"verb", "set_pool_limit",
|
||||||
NULL
|
NULL
|
||||||
@ -1037,13 +1053,14 @@ static int method_set_pool_limit(sd_bus_message *message, void *userdata, sd_bus
|
|||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return 1; /* Will call us back */
|
return 1; /* Will call us back */
|
||||||
|
}
|
||||||
|
|
||||||
/* Set up the machine directory if necessary */
|
/* Set up the machine directory if necessary */
|
||||||
r = setup_machine_directory(error, /* use_btrfs_subvol= */ true, /* use_btrfs_quota= */ true);
|
r = setup_machine_directory(error, /* use_btrfs_subvol= */ true, /* use_btrfs_quota= */ true);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = image_set_pool_limit(IMAGE_MACHINE, limit);
|
r = image_set_pool_limit(m->runtime_scope, IMAGE_MACHINE, limit);
|
||||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
||||||
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
|
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -1534,7 +1551,7 @@ int manager_unref_unit(
|
|||||||
assert(m);
|
assert(m);
|
||||||
assert(unit);
|
assert(unit);
|
||||||
|
|
||||||
return bus_call_method(m->bus, bus_systemd_mgr, "UnrefUnit", error, NULL, "s", unit);
|
return bus_call_method(m->api_bus, bus_systemd_mgr, "UnrefUnit", error, NULL, "s", unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
|
int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
|
||||||
@ -1544,7 +1561,7 @@ int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, c
|
|||||||
assert(manager);
|
assert(manager);
|
||||||
assert(unit);
|
assert(unit);
|
||||||
|
|
||||||
r = bus_call_method(manager->bus, bus_systemd_mgr, "StopUnit", error, &reply, "ss", unit, "fail");
|
r = bus_call_method(manager->api_bus, bus_systemd_mgr, "StopUnit", error, &reply, "ss", unit, "fail");
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
if (sd_bus_error_has_names(error, BUS_ERROR_NO_SUCH_UNIT,
|
if (sd_bus_error_has_names(error, BUS_ERROR_NO_SUCH_UNIT,
|
||||||
BUS_ERROR_LOAD_FAILED)) {
|
BUS_ERROR_LOAD_FAILED)) {
|
||||||
@ -1582,9 +1599,9 @@ int manager_kill_unit(Manager *manager, const char *unit, const char *subgroup,
|
|||||||
assert(unit);
|
assert(unit);
|
||||||
|
|
||||||
if (empty_or_root(subgroup))
|
if (empty_or_root(subgroup))
|
||||||
return bus_call_method(manager->bus, bus_systemd_mgr, "KillUnit", reterr_error, NULL, "ssi", unit, "all", signo);
|
return bus_call_method(manager->api_bus, bus_systemd_mgr, "KillUnit", reterr_error, NULL, "ssi", unit, "all", signo);
|
||||||
|
|
||||||
return bus_call_method(manager->bus, bus_systemd_mgr, "KillUnitSubgroup", reterr_error, NULL, "sssi", unit, "cgroup", subgroup, signo);
|
return bus_call_method(manager->api_bus, bus_systemd_mgr, "KillUnitSubgroup", reterr_error, NULL, "sssi", unit, "cgroup", subgroup, signo);
|
||||||
}
|
}
|
||||||
|
|
||||||
int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *reterr_error) {
|
int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *reterr_error) {
|
||||||
@ -1602,7 +1619,7 @@ int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *ret
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
r = sd_bus_get_property(
|
r = sd_bus_get_property(
|
||||||
manager->bus,
|
manager->api_bus,
|
||||||
"org.freedesktop.systemd1",
|
"org.freedesktop.systemd1",
|
||||||
path,
|
path,
|
||||||
"org.freedesktop.systemd1.Unit",
|
"org.freedesktop.systemd1.Unit",
|
||||||
@ -1638,7 +1655,7 @@ int manager_job_is_active(Manager *manager, const char *path, sd_bus_error *rete
|
|||||||
assert(path);
|
assert(path);
|
||||||
|
|
||||||
r = sd_bus_get_property(
|
r = sd_bus_get_property(
|
||||||
manager->bus,
|
manager->api_bus,
|
||||||
"org.freedesktop.systemd1",
|
"org.freedesktop.systemd1",
|
||||||
path,
|
path,
|
||||||
"org.freedesktop.systemd1.Job",
|
"org.freedesktop.systemd1.Job",
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
#include "machine-varlink.h"
|
#include "machine-varlink.h"
|
||||||
#include "machined.h"
|
#include "machined.h"
|
||||||
#include "machined-varlink.h"
|
#include "machined-varlink.h"
|
||||||
|
#include "path-lookup.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "user-util.h"
|
#include "user-util.h"
|
||||||
@ -614,14 +615,15 @@ static int vl_method_open_root_directory(sd_varlink *link, sd_json_variant *para
|
|||||||
return lookup_machine_and_call_method(link, parameters, flags, userdata, vl_method_open_root_directory_internal);
|
return lookup_machine_and_call_method(link, parameters, flags, userdata, vl_method_open_root_directory_internal);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int list_image_one_and_maybe_read_metadata(sd_varlink *link, Image *image, bool more, AcquireMetadata am) {
|
static int list_image_one_and_maybe_read_metadata(Manager *m, sd_varlink *link, Image *image, bool more, AcquireMetadata am) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
assert(m);
|
||||||
assert(link);
|
assert(link);
|
||||||
assert(image);
|
assert(image);
|
||||||
|
|
||||||
if (should_acquire_metadata(am) && !image->metadata_valid) {
|
if (should_acquire_metadata(am) && !image->metadata_valid) {
|
||||||
r = image_read_metadata(image, &image_policy_container);
|
r = image_read_metadata(image, &image_policy_container, m->runtime_scope);
|
||||||
if (r < 0 && am != ACQUIRE_METADATA_GRACEFUL)
|
if (r < 0 && am != ACQUIRE_METADATA_GRACEFUL)
|
||||||
return log_debug_errno(r, "Failed to read image metadata: %m");
|
return log_debug_errno(r, "Failed to read image metadata: %m");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -697,7 +699,7 @@ static int vl_method_list_images(sd_varlink *link, sd_json_variant *parameters,
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to find image: %m");
|
return log_debug_errno(r, "Failed to find image: %m");
|
||||||
|
|
||||||
return list_image_one_and_maybe_read_metadata(link, found, /* more = */ false, p.acquire_metadata);
|
return list_image_one_and_maybe_read_metadata(m, link, found, /* more = */ false, p.acquire_metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
|
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
|
||||||
@ -711,7 +713,7 @@ static int vl_method_list_images(sd_varlink *link, sd_json_variant *parameters,
|
|||||||
Image *image, *previous = NULL;
|
Image *image, *previous = NULL;
|
||||||
HASHMAP_FOREACH(image, images) {
|
HASHMAP_FOREACH(image, images) {
|
||||||
if (previous) {
|
if (previous) {
|
||||||
r = list_image_one_and_maybe_read_metadata(link, previous, /* more = */ true, p.acquire_metadata);
|
r = list_image_one_and_maybe_read_metadata(m, link, previous, /* more = */ true, p.acquire_metadata);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -720,7 +722,7 @@ static int vl_method_list_images(sd_varlink *link, sd_json_variant *parameters,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (previous)
|
if (previous)
|
||||||
return list_image_one_and_maybe_read_metadata(link, previous, /* more = */ false, p.acquire_metadata);
|
return list_image_one_and_maybe_read_metadata(m, link, previous, /* more = */ false, p.acquire_metadata);
|
||||||
|
|
||||||
return sd_varlink_error(link, VARLINK_ERROR_MACHINE_IMAGE_NO_SUCH_IMAGE, NULL);
|
return sd_varlink_error(link, VARLINK_ERROR_MACHINE_IMAGE_NO_SUCH_IMAGE, NULL);
|
||||||
}
|
}
|
||||||
@ -733,6 +735,8 @@ static int manager_varlink_init_userdb(Manager *m) {
|
|||||||
|
|
||||||
if (m->varlink_userdb_server)
|
if (m->varlink_userdb_server)
|
||||||
return 0;
|
return 0;
|
||||||
|
if (m->runtime_scope != RUNTIME_SCOPE_SYSTEM) /* no userdb in per-user mode! */
|
||||||
|
return 0;
|
||||||
|
|
||||||
r = varlink_server_new(&s, SD_VARLINK_SERVER_ACCOUNT_UID|SD_VARLINK_SERVER_INHERIT_USERDATA, m);
|
r = varlink_server_new(&s, SD_VARLINK_SERVER_ACCOUNT_UID|SD_VARLINK_SERVER_INHERIT_USERDATA, m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -817,11 +821,20 @@ static int manager_varlink_init_machine(Manager *m) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to bind to passed Varlink sockets: %m");
|
return log_error_errno(r, "Failed to bind to passed Varlink sockets: %m");
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
r = sd_varlink_server_listen_address(s, "/run/systemd/machine/io.systemd.Machine", 0666 | SD_VARLINK_SERVER_MODE_MKDIR_0755);
|
_cleanup_free_ char *socket_path = NULL;
|
||||||
|
r = runtime_directory_generic(m->runtime_scope, "systemd/machine/io.systemd.Machine", &socket_path);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to determine socket path: %m");
|
||||||
|
|
||||||
|
r = sd_varlink_server_listen_address(s, socket_path, runtime_scope_to_socket_mode(m->runtime_scope) | SD_VARLINK_SERVER_MODE_MKDIR_0755);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to bind to io.systemd.Machine varlink socket: %m");
|
return log_error_errno(r, "Failed to bind to io.systemd.Machine varlink socket: %m");
|
||||||
|
|
||||||
r = sd_varlink_server_listen_address(s, "/run/systemd/machine/io.systemd.MachineImage", 0666);
|
socket_path = mfree(socket_path);
|
||||||
|
r = runtime_directory_generic(m->runtime_scope, "systemd/machine/io.systemd.MachineImage", &socket_path);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to determine socket path: %m");
|
||||||
|
r = sd_varlink_server_listen_address(s, socket_path, runtime_scope_to_socket_mode(m->runtime_scope));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to bind to io.systemd.MachineImage varlink socket: %m");
|
return log_error_errno(r, "Failed to bind to io.systemd.MachineImage varlink socket: %m");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
#include "main-func.h"
|
#include "main-func.h"
|
||||||
#include "mkdir-label.h"
|
#include "mkdir-label.h"
|
||||||
#include "operation.h"
|
#include "operation.h"
|
||||||
|
#include "path-lookup.h"
|
||||||
#include "service-util.h"
|
#include "service-util.h"
|
||||||
#include "signal-util.h"
|
#include "signal-util.h"
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
@ -38,7 +39,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref);
|
|||||||
|
|
||||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(machine_hash_ops, char, string_hash_func, string_compare_func, Machine, machine_free);
|
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(machine_hash_ops, char, string_hash_func, string_compare_func, Machine, machine_free);
|
||||||
|
|
||||||
static int manager_new(Manager **ret) {
|
static int manager_new(RuntimeScope scope, Manager **ret) {
|
||||||
_cleanup_(manager_unrefp) Manager *m = NULL;
|
_cleanup_(manager_unrefp) Manager *m = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -49,9 +50,13 @@ static int manager_new(Manager **ret) {
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
*m = (Manager) {
|
*m = (Manager) {
|
||||||
.runtime_scope = RUNTIME_SCOPE_SYSTEM,
|
.runtime_scope = scope,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
r = runtime_directory_generic(scope, "systemd/machines", &m->state_dir);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
m->machines = hashmap_new(&machine_hash_ops);
|
m->machines = hashmap_new(&machine_hash_ops);
|
||||||
if (!m->machines)
|
if (!m->machines)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -105,9 +110,12 @@ static Manager* manager_unref(Manager *m) {
|
|||||||
|
|
||||||
manager_varlink_done(m);
|
manager_varlink_done(m);
|
||||||
|
|
||||||
sd_bus_flush_close_unref(m->bus);
|
sd_bus_flush_close_unref(m->api_bus);
|
||||||
|
sd_bus_flush_close_unref(m->system_bus);
|
||||||
sd_event_unref(m->event);
|
sd_event_unref(m->event);
|
||||||
|
|
||||||
|
free(m->state_dir);
|
||||||
|
|
||||||
return mfree(m);
|
return mfree(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,6 +126,8 @@ static int manager_add_host_machine(Manager *m) {
|
|||||||
Machine *t;
|
Machine *t;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
if (m->runtime_scope != RUNTIME_SCOPE_SYSTEM)
|
||||||
|
return 0;
|
||||||
if (m->host_machine)
|
if (m->host_machine)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -174,12 +184,12 @@ static int manager_enumerate_machines(Manager *m) {
|
|||||||
return r;
|
return r;
|
||||||
|
|
||||||
/* Read in machine data stored on disk */
|
/* Read in machine data stored on disk */
|
||||||
d = opendir("/run/systemd/machines");
|
d = opendir(m->state_dir);
|
||||||
if (!d) {
|
if (!d) {
|
||||||
if (errno == ENOENT)
|
if (errno == ENOENT)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return log_error_errno(errno, "Failed to open %s: %m", "/run/systemd/machines");
|
return log_error_errno(errno, "Failed to open '%s': %m", m->state_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
FOREACH_DIRENT(de, d, return -errno) {
|
FOREACH_DIRENT(de, d, return -errno) {
|
||||||
@ -214,26 +224,45 @@ static int manager_connect_bus(Manager *m) {
|
|||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
assert(!m->bus);
|
assert(!m->system_bus);
|
||||||
|
assert(!m->api_bus);
|
||||||
|
|
||||||
r = sd_bus_default_system(&m->bus);
|
r = sd_bus_default_system(&m->system_bus);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to connect to system bus: %m");
|
return log_error_errno(r, "Failed to connect to system bus: %m");
|
||||||
|
|
||||||
r = bus_add_implementation(m->bus, &manager_object, m);
|
r = sd_bus_attach_event(m->system_bus, m->event, 0);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to attach system bus to event loop: %m");
|
||||||
|
|
||||||
|
if (m->runtime_scope == RUNTIME_SCOPE_SYSTEM)
|
||||||
|
m->api_bus = sd_bus_ref(m->system_bus);
|
||||||
|
else {
|
||||||
|
assert(m->runtime_scope == RUNTIME_SCOPE_USER);
|
||||||
|
|
||||||
|
r = sd_bus_default_user(&m->api_bus);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to connect to user bus: %m");
|
||||||
|
|
||||||
|
r = sd_bus_attach_event(m->api_bus, m->event, 0);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to attach user bus to event loop: %m");
|
||||||
|
}
|
||||||
|
|
||||||
|
r = bus_add_implementation(m->api_bus, &manager_object, m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = bus_match_signal_async(m->bus, NULL, bus_systemd_mgr, "JobRemoved", match_job_removed, NULL, m);
|
r = bus_match_signal_async(m->api_bus, NULL, bus_systemd_mgr, "JobRemoved", match_job_removed, NULL, m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to add match for JobRemoved: %m");
|
return log_error_errno(r, "Failed to add match for JobRemoved: %m");
|
||||||
|
|
||||||
r = bus_match_signal_async(m->bus, NULL, bus_systemd_mgr, "UnitRemoved", match_unit_removed, NULL, m);
|
r = bus_match_signal_async(m->api_bus, NULL, bus_systemd_mgr, "UnitRemoved", match_unit_removed, NULL, m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to request match for UnitRemoved: %m");
|
return log_error_errno(r, "Failed to request match for UnitRemoved: %m");
|
||||||
|
|
||||||
r = sd_bus_match_signal_async(
|
r = sd_bus_match_signal_async(
|
||||||
m->bus,
|
m->api_bus,
|
||||||
NULL,
|
NULL,
|
||||||
"org.freedesktop.systemd1",
|
"org.freedesktop.systemd1",
|
||||||
NULL,
|
NULL,
|
||||||
@ -243,26 +272,22 @@ static int manager_connect_bus(Manager *m) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to request match for PropertiesChanged: %m");
|
return log_error_errno(r, "Failed to request match for PropertiesChanged: %m");
|
||||||
|
|
||||||
r = bus_match_signal_async(m->bus, NULL, bus_systemd_mgr, "Reloading", match_reloading, NULL, m);
|
r = bus_match_signal_async(m->api_bus, NULL, bus_systemd_mgr, "Reloading", match_reloading, NULL, m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to request match for Reloading: %m");
|
return log_error_errno(r, "Failed to request match for Reloading: %m");
|
||||||
|
|
||||||
r = bus_call_method_async(m->bus, NULL, bus_systemd_mgr, "Subscribe", NULL, NULL, NULL);
|
r = bus_call_method_async(m->api_bus, NULL, bus_systemd_mgr, "Subscribe", NULL, NULL, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to enable subscription: %m");
|
return log_error_errno(r, "Failed to enable subscription: %m");
|
||||||
|
|
||||||
r = bus_log_control_api_register(m->bus);
|
r = bus_log_control_api_register(m->api_bus);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.machine1", 0, NULL, NULL);
|
r = sd_bus_request_name_async(m->api_bus, NULL, "org.freedesktop.machine1", 0, NULL, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to request name: %m");
|
return log_error_errno(r, "Failed to request name: %m");
|
||||||
|
|
||||||
r = sd_bus_attach_event(m->bus, m->event, 0);
|
|
||||||
if (r < 0)
|
|
||||||
return log_error_errno(r, "Failed to attach bus to event loop: %m");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,6 +340,7 @@ static bool check_idle(void *userdata) {
|
|||||||
|
|
||||||
static int run(int argc, char *argv[]) {
|
static int run(int argc, char *argv[]) {
|
||||||
_cleanup_(manager_unrefp) Manager *m = NULL;
|
_cleanup_(manager_unrefp) Manager *m = NULL;
|
||||||
|
RuntimeScope scope = RUNTIME_SCOPE_SYSTEM;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
log_set_facility(LOG_AUTH);
|
log_set_facility(LOG_AUTH);
|
||||||
@ -324,6 +350,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
"Manage registrations of local VMs and containers.",
|
"Manage registrations of local VMs and containers.",
|
||||||
BUS_IMPLEMENTATIONS(&manager_object,
|
BUS_IMPLEMENTATIONS(&manager_object,
|
||||||
&log_control_object),
|
&log_control_object),
|
||||||
|
&scope,
|
||||||
argc, argv);
|
argc, argv);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
@ -333,11 +360,12 @@ static int run(int argc, char *argv[]) {
|
|||||||
/* Always create the directories people can create inotify watches in. Note that some applications might check
|
/* Always create the directories people can create inotify watches in. Note that some applications might check
|
||||||
* for the existence of /run/systemd/machines/ to determine whether machined is available, so please always
|
* for the existence of /run/systemd/machines/ to determine whether machined is available, so please always
|
||||||
* make sure this check stays in. */
|
* make sure this check stays in. */
|
||||||
|
if (scope == RUNTIME_SCOPE_SYSTEM)
|
||||||
(void) mkdir_label("/run/systemd/machines", 0755);
|
(void) mkdir_label("/run/systemd/machines", 0755);
|
||||||
|
|
||||||
assert_se(sigprocmask_many(SIG_BLOCK, /* ret_old_mask= */ NULL, SIGCHLD) >= 0);
|
assert_se(sigprocmask_many(SIG_BLOCK, /* ret_old_mask= */ NULL, SIGCHLD) >= 0);
|
||||||
|
|
||||||
r = manager_new(&m);
|
r = manager_new(scope, &m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to allocate manager object: %m");
|
return log_error_errno(r, "Failed to allocate manager object: %m");
|
||||||
|
|
||||||
@ -351,7 +379,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
|
|
||||||
r = bus_event_loop_with_idle(
|
r = bus_event_loop_with_idle(
|
||||||
m->event,
|
m->event,
|
||||||
m->bus,
|
m->api_bus,
|
||||||
"org.freedesktop.machine1",
|
"org.freedesktop.machine1",
|
||||||
DEFAULT_EXIT_USEC,
|
DEFAULT_EXIT_USEC,
|
||||||
check_idle, m);
|
check_idle, m);
|
||||||
|
|||||||
@ -7,7 +7,8 @@
|
|||||||
|
|
||||||
typedef struct Manager {
|
typedef struct Manager {
|
||||||
sd_event *event;
|
sd_event *event;
|
||||||
sd_bus *bus;
|
sd_bus *api_bus; /* this is where we offer our services */
|
||||||
|
sd_bus *system_bus; /* this is where we talk to system services on, for example PK or so */
|
||||||
|
|
||||||
Hashmap *machines;
|
Hashmap *machines;
|
||||||
Hashmap *machines_by_unit; /* This hashmap only tracks machines where a system-level encapsulates
|
Hashmap *machines_by_unit; /* This hashmap only tracks machines where a system-level encapsulates
|
||||||
@ -32,7 +33,8 @@ typedef struct Manager {
|
|||||||
sd_varlink_server *varlink_userdb_server;
|
sd_varlink_server *varlink_userdb_server;
|
||||||
sd_varlink_server *varlink_machine_server;
|
sd_varlink_server *varlink_machine_server;
|
||||||
|
|
||||||
RuntimeScope runtime_scope; /* for now: always RUNTIME_SCOPE_SYSTEM */
|
RuntimeScope runtime_scope;
|
||||||
|
char *state_dir;
|
||||||
} Manager;
|
} Manager;
|
||||||
|
|
||||||
int manager_add_machine(Manager *m, const char *name, Machine **ret);
|
int manager_add_machine(Manager *m, const char *name, Machine **ret);
|
||||||
|
|||||||
@ -49,5 +49,8 @@ install_data('org.freedesktop.machine1.conf',
|
|||||||
install_dir : dbuspolicydir)
|
install_dir : dbuspolicydir)
|
||||||
install_data('org.freedesktop.machine1.service',
|
install_data('org.freedesktop.machine1.service',
|
||||||
install_dir : dbussystemservicedir)
|
install_dir : dbussystemservicedir)
|
||||||
|
install_data('org.freedesktop.machine1.service-for-session',
|
||||||
|
install_dir : dbussessionservicedir,
|
||||||
|
rename : 'org.freedesktop.machine1.service')
|
||||||
install_data('org.freedesktop.machine1.policy',
|
install_data('org.freedesktop.machine1.policy',
|
||||||
install_dir : polkitpolicydir)
|
install_dir : polkitpolicydir)
|
||||||
|
|||||||
13
src/machine/org.freedesktop.machine1.service-for-session
Normal file
13
src/machine/org.freedesktop.machine1.service-for-session
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
#
|
||||||
|
# This file is part of systemd.
|
||||||
|
#
|
||||||
|
# systemd is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU Lesser General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
[D-BUS Service]
|
||||||
|
Name=org.freedesktop.machine1
|
||||||
|
Exec=/bin/false
|
||||||
|
SystemdService=dbus-org.freedesktop.machine1.service
|
||||||
@ -5,7 +5,7 @@ executables += [
|
|||||||
'name' : 'systemd-mount',
|
'name' : 'systemd-mount',
|
||||||
'public' : true,
|
'public' : true,
|
||||||
'sources' : files('mount-tool.c'),
|
'sources' : files('mount-tool.c'),
|
||||||
'dependencies' : libmount,
|
'dependencies' : libmount_cflags,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -860,14 +860,14 @@ static int find_mount_points_by_source(const char *what, char ***ret) {
|
|||||||
struct libmnt_fs *fs;
|
struct libmnt_fs *fs;
|
||||||
const char *source, *target;
|
const char *source, *target;
|
||||||
|
|
||||||
r = mnt_table_next_fs(table, iter, &fs);
|
r = sym_mnt_table_next_fs(table, iter, &fs);
|
||||||
if (r == 1)
|
if (r == 1)
|
||||||
break;
|
break;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
|
return log_error_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
|
||||||
|
|
||||||
source = mnt_fs_get_source(fs);
|
source = sym_mnt_fs_get_source(fs);
|
||||||
target = mnt_fs_get_target(fs);
|
target = sym_mnt_fs_get_target(fs);
|
||||||
if (!source || !target)
|
if (!source || !target)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@ -29,6 +29,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
r = service_parse_argv("systemd-networkd.service",
|
r = service_parse_argv("systemd-networkd.service",
|
||||||
"Manage and configure network devices, create virtual network devices",
|
"Manage and configure network devices, create virtual network devices",
|
||||||
BUS_IMPLEMENTATIONS(&manager_object, &log_control_object),
|
BUS_IMPLEMENTATIONS(&manager_object, &log_control_object),
|
||||||
|
/* runtime_scope= */ NULL,
|
||||||
argc, argv);
|
argc, argv);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@ -294,6 +294,7 @@ int register_machine(
|
|||||||
return 0;
|
return 0;
|
||||||
if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD))
|
if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD))
|
||||||
return log_error_errno(r, "Failed to register machine: %s", bus_error_message(&error, r));
|
return log_error_errno(r, "Failed to register machine: %s", bus_error_message(&error, r));
|
||||||
|
sd_bus_error_free(&error);
|
||||||
if (FLAGS_SET(flags, REGISTER_MACHINE_KEEP_UNIT)) {
|
if (FLAGS_SET(flags, REGISTER_MACHINE_KEEP_UNIT)) {
|
||||||
r = bus_call_method(
|
r = bus_call_method(
|
||||||
bus,
|
bus,
|
||||||
|
|||||||
@ -6055,6 +6055,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
/* We take an exclusive lock on this image, since it's our private, ephemeral copy
|
/* We take an exclusive lock on this image, since it's our private, ephemeral copy
|
||||||
* only owned by us and no one else. */
|
* only owned by us and no one else. */
|
||||||
r = image_path_lock(
|
r = image_path_lock(
|
||||||
|
arg_privileged ? RUNTIME_SCOPE_SYSTEM : RUNTIME_SCOPE_USER,
|
||||||
np,
|
np,
|
||||||
LOCK_EX|LOCK_NB,
|
LOCK_EX|LOCK_NB,
|
||||||
arg_privileged ? &tree_global_lock : NULL,
|
arg_privileged ? &tree_global_lock : NULL,
|
||||||
@ -6091,6 +6092,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
r = image_path_lock(
|
r = image_path_lock(
|
||||||
|
arg_privileged ? RUNTIME_SCOPE_SYSTEM : RUNTIME_SCOPE_USER,
|
||||||
arg_directory,
|
arg_directory,
|
||||||
(arg_read_only ? LOCK_SH : LOCK_EX) | LOCK_NB,
|
(arg_read_only ? LOCK_SH : LOCK_EX) | LOCK_NB,
|
||||||
arg_privileged ? &tree_global_lock : NULL,
|
arg_privileged ? &tree_global_lock : NULL,
|
||||||
@ -6218,6 +6220,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
|
|
||||||
/* Always take an exclusive lock on our own ephemeral copy. */
|
/* Always take an exclusive lock on our own ephemeral copy. */
|
||||||
r = image_path_lock(
|
r = image_path_lock(
|
||||||
|
arg_privileged ? RUNTIME_SCOPE_SYSTEM : RUNTIME_SCOPE_USER,
|
||||||
np,
|
np,
|
||||||
LOCK_EX|LOCK_NB,
|
LOCK_EX|LOCK_NB,
|
||||||
arg_privileged ? &tree_global_lock : NULL,
|
arg_privileged ? &tree_global_lock : NULL,
|
||||||
@ -6245,6 +6248,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
remove_image = true;
|
remove_image = true;
|
||||||
} else {
|
} else {
|
||||||
r = image_path_lock(
|
r = image_path_lock(
|
||||||
|
arg_privileged ? RUNTIME_SCOPE_SYSTEM : RUNTIME_SCOPE_USER,
|
||||||
arg_image,
|
arg_image,
|
||||||
(arg_read_only ? LOCK_SH : LOCK_EX) | LOCK_NB,
|
(arg_read_only ? LOCK_SH : LOCK_EX) | LOCK_NB,
|
||||||
arg_privileged ? &tree_global_lock : NULL,
|
arg_privileged ? &tree_global_lock : NULL,
|
||||||
|
|||||||
@ -61,7 +61,7 @@ int bus_image_common_get_os_release(
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!image->metadata_valid) {
|
if (!image->metadata_valid) {
|
||||||
r = image_read_metadata(image, &image_policy_service);
|
r = image_read_metadata(image, &image_policy_service, m->runtime_scope);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m");
|
return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m");
|
||||||
}
|
}
|
||||||
@ -539,7 +539,7 @@ int bus_image_common_remove(
|
|||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
|
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
|
||||||
|
|
||||||
r = image_remove(image);
|
r = image_remove(image, m->runtime_scope);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
(void) write(errno_pipe_fd[1], &r, sizeof(r));
|
(void) write(errno_pipe_fd[1], &r, sizeof(r));
|
||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
@ -801,7 +801,7 @@ int bus_image_common_mark_read_only(
|
|||||||
if (r == 0)
|
if (r == 0)
|
||||||
return 1; /* Will call us back */
|
return 1; /* Will call us back */
|
||||||
|
|
||||||
r = image_read_only(image, read_only);
|
r = image_read_only(image, read_only, m->runtime_scope);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -133,6 +133,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
"Manage registrations of portable images.",
|
"Manage registrations of portable images.",
|
||||||
BUS_IMPLEMENTATIONS(&manager_object,
|
BUS_IMPLEMENTATIONS(&manager_object,
|
||||||
&log_control_object),
|
&log_control_object),
|
||||||
|
/* runtime_scope= */ NULL,
|
||||||
argc, argv);
|
argc, argv);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@ -4,6 +4,6 @@ executables += [
|
|||||||
libexec_template + {
|
libexec_template + {
|
||||||
'name' : 'systemd-remount-fs',
|
'name' : 'systemd-remount-fs',
|
||||||
'sources' : files('remount-fs.c'),
|
'sources' : files('remount-fs.c'),
|
||||||
'dependencies' : libmount,
|
'dependencies' : libmount_cflags,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
@ -90,13 +90,13 @@ static int remount_by_fstab(Hashmap **ret_pids) {
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
struct libmnt_fs *fs;
|
struct libmnt_fs *fs;
|
||||||
|
|
||||||
r = mnt_table_next_fs(table, iter, &fs);
|
r = sym_mnt_table_next_fs(table, iter, &fs);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to get next entry from fstab: %m");
|
return log_error_errno(r, "Failed to get next entry from fstab: %m");
|
||||||
if (r > 0) /* EOF */
|
if (r > 0) /* EOF */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
const char *target = mnt_fs_get_target(fs);
|
const char *target = sym_mnt_fs_get_target(fs);
|
||||||
if (!target)
|
if (!target)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@ -30,6 +30,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
"Provide name resolution with caching using DNS, mDNS, LLMNR.",
|
"Provide name resolution with caching using DNS, mDNS, LLMNR.",
|
||||||
BUS_IMPLEMENTATIONS(&manager_object,
|
BUS_IMPLEMENTATIONS(&manager_object,
|
||||||
&log_control_object),
|
&log_control_object),
|
||||||
|
/* runtime_scope= */ NULL,
|
||||||
argc, argv);
|
argc, argv);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
#include "chase.h"
|
#include "chase.h"
|
||||||
#include "chattr-util.h"
|
#include "chattr-util.h"
|
||||||
#include "copy.h"
|
#include "copy.h"
|
||||||
|
#include "devnum-util.h"
|
||||||
#include "dirent-util.h"
|
#include "dirent-util.h"
|
||||||
#include "discover-image.h"
|
#include "discover-image.h"
|
||||||
#include "dissect-image.h"
|
#include "dissect-image.h"
|
||||||
@ -37,6 +38,7 @@
|
|||||||
#include "mkdir.h"
|
#include "mkdir.h"
|
||||||
#include "nulstr-util.h"
|
#include "nulstr-util.h"
|
||||||
#include "os-util.h"
|
#include "os-util.h"
|
||||||
|
#include "path-lookup.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "rm-rf.h"
|
#include "rm-rf.h"
|
||||||
#include "runtime-scope.h"
|
#include "runtime-scope.h"
|
||||||
@ -119,6 +121,15 @@ static const char *const image_root_runtime_table[_IMAGE_CLASS_MAX] = {
|
|||||||
|
|
||||||
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(image_root_runtime, ImageClass);
|
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(image_root_runtime, ImageClass);
|
||||||
|
|
||||||
|
static const char *const image_dirname_table[_IMAGE_CLASS_MAX] = {
|
||||||
|
[IMAGE_MACHINE] = "machines",
|
||||||
|
[IMAGE_PORTABLE] = "portables",
|
||||||
|
[IMAGE_SYSEXT] = "extensions",
|
||||||
|
[IMAGE_CONFEXT] = "confexts",
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(image_dirname, ImageClass);
|
||||||
|
|
||||||
static Image* image_free(Image *i) {
|
static Image* image_free(Image *i) {
|
||||||
assert(i);
|
assert(i);
|
||||||
|
|
||||||
@ -138,7 +149,7 @@ DEFINE_TRIVIAL_REF_UNREF_FUNC(Image, image, image_free);
|
|||||||
DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(image_hash_ops, char, string_hash_func, string_compare_func,
|
DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(image_hash_ops, char, string_hash_func, string_compare_func,
|
||||||
Image, image_unref);
|
Image, image_unref);
|
||||||
|
|
||||||
static char** image_settings_path(Image *image) {
|
static char** image_settings_path(Image *image, RuntimeScope scope) {
|
||||||
_cleanup_strv_free_ char **l = NULL;
|
_cleanup_strv_free_ char **l = NULL;
|
||||||
_cleanup_free_ char *fn = NULL;
|
_cleanup_free_ char *fn = NULL;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
@ -146,7 +157,7 @@ static char** image_settings_path(Image *image) {
|
|||||||
|
|
||||||
assert(image);
|
assert(image);
|
||||||
|
|
||||||
l = new0(char*, 4);
|
l = new0(char*, 5);
|
||||||
if (!l)
|
if (!l)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -154,7 +165,41 @@ static char** image_settings_path(Image *image) {
|
|||||||
if (!fn)
|
if (!fn)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
FOREACH_STRING(s, "/etc/systemd/nspawn", "/run/systemd/nspawn") {
|
static const uint64_t system_locations[] = {
|
||||||
|
SD_PATH_SYSTEM_CONFIGURATION,
|
||||||
|
SD_PATH_SYSTEM_RUNTIME,
|
||||||
|
SD_PATH_SYSTEM_LIBRARY_PRIVATE,
|
||||||
|
UINT64_MAX
|
||||||
|
};
|
||||||
|
static const uint64_t user_locations[] = {
|
||||||
|
SD_PATH_USER_CONFIGURATION,
|
||||||
|
SD_PATH_USER_RUNTIME,
|
||||||
|
SD_PATH_USER_LIBRARY_PRIVATE,
|
||||||
|
UINT64_MAX
|
||||||
|
};
|
||||||
|
const uint64_t *locations;
|
||||||
|
|
||||||
|
switch (scope) {
|
||||||
|
case RUNTIME_SCOPE_SYSTEM:
|
||||||
|
locations = system_locations;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RUNTIME_SCOPE_USER:
|
||||||
|
locations = user_locations;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t k = 0; locations[k] != UINT64_MAX; k++) {
|
||||||
|
_cleanup_free_ char *s = NULL;
|
||||||
|
r = sd_path_lookup(locations[k], "systemd/nspawn", &s);
|
||||||
|
if (r == -ENXIO)
|
||||||
|
continue;
|
||||||
|
if (r < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
l[i] = path_join(s, fn);
|
l[i] = path_join(s, fn);
|
||||||
if (!l[i])
|
if (!l[i])
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1086,7 +1131,7 @@ int image_discover(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int image_remove(Image *i) {
|
int image_remove(Image *i, RuntimeScope scope) {
|
||||||
_cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT;
|
_cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT;
|
||||||
_cleanup_strv_free_ char **settings = NULL;
|
_cleanup_strv_free_ char **settings = NULL;
|
||||||
_cleanup_free_ char *roothash = NULL;
|
_cleanup_free_ char *roothash = NULL;
|
||||||
@ -1097,7 +1142,7 @@ int image_remove(Image *i) {
|
|||||||
if (image_is_vendor(i) || image_is_host(i))
|
if (image_is_vendor(i) || image_is_host(i))
|
||||||
return -EROFS;
|
return -EROFS;
|
||||||
|
|
||||||
settings = image_settings_path(i);
|
settings = image_settings_path(i, scope);
|
||||||
if (!settings)
|
if (!settings)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -1106,7 +1151,7 @@ int image_remove(Image *i) {
|
|||||||
return r;
|
return r;
|
||||||
|
|
||||||
/* Make sure we don't interfere with a running nspawn */
|
/* Make sure we don't interfere with a running nspawn */
|
||||||
r = image_path_lock(i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock);
|
r = image_path_lock(scope, i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -1192,7 +1237,7 @@ int image_rename(Image *i, const char *new_name, RuntimeScope scope) {
|
|||||||
if (image_is_vendor(i) || image_is_host(i))
|
if (image_is_vendor(i) || image_is_host(i))
|
||||||
return -EROFS;
|
return -EROFS;
|
||||||
|
|
||||||
settings = image_settings_path(i);
|
settings = image_settings_path(i, scope);
|
||||||
if (!settings)
|
if (!settings)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -1201,14 +1246,14 @@ int image_rename(Image *i, const char *new_name, RuntimeScope scope) {
|
|||||||
return r;
|
return r;
|
||||||
|
|
||||||
/* Make sure we don't interfere with a running nspawn */
|
/* Make sure we don't interfere with a running nspawn */
|
||||||
r = image_path_lock(i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock);
|
r = image_path_lock(scope, i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
/* Make sure nobody takes the new name, between the time we
|
/* Make sure nobody takes the new name, between the time we
|
||||||
* checked it is currently unused in all search paths, and the
|
* checked it is currently unused in all search paths, and the
|
||||||
* time we take possession of it */
|
* time we take possession of it */
|
||||||
r = image_name_lock(new_name, LOCK_EX|LOCK_NB, &name_lock);
|
r = image_name_lock(scope, new_name, LOCK_EX|LOCK_NB, &name_lock);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -1299,11 +1344,64 @@ static int clone_auxiliary_file(const char *path, const char *new_name, const ch
|
|||||||
return copy_file_atomic(path, rs, 0664, COPY_REFLINK);
|
return copy_file_atomic(path, rs, 0664, COPY_REFLINK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_pool_directory(
|
||||||
|
RuntimeScope scope,
|
||||||
|
ImageClass class,
|
||||||
|
const char *fname,
|
||||||
|
const char *suffix,
|
||||||
|
char **ret) {
|
||||||
|
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(scope >= 0);
|
||||||
|
assert(scope < _RUNTIME_SCOPE_MAX);
|
||||||
|
assert(class >= 0);
|
||||||
|
assert(class < _IMAGE_CLASS_MAX);
|
||||||
|
assert(ret);
|
||||||
|
|
||||||
|
_cleanup_free_ char *root = NULL;
|
||||||
|
switch (scope) {
|
||||||
|
|
||||||
|
case RUNTIME_SCOPE_SYSTEM:
|
||||||
|
r = sd_path_lookup(SD_PATH_SYSTEM_STATE_PRIVATE, /* suffix= */ NULL, &root);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RUNTIME_SCOPE_USER:
|
||||||
|
r = sd_path_lookup(SD_PATH_USER_STATE_PRIVATE, /* suffix= */ NULL, &root);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
const char *n = image_dirname_to_string(class);
|
||||||
|
if (!n)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
_cleanup_free_ char *j = NULL;
|
||||||
|
const char *fn;
|
||||||
|
if (fname && suffix) {
|
||||||
|
j = strjoin(fname, suffix);
|
||||||
|
if (!j)
|
||||||
|
return -ENOMEM;
|
||||||
|
fn = j;
|
||||||
|
} else
|
||||||
|
fn = fname ?: suffix;
|
||||||
|
|
||||||
|
_cleanup_free_ char *p = path_join(root, n, fn);
|
||||||
|
if (!p)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
*ret = TAKE_PTR(p);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int image_clone(Image *i, const char *new_name, bool read_only, RuntimeScope scope) {
|
int image_clone(Image *i, const char *new_name, bool read_only, RuntimeScope scope) {
|
||||||
_cleanup_(release_lock_file) LockFile name_lock = LOCK_FILE_INIT;
|
_cleanup_(release_lock_file) LockFile name_lock = LOCK_FILE_INIT;
|
||||||
_cleanup_strv_free_ char **settings = NULL;
|
_cleanup_strv_free_ char **settings = NULL;
|
||||||
_cleanup_free_ char *roothash = NULL;
|
_cleanup_free_ char *roothash = NULL;
|
||||||
const char *new_path;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(i);
|
assert(i);
|
||||||
@ -1311,7 +1409,7 @@ int image_clone(Image *i, const char *new_name, bool read_only, RuntimeScope sco
|
|||||||
if (!image_name_is_valid(new_name))
|
if (!image_name_is_valid(new_name))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
settings = image_settings_path(i);
|
settings = image_settings_path(i, scope);
|
||||||
if (!settings)
|
if (!settings)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -1322,11 +1420,11 @@ int image_clone(Image *i, const char *new_name, bool read_only, RuntimeScope sco
|
|||||||
/* Make sure nobody takes the new name, between the time we
|
/* Make sure nobody takes the new name, between the time we
|
||||||
* checked it is currently unused in all search paths, and the
|
* checked it is currently unused in all search paths, and the
|
||||||
* time we take possession of it */
|
* time we take possession of it */
|
||||||
r = image_name_lock(new_name, LOCK_EX|LOCK_NB, &name_lock);
|
r = image_name_lock(scope, new_name, LOCK_EX|LOCK_NB, &name_lock);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = image_find(scope, IMAGE_MACHINE, new_name, NULL, NULL);
|
r = image_find(scope, i->class, new_name, NULL, NULL);
|
||||||
if (r >= 0)
|
if (r >= 0)
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
if (r != -ENOENT)
|
if (r != -ENOENT)
|
||||||
@ -1335,11 +1433,14 @@ int image_clone(Image *i, const char *new_name, bool read_only, RuntimeScope sco
|
|||||||
switch (i->type) {
|
switch (i->type) {
|
||||||
|
|
||||||
case IMAGE_SUBVOLUME:
|
case IMAGE_SUBVOLUME:
|
||||||
case IMAGE_DIRECTORY:
|
case IMAGE_DIRECTORY: {
|
||||||
/* If we can we'll always try to create a new btrfs subvolume here, even if the source is a plain
|
/* If we can we'll always try to create a new btrfs subvolume here, even if the source is a plain
|
||||||
* directory. */
|
* directory. */
|
||||||
|
|
||||||
new_path = strjoina("/var/lib/machines/", new_name);
|
_cleanup_free_ char *new_path = NULL;
|
||||||
|
r = get_pool_directory(scope, i->class, new_name, /* suffix= */ NULL, &new_path);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
r = btrfs_subvol_snapshot_at(AT_FDCWD, i->path, AT_FDCWD, new_path,
|
r = btrfs_subvol_snapshot_at(AT_FDCWD, i->path, AT_FDCWD, new_path,
|
||||||
(read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) |
|
(read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) |
|
||||||
@ -1353,19 +1454,23 @@ int image_clone(Image *i, const char *new_name, bool read_only, RuntimeScope sco
|
|||||||
(void) btrfs_subvol_auto_qgroup(new_path, 0, true);
|
(void) btrfs_subvol_auto_qgroup(new_path, 0, true);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case IMAGE_RAW:
|
case IMAGE_RAW: {
|
||||||
new_path = strjoina("/var/lib/machines/", new_name, ".raw");
|
_cleanup_free_ char *new_path = NULL;
|
||||||
|
r = get_pool_directory(scope, i->class, new_name, ".raw", &new_path);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
r = copy_file_atomic(i->path, new_path, read_only ? 0444 : 0644,
|
r = copy_file_atomic(i->path, new_path, read_only ? 0444 : 0644,
|
||||||
COPY_REFLINK|COPY_CRTIME|COPY_NOCOW_AFTER);
|
COPY_REFLINK|COPY_CRTIME|COPY_NOCOW_AFTER);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case IMAGE_BLOCK:
|
case IMAGE_BLOCK:
|
||||||
default:
|
default:
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -1382,7 +1487,7 @@ int image_clone(Image *i, const char *new_name, bool read_only, RuntimeScope sco
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int image_read_only(Image *i, bool b) {
|
int image_read_only(Image *i, bool b, RuntimeScope scope) {
|
||||||
_cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT;
|
_cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -1392,7 +1497,7 @@ int image_read_only(Image *i, bool b) {
|
|||||||
return -EROFS;
|
return -EROFS;
|
||||||
|
|
||||||
/* Make sure we don't interfere with a running nspawn */
|
/* Make sure we don't interfere with a running nspawn */
|
||||||
r = image_path_lock(i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock);
|
r = image_path_lock(scope, i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -1469,12 +1574,33 @@ int image_read_only(Image *i, bool b) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void make_lock_dir(void) {
|
static int make_lock_dir(RuntimeScope scope) {
|
||||||
(void) mkdir_p("/run/systemd/nspawn", 0755);
|
int r;
|
||||||
(void) mkdir("/run/systemd/nspawn/locks", 0700);
|
|
||||||
|
_cleanup_free_ char *p = NULL;
|
||||||
|
r = runtime_directory_generic(scope, "systemd", &p);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
_cleanup_close_ int pfd = open_mkdir_at(AT_FDCWD, p, O_CLOEXEC, 0755);
|
||||||
|
if (pfd < 0)
|
||||||
|
return pfd;
|
||||||
|
|
||||||
|
_cleanup_close_ int nfd = open_mkdir_at(pfd, "nspawn", O_CLOEXEC, 0755);
|
||||||
|
if (nfd < 0)
|
||||||
|
return nfd;
|
||||||
|
|
||||||
|
r = RET_NERRNO(mkdirat(nfd, "locks", 0700));
|
||||||
|
if (r == -EEXIST)
|
||||||
|
return 0;
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int image_path_lock(
|
int image_path_lock(
|
||||||
|
RuntimeScope scope,
|
||||||
const char *path,
|
const char *path,
|
||||||
int operation,
|
int operation,
|
||||||
LockFile *ret_global,
|
LockFile *ret_global,
|
||||||
@ -1490,7 +1616,7 @@ int image_path_lock(
|
|||||||
assert(ret_local);
|
assert(ret_local);
|
||||||
|
|
||||||
/* Locks an image path. This actually creates two locks: one "local" one, next to the image path
|
/* Locks an image path. This actually creates two locks: one "local" one, next to the image path
|
||||||
* itself, which might be shared via NFS. And another "global" one, in /run, that uses the
|
* itself, which might be shared via NFS. And another "global" one, in /run/, that uses the
|
||||||
* device/inode number. This has the benefit that we can even lock a tree that is a mount point,
|
* device/inode number. This has the benefit that we can even lock a tree that is a mount point,
|
||||||
* correctly. */
|
* correctly. */
|
||||||
|
|
||||||
@ -1534,15 +1660,21 @@ int image_path_lock(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ret_global) {
|
if (ret_global) {
|
||||||
if (stat(path, &st) >= 0) {
|
if (stat(path, &st) < 0)
|
||||||
|
log_debug_errno(errno, "Failed to stat() image '%s', not locking image: %m", path);
|
||||||
|
else {
|
||||||
|
r = runtime_directory_generic(scope, "systemd/nspawn/locks/", &p);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
if (S_ISBLK(st.st_mode))
|
if (S_ISBLK(st.st_mode))
|
||||||
r = asprintf(&p, "/run/systemd/nspawn/locks/block-%u:%u", major(st.st_rdev), minor(st.st_rdev));
|
r = strextendf(&p, "block-" DEVNUM_FORMAT_STR, DEVNUM_FORMAT_VAL(st.st_rdev));
|
||||||
else if (S_ISDIR(st.st_mode) || S_ISREG(st.st_mode))
|
else if (S_ISDIR(st.st_mode) || S_ISREG(st.st_mode))
|
||||||
r = asprintf(&p, "/run/systemd/nspawn/locks/inode-%lu:%lu", (unsigned long) st.st_dev, (unsigned long) st.st_ino);
|
r = strextendf(&p, "inode-%" PRIu64 ":%" PRIu64, (uint64_t) st.st_dev, (uint64_t) st.st_ino);
|
||||||
else
|
else
|
||||||
return -ENOTTY;
|
return -ENOTTY;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return -ENOMEM;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1551,15 +1683,15 @@ int image_path_lock(
|
|||||||
if (!path_startswith(path, "/dev/")) {
|
if (!path_startswith(path, "/dev/")) {
|
||||||
r = make_lock_file_for(path, operation, &t);
|
r = make_lock_file_for(path, operation, &t);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
if (!exclusive && r == -EROFS)
|
if (exclusive || r != -EROFS)
|
||||||
log_debug_errno(r, "Failed to create shared lock for '%s', ignoring: %m", path);
|
|
||||||
else
|
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
log_debug_errno(r, "Failed to create shared lock for '%s', ignoring: %m", path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
make_lock_dir();
|
(void) make_lock_dir(scope);
|
||||||
|
|
||||||
r = make_lock_file(p, operation, ret_global);
|
r = make_lock_file(p, operation, ret_global);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
@ -1599,36 +1731,39 @@ int image_set_limit(Image *i, uint64_t referenced_max) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int image_set_pool_limit(ImageClass class, uint64_t referenced_max) {
|
int image_set_pool_limit(RuntimeScope scope, ImageClass class, uint64_t referenced_max) {
|
||||||
const char *dir;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
assert(scope >= 0 && scope < _RUNTIME_SCOPE_MAX);
|
||||||
assert(class >= 0 && class < _IMAGE_CLASS_MAX);
|
assert(class >= 0 && class < _IMAGE_CLASS_MAX);
|
||||||
|
|
||||||
dir = image_root_to_string(class);
|
_cleanup_free_ char *pool = NULL;
|
||||||
|
r = get_pool_directory(scope, class, /* fname= */ NULL, /* suffix= */ NULL, &pool);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
r = btrfs_qgroup_set_limit(dir, /* qgroupid = */ 0, referenced_max);
|
r = btrfs_qgroup_set_limit(pool, /* qgroupid = */ 0, referenced_max);
|
||||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
||||||
return r;
|
return r;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_debug_errno(r, "Failed to set limit on btrfs quota group for '%s', ignoring: %m", dir);
|
log_debug_errno(r, "Failed to set limit on btrfs quota group for '%s', ignoring: %m", pool);
|
||||||
|
|
||||||
r = btrfs_subvol_set_subtree_quota_limit(dir, /* subvol_id = */ 0, referenced_max);
|
r = btrfs_subvol_set_subtree_quota_limit(pool, /* subvol_id = */ 0, referenced_max);
|
||||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
||||||
return r;
|
return r;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to set subtree quota limit for '%s': %m", dir);
|
return log_debug_errno(r, "Failed to set subtree quota limit for '%s': %m", pool);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int image_read_metadata(Image *i, const ImagePolicy *image_policy) {
|
int image_read_metadata(Image *i, const ImagePolicy *image_policy, RuntimeScope scope) {
|
||||||
_cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT;
|
_cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(i);
|
assert(i);
|
||||||
|
|
||||||
r = image_path_lock(i->path, LOCK_SH|LOCK_NB, &global_lock, &local_lock);
|
r = image_path_lock(scope, i->path, LOCK_SH|LOCK_NB, &global_lock, &local_lock);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -1758,8 +1893,13 @@ int image_read_metadata(Image *i, const ImagePolicy *image_policy) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int image_name_lock(const char *name, int operation, LockFile *ret) {
|
int image_name_lock(
|
||||||
const char *p;
|
RuntimeScope scope,
|
||||||
|
const char *name,
|
||||||
|
int operation,
|
||||||
|
LockFile *ret) {
|
||||||
|
|
||||||
|
int r;
|
||||||
|
|
||||||
assert(name);
|
assert(name);
|
||||||
assert(ret);
|
assert(ret);
|
||||||
@ -1777,9 +1917,16 @@ int image_name_lock(const char *name, int operation, LockFile *ret) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
make_lock_dir();
|
(void) make_lock_dir(scope);
|
||||||
|
|
||||||
|
_cleanup_free_ char *p = NULL;
|
||||||
|
r = runtime_directory_generic(scope, "systemd/nspawn/locks/name-", &p);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (!strextend(&p, name))
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
p = strjoina("/run/systemd/nspawn/locks/name-", name);
|
|
||||||
return make_lock_file(p, operation, ret);
|
return make_lock_file(p, operation, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -55,21 +55,21 @@ int image_from_path(const char *path, Image **ret);
|
|||||||
int image_find_harder(RuntimeScope scope, ImageClass class, const char *name_or_path, const char *root, Image **ret);
|
int image_find_harder(RuntimeScope scope, ImageClass class, const char *name_or_path, const char *root, Image **ret);
|
||||||
int image_discover(RuntimeScope scope, ImageClass class, const char *root, Hashmap **images);
|
int image_discover(RuntimeScope scope, ImageClass class, const char *root, Hashmap **images);
|
||||||
|
|
||||||
int image_remove(Image *i);
|
int image_remove(Image *i, RuntimeScope scope);
|
||||||
int image_rename(Image *i, const char *new_name, RuntimeScope scope);
|
int image_rename(Image *i, const char *new_name, RuntimeScope scope);
|
||||||
int image_clone(Image *i, const char *new_name, bool read_only, RuntimeScope scope);
|
int image_clone(Image *i, const char *new_name, bool read_only, RuntimeScope scope);
|
||||||
int image_read_only(Image *i, bool b);
|
int image_read_only(Image *i, bool b, RuntimeScope scope);
|
||||||
|
|
||||||
const char* image_type_to_string(ImageType t) _const_;
|
const char* image_type_to_string(ImageType t) _const_;
|
||||||
ImageType image_type_from_string(const char *s) _pure_;
|
ImageType image_type_from_string(const char *s) _pure_;
|
||||||
|
|
||||||
int image_path_lock(const char *path, int operation, LockFile *global, LockFile *local);
|
int image_path_lock(RuntimeScope scope, const char *path, int operation, LockFile *global, LockFile *local);
|
||||||
int image_name_lock(const char *name, int operation, LockFile *ret);
|
int image_name_lock(RuntimeScope scope, const char *name, int operation, LockFile *ret);
|
||||||
|
|
||||||
int image_set_limit(Image *i, uint64_t referenced_max);
|
int image_set_limit(Image *i, uint64_t referenced_max);
|
||||||
int image_set_pool_limit(ImageClass class, uint64_t referenced_max);
|
int image_set_pool_limit(RuntimeScope scope, ImageClass class, uint64_t referenced_max);
|
||||||
|
|
||||||
int image_read_metadata(Image *i, const ImagePolicy *image_policy);
|
int image_read_metadata(Image *i, const ImagePolicy *image_policy, RuntimeScope scope);
|
||||||
|
|
||||||
bool image_in_search_path(RuntimeScope scope, ImageClass class, const char *root, const char *image);
|
bool image_in_search_path(RuntimeScope scope, ImageClass class, const char *root, const char *image);
|
||||||
|
|
||||||
|
|||||||
@ -56,13 +56,13 @@ int fstab_has_fstype(const char *fstype) {
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
struct libmnt_fs *fs;
|
struct libmnt_fs *fs;
|
||||||
|
|
||||||
r = mnt_table_next_fs(table, iter, &fs);
|
r = sym_mnt_table_next_fs(table, iter, &fs);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r > 0) /* EOF */
|
if (r > 0) /* EOF */
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (streq_ptr(mnt_fs_get_fstype(fs), fstype))
|
if (streq_ptr(sym_mnt_fs_get_fstype(fs), fstype))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,13 +134,13 @@ int fstab_has_mount_point_prefix_strv(char * const *prefixes) {
|
|||||||
struct libmnt_fs *fs;
|
struct libmnt_fs *fs;
|
||||||
const char *path;
|
const char *path;
|
||||||
|
|
||||||
r = mnt_table_next_fs(table, iter, &fs);
|
r = sym_mnt_table_next_fs(table, iter, &fs);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r > 0) /* EOF */
|
if (r > 0) /* EOF */
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
path = mnt_fs_get_target(fs);
|
path = sym_mnt_fs_get_target(fs);
|
||||||
if (!path)
|
if (!path)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -168,19 +168,19 @@ int fstab_is_mount_point_full(const char *where, const char *path) {
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
struct libmnt_fs *fs;
|
struct libmnt_fs *fs;
|
||||||
|
|
||||||
r = mnt_table_next_fs(table, iter, &fs);
|
r = sym_mnt_table_next_fs(table, iter, &fs);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r > 0) /* EOF */
|
if (r > 0) /* EOF */
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (where && !path_equal(mnt_fs_get_target(fs), where))
|
if (where && !path_equal(sym_mnt_fs_get_target(fs), where))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!path)
|
if (!path)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
r = fstab_is_same_node(mnt_fs_get_source(fs), path);
|
r = fstab_is_same_node(sym_mnt_fs_get_source(fs), path);
|
||||||
if (r > 0 || (r < 0 && !ERRNO_IS_DEVICE_ABSENT(r)))
|
if (r > 0 || (r < 0 && !ERRNO_IS_DEVICE_ABSENT(r)))
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,83 @@
|
|||||||
#include "libmount-util.h"
|
#include "libmount-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
|
static void *libmount_dl = NULL;
|
||||||
|
|
||||||
|
DLSYM_PROTOTYPE(mnt_free_iter) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_free_table) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_fs_get_fs_options) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_fs_get_fstype) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_fs_get_id) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_fs_get_option) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_fs_get_options) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_fs_get_passno) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_fs_get_propagation) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_fs_get_source) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_fs_get_target) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_fs_get_vfs_options) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_get_builtin_optmap) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_init_debug) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_monitor_enable_kernel) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_monitor_enable_userspace) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_monitor_get_fd) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_monitor_next_change) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_new_iter) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_new_monitor) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_new_table) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_optstr_get_flags) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_table_find_devno) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_table_find_target) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_table_next_child_fs) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_table_next_fs) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_table_parse_file) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_table_parse_mtab) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_table_parse_stream) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_table_parse_swaps) = NULL;
|
||||||
|
DLSYM_PROTOTYPE(mnt_unref_monitor) = NULL;
|
||||||
|
|
||||||
|
int dlopen_libmount(void) {
|
||||||
|
ELF_NOTE_DLOPEN("mount",
|
||||||
|
"Support for mount enumeration",
|
||||||
|
ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
|
||||||
|
"libmount.so.1");
|
||||||
|
|
||||||
|
return dlopen_many_sym_or_warn(
|
||||||
|
&libmount_dl,
|
||||||
|
"libmount.so.1",
|
||||||
|
LOG_DEBUG,
|
||||||
|
DLSYM_ARG(mnt_free_iter),
|
||||||
|
DLSYM_ARG(mnt_free_table),
|
||||||
|
DLSYM_ARG(mnt_fs_get_fs_options),
|
||||||
|
DLSYM_ARG(mnt_fs_get_fstype),
|
||||||
|
DLSYM_ARG(mnt_fs_get_id),
|
||||||
|
DLSYM_ARG(mnt_fs_get_option),
|
||||||
|
DLSYM_ARG(mnt_fs_get_options),
|
||||||
|
DLSYM_ARG(mnt_fs_get_passno),
|
||||||
|
DLSYM_ARG(mnt_fs_get_propagation),
|
||||||
|
DLSYM_ARG(mnt_fs_get_source),
|
||||||
|
DLSYM_ARG(mnt_fs_get_target),
|
||||||
|
DLSYM_ARG(mnt_fs_get_vfs_options),
|
||||||
|
DLSYM_ARG(mnt_get_builtin_optmap),
|
||||||
|
DLSYM_ARG(mnt_init_debug),
|
||||||
|
DLSYM_ARG(mnt_monitor_enable_kernel),
|
||||||
|
DLSYM_ARG(mnt_monitor_enable_userspace),
|
||||||
|
DLSYM_ARG(mnt_monitor_get_fd),
|
||||||
|
DLSYM_ARG(mnt_monitor_next_change),
|
||||||
|
DLSYM_ARG(mnt_new_iter),
|
||||||
|
DLSYM_ARG(mnt_new_monitor),
|
||||||
|
DLSYM_ARG(mnt_new_table),
|
||||||
|
DLSYM_ARG(mnt_optstr_get_flags),
|
||||||
|
DLSYM_ARG(mnt_table_find_devno),
|
||||||
|
DLSYM_ARG(mnt_table_find_target),
|
||||||
|
DLSYM_ARG(mnt_table_next_child_fs),
|
||||||
|
DLSYM_ARG(mnt_table_next_fs),
|
||||||
|
DLSYM_ARG(mnt_table_parse_file),
|
||||||
|
DLSYM_ARG(mnt_table_parse_mtab),
|
||||||
|
DLSYM_ARG(mnt_table_parse_stream),
|
||||||
|
DLSYM_ARG(mnt_table_parse_swaps),
|
||||||
|
DLSYM_ARG(mnt_unref_monitor));
|
||||||
|
}
|
||||||
|
|
||||||
int libmount_parse_full(
|
int libmount_parse_full(
|
||||||
const char *path,
|
const char *path,
|
||||||
FILE *source,
|
FILE *source,
|
||||||
@ -19,8 +96,12 @@ int libmount_parse_full(
|
|||||||
/* Older libmount seems to require this. */
|
/* Older libmount seems to require this. */
|
||||||
assert(!source || path);
|
assert(!source || path);
|
||||||
|
|
||||||
table = mnt_new_table();
|
r = dlopen_libmount();
|
||||||
iter = mnt_new_iter(MNT_ITER_FORWARD);
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
table = sym_mnt_new_table();
|
||||||
|
iter = sym_mnt_new_iter(MNT_ITER_FORWARD);
|
||||||
if (!table || !iter)
|
if (!table || !iter)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -28,11 +109,11 @@ int libmount_parse_full(
|
|||||||
* Only if both are empty, we use mnt_table_parse_mtab(). */
|
* Only if both are empty, we use mnt_table_parse_mtab(). */
|
||||||
|
|
||||||
if (source)
|
if (source)
|
||||||
r = mnt_table_parse_stream(table, source, path);
|
r = sym_mnt_table_parse_stream(table, source, path);
|
||||||
else if (path)
|
else if (path)
|
||||||
r = mnt_table_parse_file(table, path);
|
r = sym_mnt_table_parse_file(table, path);
|
||||||
else
|
else
|
||||||
r = mnt_table_parse_mtab(table, NULL);
|
r = sym_mnt_table_parse_mtab(table, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -53,14 +134,16 @@ int libmount_is_leaf(
|
|||||||
struct libmnt_fs *fs) {
|
struct libmnt_fs *fs) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
assert(table);
|
||||||
|
|
||||||
_cleanup_(mnt_free_iterp) struct libmnt_iter *iter_children = NULL;
|
_cleanup_(mnt_free_iterp) struct libmnt_iter *iter_children = NULL;
|
||||||
iter_children = mnt_new_iter(MNT_ITER_FORWARD);
|
iter_children = sym_mnt_new_iter(MNT_ITER_FORWARD);
|
||||||
if (!iter_children)
|
if (!iter_children)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
/* We care only whether it exists, it is unused */
|
/* We care only whether it exists, it is unused */
|
||||||
_unused_ struct libmnt_fs *child;
|
_unused_ struct libmnt_fs *child;
|
||||||
r = mnt_table_next_child_fs(table, iter_children, fs, &child);
|
r = sym_mnt_table_next_child_fs(table, iter_children, fs, &child);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -4,10 +4,45 @@
|
|||||||
/* This needs to be after sys/mount.h */
|
/* This needs to be after sys/mount.h */
|
||||||
#include <libmount.h> /* IWYU pragma: export */
|
#include <libmount.h> /* IWYU pragma: export */
|
||||||
|
|
||||||
|
#include "dlfcn-util.h"
|
||||||
#include "forward.h"
|
#include "forward.h"
|
||||||
|
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct libmnt_table*, mnt_free_table, NULL);
|
extern DLSYM_PROTOTYPE(mnt_free_iter);
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct libmnt_iter*, mnt_free_iter, NULL);
|
extern DLSYM_PROTOTYPE(mnt_free_table);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_fs_get_fs_options);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_fs_get_fstype);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_fs_get_id);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_fs_get_option);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_fs_get_options);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_fs_get_passno);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_fs_get_propagation);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_fs_get_source);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_fs_get_target);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_fs_get_vfs_options);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_get_builtin_optmap);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_init_debug);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_monitor_enable_kernel);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_monitor_enable_userspace);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_monitor_get_fd);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_monitor_next_change);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_new_iter);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_new_monitor);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_new_table);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_optstr_get_flags);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_table_find_devno);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_table_find_target);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_table_next_child_fs);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_table_next_fs);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_table_parse_file);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_table_parse_mtab);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_table_parse_stream);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_table_parse_swaps);
|
||||||
|
extern DLSYM_PROTOTYPE(mnt_unref_monitor);
|
||||||
|
|
||||||
|
int dlopen_libmount(void);
|
||||||
|
|
||||||
|
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(struct libmnt_table*, sym_mnt_free_table, mnt_free_tablep, NULL);
|
||||||
|
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(struct libmnt_iter*, sym_mnt_free_iter, mnt_free_iterp, NULL);
|
||||||
|
|
||||||
int libmount_parse_full(
|
int libmount_parse_full(
|
||||||
const char *path,
|
const char *path,
|
||||||
|
|||||||
@ -322,7 +322,7 @@ libshared_deps = [threads,
|
|||||||
libgcrypt_cflags,
|
libgcrypt_cflags,
|
||||||
libkmod_cflags,
|
libkmod_cflags,
|
||||||
liblz4_cflags,
|
liblz4_cflags,
|
||||||
libmount,
|
libmount_cflags,
|
||||||
libopenssl,
|
libopenssl,
|
||||||
libp11kit_cflags,
|
libp11kit_cflags,
|
||||||
libpam_cflags,
|
libpam_cflags,
|
||||||
|
|||||||
@ -60,13 +60,13 @@ int umount_recursive_full(const char *prefix, int flags, char **keep) {
|
|||||||
struct libmnt_fs *fs;
|
struct libmnt_fs *fs;
|
||||||
const char *path;
|
const char *path;
|
||||||
|
|
||||||
r = mnt_table_next_fs(table, iter, &fs);
|
r = sym_mnt_table_next_fs(table, iter, &fs);
|
||||||
if (r == 1)
|
if (r == 1)
|
||||||
break;
|
break;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
|
return log_debug_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
|
||||||
|
|
||||||
path = mnt_fs_get_target(fs);
|
path = sym_mnt_fs_get_target(fs);
|
||||||
if (!path)
|
if (!path)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -247,20 +247,20 @@ int bind_remount_recursive_with_mountinfo(
|
|||||||
unsigned long flags = 0;
|
unsigned long flags = 0;
|
||||||
struct libmnt_fs *fs;
|
struct libmnt_fs *fs;
|
||||||
|
|
||||||
r = mnt_table_next_fs(table, iter, &fs);
|
r = sym_mnt_table_next_fs(table, iter, &fs);
|
||||||
if (r == 1) /* EOF */
|
if (r == 1) /* EOF */
|
||||||
break;
|
break;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
|
return log_debug_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
|
||||||
|
|
||||||
path = mnt_fs_get_target(fs);
|
path = sym_mnt_fs_get_target(fs);
|
||||||
if (!path)
|
if (!path)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!path_startswith(path, prefix))
|
if (!path_startswith(path, prefix))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
type = mnt_fs_get_fstype(fs);
|
type = sym_mnt_fs_get_fstype(fs);
|
||||||
if (!type)
|
if (!type)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -298,9 +298,9 @@ int bind_remount_recursive_with_mountinfo(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
opts = mnt_fs_get_vfs_options(fs);
|
opts = sym_mnt_fs_get_vfs_options(fs);
|
||||||
if (opts) {
|
if (opts) {
|
||||||
r = mnt_optstr_get_flags(opts, &flags, mnt_get_builtin_optmap(MNT_LINUX_MAP));
|
r = sym_mnt_optstr_get_flags(opts, &flags, sym_mnt_get_builtin_optmap(MNT_LINUX_MAP));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_debug_errno(r, "Could not get flags for '%s', ignoring: %m", path);
|
log_debug_errno(r, "Could not get flags for '%s', ignoring: %m", path);
|
||||||
}
|
}
|
||||||
@ -438,15 +438,19 @@ int bind_remount_one_with_mountinfo(
|
|||||||
|
|
||||||
rewind(proc_self_mountinfo);
|
rewind(proc_self_mountinfo);
|
||||||
|
|
||||||
table = mnt_new_table();
|
r = dlopen_libmount();
|
||||||
if (!table)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
r = mnt_table_parse_stream(table, proc_self_mountinfo, "/proc/self/mountinfo");
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
fs = mnt_table_find_target(table, path, MNT_ITER_FORWARD);
|
table = sym_mnt_new_table();
|
||||||
|
if (!table)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
r = sym_mnt_table_parse_stream(table, proc_self_mountinfo, "/proc/self/mountinfo");
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
fs = sym_mnt_table_find_target(table, path, MNT_ITER_FORWARD);
|
||||||
if (!fs) {
|
if (!fs) {
|
||||||
r = access_nofollow(path, F_OK); /* Hmm, it's not in the mount table, but does it exist at all? */
|
r = access_nofollow(path, F_OK); /* Hmm, it's not in the mount table, but does it exist at all? */
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -455,9 +459,9 @@ int bind_remount_one_with_mountinfo(
|
|||||||
return -EINVAL; /* Not a mount point we recognize */
|
return -EINVAL; /* Not a mount point we recognize */
|
||||||
}
|
}
|
||||||
|
|
||||||
opts = mnt_fs_get_vfs_options(fs);
|
opts = sym_mnt_fs_get_vfs_options(fs);
|
||||||
if (opts) {
|
if (opts) {
|
||||||
r = mnt_optstr_get_flags(opts, &flags, mnt_get_builtin_optmap(MNT_LINUX_MAP));
|
r = sym_mnt_optstr_get_flags(opts, &flags, sym_mnt_get_builtin_optmap(MNT_LINUX_MAP));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_debug_errno(r, "Could not get flags for '%s', ignoring: %m", path);
|
log_debug_errno(r, "Could not get flags for '%s', ignoring: %m", path);
|
||||||
}
|
}
|
||||||
@ -873,7 +877,11 @@ int mount_option_mangle(
|
|||||||
assert(ret_mount_flags);
|
assert(ret_mount_flags);
|
||||||
assert(ret_remaining_options);
|
assert(ret_remaining_options);
|
||||||
|
|
||||||
map = mnt_get_builtin_optmap(MNT_LINUX_MAP);
|
r = dlopen_libmount();
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
map = sym_mnt_get_builtin_optmap(MNT_LINUX_MAP);
|
||||||
if (!map)
|
if (!map)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@ -1637,20 +1645,20 @@ int get_sub_mounts(const char *prefix, SubMount **ret_mounts, size_t *ret_n_moun
|
|||||||
const char *path;
|
const char *path;
|
||||||
int id1, id2;
|
int id1, id2;
|
||||||
|
|
||||||
r = mnt_table_next_fs(table, iter, &fs);
|
r = sym_mnt_table_next_fs(table, iter, &fs);
|
||||||
if (r == 1)
|
if (r == 1)
|
||||||
break; /* EOF */
|
break; /* EOF */
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
|
return log_debug_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
|
||||||
|
|
||||||
path = mnt_fs_get_target(fs);
|
path = sym_mnt_fs_get_target(fs);
|
||||||
if (!path)
|
if (!path)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (isempty(path_startswith(path, prefix)))
|
if (isempty(path_startswith(path, prefix)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
id1 = mnt_fs_get_id(fs);
|
id1 = sym_mnt_fs_get_id(fs);
|
||||||
r = path_get_mnt_id(path, &id2);
|
r = path_get_mnt_id(path, &id2);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_debug_errno(r, "Failed to get mount ID of '%s', ignoring: %m", path);
|
log_debug_errno(r, "Failed to get mount ID of '%s', ignoring: %m", path);
|
||||||
@ -1982,31 +1990,31 @@ int path_get_mount_info_at(
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
struct libmnt_fs *fs;
|
struct libmnt_fs *fs;
|
||||||
|
|
||||||
r = mnt_table_next_fs(table, iter, &fs);
|
r = sym_mnt_table_next_fs(table, iter, &fs);
|
||||||
if (r == 1)
|
if (r == 1)
|
||||||
break; /* EOF */
|
break; /* EOF */
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
|
return log_debug_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
|
||||||
|
|
||||||
if (mnt_fs_get_id(fs) != mnt_id)
|
if (sym_mnt_fs_get_id(fs) != mnt_id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
_cleanup_free_ char *fstype = NULL, *options = NULL, *source = NULL;
|
_cleanup_free_ char *fstype = NULL, *options = NULL, *source = NULL;
|
||||||
|
|
||||||
if (ret_fstype) {
|
if (ret_fstype) {
|
||||||
fstype = strdup(strempty(mnt_fs_get_fstype(fs)));
|
fstype = strdup(strempty(sym_mnt_fs_get_fstype(fs)));
|
||||||
if (!fstype)
|
if (!fstype)
|
||||||
return log_oom_debug();
|
return log_oom_debug();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret_options) {
|
if (ret_options) {
|
||||||
options = strdup(strempty(mnt_fs_get_options(fs)));
|
options = strdup(strempty(sym_mnt_fs_get_options(fs)));
|
||||||
if (!options)
|
if (!options)
|
||||||
return log_oom_debug();
|
return log_oom_debug();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret_source) {
|
if (ret_source) {
|
||||||
source = strdup(strempty(mnt_fs_get_source(fs)));
|
source = strdup(strempty(sym_mnt_fs_get_source(fs)));
|
||||||
if (!source)
|
if (!source)
|
||||||
return log_oom_debug();
|
return log_oom_debug();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,9 +8,19 @@
|
|||||||
#include "bus-object.h"
|
#include "bus-object.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "pretty-print.h"
|
#include "pretty-print.h"
|
||||||
|
#include "runtime-scope.h"
|
||||||
#include "service-util.h"
|
#include "service-util.h"
|
||||||
|
|
||||||
static int help(const char *program_path, const char *service, const char *description, bool bus_introspect) {
|
typedef enum HelpFlags {
|
||||||
|
HELP_WITH_BUS_INTROSPECT = 1 << 0,
|
||||||
|
HELP_WITH_RUNTIME_SCOPE = 1 << 1,
|
||||||
|
} HelpFlags;
|
||||||
|
|
||||||
|
static int help(const char *program_path,
|
||||||
|
const char *service,
|
||||||
|
const char *description,
|
||||||
|
HelpFlags flags) {
|
||||||
|
|
||||||
_cleanup_free_ char *link = NULL;
|
_cleanup_free_ char *link = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -25,6 +35,7 @@ static int help(const char *program_path, const char *service, const char *descr
|
|||||||
" -h --help Show this help\n"
|
" -h --help Show this help\n"
|
||||||
" --version Show package version\n"
|
" --version Show package version\n"
|
||||||
"%8$s"
|
"%8$s"
|
||||||
|
"%9$s"
|
||||||
"\nSee the %2$s for details.\n",
|
"\nSee the %2$s for details.\n",
|
||||||
program_path,
|
program_path,
|
||||||
link,
|
link,
|
||||||
@ -33,7 +44,9 @@ static int help(const char *program_path, const char *service, const char *descr
|
|||||||
ansi_highlight(),
|
ansi_highlight(),
|
||||||
ansi_normal(),
|
ansi_normal(),
|
||||||
description,
|
description,
|
||||||
bus_introspect ? " --bus-introspect=PATH Write D-Bus XML introspection data\n" : "");
|
FLAGS_SET(flags, HELP_WITH_BUS_INTROSPECT) ? " --bus-introspect=PATH Write D-Bus XML introspection data\n" : "",
|
||||||
|
FLAGS_SET(flags, HELP_WITH_RUNTIME_SCOPE) ? " --system Start service in system mode\n"
|
||||||
|
" --user Start service in user mode\n" : "");
|
||||||
|
|
||||||
return 0; /* No further action */
|
return 0; /* No further action */
|
||||||
}
|
}
|
||||||
@ -42,17 +55,22 @@ int service_parse_argv(
|
|||||||
const char *service,
|
const char *service,
|
||||||
const char *description,
|
const char *description,
|
||||||
const BusObjectImplementation* const* bus_objects,
|
const BusObjectImplementation* const* bus_objects,
|
||||||
|
RuntimeScope *runtime_scope,
|
||||||
int argc, char *argv[]) {
|
int argc, char *argv[]) {
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ARG_VERSION = 0x100,
|
ARG_VERSION = 0x100,
|
||||||
ARG_BUS_INTROSPECT,
|
ARG_BUS_INTROSPECT,
|
||||||
|
ARG_SYSTEM,
|
||||||
|
ARG_USER,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct option options[] = {
|
static const struct option options[] = {
|
||||||
{ "help", no_argument, NULL, 'h' },
|
{ "help", no_argument, NULL, 'h' },
|
||||||
{ "version", no_argument, NULL, ARG_VERSION },
|
{ "version", no_argument, NULL, ARG_VERSION },
|
||||||
{ "bus-introspect", required_argument, NULL, ARG_BUS_INTROSPECT },
|
{ "bus-introspect", required_argument, NULL, ARG_BUS_INTROSPECT },
|
||||||
|
{ "system", no_argument, NULL, ARG_SYSTEM },
|
||||||
|
{ "user", no_argument, NULL, ARG_USER },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -65,7 +83,11 @@ int service_parse_argv(
|
|||||||
switch (c) {
|
switch (c) {
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
return help(argv[0], service, description, bus_objects);
|
return help(argv[0],
|
||||||
|
service,
|
||||||
|
description,
|
||||||
|
(bus_objects ? HELP_WITH_BUS_INTROSPECT : 0) |
|
||||||
|
(runtime_scope ? HELP_WITH_RUNTIME_SCOPE : 0));
|
||||||
|
|
||||||
case ARG_VERSION:
|
case ARG_VERSION:
|
||||||
return version();
|
return version();
|
||||||
@ -76,6 +98,14 @@ int service_parse_argv(
|
|||||||
optarg,
|
optarg,
|
||||||
bus_objects);
|
bus_objects);
|
||||||
|
|
||||||
|
case ARG_SYSTEM:
|
||||||
|
case ARG_USER:
|
||||||
|
if (!runtime_scope)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This service cannot be run in --system or --user mode, refusing.");
|
||||||
|
|
||||||
|
*runtime_scope = c == ARG_SYSTEM ? RUNTIME_SCOPE_SYSTEM : RUNTIME_SCOPE_USER;
|
||||||
|
break;
|
||||||
|
|
||||||
case '?':
|
case '?':
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
|||||||
@ -7,4 +7,5 @@ int service_parse_argv(
|
|||||||
const char *service,
|
const char *service,
|
||||||
const char *description,
|
const char *description,
|
||||||
const BusObjectImplementation* const* bus_objects,
|
const BusObjectImplementation* const* bus_objects,
|
||||||
|
RuntimeScope *runtime_scope,
|
||||||
int argc, char *argv[]);
|
int argc, char *argv[]);
|
||||||
|
|||||||
@ -36,12 +36,16 @@ int swap_list_get(const char *swaps, SwapDevice **head) {
|
|||||||
|
|
||||||
assert(head);
|
assert(head);
|
||||||
|
|
||||||
t = mnt_new_table();
|
r = dlopen_libmount();
|
||||||
i = mnt_new_iter(MNT_ITER_FORWARD);
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Cannot enumerate swap partitions, no libmount support.");
|
||||||
|
|
||||||
|
t = sym_mnt_new_table();
|
||||||
|
i = sym_mnt_new_iter(MNT_ITER_FORWARD);
|
||||||
if (!t || !i)
|
if (!t || !i)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
r = mnt_table_parse_swaps(t, swaps);
|
r = sym_mnt_table_parse_swaps(t, swaps);
|
||||||
if (r == -ENOENT) /* no /proc/swaps is fine */
|
if (r == -ENOENT) /* no /proc/swaps is fine */
|
||||||
return 0;
|
return 0;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -52,13 +56,13 @@ int swap_list_get(const char *swaps, SwapDevice **head) {
|
|||||||
_cleanup_free_ SwapDevice *swap = NULL;
|
_cleanup_free_ SwapDevice *swap = NULL;
|
||||||
const char *source;
|
const char *source;
|
||||||
|
|
||||||
r = mnt_table_next_fs(t, i, &fs);
|
r = sym_mnt_table_next_fs(t, i, &fs);
|
||||||
if (r == 1) /* EOF */
|
if (r == 1) /* EOF */
|
||||||
break;
|
break;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to get next entry from %s: %m", swaps ?: "/proc/swaps");
|
return log_error_errno(r, "Failed to get next entry from %s: %m", swaps ?: "/proc/swaps");
|
||||||
|
|
||||||
source = mnt_fs_get_source(fs);
|
source = sym_mnt_fs_get_source(fs);
|
||||||
if (!source)
|
if (!source)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ executables += [
|
|||||||
'name' : 'systemd-shutdown',
|
'name' : 'systemd-shutdown',
|
||||||
'sources' : systemd_shutdown_sources + systemd_shutdown_extract_sources,
|
'sources' : systemd_shutdown_sources + systemd_shutdown_extract_sources,
|
||||||
'extract' : systemd_shutdown_extract_sources,
|
'extract' : systemd_shutdown_extract_sources,
|
||||||
'dependencies' : libmount,
|
'dependencies' : libmount_cflags,
|
||||||
},
|
},
|
||||||
libexec_template + {
|
libexec_template + {
|
||||||
'name' : 'systemd-shutdown.standalone',
|
'name' : 'systemd-shutdown.standalone',
|
||||||
@ -28,11 +28,11 @@ executables += [
|
|||||||
libshared_static,
|
libshared_static,
|
||||||
libsystemd_static,
|
libsystemd_static,
|
||||||
],
|
],
|
||||||
'dependencies' : libmount,
|
'dependencies' : libmount_cflags,
|
||||||
},
|
},
|
||||||
test_template + {
|
test_template + {
|
||||||
'sources' : files('test-umount.c'),
|
'sources' : files('test-umount.c'),
|
||||||
'objects' : ['systemd-shutdown'],
|
'objects' : ['systemd-shutdown'],
|
||||||
'dependencies' : libmount,
|
'dependencies' : libmount_cflags,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
@ -69,17 +69,17 @@ int mount_points_list_get(FILE *f, MountPoint **head) {
|
|||||||
bool try_remount_ro, is_api_vfs, is_network;
|
bool try_remount_ro, is_api_vfs, is_network;
|
||||||
_cleanup_free_ MountPoint *m = NULL;
|
_cleanup_free_ MountPoint *m = NULL;
|
||||||
|
|
||||||
r = mnt_table_next_fs(table, iter, &fs);
|
r = sym_mnt_table_next_fs(table, iter, &fs);
|
||||||
if (r == 1) /* EOF */
|
if (r == 1) /* EOF */
|
||||||
break;
|
break;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
|
return log_error_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
|
||||||
|
|
||||||
path = mnt_fs_get_target(fs);
|
path = sym_mnt_fs_get_target(fs);
|
||||||
if (!path)
|
if (!path)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
fstype = mnt_fs_get_fstype(fs);
|
fstype = sym_mnt_fs_get_fstype(fs);
|
||||||
|
|
||||||
/* Combine the generic VFS options with the FS-specific options. Duplicates are not a problem
|
/* Combine the generic VFS options with the FS-specific options. Duplicates are not a problem
|
||||||
* here, because the only options that should come up twice are typically ro/rw, which are
|
* here, because the only options that should come up twice are typically ro/rw, which are
|
||||||
@ -87,9 +87,9 @@ int mount_points_list_get(FILE *f, MountPoint **head) {
|
|||||||
*
|
*
|
||||||
* Even if there are duplicates later in mount_option_mangle() they shouldn't hurt anyways as
|
* Even if there are duplicates later in mount_option_mangle() they shouldn't hurt anyways as
|
||||||
* they override each other. */
|
* they override each other. */
|
||||||
if (!strextend_with_separator(&options, ",", mnt_fs_get_vfs_options(fs)))
|
if (!strextend_with_separator(&options, ",", sym_mnt_fs_get_vfs_options(fs)))
|
||||||
return log_oom();
|
return log_oom();
|
||||||
if (!strextend_with_separator(&options, ",", mnt_fs_get_fs_options(fs)))
|
if (!strextend_with_separator(&options, ",", sym_mnt_fs_get_fs_options(fs)))
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
/* Ignore mount points we can't unmount because they are API or because we are keeping them
|
/* Ignore mount points we can't unmount because they are API or because we are keeping them
|
||||||
@ -122,7 +122,7 @@ int mount_points_list_get(FILE *f, MountPoint **head) {
|
|||||||
* were when the filesystem was mounted, except for the desired changes. So we
|
* were when the filesystem was mounted, except for the desired changes. So we
|
||||||
* reconstruct both here and adjust them for the later remount call too. */
|
* reconstruct both here and adjust them for the later remount call too. */
|
||||||
|
|
||||||
r = mnt_fs_get_propagation(fs, &remount_flags);
|
r = sym_mnt_fs_get_propagation(fs, &remount_flags);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_warning_errno(r, "mnt_fs_get_propagation() failed for %s, ignoring: %m", path);
|
log_warning_errno(r, "mnt_fs_get_propagation() failed for %s, ignoring: %m", path);
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@ -2127,7 +2127,7 @@ static int image_discover_and_read_metadata(ImageClass image_class, Hashmap **re
|
|||||||
return log_error_errno(r, "Failed to discover images: %m");
|
return log_error_errno(r, "Failed to discover images: %m");
|
||||||
|
|
||||||
HASHMAP_FOREACH(img, images) {
|
HASHMAP_FOREACH(img, images) {
|
||||||
r = image_read_metadata(img, image_class_info[image_class].default_image_policy);
|
r = image_read_metadata(img, image_class_info[image_class].default_image_policy, RUNTIME_SCOPE_SYSTEM);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to read metadata for image %s: %m", img->name);
|
return log_error_errno(r, "Failed to read metadata for image %s: %m", img->name);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2079,6 +2079,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
"System update management service.",
|
"System update management service.",
|
||||||
BUS_IMPLEMENTATIONS(&manager_object,
|
BUS_IMPLEMENTATIONS(&manager_object,
|
||||||
&log_control_object),
|
&log_control_object),
|
||||||
|
/* runtime_scope= */ NULL,
|
||||||
argc, argv);
|
argc, argv);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@ -215,7 +215,7 @@ simple_tests += files(
|
|||||||
############################################################
|
############################################################
|
||||||
|
|
||||||
common_test_dependencies = [
|
common_test_dependencies = [
|
||||||
libmount,
|
libmount_cflags,
|
||||||
librt,
|
librt,
|
||||||
libseccomp_cflags,
|
libseccomp_cflags,
|
||||||
libselinux,
|
libselinux,
|
||||||
@ -289,6 +289,7 @@ executables += [
|
|||||||
'dependencies' : [
|
'dependencies' : [
|
||||||
libblkid_cflags,
|
libblkid_cflags,
|
||||||
libkmod_cflags,
|
libkmod_cflags,
|
||||||
|
libmount_cflags,
|
||||||
libp11kit_cflags,
|
libp11kit_cflags,
|
||||||
libseccomp_cflags,
|
libseccomp_cflags,
|
||||||
],
|
],
|
||||||
@ -341,7 +342,7 @@ executables += [
|
|||||||
test_template + {
|
test_template + {
|
||||||
'sources' : files('test-libmount.c'),
|
'sources' : files('test-libmount.c'),
|
||||||
'dependencies' : [
|
'dependencies' : [
|
||||||
libmount,
|
libmount_cflags,
|
||||||
threads,
|
threads,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -359,7 +360,7 @@ executables += [
|
|||||||
},
|
},
|
||||||
test_template + {
|
test_template + {
|
||||||
'sources' : files('test-mount-util.c'),
|
'sources' : files('test-mount-util.c'),
|
||||||
'dependencies' : libmount,
|
'dependencies' : libmount_cflags,
|
||||||
},
|
},
|
||||||
test_template + {
|
test_template + {
|
||||||
'sources' : files('test-netlink-manual.c'),
|
'sources' : files('test-netlink-manual.c'),
|
||||||
|
|||||||
@ -49,7 +49,8 @@ int main(int argc, char *argv[]) {
|
|||||||
if (!can_memlock())
|
if (!can_memlock())
|
||||||
return log_tests_skipped("Can't use mlock()");
|
return log_tests_skipped("Can't use mlock()");
|
||||||
|
|
||||||
r = enter_cgroup_subroot(NULL);
|
_cleanup_free_ char *cgroup_path = NULL;
|
||||||
|
r = enter_cgroup_subroot(&cgroup_path);
|
||||||
if (r == -ENOMEDIUM)
|
if (r == -ENOMEDIUM)
|
||||||
return log_tests_skipped("cgroupfs not available");
|
return log_tests_skipped("cgroupfs not available");
|
||||||
|
|
||||||
@ -128,6 +129,8 @@ int main(int argc, char *argv[]) {
|
|||||||
SERVICE(u)->type = SERVICE_ONESHOT;
|
SERVICE(u)->type = SERVICE_ONESHOT;
|
||||||
u->load_state = UNIT_LOADED;
|
u->load_state = UNIT_LOADED;
|
||||||
|
|
||||||
|
CGroupRuntime *crt = ASSERT_PTR(unit_setup_cgroup_runtime(u));
|
||||||
|
|
||||||
unit_dump(u, stdout, NULL);
|
unit_dump(u, stdout, NULL);
|
||||||
|
|
||||||
r = bpf_firewall_compile(u);
|
r = bpf_firewall_compile(u);
|
||||||
@ -135,7 +138,6 @@ int main(int argc, char *argv[]) {
|
|||||||
return log_tests_skipped("Kernel doesn't support the necessary bpf bits (masked out via seccomp?)");
|
return log_tests_skipped("Kernel doesn't support the necessary bpf bits (masked out via seccomp?)");
|
||||||
ASSERT_OK(r);
|
ASSERT_OK(r);
|
||||||
|
|
||||||
CGroupRuntime *crt = ASSERT_PTR(unit_get_cgroup_runtime(u));
|
|
||||||
ASSERT_NOT_NULL(crt->ip_bpf_ingress);
|
ASSERT_NOT_NULL(crt->ip_bpf_ingress);
|
||||||
ASSERT_NOT_NULL(crt->ip_bpf_egress);
|
ASSERT_NOT_NULL(crt->ip_bpf_egress);
|
||||||
|
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
#include "libarchive-util.h"
|
#include "libarchive-util.h"
|
||||||
#include "libaudit-util.h"
|
#include "libaudit-util.h"
|
||||||
#include "libfido2-util.h"
|
#include "libfido2-util.h"
|
||||||
|
#include "libmount-util.h"
|
||||||
#include "main-func.h"
|
#include "main-func.h"
|
||||||
#include "module-util.h"
|
#include "module-util.h"
|
||||||
#include "pam-util.h"
|
#include "pam-util.h"
|
||||||
@ -58,6 +59,7 @@ static int run(int argc, char **argv) {
|
|||||||
ASSERT_DLOPEN(dlopen_libacl, HAVE_ACL);
|
ASSERT_DLOPEN(dlopen_libacl, HAVE_ACL);
|
||||||
ASSERT_DLOPEN(dlopen_libblkid, HAVE_BLKID);
|
ASSERT_DLOPEN(dlopen_libblkid, HAVE_BLKID);
|
||||||
ASSERT_DLOPEN(dlopen_libseccomp, HAVE_SECCOMP);
|
ASSERT_DLOPEN(dlopen_libseccomp, HAVE_SECCOMP);
|
||||||
|
ASSERT_DLOPEN(dlopen_libmount, true);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,7 +32,7 @@ static void test_libmount_unescaping_one(
|
|||||||
|
|
||||||
/* We allow this call and the checks below to fail in some cases. See the case definitions below. */
|
/* We allow this call and the checks below to fail in some cases. See the case definitions below. */
|
||||||
|
|
||||||
r = mnt_table_next_fs(table, iter, &fs);
|
r = sym_mnt_table_next_fs(table, iter, &fs);
|
||||||
if (r != 0 && may_fail) {
|
if (r != 0 && may_fail) {
|
||||||
log_error_errno(r, "mnt_table_next_fs failed: %m");
|
log_error_errno(r, "mnt_table_next_fs failed: %m");
|
||||||
return;
|
return;
|
||||||
@ -41,8 +41,8 @@ static void test_libmount_unescaping_one(
|
|||||||
|
|
||||||
assert_se(x = cescape(string));
|
assert_se(x = cescape(string));
|
||||||
|
|
||||||
assert_se(source = mnt_fs_get_source(fs));
|
assert_se(source = sym_mnt_fs_get_source(fs));
|
||||||
assert_se(target = mnt_fs_get_target(fs));
|
assert_se(target = sym_mnt_fs_get_target(fs));
|
||||||
|
|
||||||
assert_se(cs = cescape(source));
|
assert_se(cs = cescape(source));
|
||||||
assert_se(ct = cescape(target));
|
assert_se(ct = cescape(target));
|
||||||
@ -63,7 +63,7 @@ static void test_libmount_unescaping_one(
|
|||||||
assert_se(may_fail || streq(source, expected_source));
|
assert_se(may_fail || streq(source, expected_source));
|
||||||
assert_se(may_fail || streq(target, expected_target));
|
assert_se(may_fail || streq(target, expected_target));
|
||||||
|
|
||||||
assert_se(mnt_table_next_fs(table, iter, &fs) == 1);
|
assert_se(sym_mnt_table_next_fs(table, iter, &fs) == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(libmount_unescaping) {
|
TEST(libmount_unescaping) {
|
||||||
|
|||||||
@ -361,7 +361,7 @@ TEST(umount_recursive) {
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
struct libmnt_fs *fs;
|
struct libmnt_fs *fs;
|
||||||
|
|
||||||
r = mnt_table_next_fs(table, iter, &fs);
|
r = sym_mnt_table_next_fs(table, iter, &fs);
|
||||||
if (r == 1)
|
if (r == 1)
|
||||||
break;
|
break;
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
@ -369,7 +369,7 @@ TEST(umount_recursive) {
|
|||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
log_debug("left after complete umount: %s", mnt_fs_get_target(fs));
|
log_debug("left after complete umount: %s", sym_mnt_fs_get_target(fs));
|
||||||
}
|
}
|
||||||
|
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
|
|||||||
@ -1164,6 +1164,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
"Manage the system clock and timezone and NTP enablement.",
|
"Manage the system clock and timezone and NTP enablement.",
|
||||||
BUS_IMPLEMENTATIONS(&manager_object,
|
BUS_IMPLEMENTATIONS(&manager_object,
|
||||||
&log_control_object),
|
&log_control_object),
|
||||||
|
/* runtime_scope= */ NULL,
|
||||||
argc, argv);
|
argc, argv);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@ -151,6 +151,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
r = service_parse_argv("systemd-timesyncd.service",
|
r = service_parse_argv("systemd-timesyncd.service",
|
||||||
"Network time synchronization",
|
"Network time synchronization",
|
||||||
BUS_IMPLEMENTATIONS(&manager_object, &log_control_object),
|
BUS_IMPLEMENTATIONS(&manager_object, &log_control_object),
|
||||||
|
/* runtime_scope= */ NULL,
|
||||||
argc, argv);
|
argc, argv);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@ -70,7 +70,7 @@ foreach dirname : [
|
|||||||
'TEST-46-HOMED',
|
'TEST-46-HOMED',
|
||||||
'TEST-50-DISSECT',
|
'TEST-50-DISSECT',
|
||||||
'TEST-52-HONORFIRSTSHUTDOWN',
|
'TEST-52-HONORFIRSTSHUTDOWN',
|
||||||
'TEST-53-ISSUE-16347',
|
'TEST-53-TIMER',
|
||||||
'TEST-54-CREDS',
|
'TEST-54-CREDS',
|
||||||
'TEST-55-OOMD',
|
'TEST-55-OOMD',
|
||||||
'TEST-58-REPART',
|
'TEST-58-REPART',
|
||||||
|
|||||||
@ -3,8 +3,6 @@
|
|||||||
set -eux
|
set -eux
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
systemd-analyze log-level debug
|
|
||||||
|
|
||||||
cat >/run/systemd/system/floodme@.service <<EOF
|
cat >/run/systemd/system/floodme@.service <<EOF
|
||||||
[Service]
|
[Service]
|
||||||
ExecStart=true
|
ExecStart=true
|
||||||
|
|||||||
@ -4,8 +4,6 @@
|
|||||||
set -eux
|
set -eux
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
systemd-analyze log-level debug
|
|
||||||
|
|
||||||
test_quotas() {
|
test_quotas() {
|
||||||
|
|
||||||
local directory="$1"
|
local directory="$1"
|
||||||
@ -90,6 +88,4 @@ EOF
|
|||||||
|
|
||||||
test_quotas "/var/lib/private" "StateDirectory=quotadir" "StateDirectoryQuota=1%"
|
test_quotas "/var/lib/private" "StateDirectory=quotadir" "StateDirectoryQuota=1%"
|
||||||
|
|
||||||
systemd-analyze log-level info
|
|
||||||
|
|
||||||
touch /testok
|
touch /testok
|
||||||
|
|||||||
@ -20,8 +20,6 @@ at_exit() {
|
|||||||
|
|
||||||
trap at_exit EXIT
|
trap at_exit EXIT
|
||||||
|
|
||||||
systemctl service-log-level systemd-importd debug
|
|
||||||
|
|
||||||
# Mount tmpfs over /var/lib/confexts to not pollute the image
|
# Mount tmpfs over /var/lib/confexts to not pollute the image
|
||||||
mkdir -p /var/lib/confexts
|
mkdir -p /var/lib/confexts
|
||||||
mount -t tmpfs tmpfs /var/lib/confexts -o mode=755
|
mount -t tmpfs tmpfs /var/lib/confexts -o mode=755
|
||||||
|
|||||||
@ -20,8 +20,6 @@ at_exit() {
|
|||||||
|
|
||||||
trap at_exit EXIT
|
trap at_exit EXIT
|
||||||
|
|
||||||
systemctl service-log-level systemd-machined debug
|
|
||||||
systemctl service-log-level systemd-importd debug
|
|
||||||
# per request in https://github.com/systemd/systemd/pull/35117
|
# per request in https://github.com/systemd/systemd/pull/35117
|
||||||
systemctl edit --runtime --stdin 'systemd-nspawn@.service' --drop-in=debug.conf <<EOF
|
systemctl edit --runtime --stdin 'systemd-nspawn@.service' --drop-in=debug.conf <<EOF
|
||||||
[Service]
|
[Service]
|
||||||
|
|||||||
@ -11,8 +11,6 @@ if [[ "$(get_cgroup_hierarchy)" != unified ]]; then
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
systemd-analyze log-level debug
|
|
||||||
|
|
||||||
# Multiple level process tree, parent process stays up
|
# Multiple level process tree, parent process stays up
|
||||||
cat >/tmp/test19-exit-cgroup.sh <<EOF
|
cat >/tmp/test19-exit-cgroup.sh <<EOF
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
@ -98,6 +96,3 @@ systemd-run --wait \
|
|||||||
--property="Type=notify" \
|
--property="Type=notify" \
|
||||||
--property="ExitType=cgroup" \
|
--property="ExitType=cgroup" \
|
||||||
/tmp/test19-exit-cgroup-parentless.sh 'systemctl kill --signal 9 six'
|
/tmp/test19-exit-cgroup-parentless.sh 'systemctl kill --signal 9 six'
|
||||||
|
|
||||||
|
|
||||||
systemd-analyze log-level info
|
|
||||||
|
|||||||
46
test/units/TEST-19-CGROUP.abort-on-cgroup-creation-failure.sh
Executable file
46
test/units/TEST-19-CGROUP.abort-on-cgroup-creation-failure.sh
Executable file
@ -0,0 +1,46 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
set -ex
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
# Test that the service is not invoked if the cgroup cannot be created.
|
||||||
|
|
||||||
|
# It seems openSUSE kernel (at least kernel-default-6.16.8-1.1.x86_64.rpm) has a
|
||||||
|
# bag in kernel oom killer or clone3 syscall, and spawning executor on a cgroup
|
||||||
|
# with too small MemoryMax= triggers infinite loop of OOM kill, and posix_spawn()
|
||||||
|
# will never return, and the service manager will stuck.
|
||||||
|
####
|
||||||
|
# [ 119.776797] systemd invoked oom-killer: gfp_mask=0xcc0(GFP_KERNEL), order=0, oom_score_adj=0
|
||||||
|
# [ 119.776859] CPU: 1 UID: 0 PID: 1472 Comm: systemd Not tainted 6.16.8-1-default #1 PREEMPT(voluntary) openSUSE Tumbleweed 6c85865973e4ae641870ed68afe8933a6986c974
|
||||||
|
# [ 119.776865] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.17.0-5.fc42 04/01/2014
|
||||||
|
# [ 119.776867] Call Trace:
|
||||||
|
# (snip)
|
||||||
|
# [ 119.778126] Out of memory and no killable processes...
|
||||||
|
####
|
||||||
|
# On other distributions, the oom killer is triggered, but clone3 immediately
|
||||||
|
# fails with ENOMEM, and such problematic loop does not happen.
|
||||||
|
. /etc/os-release
|
||||||
|
if [[ "$ID" =~ opensuse ]]; then
|
||||||
|
echo "Skipping cgroup test with too small MemoryMax= setting on openSUSE."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat >/run/systemd/system/testslice.slice <<EOF
|
||||||
|
[Slice]
|
||||||
|
MemoryMax=1
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat >/run/systemd/system/testservice.service <<EOF
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=cat /proc/self/cgroup
|
||||||
|
Slice=testslice.slice
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
(! systemctl start testservice.service)
|
||||||
|
|
||||||
|
rm /run/systemd/system/testslice.slice
|
||||||
|
rm /run/systemd/system/testservice.service
|
||||||
|
|
||||||
|
exit 0
|
||||||
@ -5,8 +5,6 @@ set -o pipefail
|
|||||||
|
|
||||||
# Test ExecReload= (PR #13098)
|
# Test ExecReload= (PR #13098)
|
||||||
|
|
||||||
systemd-analyze log-level debug
|
|
||||||
|
|
||||||
export SYSTEMD_PAGER=
|
export SYSTEMD_PAGER=
|
||||||
SERVICE_PATH="$(mktemp /etc/systemd/system/execreloadXXX.service)"
|
SERVICE_PATH="$(mktemp /etc/systemd/system/execreloadXXX.service)"
|
||||||
SERVICE_NAME="${SERVICE_PATH##*/}"
|
SERVICE_NAME="${SERVICE_PATH##*/}"
|
||||||
@ -57,5 +55,3 @@ systemctl status "$SERVICE_NAME"
|
|||||||
systemctl reload "$SERVICE_NAME"
|
systemctl reload "$SERVICE_NAME"
|
||||||
systemctl status "$SERVICE_NAME"
|
systemctl status "$SERVICE_NAME"
|
||||||
systemctl stop "$SERVICE_NAME"
|
systemctl stop "$SERVICE_NAME"
|
||||||
|
|
||||||
systemd-analyze log-level info
|
|
||||||
|
|||||||
@ -4,8 +4,6 @@ set -eux
|
|||||||
|
|
||||||
# Test that ExecStopPost= is always run
|
# Test that ExecStopPost= is always run
|
||||||
|
|
||||||
systemd-analyze log-level debug
|
|
||||||
|
|
||||||
systemd-run --unit=simple1.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=simple \
|
systemd-run --unit=simple1.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=simple \
|
||||||
-p ExecStopPost='touch /run/simple1' true
|
-p ExecStopPost='touch /run/simple1' true
|
||||||
test -f /run/simple1
|
test -f /run/simple1
|
||||||
@ -101,5 +99,3 @@ test -f /run/idle1
|
|||||||
(! systemd-run --unit=idle2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=idle \
|
(! systemd-run --unit=idle2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=idle \
|
||||||
-p ExecStopPost='touch /run/idle2' false)
|
-p ExecStopPost='touch /run/idle2' false)
|
||||||
test -f /run/idle2
|
test -f /run/idle2
|
||||||
|
|
||||||
systemd-analyze log-level info
|
|
||||||
|
|||||||
@ -18,8 +18,6 @@ mkdir /tmp/test-extra-fd
|
|||||||
echo "Hello" > /tmp/test-extra-fd/1.txt
|
echo "Hello" > /tmp/test-extra-fd/1.txt
|
||||||
echo "Extra" > /tmp/test-extra-fd/2.txt
|
echo "Extra" > /tmp/test-extra-fd/2.txt
|
||||||
|
|
||||||
systemd-analyze log-level debug
|
|
||||||
|
|
||||||
# Open files and assign FD to variables
|
# Open files and assign FD to variables
|
||||||
exec {TEST_FD1}</tmp/test-extra-fd/1.txt
|
exec {TEST_FD1}</tmp/test-extra-fd/1.txt
|
||||||
exec {TEST_FD2}</tmp/test-extra-fd/2.txt
|
exec {TEST_FD2}</tmp/test-extra-fd/2.txt
|
||||||
@ -61,5 +59,3 @@ assert_eq "$(systemctl show -P Result "$TEST_UNIT")" "success"
|
|||||||
assert_eq "$(systemctl show -P ExecMainStatus "$TEST_UNIT")" "0"
|
assert_eq "$(systemctl show -P ExecMainStatus "$TEST_UNIT")" "0"
|
||||||
|
|
||||||
systemctl stop "$TEST_UNIT"
|
systemctl stop "$TEST_UNIT"
|
||||||
|
|
||||||
systemctl log-level info
|
|
||||||
|
|||||||
@ -6,9 +6,6 @@ set -o pipefail
|
|||||||
|
|
||||||
# Test JoinsNamespaceOf= with PrivateTmp=yes
|
# Test JoinsNamespaceOf= with PrivateTmp=yes
|
||||||
|
|
||||||
systemd-analyze log-level debug
|
|
||||||
systemd-analyze log-target journal
|
|
||||||
|
|
||||||
# simple case
|
# simple case
|
||||||
systemctl start TEST-23-UNIT-FILE-joins-namespace-of-1.service
|
systemctl start TEST-23-UNIT-FILE-joins-namespace-of-1.service
|
||||||
systemctl start TEST-23-UNIT-FILE-joins-namespace-of-2.service
|
systemctl start TEST-23-UNIT-FILE-joins-namespace-of-2.service
|
||||||
@ -27,5 +24,3 @@ systemctl start TEST-23-UNIT-FILE-joins-namespace-of-8.service
|
|||||||
systemctl start TEST-23-UNIT-FILE-joins-namespace-of-9.service
|
systemctl start TEST-23-UNIT-FILE-joins-namespace-of-9.service
|
||||||
systemctl stop TEST-23-UNIT-FILE-joins-namespace-of-6.service
|
systemctl stop TEST-23-UNIT-FILE-joins-namespace-of-6.service
|
||||||
systemctl stop TEST-23-UNIT-FILE-joins-namespace-of-8.service
|
systemctl stop TEST-23-UNIT-FILE-joins-namespace-of-8.service
|
||||||
|
|
||||||
systemd-analyze log-level info
|
|
||||||
|
|||||||
@ -5,8 +5,6 @@ set -o pipefail
|
|||||||
|
|
||||||
# Test StandardOutput=file:
|
# Test StandardOutput=file:
|
||||||
|
|
||||||
systemd-analyze log-level debug
|
|
||||||
|
|
||||||
systemd-run --wait --unit=TEST-23-UNIT-FILE-standard-output-one \
|
systemd-run --wait --unit=TEST-23-UNIT-FILE-standard-output-one \
|
||||||
-p StandardOutput=file:/tmp/stdout \
|
-p StandardOutput=file:/tmp/stdout \
|
||||||
-p StandardError=file:/tmp/stderr \
|
-p StandardError=file:/tmp/stderr \
|
||||||
@ -56,5 +54,3 @@ EOF
|
|||||||
cmp /tmp/stderr <<EOF
|
cmp /tmp/stderr <<EOF
|
||||||
b
|
b
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
systemd-analyze log-level info
|
|
||||||
|
|||||||
@ -6,9 +6,6 @@ set -o pipefail
|
|||||||
|
|
||||||
# Test OnSuccess= + Uphold= + PropagatesStopTo= + BindsTo=
|
# Test OnSuccess= + Uphold= + PropagatesStopTo= + BindsTo=
|
||||||
|
|
||||||
systemd-analyze log-level debug
|
|
||||||
systemd-analyze log-target journal
|
|
||||||
|
|
||||||
# Idea is this:
|
# Idea is this:
|
||||||
# 1. we start TEST-23-UNIT-FILE-success.service
|
# 1. we start TEST-23-UNIT-FILE-success.service
|
||||||
# 2. which through OnSuccess= starts TEST-23-UNIT-FILE-fail.service,
|
# 2. which through OnSuccess= starts TEST-23-UNIT-FILE-fail.service,
|
||||||
@ -102,5 +99,3 @@ for _ in {1..120}; do
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
[[ "$sigrtmin1" == 1 ]]
|
[[ "$sigrtmin1" == 1 ]]
|
||||||
|
|
||||||
systemd-analyze log-level info
|
|
||||||
|
|||||||
@ -5,8 +5,6 @@ set -o pipefail
|
|||||||
|
|
||||||
# Test ExecXYZEx= service unit dbus hookups
|
# Test ExecXYZEx= service unit dbus hookups
|
||||||
|
|
||||||
systemd-analyze log-level debug
|
|
||||||
|
|
||||||
declare -A property
|
declare -A property
|
||||||
|
|
||||||
property[1_one]=ExecCondition
|
property[1_one]=ExecCondition
|
||||||
@ -31,5 +29,3 @@ for c in "${!property[@]}"; do
|
|||||||
systemctl show -p "${property[$c]}" "$c" | grep -F "path=echo ; argv[]=echo \${$c} ; ignore_errors=no"
|
systemctl show -p "${property[$c]}" "$c" | grep -F "path=echo ; argv[]=echo \${$c} ; ignore_errors=no"
|
||||||
systemctl show -p "${property[$c]}Ex" "$c" | grep -F "path=echo ; argv[]=echo \${$c} ; flags=no-env-expand"
|
systemctl show -p "${property[$c]}Ex" "$c" | grep -F "path=echo ; argv[]=echo \${$c} ; flags=no-env-expand"
|
||||||
done
|
done
|
||||||
|
|
||||||
systemd-analyze log-level info
|
|
||||||
|
|||||||
@ -11,8 +11,6 @@ set -o pipefail
|
|||||||
# wait this many secs for each test service to succeed in what is being tested
|
# wait this many secs for each test service to succeed in what is being tested
|
||||||
MAX_SECS=60
|
MAX_SECS=60
|
||||||
|
|
||||||
systemctl log-level debug
|
|
||||||
|
|
||||||
# test one: Restart=on-failure should restart the service
|
# test one: Restart=on-failure should restart the service
|
||||||
(! systemd-run --unit=oneshot-restart-one -p Type=oneshot -p Restart=on-failure bash -c "exit 1")
|
(! systemd-run --unit=oneshot-restart-one -p Type=oneshot -p Restart=on-failure bash -c "exit 1")
|
||||||
|
|
||||||
@ -97,5 +95,3 @@ EOF
|
|||||||
|
|
||||||
systemctl disable "$UNIT_NAME"
|
systemctl disable "$UNIT_NAME"
|
||||||
rm "$TMP_FILE" /run/systemd/system/{"$UNIT_NAME","$ONSUCCESS_UNIT_NAME"} "$FIFO_FILE"
|
rm "$TMP_FILE" /run/systemd/system/{"$UNIT_NAME","$ONSUCCESS_UNIT_NAME"} "$FIFO_FILE"
|
||||||
|
|
||||||
systemctl log-level info
|
|
||||||
|
|||||||
@ -14,8 +14,6 @@ at_exit() {
|
|||||||
|
|
||||||
trap at_exit EXIT
|
trap at_exit EXIT
|
||||||
|
|
||||||
systemctl log-level debug
|
|
||||||
|
|
||||||
# Existing files
|
# Existing files
|
||||||
|
|
||||||
mkdir /tmp/test-open-file
|
mkdir /tmp/test-open-file
|
||||||
@ -51,5 +49,3 @@ systemctl stop TEST-23-UNIT-FILE-openfile-server.socket
|
|||||||
|
|
||||||
assert_rc 202 systemd-run -p OpenFile=/run/missing/foo:missing-file:read-only --wait true
|
assert_rc 202 systemd-run -p OpenFile=/run/missing/foo:missing-file:read-only --wait true
|
||||||
assert_rc 0 systemd-run -p OpenFile=/run/missing/foo:missing-file:read-only,graceful --wait true
|
assert_rc 0 systemd-run -p OpenFile=/run/missing/foo:missing-file:read-only,graceful --wait true
|
||||||
|
|
||||||
systemctl log-level info
|
|
||||||
|
|||||||
@ -5,8 +5,6 @@ set -o pipefail
|
|||||||
|
|
||||||
# Test OnSuccess=/OnFailure= in combination
|
# Test OnSuccess=/OnFailure= in combination
|
||||||
|
|
||||||
systemd-analyze log-level debug
|
|
||||||
|
|
||||||
# Start-up should fail, but the automatic restart should fix it
|
# Start-up should fail, but the automatic restart should fix it
|
||||||
(! systemctl start success-failure-test )
|
(! systemctl start success-failure-test )
|
||||||
|
|
||||||
@ -45,5 +43,3 @@ done
|
|||||||
test "$(systemctl is-active success-failure-test-failure)" = "inactive"
|
test "$(systemctl is-active success-failure-test-failure)" = "inactive"
|
||||||
|
|
||||||
systemctl stop success-failure-test success-failure-test-success
|
systemctl stop success-failure-test success-failure-test-success
|
||||||
|
|
||||||
systemd-analyze log-level info
|
|
||||||
|
|||||||
@ -5,8 +5,6 @@ set -o pipefail
|
|||||||
|
|
||||||
# Test Type=exec
|
# Test Type=exec
|
||||||
|
|
||||||
systemd-analyze log-level debug
|
|
||||||
|
|
||||||
# Create a binary for which execve() will fail
|
# Create a binary for which execve() will fail
|
||||||
touch /tmp/brokenbinary
|
touch /tmp/brokenbinary
|
||||||
chmod +x /tmp/brokenbinary
|
chmod +x /tmp/brokenbinary
|
||||||
@ -59,5 +57,3 @@ busctl call \
|
|||||||
sleep 0 true \
|
sleep 0 true \
|
||||||
sleep 2 sleep 1 true \
|
sleep 2 sleep 1 true \
|
||||||
0)
|
0)
|
||||||
|
|
||||||
systemd-analyze log-level info
|
|
||||||
|
|||||||
@ -3,8 +3,6 @@
|
|||||||
set -eux
|
set -eux
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
systemd-analyze log-level debug
|
|
||||||
|
|
||||||
systemctl disable --now systemd-timesyncd.service
|
systemctl disable --now systemd-timesyncd.service
|
||||||
|
|
||||||
timedatectl set-timezone Europe/Berlin
|
timedatectl set-timezone Europe/Berlin
|
||||||
@ -61,6 +59,4 @@ while test ! -f /tmp/timezone-changed-alternate-path-2 ; do sleep .5 ; done
|
|||||||
rm /run/systemd/system.conf /run/systemd/system/systemd-timedated.service.d/override.conf
|
rm /run/systemd/system.conf /run/systemd/system/systemd-timedated.service.d/override.conf
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
|
|
||||||
systemd-analyze log-level info
|
|
||||||
|
|
||||||
touch /testok
|
touch /testok
|
||||||
|
|||||||
@ -10,8 +10,6 @@ set -o pipefail
|
|||||||
# kernels where the concept was still new.
|
# kernels where the concept was still new.
|
||||||
|
|
||||||
if test -f /sys/fs/cgroup/system.slice/TEST-32-OOMPOLICY.service/memory.oom.group; then
|
if test -f /sys/fs/cgroup/system.slice/TEST-32-OOMPOLICY.service/memory.oom.group; then
|
||||||
systemd-analyze log-level debug
|
|
||||||
|
|
||||||
# Run a service that is guaranteed to be the first candidate for OOM killing
|
# Run a service that is guaranteed to be the first candidate for OOM killing
|
||||||
systemd-run --unit=oomtest.service \
|
systemd-run --unit=oomtest.service \
|
||||||
-p Type=exec -p OOMScoreAdjust=1000 -p OOMPolicy=stop -p MemoryAccounting=yes \
|
-p Type=exec -p OOMScoreAdjust=1000 -p OOMPolicy=stop -p MemoryAccounting=yes \
|
||||||
@ -29,8 +27,6 @@ if test -f /sys/fs/cgroup/system.slice/TEST-32-OOMPOLICY.service/memory.oom.grou
|
|||||||
|
|
||||||
RESULT="$(systemctl show -P Result oomtest.service)"
|
RESULT="$(systemctl show -P Result oomtest.service)"
|
||||||
test "$RESULT" = "oom-kill"
|
test "$RESULT" = "oom-kill"
|
||||||
|
|
||||||
systemd-analyze log-level info
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
touch /testok
|
touch /testok
|
||||||
|
|||||||
@ -3,8 +3,6 @@
|
|||||||
set -eux
|
set -eux
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
systemd-analyze log-level debug
|
|
||||||
|
|
||||||
test_directory() {
|
test_directory() {
|
||||||
local directory="$1"
|
local directory="$1"
|
||||||
local path="$2"
|
local path="$2"
|
||||||
@ -239,6 +237,4 @@ if systemd-analyze compare-versions "$(uname -r)" ge 5.12; then
|
|||||||
test_check_idmapped_mounts_root
|
test_check_idmapped_mounts_root
|
||||||
fi
|
fi
|
||||||
|
|
||||||
systemd-analyze log-level info
|
|
||||||
|
|
||||||
touch /testok
|
touch /testok
|
||||||
|
|||||||
@ -21,9 +21,6 @@ at_exit() {
|
|||||||
|
|
||||||
trap at_exit EXIT
|
trap at_exit EXIT
|
||||||
|
|
||||||
systemd-analyze log-level debug
|
|
||||||
systemd-analyze log-target journal
|
|
||||||
|
|
||||||
# Log files
|
# Log files
|
||||||
straceLog='strace.log'
|
straceLog='strace.log'
|
||||||
journalLog='journal.log'
|
journalLog='journal.log'
|
||||||
@ -352,6 +349,4 @@ fi
|
|||||||
rm -rf "$confDir"
|
rm -rf "$confDir"
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
|
|
||||||
systemd-analyze log-level info
|
|
||||||
|
|
||||||
touch /testok
|
touch /testok
|
||||||
|
|||||||
@ -12,8 +12,6 @@ if [[ -n "${COVERAGE_BUILD_DIR:-}" ]]; then
|
|||||||
exit 77
|
exit 77
|
||||||
fi
|
fi
|
||||||
|
|
||||||
systemd-analyze log-level debug
|
|
||||||
|
|
||||||
unit=TEST-38-FREEZER-sleep.service
|
unit=TEST-38-FREEZER-sleep.service
|
||||||
|
|
||||||
start_test_service() {
|
start_test_service() {
|
||||||
|
|||||||
@ -13,13 +13,9 @@ fi
|
|||||||
|
|
||||||
install_extension_images
|
install_extension_images
|
||||||
|
|
||||||
systemd-analyze log-level debug
|
|
||||||
|
|
||||||
runas testuser systemd-run --wait --user --unit=test-private-users \
|
runas testuser systemd-run --wait --user --unit=test-private-users \
|
||||||
-p PrivateUsers=yes -P echo hello
|
-p PrivateUsers=yes -P echo hello
|
||||||
|
|
||||||
runas testuser systemctl --user log-level debug
|
|
||||||
|
|
||||||
runas testuser systemd-run --wait --user --unit=test-private-tmp-innerfile \
|
runas testuser systemd-run --wait --user --unit=test-private-tmp-innerfile \
|
||||||
-p PrivateTmp=yes \
|
-p PrivateTmp=yes \
|
||||||
-P touch /tmp/innerfile.txt
|
-P touch /tmp/innerfile.txt
|
||||||
@ -140,6 +136,4 @@ if unshare --mount --user --map-root-user mount -t overlay overlay /tmp/c -o low
|
|||||||
grep PORTABLE_PREFIXES=app1 /usr/lib/extension-release.d/extension-release.app2
|
grep PORTABLE_PREFIXES=app1 /usr/lib/extension-release.d/extension-release.app2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
systemd-analyze log-level info
|
|
||||||
|
|
||||||
touch /testok
|
touch /testok
|
||||||
|
|||||||
@ -2,8 +2,6 @@
|
|||||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
set -eux
|
set -eux
|
||||||
|
|
||||||
systemd-analyze log-level debug
|
|
||||||
|
|
||||||
journalctl --list-namespaces -o json | jq .
|
journalctl --list-namespaces -o json | jq .
|
||||||
|
|
||||||
systemd-run --wait -p LogNamespace=foobar echo "hello world"
|
systemd-run --wait -p LogNamespace=foobar echo "hello world"
|
||||||
@ -25,6 +23,4 @@ journalctl --list-namespaces -o json | jq .
|
|||||||
grep "^hello world$" /tmp/hello-world
|
grep "^hello world$" /tmp/hello-world
|
||||||
(! grep "^hello world$" /tmp/no-hello-world)
|
(! grep "^hello world$" /tmp/no-hello-world)
|
||||||
|
|
||||||
systemd-analyze log-level info
|
|
||||||
|
|
||||||
touch /testok
|
touch /testok
|
||||||
|
|||||||
@ -40,9 +40,6 @@ FSTYPE="$(stat --file-system --format "%T" /)"
|
|||||||
|
|
||||||
systemctl start systemd-homed.service systemd-userdbd.socket
|
systemctl start systemd-homed.service systemd-userdbd.socket
|
||||||
|
|
||||||
systemd-analyze log-level debug
|
|
||||||
systemctl service-log-level systemd-homed debug
|
|
||||||
|
|
||||||
# Create a tmpfs to use as backing store for the home dir. That way we can enforce a size limit nicely.
|
# Create a tmpfs to use as backing store for the home dir. That way we can enforce a size limit nicely.
|
||||||
mkdir -p /home
|
mkdir -p /home
|
||||||
mount -t tmpfs tmpfs /home -o size=290M
|
mount -t tmpfs tmpfs /home -o size=290M
|
||||||
@ -848,6 +845,4 @@ homectl inspect matchtest
|
|||||||
homectl inspect matchtest | grep "Area: quux3"
|
homectl inspect matchtest | grep "Area: quux3"
|
||||||
homectl remove matchtest
|
homectl remove matchtest
|
||||||
|
|
||||||
systemd-analyze log-level info
|
|
||||||
|
|
||||||
touch /testok
|
touch /testok
|
||||||
|
|||||||
@ -3,8 +3,6 @@
|
|||||||
set -ex
|
set -ex
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
systemd-analyze log-level debug
|
|
||||||
|
|
||||||
systemctl enable test-honor-first-shutdown.service
|
systemctl enable test-honor-first-shutdown.service
|
||||||
systemctl start test-honor-first-shutdown.service
|
systemctl start test-honor-first-shutdown.service
|
||||||
|
|
||||||
|
|||||||
97
test/units/TEST-53-TIMER.RandomizedDelaySec-reload.sh
Executable file
97
test/units/TEST-53-TIMER.RandomizedDelaySec-reload.sh
Executable file
@ -0,0 +1,97 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
#
|
||||||
|
# When deserializing a serialized timer unit with RandomizedDelaySec= set, systemd should use the last
|
||||||
|
# inactive exit timestamp instead of current realtime to calculate the new next elapse, so the timer unit
|
||||||
|
# actually runs in the given calendar window.
|
||||||
|
#
|
||||||
|
# Provides coverage for:
|
||||||
|
# - https://github.com/systemd/systemd/issues/18678
|
||||||
|
# - https://github.com/systemd/systemd/pull/27752
|
||||||
|
set -eux
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
# shellcheck source=test/units/test-control.sh
|
||||||
|
. "$(dirname "$0")"/util.sh
|
||||||
|
|
||||||
|
UNIT_NAME="timer-RandomizedDelaySec-$RANDOM"
|
||||||
|
TARGET_TS="$(date --date="tomorrow 00:10")"
|
||||||
|
TARGET_TS_S="$(date --date="$TARGET_TS" "+%s")"
|
||||||
|
# Maximum possible next elapse timestamp: $TARGET_TS (OnCalendar=) + 22 hours (RandomizedDelaySec=)
|
||||||
|
MAX_NEXT_ELAPSE_REALTIME_S="$((TARGET_TS_S + 22 * 60 * 60))"
|
||||||
|
MAX_NEXT_ELAPSE_REALTIME="$(date --date="@$MAX_NEXT_ELAPSE_REALTIME_S")"
|
||||||
|
|
||||||
|
# Let's make sure to return the date & time back to the original state once we're done with our time
|
||||||
|
# shenigans. One way to do this would be to use hwclock, but the RTC in VMs can be unreliable or slow to
|
||||||
|
# respond, causing unexpected test fails/timeouts.
|
||||||
|
#
|
||||||
|
# Instead, let's save the realtime timestamp before we start with the test together with a current monotonic
|
||||||
|
# timestamp, after the test ends take the difference between the current monotonic timestamp and the "start"
|
||||||
|
# one, add it to the originally saved realtime timestamp, and finally use that timestamp to set the system
|
||||||
|
# time. This should advance the system time by the amount of time the test actually ran, and hence restore it
|
||||||
|
# to some sane state after the time jumps performed by the test. It won't be perfect, but it should be close
|
||||||
|
# enough for our needs.
|
||||||
|
START_REALTIME="$(date "+%s")"
|
||||||
|
START_MONOTONIC="$(cut -d . -f 1 /proc/uptime)"
|
||||||
|
at_exit() {
|
||||||
|
: "Restore the system date to a sane state"
|
||||||
|
END_MONOTONIC="$(cut -d . -f 1 /proc/uptime)"
|
||||||
|
date --set="@$((START_REALTIME + END_MONOTONIC - START_MONOTONIC))"
|
||||||
|
}
|
||||||
|
trap at_exit EXIT
|
||||||
|
|
||||||
|
# Set some predictable time so we can schedule the first timer elapse in a deterministic-ish way
|
||||||
|
date --set="23:00"
|
||||||
|
|
||||||
|
# Setup
|
||||||
|
cat >"/run/systemd/system/$UNIT_NAME.timer" <<EOF
|
||||||
|
[Timer]
|
||||||
|
# Run this timer daily, ten minutes after midnight
|
||||||
|
OnCalendar=*-*-* 00:10:00
|
||||||
|
RandomizedDelaySec=22h
|
||||||
|
AccuracySec=1ms
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat >"/run/systemd/system/$UNIT_NAME.service" <<EOF
|
||||||
|
[Service]
|
||||||
|
ExecStart=echo "Hello world"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
check_elapse_timestamp() {
|
||||||
|
systemctl status "$UNIT_NAME.timer"
|
||||||
|
systemctl show -p InactiveExitTimestamp "$UNIT_NAME.timer"
|
||||||
|
|
||||||
|
NEXT_ELAPSE_REALTIME="$(systemctl show -P NextElapseUSecRealtime "$UNIT_NAME.timer")"
|
||||||
|
NEXT_ELAPSE_REALTIME_S="$(date --date="$NEXT_ELAPSE_REALTIME" "+%s")"
|
||||||
|
: "Next elapse timestamp should be $TARGET_TS <= $NEXT_ELAPSE_REALTIME <= $MAX_NEXT_ELAPSE_REALTIME"
|
||||||
|
assert_ge "$NEXT_ELAPSE_REALTIME_S" "$TARGET_TS_S"
|
||||||
|
assert_le "$NEXT_ELAPSE_REALTIME_S" "$MAX_NEXT_ELAPSE_REALTIME_S"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Restart the timer unit and check the initial next elapse timestamp
|
||||||
|
: "Initial next elapse timestamp"
|
||||||
|
systemctl restart "$UNIT_NAME.timer"
|
||||||
|
check_elapse_timestamp
|
||||||
|
|
||||||
|
# Bump the system date to 1 minute after the original calendar timer would've expired (without any random
|
||||||
|
# delay!) - systemd should recalculate the next elapse timestamp with a new randomized delay, but it should
|
||||||
|
# use the original inactive exit timestamp as a "base", so the final timestamp should not end up beyond the
|
||||||
|
# original calendar timestamp + randomized delay range.
|
||||||
|
#
|
||||||
|
# Similarly, do the same check after doing daemon-reload, as that also forces systemd to recalculate the next
|
||||||
|
# elapse timestamp (this goes through a slightly different codepath that actually contained the original
|
||||||
|
# issue).
|
||||||
|
: "Next elapse timestamp after time jump"
|
||||||
|
date -s "tomorrow 00:11"
|
||||||
|
check_elapse_timestamp
|
||||||
|
|
||||||
|
: "Next elapse timestamp after daemon-reload"
|
||||||
|
systemctl daemon-reload
|
||||||
|
check_elapse_timestamp
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
systemctl stop "$UNIT_NAME".{timer,service}
|
||||||
|
rm -f "/run/systemd/system/$UNIT_NAME".{timer,service}
|
||||||
|
systemctl daemon-reload
|
||||||
@ -3,10 +3,9 @@
|
|||||||
set -eux
|
set -eux
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
: >/failed
|
|
||||||
|
|
||||||
# Reset host date to current time, 3 days in the past.
|
# Reset host date to current time, 3 days in the past.
|
||||||
date -s "-3 days"
|
date -s "-3 days"
|
||||||
|
trap 'date -s "+3 days"' EXIT
|
||||||
|
|
||||||
# Run a timer for every 15 minutes.
|
# Run a timer for every 15 minutes.
|
||||||
systemd-run --unit test-timer --on-calendar "*:0/15:0" true
|
systemd-run --unit test-timer --on-calendar "*:0/15:0" true
|
||||||
@ -17,15 +16,12 @@ now=$(date +%s)
|
|||||||
time_delta=$((next_elapsed - now))
|
time_delta=$((next_elapsed - now))
|
||||||
|
|
||||||
# Check that the timer will elapse in less than 20 minutes.
|
# Check that the timer will elapse in less than 20 minutes.
|
||||||
((0 < time_delta && time_delta < 1200)) || {
|
if [[ "$time_delta" -lt 0 || "$time_delta" -gt 1200 ]]; then
|
||||||
echo 'Timer elapse outside of the expected 20 minute window.'
|
echo 'Timer elapse outside of the expected 20 minute window.'
|
||||||
echo " next_elapsed=${next_elapsed}"
|
echo " next_elapsed=${next_elapsed}"
|
||||||
echo " now=${now}"
|
echo " now=${now}"
|
||||||
echo " time_delta=${time_delta}"
|
echo " time_delta=${time_delta}"
|
||||||
echo ''
|
echo
|
||||||
} >>/failed
|
|
||||||
|
|
||||||
if test ! -s /failed ; then
|
exit 1
|
||||||
rm -f /failed
|
|
||||||
touch /testok
|
|
||||||
fi
|
fi
|
||||||
77
test/units/TEST-53-TIMER.restart-trigger.sh
Executable file
77
test/units/TEST-53-TIMER.restart-trigger.sh
Executable file
@ -0,0 +1,77 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
#
|
||||||
|
# Restarting an already elapsed timer shouldn't immediately trigger the corresponding service unit.
|
||||||
|
#
|
||||||
|
# Provides coverage for:
|
||||||
|
# - https://github.com/systemd/systemd/issues/31231
|
||||||
|
# - https://github.com/systemd/systemd/issues/35805
|
||||||
|
set -eux
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
# shellcheck source=test/units/test-control.sh
|
||||||
|
. "$(dirname "$0")"/util.sh
|
||||||
|
|
||||||
|
UNIT_NAME="timer-restart-$RANDOM"
|
||||||
|
TEST_MESSAGE="Hello from timer $RANDOM"
|
||||||
|
|
||||||
|
# Setup
|
||||||
|
cat >"/run/systemd/system/$UNIT_NAME.timer" <<EOF
|
||||||
|
[Timer]
|
||||||
|
OnCalendar=$(date --date="+1 hour" "+%Y-%m-%d %H:%M:%S")
|
||||||
|
AccuracySec=1s
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat >"/run/systemd/system/$UNIT_NAME.service" <<EOF
|
||||||
|
[Service]
|
||||||
|
ExecStart=echo "$TEST_MESSAGE"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
JOURNAL_TS="$(date "+%s")"
|
||||||
|
# Paranoia check that the test message is not already in the logs
|
||||||
|
(! journalctl -p info --since="@$JOURNAL_TS" --unit="$UNIT_NAME" --grep="$TEST_MESSAGE")
|
||||||
|
|
||||||
|
# Restart time timer and move time forward by 2 hours to trigger the timer
|
||||||
|
systemctl restart "$UNIT_NAME.timer"
|
||||||
|
systemctl status "$UNIT_NAME.timer"
|
||||||
|
|
||||||
|
date -s '+2 hours'
|
||||||
|
trap 'date -s "-2 hours"' EXIT
|
||||||
|
sleep 1
|
||||||
|
systemctl status "$UNIT_NAME.timer"
|
||||||
|
assert_eq "$(journalctl -q -p info --since="@$JOURNAL_TS" --unit="$UNIT_NAME" --grep="$TEST_MESSAGE" | wc -l)" "1"
|
||||||
|
|
||||||
|
# Restarting the timer unit shouldn't trigger neither the timer nor the service, so these
|
||||||
|
# fields should remain constant through the following tests
|
||||||
|
SERVICE_INV_ID="$(systemctl show --property=InvocationID "$UNIT_NAME.service")"
|
||||||
|
TIMER_LAST_TRIGGER="$(systemctl show --property=LastTriggerUSec "$UNIT_NAME.timer")"
|
||||||
|
|
||||||
|
# Now restart the timer and check if the timer and the service weren't triggered again
|
||||||
|
systemctl restart "$UNIT_NAME.timer"
|
||||||
|
sleep 5
|
||||||
|
assert_eq "$(journalctl -q -p info --since="@$JOURNAL_TS" --unit="$UNIT_NAME" --grep="$TEST_MESSAGE" | wc -l)" "1"
|
||||||
|
assert_eq "$SERVICE_INV_ID" "$(systemctl show --property=InvocationID "$UNIT_NAME.service")"
|
||||||
|
assert_eq "$TIMER_LAST_TRIGGER" "$(systemctl show --property=LastTriggerUSec "$UNIT_NAME.timer")"
|
||||||
|
|
||||||
|
# Set the timer into the past, restart it, and again check if it wasn't triggered
|
||||||
|
TIMER_TS="$(date --date="-1 day" "+%Y-%m-%d %H:%M:%S")"
|
||||||
|
mkdir "/run/systemd/system/$UNIT_NAME.timer.d/"
|
||||||
|
cat >"/run/systemd/system/$UNIT_NAME.timer.d/99-override.conf" <<EOF
|
||||||
|
[Timer]
|
||||||
|
OnCalendar=$TIMER_TS
|
||||||
|
EOF
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl status "$UNIT_NAME.timer"
|
||||||
|
assert_in "OnCalendar=$TIMER_TS" "$(systemctl show -P TimersCalendar "$UNIT_NAME".timer)"
|
||||||
|
systemctl restart "$UNIT_NAME.timer"
|
||||||
|
sleep 5
|
||||||
|
assert_eq "$(journalctl -q -p info --since="@$JOURNAL_TS" --unit="$UNIT_NAME" --grep="$TEST_MESSAGE" | wc -l)" "1"
|
||||||
|
assert_eq "$SERVICE_INV_ID" "$(systemctl show --property=InvocationID "$UNIT_NAME.service")"
|
||||||
|
assert_eq "$TIMER_LAST_TRIGGER" "$(systemctl show --property=LastTriggerUSec "$UNIT_NAME.timer")"
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
systemctl stop "$UNIT_NAME".{timer,service}
|
||||||
|
rm -f "/run/systemd/system/$UNIT_NAME".{timer,service}
|
||||||
|
systemctl daemon-reload
|
||||||
11
test/units/TEST-53-TIMER.sh
Executable file
11
test/units/TEST-53-TIMER.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
set -eux
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
# shellcheck source=test/units/test-control.sh
|
||||||
|
. "$(dirname "$0")"/test-control.sh
|
||||||
|
|
||||||
|
run_subtests
|
||||||
|
|
||||||
|
touch /testok
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user