1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
7 #include "alloc-util.h"
9 #include "cgroup-util.h"
14 #include "fstab-util.h"
15 #include "generator.h"
16 #include "initrd-util.h"
18 #include "mkdir-label.h"
19 #include "mountpoint-util.h"
20 #include "parse-util.h"
21 #include "path-util.h"
23 #include "specifier.h"
24 #include "string-util.h"
25 #include "time-util.h"
26 #include "tmpfile-util.h"
27 #include "unit-name.h"
29 int generator_open_unit_file_full(
34 char **ret_final_path
,
35 char **ret_temp_path
) {
37 _cleanup_free_
char *p
= NULL
;
44 /* If <ret_temp_path> is specified, it creates a temporary unit file and also returns its
48 r
= fopen_temporary(dir
, &f
, &p
);
50 return log_error_errno(r
, "Failed to create temporary unit file in '%s': %m", dir
);
52 (void) fchmod(fileno(f
), 0644);
54 *ret_temp_path
= TAKE_PTR(p
);
58 p
= path_join(dir
, fn
);
62 r
= fopen_unlocked(p
, "wxe", &f
);
64 if (source
&& r
== -EEXIST
)
65 return log_error_errno(r
,
66 "Failed to create unit file '%s', as it already exists. Duplicate entry in '%s'?",
69 return log_error_errno(r
, "Failed to create unit file '%s': %m", p
);
74 "# Automatically generated by %s\n\n",
75 program_invocation_short_name
);
80 *ret_final_path
= TAKE_PTR(p
);
85 int generator_add_symlink_full(
90 const char *instance
) {
92 _cleanup_free_
char *dn
= NULL
, *fn
= NULL
, *instantiated
= NULL
, *to
= NULL
, *from
= NULL
;
99 /* If 'dep_type' is specified adds a symlink from <dst>.<dep_type>/ to <src> (if src is absolute) or ../<src> (otherwise).
101 * If 'dep_type' is NULL, it will create a symlink to <src> (i.e. create an alias.
103 * If <instance> is specified, then <src> must be a template unit name, and we'll instantiate it. */
105 r
= path_extract_directory(src
, &dn
);
106 if (r
< 0 && r
!= -EDESTADDRREQ
) /* EDESTADDRREQ → just a file name was passed */
107 return log_error_errno(r
, "Failed to extract directory name from '%s': %m", src
);
109 r
= path_extract_filename(src
, &fn
);
111 return log_error_errno(r
, "Failed to extract file name from '%s': %m", src
);
112 if (r
== O_DIRECTORY
)
113 return log_error_errno(SYNTHETIC_ERRNO(EISDIR
), "Expected path to regular file name, but got '%s', refusing.", src
);
116 r
= unit_name_replace_instance(fn
, instance
, &instantiated
);
118 return log_error_errno(r
, "Failed to instantiate '%s' for '%s': %m", fn
, instance
);
121 if (dep_type
) { /* Create a .wants/ style dep */
122 from
= path_join(dn
?: "..", fn
);
126 to
= strjoin(dir
, "/", dst
, ".", dep_type
, "/", instantiated
?: fn
);
127 } else { /* or create an alias */
128 from
= dn
? path_join(dn
, fn
) : strdup(fn
);
132 to
= strjoin(dir
, "/", dst
);
137 (void) mkdir_parents_label(to
, 0755);
139 if (symlink(from
, to
) < 0 && errno
!= EEXIST
)
140 return log_error_errno(errno
, "Failed to create symlink \"%s\": %m", to
);
145 static int generator_add_ordering(
150 const char *instance
) {
152 _cleanup_free_
char *instantiated
= NULL
, *p
= NULL
, *fn
= NULL
;
153 _cleanup_fclose_
FILE *f
= NULL
;
162 /* Adds in an explicit ordering dependency of type <order> from <src> to <dst>. If <instance> is
163 * specified, it is inserted into <dst>. */
166 r
= unit_name_replace_instance(dst
, instance
, &instantiated
);
168 return log_error_errno(r
, "Failed to instantiate '%s' for '%s': %m", dst
, instance
);
174 fn
= strjoin(src
, ".d/50-order-", to
, ".conf");
178 p
= path_join(dir
, fn
);
182 (void) mkdir_parents_label(p
, 0755);
184 r
= fopen_unlocked(p
, "wxe", &f
);
186 return log_error_errno(r
, "Failed to create '%s': %m", p
);
189 "# Automatically generated by %s\n\n"
192 program_invocation_short_name
,
196 r
= fflush_and_check(f
);
198 return log_error_errno(r
, "Failed to write drop-in '%s': %m", p
);
203 static int write_fsck_sysroot_service(
204 const char *unit
, /* Either SPECIAL_FSCK_ROOT_SERVICE or SPECIAL_FSCK_USR_SERVICE */
207 const char *extra_after
) {
209 _cleanup_free_
char *device
= NULL
, *escaped
= NULL
, *escaped2
= NULL
;
210 _cleanup_fclose_
FILE *f
= NULL
;
217 /* Writes out special versions of systemd-fsck-root.service and systemd-fsck-usr.service for use in
218 * the initrd. The regular statically shipped versions of these unit files use / and /usr for as
219 * paths, which doesn't match what we need for the initrd (where the dirs are /sysroot/ +
220 * /sysusr/usr/), hence we overwrite those versions here. */
222 escaped
= specifier_escape(what
);
226 escaped2
= cescape(escaped
);
230 r
= unit_name_from_path(what
, ".device", &device
);
232 return log_error_errno(r
, "Failed to convert device \"%s\" to unit name: %m", what
);
234 r
= generator_open_unit_file(dir
, /* source = */ NULL
, unit
, &f
);
240 "Description=File System Check on %1$s\n"
241 "Documentation=man:%2$s(8)\n"
243 "DefaultDependencies=no\n"
245 "Conflicts=shutdown.target\n"
246 "After=%4$s%5$slocal-fs-pre.target %3$s\n"
247 "Before=shutdown.target\n"
251 "RemainAfterExit=yes\n"
252 "ExecStart=" SYSTEMD_FSCK_PATH
" %6$s\n"
253 "TimeoutSec=infinity\n",
257 strempty(extra_after
),
258 isempty(extra_after
) ? "" : " ",
261 r
= fflush_and_check(f
);
263 return log_error_errno(r
, "Failed to write unit %s: %m", unit
);
268 int generator_write_fsck_deps(
274 const char *options
) {
283 /* Let's do an early exit if we are invoked for the root and /usr/ trees in the initrd, to avoid
284 * generating confusing log messages. */
285 if (in_initrd() && PATH_IN_SET(where
, "/", "/usr")) {
286 log_debug("Skipping fsck for %s in initrd.", where
);
291 if (!fstype_is_blockdev_backed(fstype
)) {
292 log_debug("Skipping file system check for non-block based file system '%s'.", what
);
296 if (fstype_is_ro(fstype
)) {
297 log_debug("Skipping file system check for read-only file system '%s'.", what
);
302 if (fstab_test_option(options
, "bind\0rbind\0")) {
303 log_debug("Skipping file system check for bind mount of '%s'.", what
);
307 if (!is_device_path(what
)) {
308 log_debug("Checking was requested for \"%s\", but it is not a device.", what
);
312 if (!isempty(fstype
) && !streq(fstype
, "auto")) {
313 r
= fsck_exists_for_fstype(fstype
);
315 log_warning_errno(r
, "Checking was requested for %s, but couldn't detect if fsck.%s may be used, proceeding: %m", what
, fstype
);
317 /* treat missing check as essentially OK */
318 log_debug("Checking was requested for %s, but fsck.%s does not exist.", what
, fstype
);
324 log_warning_errno(r
, "Checking was requested for %s, but couldn't detect if the fsck command may be used, proceeding: %m", what
);
326 /* treat missing fsck as essentially OK */
327 log_debug("Checking was requested for %s, but the fsck command does not exist.", what
);
332 if (path_equal(where
, "/")) {
335 /* We support running the fsck instance for the root fs while it is already mounted, for
336 * compatibility with non-initrd boots. It's ugly, but it is how it is. Since – unlike for
337 * regular file systems – this means the ordering is reversed (i.e. mount *before* fsck) we
338 * have a separate fsck unit for this, independent of systemd-fsck@.service. */
340 lnk
= strjoina(dir
, "/" SPECIAL_LOCAL_FS_TARGET
".wants/" SPECIAL_FSCK_ROOT_SERVICE
);
342 (void) mkdir_parents(lnk
, 0755);
343 if (symlink(SYSTEM_DATA_UNIT_DIR
"/" SPECIAL_FSCK_ROOT_SERVICE
, lnk
) < 0)
344 return log_error_errno(errno
, "Failed to create symlink %s: %m", lnk
);
347 _cleanup_free_
char *_fsck
= NULL
;
348 const char *fsck
, *dep
;
350 if (in_initrd() && path_equal(where
, "/sysroot")) {
351 r
= write_fsck_sysroot_service(SPECIAL_FSCK_ROOT_SERVICE
, dir
, what
, SPECIAL_INITRD_ROOT_DEVICE_TARGET
);
355 fsck
= SPECIAL_FSCK_ROOT_SERVICE
;
358 } else if (in_initrd() && path_equal(where
, "/sysusr/usr")) {
359 r
= write_fsck_sysroot_service(SPECIAL_FSCK_USR_SERVICE
, dir
, what
, NULL
);
363 fsck
= SPECIAL_FSCK_USR_SERVICE
;
366 /* When this is /usr, then let's add a Wants= dependency, otherwise a Requires=
367 * dependency. Why? We can't possibly unmount /usr during shutdown, but if we have a
368 * Requires= from /usr onto a fsck@.service unit and that unit is shut down, then
369 * we'd have to unmount /usr too. */
371 dep
= path_equal(where
, "/usr") ? "Wants" : "Requires";
373 r
= unit_name_from_path_instance("systemd-fsck", what
, ".service", &_fsck
);
375 return log_error_errno(r
, "Failed to create fsck service name: %m");
389 int generator_write_device_timeout(
395 /* Configure how long we wait for a device that backs a mount point or a
396 * swap partition to show up. This is useful to support endless device timeouts
397 * for devices that show up only after user input, like crypto devices. */
399 _cleanup_free_
char *node
= NULL
, *unit
= NULL
, *timeout
= NULL
;
406 r
= fstab_filter_options(opts
, "comment=systemd.device-timeout\0"
407 "x-systemd.device-timeout\0",
408 NULL
, &timeout
, NULL
, filtered
);
410 log_warning_errno(r
, "Failed to parse fstab options, ignoring: %m");
416 r
= parse_sec_fix_0(timeout
, &u
);
418 log_warning("Failed to parse timeout for device '%s', ignoring: %s", what
, timeout
);
422 node
= fstab_node_to_udev_node(what
);
425 if (!is_device_path(node
)) {
426 log_warning("'%s' is not a device path, ignoring x-systemd.device-timeout= option.", node
);
430 r
= unit_name_from_path(node
, ".device", &unit
);
432 return log_error_errno(r
, "Failed to make unit name from device path '%s': %m", node
);
434 r
= write_drop_in_format(dir
, unit
, 50, "device-timeout",
435 "# Automatically generated by %s\n"
436 "# from supplied options \"%s\"\n\n"
438 "JobRunningTimeoutSec=%s",
439 program_invocation_short_name
,
448 int generator_write_unit_timeout(
453 const char *unit_setting
) {
455 _cleanup_free_
char *timeout
= NULL
;
462 assert(unit_setting
);
464 r
= fstab_filter_options(opts
, filter
, NULL
, &timeout
, NULL
, NULL
);
466 return log_error_errno(r
, "Failed to parse options for '%s': %m", where
);
470 r
= parse_sec_fix_0(timeout
, &u
);
472 log_warning_errno(r
, "Failed to parse timeout '%s' for '%s', ignoring: %m", timeout
, where
);
476 fprintf(f
, "%s=%s\n", unit_setting
, FORMAT_TIMESPAN(u
, 0));
481 int generator_write_network_device_deps(
487 /* fstab records that specify _netdev option should apply the network
488 * ordering on the actual device depending on network connection. If we
489 * are not mounting real device (NFS, CIFS), we rely on _netdev effect
490 * on the mount unit itself. */
492 _cleanup_free_
char *node
= NULL
, *unit
= NULL
;
499 if (fstab_is_extrinsic(where
, opts
))
502 if (!fstab_test_option(opts
, "_netdev\0"))
505 node
= fstab_node_to_udev_node(what
);
509 /* Nothing to apply dependencies to. */
510 if (!is_device_path(node
))
513 r
= unit_name_from_path(node
, ".device", &unit
);
515 return log_error_errno(r
, "Failed to make unit name from path \"%s\": %m", node
);
517 /* See mount_add_default_dependencies for explanation why we create such
519 return write_drop_in_format(dir
, unit
, 50, "netdev-dependencies",
520 "# Automatically generated by %s\n\n"
522 "After=" SPECIAL_NETWORK_ONLINE_TARGET
" " SPECIAL_NETWORK_TARGET
"\n"
523 "Wants=" SPECIAL_NETWORK_ONLINE_TARGET
"\n",
524 program_invocation_short_name
);
527 int generator_write_initrd_root_device_deps(const char *dir
, const char *what
) {
528 _cleanup_free_
char *unit
= NULL
;
531 r
= unit_name_from_path(what
, ".device", &unit
);
533 return log_error_errno(r
, "Failed to make unit name from path \"%s\": %m",
536 return write_drop_in_format(dir
, SPECIAL_INITRD_ROOT_DEVICE_TARGET
, 50, "root-device",
537 "# Automatically generated by %s\n\n"
541 program_invocation_short_name
,
546 int generator_hook_up_mkswap(
550 _cleanup_free_
char *node
= NULL
, *unit
= NULL
, *escaped
= NULL
, *where_unit
= NULL
;
551 _cleanup_fclose_
FILE *f
= NULL
;
557 node
= fstab_node_to_udev_node(what
);
561 /* Nothing to work on. */
562 if (!is_device_path(node
))
563 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
564 "Cannot format something that is not a device node: %s",
567 r
= unit_name_from_path_instance("systemd-mkswap", node
, ".service", &unit
);
569 return log_error_errno(r
, "Failed to make unit instance name from path \"%s\": %m",
572 escaped
= cescape(node
);
576 r
= unit_name_from_path(what
, ".swap", &where_unit
);
578 return log_error_errno(r
, "Failed to make unit name from path \"%s\": %m",
581 r
= generator_open_unit_file(dir
, /* source = */ NULL
, unit
, &f
);
587 "Description=Make Swap on %%f\n"
588 "Documentation=man:systemd-mkswap@.service(8)\n"
590 "DefaultDependencies=no\n"
591 "BindsTo=%%i.device\n"
594 "Conflicts=shutdown.target\n"
595 "Before=shutdown.target\n"
599 "RemainAfterExit=yes\n"
600 "ExecStart="SYSTEMD_MAKEFS_PATH
" swap %s\n"
601 "TimeoutSec=infinity\n",
605 r
= fflush_and_check(f
);
607 return log_error_errno(r
, "Failed to write unit %s: %m", unit
);
609 return generator_add_symlink(dir
, where_unit
, "requires", unit
);
612 int generator_hook_up_mkfs(
618 _cleanup_free_
char *node
= NULL
, *unit
= NULL
, *escaped
= NULL
, *where_unit
= NULL
;
619 _cleanup_fclose_
FILE *f
= NULL
;
620 const char *fsck_unit
;
627 node
= fstab_node_to_udev_node(what
);
631 /* Nothing to work on. */
632 if (!is_device_path(node
))
633 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
634 "Cannot format something that is not a device node: %s",
637 if (!type
|| streq(type
, "auto"))
638 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
639 "Cannot format partition %s, filesystem type is not specified",
642 r
= unit_name_from_path_instance("systemd-makefs", node
, ".service", &unit
);
644 return log_error_errno(r
, "Failed to make unit instance name from path \"%s\": %m",
647 if (in_initrd() && path_equal(where
, "/sysroot"))
648 fsck_unit
= SPECIAL_FSCK_ROOT_SERVICE
;
649 else if (in_initrd() && path_equal(where
, "/sysusr/usr"))
650 fsck_unit
= SPECIAL_FSCK_USR_SERVICE
;
652 fsck_unit
= "systemd-fsck@%i.service";
654 escaped
= cescape(node
);
658 r
= unit_name_from_path(where
, ".mount", &where_unit
);
660 return log_error_errno(r
, "Failed to make unit name from path \"%s\": %m",
663 r
= generator_open_unit_file(dir
, /* source = */ NULL
, unit
, &f
);
669 "Description=Make File System on %%f\n"
670 "Documentation=man:systemd-makefs@.service(8)\n"
672 "DefaultDependencies=no\n"
673 "BindsTo=%%i.device\n"
675 /* fsck might or might not be used, so let's be safe and order
676 * ourselves before both systemd-fsck@.service and the mount unit. */
678 "Conflicts=shutdown.target\n"
679 "Before=shutdown.target\n"
683 "RemainAfterExit=yes\n"
684 "ExecStart="SYSTEMD_MAKEFS_PATH
" %s %s\n"
685 "TimeoutSec=infinity\n",
690 // XXX: what about local-fs-pre.target?
692 r
= fflush_and_check(f
);
694 return log_error_errno(r
, "Failed to write unit %s: %m", unit
);
696 return generator_add_symlink(dir
, where_unit
, "requires", unit
);
699 int generator_hook_up_growfs(
702 const char *target
) {
704 const char *growfs_unit
, *growfs_unit_path
;
705 _cleanup_free_
char *where_unit
= NULL
, *instance
= NULL
;
711 r
= unit_name_from_path(where
, ".mount", &where_unit
);
713 return log_error_errno(r
, "Failed to make unit name from path '%s': %m", where
);
715 if (empty_or_root(where
)) {
716 growfs_unit
= SPECIAL_GROWFS_ROOT_SERVICE
;
717 growfs_unit_path
= SYSTEM_DATA_UNIT_DIR
"/" SPECIAL_GROWFS_ROOT_SERVICE
;
719 growfs_unit
= SPECIAL_GROWFS_SERVICE
;
720 growfs_unit_path
= SYSTEM_DATA_UNIT_DIR
"/" SPECIAL_GROWFS_SERVICE
;
722 r
= unit_name_path_escape(where
, &instance
);
724 return log_error_errno(r
, "Failed to escape path '%s': %m", where
);
728 r
= generator_add_ordering(dir
, target
, "After", growfs_unit
, instance
);
733 return generator_add_symlink_full(dir
, where_unit
, "wants", growfs_unit_path
, instance
);
736 int generator_hook_up_pcrfs(
739 const char *target
) {
741 const char *pcrfs_unit
, *pcrfs_unit_path
;
742 _cleanup_free_
char *where_unit
= NULL
, *instance
= NULL
;
748 r
= unit_name_from_path(where
, ".mount", &where_unit
);
750 return log_error_errno(r
, "Failed to make unit name from path '%s': %m", where
);
752 if (empty_or_root(where
)) {
753 pcrfs_unit
= SPECIAL_PCRFS_ROOT_SERVICE
;
754 pcrfs_unit_path
= SYSTEM_DATA_UNIT_DIR
"/" SPECIAL_PCRFS_ROOT_SERVICE
;
756 pcrfs_unit
= SPECIAL_PCRFS_SERVICE
;
757 pcrfs_unit_path
= SYSTEM_DATA_UNIT_DIR
"/" SPECIAL_PCRFS_SERVICE
;
759 r
= unit_name_path_escape(where
, &instance
);
761 return log_error_errno(r
, "Failed to escape path '%s': %m", where
);
765 r
= generator_add_ordering(dir
, target
, "After", pcrfs_unit
, instance
);
770 return generator_add_symlink_full(dir
, where_unit
, "wants", pcrfs_unit_path
, instance
);
773 int generator_hook_up_validatefs(
776 const char *target
) {
778 _cleanup_free_
char *where_unit
= NULL
, *instance
= NULL
;
779 const char *validatefs_unit
, *validatefs_unit_path
;
785 /* never hook this in for the actual root fs, because it's too late then, we already are running from
786 * the root fs, it makes no sense to validate it anymore */
787 if (empty_or_root(where
))
790 r
= unit_name_from_path(where
, ".mount", &where_unit
);
792 return log_error_errno(r
, "Failed to make unit name from path '%s': %m", where
);
794 validatefs_unit
= SPECIAL_VALIDATEFS_SERVICE
;
795 validatefs_unit_path
= SYSTEM_DATA_UNIT_DIR
"/" SPECIAL_VALIDATEFS_SERVICE
;
797 r
= unit_name_path_escape(where
, &instance
);
799 return log_error_errno(r
, "Failed to escape path '%s': %m", where
);
802 r
= generator_add_ordering(dir
, target
, "After", validatefs_unit
, instance
);
807 return generator_add_symlink_full(dir
, where_unit
, "wants", validatefs_unit_path
, instance
);
810 int generator_hook_up_quotacheck(
815 const char *fstype
) {
817 _cleanup_free_
char *where_unit
= NULL
, *instance
= NULL
;
823 if (isempty(fstype
) || streq(fstype
, "auto"))
824 return log_warning_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Couldn't determine filesystem type for %s, quota cannot be activated", what
);
825 if (!fstype_needs_quota(fstype
))
826 return log_warning_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Quota was requested for %s, but not supported, ignoring: %s", what
, fstype
);
828 /* quotacheck unit for system root */
829 if (path_equal(where
, "/"))
830 return generator_add_symlink(dir
, SPECIAL_LOCAL_FS_TARGET
, "wants", SYSTEM_DATA_UNIT_DIR
"/" SPECIAL_QUOTACHECK_ROOT_SERVICE
);
832 r
= unit_name_path_escape(where
, &instance
);
834 return log_error_errno(r
, "Failed to escape path '%s': %m", where
);
837 r
= generator_add_ordering(dir
, target
, "After", SPECIAL_QUOTACHECK_SERVICE
, instance
);
842 r
= unit_name_from_path(where
, ".mount", &where_unit
);
844 return log_error_errno(r
, "Failed to make unit name from path '%s': %m", where
);
846 return generator_add_symlink_full(dir
, where_unit
, "wants", SYSTEM_DATA_UNIT_DIR
"/" SPECIAL_QUOTACHECK_SERVICE
, instance
);
849 int generator_hook_up_quotaon(
852 const char *target
) {
854 _cleanup_free_
char *where_unit
= NULL
, *instance
= NULL
;
860 /* quotaon unit for system root is not instantiated */
861 if (path_equal(where
, "/"))
862 return generator_add_symlink(dir
, SPECIAL_LOCAL_FS_TARGET
, "wants", SYSTEM_DATA_UNIT_DIR
"/" SPECIAL_QUOTAON_ROOT_SERVICE
);
864 r
= unit_name_path_escape(where
, &instance
);
866 return log_error_errno(r
, "Failed to escape path '%s': %m", where
);
869 r
= generator_add_ordering(dir
, target
, "After", SPECIAL_QUOTAON_SERVICE
, instance
);
874 r
= unit_name_from_path(where
, ".mount", &where_unit
);
876 return log_error_errno(r
, "Failed to make unit name from path '%s': %m", where
);
878 return generator_add_symlink_full(dir
, where_unit
, "wants", SYSTEM_DATA_UNIT_DIR
"/" SPECIAL_QUOTAON_SERVICE
, instance
);
881 int generator_enable_remount_fs_service(const char *dir
) {
882 /* Pull in systemd-remount-fs.service */
883 return generator_add_symlink(dir
, SPECIAL_LOCAL_FS_TARGET
, "wants",
884 SYSTEM_DATA_UNIT_DIR
"/" SPECIAL_REMOUNT_FS_SERVICE
);
887 int generator_write_blockdev_dependency(FILE *f
, const char *what
) {
888 _cleanup_free_
char *escaped
= NULL
;
894 if (!path_startswith(what
, "/dev/"))
897 r
= unit_name_path_escape(what
, &escaped
);
899 return log_error_errno(r
, "Failed to escape device node path %s: %m", what
);
902 "After=blockdev@%s.target\n",
908 int generator_write_cryptsetup_unit_section(FILE *f
, const char *source
) {
913 "Description=Cryptography Setup for %%I\n"
914 "Documentation=man:crypttab(5) man:systemd-cryptsetup-generator(8) man:systemd-cryptsetup@.service(8)\n");
917 fprintf(f
, "SourcePath=%s\n", source
);
921 "DefaultDependencies=no\n"
922 "After=cryptsetup-pre.target systemd-udevd-kernel.socket systemd-tpm2-setup-early.service\n"
923 "Before=blockdev@dev-mapper-%%i.target\n"
924 "Wants=blockdev@dev-mapper-%%i.target\n"
925 "IgnoreOnIsolate=true\n");
930 int generator_write_cryptsetup_service_section(
934 const char *key_file
,
935 const char *options
) {
937 _cleanup_free_
char *name_escaped
= NULL
, *what_escaped
= NULL
, *key_file_escaped
= NULL
, *options_escaped
= NULL
;
943 name_escaped
= specifier_escape(name
);
947 what_escaped
= specifier_escape(what
);
952 key_file_escaped
= specifier_escape(key_file
);
953 if (!key_file_escaped
)
958 options_escaped
= specifier_escape(options
);
959 if (!options_escaped
)
967 "RemainAfterExit=yes\n"
968 "TimeoutSec=infinity\n" /* The binary handles timeouts on its own */
969 "KeyringMode=shared\n" /* Make sure we can share cached keys among instances */
970 "OOMScoreAdjust=500\n" /* Unlocking can allocate a lot of memory if Argon2 is used */
971 "ImportCredential=cryptsetup.*\n"
972 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH
" attach '%s' '%s' '%s' '%s'\n"
973 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH
" detach '%s'\n",
974 name_escaped
, what_escaped
, strempty(key_file_escaped
), strempty(options_escaped
),
980 int generator_write_veritysetup_unit_section(FILE *f
, const char *source
) {
985 "Description=Integrity Protection Setup for %%I\n"
986 "Documentation=man:veritytab(5) man:systemd-veritysetup-generator(8) man:systemd-veritysetup@.service(8)\n");
989 fprintf(f
, "SourcePath=%s\n", source
);
992 "DefaultDependencies=no\n"
993 "IgnoreOnIsolate=true\n"
994 "After=veritysetup-pre.target systemd-udevd-kernel.socket\n"
995 "Before=blockdev@dev-mapper-%%i.target\n"
996 "Wants=blockdev@dev-mapper-%%i.target\n");
1001 int generator_write_veritysetup_service_section(
1004 const char *data_what
,
1005 const char *hash_what
,
1006 const char *roothash
,
1007 const char *options
) {
1009 _cleanup_free_
char *name_escaped
= NULL
, *data_what_escaped
= NULL
, *hash_what_escaped
= NULL
,
1010 *roothash_escaped
= NULL
, *options_escaped
= NULL
;
1017 name_escaped
= specifier_escape(name
);
1021 data_what_escaped
= specifier_escape(data_what
);
1022 if (!data_what_escaped
)
1025 hash_what_escaped
= specifier_escape(hash_what
);
1026 if (!hash_what_escaped
)
1030 roothash_escaped
= specifier_escape(roothash
);
1031 if (!roothash_escaped
)
1036 options_escaped
= specifier_escape(options
);
1037 if (!options_escaped
)
1045 "RemainAfterExit=yes\n"
1046 "ExecStart=" SYSTEMD_VERITYSETUP_PATH
" attach '%s' '%s' '%s' '%s' '%s'\n"
1047 "ExecStop=" SYSTEMD_VERITYSETUP_PATH
" detach '%s'\n",
1048 name_escaped
, data_what_escaped
, hash_what_escaped
, empty_to_dash(roothash_escaped
), strempty(options_escaped
),
1054 void log_setup_generator(void) {
1055 if (invoked_by_systemd()) {
1056 /* Disable talking to syslog/journal (i.e. the two IPC-based loggers) if we run in system context. */
1057 if (streq_ptr(getenv("SYSTEMD_SCOPE"), "system"))
1058 log_set_prohibit_ipc(true);
1060 /* This effectively means: journal for per-user service manager generators, kmsg for per-system service manager generators */
1061 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG
);
1063 log_set_target(LOG_TARGET_AUTO
);
1065 log_parse_environment();
1069 bool generator_soft_rebooted(void) {
1070 static int cached
= -1;
1076 const char *e
= secure_getenv("SYSTEMD_SOFT_REBOOTS_COUNT");
1078 return (cached
= false);
1082 r
= safe_atou(e
, &u
);
1084 log_debug_errno(r
, "Failed to parse $SYSTEMD_SOFT_REBOOTS_COUNT, assuming the system hasn't soft-rebooted: %m");
1085 return (cached
= false);
1088 return (cached
= (u
> 0));
1091 GptAutoRoot
parse_gpt_auto_root(const char *switch_name
, const char *value
) {
1092 assert(switch_name
);
1095 /* Parses the 'gpt-auto'/'gpt-auto-root'/'dissect'/'dissect-force' parameters to root=
1097 * note that we are not using a regular string table here, because the mode names don't fully match
1098 * the parameter names. And root= being something else is not an error. */
1100 if (streq(value
, "gpt-auto")) {
1101 log_debug("Enabling partition auto-detection (respecting factory reset mode), %s is explicitly set to 'gpt-auto'.", switch_name
);
1102 return GPT_AUTO_ROOT_ON
;
1105 if (streq(value
, "gpt-auto-force")) {
1106 log_debug("Enabling partition auto-detection (ignoring factory reset mode), %s is explicitly set to 'gpt-auto-force'.", switch_name
);
1107 return GPT_AUTO_ROOT_FORCE
;
1110 if (streq(value
, "dissect")) {
1111 log_debug("Enabling partition auto-detection via full image dissection (respecting factory reset mode), %s is explicitly set to 'dissect'.", switch_name
);
1112 return GPT_AUTO_ROOT_DISSECT
;
1115 if (streq(value
, "dissect-force")) {
1116 log_debug("Enabling partition auto-detection via full image dissection (ignoring factory reset mode), %s is explicitly set to 'dissect-force'.", switch_name
);
1117 return GPT_AUTO_ROOT_DISSECT_FORCE
;
1120 if (streq(value
, "off"))
1121 log_debug("Disabling partition auto-detection, %s handling is explicitly turned off.", switch_name
);
1123 log_debug("Disabling partition auto-detection, %s is neither unset, nor set to 'gpt-auto', 'gpt-auto-force', 'dissect' or 'dissect-force'.", switch_name
);
1125 return GPT_AUTO_ROOT_OFF
;