2018-06-14 12:50:49 +02:00
/* SPDX-License-Identifier: LGPL-2.1+ */
2017-10-17 18:23:16 +02:00
# include <stdio.h>
2017-10-20 18:31:34 +02:00
# include <linux/magic.h>
2017-10-17 18:23:16 +02:00
2018-01-11 00:39:12 +01:00
# include "sd-id128.h"
2017-10-17 18:23:16 +02:00
# include "alloc-util.h"
2017-10-20 18:31:34 +02:00
# include "blkid-util.h"
2017-10-17 18:23:16 +02:00
# include "bootspec.h"
# include "conf-files.h"
# include "def.h"
2017-10-31 11:30:40 +01:00
# include "device-nodes.h"
2017-10-17 18:23:16 +02:00
# include "efivars.h"
# include "fd-util.h"
# include "fileio.h"
2017-10-20 18:31:34 +02:00
# include "parse-util.h"
# include "stat-util.h"
2017-10-17 18:23:16 +02:00
# include "string-util.h"
# include "strv.h"
2017-10-20 18:31:34 +02:00
# include "virt.h"
2017-10-17 18:23:16 +02:00
2018-06-22 19:30:12 +02:00
static void boot_entry_free ( BootEntry * entry ) {
2017-12-11 22:22:04 +01:00
assert ( entry ) ;
2017-10-17 18:23:16 +02:00
2018-06-22 12:18:43 +02:00
free ( entry - > id ) ;
2018-09-26 08:35:12 +02:00
free ( entry - > path ) ;
2017-10-17 18:23:16 +02:00
free ( entry - > title ) ;
2017-10-20 17:58:13 +02:00
free ( entry - > show_title ) ;
2017-10-17 18:23:16 +02:00
free ( entry - > version ) ;
free ( entry - > machine_id ) ;
free ( entry - > architecture ) ;
strv_free ( entry - > options ) ;
free ( entry - > kernel ) ;
free ( entry - > efi ) ;
strv_free ( entry - > initrd ) ;
free ( entry - > device_tree ) ;
}
2018-06-22 19:30:12 +02:00
static int boot_entry_load ( const char * path , BootEntry * entry ) {
2017-12-26 09:35:35 +09:00
_cleanup_ ( boot_entry_free ) BootEntry tmp = { } ;
2017-10-17 18:23:16 +02:00
_cleanup_fclose_ FILE * f = NULL ;
unsigned line = 1 ;
2017-12-26 09:35:35 +09:00
char * b , * c ;
2017-10-17 18:23:16 +02:00
int r ;
2017-12-11 22:22:04 +01:00
assert ( path ) ;
assert ( entry ) ;
2017-12-26 09:35:35 +09:00
c = endswith_no_case ( path , " .conf " ) ;
if ( ! c ) {
log_error ( " Invalid loader entry filename: %s " , path ) ;
return - EINVAL ;
}
2017-10-17 18:23:16 +02:00
2017-12-26 09:35:35 +09:00
b = basename ( path ) ;
2018-06-22 12:18:43 +02:00
tmp . id = strndup ( b , c - b ) ;
if ( ! tmp . id )
2017-10-17 18:23:16 +02:00
return log_oom ( ) ;
2018-09-26 08:35:12 +02:00
tmp . path = strdup ( path ) ;
if ( ! tmp . path )
return log_oom ( ) ;
2017-12-26 09:35:35 +09:00
f = fopen ( path , " re " ) ;
if ( ! f )
return log_error_errno ( errno , " Failed to open \" %s \" : %m " , path ) ;
2017-10-17 18:23:16 +02:00
for ( ; ; ) {
2018-02-19 22:26:01 +09:00
_cleanup_free_ char * buf = NULL , * field = NULL ;
const char * p ;
2017-10-17 18:23:16 +02:00
r = read_line ( f , LONG_LINE_MAX , & buf ) ;
if ( r = = 0 )
break ;
if ( r = = - ENOBUFS )
return log_error_errno ( r , " %s:%u: Line too long " , path , line ) ;
if ( r < 0 )
return log_error_errno ( r , " %s:%u: Error while reading: %m " , path , line ) ;
line + + ;
if ( IN_SET ( * strstrip ( buf ) , ' # ' , ' \0 ' ) )
continue ;
2018-02-19 22:26:01 +09:00
p = buf ;
r = extract_first_word ( & p , & field , " \t " , 0 ) ;
if ( r < 0 ) {
log_error_errno ( r , " Failed to parse config file %s line %u: %m " , path , line ) ;
continue ;
}
if ( r = = 0 ) {
2017-10-17 18:23:16 +02:00
log_warning ( " %s:%u: Bad syntax " , path , line ) ;
continue ;
}
2018-02-19 22:26:01 +09:00
if ( streq ( field , " title " ) )
2017-10-17 18:23:16 +02:00
r = free_and_strdup ( & tmp . title , p ) ;
2018-02-19 22:26:01 +09:00
else if ( streq ( field , " version " ) )
2017-10-17 18:23:16 +02:00
r = free_and_strdup ( & tmp . version , p ) ;
2018-02-19 22:26:01 +09:00
else if ( streq ( field , " machine-id " ) )
2017-10-17 18:23:16 +02:00
r = free_and_strdup ( & tmp . machine_id , p ) ;
2018-02-19 22:26:01 +09:00
else if ( streq ( field , " architecture " ) )
2017-10-17 18:23:16 +02:00
r = free_and_strdup ( & tmp . architecture , p ) ;
2018-02-19 22:26:01 +09:00
else if ( streq ( field , " options " ) )
2017-10-17 18:23:16 +02:00
r = strv_extend ( & tmp . options , p ) ;
2018-02-19 22:26:01 +09:00
else if ( streq ( field , " linux " ) )
2017-10-17 18:23:16 +02:00
r = free_and_strdup ( & tmp . kernel , p ) ;
2018-02-19 22:26:01 +09:00
else if ( streq ( field , " efi " ) )
2017-10-17 18:23:16 +02:00
r = free_and_strdup ( & tmp . efi , p ) ;
2018-02-19 22:26:01 +09:00
else if ( streq ( field , " initrd " ) )
2017-10-17 18:23:16 +02:00
r = strv_extend ( & tmp . initrd , p ) ;
2018-02-19 22:26:01 +09:00
else if ( streq ( field , " devicetree " ) )
2017-10-17 18:23:16 +02:00
r = free_and_strdup ( & tmp . device_tree , p ) ;
else {
2018-02-19 22:26:01 +09:00
log_notice ( " %s:%u: Unknown line \" %s \" " , path , line , field ) ;
2017-10-17 18:23:16 +02:00
continue ;
}
if ( r < 0 )
return log_error_errno ( r , " %s:%u: Error while reading: %m " , path , line ) ;
}
* entry = tmp ;
tmp = ( BootEntry ) { } ;
return 0 ;
}
void boot_config_free ( BootConfig * config ) {
tree-wide: be more careful with the type of array sizes
Previously we were a bit sloppy with the index and size types of arrays,
we'd regularly use unsigned. While I don't think this ever resulted in
real issues I think we should be more careful there and follow a
stricter regime: unless there's a strong reason not to use size_t for
array sizes and indexes, size_t it should be. Any allocations we do
ultimately will use size_t anyway, and converting forth and back between
unsigned and size_t will always be a source of problems.
Note that on 32bit machines "unsigned" and "size_t" are equivalent, and
on 64bit machines our arrays shouldn't grow that large anyway, and if
they do we have a problem, however that kind of overly large allocation
we have protections for usually, but for overflows we do not have that
so much, hence let's add it.
So yeah, it's a story of the current code being already "good enough",
but I think some extra type hygiene is better.
This patch tries to be comprehensive, but it probably isn't and I missed
a few cases. But I guess we can cover that later as we notice it. Among
smaller fixes, this changes:
1. strv_length()' return type becomes size_t
2. the unit file changes array size becomes size_t
3. DNS answer and query array sizes become size_t
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=76745
2018-04-27 14:09:31 +02:00
size_t i ;
2017-10-17 18:23:16 +02:00
2017-12-11 22:22:04 +01:00
assert ( config ) ;
2017-10-17 18:23:16 +02:00
free ( config - > default_pattern ) ;
free ( config - > timeout ) ;
free ( config - > editor ) ;
2018-01-28 17:06:22 +01:00
free ( config - > auto_entries ) ;
free ( config - > auto_firmware ) ;
2017-10-17 18:23:16 +02:00
free ( config - > entry_oneshot ) ;
free ( config - > entry_default ) ;
for ( i = 0 ; i < config - > n_entries ; i + + )
boot_entry_free ( config - > entries + i ) ;
free ( config - > entries ) ;
}
2018-06-22 19:30:12 +02:00
static int boot_loader_read_conf ( const char * path , BootConfig * config ) {
2017-10-17 18:23:16 +02:00
_cleanup_fclose_ FILE * f = NULL ;
unsigned line = 1 ;
int r ;
2017-12-11 22:22:04 +01:00
assert ( path ) ;
assert ( config ) ;
2017-10-17 18:23:16 +02:00
f = fopen ( path , " re " ) ;
2018-06-22 19:31:50 +02:00
if ( ! f ) {
if ( errno = = ENOENT )
return 0 ;
2017-10-17 18:23:16 +02:00
return log_error_errno ( errno , " Failed to open \" %s \" : %m " , path ) ;
2018-06-22 19:31:50 +02:00
}
2017-10-17 18:23:16 +02:00
for ( ; ; ) {
2018-02-19 22:26:01 +09:00
_cleanup_free_ char * buf = NULL , * field = NULL ;
const char * p ;
2017-10-17 18:23:16 +02:00
r = read_line ( f , LONG_LINE_MAX , & buf ) ;
if ( r = = 0 )
break ;
if ( r = = - ENOBUFS )
return log_error_errno ( r , " %s:%u: Line too long " , path , line ) ;
if ( r < 0 )
return log_error_errno ( r , " %s:%u: Error while reading: %m " , path , line ) ;
line + + ;
if ( IN_SET ( * strstrip ( buf ) , ' # ' , ' \0 ' ) )
continue ;
2018-02-19 22:26:01 +09:00
p = buf ;
r = extract_first_word ( & p , & field , " \t " , 0 ) ;
if ( r < 0 ) {
log_error_errno ( r , " Failed to parse config file %s line %u: %m " , path , line ) ;
continue ;
}
if ( r = = 0 ) {
2017-10-17 18:23:16 +02:00
log_warning ( " %s:%u: Bad syntax " , path , line ) ;
continue ;
}
2018-02-19 22:26:01 +09:00
if ( streq ( field , " default " ) )
2017-10-17 18:23:16 +02:00
r = free_and_strdup ( & config - > default_pattern , p ) ;
2018-02-19 22:26:01 +09:00
else if ( streq ( field , " timeout " ) )
2017-10-17 18:23:16 +02:00
r = free_and_strdup ( & config - > timeout , p ) ;
2018-02-19 22:26:01 +09:00
else if ( streq ( field , " editor " ) )
2017-10-17 18:23:16 +02:00
r = free_and_strdup ( & config - > editor , p ) ;
2018-03-08 10:06:00 +01:00
else if ( streq ( field , " auto-entries " ) )
2018-01-28 17:06:22 +01:00
r = free_and_strdup ( & config - > auto_entries , p ) ;
2018-03-08 10:06:00 +01:00
else if ( streq ( field , " auto-firmware " ) )
2018-01-28 17:06:22 +01:00
r = free_and_strdup ( & config - > auto_firmware , p ) ;
2018-03-08 10:06:00 +01:00
else if ( streq ( field , " console-mode " ) )
2017-12-16 22:52:05 -02:00
r = free_and_strdup ( & config - > console_mode , p ) ;
2017-10-17 18:23:16 +02:00
else {
2018-02-19 22:26:01 +09:00
log_notice ( " %s:%u: Unknown line \" %s \" " , path , line , field ) ;
2017-10-17 18:23:16 +02:00
continue ;
}
if ( r < 0 )
return log_error_errno ( r , " %s:%u: Error while reading: %m " , path , line ) ;
}
2018-06-22 19:31:50 +02:00
return 1 ;
2017-10-17 18:23:16 +02:00
}
2018-09-18 08:39:24 +09:00
static int boot_entry_compare ( const BootEntry * a , const BootEntry * b ) {
2018-06-22 12:18:43 +02:00
return str_verscmp ( a - > id , b - > id ) ;
2017-10-17 18:23:16 +02:00
}
2018-06-22 19:30:12 +02:00
static int boot_entries_find ( const char * dir , BootEntry * * ret_entries , size_t * ret_n_entries ) {
2017-10-17 18:23:16 +02:00
_cleanup_strv_free_ char * * files = NULL ;
char * * f ;
int r ;
BootEntry * array = NULL ;
size_t n_allocated = 0 , n = 0 ;
2017-12-11 22:22:04 +01:00
assert ( dir ) ;
assert ( ret_entries ) ;
assert ( ret_n_entries ) ;
2017-10-17 18:23:16 +02:00
r = conf_files_list ( & files , " .conf " , NULL , 0 , dir , NULL ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to list files in \" %s \" : %m " , dir ) ;
STRV_FOREACH ( f , files ) {
if ( ! GREEDY_REALLOC0 ( array , n_allocated , n + 1 ) )
return log_oom ( ) ;
r = boot_entry_load ( * f , array + n ) ;
if ( r < 0 )
continue ;
n + + ;
}
2018-09-18 08:39:24 +09:00
typesafe_qsort ( array , n , boot_entry_compare ) ;
2017-10-17 18:23:16 +02:00
2017-12-11 22:22:04 +01:00
* ret_entries = array ;
* ret_n_entries = n ;
2017-10-17 18:23:16 +02:00
return 0 ;
}
2017-10-20 17:58:13 +02:00
static bool find_nonunique ( BootEntry * entries , size_t n_entries , bool * arr ) {
tree-wide: be more careful with the type of array sizes
Previously we were a bit sloppy with the index and size types of arrays,
we'd regularly use unsigned. While I don't think this ever resulted in
real issues I think we should be more careful there and follow a
stricter regime: unless there's a strong reason not to use size_t for
array sizes and indexes, size_t it should be. Any allocations we do
ultimately will use size_t anyway, and converting forth and back between
unsigned and size_t will always be a source of problems.
Note that on 32bit machines "unsigned" and "size_t" are equivalent, and
on 64bit machines our arrays shouldn't grow that large anyway, and if
they do we have a problem, however that kind of overly large allocation
we have protections for usually, but for overflows we do not have that
so much, hence let's add it.
So yeah, it's a story of the current code being already "good enough",
but I think some extra type hygiene is better.
This patch tries to be comprehensive, but it probably isn't and I missed
a few cases. But I guess we can cover that later as we notice it. Among
smaller fixes, this changes:
1. strv_length()' return type becomes size_t
2. the unit file changes array size becomes size_t
3. DNS answer and query array sizes become size_t
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=76745
2018-04-27 14:09:31 +02:00
size_t i , j ;
2017-10-20 17:58:13 +02:00
bool non_unique = false ;
2017-12-11 22:22:04 +01:00
assert ( entries | | n_entries = = 0 ) ;
assert ( arr | | n_entries = = 0 ) ;
2017-10-20 17:58:13 +02:00
for ( i = 0 ; i < n_entries ; i + + )
arr [ i ] = false ;
for ( i = 0 ; i < n_entries ; i + + )
for ( j = 0 ; j < n_entries ; j + + )
if ( i ! = j & & streq ( boot_entry_title ( entries + i ) ,
boot_entry_title ( entries + j ) ) )
non_unique = arr [ i ] = arr [ j ] = true ;
return non_unique ;
}
static int boot_entries_uniquify ( BootEntry * entries , size_t n_entries ) {
char * s ;
tree-wide: be more careful with the type of array sizes
Previously we were a bit sloppy with the index and size types of arrays,
we'd regularly use unsigned. While I don't think this ever resulted in
real issues I think we should be more careful there and follow a
stricter regime: unless there's a strong reason not to use size_t for
array sizes and indexes, size_t it should be. Any allocations we do
ultimately will use size_t anyway, and converting forth and back between
unsigned and size_t will always be a source of problems.
Note that on 32bit machines "unsigned" and "size_t" are equivalent, and
on 64bit machines our arrays shouldn't grow that large anyway, and if
they do we have a problem, however that kind of overly large allocation
we have protections for usually, but for overflows we do not have that
so much, hence let's add it.
So yeah, it's a story of the current code being already "good enough",
but I think some extra type hygiene is better.
This patch tries to be comprehensive, but it probably isn't and I missed
a few cases. But I guess we can cover that later as we notice it. Among
smaller fixes, this changes:
1. strv_length()' return type becomes size_t
2. the unit file changes array size becomes size_t
3. DNS answer and query array sizes become size_t
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=76745
2018-04-27 14:09:31 +02:00
size_t i ;
2017-10-20 17:58:13 +02:00
int r ;
bool arr [ n_entries ] ;
2017-12-11 22:22:04 +01:00
assert ( entries | | n_entries = = 0 ) ;
2017-10-20 17:58:13 +02:00
/* Find _all_ non-unique titles */
if ( ! find_nonunique ( entries , n_entries , arr ) )
return 0 ;
/* Add version to non-unique titles */
for ( i = 0 ; i < n_entries ; i + + )
if ( arr [ i ] & & entries [ i ] . version ) {
r = asprintf ( & s , " %s (%s) " , boot_entry_title ( entries + i ) , entries [ i ] . version ) ;
if ( r < 0 )
return - ENOMEM ;
free_and_replace ( entries [ i ] . show_title , s ) ;
}
if ( ! find_nonunique ( entries , n_entries , arr ) )
return 0 ;
/* Add machine-id to non-unique titles */
for ( i = 0 ; i < n_entries ; i + + )
if ( arr [ i ] & & entries [ i ] . machine_id ) {
r = asprintf ( & s , " %s (%s) " , boot_entry_title ( entries + i ) , entries [ i ] . machine_id ) ;
if ( r < 0 )
return - ENOMEM ;
free_and_replace ( entries [ i ] . show_title , s ) ;
}
if ( ! find_nonunique ( entries , n_entries , arr ) )
return 0 ;
/* Add file name to non-unique titles */
for ( i = 0 ; i < n_entries ; i + + )
if ( arr [ i ] ) {
2018-06-22 12:18:43 +02:00
r = asprintf ( & s , " %s (%s) " , boot_entry_title ( entries + i ) , entries [ i ] . id ) ;
2017-10-20 17:58:13 +02:00
if ( r < 0 )
return - ENOMEM ;
free_and_replace ( entries [ i ] . show_title , s ) ;
}
return 0 ;
}
2017-12-07 14:23:11 +09:00
static int boot_entries_select_default ( const BootConfig * config ) {
2017-10-17 18:23:16 +02:00
int i ;
2017-12-11 22:22:04 +01:00
assert ( config ) ;
2017-10-17 18:23:16 +02:00
if ( config - > entry_oneshot )
for ( i = config - > n_entries - 1 ; i > = 0 ; i - - )
2018-06-22 12:18:43 +02:00
if ( streq ( config - > entry_oneshot , config - > entries [ i ] . id ) ) {
log_debug ( " Found default: id \" %s \" is matched by LoaderEntryOneShot " ,
config - > entries [ i ] . id ) ;
2017-10-17 18:23:16 +02:00
return i ;
}
if ( config - > entry_default )
for ( i = config - > n_entries - 1 ; i > = 0 ; i - - )
2018-06-22 12:18:43 +02:00
if ( streq ( config - > entry_default , config - > entries [ i ] . id ) ) {
log_debug ( " Found default: id \" %s \" is matched by LoaderEntryDefault " ,
config - > entries [ i ] . id ) ;
2017-10-17 18:23:16 +02:00
return i ;
}
if ( config - > default_pattern )
for ( i = config - > n_entries - 1 ; i > = 0 ; i - - )
2018-06-22 12:18:43 +02:00
if ( fnmatch ( config - > default_pattern , config - > entries [ i ] . id , FNM_CASEFOLD ) = = 0 ) {
log_debug ( " Found default: id \" %s \" is matched by pattern \" %s \" " ,
config - > entries [ i ] . id , config - > default_pattern ) ;
2017-10-17 18:23:16 +02:00
return i ;
}
if ( config - > n_entries > 0 )
2018-06-22 12:18:43 +02:00
log_debug ( " Found default: last entry \" %s \" " , config - > entries [ config - > n_entries - 1 ] . id ) ;
2017-10-17 18:23:16 +02:00
else
log_debug ( " Found no default boot entry :( " ) ;
2017-12-11 22:22:04 +01:00
2017-10-17 18:23:16 +02:00
return config - > n_entries - 1 ; /* -1 means "no default" */
}
int boot_entries_load_config ( const char * esp_path , BootConfig * config ) {
const char * p ;
int r ;
2017-12-11 22:22:04 +01:00
assert ( esp_path ) ;
assert ( config ) ;
2017-10-17 18:23:16 +02:00
p = strjoina ( esp_path , " /loader/loader.conf " ) ;
r = boot_loader_read_conf ( p , config ) ;
if ( r < 0 )
2018-06-22 19:26:22 +02:00
return r ;
2017-10-17 18:23:16 +02:00
p = strjoina ( esp_path , " /loader/entries " ) ;
r = boot_entries_find ( p , & config - > entries , & config - > n_entries ) ;
if ( r < 0 )
2018-06-22 19:26:22 +02:00
return r ;
2017-10-17 18:23:16 +02:00
2017-10-20 17:58:13 +02:00
r = boot_entries_uniquify ( config - > entries , config - > n_entries ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to uniquify boot entries: %m " ) ;
2017-10-17 18:23:16 +02:00
r = efi_get_variable_string ( EFI_VENDOR_LOADER , " LoaderEntryOneShot " , & config - > entry_oneshot ) ;
if ( r < 0 & & r ! = - ENOENT )
return log_error_errno ( r , " Failed to read EFI var \" LoaderEntryOneShot \" : %m " ) ;
r = efi_get_variable_string ( EFI_VENDOR_LOADER , " LoaderEntryDefault " , & config - > entry_default ) ;
if ( r < 0 & & r ! = - ENOENT )
return log_error_errno ( r , " Failed to read EFI var \" LoaderEntryDefault \" : %m " ) ;
config - > default_entry = boot_entries_select_default ( config ) ;
return 0 ;
}
2017-10-20 18:31:34 +02:00
/********************************************************************************/
static int verify_esp (
const char * p ,
efi: rework find_esp() error propagation/logging a bit
This renames find_esp() to find_esp_and_warn() and tries to normalize its
behaviour:
1. Change the error that is returned when we can't find the ESP to
ENOKEY (from ENOENT). This way the error code can only mean one
thing: that our search loop didn't find a good candidate.
2. Really log about all errors, except for ENOKEY and EACCES, and
document the letter cases.
3. Normalize parameters to the call: separate out the path parameter in
two: an input path and an output path. That way the memory management
is clear: we will access the input parameter only for reading, and
only write out the output parameter, using malloc() memory.
Before the calling convention were quire surprising for internal API
code, as the path parameter had to be malloc() memory and might and
might not have changed.
4. Rename bootctl's find_esp_warn() to acquire_esp(), and make it a
simple wrapper around find_esp_warn(), that basically just adds the
friendly logging for the ENOKEY case. This rework removes double
logging in a number of error cases, as we no longer log here in
anything but ENOKEY, and leave that entirely to find_esp_warn().
5. find_esp_and_warn() now takes a bool flag parameter
"unprivileged_mode", which disables logging in the EACCES case, and
skips privileged validation of the path. This makes the function less
magic, and doesn't hide this internal silencing automatism from the
caller anymore.
With all that in place "bootctl list" and "bootctl status" work properly
(or as good as they can) when I invoke the tools whithout privileges on
my system where /boot is not world-readable
2017-12-11 22:04:46 +01:00
bool searching ,
bool unprivileged_mode ,
2017-10-20 18:31:34 +02:00
uint32_t * ret_part ,
uint64_t * ret_pstart ,
uint64_t * ret_psize ,
sd_id128_t * ret_uuid ) {
2017-12-05 14:03:11 +09:00
# if HAVE_BLKID
tree-wide: drop redundant _cleanup_ macros (#8810)
This drops a good number of type-specific _cleanup_ macros, and patches
all users to just use the generic ones.
In most recent code we abstained from defining type-specific macros, and
this basically removes all those added already, with the exception of
the really low-level ones.
Having explicit macros for this is not too useful, as the expression
without the extra macro is generally just 2ch wider. We should generally
emphesize generic code, unless there are really good reasons for
specific code, hence let's follow this in this case too.
Note that _cleanup_free_ and similar really low-level, libc'ish, Linux
API'ish macros continue to be defined, only the really high-level OO
ones are dropped. From now on this should really be the rule: for really
low-level stuff, such as memory allocation, fd handling and so one, go
ahead and define explicit per-type macros, but for high-level, specific
program code, just use the generic _cleanup_() macro directly, in order
to keep things simple and as readable as possible for the uninitiated.
Note that before this patch some of the APIs (notable libudev ones) were
already used with the high-level macros at some places and with the
generic _cleanup_ macro at others. With this patch we hence unify on the
latter.
2018-04-25 12:31:45 +02:00
_cleanup_ ( blkid_free_probep ) blkid_probe b = NULL ;
2017-10-31 11:30:40 +01:00
char t [ DEV_NUM_PATH_MAX ] ;
2017-12-05 14:03:11 +09:00
const char * v ;
# endif
2017-10-20 18:31:34 +02:00
uint64_t pstart = 0 , psize = 0 ;
struct stat st , st2 ;
2017-12-05 14:03:11 +09:00
const char * t2 ;
2017-10-20 18:31:34 +02:00
struct statfs sfs ;
sd_id128_t uuid = SD_ID128_NULL ;
uint32_t part = 0 ;
int r ;
assert ( p ) ;
efi: rework find_esp() error propagation/logging a bit
This renames find_esp() to find_esp_and_warn() and tries to normalize its
behaviour:
1. Change the error that is returned when we can't find the ESP to
ENOKEY (from ENOENT). This way the error code can only mean one
thing: that our search loop didn't find a good candidate.
2. Really log about all errors, except for ENOKEY and EACCES, and
document the letter cases.
3. Normalize parameters to the call: separate out the path parameter in
two: an input path and an output path. That way the memory management
is clear: we will access the input parameter only for reading, and
only write out the output parameter, using malloc() memory.
Before the calling convention were quire surprising for internal API
code, as the path parameter had to be malloc() memory and might and
might not have changed.
4. Rename bootctl's find_esp_warn() to acquire_esp(), and make it a
simple wrapper around find_esp_warn(), that basically just adds the
friendly logging for the ENOKEY case. This rework removes double
logging in a number of error cases, as we no longer log here in
anything but ENOKEY, and leave that entirely to find_esp_warn().
5. find_esp_and_warn() now takes a bool flag parameter
"unprivileged_mode", which disables logging in the EACCES case, and
skips privileged validation of the path. This makes the function less
magic, and doesn't hide this internal silencing automatism from the
caller anymore.
With all that in place "bootctl list" and "bootctl status" work properly
(or as good as they can) when I invoke the tools whithout privileges on
my system where /boot is not world-readable
2017-12-11 22:04:46 +01:00
/* Non-root user can only check the status, so if an error occured in the following, it does not cause any
* issues . Let ' s also , silence the error messages . */
2017-10-20 18:31:34 +02:00
if ( statfs ( p , & sfs ) < 0 ) {
/* If we are searching for the mount point, don't generate a log message if we can't find the path */
if ( errno = = ENOENT & & searching )
return - ENOENT ;
efi: rework find_esp() error propagation/logging a bit
This renames find_esp() to find_esp_and_warn() and tries to normalize its
behaviour:
1. Change the error that is returned when we can't find the ESP to
ENOKEY (from ENOENT). This way the error code can only mean one
thing: that our search loop didn't find a good candidate.
2. Really log about all errors, except for ENOKEY and EACCES, and
document the letter cases.
3. Normalize parameters to the call: separate out the path parameter in
two: an input path and an output path. That way the memory management
is clear: we will access the input parameter only for reading, and
only write out the output parameter, using malloc() memory.
Before the calling convention were quire surprising for internal API
code, as the path parameter had to be malloc() memory and might and
might not have changed.
4. Rename bootctl's find_esp_warn() to acquire_esp(), and make it a
simple wrapper around find_esp_warn(), that basically just adds the
friendly logging for the ENOKEY case. This rework removes double
logging in a number of error cases, as we no longer log here in
anything but ENOKEY, and leave that entirely to find_esp_warn().
5. find_esp_and_warn() now takes a bool flag parameter
"unprivileged_mode", which disables logging in the EACCES case, and
skips privileged validation of the path. This makes the function less
magic, and doesn't hide this internal silencing automatism from the
caller anymore.
With all that in place "bootctl list" and "bootctl status" work properly
(or as good as they can) when I invoke the tools whithout privileges on
my system where /boot is not world-readable
2017-12-11 22:04:46 +01:00
return log_full_errno ( unprivileged_mode & & errno = = EACCES ? LOG_DEBUG : LOG_ERR , errno ,
2017-10-20 18:31:34 +02:00
" Failed to check file system type of \" %s \" : %m " , p ) ;
}
if ( ! F_TYPE_EQUAL ( sfs . f_type , MSDOS_SUPER_MAGIC ) ) {
if ( searching )
return - EADDRNOTAVAIL ;
log_error ( " File system \" %s \" is not a FAT EFI System Partition (ESP) file system. " , p ) ;
return - ENODEV ;
}
if ( stat ( p , & st ) < 0 )
efi: rework find_esp() error propagation/logging a bit
This renames find_esp() to find_esp_and_warn() and tries to normalize its
behaviour:
1. Change the error that is returned when we can't find the ESP to
ENOKEY (from ENOENT). This way the error code can only mean one
thing: that our search loop didn't find a good candidate.
2. Really log about all errors, except for ENOKEY and EACCES, and
document the letter cases.
3. Normalize parameters to the call: separate out the path parameter in
two: an input path and an output path. That way the memory management
is clear: we will access the input parameter only for reading, and
only write out the output parameter, using malloc() memory.
Before the calling convention were quire surprising for internal API
code, as the path parameter had to be malloc() memory and might and
might not have changed.
4. Rename bootctl's find_esp_warn() to acquire_esp(), and make it a
simple wrapper around find_esp_warn(), that basically just adds the
friendly logging for the ENOKEY case. This rework removes double
logging in a number of error cases, as we no longer log here in
anything but ENOKEY, and leave that entirely to find_esp_warn().
5. find_esp_and_warn() now takes a bool flag parameter
"unprivileged_mode", which disables logging in the EACCES case, and
skips privileged validation of the path. This makes the function less
magic, and doesn't hide this internal silencing automatism from the
caller anymore.
With all that in place "bootctl list" and "bootctl status" work properly
(or as good as they can) when I invoke the tools whithout privileges on
my system where /boot is not world-readable
2017-12-11 22:04:46 +01:00
return log_full_errno ( unprivileged_mode & & errno = = EACCES ? LOG_DEBUG : LOG_ERR , errno ,
2017-10-20 18:31:34 +02:00
" Failed to determine block device node of \" %s \" : %m " , p ) ;
if ( major ( st . st_dev ) = = 0 ) {
log_error ( " Block device node of %p is invalid. " , p ) ;
return - ENODEV ;
}
t2 = strjoina ( p , " /.. " ) ;
r = stat ( t2 , & st2 ) ;
if ( r < 0 )
efi: rework find_esp() error propagation/logging a bit
This renames find_esp() to find_esp_and_warn() and tries to normalize its
behaviour:
1. Change the error that is returned when we can't find the ESP to
ENOKEY (from ENOENT). This way the error code can only mean one
thing: that our search loop didn't find a good candidate.
2. Really log about all errors, except for ENOKEY and EACCES, and
document the letter cases.
3. Normalize parameters to the call: separate out the path parameter in
two: an input path and an output path. That way the memory management
is clear: we will access the input parameter only for reading, and
only write out the output parameter, using malloc() memory.
Before the calling convention were quire surprising for internal API
code, as the path parameter had to be malloc() memory and might and
might not have changed.
4. Rename bootctl's find_esp_warn() to acquire_esp(), and make it a
simple wrapper around find_esp_warn(), that basically just adds the
friendly logging for the ENOKEY case. This rework removes double
logging in a number of error cases, as we no longer log here in
anything but ENOKEY, and leave that entirely to find_esp_warn().
5. find_esp_and_warn() now takes a bool flag parameter
"unprivileged_mode", which disables logging in the EACCES case, and
skips privileged validation of the path. This makes the function less
magic, and doesn't hide this internal silencing automatism from the
caller anymore.
With all that in place "bootctl list" and "bootctl status" work properly
(or as good as they can) when I invoke the tools whithout privileges on
my system where /boot is not world-readable
2017-12-11 22:04:46 +01:00
return log_full_errno ( unprivileged_mode & & errno = = EACCES ? LOG_DEBUG : LOG_ERR , errno ,
2017-10-20 18:31:34 +02:00
" Failed to determine block device node of parent of \" %s \" : %m " , p ) ;
if ( st . st_dev = = st2 . st_dev ) {
log_error ( " Directory \" %s \" is not the root of the EFI System Partition (ESP) file system. " , p ) ;
return - ENODEV ;
}
/* In a container we don't have access to block devices, skip this part of the verification, we trust the
* container manager set everything up correctly on its own . Also skip the following verification for non - root user . */
efi: rework find_esp() error propagation/logging a bit
This renames find_esp() to find_esp_and_warn() and tries to normalize its
behaviour:
1. Change the error that is returned when we can't find the ESP to
ENOKEY (from ENOENT). This way the error code can only mean one
thing: that our search loop didn't find a good candidate.
2. Really log about all errors, except for ENOKEY and EACCES, and
document the letter cases.
3. Normalize parameters to the call: separate out the path parameter in
two: an input path and an output path. That way the memory management
is clear: we will access the input parameter only for reading, and
only write out the output parameter, using malloc() memory.
Before the calling convention were quire surprising for internal API
code, as the path parameter had to be malloc() memory and might and
might not have changed.
4. Rename bootctl's find_esp_warn() to acquire_esp(), and make it a
simple wrapper around find_esp_warn(), that basically just adds the
friendly logging for the ENOKEY case. This rework removes double
logging in a number of error cases, as we no longer log here in
anything but ENOKEY, and leave that entirely to find_esp_warn().
5. find_esp_and_warn() now takes a bool flag parameter
"unprivileged_mode", which disables logging in the EACCES case, and
skips privileged validation of the path. This makes the function less
magic, and doesn't hide this internal silencing automatism from the
caller anymore.
With all that in place "bootctl list" and "bootctl status" work properly
(or as good as they can) when I invoke the tools whithout privileges on
my system where /boot is not world-readable
2017-12-11 22:04:46 +01:00
if ( detect_container ( ) > 0 | | unprivileged_mode )
2017-10-20 18:31:34 +02:00
goto finish ;
2017-12-05 14:03:11 +09:00
# if HAVE_BLKID
2017-10-31 11:30:40 +01:00
xsprintf_dev_num_path ( t , " block " , st . st_dev ) ;
2017-10-20 18:31:34 +02:00
errno = 0 ;
b = blkid_new_probe_from_filename ( t ) ;
if ( ! b )
return log_error_errno ( errno ? : ENOMEM , " Failed to open file system \" %s \" : %m " , p ) ;
blkid_probe_enable_superblocks ( b , 1 ) ;
blkid_probe_set_superblocks_flags ( b , BLKID_SUBLKS_TYPE ) ;
blkid_probe_enable_partitions ( b , 1 ) ;
blkid_probe_set_partitions_flags ( b , BLKID_PARTS_ENTRY_DETAILS ) ;
errno = 0 ;
r = blkid_do_safeprobe ( b ) ;
if ( r = = - 2 ) {
log_error ( " File system \" %s \" is ambiguous. " , p ) ;
return - ENODEV ;
} else if ( r = = 1 ) {
log_error ( " File system \" %s \" does not contain a label. " , p ) ;
return - ENODEV ;
} else if ( r ! = 0 )
return log_error_errno ( errno ? : EIO , " Failed to probe file system \" %s \" : %m " , p ) ;
errno = 0 ;
r = blkid_probe_lookup_value ( b , " TYPE " , & v , NULL ) ;
if ( r ! = 0 )
return log_error_errno ( errno ? : EIO , " Failed to probe file system type \" %s \" : %m " , p ) ;
if ( ! streq ( v , " vfat " ) ) {
log_error ( " File system \" %s \" is not FAT. " , p ) ;
return - ENODEV ;
}
errno = 0 ;
r = blkid_probe_lookup_value ( b , " PART_ENTRY_SCHEME " , & v , NULL ) ;
if ( r ! = 0 )
return log_error_errno ( errno ? : EIO , " Failed to probe partition scheme \" %s \" : %m " , p ) ;
if ( ! streq ( v , " gpt " ) ) {
log_error ( " File system \" %s \" is not on a GPT partition table. " , p ) ;
return - ENODEV ;
}
errno = 0 ;
r = blkid_probe_lookup_value ( b , " PART_ENTRY_TYPE " , & v , NULL ) ;
if ( r ! = 0 )
return log_error_errno ( errno ? : EIO , " Failed to probe partition type UUID \" %s \" : %m " , p ) ;
if ( ! streq ( v , " c12a7328-f81f-11d2-ba4b-00a0c93ec93b " ) ) {
log_error ( " File system \" %s \" has wrong type for an EFI System Partition (ESP). " , p ) ;
return - ENODEV ;
}
errno = 0 ;
r = blkid_probe_lookup_value ( b , " PART_ENTRY_UUID " , & v , NULL ) ;
if ( r ! = 0 )
return log_error_errno ( errno ? : EIO , " Failed to probe partition entry UUID \" %s \" : %m " , p ) ;
r = sd_id128_from_string ( v , & uuid ) ;
if ( r < 0 ) {
log_error ( " Partition \" %s \" has invalid UUID \" %s \" . " , p , v ) ;
return - EIO ;
}
errno = 0 ;
r = blkid_probe_lookup_value ( b , " PART_ENTRY_NUMBER " , & v , NULL ) ;
if ( r ! = 0 )
return log_error_errno ( errno ? : EIO , " Failed to probe partition number \" %s \" : m " , p ) ;
r = safe_atou32 ( v , & part ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to parse PART_ENTRY_NUMBER field. " ) ;
errno = 0 ;
r = blkid_probe_lookup_value ( b , " PART_ENTRY_OFFSET " , & v , NULL ) ;
if ( r ! = 0 )
return log_error_errno ( errno ? : EIO , " Failed to probe partition offset \" %s \" : %m " , p ) ;
r = safe_atou64 ( v , & pstart ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to parse PART_ENTRY_OFFSET field. " ) ;
errno = 0 ;
r = blkid_probe_lookup_value ( b , " PART_ENTRY_SIZE " , & v , NULL ) ;
if ( r ! = 0 )
return log_error_errno ( errno ? : EIO , " Failed to probe partition size \" %s \" : %m " , p ) ;
r = safe_atou64 ( v , & psize ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to parse PART_ENTRY_SIZE field. " ) ;
2017-12-05 14:03:11 +09:00
# endif
2017-10-20 18:31:34 +02:00
finish :
if ( ret_part )
* ret_part = part ;
if ( ret_pstart )
* ret_pstart = pstart ;
if ( ret_psize )
* ret_psize = psize ;
if ( ret_uuid )
* ret_uuid = uuid ;
return 0 ;
}
efi: rework find_esp() error propagation/logging a bit
This renames find_esp() to find_esp_and_warn() and tries to normalize its
behaviour:
1. Change the error that is returned when we can't find the ESP to
ENOKEY (from ENOENT). This way the error code can only mean one
thing: that our search loop didn't find a good candidate.
2. Really log about all errors, except for ENOKEY and EACCES, and
document the letter cases.
3. Normalize parameters to the call: separate out the path parameter in
two: an input path and an output path. That way the memory management
is clear: we will access the input parameter only for reading, and
only write out the output parameter, using malloc() memory.
Before the calling convention were quire surprising for internal API
code, as the path parameter had to be malloc() memory and might and
might not have changed.
4. Rename bootctl's find_esp_warn() to acquire_esp(), and make it a
simple wrapper around find_esp_warn(), that basically just adds the
friendly logging for the ENOKEY case. This rework removes double
logging in a number of error cases, as we no longer log here in
anything but ENOKEY, and leave that entirely to find_esp_warn().
5. find_esp_and_warn() now takes a bool flag parameter
"unprivileged_mode", which disables logging in the EACCES case, and
skips privileged validation of the path. This makes the function less
magic, and doesn't hide this internal silencing automatism from the
caller anymore.
With all that in place "bootctl list" and "bootctl status" work properly
(or as good as they can) when I invoke the tools whithout privileges on
my system where /boot is not world-readable
2017-12-11 22:04:46 +01:00
int find_esp_and_warn (
const char * path ,
bool unprivileged_mode ,
char * * ret_path ,
uint32_t * ret_part ,
uint64_t * ret_pstart ,
uint64_t * ret_psize ,
sd_id128_t * ret_uuid ) {
2017-10-20 18:31:34 +02:00
int r ;
efi: rework find_esp() error propagation/logging a bit
This renames find_esp() to find_esp_and_warn() and tries to normalize its
behaviour:
1. Change the error that is returned when we can't find the ESP to
ENOKEY (from ENOENT). This way the error code can only mean one
thing: that our search loop didn't find a good candidate.
2. Really log about all errors, except for ENOKEY and EACCES, and
document the letter cases.
3. Normalize parameters to the call: separate out the path parameter in
two: an input path and an output path. That way the memory management
is clear: we will access the input parameter only for reading, and
only write out the output parameter, using malloc() memory.
Before the calling convention were quire surprising for internal API
code, as the path parameter had to be malloc() memory and might and
might not have changed.
4. Rename bootctl's find_esp_warn() to acquire_esp(), and make it a
simple wrapper around find_esp_warn(), that basically just adds the
friendly logging for the ENOKEY case. This rework removes double
logging in a number of error cases, as we no longer log here in
anything but ENOKEY, and leave that entirely to find_esp_warn().
5. find_esp_and_warn() now takes a bool flag parameter
"unprivileged_mode", which disables logging in the EACCES case, and
skips privileged validation of the path. This makes the function less
magic, and doesn't hide this internal silencing automatism from the
caller anymore.
With all that in place "bootctl list" and "bootctl status" work properly
(or as good as they can) when I invoke the tools whithout privileges on
my system where /boot is not world-readable
2017-12-11 22:04:46 +01:00
/* This logs about all errors except:
*
* - ENOKEY → when we can ' t find the partition
* - EACCESS → when unprivileged_mode is true , and we can ' t access something
*/
2017-10-20 18:31:34 +02:00
efi: rework find_esp() error propagation/logging a bit
This renames find_esp() to find_esp_and_warn() and tries to normalize its
behaviour:
1. Change the error that is returned when we can't find the ESP to
ENOKEY (from ENOENT). This way the error code can only mean one
thing: that our search loop didn't find a good candidate.
2. Really log about all errors, except for ENOKEY and EACCES, and
document the letter cases.
3. Normalize parameters to the call: separate out the path parameter in
two: an input path and an output path. That way the memory management
is clear: we will access the input parameter only for reading, and
only write out the output parameter, using malloc() memory.
Before the calling convention were quire surprising for internal API
code, as the path parameter had to be malloc() memory and might and
might not have changed.
4. Rename bootctl's find_esp_warn() to acquire_esp(), and make it a
simple wrapper around find_esp_warn(), that basically just adds the
friendly logging for the ENOKEY case. This rework removes double
logging in a number of error cases, as we no longer log here in
anything but ENOKEY, and leave that entirely to find_esp_warn().
5. find_esp_and_warn() now takes a bool flag parameter
"unprivileged_mode", which disables logging in the EACCES case, and
skips privileged validation of the path. This makes the function less
magic, and doesn't hide this internal silencing automatism from the
caller anymore.
With all that in place "bootctl list" and "bootctl status" work properly
(or as good as they can) when I invoke the tools whithout privileges on
my system where /boot is not world-readable
2017-12-11 22:04:46 +01:00
if ( path ) {
r = verify_esp ( path , false , unprivileged_mode , ret_part , ret_pstart , ret_psize , ret_uuid ) ;
2017-10-20 18:31:34 +02:00
if ( r < 0 )
return r ;
efi: rework find_esp() error propagation/logging a bit
This renames find_esp() to find_esp_and_warn() and tries to normalize its
behaviour:
1. Change the error that is returned when we can't find the ESP to
ENOKEY (from ENOENT). This way the error code can only mean one
thing: that our search loop didn't find a good candidate.
2. Really log about all errors, except for ENOKEY and EACCES, and
document the letter cases.
3. Normalize parameters to the call: separate out the path parameter in
two: an input path and an output path. That way the memory management
is clear: we will access the input parameter only for reading, and
only write out the output parameter, using malloc() memory.
Before the calling convention were quire surprising for internal API
code, as the path parameter had to be malloc() memory and might and
might not have changed.
4. Rename bootctl's find_esp_warn() to acquire_esp(), and make it a
simple wrapper around find_esp_warn(), that basically just adds the
friendly logging for the ENOKEY case. This rework removes double
logging in a number of error cases, as we no longer log here in
anything but ENOKEY, and leave that entirely to find_esp_warn().
5. find_esp_and_warn() now takes a bool flag parameter
"unprivileged_mode", which disables logging in the EACCES case, and
skips privileged validation of the path. This makes the function less
magic, and doesn't hide this internal silencing automatism from the
caller anymore.
With all that in place "bootctl list" and "bootctl status" work properly
(or as good as they can) when I invoke the tools whithout privileges on
my system where /boot is not world-readable
2017-12-11 22:04:46 +01:00
goto found ;
}
FOREACH_STRING ( path , " /efi " , " /boot " , " /boot/efi " ) {
r = verify_esp ( path , true , unprivileged_mode , ret_part , ret_pstart , ret_psize , ret_uuid ) ;
if ( r > = 0 )
goto found ;
if ( ! IN_SET ( r , - ENOENT , - EADDRNOTAVAIL ) ) /* This one is not it */
return r ;
}
/* No logging here */
return - ENOKEY ;
found :
if ( ret_path ) {
char * c ;
c = strdup ( path ) ;
if ( ! c )
2017-10-20 18:31:34 +02:00
return log_oom ( ) ;
efi: rework find_esp() error propagation/logging a bit
This renames find_esp() to find_esp_and_warn() and tries to normalize its
behaviour:
1. Change the error that is returned when we can't find the ESP to
ENOKEY (from ENOENT). This way the error code can only mean one
thing: that our search loop didn't find a good candidate.
2. Really log about all errors, except for ENOKEY and EACCES, and
document the letter cases.
3. Normalize parameters to the call: separate out the path parameter in
two: an input path and an output path. That way the memory management
is clear: we will access the input parameter only for reading, and
only write out the output parameter, using malloc() memory.
Before the calling convention were quire surprising for internal API
code, as the path parameter had to be malloc() memory and might and
might not have changed.
4. Rename bootctl's find_esp_warn() to acquire_esp(), and make it a
simple wrapper around find_esp_warn(), that basically just adds the
friendly logging for the ENOKEY case. This rework removes double
logging in a number of error cases, as we no longer log here in
anything but ENOKEY, and leave that entirely to find_esp_warn().
5. find_esp_and_warn() now takes a bool flag parameter
"unprivileged_mode", which disables logging in the EACCES case, and
skips privileged validation of the path. This makes the function less
magic, and doesn't hide this internal silencing automatism from the
caller anymore.
With all that in place "bootctl list" and "bootctl status" work properly
(or as good as they can) when I invoke the tools whithout privileges on
my system where /boot is not world-readable
2017-12-11 22:04:46 +01:00
* ret_path = c ;
2017-10-20 18:31:34 +02:00
}
efi: rework find_esp() error propagation/logging a bit
This renames find_esp() to find_esp_and_warn() and tries to normalize its
behaviour:
1. Change the error that is returned when we can't find the ESP to
ENOKEY (from ENOENT). This way the error code can only mean one
thing: that our search loop didn't find a good candidate.
2. Really log about all errors, except for ENOKEY and EACCES, and
document the letter cases.
3. Normalize parameters to the call: separate out the path parameter in
two: an input path and an output path. That way the memory management
is clear: we will access the input parameter only for reading, and
only write out the output parameter, using malloc() memory.
Before the calling convention were quire surprising for internal API
code, as the path parameter had to be malloc() memory and might and
might not have changed.
4. Rename bootctl's find_esp_warn() to acquire_esp(), and make it a
simple wrapper around find_esp_warn(), that basically just adds the
friendly logging for the ENOKEY case. This rework removes double
logging in a number of error cases, as we no longer log here in
anything but ENOKEY, and leave that entirely to find_esp_warn().
5. find_esp_and_warn() now takes a bool flag parameter
"unprivileged_mode", which disables logging in the EACCES case, and
skips privileged validation of the path. This makes the function less
magic, and doesn't hide this internal silencing automatism from the
caller anymore.
With all that in place "bootctl list" and "bootctl status" work properly
(or as good as they can) when I invoke the tools whithout privileges on
my system where /boot is not world-readable
2017-12-11 22:04:46 +01:00
return 0 ;
2017-10-20 18:31:34 +02:00
}
2018-09-26 07:45:56 +02:00
int find_default_boot_entry (
const char * esp_path ,
char * * esp_where ,
BootConfig * config ,
const BootEntry * * e ) {
_cleanup_free_ char * where = NULL ;
int r ;
assert ( config ) ;
assert ( e ) ;
r = find_esp_and_warn ( esp_path , false , & where , NULL , NULL , NULL , NULL ) ;
if ( r < 0 )
return r ;
r = boot_entries_load_config ( where , config ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to load bootspec config from \" %s/loader \" : %m " , where ) ;
if ( config - > default_entry < 0 ) {
log_error ( " No entry suitable as default, refusing to guess. " ) ;
return - ENOENT ;
}
* e = & config - > entries [ config - > default_entry ] ;
2018-09-26 08:35:12 +02:00
log_debug ( " Found default boot entry in file \" %s \" " , ( * e ) - > path ) ;
2018-09-26 07:45:56 +02:00
if ( esp_where )
* esp_where = TAKE_PTR ( where ) ;
return 0 ;
}