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 | } |