1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-01-26 10:03:40 +03:00

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.
This commit is contained in:
Lennart Poettering 2022-08-26 16:56:04 +02:00
parent 69f0a6091b
commit 57610982f7
3 changed files with 33 additions and 11 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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(&parameter, &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;
}