switchroot: Lower config parser to otcore, add unit tests

Part of the continuation of unit testing coverage.
This commit is contained in:
Colin Walters 2023-08-25 15:54:20 -04:00
parent 4dd3cb3520
commit d36bf35c10
5 changed files with 91 additions and 33 deletions

View File

@ -366,7 +366,7 @@ tests_test_bsdiff_CFLAGS = $(TESTS_CFLAGS)
tests_test_bsdiff_LDADD = libbsdiff.la $(TESTS_LDADD)
tests_test_otcore_CFLAGS = $(AM_CFLAGS) $(OT_INTERNAL_GIO_UNIX_CFLAGS) -I$(srcdir)/src/libotutil -I$(srcdir)/src/libotcore -I$(srcdir)/libglnx
tests_test_otcore_LDADD = $(OT_INTERNAL_GIO_UNIX_LIBS) libotcore.la libglnx.la
tests_test_otcore_LDADD = $(OT_INTERNAL_GIO_UNIX_LIBS) libotcore.la libglnx.la libotutil.la
tests_test_checksum_SOURCES = \
src/libostree/ostree-core.c \

View File

@ -106,3 +106,34 @@ otcore_get_ostree_target (const char *cmdline, char **out_target, GError **error
*out_target = otcore_find_proc_cmdline_key (cmdline, "ostree");
return TRUE;
}
// Load a config file; if it doesn't exist, we return an empty configuration.
// NULL will be returned if we caught an error.
GKeyFile *
otcore_load_config (int rootfs_fd, const char *filename, GError **error)
{
// The path to the config file for this binary
static const char *const config_roots[] = { "usr/lib", "etc" };
g_autoptr (GKeyFile) ret = g_key_file_new ();
for (guint i = 0; i < G_N_ELEMENTS (config_roots); i++)
{
glnx_autofd int fd = -1;
g_autofree char *path = g_build_filename (config_roots[i], filename, NULL);
if (!ot_openat_ignore_enoent (rootfs_fd, path, &fd, error))
return NULL;
/* If the config file doesn't exist, that's OK */
if (fd == -1)
continue;
g_print ("Loading %s\n", path);
g_autofree char *buf = glnx_fd_readall_utf8 (fd, NULL, NULL, error);
if (!buf)
return NULL;
if (!g_key_file_load_from_data (ret, buf, -1, 0, error))
return NULL;
}
return g_steal_pointer (&ret);
}

View File

@ -46,6 +46,8 @@ gboolean otcore_validate_ed25519_signature (GBytes *data, GBytes *pubkey, GBytes
char *otcore_find_proc_cmdline_key (const char *cmdline, const char *key);
gboolean otcore_get_ostree_target (const char *cmdline, char **out_target, GError **error);
GKeyFile *otcore_load_config (int rootfs, const char *filename, GError **error);
// Our directory with transient state (eventually /run/ostree-booted should be a link to
// /run/ostree/booted)
#define OTCORE_RUN_OSTREE "/run/ostree"

View File

@ -76,8 +76,6 @@
#include "ot-keyfile-utils.h"
#include "otcore.h"
// The path to the config file for this binary
const char *config_roots[] = { "/usr/lib", "/etc" };
#define PREPARE_ROOT_CONFIG_PATH "ostree/prepare-root.conf"
// This key is used by default if present in the initramfs to verify
@ -106,35 +104,6 @@ const char *config_roots[] = { "/usr/lib", "/etc" };
#include "ostree-mount-util.h"
// Load our config file; if it doesn't exist, we return an empty configuration.
// NULL will be returned if we caught an error.
static GKeyFile *
load_config (GError **error)
{
g_autoptr (GKeyFile) ret = g_key_file_new ();
for (guint i = 0; i < G_N_ELEMENTS (config_roots); i++)
{
glnx_autofd int fd = -1;
g_autofree char *path = g_build_filename (config_roots[i], PREPARE_ROOT_CONFIG_PATH, NULL);
if (!ot_openat_ignore_enoent (AT_FDCWD, path, &fd, error))
return NULL;
/* If the config file doesn't exist, that's OK */
if (fd == -1)
continue;
g_print ("Loading %s\n", path);
g_autofree char *buf = glnx_fd_readall_utf8 (fd, NULL, NULL, error);
if (!buf)
return NULL;
if (!g_key_file_load_from_data (ret, buf, -1, 0, error))
return NULL;
}
return g_steal_pointer (&ret);
}
static bool
sysroot_is_configured_ro (const char *sysroot)
{
@ -350,7 +319,14 @@ main (int argc, char *argv[])
err (EXIT_FAILURE, "usage: ostree-prepare-root SYSROOT");
const char *root_arg = argv[1];
g_autoptr (GKeyFile) config = load_config (&error);
// Since several APIs want to operate in terms of file descriptors, let's
// open the initramfs now. Currently this is just used for the config parser.
glnx_autofd int initramfs_rootfs_fd = -1;
if (!glnx_opendirat (AT_FDCWD, "/", FALSE, &initramfs_rootfs_fd, &error))
errx (EXIT_FAILURE, "Failed to open /: %s", error->message);
g_autoptr (GKeyFile) config
= otcore_load_config (initramfs_rootfs_fd, PREPARE_ROOT_CONFIG_PATH, &error);
if (!config)
errx (EXIT_FAILURE, "Failed to parse config: %s", error->message);

View File

@ -81,6 +81,54 @@ test_prepare_root_cmdline (void)
free (g_steal_pointer (&target));
}
static void
test_prepare_root_config (void)
{
g_autoptr (GError) error = NULL;
g_auto (GLnxTmpDir) tmpdir = {
0,
};
g_assert (glnx_mkdtempat (AT_FDCWD, "/tmp/test-XXXXXX", 0777, &tmpdir, &error));
g_assert_no_error (error);
{
g_autoptr (GKeyFile) config = NULL;
g_auto (GStrv) keys = NULL;
config = otcore_load_config (tmpdir.fd, "ostree/someconfig.conf", &error);
g_assert (config);
keys = g_key_file_get_groups (config, NULL);
g_assert (keys && *keys == NULL);
}
g_assert (glnx_shutil_mkdir_p_at (tmpdir.fd, "usr/lib/ostree", 0755, NULL, NULL));
g_assert (glnx_file_replace_contents_at (tmpdir.fd, "usr/lib/ostree/someconfig.conf",
(guint8 *)"[foo]\nbar=baz", -1, 0, NULL, NULL));
{
g_autoptr (GKeyFile) config = NULL;
g_auto (GStrv) keys = NULL;
config = otcore_load_config (tmpdir.fd, "ostree/someconfig.conf", &error);
g_assert (config);
keys = g_key_file_get_groups (config, NULL);
g_assert (keys);
g_assert_cmpstr (*keys, ==, "foo");
}
g_assert (glnx_shutil_mkdir_p_at (tmpdir.fd, "etc/ostree", 0755, NULL, NULL));
g_assert (glnx_file_replace_contents_at (tmpdir.fd, "usr/lib/ostree/someconfig.conf",
(guint8 *)"[test]\nbar=baz", -1, 0, NULL, NULL));
{
g_autoptr (GKeyFile) config = NULL;
g_auto (GStrv) keys = NULL;
config = otcore_load_config (tmpdir.fd, "ostree/someconfig.conf", &error);
g_assert (config);
keys = g_key_file_get_groups (config, NULL);
g_assert (keys);
g_assert_cmpstr (*keys, ==, "test");
}
}
int
main (int argc, char **argv)
{
@ -88,5 +136,6 @@ main (int argc, char **argv)
otcore_ed25519_init ();
g_test_add_func ("/ed25519", test_ed25519);
g_test_add_func ("/prepare-root-cmdline", test_prepare_root_cmdline);
g_test_add_func ("/prepare-root-config", test_prepare_root_config);
return g_test_run ();
}