]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/gpt-auto-generator/gpt-auto-generator.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / gpt-auto-generator / gpt-auto-generator.c
index 80f676e477b83353aa37aebc06a8778be3237362..7d014db69daf87a3931f665609c38274ce450abb 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
 /***
   This file is part of systemd.
 
@@ -17,7 +18,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <blkid/blkid.h>
+#include <blkid.h>
 #include <stdlib.h>
 #include <sys/statfs.h>
 #include <unistd.h>
@@ -56,9 +57,9 @@ static bool arg_root_enabled = true;
 static bool arg_root_rw = false;
 
 static int add_cryptsetup(const char *id, const char *what, bool rw, bool require, char **device) {
-        _cleanup_free_ char *e = NULL, *n = NULL, *p = NULL, *d = NULL, *to = NULL;
+        _cleanup_free_ char *e = NULL, *n = NULL, *p = NULL, *d = NULL;
         _cleanup_fclose_ FILE *f = NULL;
-        char *from, *ret;
+        char *ret;
         int r;
 
         assert(id);
@@ -99,6 +100,7 @@ static int add_cryptsetup(const char *id, const char *what, bool rw, bool requir
                 "Type=oneshot\n"
                 "RemainAfterExit=yes\n"
                 "TimeoutSec=0\n" /* the binary handles timeouts anyway */
+                "KeyringMode=shared\n" /* make sure we can share cached keys among instances */
                 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '' '%s'\n"
                 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
                 d, d,
@@ -109,35 +111,21 @@ static int add_cryptsetup(const char *id, const char *what, bool rw, bool requir
         if (r < 0)
                 return log_error_errno(r, "Failed to write file %s: %m", p);
 
-        from = strjoina("../", n);
-
-        to = strjoin(arg_dest, "/", d, ".wants/", n);
-        if (!to)
-                return log_oom();
-
-        mkdir_parents_label(to, 0755);
-        if (symlink(from, to) < 0)
-                return log_error_errno(errno, "Failed to create symlink %s: %m", to);
+        r = generator_add_symlink(arg_dest, d, "wants", n);
+        if (r < 0)
+                return r;
 
         if (require) {
-                free(to);
+                const char *dmname;
 
-                to = strjoin(arg_dest, "/cryptsetup.target.requires/", n);
-                if (!to)
-                        return log_oom();
-
-                mkdir_parents_label(to, 0755);
-                if (symlink(from, to) < 0)
-                        return log_error_errno(errno, "Failed to create symlink %s: %m", to);
-
-                free(to);
-                to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n);
-                if (!to)
-                        return log_oom();
+                r = generator_add_symlink(arg_dest, "cryptsetup.target", "requires", n);
+                if (r < 0)
+                        return r;
 
-                mkdir_parents_label(to, 0755);
-                if (symlink(from, to) < 0)
-                        return log_error_errno(errno, "Failed to create symlink %s: %m", to);
+                dmname = strjoina("dev-mapper-", e, ".device");
+                r = generator_add_symlink(arg_dest, dmname, "requires", n);
+                if (r < 0)
+                        return r;
         }
 
         free(p);
@@ -173,7 +161,7 @@ static int add_mount(
                 const char *description,
                 const char *post) {
 
-        _cleanup_free_ char *unit = NULL, *lnk = NULL, *crypto_what = NULL, *p = NULL;
+        _cleanup_free_ char *unit = NULL, *crypto_what = NULL, *p = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         int r;
 
@@ -239,16 +227,8 @@ static int add_mount(
         if (r < 0)
                 return log_error_errno(r, "Failed to write unit file %s: %m", p);
 
-        if (post) {
-                lnk = strjoin(arg_dest, "/", post, ".requires/", unit);
-                if (!lnk)
-                        return log_oom();
-
-                mkdir_parents_label(lnk, 0755);
-                if (symlink(p, lnk) < 0)
-                        return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
-        }
-
+        if (post)
+                return generator_add_symlink(arg_dest, post, "requires", unit);
         return 0;
 }
 
@@ -299,12 +279,21 @@ static int add_partition_mount(
 }
 
 static int add_swap(const char *path) {
-        _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL;
+        _cleanup_free_ char *name = NULL, *unit = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         int r;
 
         assert(path);
 
+        /* Disable the swap auto logic if at least one swap is defined in /etc/fstab, see #6192. */
+        r = fstab_has_fstype("swap");
+        if (r < 0)
+                return log_error_errno(r, "Failed to parse fstab: %m");
+        if (r > 0) {
+                log_debug("swap specified in fstab, ignoring.");
+                return 0;
+        }
+
         log_debug("Adding swap: %s", path);
 
         r = unit_name_from_path(path, ".swap", &name);
@@ -332,18 +321,10 @@ static int add_swap(const char *path) {
         if (r < 0)
                 return log_error_errno(r, "Failed to write unit file %s: %m", unit);
 
-        lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name);
-        if (!lnk)
-                return log_oom();
-
-        mkdir_parents_label(lnk, 0755);
-        if (symlink(unit, lnk) < 0)
-                return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
-
-        return 0;
+        return generator_add_symlink(arg_dest, SPECIAL_SWAP_TARGET, "wants", name);
 }
 
-#ifdef ENABLE_EFI
+#if ENABLE_EFI
 static int add_automount(
                 const char *id,
                 const char *what,
@@ -354,7 +335,7 @@ static int add_automount(
                 const char *description,
                 usec_t timeout) {
 
-        _cleanup_free_ char *unit = NULL, *lnk = NULL;
+        _cleanup_free_ char *unit = NULL;
         _cleanup_free_ char *opt, *p = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         int r;
@@ -409,15 +390,7 @@ static int add_automount(
         if (r < 0)
                 return log_error_errno(r, "Failed to write unit file %s: %m", p);
 
-        lnk = strjoin(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".wants/", unit);
-        if (!lnk)
-                return log_oom();
-        mkdir_parents_label(lnk, 0755);
-
-        if (symlink(p, lnk) < 0)
-                return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
-
-        return 0;
+        return generator_add_symlink(arg_dest, SPECIAL_LOCAL_FS_TARGET, "wants", unit);
 }
 
 static int add_esp(DissectedPartition *p) {
@@ -435,7 +408,10 @@ static int add_esp(DissectedPartition *p) {
         esp = access("/efi/", F_OK) >= 0 ? "/efi" : "/boot";
 
         /* We create an .automount which is not overridden by the .mount from the fstab generator. */
-        if (fstab_is_mount_point(esp)) {
+        r = fstab_is_mount_point(esp);
+        if (r < 0)
+                return log_error_errno(r, "Failed to parse fstab: %m");
+        if (r > 0) {
                 log_debug("%s specified in fstab, ignoring.", esp);
                 return 0;
         }
@@ -597,136 +573,6 @@ static int enumerate_partitions(dev_t devnum) {
         return r;
 }
 
-static int get_block_device(const char *path, dev_t *dev) {
-        struct stat st;
-        struct statfs sfs;
-
-        assert(path);
-        assert(dev);
-
-        /* Get's the block device directly backing a file system. If
-         * the block device is encrypted, returns the device mapper
-         * block device. */
-
-        if (lstat(path, &st))
-                return -errno;
-
-        if (major(st.st_dev) != 0) {
-                *dev = st.st_dev;
-                return 1;
-        }
-
-        if (statfs(path, &sfs) < 0)
-                return -errno;
-
-        if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
-                return btrfs_get_block_device(path, dev);
-
-        return 0;
-}
-
-static int get_block_device_harder(const char *path, dev_t *dev) {
-        _cleanup_closedir_ DIR *d = NULL;
-        _cleanup_free_ char *p = NULL, *t = NULL;
-        struct dirent *de, *found = NULL;
-        const char *q;
-        unsigned maj, min;
-        dev_t dt;
-        int r;
-
-        assert(path);
-        assert(dev);
-
-        /* Gets the backing block device for a file system, and
-         * handles LUKS encrypted file systems, looking for its
-         * immediate parent, if there is one. */
-
-        r = get_block_device(path, &dt);
-        if (r <= 0)
-                return r;
-
-        if (asprintf(&p, "/sys/dev/block/%u:%u/slaves", major(dt), minor(dt)) < 0)
-                return -ENOMEM;
-
-        d = opendir(p);
-        if (!d) {
-                if (errno == ENOENT)
-                        goto fallback;
-
-                return -errno;
-        }
-
-        FOREACH_DIRENT_ALL(de, d, return -errno) {
-
-                if (dot_or_dot_dot(de->d_name))
-                        continue;
-
-                if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
-                        continue;
-
-                if (found) {
-                        _cleanup_free_ char *u = NULL, *v = NULL, *a = NULL, *b = NULL;
-
-                        /* We found a device backed by multiple other devices. We don't really support automatic
-                         * discovery on such setups, with the exception of dm-verity partitions. In this case there are
-                         * two backing devices: the data partition and the hash partition. We are fine with such
-                         * setups, however, only if both partitions are on the same physical device. Hence, let's
-                         * verify this. */
-
-                        u = strjoin(p, "/", de->d_name, "/../dev");
-                        if (!u)
-                                return -ENOMEM;
-
-                        v = strjoin(p, "/", found->d_name, "/../dev");
-                        if (!v)
-                                return -ENOMEM;
-
-                        r = read_one_line_file(u, &a);
-                        if (r < 0) {
-                                log_debug_errno(r, "Failed to read %s: %m", u);
-                                goto fallback;
-                        }
-
-                        r = read_one_line_file(v, &b);
-                        if (r < 0) {
-                                log_debug_errno(r, "Failed to read %s: %m", v);
-                                goto fallback;
-                        }
-
-                        /* Check if the parent device is the same. If not, then the two backing devices are on
-                         * different physical devices, and we don't support that. */
-                        if (!streq(a, b))
-                                goto fallback;
-                }
-
-                found = de;
-        }
-
-        if (!found)
-                goto fallback;
-
-        q = strjoina(p, "/", found->d_name, "/dev");
-
-        r = read_one_line_file(q, &t);
-        if (r == -ENOENT)
-                goto fallback;
-        if (r < 0)
-                return r;
-
-        if (sscanf(t, "%u:%u", &maj, &min) != 2)
-                return -EINVAL;
-
-        if (maj == 0)
-                goto fallback;
-
-        *dev = makedev(maj, min);
-        return 1;
-
-fallback:
-        *dev = dt;
-        return 1;
-}
-
 static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
         int r;
 
@@ -767,7 +613,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
         return 0;
 }
 
-#ifdef ENABLE_EFI
+#if ENABLE_EFI
 static int add_root_cryptsetup(void) {
 
         /* If a device /dev/gpt-auto-root-luks appears, then make it pull in systemd-cryptsetup-root.service, which
@@ -779,7 +625,7 @@ static int add_root_cryptsetup(void) {
 
 static int add_root_mount(void) {
 
-#ifdef ENABLE_EFI
+#if ENABLE_EFI
         int r;
 
         if (!is_efi_boot()) {
@@ -843,7 +689,7 @@ static int add_mounts(void) {
 }
 
 int main(int argc, char *argv[]) {
-        int r = 0, k;
+        int r, k;
 
         if (argc > 1 && argc != 4) {
                 log_error("This program takes three or no arguments.");
@@ -875,6 +721,8 @@ int main(int argc, char *argv[]) {
 
         if (arg_root_enabled)
                 r = add_root_mount();
+        else
+                r = 0;
 
         if (!in_initrd()) {
                 k = add_mounts();