chiark / gitweb /
condition: extend ConditionKernelVersion= with relative version checks
authorLennart Poettering <lennart@poettering.net>
Sat, 23 Dec 2017 14:02:58 +0000 (15:02 +0100)
committerSven Eden <yamakuzure@gmx.net>
Wed, 30 May 2018 05:49:45 +0000 (07:49 +0200)
Now that we have str_verscmp() in our source tree anyway, let's make it
generic and reuse it for ConditionKernelVersion=.

src/basic/util.c
src/basic/util.h

index 19f189135001394ded07ec4921b7139f5c971dea..a7cc3ecfb9ef22ae16baffd9b8a79bb406b13411 100644 (file)
@@ -564,3 +564,64 @@ int version(void) {
 
 #if 0 /// UNNEEDED by elogind
 #endif // 0
+/* This is a direct translation of str_verscmp from boot.c */
+static bool is_digit(int c) {
+        return c >= '0' && c <= '9';
+}
+
+static int c_order(int c) {
+        if (c == 0 || is_digit(c))
+                return 0;
+
+        if ((c >= 'a') && (c <= 'z'))
+                return c;
+
+        return c + 0x10000;
+}
+
+int str_verscmp(const char *s1, const char *s2) {
+        const char *os1, *os2;
+
+        assert(s1);
+        assert(s2);
+
+        os1 = s1;
+        os2 = s2;
+
+        while (*s1 || *s2) {
+                int first;
+
+                while ((*s1 && !is_digit(*s1)) || (*s2 && !is_digit(*s2))) {
+                        int order;
+
+                        order = c_order(*s1) - c_order(*s2);
+                        if (order != 0)
+                                return order;
+                        s1++;
+                        s2++;
+                }
+
+                while (*s1 == '0')
+                        s1++;
+                while (*s2 == '0')
+                        s2++;
+
+                first = 0;
+                while (is_digit(*s1) && is_digit(*s2)) {
+                        if (first == 0)
+                                first = *s1 - *s2;
+                        s1++;
+                        s2++;
+                }
+
+                if (is_digit(*s1))
+                        return 1;
+                if (is_digit(*s2))
+                        return -1;
+
+                if (first != 0)
+                        return first;
+        }
+
+        return strcmp(os1, os2);
+}
index 33c4854ee1c5ba9b1d1da91d94e8215d75d477b2..f9432ebb58b89f17772e3e25ecd4abf86d7dfcce 100644 (file)
@@ -204,3 +204,4 @@ int version(void);
 
 #if 0 /// UNNEEDED by elogind
 #endif // 0
+int str_verscmp(const char *s1, const char *s2);