summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorrofl0r <retnyg@gmx.net>2013-08-16 06:55:15 +0200
committerAnthony G. Basile <blueness@gentoo.org>2014-01-20 12:50:44 -0500
commitf2f5958148016b8f92085d2e98fcf94efce508bf (patch)
tree072429befc5055802cbfb766825e46dcbb2c1c60 /src
parent57721ae2d0252db5fadfaa7790998c76496d1cfb (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>
Diffstat (limited to 'src')
-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 65ea866f4d..1026a7a66d 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;
}