unsigned int devices_cur;
unsigned int devices_max;
bool devices_uptodate:1;
+ bool match_is_initialized;
};
/**
/* 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;
}
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
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))
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_dev_path(udev), "/.run/udev/tags/",
udev_list_entry_get_name(list_entry), NULL);
dir = opendir(path);
if (dir == NULL)
continue;
for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
struct udev_device *dev;
- char syspath[UTIL_PATH_SIZE];
- char *s;
- size_t l;
- ssize_t len;
if (dent->d_name[0] == '.')
continue;
- s = syspath;
- l = util_strpcpyl(&s, sizeof(syspath), udev_get_sys_path(udev), NULL);
- len = readlinkat(dirfd(dir), dent->d_name, s, l);
- if (len <= 0 || (size_t)len == l)
- continue;
- s[len] = '\0';
-
- dev = udev_device_new_from_syspath(udev_enumerate->udev, syspath);
+ dev = udev_device_new_from_id_filename(udev_enumerate->udev, dent->d_name);
if (dev == NULL)
continue;
syspath_add(udev_enumerate, udev_device_get_syspath(dev));