summaryrefslogtreecommitdiff
path: root/src/gpt-auto-generator/gpt-auto-generator.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpt-auto-generator/gpt-auto-generator.c')
-rw-r--r--src/gpt-auto-generator/gpt-auto-generator.c157
1 files changed, 148 insertions, 9 deletions
diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
index 6267d9dba5..4f5224f3de 100644
--- a/src/gpt-auto-generator/gpt-auto-generator.c
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -30,18 +30,19 @@
#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;
}