lib/grub2: Port some to new code style
I resisted trying to do anything invasive here like fd-relative porting as our coverage is weak. But this was all straightforward porting to decl-after-stmt style. Closes: #1153 Approved by: jlebon
This commit is contained in:
parent
43c78c9006
commit
6be4dfe66e
|
|
@ -75,18 +75,17 @@ _ostree_bootloader_grub2_query (OstreeBootloader *bootloader,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
gboolean ret = FALSE;
|
|
||||||
OstreeBootloaderGrub2 *self = OSTREE_BOOTLOADER_GRUB2 (bootloader);
|
OstreeBootloaderGrub2 *self = OSTREE_BOOTLOADER_GRUB2 (bootloader);
|
||||||
g_autoptr(GFile) efi_basedir = NULL;
|
|
||||||
|
|
||||||
|
/* Look for the BIOS path first */
|
||||||
if (g_file_query_exists (self->config_path_bios, NULL))
|
if (g_file_query_exists (self->config_path_bios, NULL))
|
||||||
{
|
{
|
||||||
|
/* If we found it, we're done */
|
||||||
*out_is_active = TRUE;
|
*out_is_active = TRUE;
|
||||||
ret = TRUE;
|
return TRUE;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
efi_basedir = g_file_resolve_relative_path (self->sysroot->path, "boot/efi/EFI");
|
g_autoptr(GFile) efi_basedir = g_file_resolve_relative_path (self->sysroot->path, "boot/efi/EFI");
|
||||||
|
|
||||||
g_clear_object (&self->config_path_efi);
|
g_clear_object (&self->config_path_efi);
|
||||||
|
|
||||||
|
|
@ -98,17 +97,16 @@ _ostree_bootloader_grub2_query (OstreeBootloader *bootloader,
|
||||||
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||||
cancellable, error);
|
cancellable, error);
|
||||||
if (!direnum)
|
if (!direnum)
|
||||||
goto out;
|
return FALSE;
|
||||||
|
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
GFileInfo *file_info;
|
GFileInfo *file_info;
|
||||||
const char *fname;
|
const char *fname;
|
||||||
g_autofree char *subdir_grub_cfg = NULL;
|
|
||||||
|
|
||||||
if (!g_file_enumerator_iterate (direnum, &file_info, NULL,
|
if (!g_file_enumerator_iterate (direnum, &file_info, NULL,
|
||||||
cancellable, error))
|
cancellable, error))
|
||||||
goto out;
|
return FALSE;
|
||||||
if (file_info == NULL)
|
if (file_info == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -119,8 +117,9 @@ _ostree_bootloader_grub2_query (OstreeBootloader *bootloader,
|
||||||
if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_DIRECTORY)
|
if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_DIRECTORY)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
subdir_grub_cfg = g_build_filename (gs_file_get_path_cached (efi_basedir), fname, "grub.cfg", NULL);
|
g_autofree char *subdir_grub_cfg =
|
||||||
|
g_build_filename (gs_file_get_path_cached (efi_basedir), fname, "grub.cfg", NULL);
|
||||||
|
|
||||||
if (g_file_test (subdir_grub_cfg, G_FILE_TEST_EXISTS))
|
if (g_file_test (subdir_grub_cfg, G_FILE_TEST_EXISTS))
|
||||||
{
|
{
|
||||||
self->config_path_efi = g_file_new_for_path (subdir_grub_cfg);
|
self->config_path_efi = g_file_new_for_path (subdir_grub_cfg);
|
||||||
|
|
@ -128,20 +127,18 @@ _ostree_bootloader_grub2_query (OstreeBootloader *bootloader,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we found the EFI path, we're done */
|
||||||
if (self->config_path_efi)
|
if (self->config_path_efi)
|
||||||
{
|
{
|
||||||
self->is_efi = TRUE;
|
self->is_efi = TRUE;
|
||||||
*out_is_active = TRUE;
|
*out_is_active = TRUE;
|
||||||
ret = TRUE;
|
return TRUE;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
*out_is_active = FALSE;
|
*out_is_active = FALSE;
|
||||||
|
|
||||||
ret = TRUE;
|
return TRUE;
|
||||||
out:
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
|
|
@ -150,6 +147,10 @@ _ostree_bootloader_grub2_get_name (OstreeBootloader *bootloader)
|
||||||
return "grub2";
|
return "grub2";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This implementation is quite complex; see this issue for
|
||||||
|
* a starting point:
|
||||||
|
* https://github.com/ostreedev/ostree/issues/717
|
||||||
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
_ostree_bootloader_grub2_generate_config (OstreeSysroot *sysroot,
|
_ostree_bootloader_grub2_generate_config (OstreeSysroot *sysroot,
|
||||||
int bootversion,
|
int bootversion,
|
||||||
|
|
@ -157,13 +158,6 @@ _ostree_bootloader_grub2_generate_config (OstreeSysroot *sysroot
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
gboolean ret = FALSE;
|
|
||||||
g_autoptr(GString) output = g_string_new ("");
|
|
||||||
g_autoptr(GOutputStream) out_stream = NULL;
|
|
||||||
g_autoptr(GPtrArray) loader_configs = NULL;
|
|
||||||
guint i;
|
|
||||||
gsize bytes_written;
|
|
||||||
gboolean is_efi;
|
|
||||||
/* So... yeah. Just going to hardcode these. */
|
/* So... yeah. Just going to hardcode these. */
|
||||||
static const char hardcoded_video[] = "load_video\n"
|
static const char hardcoded_video[] = "load_video\n"
|
||||||
"set gfxpayload=keep\n";
|
"set gfxpayload=keep\n";
|
||||||
|
|
@ -178,16 +172,18 @@ _ostree_bootloader_grub2_generate_config (OstreeSysroot *sysroot
|
||||||
g_assert (grub2_prepare_root_cache != NULL);
|
g_assert (grub2_prepare_root_cache != NULL);
|
||||||
|
|
||||||
/* Passed from the parent */
|
/* Passed from the parent */
|
||||||
is_efi = g_getenv ("_OSTREE_GRUB2_IS_EFI") != NULL;
|
gboolean is_efi = g_getenv ("_OSTREE_GRUB2_IS_EFI") != NULL;
|
||||||
|
|
||||||
out_stream = g_unix_output_stream_new (target_fd, FALSE);
|
g_autoptr(GOutputStream) out_stream = g_unix_output_stream_new (target_fd, FALSE);
|
||||||
|
|
||||||
|
g_autoptr(GPtrArray) loader_configs = NULL;
|
||||||
if (!_ostree_sysroot_read_boot_loader_configs (sysroot, bootversion,
|
if (!_ostree_sysroot_read_boot_loader_configs (sysroot, bootversion,
|
||||||
&loader_configs,
|
&loader_configs,
|
||||||
cancellable, error))
|
cancellable, error))
|
||||||
goto out;
|
return FALSE;
|
||||||
|
|
||||||
for (i = 0; i < loader_configs->len; i++)
|
g_autoptr(GString) output = g_string_new ("");
|
||||||
|
for (guint i = 0; i < loader_configs->len; i++)
|
||||||
{
|
{
|
||||||
OstreeBootconfigParser *config = loader_configs->pdata[i];
|
OstreeBootconfigParser *config = loader_configs->pdata[i];
|
||||||
const char *title;
|
const char *title;
|
||||||
|
|
@ -217,13 +213,9 @@ _ostree_bootloader_grub2_generate_config (OstreeSysroot *sysroot
|
||||||
g_string_append (output, hardcoded_insmods);
|
g_string_append (output, hardcoded_insmods);
|
||||||
g_string_append (output, grub2_prepare_root_cache);
|
g_string_append (output, grub2_prepare_root_cache);
|
||||||
g_string_append_c (output, '\n');
|
g_string_append_c (output, '\n');
|
||||||
|
|
||||||
if (!kernel)
|
if (!kernel)
|
||||||
{
|
return glnx_throw (error, "No \"linux\" key in bootloader config");
|
||||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
||||||
"No \"linux\" key in bootloader config");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
g_string_append (output, "linux");
|
g_string_append (output, "linux");
|
||||||
if (is_efi)
|
if (is_efi)
|
||||||
g_string_append (output, GRUB2_EFI_SUFFIX);
|
g_string_append (output, GRUB2_EFI_SUFFIX);
|
||||||
|
|
@ -256,13 +248,12 @@ _ostree_bootloader_grub2_generate_config (OstreeSysroot *sysroot
|
||||||
g_string_append (output, "}\n");
|
g_string_append (output, "}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gsize bytes_written;
|
||||||
if (!g_output_stream_write_all (out_stream, output->str, output->len,
|
if (!g_output_stream_write_all (out_stream, output->str, output->len,
|
||||||
&bytes_written, cancellable, error))
|
&bytes_written, cancellable, error))
|
||||||
goto out;
|
return FALSE;
|
||||||
|
|
||||||
ret = TRUE;
|
return TRUE;
|
||||||
out:
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -271,19 +262,24 @@ typedef struct {
|
||||||
gboolean is_efi;
|
gboolean is_efi;
|
||||||
} Grub2ChildSetupData;
|
} Grub2ChildSetupData;
|
||||||
|
|
||||||
|
/* Post-fork, pre-exec child setup for grub2-mkconfig */
|
||||||
static void
|
static void
|
||||||
grub2_child_setup (gpointer user_data)
|
grub2_child_setup (gpointer user_data)
|
||||||
{
|
{
|
||||||
Grub2ChildSetupData *cdata = user_data;
|
Grub2ChildSetupData *cdata = user_data;
|
||||||
|
|
||||||
setenv ("_OSTREE_GRUB2_BOOTVERSION", cdata->bootversion_str, TRUE);
|
setenv ("_OSTREE_GRUB2_BOOTVERSION", cdata->bootversion_str, TRUE);
|
||||||
/* We have to pass our state to the child */
|
/* We have to pass our state (whether or not we're using EFI) to the child */
|
||||||
if (cdata->is_efi)
|
if (cdata->is_efi)
|
||||||
setenv ("_OSTREE_GRUB2_IS_EFI", "1", TRUE);
|
setenv ("_OSTREE_GRUB2_IS_EFI", "1", TRUE);
|
||||||
|
|
||||||
|
/* Everything below this is dealing with the chroot case; if
|
||||||
|
* we're not doing that, return early.
|
||||||
|
*/
|
||||||
if (!cdata->root)
|
if (!cdata->root)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* TODO: investigate replacing this with bwrap */
|
||||||
if (chdir (cdata->root) != 0)
|
if (chdir (cdata->root) != 0)
|
||||||
{
|
{
|
||||||
perror ("chdir");
|
perror ("chdir");
|
||||||
|
|
@ -321,6 +317,7 @@ grub2_child_setup (gpointer user_data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Main entrypoint for writing GRUB configuration. */
|
||||||
static gboolean
|
static gboolean
|
||||||
_ostree_bootloader_grub2_write_config (OstreeBootloader *bootloader,
|
_ostree_bootloader_grub2_write_config (OstreeBootloader *bootloader,
|
||||||
int bootversion,
|
int bootversion,
|
||||||
|
|
@ -328,23 +325,13 @@ _ostree_bootloader_grub2_write_config (OstreeBootloader *bootloader,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
OstreeBootloaderGrub2 *self = OSTREE_BOOTLOADER_GRUB2 (bootloader);
|
OstreeBootloaderGrub2 *self = OSTREE_BOOTLOADER_GRUB2 (bootloader);
|
||||||
gboolean ret = FALSE;
|
|
||||||
g_autoptr(GFile) new_config_path = NULL;
|
|
||||||
g_autofree char *bootversion_str = g_strdup_printf ("%u", (guint)bootversion);
|
|
||||||
g_autoptr(GFile) config_path_efi_dir = NULL;
|
|
||||||
g_autofree char *grub2_mkconfig_chroot = NULL;
|
|
||||||
gboolean use_system_grub2_mkconfig = TRUE;
|
|
||||||
const gchar *grub_exec = NULL;
|
|
||||||
const char *grub_argv[4] = { NULL, "-o", NULL, NULL};
|
|
||||||
GSpawnFlags grub_spawnflags = G_SPAWN_SEARCH_PATH;
|
|
||||||
int grub2_estatus;
|
|
||||||
Grub2ChildSetupData cdata = { NULL, };
|
|
||||||
|
|
||||||
|
/* Autotests can set this envvar to select which code path to test, useful for OS installers as well */
|
||||||
|
gboolean use_system_grub2_mkconfig = TRUE;
|
||||||
#ifdef USE_BUILTIN_GRUB2_MKCONFIG
|
#ifdef USE_BUILTIN_GRUB2_MKCONFIG
|
||||||
use_system_grub2_mkconfig = FALSE;
|
use_system_grub2_mkconfig = FALSE;
|
||||||
#endif
|
#endif
|
||||||
/* Autotests can set this envvar to select which code path to test, useful for OS installers as well */
|
const gchar *grub_exec = g_getenv ("OSTREE_GRUB2_EXEC");
|
||||||
grub_exec = g_getenv ("OSTREE_GRUB2_EXEC");
|
|
||||||
if (grub_exec)
|
if (grub_exec)
|
||||||
{
|
{
|
||||||
if (g_str_has_suffix (grub_exec, GRUB2_MKCONFIG_PATH))
|
if (g_str_has_suffix (grub_exec, GRUB2_MKCONFIG_PATH))
|
||||||
|
|
@ -355,6 +342,7 @@ _ostree_bootloader_grub2_write_config (OstreeBootloader *bootloader,
|
||||||
else
|
else
|
||||||
grub_exec = use_system_grub2_mkconfig ? GRUB2_MKCONFIG_PATH : TARGET_PREFIX "/lib/ostree/ostree-grub-generator";
|
grub_exec = use_system_grub2_mkconfig ? GRUB2_MKCONFIG_PATH : TARGET_PREFIX "/lib/ostree/ostree-grub-generator";
|
||||||
|
|
||||||
|
g_autofree char *grub2_mkconfig_chroot = NULL;
|
||||||
if (use_system_grub2_mkconfig && ostree_sysroot_get_booted_deployment (self->sysroot) == NULL
|
if (use_system_grub2_mkconfig && ostree_sysroot_get_booted_deployment (self->sysroot) == NULL
|
||||||
&& g_file_has_parent (self->sysroot->path, NULL))
|
&& g_file_has_parent (self->sysroot->path, NULL))
|
||||||
{
|
{
|
||||||
|
|
@ -381,13 +369,15 @@ _ostree_bootloader_grub2_write_config (OstreeBootloader *bootloader,
|
||||||
grub2_mkconfig_chroot = g_file_get_path (tool_deployment_root);
|
grub2_mkconfig_chroot = g_file_get_path (tool_deployment_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_autoptr(GFile) new_config_path = NULL;
|
||||||
|
g_autoptr(GFile) config_path_efi_dir = NULL;
|
||||||
if (self->is_efi)
|
if (self->is_efi)
|
||||||
{
|
{
|
||||||
config_path_efi_dir = g_file_get_parent (self->config_path_efi);
|
config_path_efi_dir = g_file_get_parent (self->config_path_efi);
|
||||||
new_config_path = g_file_get_child (config_path_efi_dir, "grub.cfg.new");
|
new_config_path = g_file_get_child (config_path_efi_dir, "grub.cfg.new");
|
||||||
/* We use grub2-mkconfig to write to a temporary file first */
|
/* We use grub2-mkconfig to write to a temporary file first */
|
||||||
if (!ot_gfile_ensure_unlinked (new_config_path, cancellable, error))
|
if (!ot_gfile_ensure_unlinked (new_config_path, cancellable, error))
|
||||||
goto out;
|
return FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -395,12 +385,16 @@ _ostree_bootloader_grub2_write_config (OstreeBootloader *bootloader,
|
||||||
bootversion);
|
bootversion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *grub_argv[4] = { NULL, "-o", NULL, NULL};
|
||||||
|
Grub2ChildSetupData cdata = { NULL, };
|
||||||
grub_argv[0] = grub_exec;
|
grub_argv[0] = grub_exec;
|
||||||
grub_argv[2] = gs_file_get_path_cached (new_config_path);
|
grub_argv[2] = gs_file_get_path_cached (new_config_path);
|
||||||
|
|
||||||
|
GSpawnFlags grub_spawnflags = G_SPAWN_SEARCH_PATH;
|
||||||
if (!g_getenv ("OSTREE_DEBUG_GRUB2"))
|
if (!g_getenv ("OSTREE_DEBUG_GRUB2"))
|
||||||
grub_spawnflags |= G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL;
|
grub_spawnflags |= G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL;
|
||||||
cdata.root = grub2_mkconfig_chroot;
|
cdata.root = grub2_mkconfig_chroot;
|
||||||
|
g_autofree char *bootversion_str = g_strdup_printf ("%u", (guint)bootversion);
|
||||||
cdata.bootversion_str = bootversion_str;
|
cdata.bootversion_str = bootversion_str;
|
||||||
cdata.is_efi = self->is_efi;
|
cdata.is_efi = self->is_efi;
|
||||||
/* Note in older versions of the grub2 package, this script doesn't even try
|
/* Note in older versions of the grub2 package, this script doesn't even try
|
||||||
|
|
@ -411,54 +405,47 @@ _ostree_bootloader_grub2_write_config (OstreeBootloader *bootloader,
|
||||||
|
|
||||||
Upstream is fixed though.
|
Upstream is fixed though.
|
||||||
*/
|
*/
|
||||||
|
int grub2_estatus;
|
||||||
if (!g_spawn_sync (NULL, (char**)grub_argv, NULL, grub_spawnflags,
|
if (!g_spawn_sync (NULL, (char**)grub_argv, NULL, grub_spawnflags,
|
||||||
grub2_child_setup, &cdata, NULL, NULL,
|
grub2_child_setup, &cdata, NULL, NULL,
|
||||||
&grub2_estatus, error))
|
&grub2_estatus, error))
|
||||||
goto out;
|
return FALSE;
|
||||||
if (!g_spawn_check_exit_status (grub2_estatus, error))
|
if (!g_spawn_check_exit_status (grub2_estatus, error))
|
||||||
{
|
{
|
||||||
g_prefix_error (error, "%s: ", grub_argv[0]);
|
g_prefix_error (error, "%s: ", grub_argv[0]);
|
||||||
goto out;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now let's fdatasync() for the new file */
|
/* Now let's fdatasync() for the new file */
|
||||||
{ glnx_fd_close int new_config_fd = -1;
|
{ glnx_fd_close int new_config_fd = -1;
|
||||||
if (!glnx_openat_rdonly (AT_FDCWD, gs_file_get_path_cached (new_config_path), TRUE, &new_config_fd, error))
|
if (!glnx_openat_rdonly (AT_FDCWD, gs_file_get_path_cached (new_config_path), TRUE, &new_config_fd, error))
|
||||||
goto out;
|
return FALSE;
|
||||||
|
|
||||||
if (fdatasync (new_config_fd) < 0)
|
if (fdatasync (new_config_fd) < 0)
|
||||||
{
|
return glnx_throw_errno_prefix (error, "fdatasync");
|
||||||
(void)glnx_throw_errno_prefix (error, "fdatasync");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->is_efi)
|
if (self->is_efi)
|
||||||
{
|
{
|
||||||
g_autoptr(GFile) config_path_efi_old = g_file_get_child (config_path_efi_dir, "grub.cfg.old");
|
g_autoptr(GFile) config_path_efi_old = g_file_get_child (config_path_efi_dir, "grub.cfg.old");
|
||||||
|
|
||||||
/* copy current to old */
|
/* copy current to old */
|
||||||
if (!ot_gfile_ensure_unlinked (config_path_efi_old, cancellable, error))
|
if (!ot_gfile_ensure_unlinked (config_path_efi_old, cancellable, error))
|
||||||
goto out;
|
return FALSE;
|
||||||
if (!g_file_copy (self->config_path_efi, config_path_efi_old,
|
if (!g_file_copy (self->config_path_efi, config_path_efi_old,
|
||||||
G_FILE_COPY_OVERWRITE, cancellable, NULL, NULL, error))
|
G_FILE_COPY_OVERWRITE, cancellable, NULL, NULL, error))
|
||||||
goto out;
|
return FALSE;
|
||||||
|
|
||||||
/* NOTE: NON-ATOMIC REPLACEMENT; WE can't do anything else on FAT;
|
/* NOTE: NON-ATOMIC REPLACEMENT; WE can't do anything else on FAT;
|
||||||
* see https://bugzilla.gnome.org/show_bug.cgi?id=724246
|
* see https://bugzilla.gnome.org/show_bug.cgi?id=724246
|
||||||
*/
|
*/
|
||||||
if (!ot_gfile_ensure_unlinked (self->config_path_efi, cancellable, error))
|
if (!ot_gfile_ensure_unlinked (self->config_path_efi, cancellable, error))
|
||||||
goto out;
|
return FALSE;
|
||||||
if (rename (gs_file_get_path_cached (new_config_path), gs_file_get_path_cached (self->config_path_efi)) < 0)
|
if (rename (gs_file_get_path_cached (new_config_path), gs_file_get_path_cached (self->config_path_efi)) < 0)
|
||||||
{
|
return glnx_throw_errno_prefix (error, "rename");
|
||||||
glnx_set_error_from_errno (error);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = TRUE;
|
return TRUE;
|
||||||
out:
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue