summaryrefslogtreecommitdiff
path: root/udev/lib
diff options
context:
space:
mode:
Diffstat (limited to 'udev/lib')
-rw-r--r--udev/lib/exported_symbols3
-rw-r--r--udev/lib/libudev-device.c16
-rw-r--r--udev/lib/libudev-enumerate.c101
-rw-r--r--udev/lib/libudev-list.c10
-rw-r--r--udev/lib/libudev.h5
-rw-r--r--udev/lib/test-libudev.c45
6 files changed, 139 insertions, 41 deletions
diff --git a/udev/lib/exported_symbols b/udev/lib/exported_symbols
index 8c5f700d46..1877f32e89 100644
--- a/udev/lib/exported_symbols
+++ b/udev/lib/exported_symbols
@@ -10,6 +10,7 @@ udev_set_userdata
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
@@ -30,9 +31,11 @@ udev_device_get_driver
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_get_udev
udev_enumerate_get_list_entry
udev_monitor_new_from_socket
udev_monitor_new_from_netlink
diff --git a/udev/lib/libudev-device.c b/udev/lib/libudev-device.c
index a201fb25df..3437d69798 100644
--- a/udev/lib/libudev-device.c
+++ b/udev/lib/libudev-device.c
@@ -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]) {
- info(udev, "not in subdir :%s\n", syspath);
+ info(udev, "not a subdir :%s\n", syspath);
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);
- /* 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)) {
@@ -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) {
+ 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;
}
diff --git a/udev/lib/libudev-enumerate.c b/udev/lib/libudev-enumerate.c
index 8f5c5640b2..c7fb683c10 100644
--- a/udev/lib/libudev-enumerate.c
+++ b/udev/lib/libudev-enumerate.c
@@ -54,6 +54,13 @@ void udev_enumerate_unref(struct udev_enumerate *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)
@@ -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,
- struct list_node *device_list)
+ struct list_node *devices_list)
{
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));
- 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,
- 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;
}
@@ -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
- * @subsystem: the subsystem to enumerate
+ * @subsystem: the list of names of subsystems to look for devices
*
* 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;
+ va_list vargs;
+ const char *arg;
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)
@@ -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);
+ 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");
- 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");
- 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");
- 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)))
@@ -184,3 +228,8 @@ struct udev_enumerate *udev_enumerate_new_from_subsystems(struct udev *udev, con
}
return udev_enumerate;
}
+
+struct udev_enumerate *udev_enumerate_new_from_subsystems(struct udev *udev)
+{
+ return NULL;
+}
diff --git a/udev/lib/libudev-list.c b/udev/lib/libudev-list.c
index 895c665e40..00e3b7c37d 100644
--- a/udev/lib/libudev-list.c
+++ b/udev/lib/libudev-list.c
@@ -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);
}
+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)
diff --git a/udev/lib/libudev.h b/udev/lib/libudev.h
index 25b5f9c02a..29c4a47e51 100644
--- a/udev/lib/libudev.h
+++ b/udev/lib/libudev.h
@@ -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);
+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) \
@@ -93,8 +94,10 @@ extern struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev
/* 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 *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);
diff --git a/udev/lib/test-libudev.c b/udev/lib/test-libudev.c
index bff55cfcd6..0f485248e8 100644
--- a/udev/lib/test-libudev.c
+++ b/udev/lib/test-libudev.c
@@ -157,20 +157,16 @@ static int test_device_devnum(struct udev *udev)
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;
- 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;
- 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),
@@ -179,9 +175,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem)
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;
}
@@ -248,6 +242,7 @@ int main(int argc, char *argv[], char *envp[])
{ "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";
@@ -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_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);