| File: | build-scan/../src/shared/bootspec.c |
| Warning: | line 268, column 9 Declared variable-length array (VLA) has zero size |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
| 2 | ||||
| 3 | #include <stdio.h> | |||
| 4 | #include <linux1/magic.h> | |||
| 5 | ||||
| 6 | #include "sd-id128.h" | |||
| 7 | ||||
| 8 | #include "alloc-util.h" | |||
| 9 | #include "blkid-util.h" | |||
| 10 | #include "bootspec.h" | |||
| 11 | #include "conf-files.h" | |||
| 12 | #include "def.h" | |||
| 13 | #include "device-nodes.h" | |||
| 14 | #include "efivars.h" | |||
| 15 | #include "fd-util.h" | |||
| 16 | #include "fileio.h" | |||
| 17 | #include "parse-util.h" | |||
| 18 | #include "stat-util.h" | |||
| 19 | #include "string-util.h" | |||
| 20 | #include "strv.h" | |||
| 21 | #include "virt.h" | |||
| 22 | ||||
| 23 | void boot_entry_free(BootEntry *entry) { | |||
| 24 | assert(entry)do { if ((__builtin_expect(!!(!(entry)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("entry"), "../src/shared/bootspec.c", 24 , __PRETTY_FUNCTION__); } while (0); | |||
| 25 | ||||
| 26 | free(entry->filename); | |||
| 27 | free(entry->title); | |||
| 28 | free(entry->show_title); | |||
| 29 | free(entry->version); | |||
| 30 | free(entry->machine_id); | |||
| 31 | free(entry->architecture); | |||
| 32 | strv_free(entry->options); | |||
| 33 | free(entry->kernel); | |||
| 34 | free(entry->efi); | |||
| 35 | strv_free(entry->initrd); | |||
| 36 | free(entry->device_tree); | |||
| 37 | } | |||
| 38 | ||||
| 39 | int boot_entry_load(const char *path, BootEntry *entry) { | |||
| 40 | _cleanup_(boot_entry_free)__attribute__((cleanup(boot_entry_free))) BootEntry tmp = {}; | |||
| 41 | _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f = NULL((void*)0); | |||
| 42 | unsigned line = 1; | |||
| 43 | char *b, *c; | |||
| 44 | int r; | |||
| 45 | ||||
| 46 | assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("path"), "../src/shared/bootspec.c", 46, __PRETTY_FUNCTION__); } while (0); | |||
| 47 | assert(entry)do { if ((__builtin_expect(!!(!(entry)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("entry"), "../src/shared/bootspec.c", 47 , __PRETTY_FUNCTION__); } while (0); | |||
| 48 | ||||
| 49 | c = endswith_no_case(path, ".conf"); | |||
| 50 | if (!c) { | |||
| 51 | log_error("Invalid loader entry filename: %s", path)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 51, __func__, "Invalid loader entry filename: %s" , path) : -abs(_e); }); | |||
| 52 | return -EINVAL22; | |||
| 53 | } | |||
| 54 | ||||
| 55 | b = basename(path); | |||
| 56 | tmp.filename = strndup(b, c - b); | |||
| 57 | if (!tmp.filename) | |||
| 58 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/shared/bootspec.c" , 58, __func__); | |||
| 59 | ||||
| 60 | f = fopen(path, "re"); | |||
| 61 | if (!f) | |||
| 62 | return log_error_errno(errno, "Failed to open \"%s\": %m", path)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/shared/bootspec.c", 62, __func__ , "Failed to open \"%s\": %m", path) : -abs(_e); }); | |||
| 63 | ||||
| 64 | for (;;) { | |||
| 65 | _cleanup_free___attribute__((cleanup(freep))) char *buf = NULL((void*)0), *field = NULL((void*)0); | |||
| 66 | const char *p; | |||
| 67 | ||||
| 68 | r = read_line(f, LONG_LINE_MAX(1U*1024U*1024U), &buf); | |||
| 69 | if (r == 0) | |||
| 70 | break; | |||
| 71 | if (r == -ENOBUFS105) | |||
| 72 | return log_error_errno(r, "%s:%u: Line too long", path, line)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 72, __func__, "%s:%u: Line too long" , path, line) : -abs(_e); }); | |||
| 73 | if (r < 0) | |||
| 74 | return log_error_errno(r, "%s:%u: Error while reading: %m", path, line)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 74, __func__, "%s:%u: Error while reading: %m" , path, line) : -abs(_e); }); | |||
| 75 | ||||
| 76 | line++; | |||
| 77 | ||||
| 78 | if (IN_SET(*strstrip(buf), '#', '\0')({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){'#', '\0'})/sizeof(int)]; switch(*strstrip (buf)) { case '#': case '\0': _found = 1; break; default: break ; } _found; })) | |||
| 79 | continue; | |||
| 80 | ||||
| 81 | p = buf; | |||
| 82 | r = extract_first_word(&p, &field, " \t", 0); | |||
| 83 | if (r < 0) { | |||
| 84 | log_error_errno(r, "Failed to parse config file %s line %u: %m", path, line)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 84, __func__, "Failed to parse config file %s line %u: %m" , path, line) : -abs(_e); }); | |||
| 85 | continue; | |||
| 86 | } | |||
| 87 | if (r == 0) { | |||
| 88 | log_warning("%s:%u: Bad syntax", path, line)({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 88, __func__, "%s:%u: Bad syntax" , path, line) : -abs(_e); }); | |||
| 89 | continue; | |||
| 90 | } | |||
| 91 | ||||
| 92 | if (streq(field, "title")(strcmp((field),("title")) == 0)) | |||
| 93 | r = free_and_strdup(&tmp.title, p); | |||
| 94 | else if (streq(field, "version")(strcmp((field),("version")) == 0)) | |||
| 95 | r = free_and_strdup(&tmp.version, p); | |||
| 96 | else if (streq(field, "machine-id")(strcmp((field),("machine-id")) == 0)) | |||
| 97 | r = free_and_strdup(&tmp.machine_id, p); | |||
| 98 | else if (streq(field, "architecture")(strcmp((field),("architecture")) == 0)) | |||
| 99 | r = free_and_strdup(&tmp.architecture, p); | |||
| 100 | else if (streq(field, "options")(strcmp((field),("options")) == 0)) | |||
| 101 | r = strv_extend(&tmp.options, p); | |||
| 102 | else if (streq(field, "linux")(strcmp((field),("linux")) == 0)) | |||
| 103 | r = free_and_strdup(&tmp.kernel, p); | |||
| 104 | else if (streq(field, "efi")(strcmp((field),("efi")) == 0)) | |||
| 105 | r = free_and_strdup(&tmp.efi, p); | |||
| 106 | else if (streq(field, "initrd")(strcmp((field),("initrd")) == 0)) | |||
| 107 | r = strv_extend(&tmp.initrd, p); | |||
| 108 | else if (streq(field, "devicetree")(strcmp((field),("devicetree")) == 0)) | |||
| 109 | r = free_and_strdup(&tmp.device_tree, p); | |||
| 110 | else { | |||
| 111 | log_notice("%s:%u: Unknown line \"%s\"", path, line, field)({ int _level = (((5))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 111, __func__, "%s:%u: Unknown line \"%s\"" , path, line, field) : -abs(_e); }); | |||
| 112 | continue; | |||
| 113 | } | |||
| 114 | if (r < 0) | |||
| 115 | return log_error_errno(r, "%s:%u: Error while reading: %m", path, line)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 115, __func__, "%s:%u: Error while reading: %m" , path, line) : -abs(_e); }); | |||
| 116 | } | |||
| 117 | ||||
| 118 | *entry = tmp; | |||
| 119 | tmp = (BootEntry) {}; | |||
| 120 | return 0; | |||
| 121 | } | |||
| 122 | ||||
| 123 | void boot_config_free(BootConfig *config) { | |||
| 124 | size_t i; | |||
| 125 | ||||
| 126 | assert(config)do { if ((__builtin_expect(!!(!(config)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("config"), "../src/shared/bootspec.c", 126 , __PRETTY_FUNCTION__); } while (0); | |||
| 127 | ||||
| 128 | free(config->default_pattern); | |||
| 129 | free(config->timeout); | |||
| 130 | free(config->editor); | |||
| 131 | free(config->auto_entries); | |||
| 132 | free(config->auto_firmware); | |||
| 133 | ||||
| 134 | free(config->entry_oneshot); | |||
| 135 | free(config->entry_default); | |||
| 136 | ||||
| 137 | for (i = 0; i < config->n_entries; i++) | |||
| 138 | boot_entry_free(config->entries + i); | |||
| 139 | free(config->entries); | |||
| 140 | } | |||
| 141 | ||||
| 142 | int boot_loader_read_conf(const char *path, BootConfig *config) { | |||
| 143 | _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f = NULL((void*)0); | |||
| 144 | unsigned line = 1; | |||
| 145 | int r; | |||
| 146 | ||||
| 147 | assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("path"), "../src/shared/bootspec.c", 147 , __PRETTY_FUNCTION__); } while (0); | |||
| 148 | assert(config)do { if ((__builtin_expect(!!(!(config)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("config"), "../src/shared/bootspec.c", 148 , __PRETTY_FUNCTION__); } while (0); | |||
| 149 | ||||
| 150 | f = fopen(path, "re"); | |||
| 151 | if (!f) | |||
| 152 | return log_error_errno(errno, "Failed to open \"%s\": %m", path)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/shared/bootspec.c", 152, __func__ , "Failed to open \"%s\": %m", path) : -abs(_e); }); | |||
| 153 | ||||
| 154 | for (;;) { | |||
| 155 | _cleanup_free___attribute__((cleanup(freep))) char *buf = NULL((void*)0), *field = NULL((void*)0); | |||
| 156 | const char *p; | |||
| 157 | ||||
| 158 | r = read_line(f, LONG_LINE_MAX(1U*1024U*1024U), &buf); | |||
| 159 | if (r == 0) | |||
| 160 | break; | |||
| 161 | if (r == -ENOBUFS105) | |||
| 162 | return log_error_errno(r, "%s:%u: Line too long", path, line)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 162, __func__, "%s:%u: Line too long" , path, line) : -abs(_e); }); | |||
| 163 | if (r < 0) | |||
| 164 | return log_error_errno(r, "%s:%u: Error while reading: %m", path, line)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 164, __func__, "%s:%u: Error while reading: %m" , path, line) : -abs(_e); }); | |||
| 165 | ||||
| 166 | line++; | |||
| 167 | ||||
| 168 | if (IN_SET(*strstrip(buf), '#', '\0')({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){'#', '\0'})/sizeof(int)]; switch(*strstrip (buf)) { case '#': case '\0': _found = 1; break; default: break ; } _found; })) | |||
| 169 | continue; | |||
| 170 | ||||
| 171 | p = buf; | |||
| 172 | r = extract_first_word(&p, &field, " \t", 0); | |||
| 173 | if (r < 0) { | |||
| 174 | log_error_errno(r, "Failed to parse config file %s line %u: %m", path, line)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 174, __func__, "Failed to parse config file %s line %u: %m" , path, line) : -abs(_e); }); | |||
| 175 | continue; | |||
| 176 | } | |||
| 177 | if (r == 0) { | |||
| 178 | log_warning("%s:%u: Bad syntax", path, line)({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 178, __func__, "%s:%u: Bad syntax" , path, line) : -abs(_e); }); | |||
| 179 | continue; | |||
| 180 | } | |||
| 181 | ||||
| 182 | if (streq(field, "default")(strcmp((field),("default")) == 0)) | |||
| 183 | r = free_and_strdup(&config->default_pattern, p); | |||
| 184 | else if (streq(field, "timeout")(strcmp((field),("timeout")) == 0)) | |||
| 185 | r = free_and_strdup(&config->timeout, p); | |||
| 186 | else if (streq(field, "editor")(strcmp((field),("editor")) == 0)) | |||
| 187 | r = free_and_strdup(&config->editor, p); | |||
| 188 | else if (streq(field, "auto-entries")(strcmp((field),("auto-entries")) == 0)) | |||
| 189 | r = free_and_strdup(&config->auto_entries, p); | |||
| 190 | else if (streq(field, "auto-firmware")(strcmp((field),("auto-firmware")) == 0)) | |||
| 191 | r = free_and_strdup(&config->auto_firmware, p); | |||
| 192 | else if (streq(field, "console-mode")(strcmp((field),("console-mode")) == 0)) | |||
| 193 | r = free_and_strdup(&config->console_mode, p); | |||
| 194 | else { | |||
| 195 | log_notice("%s:%u: Unknown line \"%s\"", path, line, field)({ int _level = (((5))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 195, __func__, "%s:%u: Unknown line \"%s\"" , path, line, field) : -abs(_e); }); | |||
| 196 | continue; | |||
| 197 | } | |||
| 198 | if (r < 0) | |||
| 199 | return log_error_errno(r, "%s:%u: Error while reading: %m", path, line)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 199, __func__, "%s:%u: Error while reading: %m" , path, line) : -abs(_e); }); | |||
| 200 | } | |||
| 201 | ||||
| 202 | return 0; | |||
| 203 | } | |||
| 204 | ||||
| 205 | static int boot_entry_compare(const void *a, const void *b) { | |||
| 206 | const BootEntry *aa = a, *bb = b; | |||
| 207 | ||||
| 208 | return str_verscmp(aa->filename, bb->filename); | |||
| 209 | } | |||
| 210 | ||||
| 211 | int boot_entries_find(const char *dir, BootEntry **ret_entries, size_t *ret_n_entries) { | |||
| 212 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **files = NULL((void*)0); | |||
| 213 | char **f; | |||
| 214 | int r; | |||
| 215 | BootEntry *array = NULL((void*)0); | |||
| 216 | size_t n_allocated = 0, n = 0; | |||
| 217 | ||||
| 218 | assert(dir)do { if ((__builtin_expect(!!(!(dir)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("dir"), "../src/shared/bootspec.c", 218, __PRETTY_FUNCTION__); } while (0); | |||
| 219 | assert(ret_entries)do { if ((__builtin_expect(!!(!(ret_entries)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret_entries"), "../src/shared/bootspec.c" , 219, __PRETTY_FUNCTION__); } while (0); | |||
| 220 | assert(ret_n_entries)do { if ((__builtin_expect(!!(!(ret_n_entries)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret_n_entries"), "../src/shared/bootspec.c" , 220, __PRETTY_FUNCTION__); } while (0); | |||
| 221 | ||||
| 222 | r = conf_files_list(&files, ".conf", NULL((void*)0), 0, dir, NULL((void*)0)); | |||
| 223 | if (r < 0) | |||
| 224 | return log_error_errno(r, "Failed to list files in \"%s\": %m", dir)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 224, __func__, "Failed to list files in \"%s\": %m" , dir) : -abs(_e); }); | |||
| 225 | ||||
| 226 | STRV_FOREACH(f, files)for ((f) = (files); (f) && *(f); (f)++) { | |||
| 227 | if (!GREEDY_REALLOC0(array, n_allocated, n + 1)greedy_realloc0((void**) &(array), &(n_allocated), (n + 1), sizeof((array)[0]))) | |||
| 228 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/shared/bootspec.c" , 228, __func__); | |||
| 229 | ||||
| 230 | r = boot_entry_load(*f, array + n); | |||
| 231 | if (r < 0) | |||
| 232 | continue; | |||
| 233 | ||||
| 234 | n++; | |||
| 235 | } | |||
| 236 | ||||
| 237 | qsort_safe(array, n, sizeof(BootEntry), boot_entry_compare); | |||
| 238 | ||||
| 239 | *ret_entries = array; | |||
| 240 | *ret_n_entries = n; | |||
| 241 | ||||
| 242 | return 0; | |||
| 243 | } | |||
| 244 | ||||
| 245 | static bool_Bool find_nonunique(BootEntry *entries, size_t n_entries, bool_Bool *arr) { | |||
| 246 | size_t i, j; | |||
| 247 | bool_Bool non_unique = false0; | |||
| 248 | ||||
| 249 | assert(entries || n_entries == 0)do { if ((__builtin_expect(!!(!(entries || n_entries == 0)),0 ))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("entries || n_entries == 0" ), "../src/shared/bootspec.c", 249, __PRETTY_FUNCTION__); } while (0); | |||
| 250 | assert(arr || n_entries == 0)do { if ((__builtin_expect(!!(!(arr || n_entries == 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("arr || n_entries == 0"), "../src/shared/bootspec.c" , 250, __PRETTY_FUNCTION__); } while (0); | |||
| 251 | ||||
| 252 | for (i = 0; i < n_entries; i++) | |||
| 253 | arr[i] = false0; | |||
| 254 | ||||
| 255 | for (i = 0; i < n_entries; i++) | |||
| 256 | for (j = 0; j < n_entries; j++) | |||
| 257 | if (i != j && streq(boot_entry_title(entries + i),(strcmp((boot_entry_title(entries + i)),(boot_entry_title(entries + j))) == 0) | |||
| 258 | boot_entry_title(entries + j))(strcmp((boot_entry_title(entries + i)),(boot_entry_title(entries + j))) == 0)) | |||
| 259 | non_unique = arr[i] = arr[j] = true1; | |||
| 260 | ||||
| 261 | return non_unique; | |||
| 262 | } | |||
| 263 | ||||
| 264 | static int boot_entries_uniquify(BootEntry *entries, size_t n_entries) { | |||
| 265 | char *s; | |||
| 266 | size_t i; | |||
| 267 | int r; | |||
| 268 | bool_Bool arr[n_entries]; | |||
| ||||
| 269 | ||||
| 270 | assert(entries || n_entries == 0)do { if ((__builtin_expect(!!(!(entries || n_entries == 0)),0 ))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("entries || n_entries == 0" ), "../src/shared/bootspec.c", 270, __PRETTY_FUNCTION__); } while (0); | |||
| 271 | ||||
| 272 | /* Find _all_ non-unique titles */ | |||
| 273 | if (!find_nonunique(entries, n_entries, arr)) | |||
| 274 | return 0; | |||
| 275 | ||||
| 276 | /* Add version to non-unique titles */ | |||
| 277 | for (i = 0; i < n_entries; i++) | |||
| 278 | if (arr[i] && entries[i].version) { | |||
| 279 | r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].version); | |||
| 280 | if (r < 0) | |||
| 281 | return -ENOMEM12; | |||
| 282 | ||||
| 283 | free_and_replace(entries[i].show_title, s)({ free(entries[i].show_title); (entries[i].show_title) = (s) ; (s) = ((void*)0); 0; }); | |||
| 284 | } | |||
| 285 | ||||
| 286 | if (!find_nonunique(entries, n_entries, arr)) | |||
| 287 | return 0; | |||
| 288 | ||||
| 289 | /* Add machine-id to non-unique titles */ | |||
| 290 | for (i = 0; i < n_entries; i++) | |||
| 291 | if (arr[i] && entries[i].machine_id) { | |||
| 292 | r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].machine_id); | |||
| 293 | if (r < 0) | |||
| 294 | return -ENOMEM12; | |||
| 295 | ||||
| 296 | free_and_replace(entries[i].show_title, s)({ free(entries[i].show_title); (entries[i].show_title) = (s) ; (s) = ((void*)0); 0; }); | |||
| 297 | } | |||
| 298 | ||||
| 299 | if (!find_nonunique(entries, n_entries, arr)) | |||
| 300 | return 0; | |||
| 301 | ||||
| 302 | /* Add file name to non-unique titles */ | |||
| 303 | for (i = 0; i < n_entries; i++) | |||
| 304 | if (arr[i]) { | |||
| 305 | r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].filename); | |||
| 306 | if (r < 0) | |||
| 307 | return -ENOMEM12; | |||
| 308 | ||||
| 309 | free_and_replace(entries[i].show_title, s)({ free(entries[i].show_title); (entries[i].show_title) = (s) ; (s) = ((void*)0); 0; }); | |||
| 310 | } | |||
| 311 | ||||
| 312 | return 0; | |||
| 313 | } | |||
| 314 | ||||
| 315 | static int boot_entries_select_default(const BootConfig *config) { | |||
| 316 | int i; | |||
| 317 | ||||
| 318 | assert(config)do { if ((__builtin_expect(!!(!(config)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("config"), "../src/shared/bootspec.c", 318 , __PRETTY_FUNCTION__); } while (0); | |||
| 319 | ||||
| 320 | if (config->entry_oneshot) | |||
| 321 | for (i = config->n_entries - 1; i >= 0; i--) | |||
| 322 | if (streq(config->entry_oneshot, config->entries[i].filename)(strcmp((config->entry_oneshot),(config->entries[i].filename )) == 0)) { | |||
| 323 | log_debug("Found default: filename \"%s\" is matched by LoaderEntryOneShot",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 324, __func__, "Found default: filename \"%s\" is matched by LoaderEntryOneShot" , config->entries[i].filename) : -abs(_e); }) | |||
| 324 | config->entries[i].filename)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 324, __func__, "Found default: filename \"%s\" is matched by LoaderEntryOneShot" , config->entries[i].filename) : -abs(_e); }); | |||
| 325 | return i; | |||
| 326 | } | |||
| 327 | ||||
| 328 | if (config->entry_default) | |||
| 329 | for (i = config->n_entries - 1; i >= 0; i--) | |||
| 330 | if (streq(config->entry_default, config->entries[i].filename)(strcmp((config->entry_default),(config->entries[i].filename )) == 0)) { | |||
| 331 | log_debug("Found default: filename \"%s\" is matched by LoaderEntryDefault",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 332, __func__, "Found default: filename \"%s\" is matched by LoaderEntryDefault" , config->entries[i].filename) : -abs(_e); }) | |||
| 332 | config->entries[i].filename)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 332, __func__, "Found default: filename \"%s\" is matched by LoaderEntryDefault" , config->entries[i].filename) : -abs(_e); }); | |||
| 333 | return i; | |||
| 334 | } | |||
| 335 | ||||
| 336 | if (config->default_pattern) | |||
| 337 | for (i = config->n_entries - 1; i >= 0; i--) | |||
| 338 | if (fnmatch(config->default_pattern, config->entries[i].filename, FNM_CASEFOLD(1 << 4)) == 0) { | |||
| 339 | log_debug("Found default: filename \"%s\" is matched by pattern \"%s\"",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 340, __func__, "Found default: filename \"%s\" is matched by pattern \"%s\"" , config->entries[i].filename, config->default_pattern) : -abs(_e); }) | |||
| 340 | config->entries[i].filename, config->default_pattern)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 340, __func__, "Found default: filename \"%s\" is matched by pattern \"%s\"" , config->entries[i].filename, config->default_pattern) : -abs(_e); }); | |||
| 341 | return i; | |||
| 342 | } | |||
| 343 | ||||
| 344 | if (config->n_entries > 0) | |||
| 345 | log_debug("Found default: last entry \"%s\"", config->entries[config->n_entries - 1].filename)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 345, __func__, "Found default: last entry \"%s\"" , config->entries[config->n_entries - 1].filename) : -abs (_e); }); | |||
| 346 | else | |||
| 347 | log_debug("Found no default boot entry :(")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 347, __func__, "Found no default boot entry :(" ) : -abs(_e); }); | |||
| 348 | ||||
| 349 | return config->n_entries - 1; /* -1 means "no default" */ | |||
| 350 | } | |||
| 351 | ||||
| 352 | int boot_entries_load_config(const char *esp_path, BootConfig *config) { | |||
| 353 | const char *p; | |||
| 354 | int r; | |||
| 355 | ||||
| 356 | assert(esp_path)do { if ((__builtin_expect(!!(!(esp_path)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("esp_path"), "../src/shared/bootspec.c", 356, __PRETTY_FUNCTION__); } while (0); | |||
| ||||
| 357 | assert(config)do { if ((__builtin_expect(!!(!(config)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("config"), "../src/shared/bootspec.c", 357 , __PRETTY_FUNCTION__); } while (0); | |||
| 358 | ||||
| 359 | p = strjoina(esp_path, "/loader/loader.conf")({ const char *_appendees_[] = { esp_path, "/loader/loader.conf" }; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_ )/sizeof((_appendees_)[0]), ((void)0))) && _appendees_ [_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }); | |||
| 360 | r = boot_loader_read_conf(p, config); | |||
| 361 | if (r
| |||
| 362 | return log_error_errno(r, "Failed to read boot config from \"%s\": %m", p)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 362, __func__, "Failed to read boot config from \"%s\": %m" , p) : -abs(_e); }); | |||
| 363 | ||||
| 364 | p = strjoina(esp_path, "/loader/entries")({ const char *_appendees_[] = { esp_path, "/loader/entries" } ; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0 ; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_ )/sizeof((_appendees_)[0]), ((void)0))) && _appendees_ [_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }); | |||
| 365 | r = boot_entries_find(p, &config->entries, &config->n_entries); | |||
| 366 | if (r
| |||
| 367 | return log_error_errno(r, "Failed to read boot entries from \"%s\": %m", p)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 367, __func__, "Failed to read boot entries from \"%s\": %m" , p) : -abs(_e); }); | |||
| 368 | ||||
| 369 | r = boot_entries_uniquify(config->entries, config->n_entries); | |||
| 370 | if (r < 0) | |||
| 371 | return log_error_errno(r, "Failed to uniquify boot entries: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 371, __func__, "Failed to uniquify boot entries: %m" ) : -abs(_e); }); | |||
| 372 | ||||
| 373 | r = efi_get_variable_string(EFI_VENDOR_LOADER((const sd_id128_t) { .bytes = { 0x4a, 0x67, 0xb0, 0x82, 0x0a , 0x4c, 0x41, 0xcf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f }}), "LoaderEntryOneShot", &config->entry_oneshot); | |||
| 374 | if (r < 0 && r != -ENOENT2) | |||
| 375 | return log_error_errno(r, "Failed to read EFI var \"LoaderEntryOneShot\": %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 375, __func__, "Failed to read EFI var \"LoaderEntryOneShot\": %m" ) : -abs(_e); }); | |||
| 376 | ||||
| 377 | r = efi_get_variable_string(EFI_VENDOR_LOADER((const sd_id128_t) { .bytes = { 0x4a, 0x67, 0xb0, 0x82, 0x0a , 0x4c, 0x41, 0xcf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f }}), "LoaderEntryDefault", &config->entry_default); | |||
| 378 | if (r < 0 && r != -ENOENT2) | |||
| 379 | return log_error_errno(r, "Failed to read EFI var \"LoaderEntryDefault\": %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 379, __func__, "Failed to read EFI var \"LoaderEntryDefault\": %m" ) : -abs(_e); }); | |||
| 380 | ||||
| 381 | config->default_entry = boot_entries_select_default(config); | |||
| 382 | return 0; | |||
| 383 | } | |||
| 384 | ||||
| 385 | /********************************************************************************/ | |||
| 386 | ||||
| 387 | static int verify_esp( | |||
| 388 | const char *p, | |||
| 389 | bool_Bool searching, | |||
| 390 | bool_Bool unprivileged_mode, | |||
| 391 | uint32_t *ret_part, | |||
| 392 | uint64_t *ret_pstart, | |||
| 393 | uint64_t *ret_psize, | |||
| 394 | sd_id128_t *ret_uuid) { | |||
| 395 | #if HAVE_BLKID1 | |||
| 396 | _cleanup_(blkid_free_probep)__attribute__((cleanup(blkid_free_probep))) blkid_probe b = NULL((void*)0); | |||
| 397 | char t[DEV_NUM_PATH_MAX((sizeof("""/dev/block/""") - 1) + (2+(sizeof(dev_t) <= 1 ? 3 : sizeof(dev_t) <= 2 ? 5 : sizeof(dev_t) <= 4 ? 10 : sizeof(dev_t) <= 8 ? 20 : sizeof(int[-2*(sizeof(dev_t) > 8)]))) + 1 + (2+(sizeof(dev_t) <= 1 ? 3 : sizeof(dev_t) <= 2 ? 5 : sizeof(dev_t) <= 4 ? 10 : sizeof(dev_t) <= 8 ? 20 : sizeof(int[-2*(sizeof(dev_t) > 8)]))))]; | |||
| 398 | const char *v; | |||
| 399 | #endif | |||
| 400 | uint64_t pstart = 0, psize = 0; | |||
| 401 | struct stat st, st2; | |||
| 402 | const char *t2; | |||
| 403 | struct statfs sfs; | |||
| 404 | sd_id128_t uuid = SD_ID128_NULL((const sd_id128_t) { .qwords = { 0, 0 }}); | |||
| 405 | uint32_t part = 0; | |||
| 406 | int r; | |||
| 407 | ||||
| 408 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/shared/bootspec.c", 408, __PRETTY_FUNCTION__ ); } while (0); | |||
| 409 | ||||
| 410 | /* Non-root user can only check the status, so if an error occured in the following, it does not cause any | |||
| 411 | * issues. Let's also, silence the error messages. */ | |||
| 412 | ||||
| 413 | if (statfs(p, &sfs) < 0) { | |||
| 414 | /* If we are searching for the mount point, don't generate a log message if we can't find the path */ | |||
| 415 | if (errno(*__errno_location ()) == ENOENT2 && searching) | |||
| 416 | return -ENOENT2; | |||
| 417 | ||||
| 418 | return log_full_errno(unprivileged_mode && errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,({ int _level = ((unprivileged_mode && (*__errno_location ()) == 13 ? 7 : 3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/shared/bootspec.c", 419, __func__ , "Failed to check file system type of \"%s\": %m", p) : -abs (_e); }) | |||
| 419 | "Failed to check file system type of \"%s\": %m", p)({ int _level = ((unprivileged_mode && (*__errno_location ()) == 13 ? 7 : 3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/shared/bootspec.c", 419, __func__ , "Failed to check file system type of \"%s\": %m", p) : -abs (_e); }); | |||
| 420 | } | |||
| 421 | ||||
| 422 | if (!F_TYPE_EQUAL(sfs.f_type, MSDOS_SUPER_MAGIC)(sfs.f_type == (typeof(sfs.f_type)) 0x4d44)) { | |||
| 423 | if (searching) | |||
| 424 | return -EADDRNOTAVAIL99; | |||
| 425 | ||||
| 426 | log_error("File system \"%s\" is not a FAT EFI System Partition (ESP) file system.", p)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 426, __func__, "File system \"%s\" is not a FAT EFI System Partition (ESP) file system." , p) : -abs(_e); }); | |||
| 427 | return -ENODEV19; | |||
| 428 | } | |||
| 429 | ||||
| 430 | if (stat(p, &st) < 0) | |||
| 431 | return log_full_errno(unprivileged_mode && errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,({ int _level = ((unprivileged_mode && (*__errno_location ()) == 13 ? 7 : 3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/shared/bootspec.c", 432, __func__ , "Failed to determine block device node of \"%s\": %m", p) : -abs(_e); }) | |||
| 432 | "Failed to determine block device node of \"%s\": %m", p)({ int _level = ((unprivileged_mode && (*__errno_location ()) == 13 ? 7 : 3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/shared/bootspec.c", 432, __func__ , "Failed to determine block device node of \"%s\": %m", p) : -abs(_e); }); | |||
| 433 | ||||
| 434 | if (major(st.st_dev)gnu_dev_major (st.st_dev) == 0) { | |||
| 435 | log_error("Block device node of %p is invalid.", p)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 435, __func__, "Block device node of %p is invalid." , p) : -abs(_e); }); | |||
| 436 | return -ENODEV19; | |||
| 437 | } | |||
| 438 | ||||
| 439 | t2 = strjoina(p, "/..")({ const char *_appendees_[] = { p, "/.." }; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_ )/sizeof((_appendees_)[0]), ((void)0))) && _appendees_ [_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }); | |||
| 440 | r = stat(t2, &st2); | |||
| 441 | if (r < 0) | |||
| 442 | return log_full_errno(unprivileged_mode && errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,({ int _level = ((unprivileged_mode && (*__errno_location ()) == 13 ? 7 : 3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/shared/bootspec.c", 443, __func__ , "Failed to determine block device node of parent of \"%s\": %m" , p) : -abs(_e); }) | |||
| 443 | "Failed to determine block device node of parent of \"%s\": %m", p)({ int _level = ((unprivileged_mode && (*__errno_location ()) == 13 ? 7 : 3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/shared/bootspec.c", 443, __func__ , "Failed to determine block device node of parent of \"%s\": %m" , p) : -abs(_e); }); | |||
| 444 | ||||
| 445 | if (st.st_dev == st2.st_dev) { | |||
| 446 | log_error("Directory \"%s\" is not the root of the EFI System Partition (ESP) file system.", p)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 446, __func__, "Directory \"%s\" is not the root of the EFI System Partition (ESP) file system." , p) : -abs(_e); }); | |||
| 447 | return -ENODEV19; | |||
| 448 | } | |||
| 449 | ||||
| 450 | /* In a container we don't have access to block devices, skip this part of the verification, we trust the | |||
| 451 | * container manager set everything up correctly on its own. Also skip the following verification for non-root user. */ | |||
| 452 | if (detect_container() > 0 || unprivileged_mode) | |||
| 453 | goto finish; | |||
| 454 | ||||
| 455 | #if HAVE_BLKID1 | |||
| 456 | xsprintf_dev_num_path(t, "block", st.st_dev)do { if ((__builtin_expect(!!(!(((size_t) snprintf(t, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (t), typeof(&*(t))), sizeof(t)/sizeof((t)[0]), ((void)0)) ), "/dev/%s/%u:%u", "block", gnu_dev_major (st.st_dev), gnu_dev_minor (st.st_dev)) < (__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(t), typeof(&*(t))), sizeof(t)/sizeof((t)[0]), ((void )0))))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("xsprintf: " "t" "[] must be big enough"), "../src/shared/bootspec.c", 456 , __PRETTY_FUNCTION__); } while (0); | |||
| 457 | errno(*__errno_location ()) = 0; | |||
| 458 | b = blkid_new_probe_from_filename(t); | |||
| 459 | if (!b) | |||
| 460 | return log_error_errno(errno ?: ENOMEM, "Failed to open file system \"%s\": %m", p)({ int _level = ((3)), _e = (((*__errno_location ()) ?: 12)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm ) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/shared/bootspec.c", 460 , __func__, "Failed to open file system \"%s\": %m", p) : -abs (_e); }); | |||
| 461 | ||||
| 462 | blkid_probe_enable_superblocks(b, 1); | |||
| 463 | blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE(1 << 5)); | |||
| 464 | blkid_probe_enable_partitions(b, 1); | |||
| 465 | blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS(1 << 2)); | |||
| 466 | ||||
| 467 | errno(*__errno_location ()) = 0; | |||
| 468 | r = blkid_do_safeprobe(b); | |||
| 469 | if (r == -2) { | |||
| 470 | log_error("File system \"%s\" is ambiguous.", p)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 470, __func__, "File system \"%s\" is ambiguous." , p) : -abs(_e); }); | |||
| 471 | return -ENODEV19; | |||
| 472 | } else if (r == 1) { | |||
| 473 | log_error("File system \"%s\" does not contain a label.", p)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 473, __func__, "File system \"%s\" does not contain a label." , p) : -abs(_e); }); | |||
| 474 | return -ENODEV19; | |||
| 475 | } else if (r != 0) | |||
| 476 | return log_error_errno(errno ?: EIO, "Failed to probe file system \"%s\": %m", p)({ int _level = ((3)), _e = (((*__errno_location ()) ?: 5)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/shared/bootspec.c", 476, __func__ , "Failed to probe file system \"%s\": %m", p) : -abs(_e); }); | |||
| 477 | ||||
| 478 | errno(*__errno_location ()) = 0; | |||
| 479 | r = blkid_probe_lookup_value(b, "TYPE", &v, NULL((void*)0)); | |||
| 480 | if (r != 0) | |||
| 481 | return log_error_errno(errno ?: EIO, "Failed to probe file system type \"%s\": %m", p)({ int _level = ((3)), _e = (((*__errno_location ()) ?: 5)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/shared/bootspec.c", 481, __func__ , "Failed to probe file system type \"%s\": %m", p) : -abs(_e ); }); | |||
| 482 | if (!streq(v, "vfat")(strcmp((v),("vfat")) == 0)) { | |||
| 483 | log_error("File system \"%s\" is not FAT.", p)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 483, __func__, "File system \"%s\" is not FAT." , p) : -abs(_e); }); | |||
| 484 | return -ENODEV19; | |||
| 485 | } | |||
| 486 | ||||
| 487 | errno(*__errno_location ()) = 0; | |||
| 488 | r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL((void*)0)); | |||
| 489 | if (r != 0) | |||
| 490 | return log_error_errno(errno ?: EIO, "Failed to probe partition scheme \"%s\": %m", p)({ int _level = ((3)), _e = (((*__errno_location ()) ?: 5)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/shared/bootspec.c", 490, __func__ , "Failed to probe partition scheme \"%s\": %m", p) : -abs(_e ); }); | |||
| 491 | if (!streq(v, "gpt")(strcmp((v),("gpt")) == 0)) { | |||
| 492 | log_error("File system \"%s\" is not on a GPT partition table.", p)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 492, __func__, "File system \"%s\" is not on a GPT partition table." , p) : -abs(_e); }); | |||
| 493 | return -ENODEV19; | |||
| 494 | } | |||
| 495 | ||||
| 496 | errno(*__errno_location ()) = 0; | |||
| 497 | r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL((void*)0)); | |||
| 498 | if (r != 0) | |||
| 499 | return log_error_errno(errno ?: EIO, "Failed to probe partition type UUID \"%s\": %m", p)({ int _level = ((3)), _e = (((*__errno_location ()) ?: 5)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/shared/bootspec.c", 499, __func__ , "Failed to probe partition type UUID \"%s\": %m", p) : -abs (_e); }); | |||
| 500 | if (!streq(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b")(strcmp((v),("c12a7328-f81f-11d2-ba4b-00a0c93ec93b")) == 0)) { | |||
| 501 | log_error("File system \"%s\" has wrong type for an EFI System Partition (ESP).", p)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 501, __func__, "File system \"%s\" has wrong type for an EFI System Partition (ESP)." , p) : -abs(_e); }); | |||
| 502 | return -ENODEV19; | |||
| 503 | } | |||
| 504 | ||||
| 505 | errno(*__errno_location ()) = 0; | |||
| 506 | r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &v, NULL((void*)0)); | |||
| 507 | if (r != 0) | |||
| 508 | return log_error_errno(errno ?: EIO, "Failed to probe partition entry UUID \"%s\": %m", p)({ int _level = ((3)), _e = (((*__errno_location ()) ?: 5)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/shared/bootspec.c", 508, __func__ , "Failed to probe partition entry UUID \"%s\": %m", p) : -abs (_e); }); | |||
| 509 | r = sd_id128_from_string(v, &uuid); | |||
| 510 | if (r < 0) { | |||
| 511 | log_error("Partition \"%s\" has invalid UUID \"%s\".", p, v)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 511, __func__, "Partition \"%s\" has invalid UUID \"%s\"." , p, v) : -abs(_e); }); | |||
| 512 | return -EIO5; | |||
| 513 | } | |||
| 514 | ||||
| 515 | errno(*__errno_location ()) = 0; | |||
| 516 | r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL((void*)0)); | |||
| 517 | if (r != 0) | |||
| 518 | return log_error_errno(errno ?: EIO, "Failed to probe partition number \"%s\": m", p)({ int _level = ((3)), _e = (((*__errno_location ()) ?: 5)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/shared/bootspec.c", 518, __func__ , "Failed to probe partition number \"%s\": m", p) : -abs(_e) ; }); | |||
| 519 | r = safe_atou32(v, &part); | |||
| 520 | if (r < 0) | |||
| 521 | return log_error_errno(r, "Failed to parse PART_ENTRY_NUMBER field.")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 521, __func__, "Failed to parse PART_ENTRY_NUMBER field." ) : -abs(_e); }); | |||
| 522 | ||||
| 523 | errno(*__errno_location ()) = 0; | |||
| 524 | r = blkid_probe_lookup_value(b, "PART_ENTRY_OFFSET", &v, NULL((void*)0)); | |||
| 525 | if (r != 0) | |||
| 526 | return log_error_errno(errno ?: EIO, "Failed to probe partition offset \"%s\": %m", p)({ int _level = ((3)), _e = (((*__errno_location ()) ?: 5)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/shared/bootspec.c", 526, __func__ , "Failed to probe partition offset \"%s\": %m", p) : -abs(_e ); }); | |||
| 527 | r = safe_atou64(v, &pstart); | |||
| 528 | if (r < 0) | |||
| 529 | return log_error_errno(r, "Failed to parse PART_ENTRY_OFFSET field.")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 529, __func__, "Failed to parse PART_ENTRY_OFFSET field." ) : -abs(_e); }); | |||
| 530 | ||||
| 531 | errno(*__errno_location ()) = 0; | |||
| 532 | r = blkid_probe_lookup_value(b, "PART_ENTRY_SIZE", &v, NULL((void*)0)); | |||
| 533 | if (r != 0) | |||
| 534 | return log_error_errno(errno ?: EIO, "Failed to probe partition size \"%s\": %m", p)({ int _level = ((3)), _e = (((*__errno_location ()) ?: 5)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/shared/bootspec.c", 534, __func__ , "Failed to probe partition size \"%s\": %m", p) : -abs(_e); }); | |||
| 535 | r = safe_atou64(v, &psize); | |||
| 536 | if (r < 0) | |||
| 537 | return log_error_errno(r, "Failed to parse PART_ENTRY_SIZE field.")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/shared/bootspec.c", 537, __func__, "Failed to parse PART_ENTRY_SIZE field." ) : -abs(_e); }); | |||
| 538 | #endif | |||
| 539 | ||||
| 540 | finish: | |||
| 541 | if (ret_part) | |||
| 542 | *ret_part = part; | |||
| 543 | if (ret_pstart) | |||
| 544 | *ret_pstart = pstart; | |||
| 545 | if (ret_psize) | |||
| 546 | *ret_psize = psize; | |||
| 547 | if (ret_uuid) | |||
| 548 | *ret_uuid = uuid; | |||
| 549 | ||||
| 550 | return 0; | |||
| 551 | } | |||
| 552 | ||||
| 553 | int find_esp_and_warn( | |||
| 554 | const char *path, | |||
| 555 | bool_Bool unprivileged_mode, | |||
| 556 | char **ret_path, | |||
| 557 | uint32_t *ret_part, | |||
| 558 | uint64_t *ret_pstart, | |||
| 559 | uint64_t *ret_psize, | |||
| 560 | sd_id128_t *ret_uuid) { | |||
| 561 | ||||
| 562 | int r; | |||
| 563 | ||||
| 564 | /* This logs about all errors except: | |||
| 565 | * | |||
| 566 | * -ENOKEY → when we can't find the partition | |||
| 567 | * -EACCESS → when unprivileged_mode is true, and we can't access something | |||
| 568 | */ | |||
| 569 | ||||
| 570 | if (path) { | |||
| 571 | r = verify_esp(path, false0, unprivileged_mode, ret_part, ret_pstart, ret_psize, ret_uuid); | |||
| 572 | if (r < 0) | |||
| 573 | return r; | |||
| 574 | ||||
| 575 | goto found; | |||
| 576 | } | |||
| 577 | ||||
| 578 | FOREACH_STRING(path, "/efi", "/boot", "/boot/efi")for (char **_l = ({ char **_ll = ((char**) ((const char*[]) { "/efi", "/boot", "/boot/efi", ((void*)0) })); path = _ll ? _ll [0] : ((void*)0); _ll; }); _l && *_l; path = ({ _l ++ ; _l[0]; })) { | |||
| 579 | ||||
| 580 | r = verify_esp(path, true1, unprivileged_mode, ret_part, ret_pstart, ret_psize, ret_uuid); | |||
| 581 | if (r >= 0) | |||
| 582 | goto found; | |||
| 583 | if (!IN_SET(r, -ENOENT, -EADDRNOTAVAIL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){-2, -99})/sizeof(int)]; switch(r) { case -2: case -99: _found = 1; break; default: break; } _found; } )) /* This one is not it */ | |||
| 584 | return r; | |||
| 585 | } | |||
| 586 | ||||
| 587 | /* No logging here */ | |||
| 588 | return -ENOKEY126; | |||
| 589 | ||||
| 590 | found: | |||
| 591 | if (ret_path) { | |||
| 592 | char *c; | |||
| 593 | ||||
| 594 | c = strdup(path); | |||
| 595 | if (!c) | |||
| 596 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/shared/bootspec.c" , 596, __func__); | |||
| 597 | ||||
| 598 | *ret_path = c; | |||
| 599 | } | |||
| 600 | ||||
| 601 | return 0; | |||
| 602 | } |