auc: compare versions using dpkg/opkg's verrevcmp
authorDaniel Golle <daniel@makrotopia.org>
Mon, 26 Apr 2021 18:16:19 +0000 (19:16 +0100)
committerDaniel Golle <daniel@makrotopia.org>
Mon, 26 Apr 2021 18:21:43 +0000 (19:21 +0100)
Using strcmp() to compare a version string doesn't work well.
Use verrevcmp() function from opkg instead.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
utils/auc/src/CMakeLists.txt
utils/auc/src/auc.c

index de6cee83340605b5b33392212f7aa888e0f8aa82..14cc199ce219789a8f489966a250095f41c02a8b 100644 (file)
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.6)
+cmake_minimum_required(VERSION 2.6...3.12)
 
 PROJECT(auc C)
 ADD_DEFINITIONS(-Os -ggdb -Wall --std=gnu99 -Wmissing-declarations)
index d3162066a8b02ae3a681733948001b36ec1fda32..5836875a3d8bec2adb3e23d89579df084c1a184f 100644 (file)
@@ -17,6 +17,7 @@
 #define AUC_VERSION "unknown"
 #endif
 
+#include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <dlfcn.h>
@@ -359,6 +360,58 @@ static int load_config() {
        return 0;
 }
 
+/*
+ * libdpkg - Debian packaging suite library routines
+ * vercmp.c - comparison of version numbers
+ *
+ * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
+ */
+
+/* assume ascii; warning: evaluates x multiple times! */
+#define order(x) ((x) == '~' ? -1 \
+               : isdigit((x)) ? 0 \
+               : !(x) ? 0 \
+               : isalpha((x)) ? (x) \
+               : (x) + 256)
+
+static int verrevcmp(const char *val, const char *ref)
+{
+       if (!val)
+               val = "";
+       if (!ref)
+               ref = "";
+
+       while (*val || *ref) {
+               int first_diff = 0;
+
+               while ((*val && !isdigit(*val)) || (*ref && !isdigit(*ref))) {
+                       int vc = order(*val), rc = order(*ref);
+                       if (vc != rc)
+                               return vc - rc;
+                       val++;
+                       ref++;
+               }
+
+               while (*val == '0')
+                       val++;
+               while (*ref == '0')
+                       ref++;
+               while (isdigit(*val) && isdigit(*ref)) {
+                       if (!first_diff)
+                               first_diff = *val - *ref;
+                       val++;
+                       ref++;
+               }
+               if (isdigit(*val))
+                       return 1;
+               if (isdigit(*ref))
+                       return -1;
+               if (first_diff)
+                       return first_diff;
+       }
+       return 0;
+}
+
 
 /**
  * UBUS response callbacks
@@ -409,7 +462,7 @@ static void pkglist_check_cb(struct ubus_request *req, int type, struct blob_att
                        continue;
                }
 
-               cmpres = strcmp(blobmsg_get_string(cur), pkg->version);
+               cmpres = verrevcmp(blobmsg_get_string(cur), pkg->version);
                if (cmpres < 0)
                        *status |= PKG_UPGRADE;