summaryrefslogtreecommitdiffstats
path: root/src/shared/condition.c
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-06-25 09:22:50 +0200
committerGitHub <noreply@github.com>2021-06-25 09:22:50 +0200
commita2e2917162e7ca587cbad94b5366f5cee0385b29 (patch)
tree83181f2197b2c1e2fbe26b15ade4f75a3abd7f32 /src/shared/condition.c
parenttree-wide: make specifier expansion --root= aware (diff)
parentcore: add ConditionOSRelease= directive (diff)
downloadsystemd-a2e2917162e7ca587cbad94b5366f5cee0385b29.tar.xz
systemd-a2e2917162e7ca587cbad94b5366f5cee0385b29.zip
Merge pull request #19941 from bluca/condition_os_release
core: add ConditionOSRelease= directive
Diffstat (limited to 'src/shared/condition.c')
-rw-r--r--src/shared/condition.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/shared/condition.c b/src/shared/condition.c
index 55fb636673..ec9d57b292 100644
--- a/src/shared/condition.c
+++ b/src/shared/condition.c
@@ -24,6 +24,7 @@
#include "cpu-set-util.h"
#include "efi-loader.h"
#include "env-file.h"
+#include "env-util.h"
#include "extract-word.h"
#include "fd-util.h"
#include "fileio.h"
@@ -35,6 +36,7 @@
#include "list.h"
#include "macro.h"
#include "mountpoint-util.h"
+#include "os-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "proc-cmdline.h"
@@ -263,6 +265,61 @@ static int condition_test_kernel_version(Condition *c, char **env) {
return true;
}
+static int condition_test_osrelease(Condition *c, char **env) {
+ const char *parameter = c->parameter;
+ int r;
+
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_OS_RELEASE);
+
+ for (;;) {
+ _cleanup_free_ char *key = NULL, *condition = NULL, *actual_value = NULL;
+ OrderOperator order;
+ const char *word;
+ bool matches;
+
+ r = extract_first_word(&parameter, &condition, NULL, EXTRACT_UNQUOTE);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to parse parameter: %m");
+ if (r == 0)
+ break;
+
+ /* parse_order() needs the string to start with the comparators */
+ word = condition;
+ r = extract_first_word(&word, &key, "!<=>", EXTRACT_RETAIN_SEPARATORS);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to parse parameter: %m");
+ /* The os-release spec mandates env-var-like key names */
+ if (r == 0 || isempty(word) || !env_name_is_valid(key))
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+ "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 */
+ order = parse_order(&word);
+ if (order < 0 || isempty(word) || strchr(WHITESPACE, *word) != NULL)
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Failed to parse parameter, key/value format expected: %m");
+
+ r = parse_os_release(NULL, key, &actual_value);
+ 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 (order == ORDER_EQUAL)
+ matches = streq_ptr(actual_value, word);
+ else if (order == ORDER_UNEQUAL)
+ matches = !streq_ptr(actual_value, word);
+ else
+ matches = test_order(strverscmp_improved(actual_value, word), order);
+
+ if (!matches)
+ return false;
+ }
+
+ return true;
+}
+
static int condition_test_memory(Condition *c, char **env) {
OrderOperator order;
uint64_t m, k;
@@ -935,6 +992,7 @@ int condition_test(Condition *c, char **env) {
[CONDITION_MEMORY] = condition_test_memory,
[CONDITION_ENVIRONMENT] = condition_test_environment,
[CONDITION_CPU_FEATURE] = condition_test_cpufeature,
+ [CONDITION_OS_RELEASE] = condition_test_osrelease,
};
int r, b;
@@ -1059,6 +1117,7 @@ static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
[CONDITION_MEMORY] = "ConditionMemory",
[CONDITION_ENVIRONMENT] = "ConditionEnvironment",
[CONDITION_CPU_FEATURE] = "ConditionCPUFeature",
+ [CONDITION_OS_RELEASE] = "ConditionOSRelease",
};
DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType);
@@ -1092,6 +1151,7 @@ static const char* const assert_type_table[_CONDITION_TYPE_MAX] = {
[CONDITION_MEMORY] = "AssertMemory",
[CONDITION_ENVIRONMENT] = "AssertEnvironment",
[CONDITION_CPU_FEATURE] = "AssertCPUFeature",
+ [CONDITION_OS_RELEASE] = "AssertOSRelease",
};
DEFINE_STRING_TABLE_LOOKUP(assert_type, ConditionType);