xref: /trueos/lib/libxpc/xpc_type.c (revision cb2de5a914fb4eb8a09e3f16bd2d923437d9a368)
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 
33 struct _xpc_type_s {
34 };
35 
36 typedef const struct _xpc_type_s xt;
37 xt _xpc_type_array;
38 xt _xpc_type_bool;
39 xt _xpc_type_connection;
40 xt _xpc_type_data;
41 xt _xpc_type_date;
42 xt _xpc_type_dictionary;
43 xt _xpc_type_endpoint;
44 xt _xpc_type_null;
45 xt _xpc_type_error;
46 xt _xpc_type_fd;
47 xt _xpc_type_int64;
48 xt _xpc_type_uint64;
49 xt _xpc_type_shmem;
50 xt _xpc_type_string;
51 xt _xpc_type_uuid;
52 xt _xpc_type_double;
53 
54 
55 struct _xpc_bool_s {
56 };
57 
58 typedef const struct _xpc_bool_s xb;
59 
60 xb _xpc_bool_true;
61 xb _xpc_bool_false;
62 
63 static size_t xpc_data_hash(const uint8_t *data, size_t length);
64 
65 static xpc_type_t xpc_typemap[] = {
66 	NULL,
67 	XPC_TYPE_DICTIONARY,
68 	XPC_TYPE_ARRAY,
69 	XPC_TYPE_BOOL,
70 	XPC_TYPE_CONNECTION,
71 	XPC_TYPE_ENDPOINT,
72 	XPC_TYPE_NULL,
73 	NULL,
74 	XPC_TYPE_INT64,
75 	XPC_TYPE_UINT64,
76 	XPC_TYPE_DATE,
77 	XPC_TYPE_DATA,
78 	XPC_TYPE_STRING,
79 	XPC_TYPE_UUID,
80 	XPC_TYPE_FD,
81 	XPC_TYPE_SHMEM,
82 	XPC_TYPE_ERROR,
83 	XPC_TYPE_DOUBLE
84 };
85 
86 static const char *xpc_typestr[] = {
87 	"invalid",
88 	"dictionary",
89 	"array",
90 	"bool",
91 	"connection",
92 	"endpoint",
93 	"null",
94 	"invalid",
95 	"int64",
96 	"uint64",
97 	"date",
98 	"data",
99 	"string",
100 	"uuid",
101 	"fd",
102 	"shmem",
103 	"error",
104 	"double"
105 };
106 
107 __private_extern__ struct xpc_object *
_xpc_prim_create(int type,xpc_u value,size_t size)108 _xpc_prim_create(int type, xpc_u value, size_t size)
109 {
110 
111 	return (_xpc_prim_create_flags(type, value, size, 0));
112 }
113 
114 __private_extern__ struct xpc_object *
_xpc_prim_create_flags(int type,xpc_u value,size_t size,uint16_t flags)115 _xpc_prim_create_flags(int type, xpc_u value, size_t size, uint16_t flags)
116 {
117 	struct xpc_object *xo;
118 
119 	if ((xo = malloc(sizeof(*xo))) == NULL)
120 		return (NULL);
121 
122 	xo->xo_size = size;
123 	xo->xo_xpc_type = type;
124 	xo->xo_flags = flags;
125 	xo->xo_u = value;
126 	xo->xo_refcnt = 1;
127 	xo->xo_audit_token = NULL;
128 
129 	if (type == _XPC_TYPE_DICTIONARY)
130 		TAILQ_INIT(&xo->xo_dict);
131 
132 	if (type == _XPC_TYPE_ARRAY)
133 		TAILQ_INIT(&xo->xo_array);
134 
135 	return (xo);
136 }
137 
138 xpc_object_t
xpc_null_create(void)139 xpc_null_create(void)
140 {
141 	xpc_u val;
142 	return _xpc_prim_create(_XPC_TYPE_NULL, val, 0);
143 }
144 
145 xpc_object_t
xpc_bool_create(bool value)146 xpc_bool_create(bool value)
147 {
148 	xpc_u val;
149 
150 	val.b = value;
151 	return _xpc_prim_create(_XPC_TYPE_BOOL, val, 1);
152 }
153 
154 bool
xpc_bool_get_value(xpc_object_t xbool)155 xpc_bool_get_value(xpc_object_t xbool)
156 {
157 	struct xpc_object *xo;
158 
159 	xo = xbool;
160 	if (xo == NULL)
161 		return (0);
162 
163 	if (xo->xo_xpc_type == _XPC_TYPE_BOOL)
164 		return (xo->xo_bool);
165 
166 	return (false);
167 }
168 
169 xpc_object_t
xpc_int64_create(int64_t value)170 xpc_int64_create(int64_t value)
171 {
172 	xpc_u val;
173 
174 	val.i = value;
175 	return _xpc_prim_create(_XPC_TYPE_INT64, val, 1);
176 }
177 
178 int64_t
xpc_int64_get_value(xpc_object_t xint)179 xpc_int64_get_value(xpc_object_t xint)
180 {
181 	struct xpc_object *xo;
182 
183 	xo = xint;
184 	if (xo == NULL)
185 		return (0);
186 
187 	if (xo->xo_xpc_type == _XPC_TYPE_INT64)
188 		return (xo->xo_int);
189 
190 	return (0);
191 }
192 
193 xpc_object_t
xpc_uint64_create(uint64_t value)194 xpc_uint64_create(uint64_t value)
195 {
196 	xpc_u val;
197 
198 	val.ui = value;
199 	return _xpc_prim_create(_XPC_TYPE_UINT64, val, 1);
200 }
201 
202 uint64_t
xpc_uint64_get_value(xpc_object_t xuint)203 xpc_uint64_get_value(xpc_object_t xuint)
204 {
205 	struct xpc_object *xo;
206 
207 	xo = xuint;
208 	if (xo == NULL)
209 		return (0);
210 
211 	if (xo->xo_xpc_type == _XPC_TYPE_UINT64)
212 		return (xo->xo_uint);
213 
214 	return (0);
215 }
216 
217 xpc_object_t
xpc_double_create(double value)218 xpc_double_create(double value)
219 {
220 	xpc_u val;
221 
222 	val.d = value;
223 	return _xpc_prim_create(_XPC_TYPE_DOUBLE, val, 1);
224 }
225 
226 double
xpc_double_get_value(xpc_object_t xdouble)227 xpc_double_get_value(xpc_object_t xdouble)
228 {
229 	struct xpc_object *xo = xdouble;
230 
231 	if (xo->xo_xpc_type == _XPC_TYPE_DOUBLE)
232 		return (xo->xo_d);
233 
234 	return (0);
235 }
236 
237 xpc_object_t
xpc_date_create(int64_t interval)238 xpc_date_create(int64_t interval)
239 {
240 	xpc_u val;
241 
242 	val.i = interval;
243 	return _xpc_prim_create(_XPC_TYPE_DATE, val, 1);
244 }
245 
246 xpc_object_t
xpc_date_create_from_current(void)247 xpc_date_create_from_current(void)
248 {
249 
250 }
251 
252 int64_t
xpc_date_get_value(xpc_object_t xdate)253 xpc_date_get_value(xpc_object_t xdate)
254 {
255 	struct xpc_object *xo = xdate;
256 
257 	if (xo == NULL)
258 		return (0);
259 
260 	if (xo->xo_xpc_type == _XPC_TYPE_DATE)
261 		return (xo->xo_int);
262 
263 	return (0);
264 }
265 
266 xpc_object_t
xpc_data_create(const void * bytes,size_t length)267 xpc_data_create(const void *bytes, size_t length)
268 {
269 	xpc_u val;
270 
271 	val.ptr = (uintptr_t)bytes;
272 	return _xpc_prim_create(_XPC_TYPE_DATA, val, length);
273 }
274 
275 xpc_object_t
xpc_data_create_with_dispatch_data(dispatch_data_t ddata)276 xpc_data_create_with_dispatch_data(dispatch_data_t ddata)
277 {
278 
279 }
280 
281 size_t
xpc_data_get_length(xpc_object_t xdata)282 xpc_data_get_length(xpc_object_t xdata)
283 {
284 	struct xpc_object *xo = xdata;
285 
286 	if (xo == NULL)
287 		return (0);
288 
289 	if (xo->xo_xpc_type == _XPC_TYPE_DATA)
290 		return (xo->xo_size);
291 
292 	return (0);
293 }
294 
295 const void *
xpc_data_get_bytes_ptr(xpc_object_t xdata)296 xpc_data_get_bytes_ptr(xpc_object_t xdata)
297 {
298 	struct xpc_object *xo = xdata;
299 
300 	if (xo == NULL)
301 		return (NULL);
302 
303 	if (xo->xo_xpc_type == _XPC_TYPE_DATA)
304 		return (xo->xo_ptr);
305 
306 	return (0);
307 }
308 
309 size_t
xpc_data_get_bytes(xpc_object_t xdata,void * buffer,size_t off,size_t length)310 xpc_data_get_bytes(xpc_object_t xdata, void *buffer, size_t off, size_t length)
311 {
312 
313 	/* XXX */
314 	return (0);
315 }
316 
317 xpc_object_t
xpc_string_create(const char * string)318 xpc_string_create(const char *string)
319 {
320 	xpc_u val;
321 
322 	val.str = string;
323 	return _xpc_prim_create(_XPC_TYPE_STRING, val, strlen(string));
324 }
325 
326 xpc_object_t
xpc_string_create_with_format(const char * fmt,...)327 xpc_string_create_with_format(const char *fmt, ...)
328 {
329 	va_list ap;
330 	xpc_u val;
331 
332 	va_start(ap, fmt);
333 	vasprintf(&val.str, fmt, ap);
334 	va_end(ap);
335 	return _xpc_prim_create(_XPC_TYPE_STRING, val, strlen(val.str));
336 }
337 
338 xpc_object_t
xpc_string_create_with_format_and_arguments(const char * fmt,va_list ap)339 xpc_string_create_with_format_and_arguments(const char *fmt, va_list ap)
340 {
341 	xpc_u val;
342 
343 	vasprintf(&val.str, fmt, ap);
344 	return _xpc_prim_create(_XPC_TYPE_STRING, val, strlen(val.str));
345 }
346 
347 size_t
xpc_string_get_length(xpc_object_t xstring)348 xpc_string_get_length(xpc_object_t xstring)
349 {
350 	struct xpc_object *xo = xstring;
351 
352 	if (xo == NULL)
353 		return (0);
354 
355 	if (xo->xo_xpc_type == _XPC_TYPE_STRING)
356 		return (xo->xo_size);
357 
358 	return (0);
359 }
360 
361 const char *
xpc_string_get_string_ptr(xpc_object_t xstring)362 xpc_string_get_string_ptr(xpc_object_t xstring)
363 {
364 	struct xpc_object *xo = xstring;
365 
366 	if (xo == NULL)
367 		return (NULL);
368 
369 	if (xo->xo_xpc_type == _XPC_TYPE_STRING)
370 		return (xo->xo_str);
371 
372 	return (NULL);
373 }
374 
375 xpc_object_t
xpc_uuid_create(const uuid_t uuid)376 xpc_uuid_create(const uuid_t uuid)
377 {
378 	xpc_u val;
379 
380 	memcpy(val.uuid, uuid, sizeof(uuid_t));
381 	return _xpc_prim_create(_XPC_TYPE_UUID, val, 1);
382 }
383 
384 const uint8_t *
xpc_uuid_get_bytes(xpc_object_t xuuid)385 xpc_uuid_get_bytes(xpc_object_t xuuid)
386 {
387 	struct xpc_object *xo;
388 
389 	xo = xuuid;
390 	if (xo == NULL)
391 		return (NULL);
392 
393 	if (xo->xo_xpc_type == _XPC_TYPE_UUID)
394 		return ((uint8_t*)&xo->xo_uuid);
395 
396 	return (NULL);
397 }
398 
399 xpc_type_t
xpc_get_type(xpc_object_t obj)400 xpc_get_type(xpc_object_t obj)
401 {
402 	struct xpc_object *xo;
403 
404 	xo = obj;
405 	return (xpc_typemap[xo->xo_xpc_type]);
406 }
407 
408 bool
xpc_equal(xpc_object_t x1,xpc_object_t x2)409 xpc_equal(xpc_object_t x1, xpc_object_t x2)
410 {
411 	struct xpc_object *xo1, *xo2;
412 
413 	xo1 = x1;
414 	xo2 = x2;
415 }
416 
417 static size_t
xpc_data_hash(const uint8_t * data,size_t length)418 xpc_data_hash(const uint8_t *data, size_t length)
419 {
420     size_t hash = 5381;
421 
422     while (length--)
423         hash = ((hash << 5) + hash) + data[length];
424 
425     return (hash);
426 }
427 
428 size_t
xpc_hash(xpc_object_t obj)429 xpc_hash(xpc_object_t obj)
430 {
431 	struct xpc_object *xo;
432 	__block size_t hash = 0;
433 
434 	xo = obj;
435 	switch (xo->xo_xpc_type) {
436 	case _XPC_TYPE_BOOL:
437 	case _XPC_TYPE_INT64:
438 	case _XPC_TYPE_UINT64:
439 	case _XPC_TYPE_DATE:
440 	case _XPC_TYPE_ENDPOINT:
441 		return ((size_t)xo->xo_u.ui);
442 
443 	case _XPC_TYPE_STRING:
444 		return (xpc_data_hash(
445 		    xpc_string_get_string_ptr(obj),
446 		    xpc_string_get_length(obj)));
447 
448 	case _XPC_TYPE_DATA:
449 		return (xpc_data_hash(
450 		    xpc_data_get_bytes_ptr(obj),
451 		    xpc_data_get_length(obj)));
452 
453 	case _XPC_TYPE_DICTIONARY:
454 		xpc_dictionary_apply(obj, ^(const char *k, xpc_object_t v) {
455 			hash ^= xpc_data_hash(k, strlen(k));
456 			hash ^= xpc_hash(v);
457 			return ((bool)true);
458 		});
459 		return (hash);
460 
461 	case _XPC_TYPE_ARRAY:
462 		xpc_array_apply(obj, ^(size_t idx, xpc_object_t v) {
463 			hash ^= xpc_hash(v);
464 			return ((bool)true);
465 		});
466 		return (hash);
467 	}
468 }
469 
470 __private_extern__ const char *
_xpc_get_type_name(xpc_object_t obj)471 _xpc_get_type_name(xpc_object_t obj)
472 {
473 	struct xpc_object *xo;
474 
475 	xo = obj;
476 	return (xpc_typestr[xo->xo_xpc_type]);
477 }