blob: b0b384042efc3237a8f2d06c5109e4951a6cfa01 [file] [log] [blame]
Richard Hughes02c90d82018-08-09 12:13:03 +01001/*
Richard Hughes4ad41f02018-05-08 14:35:36 +01002 * Copyright (C) 2018 Richard Hughes <richard@hughsie.com>
3 *
Mario Limonciello51308e62018-05-28 20:05:46 -05004 * SPDX-License-Identifier: LGPL-2.1+
Richard Hughes4ad41f02018-05-08 14:35:36 +01005 */
6
Richard Hughesb08e7bc2018-09-11 10:51:13 +01007#define G_LOG_DOMAIN "FuInstallTask"
8
Richard Hughes4ad41f02018-05-08 14:35:36 +01009#include "config.h"
10
11#include <fwupd.h>
12
Richard Hughesb3f98412021-03-01 13:17:57 +000013#include "fu-common.h"
Richard Hughes05cbb722018-10-10 20:20:39 +010014#include "fu-common-version.h"
Richard Hughesc02cb832018-05-20 10:31:04 +010015#include "fu-device-private.h"
Richard Hughes4ad41f02018-05-08 14:35:36 +010016#include "fu-install-task.h"
17#include "fu-keyring-utils.h"
18
19struct _FuInstallTask
20{
21 GObject parent_instance;
22 FuDevice *device;
Richard Hughes481aa2a2018-09-18 20:51:46 +010023 XbNode *component;
Richard Hughes245885c2019-03-04 08:46:02 +000024 FwupdReleaseFlags trust_flags;
Richard Hughes4ad41f02018-05-08 14:35:36 +010025 gboolean is_downgrade;
26};
27
28G_DEFINE_TYPE (FuInstallTask, fu_install_task, G_TYPE_OBJECT)
29
30/**
31 * fu_install_task_get_device:
32 * @self: A #FuInstallTask
33 *
34 * Gets the device for this task.
35 *
36 * Returns: (transfer none): the device
37 **/
38FuDevice *
39fu_install_task_get_device (FuInstallTask *self)
40{
41 g_return_val_if_fail (FU_IS_INSTALL_TASK (self), NULL);
42 return self->device;
43}
44
45/**
Richard Hughes481aa2a2018-09-18 20:51:46 +010046 * fu_install_task_get_component:
Richard Hughes4ad41f02018-05-08 14:35:36 +010047 * @self: A #FuInstallTask
48 *
49 * Gets the component for this task.
50 *
51 * Returns: (transfer none): the component
52 **/
Richard Hughes481aa2a2018-09-18 20:51:46 +010053XbNode *
54fu_install_task_get_component (FuInstallTask *self)
Richard Hughes4ad41f02018-05-08 14:35:36 +010055{
56 g_return_val_if_fail (FU_IS_INSTALL_TASK (self), NULL);
Richard Hughes481aa2a2018-09-18 20:51:46 +010057 return self->component;
Richard Hughes4ad41f02018-05-08 14:35:36 +010058}
59
60/**
61 * fu_install_task_get_trust_flags:
62 * @self: A #FuInstallTask
63 *
64 * Gets the trust flags for this task.
65 *
66 * NOTE: This is only set after fu_install_task_check_requirements() has been
67 * called successfully.
68 *
Richard Hughes245885c2019-03-04 08:46:02 +000069 * Returns: the #FwupdReleaseFlags, e.g. #FWUPD_TRUST_FLAG_PAYLOAD
Richard Hughes4ad41f02018-05-08 14:35:36 +010070 **/
Richard Hughes245885c2019-03-04 08:46:02 +000071FwupdReleaseFlags
Richard Hughes4ad41f02018-05-08 14:35:36 +010072fu_install_task_get_trust_flags (FuInstallTask *self)
73{
74 g_return_val_if_fail (FU_IS_INSTALL_TASK (self), FALSE);
75 return self->trust_flags;
76}
77
78/**
79 * fu_install_task_get_is_downgrade:
80 * @self: A #FuInstallTask
81 *
82 * Gets if this task is to downgrade firmware.
83 *
84 * NOTE: This is only set after fu_install_task_check_requirements() has been
85 * called successfully.
86 *
87 * Returns: %TRUE if versions numbers are going backwards
88 **/
89gboolean
90fu_install_task_get_is_downgrade (FuInstallTask *self)
91{
92 g_return_val_if_fail (FU_IS_INSTALL_TASK (self), FALSE);
93 return self->is_downgrade;
94}
95
Richard Hughesdf049ed2019-12-03 13:04:13 +000096static gchar *
97fu_install_task_verfmts_to_string (GPtrArray *verfmts)
98{
99 GString *str = g_string_new (NULL);
100 for (guint i = 0; i < verfmts->len; i++) {
101 XbNode *verfmt = g_ptr_array_index (verfmts, i);
102 const gchar *tmp = xb_node_get_text (verfmt);
103 g_string_append_printf (str, "%s;", tmp);
104 }
105 if (str->len > 0)
106 g_string_truncate (str, str->len - 1);
107 return g_string_free (str, FALSE);
108}
109
110static gboolean
111fu_install_task_check_verfmt (FuInstallTask *self,
112 GPtrArray *verfmts,
113 FwupdInstallFlags flags,
114 GError **error)
115{
116 FwupdVersionFormat fmt_dev = fu_device_get_version_format (self->device);
117 g_autofree gchar *verfmts_str = NULL;
118
119 /* no device format */
120 if (fmt_dev == FWUPD_VERSION_FORMAT_UNKNOWN &&
121 (flags & FWUPD_INSTALL_FLAG_FORCE) == 0) {
122 verfmts_str = fu_install_task_verfmts_to_string (verfmts);
123 g_set_error (error,
124 FWUPD_ERROR,
125 FWUPD_ERROR_NOT_SUPPORTED,
126 "release version format '%s' but no device version format",
127 verfmts_str);
128 return FALSE;
129 }
130
131 /* compare all version formats */
132 for (guint i = 0; i < verfmts->len; i++) {
133 XbNode *verfmt = g_ptr_array_index (verfmts, i);
134 const gchar *tmp = xb_node_get_text (verfmt);
135 FwupdVersionFormat fmt_rel = fwupd_version_format_from_string (tmp);
136 if (fmt_dev == fmt_rel)
137 return TRUE;
138 }
139 verfmts_str = fu_install_task_verfmts_to_string (verfmts);
140 if ((flags & FWUPD_INSTALL_FLAG_FORCE) == 0) {
141 g_set_error (error,
142 FWUPD_ERROR,
143 FWUPD_ERROR_NOT_SUPPORTED,
144 "Firmware version formats were different, "
145 "device was '%s' and release is '%s'",
146 fwupd_version_format_to_string (fmt_dev),
147 verfmts_str);
148 return FALSE;
149 }
150 g_warning ("ignoring version format difference %s:%s",
151 fwupd_version_format_to_string (fmt_dev),
152 verfmts_str);
153 return TRUE;
154}
155
Richard Hughes1eb7c742020-01-07 10:58:32 +0000156static gboolean
157fu_install_task_check_requirements_version_check (FuInstallTask *self, GError **error)
158{
159 g_autoptr(GError) error_local = NULL;
160 g_autoptr(GPtrArray) reqs = NULL;
161
162 reqs = xb_node_query (fu_install_task_get_component (self),
163 "requires/*", 0, &error_local);
164 if (reqs == NULL) {
165 g_set_error_literal (error,
166 FWUPD_ERROR,
167 FWUPD_ERROR_NOT_SUPPORTED,
168 error_local->message);
169 return FALSE;
170 }
171 for (guint i = 0; i < reqs->len; i++) {
172 XbNode *req = g_ptr_array_index (reqs, i);
173 if (g_strcmp0 (xb_node_get_element (req), "firmware") == 0 &&
174 xb_node_get_text (req) == NULL) {
175 return TRUE;
176 }
177 }
178 g_set_error_literal (error,
179 FWUPD_ERROR,
180 FWUPD_ERROR_NOT_SUPPORTED,
181 "no firmware requirement");
182 return FALSE;
183}
184
Richard Hughes4ad41f02018-05-08 14:35:36 +0100185/**
186 * fu_install_task_check_requirements:
187 * @self: A #FuInstallTask
188 * @flags: A #FwupdInstallFlags, e.g. #FWUPD_INSTALL_FLAG_ALLOW_OLDER
189 * @error: A #GError, or %NULL
190 *
191 * Checks any requirements of this task. This will typically involve checking
192 * that the device can accept the component (the GUIDs match) and that the
193 * device can be upgraded with this firmware version.
194 *
195 * Returns: %TRUE if the requirements passed
196 **/
197gboolean
198fu_install_task_check_requirements (FuInstallTask *self,
199 FwupdInstallFlags flags,
200 GError **error)
201{
Richard Hughes5bbf0132020-10-05 13:44:39 +0100202 const gchar *branch_new;
203 const gchar *branch_old;
Mario Limonciellobaa9e752019-12-06 09:21:38 -0600204 const gchar *protocol;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100205 const gchar *version;
Richard Hughes1fbcb1a2019-12-04 15:05:12 +0000206 const gchar *version_release_raw;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100207 const gchar *version_lowest;
208 gboolean matches_guid = FALSE;
209 gint vercmp;
Richard Hughes1fbcb1a2019-12-04 15:05:12 +0000210 g_autofree gchar *version_release = NULL;
Mario Limonciello7d352782018-08-24 11:35:02 -0500211 g_autoptr(GError) error_local = NULL;
Richard Hughes481aa2a2018-09-18 20:51:46 +0100212 g_autoptr(GPtrArray) provides = NULL;
Richard Hughesdf049ed2019-12-03 13:04:13 +0000213 g_autoptr(GPtrArray) verfmts = NULL;
Richard Hughes481aa2a2018-09-18 20:51:46 +0100214 g_autoptr(XbNode) release = NULL;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100215
216 g_return_val_if_fail (FU_IS_INSTALL_TASK (self), FALSE);
217 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
218
Richard Hughes481aa2a2018-09-18 20:51:46 +0100219 /* does this component provide a GUID the device has */
220 provides = xb_node_query (self->component,
221 "provides/firmware[@type='flashed']",
222 0, &error_local);
223 if (provides == NULL) {
224 g_set_error (error,
225 FWUPD_ERROR,
226 FWUPD_ERROR_NOT_FOUND,
227 "No supported devices found: %s",
228 error_local->message);
229 return FALSE;
230 }
Richard Hughes4ad41f02018-05-08 14:35:36 +0100231 for (guint i = 0; i < provides->len; i++) {
Richard Hughes481aa2a2018-09-18 20:51:46 +0100232 XbNode *provide = g_ptr_array_index (provides, i);
233 if (fu_device_has_guid (self->device, xb_node_get_text (provide))) {
Richard Hughes4ad41f02018-05-08 14:35:36 +0100234 matches_guid = TRUE;
235 break;
236 }
237 }
238 if (!matches_guid) {
239 g_set_error_literal (error,
240 FWUPD_ERROR,
241 FWUPD_ERROR_NOT_FOUND,
242 "No supported devices found");
243 return FALSE;
244 }
245
Richard Hughes21eaeef2020-01-14 12:10:01 +0000246 /* device requires a version check */
Richard Hughes1eb7c742020-01-07 10:58:32 +0000247 if (fu_device_has_flag (self->device, FWUPD_DEVICE_FLAG_VERSION_CHECK_REQUIRED)) {
248 if (!fu_install_task_check_requirements_version_check (self, error)) {
249 g_prefix_error (error, "device requires firmware with a version check: ");
250 return FALSE;
251 }
252 }
253
Mario Limonciellobaa9e752019-12-06 09:21:38 -0600254 /* does the protocol match */
255 protocol = xb_node_query_text (self->component,
256 "custom/value[@key='LVFS::UpdateProtocol']",
257 NULL);
Richard Hughesb3f98412021-03-01 13:17:57 +0000258 if (fu_device_get_protocols (self->device)->len != 0 && protocol != NULL &&
259 !fu_device_has_protocol (self->device, protocol) &&
Mario Limonciellobaa9e752019-12-06 09:21:38 -0600260 (flags & FWUPD_INSTALL_FLAG_FORCE) == 0) {
Richard Hughesb3f98412021-03-01 13:17:57 +0000261 g_autofree gchar *str = NULL;
262 str = fu_common_strjoin_array ("|", fu_device_get_protocols (self->device));
Mario Limonciellobaa9e752019-12-06 09:21:38 -0600263 g_set_error (error,
264 FWUPD_ERROR,
265 FWUPD_ERROR_NOT_SUPPORTED,
Richard Hughesd7e3f092020-10-20 18:21:04 +0100266 "Device %s does not support %s, only %s",
Mario Limonciellobaa9e752019-12-06 09:21:38 -0600267 fu_device_get_name (self->device),
Richard Hughesb3f98412021-03-01 13:17:57 +0000268 protocol, str);
Mario Limonciellobaa9e752019-12-06 09:21:38 -0600269 return FALSE;
270 }
271
Richard Hughes4ad41f02018-05-08 14:35:36 +0100272 /* check the device is not locked */
273 if (fu_device_has_flag (self->device, FWUPD_DEVICE_FLAG_LOCKED)) {
274 g_set_error (error,
275 FWUPD_ERROR,
276 FWUPD_ERROR_NOT_SUPPORTED,
Richard Hughes7e77bf32018-05-08 14:56:46 +0100277 "Device %s [%s] is locked",
278 fu_device_get_name (self->device),
Richard Hughes4ad41f02018-05-08 14:35:36 +0100279 fu_device_get_id (self->device));
280 return FALSE;
281 }
282
Richard Hughes5bbf0132020-10-05 13:44:39 +0100283 /* check the branch is not switching */
284 branch_new = xb_node_query_text (self->component, "branch", NULL);
285 branch_old = fu_device_get_branch (self->device);
286 if ((flags & FWUPD_INSTALL_FLAG_ALLOW_BRANCH_SWITCH) == 0 &&
287 g_strcmp0 (branch_old, branch_new) != 0) {
288 g_set_error (error,
289 FWUPD_ERROR,
290 FWUPD_ERROR_NOT_SUPPORTED,
291 "Device %s [%s] would switch firmware branch from %s to %s",
292 fu_device_get_name (self->device),
293 fu_device_get_id (self->device),
294 branch_old != NULL ? branch_old : "default",
295 branch_new != NULL ? branch_new : "default");
296 return FALSE;
297 }
298
Richard Hughes4ad41f02018-05-08 14:35:36 +0100299 /* no update abilities */
Richard Hughes8500b4f2020-04-17 11:47:04 +0100300 if (!fu_device_has_flag (self->device, FWUPD_DEVICE_FLAG_UPDATABLE) &&
301 !fu_device_has_flag (self->device, FWUPD_DEVICE_FLAG_UPDATABLE_HIDDEN)) {
Richard Hughes4ad41f02018-05-08 14:35:36 +0100302 g_set_error (error,
303 FWUPD_ERROR,
304 FWUPD_ERROR_NOT_SUPPORTED,
Richard Hughes7e77bf32018-05-08 14:56:46 +0100305 "Device %s [%s] does not currently allow updates",
306 fu_device_get_name (self->device),
Richard Hughes4ad41f02018-05-08 14:35:36 +0100307 fu_device_get_id (self->device));
308 return FALSE;
309 }
310
311 /* called with online update, test if device is supposed to allow this */
312 if ((flags & FWUPD_INSTALL_FLAG_OFFLINE) == 0 &&
Richard Hughese6280652019-03-24 08:08:32 +0000313 (flags & FWUPD_INSTALL_FLAG_FORCE) == 0 &&
Richard Hughes4ad41f02018-05-08 14:35:36 +0100314 fu_device_has_flag (self->device, FWUPD_DEVICE_FLAG_ONLY_OFFLINE)) {
315 g_set_error (error,
316 FWUPD_ERROR,
317 FWUPD_ERROR_NOT_SUPPORTED,
Richard Hughes7e77bf32018-05-08 14:56:46 +0100318 "Device %s [%s] only allows offline updates",
319 fu_device_get_name (self->device),
Richard Hughes4ad41f02018-05-08 14:35:36 +0100320 fu_device_get_id (self->device));
321 return FALSE;
322 }
323
324 /* get device */
325 version = fu_device_get_version (self->device);
326 if (version == NULL) {
327 g_set_error (error,
328 FWUPD_ERROR,
329 FWUPD_ERROR_INTERNAL,
Richard Hughes7e77bf32018-05-08 14:56:46 +0100330 "Device %s [%s] has no firmware version",
331 fu_device_get_name (self->device),
Richard Hughes4ad41f02018-05-08 14:35:36 +0100332 fu_device_get_id (self->device));
333 return FALSE;
334 }
335
336 /* get latest release */
Richard Hughes481aa2a2018-09-18 20:51:46 +0100337 release = xb_node_query_first (self->component, "releases/release", NULL);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100338 if (release == NULL) {
339 g_set_error (error,
340 FWUPD_ERROR,
341 FWUPD_ERROR_INVALID_FILE,
342 "%s [%s] has no firmware update metadata",
Richard Hughes7e77bf32018-05-08 14:56:46 +0100343 fu_device_get_name (self->device),
344 fu_device_get_id (self->device));
Richard Hughes4ad41f02018-05-08 14:35:36 +0100345 return FALSE;
346 }
347
348 /* is this a downgrade or re-install */
Richard Hughes1fbcb1a2019-12-04 15:05:12 +0000349 version_release_raw = xb_node_get_attr (release, "version");
350 if (version_release_raw == NULL) {
Richard Hughes4ad41f02018-05-08 14:35:36 +0100351 g_set_error_literal (error,
352 FWUPD_ERROR,
353 FWUPD_ERROR_INVALID_FILE,
354 "Release has no firmware version");
355 return FALSE;
356 }
357
Richard Hughes5079f262019-04-29 09:34:27 +0100358 /* check the version formats match if set in the release */
Richard Hughes5bbf0132020-10-05 13:44:39 +0100359 if ((flags & FWUPD_INSTALL_FLAG_FORCE) == 0 &&
360 (flags & FWUPD_INSTALL_FLAG_ALLOW_BRANCH_SWITCH) == 0) {
Mario Limonciello537da0e2020-03-09 15:38:17 -0500361 verfmts = xb_node_query (self->component,
362 "custom/value[@key='LVFS::VersionFormat']",
363 0, NULL);
364 if (verfmts != NULL) {
365 if (!fu_install_task_check_verfmt (self, verfmts, flags, error))
366 return FALSE;
367 }
Richard Hughesce3cea82019-04-08 11:31:21 +0100368 }
369
Richard Hughes4ad41f02018-05-08 14:35:36 +0100370 /* compare to the lowest supported version, if it exists */
371 version_lowest = fu_device_get_version_lowest (self->device);
Mario Limoncielloda0e90f2018-09-04 23:15:56 -0500372 if (version_lowest != NULL &&
Richard Hughes9a680842020-02-20 11:11:13 +0000373 fu_common_vercmp_full (version_lowest, version,
374 fu_device_get_version_format (self->device)) > 0 &&
Mario Limoncielloda0e90f2018-09-04 23:15:56 -0500375 (flags & FWUPD_INSTALL_FLAG_FORCE) == 0) {
Richard Hughes4ad41f02018-05-08 14:35:36 +0100376 g_set_error (error,
377 FWUPD_ERROR,
378 FWUPD_ERROR_VERSION_NEWER,
379 "Specified firmware is older than the minimum "
Mario Limonciello14c823e2018-09-04 23:13:24 -0500380 "required version '%s < %s'", version, version_lowest);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100381 return FALSE;
382 }
383
384 /* check semver */
Richard Hughes1de7cc92020-02-13 09:41:57 +0000385 if (fu_device_get_version_format (self->device) == FWUPD_VERSION_FORMAT_PLAIN) {
386 version_release = g_strdup (version_release_raw);
Richard Hughes1de7cc92020-02-13 09:41:57 +0000387 } else {
388 version_release = fu_common_version_parse_from_format (version_release_raw,
389 fu_device_get_version_format (self->device));
Richard Hughes1de7cc92020-02-13 09:41:57 +0000390 }
Richard Hughes9a680842020-02-20 11:11:13 +0000391 vercmp = fu_common_vercmp_full (version, version_release,
392 fu_device_get_version_format (self->device));
Richard Hughes4ad41f02018-05-08 14:35:36 +0100393 if (vercmp == 0 && (flags & FWUPD_INSTALL_FLAG_ALLOW_REINSTALL) == 0) {
394 g_set_error (error,
395 FWUPD_ERROR,
396 FWUPD_ERROR_VERSION_SAME,
397 "Specified firmware is already installed '%s'",
398 version_release);
399 return FALSE;
400 }
401 self->is_downgrade = vercmp > 0;
Richard Hughes5bbf0132020-10-05 13:44:39 +0100402 if (self->is_downgrade &&
403 (flags & FWUPD_INSTALL_FLAG_ALLOW_OLDER) == 0 &&
404 (flags & FWUPD_INSTALL_FLAG_ALLOW_BRANCH_SWITCH) == 0) {
Richard Hughes4ad41f02018-05-08 14:35:36 +0100405 g_set_error (error,
406 FWUPD_ERROR,
407 FWUPD_ERROR_VERSION_NEWER,
408 "Specified firmware is older than installed '%s < %s'",
409 version_release, version);
410 return FALSE;
411 }
412
413 /* verify */
Richard Hughes245885c2019-03-04 08:46:02 +0000414 if (!fu_keyring_get_release_flags (release, &self->trust_flags, &error_local)) {
Mario Limonciello7d352782018-08-24 11:35:02 -0500415 if (g_error_matches (error_local, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED)) {
416 g_warning ("Ignoring verification for %s: %s",
417 fu_device_get_name (self->device),
418 error_local->message);
419 } else {
420 g_propagate_error (error, g_steal_pointer (&error_local));
421 return FALSE;
422 }
423 }
424 return TRUE;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100425}
426
427/**
428 * fu_install_task_get_action_id:
429 * @self: A #FuEngine
430 *
431 * Gets the PolicyKit action ID to use for the install operation.
432 *
433 * Returns: string, e.g. `org.freedesktop.fwupd.update-internal-trusted`
434 **/
435const gchar *
436fu_install_task_get_action_id (FuInstallTask *self)
437{
438 /* relax authentication checks for removable devices */
439 if (!fu_device_has_flag (self->device, FWUPD_DEVICE_FLAG_INTERNAL)) {
440 if (self->is_downgrade)
441 return "org.freedesktop.fwupd.downgrade-hotplug";
442 if (self->trust_flags & FWUPD_TRUST_FLAG_PAYLOAD)
443 return "org.freedesktop.fwupd.update-hotplug-trusted";
444 return "org.freedesktop.fwupd.update-hotplug";
445 }
446
447 /* internal device */
448 if (self->is_downgrade)
449 return "org.freedesktop.fwupd.downgrade-internal";
450 if (self->trust_flags & FWUPD_TRUST_FLAG_PAYLOAD)
451 return "org.freedesktop.fwupd.update-internal-trusted";
452 return "org.freedesktop.fwupd.update-internal";
453}
454
455static void
456fu_install_task_init (FuInstallTask *self)
457{
458 self->trust_flags = FWUPD_TRUST_FLAG_NONE;
459}
460
461static void
462fu_install_task_finalize (GObject *object)
463{
464 FuInstallTask *self = FU_INSTALL_TASK (object);
465
Richard Hughes10fffc72020-04-16 14:05:02 +0100466 if (self->component != NULL)
467 g_object_unref (self->component);
Richard Hughes1d1f5cf2018-05-19 23:06:03 +0100468 if (self->device != NULL)
469 g_object_unref (self->device);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100470
471 G_OBJECT_CLASS (fu_install_task_parent_class)->finalize (object);
472}
473
474static void
475fu_install_task_class_init (FuInstallTaskClass *klass)
476{
477 GObjectClass *object_class = G_OBJECT_CLASS (klass);
478 object_class->finalize = fu_install_task_finalize;
479}
480
481/**
Richard Hughesc02cb832018-05-20 10:31:04 +0100482 * fu_install_task_compare:
483 * @task1: first #FuInstallTask to compare.
484 * @task2: second #FuInstallTask to compare.
485 *
486 * Compares two install tasks.
487 *
488 * Returns: 1, 0 or -1 if @task1 is greater, equal, or less than @task2, respectively.
489 **/
490gint
491fu_install_task_compare (FuInstallTask *task1, FuInstallTask *task2)
492{
493 FuDevice *device1 = fu_install_task_get_device (task1);
494 FuDevice *device2 = fu_install_task_get_device (task2);
495 if (fu_device_get_order (device1) < fu_device_get_order (device2))
496 return -1;
497 if (fu_device_get_order (device1) > fu_device_get_order (device2))
498 return 1;
499 return 0;
500}
501
502/**
Richard Hughes4ad41f02018-05-08 14:35:36 +0100503 * fu_install_task_new:
504 * @device: A #FuDevice
Richard Hughes481aa2a2018-09-18 20:51:46 +0100505 * @component: a #XbNode
Richard Hughes4ad41f02018-05-08 14:35:36 +0100506 *
507 * Creates a new install task that may or may not be valid.
508 *
509 * Returns: (transfer full): the #FuInstallTask
510 **/
511FuInstallTask *
Richard Hughes481aa2a2018-09-18 20:51:46 +0100512fu_install_task_new (FuDevice *device, XbNode *component)
Richard Hughes4ad41f02018-05-08 14:35:36 +0100513{
514 FuInstallTask *self;
515 self = g_object_new (FU_TYPE_TASK, NULL);
Richard Hughes10fffc72020-04-16 14:05:02 +0100516 if (component != NULL)
517 self->component = g_object_ref (component);
Richard Hughes1d1f5cf2018-05-19 23:06:03 +0100518 if (device != NULL)
519 self->device = g_object_ref (device);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100520 return FU_INSTALL_TASK (self);
521}