Improve error handling in upgrade.conf(5) parsing.

This commit is contained in:
Jonas 'Sortie' Termansen 2021-01-17 22:54:35 +01:00
parent 84b008e455
commit ba8800df2c
5 changed files with 77 additions and 50 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2016 Jonas 'Sortie' Termansen.
* Copyright (c) 2015, 2016, 2017, 2021 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -28,54 +28,67 @@
#include "conf.h"
static bool conf_boolean(const char* name, const char* value, const char* path)
void conf_init(struct conf* conf)
{
memset(conf, 0, sizeof(*conf));
conf->ports = true;
conf->system = true;
}
void conf_free(struct conf* conf)
{
conf_init(conf);
}
static bool conf_boolean(const char* name,
const char* value,
const char* path,
off_t line_number)
{
if ( !strcmp(value, "yes") )
return true;
if ( !strcmp(value, "no") )
return false;
printf("%s: %s: Expected yes or no instead of unsupported value\n",
path, name);
printf("%s:%ji: %s: Expected yes or no instead of unsupported value\n",
path, (intmax_t) line_number, name);
return false;
}
static void conf_assign(struct conf* conf,
static bool conf_assign(struct conf* conf,
const char* name,
const char* value,
const char* path)
const char* path,
off_t line_number)
{
if ( !strcmp(name, "grub") )
conf->grub = conf_boolean(name, value, path);
conf->grub = conf_boolean(name, value, path, line_number);
else if ( !strcmp(name, "newsrc") )
conf->newsrc = conf_boolean(name, value, path);
conf->newsrc = conf_boolean(name, value, path, line_number);
else if ( !strcmp(name, "ports") )
conf->ports = conf_boolean(name, value, path);
conf->ports = conf_boolean(name, value, path, line_number);
else if ( !strcmp(name, "src") )
conf->src = conf_boolean(name, value, path);
conf->src = conf_boolean(name, value, path, line_number);
else if ( !strcmp(name, "system") )
conf->system = conf_boolean(name, value, path);
conf->system = conf_boolean(name, value, path, line_number);
else
printf("%s: %s: Unsupported variable\n", path, name);
printf("%s:%ji: Unsupported variable: %s\n", path,
(intmax_t) line_number, name);
return true;
}
void load_upgrade_conf(struct conf* conf, const char* path)
bool conf_load(struct conf* conf, const char* path)
{
memset(conf, 0, sizeof(*conf));
conf->ports = true;
conf->system = true;
FILE* fp = fopen(path, "r");
if ( !fp )
{
if ( errno == ENOENT )
return;
err(2, "%s", path);
}
return false;
char* line = NULL;
size_t line_size = 0;
ssize_t line_length;
intmax_t line_number = 0;
bool success = true;
while ( 0 < (line_length = getline(&line, &line_size, fp)) )
{
line_number++;
if ( line[line_length - 1] == '\n' )
line[--line_length] = '\0';
line_length = 0;
@ -87,8 +100,13 @@ void load_upgrade_conf(struct conf* conf, const char* path)
char* name = line;
while ( *name && isblank((unsigned char) *name) )
name++;
if ( !*name || *name == '=' )
if ( !*name )
continue;
if ( *name == '=' )
{
printf("%s:%ji: Ignoring malformed line\n", path, line_number);
continue;
}
size_t name_length = 1;
while ( name[name_length] &&
!isblank((unsigned char) name[name_length]) &&
@ -98,15 +116,23 @@ void load_upgrade_conf(struct conf* conf, const char* path)
while ( *value && isblank((unsigned char) *value) )
value++;
if ( *value != '=' )
{
printf("%s:%ji: Ignoring malformed line\n", path, line_number);
continue;
}
value++;
while ( *value && isblank((unsigned char) *value) )
value++;
name[name_length] = '\0';
conf_assign(conf, name, value, path);
if ( !conf_assign(conf, name, value, path, line_number) )
{
success = false;
break;
}
}
if ( ferror(fp) )
err(2, "%s", path);
success = false;
free(line);
fclose(fp);
return success;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2016 Jonas 'Sortie' Termansen.
* Copyright (c) 2015, 2016, 2017 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -29,6 +29,8 @@ struct conf
bool system;
};
void load_upgrade_conf(struct conf* conf, const char* path);
void conf_init(struct conf* conf);
void conf_free(struct conf* conf);
bool conf_load(struct conf* conf, const char* path);
#endif

View File

@ -142,27 +142,16 @@ static bool should_install_bootloader_path(const char* mnt,
warn("malloc");
return false;
}
// TODO: The load_upgrade_conf function might exit the process on failure,
// but we don't want that. Redesign the mountpoint code so the caller
// controls this.
pid_t pid = fork();
if ( pid < 0 )
{
warn("fork");
free(conf_path);
return false;
}
if ( !pid )
{
struct conf conf;
load_upgrade_conf(&conf, conf_path);
bool should = conf.grub;
_exit(should ? 0 : 1);
}
int status;
if ( waitpid(pid, &status, 0) < 0 )
return false;
return WIFEXITED(status) && WEXITSTATUS(status) == 0;
struct conf conf;
conf_init(&conf);
bool result = false;
if ( conf_load(&conf, conf_path) )
result = conf.grub;
else if ( errno != ENOENT )
warn("%s: /etc/upgrade.conf", path_of_blockdevice(bdev));
conf_free(&conf);
free(conf_path);
return result;
}
static bool should_install_bootloader_bdev(struct blockdevice* bdev)
@ -412,6 +401,11 @@ int main(void)
struct utsname uts;
uname(&uts);
struct conf conf;
conf_init(&conf);
if ( !conf_load(&conf, "/etc/upgrade.conf") && errno != ENOENT )
warn("/etc/upgrade.conf");
static char input[256];
textf("Hello and welcome to the " BRAND_DISTRIBUTION_NAME " " VERSIONSTR ""

View File

@ -241,7 +241,9 @@ int main(int argc, char* argv[])
// TODO: Check for version (skipping, downgrading).
struct conf conf;
load_upgrade_conf(&conf, "/etc/upgrade.conf");
conf_init(&conf);
if ( !conf_load(&conf, "/etc/upgrade.conf") && errno == ENOENT )
err(2, "/etc/upgrade.conf");
bool can_run_new_abi =
abi_compatible(new_release.abi_major, new_release.abi_minor,

View File

@ -721,9 +721,12 @@ int main(void)
bool do_upgrade_bootloader;
struct conf conf;
conf_init(&conf);
while ( true )
{
load_upgrade_conf(&conf, "etc/upgrade.conf");
conf_free(&conf);
if ( !conf_load(&conf, "etc/upgrade.conf") && errno != ENOENT )
err(2, "etc/upgrade.conf");
do_upgrade_bootloader =
conf.grub && (conf.ports || (conf.system && can_run_old_abi));