]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
condition: split out kernel version comparison steps
authorLennart Poettering <lennart@poettering.net>
Mon, 18 Mar 2019 15:43:33 +0000 (16:43 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 19 Mar 2019 14:55:07 +0000 (15:55 +0100)
Let's split out the operator parsing and the final verdict
determination. That way we can reuse this logic for other purposes later
on.

src/shared/condition.c

index fb77966264e41a85f475f0d0a5d941a7918111c4..12c685acd5d06cf2a2437f7fa2a997eb3308ec07 100644 (file)
@@ -128,70 +128,89 @@ static int condition_test_kernel_command_line(Condition *c) {
         return false;
 }
 
-static int condition_test_kernel_version(Condition *c) {
-        enum {
-                /* Listed in order of checking. Note that some comparators are prefixes of others, hence the longest
-                 * should be listed first. */
-                LOWER_OR_EQUAL,
-                GREATER_OR_EQUAL,
-                LOWER,
-                GREATER,
-                EQUAL,
-                _ORDER_MAX,
-        };
+typedef enum {
+        /* Listed in order of checking. Note that some comparators are prefixes of others, hence the longest
+         * should be listed first. */
+        ORDER_LOWER_OR_EQUAL,
+        ORDER_GREATER_OR_EQUAL,
+        ORDER_LOWER,
+        ORDER_GREATER,
+        ORDER_EQUAL,
+        _ORDER_MAX,
+        _ORDER_INVALID = -1
+} OrderOperator;
+
+static OrderOperator parse_order(const char **s) {
 
         static const char *const prefix[_ORDER_MAX] = {
-                [LOWER_OR_EQUAL] = "<=",
-                [GREATER_OR_EQUAL] = ">=",
-                [LOWER] = "<",
-                [GREATER] = ">",
-                [EQUAL] = "=",
+                [ORDER_LOWER_OR_EQUAL] = "<=",
+                [ORDER_GREATER_OR_EQUAL] = ">=",
+                [ORDER_LOWER] = "<",
+                [ORDER_GREATER] = ">",
+                [ORDER_EQUAL] = "=",
         };
-        const char *p = NULL;
-        struct utsname u;
-        size_t i;
-        int k;
-
-        assert(c);
-        assert(c->parameter);
-        assert(c->type == CONDITION_KERNEL_VERSION);
 
-        assert_se(uname(&u) >= 0);
+        OrderOperator i;
 
         for (i = 0; i < _ORDER_MAX; i++) {
-                p = startswith(c->parameter, prefix[i]);
-                if (p)
-                        break;
+                const char *e;
+
+                e = startswith(*s, prefix[i]);
+                if (e) {
+                        *s = e;
+                        return i;
+                }
         }
 
-        /* No prefix? Then treat as glob string */
-        if (!p)
-                return fnmatch(skip_leading_chars(c->parameter, NULL), u.release, 0) == 0;
+        return _ORDER_INVALID;
+}
 
-        k = str_verscmp(u.release, skip_leading_chars(p, NULL));
+static bool test_order(int k, OrderOperator p) {
 
-        switch (i) {
+        switch (p) {
 
-        case LOWER:
+        case ORDER_LOWER:
                 return k < 0;
 
-        case LOWER_OR_EQUAL:
+        case ORDER_LOWER_OR_EQUAL:
                 return k <= 0;
 
-        case EQUAL:
+        case ORDER_EQUAL:
                 return k == 0;
 
-        case GREATER_OR_EQUAL:
+        case ORDER_GREATER_OR_EQUAL:
                 return k >= 0;
 
-        case GREATER:
+        case ORDER_GREATER:
                 return k > 0;
 
         default:
-                assert_not_reached("Can't compare");
+                assert_not_reached("unknown order");
+
         }
 }
 
+static int condition_test_kernel_version(Condition *c) {
+        OrderOperator order;
+        struct utsname u;
+        const char *p;
+
+        assert(c);
+        assert(c->parameter);
+        assert(c->type == CONDITION_KERNEL_VERSION);
+
+        assert_se(uname(&u) >= 0);
+
+        p = c->parameter;
+        order = parse_order(&p);
+
+        /* No prefix? Then treat as glob string */
+        if (order < 0)
+                return fnmatch(skip_leading_chars(c->parameter, NULL), u.release, 0) == 0;
+
+        return test_order(str_verscmp(u.release, skip_leading_chars(p, NULL)), order);
+}
+
 static int condition_test_user(Condition *c) {
         uid_t id;
         int r;