From 7a09bb0557566f4ea2cc994d746483f08b5ce32c Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 4 Jul 2020 09:25:16 +0300 Subject: [PATCH 001/222] init --- LICENSE | 15 ++ Makefile | 49 ++++ README.md | 1 + udev.c | 40 +++ udev.h | 98 ++++++++ udev_device.c | 643 +++++++++++++++++++++++++++++++++++++++++++++++ udev_device.h | 10 + udev_enumerate.c | 162 ++++++++++++ udev_list.c | 109 ++++++++ udev_list.h | 11 + udev_monitor.c | 125 +++++++++ udev_util.c | 37 +++ udev_util.h | 1 + 13 files changed, 1301 insertions(+) create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 udev.c create mode 100644 udev.h create mode 100644 udev_device.c create mode 100644 udev_device.h create mode 100644 udev_enumerate.c create mode 100644 udev_list.c create mode 100644 udev_list.h create mode 100644 udev_monitor.c create mode 100644 udev_util.c create mode 100644 udev_util.h diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..bf87ea9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2020 illiliti + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..78877cd --- /dev/null +++ b/Makefile @@ -0,0 +1,49 @@ +# .POSIX ?? + +PREFIX = /usr/local +XCFLAGS = ${CFLAGS} -pedantic -fPIC -fvisibility=hidden \ + -D_POSIX_VERSION=200809L -D_XOPEN_SOURCE=700 -std=c99 \ + -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \ + -Wno-return-type -Wno-unused-parameter +XLDFLAGS = ${LDFLAGS} -shared -Wl,-soname,libudev.so.1 +XARFLAGS = -rc + +OBJ = \ + udev.o \ + udev_list.o \ + udev_util.o \ + udev_device.o \ + udev_monitor.o \ + udev_enumerate.o + +all: libudev.so libudev.a + +.c.o: + ${CC} ${XCFLAGS} -c -o $@ $< + +libudev.a: ${OBJ} + ${AR} ${XARFLAGS} $@ ${OBJ} + +libudev.so: ${OBJ} + ${CC} ${XCFLAGS} -o $@ ${OBJ} ${XLDFLAGS} + +install: libudev.so libudev.a + mkdir -p ${DESTDIR}${INCLUDEDIR} ${DESTDIR}${LIBDIR} + cp -f udev.h ${DESTDIR}${INCLUDEDIR}/libudev.h + chmod 0644 ${DESTDIR}${INCLUDEDIR}/libudev.h + cp -f libudev.a ${DESTDIR}${LIBDIR}/libudev.a + chmod 0644 ${DESTDIR}${LIBDIR}/libudev.a + cp -f libudev.so ${DESTDIR}${LIBDIR}/libudev.so + chmod 0755 ${DESTDIR}${LIBDIR}/libudev.so + ln -s libudev.so ${DESTDIR}${LIBDIR}/libudev.so.1 + +uninstall: + rm -f ${DESTDIR}${LIBDIR}/libudev.a \ + ${DESTDIR}${LIBDIR}/libudev.so \ + ${DESTDIR}${LIBDIR}/libudev.so.1 \ + ${DESTDIR}${INCLUDEDIR}/libudev.h + +clean: + rm -f libudev.so libudev.a ${OBJ} + +.PHONY: all clean install uninstall diff --git a/README.md b/README.md new file mode 100644 index 0000000..f77e34d --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +Nothing works here(yet), move along diff --git a/udev.c b/udev.c new file mode 100644 index 0000000..cc6a147 --- /dev/null +++ b/udev.c @@ -0,0 +1,40 @@ +#include + +#include "udev.h" + +struct udev +{ + int refcount; +}; + +UDEV_EXPORT struct udev *udev_new(void) +{ + struct udev *udev; + + udev = calloc(1, sizeof(struct udev)); + return udev; +} + +UDEV_EXPORT struct udev *udev_ref(struct udev *udev) +{ + if (!udev) { + return NULL; + } + + udev->refcount++; + return udev; +} + +UDEV_EXPORT struct udev *udev_unref(struct udev *udev) +{ + if (!udev) { + return NULL; + } + + if (--udev->refcount > 0) { + return udev; + } + + free(udev); + return NULL; +} diff --git a/udev.h b/udev.h new file mode 100644 index 0000000..83a3a9e --- /dev/null +++ b/udev.h @@ -0,0 +1,98 @@ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define UDEV_EXPORT __attribute__ ((visibility("default"))) + +#define udev_list_entry_foreach(list_entry, first_entry) \ + for (list_entry = first_entry; \ + list_entry != NULL; \ + list_entry = udev_list_entry_get_next(list_entry)) + +struct udev; +struct udev_device; +struct udev_monitor; +struct udev_enumerate; +struct udev_list_entry; + +struct udev *udev_new(void); +struct udev *udev_ref(struct udev *udev); +struct udev *udev_unref(struct udev *udev); + +const char *udev_device_get_syspath(struct udev_device *udev_device); +const char *udev_device_get_sysname(struct udev_device *udev_device); +const char *udev_device_get_sysnum(struct udev_device *udev_device); +const char *udev_device_get_devpath(struct udev_device *udev_device); +const char *udev_device_get_devnode(struct udev_device *udev_device); +dev_t udev_device_get_devnum(struct udev_device *udev_device); +const char *udev_device_get_devtype(struct udev_device *udev_device); +const char *udev_device_get_subsystem(struct udev_device *udev_device); +const char *udev_device_get_driver(struct udev_device *udev_device); +struct udev *udev_device_get_udev(struct udev_device *udev_device); +struct udev_device *udev_device_get_parent(struct udev_device *udev_device); +struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype); +int udev_device_get_is_initialized(struct udev_device *udev_device); +const char *udev_device_get_action(struct udev_device *udev_device); + +int udev_device_has_tag(struct udev_device *udev_device, const char *tag); +struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device); +struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device); +struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device); +struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device); +const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key); +const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr); +int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, const char *value); + +struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath); +struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum); +struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname); +struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id); +struct udev_device *udev_device_new_from_environment(struct udev *udev); +struct udev_device *udev_device_ref(struct udev_device *udev_device); +struct udev_device *udev_device_unref(struct udev_device *udev_device); + +int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem); +int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem); +int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value); +int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value); +int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value); +int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname); +int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag); +int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent); +int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate); + +int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate); +int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate); +struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate); +int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath); +struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate); + +struct udev_enumerate *udev_enumerate_new(struct udev *udev); +struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate); +struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate); + +struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry); +struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name); +const char *udev_list_entry_get_name(struct udev_list_entry *list_entry); +const char *udev_list_entry_get_value(struct udev_list_entry *list_entry); + +struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor); +int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor); +int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size); +int udev_monitor_get_fd(struct udev_monitor *udev_monitor); +struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor); + +int udev_monitor_filter_update(struct udev_monitor *udev_monitor); +int udev_monitor_filter_remove(struct udev_monitor *udev_monitor); +int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor, const char *subsystem, const char *devtype); +int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag); + +struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name); +struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor); +struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor); + +#ifdef __cplusplus +} +#endif diff --git a/udev_device.c b/udev_device.c new file mode 100644 index 0000000..42f9b5d --- /dev/null +++ b/udev_device.c @@ -0,0 +1,643 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "udev.h" +#include "udev_list.h" +#include "udev_util.h" +#include "udev_device.h" + +struct udev_device +{ + struct udev_list_entry properties; + 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; +}; + +UDEV_EXPORT const char *udev_device_get_syspath(struct udev_device *udev_device) +{ + if (!udev_device) { + return NULL; + } + + return udev_device->syspath; +} + +UDEV_EXPORT const char *udev_device_get_sysname(struct udev_device *udev_device) +{ + if (!udev_device) { + return NULL; + } + + return udev_device->sysname; +} + +UDEV_EXPORT const char *udev_device_get_sysnum(struct udev_device *udev_device) +{ + if (!udev_device) { + return NULL; + } + + return udev_device->sysnum; +} + +UDEV_EXPORT const char *udev_device_get_devpath(struct udev_device *udev_device) +{ + if (!udev_device) { + return NULL; + } + + return udev_device->devpath; +} + +UDEV_EXPORT const char *udev_device_get_devnode(struct udev_device *udev_device) +{ + if (!udev_device) { + return NULL; + } + + return udev_device->devnode; +} + +UDEV_EXPORT dev_t udev_device_get_devnum(struct udev_device *udev_device) +{ + if (!udev_device) { + return makedev(0, 0); + } + + return udev_device->devnum; +} + +UDEV_EXPORT const char *udev_device_get_devtype(struct udev_device *udev_device) +{ + if (!udev_device) { + return NULL; + } + + return udev_device->devtype; +} + +UDEV_EXPORT const char *udev_device_get_subsystem(struct udev_device *udev_device) +{ + if (!udev_device) { + return NULL; + } + + return udev_device->subsystem; +} + +UDEV_EXPORT const char *udev_device_get_driver(struct udev_device *udev_device) +{ + if (!udev_device) { + return NULL; + } + + return 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; +} + +UDEV_EXPORT struct udev_device *udev_device_get_parent(struct udev_device *udev_device) +{ + char *path; + int slash; + + if (!udev_device) { + return NULL; + } + + path = strdup(udev_device->syspath); + + while (1) { + slash = strrchr(path, '/') - path; + + if (!slash) { + free(path); + return NULL; + } + + path[slash] = '\0'; + + udev_device->parent = udev_device_new_from_syspath(udev_device->udev, path); + + if (udev_device->parent) { + free(path); + return udev_device->parent; + } + } +} + +UDEV_EXPORT struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype) +{ + const char *parent_subsystem, *parent_devtype; + struct udev_device *parent; + + if (!udev_device || !subsystem) { + return NULL; + } + + while ((parent = udev_device_get_parent(udev_device))) { + parent_subsystem = udev_device_get_subsystem(parent); + parent_devtype = udev_device_get_devtype(parent); + + if (parent_subsystem && strcmp(parent_subsystem, subsystem) == 0) { + if (!devtype) { + return parent; + } + + if (parent_devtype && strcmp(parent_devtype, devtype) == 0) { + return parent; + } + } + } + + return NULL; +} + +UDEV_EXPORT int udev_device_get_is_initialized(struct udev_device *udev_device) +{ + return 1; +} + +UDEV_EXPORT const char *udev_device_get_action(struct udev_device *udev_device) +{ + return NULL; +} + +UDEV_EXPORT int udev_device_has_tag(struct udev_device *udev_device, const char *tag) +{ + // XXX NOT IMPLEMENTED + return 0; +} + +UDEV_EXPORT struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device) +{ + // XXX NOT IMPLEMENTED + return NULL; +} + +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; +} + +UDEV_EXPORT struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device) +{ + // XXX NOT IMPLEMENTED + return NULL; +} + +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; +} + +UDEV_EXPORT const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key) +{ +} + +UDEV_EXPORT const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr) +{ + struct udev_list_entry *list_entry; + char data[1024], *path = NULL; + struct stat st; + ssize_t len; + int fd; + + if (!udev_device || !sysattr) { + return NULL; + } + + list_entry = udev_list_entry_get_by_name(&udev_device->sysattrs, sysattr); + + if (list_entry) { + return udev_list_entry_get_value(list_entry); + } + + if (xasprintf(path, "%s/%s", udev_device->syspath, sysattr) == -1) { + return NULL; + } + + if (stat(path, &st) != 0 || S_ISDIR(st.st_mode)) { + free(path); + return NULL; + } + + fd = open(path, O_RDONLY); + + if (fd == -1) { + free(path); + return NULL; + } + + len = read(fd, data, sizeof(data)); + + if (len == -1) { + close(fd); + free(path); + return NULL; + } + + close(fd); + free(path); + data[len] = '\0'; + list_entry = udev_list_entry_add(&udev_device->sysattrs, sysattr, data); + return udev_list_entry_get_value(list_entry); +} + +UDEV_EXPORT int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, const char *value) +{ + size_t len = strlen(value); + char *path = NULL; + struct stat st; + int fd; + + if (!udev_device || !sysattr || !value) { + return -1; + } + + if (xasprintf(path, "%s/%s", udev_device->syspath, sysattr) == -1) { + return -1; + } + + if (stat(path, &st) != 0 || S_ISDIR(st.st_mode)) { + free(path); + return -1; + } + + fd = open(path, O_WRONLY | O_NOFOLLOW); + + if (fd == -1) { + free(path); + return -1; + } + + if (write(fd, value, len) == -1) { + close(fd); + free(path); + return -1; + } + + close(fd); + free(path); + udev_list_entry_add(&udev_device->sysattrs, sysattr, value); + 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) +{ + char *link, *data, *path = NULL; + + if (xasprintf(path, "%s/%s", udev_device->syspath, name) == -1) { + return NULL; + } + + link = realpath(path, NULL); // XXX XSI + + if (!link) { + free(path); + return NULL; + } + + data = strdup(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) +{ + int i; + + udev_device->sysnum = NULL; + + if (!udev_device->sysname) { + 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; + } + } +} + +void udev_device_set_properties(struct udev_device *udev_device) +{ +} + +UDEV_EXPORT struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) +{ + struct udev_device *udev_device; + char *path, *file = NULL; + struct stat st; + + if (!udev || !syspath) { + return NULL; + } + + path = realpath(syspath, NULL); // XXX XSI + + if (!path) { + return NULL; + } + + if (stat(path, &st) != 0 || S_ISDIR(st.st_mode) == 0) { + free(path); + return NULL; + } + + if (xasprintf(file, "%s/%s", path, "uevent") == -1) { + free(path); + return NULL; + } + + if (access(file, R_OK) == -1) { + free(file); + free(path); + return NULL; + } + + free(file); + + udev_device = calloc(1, sizeof(struct udev_device)); + + if (!udev_device) { + 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); + + return udev_device; +} + +UDEV_EXPORT struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum) +{ + struct udev_device *udev_device; + char *path = NULL; + + if (!udev || !type || !devnum) { + return NULL; + } + + switch (type) { + case 'c': + xasprintf(path, "/sys/dev/char/%d:%d", major(devnum), minor(devnum)); + break; + case 'b': + xasprintf(path, "/sys/dev/block/%d:%d", major(devnum), minor(devnum)); + break; + default: + return NULL; + } + + udev_device = udev_device_new_from_syspath(udev, path); + + free(path); + return udev_device; +} + +UDEV_EXPORT struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname) +{ + // XXX NOT IMPLEMENTED + return NULL; +} + +UDEV_EXPORT struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id) +{ + // XXX NOT IMPLEMENTED + return NULL; +} + +UDEV_EXPORT struct udev_device *udev_device_new_from_environment(struct udev *udev) +{ + // XXX NOT IMPLEMENTED + return NULL; +} + +UDEV_EXPORT struct udev_device *udev_device_ref(struct udev_device *udev_device) +{ + if (!udev_device) { + return NULL; + } + + udev_device->refcount++; + return udev_device; +} + +UDEV_EXPORT struct udev_device *udev_device_unref(struct udev_device *udev_device) +{ + if (!udev_device) { + return NULL; + } + + if (--udev_device->refcount > 0) { + return NULL; + } + + if (udev_device->parent) { + udev_device_unref(udev_device->parent); + } + + 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 new file mode 100644 index 0000000..766cb80 --- /dev/null +++ b/udev_device.h @@ -0,0 +1,10 @@ +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); diff --git a/udev_enumerate.c b/udev_enumerate.c new file mode 100644 index 0000000..9e8d57e --- /dev/null +++ b/udev_enumerate.c @@ -0,0 +1,162 @@ +#include + +#include "udev.h" +#include "udev_list.h" + +struct udev_enumerate +{ + struct udev_list_entry subsystem_nomatch; + struct udev_list_entry subsystem_match; + struct udev_list_entry sysattr_nomatch; + struct udev_list_entry property_match; + struct udev_list_entry sysattr_match; + struct udev_list_entry sysname_match; + struct udev_list_entry devices; + struct udev *udev; + int refcount; +}; + +UDEV_EXPORT int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) +{ + if (!udev_enumerate || !subsystem) { + return -1; + } + + return udev_list_entry_add(&udev_enumerate->subsystem_match, subsystem, NULL) ? 0 : -1; +} + +UDEV_EXPORT int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) +{ + if (!udev_enumerate || !subsystem) { + return -1; + } + + return udev_list_entry_add(&udev_enumerate->subsystem_nomatch, subsystem, NULL) ? 0 : -1; +} + +UDEV_EXPORT int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) +{ + if (!udev_enumerate || !sysattr) { + return -1; + } + + return udev_list_entry_add(&udev_enumerate->sysattr_match, sysattr, value) ? 0 : -1; +} + +UDEV_EXPORT int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) +{ + if (!udev_enumerate || !sysattr) { + return -1; + } + + return udev_list_entry_add(&udev_enumerate->sysattr_nomatch, sysattr, value) ? 0 : -1; +} + +UDEV_EXPORT int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value) +{ + if (!udev_enumerate || !property) { + return -1; + } + + return udev_list_entry_add(&udev_enumerate->property_match, property, value) ? 0 : -1; +} + +UDEV_EXPORT int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname) +{ + if (!udev_enumerate || !sysname) { + return -1; + } + + return udev_list_entry_add(&udev_enumerate->sysname_match, sysname, NULL) ? 0 : -1; +} + +UDEV_EXPORT int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag) +{ + // XXX NOT IMPLEMENTED + return 0; +} + +UDEV_EXPORT int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent) +{ + // XXX NOT IMPLEMENTED + return 0; +} + +UDEV_EXPORT int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate) +{ + return 0; +} + +UDEV_EXPORT int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) +{ +} + +UDEV_EXPORT int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate) +{ +} + +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; +} + +UDEV_EXPORT int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath) +{ + // XXX NOT IMPLEMENTED + return 0; +} + +UDEV_EXPORT struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate) +{ + if (!udev_enumerate) { + return NULL; + } + + return udev_enumerate->udev; +} + +UDEV_EXPORT struct udev_enumerate *udev_enumerate_new(struct udev *udev) +{ + struct udev_enumerate *udev_enumerate; + + if (!udev) { + return NULL; + } + + udev_enumerate = calloc(1, sizeof(struct udev_enumerate)); + + if (!udev_enumerate) { + return NULL; + } + + udev_enumerate->refcount = 1; + udev_enumerate->udev = udev; + + udev_list_entry_init(&udev_enumerate->subsystem_nomatch); + udev_list_entry_init(&udev_enumerate->subsystem_match); + udev_list_entry_init(&udev_enumerate->sysattr_nomatch); + udev_list_entry_init(&udev_enumerate->property_match); + udev_list_entry_init(&udev_enumerate->sysattr_match); + udev_list_entry_init(&udev_enumerate->sysname_match); + udev_list_entry_init(&udev_enumerate->devices); + + return udev_enumerate; +} + +UDEV_EXPORT struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate) +{ + if (!udev_enumerate) { + return NULL; + } + + udev_enumerate->refcount++; + return udev_enumerate; +} + +UDEV_EXPORT struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate) +{ +} diff --git a/udev_list.c b/udev_list.c new file mode 100644 index 0000000..a3f2f7f --- /dev/null +++ b/udev_list.c @@ -0,0 +1,109 @@ +#include +#include + +#include "udev.h" +#include "udev_list.h" + +void udev_list_entry_init(struct udev_list_entry *list_entry) +{ + list_entry->value = NULL; + list_entry->name = NULL; + list_entry->next = NULL; +} + +void udev_list_entry_free(struct udev_list_entry *list_entry) +{ + free(list_entry->value); + free(list_entry->name); + free(list_entry); +} + +void udev_list_entry_free_all(struct udev_list_entry *list_entry) +{ + struct udev_list_entry *tmp, *tmp2; + + tmp = list_entry; + + while (tmp) { + tmp2 = tmp; + tmp = tmp->next; + udev_list_entry_free(tmp2); + } +} + +struct udev_list_entry *udev_list_entry_add(struct udev_list_entry *list_entry, const char *name, const char *value) +{ + struct udev_list_entry *new, *old; + + old = udev_list_entry_get_by_name(list_entry, name); + + if (old) { + free(old->value); + old->value = strdup(value); + return old; + } + + new = calloc(1, sizeof(struct udev_list_entry)); + + if (!new) { + return NULL; + } + + udev_list_entry_init(new); + + new->value = value ? strdup(value) : NULL; + new->name = strdup(name); + + new->next = list_entry->next; + list_entry->next = new; + + return new; +} + +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; +} + +UDEV_EXPORT struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name) +{ + struct udev_list_entry *tmp; + + if (!list_entry || !name) { + return NULL; + } + + tmp = list_entry; + + while (tmp) { + if (strcmp(tmp->name, name) == 0) { + return tmp; + } + + tmp = tmp->next; + } + + return NULL; +} + +UDEV_EXPORT const char *udev_list_entry_get_name(struct udev_list_entry *list_entry) +{ + if (!list_entry) { + return NULL; + } + + return list_entry->name; +} + +UDEV_EXPORT const char *udev_list_entry_get_value(struct udev_list_entry *list_entry) +{ + if (!list_entry) { + return NULL; + } + + return list_entry->value; +} diff --git a/udev_list.h b/udev_list.h new file mode 100644 index 0000000..370f636 --- /dev/null +++ b/udev_list.h @@ -0,0 +1,11 @@ +struct udev_list_entry +{ + struct udev_list_entry *next; + char *value; + char *name; +}; + +void udev_list_entry_init(struct udev_list_entry *list_entry); +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 *udev_list_entry_add(struct udev_list_entry *list_entry, const char *name, const char *value); diff --git a/udev_monitor.c b/udev_monitor.c new file mode 100644 index 0000000..bc2f375 --- /dev/null +++ b/udev_monitor.c @@ -0,0 +1,125 @@ +#include +#include +#include + +#include "udev.h" + +struct udev_monitor +{ + struct udev *udev; + int refcount; + int fd[2]; +}; + +UDEV_EXPORT struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor) +{ + return (void *)1; +} + +UDEV_EXPORT int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) +{ + return 0; +} + +UDEV_EXPORT int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size) +{ + return 0; +} + +UDEV_EXPORT int udev_monitor_get_fd(struct udev_monitor *udev_monitor) +{ + if (!udev_monitor) { + return -1; + } + + return udev_monitor->fd[0]; +} + +UDEV_EXPORT struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor) +{ + if (!udev_monitor) { + return NULL; + } + + return udev_monitor->udev; +} + +UDEV_EXPORT int udev_monitor_filter_update(struct udev_monitor *udev_monitor) +{ + return 0; +} + +UDEV_EXPORT int udev_monitor_filter_remove(struct udev_monitor *udev_monitor) +{ + return 0; +} + +UDEV_EXPORT int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor, const char *subsystem, const char *devtype) +{ + return 0; +} + +UDEV_EXPORT int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag) +{ + return 0; +} + +UDEV_EXPORT struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name) +{ + struct udev_monitor *udev_monitor; + int i; + + if (!udev || !name) { + return NULL; + } + + udev_monitor = calloc(1, sizeof(struct udev_monitor)); + + if (!udev_monitor) { + return NULL; + } + + // TODO better no-op, HELP WANTED ! + if (pipe(udev_monitor->fd) == -1) { + free(udev_monitor); + return NULL; + } + + for (i = 0; i < 2; i++) { + fcntl(udev_monitor->fd[i], F_SETFD, FD_CLOEXEC | O_NONBLOCK); + } + + udev_monitor->refcount = 1; + udev_monitor->udev = udev; + return udev_monitor; +} + +UDEV_EXPORT struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor) +{ + if (!udev_monitor) { + return NULL; + } + + udev_monitor->refcount++; + return udev_monitor; +} + +UDEV_EXPORT struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor) +{ + int i; + + if (!udev_monitor) { + return NULL; + } + + if (--udev_monitor->refcount > 0) { + return NULL; + } + + for (i = 0; i < 2; i++) { + close(udev_monitor->fd[i]); + } + + free(udev_monitor); + return NULL; +} diff --git a/udev_util.c b/udev_util.c new file mode 100644 index 0000000..28d07d9 --- /dev/null +++ b/udev_util.c @@ -0,0 +1,37 @@ +#include +#include +#include + +#include "udev_util.h" +#include "udev.h" + +int xasprintf(char *str, const char *fmt, ...) +{ + va_list list; + int len; + + va_start(list, fmt); + len = vsnprintf(NULL, 0, fmt, list); + va_end(list); + + if (len == -1) { + return -1; + } + + str = malloc(len + 1); + + if (!str) { + return -1; + } + + len = vsnprintf(str, len + 1, fmt, list); + + if (len == -1) { + free(str); + return -1; + } + + return len; +} + +// TODO readlink+malloc diff --git a/udev_util.h b/udev_util.h new file mode 100644 index 0000000..583a347 --- /dev/null +++ b/udev_util.h @@ -0,0 +1 @@ +int xasprintf(char *str, const char *fmt, ...); From bceae57798082dc73c00e198939eb6334cdb06e9 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 4 Jul 2020 10:13:32 +0300 Subject: [PATCH 002/222] formatting fixes --- Makefile | 10 +++++----- udev.c | 2 +- udev.h | 6 +++--- udev_device.c | 2 +- udev_util.c | 10 +++++----- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 78877cd..215332f 100644 --- a/Makefile +++ b/Makefile @@ -28,20 +28,20 @@ libudev.so: ${OBJ} ${CC} ${XCFLAGS} -o $@ ${OBJ} ${XLDFLAGS} install: libudev.so libudev.a - mkdir -p ${DESTDIR}${INCLUDEDIR} ${DESTDIR}${LIBDIR} + mkdir -p ${DESTDIR}${INCLUDEDIR} ${DESTDIR}${LIBDIR} cp -f udev.h ${DESTDIR}${INCLUDEDIR}/libudev.h chmod 0644 ${DESTDIR}${INCLUDEDIR}/libudev.h cp -f libudev.a ${DESTDIR}${LIBDIR}/libudev.a chmod 0644 ${DESTDIR}${LIBDIR}/libudev.a cp -f libudev.so ${DESTDIR}${LIBDIR}/libudev.so - chmod 0755 ${DESTDIR}${LIBDIR}/libudev.so + chmod 0755 ${DESTDIR}${LIBDIR}/libudev.so ln -s libudev.so ${DESTDIR}${LIBDIR}/libudev.so.1 uninstall: rm -f ${DESTDIR}${LIBDIR}/libudev.a \ - ${DESTDIR}${LIBDIR}/libudev.so \ - ${DESTDIR}${LIBDIR}/libudev.so.1 \ - ${DESTDIR}${INCLUDEDIR}/libudev.h + ${DESTDIR}${LIBDIR}/libudev.so \ + ${DESTDIR}${LIBDIR}/libudev.so.1 \ + ${DESTDIR}${INCLUDEDIR}/libudev.h clean: rm -f libudev.so libudev.a ${OBJ} diff --git a/udev.c b/udev.c index cc6a147..d15bce5 100644 --- a/udev.c +++ b/udev.c @@ -10,7 +10,7 @@ struct udev UDEV_EXPORT struct udev *udev_new(void) { struct udev *udev; - + udev = calloc(1, sizeof(struct udev)); return udev; } diff --git a/udev.h b/udev.h index 83a3a9e..0279592 100644 --- a/udev.h +++ b/udev.h @@ -7,9 +7,9 @@ extern "C" { #define UDEV_EXPORT __attribute__ ((visibility("default"))) #define udev_list_entry_foreach(list_entry, first_entry) \ - for (list_entry = first_entry; \ - list_entry != NULL; \ - list_entry = udev_list_entry_get_next(list_entry)) + for (list_entry = first_entry; \ + list_entry != NULL; \ + list_entry = udev_list_entry_get_next(list_entry)) struct udev; struct udev_device; diff --git a/udev_device.c b/udev_device.c index 42f9b5d..a2d1108 100644 --- a/udev_device.c +++ b/udev_device.c @@ -15,7 +15,7 @@ struct udev_device { struct udev_list_entry properties; struct udev_list_entry sysattrs; - struct udev_device *parent; + struct udev_device *parent; struct udev *udev; char *subsystem; char *syspath; diff --git a/udev_util.c b/udev_util.c index 28d07d9..d95f2e3 100644 --- a/udev_util.c +++ b/udev_util.c @@ -7,12 +7,12 @@ int xasprintf(char *str, const char *fmt, ...) { - va_list list; - int len; + va_list list; + int len; - va_start(list, fmt); - len = vsnprintf(NULL, 0, fmt, list); - va_end(list); + va_start(list, fmt); + len = vsnprintf(NULL, 0, fmt, list); + va_end(list); if (len == -1) { return -1; From debdcbcc47177bfaf50306cbdc81d0689c2d866d Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 5 Jul 2020 03:11:55 +0300 Subject: [PATCH 003/222] fix parent --- udev_device.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/udev_device.c b/udev_device.c index a2d1108..4a14b64 100644 --- a/udev_device.c +++ b/udev_device.c @@ -158,7 +158,9 @@ UDEV_EXPORT struct udev_device *udev_device_get_parent_with_subsystem_devtype(st return NULL; } - while ((parent = udev_device_get_parent(udev_device))) { + parent = udev_device_get_parent(udev_device); + + while (parent) { parent_subsystem = udev_device_get_subsystem(parent); parent_devtype = udev_device_get_devtype(parent); @@ -171,6 +173,8 @@ UDEV_EXPORT struct udev_device *udev_device_get_parent_with_subsystem_devtype(st return parent; } } + + parent = udev_device_get_parent(parent); } return NULL; From b3b80e34a06a0a78b4388d3932df2a1ae972950a Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 5 Jul 2020 12:30:53 +0300 Subject: [PATCH 004/222] switch to macro --- udev_list.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/udev_list.c b/udev_list.c index a3f2f7f..1bf01b5 100644 --- a/udev_list.c +++ b/udev_list.c @@ -20,14 +20,10 @@ 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, *tmp2; + struct udev_list_entry *tmp; - tmp = list_entry; - - while (tmp) { - tmp2 = tmp; - tmp = tmp->next; - udev_list_entry_free(tmp2); + udev_list_entry_foreach(tmp, list_entry) { + udev_list_entry_free(tmp); } } @@ -77,14 +73,10 @@ UDEV_EXPORT struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list return NULL; } - tmp = list_entry; - - while (tmp) { + udev_list_entry_foreach(tmp, list_entry) { if (strcmp(tmp->name, name) == 0) { return tmp; } - - tmp = tmp->next; } return NULL; From dbb13e92865be663fac07de79e6129074cdbdab9 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 7 Jul 2020 10:07:24 +0300 Subject: [PATCH 005/222] 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) From a5b5667dce85c93a706a78c5cc2e444321a99b26 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 8 Jul 2020 14:38:40 +0300 Subject: [PATCH 006/222] rewrite --- Makefile | 3 +- udev_device.c | 144 ++++++++++++++--------------------------------- udev_enumerate.c | 16 ++---- udev_list.c | 4 +- udev_util.c | 37 ------------ udev_util.h | 1 - 6 files changed, 52 insertions(+), 153 deletions(-) delete mode 100644 udev_util.c delete mode 100644 udev_util.h diff --git a/Makefile b/Makefile index 215332f..5c052b3 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# .POSIX ?? +.POSIX: PREFIX = /usr/local XCFLAGS = ${CFLAGS} -pedantic -fPIC -fvisibility=hidden \ @@ -11,7 +11,6 @@ XARFLAGS = -rc OBJ = \ udev.o \ udev_list.o \ - udev_util.o \ udev_device.o \ udev_monitor.o \ udev_enumerate.o diff --git a/udev_device.c b/udev_device.c index ed38dfb..696f1f9 100644 --- a/udev_device.c +++ b/udev_device.c @@ -3,12 +3,12 @@ #include #include #include +#include #include #include #include "udev.h" #include "udev_list.h" -#include "udev_util.h" #include "udev_device.h" struct udev_device @@ -35,6 +35,7 @@ UDEV_EXPORT const char *udev_device_get_sysname(struct udev_device *udev_device) return NULL; } + // TODO retrieve sysname from DEVPATH if DEVNANE is NULL return udev_device_get_property_value(udev_device, "DEVNAME"); } @@ -117,32 +118,28 @@ UDEV_EXPORT struct udev *udev_device_get_udev(struct udev_device *udev_device) UDEV_EXPORT struct udev_device *udev_device_get_parent(struct udev_device *udev_device) { - char *path; - int slash; + char *tmp, *path; if (!udev_device) { return NULL; } - path = strdup(udev_device_get_property_value(udev_device, "SYSPATH")); + path = strdup(udev_device_get_syspath(udev_device)); - while (1) { - slash = strrchr(path, '/') - path; - - if (!slash) { - free(path); - return NULL; + do { + if ((tmp = strrchr(path, '/'))) { + *tmp = '\0'; + } + else { + break; } - - path[slash] = '\0'; udev_device->parent = udev_device_new_from_syspath(udev_device->udev, path); - - if (udev_device->parent) { - free(path); - return udev_device->parent; - } } + while (!udev_device->parent); + + free(path); + return udev_device->parent; } UDEV_EXPORT struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype) @@ -219,16 +216,14 @@ UDEV_EXPORT const char *udev_device_get_property_value(struct udev_device *udev_ 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) { struct udev_list_entry *list_entry; - char data[1024], *path = NULL; + char data[1024], path[PATH_MAX]; struct stat st; - ssize_t len; int fd; if (!udev_device || !sysattr) { @@ -241,41 +236,32 @@ 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_get_property_value(udev_device, "SYSPATH"), sysattr) == -1) { - return NULL; - } + snprintf(path, sizeof(path), "%s/%s", udev_device_get_syspath(udev_device), sysattr); if (stat(path, &st) != 0 || S_ISDIR(st.st_mode)) { - free(path); return NULL; } fd = open(path, O_RDONLY | O_NOFOLLOW); if (fd == -1) { - free(path); return NULL; } - len = read(fd, data, sizeof(data)); - - if (len == -1) { + if (read(fd, data, sizeof(data)) == -1) { close(fd); - free(path); return NULL; } close(fd); - free(path); - data[len] = '\0'; // XXX strip trailing '\n' + data[strcspn(data, "\n")] = '\0'; list_entry = udev_list_entry_add(&udev_device->sysattrs, sysattr, data); return udev_list_entry_get_value(list_entry); } UDEV_EXPORT int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, const char *value) { - size_t len = strlen(value); - char *path = NULL; + char path[PATH_MAX]; struct stat st; int fd; @@ -283,75 +269,59 @@ UDEV_EXPORT int udev_device_set_sysattr_value(struct udev_device *udev_device, c return -1; } - if (xasprintf(path, "%s/%s", udev_device_get_property_value(udev_device, "SYSPATH"), sysattr) == -1) { - return -1; - } + snprintf(path, sizeof(path), "%s/%s", udev_device_get_syspath(udev_device), sysattr); if (stat(path, &st) != 0 || S_ISDIR(st.st_mode)) { - free(path); return -1; } fd = open(path, O_WRONLY | O_NOFOLLOW); if (fd == -1) { - free(path); return -1; } - if (write(fd, value, len) == -1) { + if (write(fd, value, strlen(value)) == -1) { close(fd); - free(path); return -1; } close(fd); - free(path); udev_list_entry_add(&udev_device->sysattrs, sysattr, value); return 0; } const char *udev_device_read_symlink(struct udev_device *udev_device, const char *name) { - char *link, *data, *path = NULL; + char link[PATH_MAX], path[PATH_MAX]; - if (xasprintf(path, "%s/%s", udev_device_get_property_value(udev_device, "SYSPATH"), name) == -1) { + snprintf(path, sizeof(path), "%s/%s", udev_device_get_syspath(udev_device), name); + + if (!realpath(path, link)) { return NULL; } - link = realpath(path, NULL); // XXX XSI - - if (!link) { - free(path); - return NULL; - } - - data = strrchr(link, '/') + 1; - free(path); - free(link); - return data; + return strrchr(link, '/') + 1; } 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; + char *key, *val, line[1024], path[PATH_MAX]; + char *sysname, devnode[PATH_MAX]; FILE *file; int i; - if (xasprintf(path, "%s/uevent", udev_device_get_property_value(udev_device, "SYSPATH")) == -1) { - return; - } + snprintf(path, sizeof(path), "%s/uevent", udev_device_get_syspath(udev_device)); file = fopen(path, "r"); if (!file) { - free(path); return; } - while (getline(&line, &len, file) != -1) { + while (fgets(line, sizeof(line), file)) { + line[strcspn(line, "\n")] = '\0'; + if (strncmp(line, "DEVNAME", 7) == 0) { sysname = strrchr(line + 8, '/'); @@ -371,12 +341,8 @@ void udev_device_set_properties_from_uevent(struct udev_device *udev_device) } } - if (xasprintf(devnode, "/dev/%s", line + 8) == -1) { - continue; - } - + snprintf(devnode, sizeof(devnode), "/dev/%s", line + 8); 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); @@ -392,23 +358,14 @@ void udev_device_set_properties_from_uevent(struct udev_device *udev_device) } 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; - } - } + key = line; + key[strcspn(key, "=")] = '\0'; udev_list_entry_add(&udev_device->properties, key, val); - free(key); } } fclose(file); - free(line); - free(path); } void udev_device_set_properties_from_ioctl(struct udev_device *udev_device) @@ -418,46 +375,37 @@ void udev_device_set_properties_from_ioctl(struct udev_device *udev_device) UDEV_EXPORT struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) { + char path[PATH_MAX], file[PATH_MAX]; struct udev_device *udev_device; - char *path, *file = NULL; struct stat st; if (!udev || !syspath) { return NULL; } - path = realpath(syspath, NULL); // XXX XSI - - if (!path) { + if (!realpath(syspath, path)) { return NULL; } if (stat(path, &st) != 0 || S_ISDIR(st.st_mode) == 0) { - free(path); return NULL; } - if (xasprintf(file, "%s/uevent", path) == -1) { - free(path); - return NULL; - } + snprintf(file, sizeof(file), "%s/uevent", path); if (access(file, R_OK) == -1) { - free(file); - free(path); return NULL; } 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->parent = NULL; udev_list_entry_init(&udev_device->properties); udev_list_entry_init(&udev_device->sysattrs); @@ -470,15 +418,12 @@ UDEV_EXPORT struct udev_device *udev_device_new_from_syspath(struct udev *udev, udev_device_set_properties_from_uevent(udev_device); udev_device_set_properties_from_ioctl(udev_device); - free(file); - free(path); return udev_device; } UDEV_EXPORT struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum) { - struct udev_device *udev_device; - char *path = NULL; + char path[PATH_MAX]; if (!udev || !type || !devnum) { return NULL; @@ -486,19 +431,16 @@ UDEV_EXPORT struct udev_device *udev_device_new_from_devnum(struct udev *udev, c switch (type) { case 'c': - xasprintf(path, "/sys/dev/char/%d:%d", major(devnum), minor(devnum)); + snprintf(path, sizeof(path), "/sys/dev/char/%d:%d", major(devnum), minor(devnum)); break; case 'b': - xasprintf(path, "/sys/dev/block/%d:%d", major(devnum), minor(devnum)); + snprintf(path, sizeof(path), "/sys/dev/block/%d:%d", major(devnum), minor(devnum)); break; default: return NULL; } - udev_device = udev_device_new_from_syspath(udev, path); - - free(path); - return udev_device; + return udev_device_new_from_syspath(udev, path); } UDEV_EXPORT struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname) diff --git a/udev_enumerate.c b/udev_enumerate.c index c9f7f16..ae3b187 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -1,13 +1,14 @@ +#include #include #include #include +#include #include #include #include #include "udev.h" #include "udev_list.h" -#include "udev_util.h" #include "udev_enumerate.h" struct udev_enumerate @@ -253,7 +254,6 @@ void udev_enumerate_add_device(struct udev_enumerate *udev_enumerate, const char 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) || @@ -268,7 +268,7 @@ void udev_enumerate_add_device(struct udev_enumerate *udev_enumerate, const char void udev_enumerate_scan_dir(struct udev_enumerate *udev_enumerate, const char *path) { - char *file = NULL; + char file[PATH_MAX]; struct dirent *de; struct stat st; DIR *dp; @@ -285,10 +285,7 @@ void udev_enumerate_scan_dir(struct udev_enumerate *udev_enumerate, const char * continue; } - if (xasprintf(file, "%s/%s", path, de->d_name) == -1) { - closedir(dp); - return; - } + snprintf(file, sizeof(file), "%s/%s", path, de->d_name); if (lstat(file, &st) != 0 || S_ISLNK(st.st_mode)) { continue; @@ -297,15 +294,14 @@ void udev_enumerate_scan_dir(struct udev_enumerate *udev_enumerate, const char * udev_enumerate_scan_dir(udev_enumerate, file); } else if (S_ISBLK(st.st_mode)) { - udev_enumerate_add_device(udev_enumerate, 'c', st.st_dev); + udev_enumerate_add_device(udev_enumerate, 'b', st.st_rdev); } else if (S_ISCHR(st.st_mode)) { - udev_enumerate_add_device(udev_enumerate, 'b', st.st_dev); + udev_enumerate_add_device(udev_enumerate, 'c', st.st_rdev); } } closedir(dp); - free(file); } UDEV_EXPORT int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) diff --git a/udev_list.c b/udev_list.c index 97e38c7..4c00023 100644 --- a/udev_list.c +++ b/udev_list.c @@ -22,7 +22,7 @@ void udev_list_entry_free_all(struct udev_list_entry *list_entry) { struct udev_list_entry *tmp, *tmp2; - tmp = list_entry; + tmp = list_entry->next; while (tmp) { tmp2 = tmp; @@ -77,7 +77,7 @@ UDEV_EXPORT struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list return NULL; } - tmp = list_entry; + tmp = list_entry->next; while (tmp) { if (strcmp(tmp->name, name) == 0) { diff --git a/udev_util.c b/udev_util.c deleted file mode 100644 index d95f2e3..0000000 --- a/udev_util.c +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include -#include - -#include "udev_util.h" -#include "udev.h" - -int xasprintf(char *str, const char *fmt, ...) -{ - va_list list; - int len; - - va_start(list, fmt); - len = vsnprintf(NULL, 0, fmt, list); - va_end(list); - - if (len == -1) { - return -1; - } - - str = malloc(len + 1); - - if (!str) { - return -1; - } - - len = vsnprintf(str, len + 1, fmt, list); - - if (len == -1) { - free(str); - return -1; - } - - return len; -} - -// TODO readlink+malloc diff --git a/udev_util.h b/udev_util.h deleted file mode 100644 index 583a347..0000000 --- a/udev_util.h +++ /dev/null @@ -1 +0,0 @@ -int xasprintf(char *str, const char *fmt, ...); From 944d249b408918e0c1251af3e921a73b26e2b056 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 8 Jul 2020 14:44:44 +0300 Subject: [PATCH 007/222] fix makefile --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index 5c052b3..3685f76 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,8 @@ .POSIX: PREFIX = /usr/local +LIBDIR = ${PREFIX}/lib +INCLUDEDIR = ${PREFIX}/include XCFLAGS = ${CFLAGS} -pedantic -fPIC -fvisibility=hidden \ -D_POSIX_VERSION=200809L -D_XOPEN_SOURCE=700 -std=c99 \ -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \ From 35972adc321b9a31e5438cd7a5ee87a8e08c74df Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 8 Jul 2020 16:51:57 +0300 Subject: [PATCH 008/222] implement INPUT properties --- udev_device.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/udev_device.c b/udev_device.c index 696f1f9..ddda8fb 100644 --- a/udev_device.c +++ b/udev_device.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -368,9 +369,33 @@ void udev_device_set_properties_from_uevent(struct udev_device *udev_device) fclose(file); } +// TODO extract INPUT properties using libevdev or direct ioctl's(complex), HELP WANTED! +// Very very very dirty hack to detect INPUT properties. False positives are guaranteed 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! + const char *name; + + if (strcmp(udev_device_get_subsystem(udev_device), "input") != 0) { + return; + } + + udev_list_entry_add(&udev_device->properties, "ID_INPUT", "1"); + name = udev_device_get_sysattr_value(udev_device, "name"); + + if (!name) { + return; + } + + // Your mind will be dead after reading this code + if (fnmatch("*[Mm][Ou][Uu][Ss][Ee]*", name, 0) == 0) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1"); + } + else if (fnmatch("*[Tt][Oo][Uu][Cc][Hh][Pp][Aa][Dd]*", name, 0) == 0) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHPAD", "1"); + } + else if (fnmatch("*[Kk][Ee][Yy][Bb][Oo][Aa][Rr][Dd]*", name, 0) == 0) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEYBOARD", "1"); + } } UDEV_EXPORT struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) From 8fbdeb3fe32a7346d868d05d18ea7c2196b8d35f Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 8 Jul 2020 17:07:06 +0300 Subject: [PATCH 009/222] fix udev_device_get_sysname --- udev_device.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/udev_device.c b/udev_device.c index ddda8fb..61f2e39 100644 --- a/udev_device.c +++ b/udev_device.c @@ -32,12 +32,21 @@ UDEV_EXPORT const char *udev_device_get_syspath(struct udev_device *udev_device) UDEV_EXPORT const char *udev_device_get_sysname(struct udev_device *udev_device) { + const char *sysname; + if (!udev_device) { return NULL; } - // TODO retrieve sysname from DEVPATH if DEVNANE is NULL - return udev_device_get_property_value(udev_device, "DEVNAME"); + if ((sysname = udev_device_get_property_value(udev_device, "DEVNAME"))) { + return sysname; + } + + if ((sysname = udev_device_get_devpath(udev_device))) { + return strrchr(sysname, '/') + 1; + } + + return NULL; } UDEV_EXPORT const char *udev_device_get_sysnum(struct udev_device *udev_device) From a686cc2b22501ddcf93ed1edaa0fb24ef480f627 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 8 Jul 2020 19:39:18 +0300 Subject: [PATCH 010/222] check NULL --- udev_device.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/udev_device.c b/udev_device.c index 61f2e39..e3689f8 100644 --- a/udev_device.c +++ b/udev_device.c @@ -382,9 +382,11 @@ void udev_device_set_properties_from_uevent(struct udev_device *udev_device) // Very very very dirty hack to detect INPUT properties. False positives are guaranteed void udev_device_set_properties_from_ioctl(struct udev_device *udev_device) { - const char *name; + const char *name, *subsystem; - if (strcmp(udev_device_get_subsystem(udev_device), "input") != 0) { + subsystem = udev_device_get_subsystem(udev_device); + + if (!subsystem || strcmp(subsystem, "input") != 0) { return; } From 9c3df3e390e102363fdac6f0dac1fd5dfb6bbf7e Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 9 Jul 2020 15:43:09 +0300 Subject: [PATCH 011/222] check NULL --- udev_list.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udev_list.c b/udev_list.c index 4c00023..0696468 100644 --- a/udev_list.c +++ b/udev_list.c @@ -43,7 +43,7 @@ struct udev_list_entry *udev_list_entry_add(struct udev_list_entry *list_entry, } free(old->value); - old->value = strdup(value); + old->value = value ? strdup(value) : NULL; return old; } From 1072c74cb605cdcb6813250531dc13fcb74df581 Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 10 Jul 2020 16:23:17 +0300 Subject: [PATCH 012/222] extract name from parent device --- udev_device.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/udev_device.c b/udev_device.c index e3689f8..ea9972a 100644 --- a/udev_device.c +++ b/udev_device.c @@ -383,6 +383,7 @@ void udev_device_set_properties_from_uevent(struct udev_device *udev_device) void udev_device_set_properties_from_ioctl(struct udev_device *udev_device) { const char *name, *subsystem; + struct udev_device *parent; subsystem = udev_device_get_subsystem(udev_device); @@ -394,7 +395,12 @@ void udev_device_set_properties_from_ioctl(struct udev_device *udev_device) name = udev_device_get_sysattr_value(udev_device, "name"); if (!name) { - return; + parent = udev_device_get_parent(udev_device); + name = udev_device_get_sysattr_value(parent, "name"); + + if (!name) { + return; + } } // Your mind will be dead after reading this code From 0fe2371c0d122b2acdf1078ed6bd86cd4e56bd59 Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 10 Jul 2020 20:59:25 +0300 Subject: [PATCH 013/222] add libudev.pc. thanks @E5ten --- Makefile | 17 +++++++++++++---- libudev.pc.in | 9 +++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 libudev.pc.in diff --git a/Makefile b/Makefile index 3685f76..c626b3b 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ OBJ = \ udev_monitor.o \ udev_enumerate.o -all: libudev.so libudev.a +all: libudev.so libudev.a libudev.pc .c.o: ${CC} ${XCFLAGS} -c -o $@ $< @@ -28,8 +28,14 @@ libudev.a: ${OBJ} libudev.so: ${OBJ} ${CC} ${XCFLAGS} -o $@ ${OBJ} ${XLDFLAGS} -install: libudev.so libudev.a - mkdir -p ${DESTDIR}${INCLUDEDIR} ${DESTDIR}${LIBDIR} +libudev.pc: libudev.pc.in + sed -e 's|@libdir@|${LIBDIR}|g' \ + -e 's|@includedir@|${INCLUDEDIR}|g' \ + -e 's|@VERSION@|243|g' \ + libudev.pc.in > libudev.pc + +install: libudev.so libudev.a libudev.pc + mkdir -p ${DESTDIR}${INCLUDEDIR} ${DESTDIR}${LIBDIR}/pkgconfig cp -f udev.h ${DESTDIR}${INCLUDEDIR}/libudev.h chmod 0644 ${DESTDIR}${INCLUDEDIR}/libudev.h cp -f libudev.a ${DESTDIR}${LIBDIR}/libudev.a @@ -37,14 +43,17 @@ install: libudev.so libudev.a cp -f libudev.so ${DESTDIR}${LIBDIR}/libudev.so chmod 0755 ${DESTDIR}${LIBDIR}/libudev.so ln -s libudev.so ${DESTDIR}${LIBDIR}/libudev.so.1 + cp -f libudev.pc ${DESTDIR}${LIBDIR}/pkgconfig/ + chmod 0644 ${DESTDIR}${LIBDIR}/pkgconfig/libudev.pc uninstall: rm -f ${DESTDIR}${LIBDIR}/libudev.a \ ${DESTDIR}${LIBDIR}/libudev.so \ ${DESTDIR}${LIBDIR}/libudev.so.1 \ + ${DESTDIR}${LIBDIR}/pkgconfig/libudev.pc \ ${DESTDIR}${INCLUDEDIR}/libudev.h clean: - rm -f libudev.so libudev.a ${OBJ} + rm -f libudev.so libudev.a libudev.pc ${OBJ} .PHONY: all clean install uninstall diff --git a/libudev.pc.in b/libudev.pc.in new file mode 100644 index 0000000..4955b43 --- /dev/null +++ b/libudev.pc.in @@ -0,0 +1,9 @@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libudev +Description: Daemonless replacement for libudev +Version: @VERSION@ +URL: https://github.com/illiliti/libudev-zero +Libs: -L${libdir} -ludev +Cflags: -I${includedir} From 9a9bc2e3fd9c00e3c465b5b703656584f6cd8dee Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 10 Jul 2020 21:51:45 +0300 Subject: [PATCH 014/222] update readme --- README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f77e34d..7520fc7 100644 --- a/README.md +++ b/README.md @@ -1 +1,12 @@ -Nothing works here(yet), move along +libudev-zero +============ + +Drop-in replacement for libudev intented to work without daemon + +What Works +---------- +* [x] xorg-server +* [x] libinput +* [ ] wlroots - should work, but need test +* [ ] weston - need implement udev_device_new_from_subsystem_sysname() +* [ ] ??? From e76f9b282442505bd6b0b08b411679aae1581fa5 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 11 Jul 2020 12:54:58 +0300 Subject: [PATCH 015/222] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7520fc7..77e088c 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,6 @@ What Works ---------- * [x] xorg-server * [x] libinput -* [ ] wlroots - should work, but need test +* [ ] wlroots - partially works. someone reported that mouse doesn't work * [ ] weston - need implement udev_device_new_from_subsystem_sysname() * [ ] ??? From a949a52ae153c46be1dd7f6d2d694c19f0a97b92 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 11 Jul 2020 15:08:16 +0300 Subject: [PATCH 016/222] update readme --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 77e088c..f4d9c1c 100644 --- a/README.md +++ b/README.md @@ -10,3 +10,9 @@ What Works * [ ] wlroots - partially works. someone reported that mouse doesn't work * [ ] weston - need implement udev_device_new_from_subsystem_sysname() * [ ] ??? + +TODO +---- + +* [ ] implement hotplugging support +* [ ] remove [dirty hack](https://github.com/illiliti/libudev-zero/blob/e76f9b282442505bd6b0b08b411679aae1581fa5/udev_device.c#L383). use ioctl() From a50690071e1f53ee68f2b36468d90ad547e35e71 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 12 Jul 2020 13:56:08 +0300 Subject: [PATCH 017/222] update readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f4d9c1c..57b475b 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ What Works * [x] libinput * [ ] wlroots - partially works. someone reported that mouse doesn't work * [ ] weston - need implement udev_device_new_from_subsystem_sysname() +* [ ] kwin - fails to compile for odd reason * [ ] ??? TODO From 93e84c2c4bfe3a46881acba39ebc4fee562665eb Mon Sep 17 00:00:00 2001 From: illiliti Date: Mon, 13 Jul 2020 02:16:37 +0300 Subject: [PATCH 018/222] implement ioctl() --- README.md | 2 +- udev_device.c | 64 ++++++++++++++++++++++++++++++++++----------------- udev_device.h | 1 + 3 files changed, 45 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 57b475b..0fa2c90 100644 --- a/README.md +++ b/README.md @@ -16,4 +16,4 @@ TODO ---- * [ ] implement hotplugging support -* [ ] remove [dirty hack](https://github.com/illiliti/libudev-zero/blob/e76f9b282442505bd6b0b08b411679aae1581fa5/udev_device.c#L383). use ioctl() +* [x] remove [dirty hack](https://github.com/illiliti/libudev-zero/blob/e76f9b282442505bd6b0b08b411679aae1581fa5/udev_device.c#L383). use ioctl() diff --git a/udev_device.c b/udev_device.c index ea9972a..3600f2a 100644 --- a/udev_device.c +++ b/udev_device.c @@ -4,8 +4,9 @@ #include #include #include -#include #include +#include +#include #include #include "udev.h" @@ -378,12 +379,16 @@ void udev_device_set_properties_from_uevent(struct udev_device *udev_device) fclose(file); } -// TODO extract INPUT properties using libevdev or direct ioctl's(complex), HELP WANTED! -// Very very very dirty hack to detect INPUT properties. False positives are guaranteed +int test_bit(unsigned long int arr[], int bit) +{ + return arr[bit / LONG_BIT] & (1 << (bit % LONG_BIT)); +} + void udev_device_set_properties_from_ioctl(struct udev_device *udev_device) { - const char *name, *subsystem; - struct udev_device *parent; + unsigned long int bits[96], key_bits[96], rel_bits[96], abs_bits[96]; + const char *subsystem; + int fd; subsystem = udev_device_get_subsystem(udev_device); @@ -392,27 +397,44 @@ void udev_device_set_properties_from_ioctl(struct udev_device *udev_device) } udev_list_entry_add(&udev_device->properties, "ID_INPUT", "1"); - name = udev_device_get_sysattr_value(udev_device, "name"); - if (!name) { - parent = udev_device_get_parent(udev_device); - name = udev_device_get_sysattr_value(parent, "name"); + fd = open(udev_device_get_devnode(udev_device), O_RDONLY); - if (!name) { - return; + if (fd == -1) { + return; + } + + if (ioctl(fd, EVIOCGBIT(0, sizeof(bits)), &bits) == -1 || + ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)), &key_bits) == -1 || + ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bits)), &rel_bits) == -1 || + ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), &abs_bits) == -1) { + return; + } + + if (test_bit(bits, EV_SW)) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_SWITCH", "1"); + } + + if (test_bit(bits, EV_KEY) && test_bit(key_bits, KEY_ENTER)) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEY", "1"); + udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEYBOARD", "1"); + } + + if (test_bit(bits, EV_REL) && test_bit(rel_bits, REL_Y) && test_bit(rel_bits, REL_X) && + test_bit(key_bits, BTN_MOUSE)) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1"); + } + + if (test_bit(bits, EV_ABS) && test_bit(abs_bits, ABS_Y) && test_bit(abs_bits, ABS_X)) { + if (test_bit(key_bits, BTN_TOOL_FINGER) && !test_bit(key_bits, BTN_TOOL_PEN)) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHPAD", "1"); + } + else if (test_bit(key_bits, BTN_MOUSE)) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1"); } } - // Your mind will be dead after reading this code - if (fnmatch("*[Mm][Ou][Uu][Ss][Ee]*", name, 0) == 0) { - udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1"); - } - else if (fnmatch("*[Tt][Oo][Uu][Cc][Hh][Pp][Aa][Dd]*", name, 0) == 0) { - udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHPAD", "1"); - } - else if (fnmatch("*[Kk][Ee][Yy][Bb][Oo][Aa][Rr][Dd]*", name, 0) == 0) { - udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEYBOARD", "1"); - } + close(fd); } UDEV_EXPORT struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) diff --git a/udev_device.h b/udev_device.h index e81a22d..ed1b3dd 100644 --- a/udev_device.h +++ b/udev_device.h @@ -1,3 +1,4 @@ +int test_bit(unsigned long int arr[], int bit); 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); From 54fd01f80edf8f5b166f959fc3f764a8af4d05ac Mon Sep 17 00:00:00 2001 From: illiliti Date: Mon, 13 Jul 2020 17:18:47 +0300 Subject: [PATCH 019/222] fix fd leak --- udev_device.c | 1 + 1 file changed, 1 insertion(+) diff --git a/udev_device.c b/udev_device.c index 3600f2a..82aa799 100644 --- a/udev_device.c +++ b/udev_device.c @@ -408,6 +408,7 @@ void udev_device_set_properties_from_ioctl(struct udev_device *udev_device) ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)), &key_bits) == -1 || ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bits)), &rel_bits) == -1 || ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), &abs_bits) == -1) { + close(fd); return; } From 24cc238b45ab78793951c1f2b69f295e03b91167 Mon Sep 17 00:00:00 2001 From: illiliti Date: Mon, 13 Jul 2020 19:35:01 +0300 Subject: [PATCH 020/222] add touchscreen support --- udev_device.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/udev_device.c b/udev_device.c index 82aa799..df1fb87 100644 --- a/udev_device.c +++ b/udev_device.c @@ -427,8 +427,13 @@ void udev_device_set_properties_from_ioctl(struct udev_device *udev_device) } if (test_bit(bits, EV_ABS) && test_bit(abs_bits, ABS_Y) && test_bit(abs_bits, ABS_X)) { - if (test_bit(key_bits, BTN_TOOL_FINGER) && !test_bit(key_bits, BTN_TOOL_PEN)) { - udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHPAD", "1"); + if (test_bit(key_bits, BTN_TOUCH) && !test_bit(key_bits, BTN_TOOL_PEN)) { + if (test_bit(key_bits, BTN_TOOL_FINGER)) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHPAD", "1"); + } + else { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHSCREEN", "1"); + } } else if (test_bit(key_bits, BTN_MOUSE)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1"); From 00b13d3268c28a020af26b2dc54a7d1a58a530bc Mon Sep 17 00:00:00 2001 From: illiliti Date: Mon, 13 Jul 2020 22:46:01 +0300 Subject: [PATCH 021/222] use static --- udev_device.c | 9 ++++----- udev_device.h | 4 ---- udev_enumerate.c | 13 ++++++------- udev_enumerate.h | 6 ------ 4 files changed, 10 insertions(+), 22 deletions(-) delete mode 100644 udev_device.h delete mode 100644 udev_enumerate.h diff --git a/udev_device.c b/udev_device.c index df1fb87..9da5117 100644 --- a/udev_device.c +++ b/udev_device.c @@ -11,7 +11,6 @@ #include "udev.h" #include "udev_list.h" -#include "udev_device.h" struct udev_device { @@ -302,7 +301,7 @@ UDEV_EXPORT int udev_device_set_sysattr_value(struct udev_device *udev_device, c return 0; } -const char *udev_device_read_symlink(struct udev_device *udev_device, const char *name) +static const char *udev_device_read_symlink(struct udev_device *udev_device, const char *name) { char link[PATH_MAX], path[PATH_MAX]; @@ -315,7 +314,7 @@ const char *udev_device_read_symlink(struct udev_device *udev_device, const char return strrchr(link, '/') + 1; } -void udev_device_set_properties_from_uevent(struct udev_device *udev_device) +static void udev_device_set_properties_from_uevent(struct udev_device *udev_device) { char *key, *val, line[1024], path[PATH_MAX]; char *sysname, devnode[PATH_MAX]; @@ -379,12 +378,12 @@ void udev_device_set_properties_from_uevent(struct udev_device *udev_device) fclose(file); } -int test_bit(unsigned long int arr[], int bit) +static int test_bit(unsigned long int arr[], int bit) { return arr[bit / LONG_BIT] & (1 << (bit % LONG_BIT)); } -void udev_device_set_properties_from_ioctl(struct udev_device *udev_device) +static void udev_device_set_properties_from_ioctl(struct udev_device *udev_device) { unsigned long int bits[96], key_bits[96], rel_bits[96], abs_bits[96]; const char *subsystem; diff --git a/udev_device.h b/udev_device.h deleted file mode 100644 index ed1b3dd..0000000 --- a/udev_device.h +++ /dev/null @@ -1,4 +0,0 @@ -int test_bit(unsigned long int arr[], int bit); -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 ae3b187..0f9396b 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -9,7 +9,6 @@ #include "udev.h" #include "udev_list.h" -#include "udev_enumerate.h" struct udev_enumerate { @@ -95,7 +94,7 @@ 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) +static int udev_enumerate_filter_subsystem(struct udev_enumerate *udev_enumerate, struct udev_device *udev_device) { struct udev_list_entry *list_entry; const char *subsystem; @@ -132,7 +131,7 @@ int udev_enumerate_filter_subsystem(struct udev_enumerate *udev_enumerate, struc return 1; } -int udev_enumerate_filter_sysname(struct udev_enumerate *udev_enumerate, struct udev_device *udev_device) +static int udev_enumerate_filter_sysname(struct udev_enumerate *udev_enumerate, struct udev_device *udev_device) { struct udev_list_entry *list_entry; const char *sysname; @@ -155,7 +154,7 @@ int udev_enumerate_filter_sysname(struct udev_enumerate *udev_enumerate, struct return 0; } -int udev_enumerate_filter_property(struct udev_enumerate *udev_enumerate, struct udev_device *udev_device) +static 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; @@ -198,7 +197,7 @@ int udev_enumerate_filter_property(struct udev_enumerate *udev_enumerate, struct return 0; } -int udev_enumerate_filter_sysattr(struct udev_enumerate *udev_enumerate, struct udev_device *udev_device) +static 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; @@ -244,7 +243,7 @@ int udev_enumerate_filter_sysattr(struct udev_enumerate *udev_enumerate, struct return 1; } -void udev_enumerate_add_device(struct udev_enumerate *udev_enumerate, const char type, dev_t devnum) +static void udev_enumerate_add_device(struct udev_enumerate *udev_enumerate, const char type, dev_t devnum) { struct udev_device *udev_device; @@ -266,7 +265,7 @@ void udev_enumerate_add_device(struct udev_enumerate *udev_enumerate, const char udev_device_unref(udev_device); } -void udev_enumerate_scan_dir(struct udev_enumerate *udev_enumerate, const char *path) +static void udev_enumerate_scan_dir(struct udev_enumerate *udev_enumerate, const char *path) { char file[PATH_MAX]; struct dirent *de; diff --git a/udev_enumerate.h b/udev_enumerate.h deleted file mode 100644 index 08a97f9..0000000 --- a/udev_enumerate.h +++ /dev/null @@ -1,6 +0,0 @@ -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); From 3df658c73d4ca89a2926da4f9b8661be5a8f590c Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 14 Jul 2020 00:10:51 +0300 Subject: [PATCH 022/222] remove useless include --- udev_enumerate.c | 1 - 1 file changed, 1 deletion(-) diff --git a/udev_enumerate.c b/udev_enumerate.c index 0f9396b..4e77720 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -5,7 +5,6 @@ #include #include #include -#include #include "udev.h" #include "udev_list.h" From bab130c7fd87e49267839ca51bee8f0b033a8345 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 14 Jul 2020 00:14:10 +0300 Subject: [PATCH 023/222] silence gcc --- udev_device.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/udev_device.c b/udev_device.c index 9da5117..7cc484a 100644 --- a/udev_device.c +++ b/udev_device.c @@ -403,10 +403,10 @@ static void udev_device_set_properties_from_ioctl(struct udev_device *udev_devic return; } - if (ioctl(fd, EVIOCGBIT(0, sizeof(bits)), &bits) == -1 || - ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)), &key_bits) == -1 || - ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bits)), &rel_bits) == -1 || - ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), &abs_bits) == -1) { + if (ioctl(fd, (int)EVIOCGBIT(0, sizeof(bits)), &bits) == -1 || + ioctl(fd, (int)EVIOCGBIT(EV_KEY, sizeof(key_bits)), &key_bits) == -1 || + ioctl(fd, (int)EVIOCGBIT(EV_REL, sizeof(rel_bits)), &rel_bits) == -1 || + ioctl(fd, (int)EVIOCGBIT(EV_ABS, sizeof(abs_bits)), &abs_bits) == -1) { close(fd); return; } @@ -444,7 +444,7 @@ static void udev_device_set_properties_from_ioctl(struct udev_device *udev_devic UDEV_EXPORT struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) { - char path[PATH_MAX], file[PATH_MAX]; + char path[PATH_MAX], file[PATH_MAX + 7]; struct udev_device *udev_device; struct stat st; From 82de2c9cf8cdb9dd352533ee068afdb31c308304 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 14 Jul 2020 03:19:35 +0300 Subject: [PATCH 024/222] format --- Makefile | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index c626b3b..487bdb5 100644 --- a/Makefile +++ b/Makefile @@ -3,19 +3,19 @@ PREFIX = /usr/local LIBDIR = ${PREFIX}/lib INCLUDEDIR = ${PREFIX}/include -XCFLAGS = ${CFLAGS} -pedantic -fPIC -fvisibility=hidden \ - -D_POSIX_VERSION=200809L -D_XOPEN_SOURCE=700 -std=c99 \ - -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \ - -Wno-return-type -Wno-unused-parameter +XCFLAGS = ${CFLAGS} -std=c99 -fPIC -fvisibility=hidden \ + -D_POSIX_VERSION=200809L -D_XOPEN_SOURCE=700 \ + -Wall -Wextra -Wpedantic -Wmissing-prototypes \ + -Wstrict-prototypes -Wno-unused-parameter XLDFLAGS = ${LDFLAGS} -shared -Wl,-soname,libudev.so.1 XARFLAGS = -rc OBJ = \ - udev.o \ - udev_list.o \ - udev_device.o \ - udev_monitor.o \ - udev_enumerate.o + udev.o \ + udev_list.o \ + udev_device.o \ + udev_monitor.o \ + udev_enumerate.o all: libudev.so libudev.a libudev.pc From 80b754f876e13b18a4c92f5151632850072f6dd7 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 14 Jul 2020 16:23:11 +0300 Subject: [PATCH 025/222] format --- udev.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/udev.h b/udev.h index 0279592..cbfb5ae 100644 --- a/udev.h +++ b/udev.h @@ -5,11 +5,8 @@ extern "C" { #endif #define UDEV_EXPORT __attribute__ ((visibility("default"))) - #define udev_list_entry_foreach(list_entry, first_entry) \ - for (list_entry = first_entry; \ - list_entry != NULL; \ - list_entry = udev_list_entry_get_next(list_entry)) + for (list_entry = first_entry; list_entry; list_entry = udev_list_entry_get_next(list_entry)) struct udev; struct udev_device; From 12eb197449855af03d243a1ebb7a776df2f3801f Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 16 Jul 2020 21:18:38 +0300 Subject: [PATCH 026/222] minor fixes --- udev_list.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/udev_list.c b/udev_list.c index 0696468..248317a 100644 --- a/udev_list.c +++ b/udev_list.c @@ -53,8 +53,6 @@ struct udev_list_entry *udev_list_entry_add(struct udev_list_entry *list_entry, return NULL; } - udev_list_entry_init(new); - new->value = value ? strdup(value) : NULL; new->name = strdup(name); @@ -77,10 +75,10 @@ UDEV_EXPORT struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list return NULL; } - tmp = list_entry->next; + tmp = list_entry; while (tmp) { - if (strcmp(tmp->name, name) == 0) { + if (tmp->name && strcmp(tmp->name, name) == 0) { return tmp; } From f9eeef168e7773c035d7d7c2c593983cb7e29f9d Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 16 Jul 2020 22:07:42 +0300 Subject: [PATCH 027/222] typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0fa2c90..e9881b3 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ libudev-zero ============ -Drop-in replacement for libudev intented to work without daemon +Drop-in replacement for libudev intended to work without daemon What Works ---------- From 09dbf27a07481726ccbf9482d36bf7c0cfb651c3 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 16 Jul 2020 22:53:23 +0300 Subject: [PATCH 028/222] implement udev_device_new_from_subsystem_sysname --- README.md | 2 +- udev_device.c | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e9881b3..3395f06 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ What Works * [x] xorg-server * [x] libinput * [ ] wlroots - partially works. someone reported that mouse doesn't work -* [ ] weston - need implement udev_device_new_from_subsystem_sysname() +* [ ] weston - should work. need test * [ ] kwin - fails to compile for odd reason * [ ] ??? diff --git a/udev_device.c b/udev_device.c index 7cc484a..841fcdd 100644 --- a/udev_device.c +++ b/udev_device.c @@ -514,7 +514,22 @@ UDEV_EXPORT struct udev_device *udev_device_new_from_devnum(struct udev *udev, c UDEV_EXPORT struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname) { - // XXX NOT IMPLEMENTED + char *fmt[] = { "/sys/bus/%s/devices/%s", "/sys/class/%s/%s", NULL }; + char path[PATH_MAX]; + int i; + + if (!udev || !subsystem || !sysname) { + return NULL; + } + + for (i = 0; fmt[i]; i++) { + snprintf(path, sizeof(path), fmt[i], subsystem, sysname); + + if (access(path, R_OK)) { + return udev_device_new_from_syspath(udev, path); + } + } + return NULL; } From 8b7689302dba3e02951c2c3740670b8194b3ebca Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 17 Jul 2020 04:48:15 +0300 Subject: [PATCH 029/222] fix --- udev_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udev_device.c b/udev_device.c index 841fcdd..2d00de9 100644 --- a/udev_device.c +++ b/udev_device.c @@ -525,7 +525,7 @@ UDEV_EXPORT struct udev_device *udev_device_new_from_subsystem_sysname(struct ud for (i = 0; fmt[i]; i++) { snprintf(path, sizeof(path), fmt[i], subsystem, sysname); - if (access(path, R_OK)) { + if (access(path, R_OK) == 0) { return udev_device_new_from_syspath(udev, path); } } From ce939476f75894a31674e1fcd1f2b239d87861ba Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 17 Jul 2020 07:47:23 +0300 Subject: [PATCH 030/222] update readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 3395f06..719135a 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ What Works * [x] libinput * [ ] wlroots - partially works. someone reported that mouse doesn't work * [ ] weston - should work. need test +* [ ] libusb - broken completely * [ ] kwin - fails to compile for odd reason * [ ] ??? From 20314c62569a3692454143ff39af5ac51fd788a1 Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 17 Jul 2020 07:53:32 +0300 Subject: [PATCH 031/222] add udev_hwdb --- Makefile | 1 + udev.h | 6 ++++++ udev_hwdb.c | 23 +++++++++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 udev_hwdb.c diff --git a/Makefile b/Makefile index 487bdb5..832c650 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,7 @@ XARFLAGS = -rc OBJ = \ udev.o \ + udev_hwdb.o \ udev_list.o \ udev_device.o \ udev_monitor.o \ diff --git a/udev.h b/udev.h index cbfb5ae..ed9d056 100644 --- a/udev.h +++ b/udev.h @@ -9,6 +9,7 @@ extern "C" { for (list_entry = first_entry; list_entry; list_entry = udev_list_entry_get_next(list_entry)) struct udev; +struct udev_hwdb; struct udev_device; struct udev_monitor; struct udev_enumerate; @@ -90,6 +91,11 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor); struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor); +struct udev_hwdb *udev_hwdb_new(struct udev *udev); +struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb); +struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb); +struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags); + #ifdef __cplusplus } #endif diff --git a/udev_hwdb.c b/udev_hwdb.c new file mode 100644 index 0000000..1582eb4 --- /dev/null +++ b/udev_hwdb.c @@ -0,0 +1,23 @@ +#include + +#include "udev.h" + +UDEV_EXPORT struct udev_hwdb *udev_hwdb_new(struct udev *udev) +{ + return NULL; +} + +UDEV_EXPORT struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb) +{ + return NULL; +} + +UDEV_EXPORT struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb) +{ + return NULL; +} + +UDEV_EXPORT struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags) +{ + return NULL; +} From 758ad07c26f1ee1341ca70fd15e11c71e5ca8bc9 Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 17 Jul 2020 21:36:59 +0300 Subject: [PATCH 032/222] change style --- udev.c | 3 +-- udev_device.c | 3 +-- udev_enumerate.c | 3 +-- udev_list.h | 3 +-- udev_monitor.c | 3 +-- 5 files changed, 5 insertions(+), 10 deletions(-) diff --git a/udev.c b/udev.c index d15bce5..f123cfc 100644 --- a/udev.c +++ b/udev.c @@ -2,8 +2,7 @@ #include "udev.h" -struct udev -{ +struct udev { int refcount; }; diff --git a/udev_device.c b/udev_device.c index 2d00de9..c28709f 100644 --- a/udev_device.c +++ b/udev_device.c @@ -12,8 +12,7 @@ #include "udev.h" #include "udev_list.h" -struct udev_device -{ +struct udev_device { struct udev_list_entry properties; struct udev_list_entry sysattrs; struct udev_device *parent; diff --git a/udev_enumerate.c b/udev_enumerate.c index 4e77720..1bb86fe 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -9,8 +9,7 @@ #include "udev.h" #include "udev_list.h" -struct udev_enumerate -{ +struct udev_enumerate { struct udev_list_entry subsystem_nomatch; struct udev_list_entry subsystem_match; struct udev_list_entry sysattr_nomatch; diff --git a/udev_list.h b/udev_list.h index 370f636..270bd14 100644 --- a/udev_list.h +++ b/udev_list.h @@ -1,5 +1,4 @@ -struct udev_list_entry -{ +struct udev_list_entry { struct udev_list_entry *next; char *value; char *name; diff --git a/udev_monitor.c b/udev_monitor.c index 1b5bb61..b943f0b 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -4,8 +4,7 @@ #include "udev.h" -struct udev_monitor -{ +struct udev_monitor { struct udev *udev; int refcount; int fd[2]; From 86d3dcab0fe844fb044bfdfb88ab5312b5ec9e16 Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 17 Jul 2020 23:04:36 +0300 Subject: [PATCH 033/222] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 719135a..5eeda67 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ What Works ---------- * [x] xorg-server * [x] libinput -* [ ] wlroots - partially works. someone reported that mouse doesn't work +* [x] wlroots * [ ] weston - should work. need test * [ ] libusb - broken completely * [ ] kwin - fails to compile for odd reason From 8a946ad9e6ac3474b75301604c86b0c5c4eb6a00 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 18 Jul 2020 05:15:00 +0300 Subject: [PATCH 034/222] drop UDEV_EXPORT --- Makefile | 6 ++--- udev.c | 6 ++--- udev.h | 1 - udev_device.c | 58 ++++++++++++++++++++++++------------------------ udev_enumerate.c | 34 ++++++++++++++-------------- udev_hwdb.c | 8 +++---- udev_list.c | 8 +++---- udev_monitor.c | 24 ++++++++++---------- 8 files changed, 71 insertions(+), 74 deletions(-) diff --git a/Makefile b/Makefile index 832c650..ab17fb7 100644 --- a/Makefile +++ b/Makefile @@ -3,10 +3,8 @@ PREFIX = /usr/local LIBDIR = ${PREFIX}/lib INCLUDEDIR = ${PREFIX}/include -XCFLAGS = ${CFLAGS} -std=c99 -fPIC -fvisibility=hidden \ - -D_POSIX_VERSION=200809L -D_XOPEN_SOURCE=700 \ - -Wall -Wextra -Wpedantic -Wmissing-prototypes \ - -Wstrict-prototypes -Wno-unused-parameter +XCFLAGS = ${CFLAGS} -std=c99 -fPIC -D_POSIX_VERSION=200809L -D_XOPEN_SOURCE=700 \ + -Wall -Wextra -Wpedantic -Wmissing-prototypes -Wstrict-prototypes -Wno-unused-parameter XLDFLAGS = ${LDFLAGS} -shared -Wl,-soname,libudev.so.1 XARFLAGS = -rc diff --git a/udev.c b/udev.c index f123cfc..0b4a3d0 100644 --- a/udev.c +++ b/udev.c @@ -6,7 +6,7 @@ struct udev { int refcount; }; -UDEV_EXPORT struct udev *udev_new(void) +struct udev *udev_new(void) { struct udev *udev; @@ -14,7 +14,7 @@ UDEV_EXPORT struct udev *udev_new(void) return udev; } -UDEV_EXPORT struct udev *udev_ref(struct udev *udev) +struct udev *udev_ref(struct udev *udev) { if (!udev) { return NULL; @@ -24,7 +24,7 @@ UDEV_EXPORT struct udev *udev_ref(struct udev *udev) return udev; } -UDEV_EXPORT struct udev *udev_unref(struct udev *udev) +struct udev *udev_unref(struct udev *udev) { if (!udev) { return NULL; diff --git a/udev.h b/udev.h index ed9d056..9ce8619 100644 --- a/udev.h +++ b/udev.h @@ -4,7 +4,6 @@ extern "C" { #endif -#define UDEV_EXPORT __attribute__ ((visibility("default"))) #define udev_list_entry_foreach(list_entry, first_entry) \ for (list_entry = first_entry; list_entry; list_entry = udev_list_entry_get_next(list_entry)) diff --git a/udev_device.c b/udev_device.c index c28709f..60194b2 100644 --- a/udev_device.c +++ b/udev_device.c @@ -20,7 +20,7 @@ struct udev_device { int refcount; }; -UDEV_EXPORT const char *udev_device_get_syspath(struct udev_device *udev_device) +const char *udev_device_get_syspath(struct udev_device *udev_device) { if (!udev_device) { return NULL; @@ -29,7 +29,7 @@ UDEV_EXPORT const char *udev_device_get_syspath(struct udev_device *udev_device) return udev_device_get_property_value(udev_device, "SYSPATH"); } -UDEV_EXPORT const char *udev_device_get_sysname(struct udev_device *udev_device) +const char *udev_device_get_sysname(struct udev_device *udev_device) { const char *sysname; @@ -48,7 +48,7 @@ UDEV_EXPORT const char *udev_device_get_sysname(struct udev_device *udev_device) return NULL; } -UDEV_EXPORT const char *udev_device_get_sysnum(struct udev_device *udev_device) +const char *udev_device_get_sysnum(struct udev_device *udev_device) { if (!udev_device) { return NULL; @@ -57,7 +57,7 @@ UDEV_EXPORT const char *udev_device_get_sysnum(struct udev_device *udev_device) return udev_device_get_property_value(udev_device, "SYSNUM"); } -UDEV_EXPORT const char *udev_device_get_devpath(struct udev_device *udev_device) +const char *udev_device_get_devpath(struct udev_device *udev_device) { if (!udev_device) { return NULL; @@ -66,7 +66,7 @@ UDEV_EXPORT const char *udev_device_get_devpath(struct udev_device *udev_device) return udev_device_get_property_value(udev_device, "DEVPATH"); } -UDEV_EXPORT const char *udev_device_get_devnode(struct udev_device *udev_device) +const char *udev_device_get_devnode(struct udev_device *udev_device) { if (!udev_device) { return NULL; @@ -75,7 +75,7 @@ UDEV_EXPORT const char *udev_device_get_devnode(struct udev_device *udev_device) return udev_device_get_property_value(udev_device, "DEVNODE"); } -UDEV_EXPORT dev_t udev_device_get_devnum(struct udev_device *udev_device) +dev_t udev_device_get_devnum(struct udev_device *udev_device) { const char *major, *minor; @@ -93,7 +93,7 @@ UDEV_EXPORT dev_t udev_device_get_devnum(struct udev_device *udev_device) return makedev(atoi(major), atoi(minor)); } -UDEV_EXPORT const char *udev_device_get_devtype(struct udev_device *udev_device) +const char *udev_device_get_devtype(struct udev_device *udev_device) { if (!udev_device) { return NULL; @@ -102,7 +102,7 @@ UDEV_EXPORT const char *udev_device_get_devtype(struct udev_device *udev_device) return udev_device_get_property_value(udev_device, "DEVTYPE"); } -UDEV_EXPORT const char *udev_device_get_subsystem(struct udev_device *udev_device) +const char *udev_device_get_subsystem(struct udev_device *udev_device) { if (!udev_device) { return NULL; @@ -111,7 +111,7 @@ UDEV_EXPORT const char *udev_device_get_subsystem(struct udev_device *udev_devic return udev_device_get_property_value(udev_device, "SUBSYSTEM"); } -UDEV_EXPORT const char *udev_device_get_driver(struct udev_device *udev_device) +const char *udev_device_get_driver(struct udev_device *udev_device) { if (!udev_device) { return NULL; @@ -120,12 +120,12 @@ UDEV_EXPORT const char *udev_device_get_driver(struct udev_device *udev_device) return udev_device_get_property_value(udev_device, "DRIVER"); } -UDEV_EXPORT struct udev *udev_device_get_udev(struct udev_device *udev_device) +struct udev *udev_device_get_udev(struct udev_device *udev_device) { return udev_device ? udev_device->udev : NULL; } -UDEV_EXPORT struct udev_device *udev_device_get_parent(struct udev_device *udev_device) +struct udev_device *udev_device_get_parent(struct udev_device *udev_device) { char *tmp, *path; @@ -151,7 +151,7 @@ UDEV_EXPORT struct udev_device *udev_device_get_parent(struct udev_device *udev_ return udev_device->parent; } -UDEV_EXPORT struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype) +struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype) { const char *parent_subsystem, *parent_devtype; struct udev_device *parent; @@ -182,45 +182,45 @@ UDEV_EXPORT struct udev_device *udev_device_get_parent_with_subsystem_devtype(st return NULL; } -UDEV_EXPORT int udev_device_get_is_initialized(struct udev_device *udev_device) +int udev_device_get_is_initialized(struct udev_device *udev_device) { return 1; } -UDEV_EXPORT const char *udev_device_get_action(struct udev_device *udev_device) +const char *udev_device_get_action(struct udev_device *udev_device) { return NULL; } -UDEV_EXPORT int udev_device_has_tag(struct udev_device *udev_device, const char *tag) +int udev_device_has_tag(struct udev_device *udev_device, const char *tag) { // XXX NOT IMPLEMENTED return 0; } -UDEV_EXPORT struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device) +struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device) { // XXX NOT IMPLEMENTED return NULL; } -UDEV_EXPORT struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device) +struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device) { 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) +struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device) { // XXX NOT IMPLEMENTED return NULL; } -UDEV_EXPORT struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device) +struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device) { 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) +const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key) { struct udev_list_entry *list_entry; @@ -228,7 +228,7 @@ UDEV_EXPORT const char *udev_device_get_property_value(struct udev_device *udev_ 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) +const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr) { struct udev_list_entry *list_entry; char data[1024], path[PATH_MAX]; @@ -268,7 +268,7 @@ UDEV_EXPORT const char *udev_device_get_sysattr_value(struct udev_device *udev_d return udev_list_entry_get_value(list_entry); } -UDEV_EXPORT int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, const char *value) +int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, const char *value) { char path[PATH_MAX]; struct stat st; @@ -441,7 +441,7 @@ static void udev_device_set_properties_from_ioctl(struct udev_device *udev_devic close(fd); } -UDEV_EXPORT struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) +struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) { char path[PATH_MAX], file[PATH_MAX + 7]; struct udev_device *udev_device; @@ -489,7 +489,7 @@ UDEV_EXPORT struct udev_device *udev_device_new_from_syspath(struct udev *udev, return udev_device; } -UDEV_EXPORT struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum) +struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum) { char path[PATH_MAX]; @@ -511,7 +511,7 @@ UDEV_EXPORT struct udev_device *udev_device_new_from_devnum(struct udev *udev, c return udev_device_new_from_syspath(udev, path); } -UDEV_EXPORT struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname) +struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname) { char *fmt[] = { "/sys/bus/%s/devices/%s", "/sys/class/%s/%s", NULL }; char path[PATH_MAX]; @@ -532,19 +532,19 @@ UDEV_EXPORT struct udev_device *udev_device_new_from_subsystem_sysname(struct ud return NULL; } -UDEV_EXPORT struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id) +struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id) { // XXX NOT IMPLEMENTED return NULL; } -UDEV_EXPORT struct udev_device *udev_device_new_from_environment(struct udev *udev) +struct udev_device *udev_device_new_from_environment(struct udev *udev) { // XXX NOT IMPLEMENTED return NULL; } -UDEV_EXPORT struct udev_device *udev_device_ref(struct udev_device *udev_device) +struct udev_device *udev_device_ref(struct udev_device *udev_device) { if (!udev_device) { return NULL; @@ -554,7 +554,7 @@ UDEV_EXPORT struct udev_device *udev_device_ref(struct udev_device *udev_device) return udev_device; } -UDEV_EXPORT struct udev_device *udev_device_unref(struct udev_device *udev_device) +struct udev_device *udev_device_unref(struct udev_device *udev_device) { if (!udev_device) { return NULL; diff --git a/udev_enumerate.c b/udev_enumerate.c index 1bb86fe..f37672f 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -21,7 +21,7 @@ struct udev_enumerate { int refcount; }; -UDEV_EXPORT int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) +int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) { if (!udev_enumerate || !subsystem) { return -1; @@ -30,7 +30,7 @@ UDEV_EXPORT int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_e return udev_list_entry_add(&udev_enumerate->subsystem_match, subsystem, NULL) ? 0 : -1; } -UDEV_EXPORT int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) +int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) { if (!udev_enumerate || !subsystem) { return -1; @@ -39,7 +39,7 @@ UDEV_EXPORT int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev return udev_list_entry_add(&udev_enumerate->subsystem_nomatch, subsystem, NULL) ? 0 : -1; } -UDEV_EXPORT int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) +int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) { if (!udev_enumerate || !sysattr) { return -1; @@ -48,7 +48,7 @@ UDEV_EXPORT int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enu return udev_list_entry_add(&udev_enumerate->sysattr_match, sysattr, value) ? 0 : -1; } -UDEV_EXPORT int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) +int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) { if (!udev_enumerate || !sysattr) { return -1; @@ -57,7 +57,7 @@ UDEV_EXPORT int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_e return udev_list_entry_add(&udev_enumerate->sysattr_nomatch, sysattr, value) ? 0 : -1; } -UDEV_EXPORT int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value) +int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value) { if (!udev_enumerate || !property) { return -1; @@ -66,7 +66,7 @@ UDEV_EXPORT int udev_enumerate_add_match_property(struct udev_enumerate *udev_en return udev_list_entry_add(&udev_enumerate->property_match, property, value) ? 0 : -1; } -UDEV_EXPORT int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname) +int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname) { if (!udev_enumerate || !sysname) { return -1; @@ -75,19 +75,19 @@ UDEV_EXPORT int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enu return udev_list_entry_add(&udev_enumerate->sysname_match, sysname, NULL) ? 0 : -1; } -UDEV_EXPORT int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag) +int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag) { // XXX NOT IMPLEMENTED return 0; } -UDEV_EXPORT int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent) +int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent) { // XXX NOT IMPLEMENTED return 0; } -UDEV_EXPORT int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate) +int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate) { return 0; } @@ -301,35 +301,35 @@ static void udev_enumerate_scan_dir(struct udev_enumerate *udev_enumerate, const closedir(dp); } -UDEV_EXPORT int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) +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) +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) +struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate) { 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) +int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath) { // XXX NOT IMPLEMENTED return 0; } -UDEV_EXPORT struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate) +struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate) { return udev_enumerate ? udev_enumerate->udev : NULL; } -UDEV_EXPORT struct udev_enumerate *udev_enumerate_new(struct udev *udev) +struct udev_enumerate *udev_enumerate_new(struct udev *udev) { struct udev_enumerate *udev_enumerate; @@ -357,7 +357,7 @@ UDEV_EXPORT struct udev_enumerate *udev_enumerate_new(struct udev *udev) return udev_enumerate; } -UDEV_EXPORT struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate) +struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate) { if (!udev_enumerate) { return NULL; @@ -367,7 +367,7 @@ UDEV_EXPORT struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *ude return udev_enumerate; } -UDEV_EXPORT struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate) +struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate) { if (!udev_enumerate) { return NULL; diff --git a/udev_hwdb.c b/udev_hwdb.c index 1582eb4..c76f479 100644 --- a/udev_hwdb.c +++ b/udev_hwdb.c @@ -2,22 +2,22 @@ #include "udev.h" -UDEV_EXPORT struct udev_hwdb *udev_hwdb_new(struct udev *udev) +struct udev_hwdb *udev_hwdb_new(struct udev *udev) { return NULL; } -UDEV_EXPORT struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb) +struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb) { return NULL; } -UDEV_EXPORT struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb) +struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb) { return NULL; } -UDEV_EXPORT struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags) +struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags) { return NULL; } diff --git a/udev_list.c b/udev_list.c index 248317a..d9adfdb 100644 --- a/udev_list.c +++ b/udev_list.c @@ -62,12 +62,12 @@ struct udev_list_entry *udev_list_entry_add(struct udev_list_entry *list_entry, return new; } -UDEV_EXPORT struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry) +struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry) { 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) +struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name) { struct udev_list_entry *tmp; @@ -88,12 +88,12 @@ UDEV_EXPORT struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list return NULL; } -UDEV_EXPORT const char *udev_list_entry_get_name(struct udev_list_entry *list_entry) +const char *udev_list_entry_get_name(struct udev_list_entry *list_entry) { return list_entry ? list_entry->name : NULL; } -UDEV_EXPORT const char *udev_list_entry_get_value(struct udev_list_entry *list_entry) +const char *udev_list_entry_get_value(struct udev_list_entry *list_entry) { return list_entry ? list_entry->value : NULL; } diff --git a/udev_monitor.c b/udev_monitor.c index b943f0b..1e88b70 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -10,52 +10,52 @@ struct udev_monitor { int fd[2]; }; -UDEV_EXPORT struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor) +struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor) { return (void *)1; } -UDEV_EXPORT int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) +int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) { return 0; } -UDEV_EXPORT int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size) +int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size) { return 0; } -UDEV_EXPORT int udev_monitor_get_fd(struct udev_monitor *udev_monitor) +int udev_monitor_get_fd(struct udev_monitor *udev_monitor) { return udev_monitor ? udev_monitor->fd[0] : -1; } -UDEV_EXPORT struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor) +struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor) { return udev_monitor ? udev_monitor->udev : NULL; } -UDEV_EXPORT int udev_monitor_filter_update(struct udev_monitor *udev_monitor) +int udev_monitor_filter_update(struct udev_monitor *udev_monitor) { return 0; } -UDEV_EXPORT int udev_monitor_filter_remove(struct udev_monitor *udev_monitor) +int udev_monitor_filter_remove(struct udev_monitor *udev_monitor) { return 0; } -UDEV_EXPORT int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor, const char *subsystem, const char *devtype) +int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor, const char *subsystem, const char *devtype) { return 0; } -UDEV_EXPORT int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag) +int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag) { return 0; } -UDEV_EXPORT struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name) +struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name) { struct udev_monitor *udev_monitor; int i; @@ -85,7 +85,7 @@ UDEV_EXPORT struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev return udev_monitor; } -UDEV_EXPORT struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor) +struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor) { if (!udev_monitor) { return NULL; @@ -95,7 +95,7 @@ UDEV_EXPORT struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_moni return udev_monitor; } -UDEV_EXPORT struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor) +struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor) { int i; From af7bbc8bece8434ed3e5c9183e410557296da783 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 18 Jul 2020 05:59:11 +0300 Subject: [PATCH 035/222] drop _POSIX_VERSION definition --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ab17fb7..92fda45 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ PREFIX = /usr/local LIBDIR = ${PREFIX}/lib INCLUDEDIR = ${PREFIX}/include -XCFLAGS = ${CFLAGS} -std=c99 -fPIC -D_POSIX_VERSION=200809L -D_XOPEN_SOURCE=700 \ +XCFLAGS = ${CFLAGS} -std=c99 -fPIC -D_XOPEN_SOURCE=700 \ -Wall -Wextra -Wpedantic -Wmissing-prototypes -Wstrict-prototypes -Wno-unused-parameter XLDFLAGS = ${LDFLAGS} -shared -Wl,-soname,libudev.so.1 XARFLAGS = -rc From df1b1b43193bb5c1b81183f1bb8631793e514af0 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 18 Jul 2020 18:28:33 +0300 Subject: [PATCH 036/222] add CPPFLAGS --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 92fda45..1553e72 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ PREFIX = /usr/local LIBDIR = ${PREFIX}/lib INCLUDEDIR = ${PREFIX}/include -XCFLAGS = ${CFLAGS} -std=c99 -fPIC -D_XOPEN_SOURCE=700 \ +XCFLAGS = ${CPPFLAGS} ${CFLAGS} -std=c99 -fPIC -D_XOPEN_SOURCE=700 \ -Wall -Wextra -Wpedantic -Wmissing-prototypes -Wstrict-prototypes -Wno-unused-parameter XLDFLAGS = ${LDFLAGS} -shared -Wl,-soname,libudev.so.1 XARFLAGS = -rc From df1daa9f8b445cc2516dc7f9663e9e4966ba5511 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 19 Jul 2020 03:13:35 +0300 Subject: [PATCH 037/222] add donation link --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5eeda67..ea1e47e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![Donate with Bitcoin](https://en.cryptobadges.io/badge/micro/1BwrcsgtWZeLVvNeEQSg4A28a3yrGN3FpK)](https://en.cryptobadges.io/donate/1BwrcsgtWZeLVvNeEQSg4A28a3yrGN3FpK) + libudev-zero ============ From f20aaf258ecc0f438698da04a0dd60446b7ad0a9 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 19 Jul 2020 21:55:42 +0300 Subject: [PATCH 038/222] update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ea1e47e..813f0a7 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ What Works * [x] xorg-server * [x] libinput * [x] wlroots -* [ ] weston - should work. need test +* [x] weston * [ ] libusb - broken completely -* [ ] kwin - fails to compile for odd reason +* [x] kwin - [fix](https://github.com/dilyn-corner/KISS-kde/commit/0cc72748e46f859a0fced55b0c3fcc1dd9586a38) * [ ] ??? TODO From 1f3d92132ddbbbd89b2071b19dd8a996d70751ed Mon Sep 17 00:00:00 2001 From: illiliti Date: Mon, 20 Jul 2020 01:01:02 +0300 Subject: [PATCH 039/222] update readme --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index 813f0a7..78663e9 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,22 @@ What Works * [x] kwin - [fix](https://github.com/dilyn-corner/KISS-kde/commit/0cc72748e46f859a0fced55b0c3fcc1dd9586a38) * [ ] ??? +Dependencies +------------ + +* C99 compiler (build time) +* POSIX make (build time) +* POSIX & XSI libc +* Linux >= 2.6.39 + +Installation +------------ + +```sh +make +make PREFIX=/usr install # overwrites existing udev libraries if any +``` + TODO ---- From 60336bcf3b22dea2380a40f710c4432773c87a4d Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 22 Jul 2020 21:04:31 +0300 Subject: [PATCH 040/222] add missing include --- udev.h | 1 + 1 file changed, 1 insertion(+) diff --git a/udev.h b/udev.h index 9ce8619..b8b2454 100644 --- a/udev.h +++ b/udev.h @@ -1,4 +1,5 @@ #include +#include #ifdef __cplusplus extern "C" { From 92901c5b24fc3b35632a322c98444f66e2f9ed94 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 22 Jul 2020 21:19:50 +0300 Subject: [PATCH 041/222] update readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 78663e9..45e8768 100644 --- a/README.md +++ b/README.md @@ -34,5 +34,6 @@ make PREFIX=/usr install # overwrites existing udev libraries if any TODO ---- +* [ ] speed up performance * [ ] implement hotplugging support * [x] remove [dirty hack](https://github.com/illiliti/libudev-zero/blob/e76f9b282442505bd6b0b08b411679aae1581fa5/udev_device.c#L383). use ioctl() From 28ff928699d9e3d8fcf15f0885f872e8ed1aa731 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 25 Jul 2020 16:23:46 +0300 Subject: [PATCH 042/222] split --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1553e72..fd8a60d 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,8 @@ PREFIX = /usr/local LIBDIR = ${PREFIX}/lib INCLUDEDIR = ${PREFIX}/include XCFLAGS = ${CPPFLAGS} ${CFLAGS} -std=c99 -fPIC -D_XOPEN_SOURCE=700 \ - -Wall -Wextra -Wpedantic -Wmissing-prototypes -Wstrict-prototypes -Wno-unused-parameter + -Wall -Wextra -Wpedantic -Wmissing-prototypes -Wstrict-prototypes \ + -Wno-unused-parameter XLDFLAGS = ${LDFLAGS} -shared -Wl,-soname,libudev.so.1 XARFLAGS = -rc From c7cc417701d0c30bb13ff205d6491a74f0804a6e Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 25 Jul 2020 16:38:59 +0300 Subject: [PATCH 043/222] simplify --- udev_device.c | 47 +++++++++++------------------------------------ 1 file changed, 11 insertions(+), 36 deletions(-) diff --git a/udev_device.c b/udev_device.c index 60194b2..aab14f0 100644 --- a/udev_device.c +++ b/udev_device.c @@ -37,15 +37,13 @@ const char *udev_device_get_sysname(struct udev_device *udev_device) return NULL; } - if ((sysname = udev_device_get_property_value(udev_device, "DEVNAME"))) { - return sysname; + sysname = udev_device_get_devpath(udev_device); + + if (!sysname) { + return NULL; } - if ((sysname = udev_device_get_devpath(udev_device))) { - return strrchr(sysname, '/') + 1; - } - - return NULL; + return strrchr(sysname, '/') + 1; } const char *udev_device_get_sysnum(struct udev_device *udev_device) @@ -72,7 +70,7 @@ const char *udev_device_get_devnode(struct udev_device *udev_device) return NULL; } - return udev_device_get_property_value(udev_device, "DEVNODE"); + return udev_device_get_property_value(udev_device, "DEVNAME"); } dev_t udev_device_get_devnum(struct udev_device *udev_device) @@ -316,7 +314,7 @@ static const char *udev_device_read_symlink(struct udev_device *udev_device, con static void udev_device_set_properties_from_uevent(struct udev_device *udev_device) { char *key, *val, line[1024], path[PATH_MAX]; - char *sysname, devnode[PATH_MAX]; + char devnode[PATH_MAX]; FILE *file; int i; @@ -332,38 +330,15 @@ static void udev_device_set_properties_from_uevent(struct udev_device *udev_devi line[strcspn(line, "\n")] = '\0'; 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); + for (i = 8; line[i] != '\0'; i++) { + if (line[i] >= '0' && line[i] <= '9') { + udev_list_entry_add(&udev_device->properties, "SYSNUM", line + i); break; } } snprintf(devnode, sizeof(devnode), "/dev/%s", line + 8); - udev_list_entry_add(&udev_device->properties, "DEVNODE", 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); + udev_list_entry_add(&udev_device->properties, "DEVNAME", devnode); } else if (strchr(line, '=')) { val = strchr(line, '=') + 1; From d4a60c10c0248aa5bea65057ddd29f9b831be20c Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 25 Jul 2020 16:41:10 +0300 Subject: [PATCH 044/222] use readlink --- udev_device.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/udev_device.c b/udev_device.c index aab14f0..fb6387b 100644 --- a/udev_device.c +++ b/udev_device.c @@ -301,13 +301,17 @@ int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *s static const char *udev_device_read_symlink(struct udev_device *udev_device, const char *name) { char link[PATH_MAX], path[PATH_MAX]; + ssize_t len; snprintf(path, sizeof(path), "%s/%s", udev_device_get_syspath(udev_device), name); - if (!realpath(path, link)) { + len = readlink(path, link, sizeof(link)); + + if (len == -1) { return NULL; } + link[len] = '\0'; return strrchr(link, '/') + 1; } From d05676f2322c70e1dadbe863eab03c968494a2d1 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 25 Jul 2020 16:44:17 +0300 Subject: [PATCH 045/222] drop O_NOFOLLOW --- udev_device.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/udev_device.c b/udev_device.c index fb6387b..df8a609 100644 --- a/udev_device.c +++ b/udev_device.c @@ -245,11 +245,11 @@ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const snprintf(path, sizeof(path), "%s/%s", udev_device_get_syspath(udev_device), sysattr); - if (stat(path, &st) != 0 || S_ISDIR(st.st_mode)) { + if (lstat(path, &st) != 0 || !S_ISREG(st.st_mode)) { return NULL; } - fd = open(path, O_RDONLY | O_NOFOLLOW); + fd = open(path, O_RDONLY); if (fd == -1) { return NULL; @@ -278,11 +278,11 @@ int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *s snprintf(path, sizeof(path), "%s/%s", udev_device_get_syspath(udev_device), sysattr); - if (stat(path, &st) != 0 || S_ISDIR(st.st_mode)) { + if (lstat(path, &st) != 0 || !S_ISREG(st.st_mode)) { return -1; } - fd = open(path, O_WRONLY | O_NOFOLLOW); + fd = open(path, O_WRONLY); if (fd == -1) { return -1; From 984295b4a09760c2e1de6261c34e5d53cf16d04a Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 25 Jul 2020 17:42:47 +0300 Subject: [PATCH 046/222] minor fixes --- udev_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/udev_device.c b/udev_device.c index df8a609..ee6da8a 100644 --- a/udev_device.c +++ b/udev_device.c @@ -430,11 +430,11 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * return NULL; } - if (!realpath(syspath, path)) { + if (stat(syspath, &st) != 0 || !S_ISDIR(st.st_mode)) { return NULL; } - if (stat(path, &st) != 0 || S_ISDIR(st.st_mode) == 0) { + if (!realpath(syspath, path)) { return NULL; } From b9ab0e2fe9578047212ba7f4a7c59d6d1b8d493e Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 25 Jul 2020 17:48:37 +0300 Subject: [PATCH 047/222] use limits constants instead of hardcoded ones --- udev_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/udev_device.c b/udev_device.c index ee6da8a..5844d0b 100644 --- a/udev_device.c +++ b/udev_device.c @@ -229,7 +229,7 @@ const char *udev_device_get_property_value(struct udev_device *udev_device, cons const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr) { struct udev_list_entry *list_entry; - char data[1024], path[PATH_MAX]; + char data[BUFSIZ], path[PATH_MAX]; struct stat st; int fd; @@ -317,8 +317,8 @@ static const char *udev_device_read_symlink(struct udev_device *udev_device, con static void udev_device_set_properties_from_uevent(struct udev_device *udev_device) { - char *key, *val, line[1024], path[PATH_MAX]; - char devnode[PATH_MAX]; + char line[LINE_MAX], path[PATH_MAX]; + char *key, *val, devnode[PATH_MAX]; FILE *file; int i; From a5d5e4dd2b2f9611cec337c08225f9c42f7d0978 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 26 Jul 2020 12:34:43 +0300 Subject: [PATCH 048/222] fix gcc 10 --- udev.c | 6 ++++++ udev_device.c | 21 +++++++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/udev.c b/udev.c index 0b4a3d0..57cf4c8 100644 --- a/udev.c +++ b/udev.c @@ -11,6 +11,12 @@ struct udev *udev_new(void) struct udev *udev; udev = calloc(1, sizeof(struct udev)); + + if (!udev) { + return NULL; + } + + udev->refcount = 1; return udev; } diff --git a/udev_device.c b/udev_device.c index 5844d0b..0e00c33 100644 --- a/udev_device.c +++ b/udev_device.c @@ -298,7 +298,7 @@ int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *s return 0; } -static const char *udev_device_read_symlink(struct udev_device *udev_device, const char *name) +static char *udev_device_read_symlink(struct udev_device *udev_device, const char *name) { char link[PATH_MAX], path[PATH_MAX]; ssize_t len; @@ -312,7 +312,7 @@ static const char *udev_device_read_symlink(struct udev_device *udev_device, con } link[len] = '\0'; - return strrchr(link, '/') + 1; + return strdup(strrchr(link, '/') + 1); } static void udev_device_set_properties_from_uevent(struct udev_device *udev_device) @@ -424,6 +424,7 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * { char path[PATH_MAX], file[PATH_MAX + 7]; struct udev_device *udev_device; + char *subsystem, *driver; struct stat st; if (!udev || !syspath) { @@ -459,8 +460,20 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * 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")); + + subsystem = udev_device_read_symlink(udev_device, "subsystem"); + + if (subsystem) { + udev_list_entry_add(&udev_device->properties, "SUBSYSTEM", subsystem); + free(subsystem); + } + + driver = udev_device_read_symlink(udev_device, "driver"); + + if (driver) { + udev_list_entry_add(&udev_device->properties, "DRIVER", driver); + free(driver); + } udev_device_set_properties_from_uevent(udev_device); udev_device_set_properties_from_ioctl(udev_device); From f63ec4a2e74ae1188422e53ca0eff9330f73af2d Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 26 Jul 2020 15:49:15 +0300 Subject: [PATCH 049/222] minor changes --- udev_device.c | 42 ++++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/udev_device.c b/udev_device.c index 0e00c33..09628e5 100644 --- a/udev_device.c +++ b/udev_device.c @@ -31,19 +31,11 @@ const char *udev_device_get_syspath(struct udev_device *udev_device) const char *udev_device_get_sysname(struct udev_device *udev_device) { - const char *sysname; - if (!udev_device) { return NULL; } - sysname = udev_device_get_devpath(udev_device); - - if (!sysname) { - return NULL; - } - - return strrchr(sysname, '/') + 1; + return udev_device_get_property_value(udev_device, "SYSNAME"); } const char *udev_device_get_sysnum(struct udev_device *udev_device) @@ -320,7 +312,6 @@ static void udev_device_set_properties_from_uevent(struct udev_device *udev_devi char line[LINE_MAX], path[PATH_MAX]; char *key, *val, devnode[PATH_MAX]; FILE *file; - int i; snprintf(path, sizeof(path), "%s/uevent", udev_device_get_syspath(udev_device)); @@ -334,13 +325,6 @@ static void udev_device_set_properties_from_uevent(struct udev_device *udev_devi line[strcspn(line, "\n")] = '\0'; if (strncmp(line, "DEVNAME", 7) == 0) { - for (i = 8; line[i] != '\0'; i++) { - if (line[i] >= '0' && line[i] <= '9') { - udev_list_entry_add(&udev_device->properties, "SYSNUM", line + i); - break; - } - } - snprintf(devnode, sizeof(devnode), "/dev/%s", line + 8); udev_list_entry_add(&udev_device->properties, "DEVNAME", devnode); } @@ -423,15 +407,17 @@ static void udev_device_set_properties_from_ioctl(struct udev_device *udev_devic struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) { char path[PATH_MAX], file[PATH_MAX + 7]; + char *subsystem, *driver, *sysname; struct udev_device *udev_device; - char *subsystem, *driver; - struct stat st; + int i; if (!udev || !syspath) { return NULL; } - if (stat(syspath, &st) != 0 || !S_ISDIR(st.st_mode)) { + snprintf(file, sizeof(file), "%s/uevent", syspath); + + if (access(file, R_OK) == -1) { return NULL; } @@ -439,12 +425,6 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * return NULL; } - snprintf(file, sizeof(file), "%s/uevent", path); - - if (access(file, R_OK) == -1) { - return NULL; - } - udev_device = calloc(1, sizeof(struct udev_device)); if (!udev_device) { @@ -461,6 +441,16 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * udev_list_entry_add(&udev_device->properties, "SYSPATH", path); udev_list_entry_add(&udev_device->properties, "DEVPATH", path + 4); + sysname = strrchr(path, '/') + 1; + udev_list_entry_add(&udev_device->properties, "SYSNAME", 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; + } + } + subsystem = udev_device_read_symlink(udev_device, "subsystem"); if (subsystem) { From 56537c691ae6c3a571e564f0c580557525f938a2 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 26 Jul 2020 18:50:42 +0300 Subject: [PATCH 050/222] no need --- udev_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udev_device.c b/udev_device.c index 09628e5..2c73054 100644 --- a/udev_device.c +++ b/udev_device.c @@ -406,7 +406,7 @@ static void udev_device_set_properties_from_ioctl(struct udev_device *udev_devic struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) { - char path[PATH_MAX], file[PATH_MAX + 7]; + char path[PATH_MAX], file[PATH_MAX]; char *subsystem, *driver, *sysname; struct udev_device *udev_device; int i; From e988d6f67cea8986d3ffbd7961ab51216951b7c3 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 28 Jul 2020 12:42:40 +0300 Subject: [PATCH 051/222] implement pthreads before - 3.870 total after - 2.964 total not really big difference, huh ? --- Makefile | 2 +- udev_enumerate.c | 142 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 99 insertions(+), 45 deletions(-) diff --git a/Makefile b/Makefile index fd8a60d..4c75ca3 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ PREFIX = /usr/local LIBDIR = ${PREFIX}/lib INCLUDEDIR = ${PREFIX}/include -XCFLAGS = ${CPPFLAGS} ${CFLAGS} -std=c99 -fPIC -D_XOPEN_SOURCE=700 \ +XCFLAGS = ${CPPFLAGS} ${CFLAGS} -std=c99 -fPIC -pthread -D_XOPEN_SOURCE=700 \ -Wall -Wextra -Wpedantic -Wmissing-prototypes -Wstrict-prototypes \ -Wno-unused-parameter XLDFLAGS = ${LDFLAGS} -shared -Wl,-soname,libudev.so.1 diff --git a/udev_enumerate.c b/udev_enumerate.c index f37672f..2a2e214 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "udev.h" #include "udev_list.h" @@ -21,6 +21,13 @@ struct udev_enumerate { int refcount; }; +struct udev_enumerate_thread { + struct udev_enumerate *udev_enumerate; + pthread_mutex_t *mutex; + char *name; + char *path; +}; + int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) { if (!udev_enumerate || !subsystem) { @@ -241,69 +248,116 @@ static int udev_enumerate_filter_sysattr(struct udev_enumerate *udev_enumerate, return 1; } -static void udev_enumerate_add_device(struct udev_enumerate *udev_enumerate, const char type, dev_t devnum) +static void *udev_enumerate_add_device(void *ptr) { + struct udev_enumerate_thread *data = ptr; struct udev_device *udev_device; + char path[PATH_MAX]; - udev_device = udev_device_new_from_devnum(udev_enumerate->udev, type, devnum); + snprintf(path, sizeof(path), "%s/%s", data->path, data->name); + udev_device = udev_device_new_from_syspath(data->udev_enumerate->udev, path); if (!udev_device) { - return; + return NULL; } - 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)) { + if (!udev_enumerate_filter_subsystem(data->udev_enumerate, udev_device) || + !udev_enumerate_filter_sysname(data->udev_enumerate, udev_device) || + !udev_enumerate_filter_property(data->udev_enumerate, udev_device) || + !udev_enumerate_filter_sysattr(data->udev_enumerate, udev_device)) { udev_device_unref(udev_device); - return; + return NULL; } - udev_list_entry_add(&udev_enumerate->devices, udev_device_get_syspath(udev_device), NULL); + pthread_mutex_lock(data->mutex); + udev_list_entry_add(&data->udev_enumerate->devices, udev_device_get_syspath(udev_device), NULL); + pthread_mutex_unlock(data->mutex); + udev_device_unref(udev_device); + return NULL; } -static void udev_enumerate_scan_dir(struct udev_enumerate *udev_enumerate, const char *path) +static int udev_enumerate_filter_dots(const struct dirent *de) { - char file[PATH_MAX]; - struct dirent *de; - struct stat st; - DIR *dp; - - dp = opendir(path); - - if (!dp) { - return; + if (strcmp(de->d_name, ".") == 0 || + strcmp(de->d_name, "..") == 0) { + return 0; } - while ((de = readdir(dp))) { - if (strcmp(de->d_name, ".") == 0 || - strcmp(de->d_name, "..") == 0) { - continue; - } - - snprintf(file, sizeof(file), "%s/%s", path, de->d_name); - - 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, 'b', st.st_rdev); - } - else if (S_ISCHR(st.st_mode)) { - udev_enumerate_add_device(udev_enumerate, 'c', st.st_rdev); - } - } - - closedir(dp); + return 1; } int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) { - udev_enumerate_scan_dir(udev_enumerate, "/dev"); + char *path[] = { "/sys/dev/block", "/sys/dev/char", NULL }; + struct udev_enumerate_thread *data; + pthread_mutex_t *mutex; + struct dirent **de; + pthread_t *thread; + int len, i, u; + + mutex = malloc(sizeof(pthread_mutex_t)); + + if (!mutex) { + return -1; + } + + pthread_mutex_init(mutex, NULL); + + for (i = 0; path[i]; i++) { + len = scandir(path[i], &de, udev_enumerate_filter_dots, NULL); + + if (len == -1) { + continue; + } + + thread = calloc(len, sizeof(pthread_t)); + + if (!thread) { + for (u = 0; u < len; u++) { + free(de[u]); + } + + free(de); + continue; + } + + data = calloc(len, sizeof(struct udev_enumerate_thread)); + + if (!data) { + for (u = 0; u < len; u++) { + free(de[u]); + } + + free(thread); + free(de); + continue; + } + + for (u = 0; u < len; u++) { + data[u].path = path[i]; + data[u].name = de[u]->d_name; + data[u].mutex = mutex; + data[u].udev_enumerate = udev_enumerate; + + pthread_create(&thread[u], NULL, udev_enumerate_add_device, &data[u]); + } + + for (u = 0; u < len; u++) { + pthread_join(thread[u], NULL); + } + + for (u = 0; u < len; u++) { + free(de[u]); + } + + free(de); + free(data); + free(thread); + } + + pthread_mutex_destroy(mutex); + free(mutex); return 0; } From 22317403803f4176589e20c3d4bc5e856bbc1361 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 28 Jul 2020 19:45:36 +0300 Subject: [PATCH 052/222] use static allocation --- udev_enumerate.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/udev_enumerate.c b/udev_enumerate.c index 2a2e214..da3c51e 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -291,18 +291,12 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) { char *path[] = { "/sys/dev/block", "/sys/dev/char", NULL }; struct udev_enumerate_thread *data; - pthread_mutex_t *mutex; + pthread_mutex_t mutex; struct dirent **de; pthread_t *thread; int len, i, u; - mutex = malloc(sizeof(pthread_mutex_t)); - - if (!mutex) { - return -1; - } - - pthread_mutex_init(mutex, NULL); + pthread_mutex_init(&mutex, NULL); for (i = 0; path[i]; i++) { len = scandir(path[i], &de, udev_enumerate_filter_dots, NULL); @@ -334,10 +328,11 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) continue; } + // TODO do we really need structure for every thread ? for (u = 0; u < len; u++) { data[u].path = path[i]; data[u].name = de[u]->d_name; - data[u].mutex = mutex; + data[u].mutex = &mutex; data[u].udev_enumerate = udev_enumerate; pthread_create(&thread[u], NULL, udev_enumerate_add_device, &data[u]); @@ -356,8 +351,7 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) free(thread); } - pthread_mutex_destroy(mutex); - free(mutex); + pthread_mutex_destroy(&mutex); return 0; } From 052dfec0d253b1aae76d425d814f637d40eb78e5 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 28 Jul 2020 20:05:59 +0300 Subject: [PATCH 053/222] update readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 45e8768..b1f8bf0 100644 --- a/README.md +++ b/README.md @@ -35,5 +35,7 @@ TODO ---- * [ ] speed up performance + - [x] threads + - [ ] deferred plugging via udev_monitor_receive_device() * [ ] implement hotplugging support * [x] remove [dirty hack](https://github.com/illiliti/libudev-zero/blob/e76f9b282442505bd6b0b08b411679aae1581fa5/udev_device.c#L383). use ioctl() From 60fd0bb19b5e7ec34bb21e69039e04badd83ac8b Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 28 Jul 2020 20:12:14 +0300 Subject: [PATCH 054/222] update readme --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b1f8bf0..c0fa69e 100644 --- a/README.md +++ b/README.md @@ -34,8 +34,9 @@ make PREFIX=/usr install # overwrites existing udev libraries if any TODO ---- -* [ ] speed up performance +* [ ] speed up udev_enumerate_scan_devices() - [x] threads - [ ] deferred plugging via udev_monitor_receive_device() + - ~~[ ] caching~~ impossible to implement * [ ] implement hotplugging support * [x] remove [dirty hack](https://github.com/illiliti/libudev-zero/blob/e76f9b282442505bd6b0b08b411679aae1581fa5/udev_device.c#L383). use ioctl() From 16a99644ad0d4245e789bbabf17d60bdc9525c55 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 28 Jul 2020 20:13:09 +0300 Subject: [PATCH 055/222] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c0fa69e..c5dc0ff 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,6 @@ TODO * [ ] speed up udev_enumerate_scan_devices() - [x] threads - [ ] deferred plugging via udev_monitor_receive_device() - - ~~[ ] caching~~ impossible to implement + ~~- [ ] caching~~ impossible to implement * [ ] implement hotplugging support * [x] remove [dirty hack](https://github.com/illiliti/libudev-zero/blob/e76f9b282442505bd6b0b08b411679aae1581fa5/udev_device.c#L383). use ioctl() From 89f33b8d9ce712f699a6bd82fab0447e737c0eb1 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 28 Jul 2020 20:13:36 +0300 Subject: [PATCH 056/222] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c5dc0ff..56bffc6 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,6 @@ TODO * [ ] speed up udev_enumerate_scan_devices() - [x] threads - [ ] deferred plugging via udev_monitor_receive_device() - ~~- [ ] caching~~ impossible to implement + - [ ] ~~caching~~ impossible to implement * [ ] implement hotplugging support * [x] remove [dirty hack](https://github.com/illiliti/libudev-zero/blob/e76f9b282442505bd6b0b08b411679aae1581fa5/udev_device.c#L383). use ioctl() From 1e7ec603bca368c2dd37c2e72704b5743f088129 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 28 Jul 2020 20:51:01 +0300 Subject: [PATCH 057/222] do udev_device_unref before lock --- udev_enumerate.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/udev_enumerate.c b/udev_enumerate.c index da3c51e..ab03487 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -269,11 +269,13 @@ static void *udev_enumerate_add_device(void *ptr) return NULL; } + snprintf(path, sizeof(path), "%s", udev_device_get_syspath(udev_device)); + udev_device_unref(udev_device); + pthread_mutex_lock(data->mutex); - udev_list_entry_add(&data->udev_enumerate->devices, udev_device_get_syspath(udev_device), NULL); + udev_list_entry_add(&data->udev_enumerate->devices, path, NULL); pthread_mutex_unlock(data->mutex); - udev_device_unref(udev_device); return NULL; } From f96a573155d7ef7fd9ec6d50e28f794499d3f61e Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 28 Jul 2020 21:38:57 +0300 Subject: [PATCH 058/222] simplify error handling --- udev_enumerate.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/udev_enumerate.c b/udev_enumerate.c index ab03487..9921728 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -307,27 +307,18 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) continue; } + data = calloc(len, sizeof(struct udev_enumerate_thread)); thread = calloc(len, sizeof(pthread_t)); - if (!thread) { - for (u = 0; u < len; u++) { - free(de[u]); - } - - free(de); - continue; - } - - data = calloc(len, sizeof(struct udev_enumerate_thread)); - - if (!data) { + if (!data || !thread) { for (u = 0; u < len; u++) { free(de[u]); } free(thread); + free(data); free(de); - continue; + return -1; } // TODO do we really need structure for every thread ? From eea8f66e769be0e6bb09c1a87feb758cd3847dab Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 29 Jul 2020 11:56:29 +0300 Subject: [PATCH 059/222] further simplify --- udev_enumerate.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/udev_enumerate.c b/udev_enumerate.c index 9921728..e46474f 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -24,6 +24,7 @@ struct udev_enumerate { struct udev_enumerate_thread { struct udev_enumerate *udev_enumerate; pthread_mutex_t *mutex; + pthread_t thread; char *name; char *path; }; @@ -295,7 +296,6 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) struct udev_enumerate_thread *data; pthread_mutex_t mutex; struct dirent **de; - pthread_t *thread; int len, i, u; pthread_mutex_init(&mutex, NULL); @@ -308,15 +308,12 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) } data = calloc(len, sizeof(struct udev_enumerate_thread)); - thread = calloc(len, sizeof(pthread_t)); - if (!data || !thread) { + if (!data) { for (u = 0; u < len; u++) { free(de[u]); } - free(thread); - free(data); free(de); return -1; } @@ -328,11 +325,11 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) data[u].mutex = &mutex; data[u].udev_enumerate = udev_enumerate; - pthread_create(&thread[u], NULL, udev_enumerate_add_device, &data[u]); + pthread_create(&data[u].thread, NULL, udev_enumerate_add_device, &data[u]); } for (u = 0; u < len; u++) { - pthread_join(thread[u], NULL); + pthread_join(data[u].thread, NULL); } for (u = 0; u < len; u++) { @@ -341,7 +338,6 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) free(de); free(data); - free(thread); } pthread_mutex_destroy(&mutex); From edaf268cacf7e1afda0ab2e6db53aa433fb4ce27 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 29 Jul 2020 12:09:11 +0300 Subject: [PATCH 060/222] const char where possible --- udev_device.c | 2 +- udev_enumerate.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/udev_device.c b/udev_device.c index 2c73054..39045c4 100644 --- a/udev_device.c +++ b/udev_device.c @@ -495,7 +495,7 @@ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, de struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname) { - char *fmt[] = { "/sys/bus/%s/devices/%s", "/sys/class/%s/%s", NULL }; + const char *fmt[] = { "/sys/bus/%s/devices/%s", "/sys/class/%s/%s", NULL }; char path[PATH_MAX]; int i; diff --git a/udev_enumerate.c b/udev_enumerate.c index e46474f..86c9cf3 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -25,8 +25,8 @@ struct udev_enumerate_thread { struct udev_enumerate *udev_enumerate; pthread_mutex_t *mutex; pthread_t thread; - char *name; - char *path; + const char *name; + const char *path; }; int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) @@ -292,7 +292,7 @@ static int udev_enumerate_filter_dots(const struct dirent *de) int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) { - char *path[] = { "/sys/dev/block", "/sys/dev/char", NULL }; + const char *path[] = { "/sys/dev/block", "/sys/dev/char", NULL }; struct udev_enumerate_thread *data; pthread_mutex_t mutex; struct dirent **de; From 9b7641d9ece05083716c0c9ccba91a65b29b80b4 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 29 Jul 2020 12:27:40 +0300 Subject: [PATCH 061/222] do not handle unique values when no need --- udev_device.c | 36 ++++++++++++++++++------------------ udev_enumerate.c | 14 +++++++------- udev_list.c | 18 ++++++++++-------- udev_list.h | 2 +- 4 files changed, 36 insertions(+), 34 deletions(-) diff --git a/udev_device.c b/udev_device.c index 39045c4..8868023 100644 --- a/udev_device.c +++ b/udev_device.c @@ -254,7 +254,7 @@ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const close(fd); data[strcspn(data, "\n")] = '\0'; - list_entry = udev_list_entry_add(&udev_device->sysattrs, sysattr, data); + list_entry = udev_list_entry_add(&udev_device->sysattrs, sysattr, data, 0); return udev_list_entry_get_value(list_entry); } @@ -286,7 +286,7 @@ int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *s } close(fd); - udev_list_entry_add(&udev_device->sysattrs, sysattr, value); + udev_list_entry_add(&udev_device->sysattrs, sysattr, value, 1); return 0; } @@ -326,14 +326,14 @@ static void udev_device_set_properties_from_uevent(struct udev_device *udev_devi if (strncmp(line, "DEVNAME", 7) == 0) { snprintf(devnode, sizeof(devnode), "/dev/%s", line + 8); - udev_list_entry_add(&udev_device->properties, "DEVNAME", devnode); + udev_list_entry_add(&udev_device->properties, "DEVNAME", devnode, 0); } else if (strchr(line, '=')) { val = strchr(line, '=') + 1; key = line; key[strcspn(key, "=")] = '\0'; - udev_list_entry_add(&udev_device->properties, key, val); + udev_list_entry_add(&udev_device->properties, key, val, 1); } } @@ -357,7 +357,7 @@ static void udev_device_set_properties_from_ioctl(struct udev_device *udev_devic return; } - udev_list_entry_add(&udev_device->properties, "ID_INPUT", "1"); + udev_list_entry_add(&udev_device->properties, "ID_INPUT", "1", 0); fd = open(udev_device_get_devnode(udev_device), O_RDONLY); @@ -374,30 +374,30 @@ static void udev_device_set_properties_from_ioctl(struct udev_device *udev_devic } if (test_bit(bits, EV_SW)) { - udev_list_entry_add(&udev_device->properties, "ID_INPUT_SWITCH", "1"); + udev_list_entry_add(&udev_device->properties, "ID_INPUT_SWITCH", "1", 0); } if (test_bit(bits, EV_KEY) && test_bit(key_bits, KEY_ENTER)) { - udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEY", "1"); - udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEYBOARD", "1"); + udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEY", "1", 0); + udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEYBOARD", "1", 0); } if (test_bit(bits, EV_REL) && test_bit(rel_bits, REL_Y) && test_bit(rel_bits, REL_X) && test_bit(key_bits, BTN_MOUSE)) { - udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1"); + udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1", 0); } if (test_bit(bits, EV_ABS) && test_bit(abs_bits, ABS_Y) && test_bit(abs_bits, ABS_X)) { if (test_bit(key_bits, BTN_TOUCH) && !test_bit(key_bits, BTN_TOOL_PEN)) { if (test_bit(key_bits, BTN_TOOL_FINGER)) { - udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHPAD", "1"); + udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHPAD", "1", 0); } else { - udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHSCREEN", "1"); + udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHSCREEN", "1", 0); } } else if (test_bit(key_bits, BTN_MOUSE)) { - udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1"); + udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1", 0); } } @@ -438,15 +438,15 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * udev_list_entry_init(&udev_device->properties); udev_list_entry_init(&udev_device->sysattrs); - 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, "SYSPATH", path, 0); + udev_list_entry_add(&udev_device->properties, "DEVPATH", path + 4, 0); sysname = strrchr(path, '/') + 1; - udev_list_entry_add(&udev_device->properties, "SYSNAME", sysname); + udev_list_entry_add(&udev_device->properties, "SYSNAME", sysname, 0); for (i = 0; sysname[i] != '\0'; i++) { if (sysname[i] >= '0' && sysname[i] <= '9') { - udev_list_entry_add(&udev_device->properties, "SYSNUM", sysname + i); + udev_list_entry_add(&udev_device->properties, "SYSNUM", sysname + i, 0); break; } } @@ -454,14 +454,14 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * subsystem = udev_device_read_symlink(udev_device, "subsystem"); if (subsystem) { - udev_list_entry_add(&udev_device->properties, "SUBSYSTEM", subsystem); + udev_list_entry_add(&udev_device->properties, "SUBSYSTEM", subsystem, 0); free(subsystem); } driver = udev_device_read_symlink(udev_device, "driver"); if (driver) { - udev_list_entry_add(&udev_device->properties, "DRIVER", driver); + udev_list_entry_add(&udev_device->properties, "DRIVER", driver, 0); free(driver); } diff --git a/udev_enumerate.c b/udev_enumerate.c index 86c9cf3..223b746 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -35,7 +35,7 @@ int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, co return -1; } - return udev_list_entry_add(&udev_enumerate->subsystem_match, subsystem, NULL) ? 0 : -1; + return udev_list_entry_add(&udev_enumerate->subsystem_match, subsystem, NULL, 0) ? 0 : -1; } int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) @@ -44,7 +44,7 @@ int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, return -1; } - return udev_list_entry_add(&udev_enumerate->subsystem_nomatch, subsystem, NULL) ? 0 : -1; + return udev_list_entry_add(&udev_enumerate->subsystem_nomatch, subsystem, NULL, 0) ? 0 : -1; } int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) @@ -53,7 +53,7 @@ int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, cons return -1; } - return udev_list_entry_add(&udev_enumerate->sysattr_match, sysattr, value) ? 0 : -1; + return udev_list_entry_add(&udev_enumerate->sysattr_match, sysattr, value, 0) ? 0 : -1; } int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) @@ -62,7 +62,7 @@ int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, co return -1; } - return udev_list_entry_add(&udev_enumerate->sysattr_nomatch, sysattr, value) ? 0 : -1; + return udev_list_entry_add(&udev_enumerate->sysattr_nomatch, sysattr, value, 0) ? 0 : -1; } int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value) @@ -71,7 +71,7 @@ int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, con return -1; } - return udev_list_entry_add(&udev_enumerate->property_match, property, value) ? 0 : -1; + return udev_list_entry_add(&udev_enumerate->property_match, property, value, 0) ? 0 : -1; } int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname) @@ -80,7 +80,7 @@ int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, cons return -1; } - return udev_list_entry_add(&udev_enumerate->sysname_match, sysname, NULL) ? 0 : -1; + return udev_list_entry_add(&udev_enumerate->sysname_match, sysname, NULL, 0) ? 0 : -1; } int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag) @@ -274,7 +274,7 @@ static void *udev_enumerate_add_device(void *ptr) udev_device_unref(udev_device); pthread_mutex_lock(data->mutex); - udev_list_entry_add(&data->udev_enumerate->devices, path, NULL); + udev_list_entry_add(&data->udev_enumerate->devices, path, NULL, 0); pthread_mutex_unlock(data->mutex); return NULL; diff --git a/udev_list.c b/udev_list.c index d9adfdb..e362d49 100644 --- a/udev_list.c +++ b/udev_list.c @@ -31,20 +31,22 @@ void udev_list_entry_free_all(struct udev_list_entry *list_entry) } } -struct udev_list_entry *udev_list_entry_add(struct udev_list_entry *list_entry, const char *name, const char *value) +struct udev_list_entry *udev_list_entry_add(struct udev_list_entry *list_entry, const char *name, const char *value, int uniq) { struct udev_list_entry *new, *old; - old = udev_list_entry_get_by_name(list_entry, name); + if (uniq) { + old = udev_list_entry_get_by_name(list_entry, name); - if (old) { - if (old->value && strcmp(old->value, value) == 0) { + if (old) { + if (old->value && strcmp(old->value, value) == 0) { + return old; + } + + free(old->value); + old->value = value ? strdup(value) : NULL; return old; } - - free(old->value); - old->value = value ? strdup(value) : NULL; - return old; } new = calloc(1, sizeof(struct udev_list_entry)); diff --git a/udev_list.h b/udev_list.h index 270bd14..da84f37 100644 --- a/udev_list.h +++ b/udev_list.h @@ -7,4 +7,4 @@ struct udev_list_entry { void udev_list_entry_init(struct udev_list_entry *list_entry); 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 *udev_list_entry_add(struct udev_list_entry *list_entry, const char *name, const char *value); +struct udev_list_entry *udev_list_entry_add(struct udev_list_entry *list_entry, const char *name, const char *value, int uniq); From a73c1f89b15000c49e46204913847b3b10d5fa09 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 30 Jul 2020 14:51:08 +0300 Subject: [PATCH 062/222] update readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 56bffc6..7e21bc1 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ TODO * [ ] speed up udev_enumerate_scan_devices() - [x] threads + - [ ] [readfile()](https://lwn.net/Articles/813827/) - [ ] deferred plugging via udev_monitor_receive_device() - [ ] ~~caching~~ impossible to implement * [ ] implement hotplugging support From 760346ed08e9db0ed92bba26c1780a36cd6676fe Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 30 Jul 2020 23:37:51 +0300 Subject: [PATCH 063/222] continue, no return --- udev_enumerate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udev_enumerate.c b/udev_enumerate.c index 223b746..7d2dbfe 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -315,7 +315,7 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) } free(de); - return -1; + continue; } // TODO do we really need structure for every thread ? From a0528c55858bee16080aba57d1ea834c6c22ad98 Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 31 Jul 2020 00:08:37 +0300 Subject: [PATCH 064/222] check NULL --- udev_device.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/udev_device.c b/udev_device.c index 8868023..a4cceac 100644 --- a/udev_device.c +++ b/udev_device.c @@ -125,6 +125,10 @@ struct udev_device *udev_device_get_parent(struct udev_device *udev_device) path = strdup(udev_device_get_syspath(udev_device)); + if (!path) { + return NULL; + } + do { if ((tmp = strrchr(path, '/'))) { *tmp = '\0'; From 37fe740623178f53410cea203545f9e7272d56ae Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 31 Jul 2020 00:12:50 +0300 Subject: [PATCH 065/222] check NULL before open devnode --- udev_device.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/udev_device.c b/udev_device.c index a4cceac..ddde018 100644 --- a/udev_device.c +++ b/udev_device.c @@ -352,7 +352,7 @@ static int test_bit(unsigned long int arr[], int bit) static void udev_device_set_properties_from_ioctl(struct udev_device *udev_device) { unsigned long int bits[96], key_bits[96], rel_bits[96], abs_bits[96]; - const char *subsystem; + const char *devnode, *subsystem; int fd; subsystem = udev_device_get_subsystem(udev_device); @@ -361,9 +361,13 @@ static void udev_device_set_properties_from_ioctl(struct udev_device *udev_devic return; } - udev_list_entry_add(&udev_device->properties, "ID_INPUT", "1", 0); + devnode = udev_device_get_devnode(udev_device); - fd = open(udev_device_get_devnode(udev_device), O_RDONLY); + if (!devnode) { + return; + } + + fd = open(devnode, O_RDONLY); if (fd == -1) { return; @@ -405,6 +409,7 @@ static void udev_device_set_properties_from_ioctl(struct udev_device *udev_devic } } + udev_list_entry_add(&udev_device->properties, "ID_INPUT", "1", 0); close(fd); } From bfd09f153ed9f4a4160e8a0e455bd6539262ff62 Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 31 Jul 2020 00:28:09 +0300 Subject: [PATCH 066/222] simplify logic --- udev_device.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/udev_device.c b/udev_device.c index ddde018..92188e9 100644 --- a/udev_device.c +++ b/udev_device.c @@ -460,17 +460,13 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * } } + driver = udev_device_read_symlink(udev_device, "driver"); subsystem = udev_device_read_symlink(udev_device, "subsystem"); - if (subsystem) { + if (driver || subsystem) { udev_list_entry_add(&udev_device->properties, "SUBSYSTEM", subsystem, 0); - free(subsystem); - } - - driver = udev_device_read_symlink(udev_device, "driver"); - - if (driver) { udev_list_entry_add(&udev_device->properties, "DRIVER", driver, 0); + free(subsystem); free(driver); } From e751c69241e08795615cdca67da1a5beff817a82 Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 31 Jul 2020 01:13:41 +0300 Subject: [PATCH 067/222] do not try to search parent device very deeply --- udev_device.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/udev_device.c b/udev_device.c index 92188e9..aa6db22 100644 --- a/udev_device.c +++ b/udev_device.c @@ -117,31 +117,35 @@ struct udev *udev_device_get_udev(struct udev_device *udev_device) struct udev_device *udev_device_get_parent(struct udev_device *udev_device) { - char *tmp, *path; + char *path, *syspath; if (!udev_device) { return NULL; } - path = strdup(udev_device_get_syspath(udev_device)); + syspath = path = strdup(udev_device_get_syspath(udev_device)); if (!path) { return NULL; } + if (strncmp(path, "/sys/devices/", 13) == 0) { + path += 13; + } + do { - if ((tmp = strrchr(path, '/'))) { - *tmp = '\0'; + if ((path = strrchr(path, '/'))) { + *path = '\0'; } else { break; } - udev_device->parent = udev_device_new_from_syspath(udev_device->udev, path); + udev_device->parent = udev_device_new_from_syspath(udev_device->udev, syspath); } while (!udev_device->parent); - free(path); + free(syspath); return udev_device->parent; } From 314f1b005a72e77d4698d7fee64a276fd33d8ce5 Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 31 Jul 2020 01:19:27 +0300 Subject: [PATCH 068/222] change style --- udev_device.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/udev_device.c b/udev_device.c index aa6db22..440ac6f 100644 --- a/udev_device.c +++ b/udev_device.c @@ -489,14 +489,14 @@ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, de } switch (type) { - case 'c': - snprintf(path, sizeof(path), "/sys/dev/char/%d:%d", major(devnum), minor(devnum)); - break; - case 'b': - snprintf(path, sizeof(path), "/sys/dev/block/%d:%d", major(devnum), minor(devnum)); - break; - default: - return NULL; + case 'c': + snprintf(path, sizeof(path), "/sys/dev/char/%d:%d", major(devnum), minor(devnum)); + break; + case 'b': + snprintf(path, sizeof(path), "/sys/dev/block/%d:%d", major(devnum), minor(devnum)); + break; + default: + return NULL; } return udev_device_new_from_syspath(udev, path); From 8c30f20b7e3b125e52e66a602fc97cef5364a7d1 Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 31 Jul 2020 21:30:38 +0300 Subject: [PATCH 069/222] change logic --- udev_device.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/udev_device.c b/udev_device.c index 440ac6f..0063792 100644 --- a/udev_device.c +++ b/udev_device.c @@ -123,15 +123,13 @@ struct udev_device *udev_device_get_parent(struct udev_device *udev_device) return NULL; } - syspath = path = strdup(udev_device_get_syspath(udev_device)); + syspath = strdup(udev_device_get_syspath(udev_device)); - if (!path) { + if (!syspath) { return NULL; } - if (strncmp(path, "/sys/devices/", 13) == 0) { - path += 13; - } + path = syspath + 5; do { if ((path = strrchr(path, '/'))) { From 8a57e66afe49b9ff18fd87a36bed9ccc7f4537e6 Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 31 Jul 2020 22:12:29 +0300 Subject: [PATCH 070/222] pass O_NONBLOCK to open --- udev_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udev_device.c b/udev_device.c index 0063792..9a101db 100644 --- a/udev_device.c +++ b/udev_device.c @@ -369,7 +369,7 @@ static void udev_device_set_properties_from_ioctl(struct udev_device *udev_devic return; } - fd = open(devnode, O_RDONLY); + fd = open(devnode, O_RDONLY | O_NONBLOCK); if (fd == -1) { return; From c60bcdf666c13a409d96c3b6f4ec727863b906eb Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 1 Aug 2020 03:21:01 +0300 Subject: [PATCH 071/222] rename len to cnt --- udev_enumerate.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/udev_enumerate.c b/udev_enumerate.c index 7d2dbfe..1a5681f 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -296,21 +296,21 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) struct udev_enumerate_thread *data; pthread_mutex_t mutex; struct dirent **de; - int len, i, u; + int cnt, i, u; pthread_mutex_init(&mutex, NULL); for (i = 0; path[i]; i++) { - len = scandir(path[i], &de, udev_enumerate_filter_dots, NULL); + cnt = scandir(path[i], &de, udev_enumerate_filter_dots, NULL); - if (len == -1) { + if (cnt == -1) { continue; } - data = calloc(len, sizeof(struct udev_enumerate_thread)); + data = calloc(cnt, sizeof(struct udev_enumerate_thread)); if (!data) { - for (u = 0; u < len; u++) { + for (u = 0; u < cnt; u++) { free(de[u]); } @@ -319,7 +319,7 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) } // TODO do we really need structure for every thread ? - for (u = 0; u < len; u++) { + for (u = 0; u < cnt; u++) { data[u].path = path[i]; data[u].name = de[u]->d_name; data[u].mutex = &mutex; @@ -328,11 +328,11 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) pthread_create(&data[u].thread, NULL, udev_enumerate_add_device, &data[u]); } - for (u = 0; u < len; u++) { + for (u = 0; u < cnt; u++) { pthread_join(data[u].thread, NULL); } - for (u = 0; u < len; u++) { + for (u = 0; u < cnt; u++) { free(de[u]); } From fca883ed54688481e761e92ec0955af284191732 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 1 Aug 2020 03:23:56 +0300 Subject: [PATCH 072/222] get rid of ioctl before - 2.964 total after - 0.932 total still slow ??? --- udev_device.c | 99 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 65 insertions(+), 34 deletions(-) diff --git a/udev_device.c b/udev_device.c index 9a101db..0d4b46f 100644 --- a/udev_device.c +++ b/udev_device.c @@ -5,9 +5,7 @@ #include #include #include -#include #include -#include #include "udev.h" #include "udev_list.h" @@ -346,16 +344,61 @@ static void udev_device_set_properties_from_uevent(struct udev_device *udev_devi fclose(file); } -static int test_bit(unsigned long int arr[], int bit) +static int populate_bit(unsigned long *arr, const char *val) { - return arr[bit / LONG_BIT] & (1 << (bit % LONG_BIT)); + char *bits, *space; + int i; + + if (!val) { + return -1; + } + + if (!strchr(val, ' ')) { + arr[0] = strtoul(val, NULL, 16); + return 1; + } + + bits = strdup(val); + + if (!bits) { + return -1; + } + + space = strrchr(bits, ' '); + + for (i = 0; space; i++) { + *space = '\0'; + arr[i] = strtoul(space + 1, NULL, 16); + space = strrchr(bits, ' '); + } + + free(bits); + return i; } -static void udev_device_set_properties_from_ioctl(struct udev_device *udev_device) +static int find_bit(unsigned long *arr, int cnt, int bit) { - unsigned long int bits[96], key_bits[96], rel_bits[96], abs_bits[96]; - const char *devnode, *subsystem; - int fd; + int i; + + if (cnt == -1) { + return 0; + } + + for (i = 0; i < cnt; i++) { + if (arr[i] & (1 << (bit % LONG_BIT))) { + return 1; + } + } + + return 0; +} + +static void udev_device_set_properties_from_bits(struct udev_device *udev_device) +{ + unsigned long rel_bits[96] = {0}, abs_bits[96] = {0}; + unsigned long bits[96] = {0}, key_bits[96] = {0}; + int bits_cnt, rel_cnt, key_cnt, abs_cnt; + const char *subsystem; subsystem = udev_device_get_subsystem(udev_device); @@ -363,56 +406,44 @@ static void udev_device_set_properties_from_ioctl(struct udev_device *udev_devic return; } - devnode = udev_device_get_devnode(udev_device); - - if (!devnode) { + if (!udev_device_get_parent(udev_device)) { return; } - fd = open(devnode, O_RDONLY | O_NONBLOCK); + bits_cnt = populate_bit(bits, udev_device_get_property_value(udev_device->parent, "EV")); + abs_cnt = populate_bit(abs_bits, udev_device_get_property_value(udev_device->parent, "ABS")); + rel_cnt = populate_bit(rel_bits, udev_device_get_property_value(udev_device->parent, "REL")); + key_cnt = populate_bit(key_bits, udev_device_get_property_value(udev_device->parent, "KEY")); - if (fd == -1) { - return; - } - - if (ioctl(fd, (int)EVIOCGBIT(0, sizeof(bits)), &bits) == -1 || - ioctl(fd, (int)EVIOCGBIT(EV_KEY, sizeof(key_bits)), &key_bits) == -1 || - ioctl(fd, (int)EVIOCGBIT(EV_REL, sizeof(rel_bits)), &rel_bits) == -1 || - ioctl(fd, (int)EVIOCGBIT(EV_ABS, sizeof(abs_bits)), &abs_bits) == -1) { - close(fd); - return; - } - - if (test_bit(bits, EV_SW)) { + if (find_bit(bits, bits_cnt, EV_SW)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_SWITCH", "1", 0); } - if (test_bit(bits, EV_KEY) && test_bit(key_bits, KEY_ENTER)) { + if (find_bit(bits, bits_cnt, EV_KEY) && find_bit(key_bits, key_cnt, KEY_ENTER)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEY", "1", 0); udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEYBOARD", "1", 0); } - if (test_bit(bits, EV_REL) && test_bit(rel_bits, REL_Y) && test_bit(rel_bits, REL_X) && - test_bit(key_bits, BTN_MOUSE)) { + if (find_bit(bits, bits_cnt, EV_REL) && find_bit(rel_bits, rel_cnt, REL_Y) && + find_bit(rel_bits, rel_cnt, REL_X) && find_bit(key_bits, key_cnt, BTN_MOUSE)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1", 0); } - if (test_bit(bits, EV_ABS) && test_bit(abs_bits, ABS_Y) && test_bit(abs_bits, ABS_X)) { - if (test_bit(key_bits, BTN_TOUCH) && !test_bit(key_bits, BTN_TOOL_PEN)) { - if (test_bit(key_bits, BTN_TOOL_FINGER)) { + if (find_bit(bits, bits_cnt, EV_ABS) && find_bit(abs_bits, abs_cnt, ABS_Y) && find_bit(abs_bits, abs_cnt, ABS_X)) { + if (find_bit(key_bits, key_cnt, BTN_TOUCH) && !find_bit(key_bits, key_cnt, BTN_TOOL_PEN)) { + if (find_bit(key_bits, key_cnt, BTN_TOOL_FINGER)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHPAD", "1", 0); } else { udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHSCREEN", "1", 0); } } - else if (test_bit(key_bits, BTN_MOUSE)) { + else if (find_bit(key_bits, key_cnt, BTN_MOUSE)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1", 0); } } udev_list_entry_add(&udev_device->properties, "ID_INPUT", "1", 0); - close(fd); } struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) @@ -473,7 +504,7 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * } udev_device_set_properties_from_uevent(udev_device); - udev_device_set_properties_from_ioctl(udev_device); + udev_device_set_properties_from_bits(udev_device); return udev_device; } From c73a89dafc45eb73fd826ec7af391ac51e30dc1a Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 1 Aug 2020 03:47:37 +0300 Subject: [PATCH 073/222] update readme --- README.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/README.md b/README.md index 7e21bc1..66847d9 100644 --- a/README.md +++ b/README.md @@ -34,10 +34,5 @@ make PREFIX=/usr install # overwrites existing udev libraries if any TODO ---- -* [ ] speed up udev_enumerate_scan_devices() - - [x] threads - - [ ] [readfile()](https://lwn.net/Articles/813827/) - - [ ] deferred plugging via udev_monitor_receive_device() - - [ ] ~~caching~~ impossible to implement +* [x] speed up udev_enumerate_scan_devices() * [ ] implement hotplugging support -* [x] remove [dirty hack](https://github.com/illiliti/libudev-zero/blob/e76f9b282442505bd6b0b08b411679aae1581fa5/udev_device.c#L383). use ioctl() From 8547b55072400b7a0c8d7002147e93dc34b4525f Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 1 Aug 2020 04:20:27 +0300 Subject: [PATCH 074/222] use buffered io --- udev_device.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/udev_device.c b/udev_device.c index 0d4b46f..336eaaa 100644 --- a/udev_device.c +++ b/udev_device.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -227,7 +226,7 @@ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const struct udev_list_entry *list_entry; char data[BUFSIZ], path[PATH_MAX]; struct stat st; - int fd; + FILE *file; if (!udev_device || !sysattr) { return NULL; @@ -245,18 +244,18 @@ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const return NULL; } - fd = open(path, O_RDONLY); + file = fopen(path, "r"); - if (fd == -1) { + if (!file) { return NULL; } - if (read(fd, data, sizeof(data)) == -1) { - close(fd); + if (fread(data, 1, sizeof(data), file) != sizeof(data) && ferror(file)) { + fclose(file); return NULL; } - close(fd); + fclose(file); data[strcspn(data, "\n")] = '\0'; list_entry = udev_list_entry_add(&udev_device->sysattrs, sysattr, data, 0); return udev_list_entry_get_value(list_entry); @@ -266,7 +265,8 @@ int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *s { char path[PATH_MAX]; struct stat st; - int fd; + size_t len; + FILE *file; if (!udev_device || !sysattr || !value) { return -1; @@ -278,18 +278,19 @@ int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *s return -1; } - fd = open(path, O_WRONLY); + file = fopen(path, "w"); - if (fd == -1) { + if (!file) { return -1; } - if (write(fd, value, strlen(value)) == -1) { - close(fd); + len = strlen(value); + if (fwrite(value, 1, len, file) != len) { + fclose(file); return -1; } - close(fd); + fclose(file); udev_list_entry_add(&udev_device->sysattrs, sysattr, value, 1); return 0; } From a41459e81c91d2d5ea5bd60c5145a296b8503821 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 1 Aug 2020 18:31:29 +0300 Subject: [PATCH 075/222] fix broken input --- udev_device.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/udev_device.c b/udev_device.c index 336eaaa..48f783f 100644 --- a/udev_device.c +++ b/udev_device.c @@ -347,31 +347,27 @@ static void udev_device_set_properties_from_uevent(struct udev_device *udev_devi static int populate_bit(unsigned long *arr, const char *val) { - char *bits, *space; + char *bit, *bits, *save; int i; if (!val) { return -1; } - if (!strchr(val, ' ')) { - arr[0] = strtoul(val, NULL, 16); - return 1; - } - bits = strdup(val); if (!bits) { return -1; } - space = strrchr(bits, ' '); + bit = strtok_r(bits, " ", &save); + i = 0; - for (i = 0; space; i++) { - *space = '\0'; - arr[i] = strtoul(space + 1, NULL, 16); - space = strrchr(bits, ' '); + do { + arr[i] = strtoul(bit, NULL, 16); + i++; } + while ((bit = strtok_r(NULL, " ", &save))); free(bits); return i; @@ -399,6 +395,7 @@ static void udev_device_set_properties_from_bits(struct udev_device *udev_device unsigned long rel_bits[96] = {0}, abs_bits[96] = {0}; unsigned long bits[96] = {0}, key_bits[96] = {0}; int bits_cnt, rel_cnt, key_cnt, abs_cnt; + struct udev_device *parent; const char *subsystem; subsystem = udev_device_get_subsystem(udev_device); @@ -407,14 +404,20 @@ static void udev_device_set_properties_from_bits(struct udev_device *udev_device return; } - if (!udev_device_get_parent(udev_device)) { - return; + parent = udev_device_get_parent_with_subsystem_devtype(udev_device, "input", NULL); + + while (parent) { + if (udev_device_get_property_value(parent, "EV")) { + break; + } + + parent = udev_device_get_parent_with_subsystem_devtype(parent, "input", NULL); } - bits_cnt = populate_bit(bits, udev_device_get_property_value(udev_device->parent, "EV")); - abs_cnt = populate_bit(abs_bits, udev_device_get_property_value(udev_device->parent, "ABS")); - rel_cnt = populate_bit(rel_bits, udev_device_get_property_value(udev_device->parent, "REL")); - key_cnt = populate_bit(key_bits, udev_device_get_property_value(udev_device->parent, "KEY")); + bits_cnt = populate_bit(bits, udev_device_get_property_value(parent, "EV")); + abs_cnt = populate_bit(abs_bits, udev_device_get_property_value(parent, "ABS")); + rel_cnt = populate_bit(rel_bits, udev_device_get_property_value(parent, "REL")); + key_cnt = populate_bit(key_bits, udev_device_get_property_value(parent, "KEY")); if (find_bit(bits, bits_cnt, EV_SW)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_SWITCH", "1", 0); From 3700b9c642c2a722951acb80b6af7e9ff0fd2563 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 2 Aug 2020 15:50:17 +0300 Subject: [PATCH 076/222] check NULL --- udev_device.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/udev_device.c b/udev_device.c index 48f783f..5681cc0 100644 --- a/udev_device.c +++ b/udev_device.c @@ -414,6 +414,10 @@ static void udev_device_set_properties_from_bits(struct udev_device *udev_device parent = udev_device_get_parent_with_subsystem_devtype(parent, "input", NULL); } + if (!parent) { + return; + } + bits_cnt = populate_bit(bits, udev_device_get_property_value(parent, "EV")); abs_cnt = populate_bit(abs_bits, udev_device_get_property_value(parent, "ABS")); rel_cnt = populate_bit(rel_bits, udev_device_get_property_value(parent, "REL")); From 8fa88d6697bc32c5e669510cc33ed8439a32a702 Mon Sep 17 00:00:00 2001 From: illiliti Date: Mon, 3 Aug 2020 00:05:12 +0300 Subject: [PATCH 077/222] remove useless NULL checks --- udev_device.c | 53 ++++++++------------------------------------------- 1 file changed, 8 insertions(+), 45 deletions(-) diff --git a/udev_device.c b/udev_device.c index 5681cc0..b0e255d 100644 --- a/udev_device.c +++ b/udev_device.c @@ -19,46 +19,26 @@ struct udev_device { const char *udev_device_get_syspath(struct udev_device *udev_device) { - if (!udev_device) { - return NULL; - } - return udev_device_get_property_value(udev_device, "SYSPATH"); } const char *udev_device_get_sysname(struct udev_device *udev_device) { - if (!udev_device) { - return NULL; - } - return udev_device_get_property_value(udev_device, "SYSNAME"); } const char *udev_device_get_sysnum(struct udev_device *udev_device) { - if (!udev_device) { - return NULL; - } - return udev_device_get_property_value(udev_device, "SYSNUM"); } const char *udev_device_get_devpath(struct udev_device *udev_device) { - if (!udev_device) { - return NULL; - } - return udev_device_get_property_value(udev_device, "DEVPATH"); } const char *udev_device_get_devnode(struct udev_device *udev_device) { - if (!udev_device) { - return NULL; - } - return udev_device_get_property_value(udev_device, "DEVNAME"); } @@ -66,10 +46,6 @@ dev_t udev_device_get_devnum(struct udev_device *udev_device) { const char *major, *minor; - if (!udev_device) { - return makedev(0, 0); - } - major = udev_device_get_property_value(udev_device, "MAJOR"); minor = udev_device_get_property_value(udev_device, "MINOR"); @@ -82,28 +58,16 @@ dev_t udev_device_get_devnum(struct udev_device *udev_device) const char *udev_device_get_devtype(struct udev_device *udev_device) { - if (!udev_device) { - return NULL; - } - return udev_device_get_property_value(udev_device, "DEVTYPE"); } const char *udev_device_get_subsystem(struct udev_device *udev_device) { - if (!udev_device) { - return NULL; - } - return udev_device_get_property_value(udev_device, "SUBSYSTEM"); } const char *udev_device_get_driver(struct udev_device *udev_device) { - if (!udev_device) { - return NULL; - } - return udev_device_get_property_value(udev_device, "DRIVER"); } @@ -215,10 +179,11 @@ struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *u const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key) { - struct udev_list_entry *list_entry; + if (!udev_device || !key) { + return NULL; + } - list_entry = udev_list_entry_get_by_name(&udev_device->properties, key); - return udev_list_entry_get_value(list_entry); + return udev_list_entry_get_value(udev_list_entry_get_by_name(&udev_device->properties, key)); } const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr) @@ -301,7 +266,6 @@ static char *udev_device_read_symlink(struct udev_device *udev_device, const cha ssize_t len; snprintf(path, sizeof(path), "%s/%s", udev_device_get_syspath(udev_device), name); - len = readlink(path, link, sizeof(link)); if (len == -1) { @@ -319,7 +283,6 @@ static void udev_device_set_properties_from_uevent(struct udev_device *udev_devi FILE *file; snprintf(path, sizeof(path), "%s/uevent", udev_device_get_syspath(udev_device)); - file = fopen(path, "r"); if (!file) { @@ -351,13 +314,13 @@ static int populate_bit(unsigned long *arr, const char *val) int i; if (!val) { - return -1; + return 0; } bits = strdup(val); if (!bits) { - return -1; + return 0; } bit = strtok_r(bits, " ", &save); @@ -377,7 +340,7 @@ static int find_bit(unsigned long *arr, int cnt, int bit) { int i; - if (cnt == -1) { + if (!cnt) { return 0; } @@ -447,7 +410,7 @@ static void udev_device_set_properties_from_bits(struct udev_device *udev_device } } else if (find_bit(key_bits, key_cnt, BTN_MOUSE)) { - udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1", 0); + udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1", 1); } } From 7754aa691c209b928e6c350eeaea8ea5b61b7bf3 Mon Sep 17 00:00:00 2001 From: illiliti Date: Mon, 3 Aug 2020 18:37:40 +0300 Subject: [PATCH 078/222] prevent array index out of bounds --- udev_device.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/udev_device.c b/udev_device.c index b0e255d..01bc7d8 100644 --- a/udev_device.c +++ b/udev_device.c @@ -9,6 +9,8 @@ #include "udev.h" #include "udev_list.h" +enum { BITS_SIZE = 96 }; + struct udev_device { struct udev_list_entry properties; struct udev_list_entry sysattrs; @@ -330,7 +332,7 @@ static int populate_bit(unsigned long *arr, const char *val) arr[i] = strtoul(bit, NULL, 16); i++; } - while ((bit = strtok_r(NULL, " ", &save))); + while ((bit = strtok_r(NULL, " ", &save)) && i < BITS_SIZE); free(bits); return i; @@ -355,8 +357,8 @@ static int find_bit(unsigned long *arr, int cnt, int bit) static void udev_device_set_properties_from_bits(struct udev_device *udev_device) { - unsigned long rel_bits[96] = {0}, abs_bits[96] = {0}; - unsigned long bits[96] = {0}, key_bits[96] = {0}; + unsigned long rel_bits[BITS_SIZE] = {0}, abs_bits[BITS_SIZE] = {0}; + unsigned long bits[BITS_SIZE] = {0}, key_bits[BITS_SIZE] = {0}; int bits_cnt, rel_cnt, key_cnt, abs_cnt; struct udev_device *parent; const char *subsystem; From c0d6c583938d5bc24c3bb673c152e6541e7f9f1a Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 4 Aug 2020 16:11:17 +0300 Subject: [PATCH 079/222] switch to for loop --- udev_device.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/udev_device.c b/udev_device.c index 01bc7d8..54fae0f 100644 --- a/udev_device.c +++ b/udev_device.c @@ -326,13 +326,11 @@ static int populate_bit(unsigned long *arr, const char *val) } bit = strtok_r(bits, " ", &save); - i = 0; - do { + for (i = 0; bit && i < BITS_SIZE; i++) { arr[i] = strtoul(bit, NULL, 16); - i++; + bit = strtok_r(NULL, " ", &save); } - while ((bit = strtok_r(NULL, " ", &save)) && i < BITS_SIZE); free(bits); return i; From e1e78b525e073fc9c029bdb388e52c7ddc3f983f Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 4 Aug 2020 18:02:06 +0300 Subject: [PATCH 080/222] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 66847d9..3cd7dde 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ What Works * [x] libinput * [x] wlroots * [x] weston -* [ ] libusb - broken completely +* [ ] libusb - doesn't work for now. temporary workaround is compiling libusb with --disable-udev * [x] kwin - [fix](https://github.com/dilyn-corner/KISS-kde/commit/0cc72748e46f859a0fced55b0c3fcc1dd9586a38) * [ ] ??? From 25977fddb58dcb5b2cfaf7c0c0cb5f8f118becee Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 4 Aug 2020 21:32:06 +0300 Subject: [PATCH 081/222] cleanup --- udev_device.c | 49 ++++++++++++++++++++++++------------------------ udev_enumerate.c | 6 ++---- 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/udev_device.c b/udev_device.c index 54fae0f..678571f 100644 --- a/udev_device.c +++ b/udev_device.c @@ -353,11 +353,13 @@ static int find_bit(unsigned long *arr, int cnt, int bit) return 0; } -static void udev_device_set_properties_from_bits(struct udev_device *udev_device) +static void udev_device_set_properties_from_evdev(struct udev_device *udev_device) { - unsigned long rel_bits[BITS_SIZE] = {0}, abs_bits[BITS_SIZE] = {0}; - unsigned long bits[BITS_SIZE] = {0}, key_bits[BITS_SIZE] = {0}; - int bits_cnt, rel_cnt, key_cnt, abs_cnt; + unsigned long abs_bits[BITS_SIZE] = {0}; + unsigned long rel_bits[BITS_SIZE] = {0}; + unsigned long key_bits[BITS_SIZE] = {0}; + unsigned long ev_bits[BITS_SIZE] = {0}; + int ev_cnt, rel_cnt, key_cnt, abs_cnt; struct udev_device *parent; const char *subsystem; @@ -369,7 +371,11 @@ static void udev_device_set_properties_from_bits(struct udev_device *udev_device parent = udev_device_get_parent_with_subsystem_devtype(udev_device, "input", NULL); - while (parent) { + while (1) { + if (!parent) { + return; + } + if (udev_device_get_property_value(parent, "EV")) { break; } @@ -377,30 +383,26 @@ static void udev_device_set_properties_from_bits(struct udev_device *udev_device parent = udev_device_get_parent_with_subsystem_devtype(parent, "input", NULL); } - if (!parent) { - return; - } - - bits_cnt = populate_bit(bits, udev_device_get_property_value(parent, "EV")); + ev_cnt = populate_bit(ev_bits, udev_device_get_property_value(parent, "EV")); abs_cnt = populate_bit(abs_bits, udev_device_get_property_value(parent, "ABS")); rel_cnt = populate_bit(rel_bits, udev_device_get_property_value(parent, "REL")); key_cnt = populate_bit(key_bits, udev_device_get_property_value(parent, "KEY")); - if (find_bit(bits, bits_cnt, EV_SW)) { + if (find_bit(ev_bits, ev_cnt, EV_SW)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_SWITCH", "1", 0); } - if (find_bit(bits, bits_cnt, EV_KEY) && find_bit(key_bits, key_cnt, KEY_ENTER)) { + if (find_bit(ev_bits, ev_cnt, EV_KEY) && find_bit(key_bits, key_cnt, KEY_ENTER)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEY", "1", 0); udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEYBOARD", "1", 0); } - if (find_bit(bits, bits_cnt, EV_REL) && find_bit(rel_bits, rel_cnt, REL_Y) && + if (find_bit(ev_bits, ev_cnt, EV_REL) && find_bit(rel_bits, rel_cnt, REL_Y) && find_bit(rel_bits, rel_cnt, REL_X) && find_bit(key_bits, key_cnt, BTN_MOUSE)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1", 0); } - if (find_bit(bits, bits_cnt, EV_ABS) && find_bit(abs_bits, abs_cnt, ABS_Y) && find_bit(abs_bits, abs_cnt, ABS_X)) { + if (find_bit(ev_bits, ev_cnt, EV_ABS) && find_bit(abs_bits, abs_cnt, ABS_Y) && find_bit(abs_bits, abs_cnt, ABS_X)) { if (find_bit(key_bits, key_cnt, BTN_TOUCH) && !find_bit(key_bits, key_cnt, BTN_TOOL_PEN)) { if (find_bit(key_bits, key_cnt, BTN_TOOL_FINGER)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHPAD", "1", 0); @@ -455,7 +457,12 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * udev_list_entry_add(&udev_device->properties, "DEVPATH", path + 4, 0); sysname = strrchr(path, '/') + 1; + driver = udev_device_read_symlink(udev_device, "driver"); + subsystem = udev_device_read_symlink(udev_device, "subsystem"); + + udev_list_entry_add(&udev_device->properties, "SUBSYSTEM", subsystem, 0); udev_list_entry_add(&udev_device->properties, "SYSNAME", sysname, 0); + udev_list_entry_add(&udev_device->properties, "DRIVER", driver, 0); for (i = 0; sysname[i] != '\0'; i++) { if (sysname[i] >= '0' && sysname[i] <= '9') { @@ -464,19 +471,11 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * } } - driver = udev_device_read_symlink(udev_device, "driver"); - subsystem = udev_device_read_symlink(udev_device, "subsystem"); - - if (driver || subsystem) { - udev_list_entry_add(&udev_device->properties, "SUBSYSTEM", subsystem, 0); - udev_list_entry_add(&udev_device->properties, "DRIVER", driver, 0); - free(subsystem); - free(driver); - } - udev_device_set_properties_from_uevent(udev_device); - udev_device_set_properties_from_bits(udev_device); + udev_device_set_properties_from_evdev(udev_device); + free(driver); + free(subsystem); return udev_device; } diff --git a/udev_enumerate.c b/udev_enumerate.c index 1a5681f..558f288 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -270,13 +270,11 @@ static void *udev_enumerate_add_device(void *ptr) return NULL; } - snprintf(path, sizeof(path), "%s", udev_device_get_syspath(udev_device)); - udev_device_unref(udev_device); - pthread_mutex_lock(data->mutex); - udev_list_entry_add(&data->udev_enumerate->devices, path, NULL, 0); + udev_list_entry_add(&data->udev_enumerate->devices, udev_device_get_syspath(udev_device), NULL, 0); pthread_mutex_unlock(data->mutex); + udev_device_unref(udev_device); return NULL; } From a445c3ce4758664b3a0ce9642efa01d288ce2b64 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 5 Aug 2020 00:53:23 +0300 Subject: [PATCH 082/222] update readme --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3cd7dde..8552013 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ -[![Donate with Bitcoin](https://en.cryptobadges.io/badge/micro/1BwrcsgtWZeLVvNeEQSg4A28a3yrGN3FpK)](https://en.cryptobadges.io/donate/1BwrcsgtWZeLVvNeEQSg4A28a3yrGN3FpK) - libudev-zero ============ @@ -36,3 +34,10 @@ TODO * [x] speed up udev_enumerate_scan_devices() * [ ] implement hotplugging support + +Donate +------ + +You can donate if you like this project + +BTC: 1BwrcsgtWZeLVvNeEQSg4A28a3yrGN3FpK From f60cb919d47d2e8fae52ef32c941c1a18a53aa06 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 5 Aug 2020 01:10:34 +0300 Subject: [PATCH 083/222] update readme --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8552013..45d8eec 100644 --- a/README.md +++ b/README.md @@ -26,13 +26,15 @@ Installation ```sh make -make PREFIX=/usr install # overwrites existing udev libraries if any +make PREFIX=/usr install # will overwrite existing udev libraries if any +# rebuild all packages which depends on udev +# here we go ! ``` TODO ---- -* [x] speed up udev_enumerate_scan_devices() +* [x] speed up performance * [ ] implement hotplugging support Donate From 4bbd8ddf3e9791f817d43f331085bcf2301a8757 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 5 Aug 2020 04:01:49 +0300 Subject: [PATCH 084/222] update readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 45d8eec..d97be42 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ TODO * [x] speed up performance * [ ] implement hotplugging support +* [ ] joysticks, accelerometers, pointing sticks, tablets support (pull requests are welcome) Donate ------ From 011d3db9e191d243e221f1f7ca8e05dfaad86bab Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 7 Aug 2020 05:42:20 +0300 Subject: [PATCH 085/222] check if switch has EV_KEY capability --- udev_device.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/udev_device.c b/udev_device.c index 678571f..23d7950 100644 --- a/udev_device.c +++ b/udev_device.c @@ -252,6 +252,7 @@ int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *s } len = strlen(value); + if (fwrite(value, 1, len, file) != len) { fclose(file); return -1; @@ -388,7 +389,13 @@ static void udev_device_set_properties_from_evdev(struct udev_device *udev_devic rel_cnt = populate_bit(rel_bits, udev_device_get_property_value(parent, "REL")); key_cnt = populate_bit(key_bits, udev_device_get_property_value(parent, "KEY")); + // TODO iterate over KEY_* + if (find_bit(ev_bits, ev_cnt, EV_SW)) { + if (find_bit(ev_bits, ev_cnt, EV_KEY)) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEY", "1", 0); + } + udev_list_entry_add(&udev_device->properties, "ID_INPUT_SWITCH", "1", 0); } From 9c681d6cadb56ca0c2ea63da4a71ccbb9909bae5 Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 7 Aug 2020 21:00:37 +0300 Subject: [PATCH 086/222] update readme --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d97be42..750bb6e 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,11 @@ TODO * [x] speed up performance * [ ] implement hotplugging support -* [ ] joysticks, accelerometers, pointing sticks, tablets support (pull requests are welcome) +* [ ] extend devices support (pull requests are welcome) + - [ ] tablets + - [ ] joysticks + - [ ] accelerometers + - [ ] pointing sticks Donate ------ From ca956fa663afa6aaa09b11afca0e8a7590a69086 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 9 Aug 2020 07:05:09 +0300 Subject: [PATCH 087/222] add support for tablets, pointing sticks and accelerometers --- README.md | 6 +++--- udev_device.c | 28 ++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 750bb6e..ad1b558 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,10 @@ TODO * [x] speed up performance * [ ] implement hotplugging support * [ ] extend devices support (pull requests are welcome) - - [ ] tablets + - [x] tablets - [ ] joysticks - - [ ] accelerometers - - [ ] pointing sticks + - [x] accelerometers + - [x] pointing sticks Donate ------ diff --git a/udev_device.c b/udev_device.c index 23d7950..cadcea1 100644 --- a/udev_device.c +++ b/udev_device.c @@ -356,11 +356,12 @@ static int find_bit(unsigned long *arr, int cnt, int bit) static void udev_device_set_properties_from_evdev(struct udev_device *udev_device) { + int ev_cnt, rel_cnt, key_cnt, abs_cnt, prop_cnt; + unsigned long prop_bits[BITS_SIZE] = {0}; unsigned long abs_bits[BITS_SIZE] = {0}; unsigned long rel_bits[BITS_SIZE] = {0}; unsigned long key_bits[BITS_SIZE] = {0}; unsigned long ev_bits[BITS_SIZE] = {0}; - int ev_cnt, rel_cnt, key_cnt, abs_cnt; struct udev_device *parent; const char *subsystem; @@ -388,8 +389,22 @@ static void udev_device_set_properties_from_evdev(struct udev_device *udev_devic abs_cnt = populate_bit(abs_bits, udev_device_get_property_value(parent, "ABS")); rel_cnt = populate_bit(rel_bits, udev_device_get_property_value(parent, "REL")); key_cnt = populate_bit(key_bits, udev_device_get_property_value(parent, "KEY")); + prop_cnt = populate_bit(prop_bits, udev_device_get_property_value(parent, "PROP")); - // TODO iterate over KEY_* + // TODO iterate over KEY_* to find ID_INPUT_KEY or use exclusion method + + udev_list_entry_add(&udev_device->properties, "ID_INPUT", "1", 0); + + if (find_bit(prop_bits, prop_cnt, INPUT_PROP_POINTING_STICK)) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_POINTINGSTICK", "1", 0); + } + + if (find_bit(prop_bits, prop_cnt, INPUT_PROP_ACCELEROMETER) || + (find_bit(ev_bits, ev_cnt, EV_ABS) && !find_bit(ev_bits, ev_cnt, EV_KEY) && + find_bit(abs_bits, abs_cnt, ABS_Y) && find_bit(abs_bits, abs_cnt, ABS_X) && + find_bit(abs_bits, abs_cnt, ABS_Z))) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_ACCELEROMETER", "1", 0); + } if (find_bit(ev_bits, ev_cnt, EV_SW)) { if (find_bit(ev_bits, ev_cnt, EV_KEY)) { @@ -410,7 +425,10 @@ static void udev_device_set_properties_from_evdev(struct udev_device *udev_devic } if (find_bit(ev_bits, ev_cnt, EV_ABS) && find_bit(abs_bits, abs_cnt, ABS_Y) && find_bit(abs_bits, abs_cnt, ABS_X)) { - if (find_bit(key_bits, key_cnt, BTN_TOUCH) && !find_bit(key_bits, key_cnt, BTN_TOOL_PEN)) { + if (find_bit(key_bits, key_cnt, BTN_STYLUS) || find_bit(key_bits, key_cnt, BTN_TOOL_PEN)) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_TABLET", "1", 0); + } + else if (find_bit(key_bits, key_cnt, BTN_TOUCH)) { if (find_bit(key_bits, key_cnt, BTN_TOOL_FINGER)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHPAD", "1", 0); } @@ -419,11 +437,9 @@ static void udev_device_set_properties_from_evdev(struct udev_device *udev_devic } } else if (find_bit(key_bits, key_cnt, BTN_MOUSE)) { - udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1", 1); + udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1", 0); } } - - udev_list_entry_add(&udev_device->properties, "ID_INPUT", "1", 0); } struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) From dc75e2b44e941c26aa5dcaec11f76fca6a631dd0 Mon Sep 17 00:00:00 2001 From: illiliti Date: Mon, 10 Aug 2020 00:48:02 +0300 Subject: [PATCH 088/222] correctly find ID_INPUT_KEY --- udev_device.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/udev_device.c b/udev_device.c index cadcea1..f1728e8 100644 --- a/udev_device.c +++ b/udev_device.c @@ -391,8 +391,6 @@ static void udev_device_set_properties_from_evdev(struct udev_device *udev_devic key_cnt = populate_bit(key_bits, udev_device_get_property_value(parent, "KEY")); prop_cnt = populate_bit(prop_bits, udev_device_get_property_value(parent, "PROP")); - // TODO iterate over KEY_* to find ID_INPUT_KEY or use exclusion method - udev_list_entry_add(&udev_device->properties, "ID_INPUT", "1", 0); if (find_bit(prop_bits, prop_cnt, INPUT_PROP_POINTING_STICK)) { @@ -400,31 +398,20 @@ static void udev_device_set_properties_from_evdev(struct udev_device *udev_devic } if (find_bit(prop_bits, prop_cnt, INPUT_PROP_ACCELEROMETER) || - (find_bit(ev_bits, ev_cnt, EV_ABS) && !find_bit(ev_bits, ev_cnt, EV_KEY) && - find_bit(abs_bits, abs_cnt, ABS_Y) && find_bit(abs_bits, abs_cnt, ABS_X) && - find_bit(abs_bits, abs_cnt, ABS_Z))) { + (find_bit(abs_bits, abs_cnt, ABS_Z) && !find_bit(ev_bits, ev_cnt, EV_KEY) && + find_bit(abs_bits, abs_cnt, ABS_Y) && find_bit(abs_bits, abs_cnt, ABS_X))) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_ACCELEROMETER", "1", 0); } if (find_bit(ev_bits, ev_cnt, EV_SW)) { - if (find_bit(ev_bits, ev_cnt, EV_KEY)) { - udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEY", "1", 0); - } - udev_list_entry_add(&udev_device->properties, "ID_INPUT_SWITCH", "1", 0); } - if (find_bit(ev_bits, ev_cnt, EV_KEY) && find_bit(key_bits, key_cnt, KEY_ENTER)) { - udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEY", "1", 0); - udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEYBOARD", "1", 0); - } - if (find_bit(ev_bits, ev_cnt, EV_REL) && find_bit(rel_bits, rel_cnt, REL_Y) && find_bit(rel_bits, rel_cnt, REL_X) && find_bit(key_bits, key_cnt, BTN_MOUSE)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1", 0); } - - if (find_bit(ev_bits, ev_cnt, EV_ABS) && find_bit(abs_bits, abs_cnt, ABS_Y) && find_bit(abs_bits, abs_cnt, ABS_X)) { + else if (find_bit(ev_bits, ev_cnt, EV_ABS) && find_bit(abs_bits, abs_cnt, ABS_Y) && find_bit(abs_bits, abs_cnt, ABS_X)) { if (find_bit(key_bits, key_cnt, BTN_STYLUS) || find_bit(key_bits, key_cnt, BTN_TOOL_PEN)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_TABLET", "1", 0); } @@ -440,6 +427,13 @@ static void udev_device_set_properties_from_evdev(struct udev_device *udev_devic udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1", 0); } } + else if (find_bit(ev_bits, ev_cnt, EV_KEY)) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEY", "1", 0); + + if (find_bit(key_bits, key_cnt, KEY_ENTER)) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEYBOARD", "1", 0); + } + } } struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) From 56bcf254610fc6a976b89c900e974b5720a7f9a3 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 12 Aug 2020 23:31:37 +0300 Subject: [PATCH 089/222] minor fixes, add joystick support --- README.md | 6 +----- udev_device.c | 51 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index ad1b558..6105d9d 100644 --- a/README.md +++ b/README.md @@ -35,12 +35,8 @@ TODO ---- * [x] speed up performance +* [x] extend devices support * [ ] implement hotplugging support -* [ ] extend devices support (pull requests are welcome) - - [x] tablets - - [ ] joysticks - - [x] accelerometers - - [x] pointing sticks Donate ------ diff --git a/udev_device.c b/udev_device.c index f1728e8..e059ad3 100644 --- a/udev_device.c +++ b/udev_device.c @@ -346,7 +346,7 @@ static int find_bit(unsigned long *arr, int cnt, int bit) } for (i = 0; i < cnt; i++) { - if (arr[i] & (1 << (bit % LONG_BIT))) { + if (arr[i] & (1UL << (bit % LONG_BIT))) { return 1; } } @@ -397,9 +397,7 @@ static void udev_device_set_properties_from_evdev(struct udev_device *udev_devic udev_list_entry_add(&udev_device->properties, "ID_INPUT_POINTINGSTICK", "1", 0); } - if (find_bit(prop_bits, prop_cnt, INPUT_PROP_ACCELEROMETER) || - (find_bit(abs_bits, abs_cnt, ABS_Z) && !find_bit(ev_bits, ev_cnt, EV_KEY) && - find_bit(abs_bits, abs_cnt, ABS_Y) && find_bit(abs_bits, abs_cnt, ABS_X))) { + if (find_bit(prop_bits, prop_cnt, INPUT_PROP_ACCELEROMETER)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_ACCELEROMETER", "1", 0); } @@ -407,26 +405,37 @@ static void udev_device_set_properties_from_evdev(struct udev_device *udev_devic udev_list_entry_add(&udev_device->properties, "ID_INPUT_SWITCH", "1", 0); } - if (find_bit(ev_bits, ev_cnt, EV_REL) && find_bit(rel_bits, rel_cnt, REL_Y) && - find_bit(rel_bits, rel_cnt, REL_X) && find_bit(key_bits, key_cnt, BTN_MOUSE)) { - udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1", 0); - } - else if (find_bit(ev_bits, ev_cnt, EV_ABS) && find_bit(abs_bits, abs_cnt, ABS_Y) && find_bit(abs_bits, abs_cnt, ABS_X)) { - if (find_bit(key_bits, key_cnt, BTN_STYLUS) || find_bit(key_bits, key_cnt, BTN_TOOL_PEN)) { - udev_list_entry_add(&udev_device->properties, "ID_INPUT_TABLET", "1", 0); - } - else if (find_bit(key_bits, key_cnt, BTN_TOUCH)) { - if (find_bit(key_bits, key_cnt, BTN_TOOL_FINGER)) { - udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHPAD", "1", 0); - } - else { - udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHSCREEN", "1", 0); - } - } - else if (find_bit(key_bits, key_cnt, BTN_MOUSE)) { + if (find_bit(ev_bits, ev_cnt, EV_REL)) { + if (find_bit(rel_bits, rel_cnt, REL_Y) && find_bit(rel_bits, rel_cnt, REL_X) && + find_bit(key_bits, key_cnt, BTN_MOUSE)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1", 0); } } + else if (find_bit(ev_bits, ev_cnt, EV_ABS)) { + if (find_bit(key_bits, key_cnt, BTN_SELECT) || find_bit(key_bits, key_cnt, BTN_TR) || + find_bit(key_bits, key_cnt, BTN_START) || find_bit(key_bits, key_cnt, BTN_TL)) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_JOYSTICK", "1", 0); + } + else if (find_bit(abs_bits, abs_cnt, ABS_Y) && find_bit(abs_bits, abs_cnt, ABS_X)) { + if (find_bit(abs_bits, abs_cnt, ABS_Z) && !find_bit(ev_bits, ev_cnt, EV_KEY)) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_ACCELEROMETER", "1", 0); + } + else if (find_bit(key_bits, key_cnt, BTN_STYLUS) || find_bit(key_bits, key_cnt, BTN_TOOL_PEN)) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_TABLET", "1", 0); + } + else if (find_bit(key_bits, key_cnt, BTN_TOUCH)) { + if (find_bit(key_bits, key_cnt, BTN_TOOL_FINGER)) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHPAD", "1", 0); + } + else { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHSCREEN", "1", 0); + } + } + else if (find_bit(key_bits, key_cnt, BTN_MOUSE)) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1", 0); + } + } + } else if (find_bit(ev_bits, ev_cnt, EV_KEY)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEY", "1", 0); From 380e7f889018d5faaca4eebc2c615ef92c27ac2b Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 14 Aug 2020 19:33:18 +0300 Subject: [PATCH 090/222] implement hotplugging support --- udev.h | 3 + udev_device.c | 99 +++++++++++++++++++----- udev_monitor.c | 204 ++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 278 insertions(+), 28 deletions(-) diff --git a/udev.h b/udev.h index b8b2454..08188ea 100644 --- a/udev.h +++ b/udev.h @@ -96,6 +96,9 @@ struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb); struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb); struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags); +// this is "libudev-zero" extension. do not use if portability is concern +struct udev_device *udev_device_new_from_file(struct udev *udev, const char *path); + #ifdef __cplusplus } #endif diff --git a/udev_device.c b/udev_device.c index e059ad3..a897cb3 100644 --- a/udev_device.c +++ b/udev_device.c @@ -9,7 +9,7 @@ #include "udev.h" #include "udev_list.h" -enum { BITS_SIZE = 96 }; +enum { BITS_MAX = 96 }; struct udev_device { struct udev_list_entry properties; @@ -148,7 +148,7 @@ int udev_device_get_is_initialized(struct udev_device *udev_device) const char *udev_device_get_action(struct udev_device *udev_device) { - return NULL; + return udev_device_get_property_value(udev_device, "ACTION"); } int udev_device_has_tag(struct udev_device *udev_device, const char *tag) @@ -328,7 +328,7 @@ static int populate_bit(unsigned long *arr, const char *val) bit = strtok_r(bits, " ", &save); - for (i = 0; bit && i < BITS_SIZE; i++) { + for (i = 0; bit && i < BITS_MAX; i++) { arr[i] = strtoul(bit, NULL, 16); bit = strtok_r(NULL, " ", &save); } @@ -357,12 +357,12 @@ static int find_bit(unsigned long *arr, int cnt, int bit) static void udev_device_set_properties_from_evdev(struct udev_device *udev_device) { int ev_cnt, rel_cnt, key_cnt, abs_cnt, prop_cnt; - unsigned long prop_bits[BITS_SIZE] = {0}; - unsigned long abs_bits[BITS_SIZE] = {0}; - unsigned long rel_bits[BITS_SIZE] = {0}; - unsigned long key_bits[BITS_SIZE] = {0}; - unsigned long ev_bits[BITS_SIZE] = {0}; - struct udev_device *parent; + unsigned long prop_bits[BITS_MAX] = {0}; + unsigned long abs_bits[BITS_MAX] = {0}; + unsigned long rel_bits[BITS_MAX] = {0}; + unsigned long key_bits[BITS_MAX] = {0}; + unsigned long ev_bits[BITS_MAX] = {0}; + struct udev_device *tmp; const char *subsystem; subsystem = udev_device_get_subsystem(udev_device); @@ -371,25 +371,25 @@ static void udev_device_set_properties_from_evdev(struct udev_device *udev_devic return; } - parent = udev_device_get_parent_with_subsystem_devtype(udev_device, "input", NULL); + tmp = udev_device; while (1) { - if (!parent) { + if (!tmp) { return; } - if (udev_device_get_property_value(parent, "EV")) { + if (udev_device_get_property_value(tmp, "EV")) { break; } - parent = udev_device_get_parent_with_subsystem_devtype(parent, "input", NULL); + tmp = udev_device_get_parent_with_subsystem_devtype(tmp, "input", NULL); } - ev_cnt = populate_bit(ev_bits, udev_device_get_property_value(parent, "EV")); - abs_cnt = populate_bit(abs_bits, udev_device_get_property_value(parent, "ABS")); - rel_cnt = populate_bit(rel_bits, udev_device_get_property_value(parent, "REL")); - key_cnt = populate_bit(key_bits, udev_device_get_property_value(parent, "KEY")); - prop_cnt = populate_bit(prop_bits, udev_device_get_property_value(parent, "PROP")); + ev_cnt = populate_bit(ev_bits, udev_device_get_property_value(tmp, "EV")); + abs_cnt = populate_bit(abs_bits, udev_device_get_property_value(tmp, "ABS")); + rel_cnt = populate_bit(rel_bits, udev_device_get_property_value(tmp, "REL")); + key_cnt = populate_bit(key_bits, udev_device_get_property_value(tmp, "KEY")); + prop_cnt = populate_bit(prop_bits, udev_device_get_property_value(tmp, "PROP")); udev_list_entry_add(&udev_device->properties, "ID_INPUT", "1", 0); @@ -548,6 +548,69 @@ struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, co return NULL; } +struct udev_device *udev_device_new_from_file(struct udev *udev, const char *path) +{ + char line[LINE_MAX], tmp[PATH_MAX]; + struct udev_device *udev_device; + char *key, *val, *sysname; + FILE *file; + int i; + + udev_device = calloc(1, sizeof(struct udev_device)); + + if (!udev_device) { + return NULL; + } + + udev_device->udev = udev; + udev_device->refcount = 1; + udev_device->parent = NULL; + + udev_list_entry_init(&udev_device->properties); + udev_list_entry_init(&udev_device->sysattrs); + + file = fopen(path, "r"); + + if (!file) { + return NULL; + } + + while (fgets(line, sizeof(line), file)) { + line[strcspn(line, "\n")] = '\0'; + + if (strncmp(line, "DEVPATH", 7) == 0) { + snprintf(tmp, sizeof(tmp), "/sys%s", line + 8); + udev_list_entry_add(&udev_device->properties, "SYSPATH", tmp, 0); + udev_list_entry_add(&udev_device->properties, "DEVPATH", line + 8, 0); + } + else if (strncmp(line, "DEVNAME", 7) == 0) { + snprintf(tmp, sizeof(tmp), "/dev/%s", line + 8); + udev_list_entry_add(&udev_device->properties, "DEVNAME", tmp, 0); + } + else if (strchr(line, '=')) { + val = strchr(line, '=') + 1; + key = line; + key[strcspn(key, "=")] = '\0'; + + udev_list_entry_add(&udev_device->properties, key, val, 1); + } + } + + fclose(file); + sysname = strrchr(udev_device_get_syspath(udev_device), '/'); + + for (i = 0; sysname[i] != '\0'; i++) { + if (sysname[i] >= '0' && sysname[i] <= '9') { + udev_list_entry_add(&udev_device->properties, "SYSNUM", sysname + i, 0); + break; + } + } + + udev_list_entry_add(&udev_device->properties, "SYSNAME", sysname, 0); + udev_device_set_properties_from_evdev(udev_device); + return udev_device; +} + struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id) { // XXX NOT IMPLEMENTED diff --git a/udev_monitor.c b/udev_monitor.c index 1e88b70..3749817 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -1,33 +1,128 @@ -#include +#include +#include +#include #include #include +#include +#include +#include +#include +#include #include "udev.h" +#include "udev_list.h" + +#ifndef UDEV_MONITOR_DIR +#define UDEV_MONITOR_DIR "/tmp/.libudev-zero" +#endif + +enum { THREADS_MAX = 5 }; struct udev_monitor { + struct udev_list_entry subsystem_match; + struct udev_list_entry devtype_match; + pthread_t thread[THREADS_MAX]; struct udev *udev; int refcount; - int fd[2]; + int sfd[2]; + int ifd; + int efd; }; +static int udev_monitor_filter_devtype(struct udev_monitor *udev_monitor, struct udev_device *udev_device) +{ + struct udev_list_entry *list_entry; + const char *devtype; + + devtype = udev_device_get_devtype(udev_device); + list_entry = udev_list_entry_get_next(&udev_monitor->devtype_match); + + if (!list_entry) { + return 1; + } + + if (!devtype) { + return 0; + } + + while (list_entry) { + if (strcmp(devtype, udev_list_entry_get_name(list_entry)) == 0) { + return 1; + } + + list_entry = udev_list_entry_get_next(list_entry); + } + + return 0; +} + +static int udev_monitor_filter_subsystem(struct udev_monitor *udev_monitor, 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_monitor->subsystem_match); + + if (!list_entry) { + return 1; + } + + if (!subsystem) { + return 0; + } + + while (list_entry) { + if (strcmp(subsystem, udev_list_entry_get_name(list_entry)) == 0) { + return 1; + } + + list_entry = udev_list_entry_get_next(list_entry); + } + + return 0; +} + struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor) { - return (void *)1; + char file[PATH_MAX + sizeof(UDEV_MONITOR_DIR)], data[4096]; + struct udev_device *udev_device; + + if (recv(udev_monitor->sfd[0], data, sizeof(data), 0) == -1) { + return NULL; + } + + snprintf(file, sizeof(file), UDEV_MONITOR_DIR "/%s", data); + udev_device = udev_device_new_from_file(udev_monitor->udev, file); + + if (!udev_device) { + return NULL; + } + + if (!udev_monitor_filter_subsystem(udev_monitor, udev_device) || + !udev_monitor_filter_devtype(udev_monitor, udev_device)) { + udev_device_unref(udev_device); + return NULL; + } + + return NULL; } int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) { + // TODO pthread_create should be here return 0; } int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size) { + // XXX NOT IMPLEMENTED return 0; } int udev_monitor_get_fd(struct udev_monitor *udev_monitor) { - return udev_monitor ? udev_monitor->fd[0] : -1; + return udev_monitor ? udev_monitor->sfd[0] : -1; } struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor) @@ -37,27 +132,71 @@ struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor) int udev_monitor_filter_update(struct udev_monitor *udev_monitor) { + // XXX NOT IMPLEMENTED return 0; } int udev_monitor_filter_remove(struct udev_monitor *udev_monitor) { + // XXX NOT IMPLEMENTED return 0; } int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor, const char *subsystem, const char *devtype) { + if (!udev_monitor || !subsystem) { + return -1; + } + + udev_list_entry_add(&udev_monitor->subsystem_match, subsystem, NULL, 0); + + if (devtype) { + udev_list_entry_add(&udev_monitor->devtype_match, devtype, NULL, 0); + } + return 0; } int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag) { + // XXX NOT IMPLEMENTED return 0; } +static void *udev_monitor_handle_event(void *ptr) +{ + struct udev_monitor *udev_monitor = ptr; + struct inotify_event *event; + struct epoll_event epoll; + char data[4096]; + sigset_t mask; + ssize_t len; + int i; + + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + + while (epoll_pwait(udev_monitor->efd, &epoll, 1, -1, &mask) != -1) { + len = read(udev_monitor->ifd, data, sizeof(data)); + + if (len == -1) { + continue; + } + + for (i = 0; i < len; i += sizeof(struct inotify_event) + event->len) { + event = (struct inotify_event *)&data[i]; + send(udev_monitor->sfd[1], event->name, event->len, 0); + } + } + + return NULL; +} + struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name) { struct udev_monitor *udev_monitor; + struct epoll_event epoll; + pthread_attr_t attr; int i; if (!udev || !name) { @@ -70,16 +209,51 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char return NULL; } - // TODO better no-op, HELP WANTED ! - if (pipe(udev_monitor->fd) == -1) { + udev_monitor->ifd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK); + + if (udev_monitor->ifd == -1) { free(udev_monitor); return NULL; } - for (i = 0; i < 2; i++) { - fcntl(udev_monitor->fd[i], F_SETFD, FD_CLOEXEC | O_NONBLOCK); + if (inotify_add_watch(udev_monitor->ifd, UDEV_MONITOR_DIR, IN_CREATE) == -1) { + close(udev_monitor->ifd); + free(udev_monitor); + return NULL; } + udev_monitor->efd = epoll_create1(EPOLL_CLOEXEC); + + if (udev_monitor->efd == -1) { + close(udev_monitor->ifd); + free(udev_monitor); + return NULL; + } + + epoll.events = EPOLLIN | EPOLLET; + + if (epoll_ctl(udev_monitor->efd, EPOLL_CTL_ADD, udev_monitor->ifd, &epoll) == -1) { + close(udev_monitor->ifd); + close(udev_monitor->efd); + free(udev_monitor); + return NULL; + } + + if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, udev_monitor->sfd) == -1) { + close(udev_monitor->ifd); + close(udev_monitor->efd); + free(udev_monitor); + return NULL; + } + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + for (i = 0; i < THREADS_MAX; i++) { + pthread_create(&udev_monitor->thread[i], &attr, udev_monitor_handle_event, udev_monitor); + } + + pthread_attr_destroy(&attr); udev_monitor->refcount = 1; udev_monitor->udev = udev; return udev_monitor; @@ -107,10 +281,20 @@ struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor) return NULL; } - for (i = 0; i < 2; i++) { - close(udev_monitor->fd[i]); + udev_list_entry_free_all(&udev_monitor->devtype_match); + udev_list_entry_free_all(&udev_monitor->subsystem_match); + + // TODO fix possible race condition and UB + for (i = 0; i < THREADS_MAX; i++) { + pthread_kill(udev_monitor->thread[i], SIGUSR1); } + for (i = 0; i < 2; i++) { + close(udev_monitor->sfd[i]); + } + + close(udev_monitor->ifd); + close(udev_monitor->efd); free(udev_monitor); return NULL; } From 3029436ea67a6d843e49477d6aa3d27cb7f9020a Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 14 Aug 2020 19:44:05 +0300 Subject: [PATCH 091/222] oops --- udev_monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udev_monitor.c b/udev_monitor.c index 3749817..d7788d3 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -105,7 +105,7 @@ struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monito return NULL; } - return NULL; + return udev_device; } int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) From 508424a3a2cead3c2ccf262ace44f8919e9ec981 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 15 Aug 2020 07:39:02 +0300 Subject: [PATCH 092/222] fix sysname --- udev_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udev_device.c b/udev_device.c index a897cb3..bd1c55b 100644 --- a/udev_device.c +++ b/udev_device.c @@ -597,7 +597,7 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat } fclose(file); - sysname = strrchr(udev_device_get_syspath(udev_device), '/'); + sysname = strrchr(udev_device_get_syspath(udev_device), '/') + 1; for (i = 0; sysname[i] != '\0'; i++) { if (sysname[i] >= '0' && sysname[i] <= '9') { From f8c3526a631beb96d37a6bbe2587105b652d6622 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 15 Aug 2020 07:56:36 +0300 Subject: [PATCH 093/222] move pthread_create to udev_device_enable_receiving --- udev_monitor.c | 84 ++++++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/udev_monitor.c b/udev_monitor.c index d7788d3..5f7cb91 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -108,9 +108,52 @@ struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monito return udev_device; } +static void *udev_monitor_handle_event(void *ptr) +{ + struct udev_monitor *udev_monitor = ptr; + struct inotify_event *event; + struct epoll_event epoll; + char data[4096]; + sigset_t mask; + ssize_t len; + int i; + + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + + while (epoll_pwait(udev_monitor->efd, &epoll, 1, -1, &mask) != -1) { + len = read(udev_monitor->ifd, data, sizeof(data)); + + if (len == -1) { + continue; + } + + for (i = 0; i < len; i += sizeof(struct inotify_event) + event->len) { + event = (struct inotify_event *)&data[i]; + send(udev_monitor->sfd[1], event->name, event->len, 0); + } + } + + return NULL; +} + int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) { - // TODO pthread_create should be here + pthread_attr_t attr; + int i; + + if (!udev_monitor) { + return -1; + } + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + for (i = 0; i < THREADS_MAX; i++) { + pthread_create(&udev_monitor->thread[i], &attr, udev_monitor_handle_event, udev_monitor); + } + + pthread_attr_destroy(&attr); return 0; } @@ -163,41 +206,10 @@ int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const c return 0; } -static void *udev_monitor_handle_event(void *ptr) -{ - struct udev_monitor *udev_monitor = ptr; - struct inotify_event *event; - struct epoll_event epoll; - char data[4096]; - sigset_t mask; - ssize_t len; - int i; - - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - - while (epoll_pwait(udev_monitor->efd, &epoll, 1, -1, &mask) != -1) { - len = read(udev_monitor->ifd, data, sizeof(data)); - - if (len == -1) { - continue; - } - - for (i = 0; i < len; i += sizeof(struct inotify_event) + event->len) { - event = (struct inotify_event *)&data[i]; - send(udev_monitor->sfd[1], event->name, event->len, 0); - } - } - - return NULL; -} - struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name) { struct udev_monitor *udev_monitor; struct epoll_event epoll; - pthread_attr_t attr; - int i; if (!udev || !name) { return NULL; @@ -246,14 +258,6 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char return NULL; } - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - for (i = 0; i < THREADS_MAX; i++) { - pthread_create(&udev_monitor->thread[i], &attr, udev_monitor_handle_event, udev_monitor); - } - - pthread_attr_destroy(&attr); udev_monitor->refcount = 1; udev_monitor->udev = udev; return udev_monitor; From f1388e805d13c9203861a592fb38ec7b7965eb36 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 15 Aug 2020 10:53:14 +0300 Subject: [PATCH 094/222] create UDEV_MONITOR_DIR --- udev_monitor.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/udev_monitor.c b/udev_monitor.c index 5f7cb91..0b44766 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -210,6 +211,7 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char { struct udev_monitor *udev_monitor; struct epoll_event epoll; + struct stat st; if (!udev || !name) { return NULL; @@ -221,6 +223,22 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char return NULL; } + if (lstat(UDEV_MONITOR_DIR, &st) != 0) { + if (mkdir(UDEV_MONITOR_DIR, 0) == -1) { + free(udev_monitor); + return NULL; + } + + if (chmod(UDEV_MONITOR_DIR, 0777) == -1) { + free(udev_monitor); + return NULL; + } + } + else if (!S_ISDIR(st.st_mode)) { + free(udev_monitor); + return NULL; + } + udev_monitor->ifd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK); if (udev_monitor->ifd == -1) { From ca2fb1d5faf4729c77a809833f2b96e06bba3b39 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 15 Aug 2020 11:36:12 +0300 Subject: [PATCH 095/222] update readme --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6105d9d..a26abc5 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ What Works * [x] libinput * [x] wlroots * [x] weston -* [ ] libusb - doesn't work for now. temporary workaround is compiling libusb with --disable-udev +* [x] libusb * [x] kwin - [fix](https://github.com/dilyn-corner/KISS-kde/commit/0cc72748e46f859a0fced55b0c3fcc1dd9586a38) * [ ] ??? @@ -19,6 +19,7 @@ Dependencies * C99 compiler (build time) * POSIX make (build time) * POSIX & XSI libc +* epoll & inotify * Linux >= 2.6.39 Installation @@ -36,7 +37,7 @@ TODO * [x] speed up performance * [x] extend devices support -* [ ] implement hotplugging support +* [x] implement hotplugging support Donate ------ From 752f500a90360e7b0815866f59b915ca67baee0d Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 15 Aug 2020 12:20:24 +0300 Subject: [PATCH 096/222] grab properties from uevent --- udev_device.c | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/udev_device.c b/udev_device.c index bd1c55b..a217c94 100644 --- a/udev_device.c +++ b/udev_device.c @@ -297,7 +297,7 @@ static void udev_device_set_properties_from_uevent(struct udev_device *udev_devi if (strncmp(line, "DEVNAME", 7) == 0) { snprintf(devnode, sizeof(devnode), "/dev/%s", line + 8); - udev_list_entry_add(&udev_device->properties, "DEVNAME", devnode, 0); + udev_list_entry_add(&udev_device->properties, "DEVNAME", devnode, 1); } else if (strchr(line, '=')) { val = strchr(line, '=') + 1; @@ -551,8 +551,9 @@ struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, co struct udev_device *udev_device_new_from_file(struct udev *udev, const char *path) { char line[LINE_MAX], tmp[PATH_MAX]; + char *subsystem, *driver, *sysname; struct udev_device *udev_device; - char *key, *val, *sysname; + char *key, *val; FILE *file; int i; @@ -582,6 +583,16 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat snprintf(tmp, sizeof(tmp), "/sys%s", line + 8); udev_list_entry_add(&udev_device->properties, "SYSPATH", tmp, 0); udev_list_entry_add(&udev_device->properties, "DEVPATH", line + 8, 0); + + sysname = strrchr(tmp, '/') + 1; + udev_list_entry_add(&udev_device->properties, "SYSNAME", sysname, 0); + + for (i = 0; sysname[i] != '\0'; i++) { + if (sysname[i] >= '0' && sysname[i] <= '9') { + udev_list_entry_add(&udev_device->properties, "SYSNUM", sysname + i, 0); + break; + } + } } else if (strncmp(line, "DEVNAME", 7) == 0) { snprintf(tmp, sizeof(tmp), "/dev/%s", line + 8); @@ -596,18 +607,28 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat } } - fclose(file); - sysname = strrchr(udev_device_get_syspath(udev_device), '/') + 1; + if (!udev_device_get_driver(udev_device)) { + driver = udev_device_read_symlink(udev_device, "driver"); - for (i = 0; sysname[i] != '\0'; i++) { - if (sysname[i] >= '0' && sysname[i] <= '9') { - udev_list_entry_add(&udev_device->properties, "SYSNUM", sysname + i, 0); - break; + if (driver) { + udev_list_entry_add(&udev_device->properties, "DRIVER", driver, 0); + free(driver); } } - udev_list_entry_add(&udev_device->properties, "SYSNAME", sysname, 0); + if (!udev_device_get_subsystem(udev_device)) { + subsystem = udev_device_read_symlink(udev_device, "subsystem"); + + if (subsystem) { + udev_list_entry_add(&udev_device->properties, "SUBSYSTEM", subsystem, 0); + free(subsystem); + } + } + + udev_device_set_properties_from_uevent(udev_device); udev_device_set_properties_from_evdev(udev_device); + + fclose(file); return udev_device; } From 0105b25e70eba69938362d673865620ad89e2f9f Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 15 Aug 2020 15:49:36 +0300 Subject: [PATCH 097/222] add examples --- contrib/helper.sh | 13 +++++++++++++ contrib/mdev.conf | 13 +++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 contrib/helper.sh create mode 100644 contrib/mdev.conf diff --git a/contrib/helper.sh b/contrib/helper.sh new file mode 100644 index 0000000..ef9877a --- /dev/null +++ b/contrib/helper.sh @@ -0,0 +1,13 @@ +#!/bin/sh -f +# +# this helper required for CONFIG_UEVENT_HELPER aka /proc/sys/kernel/hotplug +# for mdev you can use simple one-liner, refer to mdev.conf for more info +# +# usage: +# echo /full/path/to/helper.sh > /proc/sys/kernel/hotplug +# echo "/full/path/to/helper.sh UDEV_MONITOR_DIR" > /proc/sys/kernel/hotplug +# + +# NOTE: writing variables to file (e.g PWD or PATH) +# that are not related to uevent properties is harmless +env > "${1:-/tmp/.libudev-zero}/uevent.$$" diff --git a/contrib/mdev.conf b/contrib/mdev.conf new file mode 100644 index 0000000..ff5334c --- /dev/null +++ b/contrib/mdev.conf @@ -0,0 +1,13 @@ +# +# example basic mdev config representing libudev-zero usage +# uncomment needed rules +# +# NOTE: you must change "/tmp/.libudev-zero" if you use non-default UDEV_MONITOR_DIR +# NOTE: mdev can only handle ADD and/or REMOVE events + +# will handle all uevents +#-.* root:root 660 *env > /tmp/.libudev-zero/uevent.$$ + +# will handle only drm and input uevents (recommended) +#SUBSYSTEM=drm;.* root:video 660 *env > /tmp/.libudev-zero/uevent.$$ +#SUBSYSTEM=input;.* root:input 660 *env > /tmp/.libudev-zero/uevent.$$ From 408249b34b26801f604b6574e07168ae9aadfeea Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 16 Aug 2020 12:53:13 +0300 Subject: [PATCH 098/222] simplify key=val parsing --- udev_device.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/udev_device.c b/udev_device.c index a217c94..7256df5 100644 --- a/udev_device.c +++ b/udev_device.c @@ -282,7 +282,7 @@ static char *udev_device_read_symlink(struct udev_device *udev_device, const cha static void udev_device_set_properties_from_uevent(struct udev_device *udev_device) { char line[LINE_MAX], path[PATH_MAX]; - char *key, *val, devnode[PATH_MAX]; + char *pos, devnode[PATH_MAX]; FILE *file; snprintf(path, sizeof(path), "%s/uevent", udev_device_get_syspath(udev_device)); @@ -299,12 +299,9 @@ static void udev_device_set_properties_from_uevent(struct udev_device *udev_devi snprintf(devnode, sizeof(devnode), "/dev/%s", line + 8); udev_list_entry_add(&udev_device->properties, "DEVNAME", devnode, 1); } - else if (strchr(line, '=')) { - val = strchr(line, '=') + 1; - key = line; - key[strcspn(key, "=")] = '\0'; - - udev_list_entry_add(&udev_device->properties, key, val, 1); + else if ((pos = strchr(line, '='))) { + *pos = '\0'; + udev_list_entry_add(&udev_device->properties, line, pos + 1, 1); } } @@ -553,8 +550,8 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat char line[LINE_MAX], tmp[PATH_MAX]; char *subsystem, *driver, *sysname; struct udev_device *udev_device; - char *key, *val; FILE *file; + char *pos; int i; udev_device = calloc(1, sizeof(struct udev_device)); @@ -598,12 +595,9 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat snprintf(tmp, sizeof(tmp), "/dev/%s", line + 8); udev_list_entry_add(&udev_device->properties, "DEVNAME", tmp, 0); } - else if (strchr(line, '=')) { - val = strchr(line, '=') + 1; - key = line; - key[strcspn(key, "=")] = '\0'; - - udev_list_entry_add(&udev_device->properties, key, val, 1); + else if ((pos = strchr(line, '='))) { + *pos = '\0'; + udev_list_entry_add(&udev_device->properties, line, pos + 1, 1); } } From bcd28de8583f40ec64dd234ac8e28d3b2bd44e9b Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 16 Aug 2020 14:00:03 +0300 Subject: [PATCH 099/222] fix potential UB while reading sysattr --- udev_device.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/udev_device.c b/udev_device.c index 7256df5..92019ae 100644 --- a/udev_device.c +++ b/udev_device.c @@ -193,7 +193,9 @@ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const struct udev_list_entry *list_entry; char data[BUFSIZ], path[PATH_MAX]; struct stat st; + size_t len; FILE *file; + char *pos; if (!udev_device || !sysattr) { return NULL; @@ -217,13 +219,21 @@ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const return NULL; } - if (fread(data, 1, sizeof(data), file) != sizeof(data) && ferror(file)) { + len = fread(data, 1, sizeof(data), file); + + if (len != sizeof(data) && ferror(file)) { fclose(file); return NULL; } + if ((pos = memchr(data, '\n', len))) { + *pos = '\0'; + } + else { + data[len] = '\0'; + } + fclose(file); - data[strcspn(data, "\n")] = '\0'; list_entry = udev_list_entry_add(&udev_device->sysattrs, sysattr, data, 0); return udev_list_entry_get_value(list_entry); } From f6afe3602b2a595af547ec190a1fa76cae8d2e87 Mon Sep 17 00:00:00 2001 From: illiliti Date: Mon, 17 Aug 2020 16:57:50 +0300 Subject: [PATCH 100/222] eliminate race conditions --- udev_monitor.c | 105 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 33 deletions(-) diff --git a/udev_monitor.c b/udev_monitor.c index 0b44766..c434ad8 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -23,9 +24,11 @@ struct udev_monitor { struct udev_list_entry subsystem_match; struct udev_list_entry devtype_match; pthread_t thread[THREADS_MAX]; + pthread_barrier_t barrier; struct udev *udev; int refcount; int sfd[2]; + int pfd[2]; int ifd; int efd; }; @@ -113,16 +116,26 @@ static void *udev_monitor_handle_event(void *ptr) { struct udev_monitor *udev_monitor = ptr; struct inotify_event *event; - struct epoll_event epoll; + struct epoll_event epoll[2]; char data[4096]; sigset_t mask; ssize_t len; int i; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); + sigfillset(&mask); + pthread_sigmask(SIG_BLOCK, &mask, NULL); + + while (epoll_wait(udev_monitor->efd, epoll, 2, -1) != -1) { + for (i = 0; i < 2; i++) { + if (epoll[i].data.fd == udev_monitor->pfd[0]) { + read(udev_monitor->pfd[0], data, sizeof(data)); + write(udev_monitor->pfd[1], "1", 1); + + pthread_barrier_wait(&udev_monitor->barrier); + return NULL; + } + } - while (epoll_pwait(udev_monitor->efd, &epoll, 1, -1, &mask) != -1) { len = read(udev_monitor->ifd, data, sizeof(data)); if (len == -1) { @@ -135,6 +148,7 @@ static void *udev_monitor_handle_event(void *ptr) } } + pthread_barrier_wait(&udev_monitor->barrier); return NULL; } @@ -149,6 +163,7 @@ int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_barrier_init(&udev_monitor->barrier, NULL, THREADS_MAX + 1); for (i = 0; i < THREADS_MAX; i++) { pthread_create(&udev_monitor->thread[i], &attr, udev_monitor_handle_event, udev_monitor); @@ -210,8 +225,9 @@ int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const c struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name) { struct udev_monitor *udev_monitor; - struct epoll_event epoll; + struct epoll_event epoll[2]; struct stat st; + int i; if (!udev || !name) { return NULL; @@ -224,12 +240,8 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char } if (lstat(UDEV_MONITOR_DIR, &st) != 0) { - if (mkdir(UDEV_MONITOR_DIR, 0) == -1) { - free(udev_monitor); - return NULL; - } - - if (chmod(UDEV_MONITOR_DIR, 0777) == -1) { + if (mkdir(UDEV_MONITOR_DIR, 0) == -1 || + chmod(UDEV_MONITOR_DIR, 0777) == -1) { free(udev_monitor); return NULL; } @@ -239,37 +251,63 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char return NULL; } - udev_monitor->ifd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK); - - if (udev_monitor->ifd == -1) { - free(udev_monitor); - return NULL; - } - - if (inotify_add_watch(udev_monitor->ifd, UDEV_MONITOR_DIR, IN_CREATE) == -1) { - close(udev_monitor->ifd); - free(udev_monitor); - return NULL; - } - udev_monitor->efd = epoll_create1(EPOLL_CLOEXEC); if (udev_monitor->efd == -1) { - close(udev_monitor->ifd); free(udev_monitor); return NULL; } - epoll.events = EPOLLIN | EPOLLET; + udev_monitor->ifd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK); - if (epoll_ctl(udev_monitor->efd, EPOLL_CTL_ADD, udev_monitor->ifd, &epoll) == -1) { + if (udev_monitor->ifd == -1) { + close(udev_monitor->efd); + free(udev_monitor); + return NULL; + } + + if (inotify_add_watch(udev_monitor->ifd, UDEV_MONITOR_DIR, IN_CLOSE_WRITE) == -1) { close(udev_monitor->ifd); close(udev_monitor->efd); free(udev_monitor); return NULL; } - if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, udev_monitor->sfd) == -1) { + if (pipe(udev_monitor->pfd) == -1) { + close(udev_monitor->ifd); + close(udev_monitor->efd); + free(udev_monitor); + return NULL; + } + + for (i = 0; i < 2; i++) { + fcntl(udev_monitor->pfd[i], F_SETFD, FD_CLOEXEC); + fcntl(udev_monitor->pfd[i], F_SETFL, O_NONBLOCK); + } + + for (i = 0; i < 2; i++) { + epoll[i].events = EPOLLIN | EPOLLET; + } + + epoll[1].data.fd = udev_monitor->pfd[0]; + + if (epoll_ctl(udev_monitor->efd, EPOLL_CTL_ADD, udev_monitor->ifd, &epoll[0]) == -1 || + epoll_ctl(udev_monitor->efd, EPOLL_CTL_ADD, udev_monitor->pfd[0], &epoll[1]) == -1) { + for (i = 0; i < 2; i++) { + close(udev_monitor->pfd[i]); + } + + close(udev_monitor->ifd); + close(udev_monitor->efd); + free(udev_monitor); + return NULL; + } + + if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, udev_monitor->sfd) == -1) { + for (i = 0; i < 2; i++) { + close(udev_monitor->pfd[i]); + } + close(udev_monitor->ifd); close(udev_monitor->efd); free(udev_monitor); @@ -303,16 +341,17 @@ struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor) return NULL; } - udev_list_entry_free_all(&udev_monitor->devtype_match); udev_list_entry_free_all(&udev_monitor->subsystem_match); + udev_list_entry_free_all(&udev_monitor->devtype_match); - // TODO fix possible race condition and UB - for (i = 0; i < THREADS_MAX; i++) { - pthread_kill(udev_monitor->thread[i], SIGUSR1); - } + write(udev_monitor->pfd[1], "1", 1); + + pthread_barrier_wait(&udev_monitor->barrier); + pthread_barrier_destroy(&udev_monitor->barrier); for (i = 0; i < 2; i++) { close(udev_monitor->sfd[i]); + close(udev_monitor->pfd[i]); } close(udev_monitor->ifd); From b17173163f73be305b79e72377e4a5dd2d1e582d Mon Sep 17 00:00:00 2001 From: illiliti Date: Mon, 17 Aug 2020 17:30:07 +0300 Subject: [PATCH 101/222] drop sizeof --- udev_monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udev_monitor.c b/udev_monitor.c index c434ad8..9ceebdb 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -128,7 +128,7 @@ static void *udev_monitor_handle_event(void *ptr) while (epoll_wait(udev_monitor->efd, epoll, 2, -1) != -1) { for (i = 0; i < 2; i++) { if (epoll[i].data.fd == udev_monitor->pfd[0]) { - read(udev_monitor->pfd[0], data, sizeof(data)); + read(udev_monitor->pfd[0], data, 1); write(udev_monitor->pfd[1], "1", 1); pthread_barrier_wait(&udev_monitor->barrier); From b53bb9eb8266c72e1f4a03fa78113bef8e8ed717 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 18 Aug 2020 12:28:22 +0300 Subject: [PATCH 102/222] add helper.c --- contrib/helper.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ udev_monitor.c | 2 +- 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 contrib/helper.c diff --git a/contrib/helper.c b/contrib/helper.c new file mode 100644 index 0000000..ba46094 --- /dev/null +++ b/contrib/helper.c @@ -0,0 +1,63 @@ +/* + * this helper pretty similar to helper.sh, but it + * doesn't write unrelated variables to file (e.g PWD or PATH) + * + * build: + * cc helper.c -o helper + * + * usage: + * echo /full/path/to/helper > /proc/sys/kernel/hotplug + * echo "/full/path/to/helper UDEV_MONITOR_DIR" > /proc/sys/kernel/hotplug + */ + +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + extern char **environ; + char path[PATH_MAX]; + char *dir; + int fd, i; + + switch (argc) { + case 1: + dir = "/tmp/.libudev-zero"; + break; + case 2: + dir = argv[1]; + break; + default: + fprintf(stderr, "usage: %s [dir]\n", argv[0]); + return 1; + } + + snprintf(path, sizeof(path), "%s/uevent.XXXXXX", dir); + fd = mkstemp(path); + + if (fd == -1) { + perror("mkstemp"); + return 1; + } + + for (i = 0; environ[i]; i++) { + if (strncmp(environ[i], "PATH", 4) == 0 || + strncmp(environ[i], "HOME", 4) == 0) { + continue; + } + + if (write(fd, environ[i], strlen(environ[i])) == -1 || + write(fd, "\n", 1) == -1) { + perror("write"); + close(fd); + unlink(path); + return 1; + } + } + + close(fd); + return 0; +} diff --git a/udev_monitor.c b/udev_monitor.c index 9ceebdb..b24479c 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -266,7 +266,7 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char return NULL; } - if (inotify_add_watch(udev_monitor->ifd, UDEV_MONITOR_DIR, IN_CLOSE_WRITE) == -1) { + if (inotify_add_watch(udev_monitor->ifd, UDEV_MONITOR_DIR, IN_CLOSE_WRITE | IN_EXCL_UNLINK) == -1) { close(udev_monitor->ifd); close(udev_monitor->efd); free(udev_monitor); From 25a9dd70b0080d82600cf1eac34e7bc7051a3323 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 19 Aug 2020 13:17:10 +0300 Subject: [PATCH 103/222] replace self-pipe trick with conditional variable --- udev_monitor.c | 89 +++++++++++++++++++++----------------------------- 1 file changed, 37 insertions(+), 52 deletions(-) diff --git a/udev_monitor.c b/udev_monitor.c index b24479c..f527f05 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -24,11 +23,12 @@ struct udev_monitor { struct udev_list_entry subsystem_match; struct udev_list_entry devtype_match; pthread_t thread[THREADS_MAX]; - pthread_barrier_t barrier; + pthread_cond_t condition; + pthread_mutex_t mutex; struct udev *udev; + int thread_alive; int refcount; int sfd[2]; - int pfd[2]; int ifd; int efd; }; @@ -112,30 +112,30 @@ struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monito return udev_device; } +static void udev_monitor_abort_thread(void *ptr) +{ + struct udev_monitor *udev_monitor = ptr; + + pthread_mutex_lock(&udev_monitor->mutex); + udev_monitor->thread_alive--; + pthread_cond_signal(&udev_monitor->condition); + pthread_mutex_unlock(&udev_monitor->mutex); +} + static void *udev_monitor_handle_event(void *ptr) { struct udev_monitor *udev_monitor = ptr; struct inotify_event *event; - struct epoll_event epoll[2]; + struct epoll_event epoll; char data[4096]; sigset_t mask; ssize_t len; int i; - sigfillset(&mask); - pthread_sigmask(SIG_BLOCK, &mask, NULL); - - while (epoll_wait(udev_monitor->efd, epoll, 2, -1) != -1) { - for (i = 0; i < 2; i++) { - if (epoll[i].data.fd == udev_monitor->pfd[0]) { - read(udev_monitor->pfd[0], data, 1); - write(udev_monitor->pfd[1], "1", 1); - - pthread_barrier_wait(&udev_monitor->barrier); - return NULL; - } - } + sigemptyset(&mask); + pthread_cleanup_push(udev_monitor_abort_thread, udev_monitor); + while (epoll_pwait(udev_monitor->efd, &epoll, 1, -1, &mask) != -1) { len = read(udev_monitor->ifd, data, sizeof(data)); if (len == -1) { @@ -148,7 +148,7 @@ static void *udev_monitor_handle_event(void *ptr) } } - pthread_barrier_wait(&udev_monitor->barrier); + pthread_cleanup_pop(1); return NULL; } @@ -161,9 +161,12 @@ int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) return -1; } + udev_monitor->thread_alive = THREADS_MAX; + pthread_attr_init(&attr); + pthread_mutex_init(&udev_monitor->mutex, NULL); + pthread_cond_init(&udev_monitor->condition, NULL); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_barrier_init(&udev_monitor->barrier, NULL, THREADS_MAX + 1); for (i = 0; i < THREADS_MAX; i++) { pthread_create(&udev_monitor->thread[i], &attr, udev_monitor_handle_event, udev_monitor); @@ -225,9 +228,8 @@ int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const c struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name) { struct udev_monitor *udev_monitor; - struct epoll_event epoll[2]; + struct epoll_event epoll; struct stat st; - int i; if (!udev || !name) { return NULL; @@ -273,30 +275,9 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char return NULL; } - if (pipe(udev_monitor->pfd) == -1) { - close(udev_monitor->ifd); - close(udev_monitor->efd); - free(udev_monitor); - return NULL; - } - - for (i = 0; i < 2; i++) { - fcntl(udev_monitor->pfd[i], F_SETFD, FD_CLOEXEC); - fcntl(udev_monitor->pfd[i], F_SETFL, O_NONBLOCK); - } - - for (i = 0; i < 2; i++) { - epoll[i].events = EPOLLIN | EPOLLET; - } - - epoll[1].data.fd = udev_monitor->pfd[0]; - - if (epoll_ctl(udev_monitor->efd, EPOLL_CTL_ADD, udev_monitor->ifd, &epoll[0]) == -1 || - epoll_ctl(udev_monitor->efd, EPOLL_CTL_ADD, udev_monitor->pfd[0], &epoll[1]) == -1) { - for (i = 0; i < 2; i++) { - close(udev_monitor->pfd[i]); - } + epoll.events = EPOLLIN | EPOLLET; + if (epoll_ctl(udev_monitor->efd, EPOLL_CTL_ADD, udev_monitor->ifd, &epoll) == -1) { close(udev_monitor->ifd); close(udev_monitor->efd); free(udev_monitor); @@ -304,10 +285,6 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char } if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, udev_monitor->sfd) == -1) { - for (i = 0; i < 2; i++) { - close(udev_monitor->pfd[i]); - } - close(udev_monitor->ifd); close(udev_monitor->efd); free(udev_monitor); @@ -344,14 +321,22 @@ struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor) udev_list_entry_free_all(&udev_monitor->subsystem_match); udev_list_entry_free_all(&udev_monitor->devtype_match); - write(udev_monitor->pfd[1], "1", 1); + for (i = 0; i < THREADS_MAX; i++) { + pthread_cancel(udev_monitor->thread[i]); + } - pthread_barrier_wait(&udev_monitor->barrier); - pthread_barrier_destroy(&udev_monitor->barrier); + pthread_mutex_lock(&udev_monitor->mutex); + + while (udev_monitor->thread_alive) { + pthread_cond_wait(&udev_monitor->condition, &udev_monitor->mutex); + } + + pthread_mutex_unlock(&udev_monitor->mutex); + pthread_mutex_destroy(&udev_monitor->mutex); + pthread_cond_destroy(&udev_monitor->condition); for (i = 0; i < 2; i++) { close(udev_monitor->sfd[i]); - close(udev_monitor->pfd[i]); } close(udev_monitor->ifd); From d6e774460df9f5f2ccfb647d7281af718befaf93 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 19 Aug 2020 18:09:47 +0300 Subject: [PATCH 104/222] simplify using barrier --- udev_monitor.c | 33 +++++---------------------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/udev_monitor.c b/udev_monitor.c index f527f05..61d4449 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -23,10 +23,8 @@ struct udev_monitor { struct udev_list_entry subsystem_match; struct udev_list_entry devtype_match; pthread_t thread[THREADS_MAX]; - pthread_cond_t condition; - pthread_mutex_t mutex; + pthread_barrier_t barrier; struct udev *udev; - int thread_alive; int refcount; int sfd[2]; int ifd; @@ -112,16 +110,6 @@ struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monito return udev_device; } -static void udev_monitor_abort_thread(void *ptr) -{ - struct udev_monitor *udev_monitor = ptr; - - pthread_mutex_lock(&udev_monitor->mutex); - udev_monitor->thread_alive--; - pthread_cond_signal(&udev_monitor->condition); - pthread_mutex_unlock(&udev_monitor->mutex); -} - static void *udev_monitor_handle_event(void *ptr) { struct udev_monitor *udev_monitor = ptr; @@ -133,7 +121,6 @@ static void *udev_monitor_handle_event(void *ptr) int i; sigemptyset(&mask); - pthread_cleanup_push(udev_monitor_abort_thread, udev_monitor); while (epoll_pwait(udev_monitor->efd, &epoll, 1, -1, &mask) != -1) { len = read(udev_monitor->ifd, data, sizeof(data)); @@ -148,7 +135,7 @@ static void *udev_monitor_handle_event(void *ptr) } } - pthread_cleanup_pop(1); + pthread_barrier_wait(&udev_monitor->barrier); return NULL; } @@ -161,12 +148,9 @@ int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) return -1; } - udev_monitor->thread_alive = THREADS_MAX; - pthread_attr_init(&attr); - pthread_mutex_init(&udev_monitor->mutex, NULL); - pthread_cond_init(&udev_monitor->condition, NULL); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_barrier_init(&udev_monitor->barrier, NULL, THREADS_MAX + 1); for (i = 0; i < THREADS_MAX; i++) { pthread_create(&udev_monitor->thread[i], &attr, udev_monitor_handle_event, udev_monitor); @@ -325,15 +309,8 @@ struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor) pthread_cancel(udev_monitor->thread[i]); } - pthread_mutex_lock(&udev_monitor->mutex); - - while (udev_monitor->thread_alive) { - pthread_cond_wait(&udev_monitor->condition, &udev_monitor->mutex); - } - - pthread_mutex_unlock(&udev_monitor->mutex); - pthread_mutex_destroy(&udev_monitor->mutex); - pthread_cond_destroy(&udev_monitor->condition); + pthread_barrier_wait(&udev_monitor->barrier); + pthread_barrier_destroy(&udev_monitor->barrier); for (i = 0; i < 2; i++) { close(udev_monitor->sfd[i]); From 662062604e2233eb5dc455cefb9a9e3bef369448 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 19 Aug 2020 22:51:27 +0300 Subject: [PATCH 105/222] check IN_IGNORED --- udev_monitor.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/udev_monitor.c b/udev_monitor.c index 61d4449..77fac66 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -131,6 +131,12 @@ static void *udev_monitor_handle_event(void *ptr) for (i = 0; i < len; i += sizeof(struct inotify_event) + event->len) { event = (struct inotify_event *)&data[i]; + + // TODO user deleted directory, what should we do ? + if (event->mask & IN_IGNORED) { + break; + } + send(udev_monitor->sfd[1], event->name, event->len, 0); } } From 44409c16e7e3c5875b642a088b4b24bb637eaa67 Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 21 Aug 2020 14:55:24 +0300 Subject: [PATCH 106/222] attempt to write docs --- README.md | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a26abc5..3bf3882 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ libudev-zero ============ -Drop-in replacement for libudev intended to work without daemon +Drop-in replacement for libudev enables you to use whatever +device manager you like without worrying about udev dependency at all! What Works ---------- + * [x] xorg-server * [x] libinput * [x] wlroots @@ -32,6 +34,45 @@ make PREFIX=/usr install # will overwrite existing udev libraries if any # here we go ! ``` +Hotplugging +----------- + +There is no complicated or overengineered way to use hotplugging. Everything is +portable as much as possible. To use hotplugging the only thing you need is +uevent's receiver (device manager, busybox `uevent`, CONFIG_UEVENT_HELPER, ...). +I will describe only mdev and CONFIG_UEVENT_HELPER because their usage is very basic. +For busybox `uevent` you need to write your own parser which is kinda ... complex. + +UDEV_MONITOR_DIR is arbitrary directory where uevent files stored. +Default is `/tmp/.libudev-zero`. You can change it at build time by appending +`-DUDEV_MONITOR_DIR=` to CFLAGS. I don't recommend setting UDEV_MONITOR_DIR +to regular fs (i.e non-tmpfs) because unneeded files aren't automatically discarded +after reboot or termination (yet). + +* mdev + + - merge [mdev.conf](contrib/mdev.conf) with your mdev.conf + - restart mdev daemon + +* CONFIG_UEVENT_HELPER + + - ensure that CONFIG_UEVENT_HELPER enabled in kernel + - add full path of [helper.sh](contrib/helper.sh) (must be executable) or + [helper.c](contrib/helper.c) (compile it first) to /proc/sys/kernel/hotplug + + example: + ```sh + echo /full/path/to/helper > /proc/sys/kernel/hotplug # will use default UDEV_MONITOR_DIR + OR + echo "/full/path/to/helper " > /proc/sys/kernel/hotplug # change to your UDEV_MONITOR_DIR + ``` + +* run application which uses hotplugging (e.g xorg-server) +* unplug and plug something to test working capacity + +That's all! If you realized that this doesn't work for you, +you can always open an issue and describe your bug. + TODO ---- From b54f639cfdc720c549bce8e483fae31b1a584a3d Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 23 Aug 2020 00:51:10 +0300 Subject: [PATCH 107/222] final fixes --- udev_device.c | 67 ++++++++++++++++++++------------------------------- 1 file changed, 26 insertions(+), 41 deletions(-) diff --git a/udev_device.c b/udev_device.c index 92019ae..bebfd2c 100644 --- a/udev_device.c +++ b/udev_device.c @@ -307,7 +307,7 @@ static void udev_device_set_properties_from_uevent(struct udev_device *udev_devi if (strncmp(line, "DEVNAME", 7) == 0) { snprintf(devnode, sizeof(devnode), "/dev/%s", line + 8); - udev_list_entry_add(&udev_device->properties, "DEVNAME", devnode, 1); + udev_list_entry_add(&udev_device->properties, "DEVNAME", devnode, 0); } else if ((pos = strchr(line, '='))) { *pos = '\0'; @@ -369,7 +369,7 @@ static void udev_device_set_properties_from_evdev(struct udev_device *udev_devic unsigned long rel_bits[BITS_MAX] = {0}; unsigned long key_bits[BITS_MAX] = {0}; unsigned long ev_bits[BITS_MAX] = {0}; - struct udev_device *tmp; + struct udev_device *parent; const char *subsystem; subsystem = udev_device_get_subsystem(udev_device); @@ -378,25 +378,25 @@ static void udev_device_set_properties_from_evdev(struct udev_device *udev_devic return; } - tmp = udev_device; + parent = udev_device; while (1) { - if (!tmp) { + if (!parent) { return; } - if (udev_device_get_property_value(tmp, "EV")) { + if (udev_device_get_property_value(parent, "EV")) { break; } - tmp = udev_device_get_parent_with_subsystem_devtype(tmp, "input", NULL); + parent = udev_device_get_parent_with_subsystem_devtype(parent, "input", NULL); } - ev_cnt = populate_bit(ev_bits, udev_device_get_property_value(tmp, "EV")); - abs_cnt = populate_bit(abs_bits, udev_device_get_property_value(tmp, "ABS")); - rel_cnt = populate_bit(rel_bits, udev_device_get_property_value(tmp, "REL")); - key_cnt = populate_bit(key_bits, udev_device_get_property_value(tmp, "KEY")); - prop_cnt = populate_bit(prop_bits, udev_device_get_property_value(tmp, "PROP")); + ev_cnt = populate_bit(ev_bits, udev_device_get_property_value(parent, "EV")); + abs_cnt = populate_bit(abs_bits, udev_device_get_property_value(parent, "ABS")); + rel_cnt = populate_bit(rel_bits, udev_device_get_property_value(parent, "REL")); + key_cnt = populate_bit(key_bits, udev_device_get_property_value(parent, "KEY")); + prop_cnt = populate_bit(prop_bits, udev_device_get_property_value(parent, "PROP")); udev_list_entry_add(&udev_device->properties, "ID_INPUT", "1", 0); @@ -557,11 +557,10 @@ struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, co struct udev_device *udev_device_new_from_file(struct udev *udev, const char *path) { - char line[LINE_MAX], tmp[PATH_MAX]; - char *subsystem, *driver, *sysname; + char line[LINE_MAX], syspath[PATH_MAX], devnode[PATH_MAX]; struct udev_device *udev_device; + char *pos, *sysname; FILE *file; - char *pos; int i; udev_device = calloc(1, sizeof(struct udev_device)); @@ -587,11 +586,11 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat line[strcspn(line, "\n")] = '\0'; if (strncmp(line, "DEVPATH", 7) == 0) { - snprintf(tmp, sizeof(tmp), "/sys%s", line + 8); - udev_list_entry_add(&udev_device->properties, "SYSPATH", tmp, 0); + snprintf(syspath, sizeof(syspath), "/sys%s", line + 8); + udev_list_entry_add(&udev_device->properties, "SYSPATH", syspath, 0); udev_list_entry_add(&udev_device->properties, "DEVPATH", line + 8, 0); - sysname = strrchr(tmp, '/') + 1; + sysname = strrchr(syspath, '/') + 1; udev_list_entry_add(&udev_device->properties, "SYSNAME", sysname, 0); for (i = 0; sysname[i] != '\0'; i++) { @@ -602,37 +601,23 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat } } else if (strncmp(line, "DEVNAME", 7) == 0) { - snprintf(tmp, sizeof(tmp), "/dev/%s", line + 8); - udev_list_entry_add(&udev_device->properties, "DEVNAME", tmp, 0); + snprintf(devnode, sizeof(devnode), "/dev/%s", line + 8); + udev_list_entry_add(&udev_device->properties, "DEVNAME", devnode, 0); } else if ((pos = strchr(line, '='))) { *pos = '\0'; - udev_list_entry_add(&udev_device->properties, line, pos + 1, 1); + udev_list_entry_add(&udev_device->properties, line, pos + 1, 0); } } - if (!udev_device_get_driver(udev_device)) { - driver = udev_device_read_symlink(udev_device, "driver"); - - if (driver) { - udev_list_entry_add(&udev_device->properties, "DRIVER", driver, 0); - free(driver); - } - } - - if (!udev_device_get_subsystem(udev_device)) { - subsystem = udev_device_read_symlink(udev_device, "subsystem"); - - if (subsystem) { - udev_list_entry_add(&udev_device->properties, "SUBSYSTEM", subsystem, 0); - free(subsystem); - } - } - - udev_device_set_properties_from_uevent(udev_device); - udev_device_set_properties_from_evdev(udev_device); - fclose(file); + + if (!udev_device_get_syspath(udev_device)) { + udev_device_unref(udev_device); + return NULL; + } + + udev_device_set_properties_from_evdev(udev_device); return udev_device; } From 85707b0bbafde62f1129f40b7efd2527200d02e9 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 23 Aug 2020 01:15:49 +0300 Subject: [PATCH 108/222] update readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 3bf3882..9fb21e5 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,9 @@ What Works ---------- * [x] xorg-server +* [ ] dosfstools - need implement udev_enumerate_add_match_parent() * [x] libinput +* [x] usbutils * [x] wlroots * [x] weston * [x] libusb From 894aa4890604e684eb254313da1ff4098b20ba4f Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 23 Aug 2020 15:23:36 +0300 Subject: [PATCH 109/222] fix memory leak --- udev_device.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/udev_device.c b/udev_device.c index bebfd2c..f312810 100644 --- a/udev_device.c +++ b/udev_device.c @@ -569,6 +569,13 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat return NULL; } + file = fopen(path, "r"); + + if (!file) { + free(udev_device); + return NULL; + } + udev_device->udev = udev; udev_device->refcount = 1; udev_device->parent = NULL; @@ -576,12 +583,6 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat udev_list_entry_init(&udev_device->properties); udev_list_entry_init(&udev_device->sysattrs); - file = fopen(path, "r"); - - if (!file) { - return NULL; - } - while (fgets(line, sizeof(line), file)) { line[strcspn(line, "\n")] = '\0'; From 14e187f1e2c358c46ccb22963794aa91feccbf41 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 23 Aug 2020 15:31:10 +0300 Subject: [PATCH 110/222] check file size --- udev_device.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/udev_device.c b/udev_device.c index f312810..e8b0c9b 100644 --- a/udev_device.c +++ b/udev_device.c @@ -560,6 +560,7 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat char line[LINE_MAX], syspath[PATH_MAX], devnode[PATH_MAX]; struct udev_device *udev_device; char *pos, *sysname; + struct stat st; FILE *file; int i; @@ -569,6 +570,11 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat return NULL; } + if (stat(path, &st) != 0 || st.st_size > 8192) { + free(udev_device); + return NULL; + } + file = fopen(path, "r"); if (!file) { From 6e6fe8652cde928c97165b7f5ea07f6836867d91 Mon Sep 17 00:00:00 2001 From: illiliti Date: Mon, 24 Aug 2020 17:11:42 +0300 Subject: [PATCH 111/222] drop chmod --- Makefile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Makefile b/Makefile index 4c75ca3..d9f7ca9 100644 --- a/Makefile +++ b/Makefile @@ -37,14 +37,10 @@ libudev.pc: libudev.pc.in install: libudev.so libudev.a libudev.pc mkdir -p ${DESTDIR}${INCLUDEDIR} ${DESTDIR}${LIBDIR}/pkgconfig cp -f udev.h ${DESTDIR}${INCLUDEDIR}/libudev.h - chmod 0644 ${DESTDIR}${INCLUDEDIR}/libudev.h cp -f libudev.a ${DESTDIR}${LIBDIR}/libudev.a - chmod 0644 ${DESTDIR}${LIBDIR}/libudev.a cp -f libudev.so ${DESTDIR}${LIBDIR}/libudev.so - chmod 0755 ${DESTDIR}${LIBDIR}/libudev.so ln -s libudev.so ${DESTDIR}${LIBDIR}/libudev.so.1 cp -f libudev.pc ${DESTDIR}${LIBDIR}/pkgconfig/ - chmod 0644 ${DESTDIR}${LIBDIR}/pkgconfig/libudev.pc uninstall: rm -f ${DESTDIR}${LIBDIR}/libudev.a \ From 0c4d64fdacc18e23b1d1818f31b15b78723348bc Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 1 Sep 2020 14:03:07 +0300 Subject: [PATCH 112/222] fix xorg crash introduced in https://github.com/freedesktop/xorg-xserver/commit/74b7427c41b4e4104af7abf70a996c086d3d7628 --- udev_device.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/udev_device.c b/udev_device.c index e8b0c9b..eba4b39 100644 --- a/udev_device.c +++ b/udev_device.c @@ -80,7 +80,7 @@ struct udev *udev_device_get_udev(struct udev_device *udev_device) struct udev_device *udev_device_get_parent(struct udev_device *udev_device) { - char *path, *syspath; + char *pos, *path, *syspath; if (!udev_device) { return NULL; @@ -95,8 +95,8 @@ struct udev_device *udev_device_get_parent(struct udev_device *udev_device) path = syspath + 5; do { - if ((path = strrchr(path, '/'))) { - *path = '\0'; + if ((pos = strrchr(path, '/'))) { + *pos = '\0'; } else { break; @@ -452,6 +452,29 @@ static void udev_device_set_properties_from_evdev(struct udev_device *udev_devic } } +static void udev_device_set_properties_from_props(struct udev_device *udev_device) +{ + const char *sysname, *subsystem; + struct udev_device *parent; + char id[256]; + + subsystem = udev_device_get_subsystem(udev_device); + + if (!subsystem || strcmp(subsystem, "drm") != 0) { + return; + } + + parent = udev_device_get_parent_with_subsystem_devtype(udev_device, "pci", NULL); + sysname = udev_device_get_sysname(parent); + + if (!sysname) { + return; + } + + snprintf(id, sizeof(id), "pci-%s", sysname); + udev_list_entry_add(&udev_device->properties, "ID_PATH", id, 0); +} + struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) { char path[PATH_MAX], file[PATH_MAX]; @@ -506,6 +529,7 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * udev_device_set_properties_from_uevent(udev_device); udev_device_set_properties_from_evdev(udev_device); + udev_device_set_properties_from_props(udev_device); free(driver); free(subsystem); @@ -624,6 +648,7 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat return NULL; } + udev_device_set_properties_from_props(udev_device); udev_device_set_properties_from_evdev(udev_device); return udev_device; } From ccdc98818faf29f2e190149f5940930e36e5c38f Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 1 Sep 2020 22:03:30 +0300 Subject: [PATCH 113/222] add .gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..40b5697 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.o +*.a +*.so +*.pc From 8390f74cad1b174d4bf33e6d73361ddc1252d2e6 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 10 Sep 2020 13:10:21 +0300 Subject: [PATCH 114/222] update readme --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9fb21e5..4b6f9de 100644 --- a/README.md +++ b/README.md @@ -51,12 +51,12 @@ Default is `/tmp/.libudev-zero`. You can change it at build time by appending to regular fs (i.e non-tmpfs) because unneeded files aren't automatically discarded after reboot or termination (yet). -* mdev +1. mdev - merge [mdev.conf](contrib/mdev.conf) with your mdev.conf - restart mdev daemon -* CONFIG_UEVENT_HELPER +1. CONFIG_UEVENT_HELPER - ensure that CONFIG_UEVENT_HELPER enabled in kernel - add full path of [helper.sh](contrib/helper.sh) (must be executable) or @@ -69,8 +69,8 @@ after reboot or termination (yet). echo "/full/path/to/helper " > /proc/sys/kernel/hotplug # change to your UDEV_MONITOR_DIR ``` -* run application which uses hotplugging (e.g xorg-server) -* unplug and plug something to test working capacity +2. run application which uses hotplugging (e.g xorg-server) +3. unplug and plug something to test working capacity That's all! If you realized that this doesn't work for you, you can always open an issue and describe your bug. From 95da1614f5d894fd7e66449db7c45f4d71422a71 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 10 Sep 2020 14:02:39 +0300 Subject: [PATCH 115/222] update readme --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 4b6f9de..15d2423 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,9 @@ make PREFIX=/usr install # will overwrite existing udev libraries if any Hotplugging ----------- +Note that hotplugging support is fully optional! You can skip this step if you +don't have anything to hotplug. + There is no complicated or overengineered way to use hotplugging. Everything is portable as much as possible. To use hotplugging the only thing you need is uevent's receiver (device manager, busybox `uevent`, CONFIG_UEVENT_HELPER, ...). From 7f7c68e5e55430fd0f8f5791890c59391320584b Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 10 Sep 2020 21:27:43 +0300 Subject: [PATCH 116/222] why ???? --- README.md | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 15d2423..2b178c1 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,30 @@ libudev-zero ============ -Drop-in replacement for libudev enables you to use whatever -device manager you like without worrying about udev dependency at all! +Drop-in replacement for libudev enables you to use any device manager you like +without worrying about udev dependency at all! + +Why ? + +Because udev sucks, bloated and overengineered. udev is just like +systemd, lock you into using non-portable crap that you can't avoid +because many software depends on it. Look, even FreeBSD was forced to +rewrite[1] this crappy library because libinput has mandatory udev dependency. +Without libinput you can't use wayland and some other cool stuff. + +Michael Forney (cproc, samurai, Oasis Linux, ... author) decided to fork[2] +libinput and remove udev mandatority. This is solution ? Yes. This is long term +solution ? No. Patching upstream changes eventually will become absolutely +nightmare. Also this fork has a lot of disadvantages like requiring static +configuration which means you can't rely on automatic input devices +discovering. + +Thanks god udev has stable API and hopefully no changes will be made in +future. On this basis i decided to create this clean-room implementation of +libudev which can be used with any or without device manager. + +[1] https://github.com/FreeBSDDesktop/libudev-devd +[2] https://github.com/oasislinux/libinput What Works ---------- @@ -91,3 +113,5 @@ Donate You can donate if you like this project BTC: 1BwrcsgtWZeLVvNeEQSg4A28a3yrGN3FpK + +Thank you very much ! From d2820abf1304918a4a0abbd0c3da3d835f392940 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 10 Sep 2020 21:28:59 +0300 Subject: [PATCH 117/222] newline --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2b178c1..0bb96b3 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Thanks god udev has stable API and hopefully no changes will be made in future. On this basis i decided to create this clean-room implementation of libudev which can be used with any or without device manager. -[1] https://github.com/FreeBSDDesktop/libudev-devd +[1] https://github.com/FreeBSDDesktop/libudev-devd [2] https://github.com/oasislinux/libinput What Works From 089e09e00a6df44afa0964af22878d89b9df3389 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 13 Sep 2020 23:26:40 +0300 Subject: [PATCH 118/222] fix memory leak --- udev_device.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/udev_device.c b/udev_device.c index eba4b39..b52c9bb 100644 --- a/udev_device.c +++ b/udev_device.c @@ -86,6 +86,10 @@ struct udev_device *udev_device_get_parent(struct udev_device *udev_device) return NULL; } + if (udev_device->parent) { + return udev_device->parent; + } + syspath = strdup(udev_device_get_syspath(udev_device)); if (!syspath) { From f5e0778f794497364ec91e6de1ffdc031bae2e79 Mon Sep 17 00:00:00 2001 From: Firas Khalil Khana Date: Tue, 15 Sep 2020 00:42:25 +0300 Subject: [PATCH 119/222] PREFIX has to be specified twice `PREFIX` has to be specified for when using `make` solely. This is done to correct the wrong paths inside the generated `libudev.pc` which will always be `/usr/local/{include,lib}` regardless of the `PREFIX` value passed to `make install`. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0bb96b3..5db2261 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ Installation ------------ ```sh -make +make PREFIX=/usr make PREFIX=/usr install # will overwrite existing udev libraries if any # rebuild all packages which depends on udev # here we go ! From 7cdcebdf5823f3b135a36a82a045dc39bafdb41b Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 15 Sep 2020 01:49:49 +0300 Subject: [PATCH 120/222] drop libudev.pc from all --- Makefile | 4 ++-- README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index d9f7ca9..8147ca2 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ OBJ = \ udev_monitor.o \ udev_enumerate.o -all: libudev.so libudev.a libudev.pc +all: libudev.so libudev.a .c.o: ${CC} ${XCFLAGS} -c -o $@ $< @@ -39,7 +39,7 @@ install: libudev.so libudev.a libudev.pc cp -f udev.h ${DESTDIR}${INCLUDEDIR}/libudev.h cp -f libudev.a ${DESTDIR}${LIBDIR}/libudev.a cp -f libudev.so ${DESTDIR}${LIBDIR}/libudev.so - ln -s libudev.so ${DESTDIR}${LIBDIR}/libudev.so.1 + ln -fs libudev.so ${DESTDIR}${LIBDIR}/libudev.so.1 cp -f libudev.pc ${DESTDIR}${LIBDIR}/pkgconfig/ uninstall: diff --git a/README.md b/README.md index 5db2261..0bb96b3 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ Installation ------------ ```sh -make PREFIX=/usr +make make PREFIX=/usr install # will overwrite existing udev libraries if any # rebuild all packages which depends on udev # here we go ! From fd64152df9b4548fb2ab3666c5d5b35c460c8c04 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 15 Sep 2020 02:38:57 +0300 Subject: [PATCH 121/222] prevent format string exploit --- udev_monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udev_monitor.c b/udev_monitor.c index 77fac66..f835a5a 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -94,7 +94,7 @@ struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monito return NULL; } - snprintf(file, sizeof(file), UDEV_MONITOR_DIR "/%s", data); + snprintf(file, sizeof(file), "%s/%s", UDEV_MONITOR_DIR, data); udev_device = udev_device_new_from_file(udev_monitor->udev, file); if (!udev_device) { From bb6cc905ddec1b237aad5b6d67fb4149b48e2aa8 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 16 Sep 2020 02:43:37 +0300 Subject: [PATCH 122/222] update readme --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0bb96b3..156e227 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,14 @@ rewrite[1] this crappy library because libinput has mandatory udev dependency. Without libinput you can't use wayland and some other cool stuff. Michael Forney (cproc, samurai, Oasis Linux, ... author) decided to fork[2] -libinput and remove udev mandatority. This is solution ? Yes. This is long term -solution ? No. Patching upstream changes eventually will become absolutely -nightmare. Also this fork has a lot of disadvantages like requiring static -configuration which means you can't rely on automatic input devices -discovering. +libinput and remove udev mandatority. This is solution ? Yes. This is complete +solution ? No. This fork has a lot of disadvantages like requiring patching +application from libinput_udev to libinput_netlink API in order to use +automatic detection of input devices and hotplugging. Static confuguration also +required for anything other than input devices (e.g drm devices). Moreover +hotplugging vulnerable to race conditions when libinput handles uevent faster +than device manager which can lead to file permissions issues. libudev-zero +prevents these race conditions by design. Thanks god udev has stable API and hopefully no changes will be made in future. On this basis i decided to create this clean-room implementation of From be97914adeec6924e2cde25a99b22b61a6156789 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 16 Sep 2020 21:51:08 +0300 Subject: [PATCH 123/222] move not implemented comment to the same line of function for easier parsability --- udev_device.c | 17 ++++++----------- udev_enumerate.c | 14 +++++--------- udev_hwdb.c | 8 ++++---- udev_monitor.c | 12 ++++-------- 4 files changed, 19 insertions(+), 32 deletions(-) diff --git a/udev_device.c b/udev_device.c index b52c9bb..5d9a86b 100644 --- a/udev_device.c +++ b/udev_device.c @@ -145,7 +145,7 @@ struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_de return NULL; } -int udev_device_get_is_initialized(struct udev_device *udev_device) +/* XXX NOT IMPLEMENTED */ int udev_device_get_is_initialized(struct udev_device *udev_device) { return 1; } @@ -155,15 +155,13 @@ const char *udev_device_get_action(struct udev_device *udev_device) return udev_device_get_property_value(udev_device, "ACTION"); } -int udev_device_has_tag(struct udev_device *udev_device, const char *tag) +/* XXX NOT IMPLEMENTED */ int udev_device_has_tag(struct udev_device *udev_device, const char *tag) { - // XXX NOT IMPLEMENTED return 0; } -struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device) +/* XXX NOT IMPLEMENTED */ struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device) { - // XXX NOT IMPLEMENTED return NULL; } @@ -172,9 +170,8 @@ struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device return udev_device ? udev_list_entry_get_next(&udev_device->properties) : NULL; } -struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device) +/* XXX NOT IMPLEMENTED */ struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device) { - // XXX NOT IMPLEMENTED return NULL; } @@ -657,15 +654,13 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat return udev_device; } -struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id) +/* XXX NOT IMPLEMENTED */ struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id) { - // XXX NOT IMPLEMENTED return NULL; } -struct udev_device *udev_device_new_from_environment(struct udev *udev) +/* XXX NOT IMPLEMENTED */ struct udev_device *udev_device_new_from_environment(struct udev *udev) { - // XXX NOT IMPLEMENTED return NULL; } diff --git a/udev_enumerate.c b/udev_enumerate.c index 558f288..44d10e0 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -83,19 +83,17 @@ int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, cons return udev_list_entry_add(&udev_enumerate->sysname_match, sysname, NULL, 0) ? 0 : -1; } -int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag) +/* XXX NOT IMPLEMENTED */ int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag) { - // XXX NOT IMPLEMENTED return 0; } -int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent) +/* XXX NOT IMPLEMENTED */ int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent) { - // XXX NOT IMPLEMENTED return 0; } -int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate) +/* XXX NOT IMPLEMENTED */ int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate) { return 0; } @@ -342,9 +340,8 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) return 0; } -int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate) +/* XXX NOT IMPLEMENTED */ int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate) { - // XXX NOT IMPLEMENTED return 0; } @@ -353,9 +350,8 @@ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *ude return udev_enumerate ? udev_list_entry_get_next(&udev_enumerate->devices) : NULL; } -int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath) +/* XXX NOT IMPLEMENTED */ int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath) { - // XXX NOT IMPLEMENTED return 0; } diff --git a/udev_hwdb.c b/udev_hwdb.c index c76f479..ac69d99 100644 --- a/udev_hwdb.c +++ b/udev_hwdb.c @@ -2,22 +2,22 @@ #include "udev.h" -struct udev_hwdb *udev_hwdb_new(struct udev *udev) +/* XXX NOT IMPLEMENTED */ struct udev_hwdb *udev_hwdb_new(struct udev *udev) { return NULL; } -struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb) +/* XXX NOT IMPLEMENTED */ struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb) { return NULL; } -struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb) +/* XXX NOT IMPLEMENTED */ struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb) { return NULL; } -struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags) +/* XXX NOT IMPLEMENTED */ struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags) { return NULL; } diff --git a/udev_monitor.c b/udev_monitor.c index f835a5a..81a803c 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -166,9 +166,8 @@ int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) return 0; } -int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size) +/* XXX NOT IMPLEMENTED */ int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size) { - // XXX NOT IMPLEMENTED return 0; } @@ -182,15 +181,13 @@ struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor) return udev_monitor ? udev_monitor->udev : NULL; } -int udev_monitor_filter_update(struct udev_monitor *udev_monitor) +/* XXX NOT IMPLEMENTED */ int udev_monitor_filter_update(struct udev_monitor *udev_monitor) { - // XXX NOT IMPLEMENTED return 0; } -int udev_monitor_filter_remove(struct udev_monitor *udev_monitor) +/* XXX NOT IMPLEMENTED */ int udev_monitor_filter_remove(struct udev_monitor *udev_monitor) { - // XXX NOT IMPLEMENTED return 0; } @@ -209,9 +206,8 @@ int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_mo return 0; } -int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag) +/* XXX NOT IMPLEMENTED */ int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag) { - // XXX NOT IMPLEMENTED return 0; } From 5cebefbc853387012a578161588fcb04d41c2807 Mon Sep 17 00:00:00 2001 From: Ethan Sommer Date: Wed, 4 Nov 2020 14:48:17 -0500 Subject: [PATCH 124/222] libudev.pc: add prefix and exec_prefix support --- Makefile | 14 ++++++++++++-- libudev.pc.in | 2 ++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 8147ca2..ce8ac39 100644 --- a/Makefile +++ b/Makefile @@ -29,8 +29,18 @@ libudev.so: ${OBJ} ${CC} ${XCFLAGS} -o $@ ${OBJ} ${XLDFLAGS} libudev.pc: libudev.pc.in - sed -e 's|@libdir@|${LIBDIR}|g' \ - -e 's|@includedir@|${INCLUDEDIR}|g' \ + libdir="${LIBDIR}"; \ + if [ "$${libdir#${PREFIX}}" != "$$libdir" ]; then \ + libdir="\$${exec_prefix}$${libdir#${PREFIX}}"; \ + fi; \ + includedir="${INCLUDEDIR}"; \ + if [ "$${includedir#${PREFIX}}" != "$$includedir" ]; then \ + includedir="\$${prefix}$${includedir#${PREFIX}}"; \ + fi; \ + sed -e 's|@prefix@|${PREFIX}|g' \ + -e 's|@exec_prefix@|${PREFIX}|g' \ + -e "s|@libdir@|$$libdir|g" \ + -e "s|@includedir@|$$includedir|g" \ -e 's|@VERSION@|243|g' \ libudev.pc.in > libudev.pc diff --git a/libudev.pc.in b/libudev.pc.in index 4955b43..6a45c32 100644 --- a/libudev.pc.in +++ b/libudev.pc.in @@ -1,3 +1,5 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ From 3b3d86d66609042a0db59ad07371cd8c853c92c4 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 11 Nov 2020 20:37:29 +0300 Subject: [PATCH 125/222] guard against multiple inclusion --- udev.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/udev.h b/udev.h index 08188ea..91b520b 100644 --- a/udev.h +++ b/udev.h @@ -1,6 +1,9 @@ #include #include +#ifndef _LIBUDEV_H_ +#define _LIBUDEV_H_ + #ifdef __cplusplus extern "C" { #endif @@ -102,3 +105,5 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat #ifdef __cplusplus } #endif + +#endif From 4e31ed15b5a35327b2aad5322f4eded7d6087cd1 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 11 Nov 2020 20:37:54 +0300 Subject: [PATCH 126/222] add todo --- udev_device.c | 1 + 1 file changed, 1 insertion(+) diff --git a/udev_device.c b/udev_device.c index 5d9a86b..bd03d40 100644 --- a/udev_device.c +++ b/udev_device.c @@ -334,6 +334,7 @@ static int populate_bit(unsigned long *arr, const char *val) return 0; } + // TODO remove. strtoul is able to handle this bit = strtok_r(bits, " ", &save); for (i = 0; bit && i < BITS_MAX; i++) { From 68b42a2404b00846486c55b25bfd96e9323b9391 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 11 Nov 2020 20:49:20 +0300 Subject: [PATCH 127/222] implement udev_device_get_seqnum. closes #7 --- udev.h | 1 + udev_device.c | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/udev.h b/udev.h index 91b520b..51ba317 100644 --- a/udev.h +++ b/udev.h @@ -28,6 +28,7 @@ const char *udev_device_get_sysnum(struct udev_device *udev_device); const char *udev_device_get_devpath(struct udev_device *udev_device); const char *udev_device_get_devnode(struct udev_device *udev_device); dev_t udev_device_get_devnum(struct udev_device *udev_device); +unsigned long long udev_device_get_seqnum(struct udev_device *udev_device); const char *udev_device_get_devtype(struct udev_device *udev_device); const char *udev_device_get_subsystem(struct udev_device *udev_device); const char *udev_device_get_driver(struct udev_device *udev_device); diff --git a/udev_device.c b/udev_device.c index bd03d40..e189659 100644 --- a/udev_device.c +++ b/udev_device.c @@ -44,6 +44,19 @@ const char *udev_device_get_devnode(struct udev_device *udev_device) return udev_device_get_property_value(udev_device, "DEVNAME"); } +unsigned long long udev_device_get_seqnum(struct udev_device *udev_device) +{ + const char *seqnum; + + seqnum = udev_device_get_property_value(udev_device, "SEQNUM"); + + if (!seqnum) { + return 0; + } + + return strtoull(seqnum, NULL, 10); +} + dev_t udev_device_get_devnum(struct udev_device *udev_device) { const char *major, *minor; From f56e9982ac72821fc01ad2040a73458f093464d5 Mon Sep 17 00:00:00 2001 From: mssx86 Date: Mon, 23 Nov 2020 01:53:26 +0300 Subject: [PATCH 128/222] Touch up the README a little. --- README.md | 119 +++++++++++++++++------------------------------------- 1 file changed, 37 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index 156e227..958065e 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,21 @@ -libudev-zero -============ +# libudev-zero +Drop-in replacement for `libudev` that enables you to use any device manager +you like without worrying about the `udev` dependency at all! -Drop-in replacement for libudev enables you to use any device manager you like -without worrying about udev dependency at all! +## Why? +Because `udev` sucks, it is bloated and overengineered. `udev` is just like `systemd`, it locks you into using non-portable crap that you can't avoid because multiple programs depend on it. Look, even FreeBSD was forced to rewrite[1] this crappy library because `libinput` hard-depends on `udev`. Without `libinput` you can't use `wayland` and many other cool stuff. -Why ? +Michael Forney (author of `cproc`, `samurai`, Oasis Linux, ...) decided to fork[2] `libinput` and remove the hard dependency on `udev`. Is this a solution? Yes. +Is this a complete solution? No. This fork has a lot of disadvantages like requiring patching applications to use `libinput_netlink` instead of the `libinput_udev` API in order to use the automatic detection of input devices and hotplugging. Static configuration is also required for anything other than input devices (e.g drm devices). Moreover hotplugging is vulnerable to race conditions when `libinput` handles the `uevent` faster than the device manager which can lead to file permission issues. `libudev-zero` prevents these race conditions by design. -Because udev sucks, bloated and overengineered. udev is just like -systemd, lock you into using non-portable crap that you can't avoid -because many software depends on it. Look, even FreeBSD was forced to -rewrite[1] this crappy library because libinput has mandatory udev dependency. -Without libinput you can't use wayland and some other cool stuff. - -Michael Forney (cproc, samurai, Oasis Linux, ... author) decided to fork[2] -libinput and remove udev mandatority. This is solution ? Yes. This is complete -solution ? No. This fork has a lot of disadvantages like requiring patching -application from libinput_udev to libinput_netlink API in order to use -automatic detection of input devices and hotplugging. Static confuguration also -required for anything other than input devices (e.g drm devices). Moreover -hotplugging vulnerable to race conditions when libinput handles uevent faster -than device manager which can lead to file permissions issues. libudev-zero -prevents these race conditions by design. - -Thanks god udev has stable API and hopefully no changes will be made in -future. On this basis i decided to create this clean-room implementation of -libudev which can be used with any or without device manager. +Thankfully `udev` has stable API and hopefully no changes will be made to it the future. On this basis I decided to create this clean-room implementation of `libudev` which can be used with any or without a device manager. [1] https://github.com/FreeBSDDesktop/libudev-devd [2] https://github.com/oasislinux/libinput -What Works ----------- - +## What Works * [x] xorg-server -* [ ] dosfstools - need implement udev_enumerate_add_match_parent() +* [ ] dosfstools - need to implement udev_enumerate_add_match_parent() * [x] libinput * [x] usbutils * [x] wlroots @@ -42,79 +24,52 @@ What Works * [x] kwin - [fix](https://github.com/dilyn-corner/KISS-kde/commit/0cc72748e46f859a0fced55b0c3fcc1dd9586a38) * [ ] ??? -Dependencies ------------- - +## Dependencies * C99 compiler (build time) * POSIX make (build time) * POSIX & XSI libc * epoll & inotify * Linux >= 2.6.39 -Installation ------------- +## Installation ```sh make -make PREFIX=/usr install # will overwrite existing udev libraries if any -# rebuild all packages which depends on udev -# here we go ! +make PREFIX=/usr install # this will overwrite udev libraries if they exist +# rebuild all the packages that depend on libudev, and you're ready to go. ``` -Hotplugging ------------ +## Hotplugging +Note that hotplugging support is fully optional! You can skip this step if you don't have a need for the hotplugging capability. -Note that hotplugging support is fully optional! You can skip this step if you -don't have anything to hotplug. +Hotplugging is fairly uncomplicated and not overengineered at all. Everything is portable as much as possible. To use hotplugging the only thing you need is a `uevent` receiver (like a device manager, busybox's `uevent`, `CONFIG_UEVENT_HELPER`, ...). I will explain only the `mdev` and `CONFIG_UEVENT_HELPER` methods because their usage is fairly basic. For busybox's `uevent` you need to write your own parser which is kinda, well, complex. -There is no complicated or overengineered way to use hotplugging. Everything is -portable as much as possible. To use hotplugging the only thing you need is -uevent's receiver (device manager, busybox `uevent`, CONFIG_UEVENT_HELPER, ...). -I will describe only mdev and CONFIG_UEVENT_HELPER because their usage is very basic. -For busybox `uevent` you need to write your own parser which is kinda ... complex. +`UDEV_MONITOR_DIR` is an arbitrary directory where the `uevent` files are stored. The default is `/tmp/.libudev-zero`. You can change it at build time by appending `-DUDEV_MONITOR_DIR=` to `CFLAGS`. I don't recommend setting `UDEV_MONITOR_DIR` to regular filesystems (i.e non-tmpfs) because temporary files aren't automatically discarded after reboot or termination (yet). -UDEV_MONITOR_DIR is arbitrary directory where uevent files stored. -Default is `/tmp/.libudev-zero`. You can change it at build time by appending -`-DUDEV_MONITOR_DIR=` to CFLAGS. I don't recommend setting UDEV_MONITOR_DIR -to regular fs (i.e non-tmpfs) because unneeded files aren't automatically discarded -after reboot or termination (yet). +### a) the `mdev` method +1. merge [mdev.conf](contrib/mdev.conf) with your `mdev.conf` +2. restart the `mdev` daemon -1. mdev +### b) the `CONFIG_UEVENT_HELPER` method +1. ensure that `CONFIG_UEVENT_HELPER` is enabled in your kernel configuration +2. add the directory containing [helper.sh](contrib/helper.sh) after marking it as executable or [helper.c](contrib/helper.c) after compiling it, to `/proc/sys/kernel/hotplug` - - merge [mdev.conf](contrib/mdev.conf) with your mdev.conf - - restart mdev daemon +#### example: +```sh +echo "/full/path/to/helper" > /proc/sys/kernel/hotplug # will use the default UDEV_MONITOR_DIR +OR +echo "/full/path/to/helper " > /proc/sys/kernel/hotplug # change to your UDEV_MONITOR_DIR +``` -1. CONFIG_UEVENT_HELPER - - - ensure that CONFIG_UEVENT_HELPER enabled in kernel - - add full path of [helper.sh](contrib/helper.sh) (must be executable) or - [helper.c](contrib/helper.c) (compile it first) to /proc/sys/kernel/hotplug - - example: - ```sh - echo /full/path/to/helper > /proc/sys/kernel/hotplug # will use default UDEV_MONITOR_DIR - OR - echo "/full/path/to/helper " > /proc/sys/kernel/hotplug # change to your UDEV_MONITOR_DIR - ``` - -2. run application which uses hotplugging (e.g xorg-server) -3. unplug and plug something to test working capacity - -That's all! If you realized that this doesn't work for you, -you can always open an issue and describe your bug. - -TODO ----- +--- +Then you can run an application that uses hotplugging like `xorg-server` to see if it's working by unplugging and plugging something back. If you face any problems while trying out any of these methods, please create an issue. +## TODO * [x] speed up performance -* [x] extend devices support +* [x] extend device support * [x] implement hotplugging support -Donate ------- +## Donate +You can send a donation to `BTC: 1BwrcsgtWZeLVvNeEQSg4A28a3yrGN3FpK` if you like this project. -You can donate if you like this project - -BTC: 1BwrcsgtWZeLVvNeEQSg4A28a3yrGN3FpK - -Thank you very much ! +Thank you very much! From 9868e5e9ead2d58799c5c4b0b2b311941df99e50 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 20 Jan 2021 08:55:12 +0300 Subject: [PATCH 129/222] add pthread. fixes #13 --- libudev.pc.in | 1 + 1 file changed, 1 insertion(+) diff --git a/libudev.pc.in b/libudev.pc.in index 6a45c32..d26aee5 100644 --- a/libudev.pc.in +++ b/libudev.pc.in @@ -8,4 +8,5 @@ Description: Daemonless replacement for libudev Version: @VERSION@ URL: https://github.com/illiliti/libudev-zero Libs: -L${libdir} -ludev +Libs.private: -pthread Cflags: -I${includedir} From b90b0acc88c7935158e2a36763ccfc1cbd9c9bed Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 20 Jan 2021 08:58:19 +0300 Subject: [PATCH 130/222] general code cleanup --- udev_device.c | 87 ++++++++++--------------- udev_enumerate.c | 166 +++++++++++++++++++++-------------------------- udev_list.c | 70 +++++++++++--------- udev_monitor.c | 6 +- 4 files changed, 151 insertions(+), 178 deletions(-) diff --git a/udev_device.c b/udev_device.c index e189659..4d5a4fa 100644 --- a/udev_device.c +++ b/udev_device.c @@ -9,7 +9,7 @@ #include "udev.h" #include "udev_list.h" -enum { BITS_MAX = 96 }; +#define BITS_MAX 96 struct udev_device { struct udev_list_entry properties; @@ -136,23 +136,17 @@ struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_de return NULL; } - parent = udev_device_get_parent(udev_device); - - while (parent) { + for (parent = udev_device_get_parent(udev_device); parent; parent = udev_device_get_parent(parent)) { parent_subsystem = udev_device_get_subsystem(parent); parent_devtype = udev_device_get_devtype(parent); - if (parent_subsystem && strcmp(parent_subsystem, subsystem) == 0) { - if (!devtype) { - return parent; - } - - if (parent_devtype && strcmp(parent_devtype, devtype) == 0) { - return parent; - } + if (!parent_subsystem || strcmp(parent_subsystem, subsystem) != 0) { + continue; } - parent = udev_device_get_parent(parent); + if (!devtype || (parent_devtype && strcmp(parent_devtype, devtype) == 0)) { + return parent; + } } return NULL; @@ -205,7 +199,7 @@ const char *udev_device_get_property_value(struct udev_device *udev_device, cons const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr) { struct udev_list_entry *list_entry; - char data[BUFSIZ], path[PATH_MAX]; + char data[1024], path[PATH_MAX]; struct stat st; size_t len; FILE *file; @@ -241,13 +235,11 @@ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const } if ((pos = memchr(data, '\n', len))) { - *pos = '\0'; - } - else { - data[len] = '\0'; + len = pos - data; } fclose(file); + data[len] = '\0'; list_entry = udev_list_entry_add(&udev_device->sysattrs, sysattr, data, 0); return udev_list_entry_get_value(list_entry); } @@ -305,9 +297,9 @@ static char *udev_device_read_symlink(struct udev_device *udev_device, const cha static void udev_device_set_properties_from_uevent(struct udev_device *udev_device) { - char line[LINE_MAX], path[PATH_MAX]; - char *pos, devnode[PATH_MAX]; + char line[LINE_MAX], path[PATH_MAX], devnode[PATH_MAX]; FILE *file; + char *pos; snprintf(path, sizeof(path), "%s/uevent", udev_device_get_syspath(udev_device)); file = fopen(path, "r"); @@ -317,7 +309,7 @@ static void udev_device_set_properties_from_uevent(struct udev_device *udev_devi } while (fgets(line, sizeof(line), file)) { - line[strcspn(line, "\n")] = '\0'; + line[strlen(line) - 1] = '\0'; if (strncmp(line, "DEVNAME", 7) == 0) { snprintf(devnode, sizeof(devnode), "/dev/%s", line + 8); @@ -332,41 +324,34 @@ static void udev_device_set_properties_from_uevent(struct udev_device *udev_devi fclose(file); } -static int populate_bit(unsigned long *arr, const char *val) +static int populate_bit(unsigned long *arr, const char *str) { - char *bit, *bits, *save; + char *beg, *end; int i; - if (!val) { + if (!str) { return 0; } - bits = strdup(val); + // TODO drop strdup ? + beg = end = strdup(str); - if (!bits) { + if (!beg) { return 0; } - // TODO remove. strtoul is able to handle this - bit = strtok_r(bits, " ", &save); - - for (i = 0; bit && i < BITS_MAX; i++) { - arr[i] = strtoul(bit, NULL, 16); - bit = strtok_r(NULL, " ", &save); + for (i = 0; end[0] != '\0' && i < BITS_MAX; i++) { + arr[i] = strtoul(end, &end, 16); } - free(bits); + free(beg); return i; } -static int find_bit(unsigned long *arr, int cnt, int bit) +static int find_bit(unsigned long *arr, int cnt, unsigned long bit) { int i; - if (!cnt) { - return 0; - } - for (i = 0; i < cnt; i++) { if (arr[i] & (1UL << (bit % LONG_BIT))) { return 1; @@ -561,10 +546,10 @@ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, de switch (type) { case 'c': - snprintf(path, sizeof(path), "/sys/dev/char/%d:%d", major(devnum), minor(devnum)); + snprintf(path, sizeof(path), "/sys/dev/char/%u:%u", major(devnum), minor(devnum)); break; case 'b': - snprintf(path, sizeof(path), "/sys/dev/block/%d:%d", major(devnum), minor(devnum)); + snprintf(path, sizeof(path), "/sys/dev/block/%u:%u", major(devnum), minor(devnum)); break; default: return NULL; @@ -598,26 +583,26 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat { char line[LINE_MAX], syspath[PATH_MAX], devnode[PATH_MAX]; struct udev_device *udev_device; - char *pos, *sysname; + char *sysname = NULL; struct stat st; FILE *file; + char *pos; int i; - udev_device = calloc(1, sizeof(struct udev_device)); - - if (!udev_device) { - return NULL; - } - if (stat(path, &st) != 0 || st.st_size > 8192) { - free(udev_device); return NULL; } file = fopen(path, "r"); if (!file) { - free(udev_device); + return NULL; + } + + udev_device = calloc(1, sizeof(struct udev_device)); + + if (!udev_device) { + fclose(file); return NULL; } @@ -629,7 +614,7 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat udev_list_entry_init(&udev_device->sysattrs); while (fgets(line, sizeof(line), file)) { - line[strcspn(line, "\n")] = '\0'; + line[strlen(line) - 1] = '\0'; if (strncmp(line, "DEVPATH", 7) == 0) { snprintf(syspath, sizeof(syspath), "/sys%s", line + 8); @@ -658,7 +643,7 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat fclose(file); - if (!udev_device_get_syspath(udev_device)) { + if (!sysname) { udev_device_unref(udev_device); return NULL; } diff --git a/udev_enumerate.c b/udev_enumerate.c index 44d10e0..8916b43 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -24,63 +24,38 @@ struct udev_enumerate { struct udev_enumerate_thread { struct udev_enumerate *udev_enumerate; pthread_mutex_t *mutex; + char path[PATH_MAX]; pthread_t thread; - const char *name; - const char *path; }; int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) { - if (!udev_enumerate || !subsystem) { - return -1; - } - - return udev_list_entry_add(&udev_enumerate->subsystem_match, subsystem, NULL, 0) ? 0 : -1; + return udev_enumerate ? !!udev_list_entry_add(&udev_enumerate->subsystem_match, subsystem, NULL, 0) - 1 : -1; } int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) { - if (!udev_enumerate || !subsystem) { - return -1; - } - - return udev_list_entry_add(&udev_enumerate->subsystem_nomatch, subsystem, NULL, 0) ? 0 : -1; + return udev_enumerate ? !!udev_list_entry_add(&udev_enumerate->subsystem_nomatch, subsystem, NULL, 0) - 1 : -1; } int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) { - if (!udev_enumerate || !sysattr) { - return -1; - } - - return udev_list_entry_add(&udev_enumerate->sysattr_match, sysattr, value, 0) ? 0 : -1; + return udev_enumerate ? !!udev_list_entry_add(&udev_enumerate->sysattr_match, sysattr, value, 0) - 1 : -1; } int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) { - if (!udev_enumerate || !sysattr) { - return -1; - } - - return udev_list_entry_add(&udev_enumerate->sysattr_nomatch, sysattr, value, 0) ? 0 : -1; + return udev_enumerate ? !!udev_list_entry_add(&udev_enumerate->sysattr_nomatch, sysattr, value, 0) - 1 : -1; } int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value) { - if (!udev_enumerate || !property) { - return -1; - } - - return udev_list_entry_add(&udev_enumerate->property_match, property, value, 0) ? 0 : -1; + return udev_enumerate ? !!udev_list_entry_add(&udev_enumerate->property_match, property, value, 0) - 1 : -1; } int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname) { - if (!udev_enumerate || !sysname) { - return -1; - } - - return udev_list_entry_add(&udev_enumerate->sysname_match, sysname, NULL, 0) ? 0 : -1; + return udev_enumerate ? !!udev_list_entry_add(&udev_enumerate->sysname_match, sysname, NULL, 0) - 1 : -1; } /* XXX NOT IMPLEMENTED */ int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag) @@ -249,94 +224,99 @@ static int udev_enumerate_filter_sysattr(struct udev_enumerate *udev_enumerate, static void *udev_enumerate_add_device(void *ptr) { - struct udev_enumerate_thread *data = ptr; + struct udev_enumerate_thread *thread = ptr; struct udev_device *udev_device; - char path[PATH_MAX]; - snprintf(path, sizeof(path), "%s/%s", data->path, data->name); - udev_device = udev_device_new_from_syspath(data->udev_enumerate->udev, path); + udev_device = udev_device_new_from_syspath(thread->udev_enumerate->udev, thread->path); if (!udev_device) { return NULL; } - if (!udev_enumerate_filter_subsystem(data->udev_enumerate, udev_device) || - !udev_enumerate_filter_sysname(data->udev_enumerate, udev_device) || - !udev_enumerate_filter_property(data->udev_enumerate, udev_device) || - !udev_enumerate_filter_sysattr(data->udev_enumerate, udev_device)) { + if (!udev_enumerate_filter_subsystem(thread->udev_enumerate, udev_device) || + !udev_enumerate_filter_sysname(thread->udev_enumerate, udev_device) || + !udev_enumerate_filter_property(thread->udev_enumerate, udev_device) || + !udev_enumerate_filter_sysattr(thread->udev_enumerate, udev_device)) { udev_device_unref(udev_device); return NULL; } - pthread_mutex_lock(data->mutex); - udev_list_entry_add(&data->udev_enumerate->devices, udev_device_get_syspath(udev_device), NULL, 0); - pthread_mutex_unlock(data->mutex); + pthread_mutex_lock(thread->mutex); + udev_list_entry_add(&thread->udev_enumerate->devices, udev_device_get_syspath(udev_device), NULL, 0); + pthread_mutex_unlock(thread->mutex); udev_device_unref(udev_device); return NULL; } -static int udev_enumerate_filter_dots(const struct dirent *de) +static int filter_dot(const struct dirent *de) { - if (strcmp(de->d_name, ".") == 0 || - strcmp(de->d_name, "..") == 0) { - return 0; + return de->d_name[0] != '.'; +} + +static int udev_enumerate_add_devices(struct udev_enumerate *udev_enumerate, const char *path) +{ + struct udev_enumerate_thread *thread; + pthread_mutex_t mutex; + struct dirent **de; + int cnt, i; + + cnt = scandir(path, &de, filter_dot, NULL); + + if (cnt == -1) { + return -1; } - return 1; + thread = calloc(cnt, sizeof(struct udev_enumerate_thread)); + + if (!thread) { + for (i = 0; i < cnt; i++) { + free(de[i]); + } + + free(de); + return -1; + } + + pthread_mutex_init(&mutex, NULL); + + for (i = 0; i < cnt; i++) { + thread[i].mutex = &mutex; + thread[i].udev_enumerate = udev_enumerate; + + snprintf(thread[i].path, sizeof(thread[i].path), "%s/%s", path, de[i]->d_name); + pthread_create(&thread[i].thread, NULL, udev_enumerate_add_device, &thread[i]); + } + + for (i = 0; i < cnt; i++) { + pthread_join(thread[i].thread, NULL); + } + + for (i = 0; i < cnt; i++) { + free(de[i]); + } + + free(de); + free(thread); + pthread_mutex_destroy(&mutex); + return 0; } int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) { const char *path[] = { "/sys/dev/block", "/sys/dev/char", NULL }; - struct udev_enumerate_thread *data; - pthread_mutex_t mutex; - struct dirent **de; - int cnt, i, u; + int i; - pthread_mutex_init(&mutex, NULL); - - for (i = 0; path[i]; i++) { - cnt = scandir(path[i], &de, udev_enumerate_filter_dots, NULL); - - if (cnt == -1) { - continue; - } - - data = calloc(cnt, sizeof(struct udev_enumerate_thread)); - - if (!data) { - for (u = 0; u < cnt; u++) { - free(de[u]); - } - - free(de); - continue; - } - - // TODO do we really need structure for every thread ? - for (u = 0; u < cnt; u++) { - data[u].path = path[i]; - data[u].name = de[u]->d_name; - data[u].mutex = &mutex; - data[u].udev_enumerate = udev_enumerate; - - pthread_create(&data[u].thread, NULL, udev_enumerate_add_device, &data[u]); - } - - for (u = 0; u < cnt; u++) { - pthread_join(data[u].thread, NULL); - } - - for (u = 0; u < cnt; u++) { - free(de[u]); - } - - free(de); - free(data); + if (!udev_enumerate) { + return -1; + } + + for (i = 0; path[i]; i++) { + if (udev_enumerate_add_devices(udev_enumerate, path[i]) == -1) { + return -1; + } } - pthread_mutex_destroy(&mutex); return 0; } diff --git a/udev_list.c b/udev_list.c index e362d49..2010d42 100644 --- a/udev_list.c +++ b/udev_list.c @@ -20,48 +20,61 @@ 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, *tmp2; + struct udev_list_entry *list_entry2 = list_entry->next; - tmp = list_entry->next; - - while (tmp) { - tmp2 = tmp; - tmp = tmp->next; - udev_list_entry_free(tmp2); + while (list_entry2) { + list_entry = list_entry2; + list_entry2 = list_entry->next; + udev_list_entry_free(list_entry); } } struct udev_list_entry *udev_list_entry_add(struct udev_list_entry *list_entry, const char *name, const char *value, int uniq) { - struct udev_list_entry *new, *old; + struct udev_list_entry *list_entry2; if (uniq) { - old = udev_list_entry_get_by_name(list_entry, name); + list_entry2 = udev_list_entry_get_by_name(list_entry, name); - if (old) { - if (old->value && strcmp(old->value, value) == 0) { - return old; + if (list_entry2 && value) { + if (list_entry2->value && strcmp(list_entry2->value, value) == 0) { + return list_entry2; } - free(old->value); - old->value = value ? strdup(value) : NULL; - return old; + free(list_entry2->value); + list_entry2->value = strdup(value); + + if (!list_entry2->value) { + return NULL; + } + + return list_entry2; } } - new = calloc(1, sizeof(struct udev_list_entry)); + list_entry2 = calloc(1, sizeof(struct udev_list_entry)); - if (!new) { + if (!list_entry2) { return NULL; } - new->value = value ? strdup(value) : NULL; - new->name = strdup(name); + list_entry2->name = strdup(name); - new->next = list_entry->next; - list_entry->next = new; + if (!list_entry2->name) { + return NULL; + } - return new; + if (value) { + list_entry2->value = strdup(value); + + if (!list_entry2->value) { + return NULL; + } + } + + list_entry2->next = list_entry->next; + list_entry->next = list_entry2; + return list_entry2; } struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry) @@ -71,21 +84,16 @@ struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_en struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name) { - struct udev_list_entry *tmp; - if (!list_entry || !name) { return NULL; } - tmp = list_entry; - - while (tmp) { - if (tmp->name && strcmp(tmp->name, name) == 0) { - return tmp; + do { + if (list_entry->name && strcmp(list_entry->name, name) == 0) { + return list_entry; } - - tmp = tmp->next; } + while ((list_entry = list_entry->next)); return NULL; } diff --git a/udev_monitor.c b/udev_monitor.c index 81a803c..ecc14f5 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -13,12 +13,12 @@ #include "udev.h" #include "udev_list.h" +#define THREADS_MAX 5 + #ifndef UDEV_MONITOR_DIR #define UDEV_MONITOR_DIR "/tmp/.libudev-zero" #endif -enum { THREADS_MAX = 5 }; - struct udev_monitor { struct udev_list_entry subsystem_match; struct udev_list_entry devtype_match; @@ -132,7 +132,7 @@ static void *udev_monitor_handle_event(void *ptr) for (i = 0; i < len; i += sizeof(struct inotify_event) + event->len) { event = (struct inotify_event *)&data[i]; - // TODO user deleted directory, what should we do ? + // TODO directory is removed if (event->mask & IN_IGNORED) { break; } From d9bd4f3a1908c10437060664650183cc42a5723d Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 20 Jan 2021 09:05:42 +0300 Subject: [PATCH 131/222] implement udev_device_get_usec_since_initialized. fixes #12, closes #14 --- udev.h | 1 + udev_device.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/udev.h b/udev.h index 51ba317..65d3fe4 100644 --- a/udev.h +++ b/udev.h @@ -29,6 +29,7 @@ const char *udev_device_get_devpath(struct udev_device *udev_device); const char *udev_device_get_devnode(struct udev_device *udev_device); dev_t udev_device_get_devnum(struct udev_device *udev_device); unsigned long long udev_device_get_seqnum(struct udev_device *udev_device); +unsigned long long udev_device_get_usec_since_initialized(struct udev_device *udev_device); const char *udev_device_get_devtype(struct udev_device *udev_device); const char *udev_device_get_subsystem(struct udev_device *udev_device); const char *udev_device_get_driver(struct udev_device *udev_device); diff --git a/udev_device.c b/udev_device.c index 4d5a4fa..c5aeef7 100644 --- a/udev_device.c +++ b/udev_device.c @@ -57,6 +57,11 @@ unsigned long long udev_device_get_seqnum(struct udev_device *udev_device) return strtoull(seqnum, NULL, 10); } +unsigned long long udev_device_get_usec_since_initialized(struct udev_device *udev_device) +{ + return 0; +} + dev_t udev_device_get_devnum(struct udev_device *udev_device) { const char *major, *minor; From 84dcea670c32fe9f295a4b710c248f4ceb987489 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 20 Jan 2021 09:10:29 +0300 Subject: [PATCH 132/222] define INPUT_PROP_{POINTING_STICK,ACCELEROMETER}. fixes #11 --- udev_device.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/udev_device.c b/udev_device.c index c5aeef7..deab6f1 100644 --- a/udev_device.c +++ b/udev_device.c @@ -11,6 +11,14 @@ #define BITS_MAX 96 +#ifndef INPUT_PROP_POINTING_STICK +#define INPUT_PROP_POINTING_STICK 0x05 +#endif + +#ifndef INPUT_PROP_ACCELEROMETER +#define INPUT_PROP_ACCELEROMETER 0x06 +#endif + struct udev_device { struct udev_list_entry properties; struct udev_list_entry sysattrs; From db8c75e07ac43d7996ef544446190f6474af03b5 Mon Sep 17 00:00:00 2001 From: Mikael Olenfalk Date: Thu, 21 Jan 2021 15:42:54 +0100 Subject: [PATCH 133/222] Add missing udev log functions Without these functions Chromium and Electron crash during startup while loading libudev with a SIGTRAP. --- udev.c | 16 ++++++++++++++++ udev.h | 8 ++++++++ 2 files changed, 24 insertions(+) diff --git a/udev.c b/udev.c index 57cf4c8..b62db65 100644 --- a/udev.c +++ b/udev.c @@ -43,3 +43,19 @@ struct udev *udev_unref(struct udev *udev) free(udev); return NULL; } + +void udev_set_log_fn(struct udev *udev, + void (*log_fn)(struct udev *udev, + int priority, const char *file, int line, const char *fn, + const char *format, va_list args)) +{ +} + +int udev_get_log_priority(struct udev *udev) +{ + return 0; +} + +void udev_set_log_priority(struct udev *udev, int priority) +{ +} \ No newline at end of file diff --git a/udev.h b/udev.h index 65d3fe4..24a52d2 100644 --- a/udev.h +++ b/udev.h @@ -1,5 +1,6 @@ #include #include +#include #ifndef _LIBUDEV_H_ #define _LIBUDEV_H_ @@ -22,6 +23,13 @@ struct udev *udev_new(void); struct udev *udev_ref(struct udev *udev); struct udev *udev_unref(struct udev *udev); +void udev_set_log_fn(struct udev *udev, + void (*log_fn)(struct udev *udev, + int priority, const char *file, int line, const char *fn, + const char *format, va_list args)); +int udev_get_log_priority(struct udev *udev); +void udev_set_log_priority(struct udev *udev, int priority); + const char *udev_device_get_syspath(struct udev_device *udev_device); const char *udev_device_get_sysname(struct udev_device *udev_device); const char *udev_device_get_sysnum(struct udev_device *udev_device); From 1dfe5144c8c0fadeaae15712bcb1725f311e97cc Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 26 Jan 2021 00:20:57 +0300 Subject: [PATCH 134/222] squash --- udev.c | 15 +++++++-------- udev.h | 11 +++++------ 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/udev.c b/udev.c index b62db65..96d11d7 100644 --- a/udev.c +++ b/udev.c @@ -44,10 +44,13 @@ struct udev *udev_unref(struct udev *udev) return NULL; } -void udev_set_log_fn(struct udev *udev, - void (*log_fn)(struct udev *udev, - int priority, const char *file, int line, const char *fn, - const char *format, va_list args)) +void udev_set_log_fn(struct udev *udev, void (*log_fn)(struct udev *udev, + int priority, const char *file, int line, const char *fn, + const char *format, va_list args)) +{ +} + +void udev_set_log_priority(struct udev *udev, int priority) { } @@ -55,7 +58,3 @@ int udev_get_log_priority(struct udev *udev) { return 0; } - -void udev_set_log_priority(struct udev *udev, int priority) -{ -} \ No newline at end of file diff --git a/udev.h b/udev.h index 24a52d2..b65819a 100644 --- a/udev.h +++ b/udev.h @@ -1,6 +1,6 @@ +#include #include #include -#include #ifndef _LIBUDEV_H_ #define _LIBUDEV_H_ @@ -23,12 +23,11 @@ struct udev *udev_new(void); struct udev *udev_ref(struct udev *udev); struct udev *udev_unref(struct udev *udev); -void udev_set_log_fn(struct udev *udev, - void (*log_fn)(struct udev *udev, - int priority, const char *file, int line, const char *fn, - const char *format, va_list args)); -int udev_get_log_priority(struct udev *udev); +void udev_set_log_fn(struct udev *udev, void (*log_fn)(struct udev *udev, + int priority, const char *file, int line, const char *fn, + const char *format, va_list args)); void udev_set_log_priority(struct udev *udev, int priority); +int udev_get_log_priority(struct udev *udev); const char *udev_device_get_syspath(struct udev_device *udev_device); const char *udev_device_get_sysname(struct udev_device *udev_device); From 1aef09bf8425b486ec6ceb536d3c5d0089d9e56d Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 5 Feb 2021 05:43:02 +0300 Subject: [PATCH 135/222] replace unstable pthread_cancel() with self-pipe trick. fixes #16 --- udev_monitor.c | 115 ++++++++++++++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 44 deletions(-) diff --git a/udev_monitor.c b/udev_monitor.c index ecc14f5..3e3197a 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -1,6 +1,6 @@ +#include #include #include -#include #include #include #include @@ -27,6 +27,7 @@ struct udev_monitor { struct udev *udev; int refcount; int sfd[2]; + int pfd[2]; int ifd; int efd; }; @@ -114,15 +115,23 @@ static void *udev_monitor_handle_event(void *ptr) { struct udev_monitor *udev_monitor = ptr; struct inotify_event *event; - struct epoll_event epoll; + struct epoll_event epoll[2]; char data[4096]; - sigset_t mask; ssize_t len; int i; - sigemptyset(&mask); + while (epoll_wait(udev_monitor->efd, epoll, 2, -1) != -1) { + for (i = 0; i < 2; i++) { + if (epoll[i].data.fd != udev_monitor->pfd[0]) { + continue; + } + + read(udev_monitor->pfd[0], data, 1); + write(udev_monitor->pfd[1], "1", 1); + pthread_barrier_wait(&udev_monitor->barrier); + return NULL; + } - while (epoll_pwait(udev_monitor->efd, &epoll, 1, -1, &mask) != -1) { len = read(udev_monitor->ifd, data, sizeof(data)); if (len == -1) { @@ -214,72 +223,92 @@ int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_mo struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name) { struct udev_monitor *udev_monitor; - struct epoll_event epoll; + struct epoll_event epoll[2]; struct stat st; + int i; if (!udev || !name) { return NULL; } + if (lstat(UDEV_MONITOR_DIR, &st) != 0) { + if (mkdir(UDEV_MONITOR_DIR, 0) == -1) { + return NULL; + } + + if (chmod(UDEV_MONITOR_DIR, 0777) == -1) { + return NULL; + } + } + else if (!S_ISDIR(st.st_mode)) { + return NULL; + } + udev_monitor = calloc(1, sizeof(struct udev_monitor)); if (!udev_monitor) { return NULL; } - if (lstat(UDEV_MONITOR_DIR, &st) != 0) { - if (mkdir(UDEV_MONITOR_DIR, 0) == -1 || - chmod(UDEV_MONITOR_DIR, 0777) == -1) { - free(udev_monitor); - return NULL; - } - } - else if (!S_ISDIR(st.st_mode)) { - free(udev_monitor); - return NULL; - } - udev_monitor->efd = epoll_create1(EPOLL_CLOEXEC); if (udev_monitor->efd == -1) { - free(udev_monitor); - return NULL; + goto error_free; } udev_monitor->ifd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK); if (udev_monitor->ifd == -1) { - close(udev_monitor->efd); - free(udev_monitor); - return NULL; + goto error_efd; } if (inotify_add_watch(udev_monitor->ifd, UDEV_MONITOR_DIR, IN_CLOSE_WRITE | IN_EXCL_UNLINK) == -1) { - close(udev_monitor->ifd); - close(udev_monitor->efd); - free(udev_monitor); - return NULL; + goto error_ifd; } - epoll.events = EPOLLIN | EPOLLET; + if (pipe(udev_monitor->pfd) == -1) { + goto error_ifd; + } - if (epoll_ctl(udev_monitor->efd, EPOLL_CTL_ADD, udev_monitor->ifd, &epoll) == -1) { - close(udev_monitor->ifd); - close(udev_monitor->efd); - free(udev_monitor); - return NULL; + for (i = 0; i < 2; i++) { + fcntl(udev_monitor->pfd[i], F_SETFD, FD_CLOEXEC); + fcntl(udev_monitor->pfd[i], F_SETFL, O_NONBLOCK); + } + + epoll[0].events = EPOLLIN | EPOLLET; + epoll[1].events = EPOLLIN | EPOLLET; + epoll[1].data.fd = udev_monitor->pfd[0]; + + if (epoll_ctl(udev_monitor->efd, EPOLL_CTL_ADD, udev_monitor->ifd, &epoll[0]) == -1) { + goto error_pfd; + } + + if (epoll_ctl(udev_monitor->efd, EPOLL_CTL_ADD, udev_monitor->pfd[0], &epoll[1]) == -1) { + goto error_pfd; } if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, udev_monitor->sfd) == -1) { - close(udev_monitor->ifd); - close(udev_monitor->efd); - free(udev_monitor); - return NULL; + goto error_pfd; } udev_monitor->refcount = 1; udev_monitor->udev = udev; return udev_monitor; + +error_pfd: + for (i = 0; i < 2; i++) { + close(udev_monitor->pfd[i]); + } + +error_ifd: + close(udev_monitor->ifd); + +error_efd: + close(udev_monitor->efd); + +error_free: + free(udev_monitor); + return NULL; } struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor) @@ -304,17 +333,15 @@ struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor) return NULL; } - udev_list_entry_free_all(&udev_monitor->subsystem_match); - udev_list_entry_free_all(&udev_monitor->devtype_match); - - for (i = 0; i < THREADS_MAX; i++) { - pthread_cancel(udev_monitor->thread[i]); - } - + write(udev_monitor->pfd[1], "1", 1); pthread_barrier_wait(&udev_monitor->barrier); pthread_barrier_destroy(&udev_monitor->barrier); + udev_list_entry_free_all(&udev_monitor->devtype_match); + udev_list_entry_free_all(&udev_monitor->subsystem_match); + for (i = 0; i < 2; i++) { + close(udev_monitor->pfd[i]); close(udev_monitor->sfd[i]); } From 676c616b026a10025c6c3ba10d7813776b185035 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 16 Feb 2021 15:15:35 +0300 Subject: [PATCH 136/222] increment year --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index bf87ea9..4f36858 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ ISC License -Copyright (c) 2020 illiliti +Copyright (c) 2020-2021 illiliti Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above From 048701fa5f6e83cea569a36b602b7b74ae9d625f Mon Sep 17 00:00:00 2001 From: Arthur Williams Date: Tue, 16 Mar 2021 04:23:33 -0500 Subject: [PATCH 137/222] Detect touch devices as touchscreen The Goodix Capacitive TouchScreen on the pinephone was being detected as a joystick instead of a touchscreen. This patch correctly marks it as a touchscreen and allows it to work out of the box with libinput --- udev_device.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/udev_device.c b/udev_device.c index deab6f1..c7987a1 100644 --- a/udev_device.c +++ b/udev_device.c @@ -434,7 +434,12 @@ static void udev_device_set_properties_from_evdev(struct udev_device *udev_devic else if (find_bit(ev_bits, ev_cnt, EV_ABS)) { if (find_bit(key_bits, key_cnt, BTN_SELECT) || find_bit(key_bits, key_cnt, BTN_TR) || find_bit(key_bits, key_cnt, BTN_START) || find_bit(key_bits, key_cnt, BTN_TL)) { - udev_list_entry_add(&udev_device->properties, "ID_INPUT_JOYSTICK", "1", 0); + if (find_bit(key_bits, key_cnt, BTN_TOUCH)) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHSCREEN", "1", 0); + } + else { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_JOYSTICK", "1", 0); + } } else if (find_bit(abs_bits, abs_cnt, ABS_Y) && find_bit(abs_bits, abs_cnt, ABS_X)) { if (find_bit(abs_bits, abs_cnt, ABS_Z) && !find_bit(ev_bits, ev_cnt, EV_KEY)) { From 3d188e78e860f781c158fdb9ec4bcd9212aaa6eb Mon Sep 17 00:00:00 2001 From: Arthur Williams Date: Sun, 2 May 2021 04:40:16 -0500 Subject: [PATCH 138/222] Treat devices with keys as keyboards Some keyboards have an absolute axis and would erroneously not be treated as a keyboard. Now any device with keys would have the ID_INPUT_KEY property set. --- udev_device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/udev_device.c b/udev_device.c index c7987a1..92c1a41 100644 --- a/udev_device.c +++ b/udev_device.c @@ -461,7 +461,8 @@ static void udev_device_set_properties_from_evdev(struct udev_device *udev_devic } } } - else if (find_bit(ev_bits, ev_cnt, EV_KEY)) { + + if (find_bit(ev_bits, ev_cnt, EV_KEY)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEY", "1", 0); if (find_bit(key_bits, key_cnt, KEY_ENTER)) { From 6685cfaebad9f22d665c53490257aeb5970a07c2 Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 7 May 2021 10:26:32 +0300 Subject: [PATCH 139/222] add clarification why sys/sysmacros.h must be in udev.h --- udev.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/udev.h b/udev.h index b65819a..3735892 100644 --- a/udev.h +++ b/udev.h @@ -1,5 +1,8 @@ #include #include + +// we must keep this include here to fix some legacy programs +// https://freenode.logbot.info/kisslinux/20200722#c4467755 #include #ifndef _LIBUDEV_H_ From 721306c55df118ae01d95ee023d74df8d1b13361 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 18 May 2021 19:30:07 +0300 Subject: [PATCH 140/222] contrib/helper.c: make temporary file readable for everyone --- contrib/helper.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrib/helper.c b/contrib/helper.c index ba46094..0a45edf 100644 --- a/contrib/helper.c +++ b/contrib/helper.c @@ -15,6 +15,7 @@ #include #include #include +#include int main(int argc, char **argv) { @@ -58,6 +59,7 @@ int main(int argc, char **argv) } } + fchmod(fd, 0444); close(fd); return 0; } From f1107b0e17ae524707fc852b4d99c5baefd01161 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 18 May 2021 20:15:33 +0300 Subject: [PATCH 141/222] contrib/helper.c: minor fixes Exit with 2 if arguments are invalid. Compare unneeded environment variables with '=' delimiter to avoid false positives. --- contrib/helper.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/helper.c b/contrib/helper.c index 0a45edf..f2f3c50 100644 --- a/contrib/helper.c +++ b/contrib/helper.c @@ -33,7 +33,7 @@ int main(int argc, char **argv) break; default: fprintf(stderr, "usage: %s [dir]\n", argv[0]); - return 1; + return 2; } snprintf(path, sizeof(path), "%s/uevent.XXXXXX", dir); @@ -45,8 +45,8 @@ int main(int argc, char **argv) } for (i = 0; environ[i]; i++) { - if (strncmp(environ[i], "PATH", 4) == 0 || - strncmp(environ[i], "HOME", 4) == 0) { + if (strncmp(environ[i], "PATH=", 5) == 0 || + strncmp(environ[i], "HOME=", 5) == 0) { continue; } From 1fd071f24e80062526bd89f8b2941527e8933bb2 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 18 May 2021 20:27:26 +0300 Subject: [PATCH 142/222] contrib/helper.sh: exec env command to inherit exit status --- contrib/helper.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/helper.sh b/contrib/helper.sh index ef9877a..51bf19f 100644 --- a/contrib/helper.sh +++ b/contrib/helper.sh @@ -10,4 +10,4 @@ # NOTE: writing variables to file (e.g PWD or PATH) # that are not related to uevent properties is harmless -env > "${1:-/tmp/.libudev-zero}/uevent.$$" +exec env > "${1:-/tmp/.libudev-zero}/uevent.$$" From a885b93c3c545e8c32c13c1f304c3839bc466fbd Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 21 May 2021 05:31:53 +0300 Subject: [PATCH 143/222] udev_device.c: correctly handle multiline sysattrs Changed arbitrary size of sysattr to PAGESIZE[0]. Not sure about binary sysattrs because they may be > PAGESIZE. Either way, we need dynamic allocation to handle them. Trim only trailing newlines, not the first one. Now content of the sysattr not getting truncated. By the way, do we need to trim carrige return '\r' too? [0] https://www.kernel.org/doc/Documentation/filesystems/sysfs.txt > The buffer will always be PAGE_SIZE bytes in length. On i386, this is 4096. Fixes #25 --- udev_device.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/udev_device.c b/udev_device.c index 92c1a41..b487fd3 100644 --- a/udev_device.c +++ b/udev_device.c @@ -212,11 +212,10 @@ const char *udev_device_get_property_value(struct udev_device *udev_device, cons const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr) { struct udev_list_entry *list_entry; - char data[1024], path[PATH_MAX]; + char data[PAGESIZE], path[PATH_MAX]; struct stat st; size_t len; FILE *file; - char *pos; if (!udev_device || !sysattr) { return NULL; @@ -240,19 +239,21 @@ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const return NULL; } - len = fread(data, 1, sizeof(data), file); + // TODO dynamic allocation of data + len = fread(data, 1, sizeof(data)-1, file); - if (len != sizeof(data) && ferror(file)) { + if (len != sizeof(data)-1 && ferror(file)) { fclose(file); return NULL; } - if ((pos = memchr(data, '\n', len))) { - len = pos - data; - } - fclose(file); data[len] = '\0'; + + while (len-- > 0 && data[len] == '\n') { + data[len] = '\0'; + } + list_entry = udev_list_entry_add(&udev_device->sysattrs, sysattr, data, 0); return udev_list_entry_get_value(list_entry); } From f2083f0e47be676caa05dcf23bcfe77fbea831fb Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 25 May 2021 08:36:56 +0300 Subject: [PATCH 144/222] udev_monitor.c: block signals within event loop Fixes #23 Closes #24 --- udev_monitor.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/udev_monitor.c b/udev_monitor.c index 3e3197a..b6ff644 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -117,9 +118,13 @@ static void *udev_monitor_handle_event(void *ptr) struct inotify_event *event; struct epoll_event epoll[2]; char data[4096]; + sigset_t set; ssize_t len; int i; + sigfillset(&set); + pthread_sigmask(SIG_BLOCK, &set, NULL); + while (epoll_wait(udev_monitor->efd, epoll, 2, -1) != -1) { for (i = 0; i < 2; i++) { if (epoll[i].data.fd != udev_monitor->pfd[0]) { From 145e2c814fbf50fb1d0193da90fb947945f5e78e Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 25 May 2021 15:34:24 +0300 Subject: [PATCH 145/222] udev_device.c: attempt to fix incorrect bitmask handling Reference #22 --- udev_device.c | 108 ++++++++++++++++++++++++-------------------------- 1 file changed, 52 insertions(+), 56 deletions(-) diff --git a/udev_device.c b/udev_device.c index b487fd3..1ccd566 100644 --- a/udev_device.c +++ b/udev_device.c @@ -9,7 +9,17 @@ #include "udev.h" #include "udev_list.h" -#define BITS_MAX 96 +// sizeof(unsigned long) == 4 * 8 == 32 on 32-bit systems. +// sizeof(unsigned long) == 8 * 8 == 64 on 64-bit systems. +#ifndef LONG_BIT +#define LONG_BIT (sizeof(unsigned long) * 8) +#endif + +// https://www.kernel.org/doc/html/latest/input/ff.html#querying-device-capabilities +// https://www.kernel.org/doc/html/latest/input/input-programming.html#bits-to-longs-bit-word-bit-mask +#define BIT_WORD(x) ((x) / LONG_BIT) +#define BIT_MASK(x) (1UL << ((x) % LONG_BIT)) +#define BITS_TO_LONGS(x) (((x) + LONG_BIT - 1) / LONG_BIT) #ifndef INPUT_PROP_POINTING_STICK #define INPUT_PROP_POINTING_STICK 0x05 @@ -338,51 +348,37 @@ static void udev_device_set_properties_from_uevent(struct udev_device *udev_devi fclose(file); } -static int populate_bit(unsigned long *arr, const char *str) +static void make_bit(unsigned long *arr, int cnt, const char *str) { - char *beg, *end; + size_t len; int i; if (!str) { - return 0; + return; } - // TODO drop strdup ? - beg = end = strdup(str); - - if (!beg) { - return 0; - } - - for (i = 0; end[0] != '\0' && i < BITS_MAX; i++) { - arr[i] = strtoul(end, &end, 16); - } - - free(beg); - return i; -} - -static int find_bit(unsigned long *arr, int cnt, unsigned long bit) -{ - int i; - - for (i = 0; i < cnt; i++) { - if (arr[i] & (1UL << (bit % LONG_BIT))) { - return 1; + for (i = 0, len = strlen(str); i < cnt && len > 0; len--) { + if (str[len] == ' ') { + arr[i++] = strtoul(str + len + 1, NULL, 16); } } - return 0; + arr[i] = strtoul(str, NULL, 16); +} + +static int test_bit(unsigned long *arr, unsigned long bit) +{ + return arr[BIT_WORD(bit)] & BIT_MASK(bit); } static void udev_device_set_properties_from_evdev(struct udev_device *udev_device) { - int ev_cnt, rel_cnt, key_cnt, abs_cnt, prop_cnt; - unsigned long prop_bits[BITS_MAX] = {0}; - unsigned long abs_bits[BITS_MAX] = {0}; - unsigned long rel_bits[BITS_MAX] = {0}; - unsigned long key_bits[BITS_MAX] = {0}; - unsigned long ev_bits[BITS_MAX] = {0}; + // https://www.kernel.org/doc/html/latest/driver-api/input.html#c.input_dev + unsigned long prop_bits[BITS_TO_LONGS(INPUT_PROP_CNT)] = {0}; + unsigned long abs_bits[BITS_TO_LONGS(ABS_CNT)] = {0}; + unsigned long rel_bits[BITS_TO_LONGS(REL_CNT)] = {0}; + unsigned long key_bits[BITS_TO_LONGS(KEY_CNT)] = {0}; + unsigned long ev_bits[BITS_TO_LONGS(EV_CNT)] = {0}; struct udev_device *parent; const char *subsystem; @@ -406,67 +402,67 @@ static void udev_device_set_properties_from_evdev(struct udev_device *udev_devic parent = udev_device_get_parent_with_subsystem_devtype(parent, "input", NULL); } - ev_cnt = populate_bit(ev_bits, udev_device_get_property_value(parent, "EV")); - abs_cnt = populate_bit(abs_bits, udev_device_get_property_value(parent, "ABS")); - rel_cnt = populate_bit(rel_bits, udev_device_get_property_value(parent, "REL")); - key_cnt = populate_bit(key_bits, udev_device_get_property_value(parent, "KEY")); - prop_cnt = populate_bit(prop_bits, udev_device_get_property_value(parent, "PROP")); + make_bit(ev_bits, sizeof(ev_bits) / sizeof(ev_bits[0]), udev_device_get_property_value(parent, "EV")); + make_bit(abs_bits, sizeof(abs_bits) / sizeof(abs_bits[0]), udev_device_get_property_value(parent, "ABS")); + make_bit(rel_bits, sizeof(rel_bits) / sizeof(rel_bits[0]), udev_device_get_property_value(parent, "REL")); + make_bit(key_bits, sizeof(key_bits) / sizeof(key_bits[0]), udev_device_get_property_value(parent, "KEY")); + make_bit(prop_bits, sizeof(prop_bits) / sizeof(prop_bits[0]), udev_device_get_property_value(parent, "PROP")); udev_list_entry_add(&udev_device->properties, "ID_INPUT", "1", 0); - if (find_bit(prop_bits, prop_cnt, INPUT_PROP_POINTING_STICK)) { + if (test_bit(prop_bits, INPUT_PROP_POINTING_STICK)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_POINTINGSTICK", "1", 0); } - if (find_bit(prop_bits, prop_cnt, INPUT_PROP_ACCELEROMETER)) { + if (test_bit(prop_bits, INPUT_PROP_ACCELEROMETER)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_ACCELEROMETER", "1", 0); } - if (find_bit(ev_bits, ev_cnt, EV_SW)) { + if (test_bit(ev_bits, EV_SW)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_SWITCH", "1", 0); } - if (find_bit(ev_bits, ev_cnt, EV_REL)) { - if (find_bit(rel_bits, rel_cnt, REL_Y) && find_bit(rel_bits, rel_cnt, REL_X) && - find_bit(key_bits, key_cnt, BTN_MOUSE)) { + if (test_bit(ev_bits, EV_REL)) { + if (test_bit(rel_bits, REL_Y) && test_bit(rel_bits, REL_X) && + test_bit(key_bits, BTN_MOUSE)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1", 0); } } - else if (find_bit(ev_bits, ev_cnt, EV_ABS)) { - if (find_bit(key_bits, key_cnt, BTN_SELECT) || find_bit(key_bits, key_cnt, BTN_TR) || - find_bit(key_bits, key_cnt, BTN_START) || find_bit(key_bits, key_cnt, BTN_TL)) { - if (find_bit(key_bits, key_cnt, BTN_TOUCH)) { + else if (test_bit(ev_bits, EV_ABS)) { + if (test_bit(key_bits, BTN_SELECT) || test_bit(key_bits, BTN_TR) || + test_bit(key_bits, BTN_START) || test_bit(key_bits, BTN_TL)) { + if (test_bit(key_bits, BTN_TOUCH)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHSCREEN", "1", 0); } else { udev_list_entry_add(&udev_device->properties, "ID_INPUT_JOYSTICK", "1", 0); } } - else if (find_bit(abs_bits, abs_cnt, ABS_Y) && find_bit(abs_bits, abs_cnt, ABS_X)) { - if (find_bit(abs_bits, abs_cnt, ABS_Z) && !find_bit(ev_bits, ev_cnt, EV_KEY)) { + else if (test_bit(abs_bits, ABS_Y) && test_bit(abs_bits, ABS_X)) { + if (test_bit(abs_bits, ABS_Z) && !test_bit(ev_bits, EV_KEY)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_ACCELEROMETER", "1", 0); } - else if (find_bit(key_bits, key_cnt, BTN_STYLUS) || find_bit(key_bits, key_cnt, BTN_TOOL_PEN)) { + else if (test_bit(key_bits, BTN_STYLUS) || test_bit(key_bits, BTN_TOOL_PEN)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_TABLET", "1", 0); } - else if (find_bit(key_bits, key_cnt, BTN_TOUCH)) { - if (find_bit(key_bits, key_cnt, BTN_TOOL_FINGER)) { + else if (test_bit(key_bits, BTN_TOUCH)) { + if (test_bit(key_bits, BTN_TOOL_FINGER)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHPAD", "1", 0); } else { udev_list_entry_add(&udev_device->properties, "ID_INPUT_TOUCHSCREEN", "1", 0); } } - else if (find_bit(key_bits, key_cnt, BTN_MOUSE)) { + else if (test_bit(key_bits, BTN_MOUSE)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1", 0); } } } - if (find_bit(ev_bits, ev_cnt, EV_KEY)) { + if (test_bit(ev_bits, EV_KEY)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEY", "1", 0); - if (find_bit(key_bits, key_cnt, KEY_ENTER)) { + if (test_bit(key_bits, KEY_ENTER)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEYBOARD", "1", 0); } } From 4b044ae52cf8a127e40727d412621378b456b80a Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 26 May 2021 13:37:02 +0300 Subject: [PATCH 146/222] udev_device.c: avoid off-by-one overflow --- udev_device.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/udev_device.c b/udev_device.c index 1ccd566..dfc4431 100644 --- a/udev_device.c +++ b/udev_device.c @@ -363,7 +363,9 @@ static void make_bit(unsigned long *arr, int cnt, const char *str) } } - arr[i] = strtoul(str, NULL, 16); + if (i < cnt) { + arr[i] = strtoul(str, NULL, 16); + } } static int test_bit(unsigned long *arr, unsigned long bit) From 0ea1528dfc7375ce0cccbd4b64b3f533c8662ccb Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 26 May 2021 14:23:24 +0300 Subject: [PATCH 147/222] udev_device.c: simplify bounds checking --- udev_device.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/udev_device.c b/udev_device.c index dfc4431..593e034 100644 --- a/udev_device.c +++ b/udev_device.c @@ -357,15 +357,17 @@ static void make_bit(unsigned long *arr, int cnt, const char *str) return; } - for (i = 0, len = strlen(str); i < cnt && len > 0; len--) { + for (i = 0, len = strlen(str); len > 0; len--) { if (str[len] == ' ') { arr[i++] = strtoul(str + len + 1, NULL, 16); } + + if (i == cnt) { + return; + } } - if (i < cnt) { - arr[i] = strtoul(str, NULL, 16); - } + arr[i] = strtoul(str, NULL, 16); } static int test_bit(unsigned long *arr, unsigned long bit) From f44332df5afce755af0f54b6bf7ac2778b10ec4b Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 26 May 2021 17:55:29 +0300 Subject: [PATCH 148/222] various: drop udev_* prefix from static functions --- udev_device.c | 30 +++++++++++++++--------------- udev_enumerate.c | 24 ++++++++++++------------ udev_monitor.c | 12 ++++++------ 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/udev_device.c b/udev_device.c index 593e034..1778487 100644 --- a/udev_device.c +++ b/udev_device.c @@ -303,12 +303,12 @@ int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *s return 0; } -static char *udev_device_read_symlink(struct udev_device *udev_device, const char *name) +static char *read_symlink(const char *syspath, const char *name) { char link[PATH_MAX], path[PATH_MAX]; ssize_t len; - snprintf(path, sizeof(path), "%s/%s", udev_device_get_syspath(udev_device), name); + snprintf(path, sizeof(path), "%s/%s", syspath, name); len = readlink(path, link, sizeof(link)); if (len == -1) { @@ -319,7 +319,7 @@ static char *udev_device_read_symlink(struct udev_device *udev_device, const cha return strdup(strrchr(link, '/') + 1); } -static void udev_device_set_properties_from_uevent(struct udev_device *udev_device) +static void set_properties_from_uevent(struct udev_device *udev_device) { char line[LINE_MAX], path[PATH_MAX], devnode[PATH_MAX]; FILE *file; @@ -360,10 +360,10 @@ static void make_bit(unsigned long *arr, int cnt, const char *str) for (i = 0, len = strlen(str); len > 0; len--) { if (str[len] == ' ') { arr[i++] = strtoul(str + len + 1, NULL, 16); - } - if (i == cnt) { - return; + if (i == cnt) { + return; + } } } @@ -375,7 +375,7 @@ static int test_bit(unsigned long *arr, unsigned long bit) return arr[BIT_WORD(bit)] & BIT_MASK(bit); } -static void udev_device_set_properties_from_evdev(struct udev_device *udev_device) +static void set_properties_from_evdev(struct udev_device *udev_device) { // https://www.kernel.org/doc/html/latest/driver-api/input.html#c.input_dev unsigned long prop_bits[BITS_TO_LONGS(INPUT_PROP_CNT)] = {0}; @@ -472,7 +472,7 @@ static void udev_device_set_properties_from_evdev(struct udev_device *udev_devic } } -static void udev_device_set_properties_from_props(struct udev_device *udev_device) +static void set_properties_from_props(struct udev_device *udev_device) { const char *sysname, *subsystem; struct udev_device *parent; @@ -533,8 +533,8 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * udev_list_entry_add(&udev_device->properties, "DEVPATH", path + 4, 0); sysname = strrchr(path, '/') + 1; - driver = udev_device_read_symlink(udev_device, "driver"); - subsystem = udev_device_read_symlink(udev_device, "subsystem"); + driver = read_symlink(path, "driver"); + subsystem = read_symlink(path, "subsystem"); udev_list_entry_add(&udev_device->properties, "SUBSYSTEM", subsystem, 0); udev_list_entry_add(&udev_device->properties, "SYSNAME", sysname, 0); @@ -547,9 +547,9 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * } } - udev_device_set_properties_from_uevent(udev_device); - udev_device_set_properties_from_evdev(udev_device); - udev_device_set_properties_from_props(udev_device); + set_properties_from_uevent(udev_device); + set_properties_from_evdev(udev_device); + set_properties_from_props(udev_device); free(driver); free(subsystem); @@ -668,8 +668,8 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat return NULL; } - udev_device_set_properties_from_props(udev_device); - udev_device_set_properties_from_evdev(udev_device); + set_properties_from_props(udev_device); + set_properties_from_evdev(udev_device); return udev_device; } diff --git a/udev_enumerate.c b/udev_enumerate.c index 8916b43..2152e43 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -73,7 +73,7 @@ int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, cons return 0; } -static int udev_enumerate_filter_subsystem(struct udev_enumerate *udev_enumerate, struct udev_device *udev_device) +static int filter_subsystem(struct udev_enumerate *udev_enumerate, struct udev_device *udev_device) { struct udev_list_entry *list_entry; const char *subsystem; @@ -110,7 +110,7 @@ static int udev_enumerate_filter_subsystem(struct udev_enumerate *udev_enumerate return 1; } -static int udev_enumerate_filter_sysname(struct udev_enumerate *udev_enumerate, struct udev_device *udev_device) +static int filter_sysname(struct udev_enumerate *udev_enumerate, struct udev_device *udev_device) { struct udev_list_entry *list_entry; const char *sysname; @@ -133,7 +133,7 @@ static int udev_enumerate_filter_sysname(struct udev_enumerate *udev_enumerate, return 0; } -static int udev_enumerate_filter_property(struct udev_enumerate *udev_enumerate, struct udev_device *udev_device) +static int 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; @@ -176,7 +176,7 @@ static int udev_enumerate_filter_property(struct udev_enumerate *udev_enumerate, return 0; } -static int udev_enumerate_filter_sysattr(struct udev_enumerate *udev_enumerate, struct udev_device *udev_device) +static int filter_sysattr(struct udev_enumerate *udev_enumerate, struct udev_device *udev_device) { struct udev_list_entry *list_entry; const char *sysattr, *value; @@ -222,7 +222,7 @@ static int udev_enumerate_filter_sysattr(struct udev_enumerate *udev_enumerate, return 1; } -static void *udev_enumerate_add_device(void *ptr) +static void *add_device(void *ptr) { struct udev_enumerate_thread *thread = ptr; struct udev_device *udev_device; @@ -233,10 +233,10 @@ static void *udev_enumerate_add_device(void *ptr) return NULL; } - if (!udev_enumerate_filter_subsystem(thread->udev_enumerate, udev_device) || - !udev_enumerate_filter_sysname(thread->udev_enumerate, udev_device) || - !udev_enumerate_filter_property(thread->udev_enumerate, udev_device) || - !udev_enumerate_filter_sysattr(thread->udev_enumerate, udev_device)) { + if (!filter_subsystem(thread->udev_enumerate, udev_device) || + !filter_sysname(thread->udev_enumerate, udev_device) || + !filter_property(thread->udev_enumerate, udev_device) || + !filter_sysattr(thread->udev_enumerate, udev_device)) { udev_device_unref(udev_device); return NULL; } @@ -254,7 +254,7 @@ static int filter_dot(const struct dirent *de) return de->d_name[0] != '.'; } -static int udev_enumerate_add_devices(struct udev_enumerate *udev_enumerate, const char *path) +static int scan_devices(struct udev_enumerate *udev_enumerate, const char *path) { struct udev_enumerate_thread *thread; pthread_mutex_t mutex; @@ -285,7 +285,7 @@ static int udev_enumerate_add_devices(struct udev_enumerate *udev_enumerate, con thread[i].udev_enumerate = udev_enumerate; snprintf(thread[i].path, sizeof(thread[i].path), "%s/%s", path, de[i]->d_name); - pthread_create(&thread[i].thread, NULL, udev_enumerate_add_device, &thread[i]); + pthread_create(&thread[i].thread, NULL, add_device, &thread[i]); } for (i = 0; i < cnt; i++) { @@ -312,7 +312,7 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) } for (i = 0; path[i]; i++) { - if (udev_enumerate_add_devices(udev_enumerate, path[i]) == -1) { + if (scan_devices(udev_enumerate, path[i]) == -1) { return -1; } } diff --git a/udev_monitor.c b/udev_monitor.c index b6ff644..9bdb70e 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -33,7 +33,7 @@ struct udev_monitor { int efd; }; -static int udev_monitor_filter_devtype(struct udev_monitor *udev_monitor, struct udev_device *udev_device) +static int filter_devtype(struct udev_monitor *udev_monitor, struct udev_device *udev_device) { struct udev_list_entry *list_entry; const char *devtype; @@ -60,7 +60,7 @@ static int udev_monitor_filter_devtype(struct udev_monitor *udev_monitor, struct return 0; } -static int udev_monitor_filter_subsystem(struct udev_monitor *udev_monitor, struct udev_device *udev_device) +static int filter_subsystem(struct udev_monitor *udev_monitor, struct udev_device *udev_device) { struct udev_list_entry *list_entry; const char *subsystem; @@ -103,8 +103,8 @@ struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monito return NULL; } - if (!udev_monitor_filter_subsystem(udev_monitor, udev_device) || - !udev_monitor_filter_devtype(udev_monitor, udev_device)) { + if (!filter_subsystem(udev_monitor, udev_device) || + !filter_devtype(udev_monitor, udev_device)) { udev_device_unref(udev_device); return NULL; } @@ -112,7 +112,7 @@ struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monito return udev_device; } -static void *udev_monitor_handle_event(void *ptr) +static void *handle_event(void *ptr) { struct udev_monitor *udev_monitor = ptr; struct inotify_event *event; @@ -173,7 +173,7 @@ int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) pthread_barrier_init(&udev_monitor->barrier, NULL, THREADS_MAX + 1); for (i = 0; i < THREADS_MAX; i++) { - pthread_create(&udev_monitor->thread[i], &attr, udev_monitor_handle_event, udev_monitor); + pthread_create(&udev_monitor->thread[i], &attr, handle_event, udev_monitor); } pthread_attr_destroy(&attr); From 3d97786f09492cb62c69ccb7947f9fca280e0809 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 27 May 2021 19:13:04 +0300 Subject: [PATCH 149/222] udev_device.c: drop PAGESIZE glibc violates POSIX and does not define it. --- udev_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udev_device.c b/udev_device.c index 1778487..de86c88 100644 --- a/udev_device.c +++ b/udev_device.c @@ -222,7 +222,7 @@ const char *udev_device_get_property_value(struct udev_device *udev_device, cons const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr) { struct udev_list_entry *list_entry; - char data[PAGESIZE], path[PATH_MAX]; + char data[4096], path[PATH_MAX]; struct stat st; size_t len; FILE *file; From af98e237cb65a5cf54bf222ed18b8c75413f13a7 Mon Sep 17 00:00:00 2001 From: Arthur Williams Date: Sun, 16 May 2021 02:58:40 -0500 Subject: [PATCH 150/222] Remove epoll dependency Instead of using the Linux-specific epoll, we can use the more portable poll. --- README.md | 2 +- udev_monitor.c | 52 ++++++++++++++++---------------------------------- 2 files changed, 17 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 958065e..ae27beb 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Thankfully `udev` has stable API and hopefully no changes will be made to it the * C99 compiler (build time) * POSIX make (build time) * POSIX & XSI libc -* epoll & inotify +* inotify * Linux >= 2.6.39 ## Installation diff --git a/udev_monitor.c b/udev_monitor.c index 9bdb70e..25a27dd 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -1,13 +1,13 @@ +#include +#include #include #include -#include #include #include #include #include #include #include -#include #include #include @@ -30,7 +30,6 @@ struct udev_monitor { int sfd[2]; int pfd[2]; int ifd; - int efd; }; static int filter_devtype(struct udev_monitor *udev_monitor, struct udev_device *udev_device) @@ -116,25 +115,29 @@ static void *handle_event(void *ptr) { struct udev_monitor *udev_monitor = ptr; struct inotify_event *event; - struct epoll_event epoll[2]; + struct pollfd poll_fds[2]; char data[4096]; - sigset_t set; ssize_t len; int i; - sigfillset(&set); - pthread_sigmask(SIG_BLOCK, &set, NULL); + poll_fds[0].fd = udev_monitor->ifd; + poll_fds[0].events = POLLIN; - while (epoll_wait(udev_monitor->efd, epoll, 2, -1) != -1) { - for (i = 0; i < 2; i++) { - if (epoll[i].data.fd != udev_monitor->pfd[0]) { + poll_fds[1].fd = udev_monitor->pfd[0]; + poll_fds[1].events = POLLIN; + + while (1) { + if (poll(poll_fds, 2, -1) == -1) { + if (errno == EINTR) { continue; } + break; + } + if (poll_fds[1].revents & POLLIN) { read(udev_monitor->pfd[0], data, 1); write(udev_monitor->pfd[1], "1", 1); - pthread_barrier_wait(&udev_monitor->barrier); - return NULL; + break; } len = read(udev_monitor->ifd, data, sizeof(data)); @@ -228,7 +231,6 @@ int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_mo struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name) { struct udev_monitor *udev_monitor; - struct epoll_event epoll[2]; struct stat st; int i; @@ -255,16 +257,10 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char return NULL; } - udev_monitor->efd = epoll_create1(EPOLL_CLOEXEC); - - if (udev_monitor->efd == -1) { - goto error_free; - } - udev_monitor->ifd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK); if (udev_monitor->ifd == -1) { - goto error_efd; + goto error_free; } if (inotify_add_watch(udev_monitor->ifd, UDEV_MONITOR_DIR, IN_CLOSE_WRITE | IN_EXCL_UNLINK) == -1) { @@ -280,18 +276,6 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char fcntl(udev_monitor->pfd[i], F_SETFL, O_NONBLOCK); } - epoll[0].events = EPOLLIN | EPOLLET; - epoll[1].events = EPOLLIN | EPOLLET; - epoll[1].data.fd = udev_monitor->pfd[0]; - - if (epoll_ctl(udev_monitor->efd, EPOLL_CTL_ADD, udev_monitor->ifd, &epoll[0]) == -1) { - goto error_pfd; - } - - if (epoll_ctl(udev_monitor->efd, EPOLL_CTL_ADD, udev_monitor->pfd[0], &epoll[1]) == -1) { - goto error_pfd; - } - if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, udev_monitor->sfd) == -1) { goto error_pfd; } @@ -308,9 +292,6 @@ error_pfd: error_ifd: close(udev_monitor->ifd); -error_efd: - close(udev_monitor->efd); - error_free: free(udev_monitor); return NULL; @@ -351,7 +332,6 @@ struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor) } close(udev_monitor->ifd); - close(udev_monitor->efd); free(udev_monitor); return NULL; } From 03c53bc1c3ef8eddee0e3f75c18609798539faf2 Mon Sep 17 00:00:00 2001 From: Arthur Williams Date: Mon, 31 May 2021 18:18:34 -0500 Subject: [PATCH 151/222] Removed THREAD_MAX and the barrier and pfd fields from udev_monitor We can fix THREAD_MAX at one since we don't gain much by having multiple threads. All the threads did were translate inotify events. We also no longer need pfd and the barrier fields of udev_monitor since we don't need to signal the single thread or guard against any races. --- udev_monitor.c | 68 +++++++++++++++++++------------------------------- 1 file changed, 26 insertions(+), 42 deletions(-) diff --git a/udev_monitor.c b/udev_monitor.c index 25a27dd..30dcaf0 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -9,13 +9,12 @@ #include #include #include +#include #include #include "udev.h" #include "udev_list.h" -#define THREADS_MAX 5 - #ifndef UDEV_MONITOR_DIR #define UDEV_MONITOR_DIR "/tmp/.libudev-zero" #endif @@ -23,12 +22,11 @@ struct udev_monitor { struct udev_list_entry subsystem_match; struct udev_list_entry devtype_match; - pthread_t thread[THREADS_MAX]; - pthread_barrier_t barrier; + pthread_t thread; struct udev *udev; int refcount; + int signal_fd; int sfd[2]; - int pfd[2]; int ifd; }; @@ -123,7 +121,7 @@ static void *handle_event(void *ptr) poll_fds[0].fd = udev_monitor->ifd; poll_fds[0].events = POLLIN; - poll_fds[1].fd = udev_monitor->pfd[0]; + poll_fds[1].fd = udev_monitor->signal_fd; poll_fds[1].events = POLLIN; while (1) { @@ -134,9 +132,8 @@ static void *handle_event(void *ptr) break; } + // exit on explicit signal if (poll_fds[1].revents & POLLIN) { - read(udev_monitor->pfd[0], data, 1); - write(udev_monitor->pfd[1], "1", 1); break; } @@ -146,6 +143,11 @@ static void *handle_event(void *ptr) continue; } + // exit on ifd error or close + if (!(poll_fds[0].revents & POLLIN) || len == 0) { + break; + } + for (i = 0; i < len; i += sizeof(struct inotify_event) + event->len) { event = (struct inotify_event *)&data[i]; @@ -158,28 +160,16 @@ static void *handle_event(void *ptr) } } - pthread_barrier_wait(&udev_monitor->barrier); return NULL; } int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) { - pthread_attr_t attr; - int i; - if (!udev_monitor) { return -1; } - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_barrier_init(&udev_monitor->barrier, NULL, THREADS_MAX + 1); - - for (i = 0; i < THREADS_MAX; i++) { - pthread_create(&udev_monitor->thread[i], &attr, handle_event, udev_monitor); - } - - pthread_attr_destroy(&attr); + pthread_create(&udev_monitor->thread, NULL, handle_event, udev_monitor); return 0; } @@ -232,7 +222,6 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char { struct udev_monitor *udev_monitor; struct stat st; - int i; if (!udev || !name) { return NULL; @@ -257,41 +246,35 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char return NULL; } + udev_monitor->signal_fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); + if (udev_monitor->signal_fd == -1) { + goto error_free; + } + udev_monitor->ifd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK); if (udev_monitor->ifd == -1) { - goto error_free; + goto error_signal_fd; } if (inotify_add_watch(udev_monitor->ifd, UDEV_MONITOR_DIR, IN_CLOSE_WRITE | IN_EXCL_UNLINK) == -1) { goto error_ifd; } - if (pipe(udev_monitor->pfd) == -1) { - goto error_ifd; - } - - for (i = 0; i < 2; i++) { - fcntl(udev_monitor->pfd[i], F_SETFD, FD_CLOEXEC); - fcntl(udev_monitor->pfd[i], F_SETFL, O_NONBLOCK); - } - if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, udev_monitor->sfd) == -1) { - goto error_pfd; + goto error_ifd; } udev_monitor->refcount = 1; udev_monitor->udev = udev; return udev_monitor; -error_pfd: - for (i = 0; i < 2; i++) { - close(udev_monitor->pfd[i]); - } - error_ifd: close(udev_monitor->ifd); +error_signal_fd: + close(udev_monitor->signal_fd); + error_free: free(udev_monitor); return NULL; @@ -319,18 +302,19 @@ struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor) return NULL; } - write(udev_monitor->pfd[1], "1", 1); - pthread_barrier_wait(&udev_monitor->barrier); - pthread_barrier_destroy(&udev_monitor->barrier); + // Wake up the event thread + eventfd_write(udev_monitor->signal_fd, 1); + // waiting for event thread to end before freeing udev_monitor + pthread_join(udev_monitor->thread, NULL); udev_list_entry_free_all(&udev_monitor->devtype_match); udev_list_entry_free_all(&udev_monitor->subsystem_match); for (i = 0; i < 2; i++) { - close(udev_monitor->pfd[i]); close(udev_monitor->sfd[i]); } + close(udev_monitor->signal_fd); close(udev_monitor->ifd); free(udev_monitor); return NULL; From e06dfcd22ceac055e2436e729510da781042ca91 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 1 Jun 2021 17:23:32 +0300 Subject: [PATCH 152/222] udev_monitor.c: minor fixes --- udev_monitor.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/udev_monitor.c b/udev_monitor.c index 30dcaf0..e64be9e 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -129,12 +129,13 @@ static void *handle_event(void *ptr) if (errno == EINTR) { continue; } - break; + + return NULL; } // exit on explicit signal if (poll_fds[1].revents & POLLIN) { - break; + return NULL; } len = read(udev_monitor->ifd, data, sizeof(data)); @@ -145,7 +146,7 @@ static void *handle_event(void *ptr) // exit on ifd error or close if (!(poll_fds[0].revents & POLLIN) || len == 0) { - break; + return NULL; } for (i = 0; i < len; i += sizeof(struct inotify_event) + event->len) { @@ -160,6 +161,7 @@ static void *handle_event(void *ptr) } } + // unreacheble return NULL; } @@ -169,8 +171,7 @@ int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) return -1; } - pthread_create(&udev_monitor->thread, NULL, handle_event, udev_monitor); - return 0; + return pthread_create(&udev_monitor->thread, NULL, handle_event, udev_monitor); } /* XXX NOT IMPLEMENTED */ int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size) @@ -247,35 +248,36 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char } udev_monitor->signal_fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); + if (udev_monitor->signal_fd == -1) { - goto error_free; + goto free_monitor; } udev_monitor->ifd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK); if (udev_monitor->ifd == -1) { - goto error_signal_fd; + goto close_signal_fd; } if (inotify_add_watch(udev_monitor->ifd, UDEV_MONITOR_DIR, IN_CLOSE_WRITE | IN_EXCL_UNLINK) == -1) { - goto error_ifd; + goto close_ifd; } if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, udev_monitor->sfd) == -1) { - goto error_ifd; + goto close_ifd; } udev_monitor->refcount = 1; udev_monitor->udev = udev; return udev_monitor; -error_ifd: +close_ifd: close(udev_monitor->ifd); -error_signal_fd: +close_signal_fd: close(udev_monitor->signal_fd); -error_free: +free_monitor: free(udev_monitor); return NULL; } From 93c48c86ec4a89de922194bbe4ed92e1ec220eef Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 1 Jun 2021 22:08:00 +0300 Subject: [PATCH 153/222] udev_device.c: nitpick --- udev_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/udev_device.c b/udev_device.c index de86c88..7e56274 100644 --- a/udev_device.c +++ b/udev_device.c @@ -250,9 +250,9 @@ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const } // TODO dynamic allocation of data - len = fread(data, 1, sizeof(data)-1, file); + len = fread(data, 1, sizeof(data) - 1, file); - if (len != sizeof(data)-1 && ferror(file)) { + if (len != sizeof(data) - 1 && ferror(file)) { fclose(file); return NULL; } From 6dcad515e9ace05ff308d8ead76432866064dce4 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 1 Jun 2021 22:08:50 +0300 Subject: [PATCH 154/222] readme: add eventfd to deps --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ae27beb..43c4f98 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Thankfully `udev` has stable API and hopefully no changes will be made to it the * C99 compiler (build time) * POSIX make (build time) * POSIX & XSI libc -* inotify +* inotify & eventfd * Linux >= 2.6.39 ## Installation From 41d6cc99761e9f69ad6bac1cac7121ccbd5a3578 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 3 Jun 2021 03:21:56 +0300 Subject: [PATCH 155/222] udev_device.c: avoid passing NULL to atoi --- udev_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udev_device.c b/udev_device.c index 7e56274..063ecbe 100644 --- a/udev_device.c +++ b/udev_device.c @@ -87,7 +87,7 @@ dev_t udev_device_get_devnum(struct udev_device *udev_device) major = udev_device_get_property_value(udev_device, "MAJOR"); minor = udev_device_get_property_value(udev_device, "MINOR"); - if (!major && !minor) { + if (!major || !minor) { return makedev(0, 0); } From b3f44ae7c953197b9a62d19aa8b9d0a820bffaa7 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 3 Jun 2021 05:19:14 +0300 Subject: [PATCH 156/222] contrib/helper.c: replace strncmp with strcmp --- contrib/helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/helper.c b/contrib/helper.c index f2f3c50..3fee687 100644 --- a/contrib/helper.c +++ b/contrib/helper.c @@ -45,8 +45,8 @@ int main(int argc, char **argv) } for (i = 0; environ[i]; i++) { - if (strncmp(environ[i], "PATH=", 5) == 0 || - strncmp(environ[i], "HOME=", 5) == 0) { + if (strcmp(environ[i], "PATH=") == 0 || + strcmp(environ[i], "HOME=") == 0) { continue; } From ff6cf67c23c04d5565b8d9f942ade288180aea58 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 3 Jun 2021 05:28:46 +0300 Subject: [PATCH 157/222] udev_device.c: replace strncmp with strcmp --- udev_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/udev_device.c b/udev_device.c index 063ecbe..1b3b6e4 100644 --- a/udev_device.c +++ b/udev_device.c @@ -335,7 +335,7 @@ static void set_properties_from_uevent(struct udev_device *udev_device) while (fgets(line, sizeof(line), file)) { line[strlen(line) - 1] = '\0'; - if (strncmp(line, "DEVNAME", 7) == 0) { + if (strcmp(line, "DEVNAME=") == 0) { snprintf(devnode, sizeof(devnode), "/dev/%s", line + 8); udev_list_entry_add(&udev_device->properties, "DEVNAME", devnode, 0); } @@ -636,7 +636,7 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat while (fgets(line, sizeof(line), file)) { line[strlen(line) - 1] = '\0'; - if (strncmp(line, "DEVPATH", 7) == 0) { + if (strcmp(line, "DEVPATH=") == 0) { snprintf(syspath, sizeof(syspath), "/sys%s", line + 8); udev_list_entry_add(&udev_device->properties, "SYSPATH", syspath, 0); udev_list_entry_add(&udev_device->properties, "DEVPATH", line + 8, 0); @@ -651,7 +651,7 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat } } } - else if (strncmp(line, "DEVNAME", 7) == 0) { + else if (strcmp(line, "DEVNAME=") == 0) { snprintf(devnode, sizeof(devnode), "/dev/%s", line + 8); udev_list_entry_add(&udev_device->properties, "DEVNAME", devnode, 0); } From 53aa6f3b0411fb6dbddc5460e6275cab65080119 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 3 Jun 2021 06:26:42 +0300 Subject: [PATCH 158/222] udev_device.c: abort if uevent file is malformed --- udev_device.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/udev_device.c b/udev_device.c index 1b3b6e4..8a4c45a 100644 --- a/udev_device.c +++ b/udev_device.c @@ -15,8 +15,8 @@ #define LONG_BIT (sizeof(unsigned long) * 8) #endif -// https://www.kernel.org/doc/html/latest/input/ff.html#querying-device-capabilities -// https://www.kernel.org/doc/html/latest/input/input-programming.html#bits-to-longs-bit-word-bit-mask +// https://kernel.org/doc/html/latest/input/ff.html#querying-device-capabilities +// https://kernel.org/doc/html/latest/input/input-programming.html#bits-to-longs-bit-word-bit-mask #define BIT_WORD(x) ((x) / LONG_BIT) #define BIT_MASK(x) (1UL << ((x) % LONG_BIT)) #define BITS_TO_LONGS(x) (((x) + LONG_BIT - 1) / LONG_BIT) @@ -377,7 +377,7 @@ static int test_bit(unsigned long *arr, unsigned long bit) static void set_properties_from_evdev(struct udev_device *udev_device) { - // https://www.kernel.org/doc/html/latest/driver-api/input.html#c.input_dev + // https://kernel.org/doc/html/latest/driver-api/input.html#c.input_dev unsigned long prop_bits[BITS_TO_LONGS(INPUT_PROP_CNT)] = {0}; unsigned long abs_bits[BITS_TO_LONGS(ABS_CNT)] = {0}; unsigned long rel_bits[BITS_TO_LONGS(REL_CNT)] = {0}; @@ -603,11 +603,11 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat { char line[LINE_MAX], syspath[PATH_MAX], devnode[PATH_MAX]; struct udev_device *udev_device; - char *sysname = NULL; struct stat st; + char *sysname; FILE *file; + int i, cnt; char *pos; - int i; if (stat(path, &st) != 0 || st.st_size > 8192) { return NULL; @@ -626,6 +626,8 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat return NULL; } + cnt = 0; + udev_device->udev = udev; udev_device->refcount = 1; udev_device->parent = NULL; @@ -650,20 +652,39 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat break; } } + + cnt++; } else if (strcmp(line, "DEVNAME=") == 0) { snprintf(devnode, sizeof(devnode), "/dev/%s", line + 8); udev_list_entry_add(&udev_device->properties, "DEVNAME", devnode, 0); } - else if ((pos = strchr(line, '='))) { + else { + pos = strchr(line, '='); + + // file is malformed, abort here. + if (!pos) { + cnt = 0; + break; + } + *pos = '\0'; + + if (strcmp(line, "SUBSYSTEM") == 0 || + strcmp(line, "ACTION") == 0 || + strcmp(line, "SEQNUM") == 0) { + cnt++; + } + udev_list_entry_add(&udev_device->properties, line, pos + 1, 0); } } fclose(file); - if (!sysname) { + // https://freedesktop.org/software/systemd/man/udev_device_new_from_environment.html + // > The keys DEVPATH, SUBSYSTEM, ACTION, and SEQNUM are mandatory. + if (cnt != 4) { udev_device_unref(udev_device); return NULL; } From 0a1be0e4c0a9ce8ce89752fe057e2ba9ce01082d Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 3 Jun 2021 07:23:30 +0300 Subject: [PATCH 159/222] Revert "contrib/helper.c: replace strncmp with strcmp" This reverts commit b3f44ae7c953197b9a62d19aa8b9d0a820bffaa7. --- contrib/helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/helper.c b/contrib/helper.c index 3fee687..f2f3c50 100644 --- a/contrib/helper.c +++ b/contrib/helper.c @@ -45,8 +45,8 @@ int main(int argc, char **argv) } for (i = 0; environ[i]; i++) { - if (strcmp(environ[i], "PATH=") == 0 || - strcmp(environ[i], "HOME=") == 0) { + if (strncmp(environ[i], "PATH=", 5) == 0 || + strncmp(environ[i], "HOME=", 5) == 0) { continue; } From 0fd4054baf62ab97ecedb72d44c8a31f262f36a5 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 3 Jun 2021 07:24:19 +0300 Subject: [PATCH 160/222] Revert "udev_device.c: replace strncmp with strcmp" This reverts commit ff6cf67c23c04d5565b8d9f942ade288180aea58. --- udev_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/udev_device.c b/udev_device.c index 8a4c45a..4769167 100644 --- a/udev_device.c +++ b/udev_device.c @@ -335,7 +335,7 @@ static void set_properties_from_uevent(struct udev_device *udev_device) while (fgets(line, sizeof(line), file)) { line[strlen(line) - 1] = '\0'; - if (strcmp(line, "DEVNAME=") == 0) { + if (strncmp(line, "DEVNAME", 7) == 0) { snprintf(devnode, sizeof(devnode), "/dev/%s", line + 8); udev_list_entry_add(&udev_device->properties, "DEVNAME", devnode, 0); } @@ -638,7 +638,7 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat while (fgets(line, sizeof(line), file)) { line[strlen(line) - 1] = '\0'; - if (strcmp(line, "DEVPATH=") == 0) { + if (strncmp(line, "DEVPATH", 7) == 0) { snprintf(syspath, sizeof(syspath), "/sys%s", line + 8); udev_list_entry_add(&udev_device->properties, "SYSPATH", syspath, 0); udev_list_entry_add(&udev_device->properties, "DEVPATH", line + 8, 0); @@ -655,7 +655,7 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat cnt++; } - else if (strcmp(line, "DEVNAME=") == 0) { + else if (strncmp(line, "DEVNAME", 7) == 0) { snprintf(devnode, sizeof(devnode), "/dev/%s", line + 8); udev_list_entry_add(&udev_device->properties, "DEVNAME", devnode, 0); } From 4a6b31b8f105e8ff87c21b7e0eaa123bf23684b2 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 3 Jun 2021 09:17:39 +0300 Subject: [PATCH 161/222] udev_monitor.c: remove no longer required fcntl.h include --- udev_monitor.c | 1 - 1 file changed, 1 deletion(-) diff --git a/udev_monitor.c b/udev_monitor.c index e64be9e..17e2912 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -1,6 +1,5 @@ #include #include -#include #include #include #include From f4b2b9331eafcc84b88bb48fdec0bab4e72688a0 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 3 Jun 2021 09:19:45 +0300 Subject: [PATCH 162/222] udev_monitor.c: fail if monitored file is not dir --- udev_monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udev_monitor.c b/udev_monitor.c index 17e2912..be7ec22 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -258,7 +258,7 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char goto close_signal_fd; } - if (inotify_add_watch(udev_monitor->ifd, UDEV_MONITOR_DIR, IN_CLOSE_WRITE | IN_EXCL_UNLINK) == -1) { + if (inotify_add_watch(udev_monitor->ifd, UDEV_MONITOR_DIR, IN_CLOSE_WRITE | IN_EXCL_UNLINK | IN_ONLYDIR) == -1) { goto close_ifd; } From 32f9d14551adcdd5e6000a1884e157a193492928 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 3 Jun 2021 09:24:55 +0300 Subject: [PATCH 163/222] udev_monitor.c: fix bad return value in udev_monitor_enable_receiving --- udev_monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udev_monitor.c b/udev_monitor.c index be7ec22..804dd36 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -170,7 +170,7 @@ int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) return -1; } - return pthread_create(&udev_monitor->thread, NULL, handle_event, udev_monitor); + return (pthread_create(&udev_monitor->thread, NULL, handle_event, udev_monitor) == 0) - 1; } /* XXX NOT IMPLEMENTED */ int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size) From 37e5fa72062e6d8eb7a1cc2945954c1ef08b7333 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 3 Jun 2021 09:30:46 +0300 Subject: [PATCH 164/222] udev_monitor.c: inotify read of size 0 is impossible --- udev_monitor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/udev_monitor.c b/udev_monitor.c index 804dd36..9e26bce 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -144,7 +144,7 @@ static void *handle_event(void *ptr) } // exit on ifd error or close - if (!(poll_fds[0].revents & POLLIN) || len == 0) { + if (!(poll_fds[0].revents & POLLIN)) { return NULL; } @@ -160,7 +160,7 @@ static void *handle_event(void *ptr) } } - // unreacheble + // unreachable return NULL; } From fb44266bfd27e0d6665eb72865fd22daa4005807 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 3 Jun 2021 09:37:13 +0300 Subject: [PATCH 165/222] udev_monitor.c: check poll error early --- udev_monitor.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/udev_monitor.c b/udev_monitor.c index 9e26bce..3b3873c 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -137,14 +137,14 @@ static void *handle_event(void *ptr) return NULL; } + // exit on poll error + if (!(poll_fds[0].revents & POLLIN)) { + return NULL; + } + len = read(udev_monitor->ifd, data, sizeof(data)); if (len == -1) { - continue; - } - - // exit on ifd error or close - if (!(poll_fds[0].revents & POLLIN)) { return NULL; } From c9b824bd54aa3c57defee7029876ed9a65ddb4f6 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 3 Jun 2021 09:41:26 +0300 Subject: [PATCH 166/222] udev_monitor.c: skip inotify event if directory --- udev_monitor.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/udev_monitor.c b/udev_monitor.c index 3b3873c..e074e51 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -156,6 +156,10 @@ static void *handle_event(void *ptr) break; } + if (event->mask & IN_ISDIR) { + continue; + } + send(udev_monitor->sfd[1], event->name, event->len, 0); } } From 496291c8ddda031c9e30c78edb11a786b17de6c6 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 3 Jun 2021 10:38:40 +0300 Subject: [PATCH 167/222] udev_monitor.c: add a way to control UDEV_MONITOR_DIR at runtime --- udev_monitor.c | 56 ++++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/udev_monitor.c b/udev_monitor.c index e074e51..c717e25 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -21,10 +21,11 @@ struct udev_monitor { struct udev_list_entry subsystem_match; struct udev_list_entry devtype_match; - pthread_t thread; struct udev *udev; - int refcount; + pthread_t thread; + const char *dir; int signal_fd; + int refcount; int sfd[2]; int ifd; }; @@ -85,14 +86,18 @@ static int filter_subsystem(struct udev_monitor *udev_monitor, struct udev_devic struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor) { - char file[PATH_MAX + sizeof(UDEV_MONITOR_DIR)], data[4096]; + char file[PATH_MAX], data[4096]; struct udev_device *udev_device; if (recv(udev_monitor->sfd[0], data, sizeof(data), 0) == -1) { return NULL; } - snprintf(file, sizeof(file), "%s/%s", UDEV_MONITOR_DIR, data); + // check truncation error to make gcc happy + if ((unsigned)snprintf(file, sizeof(file), "%s/%s", udev_monitor->dir, data) >= sizeof(file)) { + return NULL; + } + udev_device = udev_device_new_from_file(udev_monitor->udev, file); if (!udev_device) { @@ -170,11 +175,7 @@ static void *handle_event(void *ptr) int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) { - if (!udev_monitor) { - return -1; - } - - return (pthread_create(&udev_monitor->thread, NULL, handle_event, udev_monitor) == 0) - 1; + return udev_monitor ? (pthread_create(&udev_monitor->thread, NULL, handle_event, udev_monitor) == 0) - 1 : -1; } /* XXX NOT IMPLEMENTED */ int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size) @@ -225,25 +226,11 @@ int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_mo struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name) { struct udev_monitor *udev_monitor; - struct stat st; if (!udev || !name) { return NULL; } - if (lstat(UDEV_MONITOR_DIR, &st) != 0) { - if (mkdir(UDEV_MONITOR_DIR, 0) == -1) { - return NULL; - } - - if (chmod(UDEV_MONITOR_DIR, 0777) == -1) { - return NULL; - } - } - else if (!S_ISDIR(st.st_mode)) { - return NULL; - } - udev_monitor = calloc(1, sizeof(struct udev_monitor)); if (!udev_monitor) { @@ -262,7 +249,28 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char goto close_signal_fd; } - if (inotify_add_watch(udev_monitor->ifd, UDEV_MONITOR_DIR, IN_CLOSE_WRITE | IN_EXCL_UNLINK | IN_ONLYDIR) == -1) { + // TODO docs + udev_monitor->dir = getenv("UDEV_MONITOR_DIR"); + + if (!udev_monitor->dir || udev_monitor->dir[0] == '\0') { + udev_monitor->dir = UDEV_MONITOR_DIR; + + if (access(udev_monitor->dir, R_OK | W_OK) == -1) { + if (errno != ENOENT) { + return NULL; + } + + if (mkdir(udev_monitor->dir, 0) == -1) { + return NULL; + } + + if (chmod(udev_monitor->dir, 1777) == -1) { + return NULL; + } + } + } + + if (inotify_add_watch(udev_monitor->ifd, udev_monitor->dir, IN_CLOSE_WRITE | IN_EXCL_UNLINK | IN_ONLYDIR) == -1) { goto close_ifd; } From e814cfa506b6b9bfd8c62cdcc5da03d0cb742607 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 3 Jun 2021 11:20:51 +0300 Subject: [PATCH 168/222] udev_device.c: fix possible uninitialized read --- udev_device.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/udev_device.c b/udev_device.c index 4769167..9958a56 100644 --- a/udev_device.c +++ b/udev_device.c @@ -260,6 +260,7 @@ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const fclose(file); data[len] = '\0'; + // TODO strrchr? while (len-- > 0 && data[len] == '\n') { data[len] = '\0'; } @@ -335,7 +336,7 @@ static void set_properties_from_uevent(struct udev_device *udev_device) while (fgets(line, sizeof(line), file)) { line[strlen(line) - 1] = '\0'; - if (strncmp(line, "DEVNAME", 7) == 0) { + if (strncmp(line, "DEVNAME=", 8) == 0) { snprintf(devnode, sizeof(devnode), "/dev/%s", line + 8); udev_list_entry_add(&udev_device->properties, "DEVNAME", devnode, 0); } @@ -463,6 +464,7 @@ static void set_properties_from_evdev(struct udev_device *udev_device) } } + // TODO do not assume keyboard if EV_KEY if (test_bit(ev_bits, EV_KEY)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEY", "1", 0); @@ -560,7 +562,7 @@ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, de { char path[PATH_MAX]; - if (!udev || !type || !devnum) { + if (!udev) { return NULL; } @@ -638,7 +640,7 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat while (fgets(line, sizeof(line), file)) { line[strlen(line) - 1] = '\0'; - if (strncmp(line, "DEVPATH", 7) == 0) { + if (strncmp(line, "DEVPATH=", 8) == 0) { snprintf(syspath, sizeof(syspath), "/sys%s", line + 8); udev_list_entry_add(&udev_device->properties, "SYSPATH", syspath, 0); udev_list_entry_add(&udev_device->properties, "DEVPATH", line + 8, 0); @@ -655,7 +657,7 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat cnt++; } - else if (strncmp(line, "DEVNAME", 7) == 0) { + else if (strncmp(line, "DEVNAME=", 8) == 0) { snprintf(devnode, sizeof(devnode), "/dev/%s", line + 8); udev_list_entry_add(&udev_device->properties, "DEVNAME", devnode, 0); } From b82f9d9e4f894e51c730d5d58d43f3041c428538 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 3 Jun 2021 11:35:08 +0300 Subject: [PATCH 169/222] udev.c: move udev_hwdb here --- Makefile | 1 - udev.c | 20 ++++++++++++++++++++ udev_hwdb.c | 23 ----------------------- 3 files changed, 20 insertions(+), 24 deletions(-) delete mode 100644 udev_hwdb.c diff --git a/Makefile b/Makefile index ce8ac39..5c350db 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,6 @@ XARFLAGS = -rc OBJ = \ udev.o \ - udev_hwdb.o \ udev_list.o \ udev_device.o \ udev_monitor.o \ diff --git a/udev.c b/udev.c index 96d11d7..5edb623 100644 --- a/udev.c +++ b/udev.c @@ -58,3 +58,23 @@ int udev_get_log_priority(struct udev *udev) { return 0; } + +/* XXX NOT IMPLEMENTED */ struct udev_hwdb *udev_hwdb_new(struct udev *udev) +{ + return NULL; +} + +/* XXX NOT IMPLEMENTED */ struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb) +{ + return NULL; +} + +/* XXX NOT IMPLEMENTED */ struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb) +{ + return NULL; +} + +/* XXX NOT IMPLEMENTED */ struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags) +{ + return NULL; +} diff --git a/udev_hwdb.c b/udev_hwdb.c deleted file mode 100644 index ac69d99..0000000 --- a/udev_hwdb.c +++ /dev/null @@ -1,23 +0,0 @@ -#include - -#include "udev.h" - -/* XXX NOT IMPLEMENTED */ struct udev_hwdb *udev_hwdb_new(struct udev *udev) -{ - return NULL; -} - -/* XXX NOT IMPLEMENTED */ struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb) -{ - return NULL; -} - -/* XXX NOT IMPLEMENTED */ struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb) -{ - return NULL; -} - -/* XXX NOT IMPLEMENTED */ struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags) -{ - return NULL; -} From 802c5b8695df561bf88a1126a3a0d3f96974ca64 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 3 Jun 2021 11:44:50 +0300 Subject: [PATCH 170/222] udev_enumerate.c: check return value of pthread_create --- udev_enumerate.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/udev_enumerate.c b/udev_enumerate.c index 2152e43..a925991 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -264,7 +264,7 @@ static int scan_devices(struct udev_enumerate *udev_enumerate, const char *path) cnt = scandir(path, &de, filter_dot, NULL); if (cnt == -1) { - return -1; + return 0; } thread = calloc(cnt, sizeof(struct udev_enumerate_thread)); @@ -275,7 +275,7 @@ static int scan_devices(struct udev_enumerate *udev_enumerate, const char *path) } free(de); - return -1; + return 0; } pthread_mutex_init(&mutex, NULL); @@ -285,7 +285,10 @@ static int scan_devices(struct udev_enumerate *udev_enumerate, const char *path) thread[i].udev_enumerate = udev_enumerate; snprintf(thread[i].path, sizeof(thread[i].path), "%s/%s", path, de[i]->d_name); - pthread_create(&thread[i].thread, NULL, add_device, &thread[i]); + + if (pthread_create(&thread[i].thread, NULL, add_device, &thread[i]) != 0) { + return 0; + } } for (i = 0; i < cnt; i++) { @@ -299,7 +302,7 @@ static int scan_devices(struct udev_enumerate *udev_enumerate, const char *path) free(de); free(thread); pthread_mutex_destroy(&mutex); - return 0; + return 1; } int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) @@ -312,7 +315,7 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) } for (i = 0; path[i]; i++) { - if (scan_devices(udev_enumerate, path[i]) == -1) { + if (!scan_devices(udev_enumerate, path[i])) { return -1; } } From 4623040b6cd87f64ce4e4fb3e8926f075752a343 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 3 Jun 2021 11:53:29 +0300 Subject: [PATCH 171/222] udev_monitor.c: free resources before return --- udev_monitor.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/udev_monitor.c b/udev_monitor.c index c717e25..3815be4 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -257,15 +257,15 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char if (access(udev_monitor->dir, R_OK | W_OK) == -1) { if (errno != ENOENT) { - return NULL; + goto close_ifd; } if (mkdir(udev_monitor->dir, 0) == -1) { - return NULL; + goto close_ifd; } if (chmod(udev_monitor->dir, 1777) == -1) { - return NULL; + goto close_ifd; } } } From 4cb97cd01e4b650d9fd0e858c321d94dbf7a47a0 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 3 Jun 2021 11:59:47 +0300 Subject: [PATCH 172/222] udev_device.c: use strncmp to compare uevent vars --- udev_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/udev_device.c b/udev_device.c index 9958a56..880c3be 100644 --- a/udev_device.c +++ b/udev_device.c @@ -672,9 +672,9 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat *pos = '\0'; - if (strcmp(line, "SUBSYSTEM") == 0 || - strcmp(line, "ACTION") == 0 || - strcmp(line, "SEQNUM") == 0) { + if (strncmp(line, "SUBSYSTEM", 10) == 0 || + strncmp(line, "ACTION", 7) == 0 || + strncmp(line, "SEQNUM", 7) == 0) { cnt++; } From a81cb4444d5a4f9c713654e553bb45cd33133103 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 3 Jun 2021 12:06:18 +0300 Subject: [PATCH 173/222] udev_device.c: decrement size by 1 SUBSYSTEM == 9, not 10. same for others --- udev_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/udev_device.c b/udev_device.c index 880c3be..964e43c 100644 --- a/udev_device.c +++ b/udev_device.c @@ -672,9 +672,9 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat *pos = '\0'; - if (strncmp(line, "SUBSYSTEM", 10) == 0 || - strncmp(line, "ACTION", 7) == 0 || - strncmp(line, "SEQNUM", 7) == 0) { + if (strncmp(line, "SUBSYSTEM", 9) == 0 || + strncmp(line, "ACTION", 6) == 0 || + strncmp(line, "SEQNUM", 6) == 0) { cnt++; } From 23e9b6f8f4222d6fea907999a42ddf6dceabbb19 Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 4 Jun 2021 00:35:15 +0300 Subject: [PATCH 174/222] udev_monitor.c: drip sticky bit for now --- udev_monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udev_monitor.c b/udev_monitor.c index 3815be4..56859c7 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -264,7 +264,7 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char goto close_ifd; } - if (chmod(udev_monitor->dir, 1777) == -1) { + if (chmod(udev_monitor->dir, 0777) == -1) { goto close_ifd; } } From ed6c3e5c2dbf5dee2ebf1340bb338a5e14d40808 Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 4 Jun 2021 20:15:45 +0300 Subject: [PATCH 175/222] udev_monitor.c: check UDEV_MONITOR_DIR only for existence Fixes #30 --- udev_monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udev_monitor.c b/udev_monitor.c index 56859c7..5a849a5 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -255,7 +255,7 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char if (!udev_monitor->dir || udev_monitor->dir[0] == '\0') { udev_monitor->dir = UDEV_MONITOR_DIR; - if (access(udev_monitor->dir, R_OK | W_OK) == -1) { + if (access(udev_monitor->dir, F_OK) == -1) { if (errno != ENOENT) { goto close_ifd; } From def1a43f53a2ff2a6ff15c5d5f555d8825f197ce Mon Sep 17 00:00:00 2001 From: Naoto Yamaguchi Date: Thu, 3 Jun 2021 12:43:46 +0000 Subject: [PATCH 176/222] Add PKGCONFIGDIR for installation Ubuntu/Debian style file placement are ; No.1 libudev.so and libudev.so.1 in /lib or /lib/arch/ No.2 libudev.h in /usr/include No.3 libudev.pc in /usr/lib/pkgconfig or /usr/lib/arch/pkgconfig Current Makefile can install No.1 and No.2 pattern by "make PREFIX=/usr LIBDIR=/lib INCLUDEDIR=/usr/include install", but it can't install No.3 pattern. This patch added PKGCONFIGDIR environment variable to achieve all install pattern by "make PREFIX=/usr LIBDIR=/lib INCLUDEDIR=/usr/include PKGCONFIGDIR=/usr/lib install" --- Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 5c350db..d691341 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ PREFIX = /usr/local LIBDIR = ${PREFIX}/lib INCLUDEDIR = ${PREFIX}/include +PKGCONFIGDIR = ${LIBDIR}/pkgconfig XCFLAGS = ${CPPFLAGS} ${CFLAGS} -std=c99 -fPIC -pthread -D_XOPEN_SOURCE=700 \ -Wall -Wextra -Wpedantic -Wmissing-prototypes -Wstrict-prototypes \ -Wno-unused-parameter @@ -44,18 +45,18 @@ libudev.pc: libudev.pc.in libudev.pc.in > libudev.pc install: libudev.so libudev.a libudev.pc - mkdir -p ${DESTDIR}${INCLUDEDIR} ${DESTDIR}${LIBDIR}/pkgconfig + mkdir -p ${DESTDIR}${INCLUDEDIR} ${DESTDIR}${LIBDIR} ${DESTDIR}${PKGCONFIGDIR} cp -f udev.h ${DESTDIR}${INCLUDEDIR}/libudev.h cp -f libudev.a ${DESTDIR}${LIBDIR}/libudev.a cp -f libudev.so ${DESTDIR}${LIBDIR}/libudev.so ln -fs libudev.so ${DESTDIR}${LIBDIR}/libudev.so.1 - cp -f libudev.pc ${DESTDIR}${LIBDIR}/pkgconfig/ + cp -f libudev.pc ${DESTDIR}${PKGCONFIGDIR}/libudev.pc uninstall: rm -f ${DESTDIR}${LIBDIR}/libudev.a \ ${DESTDIR}${LIBDIR}/libudev.so \ ${DESTDIR}${LIBDIR}/libudev.so.1 \ - ${DESTDIR}${LIBDIR}/pkgconfig/libudev.pc \ + ${DESTDIR}${PKGCONFIGDIR}/libudev.pc \ ${DESTDIR}${INCLUDEDIR}/libudev.h clean: From db72f8610d62a5e6884c6d8d86660d07e49455c4 Mon Sep 17 00:00:00 2001 From: Naoto Yamaguchi Date: Thu, 3 Jun 2021 13:23:00 +0000 Subject: [PATCH 177/222] Fix building library name from libudev.so to libudev.so.1 Currently, "-soname" set at "libudev.so.1", but building library file name was "libudev.so". Typical shared library structure as a follow; libudev.so -> libudev.so.1 libudev.so.1 Current installation is reversed. This patch fix this. --- .gitignore | 1 + Makefile | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 40b5697..403cec9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.o *.a *.so +*.so.* *.pc diff --git a/Makefile b/Makefile index d691341..232650b 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ OBJ = \ udev_monitor.o \ udev_enumerate.o -all: libudev.so libudev.a +all: libudev.so.1 libudev.a .c.o: ${CC} ${XCFLAGS} -c -o $@ $< @@ -25,7 +25,7 @@ all: libudev.so libudev.a libudev.a: ${OBJ} ${AR} ${XARFLAGS} $@ ${OBJ} -libudev.so: ${OBJ} +libudev.so.1: ${OBJ} ${CC} ${XCFLAGS} -o $@ ${OBJ} ${XLDFLAGS} libudev.pc: libudev.pc.in @@ -48,8 +48,8 @@ install: libudev.so libudev.a libudev.pc mkdir -p ${DESTDIR}${INCLUDEDIR} ${DESTDIR}${LIBDIR} ${DESTDIR}${PKGCONFIGDIR} cp -f udev.h ${DESTDIR}${INCLUDEDIR}/libudev.h cp -f libudev.a ${DESTDIR}${LIBDIR}/libudev.a - cp -f libudev.so ${DESTDIR}${LIBDIR}/libudev.so - ln -fs libudev.so ${DESTDIR}${LIBDIR}/libudev.so.1 + cp -f libudev.so.1 ${DESTDIR}${LIBDIR}/libudev.so.1 + ln -fs libudev.so.1 ${DESTDIR}${LIBDIR}/libudev.so cp -f libudev.pc ${DESTDIR}${PKGCONFIGDIR}/libudev.pc uninstall: @@ -60,6 +60,6 @@ uninstall: ${DESTDIR}${INCLUDEDIR}/libudev.h clean: - rm -f libudev.so libudev.a libudev.pc ${OBJ} + rm -f libudev.so.1 libudev.a libudev.pc ${OBJ} .PHONY: all clean install uninstall From 75a40e1040aeda1348f34f5cebe323769850670c Mon Sep 17 00:00:00 2001 From: Naoto Yamaguchi Date: Fri, 4 Jun 2021 05:27:03 +0000 Subject: [PATCH 178/222] Add license information to source files Current libudev-zero source code doesn't have license information in source files. This patch add license information to source files based on SPDX standard. --- Makefile | 1 + contrib/helper.c | 16 ++++++++++++++++ libudev.pc.in | 1 + udev.c | 17 +++++++++++++++++ udev.h | 17 +++++++++++++++++ udev_device.c | 17 +++++++++++++++++ udev_enumerate.c | 17 +++++++++++++++++ udev_list.c | 17 +++++++++++++++++ udev_list.h | 17 +++++++++++++++++ udev_monitor.c | 17 +++++++++++++++++ 10 files changed, 137 insertions(+) diff --git a/Makefile b/Makefile index 232650b..e1ade0a 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: ISC .POSIX: PREFIX = /usr/local diff --git a/contrib/helper.c b/contrib/helper.c index f2f3c50..9f9cec7 100644 --- a/contrib/helper.c +++ b/contrib/helper.c @@ -1,4 +1,20 @@ /* + * Copyright (c) 2020-2021 illiliti + * SPDX-License-Identifier: ISC + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * * this helper pretty similar to helper.sh, but it * doesn't write unrelated variables to file (e.g PWD or PATH) * diff --git a/libudev.pc.in b/libudev.pc.in index d26aee5..7e29d8c 100644 --- a/libudev.pc.in +++ b/libudev.pc.in @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: ISC prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ diff --git a/udev.c b/udev.c index 5edb623..e886f19 100644 --- a/udev.c +++ b/udev.c @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2020-2021 illiliti + * SPDX-License-Identifier: ISC + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + #include #include "udev.h" diff --git a/udev.h b/udev.h index 3735892..39e4043 100644 --- a/udev.h +++ b/udev.h @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2020-2021 illiliti + * SPDX-License-Identifier: ISC + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + #include #include diff --git a/udev_device.c b/udev_device.c index 964e43c..e48f9b6 100644 --- a/udev_device.c +++ b/udev_device.c @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2020-2021 illiliti + * SPDX-License-Identifier: ISC + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + #include #include #include diff --git a/udev_enumerate.c b/udev_enumerate.c index a925991..6f02610 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2020-2021 illiliti + * SPDX-License-Identifier: ISC + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + #include #include #include diff --git a/udev_list.c b/udev_list.c index 2010d42..a41ec43 100644 --- a/udev_list.c +++ b/udev_list.c @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2020-2021 illiliti + * SPDX-License-Identifier: ISC + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + #include #include diff --git a/udev_list.h b/udev_list.h index da84f37..9952825 100644 --- a/udev_list.h +++ b/udev_list.h @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2020-2021 illiliti + * SPDX-License-Identifier: ISC + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + struct udev_list_entry { struct udev_list_entry *next; char *value; diff --git a/udev_monitor.c b/udev_monitor.c index 5a849a5..2843742 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2020-2021 illiliti + * SPDX-License-Identifier: ISC + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + #include #include #include From 34f8727f28700e9b01efc21f540be15d2b625a70 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 6 Jun 2021 09:14:56 +0300 Subject: [PATCH 179/222] udev_device.c: use strrchr to trim newline --- udev_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/udev_device.c b/udev_device.c index e48f9b6..c61aab2 100644 --- a/udev_device.c +++ b/udev_device.c @@ -243,6 +243,7 @@ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const struct stat st; size_t len; FILE *file; + char *pos; if (!udev_device || !sysattr) { return NULL; @@ -277,9 +278,8 @@ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const fclose(file); data[len] = '\0'; - // TODO strrchr? - while (len-- > 0 && data[len] == '\n') { - data[len] = '\0'; + if ((pos = strrchr(data, '\n'))) { + *pos = '\0'; } list_entry = udev_list_entry_add(&udev_device->sysattrs, sysattr, data, 0); From e23633ec562dc781a543c8e2b6ed0007a86e7158 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 6 Jun 2021 10:26:35 +0300 Subject: [PATCH 180/222] udev_device.c: more accurate keys/keyboard detection --- udev_device.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/udev_device.c b/udev_device.c index c61aab2..136b61c 100644 --- a/udev_device.c +++ b/udev_device.c @@ -403,6 +403,7 @@ static void set_properties_from_evdev(struct udev_device *udev_device) unsigned long ev_bits[BITS_TO_LONGS(EV_CNT)] = {0}; struct udev_device *parent; const char *subsystem; + unsigned long bit; subsystem = udev_device_get_subsystem(udev_device); @@ -481,13 +482,25 @@ static void set_properties_from_evdev(struct udev_device *udev_device) } } - // TODO do not assume keyboard if EV_KEY - if (test_bit(ev_bits, EV_KEY)) { + if (!test_bit(ev_bits, EV_KEY)) { + return; + } + + // iterate over key bits until BTN_* block is hit and test if bitmask has KEY_*. + // this way, we can check if device has keys or buttons. + // https://github.com/torvalds/linux/blob/f5b6eb1e018203913dfefcf6fa988649ad11ad6e/include/uapi/linux/input-event-codes.h#L76-L338 + for (bit = KEY_ESC; bit < BTN_MISC; bit++) { + if (!test_bit(key_bits, bit)) { + continue; + } + udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEY", "1", 0); if (test_bit(key_bits, KEY_ENTER)) { udev_list_entry_add(&udev_device->properties, "ID_INPUT_KEYBOARD", "1", 0); } + + return; } } From 7c94940e1223d243ea9b7bdc90105f808b199f3a Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 6 Jun 2021 10:50:38 +0300 Subject: [PATCH 181/222] Revert "udev_device.c: use strrchr to trim newline" This reverts commit 34f8727f28700e9b01efc21f540be15d2b625a70. --- udev_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/udev_device.c b/udev_device.c index 136b61c..9a83095 100644 --- a/udev_device.c +++ b/udev_device.c @@ -243,7 +243,6 @@ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const struct stat st; size_t len; FILE *file; - char *pos; if (!udev_device || !sysattr) { return NULL; @@ -278,8 +277,9 @@ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const fclose(file); data[len] = '\0'; - if ((pos = strrchr(data, '\n'))) { - *pos = '\0'; + // TODO strrchr? + while (len-- > 0 && data[len] == '\n') { + data[len] = '\0'; } list_entry = udev_list_entry_add(&udev_device->sysattrs, sysattr, data, 0); From e75aced4de57dd969cf4db3feea0d6803ef55099 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 6 Jun 2021 10:52:20 +0300 Subject: [PATCH 182/222] udev_device.c: drop TODO --- udev_device.c | 1 - 1 file changed, 1 deletion(-) diff --git a/udev_device.c b/udev_device.c index 9a83095..86d1e98 100644 --- a/udev_device.c +++ b/udev_device.c @@ -277,7 +277,6 @@ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const fclose(file); data[len] = '\0'; - // TODO strrchr? while (len-- > 0 && data[len] == '\n') { data[len] = '\0'; } From 752403eb9c58e4d34abf033a31358c144a0d20ee Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 6 Jun 2021 10:53:03 +0300 Subject: [PATCH 183/222] readme: drop TODO --- README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.md b/README.md index 43c4f98..aaff815 100644 --- a/README.md +++ b/README.md @@ -64,11 +64,6 @@ echo "/full/path/to/helper " > /proc/sys/kernel/hotplug # change to y --- Then you can run an application that uses hotplugging like `xorg-server` to see if it's working by unplugging and plugging something back. If you face any problems while trying out any of these methods, please create an issue. -## TODO -* [x] speed up performance -* [x] extend device support -* [x] implement hotplugging support - ## Donate You can send a donation to `BTC: 1BwrcsgtWZeLVvNeEQSg4A28a3yrGN3FpK` if you like this project. From 692cb07e552f62491c462d415e3e6943814ffc74 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 6 Jun 2021 14:23:59 +0300 Subject: [PATCH 184/222] readme: prettify reading it in plain text was painful, now it's fixed. --- README.md | 72 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index aaff815..a13a136 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,35 @@ # libudev-zero -Drop-in replacement for `libudev` that enables you to use any device manager -you like without worrying about the `udev` dependency at all! + +Drop-in replacement for `libudev` that intended to work with any device manager ## Why? -Because `udev` sucks, it is bloated and overengineered. `udev` is just like `systemd`, it locks you into using non-portable crap that you can't avoid because multiple programs depend on it. Look, even FreeBSD was forced to rewrite[1] this crappy library because `libinput` hard-depends on `udev`. Without `libinput` you can't use `wayland` and many other cool stuff. -Michael Forney (author of `cproc`, `samurai`, Oasis Linux, ...) decided to fork[2] `libinput` and remove the hard dependency on `udev`. Is this a solution? Yes. -Is this a complete solution? No. This fork has a lot of disadvantages like requiring patching applications to use `libinput_netlink` instead of the `libinput_udev` API in order to use the automatic detection of input devices and hotplugging. Static configuration is also required for anything other than input devices (e.g drm devices). Moreover hotplugging is vulnerable to race conditions when `libinput` handles the `uevent` faster than the device manager which can lead to file permission issues. `libudev-zero` prevents these race conditions by design. +Because `udev` sucks, it is bloated and overengineered. `udev` is just +like `systemd`, it locks you into using non-portable crap that you can't +avoid because multiple programs depend on it. Look, even FreeBSD was forced +to rewrite[0] this crappy library because `libinput` hard-depends on `udev`. +Without `libinput` you can't use `wayland` and many other cool stuff. -Thankfully `udev` has stable API and hopefully no changes will be made to it the future. On this basis I decided to create this clean-room implementation of `libudev` which can be used with any or without a device manager. +Michael Forney (author of `cproc`, `samurai`, Oasis Linux, ...) decided to +fork[1] `libinput` and remove the hard dependency on `udev`. Is this a +solution? Yes. Is this a complete solution? No. This fork has a lot of +disadvantages like requiring patching applications to use `libinput_netlink` +instead of the `libinput_udev` API in order to use the automatic detection of +input devices and hotplugging. Static configuration is also required for +anything other than input devices (e.g drm devices). Moreover hotplugging is +vulnerable to race conditions when `libinput` handles the `uevent` faster than +the device manager which can lead to file permission issues. `libudev-zero` +prevents these race conditions by design. -[1] https://github.com/FreeBSDDesktop/libudev-devd -[2] https://github.com/oasislinux/libinput +Thankfully `udev` has stable API and hopefully no changes will be made to it +the future. On this basis I decided to create this clean-room implementation +of `libudev` which can be used with any or without a device manager. + +[0] https://github.com/FreeBSDDesktop/libudev-devd +[1] https://github.com/oasislinux/libinput ## What Works + * [x] xorg-server * [ ] dosfstools - need to implement udev_enumerate_add_match_parent() * [x] libinput @@ -21,10 +37,11 @@ Thankfully `udev` has stable API and hopefully no changes will be made to it the * [x] wlroots * [x] weston * [x] libusb -* [x] kwin - [fix](https://github.com/dilyn-corner/KISS-kde/commit/0cc72748e46f859a0fced55b0c3fcc1dd9586a38) +* [x] kwin * [ ] ??? ## Dependencies + * C99 compiler (build time) * POSIX make (build time) * POSIX & XSI libc @@ -35,36 +52,29 @@ Thankfully `udev` has stable API and hopefully no changes will be made to it the ```sh make -make PREFIX=/usr install # this will overwrite udev libraries if they exist -# rebuild all the packages that depend on libudev, and you're ready to go. +make PREFIX=/usr install ``` ## Hotplugging -Note that hotplugging support is fully optional! You can skip this step if you don't have a need for the hotplugging capability. -Hotplugging is fairly uncomplicated and not overengineered at all. Everything is portable as much as possible. To use hotplugging the only thing you need is a `uevent` receiver (like a device manager, busybox's `uevent`, `CONFIG_UEVENT_HELPER`, ...). I will explain only the `mdev` and `CONFIG_UEVENT_HELPER` methods because their usage is fairly basic. For busybox's `uevent` you need to write your own parser which is kinda, well, complex. +Note that hotplugging support is fully optional. You can skip +this step if you don't have a need for the hotplugging capability. -`UDEV_MONITOR_DIR` is an arbitrary directory where the `uevent` files are stored. The default is `/tmp/.libudev-zero`. You can change it at build time by appending `-DUDEV_MONITOR_DIR=` to `CFLAGS`. I don't recommend setting `UDEV_MONITOR_DIR` to regular filesystems (i.e non-tmpfs) because temporary files aren't automatically discarded after reboot or termination (yet). +In order to use hotplugging, you need to configure device manager to send +`uevent` messages to `UDEV_MONITOR_DIR`. `UDEV_MONITOR_DIR` is arbitrary +shared directory used by `libudev-zero` to receive `uevent` messages. By +default, `UDEV_MONITOR_DIR` points to `/tmp/.libudev-zero`. You can change +that directory at compile time by passing `-DUDEV_MONITOR_DIR=` to +`CFLAGS` or at runtime by setting `UDEV_MONITOR_DIR` environment variable. -### a) the `mdev` method -1. merge [mdev.conf](contrib/mdev.conf) with your `mdev.conf` -2. restart the `mdev` daemon +Keep in mind that already processed `uevent` messages wouldn't be automatically +purged. You can set `UDEV_MONITOR_DIR` to directory on tmpfs to purge them on +reboot/shutdown. -### b) the `CONFIG_UEVENT_HELPER` method -1. ensure that `CONFIG_UEVENT_HELPER` is enabled in your kernel configuration -2. add the directory containing [helper.sh](contrib/helper.sh) after marking it as executable or [helper.c](contrib/helper.c) after compiling it, to `/proc/sys/kernel/hotplug` - -#### example: -```sh -echo "/full/path/to/helper" > /proc/sys/kernel/hotplug # will use the default UDEV_MONITOR_DIR -OR -echo "/full/path/to/helper " > /proc/sys/kernel/hotplug # change to your UDEV_MONITOR_DIR -``` - ---- -Then you can run an application that uses hotplugging like `xorg-server` to see if it's working by unplugging and plugging something back. If you face any problems while trying out any of these methods, please create an issue. +Refer to [contrib](contrib) for usage examples and configs. ## Donate -You can send a donation to `BTC: 1BwrcsgtWZeLVvNeEQSg4A28a3yrGN3FpK` if you like this project. + +You can send a donation to `BTC: 1BwrcsgtWZeLVvNeEQSg4A28a3yrGN3FpK` Thank you very much! From eb30a8bc85d4b96b4c64516cf11d5959a6bfe36e Mon Sep 17 00:00:00 2001 From: Naoto Yamaguchi Date: Wed, 9 Jun 2021 08:19:47 +0000 Subject: [PATCH 185/222] Fix install error at make install At db72f8610d62a5e6884c6d8d86660d07e49455c4 is missing change in Makefile. This err was reporting at bkuhls. This patch fix it. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e1ade0a..e75f536 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,7 @@ libudev.pc: libudev.pc.in -e 's|@VERSION@|243|g' \ libudev.pc.in > libudev.pc -install: libudev.so libudev.a libudev.pc +install: libudev.so.1 libudev.a libudev.pc mkdir -p ${DESTDIR}${INCLUDEDIR} ${DESTDIR}${LIBDIR} ${DESTDIR}${PKGCONFIGDIR} cp -f udev.h ${DESTDIR}${INCLUDEDIR}/libudev.h cp -f libudev.a ${DESTDIR}${LIBDIR}/libudev.a From bd7d1803e6930eb40778c5ca8ee80ccb8b7bac11 Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 11 Jun 2021 13:55:00 +0300 Subject: [PATCH 186/222] udev_enumerate.c: fix possible memory leak Early return due to pthread_create() failure causes memory leak. --- udev_enumerate.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/udev_enumerate.c b/udev_enumerate.c index 6f02610..449da4f 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -276,7 +276,7 @@ static int scan_devices(struct udev_enumerate *udev_enumerate, const char *path) struct udev_enumerate_thread *thread; pthread_mutex_t mutex; struct dirent **de; - int cnt, i; + int ret, cnt, i; cnt = scandir(path, &de, filter_dot, NULL); @@ -284,15 +284,12 @@ static int scan_devices(struct udev_enumerate *udev_enumerate, const char *path) return 0; } + ret = 1; thread = calloc(cnt, sizeof(struct udev_enumerate_thread)); if (!thread) { - for (i = 0; i < cnt; i++) { - free(de[i]); - } - - free(de); - return 0; + ret = 0; + goto free_de; } pthread_mutex_init(&mutex, NULL); @@ -304,7 +301,8 @@ static int scan_devices(struct udev_enumerate *udev_enumerate, const char *path) snprintf(thread[i].path, sizeof(thread[i].path), "%s/%s", path, de[i]->d_name); if (pthread_create(&thread[i].thread, NULL, add_device, &thread[i]) != 0) { - return 0; + ret = 0; + break; } } @@ -312,14 +310,16 @@ static int scan_devices(struct udev_enumerate *udev_enumerate, const char *path) pthread_join(thread[i].thread, NULL); } + free(thread); + pthread_mutex_destroy(&mutex); + +free_de: for (i = 0; i < cnt; i++) { free(de[i]); } free(de); - free(thread); - pthread_mutex_destroy(&mutex); - return 1; + return ret; } int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) From bf23c9e5ba310ffc6ef2d67dc07c23efe48c61ae Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 26 Jun 2021 01:14:10 +0300 Subject: [PATCH 187/222] udev_device.c: fix integer overflow Bitwise AND operation can produce value that may be larger than test_bit() return value. Convert result to bool using `!!` to avoid integer overflow. Fixes: #33 --- udev_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udev_device.c b/udev_device.c index 86d1e98..7957bb2 100644 --- a/udev_device.c +++ b/udev_device.c @@ -389,7 +389,7 @@ static void make_bit(unsigned long *arr, int cnt, const char *str) static int test_bit(unsigned long *arr, unsigned long bit) { - return arr[BIT_WORD(bit)] & BIT_MASK(bit); + return !!(arr[BIT_WORD(bit)] & BIT_MASK(bit)); } static void set_properties_from_evdev(struct udev_device *udev_device) From 5f9186af418e5d54f2491709fb1f9aad3c44ac40 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 21 Aug 2021 01:57:41 +0300 Subject: [PATCH 188/222] contrib/*: be more explicit --- contrib/helper.c | 4 ++-- contrib/helper.sh | 7 ++----- contrib/mdev.conf | 13 ++++++------- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/contrib/helper.c b/contrib/helper.c index 9f9cec7..912fd57 100644 --- a/contrib/helper.c +++ b/contrib/helper.c @@ -15,8 +15,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * - * this helper pretty similar to helper.sh, but it - * doesn't write unrelated variables to file (e.g PWD or PATH) + * NOTE: you don't need this if you have mdev/mdevd, refer to mdev.conf + * NOTE: you need this if you want to use bare-bones CONFIG_UEVENT_HELPER * * build: * cc helper.c -o helper diff --git a/contrib/helper.sh b/contrib/helper.sh index 51bf19f..faa1d61 100644 --- a/contrib/helper.sh +++ b/contrib/helper.sh @@ -1,13 +1,10 @@ #!/bin/sh -f # -# this helper required for CONFIG_UEVENT_HELPER aka /proc/sys/kernel/hotplug -# for mdev you can use simple one-liner, refer to mdev.conf for more info +# NOTE: you don't need this if you have mdev/mdevd, refer to mdev.conf +# NOTE: you need this if you want to use bare-bones CONFIG_UEVENT_HELPER # # usage: # echo /full/path/to/helper.sh > /proc/sys/kernel/hotplug # echo "/full/path/to/helper.sh UDEV_MONITOR_DIR" > /proc/sys/kernel/hotplug -# -# NOTE: writing variables to file (e.g PWD or PATH) -# that are not related to uevent properties is harmless exec env > "${1:-/tmp/.libudev-zero}/uevent.$$" diff --git a/contrib/mdev.conf b/contrib/mdev.conf index ff5334c..7bc3c09 100644 --- a/contrib/mdev.conf +++ b/contrib/mdev.conf @@ -1,13 +1,12 @@ # -# example basic mdev config representing libudev-zero usage -# uncomment needed rules +# example rules for mdev.conf # # NOTE: you must change "/tmp/.libudev-zero" if you use non-default UDEV_MONITOR_DIR -# NOTE: mdev can only handle ADD and/or REMOVE events +# NOTE: you don't need helper.c or helper.sh, just add this to /etc/mdev.conf -# will handle all uevents +# handle all uevents(not recommended) #-.* root:root 660 *env > /tmp/.libudev-zero/uevent.$$ -# will handle only drm and input uevents (recommended) -#SUBSYSTEM=drm;.* root:video 660 *env > /tmp/.libudev-zero/uevent.$$ -#SUBSYSTEM=input;.* root:input 660 *env > /tmp/.libudev-zero/uevent.$$ +# handle only drm and input uevents(recommended) +SUBSYSTEM=drm;.* root:video 660 *env > /tmp/.libudev-zero/uevent.$$ +SUBSYSTEM=input;.* root:input 660 *env > /tmp/.libudev-zero/uevent.$$ From 3d98bea2898d48fa5fcdcdd483a297c42e8140a8 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 25 Aug 2021 01:38:33 +0300 Subject: [PATCH 189/222] *: code cleanup --- udev.c | 2 +- udev_device.c | 6 ++---- udev_enumerate.c | 7 +++---- udev_list.c | 2 +- udev_monitor.c | 2 +- 5 files changed, 8 insertions(+), 11 deletions(-) diff --git a/udev.c b/udev.c index e886f19..ab5d33a 100644 --- a/udev.c +++ b/udev.c @@ -27,7 +27,7 @@ struct udev *udev_new(void) { struct udev *udev; - udev = calloc(1, sizeof(struct udev)); + udev = calloc(1, sizeof(*udev)); if (!udev) { return NULL; diff --git a/udev_device.c b/udev_device.c index 7957bb2..47dd00f 100644 --- a/udev_device.c +++ b/udev_device.c @@ -26,8 +26,6 @@ #include "udev.h" #include "udev_list.h" -// sizeof(unsigned long) == 4 * 8 == 32 on 32-bit systems. -// sizeof(unsigned long) == 8 * 8 == 64 on 64-bit systems. #ifndef LONG_BIT #define LONG_BIT (sizeof(unsigned long) * 8) #endif @@ -547,7 +545,7 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * return NULL; } - udev_device = calloc(1, sizeof(struct udev_device)); + udev_device = calloc(1, sizeof(*udev_device)); if (!udev_device) { return NULL; @@ -650,7 +648,7 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat return NULL; } - udev_device = calloc(1, sizeof(struct udev_device)); + udev_device = calloc(1, sizeof(*udev_device)); if (!udev_device) { fclose(file); diff --git a/udev_enumerate.c b/udev_enumerate.c index 449da4f..2dd7aee 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -275,8 +275,8 @@ static int scan_devices(struct udev_enumerate *udev_enumerate, const char *path) { struct udev_enumerate_thread *thread; pthread_mutex_t mutex; + int i, cnt, ret = 1; struct dirent **de; - int ret, cnt, i; cnt = scandir(path, &de, filter_dot, NULL); @@ -284,8 +284,7 @@ static int scan_devices(struct udev_enumerate *udev_enumerate, const char *path) return 0; } - ret = 1; - thread = calloc(cnt, sizeof(struct udev_enumerate_thread)); + thread = calloc(cnt, sizeof(*thread)); if (!thread) { ret = 0; @@ -368,7 +367,7 @@ struct udev_enumerate *udev_enumerate_new(struct udev *udev) return NULL; } - udev_enumerate = calloc(1, sizeof(struct udev_enumerate)); + udev_enumerate = calloc(1, sizeof(*udev_enumerate)); if (!udev_enumerate) { return NULL; diff --git a/udev_list.c b/udev_list.c index a41ec43..95b08e8 100644 --- a/udev_list.c +++ b/udev_list.c @@ -69,7 +69,7 @@ struct udev_list_entry *udev_list_entry_add(struct udev_list_entry *list_entry, } } - list_entry2 = calloc(1, sizeof(struct udev_list_entry)); + list_entry2 = calloc(1, sizeof(*list_entry2)); if (!list_entry2) { return NULL; diff --git a/udev_monitor.c b/udev_monitor.c index 2843742..1e79310 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -248,7 +248,7 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char return NULL; } - udev_monitor = calloc(1, sizeof(struct udev_monitor)); + udev_monitor = calloc(1, sizeof(*udev_monitor)); if (!udev_monitor) { return NULL; From d8c4dc4ce3175d7df9d309d111b48f2db084285c Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 25 Aug 2021 03:22:30 +0300 Subject: [PATCH 190/222] udev_device.c: define INPUT_PROP_CNT --- udev_device.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/udev_device.c b/udev_device.c index 47dd00f..d9ca6c7 100644 --- a/udev_device.c +++ b/udev_device.c @@ -44,6 +44,10 @@ #define INPUT_PROP_ACCELEROMETER 0x06 #endif +#ifndef INPUT_PROP_CNT +#define INPUT_PROP_CNT 0x20 +#endif + struct udev_device { struct udev_list_entry properties; struct udev_list_entry sysattrs; From 4510b27a9b589a0ce82fef776c2648e19e79f2a4 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 25 Aug 2021 06:03:39 +0300 Subject: [PATCH 191/222] udev_enumerate.c: fix pipeware This is partial fix because pipeware relies on udev-specific properties that aren't provided by libudev-zero. Fixes: #26 --- udev_enumerate.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/udev_enumerate.c b/udev_enumerate.c index 2dd7aee..c3caee5 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -242,7 +242,7 @@ static int filter_sysattr(struct udev_enumerate *udev_enumerate, struct udev_dev static void *add_device(void *ptr) { struct udev_enumerate_thread *thread = ptr; - struct udev_device *udev_device; + struct udev_device *udev_device, *parent; udev_device = udev_device_new_from_syspath(thread->udev_enumerate->udev, thread->path); @@ -258,7 +258,14 @@ static void *add_device(void *ptr) return NULL; } + parent = udev_device_get_parent(udev_device); + pthread_mutex_lock(thread->mutex); + + if (parent) { + udev_list_entry_add(&thread->udev_enumerate->devices, udev_device_get_syspath(parent), NULL, 0); + } + udev_list_entry_add(&thread->udev_enumerate->devices, udev_device_get_syspath(udev_device), NULL, 0); pthread_mutex_unlock(thread->mutex); From fc229906094c5a17bfaef57a3b38a0fed484e03f Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 25 Aug 2021 03:36:57 +0300 Subject: [PATCH 192/222] implement file-less hotplugging --- README.md | 38 +++++---- contrib/helper.c | 85 ++++++++++---------- contrib/helper.sh | 10 --- contrib/mdev.conf | 10 +-- udev.h | 2 +- udev_device.c | 58 +++++--------- udev_monitor.c | 200 +++++++++++++--------------------------------- 7 files changed, 143 insertions(+), 260 deletions(-) delete mode 100644 contrib/helper.sh diff --git a/README.md b/README.md index a13a136..7c8ee44 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # libudev-zero -Drop-in replacement for `libudev` that intended to work with any device manager +Drop-in replacement for `libudev` intended to work with any device manager ## Why? @@ -11,15 +11,11 @@ to rewrite[0] this crappy library because `libinput` hard-depends on `udev`. Without `libinput` you can't use `wayland` and many other cool stuff. Michael Forney (author of `cproc`, `samurai`, Oasis Linux, ...) decided to -fork[1] `libinput` and remove the hard dependency on `udev`. Is this a -solution? Yes. Is this a complete solution? No. This fork has a lot of -disadvantages like requiring patching applications to use `libinput_netlink` +fork[1] `libinput` and remove the hard dependency on `udev`. However, this +fork has a drawback that requires patching applications to use `libinput_netlink` instead of the `libinput_udev` API in order to use the automatic detection of -input devices and hotplugging. Static configuration is also required for -anything other than input devices (e.g drm devices). Moreover hotplugging is -vulnerable to race conditions when `libinput` handles the `uevent` faster than -the device manager which can lead to file permission issues. `libudev-zero` -prevents these race conditions by design. +input devices and hotplugging. Static configuration is also required for anything +other than input devices (e.g drm devices). Thankfully `udev` has stable API and hopefully no changes will be made to it the future. On this basis I decided to create this clean-room implementation @@ -45,7 +41,6 @@ of `libudev` which can be used with any or without a device manager. * C99 compiler (build time) * POSIX make (build time) * POSIX & XSI libc -* inotify & eventfd * Linux >= 2.6.39 ## Installation @@ -60,18 +55,21 @@ make PREFIX=/usr install Note that hotplugging support is fully optional. You can skip this step if you don't have a need for the hotplugging capability. -In order to use hotplugging, you need to configure device manager to send -`uevent` messages to `UDEV_MONITOR_DIR`. `UDEV_MONITOR_DIR` is arbitrary -shared directory used by `libudev-zero` to receive `uevent` messages. By -default, `UDEV_MONITOR_DIR` points to `/tmp/.libudev-zero`. You can change -that directory at compile time by passing `-DUDEV_MONITOR_DIR=` to -`CFLAGS` or at runtime by setting `UDEV_MONITOR_DIR` environment variable. +If you're using mdev-like device manager, refer to [mdev.conf](contrib/mdev.conf) +for config example. -Keep in mind that already processed `uevent` messages wouldn't be automatically -purged. You can set `UDEV_MONITOR_DIR` to directory on tmpfs to purge them on -reboot/shutdown. +If you're using other device manager, you need to configure it to rebroadcast +kernel uevents. You can do this by either patching(see below) device manager +or simply executing [helper.c](contrib/helper.c) for each uevent. -Refer to [contrib](contrib) for usage examples and configs. +If you're developing your own device manager, you need to rebroadcast kernel +uevents to `0x4` netlink group of `NETLINK_KOBJECT_UEVENT`. This is required +because libudev-zero can't simply listen to kernel uevents due to potential +race conditions. Refer(but don't copy blindly) to [helper.c](contrib/helper.c) +for example how it could be implemented in C. + +Don't hesitate to ask me everything you don't understand. I'm usually hanging +around in #kisslinux at libera.chat, but you can also email me or open an issue here. ## Donate diff --git a/contrib/helper.c b/contrib/helper.c index 912fd57..6fff27e 100644 --- a/contrib/helper.c +++ b/contrib/helper.c @@ -15,50 +15,27 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * - * NOTE: you don't need this if you have mdev/mdevd, refer to mdev.conf - * NOTE: you need this if you want to use bare-bones CONFIG_UEVENT_HELPER - * - * build: - * cc helper.c -o helper - * - * usage: - * echo /full/path/to/helper > /proc/sys/kernel/hotplug - * echo "/full/path/to/helper UDEV_MONITOR_DIR" > /proc/sys/kernel/hotplug + * Construct uevent message from environment and send it to 0x4 netlink group. */ #include #include #include -#include -#include -#include +#include +#include int main(int argc, char **argv) { + struct sockaddr_nl sa = {0}; + struct msghdr hdr = {0}; + struct iovec iov = {0}; extern char **environ; - char path[PATH_MAX]; - char *dir; - int fd, i; + char buf[8192]; + size_t len; + int i, fd; - switch (argc) { - case 1: - dir = "/tmp/.libudev-zero"; - break; - case 2: - dir = argv[1]; - break; - default: - fprintf(stderr, "usage: %s [dir]\n", argv[0]); - return 2; - } - - snprintf(path, sizeof(path), "%s/uevent.XXXXXX", dir); - fd = mkstemp(path); - - if (fd == -1) { - perror("mkstemp"); - return 1; - } + iov.iov_base = buf; + iov.iov_len = 0; for (i = 0; environ[i]; i++) { if (strncmp(environ[i], "PATH=", 5) == 0 || @@ -66,16 +43,44 @@ int main(int argc, char **argv) continue; } - if (write(fd, environ[i], strlen(environ[i])) == -1 || - write(fd, "\n", 1) == -1) { - perror("write"); - close(fd); - unlink(path); + len = strlen(environ[i]) + 1; + + if (iov.iov_len + len > sizeof(buf)) { + fprintf(stderr, "%s: uevent exceeds buffer size", argv[0]); return 1; } + + memcpy(buf + iov.iov_len, environ[i], len); + iov.iov_len += len; + } + + sa.nl_family = AF_NETLINK; + sa.nl_groups = 0x4; // XXX + + hdr.msg_name = &sa; + hdr.msg_namelen = sizeof(sa); + hdr.msg_iov = &iov; + hdr.msg_iovlen = 1; + + fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); + + if (fd == -1) { + perror("socket"); + return 1; + } + + if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) { + perror("bind"); + close(fd); + return 1; + } + + if (sendmsg(fd, &hdr, 0) == -1) { + perror("sendmsg"); + close(fd); + return 1; } - fchmod(fd, 0444); close(fd); return 0; } diff --git a/contrib/helper.sh b/contrib/helper.sh deleted file mode 100644 index faa1d61..0000000 --- a/contrib/helper.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -f -# -# NOTE: you don't need this if you have mdev/mdevd, refer to mdev.conf -# NOTE: you need this if you want to use bare-bones CONFIG_UEVENT_HELPER -# -# usage: -# echo /full/path/to/helper.sh > /proc/sys/kernel/hotplug -# echo "/full/path/to/helper.sh UDEV_MONITOR_DIR" > /proc/sys/kernel/hotplug - -exec env > "${1:-/tmp/.libudev-zero}/uevent.$$" diff --git a/contrib/mdev.conf b/contrib/mdev.conf index 7bc3c09..18c9dc5 100644 --- a/contrib/mdev.conf +++ b/contrib/mdev.conf @@ -1,12 +1,10 @@ -# # example rules for mdev.conf # -# NOTE: you must change "/tmp/.libudev-zero" if you use non-default UDEV_MONITOR_DIR -# NOTE: you don't need helper.c or helper.sh, just add this to /etc/mdev.conf +# NOTE: replace /path/to/helper with path to compiled binary of helper.c # handle all uevents(not recommended) -#-.* root:root 660 *env > /tmp/.libudev-zero/uevent.$$ +#-.* root:root 660 */path/to/helper # handle only drm and input uevents(recommended) -SUBSYSTEM=drm;.* root:video 660 *env > /tmp/.libudev-zero/uevent.$$ -SUBSYSTEM=input;.* root:input 660 *env > /tmp/.libudev-zero/uevent.$$ +SUBSYSTEM=drm;.* root:video 660 */path/to/helper +SUBSYSTEM=input;.* root:input 660 */path/to/helper diff --git a/udev.h b/udev.h index 39e4043..057d4af 100644 --- a/udev.h +++ b/udev.h @@ -129,7 +129,7 @@ struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb); struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags); // this is "libudev-zero" extension. do not use if portability is concern -struct udev_device *udev_device_new_from_file(struct udev *udev, const char *path); +struct udev_device *udev_device_new_from_uevent(struct udev *udev, char *buf, size_t len); #ifdef __cplusplus } diff --git a/udev_device.c b/udev_device.c index d9ca6c7..939ab46 100644 --- a/udev_device.c +++ b/udev_device.c @@ -632,35 +632,20 @@ struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, co return NULL; } -struct udev_device *udev_device_new_from_file(struct udev *udev, const char *path) +struct udev_device *udev_device_new_from_uevent(struct udev *udev, char *buf, size_t len) { - char line[LINE_MAX], syspath[PATH_MAX], devnode[PATH_MAX]; + char syspath[PATH_MAX], devnode[PATH_MAX]; struct udev_device *udev_device; - struct stat st; - char *sysname; - FILE *file; - int i, cnt; - char *pos; - - if (stat(path, &st) != 0 || st.st_size > 8192) { - return NULL; - } - - file = fopen(path, "r"); - - if (!file) { - return NULL; - } + const char *sysname; + char *end, *pos; + int i, cnt = 0; udev_device = calloc(1, sizeof(*udev_device)); if (!udev_device) { - fclose(file); return NULL; } - cnt = 0; - udev_device->udev = udev; udev_device->refcount = 1; udev_device->parent = NULL; @@ -668,13 +653,11 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat udev_list_entry_init(&udev_device->properties); udev_list_entry_init(&udev_device->sysattrs); - while (fgets(line, sizeof(line), file)) { - line[strlen(line) - 1] = '\0'; - - if (strncmp(line, "DEVPATH=", 8) == 0) { - snprintf(syspath, sizeof(syspath), "/sys%s", line + 8); + for (end = buf + len; buf < end; buf += strlen(buf) + 1) { + if (strncmp(buf, "DEVPATH=", 8) == 0) { + snprintf(syspath, sizeof(syspath), "/sys%s", buf + 8); udev_list_entry_add(&udev_device->properties, "SYSPATH", syspath, 0); - udev_list_entry_add(&udev_device->properties, "DEVPATH", line + 8, 0); + udev_list_entry_add(&udev_device->properties, "DEVPATH", buf + 8, 0); sysname = strrchr(syspath, '/') + 1; udev_list_entry_add(&udev_device->properties, "SYSNAME", sysname, 0); @@ -688,35 +671,30 @@ struct udev_device *udev_device_new_from_file(struct udev *udev, const char *pat cnt++; } - else if (strncmp(line, "DEVNAME=", 8) == 0) { - snprintf(devnode, sizeof(devnode), "/dev/%s", line + 8); + else if (strncmp(buf, "DEVNAME=", 8) == 0) { + snprintf(devnode, sizeof(devnode), "/dev/%s", buf + 8); udev_list_entry_add(&udev_device->properties, "DEVNAME", devnode, 0); } else { - pos = strchr(line, '='); + pos = strchr(buf, '='); - // file is malformed, abort here. if (!pos) { - cnt = 0; - break; + continue; } *pos = '\0'; - if (strncmp(line, "SUBSYSTEM", 9) == 0 || - strncmp(line, "ACTION", 6) == 0 || - strncmp(line, "SEQNUM", 6) == 0) { + if (strcmp(buf, "SUBSYSTEM") == 0 || + strcmp(buf, "ACTION") == 0 || + strcmp(buf, "SEQNUM") == 0) { cnt++; } - udev_list_entry_add(&udev_device->properties, line, pos + 1, 0); + udev_list_entry_add(&udev_device->properties, buf, pos + 1, 0); + *pos = '='; } } - fclose(file); - - // https://freedesktop.org/software/systemd/man/udev_device_new_from_environment.html - // > The keys DEVPATH, SUBSYSTEM, ACTION, and SEQNUM are mandatory. if (cnt != 4) { udev_device_unref(udev_device); return NULL; diff --git a/udev_monitor.c b/udev_monitor.c index 1e79310..820d6a3 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -15,36 +15,26 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include -#include #include #include #include -#include -#include -#include #include -#include -#include +#include #include "udev.h" #include "udev_list.h" -#ifndef UDEV_MONITOR_DIR -#define UDEV_MONITOR_DIR "/tmp/.libudev-zero" +#ifndef UDEV_MONITOR_NLGRP +#define UDEV_MONITOR_NLGRP 0x4 #endif struct udev_monitor { struct udev_list_entry subsystem_match; struct udev_list_entry devtype_match; struct udev *udev; - pthread_t thread; - const char *dir; - int signal_fd; int refcount; - int sfd[2]; - int ifd; + int nlgrp; + int fd; }; static int filter_devtype(struct udev_monitor *udev_monitor, struct udev_device *udev_device) @@ -103,106 +93,75 @@ static int filter_subsystem(struct udev_monitor *udev_monitor, struct udev_devic struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor) { - char file[PATH_MAX], data[4096]; struct udev_device *udev_device; - - if (recv(udev_monitor->sfd[0], data, sizeof(data), 0) == -1) { - return NULL; - } - - // check truncation error to make gcc happy - if ((unsigned)snprintf(file, sizeof(file), "%s/%s", udev_monitor->dir, data) >= sizeof(file)) { - return NULL; - } - - udev_device = udev_device_new_from_file(udev_monitor->udev, file); - - if (!udev_device) { - return NULL; - } - - if (!filter_subsystem(udev_monitor, udev_device) || - !filter_devtype(udev_monitor, udev_device)) { - udev_device_unref(udev_device); - return NULL; - } - - return udev_device; -} - -static void *handle_event(void *ptr) -{ - struct udev_monitor *udev_monitor = ptr; - struct inotify_event *event; - struct pollfd poll_fds[2]; - char data[4096]; + struct sockaddr_nl sa = {0}; + struct msghdr hdr = {0}; + struct iovec iov = {0}; + char buf[8192]; ssize_t len; - int i; - poll_fds[0].fd = udev_monitor->ifd; - poll_fds[0].events = POLLIN; + iov.iov_base = buf; + iov.iov_len = sizeof(buf); - poll_fds[1].fd = udev_monitor->signal_fd; - poll_fds[1].events = POLLIN; + hdr.msg_name = &sa; + hdr.msg_namelen = sizeof(sa); + hdr.msg_iov = &iov; + hdr.msg_iovlen = 1; while (1) { - if (poll(poll_fds, 2, -1) == -1) { - if (errno == EINTR) { - continue; - } + len = recvmsg(udev_monitor->fd, &hdr, 0); - return NULL; + if (len <= 0) { + break; } - // exit on explicit signal - if (poll_fds[1].revents & POLLIN) { - return NULL; + if (hdr.msg_flags & MSG_TRUNC) { + continue; } - // exit on poll error - if (!(poll_fds[0].revents & POLLIN)) { - return NULL; + if (sa.nl_groups == 0x0 || (sa.nl_groups == 0x1 && sa.nl_pid)) { + continue; } - len = read(udev_monitor->ifd, data, sizeof(data)); + udev_device = udev_device_new_from_uevent(udev_monitor->udev, buf, len); - if (len == -1) { - return NULL; + if (!udev_device) { + continue; } - for (i = 0; i < len; i += sizeof(struct inotify_event) + event->len) { - event = (struct inotify_event *)&data[i]; - - // TODO directory is removed - if (event->mask & IN_IGNORED) { - break; - } - - if (event->mask & IN_ISDIR) { - continue; - } - - send(udev_monitor->sfd[1], event->name, event->len, 0); + if (!filter_subsystem(udev_monitor, udev_device) || + !filter_devtype(udev_monitor, udev_device)) { + udev_device_unref(udev_device); + continue; } + + return udev_device; } - // unreachable return NULL; } int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) { - return udev_monitor ? (pthread_create(&udev_monitor->thread, NULL, handle_event, udev_monitor) == 0) - 1 : -1; + struct sockaddr_nl sa = {0}; + + if (!udev_monitor) { + return -1; + } + + sa.nl_family = AF_NETLINK; + sa.nl_groups = udev_monitor->nlgrp; + return bind(udev_monitor->fd, (struct sockaddr *)&sa, sizeof(sa)); } -/* XXX NOT IMPLEMENTED */ int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size) +int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size) { - return 0; + return udev_monitor ? setsockopt(udev_monitor->fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) : -1; } int udev_monitor_get_fd(struct udev_monitor *udev_monitor) { - return udev_monitor ? udev_monitor->sfd[0] : -1; + return udev_monitor ? udev_monitor->fd : -1; } struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor) @@ -254,60 +213,27 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char return NULL; } - udev_monitor->signal_fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); - - if (udev_monitor->signal_fd == -1) { - goto free_monitor; + if (strcmp(name, "udev") == 0) { + udev_monitor->nlgrp = UDEV_MONITOR_NLGRP; + } + else if (strcmp(name, "kernel") == 0) { + udev_monitor->nlgrp = 0x1; + } + else { + free(udev_monitor); + return NULL; } - udev_monitor->ifd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK); + udev_monitor->fd = socket(AF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT); - if (udev_monitor->ifd == -1) { - goto close_signal_fd; - } - - // TODO docs - udev_monitor->dir = getenv("UDEV_MONITOR_DIR"); - - if (!udev_monitor->dir || udev_monitor->dir[0] == '\0') { - udev_monitor->dir = UDEV_MONITOR_DIR; - - if (access(udev_monitor->dir, F_OK) == -1) { - if (errno != ENOENT) { - goto close_ifd; - } - - if (mkdir(udev_monitor->dir, 0) == -1) { - goto close_ifd; - } - - if (chmod(udev_monitor->dir, 0777) == -1) { - goto close_ifd; - } - } - } - - if (inotify_add_watch(udev_monitor->ifd, udev_monitor->dir, IN_CLOSE_WRITE | IN_EXCL_UNLINK | IN_ONLYDIR) == -1) { - goto close_ifd; - } - - if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, udev_monitor->sfd) == -1) { - goto close_ifd; + if (udev_monitor->fd == -1) { + free(udev_monitor); + return NULL; } udev_monitor->refcount = 1; udev_monitor->udev = udev; return udev_monitor; - -close_ifd: - close(udev_monitor->ifd); - -close_signal_fd: - close(udev_monitor->signal_fd); - -free_monitor: - free(udev_monitor); - return NULL; } struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor) @@ -322,8 +248,6 @@ struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor) struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor) { - int i; - if (!udev_monitor) { return NULL; } @@ -332,20 +256,10 @@ struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor) return NULL; } - // Wake up the event thread - eventfd_write(udev_monitor->signal_fd, 1); - // waiting for event thread to end before freeing udev_monitor - pthread_join(udev_monitor->thread, NULL); - udev_list_entry_free_all(&udev_monitor->devtype_match); udev_list_entry_free_all(&udev_monitor->subsystem_match); - for (i = 0; i < 2; i++) { - close(udev_monitor->sfd[i]); - } - - close(udev_monitor->signal_fd); - close(udev_monitor->ifd); + close(udev_monitor->fd); free(udev_monitor); return NULL; } From c2a08cdd799667a32b96b00f66f1aa894ce1d904 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sat, 28 Aug 2021 02:24:47 +0300 Subject: [PATCH 193/222] contib/mdev.conf: mdevd can rebroadcast uevents natively --- contrib/mdev.conf | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/contrib/mdev.conf b/contrib/mdev.conf index 18c9dc5..f7c8c1f 100644 --- a/contrib/mdev.conf +++ b/contrib/mdev.conf @@ -1,5 +1,11 @@ # example rules for mdev.conf # +# NOTE: +# since https://github.com/skarnet/mdevd/commit/b61ab0373a724d38e059655d561b5fb3dcb2aff6, +# mdevd can rebroadcast uevents natively which means that you don't need to add anything +# to /etc/mdev.conf. In order to enable this functionality, you need to add `-O 4` to +# mdevd arguments. +# # NOTE: replace /path/to/helper with path to compiled binary of helper.c # handle all uevents(not recommended) From 8a4b5b582ce652f5c27485adc556f19f43e5288d Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 29 Aug 2021 04:55:14 +0300 Subject: [PATCH 194/222] udev_monitor.c: bitmask is unsigned --- udev_monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udev_monitor.c b/udev_monitor.c index 820d6a3..d533a48 100644 --- a/udev_monitor.c +++ b/udev_monitor.c @@ -32,8 +32,8 @@ struct udev_monitor { struct udev_list_entry subsystem_match; struct udev_list_entry devtype_match; struct udev *udev; + unsigned nlgrp; int refcount; - int nlgrp; int fd; }; From 8044ed8fd6568a31cece25673b0cb00a54468be0 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 29 Aug 2021 04:59:31 +0300 Subject: [PATCH 195/222] contrib/helper.c: remove redundant bind call --- contrib/helper.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/contrib/helper.c b/contrib/helper.c index 6fff27e..9ead4e9 100644 --- a/contrib/helper.c +++ b/contrib/helper.c @@ -69,12 +69,6 @@ int main(int argc, char **argv) return 1; } - if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) { - perror("bind"); - close(fd); - return 1; - } - if (sendmsg(fd, &hdr, 0) == -1) { perror("sendmsg"); close(fd); From 3c2593376a7870c8ae6411ff3fc83c13da98f219 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 2 Sep 2021 21:39:59 +0300 Subject: [PATCH 196/222] readme: future directions --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 7c8ee44..1b9feb5 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,12 @@ for example how it could be implemented in C. Don't hesitate to ask me everything you don't understand. I'm usually hanging around in #kisslinux at libera.chat, but you can also email me or open an issue here. +## Future directions + +1. Write a better cross-platform(*nix, maybe macos and windows) device enumeration library. +2. Convince mainstream apps(libinput, wlroots, ...) to use new library instead of libudev. +3. Declare libudev as obsolete library and archive this project. + ## Donate You can send a donation to `BTC: 1BwrcsgtWZeLVvNeEQSg4A28a3yrGN3FpK` From c7669d8eecd831e278bee8f5ee591d5b6577a445 Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 5 Sep 2021 17:22:32 +0300 Subject: [PATCH 197/222] udev_enumerate.c: fix endless loop in filter_property --- udev_enumerate.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/udev_enumerate.c b/udev_enumerate.c index c3caee5..41c9fa2 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -175,13 +175,11 @@ static int filter_property(struct udev_enumerate *udev_enumerate, struct udev_de 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; + if (value && value2) { + if (fnmatch(property, property2, 0) == 0 && + fnmatch(value, value2, 0) == 0) { + return 1; + } } list_entry2 = udev_list_entry_get_next(list_entry2); From 99676e0e0463dc5674c6aff1d158ae3c796815d9 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 7 Sep 2021 01:49:28 +0300 Subject: [PATCH 198/222] readme: What works -> What doesn't work --- README.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 1b9feb5..4fbe18b 100644 --- a/README.md +++ b/README.md @@ -24,17 +24,18 @@ of `libudev` which can be used with any or without a device manager. [0] https://github.com/FreeBSDDesktop/libudev-devd [1] https://github.com/oasislinux/libinput -## What Works +## What doesn't work -* [x] xorg-server -* [ ] dosfstools - need to implement udev_enumerate_add_match_parent() -* [x] libinput -* [x] usbutils -* [x] wlroots -* [x] weston -* [x] libusb -* [x] kwin -* [ ] ??? +* dosfstools - requires udev_enumerate_add_match_parent() +* PulseAudio - highly depends on udev internal properties +* udisks2 - highly depends on udev internal properties +* android-tools - requires udev rules for non-root usage +* NetworkManager - needs investigation +* libgudev - needs investigation +* PipeWare - depends on udev internal properties +* ldm - depends on udev internal properties +* lvm2 - uses deprecated `udev_queue` API +* ??? ## Dependencies From af4dc2ff14b020840bf5d4ac3501d639314fb55d Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 8 Sep 2021 21:26:18 +0300 Subject: [PATCH 199/222] readme: rewrite why, add pros/cons --- README.md | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 4fbe18b..5ce2e20 100644 --- a/README.md +++ b/README.md @@ -4,25 +4,37 @@ Drop-in replacement for `libudev` intended to work with any device manager ## Why? -Because `udev` sucks, it is bloated and overengineered. `udev` is just -like `systemd`, it locks you into using non-portable crap that you can't -avoid because multiple programs depend on it. Look, even FreeBSD was forced -to rewrite[0] this crappy library because `libinput` hard-depends on `udev`. -Without `libinput` you can't use `wayland` and many other cool stuff. +We all know that systemd is very hostile towards portability. Udev inherited +the same problem by exposing a very badly designed library interface. This is +dramatically reduces portability, user choice and basically creates vendor +lock-in because library interface highly tied to udev daemon. -Michael Forney (author of `cproc`, `samurai`, Oasis Linux, ...) decided to -fork[1] `libinput` and remove the hard dependency on `udev`. However, this -fork has a drawback that requires patching applications to use `libinput_netlink` -instead of the `libinput_udev` API in order to use the automatic detection of -input devices and hotplugging. Static configuration is also required for anything -other than input devices (e.g drm devices). +Another udev problem is non-portable home-grown language called "udev rules". +Udev authors definitely don't know(or care) why it's better to avoid reinventing +the wheel. Strictly speaking, I think they did that on purpose to overcomplicate +udev as much as possible. Why? So that only authors(RedHat/IBM) can rule and dictate +the future of udev. The recent eudev death only proves that it's really hard to +support such unmaintainable mess. -Thankfully `udev` has stable API and hopefully no changes will be made to it -the future. On this basis I decided to create this clean-room implementation -of `libudev` which can be used with any or without a device manager. +Udev hwdb is yet another illustration of systemd-like approach. What the hell +"userspace /dev" has to do with parsing hardware database(pci.ids, usb.ids) +and setting/remapping buttons? Udev smells like systemd by trying to implement +all possible functionality in the single daemon/code base. Standalone UNIX-way +programs much better suited for such purposes. -[0] https://github.com/FreeBSDDesktop/libudev-devd -[1] https://github.com/oasislinux/libinput +Keep in mind that libudev-zero isn't ideal. Here is some pros/cons: + +### Pros + +* Very portable. Doesn't depend on GNU features. +* No lock-in. Any device manager can be used, even smdev and CONFIG_UEVENT_HELPER. +* Source code is much cleaner than udev because of less abstractions and clever code. + +### Cons + +* Udev rules must be converted to shell script in order to work with any device manager. +* Udev hwdb interface isn't implemented. pciutils and usbutils will not display any meaningful info. +* Many functions and interfaces still aren't implemented, which may lead to breakage in some programs. ## What doesn't work From 000ff7bf2fa463ea99afaea8503c2ed9f8a1852c Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 8 Sep 2021 21:44:45 +0300 Subject: [PATCH 200/222] Makefile: add stub symbol versioning Fixes: #38 --- Makefile | 3 ++- libudev.sym | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 libudev.sym diff --git a/Makefile b/Makefile index e75f536..93567aa 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,8 @@ PKGCONFIGDIR = ${LIBDIR}/pkgconfig XCFLAGS = ${CPPFLAGS} ${CFLAGS} -std=c99 -fPIC -pthread -D_XOPEN_SOURCE=700 \ -Wall -Wextra -Wpedantic -Wmissing-prototypes -Wstrict-prototypes \ -Wno-unused-parameter -XLDFLAGS = ${LDFLAGS} -shared -Wl,-soname,libudev.so.1 +XLDFLAGS = ${LDFLAGS} -shared -Wl,-soname,libudev.so.1 \ + -Wl,-version-script,libudev.sym XARFLAGS = -rc OBJ = \ diff --git a/libudev.sym b/libudev.sym new file mode 100644 index 0000000..b69bb3b --- /dev/null +++ b/libudev.sym @@ -0,0 +1 @@ +LIBUDEV_183 {}; From 858f0b107f90b08d4031d2e3ca25a5f2145b61c4 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 9 Sep 2021 03:01:12 +0300 Subject: [PATCH 201/222] readme: pros/cons --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5ce2e20..e4c359f 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,8 @@ and setting/remapping buttons? Udev smells like systemd by trying to implement all possible functionality in the single daemon/code base. Standalone UNIX-way programs much better suited for such purposes. +## Pros/Cons + Keep in mind that libudev-zero isn't ideal. Here is some pros/cons: ### Pros From 6250984089514d7751985476a31d268c16b3d8f2 Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 9 Sep 2021 23:53:51 +0300 Subject: [PATCH 202/222] readme: add cups and workaround for pulseaudio --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e4c359f..99e0672 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Keep in mind that libudev-zero isn't ideal. Here is some pros/cons: ## What doesn't work * dosfstools - requires udev_enumerate_add_match_parent() -* PulseAudio - highly depends on udev internal properties +* PulseAudio - highly depends on udev internal properties. [workaround](https://gist.github.com/capezotte/03ee5548218e819b06459819bb120b4b#pulseaudio) * udisks2 - highly depends on udev internal properties * android-tools - requires udev rules for non-root usage * NetworkManager - needs investigation @@ -49,6 +49,7 @@ Keep in mind that libudev-zero isn't ideal. Here is some pros/cons: * PipeWare - depends on udev internal properties * ldm - depends on udev internal properties * lvm2 - uses deprecated `udev_queue` API +* cups - needs investigation * ??? ## Dependencies From caaa021290a1b84c44d084865c2512f4adf98297 Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 8 Oct 2021 08:36:20 +0300 Subject: [PATCH 203/222] udev_device.c: ignore devices without subsystem Do not allocate udev_device if device doesn't have subsystem. Fixes: #43 --- udev_device.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/udev_device.c b/udev_device.c index 939ab46..d1d57f3 100644 --- a/udev_device.c +++ b/udev_device.c @@ -530,18 +530,18 @@ static void set_properties_from_props(struct udev_device *udev_device) struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) { - char path[PATH_MAX], file[PATH_MAX]; char *subsystem, *driver, *sysname; struct udev_device *udev_device; + char path[PATH_MAX]; int i; if (!udev || !syspath) { return NULL; } - snprintf(file, sizeof(file), "%s/uevent", syspath); + subsystem = read_symlink(syspath, "subsystem"); - if (access(file, R_OK) == -1) { + if (!subsystem) { return NULL; } @@ -567,7 +567,6 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * sysname = strrchr(path, '/') + 1; driver = read_symlink(path, "driver"); - subsystem = read_symlink(path, "subsystem"); udev_list_entry_add(&udev_device->properties, "SUBSYSTEM", subsystem, 0); udev_list_entry_add(&udev_device->properties, "SYSNAME", sysname, 0); From 7265d305c27dee05436a25dc60481ad62e022756 Mon Sep 17 00:00:00 2001 From: illiliti Date: Fri, 8 Oct 2021 08:53:04 +0300 Subject: [PATCH 204/222] various: fix memory leaks Closes: #41 --- udev_device.c | 2 ++ udev_list.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/udev_device.c b/udev_device.c index d1d57f3..e202150 100644 --- a/udev_device.c +++ b/udev_device.c @@ -546,12 +546,14 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * } if (!realpath(syspath, path)) { + free(subsystem); return NULL; } udev_device = calloc(1, sizeof(*udev_device)); if (!udev_device) { + free(subsystem); return NULL; } diff --git a/udev_list.c b/udev_list.c index 95b08e8..b7fabca 100644 --- a/udev_list.c +++ b/udev_list.c @@ -78,6 +78,7 @@ struct udev_list_entry *udev_list_entry_add(struct udev_list_entry *list_entry, list_entry2->name = strdup(name); if (!list_entry2->name) { + free(list_entry2); return NULL; } @@ -85,6 +86,8 @@ struct udev_list_entry *udev_list_entry_add(struct udev_list_entry *list_entry, list_entry2->value = strdup(value); if (!list_entry2->value) { + free(list_entry2->name); + free(list_entry2); return NULL; } } From 6651ccc9d60637919f1c05a801f3edc3ba623cd7 Mon Sep 17 00:00:00 2001 From: Firas Khalil Khana Date: Sun, 24 Oct 2021 19:59:06 +0300 Subject: [PATCH 205/222] Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 99e0672..233162e 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Keep in mind that libudev-zero isn't ideal. Here is some pros/cons: * android-tools - requires udev rules for non-root usage * NetworkManager - needs investigation * libgudev - needs investigation -* PipeWare - depends on udev internal properties +* PipeWire - depends on udev internal properties * ldm - depends on udev internal properties * lvm2 - uses deprecated `udev_queue` API * cups - needs investigation From b8a0b953e6305dffeea57886fa379c5aca1b8397 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 16 Nov 2021 16:17:40 +0300 Subject: [PATCH 206/222] Revert "Makefile: add stub symbol versioning" This reverts commit 000ff7bf2fa463ea99afaea8503c2ed9f8a1852c. --- Makefile | 3 +-- libudev.sym | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) delete mode 100644 libudev.sym diff --git a/Makefile b/Makefile index 93567aa..e75f536 100644 --- a/Makefile +++ b/Makefile @@ -8,8 +8,7 @@ PKGCONFIGDIR = ${LIBDIR}/pkgconfig XCFLAGS = ${CPPFLAGS} ${CFLAGS} -std=c99 -fPIC -pthread -D_XOPEN_SOURCE=700 \ -Wall -Wextra -Wpedantic -Wmissing-prototypes -Wstrict-prototypes \ -Wno-unused-parameter -XLDFLAGS = ${LDFLAGS} -shared -Wl,-soname,libudev.so.1 \ - -Wl,-version-script,libudev.sym +XLDFLAGS = ${LDFLAGS} -shared -Wl,-soname,libudev.so.1 XARFLAGS = -rc OBJ = \ diff --git a/libudev.sym b/libudev.sym deleted file mode 100644 index b69bb3b..0000000 --- a/libudev.sym +++ /dev/null @@ -1 +0,0 @@ -LIBUDEV_183 {}; From ec47f63d6b2aeebec25efd64a0788329fdec7d0d Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 16 Nov 2021 16:17:47 +0300 Subject: [PATCH 207/222] Revert "udev_enumerate.c: fix pipeware" This reverts commit 4510b27a9b589a0ce82fef776c2648e19e79f2a4. --- udev_enumerate.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/udev_enumerate.c b/udev_enumerate.c index 41c9fa2..8aac73d 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -240,7 +240,7 @@ static int filter_sysattr(struct udev_enumerate *udev_enumerate, struct udev_dev static void *add_device(void *ptr) { struct udev_enumerate_thread *thread = ptr; - struct udev_device *udev_device, *parent; + struct udev_device *udev_device; udev_device = udev_device_new_from_syspath(thread->udev_enumerate->udev, thread->path); @@ -256,14 +256,7 @@ static void *add_device(void *ptr) return NULL; } - parent = udev_device_get_parent(udev_device); - pthread_mutex_lock(thread->mutex); - - if (parent) { - udev_list_entry_add(&thread->udev_enumerate->devices, udev_device_get_syspath(parent), NULL, 0); - } - udev_list_entry_add(&thread->udev_enumerate->devices, udev_device_get_syspath(udev_device), NULL, 0); pthread_mutex_unlock(thread->mutex); From 938b959402552483f010401051eb800c04607a41 Mon Sep 17 00:00:00 2001 From: illiliti Date: Wed, 17 Nov 2021 00:20:57 +0300 Subject: [PATCH 208/222] readme: mention PipeWire patch --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 233162e..e4afc4a 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Keep in mind that libudev-zero isn't ideal. Here is some pros/cons: * android-tools - requires udev rules for non-root usage * NetworkManager - needs investigation * libgudev - needs investigation -* PipeWire - depends on udev internal properties +* PipeWire - depends on udev internal properties. [patch](https://github.com/illiliti/libudev-zero/issues/26#issuecomment-846858706) * ldm - depends on udev internal properties * lvm2 - uses deprecated `udev_queue` API * cups - needs investigation From 505c61819b371a1802e054fe2601e64f2dc6d79e Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Mon, 29 Nov 2021 22:38:45 +0000 Subject: [PATCH 209/222] Makefile: support static-only builds One of the problems with udev is that systemd cannot be built statically[1]. With libudev-zero, on the other hand, no code changes are required to be able to do a static-only build, only Makefile changes. With this change, it's possible to "make install-static" to do a static-only build of libudev-zero. [1]: https://github.com/systemd/systemd/pull/20621#issuecomment-912014839 --- Makefile | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index e75f536..15dee2f 100644 --- a/Makefile +++ b/Makefile @@ -45,13 +45,24 @@ libudev.pc: libudev.pc.in -e 's|@VERSION@|243|g' \ libudev.pc.in > libudev.pc -install: libudev.so.1 libudev.a libudev.pc - mkdir -p ${DESTDIR}${INCLUDEDIR} ${DESTDIR}${LIBDIR} ${DESTDIR}${PKGCONFIGDIR} - cp -f udev.h ${DESTDIR}${INCLUDEDIR}/libudev.h - cp -f libudev.a ${DESTDIR}${LIBDIR}/libudev.a +install-headers: udev.h + mkdir -p ${DESTDIR}${INCLUDEDIR} + cp -f udev.h ${DESTDIR}${INCLUDEDIR}/libudev.h + +install-pkgconfig: libudev.pc + mkdir -p ${DESTDIR}${PKGCONFIGDIR} + cp -f libudev.pc ${DESTDIR}${PKGCONFIGDIR}/libudev.pc + +install-shared: libudev.so.1 install-headers install-pkgconfig + mkdir -p ${DESTDIR}${LIBDIR} cp -f libudev.so.1 ${DESTDIR}${LIBDIR}/libudev.so.1 ln -fs libudev.so.1 ${DESTDIR}${LIBDIR}/libudev.so - cp -f libudev.pc ${DESTDIR}${PKGCONFIGDIR}/libudev.pc + +install-static: libudev.a install-headers install-pkgconfig + mkdir -p ${DESTDIR}${LIBDIR} + cp -f libudev.a ${DESTDIR}${LIBDIR}/libudev.a + +install: install-shared install-static uninstall: rm -f ${DESTDIR}${LIBDIR}/libudev.a \ @@ -63,4 +74,5 @@ uninstall: clean: rm -f libudev.so.1 libudev.a libudev.pc ${OBJ} -.PHONY: all clean install uninstall +.PHONY: all clean install-headers install-pkgconfig install-shared \ + install-static install uninstall From 4154cf252c17297f98a8ca33693ead003b4509da Mon Sep 17 00:00:00 2001 From: illiliti Date: Thu, 16 Dec 2021 07:09:16 +0300 Subject: [PATCH 210/222] udev_enumerate.c: support NULL value in match/nomatch Fixes: #45 --- udev_enumerate.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/udev_enumerate.c b/udev_enumerate.c index 8aac73d..c553269 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -193,20 +193,17 @@ static int filter_property(struct udev_enumerate *udev_enumerate, struct udev_de static int filter_sysattr(struct udev_enumerate *udev_enumerate, struct udev_device *udev_device) { + const char *sysattr, *value, *value2; 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); + value2 = udev_list_entry_get_value(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) { + if (value && value2 && fnmatch(value2, value, 0) == 0) { return 0; } @@ -218,13 +215,10 @@ static int filter_sysattr(struct udev_enumerate *udev_enumerate, struct udev_dev if (list_entry) { while (list_entry) { sysattr = udev_list_entry_get_name(list_entry); + value2 = udev_list_entry_get_value(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) { + if (value && value2 && fnmatch(value2, value, 0) == 0) { return 1; } From 4a28cc57e4a25e9084eaa4d8279ca00ca65f4825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 15 Apr 2022 10:09:26 -0400 Subject: [PATCH 211/222] fix undefined LINE_MAX on Android --- udev_device.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/udev_device.c b/udev_device.c index e202150..173cbe4 100644 --- a/udev_device.c +++ b/udev_device.c @@ -26,6 +26,10 @@ #include "udev.h" #include "udev_list.h" +#ifndef LINE_MAX +#define LINE_MAX 2048 +#endif + #ifndef LONG_BIT #define LONG_BIT (sizeof(unsigned long) * 8) #endif From 713e7dbe754561bfda275a233e3ef625083a2543 Mon Sep 17 00:00:00 2001 From: Nihal Jere Date: Mon, 11 Jul 2022 16:13:25 -0500 Subject: [PATCH 212/222] README: grammar fixes --- README.md | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index e4afc4a..21f8f19 100644 --- a/README.md +++ b/README.md @@ -4,27 +4,27 @@ Drop-in replacement for `libudev` intended to work with any device manager ## Why? -We all know that systemd is very hostile towards portability. Udev inherited -the same problem by exposing a very badly designed library interface. This is +We all know that systemd is very hostile towards portability. udev inherited +the same problem by exposing a very badly designed library interface. This dramatically reduces portability, user choice and basically creates vendor -lock-in because library interface highly tied to udev daemon. +lock-in because the library interface highly tied to the udev daemon. -Another udev problem is non-portable home-grown language called "udev rules". -Udev authors definitely don't know(or care) why it's better to avoid reinventing -the wheel. Strictly speaking, I think they did that on purpose to overcomplicate -udev as much as possible. Why? So that only authors(RedHat/IBM) can rule and dictate -the future of udev. The recent eudev death only proves that it's really hard to -support such unmaintainable mess. +Another udev problem is the non-portable home-grown language called "udev +rules". The udev authors definitely don't know(or care) why it's better to +avoid reinventing the wheel. Strictly speaking, I think they did that on +purpose to overcomplicate udev as much as possible. Why? So that only the +authors(RedHat/IBM) can rule and dictate the future of udev. The recent eudev +death only proves that it's really hard to support such unmaintainable mess. -Udev hwdb is yet another illustration of systemd-like approach. What the hell -"userspace /dev" has to do with parsing hardware database(pci.ids, usb.ids) -and setting/remapping buttons? Udev smells like systemd by trying to implement -all possible functionality in the single daemon/code base. Standalone UNIX-way -programs much better suited for such purposes. +The udev hwdb is yet another illustration of a systemd-like approach. What the +hell does "userspace /dev" have to do with parsing hardware database(pci.ids, +usb.ids) and setting/remapping buttons? udev smells like systemd by trying to +implement all possible functionality in the single daemon/code base. Programs +that follow the UNIX philosophy is much better suited for such purposes. ## Pros/Cons -Keep in mind that libudev-zero isn't ideal. Here is some pros/cons: +Keep in mind that libudev-zero isn't ideal. Here are some pros/cons: ### Pros @@ -71,26 +71,26 @@ make PREFIX=/usr install Note that hotplugging support is fully optional. You can skip this step if you don't have a need for the hotplugging capability. -If you're using mdev-like device manager, refer to [mdev.conf](contrib/mdev.conf) -for config example. +If you're using an mdev-like device manager, refer to [mdev.conf](contrib/mdev.conf) +for a config example. -If you're using other device manager, you need to configure it to rebroadcast -kernel uevents. You can do this by either patching(see below) device manager +If you're using another device manager, you need to configure it to rebroadcast +kernel uevents. You can do this by either patching(see below) the device manager or simply executing [helper.c](contrib/helper.c) for each uevent. If you're developing your own device manager, you need to rebroadcast kernel -uevents to `0x4` netlink group of `NETLINK_KOBJECT_UEVENT`. This is required +uevents to the `0x4` netlink group of `NETLINK_KOBJECT_UEVENT`. This is required because libudev-zero can't simply listen to kernel uevents due to potential -race conditions. Refer(but don't copy blindly) to [helper.c](contrib/helper.c) -for example how it could be implemented in C. +race conditions. Refer to (but don't copy blindly) [helper.c](contrib/helper.c) +for an example of how it could be implemented in C. -Don't hesitate to ask me everything you don't understand. I'm usually hanging +Don't hesitate to ask me about anything you don't understand. I'm usually hanging around in #kisslinux at libera.chat, but you can also email me or open an issue here. ## Future directions 1. Write a better cross-platform(*nix, maybe macos and windows) device enumeration library. -2. Convince mainstream apps(libinput, wlroots, ...) to use new library instead of libudev. +2. Convince mainstream apps(libinput, wlroots, ...) to use a new library instead of libudev. 3. Declare libudev as obsolete library and archive this project. ## Donate From e5587c6edb12ea766e0f4e8c2431fa7b60d0d85c Mon Sep 17 00:00:00 2001 From: illiliti Date: Sun, 19 Jun 2022 11:15:35 +0300 Subject: [PATCH 213/222] Makefile: fix compatibility with smake --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 15dee2f..58f70e4 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ XCFLAGS = ${CPPFLAGS} ${CFLAGS} -std=c99 -fPIC -pthread -D_XOPEN_SOURCE=700 \ -Wno-unused-parameter XLDFLAGS = ${LDFLAGS} -shared -Wl,-soname,libudev.so.1 XARFLAGS = -rc +AR = ar OBJ = \ udev.o \ From 04a727df50fde3f69127aed4bc48e6cff5430175 Mon Sep 17 00:00:00 2001 From: illiliti Date: Tue, 18 Apr 2023 09:28:02 +0300 Subject: [PATCH 214/222] udev_device.c: consider device valid even if no subsystem symlink exists Some devices may not have subsystem symlinks, therefore we cannot rely on that to check if device is valid. Instead, check uevent file which should be always present in valid device. Reference: https://github.com/openwrt/openwrt/issues/12350 --- udev_device.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/udev_device.c b/udev_device.c index 173cbe4..7bf35d5 100644 --- a/udev_device.c +++ b/udev_device.c @@ -342,17 +342,17 @@ static char *read_symlink(const char *syspath, const char *name) return strdup(strrchr(link, '/') + 1); } -static void set_properties_from_uevent(struct udev_device *udev_device) +static int set_properties_from_uevent(struct udev_device *udev_device, const char *syspath) { - char line[LINE_MAX], path[PATH_MAX], devnode[PATH_MAX]; + char line[LINE_MAX], path[PATH_MAX + sizeof("/uevent")], devnode[PATH_MAX]; FILE *file; char *pos; - snprintf(path, sizeof(path), "%s/uevent", udev_device_get_syspath(udev_device)); + snprintf(path, sizeof(path), "%s/uevent", syspath); file = fopen(path, "r"); if (!file) { - return; + return -1; } while (fgets(line, sizeof(line), file)) { @@ -364,11 +364,12 @@ static void set_properties_from_uevent(struct udev_device *udev_device) } else if ((pos = strchr(line, '='))) { *pos = '\0'; - udev_list_entry_add(&udev_device->properties, line, pos + 1, 1); + udev_list_entry_add(&udev_device->properties, line, pos + 1, 0); } } fclose(file); + return 0; } static void make_bit(unsigned long *arr, int cnt, const char *str) @@ -543,21 +544,13 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * return NULL; } - subsystem = read_symlink(syspath, "subsystem"); - - if (!subsystem) { - return NULL; - } - if (!realpath(syspath, path)) { - free(subsystem); return NULL; } udev_device = calloc(1, sizeof(*udev_device)); if (!udev_device) { - free(subsystem); return NULL; } @@ -568,11 +561,17 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * udev_list_entry_init(&udev_device->properties); udev_list_entry_init(&udev_device->sysattrs); + if (set_properties_from_uevent(udev_device, path) == -1) { + free(udev_device); + return NULL; + } + udev_list_entry_add(&udev_device->properties, "SYSPATH", path, 0); udev_list_entry_add(&udev_device->properties, "DEVPATH", path + 4, 0); sysname = strrchr(path, '/') + 1; driver = read_symlink(path, "driver"); + subsystem = read_symlink(path, "subsystem"); udev_list_entry_add(&udev_device->properties, "SUBSYSTEM", subsystem, 0); udev_list_entry_add(&udev_device->properties, "SYSNAME", sysname, 0); @@ -585,7 +584,6 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * } } - set_properties_from_uevent(udev_device); set_properties_from_evdev(udev_device); set_properties_from_props(udev_device); From 99f1bc955a26eef8c9f4f5fee3247571618351b8 Mon Sep 17 00:00:00 2001 From: illiliti Date: Mon, 10 Jul 2023 14:13:58 +0300 Subject: [PATCH 215/222] udev_device.c: stub udev_device_get_current_tags_list_entry impl --- udev.h | 1 + udev_device.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/udev.h b/udev.h index 057d4af..3aaa327 100644 --- a/udev.h +++ b/udev.h @@ -70,6 +70,7 @@ int udev_device_has_tag(struct udev_device *udev_device, const char *tag); struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device); struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device); struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device); +struct udev_list_entry *udev_device_get_current_tags_list_entry(struct udev_device *udev_device); struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device); const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key); const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr); diff --git a/udev_device.c b/udev_device.c index 7bf35d5..84f8c07 100644 --- a/udev_device.c +++ b/udev_device.c @@ -228,6 +228,11 @@ struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device return NULL; } +/* XXX NOT IMPLEMENTED */ struct udev_list_entry *udev_device_get_current_tags_list_entry(struct udev_device *udev_device) +{ + return NULL; +} + struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device) { return udev_device ? udev_list_entry_get_next(&udev_device->sysattrs) : NULL; From ee32ac5f6494047b9ece26e7a5920650cdf46655 Mon Sep 17 00:00:00 2001 From: illiliti Date: Mon, 10 Jul 2023 14:15:04 +0300 Subject: [PATCH 216/222] Makefile: bump libudev version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 58f70e4..4e970b8 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ libudev.pc: libudev.pc.in -e 's|@exec_prefix@|${PREFIX}|g' \ -e "s|@libdir@|$$libdir|g" \ -e "s|@includedir@|$$includedir|g" \ - -e 's|@VERSION@|243|g' \ + -e 's|@VERSION@|251|g' \ libudev.pc.in > libudev.pc install-headers: udev.h From 90480bf525cf8e5ca85f4efab6a8bfd18140d70c Mon Sep 17 00:00:00 2001 From: Brian <89487381+b4yuan@users.noreply.github.com> Date: Tue, 5 Dec 2023 03:40:23 -0500 Subject: [PATCH 217/222] Add CodeQL Workflow for Code Security Analysis (#61) * Add CodeQL Workflow for Code Security Analysis Add CodeQL Workflow for Code Security Analysis This pull request introduces a CodeQL workflow to enhance the security analysis of our repository. CodeQL is a powerful static analysis tool that helps identify and mitigate security vulnerabilities in our codebase. By integrating this workflow into our GitHub Actions, we can proactively identify and address potential issues before they become security threats. We added a new CodeQL workflow file (.github/workflows/codeql.yml) that - Runs on every push and pull request to the main branch. - Excludes queries with a high false positive rate or low-severity findings. - Does not display results for third-party code, focusing only on our own codebase. Testing: To validate the functionality of this workflow, we have run several test scans on the codebase and reviewed the results. The workflow successfully compiles the project, identifies issues, and provides actionable insights while reducing noise by excluding certain queries and third-party code. Deployment: Once this pull request is merged, the CodeQL workflow will be active and automatically run on every push and pull request to the main branch. To view the results of these code scans, please follow these steps: 1. Under the repository name, click on the Security tab. 2. In the left sidebar, click Code scanning alerts. Additional Information: - You can further customize the workflow to adapt to your specific needs by modifying the workflow file. - For more information on CodeQL and how to interpret its results, refer to the GitHub documentation and the CodeQL documentation. Signed-off-by: Brian * Add CodeQL Workflow for Code Security Analysis Add CodeQL Workflow for Code Security Analysis This pull request introduces a CodeQL workflow to enhance the security analysis of our repository. CodeQL is a powerful static analysis tool that helps identify and mitigate security vulnerabilities in our codebase. By integrating this workflow into our GitHub Actions, we can proactively identify and address potential issues before they become security threats. We added a new CodeQL workflow file (.github/workflows/codeql.yml) that - Runs on every pull request (functionality to run on every push to main branches is included as a comment for convenience). - Runs daily. - Excludes queries with a high false positive rate or low-severity findings. - Does not display results for git submodules, focusing only on our own codebase. Testing: To validate the functionality of this workflow, we have run several test scans on the codebase and reviewed the results. The workflow successfully compiles the project, identifies issues, and provides actionable insights while reducing noise by excluding certain queries and third-party code. Deployment: Once this pull request is merged, the CodeQL workflow will be active and automatically run on every push and pull request to the main branch. To view the results of these code scans, please follow these steps: 1. Under the repository name, click on the Security tab. 2. In the left sidebar, click Code scanning alerts. Additional Information: - You can further customize the workflow to adapt to your specific needs by modifying the workflow file. - For more information on CodeQL and how to interpret its results, refer to the GitHub documentation and the CodeQL documentation (https://codeql.github.com/ and https://codeql.github.com/docs/). Signed-off-by: Brian * Add CodeQL Workflow for Code Security Analysis Add CodeQL Workflow for Code Security Analysis This pull request introduces a CodeQL workflow to enhance the security analysis of our repository. CodeQL is a powerful static analysis tool that helps identify and mitigate security vulnerabilities in our codebase. By integrating this workflow into our GitHub Actions, we can proactively identify and address potential issues before they become security threats. We added a new CodeQL workflow file (.github/workflows/codeql.yml) that - Runs on every pull request (functionality to run on every push to main branches is included as a comment for convenience). - Runs daily. - Excludes queries with a high false positive rate or low-severity findings. - Does not display results for git submodules, focusing only on our own codebase. Testing: To validate the functionality of this workflow, we have run several test scans on the codebase and reviewed the results. The workflow successfully compiles the project, identifies issues, and provides actionable insights while reducing noise by excluding certain queries and third-party code. Deployment: Once this pull request is merged, the CodeQL workflow will be active and automatically run on every push and pull request to the main branch. To view the results of these code scans, please follow these steps: 1. Under the repository name, click on the Security tab. 2. In the left sidebar, click Code scanning alerts. Additional Information: - You can further customize the workflow to adapt to your specific needs by modifying the workflow file. - For more information on CodeQL and how to interpret its results, refer to the GitHub documentation and the CodeQL documentation (https://codeql.github.com/ and https://codeql.github.com/docs/). Signed-off-by: Brian * Add CodeQL Workflow for Code Security Analysis Add CodeQL Workflow for Code Security Analysis This pull request introduces a CodeQL workflow to enhance the security analysis of our repository. CodeQL is a powerful static analysis tool that helps identify and mitigate security vulnerabilities in our codebase. By integrating this workflow into our GitHub Actions, we can proactively identify and address potential issues before they become security threats. We added a new CodeQL workflow file (.github/workflows/codeql.yml) that - Runs on every pull request (functionality to run on every push to main branches is included as a comment for convenience). - Runs daily. - Excludes queries with a high false positive rate or low-severity findings. - Does not display results for git submodules, focusing only on our own codebase. Testing: To validate the functionality of this workflow, we have run several test scans on the codebase and reviewed the results. The workflow successfully compiles the project, identifies issues, and provides actionable insights while reducing noise by excluding certain queries and third-party code. Deployment: Once this pull request is merged, the CodeQL workflow will be active and automatically run on every push and pull request to the main branch. To view the results of these code scans, please follow these steps: 1. Under the repository name, click on the Security tab. 2. In the left sidebar, click Code scanning alerts. Additional Information: - You can further customize the workflow to adapt to your specific needs by modifying the workflow file. - For more information on CodeQL and how to interpret its results, refer to the GitHub documentation and the CodeQL documentation (https://codeql.github.com/ and https://codeql.github.com/docs/). Signed-off-by: Brian --------- Signed-off-by: Brian --- .github/workflows/codeql-buildscript.sh | 3 + .github/workflows/codeql.yml | 126 ++++++++++++++++++++++++ .github/workflows/fail_on_error.py | 34 +++++++ 3 files changed, 163 insertions(+) create mode 100644 .github/workflows/codeql-buildscript.sh create mode 100644 .github/workflows/codeql.yml create mode 100755 .github/workflows/fail_on_error.py diff --git a/.github/workflows/codeql-buildscript.sh b/.github/workflows/codeql-buildscript.sh new file mode 100644 index 0000000..d9eae58 --- /dev/null +++ b/.github/workflows/codeql-buildscript.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +make diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..8164922 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,126 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + # push: + # branches: [ "main", "master" ] + schedule: + - cron: '0 0 * * *' + pull_request: + branches: '*' + +jobs: + analyze: + name: Analyze + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners + # Consider using larger runners for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-20.04' }} + timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'cpp' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ] + # Use only 'java' to analyze code written in Java, Kotlin or both + # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + submodules: recursive + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + queries: security-and-quality + + + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). + # If this step fails, then you should remove it and run the build manually (see below) + #- name: Autobuild + # uses: github/codeql-action/autobuild@v2 + + # â„šī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + - run: | + ./.github/workflows/codeql-buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" + upload: false + id: step1 + + # Filter out rules with low severity or high false positve rate + # Also filter out warnings in third-party code + - name: Filter out unwanted errors and warnings + uses: advanced-security/filter-sarif@v1 + with: + patterns: | + -**:cpp/path-injection + -**:cpp/world-writable-file-creation + -**:cpp/poorly-documented-function + -**:cpp/potentially-dangerous-function + -**:cpp/use-of-goto + -**:cpp/integer-multiplication-cast-to-long + -**:cpp/comparison-with-wider-type + -**:cpp/leap-year/* + -**:cpp/ambiguously-signed-bit-field + -**:cpp/suspicious-pointer-scaling + -**:cpp/suspicious-pointer-scaling-void + -**:cpp/unsigned-comparison-zero + -**/cmake*/Modules/** + input: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif + output: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif + + - name: Upload CodeQL results to code scanning + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: ${{ steps.step1.outputs.sarif-output }} + category: "/language:${{matrix.language}}" + + - name: Upload CodeQL results as an artifact + if: success() || failure() + uses: actions/upload-artifact@v3 + with: + name: codeql-results + path: ${{ steps.step1.outputs.sarif-output }} + retention-days: 5 + + - name: Fail if an error is found + run: | + ./.github/workflows/fail_on_error.py \ + ${{ steps.step1.outputs.sarif-output }}/cpp.sarif diff --git a/.github/workflows/fail_on_error.py b/.github/workflows/fail_on_error.py new file mode 100755 index 0000000..2979174 --- /dev/null +++ b/.github/workflows/fail_on_error.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 + +import json +import sys + +# Return whether SARIF file contains error-level results +def codeql_sarif_contain_error(filename): + with open(filename, 'r') as f: + s = json.load(f) + + for run in s.get('runs', []): + rules_metadata = run['tool']['driver']['rules'] + if not rules_metadata: + rules_metadata = run['tool']['extensions'][0]['rules'] + + for res in run.get('results', []): + if 'ruleIndex' in res: + rule_index = res['ruleIndex'] + elif 'rule' in res and 'index' in res['rule']: + rule_index = res['rule']['index'] + else: + continue + try: + rule_level = rules_metadata[rule_index]['defaultConfiguration']['level'] + except IndexError as e: + print(e, rule_index, len(rules_metadata)) + else: + if rule_level == 'error': + return True + return False + +if __name__ == "__main__": + if codeql_sarif_contain_error(sys.argv[1]): + sys.exit(1) From a2cc51bb142c16eac5598237d2edb46f095607be Mon Sep 17 00:00:00 2001 From: Mingjie Shen Date: Tue, 5 Dec 2023 03:41:24 -0500 Subject: [PATCH 218/222] udev_device.c: fix TOCTOU race condition (#57) Separately checking the state of a file before operating on it may allow an attacker to modify the file between the two operations. Reference: CWE-367. --- udev_device.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/udev_device.c b/udev_device.c index 84f8c07..c0895ce 100644 --- a/udev_device.c +++ b/udev_device.c @@ -267,16 +267,17 @@ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const snprintf(path, sizeof(path), "%s/%s", udev_device_get_syspath(udev_device), sysattr); - if (lstat(path, &st) != 0 || !S_ISREG(st.st_mode)) { - return NULL; - } - file = fopen(path, "r"); if (!file) { return NULL; } + if (fstat(fileno(file), &st) != 0 || !S_ISREG(st.st_mode)) { + fclose(file); + return NULL; + } + // TODO dynamic allocation of data len = fread(data, 1, sizeof(data) - 1, file); @@ -309,16 +310,17 @@ int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *s snprintf(path, sizeof(path), "%s/%s", udev_device_get_syspath(udev_device), sysattr); - if (lstat(path, &st) != 0 || !S_ISREG(st.st_mode)) { - return -1; - } - file = fopen(path, "w"); if (!file) { return -1; } + if (fstat(fileno(file), &st) != 0 || !S_ISREG(st.st_mode)) { + fclose(file); + return -1; + } + len = strlen(value); if (fwrite(value, 1, len, file) != len) { From 5eca08d71d51074bfe7b14fcf7d89318f4f6ff47 Mon Sep 17 00:00:00 2001 From: liamHowatt <30486941+liamHowatt@users.noreply.github.com> Date: Tue, 5 Dec 2023 04:15:26 -0500 Subject: [PATCH 219/222] Avoidable OOM on small systems (#62) * bandaid fix OOM * refactor fix OOM * Makefile: remove no longer needed -pthread option * libudev.pc.in: remove threads requirement --------- Co-authored-by: illiliti --- Makefile | 2 +- libudev.pc.in | 1 - udev_enumerate.c | 65 +++++++++++------------------------------------- 3 files changed, 15 insertions(+), 53 deletions(-) diff --git a/Makefile b/Makefile index 4e970b8..1fc5a1f 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ PREFIX = /usr/local LIBDIR = ${PREFIX}/lib INCLUDEDIR = ${PREFIX}/include PKGCONFIGDIR = ${LIBDIR}/pkgconfig -XCFLAGS = ${CPPFLAGS} ${CFLAGS} -std=c99 -fPIC -pthread -D_XOPEN_SOURCE=700 \ +XCFLAGS = ${CPPFLAGS} ${CFLAGS} -std=c99 -fPIC -D_XOPEN_SOURCE=700 \ -Wall -Wextra -Wpedantic -Wmissing-prototypes -Wstrict-prototypes \ -Wno-unused-parameter XLDFLAGS = ${LDFLAGS} -shared -Wl,-soname,libudev.so.1 diff --git a/libudev.pc.in b/libudev.pc.in index 7e29d8c..2d3f0b0 100644 --- a/libudev.pc.in +++ b/libudev.pc.in @@ -9,5 +9,4 @@ Description: Daemonless replacement for libudev Version: @VERSION@ URL: https://github.com/illiliti/libudev-zero Libs: -L${libdir} -ludev -Libs.private: -pthread Cflags: -I${includedir} diff --git a/udev_enumerate.c b/udev_enumerate.c index c553269..6fd49c0 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -21,7 +21,6 @@ #include #include #include -#include #include "udev.h" #include "udev_list.h" @@ -38,13 +37,6 @@ struct udev_enumerate { int refcount; }; -struct udev_enumerate_thread { - struct udev_enumerate *udev_enumerate; - pthread_mutex_t *mutex; - char path[PATH_MAX]; - pthread_t thread; -}; - int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) { return udev_enumerate ? !!udev_list_entry_add(&udev_enumerate->subsystem_match, subsystem, NULL, 0) - 1 : -1; @@ -231,31 +223,27 @@ static int filter_sysattr(struct udev_enumerate *udev_enumerate, struct udev_dev return 1; } -static void *add_device(void *ptr) +static void add_device(struct udev_enumerate *udev_enumerate, const char *path) { - struct udev_enumerate_thread *thread = ptr; struct udev_device *udev_device; - udev_device = udev_device_new_from_syspath(thread->udev_enumerate->udev, thread->path); + udev_device = udev_device_new_from_syspath(udev_enumerate->udev, path); if (!udev_device) { - return NULL; + return; } - if (!filter_subsystem(thread->udev_enumerate, udev_device) || - !filter_sysname(thread->udev_enumerate, udev_device) || - !filter_property(thread->udev_enumerate, udev_device) || - !filter_sysattr(thread->udev_enumerate, udev_device)) { + if (!filter_subsystem(udev_enumerate, udev_device) || + !filter_sysname(udev_enumerate, udev_device) || + !filter_property(udev_enumerate, udev_device) || + !filter_sysattr(udev_enumerate, udev_device)) { udev_device_unref(udev_device); - return NULL; + return; } - pthread_mutex_lock(thread->mutex); - udev_list_entry_add(&thread->udev_enumerate->devices, udev_device_get_syspath(udev_device), NULL, 0); - pthread_mutex_unlock(thread->mutex); + udev_list_entry_add(&udev_enumerate->devices, udev_device_get_syspath(udev_device), NULL, 0); udev_device_unref(udev_device); - return NULL; } static int filter_dot(const struct dirent *de) @@ -265,9 +253,7 @@ static int filter_dot(const struct dirent *de) static int scan_devices(struct udev_enumerate *udev_enumerate, const char *path) { - struct udev_enumerate_thread *thread; - pthread_mutex_t mutex; - int i, cnt, ret = 1; + int i, cnt; struct dirent **de; cnt = scandir(path, &de, filter_dot, NULL); @@ -276,41 +262,18 @@ static int scan_devices(struct udev_enumerate *udev_enumerate, const char *path) return 0; } - thread = calloc(cnt, sizeof(*thread)); - - if (!thread) { - ret = 0; - goto free_de; - } - - pthread_mutex_init(&mutex, NULL); - for (i = 0; i < cnt; i++) { - thread[i].mutex = &mutex; - thread[i].udev_enumerate = udev_enumerate; - - snprintf(thread[i].path, sizeof(thread[i].path), "%s/%s", path, de[i]->d_name); - - if (pthread_create(&thread[i].thread, NULL, add_device, &thread[i]) != 0) { - ret = 0; - break; - } + char device_path[PATH_MAX]; + snprintf(device_path, sizeof(device_path), "%s/%s", path, de[i]->d_name); + add_device(udev_enumerate, device_path); } - for (i = 0; i < cnt; i++) { - pthread_join(thread[i].thread, NULL); - } - - free(thread); - pthread_mutex_destroy(&mutex); - -free_de: for (i = 0; i < cnt; i++) { free(de[i]); } free(de); - return ret; + return 1; } int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) From c027f870c8a57b62ab501d693d5b390f80de3bc0 Mon Sep 17 00:00:00 2001 From: Sertonix Date: Tue, 13 Feb 2024 11:19:20 +0000 Subject: [PATCH 220/222] README: update link to PipeWire patch (#64) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 21f8f19..6cd5202 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Keep in mind that libudev-zero isn't ideal. Here are some pros/cons: * android-tools - requires udev rules for non-root usage * NetworkManager - needs investigation * libgudev - needs investigation -* PipeWire - depends on udev internal properties. [patch](https://github.com/illiliti/libudev-zero/issues/26#issuecomment-846858706) +* PipeWire - depends on udev internal properties. [patch](https://github.com/illiliti/libudev-zero/issues/26#issuecomment-1848802791) * ldm - depends on udev internal properties * lvm2 - uses deprecated `udev_queue` API * cups - needs investigation From bbeb7ad51c1edb7ab3cf63f30a21e9bb383b7994 Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 13 Feb 2024 11:20:52 +0000 Subject: [PATCH 221/222] Fixes incorrect detection of touchpads (#66) Some touchpad drivers (such as applespi) claim to have both EV_ABS and EV_REL capabilities. These touchpads are then reported as mice by libudev-zero. --- udev_device.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/udev_device.c b/udev_device.c index c0895ce..b057796 100644 --- a/udev_device.c +++ b/udev_device.c @@ -458,13 +458,7 @@ static void set_properties_from_evdev(struct udev_device *udev_device) udev_list_entry_add(&udev_device->properties, "ID_INPUT_SWITCH", "1", 0); } - if (test_bit(ev_bits, EV_REL)) { - if (test_bit(rel_bits, REL_Y) && test_bit(rel_bits, REL_X) && - test_bit(key_bits, BTN_MOUSE)) { - udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1", 0); - } - } - else if (test_bit(ev_bits, EV_ABS)) { + if (test_bit(ev_bits, EV_ABS)) { if (test_bit(key_bits, BTN_SELECT) || test_bit(key_bits, BTN_TR) || test_bit(key_bits, BTN_START) || test_bit(key_bits, BTN_TL)) { if (test_bit(key_bits, BTN_TOUCH)) { @@ -494,6 +488,12 @@ static void set_properties_from_evdev(struct udev_device *udev_device) } } } + else if (test_bit(ev_bits, EV_REL)) { + if (test_bit(rel_bits, REL_Y) && test_bit(rel_bits, REL_X) && + test_bit(key_bits, BTN_MOUSE)) { + udev_list_entry_add(&udev_device->properties, "ID_INPUT_MOUSE", "1", 0); + } + } if (!test_bit(ev_bits, EV_KEY)) { return; From 9dd049e2e070aeff5853e5fba0e31ec6901004c8 Mon Sep 17 00:00:00 2001 From: Mark Yacoub Date: Mon, 12 May 2025 12:20:39 -0400 Subject: [PATCH 222/222] Third-Party Import of: https://github.com/illiliti/libudev-zero.git Request Document: go/android3p For CL Reviewers: go/android3p#reviewing-a-cl For Build Team: go/ab-third-party-imports Bug: http://b/413100836 Test: libudev-zero Original import of the code can be found at: https://googleplex-android.googlesource.com/platform/external/libudev-zero/+/refs/heads/third-party-review. Security Questionnaire: http://b/413100836#comment1 Change-Id: I17b30efbd9e0785dd8ccf8a7cb77017e166af9fb --- Android.bp | 49 ++++++++++++++++++++++++++++++++++++++++++++++ METADATA | 16 +++++++++++++++ MODULE_LICENSE_ISC | 0 OWNERS | 1 + 4 files changed, 66 insertions(+) create mode 100644 Android.bp create mode 100644 METADATA create mode 100644 MODULE_LICENSE_ISC create mode 100644 OWNERS diff --git a/Android.bp b/Android.bp new file mode 100644 index 0000000..1f7dff0 --- /dev/null +++ b/Android.bp @@ -0,0 +1,49 @@ +package { + default_applicable_licenses: ["external_libudev_zero_license"], +} + +license { + name: "external_libudev_zero_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-ISC", + ], + license_text: [ + "LICENSE", + ], +} + +cc_genrule { + name: "libudev_zero_copy_headers", + srcs: ["udev.h"], + out: ["libudev.h"], + cmd: "cp $(in) $(out)", +} + +cc_library_static { + name: "libudev-zero", + visibility: [ + "//external/igt-gpu-tools", + ], + srcs: [ + "udev.c", + "udev_list.c", + "udev_device.c", + "udev_monitor.c", + "udev_enumerate.c", + ], + generated_headers: [ + "libudev_zero_copy_headers", + ], + export_generated_headers: [ + "libudev_zero_copy_headers", + ], + cflags: [ + "-Wall", + "-Wextra", + "-Wpedantic", + "-Wmissing-prototypes", + "-Wstrict-prototypes", + "-Wno-unused-parameter", + ], +} diff --git a/METADATA b/METADATA new file mode 100644 index 0000000..626de45 --- /dev/null +++ b/METADATA @@ -0,0 +1,16 @@ +name: "libudev-zero" +description: + "Drop-in replacement for libudev intended to work with any device manager" + +third_party { +homepage: "https://github.com/illiliti/libudev-zero" + identifier { + type: "Git" + value: "https://github.com/illiliti/libudev-zero" + primary_source: true + version: "bbeb7ad51c1edb7ab3cf63f30a21e9bb383b7994" + } + version: "bbeb7ad51c1edb7ab3cf63f30a21e9bb383b7994" + last_upgrade_date { year: 2025 month: 4 day: 28 } + license_type: NOTICE +} \ No newline at end of file diff --git a/MODULE_LICENSE_ISC b/MODULE_LICENSE_ISC new file mode 100644 index 0000000..e69de29 diff --git a/OWNERS b/OWNERS new file mode 100644 index 0000000..c956c29 --- /dev/null +++ b/OWNERS @@ -0,0 +1 @@ +include platform/system/core:main:/janitors/OWNERS \ No newline at end of file