]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/bus-map-properties.c
json: add helpers for dealing with id128 + strv
[thirdparty/systemd.git] / src / shared / bus-map-properties.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include "bus-map-properties.h"
4 #include "alloc-util.h"
5 #include "strv.h"
6 #include "bus-message.h"
7
8 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
9 sd_id128_t *p = userdata;
10 const void *v;
11 size_t n;
12 int r;
13
14 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
15 if (r < 0)
16 return r;
17
18 if (n == 0)
19 *p = SD_ID128_NULL;
20 else if (n == 16)
21 memcpy((*p).bytes, v, n);
22 else
23 return -EINVAL;
24
25 return 0;
26 }
27
28 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, unsigned flags, sd_bus_error *error, void *userdata) {
29 char type;
30 int r;
31
32 r = sd_bus_message_peek_type(m, &type, NULL);
33 if (r < 0)
34 return r;
35
36 switch (type) {
37
38 case SD_BUS_TYPE_STRING:
39 case SD_BUS_TYPE_OBJECT_PATH: {
40 const char **p = userdata;
41 const char *s;
42
43 r = sd_bus_message_read_basic(m, type, &s);
44 if (r < 0)
45 return r;
46
47 if (isempty(s))
48 s = NULL;
49
50 if (flags & BUS_MAP_STRDUP)
51 return free_and_strdup((char **) userdata, s);
52
53 *p = s;
54 return 0;
55 }
56
57 case SD_BUS_TYPE_ARRAY: {
58 _cleanup_strv_free_ char **l = NULL;
59 char ***p = userdata;
60
61 r = bus_message_read_strv_extend(m, &l);
62 if (r < 0)
63 return r;
64
65 return strv_extend_strv(p, l, false);
66 }
67
68 case SD_BUS_TYPE_BOOLEAN: {
69 int b;
70
71 r = sd_bus_message_read_basic(m, type, &b);
72 if (r < 0)
73 return r;
74
75 if (flags & BUS_MAP_BOOLEAN_AS_BOOL)
76 *(bool*) userdata = b;
77 else
78 *(int*) userdata = b;
79
80 return 0;
81 }
82
83 case SD_BUS_TYPE_INT32:
84 case SD_BUS_TYPE_UINT32: {
85 uint32_t u, *p = userdata;
86
87 r = sd_bus_message_read_basic(m, type, &u);
88 if (r < 0)
89 return r;
90
91 *p = u;
92 return 0;
93 }
94
95 case SD_BUS_TYPE_INT64:
96 case SD_BUS_TYPE_UINT64: {
97 uint64_t t, *p = userdata;
98
99 r = sd_bus_message_read_basic(m, type, &t);
100 if (r < 0)
101 return r;
102
103 *p = t;
104 return 0;
105 }
106
107 case SD_BUS_TYPE_DOUBLE: {
108 double d, *p = userdata;
109
110 r = sd_bus_message_read_basic(m, type, &d);
111 if (r < 0)
112 return r;
113
114 *p = d;
115 return 0;
116 }}
117
118 return -EOPNOTSUPP;
119 }
120
121 int bus_message_map_all_properties(
122 sd_bus_message *m,
123 const struct bus_properties_map *map,
124 unsigned flags,
125 sd_bus_error *error,
126 void *userdata) {
127
128 int r;
129
130 assert(m);
131 assert(map);
132
133 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
134 if (r < 0)
135 return r;
136
137 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
138 const struct bus_properties_map *prop;
139 const char *member;
140 const char *contents;
141 void *v;
142 unsigned i;
143
144 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
145 if (r < 0)
146 return r;
147
148 for (i = 0, prop = NULL; map[i].member; i++)
149 if (streq(map[i].member, member)) {
150 prop = &map[i];
151 break;
152 }
153
154 if (prop) {
155 r = sd_bus_message_peek_type(m, NULL, &contents);
156 if (r < 0)
157 return r;
158
159 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
160 if (r < 0)
161 return r;
162
163 v = (uint8_t *)userdata + prop->offset;
164 if (map[i].set)
165 r = prop->set(sd_bus_message_get_bus(m), member, m, error, v);
166 else
167 r = map_basic(sd_bus_message_get_bus(m), member, m, flags, error, v);
168 if (r < 0)
169 return r;
170
171 r = sd_bus_message_exit_container(m);
172 if (r < 0)
173 return r;
174 } else {
175 r = sd_bus_message_skip(m, "v");
176 if (r < 0)
177 return r;
178 }
179
180 r = sd_bus_message_exit_container(m);
181 if (r < 0)
182 return r;
183 }
184 if (r < 0)
185 return r;
186
187 return sd_bus_message_exit_container(m);
188 }
189
190 int bus_map_all_properties(
191 sd_bus *bus,
192 const char *destination,
193 const char *path,
194 const struct bus_properties_map *map,
195 unsigned flags,
196 sd_bus_error *error,
197 sd_bus_message **reply,
198 void *userdata) {
199
200 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
201 int r;
202
203 assert(bus);
204 assert(destination);
205 assert(path);
206 assert(map);
207 assert(reply || (flags & BUS_MAP_STRDUP));
208
209 r = sd_bus_call_method(
210 bus,
211 destination,
212 path,
213 "org.freedesktop.DBus.Properties",
214 "GetAll",
215 error,
216 &m,
217 "s", "");
218 if (r < 0)
219 return r;
220
221 r = bus_message_map_all_properties(m, map, flags, error, userdata);
222 if (r < 0)
223 return r;
224
225 if (reply)
226 *reply = sd_bus_message_ref(m);
227
228 return r;
229 }