Compare commits
19 Commits
91e50467f5
...
c0f765cac8
Author | SHA1 | Date |
---|---|---|
Christian Göttsche | c0f765cac8 | |
Christian Göttsche | f156e60c66 | |
Zbigniew Jędrzejewski-Szmek | 2979f04b99 | |
Zbigniew Jędrzejewski-Szmek | dc9fd22d3d | |
Ansgar Burchardt | eb1322744d | |
Zbigniew Jędrzejewski-Szmek | ce4121c6ff | |
Yu Watanabe | 41fd8fe716 | |
Yu Watanabe | fd3ef936ed | |
Lennart Poettering | 68bda079fd | |
Lennart Poettering | 44b0d1fd59 | |
Lennart Poettering | e3e6f99689 | |
Lennart Poettering | 61f9cf4e4c | |
Lennart Poettering | 5de0acf40d | |
Lennart Poettering | 219f3cd941 | |
Lennart Poettering | a7e8855879 | |
Lennart Poettering | 6bbd539e5e | |
Lennart Poettering | 49685fb314 | |
Lennart Poettering | 33a4c98342 | |
Lennart Poettering | 56a061f508 |
12
NEWS
12
NEWS
|
@ -257,13 +257,13 @@ CHANGES WITH 245 in spe:
|
|||
permanent MAC address of a network device even if a randomized MAC
|
||||
address is used.
|
||||
|
||||
* systemd-logind will now validate access to the operation for changing
|
||||
virtual terminals via a PolicyKit action. By default only users with
|
||||
at least one session on a local VT will get access to the method call.
|
||||
* systemd-logind will now validate access to the operation for changing
|
||||
virtual terminals via a PolicyKit action. By default only users with
|
||||
at least one session on a local VT will get access to the method call.
|
||||
|
||||
* When systemd sets up PAM sessions that invoked service processes shall
|
||||
run in, the pam_setcred() API is now invoked, thus permitting PAM
|
||||
modules to set additional credentials for the processes.
|
||||
* When systemd sets up PAM sessions that invoked service processes shall
|
||||
run in, the pam_setcred() API is now invoked, thus permitting PAM
|
||||
modules to set additional credentials for the processes.
|
||||
|
||||
…
|
||||
|
||||
|
|
3
TODO
3
TODO
|
@ -44,6 +44,9 @@ Features:
|
|||
* cryptsetup: allow encoding key directly in /etc/crypttab, maybe with a
|
||||
"base64:" prefix. Useful in particular for pkcs11 mode.
|
||||
|
||||
* cryptsetup: reimplement the mkswap/mke2fs in cryptsetup-generator to use
|
||||
systemd-makefs.service instead.
|
||||
|
||||
* socket units: allow creating a udev monitor socket with ListenDevices= or so,
|
||||
with matches, then actviate app thorugh that passing socket oveer
|
||||
|
||||
|
|
|
@ -1926,15 +1926,14 @@
|
|||
<term><varname>EmitDNS=</varname></term>
|
||||
<term><varname>DNS=</varname></term>
|
||||
|
||||
<listitem><para><varname>DNS=</varname> specifies a list of recursive
|
||||
DNS server IPv6 addresses that distributed via Router Advertisement
|
||||
messages when <varname>EmitDNS=</varname> is true. If <varname>DNS=
|
||||
</varname> is empty, DNS servers are read from the
|
||||
<literal>[Network]</literal> section. If the
|
||||
<literal>[Network]</literal> section does not contain any DNS servers
|
||||
either, DNS servers from the uplink with the highest priority default
|
||||
route are used. When <varname>EmitDNS=</varname> is false, no DNS server
|
||||
information is sent in Router Advertisement messages.
|
||||
<listitem><para><varname>DNS=</varname> specifies a list of recursive DNS server IPv6 addresses
|
||||
that are distributed via Router Advertisement messages when <varname>EmitDNS=</varname> is
|
||||
true. <varname>DNS=</varname> also takes special value <literal>_link_local</literal>; in that
|
||||
case the IPv6 link local address is distributed. If <varname>DNS=</varname> is empty, DNS
|
||||
servers are read from the <literal>[Network]</literal> section. If the
|
||||
<literal>[Network]</literal> section does not contain any DNS servers either, DNS servers from
|
||||
the uplink with the highest priority default route are used. When <varname>EmitDNS=</varname>
|
||||
is false, no DNS server information is sent in Router Advertisement messages.
|
||||
<varname>EmitDNS=</varname> defaults to true.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
<filename>cryptsetup-pre.target</filename>,
|
||||
<filename>cryptsetup.target</filename>,
|
||||
<filename>ctrl-alt-del.target</filename>,
|
||||
<filename>blockdev@.target</filename>,
|
||||
<filename>boot-complete.target</filename>,
|
||||
<filename>default.target</filename>,
|
||||
<filename>emergency.target</filename>,
|
||||
|
@ -845,6 +846,23 @@
|
|||
not useful as only unit within a transaction.</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><filename>blockdev@.target</filename></term>
|
||||
<listitem><para>This template unit may be used to order mount units and other consumers of block
|
||||
devices against services that synthesize these block devices. This is intended to be used to order
|
||||
storage services (such as
|
||||
<citerefentry><refentrytitle>systemd-cryptsetup@.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>)
|
||||
that allocate and manage a virtual block device against mount units and other consumers of
|
||||
it. Specifically, the storage services are supposed to be orderd before an instance of
|
||||
<filename>blockdev@.target</filename>, and the mount unit (or other consuming unit, such as a swap
|
||||
unit) after it. The ordering is particular relevant during shutdown, as it ensures that the mount
|
||||
is deactivated first and the service backing the mount only deactivated after that completed. The
|
||||
<filename>blockdev@.target</filename> instance should be pulled in via a <option>Wants=</option>
|
||||
dependency of the storage daemon and thus generally not be part of any transaction unless a storage
|
||||
daemon is used. The instance name for instances of this template unit is supposed to be the
|
||||
properly escaped bock device node path, e.g. <filename>blockdev@dev-mapper-foobar.target</filename>
|
||||
for a storage device <filename>/dev/mapper/foobar</filename>.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><filename>cryptsetup-pre.target</filename></term>
|
||||
<listitem>
|
||||
|
|
|
@ -3369,8 +3369,8 @@ if conf.get('ENABLE_EFI') == 1
|
|||
status += [
|
||||
'EFI machine type: @0@'.format(EFI_MACHINE_TYPE_NAME),
|
||||
'EFI CC @0@'.format(' '.join(efi_cc)),
|
||||
'EFI lib directory: @0@'.format(efi_libdir),
|
||||
'EFI lds directory: @0@'.format(efi_ldsdir),
|
||||
'EFI lds: @0@'.format(efi_lds),
|
||||
'EFI crt0: @0@'.format(efi_crt0),
|
||||
'EFI include directory: @0@'.format(efi_incdir)]
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -323,8 +323,6 @@ option('efi-ld', type : 'string',
|
|||
description : 'the linker to use for EFI modules')
|
||||
option('efi-libdir', type : 'string',
|
||||
description : 'path to the EFI lib directory')
|
||||
option('efi-ldsdir', type : 'string',
|
||||
description : 'path to the EFI lds directory')
|
||||
option('efi-includedir', type : 'string', value : '/usr/include/efi',
|
||||
description : 'path to the EFI header directory')
|
||||
option('tpm-pcrindex', type : 'integer', value : 8,
|
||||
|
|
|
@ -64,12 +64,19 @@ if conf.get('ENABLE_EFI') == 1 and get_option('gnu-efi') != 'false'
|
|||
|
||||
efi_libdir = get_option('efi-libdir')
|
||||
if efi_libdir == ''
|
||||
ret = run_command(efi_cc + ['-print-multi-os-directory'])
|
||||
if ret.returncode() == 0
|
||||
path = join_paths('/usr/lib', ret.stdout().strip())
|
||||
ret = run_command('realpath', '-e', path)
|
||||
if ret.returncode() == 0
|
||||
efi_libdir = ret.stdout().strip()
|
||||
# New location first introduced with gnu-efi 3.0.11
|
||||
efi_libdir = join_paths('/usr/lib/gnuefi', EFI_MACHINE_TYPE_NAME)
|
||||
cmd = run_command('test', '-e', efi_libdir)
|
||||
|
||||
if cmd.returncode() != 0
|
||||
# Fall back to the old approach
|
||||
cmd = run_command(efi_cc + ['-print-multi-os-directory'])
|
||||
if cmd.returncode() == 0
|
||||
path = join_paths('/usr/lib', cmd.stdout().strip())
|
||||
cmd = run_command('realpath', '-e', path)
|
||||
if cmd.returncode() == 0
|
||||
efi_libdir = cmd.stdout().strip()
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
@ -95,20 +102,35 @@ if have_gnu_efi
|
|||
|
||||
objcopy = find_program('objcopy')
|
||||
|
||||
efi_ldsdir = get_option('efi-ldsdir')
|
||||
arch_lds = 'elf_@0@_efi.lds'.format(gnu_efi_path_arch)
|
||||
if efi_ldsdir == ''
|
||||
efi_ldsdir = join_paths(efi_libdir, 'gnuefi')
|
||||
cmd = run_command('test', '-f', join_paths(efi_ldsdir, arch_lds))
|
||||
if cmd.returncode() != 0
|
||||
efi_ldsdir = efi_libdir
|
||||
cmd = run_command('test', '-f', join_paths(efi_ldsdir, arch_lds))
|
||||
if cmd.returncode() != 0
|
||||
error('Cannot find @0@'.format(arch_lds))
|
||||
efi_location_map = [
|
||||
# New locations first introduced with gnu-efi 3.0.11
|
||||
[join_paths(efi_libdir, 'efi.lds'),
|
||||
join_paths(efi_libdir, 'crt0.o')],
|
||||
# Older locations...
|
||||
[join_paths(efi_libdir, 'gnuefi', 'elf_@0@_efi.lds'.format(gnu_efi_path_arch)),
|
||||
join_paths(efi_libdir, 'gnuefi', 'crt0-efi-@0@.o'.format(gnu_efi_path_arch))],
|
||||
[join_paths(efi_libdir, 'elf_@0@_efi.lds'.format(gnu_efi_path_arch)),
|
||||
join_paths(efi_libdir, 'crt0-efi-@0@.o'.format(gnu_efi_path_arch))]]
|
||||
efi_lds = ''
|
||||
foreach location : efi_location_map
|
||||
if efi_lds == ''
|
||||
cmd = run_command('test', '-f', location[0])
|
||||
if cmd.returncode() == 0
|
||||
efi_lds = location[0]
|
||||
efi_crt0 = location[1]
|
||||
endif
|
||||
endif
|
||||
endforeach
|
||||
if efi_lds == ''
|
||||
if get_option('gnu-efi') == 'true'
|
||||
error('gnu-efi support requested, but cannot find efi.lds')
|
||||
else
|
||||
have_gnu_efi = false
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
if have_gnu_efi
|
||||
compile_args = ['-Wall',
|
||||
'-Wextra',
|
||||
'-std=gnu90',
|
||||
|
@ -145,14 +167,13 @@ if have_gnu_efi
|
|||
compile_args += ['-O2']
|
||||
endif
|
||||
|
||||
efi_ldflags = ['-T',
|
||||
join_paths(efi_ldsdir, arch_lds),
|
||||
efi_ldflags = ['-T', efi_lds,
|
||||
'-shared',
|
||||
'-Bsymbolic',
|
||||
'-nostdlib',
|
||||
'-znocombreloc',
|
||||
'-L', efi_libdir,
|
||||
join_paths(efi_ldsdir, 'crt0-efi-@0@.o'.format(gnu_efi_path_arch))]
|
||||
efi_crt0]
|
||||
if efi_arch == 'aarch64' or efi_arch == 'arm'
|
||||
# Aarch64 and ARM32 don't have an EFI capable objcopy. Use 'binary'
|
||||
# instead, and add required symbols manually.
|
||||
|
@ -219,11 +240,9 @@ if have_gnu_efi
|
|||
set_variable(tuple[0].underscorify(), so)
|
||||
set_variable(tuple[0].underscorify() + '_stub', stub)
|
||||
endforeach
|
||||
endif
|
||||
|
||||
############################################################
|
||||
############################################################
|
||||
|
||||
if have_gnu_efi
|
||||
test_efi_disk_img = custom_target(
|
||||
'test-efi-disk.img',
|
||||
input : [systemd_boot_so, stub_so_stub],
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "sd-bus.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "bus-util.h"
|
||||
#include "dbus-job.h"
|
||||
#include "dbus-unit.h"
|
||||
#include "dbus.h"
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "architecture.h"
|
||||
#include "build.h"
|
||||
#include "bus-common-errors.h"
|
||||
#include "bus-util.h"
|
||||
#include "dbus-cgroup.h"
|
||||
#include "dbus-execute.h"
|
||||
#include "dbus-job.h"
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "bpf-firewall.h"
|
||||
#include "bus-common-errors.h"
|
||||
#include "bus-polkit.h"
|
||||
#include "bus-util.h"
|
||||
#include "cgroup-util.h"
|
||||
#include "condition.h"
|
||||
#include "dbus-job.h"
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "bus-error.h"
|
||||
#include "bus-internal.h"
|
||||
#include "bus-polkit.h"
|
||||
#include "bus-util.h"
|
||||
#include "dbus-automount.h"
|
||||
#include "dbus-cgroup.h"
|
||||
#include "dbus-device.h"
|
||||
|
|
|
@ -217,7 +217,7 @@ static void mount_done(Unit *u) {
|
|||
m->timer_event_source = sd_event_source_unref(m->timer_event_source);
|
||||
}
|
||||
|
||||
_pure_ static MountParameters* get_mount_parameters_fragment(Mount *m) {
|
||||
static MountParameters* get_mount_parameters_fragment(Mount *m) {
|
||||
assert(m);
|
||||
|
||||
if (m->from_fragment)
|
||||
|
@ -226,7 +226,7 @@ _pure_ static MountParameters* get_mount_parameters_fragment(Mount *m) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
_pure_ static MountParameters* get_mount_parameters(Mount *m) {
|
||||
static MountParameters* get_mount_parameters(Mount *m) {
|
||||
assert(m);
|
||||
|
||||
if (m->from_proc_self_mountinfo)
|
||||
|
@ -342,20 +342,18 @@ static int mount_add_device_dependencies(Mount *m) {
|
|||
if (!is_device_path(p->what))
|
||||
return 0;
|
||||
|
||||
/* /dev/root is a really weird thing, it's not a real device,
|
||||
* but just a path the kernel exports for the root file system
|
||||
* specified on the kernel command line. Ignore it here. */
|
||||
if (path_equal(p->what, "/dev/root"))
|
||||
/* /dev/root is a really weird thing, it's not a real device, but just a path the kernel exports for
|
||||
* the root file system specified on the kernel command line. Ignore it here. */
|
||||
if (PATH_IN_SET(p->what, "/dev/root", "/dev/nfs"))
|
||||
return 0;
|
||||
|
||||
if (path_equal(m->where, "/"))
|
||||
return 0;
|
||||
|
||||
/* Mount units from /proc/self/mountinfo are not bound to devices
|
||||
* by default since they're subject to races when devices are
|
||||
* unplugged. But the user can still force this dep with an
|
||||
* appropriate option (or udev property) so the mount units are
|
||||
* automatically stopped when the device disappears suddenly. */
|
||||
/* Mount units from /proc/self/mountinfo are not bound to devices by default since they're subject to
|
||||
* races when devices are unplugged. But the user can still force this dep with an appropriate option
|
||||
* (or udev property) so the mount units are automatically stopped when the device disappears
|
||||
* suddenly. */
|
||||
dep = mount_is_bound_to_device(m) ? UNIT_BINDS_TO : UNIT_REQUIRES;
|
||||
|
||||
/* We always use 'what' from /proc/self/mountinfo if mounted */
|
||||
|
@ -365,7 +363,7 @@ static int mount_add_device_dependencies(Mount *m) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
return unit_add_blockdev_dependency(UNIT(m), p->what, mask);
|
||||
}
|
||||
|
||||
static int mount_add_quota_dependencies(Mount *m) {
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include "sd-bus.h"
|
||||
|
||||
#include "bus-util.h"
|
||||
#include "manager.h"
|
||||
|
||||
int mac_selinux_generic_access_check(sd_bus_message *message, const char *path, const char *permission, sd_bus_error *error);
|
||||
|
|
|
@ -184,21 +184,45 @@ static int swap_arm_timer(Swap *s, usec_t usec) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static SwapParameters* swap_get_parameters(Swap *s) {
|
||||
assert(s);
|
||||
|
||||
if (s->from_proc_swaps)
|
||||
return &s->parameters_proc_swaps;
|
||||
|
||||
if (s->from_fragment)
|
||||
return &s->parameters_fragment;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int swap_add_device_dependencies(Swap *s) {
|
||||
UnitDependencyMask mask;
|
||||
SwapParameters *p;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
if (!s->what)
|
||||
return 0;
|
||||
|
||||
if (!s->from_fragment)
|
||||
p = swap_get_parameters(s);
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
if (is_device_path(s->what))
|
||||
return unit_add_node_dependency(UNIT(s), s->what, UNIT_BINDS_TO, UNIT_DEPENDENCY_FILE);
|
||||
mask = s->from_proc_swaps ? UNIT_DEPENDENCY_PROC_SWAP : UNIT_DEPENDENCY_FILE;
|
||||
|
||||
/* File based swap devices need to be ordered after systemd-remount-fs.service,
|
||||
* since they might need a writable file system. */
|
||||
return unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_REMOUNT_FS_SERVICE, true, UNIT_DEPENDENCY_FILE);
|
||||
if (is_device_path(p->what)) {
|
||||
r = unit_add_node_dependency(UNIT(s), p->what, UNIT_REQUIRES, mask);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return unit_add_blockdev_dependency(UNIT(s), p->what, mask);
|
||||
}
|
||||
|
||||
/* File based swap devices need to be ordered after systemd-remount-fs.service, since they might need
|
||||
* a writable file system. */
|
||||
return unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_REMOUNT_FS_SERVICE, true, mask);
|
||||
}
|
||||
|
||||
static int swap_add_default_dependencies(Swap *s) {
|
||||
|
|
|
@ -3866,8 +3866,8 @@ int unit_deserialize_skip(FILE *f) {
|
|||
}
|
||||
|
||||
int unit_add_node_dependency(Unit *u, const char *what, UnitDependency dep, UnitDependencyMask mask) {
|
||||
Unit *device;
|
||||
_cleanup_free_ char *e = NULL;
|
||||
Unit *device;
|
||||
int r;
|
||||
|
||||
assert(u);
|
||||
|
@ -3879,8 +3879,7 @@ int unit_add_node_dependency(Unit *u, const char *what, UnitDependency dep, Unit
|
|||
if (!is_device_path(what))
|
||||
return 0;
|
||||
|
||||
/* When device units aren't supported (such as in a
|
||||
* container), don't create dependencies on them. */
|
||||
/* When device units aren't supported (such as in a container), don't create dependencies on them. */
|
||||
if (!unit_type_supported(UNIT_DEVICE))
|
||||
return 0;
|
||||
|
||||
|
@ -3900,6 +3899,33 @@ int unit_add_node_dependency(Unit *u, const char *what, UnitDependency dep, Unit
|
|||
device, true, mask);
|
||||
}
|
||||
|
||||
int unit_add_blockdev_dependency(Unit *u, const char *what, UnitDependencyMask mask) {
|
||||
_cleanup_free_ char *escaped = NULL, *target = NULL;
|
||||
int r;
|
||||
|
||||
assert(u);
|
||||
|
||||
if (isempty(what))
|
||||
return 0;
|
||||
|
||||
if (!path_startswith(what, "/dev/"))
|
||||
return 0;
|
||||
|
||||
/* If we don't support devices, then also don't bother with blockdev@.target */
|
||||
if (!unit_type_supported(UNIT_DEVICE))
|
||||
return 0;
|
||||
|
||||
r = unit_name_path_escape(what, &escaped);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_name_build("blockdev", escaped, ".target", &target);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return unit_add_dependency_by_name(u, UNIT_AFTER, target, true, mask);
|
||||
}
|
||||
|
||||
int unit_coldplug(Unit *u) {
|
||||
int r = 0, q;
|
||||
char **i;
|
||||
|
@ -5777,9 +5803,11 @@ bool unit_needs_console(Unit *u) {
|
|||
return exec_context_may_touch_console(ec);
|
||||
}
|
||||
|
||||
const char *unit_label_path(Unit *u) {
|
||||
const char *unit_label_path(const Unit *u) {
|
||||
const char *p;
|
||||
|
||||
assert(u);
|
||||
|
||||
/* Returns the file system path to use for MAC access decisions, i.e. the file to read the SELinux label off
|
||||
* when validating access checks. */
|
||||
|
||||
|
|
|
@ -743,6 +743,7 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds);
|
|||
int unit_deserialize_skip(FILE *f);
|
||||
|
||||
int unit_add_node_dependency(Unit *u, const char *what, UnitDependency d, UnitDependencyMask mask);
|
||||
int unit_add_blockdev_dependency(Unit *u, const char *what, UnitDependencyMask mask);
|
||||
|
||||
int unit_coldplug(Unit *u);
|
||||
void unit_catchup(Unit *u);
|
||||
|
@ -841,7 +842,7 @@ int unit_warn_leftover_processes(Unit *u);
|
|||
|
||||
bool unit_needs_console(Unit *u);
|
||||
|
||||
const char *unit_label_path(Unit *u);
|
||||
const char *unit_label_path(const Unit *u);
|
||||
|
||||
int unit_pid_attachable(Unit *unit, pid_t pid, sd_bus_error *error);
|
||||
|
||||
|
|
|
@ -99,7 +99,14 @@ static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_key
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int generate_keydev_mount(const char *name, const char *keydev, const char *keydev_timeout, bool canfail, char **unit, char **mount) {
|
||||
static int generate_keydev_mount(
|
||||
const char *name,
|
||||
const char *keydev,
|
||||
const char *keydev_timeout,
|
||||
bool canfail,
|
||||
char **unit,
|
||||
char **mount) {
|
||||
|
||||
_cleanup_free_ char *u = NULL, *where = NULL, *name_escaped = NULL, *device_unit = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
int r;
|
||||
|
@ -223,8 +230,8 @@ static int create_disk(
|
|||
const char *options) {
|
||||
|
||||
_cleanup_free_ char *n = NULL, *d = NULL, *u = NULL, *e = NULL,
|
||||
*keydev_mount = NULL, *keyfile_timeout_value = NULL, *password_escaped = NULL,
|
||||
*filtered = NULL, *u_escaped = NULL, *filtered_escaped = NULL, *name_escaped = NULL, *header_path = NULL;
|
||||
*keydev_mount = NULL, *keyfile_timeout_value = NULL,
|
||||
*filtered = NULL, *u_escaped = NULL, *name_escaped = NULL, *header_path = NULL, *password_buffer = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
const char *dmname;
|
||||
bool noauto, nofail, tmp, swap, netdev, attach_in_initrd;
|
||||
|
@ -285,39 +292,29 @@ static int create_disk(
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
fprintf(f,
|
||||
"[Unit]\n"
|
||||
"Description=Cryptography Setup for %%I\n"
|
||||
"Documentation=man:crypttab(5) man:systemd-cryptsetup-generator(8) man:systemd-cryptsetup@.service(8)\n"
|
||||
"SourcePath=%s\n"
|
||||
"DefaultDependencies=no\n"
|
||||
"IgnoreOnIsolate=true\n"
|
||||
"After=%s\n",
|
||||
arg_crypttab,
|
||||
netdev ? "remote-fs-pre.target" : "cryptsetup-pre.target");
|
||||
r = generator_write_cryptsetup_unit_section(f, arg_crypttab);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (netdev)
|
||||
fprintf(f, "After=remote-fs-pre.target\n");
|
||||
|
||||
/* If initrd takes care of attaching the disk then it should also detach it during shutdown. */
|
||||
if (!attach_in_initrd)
|
||||
fprintf(f, "Conflicts=umount.target\n");
|
||||
|
||||
if (password) {
|
||||
password_escaped = specifier_escape(password);
|
||||
if (!password_escaped)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
if (keydev) {
|
||||
_cleanup_free_ char *unit = NULL, *p = NULL;
|
||||
_cleanup_free_ char *unit = NULL;
|
||||
|
||||
r = generate_keydev_mount(name, keydev, keyfile_timeout_value, keyfile_can_timeout > 0, &unit, &keydev_mount);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to generate keydev mount unit: %m");
|
||||
|
||||
p = path_join(keydev_mount, password_escaped);
|
||||
if (!p)
|
||||
password_buffer = path_join(keydev_mount, password);
|
||||
if (!password_buffer)
|
||||
return log_oom();
|
||||
|
||||
free_and_replace(password_escaped, p);
|
||||
password = password_buffer;
|
||||
|
||||
fprintf(f, "After=%s\n", unit);
|
||||
if (keyfile_can_timeout > 0)
|
||||
|
@ -344,17 +341,13 @@ static int create_disk(
|
|||
return r;
|
||||
}
|
||||
|
||||
if (path_startswith(u, "/dev/")) {
|
||||
if (path_startswith(u, "/dev/"))
|
||||
fprintf(f,
|
||||
"BindsTo=%s\n"
|
||||
"After=%s\n"
|
||||
"Before=umount.target\n",
|
||||
d, d);
|
||||
|
||||
if (swap)
|
||||
fputs("Before=dev-mapper-%i.swap\n",
|
||||
f);
|
||||
} else
|
||||
else
|
||||
/* For loopback devices, add systemd-tmpfiles-setup-dev.service
|
||||
dependency to ensure that loopback support is available in
|
||||
the kernel (/dev/loop-control needs to exist) */
|
||||
|
@ -368,23 +361,9 @@ static int create_disk(
|
|||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to write device timeout drop-in: %m");
|
||||
|
||||
if (filtered) {
|
||||
filtered_escaped = specifier_escape(filtered);
|
||||
if (!filtered_escaped)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
fprintf(f,
|
||||
"\n[Service]\n"
|
||||
"Type=oneshot\n"
|
||||
"RemainAfterExit=yes\n"
|
||||
"TimeoutSec=0\n" /* the binary handles timeouts anyway */
|
||||
"KeyringMode=shared\n" /* make sure we can share cached keys among instances */
|
||||
"OOMScoreAdjust=500\n" /* unlocking can allocate a lot of memory if Argon2 is used */
|
||||
"ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n"
|
||||
"ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
|
||||
name_escaped, u_escaped, strempty(password_escaped), strempty(filtered_escaped),
|
||||
name_escaped);
|
||||
r = generator_write_cryptsetup_service_section(f, name, u, password, filtered);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (tmp)
|
||||
fprintf(f,
|
||||
|
|
|
@ -118,11 +118,18 @@ static int add_swap(
|
|||
|
||||
fprintf(f,
|
||||
"[Unit]\n"
|
||||
"SourcePath=%s\n"
|
||||
"Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n\n"
|
||||
"[Swap]\n",
|
||||
"Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n"
|
||||
"SourcePath=%s\n",
|
||||
fstab_path());
|
||||
|
||||
r = generator_write_blockdev_dependency(f, what);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
fprintf(f,
|
||||
"\n"
|
||||
"[Swap]\n");
|
||||
|
||||
r = write_what(f, what);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -174,8 +181,13 @@ static bool mount_in_initrd(struct mntent *me) {
|
|||
streq(me->mnt_dir, "/usr");
|
||||
}
|
||||
|
||||
static int write_timeout(FILE *f, const char *where, const char *opts,
|
||||
const char *filter, const char *variable) {
|
||||
static int write_timeout(
|
||||
FILE *f,
|
||||
const char *where,
|
||||
const char *opts,
|
||||
const char *filter,
|
||||
const char *variable) {
|
||||
|
||||
_cleanup_free_ char *timeout = NULL;
|
||||
char timespan[FORMAT_TIMESPAN_MAX];
|
||||
usec_t u;
|
||||
|
@ -208,8 +220,12 @@ static int write_mount_timeout(FILE *f, const char *where, const char *opts) {
|
|||
"x-systemd.mount-timeout\0", "TimeoutSec");
|
||||
}
|
||||
|
||||
static int write_dependency(FILE *f, const char *opts,
|
||||
const char *filter, const char *format) {
|
||||
static int write_dependency(
|
||||
FILE *f,
|
||||
const char *opts,
|
||||
const char *filter,
|
||||
const char *format) {
|
||||
|
||||
_cleanup_strv_free_ char **names = NULL, **units = NULL;
|
||||
_cleanup_free_ char *res = NULL;
|
||||
char **s;
|
||||
|
@ -230,6 +246,7 @@ static int write_dependency(FILE *f, const char *opts,
|
|||
r = unit_name_mangle_with_suffix(*s, "as dependency", 0, ".mount", &x);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to generate unit name: %m");
|
||||
|
||||
r = strv_consume(&units, x);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
@ -249,7 +266,8 @@ static int write_dependency(FILE *f, const char *opts,
|
|||
}
|
||||
|
||||
static int write_after(FILE *f, const char *opts) {
|
||||
return write_dependency(f, opts, "x-systemd.after", "After=%1$s\n");
|
||||
return write_dependency(f, opts,
|
||||
"x-systemd.after", "After=%1$s\n");
|
||||
}
|
||||
|
||||
static int write_requires_after(FILE *f, const char *opts) {
|
||||
|
@ -363,8 +381,8 @@ static int add_mount(
|
|||
|
||||
fprintf(f,
|
||||
"[Unit]\n"
|
||||
"SourcePath=%s\n"
|
||||
"Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n",
|
||||
"Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n"
|
||||
"SourcePath=%s\n",
|
||||
source);
|
||||
|
||||
/* All mounts under /sysroot need to happen later, at initrd-fs.target time. IOW, it's not
|
||||
|
@ -411,7 +429,14 @@ static int add_mount(
|
|||
return r;
|
||||
}
|
||||
|
||||
fprintf(f, "\n[Mount]\n");
|
||||
r = generator_write_blockdev_dependency(f, what);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
fprintf(f,
|
||||
"\n"
|
||||
"[Mount]\n");
|
||||
|
||||
if (original_where)
|
||||
fprintf(f, "# Canonicalized from %s\n", original_where);
|
||||
|
||||
|
|
|
@ -105,9 +105,8 @@ static int open_parent_block_device(dev_t devnum, int *ret_fd) {
|
|||
}
|
||||
|
||||
static int add_cryptsetup(const char *id, const char *what, bool rw, bool require, char **device) {
|
||||
_cleanup_free_ char *e = NULL, *n = NULL, *d = NULL, *id_escaped = NULL, *what_escaped = NULL;
|
||||
_cleanup_free_ char *e = NULL, *n = NULL, *d = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
const char *p;
|
||||
int r;
|
||||
|
||||
assert(id);
|
||||
|
@ -125,44 +124,28 @@ static int add_cryptsetup(const char *id, const char *what, bool rw, bool requir
|
|||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to generate unit name: %m");
|
||||
|
||||
id_escaped = specifier_escape(id);
|
||||
if (!id_escaped)
|
||||
return log_oom();
|
||||
r = generator_open_unit_file(arg_dest, NULL, n, &f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
what_escaped = specifier_escape(what);
|
||||
if (!what_escaped)
|
||||
return log_oom();
|
||||
|
||||
p = prefix_roota(arg_dest, n);
|
||||
f = fopen(p, "wxe");
|
||||
if (!f)
|
||||
return log_error_errno(errno, "Failed to create unit file %s: %m", p);
|
||||
r = generator_write_cryptsetup_unit_section(f, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
fprintf(f,
|
||||
"# Automatically generated by systemd-gpt-auto-generator\n\n"
|
||||
"[Unit]\n"
|
||||
"Description=Cryptography Setup for %%I\n"
|
||||
"Documentation=man:systemd-gpt-auto-generator(8) man:systemd-cryptsetup@.service(8)\n"
|
||||
"DefaultDependencies=no\n"
|
||||
"Conflicts=umount.target\n"
|
||||
"BindsTo=dev-mapper-%%i.device %s\n"
|
||||
"Before=umount.target cryptsetup.target\n"
|
||||
"After=%s\n"
|
||||
"IgnoreOnIsolate=true\n"
|
||||
"[Service]\n"
|
||||
"Type=oneshot\n"
|
||||
"RemainAfterExit=yes\n"
|
||||
"TimeoutSec=0\n" /* the binary handles timeouts anyway */
|
||||
"KeyringMode=shared\n" /* make sure we can share cached keys among instances */
|
||||
"ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '' '%s'\n"
|
||||
"ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
|
||||
d, d,
|
||||
id_escaped, what_escaped, rw ? "" : "read-only",
|
||||
id_escaped);
|
||||
"Conflicts=umount.target\n"
|
||||
"BindsTo=%s\n"
|
||||
"After=%s\n",
|
||||
d, d);
|
||||
|
||||
r = generator_write_cryptsetup_service_section(f, id, what, NULL, rw ? NULL : "read-only");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = fflush_and_check(f);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write file %s: %m", p);
|
||||
return log_error_errno(r, "Failed to write file %s: %m", n);
|
||||
|
||||
r = generator_add_symlink(arg_dest, d, "wants", n);
|
||||
if (r < 0)
|
||||
|
@ -227,7 +210,6 @@ static int add_mount(
|
|||
log_debug("Adding %s: %s fstype=%s", where, what, fstype ?: "(any)");
|
||||
|
||||
if (streq_ptr(fstype, "crypto_LUKS")) {
|
||||
|
||||
r = add_cryptsetup(id, what, rw, true, &crypto_what);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -262,6 +244,10 @@ static int add_mount(
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = generator_write_blockdev_dependency(f, what);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
fprintf(f,
|
||||
"\n"
|
||||
"[Mount]\n"
|
||||
|
@ -370,7 +356,14 @@ static int add_swap(const char *path) {
|
|||
"# Automatically generated by systemd-gpt-auto-generator\n\n"
|
||||
"[Unit]\n"
|
||||
"Description=Swap Partition\n"
|
||||
"Documentation=man:systemd-gpt-auto-generator(8)\n\n"
|
||||
"Documentation=man:systemd-gpt-auto-generator(8)\n");
|
||||
|
||||
r = generator_write_blockdev_dependency(f, path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
fprintf(f,
|
||||
"\n"
|
||||
"[Swap]\n"
|
||||
"What=%s\n",
|
||||
path);
|
||||
|
|
|
@ -1514,6 +1514,10 @@ static int link_acquire_ipv6_conf(Link *link) {
|
|||
|
||||
log_link_debug(link, "Starting IPv6 Router Advertisements");
|
||||
|
||||
r = radv_emit_dns(link);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to configure DNS or Domains in IPv6 Router Advertisement: %m");
|
||||
|
||||
r = sd_radv_start(link->radv);
|
||||
if (r < 0 && r != -EBUSY)
|
||||
return log_link_warning_errno(link, r, "Could not start IPv6 Router Advertisement: %m");
|
||||
|
|
|
@ -443,20 +443,29 @@ static int radv_get_ip6dns(Network *network, struct in6_addr **dns,
|
|||
|
||||
static int radv_set_dns(Link *link, Link *uplink) {
|
||||
_cleanup_free_ struct in6_addr *dns = NULL;
|
||||
size_t n_dns;
|
||||
usec_t lifetime_usec;
|
||||
size_t n_dns;
|
||||
int r;
|
||||
|
||||
if (!link->network->router_emit_dns)
|
||||
return 0;
|
||||
|
||||
if (link->network->router_dns) {
|
||||
dns = newdup(struct in6_addr, link->network->router_dns,
|
||||
link->network->n_router_dns);
|
||||
struct in6_addr *p;
|
||||
|
||||
dns = new(struct in6_addr, link->network->n_router_dns);
|
||||
if (!dns)
|
||||
return -ENOMEM;
|
||||
|
||||
n_dns = link->network->n_router_dns;
|
||||
p = dns;
|
||||
for (size_t i = 0; i < link->network->n_router_dns; i++)
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&link->network->router_dns[i])) {
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&link->ipv6ll_address))
|
||||
*(p++) = link->ipv6ll_address;
|
||||
} else
|
||||
*(p++) = link->network->router_dns[i];
|
||||
|
||||
n_dns = p - dns;
|
||||
lifetime_usec = link->network->router_dns_lifetime_usec;
|
||||
|
||||
goto set_dns;
|
||||
|
@ -620,7 +629,7 @@ int radv_configure(Link *link) {
|
|||
|
||||
}
|
||||
|
||||
return radv_emit_dns(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_radv_dns(
|
||||
|
@ -658,19 +667,30 @@ int config_parse_radv_dns(
|
|||
if (r == 0)
|
||||
break;
|
||||
|
||||
if (in_addr_from_string(AF_INET6, w, &a) >= 0) {
|
||||
struct in6_addr *m;
|
||||
if (streq(w, "_link_local"))
|
||||
a = IN_ADDR_NULL;
|
||||
else {
|
||||
r = in_addr_from_string(AF_INET6, w, &a);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||
"Failed to parse DNS server address, ignoring: %s", w);
|
||||
continue;
|
||||
}
|
||||
|
||||
m = reallocarray(n->router_dns, n->n_router_dns + 1, sizeof(struct in6_addr));
|
||||
if (!m)
|
||||
return log_oom();
|
||||
if (in_addr_is_null(AF_INET6, &a)) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0,
|
||||
"DNS server address is null, ignoring: %s", w);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
m[n->n_router_dns++] = a.in6;
|
||||
n->router_dns = m;
|
||||
struct in6_addr *m;
|
||||
m = reallocarray(n->router_dns, n->n_router_dns + 1, sizeof(struct in6_addr));
|
||||
if (!m)
|
||||
return log_oom();
|
||||
|
||||
} else
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0,
|
||||
"Failed to parse DNS server address, ignoring: %s", w);
|
||||
m[n->n_router_dns++] = a.in6;
|
||||
n->router_dns = m;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -519,6 +519,103 @@ int generator_enable_remount_fs_service(const char *dir) {
|
|||
SYSTEM_DATA_UNIT_PATH "/" SPECIAL_REMOUNT_FS_SERVICE);
|
||||
}
|
||||
|
||||
int generator_write_blockdev_dependency(
|
||||
FILE *f,
|
||||
const char *what) {
|
||||
|
||||
_cleanup_free_ char *escaped = NULL;
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
assert(what);
|
||||
|
||||
if (!path_startswith(what, "/dev/"))
|
||||
return 0;
|
||||
|
||||
r = unit_name_path_escape(what, &escaped);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to escape device node path %s: %m", what);
|
||||
|
||||
fprintf(f,
|
||||
"After=blockdev@%s.target\n",
|
||||
escaped);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int generator_write_cryptsetup_unit_section(
|
||||
FILE *f,
|
||||
const char *source) {
|
||||
|
||||
assert(f);
|
||||
|
||||
fprintf(f,
|
||||
"[Unit]\n"
|
||||
"Description=Cryptography Setup for %%I\n"
|
||||
"Documentation=man:crypttab(5) man:systemd-cryptsetup-generator(8) man:systemd-cryptsetup@.service(8)\n");
|
||||
|
||||
if (source)
|
||||
fprintf(f, "SourcePath=%s\n", source);
|
||||
|
||||
fprintf(f,
|
||||
"DefaultDependencies=no\n"
|
||||
"IgnoreOnIsolate=true\n"
|
||||
"After=cryptsetup-pre.target\n"
|
||||
"Before=blockdev@dev-mapper-%%i.target\n"
|
||||
"Wants=blockdev@dev-mapper-%%i.target\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int generator_write_cryptsetup_service_section(
|
||||
FILE *f,
|
||||
const char *name,
|
||||
const char *what,
|
||||
const char *password,
|
||||
const char *options) {
|
||||
|
||||
_cleanup_free_ char *name_escaped = NULL, *what_escaped = NULL, *password_escaped = NULL, *options_escaped = NULL;
|
||||
|
||||
assert(f);
|
||||
assert(name);
|
||||
assert(what);
|
||||
|
||||
name_escaped = specifier_escape(name);
|
||||
if (!name_escaped)
|
||||
return log_oom();
|
||||
|
||||
what_escaped = specifier_escape(what);
|
||||
if (!what_escaped)
|
||||
return log_oom();
|
||||
|
||||
if (password) {
|
||||
password_escaped = specifier_escape(password);
|
||||
if (!password_escaped)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
if (options) {
|
||||
options_escaped = specifier_escape(options);
|
||||
if (!options_escaped)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
fprintf(f,
|
||||
"\n"
|
||||
"[Service]\n"
|
||||
"Type=oneshot\n"
|
||||
"RemainAfterExit=yes\n"
|
||||
"TimeoutSec=0\n" /* The binary handles timeouts on its own */
|
||||
"KeyringMode=shared\n" /* Make sure we can share cached keys among instances */
|
||||
"OOMScoreAdjust=500\n" /* Unlocking can allocate a lot of memory if Argon2 is used */
|
||||
"ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n"
|
||||
"ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
|
||||
name_escaped, what_escaped, strempty(password_escaped), strempty(options_escaped),
|
||||
name_escaped);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void log_setup_generator(void) {
|
||||
log_set_prohibit_ipc(true);
|
||||
log_setup_service();
|
||||
|
|
|
@ -27,6 +27,21 @@ int generator_write_timeouts(
|
|||
const char *opts,
|
||||
char **filtered);
|
||||
|
||||
int generator_write_blockdev_dependency(
|
||||
FILE *f,
|
||||
const char *what);
|
||||
|
||||
int generator_write_cryptsetup_unit_section(
|
||||
FILE *f,
|
||||
const char *source);
|
||||
|
||||
int generator_write_cryptsetup_service_section(
|
||||
FILE *f,
|
||||
const char *name,
|
||||
const char *what,
|
||||
const char *password,
|
||||
const char *options);
|
||||
|
||||
int generator_write_device_deps(
|
||||
const char *dir,
|
||||
const char *what,
|
||||
|
|
|
@ -4,6 +4,10 @@ Name=veth-peer
|
|||
[Network]
|
||||
IPv6PrefixDelegation=yes
|
||||
|
||||
[IPv6PrefixDelegation]
|
||||
DNS=_link_local 2002:da8:1:0::1
|
||||
DNSLifetimeSec=1min
|
||||
|
||||
[IPv6Prefix]
|
||||
Prefix=2002:da8:1:0::/64
|
||||
PreferredLifetimeSec=1000s
|
||||
|
|
|
@ -2646,6 +2646,11 @@ class NetworkdRATests(unittest.TestCase, Utilities):
|
|||
start_networkd()
|
||||
self.wait_online(['veth99:routable', 'veth-peer:degraded'])
|
||||
|
||||
output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
|
||||
print(output)
|
||||
self.assertRegex(output, 'fe80::')
|
||||
self.assertRegex(output, '2002:da8:1::1')
|
||||
|
||||
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
|
||||
print(output)
|
||||
self.assertRegex(output, '2002:da8:1:0')
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
# SPDX-License-Identifier: LGPL-2.1+
|
||||
#
|
||||
# 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.
|
||||
|
||||
[Unit]
|
||||
Description=Block Device Preparation for %f
|
||||
Documentation=man:systemd.special(7)
|
||||
StopWhenUnneeded=yes
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
units = [
|
||||
['basic.target', ''],
|
||||
['blockdev@.target', ''],
|
||||
['bluetooth.target', ''],
|
||||
['boot-complete.target', ''],
|
||||
['cryptsetup-pre.target', 'HAVE_LIBCRYPTSETUP'],
|
||||
|
|
Loading…
Reference in New Issue