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 }