xref: /NextBSD/lib/libxpc/xpc_dictionary.c (revision 33da5adc555b3bc29986eeadca03829e4ad06b1e)
1 /*
2  * Copyright 2014-2015 iXsystems, Inc.
3  * All rights reserved
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted providing that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  * POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 
28 #include <sys/types.h>
29 #include <mach/mach.h>
30 #include <xpc/launchd.h>
31 #include "xpc_internal.h"
32 #include <assert.h>
33 
34 #define NVLIST_XPC_TYPE		"__XPC_TYPE"
35 
36 static void xpc2nv_primitive(nvlist_t *nv, const char *key, xpc_object_t value);
37 
38 __private_extern__ void
nv_release_entry(nvlist_t * nv,const char * key)39 nv_release_entry(nvlist_t *nv, const char *key)
40 {
41 	xpc_object_t tmp;
42 
43 	if (nvlist_exists_type(nv, key, NV_TYPE_PTR)) {
44 		tmp = (void *)nvlist_take_number(nv, key);
45 		xpc_release(tmp);
46 	}
47 }
48 
49 struct xpc_object *
nv2xpc(const nvlist_t * nv)50 nv2xpc(const nvlist_t *nv)
51 {
52 	struct xpc_object *xo, *xotmp;
53 	void *cookiep;
54 	const char *key;
55 	int type;
56 	xpc_u val;
57 	const nvlist_t *nvtmp;
58 
59 	assert(nvlist_type(nv) == NV_TYPE_NVLIST_DICTIONARY ||
60 	    nvlist_type(nv) == NV_TYPE_NVLIST_ARRAY);
61 
62 	if (nvlist_type(nv) == NV_TYPE_NVLIST_DICTIONARY)
63 		xo = xpc_dictionary_create(NULL, NULL, 0);
64 
65 	if (nvlist_type(nv) == NV_TYPE_NVLIST_ARRAY)
66 		xo = xpc_array_create(NULL, 0);
67 
68 	cookiep = NULL;
69 	while ((key = nvlist_next(nv, &type, &cookiep)) != NULL) {
70 		xotmp = NULL;
71 
72 		switch (type) {
73 		case NV_TYPE_BOOL:
74 			val.b = nvlist_get_bool(nv, key);
75 			xotmp = xpc_bool_create(val.b);
76 			break;
77 
78 		case NV_TYPE_STRING:
79 			val.str = nvlist_get_string(nv, key);
80 			xotmp = xpc_string_create(val.str);
81 			break;
82 
83 		case NV_TYPE_INT64:
84 			val.i = nvlist_get_int64(nv, key);
85 			xotmp = xpc_int64_create(val.i);
86 			break;
87 
88 		case NV_TYPE_UINT64:
89 			val.ui = nvlist_get_uint64(nv, key);
90 			xotmp = xpc_uint64_create(val.ui);
91 			break;
92 
93 		case NV_TYPE_DESCRIPTOR:
94 			val.fd = nvlist_get_descriptor(nv, key);
95 			xotmp = _xpc_prim_create(_XPC_TYPE_FD, val, 0);
96 			break;
97 
98 		case NV_TYPE_PTR:
99 			break;
100 
101 		case NV_TYPE_BINARY:
102 			break;
103 
104 		case NV_TYPE_UUID:
105 			memcpy(&val.uuid, nvlist_get_uuid(nv, key),
106 			    sizeof(uuid_t));
107 			xotmp = _xpc_prim_create(_XPC_TYPE_UUID, val, 0);
108 
109 		case NV_TYPE_NVLIST_ARRAY:
110 			nvtmp = nvlist_get_nvlist_array(nv, key);
111 			xotmp = nv2xpc(nvtmp);
112 			break;
113 
114 		case NV_TYPE_NVLIST_DICTIONARY:
115 			nvtmp = nvlist_get_nvlist_dictionary(nv, key);
116 			xotmp = nv2xpc(nvtmp);
117 			break;
118 		}
119 
120 		if (xotmp) {
121 			if (nvlist_type(nv) == NV_TYPE_NVLIST_DICTIONARY)
122 				xpc_dictionary_set_value(xo, key, xotmp);
123 
124 			if (nvlist_type(nv) == NV_TYPE_NVLIST_ARRAY)
125 				xpc_array_append_value(xo, xotmp);
126 		}
127 	}
128 
129 	return (xo);
130 }
131 
132 static void
xpc2nv_primitive(nvlist_t * nv,const char * key,xpc_object_t value)133 xpc2nv_primitive(nvlist_t *nv, const char *key, xpc_object_t value)
134 {
135 	struct xpc_object *xotmp = value;
136 
137 	switch (xotmp->xo_xpc_type) {
138 	case _XPC_TYPE_DICTIONARY:
139 		nvlist_add_nvlist_dictionary(nv, key, xpc2nv(xotmp));
140 		break;
141 
142 	case _XPC_TYPE_ARRAY:
143 		nvlist_add_nvlist_array(nv, key, xpc2nv(xotmp));
144 		break;
145 
146 	case _XPC_TYPE_BOOL:
147 		nvlist_add_bool(nv, key, xpc_bool_get_value(xotmp));
148 		break;
149 
150 	case _XPC_TYPE_CONNECTION:
151 		break;
152 
153 	case _XPC_TYPE_ENDPOINT:
154 		break;
155 
156 	case _XPC_TYPE_INT64:
157 		nvlist_add_int64(nv, key, xpc_int64_get_value(xotmp));
158 		break;
159 
160 	case _XPC_TYPE_UINT64:
161 		nvlist_add_uint64(nv, key,  xpc_uint64_get_value(xotmp));
162 		break;
163 
164 	case _XPC_TYPE_DATE:
165 		break;
166 
167 	case _XPC_TYPE_DATA:
168 		nvlist_add_binary(nv, key,
169 		    xpc_data_get_bytes_ptr(xotmp),
170 		    xpc_data_get_length(xotmp));
171 		break;
172 
173 	case _XPC_TYPE_STRING:
174 		nvlist_add_string(nv, key,
175 		    xpc_string_get_string_ptr(xotmp));
176 		break;
177 
178 	case _XPC_TYPE_UUID:
179 		nvlist_add_uuid(nv, key, (uuid_t*)xpc_uuid_get_bytes(xotmp));
180 		break;
181 
182 	case _XPC_TYPE_FD:
183 		nvlist_add_descriptor(nv, key, xotmp->xo_fd);
184 		break;
185 
186 	case _XPC_TYPE_SHMEM:
187 		break;
188 
189 	case _XPC_TYPE_ERROR:
190 		break;
191 
192 	case _XPC_TYPE_DOUBLE:
193 		break;
194 	}
195 }
196 
197 nvlist_t *
xpc2nv(struct xpc_object * xo)198 xpc2nv(struct xpc_object *xo)
199 {
200 	nvlist_t *nv;
201 	struct xpc_object *xotmp;
202 
203 	if (xo->xo_xpc_type == _XPC_TYPE_DICTIONARY) {
204 		nv = nvlist_create_dictionary(0);
205 		printf("nv = %p\n", nv);
206 		xpc_dictionary_apply(xo, ^(const char *k, xpc_object_t v) {
207 			xpc2nv_primitive(nv, k, v);
208 			return ((bool)true);
209 		});
210 	}
211 
212 	if (xo->xo_xpc_type == _XPC_TYPE_ARRAY) {
213 		char *key;
214 		nv = nvlist_create_array(0);
215 		xpc_array_apply(xo, ^(size_t index, xpc_object_t v) {
216 			asprintf(&key, "%ld", index);
217 			xpc2nv_primitive(nv, key, v);
218 			free(key);
219 			return ((bool)true);
220 		});
221 	}
222 
223 	return (nv);
224 }
225 
226 xpc_object_t
xpc_dictionary_create(const char * const * keys,const xpc_object_t * values,size_t count)227 xpc_dictionary_create(const char * const *keys, const xpc_object_t *values,
228     size_t count)
229 {
230 	struct xpc_object *xo;
231 	size_t i;
232 	xpc_u val;
233 
234 	xo = _xpc_prim_create(_XPC_TYPE_DICTIONARY, val, count);
235 
236 	for (i = 0; i < count; i++)
237 		xpc_dictionary_set_value(xo, keys[i], values[i]);
238 
239 	return (xo);
240 }
241 
242 xpc_object_t
xpc_dictionary_create_reply(xpc_object_t original)243 xpc_dictionary_create_reply(xpc_object_t original)
244 {
245 	struct xpc_object *xo, *xo_orig;
246 	nvlist_t *nv;
247 	xpc_u val;
248 
249 	xo_orig = original;
250 	if ((xo_orig->xo_flags & _XPC_FROM_WIRE) == 0)
251 		return (NULL);
252 
253 	return xpc_dictionary_create(NULL, NULL, 0);
254 }
255 
256 void
xpc_dictionary_get_audit_token(xpc_object_t xdict,audit_token_t * token)257 xpc_dictionary_get_audit_token(xpc_object_t xdict, audit_token_t *token)
258 {
259 	struct xpc_object *xo;
260 
261 	xo = xdict;
262 	if (xo->xo_audit_token != NULL)
263 		memcpy(token, xo->xo_audit_token, sizeof(*token));
264 }
265 void
xpc_dictionary_set_mach_recv(xpc_object_t xdict,const char * key,mach_port_t port)266 xpc_dictionary_set_mach_recv(xpc_object_t xdict, const char *key, mach_port_t port)
267 {
268 	struct xpc_object *xo = xdict;
269 	struct xpc_object *xotmp;
270 	xpc_u val;
271 
272 	val.port = port;
273 	xotmp = _xpc_prim_create(_XPC_TYPE_ENDPOINT, val, 0);
274 
275 	xpc_dictionary_set_value(xdict, key, xotmp);
276 }
277 
278 void
xpc_dictionary_set_mach_send(xpc_object_t xdict,const char * key,mach_port_t port)279 xpc_dictionary_set_mach_send(xpc_object_t xdict, const char *key, mach_port_t port)
280 {
281 	struct xpc_object *xotmp;
282 	xpc_u val;
283 
284 	val.port = port;
285 	xotmp = _xpc_prim_create(_XPC_TYPE_ENDPOINT, val, 0);
286 
287 	xpc_dictionary_set_value(xdict, key, xotmp);
288 }
289 
290 mach_port_t
xpc_dictionary_copy_mach_send(xpc_object_t xdict,const char * key)291 xpc_dictionary_copy_mach_send(xpc_object_t xdict, const char *key)
292 {
293 	struct xpc_object *xo;
294 	const struct xpc_object *xotmp;
295 
296 #if 0
297 	xo = xdict;
298 	if (nvlist_exists_type(xo->xo_nv, key, NV_TYPE_ENDPOINT))
299 		return (nvlist_get_number(xo->xo_nv, key));
300 	else if (nvlist_exists_binary(xo->xo_nv, key)) {
301 		xotmp = (void *)nvlist_get_number(xo->xo_nv, key);
302 		return (xotmp->xo_uint);
303 	}
304 	return (0);
305 #endif
306 }
307 
308 void
xpc_dictionary_set_value(xpc_object_t xdict,const char * key,xpc_object_t value)309 xpc_dictionary_set_value(xpc_object_t xdict, const char *key, xpc_object_t value)
310 {
311 	struct xpc_object *xo, *xotmp;
312 	struct xpc_dict_head *head;
313 	struct xpc_dict_pair *pair;
314 
315 	xo = xdict;
316 	head = &xo->xo_dict;
317 
318 	TAILQ_FOREACH(pair, head, xo_link) {
319 		if (!strcmp(pair->key, key)) {
320 			pair->value = value;
321 			return;
322 		}
323 	}
324 
325 	xo->xo_size++;
326 	pair = malloc(sizeof(struct xpc_dict_pair));
327 	pair->key = key;
328 	pair->value = value;
329 	TAILQ_INSERT_TAIL(&xo->xo_dict, pair, xo_link);
330 	xpc_retain(value);
331 }
332 
333 xpc_object_t
xpc_dictionary_get_value(xpc_object_t xdict,const char * key)334 xpc_dictionary_get_value(xpc_object_t xdict, const char *key)
335 {
336 	struct xpc_object *xo;
337 	struct xpc_dict_head *head;
338 	struct xpc_dict_pair *pair;
339 
340 	xo = xdict;
341 	head = &xo->xo_dict;
342 
343 	TAILQ_FOREACH(pair, head, xo_link) {
344 		if (!strcmp(pair->key, key))
345 			return (pair->value);
346 	}
347 
348 	return (NULL);
349 }
350 
351 size_t
xpc_dictionary_get_count(xpc_object_t xdict)352 xpc_dictionary_get_count(xpc_object_t xdict)
353 {
354 	struct xpc_object *xo;
355 
356 	xo = xdict;
357 	return (xo->xo_size);
358 }
359 
360 void
xpc_dictionary_set_bool(xpc_object_t xdict,const char * key,bool value)361 xpc_dictionary_set_bool(xpc_object_t xdict, const char *key, bool value)
362 {;
363 	struct xpc_object *xo, *xotmp;
364 
365 	xo = xdict;
366 	xotmp = xpc_bool_create(value);
367 	xpc_dictionary_set_value(xdict, key, xotmp);
368 }
369 
370 void
xpc_dictionary_set_int64(xpc_object_t xdict,const char * key,int64_t value)371 xpc_dictionary_set_int64(xpc_object_t xdict, const char *key, int64_t value)
372 {
373 	struct xpc_object *xo, *xotmp;
374 
375 	xo = xdict;
376 	xotmp = xpc_int64_create(value);
377 	xpc_dictionary_set_value(xdict, key, xotmp);
378 }
379 
380 void
xpc_dictionary_set_uint64(xpc_object_t xdict,const char * key,uint64_t value)381 xpc_dictionary_set_uint64(xpc_object_t xdict, const char *key, uint64_t value)
382 {
383 	struct xpc_object *xo, *xotmp;
384 
385 	xo = xdict;
386 	xotmp = xpc_uint64_create(value);
387 	xpc_dictionary_set_value(xdict, key, xotmp);
388 }
389 
390 void
xpc_dictionary_set_string(xpc_object_t xdict,const char * key,const char * value)391 xpc_dictionary_set_string(xpc_object_t xdict, const char *key, const char *value)
392 {
393 	struct xpc_object *xo, *xotmp;
394 
395 	xo = xdict;
396 	xotmp = xpc_string_create(value);
397 	xpc_dictionary_set_value(xdict, key, xotmp);
398 }
399 
400 bool
xpc_dictionary_get_bool(xpc_object_t xdict,const char * key)401 xpc_dictionary_get_bool(xpc_object_t xdict, const char *key)
402 {
403 	xpc_object_t xo;
404 
405 	xo = xpc_dictionary_get_value(xdict, key);
406 	return (xpc_bool_get_value(xo));
407 }
408 
409 int64_t
xpc_dictionary_get_int64(xpc_object_t xdict,const char * key)410 xpc_dictionary_get_int64(xpc_object_t xdict, const char *key)
411 {
412 	xpc_object_t xo;
413 
414 	xo = xpc_dictionary_get_value(xdict, key);
415 	return (xpc_int64_get_value(xo));
416 }
417 
418 uint64_t
xpc_dictionary_get_uint64(xpc_object_t xdict,const char * key)419 xpc_dictionary_get_uint64(xpc_object_t xdict, const char *key)
420 {
421 	xpc_object_t xo;
422 
423 	xo = xpc_dictionary_get_value(xdict, key);
424 	return (xpc_uint64_get_value(xo));
425 }
426 
427 const char *
xpc_dictionary_get_string(xpc_object_t xdict,const char * key)428 xpc_dictionary_get_string(xpc_object_t xdict, const char *key)
429 {
430 	xpc_object_t xo;
431 
432 	xo = xpc_dictionary_get_value(xdict, key);
433 	return (xpc_string_get_string_ptr(xo));
434 }
435 
436 bool
xpc_dictionary_apply(xpc_object_t xdict,xpc_dictionary_applier_t applier)437 xpc_dictionary_apply(xpc_object_t xdict, xpc_dictionary_applier_t applier)
438 {
439 	struct xpc_object *xo, *xotmp;
440 	struct xpc_dict_head *head;
441 	struct xpc_dict_pair *pair;
442 
443 	xo = xdict;
444 	head = &xo->xo_dict;
445 
446 	TAILQ_FOREACH(pair, head, xo_link) {
447 		if (!applier(pair->key, pair->value))
448 			return (false);
449 	}
450 
451 	return (true);
452 }
453