diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2018-10-28 13:00:14 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-28 13:00:14 +0100 |
commit | 815628cdd44c031880c8f58ee8f59fff7239303c (patch) | |
tree | ef8b01e93eb6f5a703845d520035a6294bb2f748 /src | |
parent | 7b36621677431e1890ce1eca297199b8785f344c (diff) | |
parent | 4cade7a15b9af5b628c2ae9d0f3e9cefbe4ef4bf (diff) | |
download | systemd-815628cdd44c031880c8f58ee8f59fff7239303c.tar.gz systemd-815628cdd44c031880c8f58ee8f59fff7239303c.tar.bz2 systemd-815628cdd44c031880c8f58ee8f59fff7239303c.zip |
Merge pull request #10512 from yuwata/udev-event-cleanup
udev-event: replace udev_device by sd_device
Diffstat (limited to 'src')
-rw-r--r-- | src/libsystemd/sd-device/device-enumerator.c | 2 | ||||
-rw-r--r-- | src/libsystemd/sd-device/sd-device.c | 7 | ||||
-rw-r--r-- | src/libsystemd/sd-device/test-sd-device.c | 2 | ||||
-rw-r--r-- | src/network/networkd-manager.c | 4 | ||||
-rw-r--r-- | src/test/test-udev.c | 2 | ||||
-rw-r--r-- | src/udev/net/link-config.c | 2 | ||||
-rw-r--r-- | src/udev/udev-event.c | 595 | ||||
-rw-r--r-- | src/udev/udev.h | 20 | ||||
-rw-r--r-- | src/udev/udevadm-test.c | 2 | ||||
-rw-r--r-- | src/udev/udevd.c | 4 |
10 files changed, 374 insertions, 266 deletions
diff --git a/src/libsystemd/sd-device/device-enumerator.c b/src/libsystemd/sd-device/device-enumerator.c index 3ae283e93c..187ea703c9 100644 --- a/src/libsystemd/sd-device/device-enumerator.c +++ b/src/libsystemd/sd-device/device-enumerator.c @@ -497,7 +497,7 @@ static int enumerator_scan_dir_and_add_devices(sd_device_enumerator *enumerator, if (!enumerator->match_allow_uninitialized && !initialized && (sd_device_get_devnum(device, &devnum) >= 0 || - (sd_device_get_ifindex(device, &ifindex) >= 0 && ifindex > 0))) + sd_device_get_ifindex(device, &ifindex) >= 0)) continue; if (!match_parent(enumerator, device)) diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index 1eb71e17db..b97c1b9719 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -38,7 +38,6 @@ int device_new_aux(sd_device **ret) { *device = (sd_device) { .n_ref = 1, .watch_handle = -1, - .ifindex = -1, .devmode = (mode_t) -1, .devuid = (uid_t) -1, .devgid = (gid_t) -1, @@ -579,7 +578,7 @@ _public_ int sd_device_get_ifindex(sd_device *device, int *ifindex) { if (r < 0) return r; - if (device->ifindex < 0) + if (device->ifindex <= 0) return -ENOENT; *ifindex = device->ifindex; @@ -1241,9 +1240,9 @@ int device_get_id_filename(sd_device *device, const char **ret) { major(devnum), minor(devnum)); if (r < 0) return -ENOMEM; - } else if (sd_device_get_ifindex(device, &ifindex) >= 0 && ifindex > 0) { + } else if (sd_device_get_ifindex(device, &ifindex) >= 0) { /* use netdev ifindex — n3 */ - r = asprintf(&id, "n%u", ifindex); + r = asprintf(&id, "n%u", (unsigned) ifindex); if (r < 0) return -ENOMEM; } else { diff --git a/src/libsystemd/sd-device/test-sd-device.c b/src/libsystemd/sd-device/test-sd-device.c index e2701e0e24..fe49a2012a 100644 --- a/src/libsystemd/sd-device/test-sd-device.c +++ b/src/libsystemd/sd-device/test-sd-device.c @@ -32,7 +32,7 @@ static void test_sd_device_basic(void) { assert_se(r >= 0 || r == -ENOENT); r = sd_device_get_ifindex(d, &i); - assert_se(r >= 0 || r == -ENOENT); + assert_se((r >= 0 && i > 0) || r == -ENOENT); r = sd_device_get_driver(d, &val); assert_se(r >= 0 || r == -ENOENT); diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 4a621950ca..f7e9b48609 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -197,8 +197,8 @@ static int manager_udev_process_link(sd_device_monitor *monitor, sd_device *devi return 0; r = sd_device_get_ifindex(device, &ifindex); - if (r < 0 || ifindex <= 0) { - log_debug("Ignoring udev ADD event for device with invalid ifindex"); + if (r < 0) { + log_debug_errno(r, "Ignoring udev ADD event for device without ifindex or with invalid ifindex: %m"); return 0; } diff --git a/src/test/test-udev.c b/src/test/test-udev.c index 2c67e13833..1285117c32 100644 --- a/src/test/test-udev.c +++ b/src/test/test-udev.c @@ -52,7 +52,7 @@ static int fake_filesystems(void) { } int main(int argc, char *argv[]) { - _cleanup_(udev_event_unrefp) struct udev_event *event = NULL; + _cleanup_(udev_event_freep) struct udev_event *event = NULL; _cleanup_(udev_device_unrefp) struct udev_device *dev = NULL; _cleanup_(udev_rules_unrefp) struct udev_rules *rules = NULL; const char *devpath, *action; diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index 2d25f75357..c39d8791f2 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -412,8 +412,6 @@ int link_config_apply(link_config_ctx *ctx, link_config *config, r = sd_device_get_ifindex(device, &ifindex); if (r < 0) return log_device_warning_errno(device, r, "Could not find ifindex: %m"); - if (ifindex <= 0) - return log_device_warning_errno(device, EINVAL, "Invalid ifindex '%d'", ifindex); if (ctx->enable_name_policy && config->name_policy) { NamePolicy *policy; diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c index cdfda51f03..70fb190897 100644 --- a/src/udev/udev-event.c +++ b/src/udev/udev-event.c @@ -13,6 +13,7 @@ #include "alloc-util.h" #include "device-private.h" +#include "device-util.h" #include "fd-util.h" #include "format-util.h" #include "libudev-device-internal.h" @@ -20,6 +21,7 @@ #include "path-util.h" #include "process-util.h" #include "signal-util.h" +#include "stdio-util.h" #include "string-util.h" #include "udev-builtin.h" #include "udev-node.h" @@ -43,30 +45,38 @@ typedef struct Spawn { struct udev_event *udev_event_new(struct udev_device *dev) { struct udev_event *event; - event = new0(struct udev_event, 1); - if (event == NULL) + assert(dev); + + event = new(struct udev_event, 1); + if (!event) return NULL; - event->dev = dev; - event->birth_usec = now(CLOCK_MONOTONIC); + + *event = (struct udev_event) { + .dev = dev, + .birth_usec = now(CLOCK_MONOTONIC), + }; + return event; } -void udev_event_unref(struct udev_event *event) { +struct udev_event *udev_event_free(struct udev_event *event) { void *p; - if (event == NULL) - return; + if (!event) + return NULL; + sd_netlink_unref(event->rtnl); while ((p = hashmap_steal_first_key(event->run_list))) free(p); + hashmap_free(event->run_list); hashmap_free_free_free(event->seclabel_list); free(event->program_result); free(event->name); - free(event); + + return mfree(event); } enum subst_type { - SUBST_UNKNOWN, SUBST_DEVNODE, SUBST_ATTR, SUBST_ENV, @@ -85,68 +95,103 @@ enum subst_type { SUBST_SYS, }; -static size_t subst_format_var(struct udev_event *event, struct udev_device *dev, - enum subst_type type, char *attr, - char *dest, size_t l) { +struct subst_map_entry { + const char *name; + const char fmt; + enum subst_type type; +}; + +static const struct subst_map_entry map[] = { + { .name = "devnode", .fmt = 'N', .type = SUBST_DEVNODE }, + { .name = "tempnode", .fmt = 'N', .type = SUBST_DEVNODE }, + { .name = "attr", .fmt = 's', .type = SUBST_ATTR }, + { .name = "sysfs", .fmt = 's', .type = SUBST_ATTR }, + { .name = "env", .fmt = 'E', .type = SUBST_ENV }, + { .name = "kernel", .fmt = 'k', .type = SUBST_KERNEL }, + { .name = "number", .fmt = 'n', .type = SUBST_KERNEL_NUMBER }, + { .name = "driver", .fmt = 'd', .type = SUBST_DRIVER }, + { .name = "devpath", .fmt = 'p', .type = SUBST_DEVPATH }, + { .name = "id", .fmt = 'b', .type = SUBST_ID }, + { .name = "major", .fmt = 'M', .type = SUBST_MAJOR }, + { .name = "minor", .fmt = 'm', .type = SUBST_MINOR }, + { .name = "result", .fmt = 'c', .type = SUBST_RESULT }, + { .name = "parent", .fmt = 'P', .type = SUBST_PARENT }, + { .name = "name", .fmt = 'D', .type = SUBST_NAME }, + { .name = "links", .fmt = 'L', .type = SUBST_LINKS }, + { .name = "root", .fmt = 'r', .type = SUBST_ROOT }, + { .name = "sys", .fmt = 'S', .type = SUBST_SYS }, +}; + +static ssize_t subst_format_var(struct udev_event *event, + const struct subst_map_entry *entry, char *attr, + char *dest, size_t l) { + sd_device *parent, *dev = event->dev->device; + const char *val = NULL; char *s = dest; + dev_t devnum; + int r; + + assert(entry); - switch (type) { + switch (entry->type) { case SUBST_DEVPATH: - l = strpcpy(&s, l, udev_device_get_devpath(dev)); + r = sd_device_get_devpath(dev, &val); + if (r < 0) + return r; + l = strpcpy(&s, l, val); break; case SUBST_KERNEL: - l = strpcpy(&s, l, udev_device_get_sysname(dev)); + r = sd_device_get_sysname(dev, &val); + if (r < 0) + return r; + l = strpcpy(&s, l, val); break; case SUBST_KERNEL_NUMBER: - if (udev_device_get_sysnum(dev) == NULL) - break; - l = strpcpy(&s, l, udev_device_get_sysnum(dev)); + r = sd_device_get_sysnum(dev, &val); + if (r < 0) + return r == -ENOENT ? 0 : r; + l = strpcpy(&s, l, val); break; case SUBST_ID: - if (event->dev_parent == NULL) - break; - l = strpcpy(&s, l, udev_device_get_sysname(event->dev_parent)); - break; - case SUBST_DRIVER: { - const char *driver; - - if (event->dev_parent == NULL) - break; - - driver = udev_device_get_driver(event->dev_parent); - if (driver == NULL) - break; - l = strpcpy(&s, l, driver); + if (!event->dev_parent) + return 0; + r = sd_device_get_sysname(event->dev_parent->device, &val); + if (r < 0) + return r; + l = strpcpy(&s, l, val); break; - } - case SUBST_MAJOR: { - char num[UTIL_PATH_SIZE]; - - sprintf(num, "%u", major(udev_device_get_devnum(dev))); - l = strpcpy(&s, l, num); + case SUBST_DRIVER: + if (!event->dev_parent) + return 0; + r = sd_device_get_driver(event->dev_parent->device, &val); + if (r < 0) + return r == -ENOENT ? 0 : r; + l = strpcpy(&s, l, val); break; - } + case SUBST_MAJOR: case SUBST_MINOR: { - char num[UTIL_PATH_SIZE]; + char buf[DECIMAL_STR_MAX(unsigned)]; - sprintf(num, "%u", minor(udev_device_get_devnum(dev))); - l = strpcpy(&s, l, num); + r = sd_device_get_devnum(dev, &devnum); + if (r < 0 && r != -ENOENT) + return r; + xsprintf(buf, "%u", r < 0 ? 0 : entry->type == SUBST_MAJOR ? major(devnum) : minor(devnum)); + l = strpcpy(&s, l, buf); break; } case SUBST_RESULT: { char *rest; int i; - if (event->program_result == NULL) - break; + if (!event->program_result) + return 0; + /* get part of the result string */ i = 0; - if (attr != NULL) + if (attr) i = strtoul(attr, &rest, 10); if (i > 0) { - char result[UTIL_PATH_SIZE]; - char tmp[UTIL_PATH_SIZE]; - char *cpos; + char result[UTIL_PATH_SIZE], tmp[UTIL_PATH_SIZE], *cpos; strscpy(result, sizeof(result), event->program_result); cpos = result; @@ -170,88 +215,79 @@ static size_t subst_format_var(struct udev_event *event, struct udev_device *dev cpos[0] = '\0'; } l = strpcpy(&s, l, tmp); - } else { + } else l = strpcpy(&s, l, event->program_result); - } break; } case SUBST_ATTR: { - const char *value = NULL; char vbuf[UTIL_NAME_SIZE]; size_t len; int count; - if (attr == NULL) { - log_error("missing file parameter for attr"); - break; - } + if (!attr) + return -EINVAL; /* try to read the value specified by "[dmi/id]product_name" */ if (util_resolve_subsys_kernel(attr, vbuf, sizeof(vbuf), 1) == 0) - value = vbuf; + val = vbuf; /* try to read the attribute the device */ - if (value == NULL) - value = udev_device_get_sysattr_value(event->dev, attr); + if (!val) + (void) sd_device_get_sysattr_value(dev, attr, &val); /* try to read the attribute of the parent device, other matches have selected */ - if (value == NULL && event->dev_parent != NULL && event->dev_parent != event->dev) - value = udev_device_get_sysattr_value(event->dev_parent, attr); + if (!val && event->dev_parent && event->dev_parent->device != dev) + (void) sd_device_get_sysattr_value(event->dev_parent->device, attr, &val); - if (value == NULL) - break; + if (!val) + return 0; /* strip trailing whitespace, and replace unwanted characters */ - if (value != vbuf) - strscpy(vbuf, sizeof(vbuf), value); + if (val != vbuf) + strscpy(vbuf, sizeof(vbuf), val); len = strlen(vbuf); while (len > 0 && isspace(vbuf[--len])) vbuf[len] = '\0'; count = util_replace_chars(vbuf, UDEV_ALLOWED_CHARS_INPUT); if (count > 0) - log_debug("%i character(s) replaced" , count); + log_device_debug(dev, "%i character(s) replaced", count); l = strpcpy(&s, l, vbuf); break; } - case SUBST_PARENT: { - struct udev_device *dev_parent; - const char *devnode; - - dev_parent = udev_device_get_parent(event->dev); - if (dev_parent == NULL) - break; - devnode = udev_device_get_devnode(dev_parent); - if (devnode != NULL) - l = strpcpy(&s, l, devnode + STRLEN("/dev/")); + case SUBST_PARENT: + r = sd_device_get_parent(dev, &parent); + if (r < 0) + return r == -ENODEV ? 0 : r; + r = sd_device_get_devname(parent, &val); + if (r < 0) + return r == -ENOENT ? 0 : r; + l = strpcpy(&s, l, val + STRLEN("/dev/")); break; - } case SUBST_DEVNODE: - if (udev_device_get_devnode(dev) != NULL) - l = strpcpy(&s, l, udev_device_get_devnode(dev)); + r = sd_device_get_devname(dev, &val); + if (r < 0) + return r == -ENOENT ? 0 : r; + l = strpcpy(&s, l, val); break; case SUBST_NAME: - if (event->name != NULL) + if (event->name) l = strpcpy(&s, l, event->name); - else if (udev_device_get_devnode(dev) != NULL) - l = strpcpy(&s, l, - udev_device_get_devnode(dev) + STRLEN("/dev/")); - else - l = strpcpy(&s, l, udev_device_get_sysname(dev)); + else if (sd_device_get_devname(dev, &val) >= 0) + l = strpcpy(&s, l, val + STRLEN("/dev/")); + else { + r = sd_device_get_sysname(dev, &val); + if (r < 0) + return r; + l = strpcpy(&s, l, val); + } break; - case SUBST_LINKS: { - struct udev_list_entry *list_entry; - - list_entry = udev_device_get_devlinks_list_entry(dev); - if (list_entry == NULL) - break; - l = strpcpy(&s, l, - udev_list_entry_get_name(list_entry) + STRLEN("/dev/")); - udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry)) - l = strpcpyl(&s, l, " ", - udev_list_entry_get_name(list_entry) + STRLEN("/dev/"), - NULL); + case SUBST_LINKS: + FOREACH_DEVICE_DEVLINK(dev, val) + if (s == dest) + l = strpcpy(&s, l, val + STRLEN("/dev/")); + else + l = strpcpyl(&s, l, " ", val + STRLEN("/dev/"), NULL); break; - } case SUBST_ROOT: l = strpcpy(&s, l, "/dev"); break; @@ -259,68 +295,42 @@ static size_t subst_format_var(struct udev_event *event, struct udev_device *dev l = strpcpy(&s, l, "/sys"); break; case SUBST_ENV: - if (attr == NULL) { - break; - } else { - const char *value; - - value = udev_device_get_property_value(event->dev, attr); - if (value == NULL) - break; - l = strpcpy(&s, l, value); - break; - } - default: - log_error("unknown substitution type=%i", type); + if (!attr) + return 0; + r = sd_device_get_property_value(dev, attr, &val); + if (r < 0) + return r == -ENOENT ? 0 : r; + l = strpcpy(&s, l, val); break; + default: + assert_not_reached("Unknown format substitution type"); } return s - dest; } -size_t udev_event_apply_format(struct udev_event *event, - const char *src, char *dest, size_t size, - bool replace_whitespace) { - struct udev_device *dev = event->dev; - static const struct subst_map { - const char *name; - const char fmt; - enum subst_type type; - } map[] = { - { .name = "devnode", .fmt = 'N', .type = SUBST_DEVNODE }, - { .name = "tempnode", .fmt = 'N', .type = SUBST_DEVNODE }, - { .name = "attr", .fmt = 's', .type = SUBST_ATTR }, - { .name = "sysfs", .fmt = 's', .type = SUBST_ATTR }, - { .name = "env", .fmt = 'E', .type = SUBST_ENV }, - { .name = "kernel", .fmt = 'k', .type = SUBST_KERNEL }, - { .name = "number", .fmt = 'n', .type = SUBST_KERNEL_NUMBER }, - { .name = "driver", .fmt = 'd', .type = SUBST_DRIVER }, - { .name = "devpath", .fmt = 'p', .type = SUBST_DEVPATH }, - { .name = "id", .fmt = 'b', .type = SUBST_ID }, - { .name = "major", .fmt = 'M', .type = SUBST_MAJOR }, - { .name = "minor", .fmt = 'm', .type = SUBST_MINOR }, - { .name = "result", .fmt = 'c', .type = SUBST_RESULT }, - { .name = "parent", .fmt = 'P', .type = SUBST_PARENT }, - { .name = "name", .fmt = 'D', .type = SUBST_NAME }, - { .name = "links", .fmt = 'L', .type = SUBST_LINKS }, - { .name = "root", .fmt = 'r', .type = SUBST_ROOT }, - { .name = "sys", .fmt = 'S', .type = SUBST_SYS }, - }; +ssize_t udev_event_apply_format(struct udev_event *event, + const char *src, char *dest, size_t size, + bool replace_whitespace) { const char *from; char *s; size_t l; - assert(dev); + assert(event); + assert(event->dev); + assert(src); + assert(dest); + assert(size > 0); from = src; s = dest; l = size; for (;;) { - enum subst_type type = SUBST_UNKNOWN; - char attrbuf[UTIL_PATH_SIZE]; - char *attr = NULL; - size_t subst_len; + const struct subst_map_entry *entry = NULL; + char attrbuf[UTIL_PATH_SIZE], *attr; + bool format_dollar = false; + ssize_t subst_len; while (from[0] != '\0') { if (from[0] == '$') { @@ -334,8 +344,9 @@ size_t udev_event_apply_format(struct udev_event *event, for (i = 0; i < ELEMENTSOF(map); i++) { if (startswith(&from[1], map[i].name)) { - type = map[i].type; + entry = &map[i]; from += strlen(map[i].name)+1; + format_dollar = true; goto subst; } } @@ -350,7 +361,7 @@ size_t udev_event_apply_format(struct udev_event *event, for (i = 0; i < ELEMENTSOF(map); i++) { if (from[1] == map[i].fmt) { - type = map[i].type; + entry = &map[i]; from += 2; goto subst; } @@ -385,14 +396,21 @@ subst: attrbuf[i] = '\0'; from += i+1; attr = attrbuf; - } else { + } else attr = NULL; - } - subst_len = subst_format_var(event, dev, type, attr, s, l); + subst_len = subst_format_var(event, entry, attr, s, l); + if (subst_len < 0) { + if (format_dollar) + log_device_warning_errno(event->dev->device, subst_len, "Failed to substitute variable '$%s', ignoring: %m", entry->name); + else + log_device_warning_errno(event->dev->device, subst_len, "Failed to apply format '%%%c', ignoring: %m", entry->fmt); + + continue; + } /* SUBST_RESULT handles spaces itself */ - if (replace_whitespace && type != SUBST_RESULT) + if (replace_whitespace && entry->type != SUBST_RESULT) /* util_replace_whitespace can replace in-place, * and does nothing if subst_len == 0 */ @@ -585,6 +603,8 @@ int udev_event_spawn(struct udev_event *event, pid_t pid; int r; + assert(event); + assert(event->dev); assert(result || ressize == 0); /* pipes from child to parent */ @@ -600,6 +620,11 @@ int udev_event_spawn(struct udev_event *event, if (!argv) return log_oom(); + if (isempty(argv[0])) { + log_error("Invalid command '%s'", cmd); + return -EINVAL; + } + /* allow programs in /usr/lib/udev/ to be called without the path */ if (!path_is_absolute(argv[0])) { char *program; @@ -613,7 +638,7 @@ int udev_event_spawn(struct udev_event *event, r = device_get_properties_strv(event->dev->device, &envp); if (r < 0) - return log_error_errno(r, "Failed to get device properties"); + return log_device_error_errno(event->dev->device, r, "Failed to get device properties"); log_debug("Starting '%s'", cmd); @@ -657,122 +682,212 @@ int udev_event_spawn(struct udev_event *event, } static int rename_netif(struct udev_event *event) { - struct udev_device *dev = event->dev; + sd_device *dev = event->dev->device; + const char *action, *oldname; char name[IFNAMSIZ]; - const char *oldname; - int r; + int ifindex, r; + + if (!event->name) + return 0; /* No new name is requested. */ + + r = sd_device_get_sysname(dev, &oldname); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to get sysname: %m"); + + if (streq(event->name, oldname)) + return 0; /* The interface name is already requested name. */ + + r = sd_device_get_property_value(dev, "ACTION", &action); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to get property 'ACTION': %m"); + + if (!streq(action, "add")) + return 0; /* Rename the interface only when it is added. */ - oldname = udev_device_get_sysname(dev); + r = sd_device_get_ifindex(dev, &ifindex); + if (r == -ENOENT) + return 0; /* Device is not a network interface. */ + if (r < 0) + return log_device_error_errno(dev, r, "Failed to get ifindex: %m"); strscpy(name, IFNAMSIZ, event->name); + r = rtnl_set_link_name(&event->rtnl, ifindex, name); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to rename network interface %i from '%s' to '%s': %m", ifindex, oldname, name); - r = rtnl_set_link_name(&event->rtnl, udev_device_get_ifindex(dev), name); + r = device_rename(dev, event->name); if (r < 0) - return log_error_errno(r, "Error changing net interface name '%s' to '%s': %m", oldname, name); + return log_warning_errno(r, "Network interface %i is renamed from '%s' to '%s', but could not update sd_device object: %m", ifindex, oldname, name); - log_debug("renamed network interface '%s' to '%s'", oldname, name); + log_device_debug(dev, "Network interface %i is renamed from '%s' to '%s'", ifindex, oldname, name); - return 0; + return 1; } -void udev_event_execute_rules(struct udev_event *event, - usec_t timeout_usec, usec_t timeout_warn_usec, - Hashmap *properties_list, - struct udev_rules *rules) { - struct udev_device *dev = event->dev; +static int update_devnode(struct udev_event *event) { + sd_device *dev = event->dev->device; + const char *action; + dev_t devnum; + bool apply; + int r; - if (udev_device_get_subsystem(dev) == NULL) - return; + r = sd_device_get_devnum(dev, &devnum); + if (r == -ENOENT) + return 0; + if (r < 0) + return log_device_error_errno(dev, r, "Failed to get devnum: %m"); - if (streq(udev_device_get_action(dev), "remove")) { - udev_device_read_db(dev); - udev_device_tag_index(dev, NULL, false); - udev_device_delete_db(dev); + /* remove/update possible left-over symlinks from old database entry */ + if (event->dev_db) + (void) udev_node_update_old_links(dev, event->dev_db->device); - if (major(udev_device_get_devnum(dev)) != 0) - udev_watch_end(dev->device); + if (!event->owner_set) { + r = device_get_devnode_uid(dev, &event->uid); + if (r < 0 && r != -ENOENT) + return log_device_error_errno(dev, r, "Failed to get devnode UID: %m"); + } - udev_rules_apply_to_event(rules, event, - timeout_usec, timeout_warn_usec, - properties_list); + if (!event->group_set) { + r = device_get_devnode_gid(dev, &event->gid); + if (r < 0 && r != -ENOENT) + return log_device_error_errno(dev, r, "Failed to get devnode GID: %m"); + } - if (major(udev_device_get_devnum(dev)) != 0) - udev_node_remove(dev->device); - } else { - event->dev_db = udev_device_clone_with_db(dev); - if (event->dev_db != NULL) { - /* disable watch during event processing */ - if (major(udev_device_get_devnum(dev)) != 0) - udev_watch_end(event->dev_db->device); - - if (major(udev_device_get_devnum(dev)) == 0 && - streq(udev_device_get_action(dev), "move")) - udev_device_copy_properties(dev, event->dev_db); + if (!event->mode_set) { + r = device_get_devnode_mode(dev, &event->mode); + if (r < 0 && r != -ENOENT) + return log_device_error_errno(dev, r, "Failed to get devnode mode: %m"); + if (r == -ENOENT) { + if (event->gid > 0) + /* default 0660 if a group is assigned */ + event->mode = 0660; + else + /* default 0600 */ + event->mode = 0600; } + } - udev_rules_apply_to_event(rules, event, - timeout_usec, timeout_warn_usec, - properties_list); + r = sd_device_get_property_value(dev, "ACTION", &action); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to get property 'ACTION': %m"); - /* rename a new network interface, if needed */ - if (udev_device_get_ifindex(dev) > 0 && streq(udev_device_get_action(dev), "add") && - event->name != NULL && !streq(event->name, udev_device_get_sysname(dev))) { - int r; + apply = streq(action, "add") || event->owner_set || event->group_set || event->mode_set; + return udev_node_add(dev, apply, event->mode, event->uid, event->gid, event->seclabel_list); +} - r = rename_netif(event); - if (r < 0) - log_warning_errno(r, "could not rename interface '%d' from '%s' to '%s': %m", udev_device_get_ifindex(dev), - udev_device_get_sysname(dev), event->name); - else { - r = udev_device_rename(dev, event->name); +static void event_execute_rules_on_remove( + struct udev_event *event, + usec_t timeout_usec, usec_t timeout_warn_usec, + Hashmap *properties_list, + struct udev_rules *rules) { + + sd_device *dev = event->dev->device; + dev_t devnum; + int r; + + r = device_read_db_force(dev); + 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"); + + r = sd_device_get_devnum(dev, &devnum); + if (r < 0) { + if (r != -ENOENT) + log_device_debug_errno(dev, r, "Failed to get devnum, ignoring: %m"); + } else + (void) udev_watch_end(dev); + + (void) udev_rules_apply_to_event(rules, event, + timeout_usec, timeout_warn_usec, + properties_list); + + if (major(devnum) > 0) + (void) udev_node_remove(dev); +} + +int udev_event_execute_rules(struct udev_event *event, + usec_t timeout_usec, usec_t timeout_warn_usec, + Hashmap *properties_list, + struct udev_rules *rules) { + _cleanup_(sd_device_unrefp) sd_device *clone = NULL; + sd_device *dev = event->dev->device; + const char *subsystem, *action; + dev_t devnum; + int r; + + assert(event); + assert(rules); + + r = sd_device_get_subsystem(dev, &subsystem); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to get subsystem: %m"); + + r = sd_device_get_property_value(dev, "ACTION", &action); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to get property 'ACTION': %m"); + + if (streq(action, "remove")) { + event_execute_rules_on_remove(event, timeout_usec, timeout_warn_usec, properties_list, rules); + return 0; + } + + r = device_clone_with_db(dev, &clone); + if (r < 0) + log_device_debug_errno(dev, r, "Failed to clone sd_device object, ignoring: %m"); + + if (clone) { + event->dev_db = udev_device_new(NULL, clone); + if (!event->dev_db) + return -ENOMEM; + + r = sd_device_get_devnum(dev, &devnum); + if (r < 0) { + if (r != -ENOENT) + log_device_debug_errno(dev, r, "Failed to get devnum, ignoring: %m"); + + if (streq(action, "move")) { + r = device_copy_properties(dev, clone); if (r < 0) - log_warning_errno(r, "renamed interface '%d' from '%s' to '%s', but could not update udev_device: %m", - udev_device_get_ifindex(dev), udev_device_get_sysname(dev), event->name); - else - log_debug("changed devpath to '%s'", udev_device_get_devpath(dev)); + log_device_debug_errno(dev, r, "Failed to copy properties from cloned device, ignoring: %m"); } - } + } else + /* Disable watch during event processing. */ + (void) udev_watch_end(clone); + } - if (major(udev_device_get_devnum(dev)) > 0) { - bool apply; - - /* remove/update possible left-over symlinks from old database entry */ - if (event->dev_db != NULL) - udev_node_update_old_links(dev->device, event->dev_db->device); - - if (!event->owner_set) - event->uid = udev_device_get_devnode_uid(dev); - - if (!event->group_set) - event->gid = udev_device_get_devnode_gid(dev); - - if (!event->mode_set) { - if (udev_device_get_devnode_mode(dev) > 0) { - /* kernel supplied value */ - event->mode = udev_device_get_devnode_mode(dev); - } else if (event->gid > 0) { - /* default 0660 if a group is assigned */ - event->mode = 0660; - } else { - /* default 0600 */ - event->mode = 0600; - } - } + (void) udev_rules_apply_to_event(rules, event, + timeout_usec, timeout_warn_usec, + properties_list); - apply = streq(udev_device_get_action(dev), "add") || event->owner_set || event->group_set || event->mode_set; - udev_node_add(dev->device, apply, event->mode, event->uid, event->gid, event->seclabel_list); - } + (void) rename_netif(event); + (void) update_devnode(event); - /* preserve old, or get new initialization timestamp */ - udev_device_ensure_usec_initialized(event->dev, event->dev_db); + /* preserve old, or get new initialization timestamp */ + r = device_ensure_usec_initialized(dev, clone); + if (r < 0) + log_device_debug_errno(dev, r, "Failed to set initialization timestamp, ignoring: %m"); - /* (re)write database file */ - udev_device_tag_index(dev, event->dev_db, true); - udev_device_update_db(dev); - udev_device_set_is_initialized(dev); + /* (re)write database file */ + r = device_tag_index(dev, clone, true); + if (r < 0) + log_device_debug_errno(dev, r, "Failed to update tags under /run/udev/tag/, ignoring: %m"); - event->dev_db = udev_device_unref(event->dev_db); - } + r = device_update_db(dev); + if (r < 0) + log_device_debug_errno(dev, r, "Failed to update database under /run/udev/data/, ignoring: %m"); + + device_set_is_initialized(dev); + + event->dev_db = udev_device_unref(event->dev_db); + + return 0; } void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec) { diff --git a/src/udev/udev.h b/src/udev/udev.h index c9250edd9a..f723dd7067 100644 --- a/src/udev/udev.h +++ b/src/udev/udev.h @@ -61,23 +61,21 @@ int udev_rules_apply_static_dev_perms(struct udev_rules *rules); /* udev-event.c */ struct udev_event *udev_event_new(struct udev_device *dev); -void udev_event_unref(struct udev_event *event); -size_t udev_event_apply_format(struct udev_event *event, - const char *src, char *dest, size_t size, - bool replace_whitespace); -int udev_event_apply_subsys_kernel(struct udev_event *event, const char *string, - char *result, size_t maxsize, int read_value); +struct udev_event *udev_event_free(struct udev_event *event); +ssize_t udev_event_apply_format(struct udev_event *event, + const char *src, char *dest, size_t size, + bool replace_whitespace); int udev_event_spawn(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, bool accept_failure, const char *cmd, char *result, size_t ressize); -void udev_event_execute_rules(struct udev_event *event, - usec_t timeout_usec, usec_t timeout_warn_usec, - Hashmap *properties_list, - struct udev_rules *rules); +int udev_event_execute_rules(struct udev_event *event, + usec_t timeout_usec, usec_t timeout_warn_usec, + Hashmap *properties_list, + struct udev_rules *rules); void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec); /* Cleanup functions */ -DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_event*, udev_event_unref); +DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_event*, udev_event_free); DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_rules*, udev_rules_unref); diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c index ea6471b837..20f713d738 100644 --- a/src/udev/udevadm-test.c +++ b/src/udev/udevadm-test.c @@ -89,7 +89,7 @@ static int parse_argv(int argc, char *argv[]) { int test_main(int argc, char *argv[], void *userdata) { _cleanup_(udev_rules_unrefp) struct udev_rules *rules = NULL; _cleanup_(udev_device_unrefp) struct udev_device *dev = NULL; - _cleanup_(udev_event_unrefp) struct udev_event *event = NULL; + _cleanup_(udev_event_freep) struct udev_event *event = NULL; struct udev_list_entry *entry; sigset_t mask, sigmask_orig; const char *cmd; diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 64f7f1ff2d..7ec30b92c3 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -398,7 +398,7 @@ static void worker_spawn(Manager *manager, struct event *event) { write_string_file("/proc/self/oom_score_adj", "0", 0); for (;;) { - struct udev_event *udev_event; + _cleanup_(udev_event_freep) struct udev_event *udev_event = NULL; int fd_lock = -1; assert(dev); @@ -477,8 +477,6 @@ skip: udev_device_unref(dev); dev = NULL; - udev_event_unref(udev_event); - /* wait for more device messages from main udevd, or term signal */ while (dev == NULL) { struct epoll_event ev[4]; |