diff options
Diffstat (limited to 'src/shared/generator.c')
-rw-r--r-- | src/shared/generator.c | 225 |
1 files changed, 218 insertions, 7 deletions
diff --git a/src/shared/generator.c b/src/shared/generator.c index 18fc469098..3495a7ef7d 100644 --- a/src/shared/generator.c +++ b/src/shared/generator.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -32,6 +33,7 @@ #include "mkdir.h" #include "path-util.h" #include "special.h" +#include "specifier.h" #include "string-util.h" #include "time-util.h" #include "unit-name.h" @@ -54,15 +56,19 @@ int generator_add_symlink(const char *root, const char *dst, const char *dep_typ } static int write_fsck_sysroot_service(const char *dir, const char *what) { - _cleanup_free_ char *device = NULL, *escaped = NULL; + _cleanup_free_ char *device = NULL, *escaped = NULL, *escaped2 = NULL; _cleanup_fclose_ FILE *f = NULL; const char *unit; int r; - escaped = cescape(what); + escaped = specifier_escape(what); if (!escaped) return log_oom(); + escaped2 = cescape(escaped); + if (!escaped2) + return log_oom(); + unit = strjoina(dir, "/systemd-fsck-root.service"); log_debug("Creating %s", unit); @@ -77,8 +83,8 @@ static int write_fsck_sysroot_service(const char *dir, const char *what) { fprintf(f, "# Automatically generated by %1$s\n\n" "[Unit]\n" - "Documentation=man:systemd-fsck-root.service(8)\n" "Description=File System Check on %2$s\n" + "Documentation=man:systemd-fsck-root.service(8)\n" "DefaultDependencies=no\n" "BindsTo=%3$s\n" "After=initrd-root-device.target local-fs-pre.target %3$s\n" @@ -90,9 +96,9 @@ static int write_fsck_sysroot_service(const char *dir, const char *what) { "ExecStart=" SYSTEMD_FSCK_PATH " %4$s\n" "TimeoutSec=0\n", program_invocation_short_name, - what, + escaped, device, - escaped); + escaped2); r = fflush_and_check(f); if (r < 0) @@ -242,7 +248,8 @@ int generator_write_device_deps( r = unit_name_from_path(node, ".device", &unit); if (r < 0) - return log_error_errno(r, "Failed to make unit name from path: %m"); + return log_error_errno(r, "Failed to make unit name from path \"%s\": %m", + node); /* See mount_add_default_dependencies for explanation why we create such * dependencies. */ @@ -260,7 +267,8 @@ int generator_write_initrd_root_device_deps(const char *dir, const char *what) { r = unit_name_from_path(what, ".device", &unit); if (r < 0) - return log_error_errno(r, "Failed to make unit name from path: %m"); + return log_error_errno(r, "Failed to make unit name from path \"%s\": %m", + what); return write_drop_in_format(dir, SPECIAL_INITRD_ROOT_DEVICE_TARGET, 50, "root-device", "# Automatically generated by %s\n\n" @@ -271,3 +279,206 @@ int generator_write_initrd_root_device_deps(const char *dir, const char *what) { unit, unit); } + +int generator_hook_up_mkswap( + const char *dir, + const char *what) { + + _cleanup_free_ char *node = NULL, *unit = NULL, *escaped = NULL, *where_unit = NULL; + _cleanup_fclose_ FILE *f = NULL; + const char *unit_file; + int r; + + node = fstab_node_to_udev_node(what); + if (!node) + return log_oom(); + + /* Nothing to work on. */ + if (!is_device_path(node)) { + log_error("Cannot format something that is not a device node: %s", node); + return -EINVAL; + } + + r = unit_name_from_path_instance("systemd-mkswap", node, ".service", &unit); + if (r < 0) + return log_error_errno(r, "Failed to make unit instance name from path \"%s\": %m", + node); + + unit_file = strjoina(dir, "/", unit); + log_debug("Creating %s", unit_file); + + escaped = cescape(node); + if (!escaped) + return log_oom(); + + r = unit_name_from_path(what, ".swap", &where_unit); + if (r < 0) + return log_error_errno(r, "Failed to make unit name from path \"%s\": %m", + what); + + f = fopen(unit_file, "wxe"); + if (!f) + return log_error_errno(errno, "Failed to create unit file %s: %m", + unit_file); + + fprintf(f, + "# Automatically generated by %s\n\n" + "[Unit]\n" + "Description=Make Swap on %%f\n" + "Documentation=man:systemd-mkswap@.service(8)\n" + "DefaultDependencies=no\n" + "BindsTo=%%i.device\n" + "After=%%i.device\n" + "Before=%s\n" + "Before=shutdown.target\n" + "\n" + "[Service]\n" + "Type=oneshot\n" + "RemainAfterExit=yes\n" + "ExecStart="SYSTEMD_MAKEFS_PATH " swap %s\n" + "TimeoutSec=0\n", + program_invocation_short_name, + where_unit, + escaped); + + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write unit file %s: %m", unit_file); + + return generator_add_symlink(dir, where_unit, "requires", unit); +} + +int generator_hook_up_mkfs( + const char *dir, + const char *what, + const char *where, + const char *type) { + + _cleanup_free_ char *node = NULL, *unit = NULL, *escaped = NULL, *where_unit = NULL; + _cleanup_fclose_ FILE *f = NULL; + const char *unit_file; + int r; + + node = fstab_node_to_udev_node(what); + if (!node) + return log_oom(); + + /* Nothing to work on. */ + if (!is_device_path(node)) { + log_error("Cannot format something that is not a device node: %s", node); + return -EINVAL; + } + + if (!type || streq(type, "auto")) { + log_error("Cannot format partition %s, filesystem type is not specified", node); + return -EINVAL; + } + + r = unit_name_from_path_instance("systemd-mkfs", node, ".service", &unit); + if (r < 0) + return log_error_errno(r, "Failed to make unit instance name from path \"%s\": %m", + node); + + unit_file = strjoina(dir, "/", unit); + log_debug("Creating %s", unit_file); + + escaped = cescape(node); + if (!escaped) + return log_oom(); + + r = unit_name_from_path(where, ".mount", &where_unit); + if (r < 0) + return log_error_errno(r, "Failed to make unit name from path \"%s\": %m", + where); + + f = fopen(unit_file, "wxe"); + if (!f) + return log_error_errno(errno, "Failed to create unit file %s: %m", + unit_file); + + fprintf(f, + "# Automatically generated by %s\n\n" + "[Unit]\n" + "Description=Make File System on %%f\n" + "Documentation=man:systemd-mkfs@.service(8)\n" + "DefaultDependencies=no\n" + "BindsTo=%%i.device\n" + "After=%%i.device\n" + /* fsck might or might not be used, so let's be safe and order + * ourselves before both systemd-fsck@.service and the mount unit. */ + "Before=systemd-fsck@%%i.service\n" + "Before=%s\n" + "Before=shutdown.target\n" + "\n" + "[Service]\n" + "Type=oneshot\n" + "RemainAfterExit=yes\n" + "ExecStart="SYSTEMD_MAKEFS_PATH " %s %s\n" + "TimeoutSec=0\n", + program_invocation_short_name, + where_unit, + type, + escaped); + // XXX: what about local-fs-pre.target? + + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write unit file %s: %m", unit_file); + + return generator_add_symlink(dir, where_unit, "requires", unit); +} + +int generator_hook_up_growfs( + const char *dir, + const char *where, + const char *target) { + + _cleanup_free_ char *unit = NULL, *escaped = NULL, *where_unit = NULL; + _cleanup_fclose_ FILE *f = NULL; + const char *unit_file; + int r; + + escaped = cescape(where); + if (!escaped) + return log_oom(); + + r = unit_name_from_path_instance("systemd-growfs", where, ".service", &unit); + if (r < 0) + return log_error_errno(r, "Failed to make unit instance name from path \"%s\": %m", + where); + + r = unit_name_from_path(where, ".mount", &where_unit); + if (r < 0) + return log_error_errno(r, "Failed to make unit name from path \"%s\": %m", + where); + + unit_file = strjoina(dir, "/", unit); + log_debug("Creating %s", unit_file); + + f = fopen(unit_file, "wxe"); + if (!f) + return log_error_errno(errno, "Failed to create unit file %s: %m", + unit_file); + + fprintf(f, + "# Automatically generated by %s\n\n" + "[Unit]\n" + "Description=Grow File System on %%f\n" + "Documentation=man:systemd-growfs@.service(8)\n" + "DefaultDependencies=no\n" + "BindsTo=%%i.mount\n" + "After=%%i.mount\n" + "Before=shutdown.target\n" + "Before=%s\n" + "\n" + "[Service]\n" + "Type=oneshot\n" + "RemainAfterExit=yes\n" + "ExecStart="SYSTEMD_GROWFS_PATH " %s\n" + "TimeoutSec=0\n", + program_invocation_short_name, + target, + escaped); + + return generator_add_symlink(dir, where_unit, "wants", unit); +} |