From ce3cea8cb49bee10078d72b835792a18b85f6be5 Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Mon, 8 Apr 2019 11:31:21 +0100 Subject: [PATCH] Require --force to install a release with a different version format If the user is trying to install version '20190104' on something with the existing version '1.2.3' then something has gone wrong. Ensure the device release version format matches the release version format and fail to apply the update if this is not true. In the common case setting the version with fu_device_set_version('1.2.3') would set the version format to TRIPLET, and setting so no action is required. In cases where the version format could be ambiguous then the format should be set both in a quirk and also in the metainfo file. --- src/fu-install-task.c | 35 ++++++++++++++++++++++++++++++++ src/fu-self-test.c | 47 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/src/fu-install-task.c b/src/fu-install-task.c index 1ef286b58..5e44db5bd 100644 --- a/src/fu-install-task.c +++ b/src/fu-install-task.c @@ -92,6 +92,20 @@ fu_install_task_get_is_downgrade (FuInstallTask *self) return self->is_downgrade; } +static FuVersionFormat +fu_install_task_guess_version_format (FuInstallTask *self, const gchar *version) +{ + const gchar *tmp; + + /* explicit set */ + tmp = xb_node_query_text (self->component, "custom/value[@key='LVFS::VersionFormat']", NULL); + if (tmp != NULL) + return fu_common_version_format_from_string (tmp); + + /* count section from dotted notation */ + return fu_common_version_guess_format (version); +} + /** * fu_install_task_check_requirements: * @self: A #FuInstallTask @@ -109,6 +123,7 @@ fu_install_task_check_requirements (FuInstallTask *self, FwupdInstallFlags flags, GError **error) { + FuVersionFormat fmt; const gchar *version; const gchar *version_release; const gchar *version_lowest; @@ -217,6 +232,26 @@ fu_install_task_check_requirements (FuInstallTask *self, return FALSE; } + /* check the version formats match */ + fmt = fu_install_task_guess_version_format (self, version_release); + if (fmt != fu_device_get_version_format (self->device)) { + FuVersionFormat fmt_dev = fu_device_get_version_format (self->device); + if (flags & FWUPD_INSTALL_FLAG_FORCE) { + g_warning ("ignoring version format difference %s:%s", + fu_common_version_format_to_string (fmt_dev), + fu_common_version_format_to_string (fmt)); + } else { + g_set_error (error, + FWUPD_ERROR, + FWUPD_ERROR_NOT_SUPPORTED, + "Firmware version formats were different, " + "device was '%s' and release is '%s'", + fu_common_version_format_to_string (fmt_dev), + fu_common_version_format_to_string (fmt)); + return FALSE; + } + } + /* compare to the lowest supported version, if it exists */ version_lowest = fu_device_get_version_lowest (self->device); if (version_lowest != NULL && diff --git a/src/fu-self-test.c b/src/fu-self-test.c index 3b6e2a310..8553487f0 100644 --- a/src/fu-self-test.c +++ b/src/fu-self-test.c @@ -433,6 +433,52 @@ fu_engine_requirements_device_func (void) g_assert (ret); } +static void +fu_engine_requirements_version_format_func (void) +{ + gboolean ret; + g_autoptr(FuDevice) device = fu_device_new (); + g_autoptr(FuEngine) engine = fu_engine_new (FU_APP_FLAGS_NONE); + g_autoptr(FuInstallTask) task = NULL; + g_autoptr(GError) error = NULL; + g_autoptr(XbNode) component = NULL; + g_autoptr(XbSilo) silo = NULL; + const gchar *xml = + "" + " " + " 12345678-1234-1234-1234-123456789012" + " " + " " + " " + " " + " " + " " + ""; + + /* set up a dummy device */ + fu_device_set_version (device, "1.2.3.4"); + fu_device_add_flag (device, FWUPD_DEVICE_FLAG_UPDATABLE); + fu_device_add_guid (device, "12345678-1234-1234-1234-123456789012"); + + /* make the component require three things */ + silo = xb_silo_new_from_xml (xml, &error); + g_assert_no_error (error); + g_assert_nonnull (silo); + component = xb_silo_query_first (silo, "component", &error); + g_assert_no_error (error); + g_assert_nonnull (component); + + /* check this fails */ + task = fu_install_task_new (device, component); + ret = fu_engine_check_requirements (engine, task, + FWUPD_INSTALL_FLAG_NONE, + &error); + g_assert_error (error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED); + g_assert_nonnull (g_strstr_len (error->message, -1, + "Firmware version formats were different")); + g_assert (!ret); +} + static void fu_engine_requirements_other_device_func (void) { @@ -3664,6 +3710,7 @@ main (int argc, char **argv) g_test_add_func ("/fwupd/engine{requirements-not-child-fail}", fu_engine_requirements_child_fail_func); g_test_add_func ("/fwupd/engine{requirements-unsupported}", fu_engine_requirements_unsupported_func); g_test_add_func ("/fwupd/engine{requirements-device}", fu_engine_requirements_device_func); + g_test_add_func ("/fwupd/engine{requirements-version-format}", fu_engine_requirements_version_format_func); g_test_add_func ("/fwupd/engine{device-auto-parent}", fu_engine_device_parent_func); g_test_add_func ("/fwupd/engine{device-priority}", fu_engine_device_priority_func); g_test_add_func ("/fwupd/engine{install-duration}", fu_engine_install_duration_func);