]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/shared/bootspec.c
Merge pull request #7817 from medhefgo/systemd-boot
[thirdparty/systemd.git] / src / shared / bootspec.c
index c0a10417d8b11905c8b56474bbea41487662b1fb..1c9ef4001919d5ef11bc5c0571e5248813007989 100644 (file)
@@ -20,6 +20,8 @@
 #include <stdio.h>
 #include <linux/magic.h>
 
+#include "sd-id128.h"
+
 #include "alloc-util.h"
 #include "blkid-util.h"
 #include "bootspec.h"
@@ -52,25 +54,33 @@ void boot_entry_free(BootEntry *entry) {
 }
 
 int boot_entry_load(const char *path, BootEntry *entry) {
+        _cleanup_(boot_entry_free) BootEntry tmp = {};
         _cleanup_fclose_ FILE *f = NULL;
         unsigned line = 1;
-        _cleanup_(boot_entry_free) BootEntry tmp = {};
+        char *b, *c;
         int r;
 
         assert(path);
         assert(entry);
 
-        f = fopen(path, "re");
-        if (!f)
-                return log_error_errno(errno, "Failed to open \"%s\": %m", path);
+        c = endswith_no_case(path, ".conf");
+        if (!c) {
+                log_error("Invalid loader entry filename: %s", path);
+                return -EINVAL;
+        }
 
-        tmp.filename = strdup(basename(path));
+        b = basename(path);
+        tmp.filename = strndup(b, c - b);
         if (!tmp.filename)
                 return log_oom();
 
+        f = fopen(path, "re");
+        if (!f)
+                return log_error_errno(errno, "Failed to open \"%s\": %m", path);
+
         for (;;) {
-                _cleanup_free_ char *buf = NULL;
-                char *p;
+                _cleanup_free_ char *buf = NULL, *field = NULL;
+                const char *p;
 
                 r = read_line(f, LONG_LINE_MAX, &buf);
                 if (r == 0)
@@ -85,34 +95,37 @@ int boot_entry_load(const char *path, BootEntry *entry) {
                 if (IN_SET(*strstrip(buf), '#', '\0'))
                         continue;
 
-                p = strchr(buf, ' ');
-                if (!p) {
+                p = buf;
+                r = extract_first_word(&p, &field, " \t", 0);
+                if (r < 0) {
+                        log_error_errno(r, "Failed to parse config file %s line %u: %m", path, line);
+                        continue;
+                }
+                if (r == 0) {
                         log_warning("%s:%u: Bad syntax", path, line);
                         continue;
                 }
-                *p = '\0';
-                p = strstrip(p + 1);
 
-                if (streq(buf, "title"))
+                if (streq(field, "title"))
                         r = free_and_strdup(&tmp.title, p);
-                else if (streq(buf, "version"))
+                else if (streq(field, "version"))
                         r = free_and_strdup(&tmp.version, p);
-                else if (streq(buf, "machine-id"))
+                else if (streq(field, "machine-id"))
                         r = free_and_strdup(&tmp.machine_id, p);
-                else if (streq(buf, "architecture"))
+                else if (streq(field, "architecture"))
                         r = free_and_strdup(&tmp.architecture, p);
-                else if (streq(buf, "options"))
+                else if (streq(field, "options"))
                         r = strv_extend(&tmp.options, p);
-                else if (streq(buf, "linux"))
+                else if (streq(field, "linux"))
                         r = free_and_strdup(&tmp.kernel, p);
-                else if (streq(buf, "efi"))
+                else if (streq(field, "efi"))
                         r = free_and_strdup(&tmp.efi, p);
-                else if (streq(buf, "initrd"))
+                else if (streq(field, "initrd"))
                         r = strv_extend(&tmp.initrd, p);
-                else if (streq(buf, "devicetree"))
+                else if (streq(field, "devicetree"))
                         r = free_and_strdup(&tmp.device_tree, p);
                 else {
-                        log_notice("%s:%u: Unknown line \"%s\"", path, line, buf);
+                        log_notice("%s:%u: Unknown line \"%s\"", path, line, field);
                         continue;
                 }
                 if (r < 0)
@@ -132,6 +145,8 @@ void boot_config_free(BootConfig *config) {
         free(config->default_pattern);
         free(config->timeout);
         free(config->editor);
+        free(config->auto_entries);
+        free(config->auto_firmware);
 
         free(config->entry_oneshot);
         free(config->entry_default);
@@ -154,8 +169,8 @@ int boot_loader_read_conf(const char *path, BootConfig *config) {
                 return log_error_errno(errno, "Failed to open \"%s\": %m", path);
 
         for (;;) {
-                _cleanup_free_ char *buf = NULL;
-                char *p;
+                _cleanup_free_ char *buf = NULL, *field = NULL;
+                const char *p;
 
                 r = read_line(f, LONG_LINE_MAX, &buf);
                 if (r == 0)
@@ -170,22 +185,29 @@ int boot_loader_read_conf(const char *path, BootConfig *config) {
                 if (IN_SET(*strstrip(buf), '#', '\0'))
                         continue;
 
-                p = strchr(buf, ' ');
-                if (!p) {
+                p = buf;
+                r = extract_first_word(&p, &field, " \t", 0);
+                if (r < 0) {
+                        log_error_errno(r, "Failed to parse config file %s line %u: %m", path, line);
+                        continue;
+                }
+                if (r == 0) {
                         log_warning("%s:%u: Bad syntax", path, line);
                         continue;
                 }
-                *p = '\0';
-                p = strstrip(p + 1);
 
-                if (streq(buf, "default"))
+                if (streq(field, "default"))
                         r = free_and_strdup(&config->default_pattern, p);
-                else if (streq(buf, "timeout"))
+                else if (streq(field, "timeout"))
                         r = free_and_strdup(&config->timeout, p);
-                else if (streq(buf, "editor"))
+                else if (streq(field, "editor"))
                         r = free_and_strdup(&config->editor, p);
+                else if (streq(buf, "auto-entries"))
+                        r = free_and_strdup(&config->auto_entries, p);
+                else if (streq(buf, "auto-firmware"))
+                        r = free_and_strdup(&config->auto_firmware, p);
                 else {
-                        log_notice("%s:%u: Unknown line \"%s\"", path, line, buf);
+                        log_notice("%s:%u: Unknown line \"%s\"", path, line, field);
                         continue;
                 }
                 if (r < 0)
@@ -195,67 +217,8 @@ int boot_loader_read_conf(const char *path, BootConfig *config) {
         return 0;
 }
 
-/* This is a direct translation of str_verscmp from boot.c */
-static bool is_digit(int c) {
-        return c >= '0' && c <= '9';
-}
-
-static int c_order(int c) {
-        if (c == '\0')
-                return 0;
-        if (is_digit(c))
-                return 0;
-        else if ((c >= 'a') && (c <= 'z'))
-                return c;
-        else
-                return c + 0x10000;
-}
-
-static int str_verscmp(const char *s1, const char *s2) {
-        const char *os1 = s1;
-        const char *os2 = s2;
-
-        while (*s1 || *s2) {
-                int first;
-
-                while ((*s1 && !is_digit(*s1)) || (*s2 && !is_digit(*s2))) {
-                        int order;
-
-                        order = c_order(*s1) - c_order(*s2);
-                        if (order)
-                                return order;
-                        s1++;
-                        s2++;
-                }
-
-                while (*s1 == '0')
-                        s1++;
-                while (*s2 == '0')
-                        s2++;
-
-                first = 0;
-                while (is_digit(*s1) && is_digit(*s2)) {
-                        if (first == 0)
-                                first = *s1 - *s2;
-                        s1++;
-                        s2++;
-                }
-
-                if (is_digit(*s1))
-                        return 1;
-                if (is_digit(*s2))
-                        return -1;
-
-                if (first != 0)
-                        return first;
-        }
-
-        return strcmp(os1, os2);
-}
-
 static int boot_entry_compare(const void *a, const void *b) {
-        const BootEntry *aa = a;
-        const BootEntry *bb = b;
+        const BootEntry *aa = a, *bb = b;
 
         return str_verscmp(aa->filename, bb->filename);
 }