summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am6
-rw-r--r--libudev/docs/libudev-sections.txt2
-rw-r--r--libudev/exported_symbols2
-rw-r--r--libudev/libudev-device-private.c4
-rw-r--r--libudev/libudev-device.c27
-rw-r--r--libudev/libudev-enumerate.c42
-rw-r--r--libudev/libudev-private.h1
-rw-r--r--libudev/libudev.h2
-rw-r--r--libudev/test-libudev.c1
-rw-r--r--udev/udev-event.c9
10 files changed, 87 insertions, 9 deletions
diff --git a/Makefile.am b/Makefile.am
index 9fe4a3ac51..2e0edd0b14 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -34,9 +34,9 @@ DISTCHECK_HOOKS =
# ------------------------------------------------------------------------------
# libudev
# ------------------------------------------------------------------------------
-LIBUDEV_CURRENT=9
-LIBUDEV_REVISION=4
-LIBUDEV_AGE=9
+LIBUDEV_CURRENT=10
+LIBUDEV_REVISION=0
+LIBUDEV_AGE=10
SUBDIRS += libudev/docs
diff --git a/libudev/docs/libudev-sections.txt b/libudev/docs/libudev-sections.txt
index 63c0ee2e98..05647768fb 100644
--- a/libudev/docs/libudev-sections.txt
+++ b/libudev/docs/libudev-sections.txt
@@ -45,6 +45,7 @@ udev_device_get_syspath
udev_device_get_sysname
udev_device_get_sysnum
udev_device_get_devnode
+udev_device_get_is_initialized
udev_device_get_devlinks_list_entry
udev_device_get_properties_list_entry
udev_device_get_tags_list_entry
@@ -89,6 +90,7 @@ udev_enumerate_add_match_sysattr
udev_enumerate_add_nomatch_sysattr
udev_enumerate_add_match_property
udev_enumerate_add_match_tag
+udev_enumerate_add_match_is_initialized
udev_enumerate_add_match_sysname
udev_enumerate_add_syspath
udev_enumerate_scan_devices
diff --git a/libudev/exported_symbols b/libudev/exported_symbols
index 935e361db5..9e77fb1be1 100644
--- a/libudev/exported_symbols
+++ b/libudev/exported_symbols
@@ -28,6 +28,7 @@ udev_device_get_sysname
udev_device_get_sysnum
udev_device_get_subsystem
udev_device_get_devtype
+udev_device_get_is_initialized
udev_device_get_devlinks_list_entry
udev_device_get_properties_list_entry
udev_device_get_tags_list_entry
@@ -48,6 +49,7 @@ udev_enumerate_add_match_sysattr
udev_enumerate_add_nomatch_sysattr
udev_enumerate_add_match_property
udev_enumerate_add_match_tag
+udev_enumerate_add_match_is_initialized
udev_enumerate_add_match_sysname
udev_enumerate_scan_devices
udev_enumerate_scan_subsystems
diff --git a/libudev/libudev-device-private.c b/libudev/libudev-device-private.c
index 406d8704f5..d1df45ee74 100644
--- a/libudev/libudev-device-private.c
+++ b/libudev/libudev-device-private.c
@@ -114,7 +114,9 @@ int udev_device_update_db(struct udev_device *udev_device)
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/db/", id, NULL);
/* do not store anything for otherwise empty devices */
- if (!has_info && udev_device_get_devnode(udev_device) == NULL) {
+ if (!has_info &&
+ major(udev_device_get_devnum(udev_device)) == 0 &&
+ udev_device_get_ifindex(udev_device) == 0) {
unlink(filename);
return 0;
}
diff --git a/libudev/libudev-device.c b/libudev/libudev-device.c
index 8b0cccd533..66f806316f 100644
--- a/libudev/libudev-device.c
+++ b/libudev/libudev-device.c
@@ -81,6 +81,7 @@ struct udev_device {
bool info_loaded;
bool db_loaded;
bool uevent_loaded;
+ bool is_initialized;
};
struct udev_list_entry *udev_device_add_property(struct udev_device *udev_device, const char *key, const char *value)
@@ -249,6 +250,7 @@ int udev_device_read_db(struct udev_device *udev_device)
info(udev_device->udev, "no db file to read %s: %m\n", filename);
return -1;
}
+ udev_device->is_initialized = true;
while (fgets(line, sizeof(line), f)) {
ssize_t len;
@@ -1308,6 +1310,31 @@ const char *udev_device_get_id_filename(struct udev_device *udev_device)
return udev_device->id_filename;
}
+/**
+ * udev_device_get_is_initialized:
+ * @udev_device: udev device
+ *
+ * Check if udev has already handled the device and has set up
+ * device node permissions and context, or has renamed a network
+ * device.
+ *
+ * For now, this is only implemented for devices with a device node
+ * or network interfaces. All other devices return 1 here.
+ *
+ * Returns: 1 if the device is set up. 0 otherwise.
+ **/
+int udev_device_get_is_initialized(struct udev_device *udev_device)
+{
+ if (!udev_device->info_loaded)
+ udev_device_read_db(udev_device);
+ return udev_device->is_initialized;
+}
+
+void udev_device_set_is_initialized(struct udev_device *udev_device)
+{
+ udev_device->is_initialized = true;
+}
+
int udev_device_add_tag(struct udev_device *udev_device, const char *tag)
{
if (strchr(tag, ':') != NULL || strchr(tag, ' ') != NULL)
diff --git a/libudev/libudev-enumerate.c b/libudev/libudev-enumerate.c
index 363d445f90..e46bc087fa 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;
};
/**
@@ -457,6 +458,32 @@ int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const ch
}
/**
+ * 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
* @sysname: filter for the name of the device to include in the list
@@ -601,6 +628,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))
diff --git a/libudev/libudev-private.h b/libudev/libudev-private.h
index 2b638ce06e..f7b4f90519 100644
--- a/libudev/libudev-private.h
+++ b/libudev/libudev-private.h
@@ -87,6 +87,7 @@ const char *udev_device_get_sysname_old(struct udev_device *udev_device);
int udev_device_set_devpath_old(struct udev_device *udev_device, const char *devpath_old);
const char *udev_device_get_knodename(struct udev_device *udev_device);
const char *udev_device_get_id_filename(struct udev_device *udev_device);
+void udev_device_set_is_initialized(struct udev_device *udev_device);
int udev_device_add_tag(struct udev_device *udev_device, const char *tag);
void udev_device_cleanup_tags_list(struct udev_device *udev_device);
int udev_device_has_tag(struct udev_device *udev_device, const char *tag);
diff --git a/libudev/libudev.h b/libudev/libudev.h
index 5bc42df5be..087991caf4 100644
--- a/libudev/libudev.h
+++ b/libudev/libudev.h
@@ -88,6 +88,7 @@ const char *udev_device_get_syspath(struct udev_device *udev_device);
const char *udev_device_get_sysname(struct udev_device *udev_device);
const char *udev_device_get_sysnum(struct udev_device *udev_device);
const char *udev_device_get_devnode(struct udev_device *udev_device);
+int udev_device_get_is_initialized(struct udev_device *udev_device);
struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device);
struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device);
struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device);
@@ -141,6 +142,7 @@ int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, co
int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value);
int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname);
int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag);
+int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate);
int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath);
/* run enumeration with active filters */
int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate);
diff --git a/libudev/test-libudev.c b/libudev/test-libudev.c
index 3eb34494df..f8eb8e5d5a 100644
--- a/libudev/test-libudev.c
+++ b/libudev/test-libudev.c
@@ -354,6 +354,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem)
if (udev_enumerate == NULL)
return -1;
udev_enumerate_add_match_subsystem(udev_enumerate,"block");
+ udev_enumerate_add_match_is_initialized(udev_enumerate);
udev_enumerate_scan_devices(udev_enumerate);
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
diff --git a/udev/udev-event.c b/udev/udev-event.c
index 02a1767b1f..4d38c5b893 100644
--- a/udev/udev-event.c
+++ b/udev/udev-event.c
@@ -631,12 +631,7 @@ int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules)
/* set device node name */
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(event->udev), "/", event->name, NULL);
udev_device_set_devnode(dev, filename);
- }
-
- udev_device_update_db(dev);
- udev_device_tag_index(dev, event->dev_db, true);
- if (major(udev_device_get_devnum(dev)) != 0) {
/* remove/update possible left-over symlinks from old database entry */
if (event->dev_db != NULL)
udev_node_update_old_links(dev, event->dev_db);
@@ -648,6 +643,10 @@ int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules)
err = udev_node_add(dev, event->mode, event->uid, event->gid);
}
+ udev_device_update_db(dev);
+ udev_device_tag_index(dev, event->dev_db, true);
+ udev_device_set_is_initialized(dev);
+
udev_device_unref(event->dev_db);
event->dev_db = NULL;
}