diff options
author | Lennart Poettering <lennart@poettering.net> | 2019-03-18 16:43:33 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2019-03-19 15:55:07 +0100 |
commit | ba22ff13a07a9478921c5342ef07dd5dcdd0e7d1 (patch) | |
tree | d4a504527d55efe744c9142f090d53e7687d270d /src/shared/condition.c | |
parent | 17b70256f251905bcce9e7cdcd84e32213c8f5b4 (diff) | |
download | systemd-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.c | 97 |
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; |