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