]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/login/logind-core.c
Merge pull request #17066 from keszybz/allow-loopback-addresses
[thirdparty/systemd.git] / src / login / logind-core.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <fcntl.h>
4 #include <sys/ioctl.h>
5 #include <sys/types.h>
6 #include <linux/vt.h>
7
8 #include "sd-device.h"
9
10 #include "alloc-util.h"
11 #include "bus-error.h"
12 #include "bus-util.h"
13 #include "cgroup-util.h"
14 #include "conf-parser.h"
15 #include "device-util.h"
16 #include "efi-loader.h"
17 #include "errno-util.h"
18 #include "fd-util.h"
19 #include "limits-util.h"
20 #include "logind.h"
21 #include "parse-util.h"
22 #include "path-util.h"
23 #include "process-util.h"
24 #include "strv.h"
25 #include "terminal-util.h"
26 #include "udev-util.h"
27 #include "user-util.h"
28 #include "userdb.h"
29 #include "utmp-wtmp.h"
30
31 void manager_reset_config(Manager *m) {
32 assert(m);
33
34 m->n_autovts = 6;
35 m->reserve_vt = 6;
36 m->remove_ipc = true;
37 m->inhibit_delay_max = 5 * USEC_PER_SEC;
38 m->user_stop_delay = 10 * USEC_PER_SEC;
39
40 m->handle_power_key = HANDLE_POWEROFF;
41 m->handle_suspend_key = HANDLE_SUSPEND;
42 m->handle_hibernate_key = HANDLE_HIBERNATE;
43 m->handle_lid_switch = HANDLE_SUSPEND;
44 m->handle_lid_switch_ep = _HANDLE_ACTION_INVALID;
45 m->handle_lid_switch_docked = HANDLE_IGNORE;
46 m->handle_reboot_key = HANDLE_REBOOT;
47 m->power_key_ignore_inhibited = false;
48 m->suspend_key_ignore_inhibited = false;
49 m->hibernate_key_ignore_inhibited = false;
50 m->lid_switch_ignore_inhibited = true;
51 m->reboot_key_ignore_inhibited = false;
52
53 m->holdoff_timeout_usec = 30 * USEC_PER_SEC;
54
55 m->idle_action_usec = 30 * USEC_PER_MINUTE;
56 m->idle_action = HANDLE_IGNORE;
57
58 m->runtime_dir_size = physical_memory_scale(10U, 100U); /* 10% */
59 m->runtime_dir_inodes = DIV_ROUND_UP(m->runtime_dir_size, 4096); /* 4k per inode */
60 m->sessions_max = 8192;
61 m->inhibitors_max = 8192;
62
63 m->kill_user_processes = KILL_USER_PROCESSES;
64
65 m->kill_only_users = strv_free(m->kill_only_users);
66 m->kill_exclude_users = strv_free(m->kill_exclude_users);
67 }
68
69 int manager_parse_config_file(Manager *m) {
70 assert(m);
71
72 return config_parse_many_nulstr(
73 PKGSYSCONFDIR "/logind.conf",
74 CONF_PATHS_NULSTR("systemd/logind.conf.d"),
75 "Login\0",
76 config_item_perf_lookup, logind_gperf_lookup,
77 CONFIG_PARSE_WARN, m,
78 NULL);
79 }
80
81 int manager_add_device(Manager *m, const char *sysfs, bool master, Device **ret_device) {
82 Device *d;
83
84 assert(m);
85 assert(sysfs);
86
87 d = hashmap_get(m->devices, sysfs);
88 if (d)
89 /* we support adding master-flags, but not removing them */
90 d->master = d->master || master;
91 else {
92 d = device_new(m, sysfs, master);
93 if (!d)
94 return -ENOMEM;
95 }
96
97 if (ret_device)
98 *ret_device = d;
99
100 return 0;
101 }
102
103 int manager_add_seat(Manager *m, const char *id, Seat **ret_seat) {
104 Seat *s;
105 int r;
106
107 assert(m);
108 assert(id);
109
110 s = hashmap_get(m->seats, id);
111 if (!s) {
112 r = seat_new(&s, m, id);
113 if (r < 0)
114 return r;
115 }
116
117 if (ret_seat)
118 *ret_seat = s;
119
120 return 0;
121 }
122
123 int manager_add_session(Manager *m, const char *id, Session **ret_session) {
124 Session *s;
125 int r;
126
127 assert(m);
128 assert(id);
129
130 s = hashmap_get(m->sessions, id);
131 if (!s) {
132 r = session_new(&s, m, id);
133 if (r < 0)
134 return r;
135 }
136
137 if (ret_session)
138 *ret_session = s;
139
140 return 0;
141 }
142
143 int manager_add_user(
144 Manager *m,
145 UserRecord *ur,
146 User **ret_user) {
147
148 User *u;
149 int r;
150
151 assert(m);
152 assert(ur);
153
154 u = hashmap_get(m->users, UID_TO_PTR(ur->uid));
155 if (!u) {
156 r = user_new(&u, m, ur);
157 if (r < 0)
158 return r;
159 }
160
161 if (ret_user)
162 *ret_user = u;
163
164 return 0;
165 }
166
167 int manager_add_user_by_name(
168 Manager *m,
169 const char *name,
170 User **ret_user) {
171
172 _cleanup_(user_record_unrefp) UserRecord *ur = NULL;
173 int r;
174
175 assert(m);
176 assert(name);
177
178 r = userdb_by_name(name, USERDB_AVOID_SHADOW, &ur);
179 if (r < 0)
180 return r;
181
182 return manager_add_user(m, ur, ret_user);
183 }
184
185 int manager_add_user_by_uid(
186 Manager *m,
187 uid_t uid,
188 User **ret_user) {
189
190 _cleanup_(user_record_unrefp) UserRecord *ur = NULL;
191 int r;
192
193 assert(m);
194 assert(uid_is_valid(uid));
195
196 r = userdb_by_uid(uid, USERDB_AVOID_SHADOW, &ur);
197 if (r < 0)
198 return r;
199
200 return manager_add_user(m, ur, ret_user);
201 }
202
203 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **ret) {
204 Inhibitor *i;
205 int r;
206
207 assert(m);
208 assert(id);
209
210 i = hashmap_get(m->inhibitors, id);
211 if (!i) {
212 r = inhibitor_new(&i, m, id);
213 if (r < 0)
214 return r;
215 }
216
217 if (ret)
218 *ret = i;
219
220 return 0;
221 }
222
223 int manager_add_button(Manager *m, const char *name, Button **ret_button) {
224 Button *b;
225
226 assert(m);
227 assert(name);
228
229 b = hashmap_get(m->buttons, name);
230 if (!b) {
231 b = button_new(m, name);
232 if (!b)
233 return -ENOMEM;
234 }
235
236 if (ret_button)
237 *ret_button = b;
238
239 return 0;
240 }
241
242 int manager_process_seat_device(Manager *m, sd_device *d) {
243 Device *device;
244 int r;
245
246 assert(m);
247
248 if (device_for_action(d, DEVICE_ACTION_REMOVE) ||
249 sd_device_has_current_tag(d, "seat") <= 0) {
250 const char *syspath;
251
252 r = sd_device_get_syspath(d, &syspath);
253 if (r < 0)
254 return 0;
255
256 device = hashmap_get(m->devices, syspath);
257 if (!device)
258 return 0;
259
260 seat_add_to_gc_queue(device->seat);
261 device_free(device);
262
263 } else {
264 const char *sn, *syspath;
265 bool master;
266 Seat *seat;
267
268 if (sd_device_get_property_value(d, "ID_SEAT", &sn) < 0 || isempty(sn))
269 sn = "seat0";
270
271 if (!seat_name_is_valid(sn)) {
272 log_device_warning(d, "Device with invalid seat name %s found, ignoring.", sn);
273 return 0;
274 }
275
276 seat = hashmap_get(m->seats, sn);
277 master = sd_device_has_current_tag(d, "master-of-seat") > 0;
278
279 /* Ignore non-master devices for unknown seats */
280 if (!master && !seat)
281 return 0;
282
283 r = sd_device_get_syspath(d, &syspath);
284 if (r < 0)
285 return r;
286
287 r = manager_add_device(m, syspath, master, &device);
288 if (r < 0)
289 return r;
290
291 if (!seat) {
292 r = manager_add_seat(m, sn, &seat);
293 if (r < 0) {
294 if (!device->seat)
295 device_free(device);
296
297 return r;
298 }
299 }
300
301 device_attach(device, seat);
302 seat_start(seat);
303 }
304
305 return 0;
306 }
307
308 int manager_process_button_device(Manager *m, sd_device *d) {
309 const char *sysname;
310 Button *b;
311 int r;
312
313 assert(m);
314
315 r = sd_device_get_sysname(d, &sysname);
316 if (r < 0)
317 return r;
318
319 if (device_for_action(d, DEVICE_ACTION_REMOVE) ||
320 sd_device_has_current_tag(d, "power-switch") <= 0) {
321
322 b = hashmap_get(m->buttons, sysname);
323 if (!b)
324 return 0;
325
326 button_free(b);
327
328 } else {
329 const char *sn;
330
331 r = manager_add_button(m, sysname, &b);
332 if (r < 0)
333 return r;
334
335 if (sd_device_get_property_value(d, "ID_SEAT", &sn) < 0 || isempty(sn))
336 sn = "seat0";
337
338 button_set_seat(b, sn);
339
340 r = button_open(b);
341 if (r < 0) /* event device doesn't have any keys or switches relevant to us? (or any other error
342 * opening the device?) let's close the button again. */
343 button_free(b);
344 }
345
346 return 0;
347 }
348
349 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **ret) {
350 _cleanup_free_ char *unit = NULL;
351 Session *s;
352 int r;
353
354 assert(m);
355
356 if (!pid_is_valid(pid))
357 return -EINVAL;
358
359 s = hashmap_get(m->sessions_by_leader, PID_TO_PTR(pid));
360 if (!s) {
361 r = cg_pid_get_unit(pid, &unit);
362 if (r >= 0)
363 s = hashmap_get(m->session_units, unit);
364 }
365
366 if (ret)
367 *ret = s;
368
369 return !!s;
370 }
371
372 int manager_get_user_by_pid(Manager *m, pid_t pid, User **ret) {
373 _cleanup_free_ char *unit = NULL;
374 User *u = NULL;
375 int r;
376
377 assert(m);
378
379 if (!pid_is_valid(pid))
380 return -EINVAL;
381
382 r = cg_pid_get_slice(pid, &unit);
383 if (r >= 0)
384 u = hashmap_get(m->user_units, unit);
385
386 if (ret)
387 *ret = u;
388
389 return !!u;
390 }
391
392 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
393 Session *s;
394 bool idle_hint;
395 dual_timestamp ts = DUAL_TIMESTAMP_NULL;
396
397 assert(m);
398
399 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0, NULL);
400
401 HASHMAP_FOREACH(s, m->sessions) {
402 dual_timestamp k;
403 int ih;
404
405 ih = session_get_idle_hint(s, &k);
406 if (ih < 0)
407 return ih;
408
409 if (!ih) {
410 if (!idle_hint) {
411 if (k.monotonic < ts.monotonic)
412 ts = k;
413 } else {
414 idle_hint = false;
415 ts = k;
416 }
417 } else if (idle_hint) {
418
419 if (k.monotonic > ts.monotonic)
420 ts = k;
421 }
422 }
423
424 if (t)
425 *t = ts;
426
427 return idle_hint;
428 }
429
430 bool manager_shall_kill(Manager *m, const char *user) {
431 assert(m);
432 assert(user);
433
434 if (!m->kill_exclude_users && streq(user, "root"))
435 return false;
436
437 if (strv_contains(m->kill_exclude_users, user))
438 return false;
439
440 if (!strv_isempty(m->kill_only_users))
441 return strv_contains(m->kill_only_users, user);
442
443 return m->kill_user_processes;
444 }
445
446 int config_parse_n_autovts(
447 const char *unit,
448 const char *filename,
449 unsigned line,
450 const char *section,
451 unsigned section_line,
452 const char *lvalue,
453 int ltype,
454 const char *rvalue,
455 void *data,
456 void *userdata) {
457
458 unsigned *n = data;
459 unsigned o;
460 int r;
461
462 assert(filename);
463 assert(lvalue);
464 assert(rvalue);
465 assert(data);
466
467 r = safe_atou(rvalue, &o);
468 if (r < 0) {
469 log_syntax(unit, LOG_WARNING, filename, line, r,
470 "Failed to parse number of autovts, ignoring: %s", rvalue);
471 return 0;
472 }
473
474 if (o > 15) {
475 log_syntax(unit, LOG_WARNING, filename, line, 0,
476 "A maximum of 15 autovts are supported, ignoring: %s", rvalue);
477 return 0;
478 }
479
480 *n = o;
481 return 0;
482 }
483
484 static int vt_is_busy(unsigned vtnr) {
485 struct vt_stat vt_stat;
486 int r;
487 _cleanup_close_ int fd;
488
489 assert(vtnr >= 1);
490
491 /* VT_GETSTATE "cannot return state for more than 16 VTs, since v_state is short" */
492 assert(vtnr <= 15);
493
494 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
495 * we'd open the latter we'd open the foreground tty which
496 * hence would be unconditionally busy. By opening /dev/tty1
497 * we avoid this. Since tty1 is special and needs to be an
498 * explicitly loaded getty or DM this is safe. */
499
500 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
501 if (fd < 0)
502 return -errno;
503
504 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
505 r = -errno;
506 else
507 r = !!(vt_stat.v_state & (1 << vtnr));
508
509 return r;
510 }
511
512 int manager_spawn_autovt(Manager *m, unsigned vtnr) {
513 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
514 char name[sizeof("autovt@tty.service") + DECIMAL_STR_MAX(unsigned)];
515 int r;
516
517 assert(m);
518 assert(vtnr >= 1);
519
520 if (vtnr > m->n_autovts &&
521 vtnr != m->reserve_vt)
522 return 0;
523
524 if (vtnr != m->reserve_vt) {
525 /* If this is the reserved TTY, we'll start the getty
526 * on it in any case, but otherwise only if it is not
527 * busy. */
528
529 r = vt_is_busy(vtnr);
530 if (r < 0)
531 return r;
532 else if (r > 0)
533 return -EBUSY;
534 }
535
536 snprintf(name, sizeof(name), "autovt@tty%u.service", vtnr);
537 r = sd_bus_call_method(
538 m->bus,
539 "org.freedesktop.systemd1",
540 "/org/freedesktop/systemd1",
541 "org.freedesktop.systemd1.Manager",
542 "StartUnit",
543 &error,
544 NULL,
545 "ss", name, "fail");
546 if (r < 0)
547 return log_error_errno(r, "Failed to start %s: %s", name, bus_error_message(&error, r));
548
549 return 0;
550 }
551
552 bool manager_is_lid_closed(Manager *m) {
553 Button *b;
554
555 HASHMAP_FOREACH(b, m->buttons)
556 if (b->lid_closed)
557 return true;
558
559 return false;
560 }
561
562 static bool manager_is_docked(Manager *m) {
563 Button *b;
564
565 HASHMAP_FOREACH(b, m->buttons)
566 if (b->docked)
567 return true;
568
569 return false;
570 }
571
572 static int manager_count_external_displays(Manager *m) {
573 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
574 sd_device *d;
575 int r, n = 0;
576
577 r = sd_device_enumerator_new(&e);
578 if (r < 0)
579 return r;
580
581 r = sd_device_enumerator_allow_uninitialized(e);
582 if (r < 0)
583 return r;
584
585 r = sd_device_enumerator_add_match_subsystem(e, "drm", true);
586 if (r < 0)
587 return r;
588
589 FOREACH_DEVICE(e, d) {
590 const char *status, *enabled, *dash, *nn, *subsys;
591 sd_device *p;
592
593 if (sd_device_get_parent(d, &p) < 0)
594 continue;
595
596 /* If the parent shares the same subsystem as the
597 * device we are looking at then it is a connector,
598 * which is what we are interested in. */
599 if (sd_device_get_subsystem(p, &subsys) < 0 || !streq(subsys, "drm"))
600 continue;
601
602 if (sd_device_get_sysname(d, &nn) < 0)
603 continue;
604
605 /* Ignore internal displays: the type is encoded in the sysfs name, as the second dash
606 * separated item (the first is the card name, the last the connector number). We implement a
607 * deny list of external displays here, rather than an allow list of internal ones, to ensure
608 * we don't block suspends too eagerly. */
609 dash = strchr(nn, '-');
610 if (!dash)
611 continue;
612
613 dash++;
614 if (!STARTSWITH_SET(dash,
615 "VGA-", "DVI-I-", "DVI-D-", "DVI-A-"
616 "Composite-", "SVIDEO-", "Component-",
617 "DIN-", "DP-", "HDMI-A-", "HDMI-B-", "TV-"))
618 continue;
619
620 /* Ignore ports that are not enabled */
621 if (sd_device_get_sysattr_value(d, "enabled", &enabled) < 0 || !streq(enabled, "enabled"))
622 continue;
623
624 /* We count any connector which is not explicitly
625 * "disconnected" as connected. */
626 if (sd_device_get_sysattr_value(d, "status", &status) < 0 || !streq(status, "disconnected"))
627 n++;
628 }
629
630 return n;
631 }
632
633 bool manager_is_docked_or_external_displays(Manager *m) {
634 int n;
635
636 /* If we are docked don't react to lid closing */
637 if (manager_is_docked(m)) {
638 log_debug("System is docked.");
639 return true;
640 }
641
642 /* If we have more than one display connected,
643 * assume that we are docked. */
644 n = manager_count_external_displays(m);
645 if (n < 0)
646 log_warning_errno(n, "Display counting failed: %m");
647 else if (n >= 1) {
648 log_debug("External (%i) displays connected.", n);
649 return true;
650 }
651
652 return false;
653 }
654
655 bool manager_is_on_external_power(void) {
656 int r;
657
658 /* For now we only check for AC power, but 'external power' can apply to anything that isn't an internal
659 * battery */
660 r = on_ac_power();
661 if (r < 0)
662 log_warning_errno(r, "Failed to read AC power status: %m");
663
664 return r != 0; /* Treat failure as 'on AC' */
665 }
666
667 bool manager_all_buttons_ignored(Manager *m) {
668 assert(m);
669
670 if (m->handle_power_key != HANDLE_IGNORE)
671 return false;
672 if (m->handle_suspend_key != HANDLE_IGNORE)
673 return false;
674 if (m->handle_hibernate_key != HANDLE_IGNORE)
675 return false;
676 if (m->handle_lid_switch != HANDLE_IGNORE)
677 return false;
678 if (!IN_SET(m->handle_lid_switch_ep, _HANDLE_ACTION_INVALID, HANDLE_IGNORE))
679 return false;
680 if (m->handle_lid_switch_docked != HANDLE_IGNORE)
681 return false;
682 if (m->handle_reboot_key != HANDLE_IGNORE)
683 return false;
684
685 return true;
686 }
687
688 int manager_read_utmp(Manager *m) {
689 #if ENABLE_UTMP
690 int r;
691 _cleanup_(utxent_cleanup) bool utmpx = false;
692
693 assert(m);
694
695 if (utmpxname(_PATH_UTMPX) < 0)
696 return log_error_errno(errno, "Failed to set utmp path to " _PATH_UTMPX ": %m");
697
698 utmpx = utxent_start();
699
700 for (;;) {
701 _cleanup_free_ char *t = NULL;
702 struct utmpx *u;
703 const char *c;
704 Session *s;
705
706 errno = 0;
707 u = getutxent();
708 if (!u) {
709 if (errno != 0)
710 log_warning_errno(errno, "Failed to read " _PATH_UTMPX ", ignoring: %m");
711 return 0;
712 }
713
714 if (u->ut_type != USER_PROCESS)
715 continue;
716
717 if (!pid_is_valid(u->ut_pid))
718 continue;
719
720 t = strndup(u->ut_line, sizeof(u->ut_line));
721 if (!t)
722 return log_oom();
723
724 c = path_startswith(t, "/dev/");
725 if (c) {
726 r = free_and_strdup(&t, c);
727 if (r < 0)
728 return log_oom();
729 }
730
731 if (isempty(t))
732 continue;
733
734 s = hashmap_get(m->sessions_by_leader, PID_TO_PTR(u->ut_pid));
735 if (!s)
736 continue;
737
738 if (s->tty_validity == TTY_FROM_UTMP && !streq_ptr(s->tty, t)) {
739 /* This may happen on multiplexed SSH connection (i.e. 'SSH connection sharing'). In
740 * this case PAM and utmp sessions don't match. In such a case let's invalidate the TTY
741 * information and never acquire it again. */
742
743 s->tty = mfree(s->tty);
744 s->tty_validity = TTY_UTMP_INCONSISTENT;
745 log_debug("Session '%s' has inconsistent TTY information, dropping TTY information.", s->id);
746 continue;
747 }
748
749 /* Never override what we figured out once */
750 if (s->tty || s->tty_validity >= 0)
751 continue;
752
753 s->tty = TAKE_PTR(t);
754 s->tty_validity = TTY_FROM_UTMP;
755 log_debug("Acquired TTY information '%s' from utmp for session '%s'.", s->tty, s->id);
756 }
757
758 #else
759 return 0;
760 #endif
761 }
762
763 #if ENABLE_UTMP
764 static int manager_dispatch_utmp(sd_event_source *s, const struct inotify_event *event, void *userdata) {
765 Manager *m = userdata;
766
767 assert(m);
768
769 /* If there's indication the file itself might have been removed or became otherwise unavailable, then let's
770 * reestablish the watch on whatever there's now. */
771 if ((event->mask & (IN_ATTRIB|IN_DELETE_SELF|IN_MOVE_SELF|IN_Q_OVERFLOW|IN_UNMOUNT)) != 0)
772 manager_connect_utmp(m);
773
774 (void) manager_read_utmp(m);
775 return 0;
776 }
777 #endif
778
779 void manager_connect_utmp(Manager *m) {
780 #if ENABLE_UTMP
781 sd_event_source *s = NULL;
782 int r;
783
784 assert(m);
785
786 /* Watch utmp for changes via inotify. We do this to deal with tools such as ssh, which will register the PAM
787 * session early, and acquire a TTY only much later for the connection. Thus during PAM the TTY won't be known
788 * yet. ssh will register itself with utmp when it finally acquired the TTY. Hence, let's make use of this, and
789 * watch utmp for the TTY asynchronously. We use the PAM session's leader PID as key, to find the right entry.
790 *
791 * Yes, relying on utmp is pretty ugly, but it's good enough for informational purposes, as well as idle
792 * detection (which, for tty sessions, relies on the TTY used) */
793
794 r = sd_event_add_inotify(m->event, &s, _PATH_UTMPX, IN_MODIFY|IN_MOVE_SELF|IN_DELETE_SELF|IN_ATTRIB, manager_dispatch_utmp, m);
795 if (r < 0)
796 log_full_errno(r == -ENOENT ? LOG_DEBUG: LOG_WARNING, r, "Failed to create inotify watch on " _PATH_UTMPX ", ignoring: %m");
797 else {
798 r = sd_event_source_set_priority(s, SD_EVENT_PRIORITY_IDLE);
799 if (r < 0)
800 log_warning_errno(r, "Failed to adjust utmp event source priority, ignoring: %m");
801
802 (void) sd_event_source_set_description(s, "utmp");
803 }
804
805 sd_event_source_unref(m->utmp_event_source);
806 m->utmp_event_source = s;
807 #endif
808 }
809
810 void manager_reconnect_utmp(Manager *m) {
811 #if ENABLE_UTMP
812 assert(m);
813
814 if (m->utmp_event_source)
815 return;
816
817 manager_connect_utmp(m);
818 #endif
819 }
820
821 int manager_read_efi_boot_loader_entries(Manager *m) {
822 #if ENABLE_EFI
823 int r;
824
825 assert(m);
826 if (m->efi_boot_loader_entries_set)
827 return 0;
828
829 r = efi_loader_get_entries(&m->efi_boot_loader_entries);
830 if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r)) {
831 log_debug_errno(r, "Boot loader reported no entries.");
832 m->efi_boot_loader_entries_set = true;
833 return 0;
834 }
835 if (r < 0)
836 return log_error_errno(r, "Failed to determine entries reported by boot loader: %m");
837
838 m->efi_boot_loader_entries_set = true;
839 return 1;
840 #else
841 return 0;
842 #endif
843 }