]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/shared/generator.c
Merge pull request #14398 from poettering/mount-prep
[thirdparty/systemd.git] / src / shared / generator.c
index 7273fde1860fb8d9072a35093ede0bbd9faf858b..acdd0096f1419391bae148a8a041928b4a8cd822 100644 (file)
@@ -156,15 +156,15 @@ int generator_write_fsck_deps(
         if (path_equal(where, "/")) {
                 const char *lnk;
 
-                lnk = strjoina(dir, "/" SPECIAL_LOCAL_FS_TARGET ".wants/"SPECIAL_FSCK_ROOT_SERVICE);
+                lnk = strjoina(dir, "/" SPECIAL_LOCAL_FS_TARGET ".wants/" SPECIAL_FSCK_ROOT_SERVICE);
 
                 (void) mkdir_parents(lnk, 0755);
-                if (symlink(SYSTEM_DATA_UNIT_PATH "/"SPECIAL_FSCK_ROOT_SERVICE, lnk) < 0)
+                if (symlink(SYSTEM_DATA_UNIT_PATH "/" SPECIAL_FSCK_ROOT_SERVICE, lnk) < 0)
                         return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
 
         } else {
                 _cleanup_free_ char *_fsck = NULL;
-                const char *fsck;
+                const char *fsck, *dep;
 
                 if (in_initrd() && path_equal(where, "/sysroot")) {
                         r = write_fsck_sysroot_service(dir, what);
@@ -172,7 +172,15 @@ int generator_write_fsck_deps(
                                 return r;
 
                         fsck = SPECIAL_FSCK_ROOT_SERVICE;
+                        dep = "Requires";
                 } else {
+                        /* When this is /usr, then let's add a Wants= dependency, otherwise a Requires=
+                         * dependency. Why? We can't possibly unmount /usr during shutdown, but if we have a
+                         * Requires= from /usr onto a fsck@.service unit and that unit is shut down, then
+                         * we'd have to unmount /usr too.  */
+
+                        dep = !in_initrd() && path_equal(where, "/usr") ? "Wants" : "Requires";
+
                         r = unit_name_from_path_instance("systemd-fsck", what, ".service", &_fsck);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to create fsck service name: %m");
@@ -181,9 +189,9 @@ int generator_write_fsck_deps(
                 }
 
                 fprintf(f,
-                        "Requires=%1$s\n"
-                        "After=%1$s\n",
-                        fsck);
+                        "%1$s=%2$s\n"
+                        "After=%2$s\n",
+                        dep, fsck);
         }
 
         return 0;
@@ -229,10 +237,12 @@ int generator_write_timeouts(
                 return log_error_errno(r, "Failed to make unit name from path: %m");
 
         return write_drop_in_format(dir, unit, 50, "device-timeout",
-                                    "# Automatically generated by %s\n\n"
+                                    "# Automatically generated by %s\n"
+                                    "# from supplied options \"%s\"\n\n"
                                     "[Unit]\n"
                                     "JobRunningTimeoutSec=%s",
                                     program_invocation_short_name,
+                                    opts,
                                     timeout);
 }
 
@@ -483,15 +493,21 @@ int generator_hook_up_growfs(
                 "BindsTo=%%i.mount\n"
                 "Conflicts=shutdown.target\n"
                 "After=%%i.mount\n"
-                "Before=shutdown.target %s\n"
+                "Before=shutdown.target %s\n",
+                program_invocation_short_name,
+                target);
+
+        if (empty_or_root(where)) /* Make sure the root fs is actually writable before we resize it */
+                fprintf(f,
+                        "After=systemd-remount-fs.service\n");
+
+        fprintf(f,
                 "\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);
@@ -503,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();