diff --git a/Makefile-libostree.am b/Makefile-libostree.am index 3576b440..d9ee1f10 100644 --- a/Makefile-libostree.am +++ b/Makefile-libostree.am @@ -46,6 +46,7 @@ libostree_1_la_SOURCES = \ src/libostree/ostree-sysroot-private.h \ src/libostree/ostree-sysroot.c \ src/libostree/ostree-sysroot-cleanup.c \ + src/libostree/ostree-sysroot-deploy.c \ src/libostree/ostree-bootconfig-parser.c \ src/libostree/ostree-deployment.c \ src/libostree/ostree-bootloader.c \ @@ -53,6 +54,8 @@ libostree_1_la_SOURCES = \ src/libostree/ostree-bootloader-syslinux.c \ src/libostree/ostree-bootloader-uboot.h \ src/libostree/ostree-bootloader-uboot.c \ + src/libostree/ostree-ordered-hash.h \ + src/libostree/ostree-ordered-hash.c \ $(NULL) if USE_LIBARCHIVE libostree_1_la_SOURCES += src/libostree/ostree-libarchive-input-stream.h \ diff --git a/Makefile-ostree.am b/Makefile-ostree.am index df5c3a41..f2a3615e 100644 --- a/Makefile-ostree.am +++ b/Makefile-ostree.am @@ -59,13 +59,8 @@ ostree_SOURCES += \ src/ostree/ot-admin-builtin-status.c \ src/ostree/ot-admin-builtin-upgrade.c \ src/ostree/ot-admin-builtins.h \ - src/ostree/ot-admin-util.c \ src/ostree/ot-admin-functions.h \ src/ostree/ot-admin-functions.c \ - src/ostree/ot-admin-deploy.h \ - src/ostree/ot-admin-deploy.c \ - src/ostree/ot-ordered-hash.h \ - src/ostree/ot-ordered-hash.c \ $(NULL) ostree_bin_shared_cflags = $(AM_CFLAGS) -I$(srcdir)/src/libgsystem -I$(srcdir)/src/libotutil -I$(srcdir)/src/libostree -I$(srcdir)/src/ostree -DLOCALEDIR=\"$(datadir)/locale\" diff --git a/src/ostree/ot-ordered-hash.c b/src/libostree/ostree-ordered-hash.c similarity index 78% rename from src/ostree/ot-ordered-hash.c rename to src/libostree/ostree-ordered-hash.c index 02c9e434..ba13bf94 100644 --- a/src/ostree/ot-ordered-hash.c +++ b/src/libostree/ostree-ordered-hash.c @@ -20,21 +20,21 @@ #include "config.h" -#include "ot-ordered-hash.h" +#include "ostree-ordered-hash.h" #include "libgsystem.h" -OtOrderedHash * -ot_ordered_hash_new (void) +OstreeOrderedHash * +_ostree_ordered_hash_new (void) { - OtOrderedHash *ret; - ret = g_new0 (OtOrderedHash, 1); + 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 -ot_ordered_hash_free (OtOrderedHash *ohash) +_ostree_ordered_hash_free (OstreeOrderedHash *ohash) { if (!ohash) return; @@ -44,13 +44,13 @@ ot_ordered_hash_free (OtOrderedHash *ohash) } void -ot_ordered_hash_cleanup (void *loc) +_ostree_ordered_hash_cleanup (void *loc) { - ot_ordered_hash_free (*((OtOrderedHash**)loc)); + _ostree_ordered_hash_free (*((OstreeOrderedHash**)loc)); } void -ot_ordered_hash_replace_key_take (OtOrderedHash *ohash, +_ostree_ordered_hash_replace_key_take (OstreeOrderedHash *ohash, char *key, const char *value) { @@ -63,7 +63,7 @@ ot_ordered_hash_replace_key_take (OtOrderedHash *ohash, } void -ot_ordered_hash_replace_key (OtOrderedHash *ohash, +_ostree_ordered_hash_replace_key (OstreeOrderedHash *ohash, const char *key, const char *val) { @@ -79,5 +79,5 @@ ot_ordered_hash_replace_key (OtOrderedHash *ohash, valblock = g_string_free (buf, FALSE); valp = valblock + keylen + 1; - ot_ordered_hash_replace_key_take (ohash, valblock, valp); + _ostree_ordered_hash_replace_key_take (ohash, valblock, valp); } diff --git a/src/ostree/ot-ordered-hash.h b/src/libostree/ostree-ordered-hash.h similarity index 63% rename from src/ostree/ot-ordered-hash.h rename to src/libostree/ostree-ordered-hash.h index 1a3aa09b..1cfe8527 100644 --- a/src/ostree/ot-ordered-hash.h +++ b/src/libostree/ostree-ordered-hash.h @@ -27,17 +27,17 @@ G_BEGIN_DECLS typedef struct { GPtrArray *order; GHashTable *table; -} OtOrderedHash; +} OstreeOrderedHash; -OtOrderedHash *ot_ordered_hash_new (void); -void ot_ordered_hash_free (OtOrderedHash *ohash); -void ot_ordered_hash_cleanup (void *loc); -void ot_ordered_hash_replace_key_take (OtOrderedHash *ohash, - char *key, - const char *value); -void ot_ordered_hash_replace_key (OtOrderedHash *ohash, - const char *key, - const char *val); +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/ostree/ot-admin-deploy.c b/src/libostree/ostree-sysroot-deploy.c similarity index 92% rename from src/ostree/ot-admin-deploy.c rename to src/libostree/ostree-sysroot-deploy.c index 32d0d958..2b3e853a 100644 --- a/src/ostree/ot-admin-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -22,13 +22,10 @@ #include "config.h" -#include "ot-admin-functions.h" -#include "ot-admin-deploy.h" +#include "ostree-sysroot-private.h" #include "otutil.h" -#include "ostree-core.h" #include "libgsystem.h" - /** * copy_one_config_file: * @@ -197,7 +194,7 @@ merge_etc_changes (GFile *orig_etc, * /ostree/deploy/OS/deploy/${treecsum}.${deployserial}. */ static gboolean -checkout_deployment_tree (GFile *sysroot, +checkout_deployment_tree (OstreeSysroot *sysroot, OstreeRepo *repo, OstreeDeployment *deployment, GFile **out_deployment_path, @@ -222,7 +219,7 @@ checkout_deployment_tree (GFile *sysroot, if (!file_info) goto out; - osdeploy_path = ot_gfile_get_child_build_path (sysroot, "ostree", "deploy", + osdeploy_path = ot_gfile_get_child_build_path (sysroot->path, "ostree", "deploy", ostree_deployment_get_osname (deployment), "deploy", NULL); checkout_target_name = g_strdup_printf ("%s.%d", csum, ostree_deployment_get_deployserial (deployment)); @@ -246,7 +243,7 @@ checkout_deployment_tree (GFile *sysroot, } static gboolean -merge_configuration (OstreeSysroot *sysroot_obj, +merge_configuration (OstreeSysroot *sysroot, OstreeDeployment *previous_deployment, OstreeDeployment *deployment, GFile *deployment_path, @@ -266,7 +263,7 @@ merge_configuration (OstreeSysroot *sysroot_obj, gs_unref_object GFile *previous_path = NULL; OstreeBootconfigParser *previous_bootconfig; - previous_path = ostree_sysroot_get_deployment_directory (sysroot_obj, previous_deployment); + previous_path = ostree_sysroot_get_deployment_directory (sysroot, previous_deployment); source_etc_path = g_file_resolve_relative_path (previous_path, "etc"); source_etc_pristine_path = g_file_resolve_relative_path (previous_path, "usr/etc"); @@ -330,20 +327,17 @@ merge_configuration (OstreeSysroot *sysroot_obj, } static gboolean -write_origin_file (GFile *sysroot, +write_origin_file (OstreeSysroot *sysroot, OstreeDeployment *deployment, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; - gs_unref_object OstreeSysroot *sysroot_obj = NULL; GKeyFile *origin = ostree_deployment_get_origin (deployment); - sysroot_obj = ostree_sysroot_new (sysroot); - if (origin) { - gs_unref_object GFile *deployment_path = ostree_sysroot_get_deployment_directory (sysroot_obj, deployment); + gs_unref_object GFile *deployment_path = ostree_sysroot_get_deployment_directory (sysroot, deployment); gs_unref_object GFile *origin_path = ostree_sysroot_get_deployment_origin_path (deployment_path); gs_free char *contents = NULL; gsize len; @@ -852,7 +846,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(ot_ordered_hash_cleanup))) OtOrderedHash *ohash = NULL; + __attribute__((cleanup(_ostree_ordered_hash_cleanup))) OstreeOrderedHash *ohash = NULL; const char *val; OstreeBootconfigParser *bootconfig; gsize len; @@ -948,9 +942,9 @@ install_deployment_kernel (OstreeSysroot *sysroot, ostree_kernel_arg = g_strdup_printf ("/ostree/boot.%d/%s/%s/%d", new_bootversion, osname, bootcsum, ostree_deployment_get_bootserial (deployment)); - ohash = ot_admin_parse_kernel_args (val); - ot_ordered_hash_replace_key (ohash, "ostree", ostree_kernel_arg); - options_key = ot_admin_kernel_arg_string_serialize (ohash); + 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); ostree_bootconfig_parser_set (bootconfig, "options", options_key); if (!ostree_bootconfig_parser_write (ostree_deployment_get_bootconfig (deployment), bootconfpath, @@ -963,7 +957,7 @@ install_deployment_kernel (OstreeSysroot *sysroot, } static gboolean -swap_bootloader (GFile *sysroot, +swap_bootloader (OstreeSysroot *sysroot, int current_bootversion, int new_bootversion, GCancellable *cancellable, @@ -976,7 +970,7 @@ swap_bootloader (GFile *sysroot, g_assert ((current_bootversion == 0 && new_bootversion == 1) || (current_bootversion == 1 && new_bootversion == 0)); - boot_loader_link = g_file_resolve_relative_path (sysroot, "boot/loader"); + boot_loader_link = g_file_resolve_relative_path (sysroot->path, "boot/loader"); new_target = g_strdup_printf ("loader.%d", new_bootversion); if (!ot_gfile_atomic_symlink_swap (boot_loader_link, new_target, @@ -989,17 +983,16 @@ swap_bootloader (GFile *sysroot, } gboolean -ot_admin_write_deployments (GFile *sysroot, - int current_bootversion, - int new_bootversion, - GPtrArray *new_deployments, - GCancellable *cancellable, - GError **error) +ostree_sysroot_write_deployments (OstreeSysroot *sysroot, + int current_bootversion, + int new_bootversion, + GPtrArray *new_deployments, + GCancellable *cancellable, + GError **error) { gboolean ret = FALSE; guint i; - gs_unref_object OstreeSysroot *sysroot_obj = ostree_sysroot_new (sysroot); - gs_unref_object OstreeBootloader *bootloader = ostree_sysroot_query_bootloader (sysroot_obj); + gs_unref_object OstreeBootloader *bootloader = ostree_sysroot_query_bootloader (sysroot); if (bootloader) g_print ("Detected bootloader: %s\n", ostree_bootloader_get_name (bootloader)); @@ -1014,7 +1007,7 @@ ot_admin_write_deployments (GFile *sysroot, goto out; } - if (!swap_bootlinks (sysroot_obj, current_bootversion, + if (!swap_bootlinks (sysroot, current_bootversion, new_deployments, cancellable, error)) { @@ -1027,7 +1020,7 @@ ot_admin_write_deployments (GFile *sysroot, for (i = 0; i < new_deployments->len; i++) { OstreeDeployment *deployment = new_deployments->pdata[i]; - if (!install_deployment_kernel (sysroot_obj, new_bootversion, + if (!install_deployment_kernel (sysroot, new_bootversion, deployment, new_deployments->len, cancellable, error)) { @@ -1037,7 +1030,7 @@ ot_admin_write_deployments (GFile *sysroot, } /* Swap bootlinks for *new* version */ - if (!swap_bootlinks (sysroot_obj, new_bootversion, new_deployments, + if (!swap_bootlinks (sysroot, new_bootversion, new_deployments, cancellable, error)) { g_prefix_error (error, "Generating new bootlinks: "); @@ -1071,25 +1064,24 @@ ot_admin_write_deployments (GFile *sysroot, } gboolean -ot_admin_deploy (GFile *sysroot, - int current_bootversion, - GPtrArray *current_deployments, - const char *osname, - const char *revision, - GKeyFile *origin, - char **add_kernel_argv, - gboolean retain, - OstreeDeployment *booted_deployment, - OstreeDeployment *provided_merge_deployment, - OstreeDeployment **out_new_deployment, - int *out_new_bootversion, - GPtrArray **out_new_deployments, - GCancellable *cancellable, - GError **error) +ostree_sysroot_deploy (OstreeSysroot *sysroot, + int current_bootversion, + GPtrArray *current_deployments, + const char *osname, + const char *revision, + GKeyFile *origin, + char **add_kernel_argv, + gboolean retain, + OstreeDeployment *booted_deployment, + OstreeDeployment *provided_merge_deployment, + OstreeDeployment **out_new_deployment, + int *out_new_bootversion, + GPtrArray **out_new_deployments, + GCancellable *cancellable, + GError **error) { gboolean ret = FALSE; OstreeDeployment *new_deployment; - gs_unref_object OstreeSysroot *sysroot_obj = NULL; gs_unref_object OstreeDeployment *merge_deployment = NULL; gs_unref_object OstreeRepo *repo = NULL; gs_unref_object GFile *commit_root = NULL; @@ -1101,9 +1093,7 @@ ot_admin_deploy (GFile *sysroot, gs_unref_ptrarray GPtrArray *new_deployments = NULL; int new_bootversion; - sysroot_obj = ostree_sysroot_new (sysroot); - - if (!ostree_sysroot_get_repo (sysroot_obj, &repo, cancellable, error)) + if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error)) goto out; /* Here we perform cleanup of any leftover data from previous @@ -1113,7 +1103,7 @@ ot_admin_deploy (GFile *sysroot, * TODO: Add /ostree/transaction file, and only do this cleanup if * we find it. */ - if (!ostree_sysroot_cleanup (sysroot_obj, cancellable, error)) + if (!ostree_sysroot_cleanup (sysroot, cancellable, error)) { g_prefix_error (error, "Performing initial cleanup: "); goto out; @@ -1144,8 +1134,8 @@ ot_admin_deploy (GFile *sysroot, if (provided_merge_deployment != NULL) merge_deployment = g_object_ref (provided_merge_deployment); else - merge_deployment = ot_admin_get_merge_deployment (current_deployments, osname, - booted_deployment); + merge_deployment = ostree_sysroot_get_merge_deployment (current_deployments, osname, + booted_deployment); compute_new_deployment_list (current_bootversion, current_deployments, osname, @@ -1179,7 +1169,7 @@ ot_admin_deploy (GFile *sysroot, bootconfig = ostree_bootconfig_parser_new (); ostree_deployment_set_bootconfig (new_deployment, bootconfig); - if (!merge_configuration (sysroot_obj, merge_deployment, new_deployment, + if (!merge_configuration (sysroot, merge_deployment, new_deployment, new_deployment_path, cancellable, error)) { @@ -1197,25 +1187,25 @@ ot_admin_deploy (GFile *sysroot, if (add_kernel_argv) { char **strviter; - __attribute__((cleanup(ot_ordered_hash_cleanup))) OtOrderedHash *ohash = NULL; + __attribute__((cleanup(_ostree_ordered_hash_cleanup))) OstreeOrderedHash *ohash = NULL; gs_free char *new_options = NULL; - ohash = ot_admin_parse_kernel_args (ostree_bootconfig_parser_get (bootconfig, "options")); + 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 = ot_admin_util_split_keyeq (karg); + const char *val = _ostree_sysroot_split_keyeq (karg); - ot_ordered_hash_replace_key_take (ohash, karg, val); + _ostree_ordered_hash_replace_key_take (ohash, karg, val); } - new_options = ot_admin_kernel_arg_string_serialize (ohash); + new_options = _ostree_sysroot_kernel_arg_string_serialize (ohash); ostree_bootconfig_parser_set (bootconfig, "options", new_options); } - if (!ot_admin_write_deployments (sysroot, current_bootversion, new_bootversion, - new_deployments, cancellable, error)) + if (!ostree_sysroot_write_deployments (sysroot, current_bootversion, new_bootversion, + new_deployments, cancellable, error)) goto out; g_print ("Transaction complete, performing cleanup\n"); @@ -1226,7 +1216,7 @@ ot_admin_deploy (GFile *sysroot, * done from the host. */ { - gs_unref_object GFile *osdir = ot_gfile_resolve_path_printf (sysroot, "ostree/deploy/%s", ostree_deployment_get_osname (new_deployment)); + gs_unref_object GFile *osdir = ot_gfile_resolve_path_printf (sysroot->path, "ostree/deploy/%s", ostree_deployment_get_osname (new_deployment)); gs_unref_object GFile *os_current_path = g_file_get_child (osdir, "current"); gs_free char *target = g_file_get_relative_path (osdir, new_deployment_path); g_assert (target != NULL); @@ -1237,7 +1227,7 @@ ot_admin_deploy (GFile *sysroot, /* And finally, cleanup of any leftover data. */ - if (!ostree_sysroot_cleanup (sysroot_obj, cancellable, error)) + if (!ostree_sysroot_cleanup (sysroot, cancellable, error)) { g_prefix_error (error, "Performing final cleanup: "); goto out; diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h index 7da65072..f8b6d10c 100644 --- a/src/libostree/ostree-sysroot-private.h +++ b/src/libostree/ostree-sysroot-private.h @@ -21,6 +21,7 @@ #pragma once #include "ostree.h" +#include "ostree-ordered-hash.h" G_BEGIN_DECLS @@ -53,5 +54,11 @@ _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); + G_END_DECLS diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index 71774deb..464a42d7 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -839,3 +839,243 @@ _ostree_sysroot_join_lines (GPtrArray *lines) } return g_string_free (buf, FALSE); } + +static gboolean +parse_kernel_commandline (OstreeOrderedHash **out_args, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = FALSE; + gs_unref_object GFile *proc_cmdline = g_file_new_for_path ("/proc/cmdline"); + gs_free char *contents = NULL; + gsize len; + + if (!g_file_load_contents (proc_cmdline, cancellable, &contents, &len, NULL, + error)) + goto out; + + ret = TRUE; + *out_args = _ostree_sysroot_parse_kernel_args (contents);; + out: + return ret; +} + +/** + * ostree_sysroot_find_booted_deployment: + * @target_sysroot: Root directory + * @deployments: (element-type OstreeDeployment): Loaded deployments + * @out_deployment: (out): The currently booted deployment + * @cancellable: + * @error: + * + * If the system is currently booted into a deployment in + * @deployments, set @out_deployment. Note that if @target_sysroot is + * not equal to "/", @out_deployment will always be set to %NULL. + */ +gboolean +ostree_sysroot_find_booted_deployment (OstreeSysroot *self, + GPtrArray *deployments, + OstreeDeployment **out_deployment, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = FALSE; + gs_unref_object GFile *active_root = g_file_new_for_path ("/"); + gs_unref_object OstreeSysroot *active_deployment_root = ostree_sysroot_new_default (); + gs_unref_object OstreeDeployment *ret_deployment = NULL; + + if (g_file_equal (active_root, self->path)) + { + guint i; + const char *bootlink_arg; + __attribute__((cleanup(_ostree_ordered_hash_cleanup))) OstreeOrderedHash *kernel_args = NULL; + guint32 root_device; + guint64 root_inode; + + if (!_ostree_sysroot_get_devino (active_root, &root_device, &root_inode, + cancellable, error)) + goto out; + + if (!parse_kernel_commandline (&kernel_args, cancellable, error)) + goto out; + + bootlink_arg = g_hash_table_lookup (kernel_args->table, "ostree"); + if (bootlink_arg) + { + for (i = 0; i < deployments->len; i++) + { + OstreeDeployment *deployment = deployments->pdata[i]; + gs_unref_object GFile *deployment_path = ostree_sysroot_get_deployment_directory (active_deployment_root, deployment); + guint32 device; + guint64 inode; + + if (!_ostree_sysroot_get_devino (deployment_path, &device, &inode, + cancellable, error)) + goto out; + + if (device == root_device && inode == root_inode) + { + ret_deployment = g_object_ref (deployment); + break; + } + } + if (ret_deployment == NULL) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Unexpected state: ostree= kernel argument found, but / is not a deployment root"); + goto out; + } + } + else + { + /* Not an ostree system */ + } + } + + ret = TRUE; + ot_transfer_out_value (out_deployment, &ret_deployment); + out: + return ret; +} + +gboolean +ostree_sysroot_require_deployment_or_osname (OstreeSysroot *sysroot, + GPtrArray *deployments, + const char *osname, + OstreeDeployment **out_deployment, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = FALSE; + gs_unref_object OstreeDeployment *ret_deployment = NULL; + + if (!ostree_sysroot_find_booted_deployment (sysroot, deployments, &ret_deployment, + cancellable, error)) + goto out; + + if (ret_deployment == NULL && osname == NULL) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Not currently booted into an OSTree system and no --os= argument given"); + goto out; + } + + ret = TRUE; + ot_transfer_out_value (out_deployment, &ret_deployment); + out: + 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); +} + +OstreeDeployment * +ostree_sysroot_get_merge_deployment (GPtrArray *deployments, + const char *osname, + OstreeDeployment *booted_deployment) +{ + g_return_val_if_fail (osname != NULL || booted_deployment != NULL, NULL); + + if (osname == NULL) + osname = ostree_deployment_get_osname (booted_deployment); + + if (booted_deployment && + g_strcmp0 (ostree_deployment_get_osname (booted_deployment), osname) == 0) + { + return g_object_ref (booted_deployment); + } + else + { + guint i; + for (i = 0; i < deployments->len; i++) + { + OstreeDeployment *deployment = deployments->pdata[i]; + + if (strcmp (ostree_deployment_get_osname (deployment), osname) != 0) + continue; + + return g_object_ref (deployment); + } + } + return NULL; +} + diff --git a/src/libostree/ostree-sysroot.h b/src/libostree/ostree-sysroot.h index 5df0ae70..2227a638 100644 --- a/src/libostree/ostree-sysroot.h +++ b/src/libostree/ostree-sysroot.h @@ -73,5 +73,46 @@ gboolean ostree_sysroot_get_repo (OstreeSysroot *self, OstreeBootloader *ostree_sysroot_query_bootloader (OstreeSysroot *sysroot); +gboolean ostree_sysroot_find_booted_deployment (OstreeSysroot *sysroot, + GPtrArray *deployments, + OstreeDeployment **out_deployment, + GCancellable *cancellable, + GError **error); + +gboolean ostree_sysroot_require_deployment_or_osname (OstreeSysroot *sysroot, + GPtrArray *deployment_list, + const char *osname, + OstreeDeployment **out_deployment, + GCancellable *cancellable, + GError **error); + +gboolean ostree_sysroot_write_deployments (OstreeSysroot *sysroot, + int current_bootversion, + int new_bootversion, + GPtrArray *new_deployments, + GCancellable *cancellable, + GError **error); + +gboolean ostree_sysroot_deploy (OstreeSysroot *sysroot, + int current_bootversion, + GPtrArray *current_deployments, + const char *osname, + const char *revision, + GKeyFile *origin, + char **add_kernel_argv, + gboolean retain, + OstreeDeployment *booted_deployment, + OstreeDeployment *merge_deployment, + OstreeDeployment **out_new_deployment, + int *out_new_bootversion, + GPtrArray **out_new_deployments, + GCancellable *cancellable, + GError **error); + + +OstreeDeployment *ostree_sysroot_get_merge_deployment (GPtrArray *deployment_list, + const char *osname, + OstreeDeployment *booted_deployment); + G_END_DECLS diff --git a/src/ostree/ot-admin-builtin-deploy.c b/src/ostree/ot-admin-builtin-deploy.c index 883f77af..6e5cc601 100644 --- a/src/ostree/ot-admin-builtin-deploy.c +++ b/src/ostree/ot-admin-builtin-deploy.c @@ -24,8 +24,6 @@ #include "ot-admin-builtins.h" #include "ot-admin-functions.h" -#include "ot-admin-deploy.h" -#include "ot-ordered-hash.h" #include "ostree.h" #include "otutil.h" @@ -90,10 +88,10 @@ ot_admin_builtin_deploy (int argc, char **argv, OstreeSysroot *sysroot, GCancell /* Find the currently booted deployment, if any; we will ensure it * is present in the new deployment list. */ - if (!ot_admin_require_deployment_or_osname (ostree_sysroot_get_path (sysroot), current_deployments, - opt_osname, - &booted_deployment, - cancellable, error)) + if (!ostree_sysroot_require_deployment_or_osname (sysroot, current_deployments, + opt_osname, + &booted_deployment, + cancellable, error)) { g_prefix_error (error, "Looking for booted deployment: "); goto out; @@ -114,12 +112,12 @@ ot_admin_builtin_deploy (int argc, char **argv, OstreeSysroot *sysroot, GCancell if (!ostree_repo_resolve_rev (repo, refspec, FALSE, &revision, error)) goto out; - if (!ot_admin_deploy (ostree_sysroot_get_path (sysroot), current_bootversion, current_deployments, - opt_osname, revision, origin, - opt_kernel_argv, opt_retain, - booted_deployment, NULL, - &new_deployment, &new_bootversion, &new_deployments, - cancellable, error)) + if (!ostree_sysroot_deploy (sysroot, current_bootversion, current_deployments, + opt_osname, revision, origin, + opt_kernel_argv, opt_retain, + booted_deployment, NULL, + &new_deployment, &new_bootversion, &new_deployments, + cancellable, error)) goto out; ret = TRUE; diff --git a/src/ostree/ot-admin-builtin-diff.c b/src/ostree/ot-admin-builtin-diff.c index 802fb177..88e3717e 100644 --- a/src/ostree/ot-admin-builtin-diff.c +++ b/src/ostree/ot-admin-builtin-diff.c @@ -68,14 +68,14 @@ ot_admin_builtin_diff (int argc, char **argv, OstreeSysroot *sysroot, GCancellab goto out; } - if (!ot_admin_require_deployment_or_osname (ostree_sysroot_get_path (sysroot), deployments, - opt_osname, &deployment, - cancellable, error)) + if (!ostree_sysroot_require_deployment_or_osname (sysroot, deployments, + opt_osname, &deployment, + cancellable, error)) goto out; if (deployment != NULL) opt_osname = (char*)ostree_deployment_get_osname (deployment); if (deployment == NULL) - deployment = ot_admin_get_merge_deployment (deployments, opt_osname, deployment); + deployment = ostree_sysroot_get_merge_deployment (deployments, opt_osname, deployment); if (deployment == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, diff --git a/src/ostree/ot-admin-builtin-status.c b/src/ostree/ot-admin-builtin-status.c index cdddf114..c561eaf0 100644 --- a/src/ostree/ot-admin-builtin-status.c +++ b/src/ostree/ot-admin-builtin-status.c @@ -57,9 +57,9 @@ ot_admin_builtin_status (int argc, char **argv, OstreeSysroot *sysroot, GCancell goto out; } - if (!ot_admin_find_booted_deployment (ostree_sysroot_get_path (sysroot), deployments, - &booted_deployment, - cancellable, error)) + if (!ostree_sysroot_find_booted_deployment (sysroot, deployments, + &booted_deployment, + cancellable, error)) goto out; if (deployments->len == 0) diff --git a/src/ostree/ot-admin-builtin-undeploy.c b/src/ostree/ot-admin-builtin-undeploy.c index e1535a52..1de2a6c2 100644 --- a/src/ostree/ot-admin-builtin-undeploy.c +++ b/src/ostree/ot-admin-builtin-undeploy.c @@ -24,8 +24,6 @@ #include "ot-admin-builtins.h" #include "ot-admin-functions.h" -#include "ot-admin-deploy.h" -#include "ot-ordered-hash.h" #include "ostree.h" #include "otutil.h" @@ -68,8 +66,8 @@ ot_admin_builtin_undeploy (int argc, char **argv, OstreeSysroot *sysroot, GCance goto out; } - if (!ot_admin_find_booted_deployment (ostree_sysroot_get_path (sysroot), current_deployments, &booted_deployment, - cancellable, error)) + if (!ostree_sysroot_find_booted_deployment (sysroot, current_deployments, &booted_deployment, + cancellable, error)) goto out; if (deploy_index < 0) @@ -95,9 +93,9 @@ ot_admin_builtin_undeploy (int argc, char **argv, OstreeSysroot *sysroot, GCance g_ptr_array_remove_index (current_deployments, deploy_index); - if (!ot_admin_write_deployments (ostree_sysroot_get_path (sysroot), current_bootversion, - current_bootversion ? 0 : 1, current_deployments, - cancellable, error)) + if (!ostree_sysroot_write_deployments (sysroot, current_bootversion, + current_bootversion ? 0 : 1, current_deployments, + cancellable, error)) goto out; g_print ("Deleted deployment %s.%d\n", ostree_deployment_get_csum (target_deployment), diff --git a/src/ostree/ot-admin-builtin-upgrade.c b/src/ostree/ot-admin-builtin-upgrade.c index 063703d4..70204006 100644 --- a/src/ostree/ot-admin-builtin-upgrade.c +++ b/src/ostree/ot-admin-builtin-upgrade.c @@ -24,7 +24,6 @@ #include "ot-admin-builtins.h" #include "ot-admin-functions.h" -#include "ot-admin-deploy.h" #include "ostree.h" #include "otutil.h" #include "libgsystem.h" @@ -78,15 +77,15 @@ ot_admin_builtin_upgrade (int argc, char **argv, OstreeSysroot *sysroot, GCancel goto out; } - if (!ot_admin_require_deployment_or_osname (ostree_sysroot_get_path (sysroot), current_deployments, - opt_osname, - &booted_deployment, - cancellable, error)) + if (!ostree_sysroot_require_deployment_or_osname (sysroot, current_deployments, + opt_osname, + &booted_deployment, + cancellable, error)) goto out; if (!opt_osname) opt_osname = (char*)ostree_deployment_get_osname (booted_deployment); - merge_deployment = ot_admin_get_merge_deployment (current_deployments, opt_osname, - booted_deployment); + merge_deployment = ostree_sysroot_get_merge_deployment (current_deployments, opt_osname, + booted_deployment); deployment_path = ostree_sysroot_get_deployment_directory (sysroot, merge_deployment); deployment_origin_path = ostree_sysroot_get_deployment_origin_path (deployment_path); @@ -135,13 +134,13 @@ ot_admin_builtin_upgrade (int argc, char **argv, OstreeSysroot *sysroot, GCancel else { gs_unref_object GFile *real_sysroot = g_file_new_for_path ("/"); - if (!ot_admin_deploy (ostree_sysroot_get_path (sysroot), - current_bootversion, current_deployments, - opt_osname, new_revision, origin, - NULL, FALSE, - booted_deployment, merge_deployment, - &new_deployment, &new_bootversion, &new_deployments, - cancellable, error)) + if (!ostree_sysroot_deploy (sysroot, + current_bootversion, current_deployments, + opt_osname, new_revision, origin, + NULL, FALSE, + booted_deployment, merge_deployment, + &new_deployment, &new_bootversion, &new_deployments, + cancellable, error)) goto out; if (opt_reboot && g_file_equal (ostree_sysroot_get_path (sysroot), real_sysroot)) diff --git a/src/ostree/ot-admin-deploy.h b/src/ostree/ot-admin-deploy.h deleted file mode 100644 index 6652201d..00000000 --- a/src/ostree/ot-admin-deploy.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2012 Colin Walters - * - * 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. - * - * Author: Colin Walters - */ - -#pragma once - -#include -#include -#include "ot-ordered-hash.h" - -G_BEGIN_DECLS - -gboolean ot_admin_write_deployments (GFile *sysroot, - int current_bootversion, - int new_bootversion, - GPtrArray *new_deployments, - GCancellable *cancellable, - GError **error); - -gboolean ot_admin_deploy (GFile *sysroot, - int current_bootversion, - GPtrArray *current_deployments, - const char *osname, - const char *revision, - GKeyFile *origin, - char **add_kernel_argv, - gboolean retain, - OstreeDeployment *booted_deployment, - OstreeDeployment *merge_deployment, - OstreeDeployment **out_new_deployment, - int *out_new_bootversion, - GPtrArray **out_new_deployments, - GCancellable *cancellable, - GError **error); - -G_END_DECLS - diff --git a/src/ostree/ot-admin-functions.c b/src/ostree/ot-admin-functions.c index f497fcbe..c72c15b5 100644 --- a/src/ostree/ot-admin-functions.c +++ b/src/ostree/ot-admin-functions.c @@ -27,240 +27,6 @@ #include "ostree.h" #include "libgsystem.h" -OtOrderedHash * -ot_admin_parse_kernel_args (const char *options) -{ - OtOrderedHash *ret; - char **args; - char **iter; - - ret = ot_ordered_hash_new (); - - if (!options) - return ret; - - args = g_strsplit (options, " ", -1); - for (iter = args; *iter; iter++) - { - char *arg = *iter; - char *val; - - val = ot_admin_util_split_keyeq (arg); - - g_ptr_array_add (ret->order, arg); - g_hash_table_insert (ret->table, arg, val); - } - - return ret; -} - -char * -ot_admin_kernel_arg_string_serialize (OtOrderedHash *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); -} - -gboolean -ot_admin_check_os (GFile *sysroot, - const char *osname, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - gs_unref_object GFile *osdir = NULL; - - osdir = ot_gfile_resolve_path_printf (sysroot, "ostree/deploy/%s/var", osname); - if (!g_file_query_exists (osdir, NULL)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "No such OS '%s', use os-init to create it", osname); - goto out; - } - - ret = TRUE; - out: - return ret; -} - -static gboolean -parse_kernel_commandline (OtOrderedHash **out_args, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - gs_unref_object GFile *proc_cmdline = g_file_new_for_path ("/proc/cmdline"); - gs_free char *contents = NULL; - gsize len; - - if (!g_file_load_contents (proc_cmdline, cancellable, &contents, &len, NULL, - error)) - goto out; - - ret = TRUE; - *out_args = ot_admin_parse_kernel_args (contents);; - out: - return ret; -} - -/** - * ot_admin_find_booted_deployment: - * @target_sysroot: Root directory - * @deployments: (element-type OstreeDeployment): Loaded deployments - * @out_deployment: (out): The currently booted deployment - * @cancellable: - * @error: - * - * If the system is currently booted into a deployment in - * @deployments, set @out_deployment. Note that if @target_sysroot is - * not equal to "/", @out_deployment will always be set to %NULL. - */ -gboolean -ot_admin_find_booted_deployment (GFile *target_sysroot, - GPtrArray *deployments, - OstreeDeployment **out_deployment, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - gs_unref_object GFile *active_root = g_file_new_for_path ("/"); - gs_unref_object OstreeSysroot *active_deployment_root = ostree_sysroot_new_default (); - gs_unref_object OstreeDeployment *ret_deployment = NULL; - - if (g_file_equal (active_root, target_sysroot)) - { - guint i; - const char *bootlink_arg; - __attribute__((cleanup(ot_ordered_hash_cleanup))) OtOrderedHash *kernel_args = NULL; - guint32 root_device; - guint64 root_inode; - - if (!ot_admin_util_get_devino (active_root, &root_device, &root_inode, - cancellable, error)) - goto out; - - if (!parse_kernel_commandline (&kernel_args, cancellable, error)) - goto out; - - bootlink_arg = g_hash_table_lookup (kernel_args->table, "ostree"); - if (bootlink_arg) - { - for (i = 0; i < deployments->len; i++) - { - OstreeDeployment *deployment = deployments->pdata[i]; - gs_unref_object GFile *deployment_path = ostree_sysroot_get_deployment_directory (active_deployment_root, deployment); - guint32 device; - guint64 inode; - - if (!ot_admin_util_get_devino (deployment_path, &device, &inode, - cancellable, error)) - goto out; - - if (device == root_device && inode == root_inode) - { - ret_deployment = g_object_ref (deployment); - break; - } - } - if (ret_deployment == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Unexpected state: ostree= kernel argument found, but / is not a deployment root"); - goto out; - } - } - else - { - /* Not an ostree system */ - } - } - - ret = TRUE; - ot_transfer_out_value (out_deployment, &ret_deployment); - out: - return ret; -} - -gboolean -ot_admin_require_deployment_or_osname (GFile *sysroot, - GPtrArray *deployments, - const char *osname, - OstreeDeployment **out_deployment, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - gs_unref_object OstreeDeployment *ret_deployment = NULL; - - if (!ot_admin_find_booted_deployment (sysroot, deployments, &ret_deployment, - cancellable, error)) - goto out; - - if (ret_deployment == NULL && osname == NULL) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Not currently booted into an OSTree system and no --os= argument given"); - goto out; - } - - ret = TRUE; - ot_transfer_out_value (out_deployment, &ret_deployment); - out: - return ret; -} - -OstreeDeployment * -ot_admin_get_merge_deployment (GPtrArray *deployments, - const char *osname, - OstreeDeployment *booted_deployment) -{ - g_return_val_if_fail (osname != NULL || booted_deployment != NULL, NULL); - - if (osname == NULL) - osname = ostree_deployment_get_osname (booted_deployment); - - if (booted_deployment && - g_strcmp0 (ostree_deployment_get_osname (booted_deployment), osname) == 0) - { - return g_object_ref (booted_deployment); - } - else - { - guint i; - for (i = 0; i < deployments->len; i++) - { - OstreeDeployment *deployment = deployments->pdata[i]; - - if (strcmp (ostree_deployment_get_osname (deployment), osname) != 0) - continue; - - return g_object_ref (deployment); - } - } - return NULL; -} - GKeyFile * ot_origin_new_from_refspec (const char *refspec) { diff --git a/src/ostree/ot-admin-functions.h b/src/ostree/ot-admin-functions.h index 4b7a6a68..189974f6 100644 --- a/src/ostree/ot-admin-functions.h +++ b/src/ostree/ot-admin-functions.h @@ -24,56 +24,9 @@ #include #include -#include "ot-ordered-hash.h" G_BEGIN_DECLS -char *ot_admin_util_split_keyeq (char *str); - -gboolean ot_admin_util_get_devino (GFile *path, - guint32 *out_device, - guint64 *out_inode, - GCancellable *cancellable, - GError **error); - -gboolean ot_admin_ensure_initialized (GFile *ostree_dir, - GCancellable *cancellable, - GError **error); - -gboolean ot_admin_check_os (GFile *sysroot, - const char *osname, - GCancellable *cancellable, - GError **error); - -OtOrderedHash *ot_admin_parse_kernel_args (const char *options); -char * ot_admin_kernel_arg_string_serialize (OtOrderedHash *ohash); - -gboolean ot_admin_find_booted_deployment (GFile *sysroot, - GPtrArray *deployments, - OstreeDeployment **out_deployment, - GCancellable *cancellable, - GError **error); - -gboolean ot_admin_require_booted_deployment (GFile *sysroot, - OstreeDeployment **out_deployment, - GCancellable *cancellable, - GError **error); - -gboolean ot_admin_require_deployment_or_osname (GFile *sysroot, - GPtrArray *deployment_list, - const char *osname, - OstreeDeployment **out_deployment, - GCancellable *cancellable, - GError **error); - -OstreeDeployment *ot_admin_get_merge_deployment (GPtrArray *deployment_list, - const char *osname, - OstreeDeployment *booted_deployment); - -gboolean ot_admin_get_default_ostree_dir (GFile **out_ostree_dir, - GCancellable *cancellable, - GError **error); - GKeyFile *ot_origin_new_from_refspec (const char *refspec); G_END_DECLS diff --git a/src/ostree/ot-admin-util.c b/src/ostree/ot-admin-util.c deleted file mode 100644 index 5e82261b..00000000 --- a/src/ostree/ot-admin-util.c +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2012 Colin Walters - * - * 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. - * - * Author: Colin Walters - */ - -#include "config.h" - -#include "ot-admin-functions.h" -#include "otutil.h" -#include "ostree-core.h" -#include "libgsystem.h" - -/* - * 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 * -ot_admin_util_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 ""; - } -} - -gboolean -ot_admin_util_get_devino (GFile *path, - guint32 *out_device, - guint64 *out_inode, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - gs_unref_object GFileInfo *finfo = g_file_query_info (path, "unix::device,unix::inode", - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - cancellable, error); - - if (!finfo) - goto out; - - ret = TRUE; - *out_device = g_file_info_get_attribute_uint32 (finfo, "unix::device"); - *out_inode = g_file_info_get_attribute_uint64 (finfo, "unix::inode"); - out: - return ret; -} -