summaryrefslogtreecommitdiffstats
path: root/src/udev
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 03:50:40 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 03:50:40 +0000
commitfc53809803cd2bc2434e312b19a18fa36776da12 (patch)
treeb4b43bd6538f51965ce32856e9c053d0f90919c8 /src/udev
parentAdding upstream version 255.5. (diff)
downloadsystemd-fc53809803cd2bc2434e312b19a18fa36776da12.tar.xz
systemd-fc53809803cd2bc2434e312b19a18fa36776da12.zip
Adding upstream version 256.upstream/256
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/udev')
-rw-r--r--src/udev/ata_id/ata_id.c14
-rw-r--r--src/udev/cdrom_id/cdrom_id.c6
-rw-r--r--src/udev/dmi_memory_id/dmi_memory_id.c8
-rw-r--r--src/udev/fido_id/fido_id.c6
-rw-r--r--src/udev/meson.build4
-rw-r--r--src/udev/net/link-config-gperf.gperf4
-rw-r--r--src/udev/net/link-config.c359
-rw-r--r--src/udev/net/link-config.h14
-rw-r--r--src/udev/scsi_id/scsi.h12
-rw-r--r--src/udev/scsi_id/scsi_id.c19
-rw-r--r--src/udev/test-udev-format.c10
-rw-r--r--src/udev/test-udev-rule-runner.c12
-rw-r--r--src/udev/test-udev-spawn.c10
-rw-r--r--src/udev/udev-builtin-blkid.c70
-rw-r--r--src/udev/udev-builtin-btrfs.c6
-rw-r--r--src/udev/udev-builtin-hwdb.c42
-rw-r--r--src/udev/udev-builtin-input_id.c89
-rw-r--r--src/udev/udev-builtin-keyboard.c7
-rw-r--r--src/udev/udev-builtin-kmod.c34
-rw-r--r--src/udev/udev-builtin-net_driver.c4
-rw-r--r--src/udev/udev-builtin-net_id.c191
-rw-r--r--src/udev/udev-builtin-net_setup_link.c47
-rw-r--r--src/udev/udev-builtin-path_id.c98
-rw-r--r--src/udev/udev-builtin-uaccess.c7
-rw-r--r--src/udev/udev-builtin-usb_id.c58
-rw-r--r--src/udev/udev-builtin.c35
-rw-r--r--src/udev/udev-builtin.h11
-rw-r--r--src/udev/udev-event.c146
-rw-r--r--src/udev/udev-event.h30
-rw-r--r--src/udev/udev-format.c6
-rw-r--r--src/udev/udev-format.h1
-rw-r--r--src/udev/udev-manager.c90
-rw-r--r--src/udev/udev-manager.h1
-rw-r--r--src/udev/udev-node.c7
-rw-r--r--src/udev/udev-rules.c121
-rw-r--r--src/udev/udev-rules.h5
-rw-r--r--src/udev/udev-spawn.c94
-rw-r--r--src/udev/udev-spawn.h7
-rw-r--r--src/udev/udev-watch.c5
-rw-r--r--src/udev/udev-worker.c37
-rw-r--r--src/udev/udev-worker.h3
-rw-r--r--src/udev/udevadm-control.c111
-rw-r--r--src/udev/udevadm-hwdb.c2
-rw-r--r--src/udev/udevadm-info.c2
-rw-r--r--src/udev/udevadm-lock.c4
-rw-r--r--src/udev/udevadm-monitor.c2
-rw-r--r--src/udev/udevadm-test-builtin.c18
-rw-r--r--src/udev/udevadm-test.c94
-rw-r--r--src/udev/udevadm-wait.c2
-rw-r--r--src/udev/udevadm.c2
-rw-r--r--src/udev/udevd.c87
-rw-r--r--src/udev/v4l_id/v4l_id.c10
52 files changed, 1287 insertions, 777 deletions
diff --git a/src/udev/ata_id/ata_id.c b/src/udev/ata_id/ata_id.c
index 4dd7e54..6baf139 100644
--- a/src/udev/ata_id/ata_id.c
+++ b/src/udev/ata_id/ata_id.c
@@ -86,14 +86,14 @@ static int disk_scsi_inquiry_command(
if (io_hdr.status != 0 ||
io_hdr.host_status != 0 ||
io_hdr.driver_status != 0)
- return log_debug_errno(SYNTHETIC_ERRNO(EIO), "ioctl v3 failed");
+ return log_debug_errno(SYNTHETIC_ERRNO(EIO), "ioctl v3 failed.");
} else {
/* even if the ioctl succeeds, we need to check the return value */
if (io_v4.device_status != 0 ||
io_v4.transport_status != 0 ||
io_v4.driver_status != 0)
- return log_debug_errno(SYNTHETIC_ERRNO(EIO), "ioctl v4 failed");
+ return log_debug_errno(SYNTHETIC_ERRNO(EIO), "ioctl v4 failed.");
}
return 0;
@@ -160,7 +160,7 @@ static int disk_identify_command(
} else {
if (!((sense[0] & 0x7f) == 0x72 && desc[0] == 0x9 && desc[1] == 0x0c) &&
!((sense[0] & 0x7f) == 0x70 && sense[12] == 0x00 && sense[13] == 0x1d))
- return log_debug_errno(SYNTHETIC_ERRNO(EIO), "ioctl v4 failed: %m");
+ return log_debug_errno(SYNTHETIC_ERRNO(EIO), "ioctl v4 failed.");
}
return 0;
@@ -232,7 +232,7 @@ static int disk_identify_packet_device_command(
return log_debug_errno(errno, "ioctl v3 failed: %m");
} else {
if ((sense[0] & 0x7f) != 0x72 || desc[0] != 0x9 || desc[1] != 0x0c)
- return log_debug_errno(SYNTHETIC_ERRNO(EIO), "ioctl v4 failed: %m");
+ return log_debug_errno(SYNTHETIC_ERRNO(EIO), "ioctl v4 failed.");
}
return 0;
@@ -413,10 +413,8 @@ static int run(int argc, char *argv[]) {
uint16_t word;
int r, peripheral_device_type = -1;
- log_set_target(LOG_TARGET_AUTO);
- udev_parse_config();
- log_parse_environment();
- log_open();
+ (void) udev_parse_config();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
diff --git a/src/udev/cdrom_id/cdrom_id.c b/src/udev/cdrom_id/cdrom_id.c
index 9285dd8..195fadc 100644
--- a/src/udev/cdrom_id/cdrom_id.c
+++ b/src/udev/cdrom_id/cdrom_id.c
@@ -959,10 +959,8 @@ static int run(int argc, char *argv[]) {
_cleanup_(context_clear) Context c = CONTEXT_EMPTY;
int r;
- log_set_target(LOG_TARGET_AUTO);
- udev_parse_config();
- log_parse_environment();
- log_open();
+ (void) udev_parse_config();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
diff --git a/src/udev/dmi_memory_id/dmi_memory_id.c b/src/udev/dmi_memory_id/dmi_memory_id.c
index 3f89cc7..9823df0 100644
--- a/src/udev/dmi_memory_id/dmi_memory_id.c
+++ b/src/udev/dmi_memory_id/dmi_memory_id.c
@@ -96,7 +96,7 @@ static const char *dmi_string(const struct dmi_header *dm, uint8_t s) {
return "Not Specified";
bp += dm->length;
- for (;s > 1 && !isempty(bp); s--)
+ for (; s > 1 && !isempty(bp); s--)
bp += strlen(bp) + 1;
if (isempty(bp))
@@ -685,10 +685,8 @@ static int run(int argc, char* const* argv) {
size_t size;
int r;
- log_set_target(LOG_TARGET_AUTO);
- udev_parse_config();
- log_parse_environment();
- log_open();
+ (void) udev_parse_config();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
diff --git a/src/udev/fido_id/fido_id.c b/src/udev/fido_id/fido_id.c
index e01f37d..6c4b099 100644
--- a/src/udev/fido_id/fido_id.c
+++ b/src/udev/fido_id/fido_id.c
@@ -70,10 +70,8 @@ static int run(int argc, char **argv) {
ssize_t desc_len;
int r;
- log_set_target(LOG_TARGET_AUTO);
- udev_parse_config();
- log_parse_environment();
- log_open();
+ (void) udev_parse_config();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
diff --git a/src/udev/meson.build b/src/udev/meson.build
index 824ec47..3535551 100644
--- a/src/udev/meson.build
+++ b/src/udev/meson.build
@@ -114,7 +114,7 @@ libudevd_core = static_library(
include_directories : includes + include_directories('net'),
link_with : udev_link_with,
dependencies : [libblkid,
- libkmod,
+ libkmod_cflags,
userspace],
build_by_default : false)
@@ -205,6 +205,7 @@ executables += [
},
udev_test_template + {
'sources' : files('net/test-link-config-tables.c'),
+ 'include_directories' : includes + include_directories('.'),
'suite' : 'udev',
},
udev_test_template + {
@@ -240,6 +241,7 @@ executables += [
},
udev_fuzz_template + {
'sources' : files('net/fuzz-link-parser.c'),
+ 'include_directories' : includes + include_directories('.'),
},
udev_fuzz_template + {
'sources' : files('fuzz-udev-rule-parse-value.c'),
diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf
index 240f16e..b77759d 100644
--- a/src/udev/net/link-config-gperf.gperf
+++ b/src/udev/net/link-config-gperf.gperf
@@ -38,6 +38,9 @@ Match.Credential, config_parse_net_condition,
Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(LinkConfig, conditions)
Match.Firmware, config_parse_net_condition, CONDITION_FIRMWARE, offsetof(LinkConfig, conditions)
Link.Description, config_parse_string, 0, offsetof(LinkConfig, description)
+Link.Property, config_parse_udev_property, 0, offsetof(LinkConfig, properties)
+Link.ImportProperty, config_parse_udev_property_name, 0, offsetof(LinkConfig, import_properties)
+Link.UnsetProperty, config_parse_udev_property_name, 0, offsetof(LinkConfig, unset_properties)
Link.MACAddressPolicy, config_parse_mac_address_policy, 0, offsetof(LinkConfig, mac_address_policy)
Link.MACAddress, config_parse_hw_addr, 0, offsetof(LinkConfig, hw_addr)
Link.NamePolicy, config_parse_name_policy, 0, offsetof(LinkConfig, name_policy)
@@ -105,6 +108,7 @@ Link.RxMaxCoalescedHighFrames, config_parse_coalesce_u32,
Link.TxCoalesceHighSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.tx_coalesce_usecs_high)
Link.TxMaxCoalescedHighFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_high)
Link.CoalescePacketRateSampleIntervalSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.rate_sample_interval)
+Link.ReceivePacketSteeringCPUMask, config_parse_rps_cpu_mask, 0, offsetof(LinkConfig, rps_cpu_mask)
Link.MDI, config_parse_mdi, 0, offsetof(LinkConfig, mdi)
Link.SR-IOVVirtualFunctions, config_parse_sr_iov_num_vfs, 0, offsetof(LinkConfig, sr_iov_num_vfs)
SR-IOV.VirtualFunction, config_parse_sr_iov_uint32, 0, offsetof(LinkConfig, sr_iov_by_section)
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index 910ec27..647cdee 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -15,6 +15,8 @@
#include "creds-util.h"
#include "device-private.h"
#include "device-util.h"
+#include "env-util.h"
+#include "escape.h"
#include "ethtool-util.h"
#include "fd-util.h"
#include "fileio.h"
@@ -30,12 +32,20 @@
#include "path-util.h"
#include "proc-cmdline.h"
#include "random-util.h"
+#include "specifier.h"
#include "stat-util.h"
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
+#include "udev-builtin.h"
#include "utf8.h"
+static const Specifier link_specifier_table[] = {
+ COMMON_SYSTEM_SPECIFIERS,
+ COMMON_TMP_SPECIFIERS,
+ {}
+};
+
struct LinkConfigContext {
LIST_HEAD(LinkConfig, configs);
int ethtool_fd;
@@ -53,6 +63,9 @@ static LinkConfig* link_config_free(LinkConfig *config) {
condition_free_list(config->conditions);
free(config->description);
+ strv_free(config->properties);
+ strv_free(config->import_properties);
+ strv_free(config->unset_properties);
free(config->name_policy);
free(config->name);
strv_free(config->alternative_names);
@@ -60,6 +73,7 @@ static LinkConfig* link_config_free(LinkConfig *config) {
free(config->alias);
free(config->wol_password_file);
erase_and_free(config->wol_password);
+ cpu_set_free(config->rps_cpu_mask);
ordered_hashmap_free_with_destructor(config->sr_iov_by_section, sr_iov_free);
@@ -363,18 +377,20 @@ Link *link_free(Link *link) {
return NULL;
sd_device_unref(link->device);
+ sd_device_unref(link->device_db_clone);
free(link->kind);
strv_free(link->altnames);
return mfree(link);
}
-int link_new(LinkConfigContext *ctx, sd_netlink **rtnl, sd_device *device, Link **ret) {
+int link_new(LinkConfigContext *ctx, sd_netlink **rtnl, sd_device *device, sd_device *device_db_clone, Link **ret) {
_cleanup_(link_freep) Link *link = NULL;
int r;
assert(ctx);
assert(rtnl);
assert(device);
+ assert(device_db_clone);
assert(ret);
link = new(Link, 1);
@@ -383,6 +399,7 @@ int link_new(LinkConfigContext *ctx, sd_netlink **rtnl, sd_device *device, Link
*link = (Link) {
.device = sd_device_ref(device),
+ .device_db_clone = sd_device_ref(device_db_clone),
};
r = sd_device_get_sysname(device, &link->ifname);
@@ -466,7 +483,7 @@ int link_get_config(LinkConfigContext *ctx, Link *link) {
return -ENOENT;
}
-static int link_apply_ethtool_settings(Link *link, int *ethtool_fd) {
+static int link_apply_ethtool_settings(Link *link, int *ethtool_fd, EventMode mode) {
LinkConfig *config;
const char *name;
int r;
@@ -475,6 +492,11 @@ static int link_apply_ethtool_settings(Link *link, int *ethtool_fd) {
assert(link->config);
assert(ethtool_fd);
+ if (mode != EVENT_UDEV_WORKER) {
+ log_link_debug(link, "Running in test mode, skipping application of ethtool settings.");
+ return 0;
+ }
+
config = link->config;
name = link->ifname;
@@ -667,7 +689,7 @@ finalize:
return 0;
}
-static int link_apply_rtnl_settings(Link *link, sd_netlink **rtnl) {
+static int link_apply_rtnl_settings(Link *link, sd_netlink **rtnl, EventMode mode) {
struct hw_addr_data hw_addr = {};
LinkConfig *config;
int r;
@@ -676,6 +698,11 @@ static int link_apply_rtnl_settings(Link *link, sd_netlink **rtnl) {
assert(link->config);
assert(rtnl);
+ if (mode != EVENT_UDEV_WORKER) {
+ log_link_debug(link, "Running in test mode, skipping application of rtnl settings.");
+ return 0;
+ }
+
config = link->config;
(void) link_generate_new_hw_addr(link, &hw_addr);
@@ -725,7 +752,7 @@ static int link_generate_new_name(Link *link) {
device = link->device;
if (link->action != SD_DEVICE_ADD) {
- log_link_debug(link, "Skipping to apply Name= and NamePolicy= on '%s' uevent.",
+ log_link_debug(link, "Not applying Name= and NamePolicy= on '%s' uevent.",
device_action_to_string(link->action));
goto no_rename;
}
@@ -805,7 +832,7 @@ static int link_generate_alternative_names(Link *link) {
assert(!link->altnames);
if (link->action != SD_DEVICE_ADD) {
- log_link_debug(link, "Skipping to apply AlternativeNames= and AlternativeNamesPolicy= on '%s' uevent.",
+ log_link_debug(link, "Not applying AlternativeNames= and AlternativeNamesPolicy= on '%s' uevent.",
device_action_to_string(link->action));
return 0;
}
@@ -879,7 +906,7 @@ static int sr_iov_configure(Link *link, sd_netlink **rtnl, SRIOV *sr_iov) {
return 0;
}
-static int link_apply_sr_iov_config(Link *link, sd_netlink **rtnl) {
+static int link_apply_sr_iov_config(Link *link, sd_netlink **rtnl, EventMode mode) {
SRIOV *sr_iov;
uint32_t n;
int r;
@@ -888,6 +915,11 @@ static int link_apply_sr_iov_config(Link *link, sd_netlink **rtnl) {
assert(link->config);
assert(link->device);
+ if (mode != EVENT_UDEV_WORKER) {
+ log_link_debug(link, "Running in test mode, skipping application of SR-IOV settings.");
+ return 0;
+ }
+
r = sr_iov_set_num_vfs(link->device, link->config->sr_iov_num_vfs, link->config->sr_iov_by_section);
if (r < 0)
log_link_warning_errno(link, r, "Failed to set the number of SR-IOV virtual functions, ignoring: %m");
@@ -921,26 +953,122 @@ static int link_apply_sr_iov_config(Link *link, sd_netlink **rtnl) {
return 0;
}
-int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link) {
+static int link_apply_rps_cpu_mask(Link *link, EventMode mode) {
+ _cleanup_free_ char *mask_str = NULL;
+ LinkConfig *config;
int r;
- assert(ctx);
- assert(rtnl);
assert(link);
+ config = ASSERT_PTR(link->config);
- if (!IN_SET(link->action, SD_DEVICE_ADD, SD_DEVICE_BIND, SD_DEVICE_MOVE)) {
- log_link_debug(link, "Skipping to apply .link settings on '%s' uevent.",
- device_action_to_string(link->action));
+ if (mode != EVENT_UDEV_WORKER) {
+ log_link_debug(link, "Running in test mode, skipping application of RPS setting.");
+ return 0;
+ }
- link->new_name = link->ifname;
+ /* Skip if the config is not specified. */
+ if (!config->rps_cpu_mask)
return 0;
+
+ mask_str = cpu_set_to_mask_string(config->rps_cpu_mask);
+ if (!mask_str)
+ return log_oom();
+
+ log_link_debug(link, "Applying RPS CPU mask: %s", mask_str);
+
+ /* Currently, this will set CPU mask to all rx queue of matched device. */
+ FOREACH_DEVICE_SYSATTR(link->device, attr) {
+ const char *c;
+
+ c = path_startswith(attr, "queues/");
+ if (!c)
+ continue;
+
+ c = startswith(c, "rx-");
+ if (!c)
+ continue;
+
+ c += strcspn(c, "/");
+
+ if (!path_equal(c, "/rps_cpus"))
+ continue;
+
+ r = sd_device_set_sysattr_value(link->device, attr, mask_str);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Failed to write %s sysfs attribute, ignoring: %m", attr);
+ }
+
+ return 0;
+}
+
+static int link_apply_udev_properties(Link *link, EventMode mode) {
+ LinkConfig *config;
+ sd_device *device;
+
+ assert(link);
+
+ config = ASSERT_PTR(link->config);
+ device = ASSERT_PTR(link->device);
+
+ /* 1. apply ImportProperty=. */
+ STRV_FOREACH(p, config->import_properties)
+ (void) udev_builtin_import_property(device, link->device_db_clone, mode, *p);
+
+ /* 2. apply Property=. */
+ STRV_FOREACH(p, config->properties) {
+ _cleanup_free_ char *key = NULL;
+ const char *eq;
+
+ eq = strchr(*p, '=');
+ if (!eq)
+ continue;
+
+ key = strndup(*p, eq - *p);
+ if (!key)
+ return log_oom();
+
+ (void) udev_builtin_add_property(device, mode, key, eq + 1);
+ }
+
+ /* 3. apply UnsetProperty=. */
+ STRV_FOREACH(p, config->unset_properties)
+ (void) udev_builtin_add_property(device, mode, *p, NULL);
+
+ /* 4. set the default properties. */
+ (void) udev_builtin_add_property(device, mode, "ID_NET_LINK_FILE", config->filename);
+
+ _cleanup_free_ char *joined = NULL;
+ STRV_FOREACH(d, config->dropins) {
+ _cleanup_free_ char *escaped = NULL;
+
+ escaped = xescape(*d, ":");
+ if (!escaped)
+ return log_oom();
+
+ if (!strextend_with_separator(&joined, ":", escaped))
+ return log_oom();
}
- r = link_apply_ethtool_settings(link, &ctx->ethtool_fd);
+ (void) udev_builtin_add_property(device, mode, "ID_NET_LINK_FILE_DROPINS", joined);
+
+ if (link->new_name)
+ (void) udev_builtin_add_property(device, mode, "ID_NET_NAME", link->new_name);
+
+ return 0;
+}
+
+int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link, EventMode mode) {
+ int r;
+
+ assert(ctx);
+ assert(rtnl);
+ assert(link);
+
+ r = link_apply_ethtool_settings(link, &ctx->ethtool_fd, mode);
if (r < 0)
return r;
- r = link_apply_rtnl_settings(link, rtnl);
+ r = link_apply_rtnl_settings(link, rtnl, mode);
if (r < 0)
return r;
@@ -952,11 +1080,151 @@ int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link) {
if (r < 0)
return r;
- r = link_apply_sr_iov_config(link, rtnl);
+ r = link_apply_sr_iov_config(link, rtnl, mode);
if (r < 0)
return r;
- return 0;
+ r = link_apply_rps_cpu_mask(link, mode);
+ if (r < 0)
+ return r;
+
+ return link_apply_udev_properties(link, mode);
+}
+
+int config_parse_udev_property(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ char ***properties = ASSERT_PTR(data);
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ if (isempty(rvalue)) {
+ /* Empty assignment resets the list */
+ *properties = strv_free(*properties);
+ return 0;
+ }
+
+ for (const char *p = rvalue;; ) {
+ _cleanup_free_ char *word = NULL, *resolved = NULL, *key = NULL;
+ const char *eq;
+
+ r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Invalid syntax, ignoring assignment: %s", rvalue);
+ return 0;
+ }
+ if (r == 0)
+ return 0;
+
+ r = specifier_printf(word, SIZE_MAX, link_specifier_table, NULL, NULL, &resolved);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to resolve specifiers in %s, ignoring assignment: %m", word);
+ continue;
+ }
+
+ /* The restriction for udev property is not clear. Let's apply the one for environment variable here. */
+ if (!env_assignment_is_valid(resolved)) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Invalid udev property, ignoring assignment: %s", word);
+ continue;
+ }
+
+ assert_se(eq = strchr(resolved, '='));
+ key = strndup(resolved, eq - resolved);
+ if (!key)
+ return log_oom();
+
+ if (!device_property_can_set(key)) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Invalid udev property name '%s', ignoring assignment: %s", key, resolved);
+ continue;
+ }
+
+ r = strv_env_replace_consume(properties, TAKE_PTR(resolved));
+ if (r < 0)
+ return log_error_errno(r, "Failed to update properties: %m");
+ }
+}
+
+int config_parse_udev_property_name(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ char ***properties = ASSERT_PTR(data);
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ if (isempty(rvalue)) {
+ /* Empty assignment resets the list */
+ *properties = strv_free(*properties);
+ return 0;
+ }
+
+ for (const char *p = rvalue;; ) {
+ _cleanup_free_ char *word = NULL, *resolved = NULL;
+
+ r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Invalid syntax, ignoring assignment: %s", rvalue);
+ return 0;
+ }
+ if (r == 0)
+ return 0;
+
+ r = specifier_printf(word, SIZE_MAX, link_specifier_table, NULL, NULL, &resolved);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to resolve specifiers in %s, ignoring assignment: %m", word);
+ continue;
+ }
+
+ /* The restriction for udev property is not clear. Let's apply the one for environment variable here. */
+ if (!env_name_is_valid(resolved)) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Invalid udev property name, ignoring assignment: %s", resolved);
+ continue;
+ }
+
+ if (!device_property_can_set(resolved)) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Invalid udev property name, ignoring assignment: %s", resolved);
+ continue;
+ }
+
+ r = strv_consume(properties, TAKE_PTR(resolved));
+ if (r < 0)
+ return log_error_errno(r, "Failed to update properties: %m");
+ }
}
int config_parse_ifalias(
@@ -1110,6 +1378,63 @@ int config_parse_wol_password(
return 0;
}
+int config_parse_rps_cpu_mask(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ _cleanup_(cpu_set_freep) CPUSet *allocated = NULL;
+ CPUSet *mask, **rps_cpu_mask = ASSERT_PTR(data);
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ if (isempty(rvalue)) {
+ *rps_cpu_mask = cpu_set_free(*rps_cpu_mask);
+ return 0;
+ }
+
+ if (*rps_cpu_mask)
+ mask = *rps_cpu_mask;
+ else {
+ allocated = new0(CPUSet, 1);
+ if (!allocated)
+ return log_oom();
+
+ mask = allocated;
+ }
+
+ if (streq(rvalue, "disable"))
+ cpu_set_reset(mask);
+
+ else if (streq(rvalue, "all")) {
+ r = cpu_mask_add_all(mask);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to create CPU affinity mask representing \"all\" cpus, ignoring: %m");
+ return 0;
+ }
+ } else {
+ r = parse_cpu_set_extend(rvalue, mask, /* warn= */ true, unit, filename, line, lvalue);
+ if (r < 0)
+ return 0;
+ }
+
+ if (allocated)
+ *rps_cpu_mask = TAKE_PTR(allocated);
+
+ return 0;
+}
+
static const char* const mac_address_policy_table[_MAC_ADDRESS_POLICY_MAX] = {
[MAC_ADDRESS_POLICY_PERSISTENT] = "persistent",
[MAC_ADDRESS_POLICY_RANDOM] = "random",
diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h
index bab9d12..103343f 100644
--- a/src/udev/net/link-config.h
+++ b/src/udev/net/link-config.h
@@ -6,11 +6,13 @@
#include "condition.h"
#include "conf-parser.h"
+#include "cpu-set-util.h"
#include "ethtool-util.h"
#include "hashmap.h"
#include "list.h"
#include "net-condition.h"
#include "netif-naming-scheme.h"
+#include "udev-event.h"
typedef struct LinkConfigContext LinkConfigContext;
typedef struct LinkConfig LinkConfig;
@@ -31,6 +33,7 @@ typedef struct Link {
LinkConfig *config;
sd_device *device;
+ sd_device *device_db_clone;
sd_device_action_t action;
char *kind;
@@ -51,6 +54,9 @@ struct LinkConfig {
LIST_HEAD(Condition, conditions);
char *description;
+ char **properties;
+ char **import_properties;
+ char **unset_properties;
struct hw_addr_data hw_addr;
MACAddressPolicy mac_address_policy;
NamePolicy *name_policy;
@@ -80,6 +86,7 @@ struct LinkConfig {
int autoneg_flow_control;
netdev_coalesce_param coalesce;
uint8_t mdi;
+ CPUSet *rps_cpu_mask;
uint32_t sr_iov_num_vfs;
OrderedHashmap *sr_iov_by_section;
@@ -95,12 +102,12 @@ int link_load_one(LinkConfigContext *ctx, const char *filename);
int link_config_load(LinkConfigContext *ctx);
bool link_config_should_reload(LinkConfigContext *ctx);
-int link_new(LinkConfigContext *ctx, sd_netlink **rtnl, sd_device *device, Link **ret);
+int link_new(LinkConfigContext *ctx, sd_netlink **rtnl, sd_device *device, sd_device *device_db_clone, Link **ret);
Link *link_free(Link *link);
DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_free);
int link_get_config(LinkConfigContext *ctx, Link *link);
-int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link);
+int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link, EventMode mode);
const char *mac_address_policy_to_string(MACAddressPolicy p) _const_;
MACAddressPolicy mac_address_policy_from_string(const char *p) _pure_;
@@ -108,6 +115,8 @@ MACAddressPolicy mac_address_policy_from_string(const char *p) _pure_;
/* gperf lookup function */
const struct ConfigPerfItem* link_config_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
+CONFIG_PARSER_PROTOTYPE(config_parse_udev_property);
+CONFIG_PARSER_PROTOTYPE(config_parse_udev_property_name);
CONFIG_PARSER_PROTOTYPE(config_parse_ifalias);
CONFIG_PARSER_PROTOTYPE(config_parse_rx_tx_queues);
CONFIG_PARSER_PROTOTYPE(config_parse_txqueuelen);
@@ -115,3 +124,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_wol_password);
CONFIG_PARSER_PROTOTYPE(config_parse_mac_address_policy);
CONFIG_PARSER_PROTOTYPE(config_parse_name_policy);
CONFIG_PARSER_PROTOTYPE(config_parse_alternative_names_policy);
+CONFIG_PARSER_PROTOTYPE(config_parse_rps_cpu_mask);
diff --git a/src/udev/scsi_id/scsi.h b/src/udev/scsi_id/scsi.h
index ee3e401..ebb8ae9 100644
--- a/src/udev/scsi_id/scsi.h
+++ b/src/udev/scsi_id/scsi.h
@@ -1,17 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
-/*
- * scsi.h
- *
- * General scsi and linux scsi specific defines and structs.
- *
- * Copyright (C) IBM Corp. 2003
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation version 2 of the License.
- */
+/* Copyright (C) IBM Corp. 2003 */
#include <scsi/scsi.h>
diff --git a/src/udev/scsi_id/scsi_id.c b/src/udev/scsi_id/scsi_id.c
index 6308c52..b63a46a 100644
--- a/src/udev/scsi_id/scsi_id.c
+++ b/src/udev/scsi_id/scsi_id.c
@@ -84,6 +84,13 @@ static void set_type(unsigned type_num, char *to, size_t len) {
case 0xf:
type = "optical";
break;
+ case 0x14:
+ /*
+ * Use "zbc" here to be brief and consistent with "lsscsi" command.
+ * Other tools, e.g., "sg3_utils" would say "host managed zoned block".
+ */
+ type = "zbc";
+ break;
default:
type = "generic";
break;
@@ -144,7 +151,7 @@ static int get_file_options(const char *vendor, const char *model,
if (*buf == '#')
continue;
- r = extract_many_words(&buf, "=\",\n", 0, &key, &value, NULL);
+ r = extract_many_words(&buf, "=\",\n", 0, &key, &value);
if (r < 2)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Error parsing config file line %d '%s'", lineno, buffer);
@@ -152,7 +159,7 @@ static int get_file_options(const char *vendor, const char *model,
vendor_in = TAKE_PTR(value);
key = mfree(key);
- r = extract_many_words(&buf, "=\",\n", 0, &key, &value, NULL);
+ r = extract_many_words(&buf, "=\",\n", 0, &key, &value);
if (r < 2)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Error parsing config file line %d '%s'", lineno, buffer);
@@ -160,7 +167,7 @@ static int get_file_options(const char *vendor, const char *model,
model_in = TAKE_PTR(value);
key = mfree(key);
- r = extract_many_words(&buf, "=\",\n", 0, &key, &value, NULL);
+ r = extract_many_words(&buf, "=\",\n", 0, &key, &value);
if (r < 2)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Error parsing config file line %d '%s'", lineno, buffer);
}
@@ -473,10 +480,8 @@ int main(int argc, char **argv) {
char maj_min_dev[MAX_PATH_LEN];
int newargc;
- log_set_target(LOG_TARGET_AUTO);
- udev_parse_config();
- log_parse_environment();
- log_open();
+ (void) udev_parse_config();
+ log_setup();
/*
* Get config file options.
diff --git a/src/udev/test-udev-format.c b/src/udev/test-udev-format.c
index d8e3808..7eacb6b 100644
--- a/src/udev/test-udev-format.c
+++ b/src/udev/test-udev-format.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#include "mountpoint-util.h"
#include "string-util.h"
#include "tests.h"
#include "udev-format.h"
@@ -34,4 +35,11 @@ TEST(udev_resolve_subsys_kernel) {
test_udev_resolve_subsys_kernel_one("[net/lo]/address", true, 0, "00:00:00:00:00:00");
}
-DEFINE_TEST_MAIN(LOG_DEBUG);
+static int intro(void) {
+ if (path_is_mount_point("/sys") <= 0)
+ return log_tests_skipped("/sys is not mounted");
+
+ return EXIT_SUCCESS;
+}
+
+DEFINE_TEST_MAIN_WITH_INTRO(LOG_DEBUG, intro);
diff --git a/src/udev/test-udev-rule-runner.c b/src/udev/test-udev-rule-runner.c
index 72296b3..10da645 100644
--- a/src/udev/test-udev-rule-runner.c
+++ b/src/udev/test-udev-rule-runner.c
@@ -12,6 +12,7 @@
#include <unistd.h>
#include "device-private.h"
+#include "device-util.h"
#include "fs-util.h"
#include "log.h"
#include "main-func.h"
@@ -141,16 +142,15 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return log_debug_errno(r, "Failed to open device '%s'", devpath);
- assert_se(event = udev_event_new(dev, 0, NULL, log_get_max_level()));
+ assert_se(event = udev_event_new(dev, NULL, EVENT_TEST_RULE_RUNNER));
- assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) >= 0);
+ assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD) >= 0);
/* do what devtmpfs usually provides us */
if (sd_device_get_devname(dev, &devname) >= 0) {
- const char *subsystem;
mode_t mode = 0600;
- if (sd_device_get_subsystem(dev, &subsystem) >= 0 && streq(subsystem, "block"))
+ if (device_in_subsystem(dev, "block"))
mode |= S_IFBLK;
else
mode |= S_IFCHR;
@@ -169,8 +169,8 @@ static int run(int argc, char *argv[]) {
}
}
- udev_event_execute_rules(event, -1, 3 * USEC_PER_SEC, SIGKILL, NULL, rules);
- udev_event_execute_run(event, 3 * USEC_PER_SEC, SIGKILL);
+ udev_event_execute_rules(event, rules);
+ udev_event_execute_run(event);
return 0;
}
diff --git a/src/udev/test-udev-spawn.c b/src/udev/test-udev-spawn.c
index 4f43fac..7cbccf3 100644
--- a/src/udev/test-udev-spawn.c
+++ b/src/udev/test-udev-spawn.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#include "mountpoint-util.h"
#include "path-util.h"
#include "signal-util.h"
#include "strv.h"
@@ -16,8 +17,8 @@ static void test_event_spawn_core(bool with_pidfd, const char *cmd, char *result
assert_se(setenv("SYSTEMD_PIDFD", yes_no(with_pidfd), 1) >= 0);
assert_se(sd_device_new_from_syspath(&dev, "/sys/class/net/lo") >= 0);
- assert_se(event = udev_event_new(dev, 0, NULL, LOG_DEBUG));
- assert_se(udev_event_spawn(event, 5 * USEC_PER_SEC, SIGKILL, false, cmd, result_buf, buf_size, NULL) == 0);
+ assert_se(event = udev_event_new(dev, NULL, EVENT_TEST_SPAWN));
+ assert_se(udev_event_spawn(event, false, cmd, result_buf, buf_size, NULL) == 0);
assert_se(unsetenv("SYSTEMD_PIDFD") >= 0);
}
@@ -80,6 +81,9 @@ static void test2(void) {
int main(int argc, char *argv[]) {
_cleanup_free_ char *self = NULL;
+ if (path_is_mount_point("/sys") <= 0)
+ return log_tests_skipped("/sys is not mounted");
+
if (argc > 1) {
if (streq(argv[1], "test1"))
test1();
@@ -93,7 +97,7 @@ int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
- assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
+ assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
test_event_spawn_cat(true, SIZE_MAX);
test_event_spawn_cat(false, SIZE_MAX);
diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c
index 11419a3..4d13035 100644
--- a/src/udev/udev-builtin-blkid.c
+++ b/src/udev/udev-builtin-blkid.c
@@ -34,95 +34,95 @@
#include "strxcpyx.h"
#include "udev-builtin.h"
-static void print_property(sd_device *dev, bool test, const char *name, const char *value) {
+static void print_property(sd_device *dev, EventMode mode, const char *name, const char *value) {
char s[256];
s[0] = '\0';
if (streq(name, "TYPE")) {
- udev_builtin_add_property(dev, test, "ID_FS_TYPE", value);
+ udev_builtin_add_property(dev, mode, "ID_FS_TYPE", value);
} else if (streq(name, "USAGE")) {
- udev_builtin_add_property(dev, test, "ID_FS_USAGE", value);
+ udev_builtin_add_property(dev, mode, "ID_FS_USAGE", value);
} else if (streq(name, "VERSION")) {
- udev_builtin_add_property(dev, test, "ID_FS_VERSION", value);
+ udev_builtin_add_property(dev, mode, "ID_FS_VERSION", value);
} else if (streq(name, "UUID")) {
blkid_safe_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_UUID", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_UUID", s);
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_UUID_ENC", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_UUID_ENC", s);
} else if (streq(name, "UUID_SUB")) {
blkid_safe_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_UUID_SUB", s);
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB_ENC", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_UUID_SUB_ENC", s);
} else if (streq(name, "LABEL")) {
blkid_safe_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_LABEL", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_LABEL", s);
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_LABEL_ENC", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_LABEL_ENC", s);
} else if (STR_IN_SET(name, "FSSIZE", "FSLASTBLOCK", "FSBLOCKSIZE")) {
strscpyl(s, sizeof(s), "ID_FS_", name + 2, NULL);
- udev_builtin_add_property(dev, test, s, value);
+ udev_builtin_add_property(dev, mode, s, value);
} else if (streq(name, "PTTYPE")) {
- udev_builtin_add_property(dev, test, "ID_PART_TABLE_TYPE", value);
+ udev_builtin_add_property(dev, mode, "ID_PART_TABLE_TYPE", value);
} else if (streq(name, "PTUUID")) {
- udev_builtin_add_property(dev, test, "ID_PART_TABLE_UUID", value);
+ udev_builtin_add_property(dev, mode, "ID_PART_TABLE_UUID", value);
} else if (streq(name, "PART_ENTRY_NAME")) {
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_PART_ENTRY_NAME", s);
+ udev_builtin_add_property(dev, mode, "ID_PART_ENTRY_NAME", s);
} else if (streq(name, "PART_ENTRY_TYPE")) {
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_PART_ENTRY_TYPE", s);
+ udev_builtin_add_property(dev, mode, "ID_PART_ENTRY_TYPE", s);
} else if (startswith(name, "PART_ENTRY_")) {
strscpyl(s, sizeof(s), "ID_", name, NULL);
- udev_builtin_add_property(dev, test, s, value);
+ udev_builtin_add_property(dev, mode, s, value);
} else if (streq(name, "SYSTEM_ID")) {
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_SYSTEM_ID", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_SYSTEM_ID", s);
} else if (streq(name, "PUBLISHER_ID")) {
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_PUBLISHER_ID", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_PUBLISHER_ID", s);
} else if (streq(name, "APPLICATION_ID")) {
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_APPLICATION_ID", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_APPLICATION_ID", s);
} else if (streq(name, "BOOT_SYSTEM_ID")) {
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_BOOT_SYSTEM_ID", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_BOOT_SYSTEM_ID", s);
} else if (streq(name, "VOLUME_ID")) {
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_VOLUME_ID", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_VOLUME_ID", s);
} else if (streq(name, "LOGICAL_VOLUME_ID")) {
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_LOGICAL_VOLUME_ID", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_LOGICAL_VOLUME_ID", s);
} else if (streq(name, "VOLUME_SET_ID")) {
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_VOLUME_SET_ID", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_VOLUME_SET_ID", s);
} else if (streq(name, "DATA_PREPARER_ID")) {
blkid_encode_string(value, s, sizeof(s));
- udev_builtin_add_property(dev, test, "ID_FS_DATA_PREPARER_ID", s);
+ udev_builtin_add_property(dev, mode, "ID_FS_DATA_PREPARER_ID", s);
}
}
-static int find_gpt_root(sd_device *dev, blkid_probe pr, bool test) {
+static int find_gpt_root(sd_device *dev, blkid_probe pr, EventMode mode) {
#if defined(SD_GPT_ROOT_NATIVE) && ENABLE_EFI
@@ -201,7 +201,7 @@ static int find_gpt_root(sd_device *dev, blkid_probe pr, bool test) {
/* We found the ESP/XBOOTLDR on this disk, and also found a root partition, nice! Let's export its
* UUID */
if (found_esp_or_xbootldr && !sd_id128_is_null(root_id))
- udev_builtin_add_property(dev, test, "ID_PART_GPT_AUTO_ROOT_UUID", SD_ID128_TO_UUID_STRING(root_id));
+ udev_builtin_add_property(dev, mode, "ID_PART_GPT_AUTO_ROOT_UUID", SD_ID128_TO_UUID_STRING(root_id));
#endif
return 0;
@@ -315,7 +315,7 @@ notloop:
return 0;
}
-static int builtin_blkid(UdevEvent *event, int argc, char *argv[], bool test) {
+static int builtin_blkid(UdevEvent *event, int argc, char *argv[]) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
const char *devnode, *root_partition = NULL, *data, *name;
_cleanup_(blkid_free_probep) blkid_probe pr = NULL;
@@ -368,7 +368,7 @@ static int builtin_blkid(UdevEvent *event, int argc, char *argv[], bool test) {
if (r < 0)
return log_device_error_errno(dev, r, "Failed to parse '%s' as an integer: %m", optarg);
if (offset < 0)
- return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Invalid offset %"PRIi64": %m", offset);
+ return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Invalid offset %"PRIi64".", offset);
break;
case 'R':
noraid = true;
@@ -422,7 +422,7 @@ static int builtin_blkid(UdevEvent *event, int argc, char *argv[], bool test) {
if (blkid_probe_get_value(pr, i, &name, &data, NULL) < 0)
continue;
- print_property(dev, test, name, data);
+ print_property(dev, event->event_mode, name, data);
/* Is this a disk with GPT partition table? */
if (streq(name, "PTTYPE") && streq(data, "gpt"))
@@ -431,11 +431,11 @@ static int builtin_blkid(UdevEvent *event, int argc, char *argv[], bool test) {
/* Is this a partition that matches the root partition
* property inherited from the parent? */
if (root_partition && streq(name, "PART_ENTRY_UUID") && streq(data, root_partition))
- udev_builtin_add_property(dev, test, "ID_PART_GPT_AUTO_ROOT", "1");
+ udev_builtin_add_property(dev, event->event_mode, "ID_PART_GPT_AUTO_ROOT", "1");
}
if (is_gpt)
- find_gpt_root(dev, pr, test);
+ find_gpt_root(dev, pr, event->event_mode);
r = read_loopback_backing_inode(
dev,
@@ -446,8 +446,8 @@ static int builtin_blkid(UdevEvent *event, int argc, char *argv[], bool test) {
if (r < 0)
log_device_debug_errno(dev, r, "Failed to read loopback backing inode, ignoring: %m");
else if (r > 0) {
- udev_builtin_add_propertyf(dev, test, "ID_LOOP_BACKING_DEVICE", DEVNUM_FORMAT_STR, DEVNUM_FORMAT_VAL(backing_devno));
- udev_builtin_add_propertyf(dev, test, "ID_LOOP_BACKING_INODE", "%" PRIu64, (uint64_t) backing_inode);
+ udev_builtin_add_propertyf(dev, event->event_mode, "ID_LOOP_BACKING_DEVICE", DEVNUM_FORMAT_STR, DEVNUM_FORMAT_VAL(backing_devno));
+ udev_builtin_add_propertyf(dev, event->event_mode, "ID_LOOP_BACKING_INODE", "%" PRIu64, (uint64_t) backing_inode);
if (backing_fname) {
/* In the worst case blkid_encode_string() will blow up to 4x the string
@@ -458,8 +458,8 @@ static int builtin_blkid(UdevEvent *event, int argc, char *argv[], bool test) {
assert(strlen(backing_fname) < ELEMENTSOF(encoded) / 4);
blkid_encode_string(backing_fname, encoded, ELEMENTSOF(encoded));
- udev_builtin_add_property(dev, test, "ID_LOOP_BACKING_FILENAME", backing_fname);
- udev_builtin_add_property(dev, test, "ID_LOOP_BACKING_FILENAME_ENC", encoded);
+ udev_builtin_add_property(dev, event->event_mode, "ID_LOOP_BACKING_FILENAME", backing_fname);
+ udev_builtin_add_property(dev, event->event_mode, "ID_LOOP_BACKING_FILENAME_ENC", encoded);
}
}
diff --git a/src/udev/udev-builtin-btrfs.c b/src/udev/udev-builtin-btrfs.c
index 9b12aeb..fe030d0 100644
--- a/src/udev/udev-builtin-btrfs.c
+++ b/src/udev/udev-builtin-btrfs.c
@@ -12,7 +12,7 @@
#include "strxcpyx.h"
#include "udev-builtin.h"
-static int builtin_btrfs(UdevEvent *event, int argc, char *argv[], bool test) {
+static int builtin_btrfs(UdevEvent *event, int argc, char *argv[]) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
struct btrfs_ioctl_vol_args args = {};
_cleanup_close_ int fd = -EBADF;
@@ -27,7 +27,7 @@ static int builtin_btrfs(UdevEvent *event, int argc, char *argv[], bool test) {
/* Driver not installed? Then we aren't ready. This is useful in initrds that lack
* btrfs.ko. After the host transition (where btrfs.ko will hopefully become
* available) the device can be retriggered and will then be considered ready. */
- udev_builtin_add_property(dev, test, "ID_BTRFS_READY", "0");
+ udev_builtin_add_property(dev, event->event_mode, "ID_BTRFS_READY", "0");
return 0;
}
@@ -39,7 +39,7 @@ static int builtin_btrfs(UdevEvent *event, int argc, char *argv[], bool test) {
if (r < 0)
return log_device_debug_errno(dev, errno, "Failed to call BTRFS_IOC_DEVICES_READY: %m");
- udev_builtin_add_property(dev, test, "ID_BTRFS_READY", one_zero(r == 0));
+ udev_builtin_add_property(dev, event->event_mode, "ID_BTRFS_READY", one_zero(r == 0));
return 0;
}
diff --git a/src/udev/udev-builtin-hwdb.c b/src/udev/udev-builtin-hwdb.c
index 19e07e7..e33a7fe 100644
--- a/src/udev/udev-builtin-hwdb.c
+++ b/src/udev/udev-builtin-hwdb.c
@@ -17,9 +17,13 @@
static sd_hwdb *hwdb;
-int udev_builtin_hwdb_lookup(sd_device *dev,
- const char *prefix, const char *modalias,
- const char *filter, bool test) {
+int udev_builtin_hwdb_lookup(
+ sd_device *dev,
+ const char *prefix,
+ const char *modalias,
+ const char *filter,
+ EventMode mode) {
+
_cleanup_free_ char *lookup = NULL;
const char *key, *value;
int n = 0, r;
@@ -38,7 +42,7 @@ int udev_builtin_hwdb_lookup(sd_device *dev,
if (filter && fnmatch(filter, key, FNM_NOESCAPE) != 0)
continue;
- r = udev_builtin_add_property(dev, test, key, value);
+ r = udev_builtin_add_property(dev, mode, key, value);
if (r < 0)
return r;
n++;
@@ -64,9 +68,14 @@ static const char *modalias_usb(sd_device *dev, char *s, size_t size) {
return s;
}
-static int udev_builtin_hwdb_search(sd_device *dev, sd_device *srcdev,
- const char *subsystem, const char *prefix,
- const char *filter, bool test) {
+static int udev_builtin_hwdb_search(
+ sd_device *dev,
+ sd_device *srcdev,
+ const char *subsystem,
+ const char *prefix,
+ const char *filter,
+ EventMode mode) {
+
char s[LINE_MAX];
bool last = false;
int r = 0;
@@ -77,20 +86,15 @@ static int udev_builtin_hwdb_search(sd_device *dev, sd_device *srcdev,
srcdev = dev;
for (sd_device *d = srcdev; d; ) {
- const char *dsubsys, *devtype, *modalias = NULL;
-
- if (sd_device_get_subsystem(d, &dsubsys) < 0)
- goto next;
+ const char *modalias = NULL;
/* look only at devices of a specific subsystem */
- if (subsystem && !streq(dsubsys, subsystem))
+ if (subsystem && !device_in_subsystem(d, subsystem))
goto next;
(void) sd_device_get_property_value(d, "MODALIAS", &modalias);
- if (streq(dsubsys, "usb") &&
- sd_device_get_devtype(d, &devtype) >= 0 &&
- streq(devtype, "usb_device")) {
+ if (device_in_subsystem(d, "usb") && device_is_devtype(d, "usb_device")) {
/* if the usb_device does not have a modalias, compose one */
if (!modalias)
modalias = modalias_usb(d, s, sizeof(s));
@@ -104,7 +108,7 @@ static int udev_builtin_hwdb_search(sd_device *dev, sd_device *srcdev,
log_device_debug(dev, "hwdb modalias key: \"%s\"", modalias);
- r = udev_builtin_hwdb_lookup(dev, prefix, modalias, filter, test);
+ r = udev_builtin_hwdb_lookup(dev, prefix, modalias, filter, mode);
if (r > 0)
break;
@@ -118,7 +122,7 @@ next:
return r;
}
-static int builtin_hwdb(UdevEvent *event, int argc, char *argv[], bool test) {
+static int builtin_hwdb(UdevEvent *event, int argc, char *argv[]) {
static const struct option options[] = {
{ "filter", required_argument, NULL, 'f' },
{ "device", required_argument, NULL, 'd' },
@@ -165,7 +169,7 @@ static int builtin_hwdb(UdevEvent *event, int argc, char *argv[], bool test) {
/* query a specific key given as argument */
if (argv[optind]) {
- r = udev_builtin_hwdb_lookup(dev, prefix, argv[optind], filter, test);
+ r = udev_builtin_hwdb_lookup(dev, prefix, argv[optind], filter, event->event_mode);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to look up hwdb: %m");
if (r == 0)
@@ -180,7 +184,7 @@ static int builtin_hwdb(UdevEvent *event, int argc, char *argv[], bool test) {
return log_device_debug_errno(dev, r, "Failed to create sd_device object '%s': %m", device);
}
- r = udev_builtin_hwdb_search(dev, srcdev, subsystem, prefix, filter, test);
+ r = udev_builtin_hwdb_search(dev, srcdev, subsystem, prefix, filter, event->event_mode);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to look up hwdb: %m");
if (r == 0)
diff --git a/src/udev/udev-builtin-input_id.c b/src/udev/udev-builtin-input_id.c
index 295e8d2..6f75d9d 100644
--- a/src/udev/udev-builtin-input_id.c
+++ b/src/udev/udev-builtin-input_id.c
@@ -44,7 +44,7 @@ static int abs_size_mm(const struct input_absinfo *absinfo) {
return (absinfo->maximum - absinfo->minimum) / absinfo->resolution;
}
-static void extract_info(sd_device *dev, bool test) {
+static void extract_info(sd_device *dev, EventMode mode) {
char width[DECIMAL_STR_MAX(int)], height[DECIMAL_STR_MAX(int)];
struct input_absinfo xabsinfo = {}, yabsinfo = {};
_cleanup_close_ int fd = -EBADF;
@@ -63,8 +63,8 @@ static void extract_info(sd_device *dev, bool test) {
xsprintf(width, "%d", abs_size_mm(&xabsinfo));
xsprintf(height, "%d", abs_size_mm(&yabsinfo));
- udev_builtin_add_property(dev, test, "ID_INPUT_WIDTH_MM", width);
- udev_builtin_add_property(dev, test, "ID_INPUT_HEIGHT_MM", height);
+ udev_builtin_add_property(dev, mode, "ID_INPUT_WIDTH_MM", width);
+ udev_builtin_add_property(dev, mode, "ID_INPUT_HEIGHT_MM", height);
}
/*
@@ -73,9 +73,13 @@ static void extract_info(sd_device *dev, bool test) {
* @param attr sysfs attribute name (e. g. "capabilities/key")
* @param bitmask: Output array which has a sizeof of bitmask_size
*/
-static void get_cap_mask(sd_device *pdev, const char* attr,
- unsigned long *bitmask, size_t bitmask_size,
- bool test) {
+static void get_cap_mask(
+ sd_device *pdev,
+ const char* attr,
+ unsigned long *bitmask,
+ size_t bitmask_size,
+ EventMode mode) {
+
const char *v;
char text[4096];
unsigned i;
@@ -110,7 +114,7 @@ static void get_cap_mask(sd_device *pdev, const char* attr,
else
log_device_debug(pdev, "Ignoring %s block %lX which is larger than maximum size", attr, val);
- if (test && DEBUG_LOGGING) {
+ if (mode == EVENT_UDEVADM_TEST_BUILTIN && DEBUG_LOGGING) {
log_device_debug(pdev, "%s decoded bit map:", attr);
val = bitmask_size / sizeof (unsigned long);
@@ -144,14 +148,16 @@ static struct input_id get_input_id(sd_device *dev) {
}
/* pointer devices */
-static bool test_pointers(sd_device *dev,
- const struct input_id *id,
- const unsigned long* bitmask_ev,
- const unsigned long* bitmask_abs,
- const unsigned long* bitmask_key,
- const unsigned long* bitmask_rel,
- const unsigned long* bitmask_props,
- bool test) {
+static bool test_pointers(
+ sd_device *dev,
+ const struct input_id *id,
+ const unsigned long* bitmask_ev,
+ const unsigned long* bitmask_abs,
+ const unsigned long* bitmask_key,
+ const unsigned long* bitmask_rel,
+ const unsigned long* bitmask_props,
+ EventMode mode) {
+
bool has_abs_coordinates = false;
bool has_rel_coordinates = false;
bool has_mt_coordinates = false;
@@ -186,7 +192,7 @@ static bool test_pointers(sd_device *dev,
is_accelerometer = true;
if (is_accelerometer) {
- udev_builtin_add_property(dev, test, "ID_INPUT_ACCELEROMETER", "1");
+ udev_builtin_add_property(dev, mode, "ID_INPUT_ACCELEROMETER", "1");
return true;
}
@@ -309,28 +315,29 @@ static bool test_pointers(sd_device *dev,
}
if (is_pointing_stick)
- udev_builtin_add_property(dev, test, "ID_INPUT_POINTINGSTICK", "1");
+ udev_builtin_add_property(dev, mode, "ID_INPUT_POINTINGSTICK", "1");
if (is_mouse || is_abs_mouse)
- udev_builtin_add_property(dev, test, "ID_INPUT_MOUSE", "1");
+ udev_builtin_add_property(dev, mode, "ID_INPUT_MOUSE", "1");
if (is_touchpad)
- udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHPAD", "1");
+ udev_builtin_add_property(dev, mode, "ID_INPUT_TOUCHPAD", "1");
if (is_touchscreen)
- udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHSCREEN", "1");
+ udev_builtin_add_property(dev, mode, "ID_INPUT_TOUCHSCREEN", "1");
if (is_joystick)
- udev_builtin_add_property(dev, test, "ID_INPUT_JOYSTICK", "1");
+ udev_builtin_add_property(dev, mode, "ID_INPUT_JOYSTICK", "1");
if (is_tablet)
- udev_builtin_add_property(dev, test, "ID_INPUT_TABLET", "1");
+ udev_builtin_add_property(dev, mode, "ID_INPUT_TABLET", "1");
if (is_tablet_pad)
- udev_builtin_add_property(dev, test, "ID_INPUT_TABLET_PAD", "1");
+ udev_builtin_add_property(dev, mode, "ID_INPUT_TABLET_PAD", "1");
return is_tablet || is_mouse || is_abs_mouse || is_touchpad || is_touchscreen || is_joystick || is_pointing_stick;
}
/* key like devices */
-static bool test_key(sd_device *dev,
- const unsigned long* bitmask_ev,
- const unsigned long* bitmask_key,
- bool test) {
+static bool test_key(
+ sd_device *dev,
+ const unsigned long* bitmask_ev,
+ const unsigned long* bitmask_key,
+ EventMode mode) {
bool found = false;
@@ -357,19 +364,19 @@ static bool test_key(sd_device *dev,
}
if (found)
- udev_builtin_add_property(dev, test, "ID_INPUT_KEY", "1");
+ udev_builtin_add_property(dev, mode, "ID_INPUT_KEY", "1");
/* the first 32 bits are ESC, numbers, and Q to D; if we have all of
* those, consider it a full keyboard; do not test KEY_RESERVED, though */
if (FLAGS_SET(bitmask_key[0], 0xFFFFFFFE)) {
- udev_builtin_add_property(dev, test, "ID_INPUT_KEYBOARD", "1");
+ udev_builtin_add_property(dev, mode, "ID_INPUT_KEYBOARD", "1");
return true;
}
return found;
}
-static int builtin_input_id(UdevEvent *event, int argc, char *argv[], bool test) {
+static int builtin_input_id(UdevEvent *event, int argc, char *argv[]) {
sd_device *pdev, *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
unsigned long bitmask_ev[NBITS(EV_MAX)];
unsigned long bitmask_abs[NBITS(ABS_MAX)];
@@ -400,28 +407,28 @@ static int builtin_input_id(UdevEvent *event, int argc, char *argv[], bool test)
/* Use this as a flag that input devices were detected, so that this
* program doesn't need to be called more than once per device */
- udev_builtin_add_property(dev, test, "ID_INPUT", "1");
- get_cap_mask(pdev, "capabilities/ev", bitmask_ev, sizeof(bitmask_ev), test);
- get_cap_mask(pdev, "capabilities/abs", bitmask_abs, sizeof(bitmask_abs), test);
- get_cap_mask(pdev, "capabilities/rel", bitmask_rel, sizeof(bitmask_rel), test);
- get_cap_mask(pdev, "capabilities/key", bitmask_key, sizeof(bitmask_key), test);
- get_cap_mask(pdev, "properties", bitmask_props, sizeof(bitmask_props), test);
+ udev_builtin_add_property(dev, event->event_mode, "ID_INPUT", "1");
+ get_cap_mask(pdev, "capabilities/ev", bitmask_ev, sizeof(bitmask_ev), event->event_mode);
+ get_cap_mask(pdev, "capabilities/abs", bitmask_abs, sizeof(bitmask_abs), event->event_mode);
+ get_cap_mask(pdev, "capabilities/rel", bitmask_rel, sizeof(bitmask_rel), event->event_mode);
+ get_cap_mask(pdev, "capabilities/key", bitmask_key, sizeof(bitmask_key), event->event_mode);
+ get_cap_mask(pdev, "properties", bitmask_props, sizeof(bitmask_props), event->event_mode);
is_pointer = test_pointers(dev, &id, bitmask_ev, bitmask_abs,
bitmask_key, bitmask_rel,
- bitmask_props, test);
- is_key = test_key(dev, bitmask_ev, bitmask_key, test);
+ bitmask_props, event->event_mode);
+ is_key = test_key(dev, bitmask_ev, bitmask_key, event->event_mode);
/* Some evdev nodes have only a scrollwheel */
if (!is_pointer && !is_key && test_bit(EV_REL, bitmask_ev) &&
(test_bit(REL_WHEEL, bitmask_rel) || test_bit(REL_HWHEEL, bitmask_rel)))
- udev_builtin_add_property(dev, test, "ID_INPUT_KEY", "1");
+ udev_builtin_add_property(dev, event->event_mode, "ID_INPUT_KEY", "1");
if (test_bit(EV_SW, bitmask_ev))
- udev_builtin_add_property(dev, test, "ID_INPUT_SWITCH", "1");
+ udev_builtin_add_property(dev, event->event_mode, "ID_INPUT_SWITCH", "1");
}
if (sd_device_get_sysname(dev, &sysname) >= 0 &&
startswith(sysname, "event"))
- extract_info(dev, test);
+ extract_info(dev, event->event_mode);
return 0;
}
diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c
index 3903bc4..e1e6de0 100644
--- a/src/udev/udev-builtin-keyboard.c
+++ b/src/udev/udev-builtin-keyboard.c
@@ -159,7 +159,7 @@ static int set_trackpoint_sensitivity(sd_device *dev, const char *value) {
return 0;
}
-static int builtin_keyboard(UdevEvent *event, int argc, char *argv[], bool test) {
+static int builtin_keyboard(UdevEvent *event, int argc, char *argv[]) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
unsigned release[1024];
unsigned release_count = 0;
@@ -167,6 +167,11 @@ static int builtin_keyboard(UdevEvent *event, int argc, char *argv[], bool test)
const char *node;
int has_abs = -1, r;
+ if (event->event_mode != EVENT_UDEV_WORKER) {
+ log_device_debug(dev, "Running in test mode, skipping execution of 'keyboard' builtin command.");
+ return 0;
+ }
+
r = sd_device_get_devname(dev, &node);
if (r < 0)
return log_device_error_errno(dev, r, "Failed to get device name: %m");
diff --git a/src/udev/udev-builtin-kmod.c b/src/udev/udev-builtin-kmod.c
index 3ab5c48..f4aa480 100644
--- a/src/udev/udev-builtin-kmod.c
+++ b/src/udev/udev-builtin-kmod.c
@@ -18,14 +18,15 @@
static struct kmod_ctx *ctx = NULL;
-_printf_(6,0) static void udev_kmod_log(void *data, int priority, const char *file, int line, const char *fn, const char *format, va_list args) {
- log_internalv(priority, 0, file, line, fn, format, args);
-}
-
-static int builtin_kmod(UdevEvent *event, int argc, char *argv[], bool test) {
+static int builtin_kmod(UdevEvent *event, int argc, char *argv[]) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
int r;
+ if (event->event_mode != EVENT_UDEV_WORKER) {
+ log_device_debug(dev, "Running in test mode, skipping execution of 'kmod' builtin command.");
+ return 0;
+ }
+
if (!ctx)
return 0;
@@ -39,7 +40,7 @@ static int builtin_kmod(UdevEvent *event, int argc, char *argv[], bool test) {
r = sd_device_get_property_value(dev, "MODALIAS", &modalias);
if (r < 0)
- return log_device_warning_errno(dev, r, "Failed to read property \"MODALIAS\".");
+ return log_device_warning_errno(dev, r, "Failed to read property \"MODALIAS\": %m");
(void) module_load_and_warn(ctx, modalias, /* verbose = */ false);
} else
@@ -51,23 +52,28 @@ static int builtin_kmod(UdevEvent *event, int argc, char *argv[], bool test) {
/* called at udev startup and reload */
static int builtin_kmod_init(void) {
+ int r;
+
if (ctx)
return 0;
- ctx = kmod_new(NULL, NULL);
- if (!ctx)
- return -ENOMEM;
-
log_debug("Loading kernel module index.");
- kmod_set_log_fn(ctx, udev_kmod_log, NULL);
- kmod_load_resources(ctx);
+
+ r = module_setup_context(&ctx);
+ if (r < 0)
+ return log_error_errno(r, "Failed to initialize libkmod context: %m");
+
return 0;
}
/* called on udev shutdown and reload request */
static void builtin_kmod_exit(void) {
log_debug("Unload kernel module index.");
- ctx = kmod_unref(ctx);
+
+ if (!ctx)
+ return;
+
+ ctx = sym_kmod_unref(ctx);
}
/* called every couple of seconds during event activity; 'true' if config has changed */
@@ -75,7 +81,7 @@ static bool builtin_kmod_should_reload(void) {
if (!ctx)
return false;
- if (kmod_validate_resources(ctx) != KMOD_RESOURCES_OK) {
+ if (sym_kmod_validate_resources(ctx) != KMOD_RESOURCES_OK) {
log_debug("Kernel module index needs reloading.");
return true;
}
diff --git a/src/udev/udev-builtin-net_driver.c b/src/udev/udev-builtin-net_driver.c
index f1642a4..90a9e8d 100644
--- a/src/udev/udev-builtin-net_driver.c
+++ b/src/udev/udev-builtin-net_driver.c
@@ -9,7 +9,7 @@
#include "string-util.h"
#include "udev-builtin.h"
-static int builtin_net_driver_set_driver(UdevEvent *event, int argc, char **argv, bool test) {
+static int builtin_net_driver_set_driver(UdevEvent *event, int argc, char **argv) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
_cleanup_close_ int ethtool_fd = -EBADF;
_cleanup_free_ char *driver = NULL;
@@ -32,7 +32,7 @@ static int builtin_net_driver_set_driver(UdevEvent *event, int argc, char **argv
if (r < 0)
return log_device_warning_errno(dev, r, "Failed to get driver for '%s': %m", sysname);
- return udev_builtin_add_property(event->dev, test, "ID_NET_DRIVER", driver);
+ return udev_builtin_add_property(event->dev, event->event_mode, "ID_NET_DRIVER", driver);
}
const UdevBuiltin udev_builtin_net_driver = {
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
index 91b4008..384a1f3 100644
--- a/src/udev/udev-builtin-net_id.c
+++ b/src/udev/udev-builtin-net_id.c
@@ -12,9 +12,10 @@
* When the code here is changed, man/systemd.net-naming-scheme.xml must be updated too.
*/
+/* Make sure the net/if.h header is included before any linux/ one */
+#include <net/if.h>
#include <errno.h>
#include <fcntl.h>
-#include <net/if.h>
#include <stdarg.h>
#include <unistd.h>
#include <linux/if.h>
@@ -49,12 +50,7 @@ static sd_device *device_skip_virtio(sd_device *dev) {
* safely ignore any virtio buses. see
* http://lists.linuxfoundation.org/pipermail/virtualization/2015-August/030331.html */
while (dev) {
- const char *subsystem;
-
- if (sd_device_get_subsystem(dev, &subsystem) < 0)
- break;
-
- if (!streq(subsystem, "virtio"))
+ if (!device_in_subsystem(dev, "virtio"))
break;
if (sd_device_get_parent(dev, &dev) < 0)
@@ -86,22 +82,15 @@ static int get_matching_parent(
return -ENODEV;
}
- if (!strv_isempty(parent_subsystems)) {
- const char *subsystem;
-
- /* check if our direct parent is in an expected subsystem. */
- r = sd_device_get_subsystem(parent, &subsystem);
- if (r < 0)
- return r;
-
- if (!strv_contains(parent_subsystems, subsystem))
- return -ENODEV;
- }
-
- if (ret)
- *ret = parent;
+ /* check if our direct parent is in an expected subsystem. */
+ STRV_FOREACH(s, parent_subsystems)
+ if (device_in_subsystem(parent, *s)) {
+ if (ret)
+ *ret = parent;
+ return 0;
+ }
- return 0;
+ return -ENODEV;
}
static int get_first_syspath_component(sd_device *dev, const char *prefix, char **ret) {
@@ -188,7 +177,7 @@ static int get_dev_port(sd_device *dev, bool fallback_to_dev_id, unsigned *ret)
/* Get kernel provided port index for the case when multiple ports on a single PCI function. */
- r = device_get_sysattr_unsigned(dev, "dev_port", &v);
+ r = device_get_sysattr_unsigned_filtered(dev, "dev_port", &v);
if (r < 0)
return r;
if (r > 0) {
@@ -204,7 +193,7 @@ static int get_dev_port(sd_device *dev, bool fallback_to_dev_id, unsigned *ret)
if (fallback_to_dev_id) {
unsigned iftype;
- r = device_get_sysattr_unsigned(dev, "type", &iftype);
+ r = device_get_sysattr_unsigned_filtered(dev, "type", &iftype);
if (r < 0)
return r;
@@ -212,7 +201,7 @@ static int get_dev_port(sd_device *dev, bool fallback_to_dev_id, unsigned *ret)
}
if (fallback_to_dev_id)
- return device_get_sysattr_unsigned(dev, "dev_id", ret);
+ return device_get_sysattr_unsigned_filtered(dev, "dev_id", ret);
/* Otherwise, return the original index 0. */
*ret = 0;
@@ -229,7 +218,7 @@ static int get_port_specifier(sd_device *dev, bool fallback_to_dev_id, char **re
assert(ret);
/* First, try to use the kernel provided front panel port name for multiple port PCI device. */
- r = sd_device_get_sysattr_value(dev, "phys_port_name", &phys_port_name);
+ r = device_get_sysattr_value_filtered(dev, "phys_port_name", &phys_port_name);
if (r >= 0 && !isempty(phys_port_name)) {
if (naming_scheme_has(NAMING_SR_IOV_R)) {
int vf_id = -1;
@@ -292,10 +281,10 @@ static int pci_get_onboard_index(sd_device *dev, unsigned *ret) {
assert(ret);
/* ACPI _DSM — device specific method for naming a PCI or PCI Express device */
- r = device_get_sysattr_unsigned(dev, "acpi_index", &idx);
+ r = device_get_sysattr_unsigned_filtered(dev, "acpi_index", &idx);
if (r < 0)
/* SMBIOS type 41 — Onboard Devices Extended Information */
- r = device_get_sysattr_unsigned(dev, "index", &idx);
+ r = device_get_sysattr_unsigned_filtered(dev, "index", &idx);
if (r < 0)
return log_device_debug_errno(dev, r, "Could not obtain onboard index: %m");
@@ -310,7 +299,7 @@ static int pci_get_onboard_index(sd_device *dev, unsigned *ret) {
return 0;
}
-static int names_pci_onboard(sd_device *dev, sd_device *pci_dev, const char *prefix, const char *suffix, bool test) {
+static int names_pci_onboard(sd_device *dev, sd_device *pci_dev, const char *prefix, const char *suffix, EventMode mode) {
_cleanup_free_ char *port = NULL;
unsigned idx = 0; /* avoid false maybe-uninitialized warning */
int r;
@@ -330,7 +319,7 @@ static int names_pci_onboard(sd_device *dev, sd_device *pci_dev, const char *pre
char str[ALTIFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%so%u%s%s", prefix, idx, strempty(port), strempty(suffix)))
- udev_builtin_add_property(dev, test, "ID_NET_NAME_ONBOARD", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_ONBOARD", str);
log_device_debug(dev, "Onboard index identifier: index=%u port=%s %s %s",
idx, strna(port),
@@ -339,7 +328,7 @@ static int names_pci_onboard(sd_device *dev, sd_device *pci_dev, const char *pre
return 0;
}
-static int names_pci_onboard_label(sd_device *dev, sd_device *pci_dev, const char *prefix, bool test) {
+static int names_pci_onboard_label(sd_device *dev, sd_device *pci_dev, const char *prefix, EventMode mode) {
const char *label;
int r;
@@ -347,7 +336,7 @@ static int names_pci_onboard_label(sd_device *dev, sd_device *pci_dev, const cha
assert(prefix);
/* retrieve on-board label from firmware */
- r = sd_device_get_sysattr_value(pci_dev, "label", &label);
+ r = device_get_sysattr_value_filtered(pci_dev, "label", &label);
if (r < 0)
return log_device_debug_errno(pci_dev, r, "Failed to get PCI onboard label: %m");
@@ -355,7 +344,7 @@ static int names_pci_onboard_label(sd_device *dev, sd_device *pci_dev, const cha
if (snprintf_ok(str, sizeof str, "%s%s",
naming_scheme_has(NAMING_LABEL_NOPREFIX) ? "" : prefix,
label))
- udev_builtin_add_property(dev, test, "ID_NET_LABEL_ONBOARD", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_LABEL_ONBOARD", str);
log_device_debug(dev, "Onboard label from PCI device: %s", label);
return 0;
@@ -392,7 +381,7 @@ static int is_pci_multifunction(sd_device *dev) {
static bool is_pci_ari_enabled(sd_device *dev) {
assert(dev);
- return device_get_sysattr_bool(dev, "ari_enabled") > 0;
+ return device_get_sysattr_bool_filtered(dev, "ari_enabled") > 0;
}
static bool is_pci_bridge(sd_device *dev) {
@@ -400,7 +389,7 @@ static bool is_pci_bridge(sd_device *dev) {
assert(dev);
- if (sd_device_get_sysattr_value(dev, "modalias", &v) < 0)
+ if (device_get_sysattr_value_filtered(dev, "modalias", &v) < 0)
return false;
if (!startswith(v, "pci:"))
@@ -442,7 +431,7 @@ static int parse_hotplug_slot_from_function_id(sd_device *dev, int slots_dirfd,
return 0;
}
- if (sd_device_get_sysattr_value(dev, "function_id", &attr) < 0) {
+ if (device_get_sysattr_value_filtered(dev, "function_id", &attr) < 0) {
*ret = 0;
return 0;
}
@@ -505,7 +494,7 @@ static int pci_get_hotplug_slot_from_address(
if (!path)
return log_oom_debug();
- if (sd_device_get_sysattr_value(pci, path, &address) < 0)
+ if (device_get_sysattr_value_filtered(pci, path, &address) < 0)
continue;
/* match slot address with device by stripping the function */
@@ -625,7 +614,7 @@ static int get_pci_slot_specifiers(
return 0;
}
-static int names_pci_slot(sd_device *dev, sd_device *pci_dev, const char *prefix, const char *suffix, bool test) {
+static int names_pci_slot(sd_device *dev, sd_device *pci_dev, const char *prefix, const char *suffix, EventMode mode) {
_cleanup_free_ char *domain = NULL, *bus_and_slot = NULL, *func = NULL, *port = NULL;
uint32_t hotplug_slot = 0; /* avoid false maybe-uninitialized warning */
char str[ALTIFNAMSIZ];
@@ -646,7 +635,7 @@ static int names_pci_slot(sd_device *dev, sd_device *pci_dev, const char *prefix
/* compose a name based on the raw kernel's PCI bus, slot numbers */
if (snprintf_ok(str, sizeof str, "%s%s%s%s%s%s",
prefix, strempty(domain), bus_and_slot, strempty(func), strempty(port), strempty(suffix)))
- udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_PATH", str);
log_device_debug(dev, "PCI path identifier: domain=%s bus_and_slot=%s func=%s port=%s %s %s",
strna(domain), bus_and_slot, strna(func), strna(port),
@@ -662,7 +651,7 @@ static int names_pci_slot(sd_device *dev, sd_device *pci_dev, const char *prefix
if (snprintf_ok(str, sizeof str, "%s%ss%"PRIu32"%s%s%s",
prefix, strempty(domain), hotplug_slot, strempty(func), strempty(port), strempty(suffix)))
- udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_SLOT", str);
log_device_debug(dev, "Slot identifier: domain=%s slot=%"PRIu32" func=%s port=%s %s %s",
strna(domain), hotplug_slot, strna(func), strna(port),
@@ -671,7 +660,7 @@ static int names_pci_slot(sd_device *dev, sd_device *pci_dev, const char *prefix
return 0;
}
-static int names_vio(sd_device *dev, const char *prefix, bool test) {
+static int names_vio(sd_device *dev, const char *prefix, EventMode mode) {
_cleanup_free_ char *s = NULL;
unsigned slotid;
int r;
@@ -710,13 +699,13 @@ static int names_vio(sd_device *dev, const char *prefix, bool test) {
char str[ALTIFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%sv%u", prefix, slotid))
- udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_SLOT", str);
log_device_debug(dev, "Vio slot identifier: slotid=%u %s %s",
slotid, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
return 0;
}
-static int names_platform(sd_device *dev, const char *prefix, bool test) {
+static int names_platform(sd_device *dev, const char *prefix, EventMode mode) {
_cleanup_free_ char *p = NULL;
const char *validchars;
char *vendor, *model_str, *instance_str;
@@ -743,15 +732,15 @@ static int names_platform(sd_device *dev, const char *prefix, bool test) {
* The Vendor (3 or 4 char), followed by hexadecimal model number : instance id. */
if (r == 10 && p[7] == ':') {
/* 3 char vendor string */
- vendor = strndupa(p, 3);
- model_str = strndupa(p + 3, 4);
- instance_str = strndupa(p + 8, 2);
+ vendor = strndupa_safe(p, 3);
+ model_str = strndupa_safe(p + 3, 4);
+ instance_str = strndupa_safe(p + 8, 2);
validchars = UPPERCASE_LETTERS;
} else if (r == 11 && p[8] == ':') {
/* 4 char vendor string */
- vendor = strndupa(p, 4);
- model_str = strndupa(p + 4, 4);
- instance_str = strndupa(p + 9, 2);
+ vendor = strndupa_safe(p, 4);
+ model_str = strndupa_safe(p + 4, 4);
+ instance_str = strndupa_safe(p + 9, 2);
validchars = UPPERCASE_LETTERS DIGITS;
} else
return -EOPNOTSUPP;
@@ -772,13 +761,13 @@ static int names_platform(sd_device *dev, const char *prefix, bool test) {
char str[ALTIFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%sa%s%xi%u", prefix, vendor, model, instance))
- udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_PATH", str);
log_device_debug(dev, "Platform identifier: vendor=%s model=%x instance=%u %s %s",
vendor, model, instance, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
return 0;
}
-static int names_devicetree(sd_device *dev, const char *prefix, bool test) {
+static int names_devicetree(sd_device *dev, const char *prefix, EventMode mode) {
_cleanup_(sd_device_unrefp) sd_device *aliases_dev = NULL, *ofnode_dev = NULL, *devicetree_dev = NULL;
const char *ofnode_path, *ofnode_syspath, *devicetree_syspath;
sd_device *parent;
@@ -825,7 +814,7 @@ static int names_devicetree(sd_device *dev, const char *prefix, bool test) {
ofnode_path = path_startswith(ofnode_syspath, devicetree_syspath);
if (!ofnode_path)
return log_device_debug_errno(ofnode_dev, SYNTHETIC_ERRNO(EINVAL),
- "The device '%s' is not a child device of '%s': %m",
+ "The device '%s' is not a child device of '%s'.",
ofnode_syspath, devicetree_syspath);
/* Get back our leading / to match the contents of the aliases */
@@ -845,7 +834,7 @@ static int names_devicetree(sd_device *dev, const char *prefix, bool test) {
if (!alias_index)
continue;
- if (sd_device_get_sysattr_value(aliases_dev, alias, &alias_path) < 0)
+ if (device_get_sysattr_value_filtered(aliases_dev, alias, &alias_path) < 0)
continue;
if (!path_equal(ofnode_path, alias_path))
@@ -864,13 +853,13 @@ static int names_devicetree(sd_device *dev, const char *prefix, bool test) {
}
/* ...but make sure we don't have an alias conflict */
- if (i == 0 && sd_device_get_sysattr_value(aliases_dev, conflict, NULL) >= 0)
+ if (i == 0 && device_get_sysattr_value_filtered(aliases_dev, conflict, NULL) >= 0)
return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EEXIST),
- "Ethernet alias conflict: ethernet and ethernet0 both exist");
+ "Ethernet alias conflict: ethernet and ethernet0 both exist.");
char str[ALTIFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%sd%u", prefix, i))
- udev_builtin_add_property(dev, test, "ID_NET_NAME_ONBOARD", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_ONBOARD", str);
log_device_debug(dev, "devicetree identifier: alias_index=%u %s \"%s\"",
i, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
return 0;
@@ -879,7 +868,7 @@ static int names_devicetree(sd_device *dev, const char *prefix, bool test) {
return -ENOENT;
}
-static int names_pci(sd_device *dev, const char *prefix, bool test) {
+static int names_pci(sd_device *dev, const char *prefix, EventMode mode) {
_cleanup_(sd_device_unrefp) sd_device *physfn_pcidev = NULL;
_cleanup_free_ char *virtfn_suffix = NULL;
sd_device *parent;
@@ -896,10 +885,10 @@ static int names_pci(sd_device *dev, const char *prefix, bool test) {
get_virtfn_info(parent, &physfn_pcidev, &virtfn_suffix) >= 0)
parent = physfn_pcidev;
else
- (void) names_pci_onboard_label(dev, parent, prefix, test);
+ (void) names_pci_onboard_label(dev, parent, prefix, mode);
- (void) names_pci_onboard(dev, parent, prefix, virtfn_suffix, test);
- (void) names_pci_slot(dev, parent, prefix, virtfn_suffix, test);
+ (void) names_pci_onboard(dev, parent, prefix, virtfn_suffix, mode);
+ (void) names_pci_slot(dev, parent, prefix, virtfn_suffix, mode);
return 0;
}
@@ -962,7 +951,7 @@ static int get_usb_specifier(sd_device *dev, char **ret) {
return 0;
}
-static int names_usb(sd_device *dev, const char *prefix, bool test) {
+static int names_usb(sd_device *dev, const char *prefix, EventMode mode) {
_cleanup_free_ char *suffix = NULL;
sd_device *usbdev, *pcidev;
int r;
@@ -983,7 +972,7 @@ static int names_usb(sd_device *dev, const char *prefix, bool test) {
/* If the USB bus is on PCI bus, then suffix the USB specifier to the name based on the PCI bus. */
r = sd_device_get_parent_with_subsystem_devtype(usbdev, "pci", NULL, &pcidev);
if (r >= 0)
- return names_pci_slot(dev, pcidev, prefix, suffix, test);
+ return names_pci_slot(dev, pcidev, prefix, suffix, mode);
if (r != -ENOENT || !naming_scheme_has(NAMING_USB_HOST))
return log_device_debug_errno(usbdev, r, "Failed to get parent PCI bus: %m");
@@ -991,7 +980,7 @@ static int names_usb(sd_device *dev, const char *prefix, bool test) {
/* Otherwise, e.g. on-chip asics that have USB ports, use the USB specifier as is. */
char str[ALTIFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%s%s", prefix, suffix))
- udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_PATH", str);
return 0;
}
@@ -1026,7 +1015,7 @@ static int get_bcma_specifier(sd_device *dev, char **ret) {
return 0;
}
-static int names_bcma(sd_device *dev, const char *prefix, bool test) {
+static int names_bcma(sd_device *dev, const char *prefix, EventMode mode) {
_cleanup_free_ char *suffix = NULL;
sd_device *bcmadev, *pcidev;
int r;
@@ -1046,10 +1035,10 @@ static int names_bcma(sd_device *dev, const char *prefix, bool test) {
if (r < 0)
return r;
- return names_pci_slot(dev, pcidev, prefix, suffix, test);
+ return names_pci_slot(dev, pcidev, prefix, suffix, mode);
}
-static int names_ccw(sd_device *dev, const char *prefix, bool test) {
+static int names_ccw(sd_device *dev, const char *prefix, EventMode mode) {
sd_device *cdev;
const char *bus_id;
size_t bus_id_start, bus_id_len;
@@ -1091,14 +1080,14 @@ static int names_ccw(sd_device *dev, const char *prefix, bool test) {
/* Use the CCW bus-ID as network device name */
char str[ALTIFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%sc%s", prefix, bus_id))
- udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_PATH", str);
log_device_debug(dev, "CCW identifier: ccw_busid=%s %s \"%s\"",
bus_id, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
return 0;
}
/* IEEE Organizationally Unique Identifier vendor string */
-static int ieee_oui(sd_device *dev, const struct hw_addr_data *hw_addr, bool test) {
+static int ieee_oui(sd_device *dev, const struct hw_addr_data *hw_addr, EventMode mode) {
char str[32];
assert(dev);
@@ -1121,10 +1110,10 @@ static int ieee_oui(sd_device *dev, const struct hw_addr_data *hw_addr, bool tes
hw_addr->bytes[4],
hw_addr->bytes[5]);
- return udev_builtin_hwdb_lookup(dev, NULL, str, NULL, test);
+ return udev_builtin_hwdb_lookup(dev, NULL, str, NULL, mode);
}
-static int names_mac(sd_device *dev, const char *prefix, bool test) {
+static int names_mac(sd_device *dev, const char *prefix, EventMode mode) {
unsigned iftype, assign_type;
struct hw_addr_data hw_addr;
const char *s;
@@ -1133,7 +1122,7 @@ static int names_mac(sd_device *dev, const char *prefix, bool test) {
assert(dev);
assert(prefix);
- r = device_get_sysattr_unsigned(dev, "type", &iftype);
+ r = device_get_sysattr_unsigned_filtered(dev, "type", &iftype);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to read 'type' attribute: %m");
@@ -1145,7 +1134,7 @@ static int names_mac(sd_device *dev, const char *prefix, bool test) {
"Not generating MAC name for infiniband device.");
/* check for NET_ADDR_PERM, skip random MAC addresses */
- r = device_get_sysattr_unsigned(dev, "addr_assign_type", &assign_type);
+ r = device_get_sysattr_unsigned_filtered(dev, "addr_assign_type", &assign_type);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to read/parse addr_assign_type: %m");
@@ -1153,7 +1142,7 @@ static int names_mac(sd_device *dev, const char *prefix, bool test) {
return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL),
"addr_assign_type=%u, MAC address is not permanent.", assign_type);
- r = sd_device_get_sysattr_value(dev, "address", &s);
+ r = device_get_sysattr_value_filtered(dev, "address", &s);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to read 'address' attribute: %m");
@@ -1168,16 +1157,16 @@ static int names_mac(sd_device *dev, const char *prefix, bool test) {
char str[ALTIFNAMSIZ];
xsprintf(str, "%sx%s", prefix, HW_ADDR_TO_STR_FULL(&hw_addr, HW_ADDR_TO_STRING_NO_COLON));
- udev_builtin_add_property(dev, test, "ID_NET_NAME_MAC", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_MAC", str);
log_device_debug(dev, "MAC address identifier: hw_addr=%s %s %s",
HW_ADDR_TO_STR(&hw_addr),
special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
- (void) ieee_oui(dev, &hw_addr, test);
+ (void) ieee_oui(dev, &hw_addr, mode);
return 0;
}
-static int names_netdevsim(sd_device *dev, const char *prefix, bool test) {
+static int names_netdevsim(sd_device *dev, const char *prefix, EventMode mode) {
sd_device *netdevsimdev;
const char *sysnum, *phys_port_name;
unsigned addr;
@@ -1203,7 +1192,7 @@ static int names_netdevsim(sd_device *dev, const char *prefix, bool test) {
if (r < 0)
return log_device_debug_errno(netdevsimdev, r, "Failed to parse device sysnum: %m");
- r = sd_device_get_sysattr_value(dev, "phys_port_name", &phys_port_name);
+ r = device_get_sysattr_value_filtered(dev, "phys_port_name", &phys_port_name);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to get 'phys_port_name' attribute: %m");
if (isempty(phys_port_name))
@@ -1212,13 +1201,13 @@ static int names_netdevsim(sd_device *dev, const char *prefix, bool test) {
char str[ALTIFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%si%un%s", prefix, addr, phys_port_name))
- udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_PATH", str);
log_device_debug(dev, "Netdevsim identifier: address=%u, port_name=%s %s %s",
addr, phys_port_name, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
return 0;
}
-static int names_xen(sd_device *dev, const char *prefix, bool test) {
+static int names_xen(sd_device *dev, const char *prefix, EventMode mode) {
_cleanup_free_ char *vif = NULL;
const char *p;
unsigned id;
@@ -1243,7 +1232,7 @@ static int names_xen(sd_device *dev, const char *prefix, bool test) {
p = startswith(vif, "vif-");
if (!p)
- return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Invalid vif name: %s: %m", vif);
+ return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Invalid vif name: %s.", vif);
r = safe_atou_full(p, SAFE_ATO_REFUSE_PLUS_MINUS | SAFE_ATO_REFUSE_LEADING_ZERO |
SAFE_ATO_REFUSE_LEADING_WHITESPACE | 10, &id);
@@ -1252,7 +1241,7 @@ static int names_xen(sd_device *dev, const char *prefix, bool test) {
char str[ALTIFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%sX%u", prefix, id))
- udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
+ udev_builtin_add_property(dev, mode, "ID_NET_NAME_SLOT", str);
log_device_debug(dev, "Xen identifier: id=%u %s %s",
id, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
return 0;
@@ -1265,22 +1254,16 @@ static int get_ifname_prefix(sd_device *dev, const char **ret) {
assert(dev);
assert(ret);
- r = device_get_sysattr_unsigned(dev, "type", &iftype);
+ r = device_get_sysattr_unsigned_filtered(dev, "type", &iftype);
if (r < 0)
return r;
/* handle only ARPHRD_ETHER, ARPHRD_SLIP and ARPHRD_INFINIBAND devices */
switch (iftype) {
case ARPHRD_ETHER: {
- const char *s = NULL;
-
- r = sd_device_get_devtype(dev, &s);
- if (r < 0 && r != -ENOENT)
- return r;
-
- if (streq_ptr(s, "wlan"))
+ if (device_is_devtype(dev, "wlan"))
*ret = "wl";
- else if (streq_ptr(s, "wwan"))
+ else if (device_is_devtype(dev, "wwan"))
*ret = "ww";
else
*ret = "en";
@@ -1311,14 +1294,14 @@ static int device_is_stacked(sd_device *dev) {
if (r < 0)
return r;
- r = device_get_sysattr_int(dev, "iflink", &iflink);
+ r = device_get_sysattr_int_filtered(dev, "iflink", &iflink);
if (r < 0)
return r;
return ifindex != iflink;
}
-static int builtin_net_id(UdevEvent *event, int argc, char *argv[], bool test) {
+static int builtin_net_id(UdevEvent *event, int argc, char *argv[]) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
const char *prefix;
int r;
@@ -1336,18 +1319,18 @@ static int builtin_net_id(UdevEvent *event, int argc, char *argv[], bool test) {
return 0;
}
- udev_builtin_add_property(dev, test, "ID_NET_NAMING_SCHEME", naming_scheme()->name);
-
- (void) names_mac(dev, prefix, test);
- (void) names_devicetree(dev, prefix, test);
- (void) names_ccw(dev, prefix, test);
- (void) names_vio(dev, prefix, test);
- (void) names_platform(dev, prefix, test);
- (void) names_netdevsim(dev, prefix, test);
- (void) names_xen(dev, prefix, test);
- (void) names_pci(dev, prefix, test);
- (void) names_usb(dev, prefix, test);
- (void) names_bcma(dev, prefix, test);
+ udev_builtin_add_property(dev, event->event_mode, "ID_NET_NAMING_SCHEME", naming_scheme()->name);
+
+ (void) names_mac(dev, prefix, event->event_mode);
+ (void) names_devicetree(dev, prefix, event->event_mode);
+ (void) names_ccw(dev, prefix, event->event_mode);
+ (void) names_vio(dev, prefix, event->event_mode);
+ (void) names_platform(dev, prefix, event->event_mode);
+ (void) names_netdevsim(dev, prefix, event->event_mode);
+ (void) names_xen(dev, prefix, event->event_mode);
+ (void) names_pci(dev, prefix, event->event_mode);
+ (void) names_usb(dev, prefix, event->event_mode);
+ (void) names_bcma(dev, prefix, event->event_mode);
return 0;
}
diff --git a/src/udev/udev-builtin-net_setup_link.c b/src/udev/udev-builtin-net_setup_link.c
index a308a21..8cfcaa9 100644
--- a/src/udev/udev-builtin-net_setup_link.c
+++ b/src/udev/udev-builtin-net_setup_link.c
@@ -1,8 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "alloc-util.h"
+#include "device-private.h"
#include "device-util.h"
-#include "escape.h"
#include "errno-util.h"
#include "link-config.h"
#include "log.h"
@@ -12,16 +12,36 @@
static LinkConfigContext *ctx = NULL;
-static int builtin_net_setup_link(UdevEvent *event, int argc, char **argv, bool test) {
+static int builtin_net_setup_link(UdevEvent *event, int argc, char **argv) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
_cleanup_(link_freep) Link *link = NULL;
- _cleanup_free_ char *joined = NULL;
int r;
if (argc > 1)
return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments.");
- r = link_new(ctx, &event->rtnl, dev, &link);
+ sd_device_action_t action;
+ r = sd_device_get_action(dev, &action);
+ if (r < 0)
+ return log_device_error_errno(dev, r, "Failed to get action: %m");
+
+ if (!IN_SET(action, SD_DEVICE_ADD, SD_DEVICE_BIND, SD_DEVICE_MOVE)) {
+ log_device_debug(dev, "Not applying .link settings on '%s' uevent.",
+ device_action_to_string(action));
+
+ /* Import previously assigned .link file name. */
+ (void) udev_builtin_import_property(dev, event->dev_db_clone, event->event_mode, "ID_NET_LINK_FILE");
+ (void) udev_builtin_import_property(dev, event->dev_db_clone, event->event_mode, "ID_NET_LINK_FILE_DROPINS");
+
+ /* Set ID_NET_NAME= with the current interface name. */
+ const char *value;
+ if (sd_device_get_sysname(dev, &value) >= 0)
+ (void) udev_builtin_add_property(dev, event->event_mode, "ID_NET_NAME", value);
+
+ return 0;
+ }
+
+ r = link_new(ctx, &event->rtnl, dev, event->dev_db_clone, &link);
if (r == -ENODEV) {
log_device_debug_errno(dev, r, "Link vanished while getting information, ignoring.");
return 0;
@@ -39,31 +59,14 @@ static int builtin_net_setup_link(UdevEvent *event, int argc, char **argv, bool
return log_device_error_errno(dev, r, "Failed to get link config: %m");
}
- r = link_apply_config(ctx, &event->rtnl, link);
+ r = link_apply_config(ctx, &event->rtnl, link, event->event_mode);
if (r == -ENODEV)
log_device_debug_errno(dev, r, "Link vanished while applying configuration, ignoring.");
else if (r < 0)
log_device_warning_errno(dev, r, "Could not apply link configuration, ignoring: %m");
- udev_builtin_add_property(dev, test, "ID_NET_LINK_FILE", link->config->filename);
- if (link->new_name)
- udev_builtin_add_property(dev, test, "ID_NET_NAME", link->new_name);
-
event->altnames = TAKE_PTR(link->altnames);
- STRV_FOREACH(d, link->config->dropins) {
- _cleanup_free_ char *escaped = NULL;
-
- escaped = xescape(*d, ":");
- if (!escaped)
- return log_oom();
-
- if (!strextend_with_separator(&joined, ":", escaped))
- return log_oom();
- }
-
- udev_builtin_add_property(dev, test, "ID_NET_LINK_FILE_DROPINS", joined);
-
return 0;
}
diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
index 467c9a6..a23b32d 100644
--- a/src/udev/udev-builtin-path_id.c
+++ b/src/udev/udev-builtin-path_id.c
@@ -95,12 +95,7 @@ static sd_device *skip_subsystem(sd_device *dev, const char *subsys) {
*/
for (parent = dev; ; ) {
- const char *subsystem;
-
- if (sd_device_get_subsystem(parent, &subsystem) < 0)
- break;
-
- if (!streq(subsystem, subsys))
+ if (!device_in_subsystem(parent, subsys))
break;
dev = parent;
@@ -191,7 +186,7 @@ static sd_device *handle_scsi_sas(sd_device *parent, char **path) {
return NULL;
/* Check if we are simple disk */
- if (strncmp(phy_count, "1", 2) != 0)
+ if (!streq(phy_count, "1"))
return handle_scsi_sas_wide_port(parent, path);
/* Get connected phy */
@@ -417,10 +412,9 @@ static sd_device *handle_scsi_hyperv(sd_device *parent, char **path, size_t guid
}
static sd_device *handle_scsi(sd_device *parent, char **path, char **compat_path, bool *supported_parent) {
- const char *devtype, *id, *name;
+ const char *id, *name;
- if (sd_device_get_devtype(parent, &devtype) < 0 ||
- !streq(devtype, "scsi_device"))
+ if (!device_is_devtype(parent, "scsi_device"))
return parent;
/* firewire */
@@ -532,12 +526,10 @@ static int get_usb_revision(sd_device *dev) {
}
static sd_device *handle_usb(sd_device *parent, char **path) {
- const char *devtype, *str, *port;
+ const char *str, *port;
int r;
- if (sd_device_get_devtype(parent, &devtype) < 0)
- return parent;
- if (!STR_IN_SET(devtype, "usb_interface", "usb_device"))
+ if (!device_is_devtype(parent, "usb_interface") && !device_is_devtype(parent, "usb_device"))
return parent;
if (sd_device_get_sysname(parent, &str) < 0)
@@ -632,7 +624,7 @@ static int find_real_nvme_parent(sd_device *dev, sd_device **ret) {
return -ENXIO;
end += strspn(end, DIGITS);
- sysname = strndupa(sysname, end - sysname);
+ sysname = strndupa_safe(sysname, end - sysname);
r = sd_device_new_from_subsystem_sysname(&nvme, "nvme", sysname);
if (r < 0)
@@ -650,9 +642,8 @@ static int find_real_nvme_parent(sd_device *dev, sd_device **ret) {
return 0;
}
-static void add_id_with_usb_revision(sd_device *dev, bool test, char *path) {
+static void add_id_with_usb_revision(sd_device *dev, EventMode mode, char *path) {
char *p;
- int r;
assert(dev);
assert(path);
@@ -668,18 +659,15 @@ static void add_id_with_usb_revision(sd_device *dev, bool test, char *path) {
if (p[1] != '-')
return;
- r = udev_builtin_add_property(dev, test, "ID_PATH_WITH_USB_REVISION", path);
- if (r < 0)
- log_device_debug_errno(dev, r, "Failed to add ID_PATH_WITH_USB_REVISION property, ignoring: %m");
+ (void) udev_builtin_add_property(dev, mode, "ID_PATH_WITH_USB_REVISION", path);
/* Drop the USB revision specifier for backward compatibility. */
memmove(p - 1, p + 1, strlen(p + 1) + 1);
}
-static void add_id_tag(sd_device *dev, bool test, const char *path) {
+static void add_id_tag(sd_device *dev, EventMode mode, const char *path) {
char tag[UDEV_NAME_SIZE];
size_t i = 0;
- int r;
/* compose valid udev tag name */
for (const char *p = path; *p; p++) {
@@ -705,115 +693,111 @@ static void add_id_tag(sd_device *dev, bool test, const char *path) {
i--;
tag[i] = '\0';
- r = udev_builtin_add_property(dev, test, "ID_PATH_TAG", tag);
- if (r < 0)
- log_device_debug_errno(dev, r, "Failed to add ID_PATH_TAG property, ignoring: %m");
+ (void) udev_builtin_add_property(dev, mode, "ID_PATH_TAG", tag);
}
-static int builtin_path_id(UdevEvent *event, int argc, char *argv[], bool test) {
+static int builtin_path_id(UdevEvent *event, int argc, char *argv[]) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
_cleanup_(sd_device_unrefp) sd_device *dev_other_branch = NULL;
_cleanup_free_ char *path = NULL, *compat_path = NULL;
bool supported_transport = false, supported_parent = false;
- const char *subsystem;
int r;
/* walk up the chain of devices and compose path */
for (sd_device *parent = dev; parent; ) {
- const char *subsys, *sysname;
+ const char *sysname;
- if (sd_device_get_subsystem(parent, &subsys) < 0 ||
- sd_device_get_sysname(parent, &sysname) < 0) {
+ if (sd_device_get_sysname(parent, &sysname) < 0) {
;
- } else if (streq(subsys, "scsi_tape")) {
+ } else if (device_in_subsystem(parent, "scsi_tape")) {
handle_scsi_tape(parent, &path);
- } else if (streq(subsys, "scsi")) {
+ } else if (device_in_subsystem(parent, "scsi")) {
parent = handle_scsi(parent, &path, &compat_path, &supported_parent);
supported_transport = true;
- } else if (streq(subsys, "cciss")) {
+ } else if (device_in_subsystem(parent, "cciss")) {
parent = handle_cciss(parent, &path);
supported_transport = true;
- } else if (streq(subsys, "usb")) {
+ } else if (device_in_subsystem(parent, "usb")) {
parent = handle_usb(parent, &path);
supported_transport = true;
- } else if (streq(subsys, "bcma")) {
+ } else if (device_in_subsystem(parent, "bcma")) {
parent = handle_bcma(parent, &path);
supported_transport = true;
- } else if (streq(subsys, "serio")) {
+ } else if (device_in_subsystem(parent, "serio")) {
const char *sysnum;
if (sd_device_get_sysnum(parent, &sysnum) >= 0 && sysnum) {
path_prepend(&path, "serio-%s", sysnum);
parent = skip_subsystem(parent, "serio");
}
- } else if (streq(subsys, "pci")) {
+ } else if (device_in_subsystem(parent, "pci")) {
path_prepend(&path, "pci-%s", sysname);
if (compat_path)
path_prepend(&compat_path, "pci-%s", sysname);
parent = skip_subsystem(parent, "pci");
supported_parent = true;
- } else if (streq(subsys, "platform")) {
+ } else if (device_in_subsystem(parent, "platform")) {
path_prepend(&path, "platform-%s", sysname);
if (compat_path)
path_prepend(&compat_path, "platform-%s", sysname);
parent = skip_subsystem(parent, "platform");
supported_transport = true;
supported_parent = true;
- } else if (streq(subsys, "amba")) {
+ } else if (device_in_subsystem(parent, "amba")) {
path_prepend(&path, "amba-%s", sysname);
if (compat_path)
path_prepend(&compat_path, "amba-%s", sysname);
parent = skip_subsystem(parent, "amba");
supported_transport = true;
supported_parent = true;
- } else if (streq(subsys, "acpi")) {
+ } else if (device_in_subsystem(parent, "acpi")) {
path_prepend(&path, "acpi-%s", sysname);
if (compat_path)
path_prepend(&compat_path, "acpi-%s", sysname);
parent = skip_subsystem(parent, "acpi");
supported_parent = true;
- } else if (streq(subsys, "xen")) {
+ } else if (device_in_subsystem(parent, "xen")) {
path_prepend(&path, "xen-%s", sysname);
if (compat_path)
path_prepend(&compat_path, "xen-%s", sysname);
parent = skip_subsystem(parent, "xen");
supported_parent = true;
- } else if (streq(subsys, "virtio")) {
+ } else if (device_in_subsystem(parent, "virtio")) {
parent = skip_subsystem(parent, "virtio");
supported_transport = true;
- } else if (streq(subsys, "scm")) {
+ } else if (device_in_subsystem(parent, "scm")) {
path_prepend(&path, "scm-%s", sysname);
if (compat_path)
path_prepend(&compat_path, "scm-%s", sysname);
parent = skip_subsystem(parent, "scm");
supported_transport = true;
supported_parent = true;
- } else if (streq(subsys, "ccw")) {
+ } else if (device_in_subsystem(parent, "ccw")) {
path_prepend(&path, "ccw-%s", sysname);
if (compat_path)
path_prepend(&compat_path, "ccw-%s", sysname);
parent = skip_subsystem(parent, "ccw");
supported_transport = true;
supported_parent = true;
- } else if (streq(subsys, "ccwgroup")) {
+ } else if (device_in_subsystem(parent, "ccwgroup")) {
path_prepend(&path, "ccwgroup-%s", sysname);
if (compat_path)
path_prepend(&compat_path, "ccwgroup-%s", sysname);
parent = skip_subsystem(parent, "ccwgroup");
supported_transport = true;
supported_parent = true;
- } else if (streq(subsys, "ap")) {
+ } else if (device_in_subsystem(parent, "ap")) {
parent = handle_ap(parent, &path);
supported_transport = true;
supported_parent = true;
- } else if (streq(subsys, "iucv")) {
+ } else if (device_in_subsystem(parent, "iucv")) {
path_prepend(&path, "iucv-%s", sysname);
if (compat_path)
path_prepend(&compat_path, "iucv-%s", sysname);
parent = skip_subsystem(parent, "iucv");
supported_transport = true;
supported_parent = true;
- } else if (STR_IN_SET(subsys, "nvme", "nvme-subsystem")) {
+ } else if (device_in_subsystem(parent, "nvme") || device_in_subsystem(parent, "nvme-subsystem")) {
const char *nsid;
if (sd_device_get_sysattr_value(dev, "nsid", &nsid) >= 0) {
@@ -821,7 +805,7 @@ static int builtin_path_id(UdevEvent *event, int argc, char *argv[], bool test)
if (compat_path)
path_prepend(&compat_path, "nvme-%s", nsid);
- if (streq(subsys, "nvme-subsystem")) {
+ if (device_in_subsystem(parent, "nvme-subsystem")) {
r = find_real_nvme_parent(dev, &dev_other_branch);
if (r < 0)
return r;
@@ -833,7 +817,7 @@ static int builtin_path_id(UdevEvent *event, int argc, char *argv[], bool test)
supported_parent = true;
supported_transport = true;
}
- } else if (streq(subsys, "spi")) {
+ } else if (device_in_subsystem(parent, "spi")) {
const char *sysnum;
if (sd_device_get_sysnum(parent, &sysnum) >= 0 && sysnum) {
@@ -864,18 +848,14 @@ static int builtin_path_id(UdevEvent *event, int argc, char *argv[], bool test)
* devices do not expose their buses and do not provide a unique
* and predictable name that way.
*/
- if (sd_device_get_subsystem(dev, &subsystem) >= 0 &&
- streq(subsystem, "block") &&
- !supported_transport)
+ if (device_in_subsystem(dev, "block") && !supported_transport)
return -ENOENT;
- add_id_with_usb_revision(dev, test, path);
+ add_id_with_usb_revision(dev, event->event_mode, path);
- r = udev_builtin_add_property(dev, test, "ID_PATH", path);
- if (r < 0)
- log_device_debug_errno(dev, r, "Failed to add ID_PATH property, ignoring: %m");
+ (void) udev_builtin_add_property(dev, event->event_mode, "ID_PATH", path);
- add_id_tag(dev, test, path);
+ add_id_tag(dev, event->event_mode, path);
/*
* Compatible link generation for ATA devices
@@ -883,7 +863,7 @@ static int builtin_path_id(UdevEvent *event, int argc, char *argv[], bool test)
* ID_PATH_ATA_COMPAT
*/
if (compat_path)
- udev_builtin_add_property(dev, test, "ID_PATH_ATA_COMPAT", compat_path);
+ (void) udev_builtin_add_property(dev, event->event_mode, "ID_PATH_ATA_COMPAT", compat_path);
return 0;
}
diff --git a/src/udev/udev-builtin-uaccess.c b/src/udev/udev-builtin-uaccess.c
index da42ef5..805d048 100644
--- a/src/udev/udev-builtin-uaccess.c
+++ b/src/udev/udev-builtin-uaccess.c
@@ -17,13 +17,18 @@
#include "log.h"
#include "udev-builtin.h"
-static int builtin_uaccess(UdevEvent *event, int argc, char *argv[], bool test) {
+static int builtin_uaccess(UdevEvent *event, int argc, char *argv[]) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
const char *path = NULL, *seat;
bool changed_acl = false;
uid_t uid;
int r;
+ if (event->event_mode != EVENT_UDEV_WORKER) {
+ log_device_debug(dev, "Running in test mode, skipping execution of 'uaccess' builtin command.");
+ return 0;
+ }
+
umask(0022);
/* don't muck around with ACLs when the system is not running systemd */
diff --git a/src/udev/udev-builtin-usb_id.c b/src/udev/udev-builtin-usb_id.c
index 8e83c9c..2413f9c 100644
--- a/src/udev/udev-builtin-usb_id.c
+++ b/src/udev/udev-builtin-usb_id.c
@@ -224,7 +224,7 @@ static int dev_if_packed_info(sd_device *dev, char *ifs_str, size_t len) {
* 6.) If the device supplies a serial number, this number
* is concatenated with the identification with an underscore '_'.
*/
-static int builtin_usb_id(UdevEvent *event, int argc, char *argv[], bool test) {
+static int builtin_usb_id(UdevEvent *event, int argc, char *argv[]) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
char vendor_str[64] = "";
char vendor_str_enc[256];
@@ -248,7 +248,7 @@ static int builtin_usb_id(UdevEvent *event, int argc, char *argv[], bool test) {
size_t l;
char *s;
- const char *syspath, *sysname, *devtype, *interface_syspath;
+ const char *syspath, *sysname, *interface_syspath;
int r;
r = sd_device_get_syspath(dev, &syspath);
@@ -260,7 +260,7 @@ static int builtin_usb_id(UdevEvent *event, int argc, char *argv[], bool test) {
return r;
/* shortcut, if we are called directly for a "usb_device" type */
- if (sd_device_get_devtype(dev, &devtype) >= 0 && streq(devtype, "usb_device")) {
+ if (device_is_devtype(dev, "usb_device")) {
dev_if_packed_info(dev, packed_if_str, sizeof(packed_if_str));
dev_usb = dev;
goto fallback;
@@ -429,55 +429,55 @@ fallback:
if (sd_device_get_property_value(dev, "ID_BUS", NULL) >= 0)
log_device_debug(dev, "ID_BUS property is already set, setting only properties prefixed with \"ID_USB_\".");
else {
- udev_builtin_add_property(dev, test, "ID_BUS", "usb");
+ udev_builtin_add_property(dev, event->event_mode, "ID_BUS", "usb");
- udev_builtin_add_property(dev, test, "ID_MODEL", model_str);
- udev_builtin_add_property(dev, test, "ID_MODEL_ENC", model_str_enc);
- udev_builtin_add_property(dev, test, "ID_MODEL_ID", product_id);
+ udev_builtin_add_property(dev, event->event_mode, "ID_MODEL", model_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_MODEL_ENC", model_str_enc);
+ udev_builtin_add_property(dev, event->event_mode, "ID_MODEL_ID", product_id);
- udev_builtin_add_property(dev, test, "ID_SERIAL", serial);
+ udev_builtin_add_property(dev, event->event_mode, "ID_SERIAL", serial);
if (!isempty(serial_str))
- udev_builtin_add_property(dev, test, "ID_SERIAL_SHORT", serial_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_SERIAL_SHORT", serial_str);
- udev_builtin_add_property(dev, test, "ID_VENDOR", vendor_str);
- udev_builtin_add_property(dev, test, "ID_VENDOR_ENC", vendor_str_enc);
- udev_builtin_add_property(dev, test, "ID_VENDOR_ID", vendor_id);
+ udev_builtin_add_property(dev, event->event_mode, "ID_VENDOR", vendor_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_VENDOR_ENC", vendor_str_enc);
+ udev_builtin_add_property(dev, event->event_mode, "ID_VENDOR_ID", vendor_id);
- udev_builtin_add_property(dev, test, "ID_REVISION", revision_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_REVISION", revision_str);
if (!isempty(type_str))
- udev_builtin_add_property(dev, test, "ID_TYPE", type_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_TYPE", type_str);
if (!isempty(instance_str))
- udev_builtin_add_property(dev, test, "ID_INSTANCE", instance_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_INSTANCE", instance_str);
}
/* Also export the same values in the above by prefixing ID_USB_. */
- udev_builtin_add_property(dev, test, "ID_USB_MODEL", model_str);
- udev_builtin_add_property(dev, test, "ID_USB_MODEL_ENC", model_str_enc);
- udev_builtin_add_property(dev, test, "ID_USB_MODEL_ID", product_id);
- udev_builtin_add_property(dev, test, "ID_USB_SERIAL", serial);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_MODEL", model_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_MODEL_ENC", model_str_enc);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_MODEL_ID", product_id);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_SERIAL", serial);
if (!isempty(serial_str))
- udev_builtin_add_property(dev, test, "ID_USB_SERIAL_SHORT", serial_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_SERIAL_SHORT", serial_str);
- udev_builtin_add_property(dev, test, "ID_USB_VENDOR", vendor_str);
- udev_builtin_add_property(dev, test, "ID_USB_VENDOR_ENC", vendor_str_enc);
- udev_builtin_add_property(dev, test, "ID_USB_VENDOR_ID", vendor_id);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_VENDOR", vendor_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_VENDOR_ENC", vendor_str_enc);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_VENDOR_ID", vendor_id);
- udev_builtin_add_property(dev, test, "ID_USB_REVISION", revision_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_REVISION", revision_str);
if (!isempty(type_str))
- udev_builtin_add_property(dev, test, "ID_USB_TYPE", type_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_TYPE", type_str);
if (!isempty(instance_str))
- udev_builtin_add_property(dev, test, "ID_USB_INSTANCE", instance_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_INSTANCE", instance_str);
if (!isempty(packed_if_str))
- udev_builtin_add_property(dev, test, "ID_USB_INTERFACES", packed_if_str);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_INTERFACES", packed_if_str);
if (ifnum)
- udev_builtin_add_property(dev, test, "ID_USB_INTERFACE_NUM", ifnum);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_INTERFACE_NUM", ifnum);
if (driver)
- udev_builtin_add_property(dev, test, "ID_USB_DRIVER", driver);
+ udev_builtin_add_property(dev, event->event_mode, "ID_USB_DRIVER", driver);
return 0;
}
diff --git a/src/udev/udev-builtin.c b/src/udev/udev-builtin.c
index bcc2018..1a1cb37 100644
--- a/src/udev/udev-builtin.c
+++ b/src/udev/udev-builtin.c
@@ -99,7 +99,7 @@ UdevBuiltinCommand udev_builtin_lookup(const char *command) {
return _UDEV_BUILTIN_INVALID;
}
-int udev_builtin_run(UdevEvent *event, UdevBuiltinCommand cmd, const char *command, bool test) {
+int udev_builtin_run(UdevEvent *event, UdevBuiltinCommand cmd, const char *command) {
_cleanup_strv_free_ char **argv = NULL;
int r;
@@ -117,10 +117,10 @@ int udev_builtin_run(UdevEvent *event, UdevBuiltinCommand cmd, const char *comma
/* we need '0' here to reset the internal state */
optind = 0;
- return builtins[cmd]->cmd(event, strv_length(argv), argv, test);
+ return builtins[cmd]->cmd(event, strv_length(argv), argv);
}
-int udev_builtin_add_property(sd_device *dev, bool test, const char *key, const char *val) {
+int udev_builtin_add_property(sd_device *dev, EventMode mode, const char *key, const char *val) {
int r;
assert(dev);
@@ -131,13 +131,13 @@ int udev_builtin_add_property(sd_device *dev, bool test, const char *key, const
return log_device_debug_errno(dev, r, "Failed to add property '%s%s%s'",
key, val ? "=" : "", strempty(val));
- if (test)
+ if (mode == EVENT_UDEVADM_TEST_BUILTIN)
printf("%s=%s\n", key, strempty(val));
return 0;
}
-int udev_builtin_add_propertyf(sd_device *dev, bool test, const char *key, const char *valf, ...) {
+int udev_builtin_add_propertyf(sd_device *dev, EventMode mode, const char *key, const char *valf, ...) {
_cleanup_free_ char *val = NULL;
va_list ap;
int r;
@@ -152,5 +152,28 @@ int udev_builtin_add_propertyf(sd_device *dev, bool test, const char *key, const
if (r < 0)
return log_oom_debug();
- return udev_builtin_add_property(dev, test, key, val);
+ return udev_builtin_add_property(dev, mode, key, val);
+}
+
+int udev_builtin_import_property(sd_device *dev, sd_device *src, EventMode mode, const char *key) {
+ const char *val;
+ int r;
+
+ assert(dev);
+ assert(key);
+
+ if (!src)
+ return 0;
+
+ r = sd_device_get_property_value(src, key, &val);
+ if (r == -ENOENT)
+ return 0;
+ if (r < 0)
+ return log_device_debug_errno(src, r, "Failed to get property \"%s\", ignoring: %m", key);
+
+ r = udev_builtin_add_property(dev, mode, key, val);
+ if (r < 0)
+ return r;
+
+ return 1;
}
diff --git a/src/udev/udev-builtin.h b/src/udev/udev-builtin.h
index fcd41d6..0d82beb 100644
--- a/src/udev/udev-builtin.h
+++ b/src/udev/udev-builtin.h
@@ -34,7 +34,7 @@ typedef enum UdevBuiltinCommand {
typedef struct UdevBuiltin {
const char *name;
- int (*cmd)(UdevEvent *event, int argc, char *argv[], bool test);
+ int (*cmd)(UdevEvent *event, int argc, char *argv[]);
const char *help;
int (*init)(void);
void (*exit)(void);
@@ -79,10 +79,11 @@ void udev_builtin_exit(void);
UdevBuiltinCommand udev_builtin_lookup(const char *command);
const char *udev_builtin_name(UdevBuiltinCommand cmd);
bool udev_builtin_run_once(UdevBuiltinCommand cmd);
-int udev_builtin_run(UdevEvent *event, UdevBuiltinCommand cmd, const char *command, bool test);
+int udev_builtin_run(UdevEvent *event, UdevBuiltinCommand cmd, const char *command);
void udev_builtin_list(void);
bool udev_builtin_should_reload(void);
-int udev_builtin_add_property(sd_device *dev, bool test, const char *key, const char *val);
-int udev_builtin_add_propertyf(sd_device *dev, bool test, const char *key, const char *valf, ...) _printf_(4, 5);
+int udev_builtin_add_property(sd_device *dev, EventMode mode, const char *key, const char *val);
+int udev_builtin_add_propertyf(sd_device *dev, EventMode mode, const char *key, const char *valf, ...) _printf_(4, 5);
+int udev_builtin_import_property(sd_device *dev, sd_device *src, EventMode mode, const char *key);
int udev_builtin_hwdb_lookup(sd_device *dev, const char *prefix, const char *modalias,
- const char *filter, bool test);
+ const char *filter, EventMode mode);
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index ed22c8b..607071a 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -14,10 +14,10 @@
#include "udev-node.h"
#include "udev-trace.h"
#include "udev-util.h"
-#include "udev-watch.h"
#include "user-util.h"
-UdevEvent *udev_event_new(sd_device *dev, usec_t exec_delay_usec, sd_netlink *rtnl, int log_level) {
+UdevEvent *udev_event_new(sd_device *dev, UdevWorker *worker, EventMode mode) {
+ int log_level = worker ? worker->log_level : log_get_max_level();
UdevEvent *event;
assert(dev);
@@ -27,15 +27,16 @@ UdevEvent *udev_event_new(sd_device *dev, usec_t exec_delay_usec, sd_netlink *rt
return NULL;
*event = (UdevEvent) {
+ .worker = worker,
+ .rtnl = worker ? sd_netlink_ref(worker->rtnl) : NULL,
.dev = sd_device_ref(dev),
.birth_usec = now(CLOCK_MONOTONIC),
- .exec_delay_usec = exec_delay_usec,
- .rtnl = sd_netlink_ref(rtnl),
.uid = UID_INVALID,
.gid = GID_INVALID,
.mode = MODE_INVALID,
.log_level_was_debug = log_level == LOG_DEBUG,
.default_log_level = log_level,
+ .event_mode = mode,
};
return event;
@@ -110,6 +111,9 @@ static int rename_netif(UdevEvent *event) {
assert(event);
+ if (!EVENT_MODE_DESTRUCTIVE(event))
+ return 0;
+
if (!event->name)
return 0; /* No new name is requested. */
@@ -171,6 +175,12 @@ static int rename_netif(UdevEvent *event) {
goto revert;
}
+ r = device_add_property(event->dev_db_clone, "ID_PROCESSING", "1");
+ if (r < 0) {
+ log_device_warning_errno(event->dev_db_clone, r, "Failed to add 'ID_PROCESSING' property: %m");
+ goto revert;
+ }
+
r = device_update_db(event->dev_db_clone);
if (r < 0) {
log_device_debug_errno(event->dev_db_clone, r, "Failed to update database under /run/udev/data/: %m");
@@ -197,6 +207,7 @@ static int rename_netif(UdevEvent *event) {
revert:
/* Restore 'dev_db_clone' */
(void) device_add_property(event->dev_db_clone, "ID_RENAMING", NULL);
+ (void) device_add_property(event->dev_db_clone, "ID_PROCESSING", NULL);
(void) device_update_db(event->dev_db_clone);
/* Restore 'dev' */
@@ -215,6 +226,9 @@ static int assign_altnames(UdevEvent *event) {
int ifindex, r;
const char *s;
+ if (!EVENT_MODE_DESTRUCTIVE(event))
+ return 0;
+
if (strv_isempty(event->altnames))
return 0;
@@ -243,6 +257,9 @@ static int update_devnode(UdevEvent *event) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
int r;
+ if (!EVENT_MODE_DESTRUCTIVE(event))
+ return 0;
+
r = sd_device_get_devnum(dev, NULL);
if (r == -ENOENT)
return 0;
@@ -276,14 +293,7 @@ static int update_devnode(UdevEvent *event) {
return udev_node_update(dev, event->dev_db_clone);
}
-static int event_execute_rules_on_remove(
- UdevEvent *event,
- int inotify_fd,
- usec_t timeout_usec,
- int timeout_signal,
- Hashmap *properties_list,
- UdevRules *rules) {
-
+static int event_execute_rules_on_remove(UdevEvent *event, UdevRules *rules) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
int r;
@@ -291,22 +301,22 @@ static int event_execute_rules_on_remove(
if (r < 0)
log_device_debug_errno(dev, r, "Failed to read database under /run/udev/data/: %m");
- r = device_tag_index(dev, NULL, false);
- if (r < 0)
- log_device_debug_errno(dev, r, "Failed to remove corresponding tag files under /run/udev/tag/, ignoring: %m");
-
- r = device_delete_db(dev);
- if (r < 0)
- log_device_debug_errno(dev, r, "Failed to delete database under /run/udev/data/, ignoring: %m");
+ if (EVENT_MODE_DESTRUCTIVE(event)) {
+ r = device_tag_index(dev, NULL, false);
+ if (r < 0)
+ log_device_debug_errno(dev, r, "Failed to remove corresponding tag files under /run/udev/tag/, ignoring: %m");
- r = udev_watch_end(inotify_fd, dev);
- if (r < 0)
- log_device_warning_errno(dev, r, "Failed to remove inotify watch, ignoring: %m");
+ r = device_delete_db(dev);
+ if (r < 0)
+ log_device_debug_errno(dev, r, "Failed to delete database under /run/udev/data/, ignoring: %m");
+ }
- r = udev_rules_apply_to_event(rules, event, timeout_usec, timeout_signal, properties_list);
+ r = udev_rules_apply_to_event(rules, event);
- if (sd_device_get_devnum(dev, NULL) >= 0)
- (void) udev_node_remove(dev);
+ if (EVENT_MODE_DESTRUCTIVE(event)) {
+ if (sd_device_get_devnum(dev, NULL) >= 0)
+ (void) udev_node_remove(dev);
+ }
return r;
}
@@ -328,19 +338,45 @@ static int copy_all_tags(sd_device *d, sd_device *s) {
return 0;
}
-int udev_event_execute_rules(
- UdevEvent *event,
- int inotify_fd, /* This may be negative */
- usec_t timeout_usec,
- int timeout_signal,
- Hashmap *properties_list,
- UdevRules *rules) {
+static int update_clone(UdevEvent *event) {
+ sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev_db_clone);
+ int r;
+
+ if (!EVENT_MODE_DESTRUCTIVE(event))
+ return 0;
+
+ /* Drop previously added property for safety to make IMPORT{db}="ID_RENAMING" not work. This is
+ * mostly for 'move' uevent, but let's do unconditionally. Why? If a network interface is renamed in
+ * initrd, then udevd may lose the 'move' uevent during switching root. Usually, we do not set the
+ * persistent flag for network interfaces, but user may set it. Just for safety. */
+ r = device_add_property(dev, "ID_RENAMING", NULL);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to remove 'ID_RENAMING' property: %m");
+
+ /* If the database file already exists, append ID_PROCESSING property to the existing database,
+ * to indicate that the device is being processed by udevd. */
+ if (device_has_db(dev) > 0) {
+ r = device_add_property(dev, "ID_PROCESSING", "1");
+ if (r < 0)
+ return log_device_warning_errno(dev, r, "Failed to add 'ID_PROCESSING' property: %m");
+
+ r = device_update_db(dev);
+ if (r < 0)
+ return log_device_warning_errno(dev, r, "Failed to update database under /run/udev/data/: %m");
+ }
+
+ return 0;
+}
+
+int udev_event_execute_rules(UdevEvent *event, UdevRules *rules) {
sd_device_action_t action;
sd_device *dev;
int r;
- dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+ assert(event);
+ assert(IN_SET(event->event_mode, EVENT_UDEV_WORKER, EVENT_UDEVADM_TEST, EVENT_TEST_RULE_RUNNER));
+ dev = ASSERT_PTR(event->dev);
assert(rules);
r = sd_device_get_action(dev, &action);
@@ -348,12 +384,7 @@ int udev_event_execute_rules(
return log_device_error_errno(dev, r, "Failed to get ACTION: %m");
if (action == SD_DEVICE_REMOVE)
- return event_execute_rules_on_remove(event, inotify_fd, timeout_usec, timeout_signal, properties_list, rules);
-
- /* Disable watch during event processing. */
- r = udev_watch_end(inotify_fd, dev);
- if (r < 0)
- log_device_warning_errno(dev, r, "Failed to remove inotify watch, ignoring: %m");
+ return event_execute_rules_on_remove(event, rules);
r = device_clone_with_db(dev, &event->dev_db_clone);
if (r < 0)
@@ -363,17 +394,13 @@ int udev_event_execute_rules(
if (r < 0)
log_device_warning_errno(dev, r, "Failed to copy all tags from old database entry, ignoring: %m");
- /* Drop previously added property for safety to make IMPORT{db}="ID_RENAMING" not work. This is
- * mostly for 'move' uevent, but let's do unconditionally. Why? If a network interface is renamed in
- * initrd, then udevd may lose the 'move' uevent during switching root. Usually, we do not set the
- * persistent flag for network interfaces, but user may set it. Just for safety. */
- r = device_add_property(event->dev_db_clone, "ID_RENAMING", NULL);
+ r = update_clone(event);
if (r < 0)
- return log_device_debug_errno(dev, r, "Failed to remove 'ID_RENAMING' property: %m");
+ return r;
DEVICE_TRACE_POINT(rules_start, dev);
- r = udev_rules_apply_to_event(rules, event, timeout_usec, timeout_signal, properties_list);
+ r = udev_rules_apply_to_event(rules, event);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to apply udev rules: %m");
@@ -396,14 +423,27 @@ int udev_event_execute_rules(
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to set initialization timestamp: %m");
- /* (re)write database file */
- r = device_tag_index(dev, event->dev_db_clone, true);
- if (r < 0)
- return log_device_debug_errno(dev, r, "Failed to update tags under /run/udev/tag/: %m");
+ if (EVENT_MODE_DESTRUCTIVE(event)) {
+ /* (re)write database file */
+ r = device_tag_index(dev, event->dev_db_clone, true);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to update tags under /run/udev/tag/: %m");
+ }
- r = device_update_db(dev);
- if (r < 0)
- return log_device_debug_errno(dev, r, "Failed to update database under /run/udev/data/: %m");
+ /* If the database file for the device will be created below, add ID_PROCESSING=1 to indicate that
+ * the device is still being processed by udevd, as commands specified in RUN are invoked after
+ * the database is created. See issue #30056. */
+ if (device_should_have_db(dev) && !ordered_hashmap_isempty(event->run_list)) {
+ r = device_add_property(dev, "ID_PROCESSING", "1");
+ if (r < 0)
+ return log_device_warning_errno(dev, r, "Failed to add 'ID_PROCESSING' property: %m");
+ }
+
+ if (EVENT_MODE_DESTRUCTIVE(event)) {
+ r = device_update_db(dev);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to update database under /run/udev/data/: %m");
+ }
device_set_is_initialized(dev);
diff --git a/src/udev/udev-event.h b/src/udev/udev-event.h
index 6b94fd0..3dc8936 100644
--- a/src/udev/udev-event.h
+++ b/src/udev/udev-event.h
@@ -15,9 +15,21 @@
#include "macro.h"
#include "time-util.h"
#include "udev-rules.h"
+#include "udev-worker.h"
#include "user-util.h"
+typedef enum EventMode {
+ EVENT_UDEV_WORKER,
+ EVENT_UDEVADM_TEST,
+ EVENT_UDEVADM_TEST_BUILTIN,
+ EVENT_TEST_RULE_RUNNER,
+ EVENT_TEST_SPAWN,
+} EventMode;
+
typedef struct UdevEvent {
+ UdevWorker *worker;
+ sd_netlink *rtnl;
+
sd_device *dev;
sd_device *dev_parent;
sd_device *dev_db_clone;
@@ -29,9 +41,7 @@ typedef struct UdevEvent {
gid_t gid;
OrderedHashmap *seclabel_list;
OrderedHashmap *run_list;
- usec_t exec_delay_usec;
usec_t birth_usec;
- sd_netlink *rtnl;
unsigned builtin_run;
unsigned builtin_ret;
UdevRuleEscapeType esc:8;
@@ -45,16 +55,16 @@ typedef struct UdevEvent {
bool run_final;
bool log_level_was_debug;
int default_log_level;
+ EventMode event_mode;
} UdevEvent;
-UdevEvent *udev_event_new(sd_device *dev, usec_t exec_delay_usec, sd_netlink *rtnl, int log_level);
+UdevEvent *udev_event_new(sd_device *dev, UdevWorker *worker, EventMode mode);
UdevEvent *udev_event_free(UdevEvent *event);
DEFINE_TRIVIAL_CLEANUP_FUNC(UdevEvent*, udev_event_free);
-int udev_event_execute_rules(
- UdevEvent *event,
- int inotify_fd,
- usec_t timeout_usec,
- int timeout_signal,
- Hashmap *properties_list,
- UdevRules *rules);
+int udev_event_execute_rules(UdevEvent *event, UdevRules *rules);
+
+static inline bool EVENT_MODE_DESTRUCTIVE(UdevEvent *event) {
+ assert(event);
+ return IN_SET(event->event_mode, EVENT_UDEV_WORKER, EVENT_TEST_RULE_RUNNER);
+}
diff --git a/src/udev/udev-format.c b/src/udev/udev-format.c
index 05ed9fd..bd74ab0 100644
--- a/src/udev/udev-format.c
+++ b/src/udev/udev-format.c
@@ -156,7 +156,6 @@ static ssize_t udev_event_subst_format(
const char *attr,
char *dest,
size_t l,
- Hashmap *global_props,
bool *ret_truncated) {
sd_device *parent, *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
@@ -349,7 +348,7 @@ static ssize_t udev_event_subst_format(
case FORMAT_SUBST_ENV:
if (isempty(attr))
return -EINVAL;
- r = device_get_property_value_with_fallback(dev, attr, global_props, &val);
+ r = device_get_property_value_with_fallback(dev, attr, event->worker ? event->worker->properties : NULL, &val);
if (r == -ENOENT)
goto null_terminate;
if (r < 0)
@@ -379,7 +378,6 @@ size_t udev_event_apply_format(
char *dest,
size_t size,
bool replace_whitespace,
- Hashmap *global_props,
bool *ret_truncated) {
bool truncated = false;
@@ -412,7 +410,7 @@ size_t udev_event_apply_format(
continue;
}
- subst_len = udev_event_subst_format(event, type, attr, dest, size, global_props, &t);
+ subst_len = udev_event_subst_format(event, type, attr, dest, size, &t);
if (subst_len < 0) {
log_device_warning_errno(event->dev, subst_len,
"Failed to substitute variable '$%s' or apply format '%%%c', ignoring: %m",
diff --git a/src/udev/udev-format.h b/src/udev/udev-format.h
index 92fef9b..9914dc0 100644
--- a/src/udev/udev-format.h
+++ b/src/udev/udev-format.h
@@ -14,7 +14,6 @@ size_t udev_event_apply_format(
char *dest,
size_t size,
bool replace_whitespace,
- Hashmap *global_props,
bool *ret_truncated);
int udev_check_format(const char *value, size_t *offset, const char **hint);
diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c
index 8077e51..bb94478 100644
--- a/src/udev/udev-manager.c
+++ b/src/udev/udev-manager.c
@@ -274,15 +274,9 @@ static void manager_reload(Manager *manager, bool force) {
return;
/* If we eat this up, then tell our service manager to just continue */
- (void) sd_notifyf(/* unset= */ false,
- "RELOADING=1\n"
- "STATUS=Skipping configuration reloading, nothing changed.\n"
- "MONOTONIC_USEC=" USEC_FMT, now(CLOCK_MONOTONIC));
+ (void) notify_reloading_full("Skipping configuration reloading, nothing changed.");
} else {
- (void) sd_notifyf(/* unset= */ false,
- "RELOADING=1\n"
- "STATUS=Flushing configuration...\n"
- "MONOTONIC_USEC=" USEC_FMT, now(CLOCK_MONOTONIC));
+ (void) notify_reloading();
manager_kill_workers(manager, false);
@@ -332,12 +326,38 @@ static int on_event_timeout_warning(sd_event_source *s, uint64_t usec, void *use
return 1;
}
+static usec_t extra_timeout_usec(void) {
+ static usec_t saved = 10 * USEC_PER_SEC;
+ static bool parsed = false;
+ usec_t timeout;
+ const char *e;
+ int r;
+
+ if (parsed)
+ return saved;
+
+ parsed = true;
+
+ e = getenv("SYSTEMD_UDEV_EXTRA_TIMEOUT_SEC");
+ if (!e)
+ return saved;
+
+ r = parse_sec(e, &timeout);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse $SYSTEMD_UDEV_EXTRA_TIMEOUT_SEC=%s, ignoring: %m", e);
+
+ if (timeout > 5 * USEC_PER_HOUR) /* Add an arbitrary upper bound */
+ log_debug("Parsed $SYSTEMD_UDEV_EXTRA_TIMEOUT_SEC=%s is too large, ignoring.", e);
+ else
+ saved = timeout;
+
+ return saved;
+}
+
static void worker_attach_event(Worker *worker, Event *event) {
- Manager *manager;
- sd_event *e;
+ Manager *manager = ASSERT_PTR(ASSERT_PTR(worker)->manager);
+ sd_event *e = ASSERT_PTR(manager->event);
- assert(worker);
- assert(worker->manager);
assert(event);
assert(!event->worker);
assert(!worker->event);
@@ -347,15 +367,16 @@ static void worker_attach_event(Worker *worker, Event *event) {
event->state = EVENT_RUNNING;
event->worker = worker;
- manager = worker->manager;
- e = manager->event;
-
(void) sd_event_add_time_relative(e, &event->timeout_warning_event, CLOCK_MONOTONIC,
udev_warn_timeout(manager->timeout_usec), USEC_PER_SEC,
on_event_timeout_warning, event);
+ /* Manager.timeout_usec is also used as the timeout for running programs specified in
+ * IMPORT{program}=, PROGRAM=, or RUN=. Here, let's add an extra time before the manager
+ * kills a worker, to make it possible that the worker detects timed out of spawned programs,
+ * kills them, and finalizes the event. */
(void) sd_event_add_time_relative(e, &event->timeout_event, CLOCK_MONOTONIC,
- manager->timeout_usec, USEC_PER_SEC,
+ usec_add(manager->timeout_usec, extra_timeout_usec()), USEC_PER_SEC,
on_event_timeout, event);
}
@@ -864,7 +885,7 @@ static int on_ctrl_msg(UdevCtrl *uctrl, UdevCtrlMessageType type, const UdevCtrl
switch (type) {
case UDEV_CTRL_SET_LOG_LEVEL:
- if ((value->intval & LOG_PRIMASK) != value->intval) {
+ if (LOG_PRI(value->intval) != value->intval) {
log_debug("Received invalid udev control message (SET_LOG_LEVEL, %i), ignoring.", value->intval);
break;
}
@@ -1194,13 +1215,33 @@ Manager* manager_new(void) {
.worker_watch = EBADF_PAIR,
.log_level = LOG_INFO,
.resolve_name_timing = RESOLVE_NAME_EARLY,
- .timeout_usec = 180 * USEC_PER_SEC,
+ .timeout_usec = DEFAULT_WORKER_TIMEOUT_USEC,
.timeout_signal = SIGKILL,
};
return manager;
}
+void manager_adjust_arguments(Manager *manager) {
+ assert(manager);
+
+ if (manager->timeout_usec < MIN_WORKER_TIMEOUT_USEC) {
+ log_debug("Timeout (%s) for processing event is too small, using the default: %s",
+ FORMAT_TIMESPAN(manager->timeout_usec, 1),
+ FORMAT_TIMESPAN(DEFAULT_WORKER_TIMEOUT_USEC, 1));
+
+ manager->timeout_usec = DEFAULT_WORKER_TIMEOUT_USEC;
+ }
+
+ if (manager->exec_delay_usec >= manager->timeout_usec) {
+ log_debug("Delay (%s) for executing RUN= commands is too large compared with the timeout (%s) for event execution, ignoring the delay.",
+ FORMAT_TIMESPAN(manager->exec_delay_usec, 1),
+ FORMAT_TIMESPAN(manager->timeout_usec, 1));
+
+ manager->exec_delay_usec = 0;
+ }
+}
+
int manager_init(Manager *manager, int fd_ctrl, int fd_uevent) {
_cleanup_free_ char *cgroup = NULL;
int r;
@@ -1260,22 +1301,22 @@ int manager_main(Manager *manager) {
udev_watch_restore(manager->inotify_fd);
- /* block and listen to all signals on signalfd */
- assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD, SIGRTMIN+18, -1) >= 0);
+ /* block SIGCHLD for listening child events. */
+ assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
r = sd_event_default(&manager->event);
if (r < 0)
return log_error_errno(r, "Failed to allocate event loop: %m");
- r = sd_event_add_signal(manager->event, NULL, SIGINT, on_sigterm, manager);
+ r = sd_event_add_signal(manager->event, NULL, SIGINT | SD_EVENT_SIGNAL_PROCMASK, on_sigterm, manager);
if (r < 0)
return log_error_errno(r, "Failed to create SIGINT event source: %m");
- r = sd_event_add_signal(manager->event, NULL, SIGTERM, on_sigterm, manager);
+ r = sd_event_add_signal(manager->event, NULL, SIGTERM | SD_EVENT_SIGNAL_PROCMASK, on_sigterm, manager);
if (r < 0)
return log_error_errno(r, "Failed to create SIGTERM event source: %m");
- r = sd_event_add_signal(manager->event, NULL, SIGHUP, on_sighup, manager);
+ r = sd_event_add_signal(manager->event, NULL, SIGHUP | SD_EVENT_SIGNAL_PROCMASK, on_sighup, manager);
if (r < 0)
return log_error_errno(r, "Failed to create SIGHUP event source: %m");
@@ -1325,7 +1366,8 @@ int manager_main(Manager *manager) {
log_full_errno(ERRNO_IS_NOT_SUPPORTED(r) || ERRNO_IS_PRIVILEGE(r) || (r == -EHOSTDOWN) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to allocate memory pressure watch, ignoring: %m");
- r = sd_event_add_signal(manager->event, &manager->memory_pressure_event_source, SIGRTMIN+18, sigrtmin18_handler, NULL);
+ r = sd_event_add_signal(manager->event, &manager->memory_pressure_event_source,
+ (SIGRTMIN+18) | SD_EVENT_SIGNAL_PROCMASK, sigrtmin18_handler, NULL);
if (r < 0)
return log_error_errno(r, "Failed to allocate SIGRTMIN+18 event source, ignoring: %m");
diff --git a/src/udev/udev-manager.h b/src/udev/udev-manager.h
index afbc67f..864fc02 100644
--- a/src/udev/udev-manager.h
+++ b/src/udev/udev-manager.h
@@ -56,6 +56,7 @@ Manager* manager_new(void);
Manager* manager_free(Manager *manager);
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
+void manager_adjust_arguments(Manager *manager);
int manager_init(Manager *manager, int fd_ctrl, int fd_uevent);
int manager_main(Manager *manager);
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index e12c26c..633fb2a 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -510,22 +510,17 @@ static int link_update(sd_device *dev, const char *slink, bool add) {
}
static int device_get_devpath_by_devnum(sd_device *dev, char **ret) {
- const char *subsystem;
dev_t devnum;
int r;
assert(dev);
assert(ret);
- r = sd_device_get_subsystem(dev, &subsystem);
- if (r < 0)
- return r;
-
r = sd_device_get_devnum(dev, &devnum);
if (r < 0)
return r;
- return device_path_make_major_minor(streq(subsystem, "block") ? S_IFBLK : S_IFCHR, devnum, ret);
+ return device_path_make_major_minor(device_in_subsystem(dev, "block") ? S_IFBLK : S_IFCHR, devnum, ret);
}
int udev_node_update(sd_device *dev, sd_device *dev_old) {
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
index 5f12002..581bbaf 100644
--- a/src/udev/udev-rules.c
+++ b/src/udev/udev-rules.c
@@ -691,9 +691,7 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude
}
if (!is_match) {
- if (STR_IN_SET(attr,
- "ACTION", "DEVLINKS", "DEVNAME", "DEVPATH", "DEVTYPE", "DRIVER",
- "IFINDEX", "MAJOR", "MINOR", "SEQNUM", "SUBSYSTEM", "TAGS"))
+ if (!device_property_can_set(attr))
return log_line_error_errno(rule_line, SYNTHETIC_ERRNO(EINVAL),
"Invalid ENV attribute. '%s' cannot be set.", attr);
@@ -1538,7 +1536,7 @@ int udev_rules_parse_file(UdevRules *rules, const char *filename, bool extra_che
r = hashmap_put_stats_by_path(&rules->stats_by_path, filename, &st);
if (r < 0)
- return log_warning_errno(errno, "Failed to save stat for %s, ignoring: %m", filename);
+ return log_warning_errno(r, "Failed to save stat for %s, ignoring: %m", filename);
(void) fd_warn_permissions(filename, fileno(f));
@@ -1761,7 +1759,7 @@ static bool token_match_attr(UdevRuleToken *token, sd_device *dev, UdevEvent *ev
switch (token->attr_subst_type) {
case SUBST_TYPE_FORMAT:
- (void) udev_event_apply_format(event, name, nbuf, sizeof(nbuf), false, NULL, &truncated);
+ (void) udev_event_apply_format(event, name, nbuf, sizeof(nbuf), false, &truncated);
if (truncated) {
log_event_truncated(dev, token, "sysfs attribute name", name,
token->type == TK_M_ATTR ? "ATTR" : "ATTRS", /* is_match = */ true);
@@ -1928,10 +1926,7 @@ static size_t udev_replace_ifname(char *str) {
static int udev_rule_apply_token_to_event(
UdevRuleToken *token,
sd_device *dev,
- UdevEvent *event,
- usec_t timeout_usec,
- int timeout_signal,
- Hashmap *properties_list) {
+ UdevEvent *event) {
int r;
@@ -1983,7 +1978,7 @@ static int udev_rule_apply_token_to_event(
case TK_M_ENV: {
const char *val = NULL;
- (void) device_get_property_value_with_fallback(dev, token->data, properties_list, &val);
+ (void) device_get_property_value_with_fallback(dev, token->data, event->worker ? event->worker->properties : NULL, &val);
return token_match_string(token, val);
}
@@ -2038,7 +2033,7 @@ static int udev_rule_apply_token_to_event(
char buf[UDEV_PATH_SIZE];
bool truncated;
- (void) udev_event_apply_format(event, token->data, buf, sizeof(buf), false, properties_list, &truncated);
+ (void) udev_event_apply_format(event, token->data, buf, sizeof(buf), false, &truncated);
if (truncated) {
log_event_truncated(dev, token, "sysctl entry name", token->data, "SYSCTL", /* is_match = */ true);
return false;
@@ -2056,7 +2051,7 @@ static int udev_rule_apply_token_to_event(
struct stat statbuf;
bool match, truncated;
- (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, properties_list, &truncated);
+ (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
if (truncated) {
log_event_truncated(dev, token, "file name", token->value, "TEST", /* is_match = */ true);
return false;
@@ -2099,15 +2094,15 @@ static int udev_rule_apply_token_to_event(
size_t count;
event->program_result = mfree(event->program_result);
- (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, properties_list, &truncated);
+ (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
if (truncated) {
log_event_truncated(dev, token, "command", token->value, "PROGRAM", /* is_match = */ true);
return false;
}
- log_event_debug(dev, token, "Running PROGRAM '%s'", buf);
+ log_event_debug(dev, token, "Running PROGRAM=\"%s\"", buf);
- r = udev_event_spawn(event, timeout_usec, timeout_signal, true, buf, result, sizeof(result), NULL);
+ r = udev_event_spawn(event, /* accept_failure = */ true, buf, result, sizeof(result), NULL);
if (r != 0) {
if (r < 0)
log_event_warning_errno(dev, token, r, "Failed to execute \"%s\": %m", buf);
@@ -2131,7 +2126,7 @@ static int udev_rule_apply_token_to_event(
char buf[UDEV_PATH_SIZE];
bool truncated;
- (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, properties_list, &truncated);
+ (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
if (truncated) {
log_event_truncated(dev, token, "file name to be imported", token->value, "IMPORT", /* is_match = */ true);
return false;
@@ -2182,7 +2177,7 @@ static int udev_rule_apply_token_to_event(
char buf[UDEV_LINE_SIZE], result[UDEV_LINE_SIZE];
bool truncated;
- (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, properties_list, &truncated);
+ (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
if (truncated) {
log_event_truncated(dev, token, "command", token->value, "IMPORT", /* is_match = */ true);
return false;
@@ -2190,7 +2185,7 @@ static int udev_rule_apply_token_to_event(
log_event_debug(dev, token, "Importing properties from results of '%s'", buf);
- r = udev_event_spawn(event, timeout_usec, timeout_signal, true, buf, result, sizeof result, &truncated);
+ r = udev_event_spawn(event, /* accept_failure = */ true, buf, result, sizeof result, &truncated);
if (r != 0) {
if (r < 0)
log_event_warning_errno(dev, token, r, "Failed to execute '%s', ignoring: %m", buf);
@@ -2261,7 +2256,7 @@ static int udev_rule_apply_token_to_event(
event->builtin_run |= mask;
}
- (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, properties_list, &truncated);
+ (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
if (truncated) {
log_event_truncated(dev, token, "builtin command", token->value, "IMPORT", /* is_match = */ true);
return false;
@@ -2269,7 +2264,7 @@ static int udev_rule_apply_token_to_event(
log_event_debug(dev, token, "Importing properties from results of builtin command '%s'", buf);
- r = udev_builtin_run(event, cmd, buf, false);
+ r = udev_builtin_run(event, cmd, buf);
if (r < 0) {
/* remember failure */
log_event_debug_errno(dev, token, r, "Failed to run builtin '%s': %m", buf);
@@ -2317,7 +2312,7 @@ static int udev_rule_apply_token_to_event(
char buf[UDEV_PATH_SIZE];
bool truncated;
- (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, properties_list, &truncated);
+ (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
if (truncated) {
log_event_truncated(dev, token, "property name", token->value, "IMPORT", /* is_match = */ true);
return false;
@@ -2378,7 +2373,7 @@ static int udev_rule_apply_token_to_event(
if (token->op == OP_ASSIGN_FINAL)
event->owner_final = true;
- (void) udev_event_apply_format(event, token->value, owner, sizeof(owner), false, properties_list, &truncated);
+ (void) udev_event_apply_format(event, token->value, owner, sizeof(owner), false, &truncated);
if (truncated) {
log_event_truncated(dev, token, "user name", token->value, "OWNER", /* is_match = */ false);
break;
@@ -2401,7 +2396,7 @@ static int udev_rule_apply_token_to_event(
if (token->op == OP_ASSIGN_FINAL)
event->group_final = true;
- (void) udev_event_apply_format(event, token->value, group, sizeof(group), false, properties_list, &truncated);
+ (void) udev_event_apply_format(event, token->value, group, sizeof(group), false, &truncated);
if (truncated) {
log_event_truncated(dev, token, "group name", token->value, "GROUP", /* is_match = */ false);
break;
@@ -2423,7 +2418,7 @@ static int udev_rule_apply_token_to_event(
if (token->op == OP_ASSIGN_FINAL)
event->mode_final = true;
- (void) udev_event_apply_format(event, token->value, mode_str, sizeof(mode_str), false, properties_list, &truncated);
+ (void) udev_event_apply_format(event, token->value, mode_str, sizeof(mode_str), false, &truncated);
if (truncated) {
log_event_truncated(dev, token, "mode", token->value, "MODE", /* is_match = */ false);
break;
@@ -2475,7 +2470,7 @@ static int udev_rule_apply_token_to_event(
if (!name)
return log_oom();
- (void) udev_event_apply_format(event, token->value, label_str, sizeof(label_str), false, properties_list, &truncated);
+ (void) udev_event_apply_format(event, token->value, label_str, sizeof(label_str), false, &truncated);
if (truncated) {
log_event_truncated(dev, token, "security label", token->value, "SECLABEL", /* is_match = */ false);
break;
@@ -2519,7 +2514,7 @@ static int udev_rule_apply_token_to_event(
}
if (token->op == OP_ADD &&
- device_get_property_value_with_fallback(dev, name, properties_list, &val) >= 0) {
+ device_get_property_value_with_fallback(dev, name, event->worker ? event->worker->properties : NULL, &val) >= 0) {
l = strpcpyl_full(&p, l, &truncated, val, " ", NULL);
if (truncated) {
log_event_warning(dev, token,
@@ -2529,7 +2524,7 @@ static int udev_rule_apply_token_to_event(
}
}
- (void) udev_event_apply_format(event, token->value, p, l, false, properties_list, &truncated);
+ (void) udev_event_apply_format(event, token->value, p, l, false, &truncated);
if (truncated) {
_cleanup_free_ char *key_with_name = strjoin("ENV{", name, "}");
log_event_truncated(dev, token, "property value", token->value,
@@ -2554,7 +2549,7 @@ static int udev_rule_apply_token_to_event(
char buf[UDEV_PATH_SIZE];
bool truncated;
- (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, properties_list, &truncated);
+ (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
if (truncated) {
log_event_truncated(dev, token, "tag name", token->value, "TAG", /* is_match = */ false);
break;
@@ -2591,7 +2586,7 @@ static int udev_rule_apply_token_to_event(
break;
}
- (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, properties_list, &truncated);
+ (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
if (truncated) {
log_event_truncated(dev, token, "network interface name", token->value, "NAME", /* is_match = */ false);
break;
@@ -2629,7 +2624,7 @@ static int udev_rule_apply_token_to_event(
device_cleanup_devlinks(dev);
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf),
- /* replace_whitespace = */ event->esc != ESCAPE_NONE, properties_list, &truncated);
+ /* replace_whitespace = */ event->esc != ESCAPE_NONE, &truncated);
if (truncated) {
log_event_truncated(dev, token, "symbolic link path", token->value, "SYMLINK", /* is_match = */ false);
break;
@@ -2701,33 +2696,37 @@ static int udev_rule_apply_token_to_event(
log_event_error_errno(dev, token, r, "Could not find file matches '%s', ignoring: %m", buf);
break;
}
- (void) udev_event_apply_format(event, token->value, value, sizeof(value), false, properties_list, &truncated);
+ (void) udev_event_apply_format(event, token->value, value, sizeof(value), false, &truncated);
if (truncated) {
log_event_truncated(dev, token, "attribute value", token->value, "ATTR", /* is_match = */ false);
break;
}
- log_event_debug(dev, token, "ATTR '%s' writing '%s'", buf, value);
- r = write_string_file(buf, value,
- WRITE_STRING_FILE_VERIFY_ON_FAILURE |
- WRITE_STRING_FILE_DISABLE_BUFFER |
- WRITE_STRING_FILE_AVOID_NEWLINE |
- WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE);
- if (r < 0)
- log_event_error_errno(dev, token, r, "Failed to write ATTR{%s}, ignoring: %m", buf);
+ if (EVENT_MODE_DESTRUCTIVE(event)) {
+ log_event_debug(dev, token, "Writing ATTR{'%s'}=\"%s\".", buf, value);
+ r = write_string_file(buf, value,
+ WRITE_STRING_FILE_VERIFY_ON_FAILURE |
+ WRITE_STRING_FILE_DISABLE_BUFFER |
+ WRITE_STRING_FILE_AVOID_NEWLINE |
+ WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE);
+ if (r < 0)
+ log_event_error_errno(dev, token, r, "Failed to write ATTR{%s}=\"%s\", ignoring: %m", buf, value);
+ } else
+ log_event_debug(dev, token, "Running in test mode, skipping writing ATTR{%s}=\"%s\".", buf, value);
+
break;
}
case TK_A_SYSCTL: {
char buf[UDEV_PATH_SIZE], value[UDEV_NAME_SIZE];
bool truncated;
- (void) udev_event_apply_format(event, token->data, buf, sizeof(buf), false, properties_list, &truncated);
+ (void) udev_event_apply_format(event, token->data, buf, sizeof(buf), false, &truncated);
if (truncated) {
log_event_truncated(dev, token, "sysctl entry name", token->data, "SYSCTL", /* is_match = */ false);
break;
}
- (void) udev_event_apply_format(event, token->value, value, sizeof(value), false, properties_list, &truncated);
+ (void) udev_event_apply_format(event, token->value, value, sizeof(value), false, &truncated);
if (truncated) {
_cleanup_free_ char *key_with_name = strjoin("SYSCTL{", buf, "}");
log_event_truncated(dev, token, "sysctl value", token->value,
@@ -2736,10 +2735,15 @@ static int udev_rule_apply_token_to_event(
}
sysctl_normalize(buf);
- log_event_debug(dev, token, "SYSCTL '%s' writing '%s'", buf, value);
- r = sysctl_write(buf, value);
- if (r < 0)
- log_event_error_errno(dev, token, r, "Failed to write SYSCTL{%s}='%s', ignoring: %m", buf, value);
+
+ if (EVENT_MODE_DESTRUCTIVE(event)) {
+ log_event_debug(dev, token, "Writing SYSCTL{%s}=\"%s\".", buf, value);
+ r = sysctl_write(buf, value);
+ if (r < 0)
+ log_event_error_errno(dev, token, r, "Failed to write SYSCTL{%s}=\"%s\", ignoring: %m", buf, value);
+ } else
+ log_event_debug(dev, token, "Running in test mode, skipping writing SYSCTL{%s}=\"%s\".", buf, value);
+
break;
}
case TK_A_RUN_BUILTIN:
@@ -2756,7 +2760,7 @@ static int udev_rule_apply_token_to_event(
if (IN_SET(token->op, OP_ASSIGN, OP_ASSIGN_FINAL))
ordered_hashmap_clear_free_key(event->run_list);
- (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, properties_list, &truncated);
+ (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
if (truncated) {
log_event_truncated(dev, token, "command", token->value,
token->type == TK_A_RUN_BUILTIN ? "RUN{builtin}" : "RUN{program}",
@@ -2793,11 +2797,7 @@ static bool token_is_for_parents(UdevRuleToken *token) {
return token->type >= TK_M_PARENTS_KERNEL && token->type <= TK_M_PARENTS_TAG;
}
-static int udev_rule_apply_parent_token_to_event(
- UdevRuleToken *head_token,
- UdevEvent *event,
- int timeout_signal) {
-
+static int udev_rule_apply_parent_token_to_event(UdevRuleToken *head_token, UdevEvent *event) {
int r;
assert(head_token);
@@ -2810,7 +2810,7 @@ static int udev_rule_apply_parent_token_to_event(
if (!token_is_for_parents(token))
return true; /* All parent tokens match. */
- r = udev_rule_apply_token_to_event(token, event->dev_parent, event, 0, timeout_signal, NULL);
+ r = udev_rule_apply_token_to_event(token, event->dev_parent, event);
if (r < 0)
return r;
if (r == 0)
@@ -2830,9 +2830,6 @@ static int udev_rule_apply_parent_token_to_event(
static int udev_rule_apply_line_to_event(
UdevRuleLine *line,
UdevEvent *event,
- usec_t timeout_usec,
- int timeout_signal,
- Hashmap *properties_list,
UdevRuleLine **next_line) {
UdevRuleLineType mask = LINE_HAS_GOTO | LINE_UPDATE_SOMETHING;
@@ -2868,7 +2865,7 @@ static int udev_rule_apply_line_to_event(
if (parents_done)
continue;
- r = udev_rule_apply_parent_token_to_event(token, event, timeout_signal);
+ r = udev_rule_apply_parent_token_to_event(token, event);
if (r <= 0)
return r;
@@ -2876,7 +2873,7 @@ static int udev_rule_apply_line_to_event(
continue;
}
- r = udev_rule_apply_token_to_event(token, event->dev, event, timeout_usec, timeout_signal, properties_list);
+ r = udev_rule_apply_token_to_event(token, event->dev, event);
if (r <= 0)
return r;
}
@@ -2887,13 +2884,7 @@ static int udev_rule_apply_line_to_event(
return 0;
}
-int udev_rules_apply_to_event(
- UdevRules *rules,
- UdevEvent *event,
- usec_t timeout_usec,
- int timeout_signal,
- Hashmap *properties_list) {
-
+int udev_rules_apply_to_event(UdevRules *rules, UdevEvent *event) {
int r;
assert(rules);
@@ -2901,7 +2892,7 @@ int udev_rules_apply_to_event(
LIST_FOREACH(rule_files, file, rules->rule_files)
LIST_FOREACH_WITH_NEXT(rule_lines, line, next_line, file->rule_lines) {
- r = udev_rule_apply_line_to_event(line, event, timeout_usec, timeout_signal, properties_list, &next_line);
+ r = udev_rule_apply_line_to_event(line, event, &next_line);
if (r < 0)
return r;
}
diff --git a/src/udev/udev-rules.h b/src/udev/udev-rules.h
index 4352312..9d19c80 100644
--- a/src/udev/udev-rules.h
+++ b/src/udev/udev-rules.h
@@ -39,10 +39,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(UdevRules*, udev_rules_free);
#define udev_rules_free_and_replace(a, b) free_and_replace_full(a, b, udev_rules_free)
bool udev_rules_should_reload(UdevRules *rules);
-int udev_rules_apply_to_event(UdevRules *rules, UdevEvent *event,
- usec_t timeout_usec,
- int timeout_signal,
- Hashmap *properties_list);
+int udev_rules_apply_to_event(UdevRules *rules, UdevEvent *event);
int udev_rules_apply_static_dev_perms(UdevRules *rules);
ResolveNameTiming resolve_name_timing_from_string(const char *s) _pure_;
diff --git a/src/udev/udev-spawn.c b/src/udev/udev-spawn.c
index 67a3005..3f867a8 100644
--- a/src/udev/udev-spawn.c
+++ b/src/udev/udev-spawn.c
@@ -23,6 +23,7 @@ typedef struct Spawn {
usec_t timeout_usec;
int timeout_signal;
usec_t event_birth_usec;
+ usec_t cmd_birth_usec;
bool accept_failure;
int fd_stdout;
int fd_stderr;
@@ -105,19 +106,18 @@ static int on_spawn_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
DEVICE_TRACE_POINT(spawn_timeout, spawn->device, spawn->cmd);
- kill_and_sigcont(spawn->pid, spawn->timeout_signal);
-
- log_device_error(spawn->device, "Spawned process '%s' ["PID_FMT"] timed out after %s, killing",
+ log_device_error(spawn->device, "Spawned process '%s' ["PID_FMT"] timed out after %s, killing.",
spawn->cmd, spawn->pid,
FORMAT_TIMESPAN(spawn->timeout_usec, USEC_PER_SEC));
+ kill_and_sigcont(spawn->pid, spawn->timeout_signal);
return 1;
}
static int on_spawn_timeout_warning(sd_event_source *s, uint64_t usec, void *userdata) {
Spawn *spawn = ASSERT_PTR(userdata);
- log_device_warning(spawn->device, "Spawned process '%s' ["PID_FMT"] is taking longer than %s to complete",
+ log_device_warning(spawn->device, "Spawned process '%s' ["PID_FMT"] is taking longer than %s to complete.",
spawn->cmd, spawn->pid,
FORMAT_TIMESPAN(spawn->timeout_warn_usec, USEC_PER_SEC));
@@ -164,31 +164,20 @@ static int spawn_wait(Spawn *spawn) {
if (r < 0)
return log_device_debug_errno(spawn->device, r, "Failed to allocate sd-event object: %m");
- if (spawn->timeout_usec > 0) {
- usec_t usec, age_usec;
-
- usec = now(CLOCK_MONOTONIC);
- age_usec = usec - spawn->event_birth_usec;
- if (age_usec < spawn->timeout_usec) {
- if (spawn->timeout_warn_usec > 0 &&
- spawn->timeout_warn_usec < spawn->timeout_usec &&
- spawn->timeout_warn_usec > age_usec) {
- spawn->timeout_warn_usec -= age_usec;
-
- r = sd_event_add_time(e, NULL, CLOCK_MONOTONIC,
- usec + spawn->timeout_warn_usec, USEC_PER_SEC,
- on_spawn_timeout_warning, spawn);
- if (r < 0)
- return log_device_debug_errno(spawn->device, r, "Failed to create timeout warning event source: %m");
- }
-
- spawn->timeout_usec -= age_usec;
-
+ if (spawn->timeout_usec != USEC_INFINITY) {
+ if (spawn->timeout_warn_usec < spawn->timeout_usec) {
r = sd_event_add_time(e, NULL, CLOCK_MONOTONIC,
- usec + spawn->timeout_usec, USEC_PER_SEC, on_spawn_timeout, spawn);
+ usec_add(spawn->cmd_birth_usec, spawn->timeout_warn_usec), USEC_PER_SEC,
+ on_spawn_timeout_warning, spawn);
if (r < 0)
- return log_device_debug_errno(spawn->device, r, "Failed to create timeout event source: %m");
+ return log_device_debug_errno(spawn->device, r, "Failed to create timeout warning event source: %m");
}
+
+ r = sd_event_add_time(e, NULL, CLOCK_MONOTONIC,
+ usec_add(spawn->cmd_birth_usec, spawn->timeout_usec), USEC_PER_SEC,
+ on_spawn_timeout, spawn);
+ if (r < 0)
+ return log_device_debug_errno(spawn->device, r, "Failed to create timeout event source: %m");
}
if (spawn->fd_stdout >= 0) {
@@ -222,8 +211,6 @@ static int spawn_wait(Spawn *spawn) {
int udev_event_spawn(
UdevEvent *event,
- usec_t timeout_usec,
- int timeout_signal,
bool accept_failure,
const char *cmd,
char *result,
@@ -238,9 +225,30 @@ int udev_event_spawn(
int r;
assert(event);
+ assert(IN_SET(event->event_mode, EVENT_UDEV_WORKER, EVENT_UDEVADM_TEST, EVENT_TEST_RULE_RUNNER, EVENT_TEST_SPAWN));
assert(event->dev);
+ assert(cmd);
assert(result || result_size == 0);
+ if (event->event_mode == EVENT_UDEVADM_TEST &&
+ !STARTSWITH_SET(cmd, "ata_id", "cdrom_id", "dmi_memory_id", "fido_id", "mtd_probe", "scsi_id")) {
+ log_device_debug(event->dev, "Running in test mode, skipping execution of '%s'.", cmd);
+ result[0] = '\0';
+ if (ret_truncated)
+ *ret_truncated = false;
+ return 0;
+ }
+
+ int timeout_signal = event->worker ? event->worker->timeout_signal : SIGKILL;
+ usec_t timeout_usec = event->worker ? event->worker->timeout_usec : DEFAULT_WORKER_TIMEOUT_USEC;
+ usec_t now_usec = now(CLOCK_MONOTONIC);
+ usec_t age_usec = usec_sub_unsigned(now_usec, event->birth_usec);
+ usec_t cmd_timeout_usec = usec_sub_unsigned(timeout_usec, age_usec);
+ if (cmd_timeout_usec <= 0)
+ return log_device_warning_errno(event->dev, SYNTHETIC_ERRNO(ETIME),
+ "The event already takes longer (%s) than the timeout (%s), skipping execution of '%s'.",
+ FORMAT_TIMESPAN(age_usec, 1), FORMAT_TIMESPAN(timeout_usec, 1), cmd);
+
/* pipes from child to parent */
if (result || log_get_max_level() >= LOG_INFO)
if (pipe2(outpipe, O_NONBLOCK|O_CLOEXEC) != 0)
@@ -300,10 +308,11 @@ int udev_event_spawn(
.cmd = cmd,
.pid = pid,
.accept_failure = accept_failure,
- .timeout_warn_usec = udev_warn_timeout(timeout_usec),
- .timeout_usec = timeout_usec,
+ .timeout_warn_usec = udev_warn_timeout(cmd_timeout_usec),
+ .timeout_usec = cmd_timeout_usec,
.timeout_signal = timeout_signal,
.event_birth_usec = event->birth_usec,
+ .cmd_birth_usec = now_usec,
.fd_stdout = outpipe[READ_END],
.fd_stderr = errpipe[READ_END],
.result = result,
@@ -323,29 +332,42 @@ int udev_event_spawn(
return r; /* 0 for success, and positive if the program failed */
}
-void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec, int timeout_signal) {
+void udev_event_execute_run(UdevEvent *event) {
const char *command;
void *val;
int r;
+ assert(event);
+
ORDERED_HASHMAP_FOREACH_KEY(val, command, event->run_list) {
UdevBuiltinCommand builtin_cmd = PTR_TO_UDEV_BUILTIN_CMD(val);
if (builtin_cmd != _UDEV_BUILTIN_INVALID) {
log_device_debug(event->dev, "Running built-in command \"%s\"", command);
- r = udev_builtin_run(event, builtin_cmd, command, false);
+ r = udev_builtin_run(event, builtin_cmd, command);
if (r < 0)
log_device_debug_errno(event->dev, r, "Failed to run built-in command \"%s\", ignoring: %m", command);
} else {
- if (event->exec_delay_usec > 0) {
+ if (event->worker && event->worker->exec_delay_usec > 0) {
+ usec_t timeout_usec = event->worker ? event->worker->timeout_usec : DEFAULT_WORKER_TIMEOUT_USEC;
+ usec_t now_usec = now(CLOCK_MONOTONIC);
+ usec_t age_usec = usec_sub_unsigned(now_usec, event->birth_usec);
+
+ if (event->worker->exec_delay_usec >= usec_sub_unsigned(timeout_usec, age_usec)) {
+ log_device_warning(event->dev,
+ "Cannot delaying execution of \"%s\" for %s, skipping.",
+ command, FORMAT_TIMESPAN(event->worker->exec_delay_usec, USEC_PER_SEC));
+ continue;
+ }
+
log_device_debug(event->dev, "Delaying execution of \"%s\" for %s.",
- command, FORMAT_TIMESPAN(event->exec_delay_usec, USEC_PER_SEC));
- (void) usleep_safe(event->exec_delay_usec);
+ command, FORMAT_TIMESPAN(event->worker->exec_delay_usec, USEC_PER_SEC));
+ (void) usleep_safe(event->worker->exec_delay_usec);
}
log_device_debug(event->dev, "Running command \"%s\"", command);
- r = udev_event_spawn(event, timeout_usec, timeout_signal, false, command, NULL, 0, NULL);
+ r = udev_event_spawn(event, /* accept_failure = */ false, command, NULL, 0, NULL);
if (r < 0)
log_device_warning_errno(event->dev, r, "Failed to execute '%s', ignoring: %m", command);
else if (r > 0) /* returned value is positive when program fails */
diff --git a/src/udev/udev-spawn.h b/src/udev/udev-spawn.h
index 5efea2e..6b22b68 100644
--- a/src/udev/udev-spawn.h
+++ b/src/udev/udev-spawn.h
@@ -14,15 +14,16 @@ typedef struct UdevEvent UdevEvent;
int udev_event_spawn(
UdevEvent *event,
- usec_t timeout_usec,
- int timeout_signal,
bool accept_failure,
const char *cmd,
char *result,
size_t ressize,
bool *ret_truncated);
-void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec, int timeout_signal);
+void udev_event_execute_run(UdevEvent *event);
static inline usec_t udev_warn_timeout(usec_t timeout_usec) {
+ if (timeout_usec == USEC_INFINITY)
+ return USEC_INFINITY;
+
return DIV_ROUND_UP(timeout_usec, 3);
}
diff --git a/src/udev/udev-watch.c b/src/udev/udev-watch.c
index 58c8279..258eb26 100644
--- a/src/udev/udev-watch.c
+++ b/src/udev/udev-watch.c
@@ -232,12 +232,9 @@ int udev_watch_end(int inotify_fd, sd_device *dev) {
_cleanup_close_ int dirfd = -EBADF;
int wd, r;
+ assert(inotify_fd >= 0);
assert(dev);
- /* This may be called by 'udevadm test'. In that case, inotify_fd is not initialized. */
- if (inotify_fd < 0)
- return 0;
-
if (sd_device_get_devname(dev, NULL) < 0)
return 0;
diff --git a/src/udev/udev-worker.c b/src/udev/udev-worker.c
index 53722b2..97c5679 100644
--- a/src/udev/udev-worker.c
+++ b/src/udev/udev-worker.c
@@ -138,11 +138,7 @@ static int worker_mark_block_device_read_only(sd_device *dev) {
if (!device_for_action(dev, SD_DEVICE_ADD))
return 0;
- r = sd_device_get_subsystem(dev, &val);
- if (r < 0)
- return log_device_debug_errno(dev, r, "Failed to get subsystem: %m");
-
- if (!streq(val, "block"))
+ if (!device_in_subsystem(dev, "block"))
return 0;
r = sd_device_get_sysname(dev, &val);
@@ -176,7 +172,7 @@ static int worker_process_device(UdevWorker *worker, sd_device *dev) {
log_device_uevent(dev, "Processing device");
- udev_event = udev_event_new(dev, worker->exec_delay_usec, worker->rtnl, worker->log_level);
+ udev_event = udev_event_new(dev, worker, EVENT_UDEV_WORKER);
if (!udev_event)
return -ENOMEM;
@@ -194,18 +190,17 @@ static int worker_process_device(UdevWorker *worker, sd_device *dev) {
if (worker->blockdev_read_only)
(void) worker_mark_block_device_read_only(dev);
+ /* Disable watch during event processing. */
+ r = udev_watch_end(worker->inotify_fd, dev);
+ if (r < 0)
+ log_device_warning_errno(dev, r, "Failed to remove inotify watch, ignoring: %m");
+
/* apply rules, create node, symlinks */
- r = udev_event_execute_rules(
- udev_event,
- worker->inotify_fd,
- worker->timeout_usec,
- worker->timeout_signal,
- worker->properties,
- worker->rules);
+ r = udev_event_execute_rules(udev_event, worker->rules);
if (r < 0)
return r;
- udev_event_execute_run(udev_event, worker->timeout_usec, worker->timeout_signal);
+ udev_event_execute_run(udev_event);
if (!worker->rtnl)
/* in case rtnl was initialized */
@@ -217,6 +212,15 @@ static int worker_process_device(UdevWorker *worker, sd_device *dev) {
log_device_warning_errno(dev, r, "Failed to add inotify watch, ignoring: %m");
}
+ /* Finalize database. */
+ r = device_add_property(dev, "ID_PROCESSING", NULL);
+ if (r < 0)
+ return log_device_warning_errno(dev, r, "Failed to remove 'ID_PROCESSING' property: %m");
+
+ r = device_update_db(dev);
+ if (r < 0)
+ return log_device_warning_errno(dev, r, "Failed to update database under /run/udev/data/: %m");
+
log_device_uevent(dev, "Device processed");
return 0;
}
@@ -245,6 +249,7 @@ void udev_broadcast_result(sd_device_monitor *monitor, sd_device *dev, EventResu
break;
}
case EVENT_RESULT_EXIT_STATUS_BASE ... EVENT_RESULT_EXIT_STATUS_MAX:
+ assert(result != EVENT_RESULT_EXIT_STATUS_BASE);
(void) device_add_propertyf(dev, "UDEV_WORKER_EXIT_STATUS", "%i", result - EVENT_RESULT_EXIT_STATUS_BASE);
break;
@@ -318,8 +323,6 @@ int udev_worker_main(UdevWorker *worker, sd_device *dev) {
DEVICE_TRACE_POINT(worker_spawned, dev, getpid_cached());
- assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, -1) >= 0);
-
/* Reset OOM score, we only protect the main daemon. */
r = set_oom_score_adjust(0);
if (r < 0)
@@ -329,7 +332,7 @@ int udev_worker_main(UdevWorker *worker, sd_device *dev) {
if (r < 0)
return log_error_errno(r, "Failed to allocate event loop: %m");
- r = sd_event_add_signal(worker->event, NULL, SIGTERM, NULL, NULL);
+ r = sd_event_add_signal(worker->event, NULL, SIGTERM | SD_EVENT_SIGNAL_PROCMASK, NULL, NULL);
if (r < 0)
return log_error_errno(r, "Failed to set SIGTERM event: %m");
diff --git a/src/udev/udev-worker.h b/src/udev/udev-worker.h
index 05c319e..e9aefc5 100644
--- a/src/udev/udev-worker.h
+++ b/src/udev/udev-worker.h
@@ -11,6 +11,9 @@
#include "hashmap.h"
#include "time-util.h"
+#define DEFAULT_WORKER_TIMEOUT_USEC (3 * USEC_PER_MINUTE)
+#define MIN_WORKER_TIMEOUT_USEC (1 * USEC_PER_MSEC)
+
typedef struct UdevRules UdevRules;
typedef struct UdevWorker {
diff --git a/src/udev/udevadm-control.c b/src/udev/udevadm-control.c
index 64615f5..29dc883 100644
--- a/src/udev/udevadm-control.c
+++ b/src/udev/udevadm-control.c
@@ -1,15 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
#include <errno.h>
#include <getopt.h>
@@ -19,6 +8,7 @@
#include <string.h>
#include <unistd.h>
+#include "creds-util.h"
#include "parse-util.h"
#include "process-util.h"
#include "static-destruct.h"
@@ -37,9 +27,21 @@ static bool arg_exit = false;
static int arg_max_children = -1;
static int arg_log_level = -1;
static int arg_start_exec_queue = -1;
+static bool arg_load_credentials = false;
STATIC_DESTRUCTOR_REGISTER(arg_env, strv_freep);
+static bool arg_has_control_commands(void) {
+ return
+ arg_exit ||
+ arg_log_level >= 0 ||
+ arg_start_exec_queue >= 0 ||
+ arg_reload ||
+ !strv_isempty(arg_env) ||
+ arg_max_children >= 0 ||
+ arg_ping;
+}
+
static int help(void) {
printf("%s control OPTION\n\n"
"Control the udev daemon.\n\n"
@@ -53,7 +55,8 @@ static int help(void) {
" -p --property=KEY=VALUE Set a global property for all events\n"
" -m --children-max=N Maximum number of children\n"
" --ping Wait for udev to respond to a ping message\n"
- " -t --timeout=SECONDS Maximum time to block for a reply\n",
+ " -t --timeout=SECONDS Maximum time to block for a reply\n"
+ " --load-credentials Load udev rules from credentials\n",
program_invocation_short_name);
return 0;
@@ -62,23 +65,25 @@ static int help(void) {
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_PING = 0x100,
+ ARG_LOAD_CREDENTIALS,
};
static const struct option options[] = {
- { "exit", no_argument, NULL, 'e' },
- { "log-level", required_argument, NULL, 'l' },
- { "log-priority", required_argument, NULL, 'l' }, /* for backward compatibility */
- { "stop-exec-queue", no_argument, NULL, 's' },
- { "start-exec-queue", no_argument, NULL, 'S' },
- { "reload", no_argument, NULL, 'R' },
- { "reload-rules", no_argument, NULL, 'R' }, /* alias for -R */
- { "property", required_argument, NULL, 'p' },
- { "env", required_argument, NULL, 'p' }, /* alias for -p */
- { "children-max", required_argument, NULL, 'm' },
- { "ping", no_argument, NULL, ARG_PING },
- { "timeout", required_argument, NULL, 't' },
- { "version", no_argument, NULL, 'V' },
- { "help", no_argument, NULL, 'h' },
+ { "exit", no_argument, NULL, 'e' },
+ { "log-level", required_argument, NULL, 'l' },
+ { "log-priority", required_argument, NULL, 'l' }, /* for backward compatibility */
+ { "stop-exec-queue", no_argument, NULL, 's' },
+ { "start-exec-queue", no_argument, NULL, 'S' },
+ { "reload", no_argument, NULL, 'R' },
+ { "reload-rules", no_argument, NULL, 'R' }, /* alias for -R */
+ { "property", required_argument, NULL, 'p' },
+ { "env", required_argument, NULL, 'p' }, /* alias for -p */
+ { "children-max", required_argument, NULL, 'm' },
+ { "ping", no_argument, NULL, ARG_PING },
+ { "timeout", required_argument, NULL, 't' },
+ { "load-credentials", no_argument, NULL, ARG_LOAD_CREDENTIALS },
+ { "version", no_argument, NULL, 'V' },
+ { "help", no_argument, NULL, 'h' },
{}
};
@@ -87,10 +92,6 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- if (argc <= 1)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "This command expects one or more options.");
-
while ((c = getopt_long(argc, argv, "el:sSRp:m:t:Vh", options, NULL)) >= 0)
switch (c) {
@@ -145,6 +146,10 @@ static int parse_argv(int argc, char *argv[]) {
return log_error_errno(r, "Failed to parse timeout value '%s': %m", optarg);
break;
+ case ARG_LOAD_CREDENTIALS:
+ arg_load_credentials = true;
+ break;
+
case 'V':
return print_version();
@@ -158,6 +163,10 @@ static int parse_argv(int argc, char *argv[]) {
assert_not_reached();
}
+ if (!arg_has_control_commands() && !arg_load_credentials)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "No control command option is specified.");
+
if (optind < argc)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Extraneous argument: %s", argv[optind]);
@@ -165,19 +174,10 @@ static int parse_argv(int argc, char *argv[]) {
return 1;
}
-int control_main(int argc, char *argv[], void *userdata) {
+static int send_control_commands(void) {
_cleanup_(udev_ctrl_unrefp) UdevCtrl *uctrl = NULL;
int r;
- if (running_in_chroot() > 0) {
- log_info("Running in chroot, ignoring request.");
- return 0;
- }
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- return r;
-
r = udev_ctrl_new(&uctrl);
if (r < 0)
return log_error_errno(r, "Failed to initialize udev control: %m");
@@ -237,3 +237,34 @@ int control_main(int argc, char *argv[], void *userdata) {
return 0;
}
+
+int control_main(int argc, char *argv[], void *userdata) {
+ int r;
+
+ if (running_in_chroot() > 0) {
+ log_info("Running in chroot, ignoring request.");
+ return 0;
+ }
+
+ r = parse_argv(argc, argv);
+ if (r <= 0)
+ return r;
+
+ if (arg_load_credentials) {
+ static const PickUpCredential table[] = {
+ { "udev.conf.", "/run/udev/udev.conf.d/", ".conf" },
+ { "udev.rules.", "/run/udev/rules.d/", ".rules" },
+ };
+ r = pick_up_credentials(table, ELEMENTSOF(table));
+ if (r < 0)
+ return r;
+ }
+
+ if (arg_has_control_commands()) {
+ r = send_control_commands();
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c
index 2f5429f..f306a4f 100644
--- a/src/udev/udevadm-hwdb.c
+++ b/src/udev/udevadm-hwdb.c
@@ -89,7 +89,7 @@ int hwdb_main(int argc, char *argv[], void *userdata) {
log_notice("udevadm hwdb is deprecated. Use systemd-hwdb instead.");
- if (arg_update) {
+ if (arg_update && !hwdb_bypass()) {
r = hwdb_update(arg_root, arg_hwdb_bin_dir, arg_strict, true);
if (r < 0)
return r;
diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c
index 4cd9ad4..7c3c0cd 100644
--- a/src/udev/udevadm-info.c
+++ b/src/udev/udevadm-info.c
@@ -759,7 +759,7 @@ static int parse_key_value_argument(const char *s, char **key, char **value) {
assert(key);
assert(value);
- r = extract_many_words(&s, "=", EXTRACT_DONT_COALESCE_SEPARATORS, &k, &v, NULL);
+ r = extract_many_words(&s, "=", EXTRACT_DONT_COALESCE_SEPARATORS, &k, &v);
if (r < 0)
return log_error_errno(r, "Failed to parse key/value pair %s: %m", s);
if (r < 2)
diff --git a/src/udev/udevadm-lock.c b/src/udev/udevadm-lock.c
index bc2d5e7..e6384e3 100644
--- a/src/udev/udevadm-lock.c
+++ b/src/udev/udevadm-lock.c
@@ -126,7 +126,7 @@ static int parse_argv(int argc, char *argv[]) {
if (arg_print) {
if (optind != argc)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No arguments expected");
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No arguments expected.");
} else {
if (optind + 1 > argc)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Too few arguments, command to execute.");
@@ -193,7 +193,7 @@ static int lock_device(
/* Extra safety: check that the device still refers to what we think it refers to */
if (!S_ISBLK(st.st_mode) || st.st_rdev != devno)
- return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "Path '%s' no longer refers to specified block device %u:%u: %m", path, major(devno), minor(devno));
+ return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "Path '%s' no longer refers to specified block device %u:%u.", path, major(devno), minor(devno));
r = lock_generic(fd, LOCK_BSD, LOCK_EX|LOCK_NB);
if (r < 0) {
diff --git a/src/udev/udevadm-monitor.c b/src/udev/udevadm-monitor.c
index 27c4853..b1124df 100644
--- a/src/udev/udevadm-monitor.c
+++ b/src/udev/udevadm-monitor.c
@@ -208,7 +208,7 @@ int monitor_main(int argc, char *argv[], void *userdata) {
goto finalize;
}
- assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
+ assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT) >= 0);
(void) sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
(void) sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
diff --git a/src/udev/udevadm-test-builtin.c b/src/udev/udevadm-test-builtin.c
index 088b4da..322f627 100644
--- a/src/udev/udevadm-test-builtin.c
+++ b/src/udev/udevadm-test-builtin.c
@@ -6,6 +6,8 @@
#include <stdio.h>
#include <stdlib.h>
+#include "device-private.h"
+#include "device-util.h"
#include "log.h"
#include "udev-builtin.h"
#include "udevadm.h"
@@ -77,8 +79,7 @@ int builtin_main(int argc, char *argv[], void *userdata) {
UdevBuiltinCommand cmd;
int r;
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
@@ -98,13 +99,22 @@ int builtin_main(int argc, char *argv[], void *userdata) {
goto finish;
}
- event = udev_event_new(dev, 0, NULL, LOG_DEBUG);
+ event = udev_event_new(dev, NULL, EVENT_UDEVADM_TEST_BUILTIN);
if (!event) {
r = log_oom();
goto finish;
}
- r = udev_builtin_run(event, cmd, arg_command, true);
+ if (arg_action != SD_DEVICE_REMOVE) {
+ /* For net_setup_link */
+ r = device_clone_with_db(dev, &event->dev_db_clone);
+ if (r < 0) {
+ log_device_error_errno(dev, r, "Failed to clone device: %m");
+ goto finish;
+ }
+ }
+
+ r = udev_builtin_run(event, cmd, arg_command);
if (r < 0) {
log_debug_errno(r, "Builtin command '%s' fails: %m", arg_command);
goto finish;
diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c
index e1afd7d..c8c23e8 100644
--- a/src/udev/udevadm-test.c
+++ b/src/udev/udevadm-test.c
@@ -16,14 +16,18 @@
#include "device-private.h"
#include "device-util.h"
+#include "format-util.h"
#include "path-util.h"
#include "string-util.h"
+#include "strv.h"
#include "strxcpyx.h"
+#include "terminal-util.h"
#include "udev-builtin.h"
#include "udev-event.h"
#include "udev-format.h"
#include "udevadm-util.h"
#include "udevadm.h"
+#include "user-util.h"
static sd_device_action_t arg_action = SD_DEVICE_ADD;
static ResolveNameTiming arg_resolve_name_timing = RESOLVE_NAME_EARLY;
@@ -89,13 +93,10 @@ int test_main(int argc, char *argv[], void *userdata) {
_cleanup_(udev_rules_freep) UdevRules *rules = NULL;
_cleanup_(udev_event_freep) UdevEvent *event = NULL;
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
- const char *cmd;
sigset_t mask, sigmask_orig;
- void *val;
int r;
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
@@ -125,24 +126,89 @@ int test_main(int argc, char *argv[], void *userdata) {
/* don't read info from the db */
device_seal(dev);
- event = udev_event_new(dev, 0, NULL, LOG_DEBUG);
+ event = udev_event_new(dev, NULL, EVENT_UDEVADM_TEST);
assert_se(sigfillset(&mask) >= 0);
assert_se(sigprocmask(SIG_SETMASK, &mask, &sigmask_orig) >= 0);
- udev_event_execute_rules(event, -1, 60 * USEC_PER_SEC, SIGKILL, NULL, rules);
+ udev_event_execute_rules(event, rules);
+ printf("%sProperties:%s\n", ansi_highlight(), ansi_normal());
FOREACH_DEVICE_PROPERTY(dev, key, value)
- printf("%s=%s\n", key, value);
+ printf(" %s=%s\n", key, value);
- ORDERED_HASHMAP_FOREACH_KEY(val, cmd, event->run_list) {
- char program[UDEV_PATH_SIZE];
- bool truncated;
+ if (sd_device_get_tag_first(dev)) {
+ printf("%sTags:%s\n", ansi_highlight(), ansi_normal());
+ FOREACH_DEVICE_TAG(dev, tag)
+ printf(" %s\n", tag);
+ }
+
+ if (sd_device_get_devnum(dev, NULL) >= 0) {
+
+ if (sd_device_get_devlink_first(dev)) {
+ int prio;
+ device_get_devlink_priority(dev, &prio);
+ printf("%sDevice node symlinks:%s (priority=%i)\n", ansi_highlight(), ansi_normal(), prio);
+ FOREACH_DEVICE_DEVLINK(dev, devlink)
+ printf(" %s\n", devlink);
+ }
+
+ printf("%sInotify watch:%s\n %s\n", ansi_highlight(), ansi_normal(), enabled_disabled(event->inotify_watch));
+
+ uid_t uid = event->uid;
+ if (!uid_is_valid(uid))
+ (void) device_get_devnode_uid(dev, &uid);
+ if (uid_is_valid(uid)) {
+ _cleanup_free_ char *user = uid_to_name(uid);
+ printf("%sDevice node owner:%s\n %s (uid="UID_FMT")\n", ansi_highlight(), ansi_normal(), strna(user), uid);
+ }
+
+ gid_t gid = event->gid;
+ if (!gid_is_valid(uid))
+ (void) device_get_devnode_gid(dev, &gid);
+ if (gid_is_valid(gid)) {
+ _cleanup_free_ char *group = gid_to_name(gid);
+ printf("%sDevice node group:%s\n %s (gid="GID_FMT")\n", ansi_highlight(), ansi_normal(), strna(group), gid);
+ }
- (void) udev_event_apply_format(event, cmd, program, sizeof(program), false, NULL, &truncated);
- if (truncated)
- log_warning("The command '%s' is truncated while substituting into '%s'.", program, cmd);
- printf("run: '%s'\n", program);
+ mode_t mode = event->mode;
+ if (mode == MODE_INVALID)
+ (void) device_get_devnode_mode(dev, &mode);
+ if (mode != MODE_INVALID)
+ printf("%sDevice node permission:%s\n %04o\n", ansi_highlight(), ansi_normal(), mode);
+
+ if (!ordered_hashmap_isempty(event->seclabel_list)) {
+ const char *name, *label;
+ printf("%sDevice node security label:%s\n", ansi_highlight(), ansi_normal());
+ ORDERED_HASHMAP_FOREACH_KEY(label, name, event->seclabel_list)
+ printf(" %s : %s\n", name, label);
+ }
+ }
+
+ if (sd_device_get_ifindex(dev, NULL) >= 0) {
+ if (!isempty(event->name))
+ printf("%sNetwork interface name:%s\n %s\n", ansi_highlight(), ansi_normal(), event->name);
+
+ if (!strv_isempty(event->altnames)) {
+ bool space = true;
+ printf("%sAlternative interface names:%s", ansi_highlight(), ansi_normal());
+ fputstrv(stdout, event->altnames, "\n ", &space);
+ puts("");
+ }
+ }
+
+ if (!ordered_hashmap_isempty(event->run_list)) {
+ void *val;
+ const char *command;
+ printf("%sQueued commands:%s\n", ansi_highlight(), ansi_normal());
+ ORDERED_HASHMAP_FOREACH_KEY(val, command, event->run_list) {
+ UdevBuiltinCommand builtin_cmd = PTR_TO_UDEV_BUILTIN_CMD(val);
+
+ if (builtin_cmd != _UDEV_BUILTIN_INVALID)
+ printf(" RUN{builtin} : %s\n", command);
+ else
+ printf(" RUN{program} : %s\n", command);
+ }
}
r = 0;
diff --git a/src/udev/udevadm-wait.c b/src/udev/udevadm-wait.c
index e6620c2..6ffc86b 100644
--- a/src/udev/udevadm-wait.c
+++ b/src/udev/udevadm-wait.c
@@ -67,7 +67,7 @@ static int check_device(const char *path) {
return r;
if (arg_wait_until == WAIT_UNTIL_INITIALIZED)
- return sd_device_get_is_initialized(dev);
+ return device_is_processed(dev);
return true;
}
diff --git a/src/udev/udevadm.c b/src/udev/udevadm.c
index 687b927..899d4e6 100644
--- a/src/udev/udevadm.c
+++ b/src/udev/udevadm.c
@@ -123,7 +123,7 @@ static int run(int argc, char *argv[]) {
if (invoked_as(argv, "udevd"))
return run_udevd(argc, argv);
- udev_parse_config();
+ (void) udev_parse_config();
log_setup();
r = parse_argv(argc, argv);
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index 2ed4282..5018541 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -10,6 +10,7 @@
#include "sd-daemon.h"
+#include "conf-parser.h"
#include "env-file.h"
#include "errno-util.h"
#include "fd-util.h"
@@ -32,16 +33,15 @@ static int arg_daemonize = false;
static int listen_fds(int *ret_ctrl, int *ret_netlink) {
int ctrl_fd = -EBADF, netlink_fd = -EBADF;
- int fd, n;
assert(ret_ctrl);
assert(ret_netlink);
- n = sd_listen_fds(true);
+ int n = sd_listen_fds(true);
if (n < 0)
return n;
- for (fd = SD_LISTEN_FDS_START; fd < n + SD_LISTEN_FDS_START; fd++) {
+ for (int fd = SD_LISTEN_FDS_START; fd < n + SD_LISTEN_FDS_START; fd++) {
if (sd_is_socket(fd, AF_UNIX, SOCK_SEQPACKET, -1) > 0) {
if (ctrl_fd >= 0)
return -EINVAL;
@@ -65,70 +65,29 @@ static int listen_fds(int *ret_ctrl, int *ret_netlink) {
return 0;
}
+static DEFINE_CONFIG_PARSE_ENUM(config_parse_resolve_name_timing, resolve_name_timing, ResolveNameTiming, "Failed to parse resolve name timing");
+
static int manager_parse_udev_config(Manager *manager) {
- _cleanup_free_ char *log_val = NULL, *children_max = NULL, *exec_delay = NULL,
- *event_timeout = NULL, *resolve_names = NULL, *timeout_signal = NULL;
- int r;
+ int r, log_val = -1;
assert(manager);
- r = parse_env_file(NULL, "/etc/udev/udev.conf",
- "udev_log", &log_val,
- "children_max", &children_max,
- "exec_delay", &exec_delay,
- "event_timeout", &event_timeout,
- "resolve_names", &resolve_names,
- "timeout_signal", &timeout_signal);
- if (r == -ENOENT)
- return 0;
- if (r < 0)
- return r;
+ const ConfigTableItem config_table[] = {
+ { NULL, "udev_log", config_parse_log_level, 0, &log_val },
+ { NULL, "children_max", config_parse_unsigned, 0, &manager->children_max },
+ { NULL, "exec_delay", config_parse_sec, 0, &manager->exec_delay_usec },
+ { NULL, "event_timeout", config_parse_sec, 0, &manager->timeout_usec },
+ { NULL, "resolve_names", config_parse_resolve_name_timing, 0, &manager->resolve_name_timing },
+ { NULL, "timeout_signal", config_parse_signal, 0, &manager->timeout_signal },
+ {}
+ };
- r = udev_set_max_log_level(log_val);
+ r = udev_parse_config_full(config_table);
if (r < 0)
- log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r,
- "Failed to set udev log level '%s', ignoring: %m", log_val);
-
- if (children_max) {
- r = safe_atou(children_max, &manager->children_max);
- if (r < 0)
- log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r,
- "Failed to parse children_max=%s, ignoring: %m", children_max);
- }
-
- if (exec_delay) {
- r = parse_sec(exec_delay, &manager->exec_delay_usec);
- if (r < 0)
- log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r,
- "Failed to parse exec_delay=%s, ignoring: %m", exec_delay);
- }
-
- if (event_timeout) {
- r = parse_sec(event_timeout, &manager->timeout_usec);
- if (r < 0)
- log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r,
- "Failed to parse event_timeout=%s, ignoring: %m", event_timeout);
- }
-
- if (resolve_names) {
- ResolveNameTiming t;
-
- t = resolve_name_timing_from_string(resolve_names);
- if (t < 0)
- log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r,
- "Failed to parse resolve_names=%s, ignoring.", resolve_names);
- else
- manager->resolve_name_timing = t;
- }
+ return r;
- if (timeout_signal) {
- r = signal_from_string(timeout_signal);
- if (r < 0)
- log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r,
- "Failed to parse timeout_signal=%s, ignoring: %m", timeout_signal);
- else
- manager->timeout_signal = r;
- }
+ if (log_val >= 0)
+ log_set_max_level(log_val);
return 0;
}
@@ -330,8 +289,7 @@ int run_udevd(int argc, char *argv[]) {
int fd_ctrl = -EBADF, fd_uevent = -EBADF;
int r;
- log_set_target(LOG_TARGET_AUTO);
- log_open();
+ log_setup();
manager = manager_new();
if (!manager)
@@ -339,9 +297,6 @@ int run_udevd(int argc, char *argv[]) {
manager_parse_udev_config(manager);
- log_parse_environment();
- log_open(); /* Done again to update after reading configuration. */
-
r = parse_argv(argc, argv, manager);
if (r <= 0)
return r;
@@ -355,6 +310,8 @@ int run_udevd(int argc, char *argv[]) {
log_set_max_level(LOG_DEBUG);
}
+ manager_adjust_arguments(manager);
+
r = must_be_root();
if (r < 0)
return r;
diff --git a/src/udev/v4l_id/v4l_id.c b/src/udev/v4l_id/v4l_id.c
index 30527e9..5c54065 100644
--- a/src/udev/v4l_id/v4l_id.c
+++ b/src/udev/v4l_id/v4l_id.c
@@ -1,16 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (c) 2009 Filippo Argiolas <filippo.argiolas@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details:
*/
#include <ctype.h>