chiark / gitweb /
libudev: fix renamed device nodes detection logic
[elogind.git] / libudev / libudev-device.c
index ac206a0e16700b14c156483516957490149c69bf..66f806316f55d75143f4d7a2e2242f99bcad805b 100644 (file)
@@ -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;
@@ -475,6 +477,32 @@ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, de
        return udev_device_new_from_syspath(udev, path);
 }
 
+struct udev_device *udev_device_new_from_id_filename(struct udev *udev, char *id)
+{
+       char type;
+       int maj, min;
+       char subsys[UTIL_PATH_SIZE];
+       char *sysname;
+
+       switch(id[0]) {
+       case 'b':
+       case 'c':
+               if (sscanf(id, "%c%i:%i", &type, &maj, &min) != 3)
+                       return NULL;
+               return udev_device_new_from_devnum(udev, type, makedev(maj, min));
+       case '+':
+               util_strscpy(subsys, sizeof(subsys), &id[1]);
+               sysname = strchr(subsys, ':');
+               if (sysname == NULL)
+                       return NULL;
+               sysname[0] = '\0';
+               sysname = &sysname[1];
+               return udev_device_new_from_subsystem_sysname(udev, subsys, sysname);
+       default:
+               return NULL;
+       }
+}
+
 /**
  * udev_device_new_from_subsystem_sysname:
  * @udev: udev library context
@@ -1261,7 +1289,7 @@ const char *udev_device_get_id_filename(struct udev_device *udev_device)
                                     major(udev_device_get_devnum(udev_device)),
                                     minor(udev_device_get_devnum(udev_device))) < 0)
                                udev_device->id_filename = NULL;
-               } else if (strcmp(udev_device_get_subsystem(udev_device), "net") == 0) {
+               } else if (udev_device_get_ifindex(udev_device) > 0) {
                        /* use netdev ifindex -- n3 */
                        if (asprintf(&udev_device->id_filename, "n%u", udev_device_get_ifindex(udev_device)) < 0)
                                udev_device->id_filename = NULL;
@@ -1282,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)
@@ -1556,6 +1609,8 @@ int udev_device_set_watch_handle(struct udev_device *udev_device, int handle)
 
 int udev_device_get_ifindex(struct udev_device *udev_device)
 {
+       if (!udev_device->info_loaded)
+               udev_device_read_uevent_file(udev_device);
        return udev_device->ifindex;
 }