mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-05 12:12:48 +00:00
Don't use AppStream-glib for version helpers
Refactor the imported version format code now we now longer need to stick to the API mistakes of libappstream-glib.
This commit is contained in:
parent
d3d2c2c39f
commit
05cbb7245c
@ -232,7 +232,7 @@ fu_plugin_dell_inject_fake_data (FuPlugin *plugin,
|
||||
data->can_switch_modes = TRUE;
|
||||
}
|
||||
|
||||
static AsVersionParseFlag
|
||||
static FuVersionFormat
|
||||
fu_plugin_dell_get_version_format (FuPlugin *plugin)
|
||||
{
|
||||
const gchar *content;
|
||||
@ -241,17 +241,15 @@ fu_plugin_dell_get_version_format (FuPlugin *plugin)
|
||||
|
||||
content = fu_plugin_get_dmi_value (plugin, FU_HWIDS_KEY_MANUFACTURER);
|
||||
if (content == NULL)
|
||||
return AS_VERSION_PARSE_FLAG_USE_TRIPLET;
|
||||
return FU_VERSION_FORMAT_TRIPLET;
|
||||
|
||||
/* any quirks match */
|
||||
group = g_strdup_printf ("SmbiosManufacturer=%s", content);
|
||||
quirk = fu_plugin_lookup_quirk_by_id (plugin, group,
|
||||
FU_QUIRKS_UEFI_VERSION_FORMAT);
|
||||
if (g_strcmp0 (quirk, "quad") == 0)
|
||||
return AS_VERSION_PARSE_FLAG_NONE;
|
||||
|
||||
/* fall back */
|
||||
return AS_VERSION_PARSE_FLAG_USE_TRIPLET;
|
||||
if (quirk == NULL)
|
||||
return FU_VERSION_FORMAT_TRIPLET;
|
||||
return fu_common_version_format_from_string (quirk);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -319,7 +317,7 @@ fu_plugin_usb_device_added (FuPlugin *plugin,
|
||||
GError **error)
|
||||
{
|
||||
FuPluginData *data = fu_plugin_get_data (plugin);
|
||||
AsVersionParseFlag parse_flags;
|
||||
FuVersionFormat version_format;
|
||||
guint16 pid;
|
||||
guint16 vid;
|
||||
const gchar *query_str;
|
||||
@ -372,7 +370,7 @@ fu_plugin_usb_device_added (FuPlugin *plugin,
|
||||
g_debug ("Dock cable type: %" G_GUINT32_FORMAT, dock_info->cable_type);
|
||||
g_debug ("Dock location: %d", dock_info->location);
|
||||
g_debug ("Dock component count: %d", dock_info->component_count);
|
||||
parse_flags = fu_plugin_dell_get_version_format (plugin);
|
||||
version_format = fu_plugin_dell_get_version_format (plugin);
|
||||
|
||||
for (guint i = 0; i < dock_info->component_count; i++) {
|
||||
g_autofree gchar *fw_str = NULL;
|
||||
@ -411,8 +409,8 @@ fu_plugin_usb_device_added (FuPlugin *plugin,
|
||||
continue;
|
||||
}
|
||||
|
||||
fw_str = as_utils_version_from_uint32 (dock_info->components[i].fw_version,
|
||||
parse_flags);
|
||||
fw_str = fu_common_version_from_uint32 (dock_info->components[i].fw_version,
|
||||
version_format);
|
||||
if (!fu_plugin_dock_node (plugin,
|
||||
platform,
|
||||
buf.record->dock_info_header.dock_type,
|
||||
@ -427,8 +425,8 @@ fu_plugin_usb_device_added (FuPlugin *plugin,
|
||||
|
||||
/* if an old EC or invalid EC version found, create updatable parent */
|
||||
if (old_ec)
|
||||
flash_ver_str = as_utils_version_from_uint32 (dock_info->flash_pkg_version,
|
||||
parse_flags);
|
||||
flash_ver_str = fu_common_version_from_uint32 (dock_info->flash_pkg_version,
|
||||
version_format);
|
||||
if (!fu_plugin_dock_node (plugin,
|
||||
platform,
|
||||
buf.record->dock_info_header.dock_type,
|
||||
@ -607,8 +605,8 @@ fu_plugin_dell_detect_tpm (FuPlugin *plugin, GError **error)
|
||||
|
||||
g_debug ("Creating primary TPM GUID %s and secondary TPM GUID %s",
|
||||
tpm_guid_raw, tpm_guid_raw_alt);
|
||||
version_str = as_utils_version_from_uint32 (out->fw_version,
|
||||
AS_VERSION_PARSE_FLAG_NONE);
|
||||
version_str = fu_common_version_from_uint32 (out->fw_version,
|
||||
FU_VERSION_FORMAT_QUAD);
|
||||
|
||||
/* make it clear that the TPM is a discrete device of the product */
|
||||
if (!data->smi_obj->fake_smbios) {
|
||||
|
@ -21,7 +21,8 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <appstream-glib.h>
|
||||
|
||||
#include "fu-common-version.h"
|
||||
|
||||
#include "dfu-common.h"
|
||||
#include "dfu-firmware.h"
|
||||
@ -642,8 +643,8 @@ dfu_firmware_to_string (DfuFirmware *firmware)
|
||||
|
||||
g_return_val_if_fail (DFU_IS_FIRMWARE (firmware), NULL);
|
||||
|
||||
release_str = as_utils_version_from_uint16 (priv->release,
|
||||
AS_VERSION_PARSE_FLAG_USE_BCD);
|
||||
release_str = fu_common_version_from_uint16 (priv->release,
|
||||
FU_VERSION_FORMAT_BCD);
|
||||
str = g_string_new ("");
|
||||
g_string_append_printf (str, "vid: 0x%04x\n", priv->vid);
|
||||
g_string_append_printf (str, "pid: 0x%04x\n", priv->pid);
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <glib-unix.h>
|
||||
#include <appstream-glib.h>
|
||||
|
||||
#include "dfu-cipher-xtea.h"
|
||||
#include "dfu-device-private.h"
|
||||
@ -2036,8 +2035,8 @@ dfu_tool_list (DfuToolPrivate *priv, gchar **values, GError **error)
|
||||
dfu_device_set_usb_context (device, usb_context);
|
||||
if (!fu_device_probe (FU_DEVICE (device), NULL))
|
||||
continue;
|
||||
version = as_utils_version_from_uint16 (g_usb_device_get_release (usb_device),
|
||||
AS_VERSION_PARSE_FLAG_USE_BCD);
|
||||
version = fu_common_version_from_uint16 (g_usb_device_get_release (usb_device),
|
||||
FU_VERSION_FORMAT_BCD);
|
||||
g_print ("%s %04x:%04x [v%s]:\n",
|
||||
/* TRANSLATORS: detected a DFU device */
|
||||
_("Found"),
|
||||
|
@ -6,8 +6,6 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <appstream-glib.h>
|
||||
|
||||
#include "fu-plugin-vfuncs.h"
|
||||
|
||||
#include "dfu-device.h"
|
||||
|
@ -203,7 +203,7 @@ fu_nvme_device_set_version (FuNvmeDevice *self, const gchar *version, GError **e
|
||||
version);
|
||||
return FALSE;
|
||||
}
|
||||
version_new = as_utils_version_from_uint32 (tmp, AS_VERSION_PARSE_FLAG_NONE);
|
||||
version_new = as_utils_version_from_uint32 (tmp, FU_VERSION_FORMAT_QUAD);
|
||||
fu_device_set_version (FU_DEVICE (self), version_new);
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -412,7 +412,7 @@ fu_plugin_device_registered (FuPlugin *plugin, FuDevice *device)
|
||||
}
|
||||
}
|
||||
|
||||
static AsVersionParseFlag
|
||||
static FuVersionFormat
|
||||
fu_plugin_uefi_get_version_format_for_type (FuPlugin *plugin, FuUefiDeviceKind device_kind)
|
||||
{
|
||||
const gchar *content;
|
||||
@ -421,21 +421,19 @@ fu_plugin_uefi_get_version_format_for_type (FuPlugin *plugin, FuUefiDeviceKind d
|
||||
|
||||
/* we have no information for devices */
|
||||
if (device_kind == FU_UEFI_DEVICE_KIND_DEVICE_FIRMWARE)
|
||||
return AS_VERSION_PARSE_FLAG_USE_TRIPLET;
|
||||
return FU_VERSION_FORMAT_TRIPLET;
|
||||
|
||||
content = fu_plugin_get_dmi_value (plugin, FU_HWIDS_KEY_MANUFACTURER);
|
||||
if (content == NULL)
|
||||
return AS_VERSION_PARSE_FLAG_USE_TRIPLET;
|
||||
return FU_VERSION_FORMAT_TRIPLET;
|
||||
|
||||
/* any quirks match */
|
||||
group = g_strdup_printf ("SmbiosManufacturer=%s", content);
|
||||
quirk = fu_plugin_lookup_quirk_by_id (plugin, group,
|
||||
FU_QUIRKS_UEFI_VERSION_FORMAT);
|
||||
if (g_strcmp0 (quirk, "quad") == 0)
|
||||
return AS_VERSION_PARSE_FLAG_NONE;
|
||||
|
||||
/* fall back */
|
||||
return AS_VERSION_PARSE_FLAG_USE_TRIPLET;
|
||||
if (quirk == NULL)
|
||||
return FU_VERSION_FORMAT_TRIPLET;
|
||||
return fu_common_version_format_from_string (quirk);
|
||||
}
|
||||
|
||||
static const gchar *
|
||||
@ -478,7 +476,7 @@ static gboolean
|
||||
fu_plugin_uefi_coldplug_device (FuPlugin *plugin, FuUefiDevice *dev, GError **error)
|
||||
{
|
||||
FuUefiDeviceKind device_kind;
|
||||
AsVersionParseFlag parse_flags;
|
||||
FuVersionFormat version_format;
|
||||
guint32 version_raw;
|
||||
g_autofree gchar *name = NULL;
|
||||
g_autofree gchar *version_lowest = NULL;
|
||||
@ -486,17 +484,17 @@ fu_plugin_uefi_coldplug_device (FuPlugin *plugin, FuUefiDevice *dev, GError **er
|
||||
|
||||
/* add details to the device */
|
||||
device_kind = fu_uefi_device_get_kind (dev);
|
||||
parse_flags = fu_plugin_uefi_get_version_format_for_type (plugin, device_kind);
|
||||
version_format = fu_plugin_uefi_get_version_format_for_type (plugin, device_kind);
|
||||
version_raw = fu_uefi_device_get_version (dev);
|
||||
version = as_utils_version_from_uint32 (version_raw, parse_flags);
|
||||
version = fu_common_version_from_uint32 (version_raw, version_format);
|
||||
fu_device_set_version (dev, version);
|
||||
name = fu_plugin_uefi_get_name_for_type (plugin, fu_uefi_device_get_kind (dev));
|
||||
if (name != NULL)
|
||||
fu_device_set_name (FU_DEVICE (dev), name);
|
||||
version_raw = fu_uefi_device_get_version_lowest (dev);
|
||||
if (version_raw != 0) {
|
||||
version_lowest = as_utils_version_from_uint32 (version_raw,
|
||||
parse_flags);
|
||||
version_lowest = fu_common_version_from_uint32 (version_raw,
|
||||
version_format);
|
||||
fu_device_set_version_lowest (FU_DEVICE (dev), version_lowest);
|
||||
}
|
||||
fu_device_add_flag (FU_DEVICE (dev), FWUPD_DEVICE_FLAG_INTERNAL);
|
||||
|
307
src/fu-common-version.c
Normal file
307
src/fu-common-version.c
Normal file
@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2018 Richard Hughes <richard@hughsie.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "FuCommon"
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "fwupd-error.h"
|
||||
|
||||
#include "fu-common-version.h"
|
||||
|
||||
#define FU_COMMON_VERSION_DECODE_BCD(val) ((((val) >> 4) & 0x0f) * 10 + ((val) & 0x0f))
|
||||
|
||||
/**
|
||||
* fu_common_version_format_from_string:
|
||||
* @str: A string, e.g. `quad`
|
||||
*
|
||||
* Converts text to a display version type.
|
||||
*
|
||||
* Returns: A #FuVersionFormat, e.g. %FU_VERSION_FORMAT_TRIPLET
|
||||
*
|
||||
* Since: 1.2.0
|
||||
**/
|
||||
FuVersionFormat
|
||||
fu_common_version_format_from_string (const gchar *str)
|
||||
{
|
||||
if (g_strcmp0 (str, "triplet") == 0)
|
||||
return FU_VERSION_FORMAT_TRIPLET;
|
||||
if (g_strcmp0 (str, "quad") == 0)
|
||||
return FU_VERSION_FORMAT_QUAD;
|
||||
if (g_strcmp0 (str, "bcd") == 0)
|
||||
return FU_VERSION_FORMAT_BCD;
|
||||
if (g_strcmp0 (str, "plain") == 0)
|
||||
return FU_VERSION_FORMAT_PLAIN;
|
||||
return FU_VERSION_FORMAT_QUAD;
|
||||
}
|
||||
|
||||
/**
|
||||
* fu_common_version_format_to_string:
|
||||
* @str: A #FuVersionFormat, e.g. %FU_VERSION_FORMAT_TRIPLET
|
||||
*
|
||||
* Converts a display version type to text.
|
||||
*
|
||||
* Returns: A string, e.g. `quad`, or %NULL if not known
|
||||
*
|
||||
* Since: 1.2.0
|
||||
**/
|
||||
const gchar *
|
||||
fu_common_version_format_to_string (FuVersionFormat kind)
|
||||
{
|
||||
if (kind == FU_VERSION_FORMAT_TRIPLET)
|
||||
return "triplet";
|
||||
if (kind == FU_VERSION_FORMAT_QUAD)
|
||||
return "quad";
|
||||
if (kind == FU_VERSION_FORMAT_BCD)
|
||||
return "bcd";
|
||||
if (kind == FU_VERSION_FORMAT_PLAIN)
|
||||
return "plain";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* fu_common_version_from_uint32:
|
||||
* @val: A uint32le version number
|
||||
* @kind: version kind used for formatting, e.g. %FU_VERSION_FORMAT_TRIPLET
|
||||
*
|
||||
* Returns a dotted decimal version string from a 32 bit number.
|
||||
*
|
||||
* Returns: A version number, e.g. "1.0.3", or %NULL if not supported
|
||||
*
|
||||
* Since: 1.2.0
|
||||
**/
|
||||
gchar *
|
||||
fu_common_version_from_uint32 (guint32 val, FuVersionFormat kind)
|
||||
{
|
||||
if (kind == FU_VERSION_FORMAT_QUAD) {
|
||||
/* AA.BB.CC.DD */
|
||||
return g_strdup_printf ("%u.%u.%u.%u",
|
||||
(val >> 24) & 0xff,
|
||||
(val >> 16) & 0xff,
|
||||
(val >> 8) & 0xff,
|
||||
val & 0xff);
|
||||
}
|
||||
if (kind == FU_VERSION_FORMAT_TRIPLET) {
|
||||
/* AA.BB.CCDD */
|
||||
return g_strdup_printf ("%u.%u.%u",
|
||||
(val >> 24) & 0xff,
|
||||
(val >> 16) & 0xff,
|
||||
val & 0xffff);
|
||||
}
|
||||
if (kind == FU_VERSION_FORMAT_PAIR) {
|
||||
/* AABB.CCDD */
|
||||
return g_strdup_printf ("%u.%u",
|
||||
(val >> 16) & 0xffff,
|
||||
val & 0xffff);
|
||||
}
|
||||
if (kind == FU_VERSION_FORMAT_PLAIN) {
|
||||
/* AABBCCDD */
|
||||
return g_strdup_printf ("%" G_GUINT32_FORMAT, val);
|
||||
}
|
||||
if (kind == FU_VERSION_FORMAT_BCD) {
|
||||
/* AA.BB.CC.DD, but BCD */
|
||||
return g_strdup_printf ("%u.%u.%u.%u",
|
||||
FU_COMMON_VERSION_DECODE_BCD(val >> 24),
|
||||
FU_COMMON_VERSION_DECODE_BCD(val >> 16),
|
||||
FU_COMMON_VERSION_DECODE_BCD(val >> 8),
|
||||
FU_COMMON_VERSION_DECODE_BCD(val));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* fu_common_version_from_uint16:
|
||||
* @val: A uint16le version number
|
||||
* @kind: version kind used for formatting, e.g. %FU_VERSION_FORMAT_TRIPLET
|
||||
*
|
||||
* Returns a dotted decimal version string from a 16 bit number.
|
||||
*
|
||||
* Returns: A version number, e.g. "1.3", or %NULL if not supported
|
||||
*
|
||||
* Since: 1.2.0
|
||||
**/
|
||||
gchar *
|
||||
fu_common_version_from_uint16 (guint16 val, FuVersionFormat kind)
|
||||
{
|
||||
if (kind == FU_VERSION_FORMAT_BCD) {
|
||||
return g_strdup_printf ("%i.%i",
|
||||
FU_COMMON_VERSION_DECODE_BCD(val >> 8),
|
||||
FU_COMMON_VERSION_DECODE_BCD(val));
|
||||
}
|
||||
if (kind == FU_VERSION_FORMAT_PAIR) {
|
||||
return g_strdup_printf ("%u.%u",
|
||||
(guint) (val >> 8) & 0xff,
|
||||
(guint) val & 0xff);
|
||||
}
|
||||
if (kind == FU_VERSION_FORMAT_PLAIN) {
|
||||
return g_strdup_printf ("%" G_GUINT16_FORMAT, val);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gint
|
||||
fu_common_vercmp_char (gchar chr1, gchar chr2)
|
||||
{
|
||||
if (chr1 == chr2)
|
||||
return 0;
|
||||
if (chr1 == '~')
|
||||
return -1;
|
||||
if (chr2 == '~')
|
||||
return 1;
|
||||
return chr1 < chr2 ? -1 : 1;
|
||||
}
|
||||
|
||||
static gint
|
||||
fu_common_vercmp_chunk (const gchar *str1, const gchar *str2)
|
||||
{
|
||||
guint i;
|
||||
|
||||
/* trivial */
|
||||
if (g_strcmp0 (str1, str2) == 0)
|
||||
return 0;
|
||||
if (str1 == NULL)
|
||||
return 1;
|
||||
if (str2 == NULL)
|
||||
return -1;
|
||||
|
||||
/* check each char of the chunk */
|
||||
for (i = 0; str1[i] != '\0' && str2[i] != '\0'; i++) {
|
||||
gint rc = fu_common_vercmp_char (str1[i], str2[i]);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
}
|
||||
return fu_common_vercmp_char (str1[i], str2[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* fu_common_version_parse:
|
||||
* @version: A version number
|
||||
*
|
||||
* Returns a dotted decimal version string from a version string. The supported
|
||||
* formats are:
|
||||
*
|
||||
* - Dotted decimal, e.g. "1.2.3"
|
||||
* - Base 16, a hex number *with* a 0x prefix, e.g. "0x10203"
|
||||
* - Base 10, a string containing just [0-9], e.g. "66051"
|
||||
* - Date in YYYYMMDD format, e.g. 20150915
|
||||
*
|
||||
* Anything with a '.' or that doesn't match [0-9] or 0x[a-f,0-9] is considered
|
||||
* a string and returned without modification.
|
||||
*
|
||||
* Returns: A version number, e.g. "1.0.3"
|
||||
*
|
||||
* Since: 1.2.0
|
||||
*/
|
||||
gchar *
|
||||
fu_common_version_parse (const gchar *version)
|
||||
{
|
||||
const gchar *version_noprefix = version;
|
||||
gchar *endptr = NULL;
|
||||
guint64 tmp;
|
||||
guint base;
|
||||
guint i;
|
||||
|
||||
/* already dotted decimal */
|
||||
if (g_strstr_len (version, -1, ".") != NULL)
|
||||
return g_strdup (version);
|
||||
|
||||
/* is a date */
|
||||
if (g_str_has_prefix (version, "20") &&
|
||||
strlen (version) == 8)
|
||||
return g_strdup (version);
|
||||
|
||||
/* convert 0x prefixed strings to dotted decimal */
|
||||
if (g_str_has_prefix (version, "0x")) {
|
||||
version_noprefix += 2;
|
||||
base = 16;
|
||||
} else {
|
||||
/* for non-numeric content, just return the string */
|
||||
for (i = 0; version[i] != '\0'; i++) {
|
||||
if (!g_ascii_isdigit (version[i]))
|
||||
return g_strdup (version);
|
||||
}
|
||||
base = 10;
|
||||
}
|
||||
|
||||
/* convert */
|
||||
tmp = g_ascii_strtoull (version_noprefix, &endptr, base);
|
||||
if (endptr != NULL && endptr[0] != '\0')
|
||||
return g_strdup (version);
|
||||
if (tmp == 0)
|
||||
return g_strdup (version);
|
||||
return fu_common_version_from_uint32 ((guint32) tmp, FU_VERSION_FORMAT_TRIPLET);
|
||||
}
|
||||
|
||||
/**
|
||||
* fu_common_vercmp:
|
||||
* @version_a: the release version, e.g. 1.2.3
|
||||
* @version_b: the release version, e.g. 1.2.3.1
|
||||
*
|
||||
* Compares version numbers for sorting.
|
||||
*
|
||||
* Returns: -1 if a < b, +1 if a > b, 0 if they are equal, and %G_MAXINT on error
|
||||
*
|
||||
* Since: 0.3.5
|
||||
*/
|
||||
gint
|
||||
fu_common_vercmp (const gchar *version_a, const gchar *version_b)
|
||||
{
|
||||
guint longest_split;
|
||||
g_autofree gchar *str_a = NULL;
|
||||
g_autofree gchar *str_b = NULL;
|
||||
g_auto(GStrv) split_a = NULL;
|
||||
g_auto(GStrv) split_b = NULL;
|
||||
|
||||
/* sanity check */
|
||||
if (version_a == NULL || version_b == NULL)
|
||||
return G_MAXINT;
|
||||
|
||||
/* optimisation */
|
||||
if (g_strcmp0 (version_a, version_b) == 0)
|
||||
return 0;
|
||||
|
||||
/* split into sections, and try to parse */
|
||||
str_a = fu_common_version_parse (version_a);
|
||||
str_b = fu_common_version_parse (version_b);
|
||||
split_a = g_strsplit (str_a, ".", -1);
|
||||
split_b = g_strsplit (str_b, ".", -1);
|
||||
longest_split = MAX (g_strv_length (split_a), g_strv_length (split_b));
|
||||
for (guint i = 0; i < longest_split; i++) {
|
||||
gchar *endptr_a = NULL;
|
||||
gchar *endptr_b = NULL;
|
||||
gint64 ver_a;
|
||||
gint64 ver_b;
|
||||
|
||||
/* we lost or gained a dot */
|
||||
if (split_a[i] == NULL)
|
||||
return -1;
|
||||
if (split_b[i] == NULL)
|
||||
return 1;
|
||||
|
||||
/* compare integers */
|
||||
ver_a = g_ascii_strtoll (split_a[i], &endptr_a, 10);
|
||||
ver_b = g_ascii_strtoll (split_b[i], &endptr_b, 10);
|
||||
if (ver_a < ver_b)
|
||||
return -1;
|
||||
if (ver_a > ver_b)
|
||||
return 1;
|
||||
|
||||
/* compare strings */
|
||||
if ((endptr_a != NULL && endptr_a[0] != '\0') ||
|
||||
(endptr_b != NULL && endptr_b[0] != '\0')) {
|
||||
gint rc = fu_common_vercmp_chunk (endptr_a, endptr_b);
|
||||
if (rc < 0)
|
||||
return -1;
|
||||
if (rc > 0)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* we really shouldn't get here */
|
||||
return 0;
|
||||
}
|
45
src/fu-common-version.h
Normal file
45
src/fu-common-version.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2018 Richard Hughes <richard@hughsie.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#ifndef __FU_COMMON_VERSION_H__
|
||||
#define __FU_COMMON_VERSION_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
/**
|
||||
* FuVersionFormat:
|
||||
* @FU_VERSION_FORMAT_UNKNOWN: Unknown version format
|
||||
* @FU_VERSION_FORMAT_PLAIN: Use plain integer version numbers
|
||||
* @FU_VERSION_FORMAT_QUAD: Use Dell-style AA.BB.CC.DD version numbers
|
||||
* @FU_VERSION_FORMAT_TRIPLET: Use Microsoft-style AA.BB.CCDD version numbers
|
||||
* @FU_VERSION_FORMAT_PAIR: Use two AABB.CCDD version numbers
|
||||
* @FU_VERSION_FORMAT_BCD: Use binary coded decimal notation
|
||||
*
|
||||
* The flags used when parsing version numbers.
|
||||
**/
|
||||
typedef enum {
|
||||
FU_VERSION_FORMAT_UNKNOWN, /* Since: 1.2.0 */
|
||||
FU_VERSION_FORMAT_PLAIN, /* Since: 1.2.0 */
|
||||
FU_VERSION_FORMAT_QUAD, /* Since: 1.2.0 */
|
||||
FU_VERSION_FORMAT_TRIPLET, /* Since: 1.2.0 */
|
||||
FU_VERSION_FORMAT_PAIR, /* Since: 1.2.0 */
|
||||
FU_VERSION_FORMAT_BCD, /* Since: 1.2.0 */
|
||||
/*< private >*/
|
||||
FU_VERSION_FORMAT_LAST
|
||||
} FuVersionFormat;
|
||||
|
||||
FuVersionFormat fu_common_version_format_from_string (const gchar *str);
|
||||
const gchar *fu_common_version_format_to_string (FuVersionFormat kind);
|
||||
|
||||
gint fu_common_vercmp (const gchar *version_a,
|
||||
const gchar *version_b);
|
||||
gchar *fu_common_version_from_uint32 (guint32 val,
|
||||
FuVersionFormat flags);
|
||||
gchar *fu_common_version_from_uint16 (guint16 val,
|
||||
FuVersionFormat flags);
|
||||
gchar *fu_common_version_parse (const gchar *version);
|
||||
|
||||
#endif /* __FU_COMMON_VERSION_H__ */
|
@ -1007,7 +1007,7 @@ fu_engine_vendor_fixup_provide_value (AsApp *app)
|
||||
static void
|
||||
fu_engine_vendor_quirk_release_version (FuEngine *self, AsApp *app)
|
||||
{
|
||||
AsVersionParseFlag flags = AS_VERSION_PARSE_FLAG_USE_TRIPLET;
|
||||
FuVersionFormat flags = FU_VERSION_FORMAT_TRIPLET;
|
||||
GPtrArray *releases;
|
||||
const gchar *quirk;
|
||||
const gchar *version_format;
|
||||
@ -1024,7 +1024,7 @@ fu_engine_vendor_quirk_release_version (FuEngine *self, AsApp *app)
|
||||
g_auto(GStrv) globs = g_strsplit (quirk, ",", -1);
|
||||
for (guint i = 0; globs[i] != NULL; i++) {
|
||||
if (fnmatch (globs[i], as_app_get_id (app), 0) == 0) {
|
||||
flags = AS_VERSION_PARSE_FLAG_NONE;
|
||||
flags = FU_VERSION_FORMAT_QUAD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1033,7 +1033,7 @@ fu_engine_vendor_quirk_release_version (FuEngine *self, AsApp *app)
|
||||
/* specified in metadata */
|
||||
version_format = as_app_get_metadata_item (app, "LVFS::VersionFormat");
|
||||
if (g_strcmp0 (version_format, "quad") == 0)
|
||||
flags = AS_VERSION_PARSE_FLAG_NONE;
|
||||
flags = FU_VERSION_FORMAT_QUAD;
|
||||
|
||||
/* fix each release */
|
||||
releases = as_app_get_releases (app);
|
||||
@ -1056,7 +1056,7 @@ fu_engine_vendor_quirk_release_version (FuEngine *self, AsApp *app)
|
||||
continue;
|
||||
|
||||
/* convert to dotted decimal */
|
||||
version_new = as_utils_version_from_uint32 ((guint32) ver_uint32, flags);
|
||||
version_new = fu_common_version_from_uint32 ((guint32) ver_uint32, flags);
|
||||
as_release_set_version (rel, version_new);
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include <fwupd.h>
|
||||
|
||||
#include "fu-common-version.h"
|
||||
#include "fu-device-private.h"
|
||||
#include "fu-install-task.h"
|
||||
#include "fu-keyring-utils.h"
|
||||
@ -210,7 +211,7 @@ fu_install_task_check_requirements (FuInstallTask *self,
|
||||
/* compare to the lowest supported version, if it exists */
|
||||
version_lowest = fu_device_get_version_lowest (self->device);
|
||||
if (version_lowest != NULL &&
|
||||
as_utils_vercmp (version_lowest, version) > 0 &&
|
||||
fu_common_vercmp (version_lowest, version) > 0 &&
|
||||
(flags & FWUPD_INSTALL_FLAG_FORCE) == 0) {
|
||||
g_set_error (error,
|
||||
FWUPD_ERROR,
|
||||
@ -221,7 +222,7 @@ fu_install_task_check_requirements (FuInstallTask *self,
|
||||
}
|
||||
|
||||
/* check semver */
|
||||
vercmp = as_utils_vercmp (version, version_release);
|
||||
vercmp = fu_common_vercmp (version, version_release);
|
||||
if (vercmp == 0 && (flags & FWUPD_INSTALL_FLAG_ALLOW_REINSTALL) == 0) {
|
||||
g_set_error (error,
|
||||
FWUPD_ERROR,
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include <gudev/gudev.h>
|
||||
|
||||
#include "fu-common.h"
|
||||
#include "fu-common-guid.h"
|
||||
#include "fu-common-version.h"
|
||||
#include "fu-device.h"
|
||||
#include "fu-device-locker.h"
|
||||
#include "fu-quirks.h"
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "fu-common-cab.h"
|
||||
#include "fu-common-guid.h"
|
||||
#include "fu-common-version.h"
|
||||
#include "fu-chunk.h"
|
||||
#include "fu-config.h"
|
||||
#include "fu-device-list.h"
|
||||
@ -2862,6 +2863,134 @@ fu_common_guid_func (void)
|
||||
g_assert_cmpstr (guid2, ==, "1fbd1f2c-80f4-5d7c-a6ad-35c7b9bd5486");
|
||||
}
|
||||
|
||||
static void
|
||||
fu_common_version_func (void)
|
||||
{
|
||||
guint i;
|
||||
struct {
|
||||
guint32 val;
|
||||
const gchar *ver;
|
||||
FuVersionFormat flags;
|
||||
} version_from_uint32[] = {
|
||||
{ 0x0, "0.0.0.0", FU_VERSION_FORMAT_QUAD },
|
||||
{ 0xff, "0.0.0.255", FU_VERSION_FORMAT_QUAD },
|
||||
{ 0xff01, "0.0.255.1", FU_VERSION_FORMAT_QUAD },
|
||||
{ 0xff0001, "0.255.0.1", FU_VERSION_FORMAT_QUAD },
|
||||
{ 0xff000100, "255.0.1.0", FU_VERSION_FORMAT_QUAD },
|
||||
{ 0x0, "0.0.0", FU_VERSION_FORMAT_TRIPLET },
|
||||
{ 0xff, "0.0.255", FU_VERSION_FORMAT_TRIPLET },
|
||||
{ 0xff01, "0.0.65281", FU_VERSION_FORMAT_TRIPLET },
|
||||
{ 0xff0001, "0.255.1", FU_VERSION_FORMAT_TRIPLET },
|
||||
{ 0xff000100, "255.0.256", FU_VERSION_FORMAT_TRIPLET },
|
||||
{ 0x0, "0", FU_VERSION_FORMAT_PLAIN },
|
||||
{ 0xff000100, "4278190336", FU_VERSION_FORMAT_PLAIN },
|
||||
{ 0, NULL }
|
||||
};
|
||||
struct {
|
||||
guint16 val;
|
||||
const gchar *ver;
|
||||
FuVersionFormat flags;
|
||||
} version_from_uint16[] = {
|
||||
{ 0x0, "0.0", FU_VERSION_FORMAT_PAIR },
|
||||
{ 0xff, "0.255", FU_VERSION_FORMAT_PAIR },
|
||||
{ 0xff01, "255.1", FU_VERSION_FORMAT_PAIR },
|
||||
{ 0x0, "0.0", FU_VERSION_FORMAT_BCD },
|
||||
{ 0x0110, "1.10", FU_VERSION_FORMAT_BCD },
|
||||
{ 0x9999, "99.99", FU_VERSION_FORMAT_BCD },
|
||||
{ 0x0, "0", FU_VERSION_FORMAT_PLAIN },
|
||||
{ 0x1234, "4660", FU_VERSION_FORMAT_PLAIN },
|
||||
{ 0, NULL }
|
||||
};
|
||||
struct {
|
||||
const gchar *old;
|
||||
const gchar *new;
|
||||
} version_parse[] = {
|
||||
{ "0", "0" },
|
||||
{ "0x1a", "0.0.26" },
|
||||
{ "257", "0.0.257" },
|
||||
{ "1.2.3", "1.2.3" },
|
||||
{ "0xff0001", "0.255.1" },
|
||||
{ "16711681", "0.255.1" },
|
||||
{ "20150915", "20150915" },
|
||||
{ "dave", "dave" },
|
||||
{ "0x1x", "0x1x" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/* check version conversion */
|
||||
for (i = 0; version_from_uint32[i].ver != NULL; i++) {
|
||||
g_autofree gchar *ver = NULL;
|
||||
ver = fu_common_version_from_uint32 (version_from_uint32[i].val,
|
||||
version_from_uint32[i].flags);
|
||||
g_assert_cmpstr (ver, ==, version_from_uint32[i].ver);
|
||||
}
|
||||
for (i = 0; version_from_uint16[i].ver != NULL; i++) {
|
||||
g_autofree gchar *ver = NULL;
|
||||
ver = fu_common_version_from_uint16 (version_from_uint16[i].val,
|
||||
version_from_uint16[i].flags);
|
||||
g_assert_cmpstr (ver, ==, version_from_uint16[i].ver);
|
||||
}
|
||||
|
||||
/* check version parsing */
|
||||
for (i = 0; version_parse[i].old != NULL; i++) {
|
||||
g_autofree gchar *ver = NULL;
|
||||
ver = fu_common_version_parse (version_parse[i].old);
|
||||
g_assert_cmpstr (ver, ==, version_parse[i].new);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fu_common_vercmp_func (void)
|
||||
{
|
||||
/* same */
|
||||
g_assert_cmpint (fu_common_vercmp ("1.2.3", "1.2.3"), ==, 0);
|
||||
g_assert_cmpint (fu_common_vercmp ("001.002.003", "001.002.003"), ==, 0);
|
||||
|
||||
/* same, not dotted decimal */
|
||||
g_assert_cmpint (fu_common_vercmp ("1.2.3", "0x1020003"), ==, 0);
|
||||
g_assert_cmpint (fu_common_vercmp ("0x10203", "0x10203"), ==, 0);
|
||||
|
||||
/* upgrade and downgrade */
|
||||
g_assert_cmpint (fu_common_vercmp ("1.2.3", "1.2.4"), <, 0);
|
||||
g_assert_cmpint (fu_common_vercmp ("001.002.000", "001.002.009"), <, 0);
|
||||
g_assert_cmpint (fu_common_vercmp ("1.2.3", "1.2.2"), >, 0);
|
||||
g_assert_cmpint (fu_common_vercmp ("001.002.009", "001.002.000"), >, 0);
|
||||
|
||||
/* unequal depth */
|
||||
g_assert_cmpint (fu_common_vercmp ("1.2.3", "1.2.3.1"), <, 0);
|
||||
g_assert_cmpint (fu_common_vercmp ("1.2.3.1", "1.2.4"), <, 0);
|
||||
|
||||
/* mixed-alpha-numeric */
|
||||
g_assert_cmpint (fu_common_vercmp ("1.2.3a", "1.2.3a"), ==, 0);
|
||||
g_assert_cmpint (fu_common_vercmp ("1.2.3a", "1.2.3b"), <, 0);
|
||||
g_assert_cmpint (fu_common_vercmp ("1.2.3b", "1.2.3a"), >, 0);
|
||||
|
||||
/* alpha version append */
|
||||
g_assert_cmpint (fu_common_vercmp ("1.2.3", "1.2.3a"), <, 0);
|
||||
g_assert_cmpint (fu_common_vercmp ("1.2.3a", "1.2.3"), >, 0);
|
||||
|
||||
/* alpha only */
|
||||
g_assert_cmpint (fu_common_vercmp ("alpha", "alpha"), ==, 0);
|
||||
g_assert_cmpint (fu_common_vercmp ("alpha", "beta"), <, 0);
|
||||
g_assert_cmpint (fu_common_vercmp ("beta", "alpha"), >, 0);
|
||||
|
||||
/* alpha-compare */
|
||||
g_assert_cmpint (fu_common_vercmp ("1.2a.3", "1.2a.3"), ==, 0);
|
||||
g_assert_cmpint (fu_common_vercmp ("1.2a.3", "1.2b.3"), <, 0);
|
||||
g_assert_cmpint (fu_common_vercmp ("1.2b.3", "1.2a.3"), >, 0);
|
||||
|
||||
/* tilde is all-powerful */
|
||||
g_assert_cmpint (fu_common_vercmp ("1.2.3~rc1", "1.2.3~rc1"), ==, 0);
|
||||
g_assert_cmpint (fu_common_vercmp ("1.2.3~rc1", "1.2.3"), <, 0);
|
||||
g_assert_cmpint (fu_common_vercmp ("1.2.3", "1.2.3~rc1"), >, 0);
|
||||
g_assert_cmpint (fu_common_vercmp ("1.2.3~rc2", "1.2.3~rc1"), >, 0);
|
||||
|
||||
/* invalid */
|
||||
g_assert_cmpint (fu_common_vercmp ("1", NULL), ==, G_MAXINT);
|
||||
g_assert_cmpint (fu_common_vercmp (NULL, "1"), ==, G_MAXINT);
|
||||
g_assert_cmpint (fu_common_vercmp (NULL, NULL), ==, G_MAXINT);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
@ -2924,6 +3053,8 @@ main (int argc, char **argv)
|
||||
g_test_add_func ("/fwupd/keyring{pkcs7}", fu_keyring_pkcs7_func);
|
||||
g_test_add_func ("/fwupd/chunk", fu_chunk_func);
|
||||
g_test_add_func ("/fwupd/common{guid}", fu_common_guid_func);
|
||||
g_test_add_func ("/fwupd/common{version}", fu_common_version_func);
|
||||
g_test_add_func ("/fwupd/common{vercmp}", fu_common_vercmp_func);
|
||||
g_test_add_func ("/fwupd/common{strstrip}", fu_common_strstrip_func);
|
||||
g_test_add_func ("/fwupd/common{endian}", fu_common_endian_func);
|
||||
g_test_add_func ("/fwupd/common{cab-success}", fu_common_store_cab_func);
|
||||
|
@ -8,8 +8,6 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <appstream-glib.h>
|
||||
|
||||
#include "fu-usb-device-private.h"
|
||||
|
||||
/**
|
||||
@ -238,8 +236,8 @@ fu_usb_device_probe (FuDevice *device, GError **error)
|
||||
/* set the version if the release has been set */
|
||||
release = g_usb_device_get_release (priv->usb_device);
|
||||
if (release != 0x0) {
|
||||
g_autofree gchar *version = as_utils_version_from_uint16 (release,
|
||||
AS_VERSION_PARSE_FLAG_USE_BCD);
|
||||
g_autofree gchar *version = NULL;
|
||||
version = fu_common_version_from_uint16 (release, FU_VERSION_FORMAT_BCD);
|
||||
fu_device_set_version (device, version);
|
||||
}
|
||||
|
||||
|
@ -742,8 +742,8 @@ fu_util_install_prepared (FuUtilPrivate *priv, gchar **values, GError **error)
|
||||
continue;
|
||||
|
||||
/* tell the user what's going to happen */
|
||||
vercmp = as_utils_vercmp (fwupd_device_get_version (dev),
|
||||
fwupd_release_get_version (rel));
|
||||
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
|
||||
|
@ -27,6 +27,7 @@ libfwupdprivate = static_library(
|
||||
sources : [
|
||||
'fu-common.c',
|
||||
'fu-common-guid.c',
|
||||
'fu-common-version.c',
|
||||
'fu-chunk.c',
|
||||
'fu-device.c',
|
||||
'fu-device-locker.c',
|
||||
@ -111,6 +112,7 @@ fwupdtool = executable(
|
||||
'fu-common.c',
|
||||
'fu-common-cab.c',
|
||||
'fu-common-guid.c',
|
||||
'fu-common-version.c',
|
||||
'fu-config.c',
|
||||
'fu-keyring.c',
|
||||
'fu-keyring-result.c',
|
||||
@ -189,6 +191,7 @@ executable(
|
||||
'fu-common.c',
|
||||
'fu-common-cab.c',
|
||||
'fu-common-guid.c',
|
||||
'fu-common-version.c',
|
||||
'fu-config.c',
|
||||
'fu-keyring.c',
|
||||
'fu-keyring-result.c',
|
||||
@ -258,6 +261,7 @@ if get_option('tests')
|
||||
'fu-common.c',
|
||||
'fu-common-cab.c',
|
||||
'fu-common-guid.c',
|
||||
'fu-common-version.c',
|
||||
'fu-config.c',
|
||||
'fu-engine.c',
|
||||
'fu-keyring.c',
|
||||
@ -322,6 +326,8 @@ if get_option('introspection')
|
||||
'fu-common.c',
|
||||
'fu-common-guid.c',
|
||||
'fu-common-guid.h',
|
||||
'fu-common-version.c',
|
||||
'fu-common-version.h',
|
||||
'fu-common.h',
|
||||
'fu-device.c',
|
||||
'fu-device.h',
|
||||
|
Loading…
Reference in New Issue
Block a user