diff --git a/.github/workflows/codeql-buildscript.sh b/.github/workflows/codeql-buildscript.sh deleted file mode 100644 index d9eae58..0000000 --- a/.github/workflows/codeql-buildscript.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -make diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index 8164922..0000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,126 +0,0 @@ -# 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 deleted file mode 100755 index 2979174..0000000 --- a/.github/workflows/fail_on_error.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/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) diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 403cec9..0000000 --- a/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -*.o -*.a -*.so -*.so.* -*.pc diff --git a/Android.bp b/Android.bp index e35298b..fbd0983 100644 --- a/Android.bp +++ b/Android.bp @@ -1,52 +1,17 @@ -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 { - name: "libudev-zero", + name: "libudev", vendor_available: true, - visibility: [ - "//external/ffmpeg/libavcodec", - "//external/igt-gpu-tools", - "//external/v4l-utils/utils/media-ctl", - ], + export_include_dirs: ["."], + srcs: [ "udev.c", - "udev_list.c", "udev_device.c", - "udev_monitor.c", "udev_enumerate.c", + "udev_list.c", + "udev_monitor.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 deleted file mode 100644 index 626de45..0000000 --- a/METADATA +++ /dev/null @@ -1,16 +0,0 @@ -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 deleted file mode 100644 index e69de29..0000000 diff --git a/Makefile b/Makefile index 1fc5a1f..58f70e4 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 -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 @@ -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@|251|g' \ + -e 's|@VERSION@|243|g' \ libudev.pc.in > libudev.pc install-headers: udev.h diff --git a/OWNERS b/OWNERS deleted file mode 100644 index c956c29..0000000 --- a/OWNERS +++ /dev/null @@ -1 +0,0 @@ -include platform/system/core:main:/janitors/OWNERS \ No newline at end of file diff --git a/README.md b/README.md index 6cd5202..21f8f19 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-1848802791) +* 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 diff --git a/libudev.h b/libudev.h new file mode 120000 index 0000000..adc211b --- /dev/null +++ b/libudev.h @@ -0,0 +1 @@ +udev.h \ No newline at end of file diff --git a/libudev.pc.in b/libudev.pc.in index 2d3f0b0..7e29d8c 100644 --- a/libudev.pc.in +++ b/libudev.pc.in @@ -9,4 +9,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} diff --git a/udev.h b/udev.h index 3aaa327..057d4af 100644 --- a/udev.h +++ b/udev.h @@ -70,7 +70,6 @@ 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 b057796..173cbe4 100644 --- a/udev_device.c +++ b/udev_device.c @@ -228,11 +228,6 @@ 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; @@ -267,14 +262,13 @@ 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); - file = fopen(path, "r"); - - if (!file) { + if (lstat(path, &st) != 0 || !S_ISREG(st.st_mode)) { return NULL; } - if (fstat(fileno(file), &st) != 0 || !S_ISREG(st.st_mode)) { - fclose(file); + file = fopen(path, "r"); + + if (!file) { return NULL; } @@ -310,14 +304,13 @@ 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); - file = fopen(path, "w"); - - if (!file) { + if (lstat(path, &st) != 0 || !S_ISREG(st.st_mode)) { return -1; } - if (fstat(fileno(file), &st) != 0 || !S_ISREG(st.st_mode)) { - fclose(file); + file = fopen(path, "w"); + + if (!file) { return -1; } @@ -349,17 +342,17 @@ static char *read_symlink(const char *syspath, const char *name) return strdup(strrchr(link, '/') + 1); } -static int set_properties_from_uevent(struct udev_device *udev_device, const char *syspath) +static void set_properties_from_uevent(struct udev_device *udev_device) { - char line[LINE_MAX], path[PATH_MAX + sizeof("/uevent")], devnode[PATH_MAX]; + char line[LINE_MAX], path[PATH_MAX], devnode[PATH_MAX]; FILE *file; char *pos; - snprintf(path, sizeof(path), "%s/uevent", syspath); + snprintf(path, sizeof(path), "%s/uevent", udev_device_get_syspath(udev_device)); file = fopen(path, "r"); if (!file) { - return -1; + return; } while (fgets(line, sizeof(line), file)) { @@ -371,12 +364,11 @@ static int set_properties_from_uevent(struct udev_device *udev_device, const cha } else if ((pos = strchr(line, '='))) { *pos = '\0'; - udev_list_entry_add(&udev_device->properties, line, pos + 1, 0); + udev_list_entry_add(&udev_device->properties, line, pos + 1, 1); } } fclose(file); - return 0; } static void make_bit(unsigned long *arr, int cnt, const char *str) @@ -458,7 +450,13 @@ 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_ABS)) { + 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(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)) { @@ -488,12 +486,6 @@ 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; @@ -551,13 +543,21 @@ 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,17 +568,11 @@ 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); @@ -591,6 +585,7 @@ 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); diff --git a/udev_enumerate.c b/udev_enumerate.c index 6fd49c0..c553269 100644 --- a/udev_enumerate.c +++ b/udev_enumerate.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "udev.h" #include "udev_list.h" @@ -37,6 +38,13 @@ 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; @@ -223,27 +231,31 @@ static int filter_sysattr(struct udev_enumerate *udev_enumerate, struct udev_dev return 1; } -static void add_device(struct udev_enumerate *udev_enumerate, const char *path) +static void *add_device(void *ptr) { + struct udev_enumerate_thread *thread = ptr; struct udev_device *udev_device; - udev_device = udev_device_new_from_syspath(udev_enumerate->udev, path); + udev_device = udev_device_new_from_syspath(thread->udev_enumerate->udev, thread->path); if (!udev_device) { - return; + return NULL; } - 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)) { + 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; + return NULL; } - udev_list_entry_add(&udev_enumerate->devices, udev_device_get_syspath(udev_device), NULL, 0); + 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 filter_dot(const struct dirent *de) @@ -253,7 +265,9 @@ static int filter_dot(const struct dirent *de) static int scan_devices(struct udev_enumerate *udev_enumerate, const char *path) { - int i, cnt; + struct udev_enumerate_thread *thread; + pthread_mutex_t mutex; + int i, cnt, ret = 1; struct dirent **de; cnt = scandir(path, &de, filter_dot, NULL); @@ -262,18 +276,41 @@ static int scan_devices(struct udev_enumerate *udev_enumerate, const char *path) return 0; } - for (i = 0; i < cnt; i++) { - char device_path[PATH_MAX]; - snprintf(device_path, sizeof(device_path), "%s/%s", path, de[i]->d_name); - add_device(udev_enumerate, device_path); + 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); + } + + free(thread); + pthread_mutex_destroy(&mutex); + +free_de: for (i = 0; i < cnt; i++) { free(de[i]); } free(de); - return 1; + return ret; } int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate)