lib/kargs: Make API public and upstream new rpm-ostree APIs

This change makes public the current kargs API in src/libostree/ostree-kernel-args.c
and adds documentations.

Upstreams the new kargs API from rpm-ostree/src/libpriv/rpmostree-kargs-process.c

Merges libostree_kernel_args_la_SOURCES to libostree_1_la_SOURCES in Makefile-libostree.am

Upstreams tests/check/test-kargs.c from rpm-ostree.

Closes: #1833

Closes: #1869
Approved by: jlebon
This commit is contained in:
Allen Bai 2019-05-28 14:02:54 -04:00 committed by Atomic Bot
parent 2db79fb398
commit be2572bf68
22 changed files with 887 additions and 114 deletions

View File

@ -45,6 +45,7 @@ libostree_public_headers = \
src/libostree/ostree-repo-finder-config.h \
src/libostree/ostree-repo-finder-mount.h \
src/libostree/ostree-repo-finder-override.h \
src/libostree/ostree-kernel-args.h \
$(NULL)
# This one is generated via configure.ac, and the gtk-doc

View File

@ -21,8 +21,6 @@
include Makefile-libostree-defines.am
noinst_LTLIBRARIES += libostree-kernel-args.la
if ENABLE_RUST
bupsplitpath = @abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/libbupsplit_rs.a
@ -36,13 +34,6 @@ noinst_LTLIBRARIES += libbupsplit.la
libbupsplit_la_SOURCES = src/libostree/bupsplit.h src/libostree/bupsplit.c
endif # ENABLE_RUST
libostree_kernel_args_la_SOURCES = \
src/libostree/ostree-kernel-args.h \
src/libostree/ostree-kernel-args.c \
$(NULL)
libostree_kernel_args_la_CFLAGS = -I$(srcdir)/libglnx $(OT_INTERNAL_GIO_UNIX_CFLAGS)
libostree_kernel_args_la_LIBADD = $(OT_INTERNAL_GIO_UNIX_LIBS)
lib_LTLIBRARIES += libostree-1.la
libostreeincludedir = $(includedir)/ostree-1
@ -147,6 +138,8 @@ libostree_1_la_SOURCES = \
src/libostree/ostree-repo-finder-config.c \
src/libostree/ostree-repo-finder-mount.c \
src/libostree/ostree-repo-finder-override.c \
src/libostree/ostree-kernel-args.h \
src/libostree/ostree-kernel-args.c \
$(NULL)
if USE_LIBARCHIVE
libostree_1_la_SOURCES += src/libostree/ostree-libarchive-input-stream.h \
@ -191,7 +184,7 @@ libostree_1_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/bsdiff -I$(srcdir)/libglnx -I$(
$(OT_INTERNAL_GIO_UNIX_CFLAGS) $(OT_INTERNAL_GPGME_CFLAGS) $(OT_DEP_LZMA_CFLAGS) $(OT_DEP_ZLIB_CFLAGS) $(OT_DEP_CRYPTO_CFLAGS) \
-fvisibility=hidden '-D_OSTREE_PUBLIC=__attribute__((visibility("default"))) extern'
libostree_1_la_LDFLAGS = -version-number 1:0:0 -Bsymbolic-functions $(addprefix $(wl_versionscript_arg),$(symbol_files))
libostree_1_la_LIBADD = libotutil.la libglnx.la libbsdiff.la libostree-kernel-args.la $(OT_INTERNAL_GIO_UNIX_LIBS) $(OT_INTERNAL_GPGME_LIBS) \
libostree_1_la_LIBADD = libotutil.la libglnx.la libbsdiff.la $(OT_INTERNAL_GIO_UNIX_LIBS) $(OT_INTERNAL_GPGME_LIBS) \
$(OT_DEP_LZMA_LIBS) $(OT_DEP_ZLIB_LIBS) $(OT_DEP_CRYPTO_LIBS)
# Some change between rust-1.21.0-1.fc27 and rust-1.22.1-1.fc27.x86_64
if ENABLE_RUST

View File

@ -125,7 +125,7 @@ ostree_bin_shared_ldadd = $(AM_LDFLAGS) libglnx.la libotutil.la libostree-1.la \
$(OT_INTERNAL_GIO_UNIX_LIBS)
ostree_CFLAGS = $(ostree_bin_shared_cflags)
ostree_LDADD = $(ostree_bin_shared_ldadd) libbsdiff.la libostree-kernel-args.la $(LIBSYSTEMD_LIBS)
ostree_LDADD = $(ostree_bin_shared_ldadd) libbsdiff.la $(LIBSYSTEMD_LIBS)
if USE_CURL_OR_SOUP

View File

@ -246,7 +246,7 @@ endif
_installed_or_uninstalled_test_programs = tests/test-varint tests/test-ot-unix-utils tests/test-bsdiff tests/test-mutable-tree \
tests/test-keyfile-utils tests/test-ot-opt-utils tests/test-ot-tool-util \
tests/test-gpg-verify-result tests/test-checksum tests/test-lzma tests/test-rollsum \
tests/test-basic-c tests/test-sysroot-c tests/test-pull-c tests/test-repo tests/test-include-ostree-h
tests/test-basic-c tests/test-sysroot-c tests/test-pull-c tests/test-repo tests/test-include-ostree-h tests/test-kargs
if USE_AVAHI
test_programs += tests/test-repo-finder-avahi
@ -295,6 +295,10 @@ tests_test_repo_finder_avahi_CFLAGS = $(TESTS_CFLAGS)
tests_test_repo_finder_avahi_LDADD = $(TESTS_LDADD)
endif
tests_test_kargs_SOURCES = src/libostree/ostree-kernel-args.c tests/test-kargs.c
tests_test_kargs_CFLAGS = $(TESTS_CFLAGS)
tests_test_kargs_LDADD = $(TESTS_LDADD)
tests_test_repo_finder_config_SOURCES = tests/test-repo-finder-config.c
tests_test_repo_finder_config_CFLAGS = $(TESTS_CFLAGS)
tests_test_repo_finder_config_LDADD = $(TESTS_LDADD)

View File

@ -78,7 +78,6 @@ IGNORE_HFILES= \
ostree-fetcher.h \
ostree-gpg-verifier.h \
ostree-gpg-verify-result-private.h \
ostree-kernel-args.h \
ostree-libarchive-input-stream.h \
ostree-lzma-compressor.h \
ostree-lzma-decompressor.h \

View File

@ -669,3 +669,25 @@ ostree_repo_set_collection_ref_immediate
ostree_repo_transaction_set_collection_ref
ostree_repo_resolve_collection_ref
</SECTION>
<SECTION>
<FILE>ostree-kernel-args</FILE>
OstreeKernelArgs
ostree_kernel_args_free
ostree_kernel_args_new
ostree_kernel_args_cleanup
ostree_kernel_args_replace_take
ostree_kernel_args_replace
ostree_kernel_args_replace_argv
ostree_kernel_args_append
ostree_kernel_args_append_argv
ostree_kernel_args_append_argv_filtered
ostree_kernel_args_new_replace
ostree_kernel_args_delete
ostree_kernel_args_delete_key_entry
ostree_kernel_args_append_proc_cmdline
ostree_kernel_args_parse_append
ostree_kernel_args_from_string
ostree_kernel_args_to_strv
ostree_kernel_args_to_string
</SECTION>

View File

@ -21,6 +21,23 @@
LIBOSTREE_2019.3 {
global:
ostree_repo_write_archive_to_mtree_from_fd;
ostree_kernel_args_free;
ostree_kernel_args_new;
ostree_kernel_args_cleanup;
ostree_kernel_args_replace_take;
ostree_kernel_args_replace;
ostree_kernel_args_replace_argv;
ostree_kernel_args_append;
ostree_kernel_args_append_argv;
ostree_kernel_args_append_argv_filtered;
ostree_kernel_args_new_replace;
ostree_kernel_args_delete;
ostree_kernel_args_delete_key_entry;
ostree_kernel_args_append_proc_cmdline;
ostree_kernel_args_parse_append;
ostree_kernel_args_from_string;
ostree_kernel_args_to_strv;
ostree_kernel_args_to_string;
} LIBOSTREE_2018.9;
/* Stub section for the stable release *after* this development one; don't

View File

@ -78,8 +78,8 @@ append_system_uenv (OstreeBootloaderUboot *self,
const char *uenv_path = NULL;
const char *ostree_arg = NULL;
kargs = _ostree_kernel_args_from_string (bootargs);
ostree_arg = _ostree_kernel_args_get_last_value (kargs, "ostree");
kargs = ostree_kernel_args_from_string (bootargs);
ostree_arg = ostree_kernel_args_get_last_value (kargs, "ostree");
if (!ostree_arg)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,

View File

@ -21,6 +21,7 @@
#include "ostree-kernel-args.h"
#include "libglnx.h"
#include "otutil.h"
#include <string.h>
@ -60,8 +61,24 @@ _arg_has_prefix (const char *arg,
return FALSE;
}
static gboolean
strcmp0_equal (gconstpointer v1,
gconstpointer v2)
{
return g_strcmp0 (v1, v2) == 0;
}
/**
* ostree_kernel_args_new: (skip)
*
* Initializes a new OstreeKernelArgs structure and returns it
*
* Returns: (transfer full): A newly created #OstreeKernelArgs for kernel arguments
*
* Since: 2019.3
**/
OstreeKernelArgs *
_ostree_kernel_args_new (void)
ostree_kernel_args_new (void)
{
OstreeKernelArgs *ret;
ret = g_new0 (OstreeKernelArgs, 1);
@ -71,8 +88,16 @@ _ostree_kernel_args_new (void)
return ret;
}
/**
* ostree_kernel_args_free:
* @kargs: An OstreeKernelArgs that represents kernel arguments
*
* Frees the kargs structure
*
* Since: 2019.3
**/
void
_ostree_kernel_args_free (OstreeKernelArgs *kargs)
ostree_kernel_args_free (OstreeKernelArgs *kargs)
{
if (!kargs)
return;
@ -81,9 +106,238 @@ _ostree_kernel_args_free (OstreeKernelArgs *kargs)
g_free (kargs);
}
/**
* ostree_kernel_args_cleanup:
* @loc: Address of an OstreeKernelArgs pointer
*
* Frees the OstreeKernelArgs structure pointed by *loc
*
* Since: 2019.3
**/
void
_ostree_kernel_args_replace_take (OstreeKernelArgs *kargs,
char *arg)
ostree_kernel_args_cleanup (void *loc)
{
ostree_kernel_args_free (*((OstreeKernelArgs**)loc));
}
/**
* _ostree_kernel_arg_get_kargs_table:
* @kargs: An OstreeKernelArgs that represents kernel arguments
*
* Returns: (transfer none): #GHashTable that associates with the @kargs
*
* Note: this function is private for now, since the data structures underneath might be changed
*
* Since: 2019.3
**/
GHashTable*
_ostree_kernel_arg_get_kargs_table (OstreeKernelArgs *kargs)
{
if (kargs != NULL)
return kargs->table;
return NULL;
}
/**
* _ostree_kernel_arg_get_key_array:
* @kargs: An OstreeKernelArgs that represents kernel arguments
*
* Returns: (transfer none) (element-type utf8): #GPtrArray that associates with @kargs
*
* Note: this function is private for now, since the data structures underneath might be changed
*
* Since: 2019.3
**/
GPtrArray*
_ostree_kernel_arg_get_key_array (OstreeKernelArgs *kargs)
{
if (kargs != NULL)
return kargs->order;
return NULL;
}
/**
* ostree_kernel_args_new_replace:
* @kargs: OstreeKernelArgs instance
* @arg: a string argument
* @error: error instance
*
* This function implements the basic logic behind key/value pair
* replacement. Do note that the arg need to be properly formatted
*
* When replacing key with exact one value, the arg can be in
* the form:
* key, key=new_val, or key=old_val=new_val
* The first one swaps the old_val with the key to an empty value
* The second and third replace the old_val into the new_val
*
* When replacing key with multiple values, the arg can only be
* in the form of:
* key=old_val=new_val. Unless there is a special case where
* there is an empty value associated with the key, then
* key=new_val will work because old_val is empty. The empty
* val will be swapped with the new_val in that case
*
* Returns: %TRUE on success, %FALSE on failure (and in some other instances such as:
* 1. key not found in @kargs
* 2. old value not found when @arg is in the form of key=old_val=new_val
* 3. multiple old values found when @arg is in the form of key=old_val)
*
* Since: 2019.3
**/
gboolean
ostree_kernel_args_new_replace (OstreeKernelArgs *kargs,
const char *arg,
GError **error)
{
g_autofree char *arg_owned = g_strdup (arg);
const char *key = arg_owned;
const char *val = split_keyeq (arg_owned);
GPtrArray *values = g_hash_table_lookup (kargs->table, key);
if (!values)
return glnx_throw (error, "No key '%s' found", key);
g_assert_cmpuint (values->len, >, 0);
/* first handle the case where the user just wants to replace an old value */
if (val && strchr (val, '='))
{
g_autofree char *old_val = g_strdup (val);
const char *new_val = split_keyeq (old_val);
g_assert (new_val);
guint i = 0;
if (!ot_ptr_array_find_with_equal_func (values, old_val, strcmp0_equal, &i))
return glnx_throw (error, "No karg '%s=%s' found", key, old_val);
g_clear_pointer (&values->pdata[i], g_free);
values->pdata[i] = g_strdup (new_val);
return TRUE;
}
/* can't know which val to replace without the old_val=new_val syntax */
if (values->len > 1)
return glnx_throw (error, "Multiple values for key '%s' found", key);
g_clear_pointer (&values->pdata[0], g_free);
values->pdata[0] = g_strdup (val);
return TRUE;
}
/**
* ostree_kernel_args_delete_key_entry
* @kargs: an OstreeKernelArgs instance
* @key: the key to remove
* @error: an GError instance
*
* This function removes the key entry from the hashtable
* as well from the order pointer array inside kargs
*
* Note: since both table and order inside kernel args
* are with free function, no extra free functions are
* being called as they are done automatically by GLib
*
* Returns: %TRUE on success, %FALSE on failure
*
* Since: 2019.3
**/
gboolean
ostree_kernel_args_delete_key_entry (OstreeKernelArgs *kargs,
const char *key,
GError **error)
{
if (!g_hash_table_remove (kargs->table, key))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Failed to find kernel argument '%s'",
key);
return FALSE;
}
/* Then remove the key from order table */
guint key_index;
g_assert (ot_ptr_array_find_with_equal_func (kargs->order, key, g_str_equal, &key_index));
g_assert (g_ptr_array_remove_index (kargs->order, key_index));
return TRUE;
}
/**
* ostree_kernel_args_delete:
* @kargs: a OstreeKernelArgs instance
* @arg: key or key/value pair for deletion
* @error: an GError instance
*
* There are few scenarios being handled for deletion:
*
* 1: for input arg with a single key(i.e without = for split),
* the key/value pair will be deleted if there is only
* one value that is associated with the key
*
* 2: for input arg wth key/value pair, the specific key
* value pair will be deleted from the pointer array
* if those exist.
*
* 3: If the found key has only one value
* associated with it, the key entry in the table will also
* be removed, and the key will be removed from order table
*
* Returns: %TRUE on success, %FALSE on failure
*
* Since: 2019.3
**/
gboolean
ostree_kernel_args_delete (OstreeKernelArgs *kargs,
const char *arg,
GError **error)
{
g_autofree char *arg_owned = g_strdup (arg);
const char *key = arg_owned;
const char *val = split_keyeq (arg_owned);
GPtrArray *values = g_hash_table_lookup (kargs->table, key);
if (!values)
return glnx_throw (error, "No key '%s' found", key);
g_assert_cmpuint (values->len, >, 0);
/* special-case: we allow deleting by key only if there's only one val */
if (values->len == 1)
{
/* but if a specific val was passed, check that it's the same */
if (val && !strcmp0_equal (val, values->pdata[0]))
return glnx_throw (error, "No karg '%s=%s' found", key, val);
return ostree_kernel_args_delete_key_entry (kargs, key, error);
}
/* note val might be NULL here, in which case we're looking for `key`, not `key=` or
* `key=val` */
guint i = 0;
if (!ot_ptr_array_find_with_equal_func (values, val, strcmp0_equal, &i))
{
if (!val)
/* didn't find NULL -> only key= key=val1 key=val2 style things left, so the user
* needs to be more specific */
return glnx_throw (error, "Multiple values for key '%s' found", arg);
return glnx_throw (error, "No karg '%s' found", arg);
}
g_ptr_array_remove_index (values, i);
return TRUE;
}
/**
* ostree_kernel_args_replace_take:
* @kargs: a OstreeKernelArgs instance
* @arg: (transfer full): key or key/value pair for replacement
*
* Finds and replaces the old key if @arg is already in the hash table,
* otherwise adds @arg as new key and split_keyeq (arg) as value.
* Note that when replacing old key, the old values are freed.
*
* Since: 2019.3
**/
void
ostree_kernel_args_replace_take (OstreeKernelArgs *kargs,
char *arg)
{
gboolean existed;
GPtrArray *values = g_ptr_array_new_with_free_func (g_free);
@ -105,16 +359,38 @@ _ostree_kernel_args_replace_take (OstreeKernelArgs *kargs,
}
}
/**
* ostree_kernel_args_replace:
* @kargs: a OstreeKernelArgs instance
* @arg: key or key/value pair for replacement
*
* Finds and replaces the old key if @arg is already in the hash table,
* otherwise adds @arg as new key and split_keyeq (arg) as value.
* Note that when replacing old key value pair, the old values are freed.
*
* Since: 2019.3
**/
void
_ostree_kernel_args_replace (OstreeKernelArgs *kargs,
const char *arg)
ostree_kernel_args_replace (OstreeKernelArgs *kargs,
const char *arg)
{
_ostree_kernel_args_replace_take (kargs, g_strdup (arg));
ostree_kernel_args_replace_take (kargs, g_strdup (arg));
}
/**
* ostree_kernel_args_append:
* @kargs: a OstreeKernelArgs instance
* @arg: key or key/value pair to be added
*
* Appends @arg which is in the form of key=value pair to the hash table kargs->table
* (appends to the value list if key is already in the hash table)
* and appends key to kargs->order if it is not in the hash table already.
*
* Since: 2019.3
**/
void
_ostree_kernel_args_append (OstreeKernelArgs *kargs,
const char *arg)
ostree_kernel_args_append (OstreeKernelArgs *kargs,
const char *arg)
{
gboolean existed = TRUE;
GPtrArray *values;
@ -141,23 +417,44 @@ _ostree_kernel_args_append (OstreeKernelArgs *kargs,
}
}
/**
* ostree_kernel_args_replace_argv:
* @kargs: a OstreeKernelArgs instance
* @argv: an array of key or key/value pairs
*
* Finds and replaces each non-null arguments of @argv in the hash table,
* otherwise adds individual arg as new key and split_keyeq (arg) as value.
* Note that when replacing old key value pair, the old values are freed.
*
* Since: 2019.3
**/
void
_ostree_kernel_args_replace_argv (OstreeKernelArgs *kargs,
char **argv)
ostree_kernel_args_replace_argv (OstreeKernelArgs *kargs,
char **argv)
{
char **strviter;
for (strviter = argv; strviter && *strviter; strviter++)
{
const char *arg = *strviter;
_ostree_kernel_args_replace (kargs, arg);
ostree_kernel_args_replace (kargs, arg);
}
}
/**
* ostree_kernel_args_append_argv_filtered:
* @kargs: a OstreeKernelArgs instance
* @argv: an array of key=value argument pairs
* @prefixes: an array of prefix strings
*
* Appends each argument that does not have one of the @prefixes as prefix to the @kargs
*
* Since: 2019.3
**/
void
_ostree_kernel_args_append_argv_filtered (OstreeKernelArgs *kargs,
char **argv,
char **prefixes)
ostree_kernel_args_append_argv_filtered (OstreeKernelArgs *kargs,
char **argv,
char **prefixes)
{
char **strviter;
@ -166,21 +463,44 @@ _ostree_kernel_args_append_argv_filtered (OstreeKernelArgs *kargs,
const char *arg = *strviter;
if (!_arg_has_prefix (arg, prefixes))
_ostree_kernel_args_append (kargs, arg);
ostree_kernel_args_append (kargs, arg);
}
}
/**
* ostree_kernel_args_append_argv:
* @kargs: a OstreeKernelArgs instance
* @argv: an array of key=value argument pairs
*
* Appends each value in @argv to the corresponding value array and
* appends key to kargs->order if it is not in the hash table already.
*
* Since: 2019.3
**/
void
_ostree_kernel_args_append_argv (OstreeKernelArgs *kargs,
char **argv)
ostree_kernel_args_append_argv (OstreeKernelArgs *kargs,
char **argv)
{
_ostree_kernel_args_append_argv_filtered (kargs, argv, NULL);
ostree_kernel_args_append_argv_filtered (kargs, argv, NULL);
}
/**
* ostree_kernel_args_append_proc_cmdline:
* @kargs: a OstreeKernelArgs instance
* @cancellable: optional GCancellable object, NULL to ignore
* @error: an GError instance
*
* Appends the command line arguments in the file "/proc/cmdline"
* that does not have "BOOT_IMAGE=" and "initrd=" as prefixes to the @kargs
*
* Returns: %TRUE on success, %FALSE on failure
*
* Since: 2019.3
**/
gboolean
_ostree_kernel_args_append_proc_cmdline (OstreeKernelArgs *kargs,
GCancellable *cancellable,
GError **error)
ostree_kernel_args_append_proc_cmdline (OstreeKernelArgs *kargs,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GFile) proc_cmdline_path = g_file_new_for_path ("/proc/cmdline");
g_autofree char *proc_cmdline = NULL;
@ -202,44 +522,76 @@ _ostree_kernel_args_append_proc_cmdline (OstreeKernelArgs *kargs,
g_strchomp (proc_cmdline);
proc_cmdline_args = g_strsplit (proc_cmdline, " ", -1);
_ostree_kernel_args_append_argv_filtered (kargs, proc_cmdline_args,
ostree_kernel_args_append_argv_filtered (kargs, proc_cmdline_args,
filtered_prefixes);
return TRUE;
}
/**
* ostree_kernel_args_parse_append:
* @kargs: a OstreeKernelArgs instance
* @options: a string representing command line arguments
*
* Parses @options by separating it by whitespaces and appends each argument to @kargs
*
* Since: 2019.3
**/
void
_ostree_kernel_args_parse_append (OstreeKernelArgs *kargs,
const char *options)
ostree_kernel_args_parse_append (OstreeKernelArgs *kargs,
const char *options)
{
char **args = NULL;
char **iter;
if (!options)
return;
args = g_strsplit (options, " ", -1);
for (iter = args; *iter; iter++)
{
char *arg = *iter;
_ostree_kernel_args_append (kargs, arg);
ostree_kernel_args_append (kargs, arg);
}
g_strfreev (args);
}
/**
* ostree_kernel_args_from_string: (skip)
* @options: a string representing command line arguments
*
* Initializes a new OstreeKernelArgs then parses and appends @options
* to the empty OstreeKernelArgs
*
* Returns: (transfer full): newly allocated #OstreeKernelArgs with @options appended
*
* Since: 2019.3
**/
OstreeKernelArgs *
_ostree_kernel_args_from_string (const char *options)
ostree_kernel_args_from_string (const char *options)
{
OstreeKernelArgs *ret;
ret = _ostree_kernel_args_new ();
_ostree_kernel_args_parse_append (ret, options);
ret = ostree_kernel_args_new ();
ostree_kernel_args_parse_append (ret, options);
return ret;
}
/**
* ostree_kernel_args_to_strv:
* @kargs: a OstreeKernelArgs instance
*
* Extracts all key value pairs in @kargs and appends to a temporary
* array in forms of "key=value" or "key" if value is NULL, and returns
* the temporary array with the GPtrArray wrapper freed
*
* Returns: (transfer full): an array of "key=value" pairs or "key" if value is NULL
*
* Since: 2019.3
**/
char **
_ostree_kernel_args_to_strv (OstreeKernelArgs *kargs)
ostree_kernel_args_to_strv (OstreeKernelArgs *kargs)
{
GPtrArray *strv = g_ptr_array_new ();
guint i;
@ -266,8 +618,25 @@ _ostree_kernel_args_to_strv (OstreeKernelArgs *kargs)
return (char**)g_ptr_array_free (strv, FALSE);
}
/**
* ostree_kernel_args_to_string:
* @kargs: a OstreeKernelArgs instance
*
* Extracts all key value pairs in @kargs and appends to a temporary
* GString in forms of "key=value" or "key" if value is NULL separated
* by a single whitespace, and returns the temporary string with the
* GString wrapper freed
*
* Note: the application will be terminated if one of the values array
* in @kargs is NULL
*
* Returns: (transfer full): a string of "key=value" pairs or "key" if value is NULL,
* separated by single whitespaces
*
* Since: 2019.3
**/
char *
_ostree_kernel_args_to_string (OstreeKernelArgs *kargs)
ostree_kernel_args_to_string (OstreeKernelArgs *kargs)
{
GString *buf = g_string_new ("");
gboolean first = TRUE;
@ -302,8 +671,22 @@ _ostree_kernel_args_to_string (OstreeKernelArgs *kargs)
return g_string_free (buf, FALSE);
}
/**
* ostree_kernel_args_get_last_value:
* @kargs: a OstreeKernelArgs instance
* @key: a key to look for in @kargs hash table
*
* Finds and returns the last element of value array
* corresponding to the @key in @kargs hash table. Note that the application
* will be terminated if the @key is found but the value array is empty
*
* Returns: NULL if @key is not found in the @kargs hash table,
* otherwise returns last element of value array corresponding to @key
*
* Since: 2019.3
**/
const char *
_ostree_kernel_args_get_last_value (OstreeKernelArgs *kargs, const char *key)
ostree_kernel_args_get_last_value (OstreeKernelArgs *kargs, const char *key)
{
GPtrArray *values = g_hash_table_lookup (kargs->table, key);

View File

@ -19,41 +19,90 @@
#pragma once
#include "libglnx.h"
#include <gio/gio.h>
#include <glib.h>
#include <glib-object.h>
#include "ostree-types.h"
G_BEGIN_DECLS
typedef struct _OstreeKernelArgs OstreeKernelArgs;
void _ostree_kernel_args_free (OstreeKernelArgs *kargs);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(OstreeKernelArgs, _ostree_kernel_args_free);
OstreeKernelArgs *_ostree_kernel_args_new (void);
void _ostree_kernel_args_replace_take (OstreeKernelArgs *kargs,
char *key);
void _ostree_kernel_args_replace (OstreeKernelArgs *kargs,
const char *key);
void _ostree_kernel_args_replace_argv (OstreeKernelArgs *kargs,
char **argv);
void _ostree_kernel_args_append (OstreeKernelArgs *kargs,
const char *key);
void _ostree_kernel_args_append_argv (OstreeKernelArgs *kargs,
char **argv);
void _ostree_kernel_args_append_argv_filtered (OstreeKernelArgs *kargs,
char **argv,
char **prefixes);
GHashTable *_ostree_kernel_arg_get_kargs_table (OstreeKernelArgs *kargs);
gboolean _ostree_kernel_args_append_proc_cmdline (OstreeKernelArgs *kargs,
GCancellable *cancellable,
GError **error);
GPtrArray *_ostree_kernel_arg_get_key_array (OstreeKernelArgs *kargs);
void _ostree_kernel_args_parse_append (OstreeKernelArgs *kargs,
const char *options);
_OSTREE_PUBLIC
void ostree_kernel_args_free (OstreeKernelArgs *kargs);
const char *_ostree_kernel_args_get_last_value (OstreeKernelArgs *kargs, const char *key);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(OstreeKernelArgs, ostree_kernel_args_free)
OstreeKernelArgs * _ostree_kernel_args_from_string (const char *options);
_OSTREE_PUBLIC
OstreeKernelArgs *ostree_kernel_args_new (void);
char ** _ostree_kernel_args_to_strv (OstreeKernelArgs *kargs);
char * _ostree_kernel_args_to_string (OstreeKernelArgs *kargs);
_OSTREE_PUBLIC
void ostree_kernel_args_cleanup (void *loc);
_OSTREE_PUBLIC
void ostree_kernel_args_replace_take (OstreeKernelArgs *kargs,
char *arg);
_OSTREE_PUBLIC
void ostree_kernel_args_replace (OstreeKernelArgs *kargs,
const char *arg);
_OSTREE_PUBLIC
void ostree_kernel_args_replace_argv (OstreeKernelArgs *kargs,
char **argv);
_OSTREE_PUBLIC
void ostree_kernel_args_append (OstreeKernelArgs *kargs,
const char *arg);
_OSTREE_PUBLIC
void ostree_kernel_args_append_argv (OstreeKernelArgs *kargs,
char **argv);
_OSTREE_PUBLIC
void ostree_kernel_args_append_argv_filtered (OstreeKernelArgs *kargs,
char **argv,
char **prefixes);
_OSTREE_PUBLIC
gboolean ostree_kernel_args_new_replace (OstreeKernelArgs *kargs,
const char *arg,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_kernel_args_delete (OstreeKernelArgs *kargs,
const char *arg,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_kernel_args_delete_key_entry (OstreeKernelArgs *kargs,
const char *key,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_kernel_args_append_proc_cmdline (OstreeKernelArgs *kargs,
GCancellable *cancellable,
GError **error);
_OSTREE_PUBLIC
void ostree_kernel_args_parse_append (OstreeKernelArgs *kargs,
const char *options);
_OSTREE_PUBLIC
const char *ostree_kernel_args_get_last_value (OstreeKernelArgs *kargs,
const char *key);
_OSTREE_PUBLIC
OstreeKernelArgs *ostree_kernel_args_from_string (const char *options);
_OSTREE_PUBLIC
char **ostree_kernel_args_to_strv (OstreeKernelArgs *kargs);
_OSTREE_PUBLIC
char *ostree_kernel_args_to_string (OstreeKernelArgs *kargs);
G_END_DECLS

View File

@ -1759,7 +1759,7 @@ install_deployment_kernel (OstreeSysroot *sysroot,
ostree_bootconfig_parser_set (bootconfig, "linux", boot_relpath);
val = ostree_bootconfig_parser_get (bootconfig, "options");
g_autoptr(OstreeKernelArgs) kargs = _ostree_kernel_args_from_string (val);
g_autoptr(OstreeKernelArgs) kargs = ostree_kernel_args_from_string (val);
if (kernel_layout->initramfs_namever)
{
@ -1772,7 +1772,7 @@ install_deployment_kernel (OstreeSysroot *sysroot,
prepare_root_arg = g_strdup_printf ("init=/ostree/boot.%d/%s/%s/%d/usr/lib/ostree/ostree-prepare-root",
new_bootversion, osname, bootcsum,
ostree_deployment_get_bootserial (deployment));
_ostree_kernel_args_replace_take (kargs, g_steal_pointer (&prepare_root_arg));
ostree_kernel_args_replace_take (kargs, g_steal_pointer (&prepare_root_arg));
}
if (kernel_layout->devicetree_namever)
@ -1785,9 +1785,9 @@ install_deployment_kernel (OstreeSysroot *sysroot,
g_autofree char *ostree_kernel_arg = g_strdup_printf ("ostree=/ostree/boot.%d/%s/%s/%d",
new_bootversion, osname, bootcsum,
ostree_deployment_get_bootserial (deployment));
_ostree_kernel_args_replace_take (kargs, g_steal_pointer (&ostree_kernel_arg));
ostree_kernel_args_replace_take (kargs, g_steal_pointer (&ostree_kernel_arg));
g_autofree char *options_key = _ostree_kernel_args_to_string (kargs);
g_autofree char *options_key = ostree_kernel_args_to_string (kargs);
ostree_bootconfig_parser_set (bootconfig, "options", options_key);
glnx_autofd int bootconf_dfd = -1;
@ -1895,9 +1895,9 @@ get_deployment_nonostree_kargs (OstreeDeployment *deployment)
/* pick up kernel arguments but filter out ostree= */
OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (deployment);
const char *boot_options = ostree_bootconfig_parser_get (bootconfig, "options");
g_autoptr(OstreeKernelArgs) kargs = _ostree_kernel_args_from_string (boot_options);
_ostree_kernel_args_replace (kargs, "ostree");
return _ostree_kernel_args_to_string (kargs);
g_autoptr(OstreeKernelArgs) kargs = ostree_kernel_args_from_string (boot_options);
ostree_kernel_args_replace (kargs, "ostree");
return ostree_kernel_args_to_string (kargs);
}
static char*
@ -2463,9 +2463,9 @@ _ostree_deployment_set_bootconfig_from_kargs (OstreeDeployment *deployment,
*/
if (override_kernel_argv)
{
g_autoptr(OstreeKernelArgs) kargs = _ostree_kernel_args_new ();
_ostree_kernel_args_append_argv (kargs, override_kernel_argv);
g_autofree char *new_options = _ostree_kernel_args_to_string (kargs);
g_autoptr(OstreeKernelArgs) kargs = ostree_kernel_args_new ();
ostree_kernel_args_append_argv (kargs, override_kernel_argv);
g_autofree char *new_options = ostree_kernel_args_to_string (kargs);
ostree_bootconfig_parser_set (bootconfig, "options", new_options);
}
}
@ -3004,9 +3004,9 @@ ostree_sysroot_deployment_set_kargs (OstreeSysroot *self,
g_autoptr(OstreeDeployment) new_deployment = ostree_deployment_clone (deployment);
OstreeBootconfigParser *new_bootconfig = ostree_deployment_get_bootconfig (new_deployment);
g_autoptr(OstreeKernelArgs) kargs = _ostree_kernel_args_new ();
_ostree_kernel_args_append_argv (kargs, new_kargs);
g_autofree char *new_options = _ostree_kernel_args_to_string (kargs);
g_autoptr(OstreeKernelArgs) kargs = ostree_kernel_args_new ();
ostree_kernel_args_append_argv (kargs, new_kargs);
g_autofree char *new_options = ostree_kernel_args_to_string (kargs);
ostree_bootconfig_parser_set (new_bootconfig, "options", new_options);
g_autoptr(GPtrArray) new_deployments = g_ptr_array_new_with_free_func (g_object_unref);

View File

@ -23,7 +23,6 @@
#include "libglnx.h"
#include "ostree.h"
#include "ostree-kernel-args.h"
#include "ostree-bootloader.h"
G_BEGIN_DECLS

View File

@ -1688,12 +1688,12 @@ clone_deployment (OstreeSysroot *sysroot,
/* Copy the bootloader config options */
OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (merge_deployment);
g_auto(GStrv) previous_args = g_strsplit (ostree_bootconfig_parser_get (bootconfig, "options"), " ", -1);
g_autoptr(OstreeKernelArgs) kargs = _ostree_kernel_args_new ();
_ostree_kernel_args_append_argv (kargs, previous_args);
g_autoptr(OstreeKernelArgs) kargs = ostree_kernel_args_new ();
ostree_kernel_args_append_argv (kargs, previous_args);
/* Deploy the copy */
g_autoptr(OstreeDeployment) new_deployment = NULL;
g_auto(GStrv) kargs_strv = _ostree_kernel_args_to_strv (kargs);
g_auto(GStrv) kargs_strv = ostree_kernel_args_to_strv (kargs);
if (!ostree_sysroot_deploy_tree (sysroot,
ostree_deployment_get_osname (target_deployment),
ostree_deployment_get_csum (target_deployment),

View File

@ -41,3 +41,4 @@
#include <ostree-repo-finder-override.h>
#include <ostree-autocleanups.h>
#include <ostree-version.h>
#include <ostree-kernel-args.h>

View File

@ -62,3 +62,55 @@ ot_parse_keyvalue (const char *keyvalue,
*out_value = g_strdup (eq + 1);
return TRUE;
}
/**
* Note: temporarily copied from GLib: https://github.com/GNOME/glib/blob/a419146578a42c760cff684292465b38df855f75/glib/garray.c#L1664
* See documentation at: https://developer.gnome.org/glib/stable/glib-Pointer-Arrays.html#g-ptr-array-find-with-equal-func
*
* ot_ptr_array_find_with_equal_func: (skip)
* @haystack: pointer array to be searched
* @needle: pointer to look for
* @equal_func: (nullable): the function to call for each element, which should
* return %TRUE when the desired element is found; or %NULL to use pointer
* equality
* @index_: (optional) (out caller-allocates): return location for the index of
* the element, if found
*
* Checks whether @needle exists in @haystack, using the given @equal_func.
* If the element is found, %TRUE is returned and the elements index is
* returned in @index_ (if non-%NULL). Otherwise, %FALSE is returned and @index_
* is undefined. If @needle exists multiple times in @haystack, the index of
* the first instance is returned.
*
* @equal_func is called with the element from the array as its first parameter,
* and @needle as its second parameter. If @equal_func is %NULL, pointer
* equality is used.
*
* Returns: %TRUE if @needle is one of the elements of @haystack
* Since: 2.54
*/
gboolean
ot_ptr_array_find_with_equal_func (GPtrArray *haystack,
gconstpointer needle,
GEqualFunc equal_func,
guint *index_)
{
guint i;
g_return_val_if_fail (haystack != NULL, FALSE);
if (equal_func == NULL)
equal_func = g_direct_equal;
for (i = 0; i < haystack->len; i++)
{
if (equal_func (g_ptr_array_index (haystack, i), needle))
{
if (index_ != NULL)
*index_ = i;
return TRUE;
}
}
return FALSE;
}

View File

@ -34,5 +34,10 @@ ot_parse_keyvalue (const char *keyvalue,
char **out_key,
char **out_value,
GError **error);
gboolean
ot_ptr_array_find_with_equal_func (GPtrArray *haystack,
gconstpointer needle,
GEqualFunc equal_func,
guint *index_);
G_END_DECLS

View File

@ -62,3 +62,4 @@
#include <ot-checksum-utils.h>
#include <ot-gpg-utils.h>
#include <ot-checksum-instream.h>
#include <ot-tool-util.h>

View File

@ -29,8 +29,6 @@
#include "ostree.h"
#include "otutil.h"
#include "../libostree/ostree-kernel-args.h"
#include <glib/gi18n.h>
static gboolean opt_retain;
@ -133,20 +131,20 @@ ot_admin_builtin_deploy (int argc, char **argv, OstreeCommandInvocation *invocat
g_autoptr(OstreeKernelArgs) kargs = NULL;
if (opt_kernel_arg_none)
{
kargs = _ostree_kernel_args_new ();
kargs = ostree_kernel_args_new ();
}
else if (opt_kernel_proc_cmdline)
{
kargs = _ostree_kernel_args_new ();
if (!_ostree_kernel_args_append_proc_cmdline (kargs, cancellable, error))
kargs = ostree_kernel_args_new ();
if (!ostree_kernel_args_append_proc_cmdline (kargs, cancellable, error))
return FALSE;
}
else if (merge_deployment && (opt_kernel_argv || opt_kernel_argv_append))
{
OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (merge_deployment);
g_auto(GStrv) previous_args = g_strsplit (ostree_bootconfig_parser_get (bootconfig, "options"), " ", -1);
kargs = _ostree_kernel_args_new ();
_ostree_kernel_args_append_argv (kargs, previous_args);
kargs = ostree_kernel_args_new ();
ostree_kernel_args_append_argv (kargs, previous_args);
}
/* Now replace/extend the above set. Note that if no options are specified,
@ -156,19 +154,19 @@ ot_admin_builtin_deploy (int argc, char **argv, OstreeCommandInvocation *invocat
if (opt_kernel_argv)
{
if (!kargs)
kargs = _ostree_kernel_args_new ();
_ostree_kernel_args_replace_argv (kargs, opt_kernel_argv);
kargs = ostree_kernel_args_new ();
ostree_kernel_args_replace_argv (kargs, opt_kernel_argv);
}
if (opt_kernel_argv_append)
{
if (!kargs)
kargs = _ostree_kernel_args_new ();
_ostree_kernel_args_append_argv (kargs, opt_kernel_argv_append);
kargs = ostree_kernel_args_new ();
ostree_kernel_args_append_argv (kargs, opt_kernel_argv_append);
}
g_autoptr(OstreeDeployment) new_deployment = NULL;
g_auto(GStrv) kargs_strv = kargs ? _ostree_kernel_args_to_strv (kargs) : NULL;
g_auto(GStrv) kargs_strv = kargs ? ostree_kernel_args_to_strv (kargs) : NULL;
if (opt_stage)
{
if (opt_retain_pending || opt_retain_rollback)

View File

@ -27,8 +27,6 @@
#include "ostree.h"
#include "otutil.h"
#include "../libostree/ostree-kernel-args.h"
#include <glib/gi18n.h>
#include <err.h>

View File

@ -26,8 +26,7 @@
#include "ot-admin-instutil-builtins.h"
#include "otutil.h"
#include "../libostree/ostree-kernel-args.h"
#include "ostree.h"
static gboolean opt_proc_cmdline;
static gboolean opt_merge;
@ -69,14 +68,14 @@ ot_admin_instutil_builtin_set_kargs (int argc, char **argv, OstreeCommandInvocat
}
first_deployment = deployments->pdata[0];
kargs = _ostree_kernel_args_new ();
kargs = ostree_kernel_args_new ();
/* If they want the current kernel's args, they very likely don't
* want the ones from the merge.
*/
if (opt_proc_cmdline)
{
if (!_ostree_kernel_args_append_proc_cmdline (kargs, cancellable, error))
if (!ostree_kernel_args_append_proc_cmdline (kargs, cancellable, error))
goto out;
}
else if (opt_merge)
@ -84,24 +83,24 @@ ot_admin_instutil_builtin_set_kargs (int argc, char **argv, OstreeCommandInvocat
OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (first_deployment);
g_auto(GStrv) previous_args = g_strsplit (ostree_bootconfig_parser_get (bootconfig, "options"), " ", -1);
_ostree_kernel_args_append_argv (kargs, previous_args);
ostree_kernel_args_append_argv (kargs, previous_args);
}
if (opt_replace)
{
_ostree_kernel_args_replace_argv (kargs, opt_replace);
ostree_kernel_args_replace_argv (kargs, opt_replace);
}
if (opt_append)
{
_ostree_kernel_args_append_argv (kargs, opt_append);
ostree_kernel_args_append_argv (kargs, opt_append);
}
for (i = 1; i < argc; i++)
_ostree_kernel_args_append (kargs, argv[i]);
ostree_kernel_args_append (kargs, argv[i]);
{
g_auto(GStrv) kargs_strv = _ostree_kernel_args_to_strv (kargs);
g_auto(GStrv) kargs_strv = ostree_kernel_args_to_strv (kargs);
if (!ostree_sysroot_deployment_set_kargs (sysroot, first_deployment,
kargs_strv,

1
tests/.gitignore vendored
View File

@ -22,3 +22,4 @@ test-repo-finder-avahi
test-repo-finder-config
test-repo-finder-mount
test-rollsum-cli
test-kargs

251
tests/test-kargs.c Normal file
View File

@ -0,0 +1,251 @@
/*
* Copyright (C) 2015 Red Hat, Inc.
*
* SPDX-License-Identifier: LGPL-2.0+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "ostree-kernel-args.h"
#include "otutil.h"
static gboolean
check_string_existance (OstreeKernelArgs *karg,
const char *string_to_find)
{
g_autofree gchar* string_with_spaces = ostree_kernel_args_to_string (karg);
g_auto(GStrv) string_list = g_strsplit (string_with_spaces, " ", -1);
return g_strv_contains ((const char* const*) string_list, string_to_find);
}
static void
test_kargs_delete (void)
{
g_autoptr(GError) error = NULL;
gboolean ret;
__attribute__((cleanup(ostree_kernel_args_cleanup))) OstreeKernelArgs *karg = ostree_kernel_args_new ();
ostree_kernel_args_append (karg, "single_key=test");
ostree_kernel_args_append (karg, "test=firstval");
ostree_kernel_args_append (karg, "test=secondval");
ostree_kernel_args_append (karg, "test=");
ostree_kernel_args_append (karg, "test");
/* Delete a non-existant key should fail */
ret = ostree_kernel_args_delete (karg, "non_existant_key", &error);
g_assert (!ret);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
g_clear_error (&error);
/* Delete a key with multiple values when only specifying key should work if a no-value
* variant exists */
ret = ostree_kernel_args_delete (karg, "test", &error);
g_assert_no_error (error);
g_assert (ret);
g_assert (!check_string_existance (karg, "test"));
/* Trying again now should fail since there are only kargs with various values */
ret = ostree_kernel_args_delete (karg, "test", &error);
g_assert (!ret);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
g_clear_error (&error);
/* Delete a key with a non existant value should fail */
ret = ostree_kernel_args_delete (karg, "test=non_existant_value", &error);
g_assert (!ret);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
g_clear_error (&error);
/* Delete a key with only one value should fail if the value doesn't match */
ret = ostree_kernel_args_delete (karg, "single_key=non_existent_value", &error);
g_assert (!ret);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
g_clear_error (&error);
/* Delete a key with only one value should succeed by only specifying key */
ret = ostree_kernel_args_delete (karg, "single_key", &error);
g_assert_no_error (error);
g_assert (ret);
/* verify the value array is properly updated */
GPtrArray *kargs_array = _ostree_kernel_arg_get_key_array (karg);
g_assert (!ot_ptr_array_find_with_equal_func (kargs_array, "single_key", g_str_equal, NULL));
g_assert (!check_string_existance (karg, "single_key"));
/* Delete specific key/value pair */
ret = ostree_kernel_args_delete (karg, "test=secondval", &error);
g_assert_no_error (error);
g_assert (ret);
g_assert (!check_string_existance (karg, "test=secondval"));
/* Delete key/value pair with empty string value */
ret = ostree_kernel_args_delete (karg, "test=", &error);
g_assert_no_error (error);
g_assert (ret);
g_assert (!check_string_existance (karg, "test="));
ret = ostree_kernel_args_delete (karg, "test=firstval", &error);
g_assert_no_error (error);
g_assert (ret);
g_assert (!check_string_existance (karg, "test=firstval"));
/* Check that we can delete duplicate keys */
ostree_kernel_args_append (karg, "test=foo");
ostree_kernel_args_append (karg, "test=foo");
check_string_existance (karg, "test=foo");
ret = ostree_kernel_args_delete (karg, "test=foo", &error);
g_assert_no_error (error);
g_assert (ret);
g_assert (check_string_existance (karg, "test=foo"));
ret = ostree_kernel_args_delete (karg, "test=foo", &error);
g_assert_no_error (error);
g_assert (ret);
g_assert (!check_string_existance (karg, "test=foo"));
/* Make sure we also gracefully do this for key-only args */
ostree_kernel_args_append (karg, "nosmt");
ostree_kernel_args_append (karg, "nosmt");
check_string_existance (karg, "nosmt");
ret = ostree_kernel_args_delete (karg, "nosmt", &error);
g_assert_no_error (error);
g_assert (ret);
g_assert (check_string_existance (karg, "nosmt"));
ret = ostree_kernel_args_delete (karg, "nosmt", &error);
g_assert_no_error (error);
g_assert (ret);
g_assert (!check_string_existance (karg, "nosmt"));
}
static void
test_kargs_replace (void)
{
g_autoptr(GError) error = NULL;
gboolean ret;
__attribute__((cleanup(ostree_kernel_args_cleanup))) OstreeKernelArgs *karg = ostree_kernel_args_new ();
ostree_kernel_args_append (karg, "single_key");
ostree_kernel_args_append (karg, "test=firstval");
ostree_kernel_args_append (karg, "test=secondval");
/* Replace when the input key is non-existant should fail */
ret = ostree_kernel_args_new_replace (karg, "nonexistantkey", &error);
g_assert (!ret);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
g_clear_error (&error);
/* Replace non-existant value with input key=nonexistantvalue=newvalue should fail */
ret = ostree_kernel_args_new_replace (karg, "single_key=nonexistantval=newval", &error);
g_assert (!ret);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
g_clear_error (&error);
/* Replace with input key=value will fail for a key with multiple values */
ret = ostree_kernel_args_new_replace (karg, "test=newval", &error);
g_assert (!ret);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
g_clear_error (&error);
/* Replace with input key=value for a key with single value should succeed
* Also note, we also allow ''(empty string) valid to be a value
*/
ret = ostree_kernel_args_new_replace (karg, "single_key=newvalue", &error);
g_assert_no_error (error);
g_assert (ret);
g_assert (!check_string_existance (karg, "single_key"));
g_assert (check_string_existance (karg, "single_key=newvalue"));
/* Replace with input key=value=newvalue if key and value both
* exist, the action should succeed
*/
ret = ostree_kernel_args_new_replace (karg, "test=firstval=newval", &error);
g_assert_no_error (error);
g_assert (ret);
g_assert (!check_string_existance (karg, "test=firstval"));
g_assert (check_string_existance (karg, "test=newval"));
}
static gboolean
strcmp0_equal (gconstpointer v1,
gconstpointer v2)
{
return g_strcmp0 (v1, v2) == 0;
}
/* In this function, we want to verify that ostree_kernel_args_append
* and ostree_kernel_args_to_string is correct. After that
* we will use these two functions(append and tostring) in other tests: delete and replace
*/
static void
test_kargs_append (void)
{
__attribute__((cleanup(ostree_kernel_args_cleanup))) OstreeKernelArgs *append_arg = ostree_kernel_args_new ();
/* Some valid cases (key=value) pair */
ostree_kernel_args_append (append_arg, "test=valid");
ostree_kernel_args_append (append_arg, "test=secondvalid");
ostree_kernel_args_append (append_arg, "test=");
ostree_kernel_args_append (append_arg, "test");
ostree_kernel_args_append (append_arg, "second_test");
/* We loops through the kargs inside table to verify
* the functionality of append because at this stage
* we have yet to find the conversion kargs to string fully "functional"
*/
GHashTable *kargs_table = _ostree_kernel_arg_get_kargs_table (append_arg);
GLNX_HASH_TABLE_FOREACH_KV (kargs_table, const char*, key, GPtrArray*, value_array)
{
if (g_str_equal (key, "test"))
{
g_assert (ot_ptr_array_find_with_equal_func (value_array, "valid", strcmp0_equal, NULL));
g_assert (ot_ptr_array_find_with_equal_func (value_array, "secondvalid", strcmp0_equal, NULL));
g_assert (ot_ptr_array_find_with_equal_func (value_array, "", strcmp0_equal, NULL));
g_assert (ot_ptr_array_find_with_equal_func (value_array, NULL, strcmp0_equal, NULL));
}
else
{
g_assert_cmpstr (key, ==, "second_test");
g_assert (ot_ptr_array_find_with_equal_func (value_array, NULL, strcmp0_equal, NULL));
}
}
/* verify the value array is properly updated */
GPtrArray *kargs_array = _ostree_kernel_arg_get_key_array (append_arg);
g_assert (ot_ptr_array_find_with_equal_func (kargs_array, "test", g_str_equal, NULL));
g_assert (ot_ptr_array_find_with_equal_func (kargs_array, "second_test", g_str_equal, NULL));
/* Up till this point, we verified that the above was all correct, we then
* check ostree_kernel_args_to_string has the right result
*/
g_autofree gchar* kargs_str = ostree_kernel_args_to_string (append_arg);
g_auto(GStrv) kargs_list = g_strsplit(kargs_str, " ", -1);
g_assert (g_strv_contains ((const char* const *)kargs_list, "test=valid"));
g_assert (g_strv_contains ((const char* const *)kargs_list, "test=secondvalid"));
g_assert (g_strv_contains ((const char* const *)kargs_list, "test="));
g_assert (g_strv_contains ((const char* const *)kargs_list, "test"));
g_assert (g_strv_contains ((const char* const *)kargs_list, "second_test"));
g_assert_cmpint (5, ==, g_strv_length (kargs_list));
}
int
main (int argc,
char *argv[])
{
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/kargs/kargs_append", test_kargs_append);
g_test_add_func ("/kargs/kargs_delete", test_kargs_delete);
g_test_add_func ("/kargs/kargs_replace", test_kargs_replace);
return g_test_run ();
}