1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-23 21:35:11 +03:00

libudev: enumerate - accept list of subsystems to scan, or skip

This commit is contained in:
Kay Sievers 2008-09-28 17:39:31 +02:00
parent 41b7a00922
commit bc8184ede9
8 changed files with 145 additions and 48 deletions

11
TODO
View File

@ -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"
o add libudev interface for /dev/.udev/queue/ state
o libudev queue - interface for /dev/.udev/queue/ state
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
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,

View File

@ -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

View 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]) {
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;
}

View File

@ -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_include_list != NULL) {
struct udev_list_entry *list_entry;
if (subsystem != NULL)
return devices_scan_subsystem(udev, basedir, subsystem, 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;
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 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;
}

View 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);
}
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)

View 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);
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);

View File

@ -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);

View File

@ -186,7 +186,7 @@ static int export_devices(struct udev *udev)
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)) {
@ -301,7 +301,7 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
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));