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