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;
}
}
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;
/* 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,
_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;
}
typedef enum CompareOperatorParseFlags {
COMPARE_ALLOW_FNMATCH = 1 << 0,
+ COMPARE_EQUAL_BY_STRING = 1 << 1,
} CompareOperatorParseFlags;
CompareOperator parse_compare_operator(const char **s, CompareOperatorParseFlags flags);
_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)
"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");
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;
}