]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/cryptsetup/cryptsetup-generator.c
util-lib: split our string related calls from util.[ch] into its own file string...
[thirdparty/systemd.git] / src / cryptsetup / cryptsetup-generator.c
index efbcb3afbcbbca1a9b85102882bfd8a43af2a7a4..fde508ac2501cfa8eb5500cb8844b33876c07ddc 100644 (file)
 ***/
 
 #include <errno.h>
-#include <string.h>
-#include <unistd.h>
 
 #include "dropin.h"
-#include "fileio.h"
+#include "fstab-util.h"
 #include "generator.h"
 #include "hashmap.h"
 #include "log.h"
 #include "mkdir.h"
 #include "path-util.h"
+#include "string-util.h"
 #include "strv.h"
 #include "unit-name.h"
 #include "util.h"
@@ -37,6 +36,7 @@
 typedef struct crypto_device {
         char *uuid;
         char *keyfile;
+        char *name;
         char *options;
         bool create;
 } crypto_device;
@@ -49,35 +49,6 @@ static Hashmap *arg_disks = NULL;
 static char *arg_default_options = NULL;
 static char *arg_default_keyfile = NULL;
 
-static bool has_option(const char *haystack, const char *needle) {
-        const char *f = haystack;
-        size_t l;
-
-        assert(needle);
-
-        if (!haystack)
-                return false;
-
-        l = strlen(needle);
-
-        while ((f = strstr(f, needle))) {
-
-                if (f > haystack && f[-1] != ',') {
-                        f++;
-                        continue;
-                }
-
-                if (f[l] != 0 && f[l] != ',') {
-                        f++;
-                        continue;
-                }
-
-                return true;
-        }
-
-        return false;
-}
-
 static int create_disk(
                 const char *name,
                 const char *device,
@@ -94,10 +65,10 @@ static int create_disk(
         assert(name);
         assert(device);
 
-        noauto = has_option(options, "noauto");
-        nofail = has_option(options, "nofail");
-        tmp = has_option(options, "tmp");
-        swap = has_option(options, "swap");
+        noauto = fstab_test_yes_no_option(options, "noauto\0" "auto\0");
+        nofail = fstab_test_yes_no_option(options, "nofail\0" "fail\0");
+        tmp = fstab_test_option(options, "tmp\0");
+        swap = fstab_test_option(options, "swap\0");
 
         if (tmp && swap) {
                 log_error("Device '%s' cannot be both 'tmp' and 'swap'. Ignoring.", name);
@@ -108,9 +79,9 @@ static int create_disk(
         if (!e)
                 return log_oom();
 
-        n = unit_name_build("systemd-cryptsetup", e, ".service");
-        if (!n)
-                return log_oom();
+        r = unit_name_build("systemd-cryptsetup", e, ".service", &n);
+        if (r < 0)
+                return log_error_errno(r, "Failed to generate unit name: %m");
 
         p = strjoin(arg_dest, "/", n, NULL);
         if (!p)
@@ -120,9 +91,9 @@ static int create_disk(
         if (!u)
                 return log_oom();
 
-        d = unit_name_from_path(u, ".device");
-        if (!d)
-                return log_oom();
+        r = unit_name_from_path(u, ".device", &d);
+        if (r < 0)
+                return log_error_errno(r, "Failed to generate unit name: %m");
 
         f = fopen(p, "wxe");
         if (!f)
@@ -158,11 +129,11 @@ static int create_disk(
                         if (!path_equal(uu, "/dev/null")) {
 
                                 if (is_device_path(uu)) {
-                                        _cleanup_free_ char *dd;
+                                        _cleanup_free_ char *dd = NULL;
 
-                                        dd = unit_name_from_path(uu, ".device");
-                                        if (!dd)
-                                                return log_oom();
+                                        r = unit_name_from_path(uu, ".device", &dd);
+                                        if (r < 0)
+                                                return log_error_errno(r, "Failed to generate unit name: %m");
 
                                         fprintf(f, "After=%1$s\nRequires=%1$s\n", dd);
                                 } else
@@ -206,11 +177,11 @@ static int create_disk(
                         "ExecStartPost=/sbin/mkswap '/dev/mapper/%s'\n",
                         name);
 
-        fflush(f);
-        if (ferror(f))
-                return log_error_errno(errno, "Failed to write file %s: %m", p);
+        r = fflush_and_check(f);
+        if (r < 0)
+                return log_error_errno(r, "Failed to write file %s: %m", p);
 
-        from = strappenda("../", n);
+        from = strjoina("../", n);
 
         if (!noauto) {
 
@@ -266,6 +237,7 @@ static void free_arg_disks(void) {
         while ((d = hashmap_steal_first(arg_disks))) {
                 free(d->uuid);
                 free(d->keyfile);
+                free(d->name);
                 free(d->options);
                 free(d);
         }
@@ -286,7 +258,7 @@ static crypto_device *get_crypto_device(const char *uuid) {
                         return NULL;
 
                 d->create = false;
-                d->keyfile = d->options = NULL;
+                d->keyfile = d->options = d->name = NULL;
 
                 d->uuid = strdup(uuid);
                 if (!d->uuid) {
@@ -359,9 +331,25 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
                         free(d->keyfile);
                         d->keyfile = uuid_value;
                         uuid_value = NULL;
-                } else if (free_and_strdup(&arg_default_keyfile, value))
+                } else if (free_and_strdup(&arg_default_keyfile, value) < 0)
                         return log_oom();
 
+        } else if (STR_IN_SET(key, "luks.name", "rd.luks.name") && value) {
+
+                r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value);
+                if (r == 2) {
+                        d = get_crypto_device(uuid);
+                        if (!d)
+                                return log_oom();
+
+                        d->create = arg_whitelist = true;
+
+                        free(d->name);
+                        d->name = uuid_value;
+                        uuid_value = NULL;
+                } else
+                        log_warning("Failed to parse luks name switch %s. Ignoring.", value);
+
         }
 
         return 0;
@@ -387,13 +375,6 @@ static int add_crypttab_devices(void) {
                 return 0;
         }
 
-        /* If we readd support for specifying passphrases
-         * directly in crypttab we should upgrade the warning
-         * below, though possibly only if a passphrase is
-         * specified directly. */
-        if (st.st_mode & 0005)
-                log_debug("/etc/crypttab is world-readable. This is usually not a good idea.");
-
         for (;;) {
                 int r, k;
                 char line[LINE_MAX], *l, *uuid;
@@ -446,14 +427,16 @@ static int add_proc_cmdline_devices(void) {
 
         HASHMAP_FOREACH(d, arg_disks, i) {
                 const char *options;
-                _cleanup_free_ char *name = NULL, *device = NULL;
+                _cleanup_free_ char *device = NULL;
 
                 if (!d->create)
                         continue;
 
-                name = strappend("luks-", d->uuid);
-                if (!name)
-                        return log_oom();
+                if (!d->name) {
+                        d->name = strappend("luks-", d->uuid);
+                        if (!d->name)
+                                return log_oom();
+                }
 
                 device = strappend("UUID=", d->uuid);
                 if (!device)
@@ -466,7 +449,7 @@ static int add_proc_cmdline_devices(void) {
                 else
                         options = "timeout=0";
 
-                r = create_disk(name, device, d->keyfile ?: arg_default_keyfile, options);
+                r = create_disk(d->name, device, d->keyfile ?: arg_default_keyfile, options);
                 if (r < 0)
                         return r;
         }