From dbb13e92865be663fac07de79e6129074cdbdab9 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 7 Jul 2020 10:07:24 +0300 Subject: [PATCH] implement udev_enumerate_scan_devices, rewrite udev_device logic --- udev_device.c | 328 +++++++++++++++++------------------------------ udev_device.h | 13 +- udev_enumerate.c | 255 ++++++++++++++++++++++++++++++++++-- udev_enumerate.h | 6 + udev_list.c | 38 +++--- udev_monitor.c | 12 +- 6 files changed, 391 insertions(+), 261 deletions(-) create mode 100644 udev_enumerate.h diff --git a/udev_device.c b/udev_device.c index 4a14b64..ed38dfb 100644 --- a/udev_device.c +++ b/udev_device.c @@ -17,15 +17,6 @@ struct udev_device struct udev_list_entry sysattrs; struct udev_device *parent; struct udev *udev; - char *subsystem; - char *syspath; - char *sysname; - char *devpath; - char *devnode; - char *devtype; - char *driver; - char *sysnum; - dev_t devnum; int refcount; }; @@ -35,7 +26,7 @@ UDEV_EXPORT const char *udev_device_get_syspath(struct udev_device *udev_device) return NULL; } - return udev_device->syspath; + return udev_device_get_property_value(udev_device, "SYSPATH"); } UDEV_EXPORT const char *udev_device_get_sysname(struct udev_device *udev_device) @@ -44,7 +35,7 @@ UDEV_EXPORT const char *udev_device_get_sysname(struct udev_device *udev_device) return NULL; } - return udev_device->sysname; + return udev_device_get_property_value(udev_device, "DEVNAME"); } UDEV_EXPORT const char *udev_device_get_sysnum(struct udev_device *udev_device) @@ -53,7 +44,7 @@ UDEV_EXPORT const char *udev_device_get_sysnum(struct udev_device *udev_device) return NULL; } - return udev_device->sysnum; + return udev_device_get_property_value(udev_device, "SYSNUM"); } UDEV_EXPORT const char *udev_device_get_devpath(struct udev_device *udev_device) @@ -62,7 +53,7 @@ UDEV_EXPORT const char *udev_device_get_devpath(struct udev_device *udev_device) return NULL; } - return udev_device->devpath; + return udev_device_get_property_value(udev_device, "DEVPATH"); } UDEV_EXPORT const char *udev_device_get_devnode(struct udev_device *udev_device) @@ -71,16 +62,25 @@ UDEV_EXPORT const char *udev_device_get_devnode(struct udev_device *udev_device) return NULL; } - return udev_device->devnode; + return udev_device_get_property_value(udev_device, "DEVNODE"); } UDEV_EXPORT dev_t udev_device_get_devnum(struct udev_device *udev_device) { + const char *major, *minor; + if (!udev_device) { return makedev(0, 0); } - return udev_device->devnum; + major = udev_device_get_property_value(udev_device, "MAJOR"); + minor = udev_device_get_property_value(udev_device, "MINOR"); + + if (!major && !minor) { + return makedev(0, 0); + } + + return makedev(atoi(major), atoi(minor)); } UDEV_EXPORT const char *udev_device_get_devtype(struct udev_device *udev_device) @@ -89,7 +89,7 @@ UDEV_EXPORT const char *udev_device_get_devtype(struct udev_device *udev_device) return NULL; } - return udev_device->devtype; + return udev_device_get_property_value(udev_device, "DEVTYPE"); } UDEV_EXPORT const char *udev_device_get_subsystem(struct udev_device *udev_device) @@ -98,7 +98,7 @@ UDEV_EXPORT const char *udev_device_get_subsystem(struct udev_device *udev_devic return NULL; } - return udev_device->subsystem; + return udev_device_get_property_value(udev_device, "SUBSYSTEM"); } UDEV_EXPORT const char *udev_device_get_driver(struct udev_device *udev_device) @@ -107,16 +107,12 @@ UDEV_EXPORT const char *udev_device_get_driver(struct udev_device *udev_device) return NULL; } - return udev_device->driver; + return udev_device_get_property_value(udev_device, "DRIVER"); } UDEV_EXPORT struct udev *udev_device_get_udev(struct udev_device *udev_device) { - if (!udev_device) { - return NULL; - } - - return udev_device->udev; + return udev_device ? udev_device->udev : NULL; } UDEV_EXPORT struct udev_device *udev_device_get_parent(struct udev_device *udev_device) @@ -128,7 +124,7 @@ UDEV_EXPORT struct udev_device *udev_device_get_parent(struct udev_device *udev_ return NULL; } - path = strdup(udev_device->syspath); + path = strdup(udev_device_get_property_value(udev_device, "SYSPATH")); while (1) { slash = strrchr(path, '/') - path; @@ -204,11 +200,7 @@ UDEV_EXPORT struct udev_list_entry *udev_device_get_devlinks_list_entry(struct u UDEV_EXPORT struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device) { - if (!udev_device) { - return NULL; - } - - return &udev_device->properties; + return udev_device ? udev_list_entry_get_next(&udev_device->properties) : NULL; } UDEV_EXPORT struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device) @@ -219,15 +211,16 @@ UDEV_EXPORT struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_ UDEV_EXPORT struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device) { - if (!udev_device) { - return NULL; - } - - return &udev_device->sysattrs; + return udev_device ? udev_list_entry_get_next(&udev_device->sysattrs) : NULL; } UDEV_EXPORT const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key) { + struct udev_list_entry *list_entry; + + list_entry = udev_list_entry_get_by_name(&udev_device->properties, key); + + return udev_list_entry_get_value(list_entry); } UDEV_EXPORT const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr) @@ -248,7 +241,7 @@ UDEV_EXPORT const char *udev_device_get_sysattr_value(struct udev_device *udev_d return udev_list_entry_get_value(list_entry); } - if (xasprintf(path, "%s/%s", udev_device->syspath, sysattr) == -1) { + if (xasprintf(path, "%s/%s", udev_device_get_property_value(udev_device, "SYSPATH"), sysattr) == -1) { return NULL; } @@ -257,7 +250,7 @@ UDEV_EXPORT const char *udev_device_get_sysattr_value(struct udev_device *udev_d return NULL; } - fd = open(path, O_RDONLY); + fd = open(path, O_RDONLY | O_NOFOLLOW); if (fd == -1) { free(path); @@ -274,7 +267,7 @@ UDEV_EXPORT const char *udev_device_get_sysattr_value(struct udev_device *udev_d close(fd); free(path); - data[len] = '\0'; + data[len] = '\0'; // XXX strip trailing '\n' list_entry = udev_list_entry_add(&udev_device->sysattrs, sysattr, data); return udev_list_entry_get_value(list_entry); } @@ -290,7 +283,7 @@ UDEV_EXPORT int udev_device_set_sysattr_value(struct udev_device *udev_device, c return -1; } - if (xasprintf(path, "%s/%s", udev_device->syspath, sysattr) == -1) { + if (xasprintf(path, "%s/%s", udev_device_get_property_value(udev_device, "SYSPATH"), sysattr) == -1) { return -1; } @@ -318,41 +311,11 @@ UDEV_EXPORT int udev_device_set_sysattr_value(struct udev_device *udev_device, c return 0; } -char *udev_device_read_uevent(struct udev_device *udev_device, const char *name) -{ - char *line, *path = NULL, *data = NULL; - size_t nlen = strlen(name), glen = 0; - FILE *file; - - if (xasprintf(path, "%s/%s", udev_device->syspath, "uevent") == -1) { - return NULL; - } - - file = fopen(path, "r"); - - if (!file) { - free(path); - return NULL; - } - - while (getline(&line, &glen, file) != -1) { - if (strncmp(line, name, nlen) == 0) { - data = strdup(line + nlen); - break; - } - } - - fclose(file); - free(line); - free(path); - return data; -} - -char *udev_device_read_symlink(struct udev_device *udev_device, const char *name) +const char *udev_device_read_symlink(struct udev_device *udev_device, const char *name) { char *link, *data, *path = NULL; - if (xasprintf(path, "%s/%s", udev_device->syspath, name) == -1) { + if (xasprintf(path, "%s/%s", udev_device_get_property_value(udev_device, "SYSPATH"), name) == -1) { return NULL; } @@ -363,142 +326,94 @@ char *udev_device_read_symlink(struct udev_device *udev_device, const char *name return NULL; } - data = strdup(strrchr(link, '/') + 1); + data = strrchr(link, '/') + 1; free(path); free(link); return data; } -void udev_device_set_subsystem(struct udev_device *udev_device) -{ - char *subsystem; - - udev_device->subsystem = NULL; - - subsystem = udev_device_read_symlink(udev_device, "subsystem"); - - if (!subsystem) { - return; - } - - udev_device->subsystem = subsystem; -} - -void udev_device_set_sysname(struct udev_device *udev_device) -{ - char *devname, *sysname; - - udev_device->sysname = NULL; - - devname = udev_device_read_uevent(udev_device, "DEVNAME="); - - if (!devname) { - return; - } - - sysname = strrchr(devname, '/'); - - if (!sysname) { - sysname = devname; - } - else { - sysname++; - } - - udev_device->sysname = strdup(sysname); - free(devname); -} - -void udev_device_set_devnode(struct udev_device *udev_device) -{ - char *devname, *devnode = NULL; - - udev_device->devnode = NULL; - - devname = udev_device_read_uevent(udev_device, "DEVNAME="); - - if (!devname) { - return; - } - - if (xasprintf(devnode, "/dev/%s", devname) == -1) { - free(devname); - return; - } - - udev_device->devnode = devnode; - free(devname); -} - -void udev_device_set_devtype(struct udev_device *udev_device) -{ - char *devtype; - - udev_device->devtype = NULL; - - devtype = udev_device_read_uevent(udev_device, "DEVTYPE="); - - if (!devtype) { - return; - } - - udev_device->devtype = devtype; -} - -void udev_device_set_driver(struct udev_device *udev_device) -{ - char *driver; - - udev_device->driver = NULL; - - driver = udev_device_read_symlink(udev_device, "driver"); - - if (!driver) { - return; - } - - udev_device->driver = driver; -} - -void udev_device_set_devnum(struct udev_device *udev_device) -{ - char *major, *minor; - - udev_device->devnum = makedev(0, 0); - - major = udev_device_read_uevent(udev_device, "MAJOR="); - minor = udev_device_read_uevent(udev_device, "MINOR="); - - if (!major && !minor) { - return; - } - - udev_device->devnum = makedev(atoi(major), atoi(minor)); - free(major); - free(minor); -} - -void udev_device_set_sysnum(struct udev_device *udev_device) +void udev_device_set_properties_from_uevent(struct udev_device *udev_device) { + char *key, *val, *line, *path = NULL; + char *sysname, *devnode = NULL; + size_t len = 0; + FILE *file; int i; - udev_device->sysnum = NULL; - - if (!udev_device->sysname) { + if (xasprintf(path, "%s/uevent", udev_device_get_property_value(udev_device, "SYSPATH")) == -1) { return; } - for (i = 0; udev_device->sysname[i] != '\0'; i++) { - if (udev_device->sysname[i] >= '0' && - udev_device->sysname[i] <= '9') { - udev_device->sysnum = strdup(udev_device->sysname + i); - return; + file = fopen(path, "r"); + + if (!file) { + free(path); + return; + } + + while (getline(&line, &len, file) != -1) { + if (strncmp(line, "DEVNAME", 7) == 0) { + sysname = strrchr(line + 8, '/'); + + if (!sysname) { + sysname = line + 8; + } + else { + sysname++; + } + + udev_list_entry_add(&udev_device->properties, "DEVNAME", sysname); + + for (i = 0; sysname[i] != '\0'; i++) { + if (sysname[i] >= '0' && sysname[i] <= '9') { + udev_list_entry_add(&udev_device->properties, "SYSNUM", sysname + i); + break; + } + } + + if (xasprintf(devnode, "/dev/%s", line + 8) == -1) { + continue; + } + + udev_list_entry_add(&udev_device->properties, "DEVNODE", devnode); + free(devnode); + } + else if (strncmp(line, "DEVTYPE", 7) == 0) { + udev_list_entry_add(&udev_device->properties, "DEVTYPE", line + 8); + } + else if (strncmp(line, "DRIVER", 6) == 0) { + continue; + } + else if (strncmp(line, "MAJOR", 5) == 0) { + udev_list_entry_add(&udev_device->properties, "MAJOR", line + 6); + } + else if (strncmp(line, "MINOR", 5) == 0) { + udev_list_entry_add(&udev_device->properties, "MINOR", line + 6); + } + else if (strchr(line, '=')) { + val = strchr(line, '=') + 1; + key = strdup(line); + + for (i = 0; key[i] != '\0'; i++) { + if (key[i] == '=') { + key[i] = '\0'; + break; + } + } + + udev_list_entry_add(&udev_device->properties, key, val); + free(key); } } + + fclose(file); + free(line); + free(path); } -void udev_device_set_properties(struct udev_device *udev_device) +void udev_device_set_properties_from_ioctl(struct udev_device *udev_device) { + // TODO extract INPUT properties using libevdev or direct ioctl's(complex), HELP WANTED! } UDEV_EXPORT struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) @@ -522,7 +437,7 @@ UDEV_EXPORT struct udev_device *udev_device_new_from_syspath(struct udev *udev, return NULL; } - if (xasprintf(file, "%s/%s", path, "uevent") == -1) { + if (xasprintf(file, "%s/uevent", path) == -1) { free(path); return NULL; } @@ -533,32 +448,30 @@ UDEV_EXPORT struct udev_device *udev_device_new_from_syspath(struct udev *udev, return NULL; } - free(file); - udev_device = calloc(1, sizeof(struct udev_device)); if (!udev_device) { + free(file); free(path); return NULL; } udev_device->udev = udev; udev_device->refcount = 1; - udev_device->syspath = path; - udev_device->devpath = strdup(path + 4); udev_list_entry_init(&udev_device->properties); udev_list_entry_init(&udev_device->sysattrs); - udev_device_set_properties(udev_device); - udev_device_set_subsystem(udev_device); - udev_device_set_sysname(udev_device); - udev_device_set_devnode(udev_device); - udev_device_set_devtype(udev_device); - udev_device_set_driver(udev_device); - udev_device_set_sysnum(udev_device); - udev_device_set_devnum(udev_device); + udev_list_entry_add(&udev_device->properties, "SYSPATH", path); + udev_list_entry_add(&udev_device->properties, "DEVPATH", path + 4); + udev_list_entry_add(&udev_device->properties, "DRIVER", udev_device_read_symlink(udev_device, "driver")); + udev_list_entry_add(&udev_device->properties, "SUBSYSTEM", udev_device_read_symlink(udev_device, "subsystem")); + udev_device_set_properties_from_uevent(udev_device); + udev_device_set_properties_from_ioctl(udev_device); + + free(file); + free(path); return udev_device; } @@ -633,15 +546,6 @@ UDEV_EXPORT struct udev_device *udev_device_unref(struct udev_device *udev_devic udev_list_entry_free_all(&udev_device->properties); udev_list_entry_free_all(&udev_device->sysattrs); - free(udev_device->subsystem); - free(udev_device->syspath); - free(udev_device->devpath); - free(udev_device->sysname); - free(udev_device->devnode); - free(udev_device->devtype); - free(udev_device->driver); - free(udev_device->sysnum); free(udev_device); - return NULL; } diff --git a/udev_device.h b/udev_device.h index 766cb80..e81a22d 100644 --- a/udev_device.h +++ b/udev_device.h @@ -1,10 +1,3 @@ -char *udev_device_read_uevent(struct udev_device *udev_device, const char *name); -char *udev_device_read_symlink(struct udev_device *udev_device, const char *name); -void udev_device_set_properties(struct udev_device *udev_device); -void udev_device_set_subsystem(struct udev_device *udev_device); -void udev_device_set_sysname(struct udev_device *udev_device); -void udev_device_set_devnode(struct udev_device *udev_device); -void udev_device_set_devtype(struct udev_device *udev_device); -void udev_device_set_driver(struct udev_device *udev_device); -void udev_device_set_sysnum(struct udev_device *udev_device); -void udev_device_set_devnum(struct udev_device *udev_device); +const char *udev_device_read_symlink(struct udev_device *udev_device, const char *name); +void udev_device_set_properties_from_uevent(struct udev_device *udev_device); +void udev_device_set_properties_from_ioctl(struct udev_device *udev_device); diff --git a/udev_enumerate.c b/udev_enumerate.c index 9e8d57e..c9f7f16 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -1,7 +1,14 @@ #include +#include +#include +#include +#include +#include #include "udev.h" #include "udev_list.h" +#include "udev_util.h" +#include "udev_enumerate.h" struct udev_enumerate { @@ -87,21 +94,235 @@ UDEV_EXPORT int udev_enumerate_add_match_is_initialized(struct udev_enumerate *u return 0; } +int udev_enumerate_filter_subsystem(struct udev_enumerate *udev_enumerate, struct udev_device *udev_device) +{ + struct udev_list_entry *list_entry; + const char *subsystem; + + subsystem = udev_device_get_subsystem(udev_device); + list_entry = udev_list_entry_get_next(&udev_enumerate->subsystem_nomatch); + + if (!subsystem) { + return 0; + } + + while (list_entry) { + if (fnmatch(udev_list_entry_get_name(list_entry), subsystem, 0) == 0) { + return 0; + } + + list_entry = udev_list_entry_get_next(list_entry); + } + + list_entry = udev_list_entry_get_next(&udev_enumerate->subsystem_match); + + if (list_entry) { + while (list_entry) { + if (fnmatch(udev_list_entry_get_name(list_entry), subsystem, 0) == 0) { + return 1; + } + + list_entry = udev_list_entry_get_next(list_entry); + } + + return 0; + } + + return 1; +} + +int udev_enumerate_filter_sysname(struct udev_enumerate *udev_enumerate, struct udev_device *udev_device) +{ + struct udev_list_entry *list_entry; + const char *sysname; + + sysname = udev_device_get_sysname(udev_device); + list_entry = udev_list_entry_get_next(&udev_enumerate->sysname_match); + + if (!list_entry) { + return 1; + } + + while (list_entry) { + if (fnmatch(udev_list_entry_get_name(list_entry), sysname, 0) == 0) { + return 1; + } + + list_entry = udev_list_entry_get_next(list_entry); + } + + return 0; +} + +int udev_enumerate_filter_property(struct udev_enumerate *udev_enumerate, struct udev_device *udev_device) +{ + const char *property, *property2, *value, *value2; + struct udev_list_entry *list_entry, *list_entry2; + + list_entry = udev_list_entry_get_next(&udev_enumerate->property_match); + + if (!list_entry) { + return 1; + } + + while (list_entry) { + property = udev_list_entry_get_name(list_entry); + value = udev_list_entry_get_value(list_entry); + + list_entry2 = udev_device_get_properties_list_entry(udev_device); + + if (!list_entry2) { + return 0; + } + + while (list_entry2) { + property2 = udev_list_entry_get_name(list_entry2); + value2 = udev_list_entry_get_value(list_entry2); + + if (!value || !value2) { + continue; + } + + if (fnmatch(property, property2, 0) == 0 && + fnmatch(value, value2, 0) == 0) { + return 1; + } + + list_entry2 = udev_list_entry_get_next(list_entry2); + } + + list_entry = udev_list_entry_get_next(list_entry); + } + + return 0; +} + +int udev_enumerate_filter_sysattr(struct udev_enumerate *udev_enumerate, struct udev_device *udev_device) +{ + struct udev_list_entry *list_entry; + const char *sysattr, *value; + + list_entry = udev_list_entry_get_next(&udev_enumerate->sysattr_nomatch); + + while (list_entry) { + sysattr = udev_list_entry_get_name(list_entry); + value = udev_device_get_sysattr_value(udev_device, sysattr); + + if (!value) { + return 1; + } + + if (fnmatch(udev_list_entry_get_value(list_entry), value, 0) == 0) { + return 0; + } + + list_entry = udev_list_entry_get_next(list_entry); + } + + list_entry = udev_list_entry_get_next(&udev_enumerate->sysattr_match); + + if (list_entry) { + while (list_entry) { + sysattr = udev_list_entry_get_name(list_entry); + value = udev_device_get_sysattr_value(udev_device, sysattr); + + if (!value) { + return 0; + } + + if (fnmatch(udev_list_entry_get_value(list_entry), value, 0) == 0) { + return 1; + } + + list_entry = udev_list_entry_get_next(list_entry); + } + + return 0; + } + + return 1; +} + +void udev_enumerate_add_device(struct udev_enumerate *udev_enumerate, const char type, dev_t devnum) +{ + struct udev_device *udev_device; + + udev_device = udev_device_new_from_devnum(udev_enumerate->udev, type, devnum); + + if (!udev_device) { + return; + } + + // TODO double check if logic is correct + if (!udev_enumerate_filter_subsystem(udev_enumerate, udev_device) || + !udev_enumerate_filter_sysname(udev_enumerate, udev_device) || + !udev_enumerate_filter_property(udev_enumerate, udev_device) || + !udev_enumerate_filter_sysattr(udev_enumerate, udev_device)) { + udev_device_unref(udev_device); + return; + } + + udev_list_entry_add(&udev_enumerate->devices, udev_device_get_syspath(udev_device), NULL); + udev_device_unref(udev_device); +} + +void udev_enumerate_scan_dir(struct udev_enumerate *udev_enumerate, const char *path) +{ + char *file = NULL; + struct dirent *de; + struct stat st; + DIR *dp; + + dp = opendir(path); + + if (!dp) { + return; + } + + while ((de = readdir(dp))) { + if (strcmp(de->d_name, ".") == 0 || + strcmp(de->d_name, "..") == 0) { + continue; + } + + if (xasprintf(file, "%s/%s", path, de->d_name) == -1) { + closedir(dp); + return; + } + + if (lstat(file, &st) != 0 || S_ISLNK(st.st_mode)) { + continue; + } + else if (S_ISDIR(st.st_mode)) { + udev_enumerate_scan_dir(udev_enumerate, file); + } + else if (S_ISBLK(st.st_mode)) { + udev_enumerate_add_device(udev_enumerate, 'c', st.st_dev); + } + else if (S_ISCHR(st.st_mode)) { + udev_enumerate_add_device(udev_enumerate, 'b', st.st_dev); + } + } + + closedir(dp); + free(file); +} + UDEV_EXPORT int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) { + udev_enumerate_scan_dir(udev_enumerate, "/dev"); + return 0; } UDEV_EXPORT int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate) { + // XXX NOT IMPLEMENTED + return 0; } UDEV_EXPORT struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate) { - if (!udev_enumerate) { - return NULL; - } - - return &udev_enumerate->devices; + return udev_enumerate ? udev_list_entry_get_next(&udev_enumerate->devices) : NULL; } UDEV_EXPORT int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath) @@ -112,11 +333,7 @@ UDEV_EXPORT int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate UDEV_EXPORT struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate) { - if (!udev_enumerate) { - return NULL; - } - - return udev_enumerate->udev; + return udev_enumerate ? udev_enumerate->udev : NULL; } UDEV_EXPORT struct udev_enumerate *udev_enumerate_new(struct udev *udev) @@ -159,4 +376,22 @@ UDEV_EXPORT struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *ude UDEV_EXPORT struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate) { + if (!udev_enumerate) { + return NULL; + } + + if (--udev_enumerate->refcount > 0) { + return NULL; + } + + udev_list_entry_free_all(&udev_enumerate->subsystem_nomatch); + udev_list_entry_free_all(&udev_enumerate->subsystem_match); + udev_list_entry_free_all(&udev_enumerate->sysattr_nomatch); + udev_list_entry_free_all(&udev_enumerate->property_match); + udev_list_entry_free_all(&udev_enumerate->sysattr_match); + udev_list_entry_free_all(&udev_enumerate->sysname_match); + udev_list_entry_free_all(&udev_enumerate->devices); + + free(udev_enumerate); + return NULL; } diff --git a/udev_enumerate.h b/udev_enumerate.h new file mode 100644 index 0000000..08a97f9 --- /dev/null +++ b/udev_enumerate.h @@ -0,0 +1,6 @@ +int udev_enumerate_filter_subsystem(struct udev_enumerate *udev_enumerate, struct udev_device *udev_device); +int udev_enumerate_filter_property(struct udev_enumerate *udev_enumerate, struct udev_device *udev_device); +int udev_enumerate_filter_sysname(struct udev_enumerate *udev_enumerate, struct udev_device *udev_device); +int udev_enumerate_filter_sysattr(struct udev_enumerate *udev_enumerate, struct udev_device *udev_device); +void udev_enumerate_add_device(struct udev_enumerate *udev_enumerate, const char type, dev_t devnum); +void udev_enumerate_scan_dir(struct udev_enumerate *udev_enumerate, const char *path); diff --git a/udev_list.c b/udev_list.c index 1bf01b5..97e38c7 100644 --- a/udev_list.c +++ b/udev_list.c @@ -20,10 +20,14 @@ void udev_list_entry_free(struct udev_list_entry *list_entry) void udev_list_entry_free_all(struct udev_list_entry *list_entry) { - struct udev_list_entry *tmp; + struct udev_list_entry *tmp, *tmp2; - udev_list_entry_foreach(tmp, list_entry) { - udev_list_entry_free(tmp); + tmp = list_entry; + + while (tmp) { + tmp2 = tmp; + tmp = tmp->next; + udev_list_entry_free(tmp2); } } @@ -34,6 +38,10 @@ struct udev_list_entry *udev_list_entry_add(struct udev_list_entry *list_entry, old = udev_list_entry_get_by_name(list_entry, name); if (old) { + if (old->value && strcmp(old->value, value) == 0) { + return old; + } + free(old->value); old->value = strdup(value); return old; @@ -58,11 +66,7 @@ struct udev_list_entry *udev_list_entry_add(struct udev_list_entry *list_entry, UDEV_EXPORT struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry) { - if (!list_entry) { - return NULL; - } - - return list_entry->next; + return list_entry ? list_entry->next : NULL; } UDEV_EXPORT struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name) @@ -73,10 +77,14 @@ UDEV_EXPORT struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list return NULL; } - udev_list_entry_foreach(tmp, list_entry) { + tmp = list_entry; + + while (tmp) { if (strcmp(tmp->name, name) == 0) { return tmp; } + + tmp = tmp->next; } return NULL; @@ -84,18 +92,10 @@ UDEV_EXPORT struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list UDEV_EXPORT const char *udev_list_entry_get_name(struct udev_list_entry *list_entry) { - if (!list_entry) { - return NULL; - } - - return list_entry->name; + return list_entry ? list_entry->name : NULL; } UDEV_EXPORT const char *udev_list_entry_get_value(struct udev_list_entry *list_entry) { - if (!list_entry) { - return NULL; - } - - return list_entry->value; + return list_entry ? list_entry->value : NULL; } diff --git a/udev_monitor.c b/udev_monitor.c index bc2f375..1b5bb61 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -28,20 +28,12 @@ UDEV_EXPORT int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_m UDEV_EXPORT int udev_monitor_get_fd(struct udev_monitor *udev_monitor) { - if (!udev_monitor) { - return -1; - } - - return udev_monitor->fd[0]; + return udev_monitor ? udev_monitor->fd[0] : -1; } UDEV_EXPORT struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor) { - if (!udev_monitor) { - return NULL; - } - - return udev_monitor->udev; + return udev_monitor ? udev_monitor->udev : NULL; } UDEV_EXPORT int udev_monitor_filter_update(struct udev_monitor *udev_monitor)