@@ -210,7 +210,7 @@ void cleanup_version(char* str)
* Also major.minor or major.minor.revision are allowed
* The conversion generates a 64 bit value that can be compared
*/
-__u64 version_to_number(const char *version_string)
+static __u64 version_to_number(const char *version_string)
{
char **versions = NULL;
char **ver;
@@ -235,3 +235,49 @@ __u64 version_to_number(const char *version_string)
return version;
}
+
+/*
+ * Compare 2 versions.
+ *
+ * Mind that this function accepts both version types:
+ * - old-style: major.minor.revision.buildinfo
+ * - semantic versioning: major.minor.patch[-prerelease][+buildinfo]
+ * see https://semver.org
+ *
+ * Returns -1, 0 or 1 of left is respectively lower than, equal to or greater than right.
+ */
+int compare_versions(const char* left_version, const char* right_version)
+{
+ if (is_oldstyle_version(left_version) && is_oldstyle_version(right_version))
+ {
+ __u64 left_u64 = version_to_number(left_version);
+ __u64 right_u64 = version_to_number(right_version);
+
+ if (left_u64 < right_u64)
+ return -1;
+ else if (left_u64 > right_u64)
+ return 1;
+ else
+ return 0;
+ }
+ else
+ {
+ semver_t left_sem = {};
+ semver_t right_sem = {};
+ int comparison;
+
+ /* There's no error checking here.
+ * Oldstyle code also defaults to treating unparseable version as 0.
+ * Failed semver_parse also leads to 0.0.0 if properly initialized.
+ */
+ semver_parse(left_version, &left_sem);
+ semver_parse(right_version, &right_sem);
+
+ comparison = semver_compare(left_sem, right_sem);
+
+ semver_free(&left_sem);
+ semver_free(&right_sem);
+
+ return comparison;
+ }
+}
@@ -172,15 +172,15 @@ static int is_image_higher(struct swver *sw_ver_list,
return false;
LIST_FOREACH(swver, sw_ver_list, next) {
- __u64 minimum_version = version_to_number(swver->version);
- __u64 newversion = version_to_number(img->id.version);
+ const char* current_version = swver->version;
+ const char* proposed_version = img->id.version;
/*
* Check if name are identical and the new version is lower
* or equal.
*/
if (!strncmp(img->id.name, swver->name, sizeof(img->id.name)) &&
- (minimum_version >= newversion)) {
+ (compare_versions(proposed_version, current_version) < 0)) {
TRACE("%s(%s) has a higher version installed, skipping...",
img->id.name,
img->id.version);
@@ -306,10 +306,7 @@ int parse(struct swupdate_cfg *sw, const char *descfile)
* newer version
*/
if (sw->globals.no_downgrading) {
- __u64 minimum_version = version_to_number(sw->globals.minimum_version);
- __u64 newversion = version_to_number(sw->version);
-
- if (newversion < minimum_version) {
+ if (compare_versions(sw->version, sw->globals.minimum_version) < 0) {
ERROR("No downgrading allowed: new version %s <= installed %s",
sw->version, sw->globals.minimum_version);
return -EPERM;
@@ -217,7 +217,7 @@ void freeargs (char **argv);
int get_hw_revision(struct hw_type *hw);
void get_sw_versions(char *cfgfname, struct swupdate_cfg *sw);
void cleanup_version(char* str);
-__u64 version_to_number(const char *version_string);
+int compare_versions(const char* left_version, const char* right_version);
int hwid_match(const char* rev, const char* hwrev);
int check_hw_compatibility(struct swupdate_cfg *cfg);
int count_elem_list(struct imglist *list);
Still, fallback to legacy versioning scheme if needed. Signed-off-by: Stijn Devriendt <sde@unmatched.eu> --- core/artifacts_versions.c | 48 ++++++++++++++++++++++++++++++++++++++- core/parser.c | 11 ++++----- include/util.h | 2 +- 3 files changed, 52 insertions(+), 9 deletions(-)