diff options
author | Colin Walters <walters@verbum.org> | 2014-01-16 13:04:00 -0500 |
---|---|---|
committer | Colin Walters <walters@verbum.org> | 2014-01-16 15:07:55 -0500 |
commit | b2d0ba7ac1e742586eeb3018d88e01dc436d5b4d (patch) | |
tree | 01abcbdef606c1587e9a3ade713a08511debdd89 /src | |
parent | 7db2031fa06621d0564f859776e072130d49a867 (diff) | |
download | ostree-b2d0ba7ac1e742586eeb3018d88e01dc436d5b4d.tar.gz |
deploy: Rework kernel arguments, add --karg-append to "admin deploy"
The "ordered hash" code was really just for kernel arguments. And it
turns out it needs to be a multihash (for e.g. multiple console=
arguments).
So turn the OstreeOrderedHash into OstreeKernelArgs, and move the bits
to split key=value and such into there.
Now we're not making this public API yet - the public OstreeSysroot
just takes char **kargs. To facilitate code reuse between ostree/ and
libostree/, make it a noinst libtool library. It'll be duplicated in
the binary and library, but that's OK for now. We can investigate
making OstreeKernelArgs public later.
https://bugzilla.gnome.org/show_bug.cgi?id=721136
Diffstat (limited to 'src')
-rw-r--r-- | src/libostree/ostree-kernel-args.c | 263 | ||||
-rw-r--r-- | src/libostree/ostree-kernel-args.h | 54 | ||||
-rw-r--r-- | src/libostree/ostree-ordered-hash.c | 83 | ||||
-rw-r--r-- | src/libostree/ostree-ordered-hash.h | 44 | ||||
-rw-r--r-- | src/libostree/ostree-sysroot-deploy.c | 67 | ||||
-rw-r--r-- | src/libostree/ostree-sysroot-private.h | 8 | ||||
-rw-r--r-- | src/libostree/ostree-sysroot.c | 96 | ||||
-rw-r--r-- | src/libostree/ostree-sysroot.h | 18 | ||||
-rw-r--r-- | src/ostree/ot-admin-builtin-deploy.c | 61 | ||||
-rw-r--r-- | src/ostree/ot-admin-builtin-upgrade.c | 12 |
10 files changed, 404 insertions, 302 deletions
diff --git a/src/libostree/ostree-kernel-args.c b/src/libostree/ostree-kernel-args.c new file mode 100644 index 00000000..f31932ed --- /dev/null +++ b/src/libostree/ostree-kernel-args.c @@ -0,0 +1,263 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2013,2014 Colin Walters <walters@verbum.org> + * + * This program 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 licence 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 <string.h> + +struct _OstreeKernelArgs { + GPtrArray *order; + GHashTable *table; +}; + +static char * +split_keyeq (char *arg) +{ + char *eq; + + eq = strchr (arg, '='); + if (eq) + { + /* Note key/val are in one malloc block, + * so we don't free val... + */ + *eq = '\0'; + return eq+1; + } + else + { + /* ...and this allows us to insert a constant + * string. + */ + return ""; + } +} + +OstreeKernelArgs * +_ostree_kernel_args_new (void) +{ + OstreeKernelArgs *ret; + ret = g_new0 (OstreeKernelArgs, 1); + ret->order = g_ptr_array_new_with_free_func (g_free); + ret->table = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, (GDestroyNotify)g_ptr_array_unref); + return ret; +} + +void +_ostree_kernel_args_free (OstreeKernelArgs *kargs) +{ + if (!kargs) + return; + g_ptr_array_unref (kargs->order); + g_hash_table_unref (kargs->table); + g_free (kargs); +} + +void +_ostree_kernel_args_cleanup (void *loc) +{ + _ostree_kernel_args_free (*((OstreeKernelArgs**)loc)); +} + +void +_ostree_kernel_args_replace_take (OstreeKernelArgs *kargs, + char *arg) +{ + gboolean existed; + GPtrArray *values = g_ptr_array_new_with_free_func (g_free); + const char *value = split_keyeq (arg); + + existed = g_hash_table_remove (kargs->table, arg); + if (!existed) + g_ptr_array_add (kargs->order, arg); + g_ptr_array_add (values, g_strdup (value)); + g_hash_table_replace (kargs->table, arg, values); +} + +void +_ostree_kernel_args_replace (OstreeKernelArgs *kargs, + const char *arg) +{ + _ostree_kernel_args_replace_take (kargs, g_strdup (arg)); +} + +void +_ostree_kernel_args_append (OstreeKernelArgs *kargs, + const char *arg) +{ + gboolean existed = TRUE; + GPtrArray *values; + char *duped = g_strdup (arg); + const char *val = split_keyeq (duped); + + values = g_hash_table_lookup (kargs->table, duped); + if (!values) + { + values = g_ptr_array_new_with_free_func (g_free); + existed = FALSE; + } + + g_ptr_array_add (values, g_strdup (val)); + + if (!existed) + { + g_hash_table_replace (kargs->table, duped, values); + g_ptr_array_add (kargs->order, duped); + } + else + { + g_free (duped); + } +} + +void +_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); + } +} + +void +_ostree_kernel_args_append_argv (OstreeKernelArgs *kargs, + char **argv) +{ + char **strviter; + + for (strviter = argv; strviter && *strviter; strviter++) + { + const char *arg = *strviter; + _ostree_kernel_args_append (kargs, arg); + } +} + +void +_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); + } + g_strfreev (args); +} + +OstreeKernelArgs * +_ostree_kernel_args_from_string (const char *options) +{ + OstreeKernelArgs *ret; + + ret = _ostree_kernel_args_new (); + _ostree_kernel_args_parse_append (ret, options); + + return ret; +} + +char ** +_ostree_kernel_args_to_strv (OstreeKernelArgs *kargs) +{ + GPtrArray *strv = g_ptr_array_new (); + guint i; + + for (i = 0; i < kargs->order->len; i++) + { + const char *key = kargs->order->pdata[i]; + GPtrArray *values = g_hash_table_lookup (kargs->table, key); + guint j; + + g_assert (values != NULL); + + for (j = 0; j < values->len; j++) + { + const char *value = values->pdata[j]; + + g_ptr_array_add (strv, g_strconcat (key, "=", value, NULL)); + } + } + g_ptr_array_add (strv, NULL); + + return (char**)g_ptr_array_free (strv, FALSE); +} + +char * +_ostree_kernel_args_to_string (OstreeKernelArgs *kargs) +{ + GString *buf = g_string_new (""); + gboolean first = TRUE; + guint i; + + for (i = 0; i < kargs->order->len; i++) + { + const char *key = kargs->order->pdata[i]; + GPtrArray *values = g_hash_table_lookup (kargs->table, key); + guint j; + + g_assert (values != NULL); + + for (j = 0; j < values->len; j++) + { + const char *value = values->pdata[j]; + + if (first) + first = FALSE; + else + g_string_append_c (buf, ' '); + + if (value && *value) + { + g_string_append (buf, key); + g_string_append_c (buf, '='); + g_string_append (buf, value); + } + else + g_string_append (buf, key); + } + } + + return g_string_free (buf, FALSE); +} + +const char * +_ostree_kernel_args_get_last_value (OstreeKernelArgs *kargs, const char *key) +{ + GPtrArray *values = g_hash_table_lookup (kargs->table, key); + + if (!values) + return NULL; + + g_assert (values->len > 0); + return (char*)values->pdata[values->len-1]; +} diff --git a/src/libostree/ostree-kernel-args.h b/src/libostree/ostree-kernel-args.h new file mode 100644 index 00000000..89d4fc9f --- /dev/null +++ b/src/libostree/ostree-kernel-args.h @@ -0,0 +1,54 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2013,2014 Colin Walters <walters@verbum.org> + * + * This program 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 licence 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. + */ + +#pragma once + +#include <gio/gio.h> + +G_BEGIN_DECLS + +typedef struct _OstreeKernelArgs OstreeKernelArgs; + +OstreeKernelArgs *_ostree_kernel_args_new (void); +void _ostree_kernel_args_free (OstreeKernelArgs *kargs); +void _ostree_kernel_args_cleanup (void *loc); +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_parse_append (OstreeKernelArgs *kargs, + const char *options); + +const char *_ostree_kernel_args_get_last_value (OstreeKernelArgs *kargs, const char *key); + +OstreeKernelArgs * _ostree_kernel_args_from_string (const char *options); + +char ** _ostree_kernel_args_to_strv (OstreeKernelArgs *kargs); +char * _ostree_kernel_args_to_string (OstreeKernelArgs *kargs); + +G_END_DECLS + diff --git a/src/libostree/ostree-ordered-hash.c b/src/libostree/ostree-ordered-hash.c deleted file mode 100644 index ba13bf94..00000000 --- a/src/libostree/ostree-ordered-hash.c +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2013 Colin Walters <walters@verbum.org> - * - * This program 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 licence 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-ordered-hash.h" -#include "libgsystem.h" - -OstreeOrderedHash * -_ostree_ordered_hash_new (void) -{ - OstreeOrderedHash *ret; - ret = g_new0 (OstreeOrderedHash, 1); - ret->order = g_ptr_array_new_with_free_func (g_free); - ret->table = g_hash_table_new (g_str_hash, g_str_equal); - return ret; -} - -void -_ostree_ordered_hash_free (OstreeOrderedHash *ohash) -{ - if (!ohash) - return; - g_ptr_array_unref (ohash->order); - g_hash_table_unref (ohash->table); - g_free (ohash); -} - -void -_ostree_ordered_hash_cleanup (void *loc) -{ - _ostree_ordered_hash_free (*((OstreeOrderedHash**)loc)); -} - -void -_ostree_ordered_hash_replace_key_take (OstreeOrderedHash *ohash, - char *key, - const char *value) -{ - gboolean existed; - - existed = g_hash_table_remove (ohash->table, key); - if (!existed) - g_ptr_array_add (ohash->order, key); - g_hash_table_insert (ohash->table, key, (char*)value); -} - -void -_ostree_ordered_hash_replace_key (OstreeOrderedHash *ohash, - const char *key, - const char *val) -{ - GString *buf; - gsize keylen; - char *valp; - char *valblock; - - buf = g_string_new (key); - keylen = buf->len; - g_string_append_c (buf, '\0'); - g_string_append (buf, val); - valblock = g_string_free (buf, FALSE); - valp = valblock + keylen + 1; - - _ostree_ordered_hash_replace_key_take (ohash, valblock, valp); -} diff --git a/src/libostree/ostree-ordered-hash.h b/src/libostree/ostree-ordered-hash.h deleted file mode 100644 index 1cfe8527..00000000 --- a/src/libostree/ostree-ordered-hash.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2013 Colin Walters <walters@verbum.org> - * - * This program 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 licence 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. - */ - -#pragma once - -#include <gio/gio.h> - -G_BEGIN_DECLS - -typedef struct { - GPtrArray *order; - GHashTable *table; -} OstreeOrderedHash; - -OstreeOrderedHash *_ostree_ordered_hash_new (void); -void _ostree_ordered_hash_free (OstreeOrderedHash *ohash); -void _ostree_ordered_hash_cleanup (void *loc); -void _ostree_ordered_hash_replace_key_take (OstreeOrderedHash *ohash, - char *key, - const char *value); -void _ostree_ordered_hash_replace_key (OstreeOrderedHash *ohash, - const char *key, - const char *val); - - -G_END_DECLS - diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 749a375a..4a217401 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -601,7 +601,7 @@ install_deployment_kernel (OstreeSysroot *sysroot, gs_free char *version_key = NULL; gs_free char *ostree_kernel_arg = NULL; gs_free char *options_key = NULL; - __attribute__((cleanup(_ostree_ordered_hash_cleanup))) OstreeOrderedHash *ohash = NULL; + __attribute__((cleanup(_ostree_kernel_args_cleanup))) OstreeKernelArgs *kargs = NULL; const char *val; OstreeBootconfigParser *bootconfig; gsize len; @@ -693,12 +693,14 @@ install_deployment_kernel (OstreeSysroot *sysroot, } val = ostree_bootconfig_parser_get (bootconfig, "options"); - ostree_kernel_arg = g_strdup_printf ("/ostree/boot.%d/%s/%s/%d", + + ostree_kernel_arg = g_strdup_printf ("ostree=/ostree/boot.%d/%s/%s/%d", new_bootversion, osname, bootcsum, ostree_deployment_get_bootserial (deployment)); - ohash = _ostree_sysroot_parse_kernel_args (val); - _ostree_ordered_hash_replace_key (ohash, "ostree", ostree_kernel_arg); - options_key = _ostree_sysroot_kernel_arg_string_serialize (ohash); + kargs = _ostree_kernel_args_from_string (val); + _ostree_kernel_args_replace_take (kargs, ostree_kernel_arg); + ostree_kernel_arg = NULL; + options_key = _ostree_kernel_args_to_string (kargs); ostree_bootconfig_parser_set (bootconfig, "options", options_key); if (!ostree_bootconfig_parser_write (ostree_deployment_get_bootconfig (deployment), bootconfpath, @@ -773,14 +775,14 @@ bootconfig_counts_for_deployment_list (GPtrArray *deployments) const char *boot_options = ostree_bootconfig_parser_get (bootconfig, "options"); GChecksum *bootconfig_checksum = g_checksum_new (G_CHECKSUM_SHA256); const char *bootconfig_checksum_str; - __attribute__((cleanup(_ostree_ordered_hash_cleanup))) OstreeOrderedHash *ohash = NULL; + __attribute__((cleanup(_ostree_kernel_args_cleanup))) OstreeKernelArgs *kargs = NULL; gs_free char *boot_options_without_ostree = NULL; guint count; /* We checksum the kernel arguments *except* ostree= */ - ohash = _ostree_sysroot_parse_kernel_args (boot_options); - _ostree_ordered_hash_replace_key (ohash, "ostree", ""); - boot_options_without_ostree = _ostree_sysroot_kernel_arg_string_serialize (ohash); + kargs = _ostree_kernel_args_from_string (boot_options); + _ostree_kernel_args_replace (kargs, "ostree"); + boot_options_without_ostree = _ostree_kernel_args_to_string (kargs); g_checksum_update (bootconfig_checksum, (guint8*)bootcsum, strlen (bootcsum)); g_checksum_update (bootconfig_checksum, (guint8*)boot_options_without_ostree, @@ -1049,13 +1051,13 @@ allocate_deployserial (OstreeSysroot *self, } /** - * ostree_sysroot_deploy_one_tree: + * ostree_sysroot_deploy_tree: * @self: Sysroot * @osname: (allow-none): osname to use for merge deployment * @revision: Checksum to add * @origin: (allow-none): Origin to use for upgrades - * @add_kernel_argv: (allow-none): Append these arguments to kernel configuration * @provided_merge_deployment: (allow-none): Use this deployment for merge path + * @override_kernel_argv: (allow-none) (array zero-terminated=1) (element-type utf8): Use these as kernel arguments; if %NULL, inherit options from provided_merge_deployment * @out_new_deployment: (out): The new deployment path * @cancellable: Cancellable * @error: Error @@ -1064,15 +1066,15 @@ allocate_deployserial (OstreeSysroot *self, * way merge with @provided_merge_deployment for configuration. */ gboolean -ostree_sysroot_deploy_one_tree (OstreeSysroot *self, - const char *osname, - const char *revision, - GKeyFile *origin, - char **add_kernel_argv, - OstreeDeployment *provided_merge_deployment, - OstreeDeployment **out_new_deployment, - GCancellable *cancellable, - GError **error) +ostree_sysroot_deploy_tree (OstreeSysroot *self, + const char *osname, + const char *revision, + GKeyFile *origin, + OstreeDeployment *provided_merge_deployment, + char **override_kernel_argv, + OstreeDeployment **out_new_deployment, + GCancellable *cancellable, + GError **error) { gboolean ret = FALSE; gint new_deployserial; @@ -1160,30 +1162,17 @@ ostree_sysroot_deploy_one_tree (OstreeSysroot *self, goto out; } - /* We have inherited kernel arguments from the previous deployment; - * now, override/extend that with arguments provided by the command - * line. - * - * After this, install_deployment_kernel() will set the other boot + /* After this, install_deployment_kernel() will set the other boot * options and write it out to disk. */ - if (add_kernel_argv) + if (override_kernel_argv) { - char **strviter; - __attribute__((cleanup(_ostree_ordered_hash_cleanup))) OstreeOrderedHash *ohash = NULL; + __attribute__((cleanup(_ostree_kernel_args_cleanup))) OstreeKernelArgs *kargs = NULL; gs_free char *new_options = NULL; - ohash = _ostree_sysroot_parse_kernel_args (ostree_bootconfig_parser_get (bootconfig, "options")); - - for (strviter = add_kernel_argv; *strviter; strviter++) - { - char *karg = g_strdup (*strviter); - const char *val = _ostree_sysroot_split_keyeq (karg); - - _ostree_ordered_hash_replace_key_take (ohash, karg, val); - } - - new_options = _ostree_sysroot_kernel_arg_string_serialize (ohash); + kargs = _ostree_kernel_args_new (); + _ostree_kernel_args_append_argv (kargs, override_kernel_argv); + new_options = _ostree_kernel_args_to_string (kargs); ostree_bootconfig_parser_set (bootconfig, "options", new_options); } diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h index ce79fb8e..0857e4cc 100644 --- a/src/libostree/ostree-sysroot-private.h +++ b/src/libostree/ostree-sysroot-private.h @@ -21,7 +21,7 @@ #pragma once #include "ostree.h" -#include "ostree-ordered-hash.h" +#include "ostree-kernel-args.h" #include "ostree-bootloader.h" G_BEGIN_DECLS @@ -75,12 +75,6 @@ _ostree_sysroot_get_devino (GFile *path, char *_ostree_sysroot_join_lines (GPtrArray *lines); -char *_ostree_sysroot_split_keyeq (char *str); - -OstreeOrderedHash *_ostree_sysroot_parse_kernel_args (const char *options); - -char * _ostree_sysroot_kernel_arg_string_serialize (OstreeOrderedHash *ohash); - OstreeBootloader *_ostree_sysroot_query_bootloader (OstreeSysroot *sysroot); G_END_DECLS diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index f61324af..56811b88 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -884,9 +884,9 @@ _ostree_sysroot_join_lines (GPtrArray *lines) } static gboolean -parse_kernel_commandline (OstreeOrderedHash **out_args, - GCancellable *cancellable, - GError **error) +parse_kernel_commandline (OstreeKernelArgs **out_args, + GCancellable *cancellable, + GError **error) { gboolean ret = FALSE; gs_unref_object GFile *proc_cmdline = g_file_new_for_path ("/proc/cmdline"); @@ -897,8 +897,10 @@ parse_kernel_commandline (OstreeOrderedHash **out_args, error)) goto out; + g_strchomp (contents); + ret = TRUE; - *out_args = _ostree_sysroot_parse_kernel_args (contents);; + *out_args = _ostree_kernel_args_from_string (contents); out: return ret; } @@ -919,7 +921,7 @@ find_booted_deployment (OstreeSysroot *self, gs_unref_object OstreeSysroot *active_deployment_root = ostree_sysroot_new_default (); guint i; const char *bootlink_arg; - __attribute__((cleanup(_ostree_ordered_hash_cleanup))) OstreeOrderedHash *kernel_args = NULL; + __attribute__((cleanup(_ostree_kernel_args_cleanup))) OstreeKernelArgs *kernel_args = NULL; guint32 root_device; guint64 root_inode; @@ -930,7 +932,7 @@ find_booted_deployment (OstreeSysroot *self, if (!parse_kernel_commandline (&kernel_args, cancellable, error)) goto out; - bootlink_arg = g_hash_table_lookup (kernel_args->table, "ostree"); + bootlink_arg = _ostree_kernel_args_get_last_value (kernel_args, "ostree"); if (bootlink_arg) { for (i = 0; i < deployments->len; i++) @@ -969,88 +971,6 @@ find_booted_deployment (OstreeSysroot *self, return ret; } -OstreeOrderedHash * -_ostree_sysroot_parse_kernel_args (const char *options) -{ - OstreeOrderedHash *ret; - char **args; - char **iter; - - ret = _ostree_ordered_hash_new (); - - if (!options) - return ret; - - args = g_strsplit (options, " ", -1); - for (iter = args; *iter; iter++) - { - char *arg = *iter; - char *val; - - val = _ostree_sysroot_split_keyeq (arg); - - g_ptr_array_add (ret->order, arg); - g_hash_table_insert (ret->table, arg, val); - } - - return ret; -} - -/* - * Modify @arg which should be of the form key=value to make @arg just - * contain key. Return a pointer to the start of value. - */ -char * -_ostree_sysroot_split_keyeq (char *arg) -{ - char *eq; - - eq = strchr (arg, '='); - if (eq) - { - /* Note key/val are in one malloc block, - * so we don't free val... - */ - *eq = '\0'; - return eq+1; - } - else - { - /* ...and this allows us to insert a constant - * string. - */ - return ""; - } -} - -char * -_ostree_sysroot_kernel_arg_string_serialize (OstreeOrderedHash *ohash) -{ - guint i; - GString *buf = g_string_new (""); - gboolean first = TRUE; - - for (i = 0; i < ohash->order->len; i++) - { - const char *key = ohash->order->pdata[i]; - const char *val = g_hash_table_lookup (ohash->table, key); - - g_assert (val != NULL); - - if (first) - first = FALSE; - else - g_string_append_c (buf, ' '); - - if (*val) - g_string_append_printf (buf, "%s=%s", key, val); - else - g_string_append (buf, key); - } - - return g_string_free (buf, FALSE); -} - /** * ostree_sysroot_get_merge_deployment: * @self: Sysroot diff --git a/src/libostree/ostree-sysroot.h b/src/libostree/ostree-sysroot.h index 5bed1192..fbf3dffc 100644 --- a/src/libostree/ostree-sysroot.h +++ b/src/libostree/ostree-sysroot.h @@ -71,15 +71,15 @@ gboolean ostree_sysroot_write_deployments (OstreeSysroot *self, GCancellable *cancellable, GError **error); -gboolean ostree_sysroot_deploy_one_tree (OstreeSysroot *self, - const char *osname, - const char *revision, - GKeyFile *origin, - char **add_kernel_argv, - OstreeDeployment *provided_merge_deployment, - OstreeDeployment **out_new_deployment, - GCancellable *cancellable, - GError **error); +gboolean ostree_sysroot_deploy_tree (OstreeSysroot *self, + const char *osname, + const char *revision, + GKeyFile *origin, + OstreeDeployment *provided_merge_deployment, + char **override_kernel_argv, + OstreeDeployment **out_new_deployment, + GCancellable *cancellable, + GError **error); OstreeDeployment *ostree_sysroot_get_merge_deployment (OstreeSysroot *self, const char *osname); diff --git a/src/ostree/ot-admin-builtin-deploy.c b/src/ostree/ot-admin-builtin-deploy.c index 9d479249..6bcde910 100644 --- a/src/ostree/ot-admin-builtin-deploy.c +++ b/src/ostree/ot-admin-builtin-deploy.c @@ -27,11 +27,14 @@ #include "ostree.h" #include "otutil.h" +#include "../libostree/ostree-kernel-args.h" + #include <glib/gi18n.h> static gboolean opt_no_bootloader; static gboolean opt_retain; static char **opt_kernel_argv; +static char **opt_kernel_argv_append; static gboolean opt_kernel_proc_cmdline; static char *opt_osname; static char *opt_origin_path; @@ -42,7 +45,8 @@ static GOptionEntry options[] = { { "no-bootloader", 0, 0, G_OPTION_ARG_NONE, &opt_no_bootloader, "Don't update bootloader", NULL }, { "retain", 0, 0, G_OPTION_ARG_NONE, &opt_retain, "Do not delete previous deployment", NULL }, { "karg-proc-cmdline", 0, 0, G_OPTION_ARG_NONE, &opt_kernel_proc_cmdline, "Import current /proc/cmdline", NULL }, - { "karg", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_kernel_argv, "Set kernel argument, like --karg=root=/dev/sda1", NULL }, + { "karg", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_kernel_argv, "Set kernel argument, like root=/dev/sda1; this overrides any earlier argument with the same name", "KEY=VALUE" }, + { "karg-append", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_kernel_argv_append, "Append kernel argument; useful with e.g. console= that can be used multiple times", "KEY=VALUE" }, { NULL } }; @@ -58,7 +62,7 @@ ot_admin_builtin_deploy (int argc, char **argv, OstreeSysroot *sysroot, GCancell gs_unref_object OstreeDeployment *new_deployment = NULL; gs_unref_object OstreeDeployment *merge_deployment = NULL; gs_free char *revision = NULL; - gs_unref_ptrarray GPtrArray *kargs = NULL; + __attribute__((cleanup(_ostree_kernel_args_cleanup))) OstreeKernelArgs *kargs = NULL; context = g_option_context_new ("REFSPEC - Checkout revision REFSPEC as the new default deployment"); @@ -121,51 +125,56 @@ ot_admin_builtin_deploy (int argc, char **argv, OstreeSysroot *sysroot, GCancell goto out; } - kargs = g_ptr_array_new_with_free_func (g_free); + 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_kernel_proc_cmdline) { gs_unref_object GFile *proc_cmdline_path = g_file_new_for_path ("/proc/cmdline"); gs_free char *proc_cmdline = NULL; gsize proc_cmdline_len = 0; gs_strfreev char **proc_cmdline_args = NULL; - char **strviter; if (!g_file_load_contents (proc_cmdline_path, cancellable, &proc_cmdline, &proc_cmdline_len, NULL, error)) goto out; + g_strchomp (proc_cmdline); + proc_cmdline_args = g_strsplit (proc_cmdline, " ", -1); - for (strviter = proc_cmdline_args; strviter && *strviter; strviter++) - { - char *arg = *strviter; - g_strchomp (arg); - g_ptr_array_add (kargs, arg); - *strviter = NULL; /* transfer ownership */ - } + _ostree_kernel_args_replace_argv (kargs, proc_cmdline_args); + } + else if (merge_deployment) + { + OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (merge_deployment); + gs_strfreev char **previous_args = g_strsplit (ostree_bootconfig_parser_get (bootconfig, "options"), " ", -1); + + _ostree_kernel_args_replace_argv (kargs, previous_args); } if (opt_kernel_argv) { - char **strviter; - for (strviter = opt_kernel_argv; strviter && *strviter; strviter++) - { - const char *arg = *strviter; - char *val = g_strdup (arg); - g_strchomp (val); - g_ptr_array_add (kargs, val); - } + _ostree_kernel_args_replace_argv (kargs, opt_kernel_argv); } - g_ptr_array_add (kargs, NULL); + if (opt_kernel_argv_append) + { + _ostree_kernel_args_append_argv (kargs, opt_kernel_argv_append); + } - if (!ostree_sysroot_deploy_one_tree (sysroot, - opt_osname, revision, origin, - (char**)kargs->pdata, merge_deployment, - &new_deployment, - cancellable, error)) - goto out; + { + gs_strfreev char **kargs_strv = _ostree_kernel_args_to_strv (kargs); + + if (!ostree_sysroot_deploy_tree (sysroot, + opt_osname, revision, origin, + merge_deployment, kargs_strv, + &new_deployment, + cancellable, error)) + goto out; + } if (!ot_admin_complete_deploy_one (sysroot, opt_osname, new_deployment, merge_deployment, opt_retain, diff --git a/src/ostree/ot-admin-builtin-upgrade.c b/src/ostree/ot-admin-builtin-upgrade.c index 299c6a81..d222e9e0 100644 --- a/src/ostree/ot-admin-builtin-upgrade.c +++ b/src/ostree/ot-admin-builtin-upgrade.c @@ -147,12 +147,12 @@ ot_admin_builtin_upgrade (int argc, char **argv, OstreeSysroot *sysroot, GCancel goto out; } - if (!ostree_sysroot_deploy_one_tree (sysroot, - opt_osname, new_revision, origin, - NULL, - merge_deployment, - &new_deployment, - cancellable, error)) + if (!ostree_sysroot_deploy_tree (sysroot, + opt_osname, new_revision, origin, + merge_deployment, + NULL, + &new_deployment, + cancellable, error)) goto out; if (!ot_admin_complete_deploy_one (sysroot, opt_osname, |