Improve error handling in upgrade.conf(5) parsing.
This commit is contained in:
parent
84b008e455
commit
ba8800df2c
|
@ -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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -28,54 +28,67 @@
|
||||||
|
|
||||||
#include "conf.h"
|
#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") )
|
if ( !strcmp(value, "yes") )
|
||||||
return true;
|
return true;
|
||||||
if ( !strcmp(value, "no") )
|
if ( !strcmp(value, "no") )
|
||||||
return false;
|
return false;
|
||||||
printf("%s: %s: Expected yes or no instead of unsupported value\n",
|
printf("%s:%ji: %s: Expected yes or no instead of unsupported value\n",
|
||||||
path, name);
|
path, (intmax_t) line_number, name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void conf_assign(struct conf* conf,
|
static bool conf_assign(struct conf* conf,
|
||||||
const char* name,
|
const char* name,
|
||||||
const char* value,
|
const char* value,
|
||||||
const char* path)
|
const char* path,
|
||||||
|
off_t line_number)
|
||||||
{
|
{
|
||||||
if ( !strcmp(name, "grub") )
|
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") )
|
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") )
|
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") )
|
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") )
|
else if ( !strcmp(name, "system") )
|
||||||
conf->system = conf_boolean(name, value, path);
|
conf->system = conf_boolean(name, value, path, line_number);
|
||||||
else
|
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");
|
FILE* fp = fopen(path, "r");
|
||||||
if ( !fp )
|
if ( !fp )
|
||||||
{
|
return false;
|
||||||
if ( errno == ENOENT )
|
|
||||||
return;
|
|
||||||
err(2, "%s", path);
|
|
||||||
}
|
|
||||||
char* line = NULL;
|
char* line = NULL;
|
||||||
size_t line_size = 0;
|
size_t line_size = 0;
|
||||||
ssize_t line_length;
|
ssize_t line_length;
|
||||||
|
intmax_t line_number = 0;
|
||||||
|
bool success = true;
|
||||||
while ( 0 < (line_length = getline(&line, &line_size, fp)) )
|
while ( 0 < (line_length = getline(&line, &line_size, fp)) )
|
||||||
{
|
{
|
||||||
|
line_number++;
|
||||||
if ( line[line_length - 1] == '\n' )
|
if ( line[line_length - 1] == '\n' )
|
||||||
line[--line_length] = '\0';
|
line[--line_length] = '\0';
|
||||||
line_length = 0;
|
line_length = 0;
|
||||||
|
@ -87,8 +100,13 @@ void load_upgrade_conf(struct conf* conf, const char* path)
|
||||||
char* name = line;
|
char* name = line;
|
||||||
while ( *name && isblank((unsigned char) *name) )
|
while ( *name && isblank((unsigned char) *name) )
|
||||||
name++;
|
name++;
|
||||||
if ( !*name || *name == '=' )
|
if ( !*name )
|
||||||
continue;
|
continue;
|
||||||
|
if ( *name == '=' )
|
||||||
|
{
|
||||||
|
printf("%s:%ji: Ignoring malformed line\n", path, line_number);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
size_t name_length = 1;
|
size_t name_length = 1;
|
||||||
while ( name[name_length] &&
|
while ( name[name_length] &&
|
||||||
!isblank((unsigned char) 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) )
|
while ( *value && isblank((unsigned char) *value) )
|
||||||
value++;
|
value++;
|
||||||
if ( *value != '=' )
|
if ( *value != '=' )
|
||||||
|
{
|
||||||
|
printf("%s:%ji: Ignoring malformed line\n", path, line_number);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
value++;
|
value++;
|
||||||
while ( *value && isblank((unsigned char) *value) )
|
while ( *value && isblank((unsigned char) *value) )
|
||||||
value++;
|
value++;
|
||||||
name[name_length] = '\0';
|
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) )
|
if ( ferror(fp) )
|
||||||
err(2, "%s", path);
|
success = false;
|
||||||
free(line);
|
free(line);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -29,6 +29,8 @@ struct conf
|
||||||
bool system;
|
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
|
#endif
|
||||||
|
|
|
@ -142,27 +142,16 @@ static bool should_install_bootloader_path(const char* mnt,
|
||||||
warn("malloc");
|
warn("malloc");
|
||||||
return false;
|
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;
|
struct conf conf;
|
||||||
load_upgrade_conf(&conf, conf_path);
|
conf_init(&conf);
|
||||||
bool should = conf.grub;
|
bool result = false;
|
||||||
_exit(should ? 0 : 1);
|
if ( conf_load(&conf, conf_path) )
|
||||||
}
|
result = conf.grub;
|
||||||
int status;
|
else if ( errno != ENOENT )
|
||||||
if ( waitpid(pid, &status, 0) < 0 )
|
warn("%s: /etc/upgrade.conf", path_of_blockdevice(bdev));
|
||||||
return false;
|
conf_free(&conf);
|
||||||
return WIFEXITED(status) && WEXITSTATUS(status) == 0;
|
free(conf_path);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool should_install_bootloader_bdev(struct blockdevice* bdev)
|
static bool should_install_bootloader_bdev(struct blockdevice* bdev)
|
||||||
|
@ -412,6 +401,11 @@ int main(void)
|
||||||
struct utsname uts;
|
struct utsname uts;
|
||||||
uname(&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];
|
static char input[256];
|
||||||
|
|
||||||
textf("Hello and welcome to the " BRAND_DISTRIBUTION_NAME " " VERSIONSTR ""
|
textf("Hello and welcome to the " BRAND_DISTRIBUTION_NAME " " VERSIONSTR ""
|
||||||
|
|
|
@ -241,7 +241,9 @@ int main(int argc, char* argv[])
|
||||||
// TODO: Check for version (skipping, downgrading).
|
// TODO: Check for version (skipping, downgrading).
|
||||||
|
|
||||||
struct conf conf;
|
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 =
|
bool can_run_new_abi =
|
||||||
abi_compatible(new_release.abi_major, new_release.abi_minor,
|
abi_compatible(new_release.abi_major, new_release.abi_minor,
|
||||||
|
|
|
@ -721,9 +721,12 @@ int main(void)
|
||||||
|
|
||||||
bool do_upgrade_bootloader;
|
bool do_upgrade_bootloader;
|
||||||
struct conf conf;
|
struct conf conf;
|
||||||
|
conf_init(&conf);
|
||||||
while ( true )
|
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 =
|
do_upgrade_bootloader =
|
||||||
conf.grub && (conf.ports || (conf.system && can_run_old_abi));
|
conf.grub && (conf.ports || (conf.system && can_run_old_abi));
|
||||||
|
|
Loading…
Reference in New Issue