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