Check if the system is offline during install, rather than at startup

This splits out the systemd functionality to a new file, but makes no other
logic changes.
This commit is contained in:
Richard Hughes 2019-05-17 14:02:41 +01:00 committed by Mario Limonciello
parent 54e636e96d
commit 3d00522dd3
10 changed files with 257 additions and 120 deletions

View File

@ -14,14 +14,12 @@ G_BEGIN_DECLS
* FuAppFlags: * FuAppFlags:
* @FU_APP_FLAGS_NONE: No flags set * @FU_APP_FLAGS_NONE: No flags set
* @FU_APP_FLAGS_NO_IDLE_SOURCES: Disallow idle sources * @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. * The flags to use when loading an application.
**/ **/
typedef enum { typedef enum {
FU_APP_FLAGS_NONE = 0, FU_APP_FLAGS_NONE = 0,
FU_APP_FLAGS_NO_IDLE_SOURCES = 1 << 0, FU_APP_FLAGS_NO_IDLE_SOURCES = 1 << 0,
FU_APP_FLAGS_IS_OFFLINE = 1 << 1,
/*< private >*/ /*< private >*/
FU_APP_FLAGS_LAST FU_APP_FLAGS_LAST
} FuAppFlags; } FuAppFlags;

View File

@ -44,6 +44,10 @@
#include "fu-udev-device-private.h" #include "fu-udev-device-private.h"
#include "fu-usb-device-private.h" #include "fu-usb-device-private.h"
#ifdef HAVE_SYSTEMD
#include "fu-systemd.h"
#endif
static void fu_engine_finalize (GObject *obj); static void fu_engine_finalize (GObject *obj);
struct _FuEngine struct _FuEngine
@ -1479,6 +1483,23 @@ fu_engine_create_release_metadata (FuEngine *self, FuPlugin *plugin, GError **er
return g_steal_pointer (&release); 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: * fu_engine_install:
* @self: A #FuEngine * @self: A #FuEngine
@ -1597,8 +1618,8 @@ fu_engine_install (FuEngine *self,
g_prefix_error (error, "failed to get release version: "); g_prefix_error (error, "failed to get release version: ");
return FALSE; return FALSE;
} }
if ((self->app_flags & FU_APP_FLAGS_IS_OFFLINE) == 0 && if ((flags & FWUPD_INSTALL_FLAG_OFFLINE) > 0 &&
(flags & FWUPD_INSTALL_FLAG_OFFLINE) > 0) { !fu_engine_is_running_offline (self)) {
g_autoptr(FwupdRelease) release_tmp = NULL; g_autoptr(FwupdRelease) release_tmp = NULL;
plugin = fu_plugin_list_find_by_name (self->plugin_list, "upower", NULL); plugin = fu_plugin_list_find_by_name (self->plugin_list, "upower", NULL);
if (plugin != NULL) { if (plugin != NULL) {

View File

@ -1372,29 +1372,6 @@ fu_main_daemon_get_property (GDBusConnection *connection_, const gchar *sender,
return NULL; 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 static void
fu_main_on_bus_acquired_cb (GDBusConnection *connection, fu_main_on_bus_acquired_cb (GDBusConnection *connection,
const gchar *name, const gchar *name,
@ -1419,10 +1396,6 @@ fu_main_on_bus_acquired_cb (GDBusConnection *connection,
NULL); /* GError** */ NULL); /* GError** */
g_assert (registration_id > 0); 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 */ /* connect to D-Bus directly */
priv->proxy_uid = priv->proxy_uid =
g_dbus_proxy_new_sync (priv->connection, g_dbus_proxy_new_sync (priv->connection,

182
src/fu-systemd.c Normal file
View File

@ -0,0 +1,182 @@
/*
* Copyright (C) 2017-2019 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include <config.h>
#include <stdio.h>
#include <glib/gi18n.h>
#include <gusb.h>
#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;
}

23
src/fu-systemd.h Normal file
View File

@ -0,0 +1,23 @@
/*
* Copyright (C) 2017-2019 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#pragma once
#include <glib.h>
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

View File

@ -28,6 +28,10 @@
#include "fwupd-common-private.h" #include "fwupd-common-private.h"
#include "fwupd-device-private.h" #include "fwupd-device-private.h"
#ifdef HAVE_SYSTEMD
#include "fu-systemd.h"
#endif
/* custom return code */ /* custom return code */
#define EXIT_NOTHING_TO_DO 2 #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; 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); g_debug ("Failed top stop daemon: %s", error_local->message);
if (!fu_engine_load (priv->engine, flags, error)) if (!fu_engine_load (priv->engine, flags, error))
return FALSE; return FALSE;

View File

@ -13,13 +13,14 @@
#include "fu-util-common.h" #include "fu-util-common.h"
#include "fu-device.h" #include "fu-device.h"
#define SYSTEMD_SERVICE "org.freedesktop.systemd1" #ifdef HAVE_SYSTEMD
#define SYSTEMD_OBJECT_PATH "/org/freedesktop/systemd1" #include "fu-systemd.h"
#define SYSTEMD_MANAGER_INTERFACE "org.freedesktop.systemd1.Manager" #endif
#define SYSTEMD_FWUPD_UNIT "fwupd.service" #define SYSTEMD_FWUPD_UNIT "fwupd.service"
#define SYSTEMD_SNAP_FWUPD_UNIT "snap.fwupd.fwupd.service" #define SYSTEMD_SNAP_FWUPD_UNIT "snap.fwupd.fwupd.service"
static const gchar * const gchar *
fu_util_get_systemd_unit (void) fu_util_get_systemd_unit (void)
{ {
if (g_getenv ("SNAP") != NULL) if (g_getenv ("SNAP") != NULL)
@ -38,45 +39,17 @@ fu_util_get_expected_command (const gchar *target)
gboolean gboolean
fu_util_using_correct_daemon (GError **error) fu_util_using_correct_daemon (GError **error)
{ {
g_autoptr(GDBusConnection) connection = NULL; g_autofree gchar *default_target = NULL;
g_autoptr(GVariant) default_target = NULL;
g_autoptr(GVariant) val_path = NULL;
g_autoptr(GError) error_local = NULL; g_autoptr(GError) error_local = NULL;
const gchar *target = fu_util_get_systemd_unit (); const gchar *target = fu_util_get_systemd_unit ();
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error); default_target = fu_systemd_get_default_target (&error_local);
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);
if (default_target == NULL) { if (default_target == NULL) {
g_debug ("Systemd isn't accessible: %s\n", error_local->message); g_debug ("Systemd isn't accessible: %s\n", error_local->message);
return TRUE; return TRUE;
} }
if (!fu_systemd_unit_check_exists (target, &error_local)) {
val_path = g_dbus_connection_call_sync (connection, g_debug ("wrong target: %s\n", error_local->message);
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) {
g_set_error (error, g_set_error (error,
FWUPD_ERROR, FWUPD_ERROR,
FWUPD_ERROR_INVALID_ARGS, FWUPD_ERROR_INVALID_ARGS,
@ -89,56 +62,6 @@ fu_util_using_correct_daemon (GError **error)
return TRUE; 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 void
fu_util_print_data (const gchar *title, const gchar *msg) fu_util_print_data (const gchar *title, const gchar *msg)
{ {

View File

@ -60,7 +60,7 @@ gboolean fu_util_cmd_array_run (GPtrArray *array,
GError **error); GError **error);
gchar *fu_util_release_get_name (FwupdRelease *release); 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_using_correct_daemon (GError **error);
gboolean fu_util_stop_daemon (GError **error);
G_END_DECLS G_END_DECLS

View File

@ -28,6 +28,10 @@
#include "fu-util-common.h" #include "fu-util-common.h"
#include "fwupd-common-private.h" #include "fwupd-common-private.h"
#ifdef HAVE_SYSTEMD
#include "fu-systemd.h"
#endif
/* custom return code */ /* custom return code */
#define EXIT_NOTHING_TO_DO 2 #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)) if (!fu_util_prompt_for_boolean (FALSE))
return TRUE; return TRUE;
} }
return fu_util_stop_daemon (error); return fu_systemd_unit_stop (fu_util_get_systemd_unit (), error);
} }
static void static void

View File

@ -7,6 +7,7 @@ endif
keyring_deps = [] keyring_deps = []
keyring_src = [] keyring_src = []
test_deps = [] test_deps = []
init_src = []
if get_option('gpg') if get_option('gpg')
keyring_src += 'fu-keyring-gpg.c' keyring_src += 'fu-keyring-gpg.c'
@ -22,9 +23,14 @@ if get_option('pkcs7')
endif endif
endif endif
if get_option('systemd')
init_src += 'fu-systemd.c'
endif
libfwupdprivate = static_library( libfwupdprivate = static_library(
'fwupdprivate', 'fwupdprivate',
sources : [ sources : [
init_src,
'fu-archive.c', 'fu-archive.c',
'fu-common.c', 'fu-common.c',
'fu-common-guid.c', 'fu-common-guid.c',
@ -180,6 +186,7 @@ fwupdtool = executable(
sources : [ sources : [
'fu-tool.c', 'fu-tool.c',
keyring_src, keyring_src,
init_src,
'fu-archive.c', 'fu-archive.c',
'fu-chunk.c', 'fu-chunk.c',
'fu-common.c', 'fu-common.c',
@ -263,6 +270,7 @@ executable(
fu_hash, fu_hash,
sources : [ sources : [
keyring_src, keyring_src,
init_src,
'fu-archive.c', 'fu-archive.c',
'fu-chunk.c', 'fu-chunk.c',
'fu-common.c', 'fu-common.c',
@ -337,6 +345,7 @@ if get_option('tests')
fu_hash, fu_hash,
sources : [ sources : [
keyring_src, keyring_src,
init_src,
'fu-self-test.c', 'fu-self-test.c',
'fu-archive.c', 'fu-archive.c',
'fu-chunk.c', 'fu-chunk.c',