diff --git a/src/app/rpmostree-builtin-upgrade.cxx b/src/app/rpmostree-builtin-upgrade.cxx index d4a876e6..437cdd85 100644 --- a/src/app/rpmostree-builtin-upgrade.cxx +++ b/src/app/rpmostree-builtin-upgrade.cxx @@ -28,7 +28,6 @@ #include "rpmostree-libbuiltin.h" #include "rpmostree-rpm-util.h" #include "rpmostree-dbus-helpers.h" -#include "rpmostreed-transaction-types.h" #include @@ -60,41 +59,10 @@ static GOptionEntry option_entries[] = { { "unchanged-exit-77", 0, 0, G_OPTION_ARG_NONE, &opt_unchanged_exit_77, "If no new deployment made, exit 77", NULL }, { "trigger-automatic-update-policy", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &opt_automatic, "For automated use only; triggered by automatic timer", NULL }, { "lock-finalization", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &opt_lock_finalization, "Prevent automatic deployment finalization on shutdown", NULL }, - { "bypass-driver", 0, 0, G_OPTION_ARG_NONE, &opt_bypass_driver, "Force an upgrade even if an updates driver is registered.", NULL}, + { "bypass-driver", 0, 0, G_OPTION_ARG_NONE, &opt_bypass_driver, "Force an upgrade even if an updates driver is registered", NULL}, { NULL } }; -/* Get the `Documentation` property `update_driver_sd_unit`. Documentation is returned - * as a string array GVariant in `unit_doc_array`. */ -static gboolean -get_update_driver_doc (GDBusConnection *connection, - const char *update_driver_sd_unit, - GVariant **unit_doc_array, - GCancellable *cancellable, - GError **error) -{ - const char *update_driver_objpath = NULL; - if (!get_sd_unit_objpath (connection, update_driver_sd_unit, &update_driver_objpath, - cancellable, error)) - return FALSE; - - /* Look up `Documentation` property of update driver's systemd unit. */ - g_autoptr(GDBusProxy) update_driver_unit_obj_proxy = - g_dbus_proxy_new_sync (connection, G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, - "org.freedesktop.systemd1", update_driver_objpath, - "org.freedesktop.systemd1.Unit", cancellable, error); - if (!update_driver_unit_obj_proxy) - return FALSE; - - *unit_doc_array = - g_dbus_proxy_get_cached_property (update_driver_unit_obj_proxy, "Documentation"); - if (!*unit_doc_array) - return glnx_throw (error, "Documentation property not found in proxy's cache (%s)", - update_driver_objpath); - - return TRUE; -} - gboolean rpmostree_builtin_upgrade (int argc, char **argv, @@ -165,56 +133,8 @@ rpmostree_builtin_upgrade (int argc, } if (!opt_bypass_driver) - { - g_autofree char *update_driver_sd_unit = NULL; - g_autofree char *update_driver_name = NULL; - if (!get_driver_info (&update_driver_name, &update_driver_sd_unit, error)) - return FALSE; - - /* Notify user that an updates driver is registered and upgrades should be - * done through the driver. */ - if (update_driver_sd_unit && update_driver_name) - { - g_autoptr(GString) error_msg = g_string_new(NULL); - g_string_printf (error_msg, "Updates are driven by %s (%s)\n", - update_driver_name, update_driver_sd_unit); - /* only try to get unit's `Documentation` if we're on the system bus */ - if (bus_type == G_BUS_TYPE_SYSTEM) - { - g_autoptr(GVariant) update_driver_docs_array = NULL; - g_autoptr(GError) local_error = NULL; - GDBusConnection *connection = - g_dbus_proxy_get_connection (G_DBUS_PROXY (sysroot_proxy)); - if (!get_update_driver_doc (connection, update_driver_sd_unit, &update_driver_docs_array, - cancellable, &local_error)) - { - g_printerr ("%s", local_error->message); - } - else if (update_driver_docs_array) - { - g_string_append_printf (error_msg, "See %s's documentation", update_driver_name); - gsize docs_len; - g_autofree const char **update_driver_docs = - g_variant_get_strv (update_driver_docs_array, &docs_len); - if (docs_len > 0) - { - g_string_append_printf (error_msg, " at "); - for (guint i = 0; i < docs_len; i++) - g_string_append_printf (error_msg, "%s%s", update_driver_docs[i], - i < docs_len - 1 ? ", " : "\n"); - } - else - { - g_string_append_printf (error_msg, "\n"); - } - } - } - - g_string_append_printf (error_msg, "Use --bypass-driver to bypass %s and force an upgrade anyway", - update_driver_name); - return glnx_throw (error, "%s", error_msg->str); - } - } + if (!error_if_driver_registered (bus_type, sysroot_proxy, cancellable, error)) + return FALSE; g_autoptr(GVariant) previous_deployment = rpmostree_os_dup_default_deployment (os_proxy); diff --git a/src/app/rpmostree-dbus-helpers.cxx b/src/app/rpmostree-dbus-helpers.cxx index 5e3bbd44..a4d768a8 100644 --- a/src/app/rpmostree-dbus-helpers.cxx +++ b/src/app/rpmostree-dbus-helpers.cxx @@ -36,6 +36,7 @@ #include "rpmostree-rpm-util.h" #include "rpmostree-rust.h" #include "rpmostree-cxxrs.h" +#include "rpmostreed-transaction-types.h" #define RPMOSTREE_CLI_ID "cli" @@ -1524,3 +1525,129 @@ rpmostree_print_cached_update (GVariant *cached_update, return TRUE; } + +/* Query systemd for update driver's systemd unit's object path. */ +gboolean +get_sd_unit_objpath (GDBusConnection *connection, + const char *update_driver_sd_unit, + const char **update_driver_objpath, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GVariant) update_driver_objpath_tuple = + g_dbus_connection_call_sync (connection, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", "LoadUnit", + g_variant_new ("(s)", update_driver_sd_unit), G_VARIANT_TYPE_TUPLE, + G_DBUS_CALL_FLAGS_NONE, -1, cancellable, error); + if (!update_driver_objpath_tuple) + return FALSE; + else if (g_variant_n_children (update_driver_objpath_tuple) < 1) + return glnx_throw (error, "LoadUnit(%s) returned empty tuple", update_driver_sd_unit); + + g_autoptr(GVariant) update_driver_objpath_val = + g_variant_get_child_value (update_driver_objpath_tuple, 0); + *update_driver_objpath = g_variant_dup_string (update_driver_objpath_val, NULL); + g_assert (*update_driver_objpath); + + return TRUE; +} + +/* Get the `Documentation` property of `sd_unit`. Documentation is returned + * as a string array GVariant in `unit_doc_array`. */ +static gboolean +get_sd_unit_doc (GDBusConnection *connection, + const char *sd_unit, + GVariant **unit_doc_array, + GCancellable *cancellable, + GError **error) +{ + const char *objpath = NULL; + if (!get_sd_unit_objpath (connection, sd_unit, &objpath, + cancellable, error)) + return FALSE; + + /* Look up `Documentation` property of systemd unit. */ + g_autoptr(GDBusProxy) unit_obj_proxy = + g_dbus_proxy_new_sync (connection, G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, + "org.freedesktop.systemd1", objpath, + "org.freedesktop.systemd1.Unit", cancellable, error); + if (!unit_obj_proxy) + return FALSE; + + *unit_doc_array = + g_dbus_proxy_get_cached_property (unit_obj_proxy, "Documentation"); + if (!*unit_doc_array) + return glnx_throw (error, "Documentation property not found in proxy's cache (%s)", + objpath); + + return TRUE; +} + +/* Helper function to append docs information for sd_unit to str. + * Prints any errors that occur. */ +static void +append_docs_to_str (GString *str, + RPMOSTreeSysroot *sysroot_proxy, + char *name, + char *sd_unit, + GCancellable *cancellable) +{ + g_autoptr(GVariant) docs_array = NULL; + g_autoptr(GError) local_error = NULL; + GDBusConnection *connection = + g_dbus_proxy_get_connection (G_DBUS_PROXY (sysroot_proxy)); + if (!get_sd_unit_doc (connection, sd_unit, &docs_array, cancellable, &local_error)) + { + g_printerr ("%s", local_error->message); + } + else if (docs_array) + { + g_string_append_printf (str, "See %s's documentation", name); + gsize docs_len; + g_autofree const char **docs = + g_variant_get_strv (docs_array, &docs_len); + if (docs_len > 0) + { + g_string_append_printf (str, " at "); + for (guint i = 0; i < docs_len; i++) + g_string_append_printf (str, "%s%s", docs[i], + i < docs_len - 1 ? ", " : "\n"); + } + else + { + g_string_append_printf (str, "\n"); + } + } +} + +/* Throw an error if an updates driver is registered. */ +gboolean +error_if_driver_registered (GBusType bus_type, + RPMOSTreeSysroot *sysroot_proxy, + GCancellable *cancellable, + GError **error) +{ + g_autofree char *update_driver_sd_unit = NULL; + g_autofree char *update_driver_name = NULL; + if (!get_driver_info (&update_driver_name, &update_driver_sd_unit, error)) + return FALSE; + + /* Throw an error if an updates driver is registered since deployments should be + * done through the driver. */ + if (update_driver_sd_unit && update_driver_name) + { + g_autoptr(GString) error_msg = g_string_new(NULL); + g_string_printf (error_msg, "Updates and deployments are driven by %s (%s)\n", + update_driver_name, update_driver_sd_unit); + /* only try to get unit's `Documentation` if we're on the system bus */ + if (bus_type == G_BUS_TYPE_SYSTEM) + append_docs_to_str (error_msg, sysroot_proxy, update_driver_name, + update_driver_sd_unit, cancellable); + g_string_append_printf (error_msg, + "Use --bypass-driver to bypass %s and perform the operation anyways", + update_driver_name); + return glnx_throw (error, "%s", error_msg->str); + } + + return TRUE; +} diff --git a/src/app/rpmostree-dbus-helpers.h b/src/app/rpmostree-dbus-helpers.h index 31610c6f..68074cc4 100644 --- a/src/app/rpmostree-dbus-helpers.h +++ b/src/app/rpmostree-dbus-helpers.h @@ -131,4 +131,17 @@ rpmostree_print_cached_update (GVariant *cached_update, GCancellable *cancellable, GError **error); +gboolean +get_sd_unit_objpath (GDBusConnection *connection, + const char *update_driver_sd_unit, + const char **update_driver_objpath, + GCancellable *cancellable, + GError **error); + +gboolean +error_if_driver_registered (GBusType bus_type, + RPMOSTreeSysroot *sysroot_proxy, + GCancellable *cancellable, + GError **error); + G_END_DECLS diff --git a/src/app/rpmostree-libbuiltin.cxx b/src/app/rpmostree-libbuiltin.cxx index 94bc9fa4..3d91cea1 100644 --- a/src/app/rpmostree-libbuiltin.cxx +++ b/src/app/rpmostree-libbuiltin.cxx @@ -141,29 +141,3 @@ rpmostree_print_timestamp_version (const char *version_string, rpmostree_print_kv ("Version", max_key_len, version_time); } } - -/* Query systemd for update driver's systemd unit's object path. */ -gboolean -get_sd_unit_objpath (GDBusConnection *connection, - const char *update_driver_sd_unit, - const char **update_driver_objpath, - GCancellable *cancellable, - GError **error) -{ - g_autoptr(GVariant) update_driver_objpath_tuple = - g_dbus_connection_call_sync (connection, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", - "org.freedesktop.systemd1.Manager", "LoadUnit", - g_variant_new ("(s)", update_driver_sd_unit), G_VARIANT_TYPE_TUPLE, - G_DBUS_CALL_FLAGS_NONE, -1, cancellable, error); - if (!update_driver_objpath_tuple) - return FALSE; - else if (g_variant_n_children (update_driver_objpath_tuple) < 1) - return glnx_throw (error, "LoadUnit(%s) returned empty tuple", update_driver_sd_unit); - - g_autoptr(GVariant) update_driver_objpath_val = - g_variant_get_child_value (update_driver_objpath_tuple, 0); - *update_driver_objpath = g_variant_dup_string (update_driver_objpath_val, NULL); - g_assert (*update_driver_objpath); - - return TRUE; -} diff --git a/src/app/rpmostree-libbuiltin.h b/src/app/rpmostree-libbuiltin.h index a50f074c..eeec573f 100644 --- a/src/app/rpmostree-libbuiltin.h +++ b/src/app/rpmostree-libbuiltin.h @@ -75,11 +75,4 @@ rpmostree_print_timestamp_version (const char *version_string, const char *timestamp_string, guint max_key_len); -gboolean -get_sd_unit_objpath (GDBusConnection *connection, - const char *update_driver_sd_unit, - const char **update_driver_objpath, - GCancellable *cancellable, - GError **error); - G_END_DECLS