From 57610982f73162ec37b1de03734250bb5a3222da Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 26 Aug 2022 16:56:04 +0200 Subject: [PATCH] compare: add flag for parse_compare_operator() to do equality/inequality comparison via simple string compares This allows us to switch condition_test_osrelease() to use generic version_or_fnmatch_compare() for executing the comparison. --- src/shared/compare-operator.c | 17 +++++++++++++++++ src/shared/compare-operator.h | 11 +++++++++++ src/shared/condition.c | 16 +++++----------- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/shared/compare-operator.c b/src/shared/compare-operator.c index 1a19e4219d..2bd64add7f 100644 --- a/src/shared/compare-operator.c +++ b/src/shared/compare-operator.c @@ -27,12 +27,23 @@ CompareOperator parse_compare_operator(const char **s, CompareOperatorParseFlags for (CompareOperator i = 0; i < _COMPARE_OPERATOR_MAX; i++) { const char *e; + if (!prefix[i]) + continue; + e = startswith(*s, prefix[i]); if (e) { if (!FLAGS_SET(flags, COMPARE_ALLOW_FNMATCH) && COMPARE_OPERATOR_IS_FNMATCH(i)) return _COMPARE_OPERATOR_INVALID; *s = e; + + if (FLAGS_SET(flags, COMPARE_EQUAL_BY_STRING)) { + if (i == COMPARE_EQUAL) + return COMPARE_STRING_EQUAL; + if (i == COMPARE_UNEQUAL) + return COMPARE_STRING_UNEQUAL; + } + return i; } } @@ -74,6 +85,12 @@ int version_or_fnmatch_compare( switch (op) { + case COMPARE_STRING_EQUAL: + return streq_ptr(a, b); + + case COMPARE_STRING_UNEQUAL: + return !streq_ptr(a, b); + case COMPARE_FNMATCH_EQUAL: return fnmatch(b, a, 0) != FNM_NOMATCH; diff --git a/src/shared/compare-operator.h b/src/shared/compare-operator.h index f7137bba1a..363b4bdc75 100644 --- a/src/shared/compare-operator.h +++ b/src/shared/compare-operator.h @@ -8,6 +8,12 @@ typedef enum CompareOperator { /* Listed in order of checking. Note that some comparators are prefixes of others, hence the longest * should be listed first. */ + /* Simple string compare operators */ + _COMPARE_OPERATOR_STRING_FIRST, + COMPARE_STRING_EQUAL = _COMPARE_OPERATOR_STRING_FIRST, + COMPARE_STRING_UNEQUAL, + _COMPARE_OPERATOR_STRING_LAST = COMPARE_STRING_UNEQUAL, + /* fnmatch() compare operators */ _COMPARE_OPERATOR_FNMATCH_FIRST, COMPARE_FNMATCH_EQUAL = _COMPARE_OPERATOR_FNMATCH_FIRST, @@ -28,6 +34,10 @@ typedef enum CompareOperator { _COMPARE_OPERATOR_INVALID = -EINVAL, } CompareOperator; +static inline bool COMPARE_OPERATOR_IS_STRING(CompareOperator c) { + return c >= _COMPARE_OPERATOR_STRING_FIRST && c <= _COMPARE_OPERATOR_STRING_LAST; +} + static inline bool COMPARE_OPERATOR_IS_FNMATCH(CompareOperator c) { return c >= _COMPARE_OPERATOR_FNMATCH_FIRST && c <= _COMPARE_OPERATOR_FNMATCH_LAST; } @@ -38,6 +48,7 @@ static inline bool COMPARE_OPERATOR_IS_ORDER(CompareOperator c) { typedef enum CompareOperatorParseFlags { COMPARE_ALLOW_FNMATCH = 1 << 0, + COMPARE_EQUAL_BY_STRING = 1 << 1, } CompareOperatorParseFlags; CompareOperator parse_compare_operator(const char **s, CompareOperatorParseFlags flags); diff --git a/src/shared/condition.c b/src/shared/condition.c index 1f9e6d221f..db7a02db7d 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -248,7 +248,6 @@ static int condition_test_osrelease(Condition *c, char **env) { _cleanup_free_ char *key = NULL, *condition = NULL, *actual_value = NULL; CompareOperator operator; const char *word; - bool matches; r = extract_first_word(¶meter, &condition, NULL, EXTRACT_UNQUOTE); if (r < 0) @@ -267,7 +266,7 @@ static int condition_test_osrelease(Condition *c, char **env) { "Failed to parse parameter, key/value format expected: %m"); /* Do not allow whitespace after the separator, as that's not a valid os-release format */ - operator = parse_compare_operator(&word, 0); + operator = parse_compare_operator(&word, COMPARE_EQUAL_BY_STRING); if (operator < 0 || isempty(word) || strchr(WHITESPACE, *word) != NULL) return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse parameter, key/value format expected: %m"); @@ -276,15 +275,10 @@ static int condition_test_osrelease(Condition *c, char **env) { if (r < 0) return log_debug_errno(r, "Failed to parse os-release: %m"); - /* Might not be comparing versions, so do exact string matching */ - if (operator == COMPARE_EQUAL) - matches = streq_ptr(actual_value, word); - else if (operator == COMPARE_UNEQUAL) - matches = !streq_ptr(actual_value, word); - else - matches = test_order(strverscmp_improved(actual_value, word), operator); - - if (!matches) + r = version_or_fnmatch_compare(operator, actual_value, word); + if (r < 0) + return r; + if (!r) return false; } -- 2.25.1