]> git.ozlabs.org Git - petitboot/blob - lib/talloc/talloc.c
discover/grub2: Allow to separate the --id argument using a space char
[petitboot] / lib / talloc / talloc.c
1 /*
2    Samba Unix SMB/CIFS implementation.
3
4    Samba trivial allocation library - new interface
5
6    NOTE: Please read talloc_guide.txt for full documentation
7
8    Copyright (C) Andrew Tridgell 2004
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 /*
26   inspired by http://swapped.cc/halloc/
27 */
28
29 #if defined(HAVE_CONFIG_H)
30 #include "config.h"
31 #else
32 /* nfsim additions */
33 #define HAVE_SYS_TYPES_H
34 #define HAVE_UNISTD_H
35 #define HAVE_STDARG_H
36 #define HAVE_STDINT_H
37 #define HAVE_VA_COPY
38 #endif
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <assert.h>
44
45 #ifdef HAVE_SYS_TYPES_H
46 #include <sys/types.h>
47 #endif
48
49 #ifdef HAVE_UNISTD_H
50 #include <unistd.h>
51 #endif
52
53 #ifdef HAVE_STDARG_H
54 #include <stdarg.h>
55 #else
56 #include <varargs.h>
57 #endif
58
59 #ifdef HAVE_STDINT_H
60 #include <stdint.h>
61 #endif
62
63 #include "log/log.h"
64 #include "talloc.h"
65
66 /* use this to force every realloc to change the pointer, to stress test
67    code that might not cope */
68 #define ALWAYS_REALLOC 0
69
70
71 #define MAX_TALLOC_SIZE 0x10000000
72 #define TALLOC_MAGIC 0xe814ec4f
73 #define TALLOC_MAGIC_FREE 0x7faebef3
74 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
75
76 #ifndef discard_const_p
77 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
78 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
79 #else
80 # define discard_const_p(type, ptr) ((type *)(ptr))
81 #endif
82 #endif
83
84 /* this null_context is only used if talloc_enable_leak_report() or
85    talloc_enable_leak_report_full() is called, otherwise it remains
86    NULL
87 */
88 static const void *null_context;
89 static void *cleanup_context;
90
91
92 struct talloc_reference_handle {
93         struct talloc_reference_handle *next, *prev;
94         void *ptr;
95 };
96
97 typedef int (*talloc_destructor_t)(void *);
98
99 struct talloc_chunk {
100         struct talloc_chunk *next, *prev;
101         struct talloc_chunk *parent, *child;
102         struct talloc_reference_handle *refs;
103         size_t size;
104         talloc_destructor_t destructor;
105         const char *name;
106         union {
107                 unsigned magic;
108                 double align_dummy;
109         } u;
110 };
111
112 /* panic if we get a bad magic value */
113 static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
114 {
115         struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1;
116         if (tc->u.magic != TALLOC_MAGIC) {
117                 if (tc->u.magic == TALLOC_MAGIC_FREE) {
118                         pb_log_fn("Failed: Bad talloc magic value - double free, for name: %s\n",
119                                 tc->name);
120                         fprintf(stderr, "%s: name: %s\n", __func__, tc->name);
121                         fflush(stderr);
122                         assert(0 && "Bad talloc magic value - double free");
123                 } else {
124                         pb_log_fn("Failed: Bad talloc magic value - unknown value\n");
125                         assert(0 && "Bad talloc magic value - unknown value");
126                 }
127                 abort();
128         }
129
130         return tc;
131 }
132
133 /* hook into the front of the list */
134 #define _TLIST_ADD(list, p) \
135 do { \
136         if (!(list)) { \
137                 (list) = (p); \
138                 (p)->next = (p)->prev = NULL; \
139         } else { \
140                 (list)->prev = (p); \
141                 (p)->next = (list); \
142                 (p)->prev = NULL; \
143                 (list) = (p); \
144         }\
145 } while (0)
146
147 /* remove an element from a list - element doesn't have to be in list. */
148 #define _TLIST_REMOVE(list, p) \
149 do { \
150         if ((p) == (list)) { \
151                 (list) = (p)->next; \
152                 if (list) (list)->prev = NULL; \
153         } else { \
154                 if ((p)->prev) (p)->prev->next = (p)->next; \
155                 if ((p)->next) (p)->next->prev = (p)->prev; \
156         } \
157         if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
158 } while (0)
159
160
161 /*
162   return the parent chunk of a pointer
163 */
164 static struct talloc_chunk *talloc_parent_chunk(const void *ptr)
165 {
166         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
167         while (tc->prev) tc=tc->prev;
168         return tc->parent;
169 }
170
171 void *talloc_parent(const void *ptr)
172 {
173         struct talloc_chunk *tc = talloc_parent_chunk(ptr);
174         return (void *)(tc+1);
175 }
176
177 /*
178    Allocate a bit of memory as a child of an existing pointer
179 */
180 void *_talloc(const void *context, size_t size)
181 {
182         struct talloc_chunk *tc;
183
184         if (context == NULL) {
185                 context = null_context;
186         }
187
188         if (size >= MAX_TALLOC_SIZE) {
189                 return NULL;
190         }
191
192         tc = malloc(sizeof(*tc)+size);
193         if (tc == NULL) return NULL;
194
195         tc->size = size;
196         tc->u.magic = TALLOC_MAGIC;
197         tc->destructor = NULL;
198         tc->child = NULL;
199         tc->name = NULL;
200         tc->refs = NULL;
201
202         if (context) {
203                 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
204
205                 tc->parent = parent;
206
207                 if (parent->child) {
208                         parent->child->parent = NULL;
209                 }
210
211                 _TLIST_ADD(parent->child, tc);
212         } else {
213                 tc->next = tc->prev = tc->parent = NULL;
214         }
215
216         return (void *)(tc+1);
217 }
218
219
220 /*
221   setup a destructor to be called on free of a pointer
222   the destructor should return 0 on success, or -1 on failure.
223   if the destructor fails then the free is failed, and the memory can
224   be continued to be used
225 */
226 void talloc_set_destructor(const void *ptr, int (*destructor)(void *))
227 {
228         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
229         tc->destructor = destructor;
230 }
231
232 /*
233   increase the reference count on a piece of memory.
234 */
235 void talloc_increase_ref_count(const void *ptr)
236 {
237         talloc_reference(null_context, ptr);
238 }
239
240 /*
241   helper for talloc_reference()
242 */
243 static int talloc_reference_destructor(void *ptr)
244 {
245         struct talloc_reference_handle *handle = ptr;
246         struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr);
247         struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr);
248         if (tc1->destructor != (talloc_destructor_t)-1) {
249                 tc1->destructor = NULL;
250         }
251         _TLIST_REMOVE(tc2->refs, handle);
252         talloc_free(handle);
253         return 0;
254 }
255
256 /*
257   make a secondary reference to a pointer, hanging off the given context.
258   the pointer remains valid until both the original caller and this given
259   context are freed.
260
261   the major use for this is when two different structures need to reference the
262   same underlying data, and you want to be able to free the two instances
263   separately, and in either order
264 */
265 void *talloc_reference(const void *context, const void *ptr)
266 {
267         struct talloc_chunk *tc;
268         struct talloc_reference_handle *handle;
269         if (ptr == NULL) return NULL;
270
271         tc = talloc_chunk_from_ptr(ptr);
272         handle = talloc_named_const(context, sizeof(*handle),
273                         TALLOC_MAGIC_REFERENCE);
274
275         if (handle == NULL) return NULL;
276
277         /* note that we hang the destructor off the handle, not the
278            main context as that allows the caller to still setup their
279            own destructor on the context if they want to */
280         talloc_set_destructor(handle, talloc_reference_destructor);
281         handle->ptr = discard_const_p(void, ptr);
282         _TLIST_ADD(tc->refs, handle);
283         return handle->ptr;
284 }
285
286 /*
287   remove a secondary reference to a pointer. This undo's what
288   talloc_reference() has done. The context and pointer arguments
289   must match those given to a talloc_reference()
290 */
291 static int talloc_unreference(const void *context, const void *ptr)
292 {
293         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
294         struct talloc_reference_handle *h;
295
296         if (context == NULL) {
297                 context = null_context;
298         }
299
300         for (h=tc->refs;h;h=h->next) {
301                 struct talloc_chunk *p = talloc_parent_chunk(h);
302                 if ((p==NULL && context==NULL) || p+1 == context) break;
303         }
304         if (h == NULL) {
305                 return -1;
306         }
307
308         talloc_set_destructor(h, NULL);
309         _TLIST_REMOVE(tc->refs, h);
310         talloc_free(h);
311         return 0;
312 }
313
314 /*
315   remove a specific parent context from a pointer. This is a more
316   controlled varient of talloc_free()
317 */
318 int talloc_unlink(const void *context, void *ptr)
319 {
320         struct talloc_chunk *tc_p, *new_p;
321         void *new_parent;
322
323         if (ptr == NULL) {
324                 return -1;
325         }
326
327         if (context == NULL) {
328                 context = null_context;
329         }
330
331         if (talloc_unreference(context, ptr) == 0) {
332                 return 0;
333         }
334
335         if (context == NULL) {
336                 if (talloc_parent_chunk(ptr) != NULL) {
337                         return -1;
338                 }
339         } else {
340                 if (talloc_chunk_from_ptr(context)
341                                 != talloc_parent_chunk(ptr)) {
342                         return -1;
343                 }
344         }
345
346         tc_p = talloc_chunk_from_ptr(ptr);
347
348         if (tc_p->refs == NULL) {
349                 return talloc_free(ptr);
350         }
351
352         new_p = talloc_parent_chunk(tc_p->refs);
353         if (new_p) {
354                 new_parent = new_p+1;
355         } else {
356                 new_parent = NULL;
357         }
358
359         if (talloc_unreference(new_parent, ptr) != 0) {
360                 return -1;
361         }
362
363         talloc_steal(new_parent, ptr);
364
365         return 0;
366 }
367
368 /*
369   add a name to an existing pointer - va_list version
370 */
371 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
372         PRINTF_ATTRIBUTE(2,0);
373
374 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
375 {
376         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
377         tc->name = talloc_vasprintf(ptr, fmt, ap);
378         if (tc->name) {
379                 talloc_set_name_const(tc->name, ".name");
380         }
381 }
382
383 /*
384   add a name to an existing pointer
385 */
386 void talloc_set_name(const void *ptr, const char *fmt, ...)
387 {
388         va_list ap;
389         va_start(ap, fmt);
390         talloc_set_name_v(ptr, fmt, ap);
391         va_end(ap);
392 }
393
394 /*
395    more efficient way to add a name to a pointer - the name must point to a
396    true string constant
397 */
398 void talloc_set_name_const(const void *ptr, const char *name)
399 {
400         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
401         tc->name = name;
402 }
403
404 /*
405   create a named talloc pointer. Any talloc pointer can be named, and
406   talloc_named() operates just like talloc() except that it allows you
407   to name the pointer.
408 */
409 void *talloc_named(const void *context, size_t size, const char *fmt, ...)
410 {
411         va_list ap;
412         void *ptr;
413
414         ptr = _talloc(context, size);
415         if (ptr == NULL) return NULL;
416
417         va_start(ap, fmt);
418         talloc_set_name_v(ptr, fmt, ap);
419         va_end(ap);
420
421         return ptr;
422 }
423
424 /*
425   create a named talloc pointer. Any talloc pointer can be named, and
426   talloc_named() operates just like talloc() except that it allows you
427   to name the pointer.
428 */
429 void *talloc_named_const(const void *context, size_t size, const char *name)
430 {
431         void *ptr;
432
433         ptr = _talloc(context, size);
434         if (ptr == NULL) {
435                 return NULL;
436         }
437
438         talloc_set_name_const(ptr, name);
439
440         return ptr;
441 }
442
443 /*
444   return the name of a talloc ptr, or "UNNAMED"
445 */
446 const char *talloc_get_name(const void *ptr)
447 {
448         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
449         if (tc->name == TALLOC_MAGIC_REFERENCE) {
450                 return ".reference";
451         }
452         if (tc->name) {
453                 return tc->name;
454         }
455         return "UNNAMED";
456 }
457
458
459 /*
460   check if a pointer has the given name. If it does, return the pointer,
461   otherwise return NULL
462 */
463 void *talloc_check_name(const void *ptr, const char *name)
464 {
465         const char *pname;
466         if (ptr == NULL) return NULL;
467         pname = talloc_get_name(ptr);
468         if (pname == name || strcmp(pname, name) == 0) {
469                 return discard_const_p(void, ptr);
470         }
471         return NULL;
472 }
473
474
475 /*
476   this is for compatibility with older versions of talloc
477 */
478 void *talloc_init(const char *fmt, ...)
479 {
480         va_list ap;
481         void *ptr;
482
483         ptr = _talloc(NULL, 0);
484         if (ptr == NULL) return NULL;
485
486         va_start(ap, fmt);
487         talloc_set_name_v(ptr, fmt, ap);
488         va_end(ap);
489
490         return ptr;
491 }
492
493 /*
494   this is a replacement for the Samba3 talloc_destroy_pool functionality. It
495   should probably not be used in new code. It's in here to keep the talloc
496   code consistent across Samba 3 and 4.
497 */
498 static void talloc_free_children(void *ptr)
499 {
500         struct talloc_chunk *tc;
501
502         if (ptr == NULL) {
503                 return;
504         }
505
506         tc = talloc_chunk_from_ptr(ptr);
507
508         while (tc->child) {
509                 /* we need to work out who will own an abandoned child
510                    if it cannot be freed. In priority order, the first
511                    choice is owner of any remaining reference to this
512                    pointer, the second choice is our parent, and the
513                    final choice is the null context. */
514                 void *child = tc->child+1;
515                 const void *new_parent = null_context;
516                 if (tc->child->refs) {
517                         struct talloc_chunk *p =
518                                 talloc_parent_chunk(tc->child->refs);
519                         if (p) new_parent = p+1;
520                 }
521                 if (talloc_free(child) == -1) {
522                         if (new_parent == null_context) {
523                                 struct talloc_chunk *p =
524                                         talloc_parent_chunk(ptr);
525                                 if (p) new_parent = p+1;
526                         }
527                         talloc_steal(new_parent, child);
528                 }
529         }
530 }
531
532 /*
533    free a talloc pointer. This also frees all child pointers of this
534    pointer recursively
535
536    return 0 if the memory is actually freed, otherwise -1. The memory
537    will not be freed if the ref_count is > 1 or the destructor (if
538    any) returns non-zero
539 */
540 int talloc_free(void *ptr)
541 {
542         struct talloc_chunk *tc;
543
544         if (ptr == NULL) {
545                 return -1;
546         }
547
548         tc = talloc_chunk_from_ptr(ptr);
549
550         if (tc->refs) {
551                 talloc_reference_destructor(tc->refs);
552                 return -1;
553         }
554
555         if (tc->destructor) {
556                 talloc_destructor_t d = tc->destructor;
557                 if (d == (talloc_destructor_t)-1) {
558                         return -1;
559                 }
560                 tc->destructor = (talloc_destructor_t)-1;
561                 if (d(ptr) == -1) {
562                         tc->destructor = d;
563                         return -1;
564                 }
565                 tc->destructor = NULL;
566         }
567
568         talloc_free_children(ptr);
569
570         if (tc->parent) {
571                 _TLIST_REMOVE(tc->parent->child, tc);
572                 if (tc->parent->child) {
573                         tc->parent->child->parent = tc->parent;
574                 }
575         } else {
576                 if (tc->prev) tc->prev->next = tc->next;
577                 if (tc->next) tc->next->prev = tc->prev;
578         }
579
580         tc->u.magic = TALLOC_MAGIC_FREE;
581
582         free(tc);
583         return 0;
584 }
585
586
587
588 /*
589   A talloc version of realloc. The context argument is only used if
590   ptr is NULL
591 */
592 void *_talloc_realloc(const void *context, void *ptr, size_t size,
593                 const char *name)
594 {
595         struct talloc_chunk *tc;
596         void *new_ptr;
597
598         /* size zero is equivalent to free() */
599         if (size == 0) {
600                 talloc_free(ptr);
601                 return NULL;
602         }
603
604         if (size >= MAX_TALLOC_SIZE) {
605                 return NULL;
606         }
607
608         /* realloc(NULL) is equavalent to malloc() */
609         if (ptr == NULL) {
610                 return talloc_named_const(context, size, name);
611         }
612
613         tc = talloc_chunk_from_ptr(ptr);
614
615         /* don't allow realloc on referenced pointers */
616         if (tc->refs) {
617                 return NULL;
618         }
619
620         /* by resetting magic we catch users of the old memory */
621         tc->u.magic = TALLOC_MAGIC_FREE;
622
623 #if ALWAYS_REALLOC
624         new_ptr = malloc(size + sizeof(*tc));
625         if (new_ptr) {
626                 memcpy(new_ptr, tc, tc->size + sizeof(*tc));
627                 free(tc);
628         }
629 #else
630         new_ptr = realloc(tc, size + sizeof(*tc));
631 #endif
632         if (!new_ptr) {
633                 tc->u.magic = TALLOC_MAGIC;
634                 return NULL;
635         }
636
637         tc = new_ptr;
638         tc->u.magic = TALLOC_MAGIC;
639         if (tc->parent) {
640                 tc->parent->child = new_ptr;
641         }
642         if (tc->child) {
643                 tc->child->parent = new_ptr;
644         }
645
646         if (tc->prev) {
647                 tc->prev->next = tc;
648         }
649         if (tc->next) {
650                 tc->next->prev = tc;
651         }
652
653         tc->size = size;
654         talloc_set_name_const(tc+1, name);
655
656         return (void *)(tc+1);
657 }
658
659 /*
660    move a lump of memory from one talloc context to another return the
661    ptr on success, or NULL if it could not be transferred.
662    passing NULL as ptr will always return NULL with no side effects.
663 */
664 void *talloc_steal(const void *new_ctx, const void *ptr)
665 {
666         struct talloc_chunk *tc, *new_tc;
667
668         if (!ptr) {
669                 return NULL;
670         }
671
672         if (new_ctx == NULL) {
673                 new_ctx = null_context;
674         }
675
676         tc = talloc_chunk_from_ptr(ptr);
677
678         if (new_ctx == NULL) {
679                 if (tc->parent) {
680                         _TLIST_REMOVE(tc->parent->child, tc);
681                         if (tc->parent->child) {
682                                 tc->parent->child->parent = tc->parent;
683                         }
684                 } else {
685                         if (tc->prev) tc->prev->next = tc->next;
686                         if (tc->next) tc->next->prev = tc->prev;
687                 }
688
689                 tc->parent = tc->next = tc->prev = NULL;
690                 return discard_const_p(void, ptr);
691         }
692
693         new_tc = talloc_chunk_from_ptr(new_ctx);
694
695         if (tc == new_tc) {
696                 return discard_const_p(void, ptr);
697         }
698
699         if (tc->parent) {
700                 _TLIST_REMOVE(tc->parent->child, tc);
701                 if (tc->parent->child) {
702                         tc->parent->child->parent = tc->parent;
703                 }
704         } else {
705                 if (tc->prev) tc->prev->next = tc->next;
706                 if (tc->next) tc->next->prev = tc->prev;
707         }
708
709         tc->parent = new_tc;
710         if (new_tc->child) new_tc->child->parent = NULL;
711         _TLIST_ADD(new_tc->child, tc);
712
713         return discard_const_p(void, ptr);
714 }
715
716 /*
717   return the total size of a talloc pool (subtree)
718 */
719 off_t talloc_total_size(const void *ptr)
720 {
721         off_t total = 0;
722         struct talloc_chunk *c, *tc;
723
724         if (ptr == NULL) {
725                 ptr = null_context;
726         }
727         if (ptr == NULL) {
728                 return 0;
729         }
730
731         tc = talloc_chunk_from_ptr(ptr);
732
733         total = tc->size;
734         for (c=tc->child;c;c=c->next) {
735                 total += talloc_total_size(c+1);
736         }
737         return total;
738 }
739
740 /*
741   return the total number of blocks in a talloc pool (subtree)
742 */
743 off_t talloc_total_blocks(const void *ptr)
744 {
745         off_t total = 0;
746         struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
747
748         total++;
749         for (c=tc->child;c;c=c->next) {
750                 total += talloc_total_blocks(c+1);
751         }
752         return total;
753 }
754
755 /*
756   return the number of external references to a pointer
757 */
758 int talloc_reference_count(const void *ptr)
759 {
760         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
761         struct talloc_reference_handle *h;
762         int ret = 0;
763
764         for (h=tc->refs;h;h=h->next) {
765                 ret++;
766         }
767         return ret;
768 }
769
770 /*
771   report on memory usage by all children of a pointer, giving a full tree view
772 */
773 void talloc_report_depth(const void *ptr, FILE *f, int depth)
774 {
775         struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
776
777         for (c=tc->child;c;c=c->next) {
778                 if (c->name == TALLOC_MAGIC_REFERENCE) {
779                         struct talloc_reference_handle *handle = (void *)(c+1);
780                         const char *name2 = talloc_get_name(handle->ptr);
781                         fprintf(f, "%*sreference to: %s\n", depth*4, "", name2);
782                 } else {
783                         const char *name = talloc_get_name(c+1);
784                         fprintf(f, "%*s%-30s contains %6lu bytes "
785                                         "in %3lu blocks (ref %d)\n",
786                                 depth * 4, "", name,
787                                 (unsigned long)talloc_total_size(c+1),
788                                 (unsigned long)talloc_total_blocks(c+1),
789                                 talloc_reference_count(c+1));
790                         talloc_report_depth(c+1, f, depth+1);
791                 }
792         }
793
794 }
795
796 /*
797   report on memory usage by all children of a pointer, giving a full tree view
798 */
799 void talloc_report_full(const void *ptr, FILE *f)
800 {
801         if (ptr == NULL) {
802                 ptr = null_context;
803         }
804         if (ptr == NULL) return;
805
806         fprintf(f, "full talloc report on '%s' "
807                         "(total %lu bytes in %lu blocks)\n",
808                 talloc_get_name(ptr),
809                 (unsigned long)talloc_total_size(ptr),
810                 (unsigned long)talloc_total_blocks(ptr));
811
812         talloc_report_depth(ptr, f, 1);
813         fflush(f);
814 }
815
816 /*
817   report on memory usage by all children of a pointer
818 */
819 void talloc_report(const void *ptr, FILE *f)
820 {
821         struct talloc_chunk *c, *tc;
822
823         if (ptr == NULL) {
824                 ptr = null_context;
825         }
826         if (ptr == NULL) return;
827
828         fprintf(f, "talloc report on '%s' (total %lu bytes in %lu blocks)\n",
829                 talloc_get_name(ptr),
830                 (unsigned long)talloc_total_size(ptr),
831                 (unsigned long)talloc_total_blocks(ptr));
832
833         tc = talloc_chunk_from_ptr(ptr);
834
835         for (c=tc->child;c;c=c->next) {
836                 fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n",
837                         talloc_get_name(c+1),
838                         (unsigned long)talloc_total_size(c+1),
839                         (unsigned long)talloc_total_blocks(c+1));
840         }
841         fflush(f);
842 }
843
844 /*
845   report on any memory hanging off the null context
846 */
847 static void talloc_report_null(void)
848 {
849         if (talloc_total_size(null_context) != 0) {
850                 talloc_report(null_context, stderr);
851         }
852 }
853
854 /*
855   report on any memory hanging off the null context
856 */
857 static void talloc_report_null_full(void)
858 {
859         if (talloc_total_size(null_context) != 0) {
860                 talloc_report_full(null_context, stderr);
861         }
862 }
863
864 /*
865   enable tracking of the NULL context
866 */
867 void talloc_enable_null_tracking(void)
868 {
869         if (null_context == NULL) {
870                 null_context = talloc_named_const(NULL, 0, "null_context");
871         }
872 }
873
874 /*
875   enable leak reporting on exit
876 */
877 void talloc_enable_leak_report(void)
878 {
879         talloc_enable_null_tracking();
880         atexit(talloc_report_null);
881 }
882
883 /*
884   enable full leak reporting on exit
885 */
886 void talloc_enable_leak_report_full(void)
887 {
888         talloc_enable_null_tracking();
889         atexit(talloc_report_null_full);
890 }
891
892 /*
893    talloc and zero memory.
894 */
895 void *_talloc_zero(const void *ctx, size_t size, const char *name)
896 {
897         void *p = talloc_named_const(ctx, size, name);
898
899         if (p) {
900                 memset(p, '\0', size);
901         }
902
903         return p;
904 }
905
906
907 /*
908   memdup with a talloc.
909 */
910 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
911 {
912         void *newp = talloc_named_const(t, size, name);
913
914         if (newp) {
915                 memcpy(newp, p, size);
916         }
917
918         return newp;
919 }
920
921 /*
922   strdup with a talloc
923 */
924 char *talloc_strdup(const void *t, const char *p)
925 {
926         char *ret;
927         if (!p) {
928                 return NULL;
929         }
930         ret = talloc_memdup(t, p, strlen(p) + 1);
931         if (ret) {
932                 talloc_set_name_const(ret, ret);
933         }
934         return ret;
935 }
936
937 /*
938   strndup with a talloc
939 */
940 char *talloc_strndup(const void *t, const char *p, size_t n)
941 {
942         size_t len;
943         char *ret;
944
945         for (len=0; len<n && p[len]; len++) ;
946
947         ret = _talloc(t, len + 1);
948         if (!ret) { return NULL; }
949         memcpy(ret, p, len);
950         ret[len] = 0;
951         talloc_set_name_const(ret, ret);
952         return ret;
953 }
954
955 #ifndef VA_COPY
956 #ifdef HAVE_VA_COPY
957 #define VA_COPY(dest, src) va_copy(dest, src)
958 #elif defined(HAVE___VA_COPY)
959 #define VA_COPY(dest, src) __va_copy(dest, src)
960 #else
961 #define VA_COPY(dest, src) (dest) = (src)
962 #endif
963 #endif
964
965 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
966 {
967         int len;
968         char *ret;
969         va_list ap2;
970
971         VA_COPY(ap2, ap);
972
973         len = vsnprintf(NULL, 0, fmt, ap2);
974
975         ret = _talloc(t, len+1);
976         if (ret) {
977                 VA_COPY(ap2, ap);
978                 vsnprintf(ret, len+1, fmt, ap2);
979                 talloc_set_name_const(ret, ret);
980         }
981
982         va_end(ap2);
983         return ret;
984 }
985
986
987 /*
988   Perform string formatting, and return a pointer to newly allocated
989   memory holding the result, inside a memory pool.
990  */
991 char *talloc_asprintf(const void *t, const char *fmt, ...)
992 {
993         va_list ap;
994         char *ret;
995
996         va_start(ap, fmt);
997         ret = talloc_vasprintf(t, fmt, ap);
998         va_end(ap);
999         return ret;
1000 }
1001
1002
1003 /**
1004  * Realloc @p s to append the formatted result of @p fmt and @p ap,
1005  * and return @p s, which may have moved.  Good for gradually
1006  * accumulating output into a string buffer.
1007  **/
1008
1009 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1010         PRINTF_ATTRIBUTE(2,0);
1011
1012 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1013 {
1014         struct talloc_chunk *tc;
1015         int len, s_len;
1016         va_list ap2;
1017
1018         if (s == NULL) {
1019                 return talloc_vasprintf(NULL, fmt, ap);
1020         }
1021
1022         tc = talloc_chunk_from_ptr(s);
1023
1024         VA_COPY(ap2, ap);
1025
1026         s_len = tc->size - 1;
1027         len = vsnprintf(NULL, 0, fmt, ap2);
1028
1029         s = talloc_realloc(NULL, s, char, s_len + len+1);
1030         if (!s)
1031                 goto out;
1032
1033         VA_COPY(ap2, ap);
1034
1035         vsnprintf(s+s_len, len+1, fmt, ap2);
1036         talloc_set_name_const(s, s);
1037
1038 out:
1039         va_end(ap2);
1040         return s;
1041 }
1042
1043 /*
1044   Realloc @p s to append the formatted result of @p fmt and return @p
1045   s, which may have moved.  Good for gradually accumulating output
1046   into a string buffer.
1047  */
1048 char *talloc_asprintf_append(char *s, const char *fmt, ...)
1049 {
1050         va_list ap;
1051
1052         va_start(ap, fmt);
1053         s = talloc_vasprintf_append(s, fmt, ap);
1054         va_end(ap);
1055         return s;
1056 }
1057
1058 /*
1059   alloc an array, checking for integer overflow in the array size
1060 */
1061 void *_talloc_array(const void *ctx, size_t el_size, unsigned count,
1062                 const char *name)
1063 {
1064         if (count >= MAX_TALLOC_SIZE/el_size) {
1065                 return NULL;
1066         }
1067         return talloc_named_const(ctx, el_size * count, name);
1068 }
1069
1070 /*
1071   alloc an zero array, checking for integer overflow in the array size
1072 */
1073 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count,
1074                 const char *name)
1075 {
1076         if (count >= MAX_TALLOC_SIZE/el_size) {
1077                 return NULL;
1078         }
1079         return _talloc_zero(ctx, el_size * count, name);
1080 }
1081
1082
1083 /*
1084   realloc an array, checking for integer overflow in the array size
1085 */
1086 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size,
1087                 unsigned count, const char *name)
1088 {
1089         if (count >= MAX_TALLOC_SIZE/el_size) {
1090                 return NULL;
1091         }
1092         return _talloc_realloc(ctx, ptr, el_size * count, name);
1093 }
1094
1095 /*
1096   a function version of talloc_realloc(), so it can be passed as a function
1097   pointer to libraries that want a realloc function (a realloc function
1098   encapsulates all the basic capabilities of an allocation library, which is
1099   why this is useful)
1100 */
1101 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1102 {
1103         return _talloc_realloc(context, ptr, size, NULL);
1104 }
1105
1106
1107 static void talloc_autofree(void)
1108 {
1109         talloc_free(cleanup_context);
1110         cleanup_context = NULL;
1111 }
1112
1113 /*
1114   return a context which will be auto-freed on exit
1115   this is useful for reducing the noise in leak reports
1116 */
1117 void *talloc_autofree_context(void)
1118 {
1119         if (cleanup_context == NULL) {
1120                 cleanup_context = talloc_named_const(NULL, 0,
1121                                 "autofree_context");
1122                 atexit(talloc_autofree);
1123         }
1124         return cleanup_context;
1125 }
1126
1127 size_t talloc_get_size(const void *context)
1128 {
1129         struct talloc_chunk *tc;
1130
1131         if (context == NULL)
1132                 return 0;
1133
1134         tc = talloc_chunk_from_ptr(context);
1135
1136         return tc->size;
1137 }