diff --git a/src/libotutil/ot-keyfile-utils.c b/src/libotutil/ot-keyfile-utils.c index d6cd102ca0..12f4ac0b6d 100644 --- a/src/libotutil/ot-keyfile-utils.c +++ b/src/libotutil/ot-keyfile-utils.c @@ -60,6 +60,51 @@ ot_keyfile_get_boolean_with_default (GKeyFile *keyfile, const char *section, con return TRUE; } +// Keep this in sync with +// https://gitlab.gnome.org/GNOME/glib/-/blob/4a73fbda8be6f80f14b05983eb575c1eb1329c2c/glib/gkeyfile.c?page=5#L4585 +// Except for some reason at some point we added "yes" or "no" as possible values too... +gboolean +_ostree_parse_boolean (const char *s, gboolean *out_val, GError **error) +{ + g_assert (s); + g_assert (out_val); + + if (g_str_equal (s, "yes") || g_str_equal (s, "true") || g_str_equal (s, "1")) + { + *out_val = TRUE; + return TRUE; + } + else if (g_str_equal (s, "no") || g_str_equal (s, "false") || g_str_equal (s, "0")) + { + *out_val = FALSE; + return TRUE; + } + return glnx_throw (error, "Invalid boolean: %s", s); +} + +gboolean +_ostree_parse_tristate (const char *s, OtTristate *out_tri, GError **error) +{ + if (strcmp (s, "maybe") == 0) + { + *out_tri = OT_TRISTATE_MAYBE; + return TRUE; + } + + gboolean bool_value = FALSE; + // Discard the error here, just check if it's valid + if (_ostree_parse_boolean (s, &bool_value, NULL)) + { + if (bool_value) + *out_tri = OT_TRISTATE_YES; + else + *out_tri = OT_TRISTATE_NO; + return TRUE; + } + // If it's invalid, be clear a tristate was expected. + return glnx_throw (error, "Invalid tri-state value: %s", s); +} + gboolean ot_keyfile_get_tristate_with_default (GKeyFile *keyfile, const char *section, const char *value, OtTristate default_value, OtTristate *out_tri, GError **error) @@ -85,23 +130,7 @@ ot_keyfile_get_tristate_with_default (GKeyFile *keyfile, const char *section, co } ret_value = g_strstrip (ret_value); - - if (strcmp (ret_value, "yes") == 0 || strcmp (ret_value, "true") == 0 - || strcmp (ret_value, "1") == 0) - *out_tri = OT_TRISTATE_YES; - else if (strcmp (ret_value, "no") == 0 || strcmp (ret_value, "false") == 0 - || strcmp (ret_value, "0") == 0) - *out_tri = OT_TRISTATE_NO; - else if (strcmp (ret_value, "maybe") == 0) - *out_tri = OT_TRISTATE_MAYBE; - else - { - g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE, - "Invalid tri-state value: %s", ret_value); - return FALSE; - } - - return TRUE; + return _ostree_parse_tristate (ret_value, out_tri, error); } gboolean diff --git a/src/libotutil/ot-keyfile-utils.h b/src/libotutil/ot-keyfile-utils.h index eb97c8d7c6..1ed6747328 100644 --- a/src/libotutil/ot-keyfile-utils.h +++ b/src/libotutil/ot-keyfile-utils.h @@ -32,6 +32,9 @@ typedef enum G_BEGIN_DECLS +gboolean _ostree_parse_boolean (const char *s, gboolean *out_val, GError **error); +gboolean _ostree_parse_tristate (const char *s, OtTristate *out_tri, GError **error); + gboolean ot_keyfile_get_boolean_with_default (GKeyFile *keyfile, const char *section, const char *value, gboolean default_value, gboolean *out_bool, GError **error); diff --git a/tests/test-keyfile-utils.c b/tests/test-keyfile-utils.c index 198e71d256..748e029af0 100644 --- a/tests/test-keyfile-utils.c +++ b/tests/test-keyfile-utils.c @@ -173,6 +173,42 @@ fill_keyfile (GKeyFile *file) g_key_file_set_value (file, "section", "value_bar", "bar"); } +static void +test_parse_tristate (void) +{ + g_autoptr (GError) error = NULL; + + OtTristate t = OT_TRISTATE_NO; + // Verify maybe + (void)_ostree_parse_tristate ("maybe", &t, &error); + g_assert_no_error (error); + g_assert_cmpint (t, ==, OT_TRISTATE_MAYBE); + + // Alternate yes and no + (void)_ostree_parse_tristate ("yes", &t, &error); + g_assert_no_error (error); + g_assert_cmpint (t, ==, OT_TRISTATE_YES); + (void)_ostree_parse_tristate ("no", &t, &error); + g_assert_no_error (error); + g_assert_cmpint (t, ==, OT_TRISTATE_NO); + (void)_ostree_parse_tristate ("1", &t, &error); + g_assert_no_error (error); + g_assert_cmpint (t, ==, OT_TRISTATE_YES); + (void)_ostree_parse_tristate ("0", &t, &error); + g_assert_no_error (error); + g_assert_cmpint (t, ==, OT_TRISTATE_NO); + (void)_ostree_parse_tristate ("true", &t, &error); + g_assert_no_error (error); + g_assert_cmpint (t, ==, OT_TRISTATE_YES); + (void)_ostree_parse_tristate ("false", &t, &error); + g_assert_no_error (error); + g_assert_cmpint (t, ==, OT_TRISTATE_NO); + + // And an error case + (void)_ostree_parse_tristate ("foobar", &t, &error); + g_assert (error != NULL); +} + int main (int argc, char **argv) { @@ -186,6 +222,7 @@ main (int argc, char **argv) g_test_add_func ("/keyfile-utils/get-value-with-default-group-optional", test_get_value_with_default_group_optional); g_test_add_func ("/keyfile-utils/copy-group", test_copy_group); + g_test_add_func ("/keyfile-utils/parse-tristate", test_parse_tristate); ret = g_test_run ();