summaryrefslogtreecommitdiff
path: root/src/shared/condition.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2019-03-18 16:43:33 +0100
committerLennart Poettering <lennart@poettering.net>2019-03-19 15:55:07 +0100
commitba22ff13a07a9478921c5342ef07dd5dcdd0e7d1 (patch)
treed4a504527d55efe744c9142f090d53e7687d270d /src/shared/condition.c
parent17b70256f251905bcce9e7cdcd84e32213c8f5b4 (diff)
downloadsystemd-ba22ff13a07a9478921c5342ef07dd5dcdd0e7d1.tar.gz
systemd-ba22ff13a07a9478921c5342ef07dd5dcdd0e7d1.tar.bz2
systemd-ba22ff13a07a9478921c5342ef07dd5dcdd0e7d1.zip
condition: split out kernel version comparison steps
Let's split out the operator parsing and the final verdict determination. That way we can reuse this logic for other purposes later on.
Diffstat (limited to 'src/shared/condition.c')
-rw-r--r--src/shared/condition.c97
1 files changed, 58 insertions, 39 deletions
diff --git a/src/shared/condition.c b/src/shared/condition.c
index fb77966264..12c685acd5 100644
--- a/src/shared/condition.c
+++ b/src/shared/condition.c
@@ -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;