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