chiark / gitweb /
libudev: return kernel provided devnode when asked before we handled any rules
[elogind.git] / libudev / libudev-device.c
index 478fdcb92d7f80231662b10ccfceef6f1a2c7900..9b5d79ff4bf7e7caadd179794fa810f2497c16e5 100644 (file)
@@ -67,6 +67,7 @@ struct udev_device {
        int devlink_priority;
        int refcount;
        dev_t devnum;
+       int ifindex;
        int watch_handle;
        int maj, min;
        bool parent_set;
@@ -187,6 +188,8 @@ void udev_device_add_property_from_string_parse(struct udev_device *udev_device,
                udev_device_set_seqnum(udev_device, strtoull(&property[7], NULL, 10));
        } else if (strncmp(property, "TIMEOUT=", 8) == 0) {
                udev_device_set_timeout(udev_device, strtoull(&property[8], NULL, 10));
+       } else if (strncmp(property, "IFINDEX=", 8) == 0) {
+               udev_device_set_ifindex(udev_device, strtoull(&property[8], NULL, 10));
        } else {
                udev_device_add_property_from_string(udev_device, property);
        }
@@ -279,11 +282,13 @@ int udev_device_read_db(struct udev_device *udev_device)
                return 0;
        }
 
-       f = fopen(filename, "r");
+       f = fopen(filename, "re");
        if (f == NULL) {
                dbg(udev_device->udev, "error reading db file %s: %m\n", filename);
                return -1;
        }
+       udev_device->db_loaded = true;
+
        while (fgets(line, sizeof(line), f)) {
                ssize_t len;
                const char *val;
@@ -322,7 +327,6 @@ int udev_device_read_db(struct udev_device *udev_device)
        fclose(f);
 
        info(udev_device->udev, "device %p filled with db file data\n", udev_device);
-       udev_device->db_loaded = true;
        return 0;
 }
 
@@ -338,9 +342,10 @@ int udev_device_read_uevent_file(struct udev_device *udev_device)
                return 0;
 
        util_strscpyl(filename, sizeof(filename), udev_device->syspath, "/uevent", NULL);
-       f = fopen(filename, "r");
+       f = fopen(filename, "re");
        if (f == NULL)
                return -1;
+       udev_device->uevent_loaded = true;
 
        while (fgets(line, sizeof(line), f)) {
                char *pos;
@@ -356,6 +361,8 @@ int udev_device_read_uevent_file(struct udev_device *udev_device)
                        maj = strtoull(&line[6], NULL, 10);
                else if (strncmp(line, "MINOR=", 6) == 0)
                        min = strtoull(&line[6], NULL, 10);
+               else if (strncmp(line, "IFINDEX=", 8) == 0)
+                       udev_device_set_ifindex(udev_device, strtoull(&line[8], NULL, 10));
                else if (strncmp(line, "DEVNAME=", 8) == 0)
                        udev_device_set_knodename(udev_device, &line[8]);
 
@@ -364,7 +371,6 @@ int udev_device_read_uevent_file(struct udev_device *udev_device)
 
        udev_device->devnum = makedev(maj, min);
        fclose(f);
-       udev_device->uevent_loaded = true;
        return 0;
 }
 
@@ -870,8 +876,19 @@ const char *udev_device_get_devnode(struct udev_device *udev_device)
 {
        if (udev_device == NULL)
                return NULL;
-       if (!udev_device->info_loaded)
+       if (!udev_device->info_loaded) {
+               udev_device_read_uevent_file(udev_device);
                udev_device_read_db(udev_device);
+       }
+
+       /* we might get called before we handled an event and have a db, use the kernel-provided name */
+       if (udev_device->devnode == NULL && udev_device_get_knodename(udev_device) != NULL) {
+               if (asprintf(&udev_device->devnode, "%s/%s",
+                            udev_get_dev_path(udev_device->udev), udev_device_get_knodename(udev_device)) < 0)
+                       return NULL;
+               return udev_device->devnode;
+       }
+
        return udev_device->devnode;
 }
 
@@ -1163,7 +1180,7 @@ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const
                goto out;
 
        /* read attribute value */
-       fd = open(path, O_RDONLY);
+       fd = open(path, O_RDONLY|O_CLOEXEC);
        if (fd < 0) {
                dbg(udev_device->udev, "attribute '%s' can not be opened\n", path);
                goto out;
@@ -1286,8 +1303,21 @@ void udev_device_cleanup_tags_list(struct udev_device *udev_device)
        udev_list_cleanup_entries(udev_device->udev, &udev_device->tags_list);
 }
 
+/**
+ * udev_device_get_tags_list_entry:
+ * @udev_device: udev device
+ *
+ * Retrieve the list of tags attached to the udev device. The next
+ * list entry can be retrieved with udev_list_entry_next(),
+ * which returns #NULL if no more entries exist. The tag string
+ * can be retrieved from the list entry by udev_list_get_name().
+ *
+ * Returns: the first entry of the tag list
+ **/
 struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device)
 {
+       if (udev_device == NULL)
+               return NULL;
        return udev_list_get_entry(&udev_device->tags_list);
 }
 
@@ -1522,3 +1552,14 @@ int udev_device_set_watch_handle(struct udev_device *udev_device, int handle)
        udev_device->watch_handle = handle;
        return 0;
 }
+
+int udev_device_get_ifindex(struct udev_device *udev_device)
+{
+       return udev_device->ifindex;
+}
+
+int udev_device_set_ifindex(struct udev_device *udev_device, int ifindex)
+{
+       udev_device->ifindex = ifindex;
+       return 0;
+}