#include <stdio.h>
#include <linux/magic.h>
+#include "sd-id128.h"
+
#include "alloc-util.h"
#include "blkid-util.h"
#include "bootspec.h"
}
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)
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)
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);
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)
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)
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);
}