chiark / gitweb /
libudev: enumerate - accept list of subsystems to scan, or skip
authorKay Sievers <kay.sievers@vrfy.org>
Sun, 28 Sep 2008 15:39:31 +0000 (17:39 +0200)
committerKay Sievers <kay.sievers@vrfy.org>
Sun, 28 Sep 2008 15:39:31 +0000 (17:39 +0200)
TODO
udev/lib/exported_symbols
udev/lib/libudev-device.c
udev/lib/libudev-enumerate.c
udev/lib/libudev-list.c
udev/lib/libudev.h
udev/lib/test-libudev.c
udev/udevadm-info.c

diff --git a/TODO b/TODO
index 01c41254601d6496fb86899cdafff120b9894b53..8d7858fbeffa15ee985aee3581f14c8c2c547354 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,13 +1,12 @@
-  o enumerate() - add buses and drivers
+  o libudev enumerate
+      add buses and drivers
+      add /sys/block/ scanning crap
       use enumerate for "trigger"
       use enumerate for "trigger"
-
-  o add libudev interface for /dev/.udev/queue/ state
+  o libudev queue - interface for /dev/.udev/queue/ state
       use queue interface for "settle"
       use queue interface for "settle"
-
-  o use libudev in udev_rules.c
+  o use libudev device in udev_rules.c
       get rid of udevice, store rule matching state in rule iterator
   o rework rules to a match-action list, instead of a rules array
       get rid of udevice, store rule matching state in rule iterator
   o rework rules to a match-action list, instead of a rules array
-
   o add DVB variables to kernel, and drop shell script rule
   o add watershed extra
   o log warning if the kernel uses CONFIG_SYSFS_DEPRECATED*=y,
   o add DVB variables to kernel, and drop shell script rule
   o add watershed extra
   o log warning if the kernel uses CONFIG_SYSFS_DEPRECATED*=y,
index 8c5f700d4634a3f57a54cd93539e992c7d60143e..1877f32e8910ea253439a94be91c35d51731d585 100644 (file)
@@ -10,6 +10,7 @@ udev_set_userdata
 udev_get_sys_path
 udev_get_dev_path
 udev_list_entry_get_next
 udev_get_sys_path
 udev_get_dev_path
 udev_list_entry_get_next
+udev_list_entry_get_by_name
 udev_list_entry_get_name
 udev_list_entry_get_value
 udev_device_new_from_syspath
 udev_list_entry_get_name
 udev_list_entry_get_value
 udev_device_new_from_syspath
@@ -30,9 +31,11 @@ udev_device_get_driver
 udev_device_get_devnum
 udev_device_get_seqnum
 udev_device_get_attr_value
 udev_device_get_devnum
 udev_device_get_seqnum
 udev_device_get_attr_value
+udev_enumerate_new_from_devices
 udev_enumerate_new_from_subsystems
 udev_enumerate_ref
 udev_enumerate_unref
 udev_enumerate_new_from_subsystems
 udev_enumerate_ref
 udev_enumerate_unref
+udev_enumerate_get_udev
 udev_enumerate_get_list_entry
 udev_monitor_new_from_socket
 udev_monitor_new_from_netlink
 udev_enumerate_get_list_entry
 udev_monitor_new_from_socket
 udev_monitor_new_from_netlink
index a201fb25df95c17250ec184ce44822eeff8a200a..3437d69798706cd8c3730d25df34ad932845bd50 100644 (file)
@@ -252,7 +252,7 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *
        subdir = &syspath[len+1];
        pos = strrchr(subdir, '/');
        if (pos == NULL || pos < &subdir[2]) {
        subdir = &syspath[len+1];
        pos = strrchr(subdir, '/');
        if (pos == NULL || pos < &subdir[2]) {
-               info(udev, "not in subdir :%s\n", syspath);
+               info(udev, "not a subdir :%s\n", syspath);
                return NULL;
        }
 
                return NULL;
        }
 
@@ -312,8 +312,11 @@ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, de
        if (util_resolve_sys_link(udev, path, sizeof(path)) == 0)
                return udev_device_new_from_syspath(udev, path);
 
        if (util_resolve_sys_link(udev, path, sizeof(path)) == 0)
                return udev_device_new_from_syspath(udev, path);
 
-       /* fallback to search all sys devices for the major/minor */
-       enumerate = udev_enumerate_new_from_subsystems(udev, NULL);
+       /* fallback to search sys devices for the major/minor */
+       if (type == 'b')
+               enumerate = udev_enumerate_new_from_devices(udev, "block", NULL);
+       else if (type == 'c')
+               enumerate = udev_enumerate_new_from_devices(udev, "!block", NULL);
        if (enumerate == NULL)
                return NULL;
        udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) {
        if (enumerate == NULL)
                return NULL;
        udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) {
@@ -322,6 +325,13 @@ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, de
                device_loop = udev_device_new_from_syspath(udev, udev_list_entry_get_name(list_entry));
                if (device_loop != NULL) {
                        if (udev_device_get_devnum(device_loop) == devnum) {
                device_loop = udev_device_new_from_syspath(udev, udev_list_entry_get_name(list_entry));
                if (device_loop != NULL) {
                        if (udev_device_get_devnum(device_loop) == devnum) {
+                               const char *subsystem;
+
+                               subsystem = udev_device_get_subsystem(device_loop);
+                               if (type == 'b' && strcmp(subsystem, "block") != 0)
+                                       continue;
+                               if (type == 'c' && strcmp(subsystem, "block") == 0)
+                                       continue;
                                device = device_loop;
                                break;
                        }
                                device = device_loop;
                                break;
                        }
index 8f5c5640b25113748239e6568b4210d169df1831..c7fb683c1084354e37c78bb9f5c397993dfe7de0 100644 (file)
@@ -54,6 +54,13 @@ void udev_enumerate_unref(struct udev_enumerate *udev_enumerate)
        free(udev_enumerate);
 }
 
        free(udev_enumerate);
 }
 
+struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate)
+{
+       if (udev_enumerate == NULL)
+               return NULL;
+       return udev_enumerate->udev;
+}
+
 struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate)
 {
        if (udev_enumerate == NULL)
 struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate)
 {
        if (udev_enumerate == NULL)
@@ -63,7 +70,7 @@ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *ude
 
 static int devices_scan_subsystem(struct udev *udev,
                                  const char *basedir, const char *subsystem, const char *subdir,
 
 static int devices_scan_subsystem(struct udev *udev,
                                  const char *basedir, const char *subsystem, const char *subdir,
-                                 struct list_node *device_list)
+                                 struct list_node *devices_list)
 {
        char path[UTIL_PATH_SIZE];
        DIR *dir;
 {
        char path[UTIL_PATH_SIZE];
        DIR *dir;
@@ -87,34 +94,44 @@ static int devices_scan_subsystem(struct udev *udev,
                util_strlcat(syspath, "/", sizeof(syspath));
                util_strlcat(syspath, dent->d_name, sizeof(syspath));
                util_resolve_sys_link(udev, syspath, sizeof(syspath));
                util_strlcat(syspath, "/", sizeof(syspath));
                util_strlcat(syspath, dent->d_name, sizeof(syspath));
                util_resolve_sys_link(udev, syspath, sizeof(syspath));
-               list_entry_add(udev, device_list, syspath, NULL, 1, 1);
+               list_entry_add(udev, devices_list, syspath, NULL, 1, 1);
        }
        closedir(dir);
        return 0;
 }
 
 static int devices_scan_subsystems(struct udev *udev,
        }
        closedir(dir);
        return 0;
 }
 
 static int devices_scan_subsystems(struct udev *udev,
-                                  const char *basedir, const char *subsystem, const char *subdir,
-                                  struct list_node *device_list)
+                                  const char *basedir, const char *subdir,
+                                  struct udev_list_entry *subsystem_include_list,
+                                  struct udev_list_entry *subsystem_exclude_list,
+                                  struct list_node *devices_list)
 {
 {
-       char path[UTIL_PATH_SIZE];
-       DIR *dir;
-       struct dirent *dent;
-
-       if (subsystem != NULL)
-               return devices_scan_subsystem(udev, basedir, subsystem, subdir, device_list);
+       if (subsystem_include_list != NULL) {
+               struct udev_list_entry *list_entry;
 
 
-       util_strlcpy(path, udev_get_sys_path(udev), sizeof(path));
-       util_strlcat(path, basedir, sizeof(path));
-       dir = opendir(path);
-       if (dir == NULL)
-               return -1;
-       for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
-               if (dent->d_name[0] == '.')
-                       continue;
-               devices_scan_subsystem(udev, basedir, dent->d_name, subdir, device_list);
+               /* if list of subsystems to scan is given, just use this list */
+               udev_list_entry_foreach(list_entry, subsystem_include_list)
+                       devices_scan_subsystem(udev, basedir, udev_list_entry_get_name(list_entry), subdir, devices_list);
+       } else {
+               char path[UTIL_PATH_SIZE];
+               DIR *dir;
+               struct dirent *dent;
+
+               /* if no list of subsystems to scan is given, scan all, and possible exclude some subsystems */
+               util_strlcpy(path, udev_get_sys_path(udev), sizeof(path));
+               util_strlcat(path, basedir, sizeof(path));
+               dir = opendir(path);
+               if (dir == NULL)
+                       return -1;
+               for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
+                       if (dent->d_name[0] == '.')
+                               continue;
+                       if (udev_list_entry_get_by_name(subsystem_exclude_list, dent->d_name) != NULL)
+                                       continue;
+                       devices_scan_subsystem(udev, basedir, dent->d_name, subdir, devices_list);
+               }
+               closedir(dir);
        }
        }
-       closedir(dir);
        return 0;
 }
 
        return 0;
 }
 
@@ -140,17 +157,21 @@ static int devices_delay(struct udev *udev, const char *syspath)
 }
 
 /**
 }
 
 /**
- * udev_enumerate_new_from_subsystems:
+ * udev_enumerate_new_from_devices:
  * @udev: udev library context
  * @udev: udev library context
- * @subsystem: the subsystem to enumerate
+ * @subsystem: the list of names of subsystems to look for devices
  *
  * Returns: an enumeration context
  **/
  *
  * Returns: an enumeration context
  **/
-struct udev_enumerate *udev_enumerate_new_from_subsystems(struct udev *udev, const char *subsystem)
+struct udev_enumerate *udev_enumerate_new_from_devices(struct udev *udev, const char *subsystem, ...)
 {
        struct udev_enumerate *udev_enumerate;
 {
        struct udev_enumerate *udev_enumerate;
+       va_list vargs;
+       const char *arg;
        char base[UTIL_PATH_SIZE];
        struct stat statbuf;
        char base[UTIL_PATH_SIZE];
        struct stat statbuf;
+       struct list_node subsystem_include_list;
+       struct list_node subsystem_exclude_list;
        struct udev_list_entry *list_entry;
 
        if (udev == NULL)
        struct udev_list_entry *list_entry;
 
        if (udev == NULL)
@@ -164,19 +185,42 @@ struct udev_enumerate *udev_enumerate_new_from_subsystems(struct udev *udev, con
        udev_enumerate->udev = udev;
        list_init(&udev_enumerate->devices_list);
 
        udev_enumerate->udev = udev;
        list_init(&udev_enumerate->devices_list);
 
+       va_start(vargs, subsystem);
+       list_init(&subsystem_include_list);
+       list_init(&subsystem_exclude_list);
+       for (arg = subsystem; arg != NULL; arg = va_arg(vargs, const char *)) {
+               if (arg[0] != '!')
+                       list_entry_add(udev, &subsystem_include_list, arg, NULL, 1, 0);
+               else
+                       list_entry_add(udev, &subsystem_exclude_list, &arg[1], NULL, 1, 0);
+       }
+       va_end(vargs);
+
        /* if we have /sys/subsystem/, forget all the old stuff */
        util_strlcpy(base, udev_get_sys_path(udev), sizeof(base));
        util_strlcat(base, "/subsystem", sizeof(base));
        if (stat(base, &statbuf) == 0) {
                info(udev, "searching 'subsystem/*/devices/*' dir\n");
        /* if we have /sys/subsystem/, forget all the old stuff */
        util_strlcpy(base, udev_get_sys_path(udev), sizeof(base));
        util_strlcat(base, "/subsystem", sizeof(base));
        if (stat(base, &statbuf) == 0) {
                info(udev, "searching 'subsystem/*/devices/*' dir\n");
-               devices_scan_subsystems(udev, "/subsystem", subsystem, "/devices", &udev_enumerate->devices_list);
+               devices_scan_subsystems(udev, "/subsystem", "/devices",
+                                       list_get_entry(&subsystem_include_list),
+                                       list_get_entry(&subsystem_exclude_list),
+                                       &udev_enumerate->devices_list);
        } else {
                info(udev, "searching 'bus/*/devices/*' dir\n");
        } else {
                info(udev, "searching 'bus/*/devices/*' dir\n");
-               devices_scan_subsystems(udev, "/bus", subsystem, "/devices", &udev_enumerate->devices_list);
+               devices_scan_subsystems(udev, "/bus", "/devices",
+                                       list_get_entry(&subsystem_include_list),
+                                       list_get_entry(&subsystem_exclude_list),
+                                       &udev_enumerate->devices_list);
                info(udev, "searching 'class/*' dir\n");
                info(udev, "searching 'class/*' dir\n");
-               devices_scan_subsystems(udev, "/class", subsystem, NULL, &udev_enumerate->devices_list);
+               devices_scan_subsystems(udev, "/class", NULL,
+                                       list_get_entry(&subsystem_include_list),
+                                       list_get_entry(&subsystem_exclude_list),
+                                       &udev_enumerate->devices_list);
        }
 
        }
 
+       list_cleanup(udev, &subsystem_include_list);
+       list_cleanup(udev, &subsystem_exclude_list);
+
        /* sort delayed devices to the end of the list */
        udev_list_entry_foreach(list_entry, list_get_entry(&udev_enumerate->devices_list)) {
                if (devices_delay(udev, udev_list_entry_get_name(list_entry)))
        /* sort delayed devices to the end of the list */
        udev_list_entry_foreach(list_entry, list_get_entry(&udev_enumerate->devices_list)) {
                if (devices_delay(udev, udev_list_entry_get_name(list_entry)))
@@ -184,3 +228,8 @@ struct udev_enumerate *udev_enumerate_new_from_subsystems(struct udev *udev, con
        }
        return udev_enumerate;
 }
        }
        return udev_enumerate;
 }
+
+struct udev_enumerate *udev_enumerate_new_from_subsystems(struct udev *udev)
+{
+       return NULL;
+}
index 895c665e407c24c57d1751df14835f18cedb102d..00e3b7c37d6ac0a278a65a4c1ee8dbe51f2e4f19 100644 (file)
@@ -192,6 +192,16 @@ struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_en
        return list_node_to_entry(next);
 }
 
        return list_node_to_entry(next);
 }
 
+struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name)
+{
+       struct udev_list_entry *entry;
+
+       udev_list_entry_foreach(entry, list_entry)
+               if (strcmp(udev_list_entry_get_name(entry), name) == 0)
+                       return entry;
+       return NULL;
+}
+
 const char *udev_list_entry_get_name(struct udev_list_entry *list_entry)
 {
        if (list_entry == NULL)
 const char *udev_list_entry_get_name(struct udev_list_entry *list_entry)
 {
        if (list_entry == NULL)
index 25b5f9c02ac2221ef92ad7cdd3285b8f2a8ffd13..29c4a47e51475af27aa6dc0cfc3990d02d401255 100644 (file)
@@ -52,6 +52,7 @@ extern void udev_selinux_lsetfilecon(struct udev *udev, const char *file, unsign
 /* list iteration */
 struct udev_list_entry;
 extern struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry);
 /* list iteration */
 struct udev_list_entry;
 extern struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry);
+extern struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name);
 extern const char *udev_list_entry_get_name(struct udev_list_entry *list_entry);
 extern const char *udev_list_entry_get_value(struct udev_list_entry *list_entry);
 #define udev_list_entry_foreach(entry, first) \
 extern const char *udev_list_entry_get_name(struct udev_list_entry *list_entry);
 extern const char *udev_list_entry_get_value(struct udev_list_entry *list_entry);
 #define udev_list_entry_foreach(entry, first) \
@@ -93,8 +94,10 @@ extern struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev
 
 /* sys enumeration */
 struct udev_enumerate;
 
 /* sys enumeration */
 struct udev_enumerate;
-extern struct udev_enumerate *udev_enumerate_new_from_subsystems(struct udev *udev, const char *subsystem);
+extern struct udev_enumerate *udev_enumerate_new_from_devices(struct udev *udev, const char *subsystem, ...);
+extern struct udev_enumerate *udev_enumerate_new_from_subsystems(struct udev *udev);
 extern struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate);
 extern struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate);
+extern struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate);
 extern void udev_enumerate_unref(struct udev_enumerate *udev_enumerate);
 extern struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate);
 
 extern void udev_enumerate_unref(struct udev_enumerate *udev_enumerate);
 extern struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate);
 
index bff55cfcd61180c9166ce595ea195bec90e90f1e..0f485248e83a36d6fc9757574d4a5b592cd290cb 100644 (file)
@@ -157,20 +157,16 @@ static int test_device_devnum(struct udev *udev)
        return 0;
 }
 
        return 0;
 }
 
-static int test_enumerate(struct udev *udev, const char *subsystem)
+static int test_enumerate_print_list(struct udev_enumerate *enumerate)
 {
 {
-       struct udev_enumerate *enumerate;
        struct udev_list_entry *list_entry;
        int count = 0;
 
        struct udev_list_entry *list_entry;
        int count = 0;
 
-       enumerate = udev_enumerate_new_from_subsystems(udev, NULL);
-       if (enumerate == NULL)
-               return -1;
-       list_entry = udev_enumerate_get_list_entry(enumerate);
-       while (list_entry != NULL) {
+       udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) {
                struct udev_device *device;
 
                struct udev_device *device;
 
-               device = udev_device_new_from_syspath(udev, udev_list_entry_get_name(list_entry));
+               device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate),
+                                                     udev_list_entry_get_name(list_entry));
                if (device != NULL) {
                        printf("device:    '%s' (%s) '%s'\n",
                               udev_device_get_syspath(device),
                if (device != NULL) {
                        printf("device:    '%s' (%s) '%s'\n",
                               udev_device_get_syspath(device),
@@ -179,9 +175,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem)
                        udev_device_unref(device);
                        count++;
                }
                        udev_device_unref(device);
                        count++;
                }
-               list_entry = udev_list_entry_get_next(list_entry);
        }
        }
-       udev_enumerate_unref(enumerate);
        printf("found %i devices\n\n", count);
        return count;
 }
        printf("found %i devices\n\n", count);
        return count;
 }
@@ -248,6 +242,7 @@ int main(int argc, char *argv[], char *envp[])
                { "version", 0, NULL, 'V' },
                {}
        };
                { "version", 0, NULL, 'V' },
                {}
        };
+       struct udev_enumerate *enumerate;
        const char *syspath = "/devices/virtual/mem/null";
        const char *subsystem = NULL;
        const char *socket = "@/org/kernel/udev/monitor";
        const char *syspath = "/devices/virtual/mem/null";
        const char *subsystem = NULL;
        const char *socket = "@/org/kernel/udev/monitor";
@@ -309,7 +304,35 @@ int main(int argc, char *argv[], char *envp[])
        test_device(udev, syspath);
        test_device_devnum(udev);
        test_device_parents(udev, syspath);
        test_device(udev, syspath);
        test_device_devnum(udev);
        test_device_parents(udev, syspath);
-       test_enumerate(udev, subsystem);
+
+       printf("enumerate '%s'\n", subsystem == NULL ? "<all>" : subsystem);
+       enumerate = udev_enumerate_new_from_devices(udev, subsystem, NULL);
+       if (enumerate == NULL)
+               return -1;
+       test_enumerate_print_list(enumerate);
+       udev_enumerate_unref(enumerate);
+
+       printf("enumerate 'block'\n");
+       enumerate = udev_enumerate_new_from_devices(udev, "block", NULL);
+       if (enumerate == NULL)
+               return -1;
+       test_enumerate_print_list(enumerate);
+       udev_enumerate_unref(enumerate);
+
+       printf("enumerate '!block'\n");
+       enumerate = udev_enumerate_new_from_devices(udev, "!block", NULL);
+       if (enumerate == NULL)
+               return -1;
+       test_enumerate_print_list(enumerate);
+       udev_enumerate_unref(enumerate);
+
+       printf("enumerate 'pci, mem, vc'\n");
+       enumerate = udev_enumerate_new_from_devices(udev, "pci", "mem", "vc", NULL);
+       if (enumerate == NULL)
+               return -1;
+       test_enumerate_print_list(enumerate);
+       udev_enumerate_unref(enumerate);
+
        test_monitor(udev, socket);
 out:
        udev_unref(udev);
        test_monitor(udev, socket);
 out:
        udev_unref(udev);
index f59c196e02e1796c5c95712edb8e117cbffbc098..e470ff624da662997ae1865ad965ca4eaa18cfad 100644 (file)
@@ -186,7 +186,7 @@ static int export_devices(struct udev *udev)
        struct udev_enumerate *enumerate;
        struct udev_list_entry *list_entry;
 
        struct udev_enumerate *enumerate;
        struct udev_list_entry *list_entry;
 
-       enumerate = udev_enumerate_new_from_subsystems(udev, NULL);
+       enumerate = udev_enumerate_new_from_devices(udev, NULL);
        if (enumerate == NULL)
                return -1;
        udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) {
        if (enumerate == NULL)
                return -1;
        udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) {
@@ -301,7 +301,7 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
                                rc = 2;
                                goto exit;
                        }
                                rc = 2;
                                goto exit;
                        }
-                       /* add /sys if needed */
+                       /* add sys dir if needed */
                        if (strncmp(optarg, udev_get_sys_path(udev), strlen(udev_get_sys_path(udev))) != 0) {
                                util_strlcpy(path, udev_get_sys_path(udev), sizeof(path));
                                util_strlcat(path, optarg, sizeof(path));
                        if (strncmp(optarg, udev_get_sys_path(udev), strlen(udev_get_sys_path(udev))) != 0) {
                                util_strlcpy(path, udev_get_sys_path(udev), sizeof(path));
                                util_strlcat(path, optarg, sizeof(path));