udev: introduce CONST key name

Currently, there is no way to match against system-wide constants, such
as architecture or virtualization type, without forking helper binaries.
That potentially results in a huge number of spawned processes which
output always the same answer.

This patch introduces a special CONST keyword which takes a hard-coded
string as its key and returns a value assigned to that key. Currently
implemented are CONST{arch} and CONST{virt}, which can be used to match
against the system's architecture and virtualization type.
This commit is contained in:
Jan Synacek 2019-10-07 10:03:07 +02:00 committed by Yu Watanabe
parent 55d3fdcf5e
commit 4801d8afe2
2 changed files with 46 additions and 0 deletions

View File

@ -236,6 +236,32 @@
</listitem>
</varlistentry>
<varlistentry>
<term><varname>CONST{<replaceable>key</replaceable>}</varname></term>
<listitem>
<para>Match against a system-wide constant. Supported keys are:</para>
<variablelist>
<varlistentry>
<term><literal>arch</literal></term>
<listitem>
<para>System's architecture. See <option>ConditionArchitecture=</option> in
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for possible values.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>virt</literal></term>
<listitem>
<para>System's virtualization environment. See
<citerefentry><refentrytitle>systemd-detect-virt</refentrytitle><manvolnum>1</manvolnum></citerefentry>
for possible values.</para>
</listitem>
</varlistentry>
</variablelist>
<para>Unknown keys will never match.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>TAG</varname></term>
<listitem>

View File

@ -3,6 +3,7 @@
#include <ctype.h>
#include "alloc-util.h"
#include "architecture.h"
#include "conf-files.h"
#include "def.h"
#include "device-util.h"
@ -28,6 +29,7 @@
#include "udev-event.h"
#include "udev-rules.h"
#include "user-util.h"
#include "virt.h"
#define RULES_DIRS (const char* const*) CONF_PATHS_STRV("udev/rules.d")
@ -69,6 +71,7 @@ typedef enum {
TK_M_DEVLINK, /* strv, sd_device_get_devlink_first(), sd_device_get_devlink_next() */
TK_M_NAME, /* string, name of network interface */
TK_M_ENV, /* string, device property, takes key through attribute */
TK_M_CONST, /* string, system-specific hard-coded constant */
TK_M_TAG, /* strv, sd_device_get_tag_first(), sd_device_get_tag_next() */
TK_M_SUBSYSTEM, /* string, sd_device_get_subsystem() */
TK_M_DRIVER, /* string, sd_device_get_driver() */
@ -618,6 +621,12 @@ static int parse_token(UdevRules *rules, const char *key, char *attr, UdevRuleOp
r = rule_line_add_token(rule_line, TK_A_ENV, op, value, attr);
} else
r = rule_line_add_token(rule_line, TK_M_ENV, op, value, attr);
} else if (streq(key, "CONST")) {
if (isempty(attr) || !STR_IN_SET(attr, "arch", "virt"))
return log_token_invalid_attr(rules, key);
if (!is_match)
return log_token_invalid_op(rules, key);
r = rule_line_add_token(rule_line, TK_M_CONST, op, value, attr);
} else if (streq(key, "TAG")) {
if (attr)
return log_token_invalid_attr(rules, key);
@ -1574,6 +1583,17 @@ static int udev_rule_apply_token_to_event(
val = hashmap_get(properties_list, token->data);
return token_match_string(token, val);
case TK_M_CONST: {
const char *k = token->data;
if (streq(k, "arch"))
val = architecture_to_string(uname_architecture());
else if (streq(k, "virt"))
val = virtualization_to_string(detect_virtualization());
else
assert_not_reached("Invalid CONST key");
return token_match_string(token, val);
}
case TK_M_TAG:
case TK_M_PARENTS_TAG:
FOREACH_DEVICE_TAG(dev, val)