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