X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=libudev%2Flibudev-enumerate.c;h=6870bb611598a3f752b67d2301624a4506c00869;hb=b4155660f2b60006816de5966d2b1859dc57ff6a;hp=363d445f90a5f63a569cf4d1d15378456b119180;hpb=cad40a5fe75d876af22f68b688494b9cd98cc899;p=elogind.git diff --git a/libudev/libudev-enumerate.c b/libudev/libudev-enumerate.c index 363d445f9..6870bb611 100644 --- a/libudev/libudev-enumerate.c +++ b/libudev/libudev-enumerate.c @@ -57,6 +57,7 @@ struct udev_enumerate { unsigned int devices_cur; unsigned int devices_max; bool devices_uptodate:1; + bool match_is_initialized; }; /** @@ -273,6 +274,8 @@ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *ude /* skip to be delayed devices, and add them to the end of the list */ if (devices_delay_end(udev_enumerate->udev, entry->syspath)) { syspath_add(udev_enumerate, entry->syspath); + /* need to update prev here for the case realloc() gives a different address */ + prev = &udev_enumerate->devices[i]; continue; } @@ -456,6 +459,32 @@ int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const ch return 0; } +/** + * udev_enumerate_add_match_is_initialized: + * @udev_enumerate: context + * + * Match only devices which udev has set up already. This makes + * sure, that the device node permissions and context are properly set + * and that network devices are fully renamed. + * + * Usually, devices which are found in the kernel but not already + * handled by udev, have still pending events. Services should subscribe + * to monitor events and wait for these devices to become ready, instead + * of using uninitialized devices. + * + * For now, this will not affect devices which do not have a device node + * and are not network interfaces. + * + * Returns: 0 on success, otherwise a negative error value. + */ +int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate) +{ + if (udev_enumerate == NULL) + return -EINVAL; + udev_enumerate->match_is_initialized = true; + return 0; +} + /** * udev_enumerate_add_match_sysname: * @udev_enumerate: context @@ -601,6 +630,21 @@ static int scan_dir_and_add_devices(struct udev_enumerate *udev_enumerate, if (dev == NULL) continue; + if (udev_enumerate->match_is_initialized) { + /* + * All devices with a device node or network interfaces + * possibly need udev to adjust the device node permission + * or context, or rename the interface before it can be + * reliably used from other processes. + * + * For now, we can only check these types of devices, we + * might not store a database, and have no way to find out + * for all other types of devices. + */ + if (!udev_device_get_is_initialized(dev) && + (major(udev_device_get_devnum(dev)) > 0 || udev_device_get_ifindex(dev) > 0)) + goto nomatch; + } if (!match_tag(udev_enumerate, dev)) goto nomatch; if (!match_property(udev_enumerate, dev)) @@ -707,7 +751,7 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) struct dirent *dent; char path[UTIL_PATH_SIZE]; - util_strscpyl(path, sizeof(path), udev_get_dev_path(udev), "/.udev/tags/", + util_strscpyl(path, sizeof(path), udev_get_run_path(udev), "/tags/", udev_list_entry_get_name(list_entry), NULL); dir = opendir(path); if (dir == NULL)