chiark / gitweb /
gpt-auto-generator: properly handle LUKS partitions
authorLennart Poettering <lennart@poettering.net>
Thu, 6 Mar 2014 03:05:13 +0000 (04:05 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 6 Mar 2014 04:04:51 +0000 (05:04 +0100)
src/gpt-auto-generator/gpt-auto-generator.c

index 6267d9dba5f7caaeb39fdd9d1344146250eec22f..4f5224f3de8114a43bde3d74b48f533823cf186c 100644 (file)
 #include <linux/btrfs.h>
 #endif
 
+#include "sd-id128.h"
+#include "libudev.h"
 #include "path-util.h"
 #include "util.h"
 #include "mkdir.h"
 #include "missing.h"
-#include "sd-id128.h"
-#include "libudev.h"
 #include "udev-util.h"
 #include "special.h"
 #include "unit-name.h"
 #include "virt.h"
 #include "generator.h"
 #include "gpt.h"
+#include "fileio.h"
 
 static const char *arg_dest = "/tmp";
 
@@ -166,11 +167,134 @@ static int add_swap(const char *path, const char *fstype) {
         return 0;
 }
 
-static int add_mount(const char *what, const char *where, const char *fstype, const char *description) {
-        _cleanup_free_ char *unit = NULL, *lnk = NULL, *p = NULL;
+static int add_cryptsetup(const char *id, const char *what, char **device) {
+        _cleanup_free_ char *e = NULL, *n = NULL, *p = NULL, *d = NULL, *to = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
+        char *from, *ret;
+        int r;
+
+        assert(id);
+        assert(what);
+        assert(device);
+
+        d = unit_name_from_path(what, ".device");
+        if (!d)
+                return log_oom();
+
+        e = unit_name_escape(id);
+        if (!e)
+                return log_oom();
+
+        n = unit_name_build("systemd-cryptsetup", e, ".service");
+        if (!n)
+                return log_oom();
+
+        p = strjoin(arg_dest, "/", n, NULL);
+        if (!n)
+                return log_oom();
+
+        f = fopen(p, "wxe");
+        if (!f) {
+                log_error("Failed to create unit file %s: %m", p);
+                return -errno;
+        }
+
+        fprintf(f,
+                "# Automatically generated by systemd-gpt-auto-generator\n\n"
+                "[Unit]\n"
+                "Description=Cryptography Setup for %%I\n"
+                "Documentation=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"
+                "After=systemd-readahead-collect.service systemd-readahead-replay.service\n\n"
+                "[Service]\n"
+                "Type=oneshot\n"
+                "RemainAfterExit=yes\n"
+                "TimeoutSec=0\n" /* the binary handles timeouts anyway */
+                "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s'\n"
+                "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
+                d, d,
+                id, what,
+                id);
+
+        fflush(f);
+        if (ferror(f)) {
+                log_error("Failed to write file %s: %m", p);
+                return -errno;
+        }
+
+        from = strappenda("../", n);
+
+        to = strjoin(arg_dest, "/", d, ".wants/", n, NULL);
+        if (!to)
+                return log_oom();
+
+        mkdir_parents_label(to, 0755);
+        if (symlink(from, to) < 0) {
+                log_error("Failed to create symlink %s: %m", to);
+                return -errno;
+        }
+
+        free(to);
+        to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
+        if (!to)
+                return log_oom();
+
+        mkdir_parents_label(to, 0755);
+        if (symlink(from, to) < 0) {
+                log_error("Failed to create symlink %s: %m", to);
+                return -errno;
+        }
+
+        free(to);
+        to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
+        if (!to)
+                return log_oom();
+
+        mkdir_parents_label(to, 0755);
+        if (symlink(from, to) < 0) {
+                log_error("Failed to create symlink %s: %m", to);
+                return -errno;
+        }
+
+        free(p);
+        p = strjoin(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf", NULL);
+        if (!p)
+                return log_oom();
+
+        mkdir_parents_label(p, 0755);
+        r = write_string_file(p,
+                        "# Automatically generated by systemd-gpt-auto-generator\n\n"
+                        "[Unit]\n"
+                        "JobTimeoutSec=0\n"); /* the binary handles timeouts anyway */
+        if (r < 0) {
+                log_error("Failed to write device drop-in: %s", strerror(-r));
+                return r;
+        }
+
+        ret = strappend("/dev/mapper/", id);
+        if (!ret)
+                return log_oom();
+
+        *device = ret;
+        return 0;
+}
+
+static int add_mount(const char *id, const char *what, const char *where, const char *fstype, const char *description) {
+        _cleanup_free_ char *unit = NULL, *lnk = NULL, *crypto_what = NULL, *p = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         int r;
 
+        assert(id);
+        assert(what);
+        assert(where);
+        assert(fstype);
+        assert(description);
+
         if (dir_is_empty(where) <= 0) {
                 log_debug("%s already populated, ignoring.", where);
                 return 0;
@@ -178,6 +302,16 @@ static int add_mount(const char *what, const char *where, const char *fstype, co
 
         log_debug("Adding %s: %s %s", where, what, fstype);
 
+        if (streq(fstype, "crypto_LUKS")) {
+
+                r = add_cryptsetup(id, what, &crypto_what);
+                if (r < 0)
+                        return r;
+
+                what = crypto_what;
+                fstype = NULL;
+        }
+
         unit = unit_name_from_path(where, ".mount");
         if (!unit)
                 return log_oom();
@@ -206,9 +340,14 @@ static int add_mount(const char *what, const char *where, const char *fstype, co
                 "\n"
                 "[Mount]\n"
                 "What=%s\n"
-                "Where=%s\n"
-                "Type=%s\n",
-                what, where, fstype);
+                "Where=%s\n",
+                what, where);
+
+        if (fstype) {
+                fprintf(f,
+                        "Type=%s\n",
+                        fstype);
+        }
 
         fflush(f);
         if (ferror(f)) {
@@ -337,10 +476,10 @@ static int enumerate_partitions(struct udev *udev, dev_t dev) {
         }
 
         if (home && home_fstype)
-                add_mount(home, "/home", home_fstype, "Home Partition");
+                add_mount("home", home, "/home", home_fstype, "Home Partition");
 
         if (srv && srv_fstype)
-                add_mount(srv, "/srv", srv_fstype, "Server Data Partition");
+                add_mount("srv", srv, "/srv", srv_fstype, "Server Data Partition");
 
         return r;
 }