libudev-zero: update to 1.0.4
authorAlexandru Ardelean <redacted>
Mon, 25 May 2026 16:09:14 +0000 (19:09 +0300)
committerDaniel Golle <redacted>
Mon, 25 May 2026 19:06:09 +0000 (20:06 +0100)
First upstream release since 2023-07. All four locally-carried patches
are merged in 1.0.4 and can be dropped:

- 0001 (PR #57): udev_device.c TOCTOU race fix
- 0002 (PR #62): avoid OOM on small systems
- 0003 (PR #66): correct touchpad detection
- 0004 (PR #80): hwdb USB ID lookup from usb.ids

The release also pulls in PR #79 (do not assume EV_REL and EV_ABS are
mutually exclusive in udev_device.c).

Release notes:
https://github.com/illiliti/libudev-zero/releases/tag/1.0.4

Signed-off-by: Alexandru Ardelean <redacted>
libs/libudev-zero/Makefile
libs/libudev-zero/patches/0001-udev_device.c-fix-TOCTOU-race-condition-57.patch [deleted file]
libs/libudev-zero/patches/0002-Avoidable-OOM-on-small-systems-62.patch [deleted file]
libs/libudev-zero/patches/0003-Fixes-incorrect-detection-of-touchpads-66.patch [deleted file]
libs/libudev-zero/patches/0004-udev-implement-hwdb-USB-ID-lookup-from-usb.ids.patch [deleted file]

index 77e78573b3c3262ddfd3f762a3bbf5fae21049de..843bcdd54adf5bde0886eded6e6ef944f6cc6f83 100644 (file)
@@ -5,12 +5,12 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=libudev-zero
-PKG_VERSION:=1.0.3
-PKG_RELEASE:=3
+PKG_VERSION:=1.0.4
+PKG_RELEASE:=1
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
 PKG_SOURCE_URL:=https://codeload.github.com/illiliti/libudev-zero/tar.gz/$(PKG_VERSION)?
-PKG_HASH:=0bd89b657d62d019598e6c7ed726ff8fed80e8ba092a83b484d66afb80b77da5
+PKG_HASH:=10148cfd6047d387bf71eca72cd19c177084224d96434a118d8def6e0a3d6316
 
 PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
 PKG_LICENSE:=ISC
diff --git a/libs/libudev-zero/patches/0001-udev_device.c-fix-TOCTOU-race-condition-57.patch b/libs/libudev-zero/patches/0001-udev_device.c-fix-TOCTOU-race-condition-57.patch
deleted file mode 100644 (file)
index 4d3528d..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-From a2cc51bb142c16eac5598237d2edb46f095607be Mon Sep 17 00:00:00 2001
-From: Mingjie Shen <mjshen137@gmail.com>
-Date: Tue, 5 Dec 2023 03:41:24 -0500
-Subject: [PATCH] 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(-)
-
---- a/udev_device.c
-+++ b/udev_device.c
-@@ -267,16 +267,17 @@ const char *udev_device_get_sysattr_valu
-     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
-     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) {
diff --git a/libs/libudev-zero/patches/0002-Avoidable-OOM-on-small-systems-62.patch b/libs/libudev-zero/patches/0002-Avoidable-OOM-on-small-systems-62.patch
deleted file mode 100644 (file)
index 904f41f..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-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] 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 <illiliti@protonmail.com>
----
- Makefile         |  2 +-
- libudev.pc.in    |  1 -
- udev_enumerate.c | 65 +++++++++++-------------------------------------
- 3 files changed, 15 insertions(+), 53 deletions(-)
-
---- 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
---- a/libudev.pc.in
-+++ b/libudev.pc.in
-@@ -9,5 +9,4 @@ Description: Daemonless replacement for
- Version: @VERSION@
- URL: https://github.com/illiliti/libudev-zero
- Libs: -L${libdir} -ludev
--Libs.private: -pthread
- Cflags: -I${includedir}
---- a/udev_enumerate.c
-+++ b/udev_enumerate.c
-@@ -21,7 +21,6 @@
- #include <string.h>
- #include <limits.h>
- #include <fnmatch.h>
--#include <pthread.h>
- #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_en
-     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 diren
- 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_enum
-         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;
--        }
--    }
--
-     for (i = 0; i < cnt; i++) {
--        pthread_join(thread[i].thread, NULL);
-+        char device_path[PATH_MAX];
-+        snprintf(device_path, sizeof(device_path), "%s/%s", path, de[i]->d_name);
-+        add_device(udev_enumerate, device_path);
-     }
--    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)
diff --git a/libs/libudev-zero/patches/0003-Fixes-incorrect-detection-of-touchpads-66.patch b/libs/libudev-zero/patches/0003-Fixes-incorrect-detection-of-touchpads-66.patch
deleted file mode 100644 (file)
index 1884192..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-From bbeb7ad51c1edb7ab3cf63f30a21e9bb383b7994 Mon Sep 17 00:00:00 2001
-From: Matt <smattie@users.noreply.github.com>
-Date: Tue, 13 Feb 2024 11:20:52 +0000
-Subject: [PATCH] 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(-)
-
---- a/udev_device.c
-+++ b/udev_device.c
-@@ -458,13 +458,7 @@ static void set_properties_from_evdev(st
-         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(st
-             }
-         }
-     }
-+    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;
diff --git a/libs/libudev-zero/patches/0004-udev-implement-hwdb-USB-ID-lookup-from-usb.ids.patch b/libs/libudev-zero/patches/0004-udev-implement-hwdb-USB-ID-lookup-from-usb.ids.patch
deleted file mode 100644 (file)
index 890a00e..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-From 2bebebc9e0444ec53afd7f1f37aa80ff6b95f5f7 Mon Sep 17 00:00:00 2001
-From: Alexandru Ardelean <ardeleanalex@gmail.com>
-Date: Tue, 19 May 2026 17:52:47 +0300
-Subject: [PATCH] udev: implement hwdb USB ID lookup from usb.ids (#80)
-
-Replace the four stub udev_hwdb_*() functions with a working
-implementation that looks up vendor and product names from a
-usb.ids database file (e.g. provided by the hwdata package).
-
-udev_hwdb_get_properties_list_entry() parses the file for USB
-modalias strings of the form "usb:vVVVVpPPPP" (product lookup)
-or "usb:vVVVV" (vendor lookup), and populates the entry list with
-ID_MODEL_FROM_DATABASE or ID_VENDOR_FROM_DATABASE properties.
-
-Lines are read via POSIX getline() so the buffer grows as needed
-on long usb.ids entries.
-
-The path to the usb.ids file is set at build time via the
-USB_IDS_PATH Makefile variable, which defaults to
-${SHAREDIR}/hwdata/usb.ids.
----
- Makefile |   3 ++
- udev.c   | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
- 2 files changed, 144 insertions(+), 7 deletions(-)
-
---- a/Makefile
-+++ b/Makefile
-@@ -3,9 +3,12 @@
- PREFIX = /usr/local
- LIBDIR = ${PREFIX}/lib
-+SHAREDIR = ${PREFIX}/share
- INCLUDEDIR = ${PREFIX}/include
- PKGCONFIGDIR = ${LIBDIR}/pkgconfig
-+USB_IDS_PATH = ${SHAREDIR}/hwdata/usb.ids
- XCFLAGS = ${CPPFLAGS} ${CFLAGS} -std=c99 -fPIC -D_XOPEN_SOURCE=700 \
-+                -DUSB_IDS_PATH=\"${USB_IDS_PATH}\" \
-                 -Wall -Wextra -Wpedantic -Wmissing-prototypes -Wstrict-prototypes \
-                 -Wno-unused-parameter
- XLDFLAGS = ${LDFLAGS} -shared -Wl,-soname,libudev.so.1
---- a/udev.c
-+++ b/udev.c
-@@ -15,9 +15,13 @@
-  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-  */
-+#include <stdio.h>
-+#include <stdint.h>
- #include <stdlib.h>
-+#include <string.h>
- #include "udev.h"
-+#include "udev_list.h"
- struct udev {
-     int refcount;
-@@ -76,22 +80,152 @@ int udev_get_log_priority(struct udev *u
-     return 0;
- }
--/* XXX NOT IMPLEMENTED */ struct udev_hwdb *udev_hwdb_new(struct udev *udev)
-+struct udev_hwdb {
-+    struct udev_list_entry head;
-+    int refcount;
-+};
-+
-+static int usb_ids_lookup_vendor(uint16_t vendorid, char *buf, size_t buflen)
- {
--    return NULL;
-+    char *line = NULL, *name;
-+    size_t cap = 0, len;
-+    unsigned int id;
-+    FILE *f;
-+
-+    f = fopen(USB_IDS_PATH, "r");
-+    if (!f) {
-+        return 0;
-+    }
-+    while (getline(&line, &cap, f) != -1) {
-+        if (line[0] == '#' || line[0] == '\t' || line[0] == '\n') {
-+            continue;
-+        }
-+        if (sscanf(line, "%04x", &id) != 1 || id != vendorid) {
-+            continue;
-+        }
-+        name = strchr(line, ' ');
-+        if (name) {
-+            while (*name == ' ') {
-+                name++;
-+            }
-+            len = strlen(name);
-+            while (len > 0 && (name[len - 1] == '\n' || name[len - 1] == '\r')) {
-+                name[--len] = '\0';
-+            }
-+            snprintf(buf, buflen, "%s", name);
-+        }
-+        break;
-+    }
-+    free(line);
-+    fclose(f);
-+    return buf[0] != '\0';
-+}
-+
-+static int usb_ids_lookup_product(uint16_t vendorid, uint16_t productid, char *buf, size_t buflen)
-+{
-+    char *line = NULL, *name;
-+    size_t cap = 0, len;
-+    int in_vendor = 0;
-+    unsigned int id;
-+    FILE *f;
-+
-+    f = fopen(USB_IDS_PATH, "r");
-+    if (!f) {
-+        return 0;
-+    }
-+    while (getline(&line, &cap, f) != -1) {
-+        if (line[0] == '#' || line[0] == '\n') {
-+            continue;
-+        }
-+        if (in_vendor) {
-+            if (line[0] != '\t') {
-+                break;
-+            }
-+            if (line[1] == '\t') {
-+                continue;
-+            }
-+            if (sscanf(line + 1, "%04x", &id) != 1 || id != productid) {
-+                continue;
-+            }
-+            name = strchr(line + 1, ' ');
-+            if (name) {
-+                while (*name == ' ') {
-+                    name++;
-+                }
-+                len = strlen(name);
-+                while (len > 0 && (name[len - 1] == '\n' || name[len - 1] == '\r')) {
-+                    name[--len] = '\0';
-+                }
-+                snprintf(buf, buflen, "%s", name);
-+            }
-+            break;
-+        }
-+        if (line[0] == '\t') {
-+            continue;
-+        }
-+        if (sscanf(line, "%04x", &id) != 1 || id != vendorid) {
-+            continue;
-+        }
-+        in_vendor = 1;
-+    }
-+    free(line);
-+    fclose(f);
-+    return buf[0] != '\0';
- }
--/* XXX NOT IMPLEMENTED */ struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb)
-+struct udev_hwdb *udev_hwdb_new(struct udev *udev)
- {
--    return NULL;
-+    struct udev_hwdb *hwdb;
-+
-+    hwdb = calloc(1, sizeof(*hwdb));
-+    if (!hwdb) {
-+        return NULL;
-+    }
-+    hwdb->refcount = 1;
-+    return hwdb;
- }
--/* XXX NOT IMPLEMENTED */ struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb)
-+struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb)
- {
--    return NULL;
-+    if (!hwdb) {
-+        return NULL;
-+    }
-+    hwdb->refcount++;
-+    return hwdb;
- }
--/* XXX NOT IMPLEMENTED */ struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags)
-+struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb)
- {
-+    if (!hwdb) {
-+        return NULL;
-+    }
-+    if (--hwdb->refcount > 0) {
-+        return NULL;
-+    }
-+    udev_list_entry_free_all(&hwdb->head);
-+    free(hwdb);
-     return NULL;
- }
-+
-+struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags)
-+{
-+    unsigned int vendorid, productid;
-+    char name[64];
-+
-+    if (!hwdb || !modalias) {
-+        return NULL;
-+    }
-+    udev_list_entry_free_all(&hwdb->head);
-+    hwdb->head.next = NULL;
-+    name[0] = '\0';
-+    if (sscanf(modalias, "usb:v%4xp%4x", &vendorid, &productid) == 2) {
-+        if (usb_ids_lookup_product((uint16_t)vendorid, (uint16_t)productid, name, sizeof(name))) {
-+            udev_list_entry_add(&hwdb->head, "ID_MODEL_FROM_DATABASE", name, 0);
-+        }
-+    } else if (sscanf(modalias, "usb:v%4x", &vendorid) == 1) {
-+        if (usb_ids_lookup_vendor((uint16_t)vendorid, name, sizeof(name))) {
-+            udev_list_entry_add(&hwdb->head, "ID_VENDOR_FROM_DATABASE", name, 0);
-+        }
-+    }
-+    return hwdb->head.next;
-+}
git clone https://git.99rst.org/PROJECT