diff --git a/src/libostree/ostree-kernel-args.c b/src/libostree/ostree-kernel-args.c index 9a9e0be248..054dcdbdbc 100644 --- a/src/libostree/ostree-kernel-args.c +++ b/src/libostree/ostree-kernel-args.c @@ -163,6 +163,44 @@ strcmp0_equal (gconstpointer v1, gconstpointer v2) return g_strcmp0 (v1, v2) == 0; } +/* Split string with whitespace, but keep quotes. + For example, "test=\"1 2\"" will be saved in hash table as: test="1 2". + */ +static char ** +split_whitespace (const char *str) +{ + gboolean quoted = FALSE; + g_return_val_if_fail (str != NULL, NULL); + + GPtrArray *strv = g_ptr_array_new (); + + guint len = strlen (str); + guint start; + // Skip first whitespaces + for (start = 0; start < len && str[start] == ' '; start++) + { + } + for (guint i = start; str[i] != '\0'; i++) + { + if (str[i] == ' ' && !quoted) + { + g_ptr_array_add (strv, g_strndup (str + start, i - start)); + start = i + 1; + } + if (str[i] == '"') + { + quoted = !quoted; + } + if (i == (len - 1)) + { + if (!quoted) + g_ptr_array_add (strv, g_strndup (str + start, len - start)); + } + } + g_ptr_array_add (strv, NULL); + return (char **)g_ptr_array_free (strv, FALSE); +} + /** * ostree_kernel_args_new: (skip) * @@ -395,8 +433,10 @@ ostree_kernel_args_delete (OstreeKernelArgs *kargs, const char *arg, GError **er { /* but if a specific val was passed, check that it's the same */ OstreeKernelArgsEntry *e = entries->pdata[0]; - if (val && !strcmp0_equal (val, _ostree_kernel_args_entry_get_value (e))) - return glnx_throw (error, "No karg '%s=%s' found", key, val); + g_autofree char *existing_value = _ostree_kernel_args_entry_get_value (e); + if (val && !strcmp0_equal (val, existing_value)) + return glnx_throw (error, "No karg '%s=%s' found, acutal value is '%s'", key, val, + existing_value); return ostree_kernel_args_delete_key_entry (kargs, key, error); } @@ -644,7 +684,7 @@ ostree_kernel_args_parse_append (OstreeKernelArgs *kargs, const char *options) if (!options) return; - args = g_strsplit (options, " ", -1); + args = split_whitespace (options); for (iter = args; *iter; iter++) { char *arg = *iter; diff --git a/tests/test-admin-deploy-karg.sh b/tests/test-admin-deploy-karg.sh index 39fcdf3614..99a4941bd5 100755 --- a/tests/test-admin-deploy-karg.sh +++ b/tests/test-admin-deploy-karg.sh @@ -24,7 +24,7 @@ set -euo pipefail # Exports OSTREE_SYSROOT so --sysroot not needed. setup_os_repository "archive" "syslinux" -echo "1..4" +echo "1..5" ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmain/x86_64-runtime rev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmain/x86_64-runtime) @@ -77,3 +77,10 @@ assert_not_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'op assert_not_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'options.*APPENDARG=VALAPPEND' echo "ok deploy --karg-delete" + +${CMD_PREFIX} ostree admin deploy --os=testos --karg-append="test=\"1 2\"" testos:testos/buildmain/x86_64-runtime +assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'options.*test="1 2"' +${CMD_PREFIX} ostree admin deploy --os=testos --karg-delete="test=\"1 2\"" testos:testos/buildmain/x86_64-runtime +assert_not_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'options.*test="1 2"' + +echo "ok deploy --karg-delete with quotes"