]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/gpt-auto-generator/gpt-auto-generator.c
util-lib: split our string related calls from util.[ch] into its own file string...
[thirdparty/systemd.git] / src / gpt-auto-generator / gpt-auto-generator.c
index 0a34f86be7cde2c44021b8b14575073f2fedcf2b..3e8c745238864dd882c5e4b9e9e93b4900394649 100644 (file)
 #include <sys/statfs.h>
 #include <blkid/blkid.h>
 
-#include "sd-id128.h"
 #include "libudev.h"
-#include "path-util.h"
-#include "util.h"
-#include "mkdir.h"
+#include "sd-id128.h"
+
+#include "blkid-util.h"
+#include "btrfs-util.h"
+#include "efivars.h"
+#include "fileio.h"
+#include "fstab-util.h"
+#include "generator.h"
+#include "gpt.h"
 #include "missing.h"
-#include "udev-util.h"
+#include "mkdir.h"
+#include "path-util.h"
 #include "special.h"
+#include "string-util.h"
+#include "udev-util.h"
 #include "unit-name.h"
+#include "util.h"
 #include "virt.h"
-#include "generator.h"
-#include "gpt.h"
-#include "fileio.h"
-#include "efivars.h"
-#include "blkid-util.h"
-#include "btrfs-util.h"
 
 static const char *arg_dest = "/tmp";
 static bool arg_enabled = true;
@@ -460,11 +463,17 @@ static int add_boot(const char *what) {
                 return 0;
         }
 
-        if (detect_container(NULL) > 0) {
+        if (detect_container() > 0) {
                 log_debug("In a container, ignoring /boot.");
                 return 0;
         }
 
+        /* We create an .automount which is not overridden by the .mount from the fstab generator. */
+        if (fstab_is_mount_point("/boot")) {
+                log_debug("/boot specified in fstab, ignoring.");
+                return 0;
+        }
+
         if (path_is_busy("/boot")) {
                 log_debug("/boot already populated, ignoring.");
                 return 0;
@@ -526,9 +535,9 @@ static int add_boot(const char *what) {
                        what,
                        "/boot",
                        "vfat",
-                       "EFI System Partition Automount",
-                       false,
+                       true,
                        "umask=0077",
+                       "EFI System Partition Automount",
                        120 * USEC_PER_SEC);
 
         return r;
@@ -666,6 +675,7 @@ static int enumerate_partitions(dev_t devnum) {
         first = udev_enumerate_get_list_entry(e);
         udev_list_entry_foreach(item, first) {
                 _cleanup_udev_device_unref_ struct udev_device *q;
+                unsigned long long flags;
                 const char *stype, *subnode;
                 sd_id128_t type_id;
                 blkid_partition pp;
@@ -705,10 +715,10 @@ static int enumerate_partitions(dev_t devnum) {
                 if (sd_id128_from_string(stype, &type_id) < 0)
                         continue;
 
+                flags = blkid_partition_get_flags(pp);
+
                 if (sd_id128_equal(type_id, GPT_SWAP)) {
-                        unsigned long long flags;
 
-                        flags = blkid_partition_get_flags(pp);
                         if (flags & GPT_FLAG_NO_AUTO)
                                 continue;
 
@@ -727,6 +737,10 @@ static int enumerate_partitions(dev_t devnum) {
                         if (boot && nr >= boot_nr)
                                 continue;
 
+                        /* Note that we do not honour the "no-auto"
+                         * flag for the ESP, as it is often unset, to
+                         * hide it from Windows. */
+
                         boot_nr = nr;
 
                         r = free_and_strdup(&boot, subnode);
@@ -734,9 +748,7 @@ static int enumerate_partitions(dev_t devnum) {
                                 return log_oom();
 
                 } else if (sd_id128_equal(type_id, GPT_HOME)) {
-                        unsigned long long flags;
 
-                        flags = blkid_partition_get_flags(pp);
                         if (flags & GPT_FLAG_NO_AUTO)
                                 continue;
 
@@ -752,9 +764,7 @@ static int enumerate_partitions(dev_t devnum) {
                                 return log_oom();
 
                 } else if (sd_id128_equal(type_id, GPT_SRV)) {
-                        unsigned long long flags;
 
-                        flags = blkid_partition_get_flags(pp);
                         if (flags & GPT_FLAG_NO_AUTO)
                                 continue;
 
@@ -799,6 +809,10 @@ static int get_block_device(const char *path, dev_t *dev) {
         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;
 
@@ -816,6 +830,76 @@ static int get_block_device(const char *path, dev_t *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 (STR_IN_SET(de->d_name, ".", ".."))
+                        continue;
+
+                if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
+                        continue;
+
+                if (found) /* Don't try to support multiple backing block devices */
+                        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) {
         int r;
 
@@ -883,11 +967,11 @@ static int add_mounts(void) {
         dev_t devno;
         int r;
 
-        r = get_block_device("/", &devno);
+        r = get_block_device_harder("/", &devno);
         if (r < 0)
                 return log_error_errno(r, "Failed to determine block device of root file system: %m");
         else if (r == 0) {
-                r = get_block_device("/usr", &devno);
+                r = get_block_device_harder("/usr", &devno);
                 if (r < 0)
                         return log_error_errno(r, "Failed to determine block device of /usr file system: %m");
                 else if (r == 0) {
@@ -916,7 +1000,7 @@ int main(int argc, char *argv[]) {
 
         umask(0022);
 
-        if (detect_container(NULL) > 0) {
+        if (detect_container() > 0) {
                 log_debug("In a container, exiting.");
                 return EXIT_SUCCESS;
         }