diff --git a/src/fu-common.h b/src/fu-common.h index 44347f85e..a727ff734 100644 --- a/src/fu-common.h +++ b/src/fu-common.h @@ -14,14 +14,12 @@ G_BEGIN_DECLS * FuAppFlags: * @FU_APP_FLAGS_NONE: No flags set * @FU_APP_FLAGS_NO_IDLE_SOURCES: Disallow idle sources - * @FU_APP_FLAGS_IS_OFFLINE: Offline is set * * The flags to use when loading an application. **/ typedef enum { FU_APP_FLAGS_NONE = 0, FU_APP_FLAGS_NO_IDLE_SOURCES = 1 << 0, - FU_APP_FLAGS_IS_OFFLINE = 1 << 1, /*< private >*/ FU_APP_FLAGS_LAST } FuAppFlags; diff --git a/src/fu-engine.c b/src/fu-engine.c index e4b02b00b..f03faf35e 100644 --- a/src/fu-engine.c +++ b/src/fu-engine.c @@ -44,6 +44,10 @@ #include "fu-udev-device-private.h" #include "fu-usb-device-private.h" +#ifdef HAVE_SYSTEMD +#include "fu-systemd.h" +#endif + static void fu_engine_finalize (GObject *obj); struct _FuEngine @@ -1479,6 +1483,23 @@ fu_engine_create_release_metadata (FuEngine *self, FuPlugin *plugin, GError **er return g_steal_pointer (&release); } +static gboolean +fu_engine_is_running_offline (FuEngine *self) +{ +#ifdef HAVE_SYSTEMD + g_autofree gchar *default_target = NULL; + g_autoptr(GError) error = NULL; + default_target = fu_systemd_get_default_target (&error); + if (default_target == NULL) { + g_warning ("failed to get default.target: %s", error->message); + return FALSE; + } + return g_strcmp0 (default_target, "system-update.target") == 0; +#else + return FALSE; +#endif +} + /** * fu_engine_install: * @self: A #FuEngine @@ -1597,8 +1618,8 @@ fu_engine_install (FuEngine *self, g_prefix_error (error, "failed to get release version: "); return FALSE; } - if ((self->app_flags & FU_APP_FLAGS_IS_OFFLINE) == 0 && - (flags & FWUPD_INSTALL_FLAG_OFFLINE) > 0) { + if ((flags & FWUPD_INSTALL_FLAG_OFFLINE) > 0 && + !fu_engine_is_running_offline (self)) { g_autoptr(FwupdRelease) release_tmp = NULL; plugin = fu_plugin_list_find_by_name (self->plugin_list, "upower", NULL); if (plugin != NULL) { diff --git a/src/fu-main.c b/src/fu-main.c index 1edd41411..b89b9b68e 100644 --- a/src/fu-main.c +++ b/src/fu-main.c @@ -1372,29 +1372,6 @@ fu_main_daemon_get_property (GDBusConnection *connection_, const gchar *sender, return NULL; } -static gboolean -fu_main_is_running_offline_update (FuMainPrivate *priv) -{ - const gchar *default_target = NULL; - g_autoptr(GError) error = NULL; - g_autoptr(GVariant) val = NULL; - - val = g_dbus_connection_call_sync (priv->connection, - "org.freedesktop.systemd1", - "/org/freedesktop/systemd1", - "org.freedesktop.systemd1.Manager", - "GetDefaultTarget", - NULL, NULL, - G_DBUS_CALL_FLAGS_NONE, - 1500, NULL, &error); - if (val == NULL) { - g_warning ("failed to get default.target: %s", error->message); - return FALSE; - } - g_variant_get (val, "(&s)", &default_target); - return g_strcmp0 (default_target, "system-update.target") == 0; -} - static void fu_main_on_bus_acquired_cb (GDBusConnection *connection, const gchar *name, @@ -1419,10 +1396,6 @@ fu_main_on_bus_acquired_cb (GDBusConnection *connection, NULL); /* GError** */ g_assert (registration_id > 0); - /* are we running in the offline target */ - if (fu_main_is_running_offline_update (priv)) - fu_engine_add_app_flag (priv->engine, FU_APP_FLAGS_IS_OFFLINE); - /* connect to D-Bus directly */ priv->proxy_uid = g_dbus_proxy_new_sync (priv->connection, diff --git a/src/fu-systemd.c b/src/fu-systemd.c new file mode 100644 index 000000000..f1406a351 --- /dev/null +++ b/src/fu-systemd.c @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2017-2019 Richard Hughes + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include + +#include +#include +#include + +#include "fu-systemd.h" + +#define SYSTEMD_SERVICE "org.freedesktop.systemd1" +#define SYSTEMD_OBJECT_PATH "/org/freedesktop/systemd1" +#define SYSTEMD_INTERFACE "org.freedesktop.systemd1" +#define SYSTEMD_MANAGER_INTERFACE "org.freedesktop.systemd1.Manager" + +static GDBusProxy * +fu_systemd_get_manager (GError **error) +{ + g_autoptr(GDBusConnection) connection = NULL; + g_autoptr(GDBusProxy) proxy = NULL; + + connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error); + if (connection == NULL) { + g_prefix_error (error, "failed to get bus: "); + return NULL; + } + proxy = g_dbus_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_NONE, NULL, + SYSTEMD_SERVICE, + SYSTEMD_OBJECT_PATH, + SYSTEMD_MANAGER_INTERFACE, + NULL, error); + if (proxy == NULL) { + g_prefix_error (error, "failed to find %s: ", SYSTEMD_SERVICE); + return NULL; + } + return g_steal_pointer (&proxy); +} + +static gchar * +fu_systemd_unit_get_path (GDBusProxy *proxy_manager, const gchar *unit, GError **error) +{ + g_autofree gchar *path = NULL; + g_autoptr(GVariant) val = NULL; + + val = g_dbus_proxy_call_sync (proxy_manager, + "GetUnit", + g_variant_new ("(s)", unit), + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, error); + if (val == NULL) { + g_prefix_error (error, "failed to find %s: ", unit); + return NULL; + } + g_variant_get (val, "(o)", &path); + return g_steal_pointer (&path); +} + +static GDBusProxy * +fu_systemd_unit_get_proxy (GDBusProxy *proxy_manager, const gchar *unit, GError **error) +{ + g_autofree gchar *path = NULL; + g_autoptr(GDBusProxy) proxy_unit = NULL; + + path = fu_systemd_unit_get_path (proxy_manager, unit, error); + if (path == NULL) + return NULL; + proxy_unit = g_dbus_proxy_new_sync (g_dbus_proxy_get_connection (proxy_manager), + G_DBUS_PROXY_FLAGS_NONE, NULL, + SYSTEMD_SERVICE, + path, + SYSTEMD_INTERFACE, + NULL, error); + if (proxy_unit == NULL) { + g_prefix_error (error, "failed to register proxy for %s: ", path); + return NULL; + } + return g_steal_pointer (&proxy_unit); +} + +gchar * +fu_systemd_get_default_target (GError **error) +{ + const gchar *path = NULL; + g_autoptr(GDBusProxy) proxy_manager = NULL; + g_autoptr(GVariant) val = NULL; + + proxy_manager = fu_systemd_get_manager (error); + if (proxy_manager == NULL) + return NULL; + val = g_dbus_proxy_call_sync (proxy_manager, + "GetDefaultTarget", NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, error); + if (val == NULL) + return NULL; + g_variant_get (val, "(&s)", &path); + return g_strdup (path); + +} + +gboolean +fu_systemd_unit_stop (const gchar *unit, GError **error) +{ + g_autoptr(GDBusProxy) proxy_manager = NULL; + g_autoptr(GDBusProxy) proxy_unit = NULL; + g_autoptr(GVariant) val = NULL; + + g_return_val_if_fail (unit != NULL, FALSE); + + proxy_manager = fu_systemd_get_manager (error); + if (proxy_manager == NULL) + return FALSE; + proxy_unit = fu_systemd_unit_get_proxy (proxy_manager, unit, error); + if (proxy_unit == NULL) + return FALSE; + val = g_dbus_proxy_call_sync (proxy_unit, + "StopUnit", + g_variant_new ("(ss)", unit, "replace"), + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, error); + return val != NULL; +} + +gboolean +fu_systemd_unit_enable (const gchar *unit, GError **error) +{ + const gchar *units[] = { unit, NULL }; + g_autoptr(GDBusProxy) proxy_manager = NULL; + g_autoptr(GVariant) val = NULL; + + g_return_val_if_fail (unit != NULL, FALSE); + + proxy_manager = fu_systemd_get_manager (error); + if (proxy_manager == NULL) + return FALSE; + val = g_dbus_proxy_call_sync (proxy_manager, + "EnableUnitFiles", + g_variant_new ("(^asbb)", units, TRUE, TRUE), + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, error); + return val != NULL; +} + +gboolean +fu_systemd_unit_disable (const gchar *unit, GError **error) +{ + const gchar *units[] = { unit, NULL }; + g_autoptr(GDBusProxy) proxy_manager = NULL; + g_autoptr(GVariant) val = NULL; + + g_return_val_if_fail (unit != NULL, FALSE); + + proxy_manager = fu_systemd_get_manager (error); + if (proxy_manager == NULL) + return FALSE; + val = g_dbus_proxy_call_sync (proxy_manager, + "DisableUnitFiles", + g_variant_new ("(^asb)", units, TRUE), + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, error); + return val != NULL; +} + +gboolean +fu_systemd_unit_check_exists (const gchar *unit, GError **error) +{ + g_autoptr(GDBusProxy) proxy_manager = NULL; + g_autofree gchar *path = NULL; + + g_return_val_if_fail (unit != NULL, FALSE); + + proxy_manager = fu_systemd_get_manager (error); + if (proxy_manager == NULL) + return FALSE; + path = fu_systemd_unit_get_path (proxy_manager, unit, error); + return path != NULL; +} diff --git a/src/fu-systemd.h b/src/fu-systemd.h new file mode 100644 index 000000000..72b899ec1 --- /dev/null +++ b/src/fu-systemd.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2017-2019 Richard Hughes + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#pragma once + +#include + +G_BEGIN_DECLS + +gboolean fu_systemd_unit_check_exists (const gchar *unit, + GError **error); +gboolean fu_systemd_unit_stop (const gchar *unit, + GError **error); +gboolean fu_systemd_unit_enable (const gchar *unit, + GError **error); +gboolean fu_systemd_unit_disable (const gchar *unit, + GError **error); +gchar *fu_systemd_get_default_target (GError **error); + +G_END_DECLS diff --git a/src/fu-tool.c b/src/fu-tool.c index 5508c12b0..353a52e88 100644 --- a/src/fu-tool.c +++ b/src/fu-tool.c @@ -28,6 +28,10 @@ #include "fwupd-common-private.h" #include "fwupd-device-private.h" +#ifdef HAVE_SYSTEMD +#include "fu-systemd.h" +#endif + /* custom return code */ #define EXIT_NOTHING_TO_DO 2 @@ -109,7 +113,7 @@ fu_util_start_engine (FuUtilPrivate *priv, FuEngineLoadFlags flags, GError **err { g_autoptr(GError) error_local = NULL; - if (!fu_util_stop_daemon (&error_local)) + if (!fu_systemd_unit_stop (fu_util_get_systemd_unit (), &error_local)) g_debug ("Failed top stop daemon: %s", error_local->message); if (!fu_engine_load (priv->engine, flags, error)) return FALSE; diff --git a/src/fu-util-common.c b/src/fu-util-common.c index 0072de47e..9567c52c3 100644 --- a/src/fu-util-common.c +++ b/src/fu-util-common.c @@ -13,13 +13,14 @@ #include "fu-util-common.h" #include "fu-device.h" -#define SYSTEMD_SERVICE "org.freedesktop.systemd1" -#define SYSTEMD_OBJECT_PATH "/org/freedesktop/systemd1" -#define SYSTEMD_MANAGER_INTERFACE "org.freedesktop.systemd1.Manager" +#ifdef HAVE_SYSTEMD +#include "fu-systemd.h" +#endif + #define SYSTEMD_FWUPD_UNIT "fwupd.service" #define SYSTEMD_SNAP_FWUPD_UNIT "snap.fwupd.fwupd.service" -static const gchar * +const gchar * fu_util_get_systemd_unit (void) { if (g_getenv ("SNAP") != NULL) @@ -38,45 +39,17 @@ fu_util_get_expected_command (const gchar *target) gboolean fu_util_using_correct_daemon (GError **error) { - g_autoptr(GDBusConnection) connection = NULL; - g_autoptr(GVariant) default_target = NULL; - g_autoptr(GVariant) val_path = NULL; + g_autofree gchar *default_target = NULL; g_autoptr(GError) error_local = NULL; const gchar *target = fu_util_get_systemd_unit (); - connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error); - if (connection == NULL) - return FALSE; - - default_target = g_dbus_connection_call_sync (connection, - SYSTEMD_SERVICE, - SYSTEMD_OBJECT_PATH, - SYSTEMD_MANAGER_INTERFACE, - "GetDefaultTarget", - NULL, - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - &error_local); + default_target = fu_systemd_get_default_target (&error_local); if (default_target == NULL) { g_debug ("Systemd isn't accessible: %s\n", error_local->message); return TRUE; } - - val_path = g_dbus_connection_call_sync (connection, - SYSTEMD_SERVICE, - SYSTEMD_OBJECT_PATH, - SYSTEMD_MANAGER_INTERFACE, - "GetUnit", - g_variant_new ("(s)", - target), - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - NULL); - if (val_path == NULL) { + if (!fu_systemd_unit_check_exists (target, &error_local)) { + g_debug ("wrong target: %s\n", error_local->message); g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INVALID_ARGS, @@ -89,56 +62,6 @@ fu_util_using_correct_daemon (GError **error) return TRUE; } -gboolean -fu_util_stop_daemon (GError **error) -{ - g_autoptr(GDBusConnection) connection = NULL; - g_autoptr(GDBusProxy) proxy = NULL; - g_autoptr(GVariant) val = NULL; - const gchar *target = fu_util_get_systemd_unit (); - - connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error); - if (connection == NULL) { - g_prefix_error (error, "failed to get bus: "); - return FALSE; - } - proxy = g_dbus_proxy_new_sync (connection, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - SYSTEMD_SERVICE, - SYSTEMD_OBJECT_PATH, - SYSTEMD_MANAGER_INTERFACE, - NULL, - error); - if (proxy == NULL) { - g_prefix_error (error, "failed to find %s: ", SYSTEMD_SERVICE); - return FALSE; - } - val = g_dbus_proxy_call_sync (proxy, - "GetUnit", - g_variant_new ("(s)", - target), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - error); - if (val == NULL) { - g_prefix_error (error, "failed to find %s: ", target); - return FALSE; - } - g_variant_unref (val); - val = g_dbus_proxy_call_sync (proxy, - "StopUnit", - g_variant_new ("(ss)", - target, - "replace"), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - error); - return val != NULL; -} - void fu_util_print_data (const gchar *title, const gchar *msg) { diff --git a/src/fu-util-common.h b/src/fu-util-common.h index 41dd53ab6..ef19aeb20 100644 --- a/src/fu-util-common.h +++ b/src/fu-util-common.h @@ -60,7 +60,7 @@ gboolean fu_util_cmd_array_run (GPtrArray *array, GError **error); gchar *fu_util_release_get_name (FwupdRelease *release); +const gchar *fu_util_get_systemd_unit (void); gboolean fu_util_using_correct_daemon (GError **error); -gboolean fu_util_stop_daemon (GError **error); G_END_DECLS diff --git a/src/fu-util.c b/src/fu-util.c index 91a458d40..c8528e71e 100644 --- a/src/fu-util.c +++ b/src/fu-util.c @@ -28,6 +28,10 @@ #include "fu-util-common.h" #include "fwupd-common-private.h" +#ifdef HAVE_SYSTEMD +#include "fu-systemd.h" +#endif + /* custom return code */ #define EXIT_NOTHING_TO_DO 2 @@ -2118,7 +2122,7 @@ fu_util_modify_config (FuUtilPrivate *priv, gchar **values, GError **error) if (!fu_util_prompt_for_boolean (FALSE)) return TRUE; } - return fu_util_stop_daemon (error); + return fu_systemd_unit_stop (fu_util_get_systemd_unit (), error); } static void diff --git a/src/meson.build b/src/meson.build index 0350bd3a4..b841aa846 100644 --- a/src/meson.build +++ b/src/meson.build @@ -7,6 +7,7 @@ endif keyring_deps = [] keyring_src = [] test_deps = [] +init_src = [] if get_option('gpg') keyring_src += 'fu-keyring-gpg.c' @@ -22,9 +23,14 @@ if get_option('pkcs7') endif endif +if get_option('systemd') + init_src += 'fu-systemd.c' +endif + libfwupdprivate = static_library( 'fwupdprivate', sources : [ + init_src, 'fu-archive.c', 'fu-common.c', 'fu-common-guid.c', @@ -180,6 +186,7 @@ fwupdtool = executable( sources : [ 'fu-tool.c', keyring_src, + init_src, 'fu-archive.c', 'fu-chunk.c', 'fu-common.c', @@ -263,6 +270,7 @@ executable( fu_hash, sources : [ keyring_src, + init_src, 'fu-archive.c', 'fu-chunk.c', 'fu-common.c', @@ -337,6 +345,7 @@ if get_option('tests') fu_hash, sources : [ keyring_src, + init_src, 'fu-self-test.c', 'fu-archive.c', 'fu-chunk.c',