mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-03 13:27:59 +00:00
Move out the offline update functionality to a new binary
The offline updates environment is special, and we have to be careful to delete the trigger before doing anything that can fail to avoid boot loops. For this reason, split it out to a simple self-contained binary that is easy to understand.
This commit is contained in:
parent
ad73719fa4
commit
4499d19ba3
@ -10,6 +10,7 @@ usr/share/locale
|
||||
usr/share/metainfo/*
|
||||
usr/lib/*/fwupd
|
||||
usr/lib/*/fwupdagent
|
||||
usr/lib/*/fwupdoffline
|
||||
usr/lib/*/fwupdtool
|
||||
usr/share/man/man1/*
|
||||
lib/systemd/system/*
|
||||
|
@ -214,6 +214,7 @@ mkdir -p --mode=0700 $RPM_BUILD_ROOT%{_localstatedir}/lib/fwupd/gnupg
|
||||
%{_libexecdir}/fwupd/fwupd
|
||||
%{_libexecdir}/fwupd/fwupdtool
|
||||
%{_libexecdir}/fwupd/fwupdagent
|
||||
%{_libexecdir}/fwupd/fwupdoffline
|
||||
%if 0%{?have_uefi}
|
||||
%{_libexecdir}/fwupd/efi/*.efi
|
||||
%{_libexecdir}/fwupd/efi/*.efi.signed
|
||||
|
@ -16,7 +16,6 @@ _fwupdmgr_cmd_list=(
|
||||
'get-topology'
|
||||
'get-updates'
|
||||
'install'
|
||||
'install-prepared'
|
||||
'modify-remote'
|
||||
'refresh'
|
||||
'report-history'
|
||||
|
@ -9,5 +9,5 @@ Before=shutdown.target system-update.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=@bindir@/fwupdmgr install-prepared
|
||||
ExecStart=@bindir@/fwupdoffline
|
||||
FailureAction=reboot
|
||||
|
@ -8,6 +8,7 @@ src/fu-agent.c
|
||||
src/fu-config.c
|
||||
src/fu-debug.c
|
||||
src/fu-main.c
|
||||
src/fu-offline.c
|
||||
src/fu-tool.c
|
||||
src/fu-progressbar.c
|
||||
src/fu-util.c
|
||||
|
142
src/fu-offline.c
Normal file
142
src/fu-offline.c
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2019 Richard Hughes <richard@hughsie.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <fwupd.h>
|
||||
#include <locale.h>
|
||||
#include <stdlib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include "fu-history.h"
|
||||
#include "fu-plugin-private.h"
|
||||
#include "fu-util-common.h"
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
gint vercmp;
|
||||
guint cnt = 0;
|
||||
g_autofree gchar *link = NULL;
|
||||
g_autoptr(FuHistory) history = NULL;
|
||||
g_autoptr(FwupdClient) client = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(GPtrArray) results = NULL;
|
||||
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
|
||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||
textdomain (GETTEXT_PACKAGE);
|
||||
|
||||
/* verify this is pointing to our cache */
|
||||
link = g_file_read_link (FU_OFFLINE_TRIGGER_FILENAME, NULL);
|
||||
if (link == NULL)
|
||||
return EXIT_SUCCESS;
|
||||
if (g_strcmp0 (link, "/var/lib/fwupd") != 0)
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
/* do this first to avoid a loop if this tool segfaults */
|
||||
g_unlink (FU_OFFLINE_TRIGGER_FILENAME);
|
||||
|
||||
/* ensure root user */
|
||||
if (getuid () != 0 || geteuid () != 0) {
|
||||
/* TRANSLATORS: the user needs to stop playing with stuff */
|
||||
g_printerr ("%s\n", _("This tool can only be used by the root user"));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* ensure D-Bus errors are registered */
|
||||
fwupd_error_quark ();
|
||||
|
||||
/* get prepared updates */
|
||||
history = fu_history_new ();
|
||||
results = fu_history_get_devices (history, &error);
|
||||
if (results == NULL) {
|
||||
/* TRANSLATORS: we could not get the devices to update offline */
|
||||
g_printerr ("%s: %s\n", _("Failed to get pending devices"),
|
||||
error->message);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* connect to the daemon */
|
||||
client = fwupd_client_new ();
|
||||
if (!fwupd_client_connect (client, NULL, &error)) {
|
||||
/* TRANSLATORS: we could not talk to the fwupd daemon */
|
||||
g_printerr ("%s: %s\n", _("Failed to connect to daemon"),
|
||||
error->message);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* apply each update */
|
||||
for (guint i = 0; i < results->len; i++) {
|
||||
FwupdDevice *dev = g_ptr_array_index (results, i);
|
||||
FwupdRelease *rel = fwupd_device_get_release_default (dev);
|
||||
|
||||
/* check not already done */
|
||||
if (fwupd_device_get_update_state (dev) != FWUPD_UPDATE_STATE_PENDING)
|
||||
continue;
|
||||
|
||||
/* tell the user what's going to happen */
|
||||
vercmp = fu_common_vercmp (fwupd_device_get_version (dev),
|
||||
fwupd_release_get_version (rel));
|
||||
if (vercmp == 0) {
|
||||
/* TRANSLATORS: the first replacement is a display name
|
||||
* e.g. "ColorHugALS" and the second is a version number
|
||||
* e.g. "1.2.3" */
|
||||
g_print (_("Reinstalling %s with %s... "),
|
||||
fwupd_device_get_name (dev),
|
||||
fwupd_release_get_version (rel));
|
||||
} else if (vercmp > 0) {
|
||||
/* TRANSLATORS: the first replacement is a display name
|
||||
* e.g. "ColorHugALS" and the second and third are
|
||||
* version numbers e.g. "1.2.3" */
|
||||
g_print (_("Downgrading %s from %s to %s... "),
|
||||
fwupd_device_get_name (dev),
|
||||
fwupd_device_get_version (dev),
|
||||
fwupd_release_get_version (rel));
|
||||
} else if (vercmp < 0) {
|
||||
/* TRANSLATORS: the first replacement is a display name
|
||||
* e.g. "ColorHugALS" and the second and third are
|
||||
* version numbers e.g. "1.2.3" */
|
||||
g_print (_("Updating %s from %s to %s... "),
|
||||
fwupd_device_get_name (dev),
|
||||
fwupd_device_get_version (dev),
|
||||
fwupd_release_get_version (rel));
|
||||
}
|
||||
if (!fwupd_client_install (client,
|
||||
fwupd_device_get_id (dev),
|
||||
fwupd_release_get_filename (rel),
|
||||
FWUPD_INSTALL_FLAG_NONE,
|
||||
NULL,
|
||||
&error)) {
|
||||
/* TRANSLATORS: we could not install for some reason */
|
||||
g_printerr ("%s: %s\n", _("Failed to install firmware update"),
|
||||
error->message);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
|
||||
/* nothing to do */
|
||||
if (cnt == 0) {
|
||||
/* TRANSLATORS: nothing was updated offline */
|
||||
g_printerr ("%s\n", _("No updates were applied"));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* reboot */
|
||||
if (!fu_util_update_reboot (&error)) {
|
||||
/* TRANSLATORS: we could not reboot for some reason */
|
||||
g_printerr ("%s: %s\n", _("Failed to reboot"), error->message);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* success */
|
||||
g_print ("%s\n", _("Done!"));
|
||||
return EXIT_SUCCESS;
|
||||
}
|
@ -219,7 +219,7 @@ fu_util_update_shutdown (GError **error)
|
||||
return val != NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gboolean
|
||||
fu_util_update_reboot (GError **error)
|
||||
{
|
||||
g_autoptr(GDBusConnection) connection = NULL;
|
||||
|
@ -41,6 +41,7 @@ gchar *fu_util_get_versions (void);
|
||||
gboolean fu_util_prompt_complete (FwupdDeviceFlags flags,
|
||||
gboolean prompt,
|
||||
GError **error);
|
||||
gboolean fu_util_update_reboot (GError **error);
|
||||
|
||||
GPtrArray *fu_util_cmd_array_new (void);
|
||||
void fu_util_cmd_array_add (GPtrArray *array,
|
||||
|
115
src/fu-util.c
115
src/fu-util.c
@ -562,115 +562,6 @@ fu_util_get_details (FuUtilPrivate *priv, gchar **values, GError **error)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_util_install_prepared (FuUtilPrivate *priv, gchar **values, GError **error)
|
||||
{
|
||||
gint vercmp;
|
||||
guint cnt = 0;
|
||||
g_autofree gchar *link = NULL;
|
||||
g_autoptr(GPtrArray) results = NULL;
|
||||
g_autoptr(FuHistory) history = NULL;
|
||||
|
||||
/* verify this is pointing to our cache */
|
||||
link = g_file_read_link (FU_OFFLINE_TRIGGER_FILENAME, NULL);
|
||||
if (link == NULL) {
|
||||
g_debug ("No %s, exiting", FU_OFFLINE_TRIGGER_FILENAME);
|
||||
return TRUE;
|
||||
}
|
||||
if (g_strcmp0 (link, "/var/lib/fwupd") != 0) {
|
||||
g_debug ("Another framework set up the trigger, exiting");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* do this first to avoid a loop if this tool segfaults */
|
||||
g_unlink (FU_OFFLINE_TRIGGER_FILENAME);
|
||||
|
||||
if (g_strv_length (values) != 0) {
|
||||
g_set_error_literal (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_ARGS,
|
||||
"Invalid arguments: none expected");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* ensure root user */
|
||||
if (getuid () != 0 || geteuid () != 0) {
|
||||
g_set_error_literal (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_ARGS,
|
||||
"This function can only be used as root");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* get prepared updates */
|
||||
history = fu_history_new ();
|
||||
results = fu_history_get_devices (history, error);
|
||||
if (results == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* apply each update */
|
||||
for (guint i = 0; i < results->len; i++) {
|
||||
FwupdDevice *dev = g_ptr_array_index (results, i);
|
||||
FwupdRelease *rel = fwupd_device_get_release_default (dev);
|
||||
|
||||
/* check not already done */
|
||||
if (fwupd_device_get_update_state (dev) != FWUPD_UPDATE_STATE_PENDING)
|
||||
continue;
|
||||
|
||||
/* tell the user what's going to happen */
|
||||
vercmp = fu_common_vercmp (fwupd_device_get_version (dev),
|
||||
fwupd_release_get_version (rel));
|
||||
if (vercmp == 0) {
|
||||
/* TRANSLATORS: the first replacement is a display name
|
||||
* e.g. "ColorHugALS" and the second is a version number
|
||||
* e.g. "1.2.3" */
|
||||
g_print (_("Reinstalling %s with %s... "),
|
||||
fwupd_device_get_name (dev),
|
||||
fwupd_release_get_version (rel));
|
||||
} else if (vercmp > 0) {
|
||||
/* TRANSLATORS: the first replacement is a display name
|
||||
* e.g. "ColorHugALS" and the second and third are
|
||||
* version numbers e.g. "1.2.3" */
|
||||
g_print (_("Downgrading %s from %s to %s... "),
|
||||
fwupd_device_get_name (dev),
|
||||
fwupd_device_get_version (dev),
|
||||
fwupd_release_get_version (rel));
|
||||
} else if (vercmp < 0) {
|
||||
/* TRANSLATORS: the first replacement is a display name
|
||||
* e.g. "ColorHugALS" and the second and third are
|
||||
* version numbers e.g. "1.2.3" */
|
||||
g_print (_("Updating %s from %s to %s... "),
|
||||
fwupd_device_get_name (dev),
|
||||
fwupd_device_get_version (dev),
|
||||
fwupd_release_get_version (rel));
|
||||
}
|
||||
if (!fwupd_client_install (priv->client,
|
||||
fwupd_device_get_id (dev),
|
||||
fwupd_release_get_filename (rel),
|
||||
priv->flags,
|
||||
NULL,
|
||||
error))
|
||||
return FALSE;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
/* nothing to do */
|
||||
if (cnt == 0) {
|
||||
g_set_error_literal (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_NOTHING_TO_DO,
|
||||
"No updates prepared");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* reboot */
|
||||
if (!fu_util_prompt_complete (FWUPD_DEVICE_FLAG_NEEDS_REBOOT, FALSE, error))
|
||||
return FALSE;
|
||||
|
||||
g_print ("%s\n", _("Done!"));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_util_clear_history (FuUtilPrivate *priv, gchar **values, GError **error)
|
||||
{
|
||||
@ -2297,12 +2188,6 @@ main (int argc, char *argv[])
|
||||
/* TRANSLATORS: command description */
|
||||
_("Get all devices according to the system topology"),
|
||||
fu_util_get_topology);
|
||||
fu_util_cmd_array_add (cmd_array,
|
||||
"install-prepared",
|
||||
NULL,
|
||||
/* TRANSLATORS: command description */
|
||||
_("Install prepared updates now"),
|
||||
fu_util_install_prepared);
|
||||
fu_util_cmd_array_add (cmd_array,
|
||||
"get-history",
|
||||
NULL,
|
||||
|
@ -128,6 +128,35 @@ fwupdagent = executable(
|
||||
)
|
||||
endif
|
||||
|
||||
if get_option('systemd')
|
||||
fwupdagent = executable(
|
||||
'fwupdoffline',
|
||||
sources : [
|
||||
'fu-offline.c',
|
||||
'fu-util-common.c',
|
||||
],
|
||||
include_directories : [
|
||||
include_directories('..'),
|
||||
include_directories('../libfwupd'),
|
||||
],
|
||||
dependencies : [
|
||||
giounix,
|
||||
gudev,
|
||||
gusb,
|
||||
soup,
|
||||
],
|
||||
link_with : [
|
||||
fwupd,
|
||||
libfwupdprivate,
|
||||
],
|
||||
c_args : [
|
||||
'-DFU_OFFLINE_DESTDIR=""',
|
||||
],
|
||||
install : true,
|
||||
install_dir : join_paths(libexecdir, 'fwupd')
|
||||
)
|
||||
endif
|
||||
|
||||
resources_src = gnome.compile_resources(
|
||||
'fwupd-resources',
|
||||
'fwupd.gresource.xml',
|
||||
|
Loading…
Reference in New Issue
Block a user