summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrofl0r <retnyg@gmx.net>2013-08-16 06:55:15 +0200
committerAnthony G. Basile <blueness@gentoo.org>2013-08-16 18:26:01 -0400
commitd5e3a2466f627f177aead0275b9da01d300f26bf (patch)
treea2eabec2c8591fd655300d802a7b6e664f4d18cd
parentcc860bb8c2f94d48e135d2d5c8680cf29a0ef75e (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.c15
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;
}