summaryrefslogtreecommitdiff
path: root/libnm-core/nm-json.c
blob: e709cb8eee99a40c5ce5a89ee5c73c3527b2607b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright 2017, 2018 Red Hat, Inc.
 */

#include "nm-default.h"

#define NM_JANSSON_C
#include "nm-json.h"

#include <dlfcn.h>

void *_nm_jansson_json_object_iter_value;
void *_nm_jansson_json_object_key_to_iter;
void *_nm_jansson_json_integer;
void *_nm_jansson_json_object_del;
void *_nm_jansson_json_array_get;
void *_nm_jansson_json_array_size;
void *_nm_jansson_json_array_append_new;
void *_nm_jansson_json_string;
void *_nm_jansson_json_object_iter_next;
void *_nm_jansson_json_loads;
void *_nm_jansson_json_dumps;
void *_nm_jansson_json_object_iter_key;
void *_nm_jansson_json_object;
void *_nm_jansson_json_object_get;
void *_nm_jansson_json_array;
void *_nm_jansson_json_false;
void *_nm_jansson_json_delete;
void *_nm_jansson_json_true;
void *_nm_jansson_json_object_size;
void *_nm_jansson_json_object_set_new;
void *_nm_jansson_json_object_iter;
void *_nm_jansson_json_integer_value;
void *_nm_jansson_json_string_value;

#define TRY_BIND_SYMBOL(symbol) \
	G_STMT_START { \
		void *sym = dlsym (handle, #symbol); \
		if (_nm_jansson_ ## symbol && sym != _nm_jansson_ ## symbol) \
			return FALSE; \
		_nm_jansson_ ## symbol = sym; \
	} G_STMT_END

static gboolean
bind_symbols (void *handle)
{
	TRY_BIND_SYMBOL (json_object_iter_value);
	TRY_BIND_SYMBOL (json_object_key_to_iter);
	TRY_BIND_SYMBOL (json_integer);
	TRY_BIND_SYMBOL (json_object_del);
	TRY_BIND_SYMBOL (json_array_get);
	TRY_BIND_SYMBOL (json_array_size);
	TRY_BIND_SYMBOL (json_array_append_new);
	TRY_BIND_SYMBOL (json_string);
	TRY_BIND_SYMBOL (json_object_iter_next);
	TRY_BIND_SYMBOL (json_loads);
	TRY_BIND_SYMBOL (json_dumps);
	TRY_BIND_SYMBOL (json_object_iter_key);
	TRY_BIND_SYMBOL (json_object);
	TRY_BIND_SYMBOL (json_object_get);
	TRY_BIND_SYMBOL (json_array);
	TRY_BIND_SYMBOL (json_false);
	TRY_BIND_SYMBOL (json_delete);
	TRY_BIND_SYMBOL (json_true);
	TRY_BIND_SYMBOL (json_object_size);
	TRY_BIND_SYMBOL (json_object_set_new);
	TRY_BIND_SYMBOL (json_object_iter);
	TRY_BIND_SYMBOL (json_integer_value);
	TRY_BIND_SYMBOL (json_string_value);

	return TRUE;
}

gboolean
nm_jansson_load (void)
{
	static enum {
		UNKNOWN,
		AVAILABLE,
		MISSING,
	} state = UNKNOWN;
	void *handle;
	int mode;

	if (G_LIKELY (state != UNKNOWN))
		goto out;

	/* First just resolve the symbols to see if there's a conflict already. */
	if (!bind_symbols (RTLD_DEFAULT))
		goto out;

	mode = RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE | RTLD_DEEPBIND;
#if defined (ASAN_BUILD)
	/* Address sanitizer is incompatible with RTLD_DEEPBIND. */
	mode &= ~RTLD_DEEPBIND;
#endif
	handle = dlopen (JANSSON_SONAME, mode);

	if (!handle)
		goto out;

	/* Now do the actual binding. */
	if (!bind_symbols (handle))
		goto out;

	state = AVAILABLE;
out:
	return state == AVAILABLE;
}