Libinfo-517.200.9.tar.gz
[apple/libinfo.git] / lookup.subproj / ils.c
1 /*
2 * Copyright (c) 1999-2018 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include "libinfo_common.h"
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <mach/mach.h>
30 #include <servers/bootstrap.h>
31 #include <pthread.h>
32 #include <errno.h>
33 #include <notify.h>
34 #include <syslog.h>
35 #include <unistd.h>
36 #ifdef DEBUG
37 #include <asl.h>
38 #endif
39 #include <ils.h>
40
41 #define ILS_MAGIC_SIZE 8
42 #define ILS_MAGIC "ILSMAGIC"
43
44 /* GLOBAL */
45
46 #if __ARM_ARCH_7K__ || __ARM64_ARCH_8_32__
47 static const uint32_t align_32[] = { 0, 1, 2, 0, 4, 0, 0, 0, 8 };
48 #else
49 static const uint32_t align_32[] = { 0, 1, 2, 0, 4, 0, 0, 0, 4 };
50 #endif
51
52 static const uint32_t align_64[] = { 0, 1, 2, 0, 4, 0, 0, 0, 8 };
53
54 static uint32_t
55 padsize(size_t curr, size_t item, const uint32_t *align)
56 {
57 uint32_t na, diff;
58
59 if (item > 8) item = 8;
60
61 na = align[item];
62 if (na == 0) return 0;
63
64 diff = curr % na;
65 if (diff == 0) return 0;
66
67 return na - diff;
68 }
69
70 /*
71 * Create a structure using in-line memory (i.e. all one blob).
72 * This reduces malloc/free workload.
73 *
74 * Structure components may be strings, 1, 2, 4, or 8-byte values,
75 * lists of strings, or lists of 4, 8, or 16-byte values.
76 *
77 * Format keys:
78 * s NUL terminated string
79 * 1 1 byte value
80 * 2 2 byte value
81 * 4 4 byte value
82 * 8 8 byte value
83 * S 128 byte value (_SS_MAXSIZE for a sockaddr)
84 * L long (32 or 64 bits, depending on architecture)
85 * m mach_port_t
86 * * NULL-terminated list of strings
87 * a NULL-terminated list of 4-byte values
88 * b NULL-terminated list of 8-byte values
89 * c NULL-terminated list of 16-byte values
90 * @ length (4 bytes) and buffer (requires two parameters)
91 *
92 */
93 LIBINFO_EXPORT
94 void *
95 LI_ils_create(char *fmt, ...)
96 {
97 va_list ap;
98 char *arg, *f;
99 char **list;
100 void *hp, *dp, *lp, *ils;
101 uint8_t u8;
102 uint16_t u16;
103 uint32_t u32, i, pad;
104 uint64_t u64;
105 unsigned long l;
106 mach_port_t m;
107 socket_data_t sdata;
108 size_t memsize, hsize, csize, csizep1, csizep2, slen, largest;
109 const uint32_t *align;
110
111 if (fmt == NULL) return NULL;
112
113 largest = 0;
114 align = align_32;
115 if (sizeof(char *) == 8) align = align_64;
116
117 /* first pass: calculate size */
118 memsize = ILS_MAGIC_SIZE;
119 hsize = 0;
120
121 va_start(ap, fmt);
122
123 for (f = fmt; (*f) != '\0'; f++)
124 {
125 csize = 0;
126 slen = 0;
127
128 switch (*f)
129 {
130 case 's':
131 {
132 if (largest < sizeof(char *)) largest = sizeof(char *);
133
134 csize = sizeof(char *) + padsize(hsize, sizeof(char *), align);
135 arg = va_arg(ap, char *);
136 if (arg != NULL) slen = strlen(arg) + 1;
137
138 break;
139 }
140
141 case '1':
142 {
143 if (largest < 1) largest = 1;
144
145 csize = 1;
146 u8 = va_arg(ap, int);
147
148 break;
149 }
150
151 case '2':
152 {
153 if (largest < 2) largest = 2;
154
155 csize = 2 + padsize(hsize, 2, align);
156 u16 = va_arg(ap, int);
157
158 break;
159 }
160
161 case '4':
162 {
163 if (largest < 4) largest = 4;
164
165 csize = 4 + padsize(hsize, 4, align);
166 u32 = va_arg(ap, uint32_t);
167
168 break;
169 }
170
171 case '8':
172 {
173 if (largest < 8) largest = 8;
174
175 csize = 8 + padsize(hsize, 8, align);
176 u64 = va_arg(ap, uint64_t);
177
178 break;
179 }
180
181 case 'S':
182 {
183 if (largest < 128) largest = 128;
184
185 /* 4-byte-align since a socket_data_t is really just a buffer */
186 csize = 128 + padsize(hsize, 4, align);
187 sdata = va_arg(ap, socket_data_t);
188
189 break;
190 }
191
192 case 'L':
193 {
194 if (largest < sizeof(unsigned long)) largest = sizeof(unsigned long);
195
196 csize = sizeof(unsigned long) + padsize(hsize, sizeof(unsigned long), align);
197 l = va_arg(ap, unsigned long);
198
199 break;
200 }
201
202 case 'm':
203 {
204 if (largest < sizeof(mach_port_t)) largest = sizeof(mach_port_t);
205
206 csize = sizeof(mach_port_t) + padsize(hsize, sizeof(mach_port_t), align);
207 m = va_arg(ap, mach_port_t);
208
209 break;
210 }
211
212 case '*':
213 {
214 // NULL-terminated list of strings
215 if (largest < sizeof(char *)) largest = sizeof(char *);
216
217 csize = sizeof(char *) + padsize(hsize, sizeof(char *), align);
218 list = va_arg(ap, char **);
219 if (list != NULL)
220 {
221 for (i = 0; list[i] != NULL; i++)
222 {
223 slen += sizeof(char *);
224 slen += (strlen(list[i]) + 1);
225 }
226 }
227
228 // reserve space for the terminator
229 slen += sizeof(char *);
230
231 break;
232 }
233
234 case 'a':
235 {
236 /* NULL-terminated list of 4-byte values */
237 if (largest < sizeof(char *)) largest = sizeof(char *);
238
239 csize = sizeof(char *) + padsize(hsize, sizeof(char *), align);
240 list = va_arg(ap, char **);
241 if (list != NULL)
242 {
243 for (i = 0; list[i] != NULL; i++)
244 {
245 slen += sizeof(char *);
246 slen += 4;
247 }
248
249 slen += sizeof(char *);
250 }
251
252 break;
253 }
254
255 case 'b':
256 {
257 /* NULL-terminated list of 8-byte values */
258 if (largest < sizeof(char *)) largest = sizeof(char *);
259
260 csize = sizeof(char *) + padsize(hsize, sizeof(char *), align);
261 list = va_arg(ap, char **);
262 if (list != NULL)
263 {
264 for (i = 0; list[i] != NULL; i++)
265 {
266 slen += sizeof(char *);
267 slen += 8;
268 }
269
270 slen += sizeof(char *);
271 }
272
273 break;
274 }
275
276 case 'c':
277 {
278 /* NULL-terminated list of 16-byte values */
279 if (largest < sizeof(char *)) largest = sizeof(char *);
280
281 csize = sizeof(char *) + padsize(hsize, sizeof(char *), align);
282 list = va_arg(ap, char **);
283 if (list != NULL)
284 {
285 for (i = 0; list[i] != NULL; i++)
286 {
287 slen += sizeof(char *);
288 slen += 16;
289 }
290
291 slen += sizeof(char *);
292 }
293
294 break;
295 }
296
297 case '@':
298 {
299 if (largest < 4) largest = 4;
300 csizep1 = 4 + padsize(hsize, 4, align);
301 slen = va_arg(ap, uint32_t);
302
303 if (largest < sizeof(char *)) largest = sizeof(char *);
304 csizep2 = sizeof(char *) + padsize(hsize + csizep1, sizeof(char *), align);
305 arg = va_arg(ap, char *);
306
307 csize = csizep1 + csizep2;
308
309 break;
310 }
311
312 default: return NULL;
313 }
314
315 memsize += csize;
316 memsize += slen;
317 hsize += csize;
318 }
319
320 va_end(ap);
321
322 pad = padsize(hsize, largest, align);
323 memsize += pad;
324 hsize += pad;
325
326 ils = malloc(memsize);
327 if (ils == NULL)
328 {
329 errno = ENOMEM;
330 return NULL;
331 }
332
333 /* insert magic cookie */
334 dp = ils + hsize;
335 memcpy(dp, ILS_MAGIC, ILS_MAGIC_SIZE);
336 dp += ILS_MAGIC_SIZE;
337
338 hp = ils;
339 hsize = 0;
340
341 /* second pass: copy data */
342 va_start(ap, fmt);
343 for (f = fmt; (*f) != '\0'; f++)
344 {
345 switch (*f)
346 {
347 case 's':
348 {
349 pad = padsize(hsize, sizeof(char *), align);
350 if (pad != 0)
351 {
352 memset(hp, 0, pad);
353 hp += pad;
354 hsize += pad;
355 }
356
357 arg = va_arg(ap, char *);
358 if (arg == NULL)
359 {
360 memset(hp, 0, sizeof(char *));
361 }
362 else
363 {
364 memcpy(hp, &dp, sizeof(char *));
365 slen = strlen(arg) + 1;
366 memcpy(dp, arg, slen);
367 dp += slen;
368 }
369
370 hp += sizeof(char *);
371 hsize += sizeof(char *);
372
373 break;
374 }
375
376 case '1':
377 {
378 u8 = va_arg(ap, int);
379 memcpy(hp, &u8, sizeof(uint8_t));
380 hp += sizeof(uint8_t);
381
382 break;
383 }
384
385 case '2':
386 {
387 pad = padsize(hsize, 2, align);
388 if (pad != 0)
389 {
390 memset(hp, 0, pad);
391 hp += pad;
392 hsize += pad;
393 }
394
395 u16 = va_arg(ap, int);
396 memcpy(hp, &u16, sizeof(uint16_t));
397
398 hp += sizeof(uint16_t);
399 hsize += sizeof(uint16_t);
400
401 break;
402 }
403
404 case '4':
405 {
406 pad = padsize(hsize, 4, align);
407 if (pad != 0)
408 {
409 memset(hp, 0, pad);
410 hp += pad;
411 hsize += pad;
412 }
413
414 u32 = va_arg(ap, uint32_t);
415 memcpy(hp, &u32, sizeof(uint32_t));
416
417 hp += sizeof(uint32_t);
418 hsize += sizeof(uint32_t);
419
420 break;
421 }
422
423 case '8':
424 {
425 pad = padsize(hsize, 8, align);
426 if (pad != 0)
427 {
428 memset(hp, 0, pad);
429 hp += pad;
430 hsize += pad;
431 }
432
433 u64 = va_arg(ap, uint64_t);
434 memcpy(hp, &u64, sizeof(uint64_t));
435
436 hp += sizeof(uint64_t);
437 hsize += sizeof(uint64_t);
438
439 break;
440 }
441
442 case 'S':
443 {
444 pad = padsize(hsize, 4, align);
445 if (pad != 0)
446 {
447 memset(hp, 0, pad);
448 hp += pad;
449 hsize += pad;
450 }
451
452 sdata = va_arg(ap, socket_data_t);
453 memcpy(hp, (char *)(sdata.x), sizeof(socket_data_t));
454
455 hp += sizeof(socket_data_t);
456 hsize += sizeof(socket_data_t);
457
458 break;
459 }
460
461 case 'L':
462 {
463 pad = padsize(hsize, sizeof(unsigned long), align);
464 if (pad != 0)
465 {
466 memset(hp, 0, pad);
467 hp += pad;
468 hsize += pad;
469 }
470
471 l = va_arg(ap, unsigned long);
472 memcpy(hp, &l, sizeof(unsigned long));
473
474 hp += sizeof(unsigned long);
475 hsize += sizeof(unsigned long);
476
477 break;
478 }
479
480 case 'm':
481 {
482 pad = padsize(hsize, sizeof(mach_port_t), align);
483 if (pad != 0)
484 {
485 memset(hp, 0, pad);
486 hp += pad;
487 hsize += pad;
488 }
489
490 m = va_arg(ap, mach_port_t);
491 memcpy(hp, &m, sizeof(mach_port_t));
492
493 hp += sizeof(mach_port_t);
494 hsize += sizeof(mach_port_t);
495
496 break;
497 }
498
499 case '*':
500 {
501 pad = padsize(hsize, sizeof(char *), align);
502 if (pad != 0)
503 {
504 memset(hp, 0, pad);
505 hp += pad;
506 hsize += pad;
507 }
508
509 list = va_arg(ap, char **);
510
511 memcpy(hp, &dp, sizeof(char *));
512
513 for (i = 0; list && list[i] != NULL; i++);
514
515 lp = dp;
516 dp += ((i + 1) * sizeof(char *));
517
518 for (i = 0; list && list[i] != NULL; i++)
519 {
520 memcpy(lp, &dp, sizeof(char *));
521 lp += sizeof(char *);
522 slen = strlen(list[i]) + 1;
523 memcpy(dp, list[i], slen);
524 dp += slen;
525 }
526
527 memset(lp, 0, sizeof(char *));
528
529 hp += sizeof(char *);
530 hsize += sizeof(char *);
531
532 break;
533 }
534
535 case 'a':
536 {
537 pad = padsize(hsize, sizeof(char *), align);
538 if (pad != 0)
539 {
540 memset(hp, 0, pad);
541 hp += pad;
542 hsize += pad;
543 }
544
545 list = va_arg(ap, char **);
546
547 if (list == NULL)
548 {
549 memset(hp, 0, sizeof(char *));
550 }
551 else
552 {
553 memcpy(hp, &dp, sizeof(char *));
554
555 for (i = 0; list[i] != NULL; i++);
556
557 lp = dp;
558 dp += ((i + 1) * sizeof(char *));
559
560 for (i = 0; list[i] != NULL; i++)
561 {
562 memcpy(lp, &dp, sizeof(char *));
563 lp += sizeof(char *);
564 slen = 4;
565 memcpy(dp, list[i], slen);
566 dp += slen;
567 }
568
569 memset(lp, 0, sizeof(char *));
570 }
571
572 hp += sizeof(char *);
573 hsize += sizeof(char *);
574
575 break;
576 }
577
578 case 'b':
579 {
580 pad = padsize(hsize, sizeof(char *), align);
581 if (pad != 0)
582 {
583 memset(hp, 0, pad);
584 hp += pad;
585 hsize += pad;
586 }
587
588 list = va_arg(ap, char **);
589
590 if (list == NULL)
591 {
592 memset(hp, 0, sizeof(char *));
593 }
594 else
595 {
596 memcpy(hp, &dp, sizeof(char *));
597
598 for (i = 0; list[i] != NULL; i++);
599
600 lp = dp;
601 dp += ((i + 1) * sizeof(char *));
602
603 for (i = 0; list[i] != NULL; i++)
604 {
605 memcpy(lp, &dp, sizeof(char *));
606 lp += sizeof(char *);
607 slen = 8;
608 memcpy(dp, list[i], slen);
609 dp += slen;
610 }
611
612 memset(lp, 0, sizeof(char *));
613 }
614
615 hp += sizeof(char *);
616 hsize += sizeof(char *);
617
618 break;
619 }
620
621 case 'c':
622 {
623 pad = padsize(hsize, sizeof(char *), align);
624 if (pad != 0)
625 {
626 memset(hp, 0, pad);
627 hp += pad;
628 hsize += pad;
629 }
630
631 list = va_arg(ap, char **);
632
633 if (list == NULL)
634 {
635 memset(hp, 0, sizeof(char *));
636 }
637 else
638 {
639 memcpy(hp, &dp, sizeof(char *));
640
641 for (i = 0; list[i] != NULL; i++);
642
643 lp = dp;
644 dp += ((i + 1) * sizeof(char *));
645
646 for (i = 0; list[i] != NULL; i++)
647 {
648 memcpy(lp, &dp, sizeof(char *));
649 lp += sizeof(char *);
650 slen = 16;
651 memcpy(dp, list[i], slen);
652 dp += slen;
653 }
654
655 memset(lp, 0, sizeof(char *));
656 }
657
658 hp += sizeof(char *);
659 hsize += sizeof(char *);
660
661 break;
662 }
663
664 case '@':
665 {
666 pad = padsize(hsize, 4, align);
667 if (pad != 0)
668 {
669 memset(hp, 0, pad);
670 hp += pad;
671 hsize += pad;
672 }
673
674 slen = va_arg(ap, uint32_t);
675 memcpy(hp, &slen, sizeof(uint32_t));
676
677 hp += sizeof(uint32_t);
678 hsize += sizeof(uint32_t);
679
680 pad = padsize(hsize, sizeof(char *), align);
681 if (pad != 0)
682 {
683 memset(hp, 0, pad);
684 hp += pad;
685 hsize += pad;
686 }
687
688 arg = va_arg(ap, char *);
689 if (arg == NULL)
690 {
691 memset(hp, 0, sizeof(char *));
692 }
693 else
694 {
695 memcpy(hp, &dp, sizeof(char *));
696 memcpy(dp, arg, slen);
697 dp += slen;
698 }
699
700 hp += sizeof(char *);
701 hsize += sizeof(char *);
702 }
703 }
704 }
705
706 va_end(ap);
707
708 pad = padsize(hsize, largest, align);
709 if (pad > 0) memset(hp, 0, pad);
710
711 return ils;
712 }