diff --git a/man/sd_hwdb_new.xml b/man/sd_hwdb_new.xml index c071599ae6..0584add423 100644 --- a/man/sd_hwdb_new.xml +++ b/man/sd_hwdb_new.xml @@ -16,6 +16,7 @@ sd_hwdb_new + sd_hwdb_new_from_path sd_hwdb_ref sd_hwdb_unref @@ -31,6 +32,12 @@ sd_hwdb **hwdb + + int sd_hwdb_new_from_path + const char *path + sd_hwdb **hwdb + + sd_hwdb* sd_hwdb_ref sd_hwdb *hwdb @@ -50,6 +57,9 @@ database. Upon initialization, the file containing the binary representation of the hardware database is located and opened. The new object is returned in hwdb. + sd_hwdb_new_from_path() may be used to specify the path from which the binary + hardware database should be opened. + The hwdb object is reference counted. sd_hwdb_ref() and sd_hwdb_unref() may be used to get a new reference or destroy an existing reference to an object. The caller must dispose of the reference acquired with sd_hwdb_new() @@ -65,8 +75,8 @@ Return Value - On success, sd_hwdb_new() returns a non-negative integer. On - failure, it returns a negative errno-style error code. + On success, sd_hwdb_new() and sd_hwdb_new_from_path() + return a non-negative integer. On failure, a negative errno-style error code is returned. sd_hwdb_ref() always returns the argument. diff --git a/src/hwdb/hwdb.c b/src/hwdb/hwdb.c index 17ac7e4fbe..6925aecd84 100644 --- a/src/hwdb/hwdb.c +++ b/src/hwdb/hwdb.c @@ -18,7 +18,7 @@ static const char *arg_root = NULL; static bool arg_strict = false; static int verb_query(int argc, char *argv[], void *userdata) { - return hwdb_query(argv[1]); + return hwdb_query(argv[1], arg_root); } static int verb_update(int argc, char *argv[], void *userdata) { diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index ccc321ec33..528e86b663 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -778,3 +778,8 @@ global: sd_device_open; sd_device_enumerator_add_nomatch_sysname; } LIBSYSTEMD_250; + +LIBSYSTEMD_252 { +global: + sd_hwdb_new_from_path; +} LIBSYSTEMD_251; diff --git a/src/libsystemd/sd-hwdb/hwdb-internal.h b/src/libsystemd/sd-hwdb/hwdb-internal.h index 5ddc2211e6..62d27f7b89 100644 --- a/src/libsystemd/sd-hwdb/hwdb-internal.h +++ b/src/libsystemd/sd-hwdb/hwdb-internal.h @@ -2,6 +2,7 @@ #pragma once #include +#include #include "def.h" #include "hashmap.h" diff --git a/src/libsystemd/sd-hwdb/sd-hwdb.c b/src/libsystemd/sd-hwdb/sd-hwdb.c index 748cf26934..f73d1fc21e 100644 --- a/src/libsystemd/sd-hwdb/sd-hwdb.c +++ b/src/libsystemd/sd-hwdb/sd-hwdb.c @@ -281,9 +281,9 @@ static int trie_search_f(sd_hwdb *hwdb, const char *search) { return 0; } -_public_ int sd_hwdb_new(sd_hwdb **ret) { +static int hwdb_new(const char *path, sd_hwdb **ret) { _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL; - const char *hwdb_bin_path; + const char *hwdb_bin_path = NULL; const char sig[] = HWDB_SIG; assert_return(ret, -EINVAL); @@ -294,19 +294,26 @@ _public_ int sd_hwdb_new(sd_hwdb **ret) { hwdb->n_ref = 1; - /* find hwdb.bin in hwdb_bin_paths */ - NULSTR_FOREACH(hwdb_bin_path, hwdb_bin_paths) { - log_debug("Trying to open \"%s\"...", hwdb_bin_path); - hwdb->f = fopen(hwdb_bin_path, "re"); - if (hwdb->f) - break; - if (errno != ENOENT) - return log_debug_errno(errno, "Failed to open %s: %m", hwdb_bin_path); - } + /* find hwdb.bin in hwdb_bin_paths, or from an explicit path if provided */ + if (!isempty(path)) { + log_debug("Trying to open \"%s\"...", path); + hwdb->f = fopen(path, "re"); + if (!hwdb->f) + return log_debug_errno(errno, "Failed to open %s: %m", path); + } else { + NULSTR_FOREACH(hwdb_bin_path, hwdb_bin_paths) { + log_debug("Trying to open \"%s\"...", hwdb_bin_path); + hwdb->f = fopen(hwdb_bin_path, "re"); + if (hwdb->f) + break; + if (errno != ENOENT) + return log_debug_errno(errno, "Failed to open %s: %m", hwdb_bin_path); + } - if (!hwdb->f) - return log_debug_errno(SYNTHETIC_ERRNO(ENOENT), - "hwdb.bin does not exist, please run 'systemd-hwdb update'"); + if (!hwdb->f) + return log_debug_errno(SYNTHETIC_ERRNO(ENOENT), + "hwdb.bin does not exist, please run 'systemd-hwdb update'"); + } if (fstat(fileno(hwdb->f), &hwdb->st) < 0) return log_debug_errno(errno, "Failed to stat %s: %m", hwdb_bin_path); @@ -339,6 +346,16 @@ _public_ int sd_hwdb_new(sd_hwdb **ret) { return 0; } +_public_ int sd_hwdb_new_from_path(const char *path, sd_hwdb **ret) { + assert_return(!isempty(path), -EINVAL); + + return hwdb_new(path, ret); +} + +_public_ int sd_hwdb_new(sd_hwdb **ret) { + return hwdb_new(NULL, ret); +} + static sd_hwdb *hwdb_free(sd_hwdb *hwdb) { assert(hwdb); diff --git a/src/shared/hwdb-util.c b/src/shared/hwdb-util.c index f98d03f766..1ec861f76f 100644 --- a/src/shared/hwdb-util.c +++ b/src/shared/hwdb-util.c @@ -650,14 +650,27 @@ int hwdb_update(const char *root, const char *hwdb_bin_dir, bool strict, bool co return r; } -int hwdb_query(const char *modalias) { +int hwdb_query(const char *modalias, const char *root) { _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL; - const char *key, *value; + const char *key, *value, *p; int r; assert(modalias); - r = sd_hwdb_new(&hwdb); + if (!isempty(root)) + NULSTR_FOREACH(p, hwdb_bin_paths) { + _cleanup_free_ char *hwdb_bin = NULL; + + hwdb_bin = path_join(root, p); + if (!hwdb_bin) + return -ENOMEM; + + r = sd_hwdb_new_from_path(hwdb_bin, &hwdb); + if (r >= 0) + break; + } + else + r = sd_hwdb_new(&hwdb); if (r < 0) return r; diff --git a/src/shared/hwdb-util.h b/src/shared/hwdb-util.h index 5afde74723..bfecddea42 100644 --- a/src/shared/hwdb-util.h +++ b/src/shared/hwdb-util.h @@ -7,4 +7,4 @@ bool hwdb_validate(sd_hwdb *hwdb); int hwdb_update(const char *root, const char *hwdb_bin_dir, bool strict, bool compat); -int hwdb_query(const char *modalias); +int hwdb_query(const char *modalias, const char *root); diff --git a/src/systemd/sd-hwdb.h b/src/systemd/sd-hwdb.h index 9380759e07..9eee1c192b 100644 --- a/src/systemd/sd-hwdb.h +++ b/src/systemd/sd-hwdb.h @@ -27,6 +27,7 @@ sd_hwdb *sd_hwdb_ref(sd_hwdb *hwdb); sd_hwdb *sd_hwdb_unref(sd_hwdb *hwdb); int sd_hwdb_new(sd_hwdb **ret); +int sd_hwdb_new_from_path(const char *path, sd_hwdb **ret); int sd_hwdb_get(sd_hwdb *hwdb, const char *modalias, const char *key, const char **value); diff --git a/src/test/test-sd-hwdb.c b/src/test/test-sd-hwdb.c index 4251e2a809..8d08ea57af 100644 --- a/src/test/test-sd-hwdb.c +++ b/src/test/test-sd-hwdb.c @@ -5,6 +5,8 @@ #include "alloc-util.h" #include "errno-util.h" #include "errno.h" +#include "hwdb-internal.h" +#include "nulstr-util.h" #include "tests.h" TEST(failed_enumerate) { @@ -52,6 +54,24 @@ TEST(basic_enumerate) { assert_se(len1 == len2); } +TEST(sd_hwdb_new_from_path) { + _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL; + const char *hwdb_bin_path = NULL; + int r; + + assert_se(sd_hwdb_new_from_path(NULL, &hwdb) == -EINVAL); + assert_se(sd_hwdb_new_from_path("", &hwdb) == -EINVAL); + assert_se(sd_hwdb_new_from_path("/path/that/should/not/exist", &hwdb) < 0); + + NULSTR_FOREACH(hwdb_bin_path, hwdb_bin_paths) { + r = sd_hwdb_new_from_path(hwdb_bin_path, &hwdb); + if (r >= 0) + break; + } + + assert_se(r >= 0); +} + static int intro(void) { _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL; int r; diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c index 162b3516b8..972cda129d 100644 --- a/src/udev/udevadm-hwdb.c +++ b/src/udev/udevadm-hwdb.c @@ -95,7 +95,7 @@ int hwdb_main(int argc, char *argv[], void *userdata) { } if (arg_test) - return hwdb_query(arg_test); + return hwdb_query(arg_test, NULL); return 0; }