summaryrefslogtreecommitdiff
path: root/src/udev
diff options
context:
space:
mode:
Diffstat (limited to 'src/udev')
-rw-r--r--src/udev/meson.build9
-rw-r--r--src/udev/net/ethtool-util.c12
-rw-r--r--src/udev/net/ethtool-util.h16
-rw-r--r--src/udev/net/link-config.c136
-rw-r--r--src/udev/net/link-config.h1
-rw-r--r--src/udev/net/naming-scheme.c64
-rw-r--r--src/udev/net/naming-scheme.h48
-rw-r--r--src/udev/scsi_id/scsi_id.c3
-rw-r--r--src/udev/udev-builtin-blkid.c2
-rw-r--r--src/udev/udev-builtin-btrfs.c2
-rw-r--r--src/udev/udev-builtin-hwdb.c4
-rw-r--r--src/udev/udev-builtin-input_id.c2
-rw-r--r--src/udev/udev-builtin-keyboard.c6
-rw-r--r--src/udev/udev-builtin-net_id.c103
-rw-r--r--src/udev/udev-builtin-net_setup_link.c2
-rw-r--r--src/udev/udev-builtin-path_id.c1
-rw-r--r--src/udev/udev-builtin.c2
-rw-r--r--src/udev/udev-ctrl.c68
-rw-r--r--src/udev/udev-ctrl.h17
-rw-r--r--src/udev/udev-event.c54
-rw-r--r--src/udev/udev-node.c5
-rw-r--r--src/udev/udev-rules.c226
-rw-r--r--src/udev/udev.pc.in2
-rw-r--r--src/udev/udevadm-control.c79
-rw-r--r--src/udev/udevadm-info.c13
-rw-r--r--src/udev/udevadm-monitor.c10
-rw-r--r--src/udev/udevadm-settle.c10
-rw-r--r--src/udev/udevadm-trigger.c55
-rw-r--r--src/udev/udevadm.c3
-rw-r--r--src/udev/udevadm.h6
-rw-r--r--src/udev/udevd.c169
31 files changed, 635 insertions, 495 deletions
diff --git a/src/udev/meson.build b/src/udev/meson.build
index e378d9190c..9d3f6d1c56 100644
--- a/src/udev/meson.build
+++ b/src/udev/meson.build
@@ -41,6 +41,8 @@ libudev_core_sources = '''
net/link-config.h
net/ethtool-util.c
net/ethtool-util.h
+ net/naming-scheme.c
+ net/naming-scheme.h
'''.split()
if conf.get('HAVE_KMOD') == 1
@@ -187,12 +189,11 @@ endforeach
install_data('udev.conf',
install_dir : join_paths(sysconfdir, 'udev'))
-udev_pc = configure_file(
+configure_file(
input : 'udev.pc.in',
output : 'udev.pc',
- configuration : substs)
-install_data(udev_pc,
- install_dir : pkgconfigdatadir)
+ configuration : substs,
+ install_dir : pkgconfigdatadir == 'no' ? '' : pkgconfigdatadir)
meson.add_install_script('sh', '-c',
mkdir_p.format(join_paths(sysconfdir, 'udev/rules.d')))
diff --git a/src/udev/net/ethtool-util.c b/src/udev/net/ethtool-util.c
index bc0deaf347..0dcec03f67 100644
--- a/src/udev/net/ethtool-util.c
+++ b/src/udev/net/ethtool-util.c
@@ -31,18 +31,18 @@ static const char* const wol_table[_WOL_MAX] = {
[WOL_ARP] = "arp",
[WOL_MAGIC] = "magic",
[WOL_MAGICSECURE] = "secureon",
- [WOL_OFF] = "off"
+ [WOL_OFF] = "off",
};
DEFINE_STRING_TABLE_LOOKUP(wol, WakeOnLan);
DEFINE_CONFIG_PARSE_ENUM(config_parse_wol, wol, WakeOnLan, "Failed to parse WakeOnLan setting");
-static const char* const port_table[_NET_DEV_PORT_MAX] = {
+static const char* const port_table[] = {
[NET_DEV_PORT_TP] = "tp",
[NET_DEV_PORT_AUI] = "aui",
[NET_DEV_PORT_MII] = "mii",
[NET_DEV_PORT_FIBRE] = "fibre",
- [NET_DEV_PORT_BNC] = "bnc"
+ [NET_DEV_PORT_BNC] = "bnc",
};
DEFINE_STRING_TABLE_LOOKUP(port, NetDevPort);
@@ -583,7 +583,7 @@ int ethtool_set_glinksettings(int *fd, const char *ifname, struct link_config *l
struct ifreq ifr = {};
int r;
- if (link->autonegotiation != 0) {
+ if (link->autonegotiation != AUTONEG_DISABLE && eqzero(link->advertise)) {
log_info("link_config: autonegotiation is unset or enabled, the speed and duplex are not writable.");
return 0;
}
@@ -612,9 +612,11 @@ int ethtool_set_glinksettings(int *fd, const char *ifname, struct link_config *l
if (link->port != _NET_DEV_PORT_INVALID)
u->base.port = link->port;
- u->base.autoneg = link->autonegotiation;
+ if (link->autonegotiation >= 0)
+ u->base.autoneg = link->autonegotiation;
if (!eqzero(link->advertise)) {
+ u->base.autoneg = AUTONEG_ENABLE;
memcpy(&u->link_modes.advertising, link->advertise, sizeof(link->advertise));
memzero((uint8_t*) &u->link_modes.advertising + sizeof(link->advertise),
ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBYTES - sizeof(link->advertise));
diff --git a/src/udev/net/ethtool-util.h b/src/udev/net/ethtool-util.h
index e4bc5161d5..618b26bf59 100644
--- a/src/udev/net/ethtool-util.h
+++ b/src/udev/net/ethtool-util.h
@@ -42,14 +42,14 @@ typedef enum NetDevFeature {
} NetDevFeature;
typedef enum NetDevPort {
- NET_DEV_PORT_TP = 0x00,
- NET_DEV_PORT_AUI = 0x01,
- NET_DEV_PORT_MII = 0x02,
- NET_DEV_PORT_FIBRE = 0x03,
- NET_DEV_PORT_BNC = 0x04,
- NET_DEV_PORT_DA = 0x05,
- NET_DEV_PORT_NONE = 0xef,
- NET_DEV_PORT_OTHER = 0xff,
+ NET_DEV_PORT_TP = PORT_TP,
+ NET_DEV_PORT_AUI = PORT_AUI,
+ NET_DEV_PORT_MII = PORT_MII,
+ NET_DEV_PORT_FIBRE = PORT_FIBRE,
+ NET_DEV_PORT_BNC = PORT_BNC,
+ NET_DEV_PORT_DA = PORT_DA,
+ NET_DEV_PORT_NONE = PORT_NONE,
+ NET_DEV_PORT_OTHER = PORT_OTHER,
_NET_DEV_PORT_MAX,
_NET_DEV_PORT_INVALID = -1
} NetDevPort;
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index ac66ffd047..eb2477cea4 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -14,6 +14,7 @@
#include "link-config.h"
#include "log.h"
#include "missing_network.h"
+#include "naming-scheme.h"
#include "netlink-util.h"
#include "network-internal.h"
#include "parse-util.h"
@@ -186,6 +187,22 @@ static bool enable_name_policy(void) {
return proc_cmdline_get_bool("net.ifnames", &b) <= 0 || b;
}
+static int link_name_type(sd_device *device, unsigned *type) {
+ const char *s;
+ int r;
+
+ r = sd_device_get_sysattr_value(device, "name_assign_type", &s);
+ if (r < 0)
+ return log_device_debug_errno(device, r, "Failed to query name_assign_type: %m");
+
+ r = safe_atou(s, type);
+ if (r < 0)
+ return log_device_warning_errno(device, r, "Failed to parse name_assign_type \"%s\": %m", s);
+
+ log_device_debug(device, "Device has name_assign_type=%d", *type);
+ return 0;
+}
+
int link_config_load(link_config_ctx *ctx) {
_cleanup_strv_free_ char **files;
char **f;
@@ -256,13 +273,13 @@ int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret)
if (name_assign_type == NET_NAME_ENUM) {
log_warning("Config file %s applies to device based on potentially unpredictable interface name '%s'",
- link->filename, sysname);
+ link->filename, sysname);
*ret = link;
return 0;
} else if (name_assign_type == NET_NAME_RENAMED) {
log_warning("Config file %s matches device based on renamed interface name '%s', ignoring",
- link->filename, sysname);
+ link->filename, sysname);
continue;
}
@@ -272,13 +289,11 @@ int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret)
link->filename, sysname);
*ret = link;
-
return 0;
}
}
*ret = NULL;
-
return -ENOENT;
}
@@ -298,31 +313,6 @@ static bool mac_is_random(sd_device *device) {
return type == NET_ADDR_RANDOM;
}
-static bool should_rename(sd_device *device, bool respect_predictable) {
- const char *s;
- unsigned type;
- int r;
-
- /* if we can't get the assgin type, assume we should rename */
- if (sd_device_get_sysattr_value(device, "name_assign_type", &s) < 0)
- return true;
-
- r = safe_atou(s, &type);
- if (r < 0)
- return true;
-
- switch (type) {
- case NET_NAME_PREDICTABLE:
- /* the kernel claims to have given a predictable name */
- if (respect_predictable)
- return false;
- _fallthrough_;
- default:
- /* the name is known to be bad, or of an unknown type */
- return true;
- }
-}
-
static int get_mac(sd_device *device, bool want_random,
struct ether_addr *mac) {
int r;
@@ -349,12 +339,12 @@ static int get_mac(sd_device *device, bool want_random,
int link_config_apply(link_config_ctx *ctx, link_config *config,
sd_device *device, const char **name) {
- bool respect_predictable = false;
struct ether_addr generated_mac;
struct ether_addr *mac = NULL;
const char *new_name = NULL;
const char *old_name;
- unsigned speed;
+ unsigned speed, name_type = NET_NAME_UNKNOWN;
+ NamePolicy policy;
int r, ifindex;
assert(ctx);
@@ -407,38 +397,63 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
if (r < 0)
return log_device_warning_errno(device, r, "Could not find ifindex: %m");
- if (ctx->enable_name_policy && config->name_policy) {
- NamePolicy *policy;
- for (policy = config->name_policy;
- !new_name && *policy != _NAMEPOLICY_INVALID; policy++) {
- switch (*policy) {
- case NAMEPOLICY_KERNEL:
- respect_predictable = true;
- break;
- case NAMEPOLICY_DATABASE:
- (void) sd_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE", &new_name);
- break;
- case NAMEPOLICY_ONBOARD:
- (void) sd_device_get_property_value(device, "ID_NET_NAME_ONBOARD", &new_name);
- break;
- case NAMEPOLICY_SLOT:
- (void) sd_device_get_property_value(device, "ID_NET_NAME_SLOT", &new_name);
- break;
- case NAMEPOLICY_PATH:
- (void) sd_device_get_property_value(device, "ID_NET_NAME_PATH", &new_name);
- break;
- case NAMEPOLICY_MAC:
- (void) sd_device_get_property_value(device, "ID_NET_NAME_MAC", &new_name);
- break;
- default:
- break;
+ (void) link_name_type(device, &name_type);
+
+ if (IN_SET(name_type, NET_NAME_USER, NET_NAME_RENAMED)
+ && !naming_scheme_has(NAMING_ALLOW_RERENAMES)) {
+ log_device_debug(device, "Device already has a name given by userspace, not renaming.");
+ goto no_rename;
+ }
+
+ if (ctx->enable_name_policy && config->name_policy)
+ for (NamePolicy *p = config->name_policy; !new_name && *p != _NAMEPOLICY_INVALID; p++) {
+ policy = *p;
+
+ switch (policy) {
+ case NAMEPOLICY_KERNEL:
+ if (name_type != NET_NAME_PREDICTABLE)
+ continue;
+
+ /* The kernel claims to have given a predictable name, keep it. */
+ log_device_debug(device, "Policy *%s*: keeping predictable kernel name",
+ name_policy_to_string(policy));
+ goto no_rename;
+ case NAMEPOLICY_KEEP:
+ if (!IN_SET(name_type, NET_NAME_USER, NET_NAME_RENAMED))
+ continue;
+
+ log_device_debug(device, "Policy *%s*: keeping existing userspace name",
+ name_policy_to_string(policy));
+ goto no_rename;
+ case NAMEPOLICY_DATABASE:
+ (void) sd_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE", &new_name);
+ break;
+ case NAMEPOLICY_ONBOARD:
+ (void) sd_device_get_property_value(device, "ID_NET_NAME_ONBOARD", &new_name);
+ break;
+ case NAMEPOLICY_SLOT:
+ (void) sd_device_get_property_value(device, "ID_NET_NAME_SLOT", &new_name);
+ break;
+ case NAMEPOLICY_PATH:
+ (void) sd_device_get_property_value(device, "ID_NET_NAME_PATH", &new_name);
+ break;
+ case NAMEPOLICY_MAC:
+ (void) sd_device_get_property_value(device, "ID_NET_NAME_MAC", &new_name);
+ break;
+ default:
+ assert_not_reached("invalid policy");
}
}
- }
- if (!new_name && should_rename(device, respect_predictable))
+ if (new_name)
+ log_device_debug(device, "Policy *%s* yields \"%s\".", name_policy_to_string(policy), new_name);
+ else if (config->name) {
new_name = config->name;
+ log_device_debug(device, "Policies didn't yield a name, using specified Name=%s.", new_name);
+ } else
+ log_device_debug(device, "Policies didn't yield a name and Name= is not given, not renaming.");
+ no_rename:
switch (config->mac_policy) {
case MACPOLICY_PERSISTENT:
@@ -497,7 +512,7 @@ int link_get_driver(link_config_ctx *ctx, sd_device *device, char **ret) {
static const char* const mac_policy_table[_MACPOLICY_MAX] = {
[MACPOLICY_PERSISTENT] = "persistent",
[MACPOLICY_RANDOM] = "random",
- [MACPOLICY_NONE] = "none"
+ [MACPOLICY_NONE] = "none",
};
DEFINE_STRING_TABLE_LOOKUP(mac_policy, MACPolicy);
@@ -506,11 +521,12 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy, mac_policy, MACPolicy,
static const char* const name_policy_table[_NAMEPOLICY_MAX] = {
[NAMEPOLICY_KERNEL] = "kernel",
+ [NAMEPOLICY_KEEP] = "keep",
[NAMEPOLICY_DATABASE] = "database",
[NAMEPOLICY_ONBOARD] = "onboard",
[NAMEPOLICY_SLOT] = "slot",
[NAMEPOLICY_PATH] = "path",
- [NAMEPOLICY_MAC] = "mac"
+ [NAMEPOLICY_MAC] = "mac",
};
DEFINE_STRING_TABLE_LOOKUP(name_policy, NamePolicy);
diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h
index 8204959034..1113b1052e 100644
--- a/src/udev/net/link-config.h
+++ b/src/udev/net/link-config.h
@@ -22,6 +22,7 @@ typedef enum MACPolicy {
typedef enum NamePolicy {
NAMEPOLICY_KERNEL,
+ NAMEPOLICY_KEEP,
NAMEPOLICY_DATABASE,
NAMEPOLICY_ONBOARD,
NAMEPOLICY_SLOT,
diff --git a/src/udev/net/naming-scheme.c b/src/udev/net/naming-scheme.c
new file mode 100644
index 0000000000..27cede5e2e
--- /dev/null
+++ b/src/udev/net/naming-scheme.c
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#include "alloc-util.h"
+#include "naming-scheme.h"
+#include "proc-cmdline.h"
+#include "string-util.h"
+
+static const NamingScheme naming_schemes[] = {
+ { "v238", NAMING_V238 },
+ { "v239", NAMING_V239 },
+ { "v240", NAMING_V240 },
+ /* … add more schemes here, as the logic to name devices is updated … */
+};
+
+static const NamingScheme* naming_scheme_from_name(const char *name) {
+ size_t i;
+
+ if (streq(name, "latest"))
+ return naming_schemes + ELEMENTSOF(naming_schemes) - 1;
+
+ for (i = 0; i < ELEMENTSOF(naming_schemes); i++)
+ if (streq(naming_schemes[i].name, name))
+ return naming_schemes + i;
+
+ return NULL;
+}
+
+const NamingScheme* naming_scheme(void) {
+ static const NamingScheme *cache = NULL;
+ _cleanup_free_ char *buffer = NULL;
+ const char *e, *k;
+
+ if (cache)
+ return cache;
+
+ /* Acquire setting from the kernel command line */
+ (void) proc_cmdline_get_key("net.naming-scheme", 0, &buffer);
+
+ /* Also acquire it from an env var */
+ e = getenv("NET_NAMING_SCHEME");
+ if (e) {
+ if (*e == ':') {
+ /* If prefixed with ':' the kernel cmdline takes precedence */
+ k = buffer ?: e + 1;
+ } else
+ k = e; /* Otherwise the env var takes precedence */
+ } else
+ k = buffer;
+
+ if (k) {
+ cache = naming_scheme_from_name(k);
+ if (cache) {
+ log_info("Using interface naming scheme '%s'.", cache->name);
+ return cache;
+ }
+
+ log_warning("Unknown interface naming scheme '%s' requested, ignoring.", k);
+ }
+
+ cache = naming_scheme_from_name(DEFAULT_NET_NAMING_SCHEME);
+ assert(cache);
+ log_info("Using default interface naming scheme '%s'.", cache->name);
+
+ return cache;
+}
diff --git a/src/udev/net/naming-scheme.h b/src/udev/net/naming-scheme.h
new file mode 100644
index 0000000000..0b3d9bff1d
--- /dev/null
+++ b/src/udev/net/naming-scheme.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdbool.h>
+
+#include "macro.h"
+
+/* So here's the deal: net_id is supposed to be an excercise in providing stable names for network devices. However, we
+ * also want to keep updating the naming scheme used in future versions of net_id. These two goals of course are
+ * contradictory: on one hand we want things to not change and on the other hand we want them to improve. Our way out
+ * of this dilemma is to introduce the "naming scheme" concept: each time we improve the naming logic we define a new
+ * flag for it. Then, we keep a list of schemes, each identified by a name associated with the flags it implements. Via
+ * a kernel command line and environment variable we then allow the user to pick the scheme they want us to follow:
+ * installers could "freeze" the used scheme at the moment of installation this way.
+ *
+ * Developers: each time you tweak the naming logic here, define a new flag below, and condition the tweak with
+ * it. Each time we do a release we'll then add a new scheme entry and include all newly defined flags.
+ *
+ * Note that this is only half a solution to the problem though: not only udev/net_id gets updated all the time, the
+ * kernel gets too. And thus a kernel that previously didn't expose some sysfs attribute we look for might eventually
+ * do, and thus affect our naming scheme too. Thus, enforcing a naming scheme will make interfacing more stable across
+ * OS versions, but not fully stabilize them. */
+typedef enum NamingSchemeFlags {
+ /* First, the individual features */
+ NAMING_SR_IOV_V = 1 << 0, /* Use "v" suffix for SR-IOV, see 609948c7043a40008b8299529c978ed8e11de8f6*/
+ NAMING_NPAR_ARI = 1 << 1, /* Use NPAR "ARI", see 6bc04997b6eab35d1cb9fa73889892702c27be09 */
+ NAMING_INFINIBAND = 1 << 2, /* Use "ib" prefix for infiniband, see 938d30aa98df887797c9e05074a562ddacdcdf5e */
+ NAMING_ZERO_ACPI_INDEX = 1 << 3, /* Allow zero acpi_index field, see d81186ef4f6a888a70f20a1e73a812d6acb9e22f */
+ NAMING_ALLOW_RERENAMES = 1 << 4, /* Allow re-renaming of devices, see #9006 */
+
+ /* And now the masks that combine the features above */
+ NAMING_V238 = 0,
+ NAMING_V239 = NAMING_V238 | NAMING_SR_IOV_V | NAMING_NPAR_ARI,
+ NAMING_V240 = NAMING_V239 | NAMING_INFINIBAND | NAMING_ZERO_ACPI_INDEX | NAMING_ALLOW_RERENAMES,
+
+ _NAMING_SCHEME_FLAGS_INVALID = -1,
+} NamingSchemeFlags;
+
+typedef struct NamingScheme {
+ const char *name;
+ NamingSchemeFlags flags;
+} NamingScheme;
+
+const NamingScheme* naming_scheme(void);
+
+static inline bool naming_scheme_has(NamingSchemeFlags flags) {
+ return FLAGS_SET(naming_scheme()->flags, flags);
+}
diff --git a/src/udev/scsi_id/scsi_id.c b/src/udev/scsi_id/scsi_id.c
index e94f2946f9..2698cdd82f 100644
--- a/src/udev/scsi_id/scsi_id.c
+++ b/src/udev/scsi_id/scsi_id.c
@@ -18,6 +18,7 @@
#include <unistd.h>
#include "alloc-util.h"
+#include "build.h"
#include "fd-util.h"
#include "libudev-util.h"
#include "scsi_id.h"
@@ -370,7 +371,7 @@ static int set_options(int argc, char **argv,
break;
case 'V':
- printf("%s\n", PACKAGE_VERSION);
+ printf("%s\n", GIT_VERSION);
exit(EXIT_SUCCESS);
case 'x':
diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c
index df0f95461d..69d6c4bbee 100644
--- a/src/udev/udev-builtin-blkid.c
+++ b/src/udev/udev-builtin-blkid.c
@@ -240,7 +240,7 @@ static int builtin_blkid(sd_device *dev, 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, -ERANGE, "Invalid offset %"PRIi64": %m", offset);
+ return log_device_error_errno(dev, SYNTHETIC_ERRNO(ERANGE), "Invalid offset %"PRIi64": %m", offset);
break;
case 'R':
noraid = true;
diff --git a/src/udev/udev-builtin-btrfs.c b/src/udev/udev-builtin-btrfs.c
index 85dba3d099..956be59afb 100644
--- a/src/udev/udev-builtin-btrfs.c
+++ b/src/udev/udev-builtin-btrfs.c
@@ -18,7 +18,7 @@ static int builtin_btrfs(sd_device *dev, int argc, char *argv[], bool test) {
int r;
if (argc != 3 || !streq(argv[1], "ready"))
- return log_device_error_errno(dev, EINVAL, "Invalid arguments");
+ return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Invalid arguments");
fd = open("/dev/btrfs-control", O_RDWR|O_CLOEXEC);
if (fd < 0)
diff --git a/src/udev/udev-builtin-hwdb.c b/src/udev/udev-builtin-hwdb.c
index ccad98e892..225e0265a4 100644
--- a/src/udev/udev-builtin-hwdb.c
+++ b/src/udev/udev-builtin-hwdb.c
@@ -165,7 +165,7 @@ static int builtin_hwdb(sd_device *dev, int argc, char *argv[], bool test) {
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to lookup hwdb: %m");
if (r == 0)
- return log_device_debug_errno(dev, ENOENT, "No entry found from hwdb: %m");
+ return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ENODATA), "No entry found from hwdb.");
return r;
}
@@ -180,7 +180,7 @@ static int builtin_hwdb(sd_device *dev, int argc, char *argv[], bool test) {
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to lookup hwdb: %m");
if (r == 0)
- return log_device_debug_errno(dev, ENOENT, "No entry found from hwdb: %m");
+ return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ENODATA), "No entry found from hwdb.");
return r;
}
diff --git a/src/udev/udev-builtin-input_id.c b/src/udev/udev-builtin-input_id.c
index 13e9f0108d..e3db55b1a9 100644
--- a/src/udev/udev-builtin-input_id.c
+++ b/src/udev/udev-builtin-input_id.c
@@ -42,7 +42,7 @@ static const struct range high_key_blocks[] = {
{ KEY_ALS_TOGGLE, BTN_TRIGGER_HAPPY }
};
-static inline int abs_size_mm(const struct input_absinfo *absinfo) {
+static int abs_size_mm(const struct input_absinfo *absinfo) {
/* Resolution is defined to be in units/mm for ABS_X/Y */
return (absinfo->maximum - absinfo->minimum) / absinfo->resolution;
}
diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c
index cb49a17c33..d80cdd26aa 100644
--- a/src/udev/udev-builtin-keyboard.c
+++ b/src/udev/udev-builtin-keyboard.c
@@ -74,7 +74,7 @@ static int map_keycode(sd_device *dev, int fd, int scancode, const char *keycode
/* check if it's a numeric code already */
keycode_num = strtoul(keycode, &endptr, 0);
if (endptr[0] !='\0')
- return log_device_error_errno(dev, EINVAL, "Failed to parse key identifier '%s'", keycode);
+ return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Failed to parse key identifier '%s'", keycode);
}
map.scan = scancode;
@@ -89,7 +89,7 @@ static int map_keycode(sd_device *dev, int fd, int scancode, const char *keycode
return 0;
}
-static inline char* parse_token(const char *current, int32_t *val_out) {
+static char* parse_token(const char *current, int32_t *val_out) {
char *next;
int32_t val;
@@ -152,7 +152,7 @@ static int set_trackpoint_sensitivity(sd_device *dev, const char *value) {
if (r < 0)
return log_device_error_errno(dev, r, "Failed to parse POINTINGSTICK_SENSITIVITY '%s': %m", value);
else if (val_i < 0 || val_i > 255)
- return log_device_error_errno(dev, ERANGE, "POINTINGSTICK_SENSITIVITY %d outside range [0..255]", val_i);
+ return log_device_error_errno(dev, SYNTHETIC_ERRNO(ERANGE), "POINTINGSTICK_SENSITIVITY %d outside range [0..255]", val_i);
xsprintf(val_s, "%d", val_i);
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
index 0292c4973c..03b281a771 100644
--- a/src/udev/udev-builtin-net_id.c
+++ b/src/udev/udev-builtin-net_id.c
@@ -106,6 +106,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
+#include "naming-scheme.h"
#include "parse-util.h"
#include "proc-cmdline.h"
#include "stdio-util.h"
@@ -116,48 +117,6 @@
#define ONBOARD_INDEX_MAX (16*1024-1)
-/* So here's the deal: net_id is supposed to be an excercise in providing stable names for network devices. However, we
- * also want to keep updating the naming scheme used in future versions of net_id. These two goals of course are
- * contradictory: on one hand we want things to not change and on the other hand we want them to improve. Our way out
- * of this dilemma is to introduce the "naming scheme" concept: each time we improve the naming logic we define a new
- * flag for it. Then, we keep a list of schemes, each identified by a name associated with the flags it implements. Via
- * a kernel command line and environment variable we then allow the user to pick the scheme they want us to follow:
- * installers could "freeze" the used scheme at the moment of installation this way.
- *
- * Developers: each time you tweak the naming logic here, define a new flag below, and condition the tweak with
- * it. Each time we do a release we'll then add a new scheme entry and include all newly defined flags.
- *
- * Note that this is only half a solution to the problem though: not only udev/net_id gets updated all the time, the
- * kernel gets too. And thus a kernel that previously didn't expose some sysfs attribute we look for might eventually
- * do, and thus affect our naming scheme too. Thus, enforcing a naming scheme will make interfacing more stable across
- * OS versions, but not fully stabilize them. */
-typedef enum NamingSchemeFlags {
- /* First, the individual features */
- NAMING_SR_IOV_V = 1 << 0, /* Use "v" suffix for SR-IOV, see 609948c7043a40008b8299529c978ed8e11de8f6*/
- NAMING_NPAR_ARI = 1 << 1, /* Use NPAR "ARI", see 6bc04997b6eab35d1cb9fa73889892702c27be09 */
- NAMING_INFINIBAND = 1 << 2, /* Use "ib" prefix for infiniband, see 938d30aa98df887797c9e05074a562ddacdcdf5e */
- NAMING_ZERO_ACPI_INDEX = 1 << 3, /* Allow zero acpi_index field, see d81186ef4f6a888a70f20a1e73a812d6acb9e22f */
-
- /* And now the masks that combine the features above */
- NAMING_V238 = 0,
- NAMING_V239 = NAMING_V238|NAMING_SR_IOV_V|NAMING_NPAR_ARI,
- NAMING_V240 = NAMING_V239|NAMING_INFINIBAND|NAMING_ZERO_ACPI_INDEX,
-
- _NAMING_SCHEME_FLAGS_INVALID = -1,
-} NamingSchemeFlags;
-
-typedef struct NamingScheme {
- const char *name;
- NamingSchemeFlags flags;
-} NamingScheme;
-
-static const NamingScheme naming_schemes[] = {
- { "v238", NAMING_V238 },
- { "v239", NAMING_V239 },
- { "v240", NAMING_V240 },
- /* … add more schemes here, as the logic to name devices is updated … */
-};
-
enum netname_type{
NET_UNDEF,
NET_PCI,
@@ -193,62 +152,6 @@ struct virtfn_info {
char suffix[IFNAMSIZ];
};
-static const NamingScheme* naming_scheme_from_name(const char *name) {
- size_t i;
-
- if (streq(name, "latest"))
- return naming_schemes + ELEMENTSOF(naming_schemes) - 1;
-
- for (i = 0; i < ELEMENTSOF(naming_schemes); i++)
- if (streq(naming_schemes[i].name, name))
- return naming_schemes + i;
-
- return NULL;
-}
-
-static const NamingScheme* naming_scheme(void) {
- static const NamingScheme *cache = NULL;
- _cleanup_free_ char *buffer = NULL;
- const char *e, *k;
-
- if (cache)
- return cache;
-
- /* Acquire setting from the kernel command line */
- (void) proc_cmdline_get_key("net.naming-scheme", 0, &buffer);
-
- /* Also acquire it from an env var */
- e = getenv("NET_NAMING_SCHEME");
- if (e) {
- if (*e == ':') {
- /* If prefixed with ':' the kernel cmdline takes precedence */
- k = buffer ?: e + 1;
- } else
- k = e; /* Otherwise the env var takes precedence */
- } else
- k = buffer;
-
- if (k) {
- cache = naming_scheme_from_name(k);
- if (cache) {
- log_info("Using interface naming scheme '%s'.", cache->name);
- return cache;
- }
-
- log_warning("Unknown interface naming scheme '%s' requested, ignoring.", k);
- }
-
- cache = naming_scheme_from_name(DEFAULT_NET_NAMING_SCHEME);
- assert(cache);
- log_info("Using default interface naming scheme '%s'.", cache->name);
-
- return cache;
-}
-
-static bool naming_scheme_has(NamingSchemeFlags flags) {
- return FLAGS_SET(naming_scheme()->flags, flags);
-}
-
/* skip intermediate virtio devices */
static sd_device *skip_virtio(sd_device *dev) {
sd_device *parent;
@@ -460,7 +363,7 @@ static int dev_pci_slot(sd_device *dev, struct netnames *names) {
}
}
- /* kernel provided front panel port name for multiple port PCI device */
+ /* kernel provided front panel port name for multi-port PCI device */
(void) sd_device_get_sysattr_value(dev, "phys_port_name", &port_name);
/* compose a name based on the raw kernel's PCI bus, slot numbers */
@@ -478,7 +381,7 @@ static int dev_pci_slot(sd_device *dev, struct netnames *names) {
if (l == 0)
names->pci_path[0] = '\0';
- /* ACPI _SUN — slot user number */
+ /* ACPI _SUN — slot user number */
r = sd_device_new_from_subsystem_sysname(&pci, "subsystem", "pci");
if (r < 0)
return r;
diff --git a/src/udev/udev-builtin-net_setup_link.c b/src/udev/udev-builtin-net_setup_link.c
index c0d3d4aa01..a845dfa5c1 100644
--- a/src/udev/udev-builtin-net_setup_link.c
+++ b/src/udev/udev-builtin-net_setup_link.c
@@ -16,7 +16,7 @@ static int builtin_net_setup_link(sd_device *dev, int argc, char **argv, bool te
int r;
if (argc > 1)
- return log_device_error_errno(dev, EINVAL, "This program takes no arguments.");
+ return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments.");
r = link_get_driver(ctx, dev, &driver);
if (r >= 0)
diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
index 94f2740592..7ce1c5644f 100644
--- a/src/udev/udev-builtin-path_id.c
+++ b/src/udev/udev-builtin-path_id.c
@@ -110,7 +110,6 @@ static sd_device *handle_scsi_fibre_channel(sd_device *parent, char **path) {
assert(parent);
assert(path);
-
if (sd_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target", &targetdev) < 0)
return NULL;
if (sd_device_get_sysname(targetdev, &sysname) < 0)
diff --git a/src/udev/udev-builtin.c b/src/udev/udev-builtin.c
index 3a61be10ca..48ce295a46 100644
--- a/src/udev/udev-builtin.c
+++ b/src/udev/udev-builtin.c
@@ -139,7 +139,7 @@ int udev_builtin_add_property(sd_device *dev, bool test, const char *key, const
key, val ? "=" : "", strempty(val));
if (test)
- printf("%s=%s\n", key, val);
+ printf("%s=%s\n", key, strempty(val));
return 0;
}
diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c
index d90ebb7259..c217815ac6 100644
--- a/src/udev/udev-ctrl.c
+++ b/src/udev/udev-ctrl.c
@@ -213,14 +213,12 @@ static struct udev_ctrl_connection *udev_ctrl_connection_free(struct udev_ctrl_c
DEFINE_TRIVIAL_REF_UNREF_FUNC(struct udev_ctrl_connection, udev_ctrl_connection, udev_ctrl_connection_free);
-static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int intval, const char *buf, int timeout) {
- struct udev_ctrl_msg_wire ctrl_msg_wire;
- int err = 0;
-
- memzero(&ctrl_msg_wire, sizeof(struct udev_ctrl_msg_wire));
- strcpy(ctrl_msg_wire.version, "udev-" PACKAGE_VERSION);
- ctrl_msg_wire.magic = UDEV_CTRL_MAGIC;
- ctrl_msg_wire.type = type;
+static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int intval, const char *buf, usec_t timeout) {
+ struct udev_ctrl_msg_wire ctrl_msg_wire = {
+ .version = "udev-" STRINGIFY(PROJECT_VERSION),
+ .magic = UDEV_CTRL_MAGIC,
+ .type = type,
+ };
if (buf)
strscpy(ctrl_msg_wire.buf, sizeof(ctrl_msg_wire.buf), buf);
@@ -228,74 +226,64 @@ static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int
ctrl_msg_wire.intval = intval;
if (!uctrl->connected) {
- if (connect(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen) < 0) {
- err = -errno;
- goto out;
- }
+ if (connect(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen) < 0)
+ return -errno;
uctrl->connected = true;
}
- if (send(uctrl->sock, &ctrl_msg_wire, sizeof(ctrl_msg_wire), 0) < 0) {
- err = -errno;
- goto out;
- }
+ if (send(uctrl->sock, &ctrl_msg_wire, sizeof(ctrl_msg_wire), 0) < 0)
+ return -errno;
/* wait for peer message handling or disconnect */
for (;;) {
- struct pollfd pfd[1];
+ struct pollfd pfd = {
+ .fd = uctrl->sock,
+ .events = POLLIN,
+ };
int r;
- pfd[0].fd = uctrl->sock;
- pfd[0].events = POLLIN;
- r = poll(pfd, 1, timeout * MSEC_PER_SEC);
+ r = poll(&pfd, 1, DIV_ROUND_UP(timeout, USEC_PER_MSEC));
if (r < 0) {
if (errno == EINTR)
continue;
- err = -errno;
- break;
- }
-
- if (r > 0 && pfd[0].revents & POLLERR) {
- err = -EIO;
- break;
+ return -errno;
}
-
if (r == 0)
- err = -ETIMEDOUT;
- break;
+ return -ETIMEDOUT;
+ if (pfd.revents & POLLERR)
+ return -EIO;
+ return 0;
}
-out:
- return err;
}
-int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, int timeout) {
+int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, usec_t timeout) {
return ctrl_send(uctrl, UDEV_CTRL_SET_LOG_LEVEL, priority, NULL, timeout);
}
-int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, int timeout) {
+int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, usec_t timeout) {
return ctrl_send(uctrl, UDEV_CTRL_STOP_EXEC_QUEUE, 0, NULL, timeout);
}
-int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, int timeout) {
+int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, usec_t timeout) {
return ctrl_send(uctrl, UDEV_CTRL_START_EXEC_QUEUE, 0, NULL, timeout);
}
-int udev_ctrl_send_reload(struct udev_ctrl *uctrl, int timeout) {
+int udev_ctrl_send_reload(struct udev_ctrl *uctrl, usec_t timeout) {
return ctrl_send(uctrl, UDEV_CTRL_RELOAD, 0, NULL, timeout);
}
-int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, int timeout) {
+int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, usec_t timeout) {
return ctrl_send(uctrl, UDEV_CTRL_SET_ENV, 0, key, timeout);
}
-int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, int timeout) {
+int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, usec_t timeout) {
return ctrl_send(uctrl, UDEV_CTRL_SET_CHILDREN_MAX, count, NULL, timeout);
}
-int udev_ctrl_send_ping(struct udev_ctrl *uctrl, int timeout) {
+int udev_ctrl_send_ping(struct udev_ctrl *uctrl, usec_t timeout) {
return ctrl_send(uctrl, UDEV_CTRL_PING, 0, NULL, timeout);
}
-int udev_ctrl_send_exit(struct udev_ctrl *uctrl, int timeout) {
+int udev_ctrl_send_exit(struct udev_ctrl *uctrl, usec_t timeout) {
return ctrl_send(uctrl, UDEV_CTRL_EXIT, 0, NULL, timeout);
}
diff --git a/src/udev/udev-ctrl.h b/src/udev/udev-ctrl.h
index 87021cb880..8e452a4249 100644
--- a/src/udev/udev-ctrl.h
+++ b/src/udev/udev-ctrl.h
@@ -2,6 +2,7 @@
#pragma once
#include "macro.h"
+#include "time-util.h"
struct udev_ctrl;
struct udev_ctrl *udev_ctrl_new(void);
@@ -10,14 +11,14 @@ int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl);
struct udev_ctrl *udev_ctrl_unref(struct udev_ctrl *uctrl);
int udev_ctrl_cleanup(struct udev_ctrl *uctrl);
int udev_ctrl_get_fd(struct udev_ctrl *uctrl);
-int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, int timeout);
-int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, int timeout);
-int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, int timeout);
-int udev_ctrl_send_reload(struct udev_ctrl *uctrl, int timeout);
-int udev_ctrl_send_ping(struct udev_ctrl *uctrl, int timeout);
-int udev_ctrl_send_exit(struct udev_ctrl *uctrl, int timeout);
-int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, int timeout);
-int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, int timeout);
+int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, usec_t timeout);
+int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, usec_t timeout);
+int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, usec_t timeout);
+int udev_ctrl_send_reload(struct udev_ctrl *uctrl, usec_t timeout);
+int udev_ctrl_send_ping(struct udev_ctrl *uctrl, usec_t timeout);
+int udev_ctrl_send_exit(struct udev_ctrl *uctrl, usec_t timeout);
+int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, usec_t timeout);
+int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, usec_t timeout);
struct udev_ctrl_connection;
struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl);
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index e28d6a5d08..07b7365e3a 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -504,38 +504,34 @@ static int on_spawn_timeout_warning(sd_event_source *s, uint64_t usec, void *use
static int on_spawn_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata) {
Spawn *spawn = userdata;
+ int ret = -EIO;
assert(spawn);
switch (si->si_code) {
case CLD_EXITED:
- if (si->si_status == 0) {
+ if (si->si_status == 0)
log_debug("Process '%s' succeeded.", spawn->cmd);
- sd_event_exit(sd_event_source_get_event(s), 0);
-
- return 1;
- }
-
- log_full(spawn->accept_failure ? LOG_DEBUG : LOG_WARNING,
- "Process '%s' failed with exit code %i.", spawn->cmd, si->si_status);
+ else
+ log_full(spawn->accept_failure ? LOG_DEBUG : LOG_WARNING,
+ "Process '%s' failed with exit code %i.", spawn->cmd, si->si_status);
+ ret = si->si_status;
break;
case CLD_KILLED:
case CLD_DUMPED:
- log_warning("Process '%s' terminated by signal %s.", spawn->cmd, signal_to_string(si->si_status));
-
+ log_error("Process '%s' terminated by signal %s.", spawn->cmd, signal_to_string(si->si_status));
break;
default:
log_error("Process '%s' failed due to unknown reason.", spawn->cmd);
}
- sd_event_exit(sd_event_source_get_event(s), -EIO);
-
+ sd_event_exit(sd_event_source_get_event(s), ret);
return 1;
}
static int spawn_wait(Spawn *spawn) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
- int r, ret;
+ int r;
assert(spawn);
@@ -570,27 +566,23 @@ static int spawn_wait(Spawn *spawn) {
}
}
- r = sd_event_add_io(e, NULL, spawn->fd_stdout, EPOLLIN, on_spawn_io, spawn);
- if (r < 0)
- return r;
+ if (spawn->fd_stdout >= 0) {
+ r = sd_event_add_io(e, NULL, spawn->fd_stdout, EPOLLIN, on_spawn_io, spawn);
+ if (r < 0)
+ return r;
+ }
- r = sd_event_add_io(e, NULL, spawn->fd_stderr, EPOLLIN, on_spawn_io, spawn);
- if (r < 0)
- return r;
+ if (spawn->fd_stderr >= 0) {
+ r = sd_event_add_io(e, NULL, spawn->fd_stderr, EPOLLIN, on_spawn_io, spawn);
+ if (r < 0)
+ return r;
+ }
r = sd_event_add_child(e, NULL, spawn->pid, WEXITED, on_spawn_sigchld, spawn);
if (r < 0)
return r;
- r = sd_event_loop(e);
- if (r < 0)
- return r;
-
- r = sd_event_get_exit_code(e, &ret);
- if (r < 0)
- return r;
-
- return ret;
+ return sd_event_loop(e);
}
int udev_event_spawn(UdevEvent *event,
@@ -675,12 +667,12 @@ int udev_event_spawn(UdevEvent *event,
};
r = spawn_wait(&spawn);
if (r < 0)
- return log_error_errno(r, "Failed to wait spawned command '%s': %m", cmd);
+ return log_error_errno(r, "Failed to wait for spawned command '%s': %m", cmd);
if (result)
result[spawn.result_len] = '\0';
- return r;
+ return r; /* 0 for success, and positive if the program failed */
}
static int rename_netif(UdevEvent *event) {
@@ -895,7 +887,7 @@ void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec) {
(void) usleep(event->exec_delay_usec);
}
- udev_event_spawn(event, timeout_usec, false, command, NULL, 0);
+ (void) udev_event_spawn(event, timeout_usec, false, command, NULL, 0);
}
}
}
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index c11eb8c1ac..1c00dd1e9e 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -181,6 +181,9 @@ static int link_find_prioritized(sd_device *dev, bool add, const char *stackdir,
priority = db_prio;
}
+ if (!target)
+ return -ENOENT;
+
*ret = TAKE_PTR(target);
return 0;
}
@@ -297,7 +300,7 @@ static int node_permissions_apply(sd_device *dev, bool apply,
return log_device_debug_errno(dev, errno, "cannot stat() node '%s' (%m)", devnode);
if (((stats.st_mode & S_IFMT) != (mode & S_IFMT)) || (stats.st_rdev != devnum))
- return log_device_debug_errno(dev, EEXIST, "Found node '%s' with non-matching devnum %s, skip handling",
+ return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EEXIST), "Found node '%s' with non-matching devnum %s, skip handling",
devnode, id_filename);
if (apply) {
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
index 53c68d254a..bc9c6c26c5 100644
--- a/src/udev/udev-rules.c
+++ b/src/udev/udev-rules.c
@@ -441,8 +441,8 @@ static void dump_rules(UdevRules *rules) {
dump_token(rules, &rules->tokens[i]);
}
#else
-static inline void dump_token(UdevRules *rules, struct token *token) {}
-static inline void dump_rules(UdevRules *rules) {}
+static void dump_token(UdevRules *rules, struct token *token) {}
+static void dump_rules(UdevRules *rules) {}
#endif /* ENABLE_DEBUG_UDEV */
static int add_token(UdevRules *rules, struct token *token) {
@@ -645,11 +645,13 @@ static int import_program_into_properties(UdevEvent *event,
const char *program) {
char result[UTIL_LINE_SIZE];
char *line;
- int err;
+ int r;
- err = udev_event_spawn(event, timeout_usec, true, program, result, sizeof(result));
- if (err < 0)
- return err;
+ r = udev_event_spawn(event, timeout_usec, false, program, result, sizeof result);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ return -EIO;
line = result;
while (line) {
@@ -831,13 +833,15 @@ static const char *get_key_attribute(char *str) {
return NULL;
}
-static void rule_add_key(struct rule_tmp *rule_tmp, enum token_type type,
- enum operation_type op,
- const char *value, const void *data) {
+static int rule_add_key(struct rule_tmp *rule_tmp, enum token_type type,
+ enum operation_type op,
+ const char *value, const void *data) {
struct token *token = rule_tmp->token + rule_tmp->token_cur;
const char *attr = NULL;
- assert(rule_tmp->token_cur < ELEMENTSOF(rule_tmp->token));
+ if (rule_tmp->token_cur >= ELEMENTSOF(rule_tmp->token))
+ return -E2BIG;
+
memzero(token, sizeof(struct token));
switch (type) {
@@ -968,6 +972,8 @@ static void rule_add_key(struct rule_tmp *rule_tmp, enum token_type type,
token->key.type = type;
token->key.op = op;
rule_tmp->token_cur++;
+
+ return 0;
}
static int sort_token(UdevRules *rules, struct rule_tmp *rule_tmp) {
@@ -1009,6 +1015,7 @@ static int sort_token(UdevRules *rules, struct rule_tmp *rule_tmp) {
#define LOG_RULE_WARNING(fmt, ...) LOG_RULE_FULL(LOG_WARNING, fmt, ##__VA_ARGS__)
#define LOG_RULE_DEBUG(fmt, ...) LOG_RULE_FULL(LOG_DEBUG, fmt, ##__VA_ARGS__)
#define LOG_AND_RETURN(fmt, ...) { LOG_RULE_ERROR(fmt, __VA_ARGS__); return; }
+#define LOG_AND_RETURN_ADD_KEY LOG_AND_RETURN("Temporary rule array too small, aborting event processing with %u items", rule_tmp.token_cur);
static void add_rule(UdevRules *rules, char *line,
const char *filename, unsigned filename_off, unsigned lineno) {
@@ -1018,6 +1025,7 @@ static void add_rule(UdevRules *rules, char *line,
.rules = rules,
.rule.type = TK_RULE,
};
+ int r;
/* the offset in the rule is limited to unsigned short */
if (filename_off < USHRT_MAX)
@@ -1051,26 +1059,26 @@ static void add_rule(UdevRules *rules, char *line,
break;
}
- if (rule_tmp.token_cur >= ELEMENTSOF(rule_tmp.token))
- LOG_AND_RETURN("Temporary rule array too small, aborting event processing with %u items", rule_tmp.token_cur);
-
if (streq(key, "ACTION")) {
if (op > OP_MATCH_MAX)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_M_ACTION, op, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_M_ACTION, op, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "DEVPATH")) {
if (op > OP_MATCH_MAX)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_M_DEVPATH, op, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_M_DEVPATH, op, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "KERNEL")) {
if (op > OP_MATCH_MAX)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_M_KERNEL, op, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_M_KERNEL, op, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "SUBSYSTEM")) {
if (op > OP_MATCH_MAX)
@@ -1081,15 +1089,18 @@ static void add_rule(UdevRules *rules, char *line,
if (!streq(value, "subsystem"))
LOG_RULE_WARNING("'%s' must be specified as 'subsystem'; please fix", value);
- rule_add_key(&rule_tmp, TK_M_SUBSYSTEM, op, "subsystem|class|bus", NULL);
+ r = rule_add_key(&rule_tmp, TK_M_SUBSYSTEM, op, "subsystem|class|bus", NULL);
} else
- rule_add_key(&rule_tmp, TK_M_SUBSYSTEM, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_M_SUBSYSTEM, op, value, NULL);
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "DRIVER")) {
if (op > OP_MATCH_MAX)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_M_DRIVER, op, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_M_DRIVER, op, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (startswith(key, "ATTR{")) {
attr = get_key_attribute(key + STRLEN("ATTR"));
@@ -1100,9 +1111,11 @@ static void add_rule(UdevRules *rules, char *line,
LOG_AND_RETURN("Invalid %s operation", "ATTR");
if (op < OP_MATCH_MAX)
- rule_add_key(&rule_tmp, TK_M_ATTR, op, value, attr);
+ r = rule_add_key(&rule_tmp, TK_M_ATTR, op, value, attr);
else
- rule_add_key(&rule_tmp, TK_A_ATTR, op, value, attr);
+ r = rule_add_key(&rule_tmp, TK_A_ATTR, op, value, attr);
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (startswith(key, "SYSCTL{")) {
attr = get_key_attribute(key + STRLEN("SYSCTL"));
@@ -1113,9 +1126,11 @@ static void add_rule(UdevRules *rules, char *line,
LOG_AND_RETURN("Invalid %s operation", "ATTR");
if (op < OP_MATCH_MAX)
- rule_add_key(&rule_tmp, TK_M_SYSCTL, op, value, attr);
+ r = rule_add_key(&rule_tmp, TK_M_SYSCTL, op, value, attr);
else
- rule_add_key(&rule_tmp, TK_A_SYSCTL, op, value, attr);
+ r = rule_add_key(&rule_tmp, TK_A_SYSCTL, op, value, attr);
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (startswith(key, "SECLABEL{")) {
attr = get_key_attribute(key + STRLEN("SECLABEL"));
@@ -1125,25 +1140,29 @@ static void add_rule(UdevRules *rules, char *line,
if (op == OP_REMOVE)
LOG_AND_RETURN("Invalid %s operation", "SECLABEL");
- rule_add_key(&rule_tmp, TK_A_SECLABEL, op, value, attr);
+ if (rule_add_key(&rule_tmp, TK_A_SECLABEL, op, value, attr) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "KERNELS")) {
if (op > OP_MATCH_MAX)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_M_KERNELS, op, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_M_KERNELS, op, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "SUBSYSTEMS")) {
if (op > OP_MATCH_MAX)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_M_SUBSYSTEMS, op, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_M_SUBSYSTEMS, op, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "DRIVERS")) {
if (op > OP_MATCH_MAX)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_M_DRIVERS, op, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_M_DRIVERS, op, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (startswith(key, "ATTRS{")) {
if (op > OP_MATCH_MAX)
@@ -1157,13 +1176,15 @@ static void add_rule(UdevRules *rules, char *line,
LOG_RULE_WARNING("'device' link may not be available in future kernels; please fix");
if (strstr(attr, "../"))
LOG_RULE_WARNING("Direct reference to parent sysfs directory, may break in future kernels; please fix");
- rule_add_key(&rule_tmp, TK_M_ATTRS, op, value, attr);
+ if (rule_add_key(&rule_tmp, TK_M_ATTRS, op, value, attr) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "TAGS")) {
if (op > OP_MATCH_MAX)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_M_TAGS, op, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_M_TAGS, op, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (startswith(key, "ENV{")) {
attr = get_key_attribute(key + STRLEN("ENV"));
@@ -1174,7 +1195,7 @@ static void add_rule(UdevRules *rules, char *line,
LOG_AND_RETURN("Invalid %s operation", "ENV");
if (op < OP_MATCH_MAX)
- rule_add_key(&rule_tmp, TK_M_ENV, op, value, attr);
+ r = rule_add_key(&rule_tmp, TK_M_ENV, op, value, attr);
else {
if (STR_IN_SET(attr,
"ACTION",
@@ -1190,26 +1211,32 @@ static void add_rule(UdevRules *rules, char *line,
"TAGS"))
LOG_AND_RETURN("Invalid ENV attribute, '%s' cannot be set", attr);
- rule_add_key(&rule_tmp, TK_A_ENV, op, value, attr);
+ r = rule_add_key(&rule_tmp, TK_A_ENV, op, value, attr);
}
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "TAG")) {
if (op < OP_MATCH_MAX)
- rule_add_key(&rule_tmp, TK_M_TAG, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_M_TAG, op, value, NULL);
else
- rule_add_key(&rule_tmp, TK_A_TAG, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_A_TAG, op, value, NULL);
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "PROGRAM")) {
if (op == OP_REMOVE)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_M_PROGRAM, op, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_M_PROGRAM, op, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "RESULT")) {
if (op > OP_MATCH_MAX)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_M_RESULT, op, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_M_RESULT, op, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (startswith(key, "IMPORT")) {
attr = get_key_attribute(key + STRLEN("IMPORT"));
@@ -1227,28 +1254,34 @@ static void add_rule(UdevRules *rules, char *line,
if (cmd >= 0) {
LOG_RULE_DEBUG("IMPORT found builtin '%s', replacing", value);
- rule_add_key(&rule_tmp, TK_M_IMPORT_BUILTIN, op, value, &cmd);
+ if (rule_add_key(&rule_tmp, TK_M_IMPORT_BUILTIN, op, value, &cmd) < 0)
+ LOG_AND_RETURN_ADD_KEY;
continue;
}
}
- rule_add_key(&rule_tmp, TK_M_IMPORT_PROG, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_M_IMPORT_PROG, op, value, NULL);
} else if (streq(attr, "builtin")) {
const enum udev_builtin_cmd cmd = udev_builtin_lookup(value);
- if (cmd < 0)
- LOG_RULE_WARNING("IMPORT{builtin} '%s' unknown", value);
- else
- rule_add_key(&rule_tmp, TK_M_IMPORT_BUILTIN, op, value, &cmd);
+ if (cmd < 0) {
+ LOG_RULE_WARNING("IMPORT{builtin} '%s' unknown, ignoring", value);
+ continue;
+ } else
+ r = rule_add_key(&rule_tmp, TK_M_IMPORT_BUILTIN, op, value, &cmd);
} else if (streq(attr, "file"))
- rule_add_key(&rule_tmp, TK_M_IMPORT_FILE, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_M_IMPORT_FILE, op, value, NULL);
else if (streq(attr, "db"))
- rule_add_key(&rule_tmp, TK_M_IMPORT_DB, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_M_IMPORT_DB, op, value, NULL);
else if (streq(attr, "cmdline"))
- rule_add_key(&rule_tmp, TK_M_IMPORT_CMDLINE, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_M_IMPORT_CMDLINE, op, value, NULL);
else if (streq(attr, "parent"))
- rule_add_key(&rule_tmp, TK_M_IMPORT_PARENT, op, value, NULL);
- else
+ r = rule_add_key(&rule_tmp, TK_M_IMPORT_PARENT, op, value, NULL);
+ else {
LOG_RULE_ERROR("Ignoring unknown %s{} type '%s'", "IMPORT", attr);
+ continue;
+ }
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (startswith(key, "TEST")) {
mode_t mode = 0;
@@ -1259,9 +1292,11 @@ static void add_rule(UdevRules *rules, char *line,
attr = get_key_attribute(key + STRLEN("TEST"));
if (attr) {
mode = strtol(attr, NULL, 8);
- rule_add_key(&rule_tmp, TK_M_TEST, op, value, &mode);
+ r = rule_add_key(&rule_tmp, TK_M_TEST, op, value, &mode);
} else
- rule_add_key(&rule_tmp, TK_M_TEST, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_M_TEST, op, value, NULL);
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (startswith(key, "RUN")) {
attr = get_key_attribute(key + STRLEN("RUN"));
@@ -1273,16 +1308,21 @@ static void add_rule(UdevRules *rules, char *line,
if (streq(attr, "builtin")) {
const enum udev_builtin_cmd cmd = udev_builtin_lookup(value);
- if (cmd < 0)
- LOG_RULE_ERROR("RUN{builtin}: '%s' unknown", value);
- else
- rule_add_key(&rule_tmp, TK_A_RUN_BUILTIN, op, value, &cmd);
+ if (cmd < 0) {
+ LOG_RULE_ERROR("RUN{builtin}: '%s' unknown, ignoring", value);
+ continue;
+ } else
+ r = rule_add_key(&rule_tmp, TK_A_RUN_BUILTIN, op, value, &cmd);
} else if (streq(attr, "program")) {
const enum udev_builtin_cmd cmd = _UDEV_BUILTIN_MAX;
- rule_add_key(&rule_tmp, TK_A_RUN_PROGRAM, op, value, &cmd);
- } else
+ r = rule_add_key(&rule_tmp, TK_A_RUN_PROGRAM, op, value, &cmd);
+ } else {
LOG_RULE_ERROR("Ignoring unknown %s{} type '%s'", "RUN", attr);
+ continue;
+ }
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (streq(key, "LABEL")) {
if (op == OP_REMOVE)
@@ -1294,14 +1334,15 @@ static void add_rule(UdevRules *rules, char *line,
if (op == OP_REMOVE)
LOG_AND_RETURN("Invalid %s operation", key);
- rule_add_key(&rule_tmp, TK_A_GOTO, 0, value, NULL);
+ if (rule_add_key(&rule_tmp, TK_A_GOTO, 0, value, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else if (startswith(key, "NAME")) {
if (op == OP_REMOVE)
LOG_AND_RETURN("Invalid %s operation", key);
if (op < OP_MATCH_MAX)
- rule_add_key(&rule_tmp, TK_M_NAME, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_M_NAME, op, value, NULL);
else {
if (streq(value, "%k")) {
LOG_RULE_WARNING("NAME=\"%%k\" is ignored, because it breaks kernel supplied names; please remove");
@@ -1311,8 +1352,10 @@ static void add_rule(UdevRules *rules, char *line,
LOG_RULE_DEBUG("NAME=\"\" is ignored, because udev will not delete any device nodes; please remove");
continue;
}
- rule_add_key(&rule_tmp, TK_A_NAME, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_A_NAME, op, value, NULL);
}
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
rule_tmp.rule.rule.can_set_name = true;
} else if (streq(key, "SYMLINK")) {
@@ -1320,9 +1363,11 @@ static void add_rule(UdevRules *rules, char *line,
LOG_AND_RETURN("Invalid %s operation", key);
if (op < OP_MATCH_MAX)
- rule_add_key(&rule_tmp, TK_M_DEVLINK, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_M_DEVLINK, op, value, NULL);
else
- rule_add_key(&rule_tmp, TK_A_DEVLINK, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_A_DEVLINK, op, value, NULL);
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
rule_tmp.rule.rule.can_set_name = true;
} else if (streq(key, "OWNER")) {
@@ -1334,12 +1379,18 @@ static void add_rule(UdevRules *rules, char *line,
uid = strtoul(value, &endptr, 10);
if (endptr[0] == '\0')
- rule_add_key(&rule_tmp, TK_A_OWNER_ID, op, NULL, &uid);
+ r = rule_add_key(&rule_tmp, TK_A_OWNER_ID, op, NULL, &uid);
else if (rules->resolve_name_timing == RESOLVE_NAME_EARLY && !strchr("$%", value[0])) {
uid = add_uid(rules, value);
- rule_add_key(&rule_tmp, TK_A_OWNER_ID, op, NULL, &uid);
+ r = rule_add_key(&rule_tmp, TK_A_OWNER_ID, op, NULL, &uid);
} else if (rules->resolve_name_timing != RESOLVE_NAME_NEVER)
- rule_add_key(&rule_tmp, TK_A_OWNER, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_A_OWNER, op, value, NULL);
+ else {
+ LOG_RULE_ERROR("Invalid %s operation", key);
+ continue;
+ }
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
rule_tmp.rule.rule.can_set_name = true;
@@ -1352,12 +1403,18 @@ static void add_rule(UdevRules *rules, char *line,
gid = strtoul(value, &endptr, 10);
if (endptr[0] == '\0')
- rule_add_key(&rule_tmp, TK_A_GROUP_ID, op, NULL, &gid);
+ r = rule_add_key(&rule_tmp, TK_A_GROUP_ID, op, NULL, &gid);
else if ((rules->resolve_name_timing == RESOLVE_NAME_EARLY) && !strchr("$%", value[0])) {
gid = add_gid(rules, value);
- rule_add_key(&rule_tmp, TK_A_GROUP_ID, op, NULL, &gid);
+ r = rule_add_key(&rule_tmp, TK_A_GROUP_ID, op, NULL, &gid);
} else if (rules->resolve_name_timing != RESOLVE_NAME_NEVER)
- rule_add_key(&rule_tmp, TK_A_GROUP, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_A_GROUP, op, value, NULL);
+ else {
+ LOG_RULE_ERROR("Invalid %s operation", key);
+ continue;
+ }
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
rule_tmp.rule.rule.can_set_name = true;
@@ -1370,9 +1427,12 @@ static void add_rule(UdevRules *rules, char *line,
mode = strtol(value, &endptr, 8);
if (endptr[0] == '\0')
- rule_add_key(&rule_tmp, TK_A_MODE_ID, op, NULL, &mode);
+ r = rule_add_key(&rule_tmp, TK_A_MODE_ID, op, NULL, &mode);
else
- rule_add_key(&rule_tmp, TK_A_MODE, op, value, NULL);
+ r = rule_add_key(&rule_tmp, TK_A_MODE, op, value, NULL);
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
+
rule_tmp.rule.rule.can_set_name = true;
} else if (streq(key, "OPTIONS")) {
@@ -1385,37 +1445,48 @@ static void add_rule(UdevRules *rules, char *line,
if (pos) {
int prio = atoi(pos + STRLEN("link_priority="));
- rule_add_key(&rule_tmp, TK_A_DEVLINK_PRIO, op, NULL, &prio);
+ if (rule_add_key(&rule_tmp, TK_A_DEVLINK_PRIO, op, NULL, &prio) < 0)
+ LOG_AND_RETURN_ADD_KEY;
}
pos = strstr(value, "string_escape=");
if (pos) {
pos += STRLEN("string_escape=");
if (startswith(pos, "none"))
- rule_add_key(&rule_tmp, TK_A_STRING_ESCAPE_NONE, op, NULL, NULL);
+ r = rule_add_key(&rule_tmp, TK_A_STRING_ESCAPE_NONE, op, NULL, NULL);
else if (startswith(pos, "replace"))
- rule_add_key(&rule_tmp, TK_A_STRING_ESCAPE_REPLACE, op, NULL, NULL);
+ r = rule_add_key(&rule_tmp, TK_A_STRING_ESCAPE_REPLACE, op, NULL, NULL);
+ else {
+ LOG_RULE_ERROR("OPTIONS: unknown string_escape mode '%s', ignoring", pos);
+ r = 0;
+ }
+ if (r < 0)
+ LOG_AND_RETURN_ADD_KEY;
}
pos = strstr(value, "db_persist");
if (pos)
- rule_add_key(&rule_tmp, TK_A_DB_PERSIST, op, NULL, NULL);
+ if (rule_add_key(&rule_tmp, TK_A_DB_PERSIST, op, NULL, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
pos = strstr(value, "nowatch");
if (pos) {
static const int zero = 0;
- rule_add_key(&rule_tmp, TK_A_INOTIFY_WATCH, op, NULL, &zero);
+ if (rule_add_key(&rule_tmp, TK_A_INOTIFY_WATCH, op, NULL, &zero) < 0)
+ LOG_AND_RETURN_ADD_KEY;
} else {
static const int one = 1;
pos = strstr(value, "watch");
if (pos)
- rule_add_key(&rule_tmp, TK_A_INOTIFY_WATCH, op, NULL, &one);
+ if (rule_add_key(&rule_tmp, TK_A_INOTIFY_WATCH, op, NULL, &one) < 0)
+ LOG_AND_RETURN_ADD_KEY;
}
pos = strstr(value, "static_node=");
if (pos) {
pos += STRLEN("static_node=");
- rule_add_key(&rule_tmp, TK_A_STATIC_NODE, op, pos, NULL);
+ if (rule_add_key(&rule_tmp, TK_A_STATIC_NODE, op, pos, NULL) < 0)
+ LOG_AND_RETURN_ADD_KEY;
rule_tmp.rule.rule.has_static_node = true;
}
@@ -1959,7 +2030,7 @@ int udev_rules_apply_to_event(
rules_str(rules, rule->rule.filename_off),
rule->rule.filename_line);
- if (udev_event_spawn(event, timeout_usec, true, program, result, sizeof(result)) < 0) {
+ if (udev_event_spawn(event, timeout_usec, true, program, result, sizeof(result)) != 0) {
if (cur->key.op != OP_NOMATCH)
goto nomatch;
} else {
@@ -2229,13 +2300,12 @@ int udev_rules_apply_to_event(
r = hashmap_put(event->seclabel_list, name, label);
if (r < 0)
return log_oom();
-
- name = label = NULL;
-
log_device_debug(dev, "SECLABEL{%s}='%s' %s:%u",
name, label,
rules_str(rules, rule->rule.filename_off),
rule->rule.filename_line);
+ name = label = NULL;
+
break;
}
case TK_A_ENV: {
diff --git a/src/udev/udev.pc.in b/src/udev/udev.pc.in
index e384a6f7c9..5acbb2d01a 100644
--- a/src/udev/udev.pc.in
+++ b/src/udev/udev.pc.in
@@ -1,5 +1,5 @@
Name: udev
Description: udev
-Version: @PACKAGE_VERSION@
+Version: @PROJECT_VERSION@
udevdir=@udevlibexecdir@
diff --git a/src/udev/udevadm-control.c b/src/udev/udevadm-control.c
index d9320418cf..7cfc4c929d 100644
--- a/src/udev/udevadm-control.c
+++ b/src/udev/udevadm-control.c
@@ -26,6 +26,7 @@
#include "udevadm.h"
#include "udev-ctrl.h"
#include "util.h"
+#include "virt.h"
static int help(void) {
printf("%s control OPTION\n\n"
@@ -39,6 +40,7 @@ static int help(void) {
" -R --reload Reload rules and databases\n"
" -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"
, program_invocation_short_name);
@@ -47,22 +49,27 @@ static int help(void) {
int control_main(int argc, char *argv[], void *userdata) {
_cleanup_(udev_ctrl_unrefp) struct udev_ctrl *uctrl = NULL;
- int timeout = 60;
+ usec_t timeout = 60 * USEC_PER_SEC;
int c, r;
+ enum {
+ ARG_PING = 0x100,
+ };
+
static const struct option options[] = {
- { "exit", no_argument, NULL, 'e' },
- { "log-priority", required_argument, NULL, 'l' },
- { "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' },
- { "timeout", required_argument, NULL, 't' },
- { "version", no_argument, NULL, 'V' },
- { "help", no_argument, NULL, 'h' },
+ { "exit", no_argument, NULL, 'e' },
+ { "log-priority", required_argument, NULL, 'l' },
+ { "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' },
{}
};
@@ -70,12 +77,18 @@ int control_main(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
+ if (running_in_chroot() > 0) {
+ log_info("Running in chroot, ignoring request.");
+ return 0;
+ }
+
if (argc <= 1)
- log_error("Option missing");
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "This command expects one or more options.");
uctrl = udev_ctrl_new();
if (!uctrl)
- return -ENOMEM;
+ return log_oom();
while ((c = getopt_long(argc, argv, "el:sSRp:m:t:Vh", options, NULL)) >= 0)
switch (c) {
@@ -109,10 +122,9 @@ int control_main(int argc, char *argv[], void *userdata) {
return r;
break;
case 'p':
- if (!strchr(optarg, '=')) {
- log_error("expect <KEY>=<value> instead of '%s'", optarg);
- return -EINVAL;
- }
+ if (!strchr(optarg, '='))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "expect <KEY>=<value> instead of '%s'", optarg);
+
r = udev_ctrl_send_set_env(uctrl, optarg, timeout);
if (r < 0)
return r;
@@ -129,19 +141,16 @@ int control_main(int argc, char *argv[], void *userdata) {
return r;
break;
}
- case 't': {
- usec_t s;
-
- r = parse_sec(optarg, &s);
+ case ARG_PING:
+ r = udev_ctrl_send_ping(uctrl, timeout);
if (r < 0)
- return log_error_errno(r, "Failed to parse timeout value '%s'.", optarg);
-
- if (DIV_ROUND_UP(s, USEC_PER_SEC) > INT_MAX)
- log_error("Timeout value is out of range, ignoring.");
- else
- timeout = s != USEC_INFINITY ? (int) DIV_ROUND_UP(s, USEC_PER_SEC) : INT_MAX;
+ return log_error_errno(r, "Failed to connect to udev daemon: %m");
+ break;
+ case 't':
+ r = parse_sec(optarg, &timeout);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse timeout value '%s': %m", optarg);
break;
- }
case 'V':
return print_version();
case 'h':
@@ -152,13 +161,9 @@ int control_main(int argc, char *argv[], void *userdata) {
assert_not_reached("Unknown option.");
}
- if (optind < argc) {
- log_error("Extraneous argument: %s", argv[optind]);
- return -EINVAL;
- } else if (optind == 1) {
- log_error("Option missing");
- return -EINVAL;
- }
+ if (optind < argc)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Extraneous argument: %s", argv[optind]);
return 0;
}
diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c
index d141bc74b2..ebd15d384a 100644
--- a/src/udev/udevadm-info.c
+++ b/src/udev/udevadm-info.c
@@ -61,12 +61,15 @@ static bool skip_attribute(const char *name) {
static void print_all_attributes(sd_device *device, const char *key) {
const char *name, *value;
- FOREACH_DEVICE_PROPERTY(device, name, value) {
+ FOREACH_DEVICE_SYSATTR(device, name) {
size_t len;
if (skip_attribute(name))
continue;
+ if (sd_device_get_sysattr_value(device, name, &value) < 0)
+ continue;
+
/* skip any values that look like a path */
if (value[0] == '/')
continue;
@@ -387,10 +390,8 @@ int info_main(int argc, char *argv[], void *userdata) {
query = QUERY_PATH;
else if (streq(optarg, "all"))
query = QUERY_ALL;
- else {
- log_error("unknown query type");
- return -EINVAL;
- }
+ else
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "unknown query type");
break;
case 'r':
arg_root = true;
@@ -413,6 +414,7 @@ int info_main(int argc, char *argv[], void *userdata) {
arg_export = true;
break;
case 'P':
+ arg_export = true;
arg_export_prefix = optarg;
break;
case 'V':
@@ -425,7 +427,6 @@ int info_main(int argc, char *argv[], void *userdata) {
assert_not_reached("Unknown option");
}
-
if (action == ACTION_DEVICE_ID_FILE) {
if (argv[optind])
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
diff --git a/src/udev/udevadm-monitor.c b/src/udev/udevadm-monitor.c
index f7737d0790..3dde3f338a 100644
--- a/src/udev/udevadm-monitor.c
+++ b/src/udev/udevadm-monitor.c
@@ -17,6 +17,7 @@
#include "signal-util.h"
#include "string-util.h"
#include "udevadm.h"
+#include "virt.h"
static bool arg_show_property = false;
static bool arg_print_kernel = false;
@@ -143,11 +144,11 @@ static int parse_argv(int argc, char *argv[]) {
slash = strchr(optarg, '/');
if (slash) {
- devtype = strdup(devtype + 1);
+ devtype = strdup(slash + 1);
if (!devtype)
return -ENOMEM;
- subsystem = strndup(optarg, devtype - optarg);
+ subsystem = strndup(optarg, slash - optarg);
} else
subsystem = strdup(optarg);
@@ -210,6 +211,11 @@ int monitor_main(int argc, char *argv[], void *userdata) {
if (r <= 0)
goto finalize;
+ if (running_in_chroot() > 0) {
+ log_info("Running in chroot, ignoring request.");
+ return 0;
+ }
+
/* Callers are expecting to see events as they happen: Line buffering */
setlinebuf(stdout);
diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c
index 4ae237d430..8d9c4509ff 100644
--- a/src/udev/udevadm-settle.c
+++ b/src/udev/udevadm-settle.c
@@ -18,6 +18,7 @@
#include "udevadm.h"
#include "udev-ctrl.h"
#include "util.h"
+#include "virt.h"
static usec_t arg_timeout = 120 * USEC_PER_SEC;
static const char *arg_exists = NULL;
@@ -88,6 +89,11 @@ int settle_main(int argc, char *argv[], void *userdata) {
if (r <= 0)
return r;
+ if (running_in_chroot() > 0) {
+ log_info("Running in chroot, ignoring request.");
+ return 0;
+ }
+
deadline = now(CLOCK_MONOTONIC) + arg_timeout;
/* guarantee that the udev daemon isn't pre-processing */
@@ -96,9 +102,9 @@ int settle_main(int argc, char *argv[], void *userdata) {
uctrl = udev_ctrl_new();
if (uctrl) {
- r = udev_ctrl_send_ping(uctrl, MAX(5U, arg_timeout / USEC_PER_SEC));
+ r = udev_ctrl_send_ping(uctrl, MAX(5 * USEC_PER_SEC, arg_timeout));
if (r < 0) {
- log_debug_errno(r, "Failed to connect to udev daemon.");
+ log_debug_errno(r, "Failed to connect to udev daemon: %m");
return 0;
}
}
diff --git a/src/udev/udevadm-trigger.c b/src/udev/udevadm-trigger.c
index f13a08f3f9..95329469e3 100644
--- a/src/udev/udevadm-trigger.c
+++ b/src/udev/udevadm-trigger.c
@@ -10,11 +10,14 @@
#include "fd-util.h"
#include "fileio.h"
#include "path-util.h"
+#include "process-util.h"
#include "set.h"
#include "string-util.h"
#include "strv.h"
#include "udevadm.h"
#include "udevadm-util.h"
+#include "udev-ctrl.h"
+#include "virt.h"
static bool arg_verbose = false;
static bool arg_dry_run = false;
@@ -117,6 +120,8 @@ static int help(void) {
" --name-match=NAME Trigger devices with this /dev name\n"
" -b --parent-match=NAME Trigger devices with that parent device\n"
" -w --settle Wait for the triggered events to complete\n"
+ " --wait-daemon[=SECONDS] Wait for udevd daemon to be initialized\n"
+ " before triggering uevents\n"
, program_invocation_short_name);
return 0;
@@ -125,6 +130,7 @@ static int help(void) {
int trigger_main(int argc, char *argv[], void *userdata) {
enum {
ARG_NAME = 0x100,
+ ARG_PING,
};
static const struct option options[] = {
@@ -142,6 +148,7 @@ int trigger_main(int argc, char *argv[], void *userdata) {
{ "name-match", required_argument, NULL, ARG_NAME },
{ "parent-match", required_argument, NULL, 'b' },
{ "settle", no_argument, NULL, 'w' },
+ { "wait-daemon", optional_argument, NULL, ARG_PING },
{ "version", no_argument, NULL, 'V' },
{ "help", no_argument, NULL, 'h' },
{}
@@ -155,9 +162,15 @@ int trigger_main(int argc, char *argv[], void *userdata) {
_cleanup_(sd_device_monitor_unrefp) sd_device_monitor *m = NULL;
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
_cleanup_set_free_free_ Set *settle_set = NULL;
- bool settle = false;
+ usec_t ping_timeout_usec = 5 * USEC_PER_SEC;
+ bool settle = false, ping = false;
int c, r;
+ if (running_in_chroot() > 0) {
+ log_info("Running in chroot, ignoring request.");
+ return 0;
+ }
+
r = sd_device_enumerator_new(&e);
if (r < 0)
return r;
@@ -182,18 +195,14 @@ int trigger_main(int argc, char *argv[], void *userdata) {
device_type = TYPE_DEVICES;
else if (streq(optarg, "subsystems"))
device_type = TYPE_SUBSYSTEMS;
- else {
- log_error("Unknown type --type=%s", optarg);
- return -EINVAL;
- }
+ else
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown type --type=%s", optarg);
break;
case 'c':
if (STR_IN_SET(optarg, "add", "remove", "change"))
action = optarg;
- else {
- log_error("Unknown action '%s'", optarg);
- return -EINVAL;
- }
+ else
+ log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown action '%s'", optarg);
break;
case 's':
@@ -269,6 +278,16 @@ int trigger_main(int argc, char *argv[], void *userdata) {
break;
}
+ case ARG_PING: {
+ ping = true;
+ if (optarg) {
+ r = parse_sec(optarg, &ping_timeout_usec);
+ if (r < 0)
+ log_error_errno(r, "Failed to parse timeout value '%s', ignoring: %m", optarg);
+ }
+ break;
+ }
+
case 'V':
return print_version();
case 'h':
@@ -280,6 +299,24 @@ int trigger_main(int argc, char *argv[], void *userdata) {
}
}
+ if (!arg_dry_run || ping) {
+ r = must_be_root();
+ if (r < 0)
+ return r;
+ }
+
+ if (ping) {
+ _cleanup_(udev_ctrl_unrefp) struct udev_ctrl *uctrl = NULL;
+
+ uctrl = udev_ctrl_new();
+ if (!uctrl)
+ return log_oom();
+
+ r = udev_ctrl_send_ping(uctrl, ping_timeout_usec);
+ if (r < 0)
+ return log_error_errno(r, "Failed to connect to udev daemon: %m");
+ }
+
for (; optind < argc; optind++) {
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
diff --git a/src/udev/udevadm.c b/src/udev/udevadm.c
index 1125c54b9f..28194314de 100644
--- a/src/udev/udevadm.c
+++ b/src/udev/udevadm.c
@@ -113,12 +113,13 @@ static int run(int argc, char *argv[]) {
udev_parse_config();
log_parse_environment();
log_open();
- log_set_max_level_realm(LOG_REALM_SYSTEMD, log_get_max_level());
r = parse_argv(argc, argv);
if (r <= 0)
return r;
+ log_set_max_level_realm(LOG_REALM_SYSTEMD, log_get_max_level());
+
mac_selinux_init();
return udevadm_main(argc, argv);
}
diff --git a/src/udev/udevadm.h b/src/udev/udevadm.h
index 98f9019a48..86b24af086 100644
--- a/src/udev/udevadm.h
+++ b/src/udev/udevadm.h
@@ -3,6 +3,9 @@
#include <stdio.h>
+#include "build.h"
+#include "macro.h"
+
int info_main(int argc, char *argv[], void *userdata);
int trigger_main(int argc, char *argv[], void *userdata);
int settle_main(int argc, char *argv[], void *userdata);
@@ -13,6 +16,7 @@ int test_main(int argc, char *argv[], void *userdata);
int builtin_main(int argc, char *argv[], void *userdata);
static inline int print_version(void) {
- puts(PACKAGE_VERSION);
+ /* Dracut relies on the version being a single integer */
+ puts(STRINGIFY(PROJECT_VERSION));
return 0;
}
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index fb8724ea87..0303f36b4f 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -31,6 +31,7 @@
#include "sd-event.h"
#include "alloc-util.h"
+#include "build.h"
#include "cgroup-util.h"
#include "cpu-set-util.h"
#include "dev-setup.h"
@@ -185,20 +186,11 @@ static void worker_free(struct worker *worker) {
free(worker);
}
-static void manager_workers_free(Manager *manager) {
- struct worker *worker;
- Iterator i;
-
- assert(manager);
-
- HASHMAP_FOREACH(worker, manager->workers, i)
- worker_free(worker);
-
- manager->workers = hashmap_free(manager->workers);
-}
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct worker *, worker_free);
+DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(worker_hash_op, void, trivial_hash_func, trivial_compare_func, struct worker, worker_free);
static int worker_new(struct worker **ret, Manager *manager, sd_device_monitor *worker_monitor, pid_t pid) {
- _cleanup_free_ struct worker *worker = NULL;
+ _cleanup_(worker_freep) struct worker *worker = NULL;
int r;
assert(ret);
@@ -206,17 +198,20 @@ static int worker_new(struct worker **ret, Manager *manager, sd_device_monitor *
assert(worker_monitor);
assert(pid > 1);
- worker = new0(struct worker, 1);
+ /* close monitor, but keep address around */
+ device_monitor_disconnect(worker_monitor);
+
+ worker = new(struct worker, 1);
if (!worker)
return -ENOMEM;
- worker->manager = manager;
- /* close monitor, but keep address around */
- device_monitor_disconnect(worker_monitor);
- worker->monitor = sd_device_monitor_ref(worker_monitor);
- worker->pid = pid;
+ *worker = (struct worker) {
+ .manager = manager,
+ .monitor = sd_device_monitor_ref(worker_monitor),
+ .pid = pid,
+ };
- r = hashmap_ensure_allocated(&manager->workers, NULL);
+ r = hashmap_ensure_allocated(&manager->workers, &worker_hash_op);
if (r < 0)
return r;
@@ -290,7 +285,7 @@ static void manager_clear_for_worker(Manager *manager) {
manager->event = sd_event_unref(manager->event);
- manager_workers_free(manager);
+ manager->workers = hashmap_free(manager->workers);
event_queue_cleanup(manager, EVENT_UNDEF);
manager->monitor = sd_device_monitor_unref(manager->monitor);
@@ -396,7 +391,7 @@ static int worker_lock_block_device(sd_device *dev, int *ret_fd) {
static int worker_process_device(Manager *manager, sd_device *dev) {
_cleanup_(udev_event_freep) UdevEvent *udev_event = NULL;
_cleanup_close_ int fd_lock = -1;
- const char *seqnum;
+ const char *seqnum, *action;
int r;
assert(manager);
@@ -404,9 +399,13 @@ static int worker_process_device(Manager *manager, sd_device *dev) {
r = sd_device_get_property_value(dev, "SEQNUM", &seqnum);
if (r < 0)
- log_device_debug_errno(dev, r, "Failed to get SEQNUM: %m");
+ return log_device_debug_errno(dev, r, "Failed to get SEQNUM: %m");
- log_device_debug(dev, "Processing device (SEQNUM=%s)", seqnum);
+ r = sd_device_get_property_value(dev, "ACTION", &action);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to get ACTION: %m");
+
+ log_device_debug(dev, "Processing device (SEQNUM=%s, ACTION=%s)", seqnum, action);
udev_event = udev_event_new(dev, arg_exec_delay_usec, manager->rtnl);
if (!udev_event)
@@ -432,7 +431,7 @@ static int worker_process_device(Manager *manager, sd_device *dev) {
return log_device_debug_errno(dev, r, "Failed to update database under /run/udev/data/: %m");
}
- log_device_debug(dev, "Device (SEQNUM=%s) processed", seqnum);
+ log_device_debug(dev, "Device (SEQNUM=%s, ACTION=%s) processed", seqnum, action);
return 0;
}
@@ -464,7 +463,7 @@ static int worker_device_monitor_handler(sd_device_monitor *monitor, sd_device *
static int worker_main(Manager *_manager, sd_device_monitor *monitor, sd_device *first_device) {
_cleanup_(sd_device_unrefp) sd_device *dev = first_device;
_cleanup_(manager_freep) Manager *manager = _manager;
- int r, ret;
+ int r;
assert(manager);
assert(monitor);
@@ -507,11 +506,7 @@ static int worker_main(Manager *_manager, sd_device_monitor *monitor, sd_device
if (r < 0)
return log_error_errno(r, "Event loop failed: %m");
- r = sd_event_get_exit_code(manager->event, &ret);
- if (r < 0)
- return log_error_errno(r, "Failed to get exit code: %m");
-
- return ret;
+ return 0;
}
static int worker_spawn(Manager *manager, struct event *event) {
@@ -534,7 +529,7 @@ static int worker_spawn(Manager *manager, struct event *event) {
if (r < 0)
return log_error_errno(r, "Worker: Failed to enable receiving of device: %m");
- r = safe_fork("(worker)", FORK_DEATHSIG, &pid);
+ r = safe_fork(NULL, FORK_DEATHSIG, &pid);
if (r < 0) {
event->state = EVENT_QUEUED;
return log_error_errno(r, "Failed to fork() worker: %m");
@@ -592,8 +587,8 @@ static void event_run(Manager *manager, struct event *event) {
static int event_queue_insert(Manager *manager, sd_device *dev) {
_cleanup_(sd_device_unrefp) sd_device *clone = NULL;
+ const char *val, *action;
struct event *event;
- const char *val;
uint64_t seqnum;
int r;
@@ -618,6 +613,11 @@ static int event_queue_insert(Manager *manager, sd_device *dev) {
if (seqnum == 0)
return -EINVAL;
+ /* Refuse devices do not have ACTION property. */
+ r = sd_device_get_property_value(dev, "ACTION", &action);
+ if (r < 0)
+ return r;
+
/* Save original device to restore the state on failures. */
r = device_shallow_clone(dev, &clone);
if (r < 0)
@@ -647,12 +647,7 @@ static int event_queue_insert(Manager *manager, sd_device *dev) {
LIST_APPEND(event, manager->events, event);
- if (DEBUG_LOGGING) {
- if (sd_device_get_property_value(dev, "ACTION", &val) < 0)
- val = NULL;
-
- log_device_debug(dev, "Device (SEQNUM=%"PRIu64", ACTION=%s) is queued", seqnum, strnull(val));
- }
+ log_device_debug(dev, "Device (SEQNUM=%"PRIu64", ACTION=%s) is queued", seqnum, action);
return 0;
}
@@ -875,7 +870,7 @@ static void event_queue_start(Manager *manager) {
assert_se(sd_event_now(manager->event, CLOCK_MONOTONIC, &usec) >= 0);
/* check for changed config, every 3 seconds at most */
if (manager->last_usec == 0 ||
- (usec - manager->last_usec) > 3 * USEC_PER_SEC) {
+ usec - manager->last_usec > 3 * USEC_PER_SEC) {
if (udev_rules_check_timestamp(manager->rules) ||
udev_builtin_validate())
manager_reload(manager);
@@ -960,12 +955,11 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat
continue;
}
- CMSG_FOREACH(cmsg, &msghdr) {
+ CMSG_FOREACH(cmsg, &msghdr)
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_CREDENTIALS &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
ucred = (struct ucred*) CMSG_DATA(cmsg);
- }
if (!ucred || ucred->pid <= 0) {
log_warning("Ignoring worker message without valid PID");
@@ -1033,7 +1027,8 @@ static int on_ctrl_msg(sd_event_source *s, int fd, uint32_t revents, void *userd
i = udev_ctrl_get_set_log_level(ctrl_msg);
if (i >= 0) {
log_debug("Received udev control message (SET_LOG_LEVEL), setting log_priority=%i", i);
- log_set_max_level(i);
+ log_set_max_level_realm(LOG_REALM_UDEV, i);
+ log_set_max_level_realm(LOG_REALM_SYSTEMD, i);
manager_kill_workers(manager);
}
@@ -1118,7 +1113,7 @@ static int on_ctrl_msg(sd_event_source *s, int fd, uint32_t revents, void *userd
}
if (udev_ctrl_get_ping(ctrl_msg) > 0)
- log_debug("Received udev control message (SYNC)");
+ log_debug("Received udev control message (PING)");
if (udev_ctrl_get_exit(ctrl_msg) > 0) {
log_debug("Received udev control message (EXIT)");
@@ -1338,9 +1333,9 @@ static int on_sigchld(sd_event_source *s, const struct signalfd_siginfo *si, voi
log_debug("Worker ["PID_FMT"] exited", pid);
else
log_warning("Worker ["PID_FMT"] exited with return code %i", pid, WEXITSTATUS(status));
- } else if (WIFSIGNALED(status)) {
+ } else if (WIFSIGNALED(status))
log_warning("Worker ["PID_FMT"] terminated by signal %i (%s)", pid, WTERMSIG(status), signal_to_string(WTERMSIG(status)));
- } else if (WIFSTOPPED(status)) {
+ else if (WIFSTOPPED(status)) {
log_info("Worker ["PID_FMT"] stopped", pid);
continue;
} else if (WIFCONTINUED(status)) {
@@ -1579,7 +1574,7 @@ static int parse_argv(int argc, char *argv[]) {
case 'h':
return help();
case 'V':
- printf("%s\n", PACKAGE_VERSION);
+ printf("%s\n", GIT_VERSION);
return 0;
case '?':
return -EINVAL;
@@ -1594,7 +1589,7 @@ static int parse_argv(int argc, char *argv[]) {
static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cgroup) {
_cleanup_(manager_freep) Manager *manager = NULL;
- int r, fd_worker;
+ int r;
assert(ret);
@@ -1608,25 +1603,13 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
.cgroup = cgroup,
};
- udev_builtin_init();
-
- r = udev_rules_new(&manager->rules, arg_resolve_name_timing);
- if (!manager->rules)
- return log_error_errno(r, "Failed to read udev rules: %m");
-
manager->ctrl = udev_ctrl_new_from_fd(fd_ctrl);
if (!manager->ctrl)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to initialize udev control socket");
- if (fd_ctrl < 0) {
- r = udev_ctrl_enable_receiving(manager->ctrl);
- if (r < 0)
- return log_error_errno(r, "Failed to bind udev control socket: %m");
- }
-
- fd_ctrl = udev_ctrl_get_fd(manager->ctrl);
- if (fd_ctrl < 0)
- return log_error_errno(fd_ctrl, "Failed to get udev control socket fd: %m");
+ r = udev_ctrl_enable_receiving(manager->ctrl);
+ if (r < 0)
+ return log_error_errno(r, "Failed to bind udev control socket: %m");
r = device_monitor_new_full(&manager->monitor, MONITOR_GROUP_KERNEL, fd_uevent);
if (r < 0)
@@ -1634,6 +1617,18 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
(void) sd_device_monitor_set_receive_buffer_size(manager->monitor, 128 * 1024 * 1024);
+ r = device_monitor_enable_receiving(manager->monitor);
+ if (r < 0)
+ return log_error_errno(r, "Failed to bind netlink socket: %m");
+
+ *ret = TAKE_PTR(manager);
+
+ return 0;
+}
+
+static int main_loop(Manager *manager) {
+ int fd_worker, fd_ctrl, r;
+
/* unnamed socket from workers to the main daemon */
r = socketpair(AF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0, manager->worker_watch);
if (r < 0)
@@ -1679,6 +1674,10 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
if (r < 0)
return log_error_errno(r, "Failed to create watchdog event source: %m");
+ fd_ctrl = udev_ctrl_get_fd(manager->ctrl);
+ if (fd_ctrl < 0)
+ return log_error_errno(fd_ctrl, "Failed to get udev control socket fd: %m");
+
r = sd_event_add_io(manager->event, &manager->ctrl_event, fd_ctrl, EPOLLIN, on_ctrl_msg, manager);
if (r < 0)
return log_error_errno(r, "Failed to create udev control event source: %m");
@@ -1713,20 +1712,11 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
if (r < 0)
return log_error_errno(r, "Failed to create post event source: %m");
- *ret = TAKE_PTR(manager);
-
- return 0;
-}
-
-static int main_loop(int fd_ctrl, int fd_uevent, const char *cgroup) {
- _cleanup_(manager_freep) Manager *manager = NULL;
- int r;
+ udev_builtin_init();
- r = manager_new(&manager, fd_ctrl, fd_uevent, cgroup);
- if (r < 0) {
- r = log_error_errno(r, "Failed to allocate manager object: %m");
- goto exit;
- }
+ r = udev_rules_new(&manager->rules, arg_resolve_name_timing);
+ if (!manager->rules)
+ return log_error_errno(r, "Failed to read udev rules: %m");
r = udev_rules_apply_static_dev_perms(manager->rules);
if (r < 0)
@@ -1737,24 +1727,18 @@ static int main_loop(int fd_ctrl, int fd_uevent, const char *cgroup) {
"STATUS=Processing with %u children at max", arg_children_max);
r = sd_event_loop(manager->event);
- if (r < 0) {
+ if (r < 0)
log_error_errno(r, "Event loop failed: %m");
- goto exit;
- }
- sd_event_get_exit_code(manager->event, &r);
-
-exit:
sd_notify(false,
"STOPPING=1\n"
"STATUS=Shutting down...");
- if (manager)
- udev_ctrl_cleanup(manager->ctrl);
return r;
}
static int run(int argc, char *argv[]) {
_cleanup_free_ char *cgroup = NULL;
+ _cleanup_(manager_freep) Manager *manager = NULL;
int fd_ctrl = -1, fd_uevent = -1;
int r;
@@ -1814,10 +1798,10 @@ static int run(int argc, char *argv[]) {
dev_setup(NULL, UID_INVALID, GID_INVALID);
- if (getppid() == 1) {
- /* get our own cgroup, we regularly kill everything udev has left behind
- we only do this on systemd systems, and only if we are directly spawned
- by PID1. otherwise we are not guaranteed to have a dedicated cgroup */
+ if (getppid() == 1 && sd_booted() > 0) {
+ /* Get our own cgroup, we regularly kill everything udev has left behind.
+ * We only do this on systemd systems, and only if we are directly spawned
+ * by PID1. Otherwise we are not guaranteed to have a dedicated cgroup. */
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup);
if (r < 0) {
if (IN_SET(r, -ENOENT, -ENOMEDIUM))
@@ -1831,10 +1815,14 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to listen on fds: %m");
+ r = manager_new(&manager, fd_ctrl, fd_uevent, cgroup);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create manager: %m");
+
if (arg_daemonize) {
pid_t pid;
- log_info("starting version " PACKAGE_VERSION);
+ log_info("Starting version " GIT_VERSION);
/* connect /dev/null to stdin, stdout, stderr */
if (log_get_max_level() < LOG_DEBUG) {
@@ -1858,7 +1846,10 @@ static int run(int argc, char *argv[]) {
log_debug_errno(r, "Failed to adjust OOM score, ignoring: %m");
}
- return main_loop(fd_ctrl, fd_uevent, cgroup);
+ r = main_loop(manager);
+ /* FIXME: move this into manager_free() */
+ udev_ctrl_cleanup(manager->ctrl);
+ return r;
}
DEFINE_MAIN_FUNCTION(run);