From: Lennart Poettering Date: Thu, 6 Mar 2014 03:05:13 +0000 (+0100) Subject: gpt-auto-generator: properly handle LUKS partitions X-Git-Tag: v211~101 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=1af7211984a8dba3c5ba40fae794c4c55f5e6bd3;ds=sidebyside gpt-auto-generator: properly handle LUKS partitions --- diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index 6267d9dba..4f5224f3d 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -30,18 +30,19 @@ #include #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; }