diff options
author | rofl0r <retnyg@gmx.net> | 2013-08-16 06:55:15 +0200 |
---|---|---|
committer | Anthony G. Basile <blueness@gentoo.org> | 2013-08-16 18:26:01 -0400 |
commit | d5e3a2466f627f177aead0275b9da01d300f26bf (patch) | |
tree | a2eabec2c8591fd655300d802a7b6e664f4d18cd | |
parent | cc860bb8c2f94d48e135d2d5c8680cf29a0ef75e (diff) |
udev/udevadm-hwdb.c: remove usage of qsort_r
while theoretically a nice interface, qsort_r on GLIBC was
implemented with a prototype that shuffles the argument order
around when compared to the traditional BSD implementations,
yielding in 2 separate incompatible implementations.
even worse, the arguments are all of pointer type so one would
not even notice that the order is wrong and so this would yield
in crashes or silent memory corruption.
thus musl does not implement it, because configure scripts would
check for its existance and use it unconditionally, even when
assuming the BSD version.
a more portable solution is to use TLS via __thread, which any
modern GCC should provide. (even 3.4.6 on x86/x86_64 does so).
Signed-off-by: Anthony G. Basile <blueness@gentoo.org>
-rw-r--r-- | src/udev/udevadm-hwdb.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c index 68a285905f..34e34b1e10 100644 --- a/src/udev/udevadm-hwdb.c +++ b/src/udev/udevadm-hwdb.c @@ -123,14 +123,20 @@ static void trie_node_cleanup(struct trie_node *node) { free(node); } -static int trie_values_cmp(const void *v1, const void *v2, void *arg) { + +static __thread void* trie_values_cmp_param; +static int trie_values_cmp(const void *v1, const void *v2) { const struct trie_value_entry *val1 = v1; const struct trie_value_entry *val2 = v2; - struct trie *trie = arg; + struct trie *trie = trie_values_cmp_param; return strcmp(trie->strings->buf + val1->key_off, trie->strings->buf + val2->key_off); } +static int trie_values_cmp_r(const void *v1, const void *v2, void* arg) { + trie_values_cmp_param = arg; + return trie_values_cmp(v1, v2); +} static int trie_node_add_value(struct trie *trie, struct trie_node *node, const char *key, const char *value) { @@ -150,7 +156,7 @@ static int trie_node_add_value(struct trie *trie, struct trie_node *node, .value_off = v, }; - val = xbsearch_r(&search, node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp, trie); + val = xbsearch_r(&search, node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp_r, trie); if (val) { /* replace existing earlier key with new value */ val->value_off = v; @@ -167,7 +173,8 @@ static int trie_node_add_value(struct trie *trie, struct trie_node *node, node->values[node->values_count].key_off = k; node->values[node->values_count].value_off = v; node->values_count++; - qsort_r(node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp, trie); + trie_values_cmp_param = trie; + qsort(node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp); return 0; } |