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