mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 00:14:32 +09:00
condition: introduce ConditionVersion=/AssertVersion=
Add a new condition wich checks against systemd version.
Change condition_test_kernel_version() into a generic condition_test_version()
so most of the code can be reused.
$ systemctl --version
systemd 258 (258~devel-g53ca5f6)
$ systemd-analyze condition 'ConditionVersion=systemd>255'
test.service: ConditionVersion=>255 succeeded.
$ systemd-analyze condition 'ConditionVersion=systemd>260'
test.service: ConditionVersion=>260 failed.
$ systemd-analyze condition 'ConditionVersion=systemd>=258'
test.service: ConditionVersion=>=258 succeeded.
$ systemd-analyze condition 'ConditionVersion=systemd>=257.1'
test.service: ConditionVersion=>=257.1 succeeded.
$ uname -r
6.12.13-200.fc41.aarch64
$ systemd-analyze condition 'ConditionVersion=kernel > 4.4'
test.service: ConditionVersion=kernel > 4.4 succeeded.
$ systemd-analyze condition 'ConditionVersion=kernel > 6.20'
test.service: ConditionVersion=kernel > 6.20 failed.
$ systemd-analyze condition 'ConditionVersion=kernel < 9.0'
test.service: ConditionVersion=kernel < 9.0 succeeded.
This commit is contained in:
committed by
Yu Watanabe
parent
f91273f4fc
commit
c154bb65ad
@@ -69,6 +69,7 @@ Most generic unit settings are available for transient units.
|
||||
✓ ConditionFirstBoot=
|
||||
✓ ConditionKernelCommandLine=
|
||||
✓ ConditionKernelVersion=
|
||||
✓ ConditionVersion=
|
||||
✓ ConditionArchitecture=
|
||||
✓ ConditionFirmware=
|
||||
✓ ConditionVirtualization=
|
||||
|
||||
@@ -525,8 +525,8 @@ cap_net_raw 13
|
||||
<example>
|
||||
<title>Evaluate conditions that check kernel versions</title>
|
||||
|
||||
<programlisting>$ systemd-analyze condition 'ConditionKernelVersion = ! <4.0' \
|
||||
'ConditionKernelVersion = >=5.1' \
|
||||
<programlisting>$ systemd-analyze condition 'ConditionVersion = ! <4.0' \
|
||||
'ConditionVersion = >=5.1' \
|
||||
'ConditionACPower=|false' \
|
||||
'ConditionArchitecture=|!arm' \
|
||||
'AssertPathExists=/etc/os-release'
|
||||
@@ -534,8 +534,8 @@ test.service: AssertPathExists=/etc/os-release succeeded.
|
||||
Asserts succeeded.
|
||||
test.service: ConditionArchitecture=|!arm succeeded.
|
||||
test.service: ConditionACPower=|false failed.
|
||||
test.service: ConditionKernelVersion=>=5.1 succeeded.
|
||||
test.service: ConditionKernelVersion=!<4.0 succeeded.
|
||||
test.service: ConditionVersion=>=5.1 succeeded.
|
||||
test.service: ConditionVersion=!<4.0 succeeded.
|
||||
Conditions succeeded.</programlisting>
|
||||
</example>
|
||||
</refsect2>
|
||||
|
||||
@@ -306,6 +306,19 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry id='version'>
|
||||
<term><varname>Version=</varname></term>
|
||||
<listitem>
|
||||
<para>Checks whether a software version matches a certain expression. See
|
||||
<varname>ConditionVersion=</varname> in
|
||||
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details. When prefixed with an exclamation mark (<literal>!</literal>), the result is negated.
|
||||
If an empty string is assigned, the previously assigned value is cleared.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry id='credential'>
|
||||
<term><varname>Credential=</varname></term>
|
||||
<listitem>
|
||||
|
||||
@@ -223,6 +223,7 @@
|
||||
<xi:include href="systemd.link.xml" xpointer="virtualization" />
|
||||
<xi:include href="systemd.link.xml" xpointer="kernel-command-line" />
|
||||
<xi:include href="systemd.link.xml" xpointer="kernel-version" />
|
||||
<xi:include href="systemd.link.xml" xpointer="version" />
|
||||
<xi:include href="systemd.link.xml" xpointer="credential" />
|
||||
<xi:include href="systemd.link.xml" xpointer="architecture" />
|
||||
<xi:include href="systemd.link.xml" xpointer="firmware" />
|
||||
|
||||
@@ -152,6 +152,7 @@
|
||||
<xi:include href="systemd.link.xml" xpointer="virtualization" />
|
||||
<xi:include href="systemd.link.xml" xpointer="kernel-command-line" />
|
||||
<xi:include href="systemd.link.xml" xpointer="kernel-version" />
|
||||
<xi:include href="systemd.link.xml" xpointer="version" />
|
||||
<xi:include href="systemd.link.xml" xpointer="credential" />
|
||||
<xi:include href="systemd.link.xml" xpointer="architecture" />
|
||||
<xi:include href="systemd.link.xml" xpointer="firmware" />
|
||||
|
||||
@@ -1481,6 +1481,24 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>ConditionVersion=</varname></term>
|
||||
|
||||
<listitem><para><varname>ConditionVersion=</varname> may be used to check whether a software
|
||||
version matches a certain expression, or if prefixed with the exclamation mark, does not match.
|
||||
The first argument is the software whose version has to be checked. Currently
|
||||
<literal>kernel</literal> and <literal>systemd</literal> are supported. If this argument is
|
||||
omitted, <literal>kernel</literal> is implied. The second argument must be a list
|
||||
of (potentially quoted) expressions. Each expression starts with one of <literal>=</literal> or
|
||||
<literal>!=</literal> for string comparisons, <literal><</literal>, <literal><=</literal>,
|
||||
<literal>==</literal>, <literal><></literal>, <literal>>=</literal>,
|
||||
<literal>></literal> for version comparisons, or <literal>$=</literal>, <literal>!$=</literal>
|
||||
for a shell-style glob match. If no operator is specified, <literal>$=</literal> is implied.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>ConditionCredential=</varname></term>
|
||||
|
||||
|
||||
@@ -360,7 +360,8 @@ Unit.ConditionFirmware, config_parse_unit_condition_string
|
||||
Unit.ConditionVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, offsetof(Unit, conditions)
|
||||
Unit.ConditionHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, conditions)
|
||||
Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, conditions)
|
||||
Unit.ConditionKernelVersion, config_parse_unit_condition_string, CONDITION_KERNEL_VERSION, offsetof(Unit, conditions)
|
||||
Unit.ConditionKernelVersion, config_parse_unit_condition_string, CONDITION_VERSION, offsetof(Unit, conditions)
|
||||
Unit.ConditionVersion, config_parse_unit_condition_string, CONDITION_VERSION, offsetof(Unit, conditions)
|
||||
Unit.ConditionCredential, config_parse_unit_condition_string, CONDITION_CREDENTIAL, offsetof(Unit, conditions)
|
||||
Unit.ConditionSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, offsetof(Unit, conditions)
|
||||
Unit.ConditionCapability, config_parse_unit_condition_string, CONDITION_CAPABILITY, offsetof(Unit, conditions)
|
||||
@@ -393,7 +394,8 @@ Unit.AssertArchitecture, config_parse_unit_condition_string
|
||||
Unit.AssertVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, offsetof(Unit, asserts)
|
||||
Unit.AssertHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, asserts)
|
||||
Unit.AssertKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, asserts)
|
||||
Unit.AssertKernelVersion, config_parse_unit_condition_string, CONDITION_KERNEL_VERSION, offsetof(Unit, asserts)
|
||||
Unit.AssertKernelVersion, config_parse_unit_condition_string, CONDITION_VERSION, offsetof(Unit, asserts)
|
||||
Unit.AssertVersion, config_parse_unit_condition_string, CONDITION_VERSION, offsetof(Unit, asserts)
|
||||
Unit.AssertCredential, config_parse_unit_condition_string, CONDITION_CREDENTIAL, offsetof(Unit, asserts)
|
||||
Unit.AssertSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, offsetof(Unit, asserts)
|
||||
Unit.AssertCapability, config_parse_unit_condition_string, CONDITION_CAPABILITY, offsetof(Unit, asserts)
|
||||
|
||||
@@ -45,7 +45,8 @@ struct ConfigPerfItem;
|
||||
Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(NetDev, conditions)
|
||||
Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(NetDev, conditions)
|
||||
Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(NetDev, conditions)
|
||||
Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(NetDev, conditions)
|
||||
Match.KernelVersion, config_parse_net_condition, CONDITION_VERSION, offsetof(NetDev, conditions)
|
||||
Match.Version, config_parse_net_condition, CONDITION_VERSION, offsetof(NetDev, conditions)
|
||||
Match.Credential, config_parse_net_condition, CONDITION_CREDENTIAL, offsetof(NetDev, conditions)
|
||||
Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(NetDev, conditions)
|
||||
Match.Firmware, config_parse_net_condition, CONDITION_FIRMWARE, offsetof(NetDev, conditions)
|
||||
|
||||
@@ -67,7 +67,8 @@ Match.Property, config_parse_match_property,
|
||||
Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(Network, conditions)
|
||||
Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(Network, conditions)
|
||||
Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(Network, conditions)
|
||||
Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(Network, conditions)
|
||||
Match.KernelVersion, config_parse_net_condition, CONDITION_VERSION, offsetof(Network, conditions)
|
||||
Match.Version, config_parse_net_condition, CONDITION_VERSION, offsetof(Network, conditions)
|
||||
Match.Credential, config_parse_net_condition, CONDITION_CREDENTIAL, offsetof(Network, conditions)
|
||||
Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(Network, conditions)
|
||||
Match.Firmware, config_parse_net_condition, CONDITION_FIRMWARE, offsetof(Network, conditions)
|
||||
|
||||
@@ -185,18 +185,14 @@ static int condition_test_credential(Condition *c, char **env) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static int condition_test_kernel_version(Condition *c, char **env) {
|
||||
static int condition_test_version_cmp(const char *condition, const char *ver) {
|
||||
CompareOperator operator;
|
||||
struct utsname u;
|
||||
bool first = true;
|
||||
|
||||
assert(c);
|
||||
assert(c->parameter);
|
||||
assert(c->type == CONDITION_KERNEL_VERSION);
|
||||
assert(condition);
|
||||
assert(ver);
|
||||
|
||||
assert_se(uname(&u) >= 0);
|
||||
|
||||
for (const char *p = c->parameter;;) {
|
||||
for (const char *p = condition;;) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
const char *s;
|
||||
int r;
|
||||
@@ -228,7 +224,7 @@ static int condition_test_kernel_version(Condition *c, char **env) {
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unexpected end of expression: %s", p);
|
||||
}
|
||||
|
||||
r = version_or_fnmatch_compare(operator, u.release, s);
|
||||
r = version_or_fnmatch_compare(operator, ver, s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (!r)
|
||||
@@ -240,6 +236,37 @@ static int condition_test_kernel_version(Condition *c, char **env) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int condition_test_version(Condition *c, char **env) {
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
assert(c->type == CONDITION_VERSION);
|
||||
|
||||
/* An empty condition is considered true. */
|
||||
if (isempty(c->parameter))
|
||||
return true;
|
||||
|
||||
const char *p = c->parameter;
|
||||
_cleanup_free_ char *word = NULL;
|
||||
r = extract_first_word(&p, &word, COMPARE_OPERATOR_WITH_FNMATCH_CHARS WHITESPACE,
|
||||
EXTRACT_DONT_COALESCE_SEPARATORS|EXTRACT_RETAIN_SEPARATORS);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to parse compare predicate \"%s\": %m", p);
|
||||
if (r == 0)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Missing right operand in condition: %s", c->parameter);
|
||||
|
||||
if (streq(word, "systemd"))
|
||||
return condition_test_version_cmp(p, STRINGIFY(PROJECT_VERSION));
|
||||
|
||||
/* if no predicate has been set, default to "kernel" and use the whole parameter as condition */
|
||||
if (!streq(word, "kernel"))
|
||||
p = c->parameter;
|
||||
|
||||
struct utsname u;
|
||||
assert_se(uname(&u) >= 0);
|
||||
return condition_test_version_cmp(p, u.release);
|
||||
}
|
||||
|
||||
static int condition_test_osrelease(Condition *c, char **env) {
|
||||
int r;
|
||||
|
||||
@@ -1222,7 +1249,7 @@ int condition_test(Condition *c, char **env) {
|
||||
[CONDITION_FILE_NOT_EMPTY] = condition_test_file_not_empty,
|
||||
[CONDITION_FILE_IS_EXECUTABLE] = condition_test_file_is_executable,
|
||||
[CONDITION_KERNEL_COMMAND_LINE] = condition_test_kernel_command_line,
|
||||
[CONDITION_KERNEL_VERSION] = condition_test_kernel_version,
|
||||
[CONDITION_VERSION] = condition_test_version,
|
||||
[CONDITION_CREDENTIAL] = condition_test_credential,
|
||||
[CONDITION_VIRTUALIZATION] = condition_test_virtualization,
|
||||
[CONDITION_SECURITY] = condition_test_security,
|
||||
@@ -1335,13 +1362,13 @@ void condition_dump_list(Condition *first, FILE *f, const char *prefix, conditio
|
||||
condition_dump(c, f, prefix, to_string);
|
||||
}
|
||||
|
||||
static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
|
||||
static const char* const _condition_type_table[_CONDITION_TYPE_MAX] = {
|
||||
[CONDITION_ARCHITECTURE] = "ConditionArchitecture",
|
||||
[CONDITION_FIRMWARE] = "ConditionFirmware",
|
||||
[CONDITION_VIRTUALIZATION] = "ConditionVirtualization",
|
||||
[CONDITION_HOST] = "ConditionHost",
|
||||
[CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
|
||||
[CONDITION_KERNEL_VERSION] = "ConditionKernelVersion",
|
||||
[CONDITION_VERSION] = "ConditionVersion",
|
||||
[CONDITION_CREDENTIAL] = "ConditionCredential",
|
||||
[CONDITION_SECURITY] = "ConditionSecurity",
|
||||
[CONDITION_CAPABILITY] = "ConditionCapability",
|
||||
@@ -1372,15 +1399,27 @@ static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
|
||||
[CONDITION_KERNEL_MODULE_LOADED] = "ConditionKernelModuleLoaded",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType);
|
||||
DEFINE_PRIVATE_STRING_TABLE_LOOKUP(_condition_type, ConditionType);
|
||||
|
||||
static const char* const assert_type_table[_CONDITION_TYPE_MAX] = {
|
||||
const char* condition_type_to_string(ConditionType t) {
|
||||
return _condition_type_to_string(t);
|
||||
}
|
||||
|
||||
ConditionType condition_type_from_string(const char *s) {
|
||||
/* for backward compatibility */
|
||||
if (streq_ptr(s, "ConditionKernelVersion"))
|
||||
return CONDITION_VERSION;
|
||||
|
||||
return _condition_type_from_string(s);
|
||||
}
|
||||
|
||||
static const char* const _assert_type_table[_CONDITION_TYPE_MAX] = {
|
||||
[CONDITION_ARCHITECTURE] = "AssertArchitecture",
|
||||
[CONDITION_FIRMWARE] = "AssertFirmware",
|
||||
[CONDITION_VIRTUALIZATION] = "AssertVirtualization",
|
||||
[CONDITION_HOST] = "AssertHost",
|
||||
[CONDITION_KERNEL_COMMAND_LINE] = "AssertKernelCommandLine",
|
||||
[CONDITION_KERNEL_VERSION] = "AssertKernelVersion",
|
||||
[CONDITION_VERSION] = "AssertVersion",
|
||||
[CONDITION_CREDENTIAL] = "AssertCredential",
|
||||
[CONDITION_SECURITY] = "AssertSecurity",
|
||||
[CONDITION_CAPABILITY] = "AssertCapability",
|
||||
@@ -1411,7 +1450,19 @@ static const char* const assert_type_table[_CONDITION_TYPE_MAX] = {
|
||||
[CONDITION_KERNEL_MODULE_LOADED] = "AssertKernelModuleLoaded",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(assert_type, ConditionType);
|
||||
DEFINE_PRIVATE_STRING_TABLE_LOOKUP(_assert_type, ConditionType);
|
||||
|
||||
const char* assert_type_to_string(ConditionType t) {
|
||||
return _assert_type_to_string(t);
|
||||
}
|
||||
|
||||
ConditionType assert_type_from_string(const char *s) {
|
||||
/* for backward compatibility */
|
||||
if (streq_ptr(s, "AssertKernelVersion"))
|
||||
return CONDITION_VERSION;
|
||||
|
||||
return _assert_type_from_string(s);
|
||||
}
|
||||
|
||||
static const char* const condition_result_table[_CONDITION_RESULT_MAX] = {
|
||||
[CONDITION_UNTESTED] = "untested",
|
||||
|
||||
@@ -13,7 +13,7 @@ typedef enum ConditionType {
|
||||
CONDITION_VIRTUALIZATION,
|
||||
CONDITION_HOST,
|
||||
CONDITION_KERNEL_COMMAND_LINE,
|
||||
CONDITION_KERNEL_VERSION,
|
||||
CONDITION_VERSION,
|
||||
CONDITION_CREDENTIAL,
|
||||
CONDITION_SECURITY,
|
||||
CONDITION_CAPABILITY,
|
||||
|
||||
@@ -460,115 +460,220 @@ TEST(condition_test_kernel_version) {
|
||||
struct utsname u;
|
||||
const char *v;
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, "*thisreallyshouldntbeinthekernelversion*", false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "*thisreallyshouldntbeinthekernelversion*", false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, "*", false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "*", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
/* An artificially empty condition. It evaluates to true, but normally
|
||||
* such condition cannot be created, because the condition list is reset instead. */
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, "", false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_OK_ERRNO(uname(&u));
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, u.release, false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, u.release, false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
strshorten(u.release, 4);
|
||||
strcpy(strchr(u.release, 0), "*");
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, u.release, false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, u.release, false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
/* 0.1.2 would be a very very very old kernel */
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, "> 0.1.2", false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "> 0.1.2", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, ">0.1.2", false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, ">0.1.2", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, "'>0.1.2' '<9.0.0'", false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "'>0.1.2' '<9.0.0'", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, "> 0.1.2 < 9.0.0", false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "> 0.1.2 < 9.0.0", false, false)));
|
||||
ASSERT_ERROR(condition_test(condition, environ), EINVAL);
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, ">", false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, ">", false, false)));
|
||||
ASSERT_ERROR(condition_test(condition, environ), EINVAL);
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, ">= 0.1.2", false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, ">= 0.1.2", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, "< 0.1.2", false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "< 0.1.2", false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, "<= 0.1.2", false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "<= 0.1.2", false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, "= 0.1.2", false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "= 0.1.2", false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
/* 4711.8.15 is a very very very future kernel */
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, "< 4711.8.15", false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "< 4711.8.15", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, "<= 4711.8.15", false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "<= 4711.8.15", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, "= 4711.8.15", false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "= 4711.8.15", false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, "> 4711.8.15", false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "> 4711.8.15", false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, " >= 4711.8.15", false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, " >= 4711.8.15", false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_OK_ERRNO(uname(&u));
|
||||
|
||||
v = strjoina(">=", u.release);
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, v, false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
v = strjoina("= ", u.release);
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, v, false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
v = strjoina("<=", u.release);
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, v, false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
v = strjoina("> ", u.release);
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, v, false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
v = strjoina("< ", u.release);
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false)));
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, v, false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
}
|
||||
|
||||
TEST(condition_test_version) {
|
||||
Condition *condition;
|
||||
const char *v;
|
||||
char ver[8];
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "systemd *thisreallyshouldntbeinthesystemdversion*", false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "systemd *", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
/* An artificially empty condition. It evaluates to true, but normally
|
||||
* such condition cannot be created, because the condition list is reset instead. */
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
/* 42 would be a very very very old systemd release */
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "systemd > 42", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "systemd>42", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "systemd '>42' '<9000'", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "systemd > 42 < 9000", false, false)));
|
||||
ASSERT_ERROR(condition_test(condition, environ), EINVAL);
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "systemd>", false, false)));
|
||||
ASSERT_ERROR(condition_test(condition, environ), EINVAL);
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "systemd >= 42", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "systemd < 42", false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "systemd <= 42", false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "systemd = 42", false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
/* 9000 is a very very very future systemd release */
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "systemd < 9000", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "systemd <= 9000", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "systemd = 9000", false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "systemd > 9000", false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, "systemd >= 9000", false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
xsprintf(ver, "%d", PROJECT_VERSION);
|
||||
|
||||
v = strjoina("systemd>=", ver);
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, v, false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
v = strjoina("systemd = ", ver);
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, v, false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
v = strjoina("systemd<=", ver);
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, v, false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
v = strjoina("systemd > ", ver);
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, v, false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
v = strjoina("systemd < ", ver);
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_VERSION, v, false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,8 @@ Match.Property, config_parse_match_property,
|
||||
Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(LinkConfig, conditions)
|
||||
Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(LinkConfig, conditions)
|
||||
Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(LinkConfig, conditions)
|
||||
Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(LinkConfig, conditions)
|
||||
Match.KernelVersion, config_parse_net_condition, CONDITION_VERSION, offsetof(LinkConfig, conditions)
|
||||
Match.Version, config_parse_net_condition, CONDITION_VERSION, offsetof(LinkConfig, conditions)
|
||||
Match.Credential, config_parse_net_condition, CONDITION_CREDENTIAL, offsetof(LinkConfig, conditions)
|
||||
Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(LinkConfig, conditions)
|
||||
Match.Firmware, config_parse_net_condition, CONDITION_FIRMWARE, offsetof(LinkConfig, conditions)
|
||||
|
||||
@@ -6,6 +6,21 @@ ConditionKernelVersion=">=2.0" "<=60" "!=1.4"
|
||||
ConditionKernelVersion=" >= 2.0" " <= 60 " "!= 1.4"
|
||||
ConditionKernelVersion=" >= 2.0" " * " "*.*"
|
||||
|
||||
ConditionVersion=kernel ">=3.0"
|
||||
ConditionVersion=kernel ">=2.0" "<=60" "!=1.4"
|
||||
ConditionVersion=kernel " >= 2.0" " <= 60 " "!= 1.4"
|
||||
ConditionVersion=kernel " >= 2.0" " * " "*.*"
|
||||
|
||||
ConditionVersion=">=3.0"
|
||||
ConditionVersion=">=2.0" "<=60" "!=1.4"
|
||||
ConditionVersion=" >= 2.0" " <= 60 " "!= 1.4"
|
||||
ConditionVersion=" >= 2.0" " * " "*.*"
|
||||
|
||||
ConditionVersion=systemd ">=30"
|
||||
ConditionVersion=systemd ">=20" "<=9000" "!=14"
|
||||
ConditionVersion=systemd " >= 20" " <= 9000 " "!= 14"
|
||||
ConditionVersion=systemd " >= 20" " * "
|
||||
|
||||
[Service]
|
||||
ExecStart=touch /tmp/a ; /bin/sh -c 'touch /tmp/b' ; touch /tmp/c
|
||||
ExecStart=test -f /tmp/a
|
||||
|
||||
Reference in New Issue
Block a user