r17893: add a function to disable the null_context
[kamenim/samba.git] / source4 / 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      ** NOTE! The following LGPL license applies to the talloc
11      ** library. This does NOT imply that all of Samba is released
12      ** under the LGPL
13    
14    This library is free software; you can redistribute it and/or
15    modify it under the terms of the GNU Lesser General Public
16    License as published by the Free Software Foundation; either
17    version 2 of the License, or (at your option) any later version.
18
19    This library is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22    Lesser General Public License for more details.
23
24    You should have received a copy of the GNU Lesser General Public
25    License along with this library; if not, write to the Free Software
26    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27 */
28
29 /*
30   inspired by http://swapped.cc/halloc/
31 */
32
33 #include "config.h"
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <errno.h>
39 #ifdef HAVE_STDINT_H
40 #include <stdint.h>
41 #endif
42
43 #if defined(HAVE_STDARG_H)
44 #include <stdarg.h>
45 #elif defined (HAVE_VARARGS_H)
46 #include <varargs.h>
47 #else
48 #error "no var arg header"
49 #endif
50
51 #include "talloc.h"
52
53 /* use this to force every realloc to change the pointer, to stress test
54    code that might not cope */
55 #define ALWAYS_REALLOC 0
56
57
58 #define MAX_TALLOC_SIZE 0x10000000
59 #define TALLOC_MAGIC 0xe814ec70
60 #define TALLOC_FLAG_FREE 0x01
61 #define TALLOC_FLAG_LOOP 0x02
62 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
63
64 /* by default we abort when given a bad pointer (such as when talloc_free() is called 
65    on a pointer that came from malloc() */
66 #ifndef TALLOC_ABORT
67 #define TALLOC_ABORT(reason) abort()
68 #endif
69
70 #ifndef discard_const_p
71 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
72 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
73 #else
74 # define discard_const_p(type, ptr) ((type *)(ptr))
75 #endif
76 #endif
77
78 /* this null_context is only used if talloc_enable_leak_report() or
79    talloc_enable_leak_report_full() is called, otherwise it remains
80    NULL
81 */
82 static void *null_context;
83 static void *cleanup_context;
84
85 struct talloc_reference_handle {
86         struct talloc_reference_handle *next, *prev;
87         void *ptr;
88 };
89
90 typedef int (*talloc_destructor_t)(void *);
91
92 struct talloc_chunk {
93         struct talloc_chunk *next, *prev;
94         struct talloc_chunk *parent, *child;
95         struct talloc_reference_handle *refs;
96         talloc_destructor_t destructor;
97         const char *name;
98         size_t size;
99         unsigned flags;
100 };
101
102 /* 16 byte alignment seems to keep everyone happy */
103 #define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
104 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
105
106 /* panic if we get a bad magic value */
107 static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
108 {
109         const char *pp = (const char *)ptr;
110         struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
111         if ((tc->flags & ~0xF) != TALLOC_MAGIC) { 
112                 TALLOC_ABORT("Bad talloc magic value - unknown value"); 
113         }
114         if (tc->flags & TALLOC_FLAG_FREE) {
115                 TALLOC_ABORT("Bad talloc magic value - double free"); 
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 tc? TC_PTR_FROM_CHUNK(tc) : NULL;
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 = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size);
180         if (tc == NULL) return NULL;
181
182         tc->size = size;
183         tc->flags = 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 TC_PTR_FROM_CHUNK(tc);
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(struct talloc_reference_handle *handle)
231 {
232         struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
233         _TLIST_REMOVE(ptr_tc->refs, handle);
234         return 0;
235 }
236
237 /*
238   make a secondary reference to a pointer, hanging off the given context.
239   the pointer remains valid until both the original caller and this given
240   context are freed.
241   
242   the major use for this is when two different structures need to reference the 
243   same underlying data, and you want to be able to free the two instances separately,
244   and in either order
245 */
246 void *talloc_reference(const void *context, const void *ptr)
247 {
248         struct talloc_chunk *tc;
249         struct talloc_reference_handle *handle;
250         if (ptr == NULL) return NULL;
251
252         tc = talloc_chunk_from_ptr(ptr);
253         handle = (struct talloc_reference_handle *)talloc_named_const(context,
254                                                    sizeof(struct talloc_reference_handle),
255                                                    TALLOC_MAGIC_REFERENCE);
256         if (handle == NULL) return NULL;
257
258         /* note that we hang the destructor off the handle, not the
259            main context as that allows the caller to still setup their
260            own destructor on the context if they want to */
261         talloc_set_destructor(handle, talloc_reference_destructor);
262         handle->ptr = discard_const_p(void, ptr);
263         _TLIST_ADD(tc->refs, handle);
264         return handle->ptr;
265 }
266
267 /*
268   remove a secondary reference to a pointer. This undo's what
269   talloc_reference() has done. The context and pointer arguments
270   must match those given to a talloc_reference()
271 */
272 static int talloc_unreference(const void *context, const void *ptr)
273 {
274         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
275         struct talloc_reference_handle *h;
276
277         if (context == NULL) {
278                 context = null_context;
279         }
280
281         for (h=tc->refs;h;h=h->next) {
282                 struct talloc_chunk *p = talloc_parent_chunk(h);
283                 if (p == NULL) {
284                         if (context == NULL) break;
285                 } else if (TC_PTR_FROM_CHUNK(p) == context) {
286                         break;
287                 }
288         }
289         if (h == NULL) {
290                 return -1;
291         }
292
293         return talloc_free(h);
294 }
295
296 /*
297   remove a specific parent context from a pointer. This is a more
298   controlled varient of talloc_free()
299 */
300 int talloc_unlink(const void *context, void *ptr)
301 {
302         struct talloc_chunk *tc_p, *new_p;
303         void *new_parent;
304
305         if (ptr == NULL) {
306                 return -1;
307         }
308
309         if (context == NULL) {
310                 context = null_context;
311         }
312
313         if (talloc_unreference(context, ptr) == 0) {
314                 return 0;
315         }
316
317         if (context == NULL) {
318                 if (talloc_parent_chunk(ptr) != NULL) {
319                         return -1;
320                 }
321         } else {
322                 if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) {
323                         return -1;
324                 }
325         }
326         
327         tc_p = talloc_chunk_from_ptr(ptr);
328
329         if (tc_p->refs == NULL) {
330                 return talloc_free(ptr);
331         }
332
333         new_p = talloc_parent_chunk(tc_p->refs);
334         if (new_p) {
335                 new_parent = TC_PTR_FROM_CHUNK(new_p);
336         } else {
337                 new_parent = NULL;
338         }
339
340         if (talloc_unreference(new_parent, ptr) != 0) {
341                 return -1;
342         }
343
344         talloc_steal(new_parent, ptr);
345
346         return 0;
347 }
348
349 /*
350   add a name to an existing pointer - va_list version
351 */
352 static const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
353
354 static const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
355 {
356         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
357         tc->name = talloc_vasprintf(ptr, fmt, ap);
358         if (tc->name) {
359                 talloc_set_name_const(tc->name, ".name");
360         }
361         return tc->name;
362 }
363
364 /*
365   add a name to an existing pointer
366 */
367 const char *talloc_set_name(const void *ptr, const char *fmt, ...)
368 {
369         const char *name;
370         va_list ap;
371         va_start(ap, fmt);
372         name = talloc_set_name_v(ptr, fmt, ap);
373         va_end(ap);
374         return name;
375 }
376
377 /*
378    more efficient way to add a name to a pointer - the name must point to a 
379    true string constant
380 */
381 void talloc_set_name_const(const void *ptr, const char *name)
382 {
383         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
384         tc->name = name;
385 }
386
387 /*
388   create a named talloc pointer. Any talloc pointer can be named, and
389   talloc_named() operates just like talloc() except that it allows you
390   to name the pointer.
391 */
392 void *talloc_named(const void *context, size_t size, const char *fmt, ...)
393 {
394         va_list ap;
395         void *ptr;
396         const char *name;
397
398         ptr = _talloc(context, size);
399         if (ptr == NULL) return NULL;
400
401         va_start(ap, fmt);
402         name = talloc_set_name_v(ptr, fmt, ap);
403         va_end(ap);
404
405         if (name == NULL) {
406                 talloc_free(ptr);
407                 return NULL;
408         }
409
410         return ptr;
411 }
412
413 /*
414   create a named talloc pointer. Any talloc pointer can be named, and
415   talloc_named() operates just like talloc() except that it allows you
416   to name the pointer.
417 */
418 void *talloc_named_const(const void *context, size_t size, const char *name)
419 {
420         void *ptr;
421
422         ptr = _talloc(context, size);
423         if (ptr == NULL) {
424                 return NULL;
425         }
426
427         talloc_set_name_const(ptr, name);
428
429         return ptr;
430 }
431
432 /*
433   return the name of a talloc ptr, or "UNNAMED"
434 */
435 const char *talloc_get_name(const void *ptr)
436 {
437         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
438         if (tc->name == TALLOC_MAGIC_REFERENCE) {
439                 return ".reference";
440         }
441         if (tc->name) {
442                 return tc->name;
443         }
444         return "UNNAMED";
445 }
446
447
448 /*
449   check if a pointer has the given name. If it does, return the pointer,
450   otherwise return NULL
451 */
452 void *talloc_check_name(const void *ptr, const char *name)
453 {
454         const char *pname;
455         if (ptr == NULL) return NULL;
456         pname = talloc_get_name(ptr);
457         if (pname == name || strcmp(pname, name) == 0) {
458                 return discard_const_p(void, ptr);
459         }
460         return NULL;
461 }
462
463
464 /*
465   this is for compatibility with older versions of talloc
466 */
467 void *talloc_init(const char *fmt, ...)
468 {
469         va_list ap;
470         void *ptr;
471         const char *name;
472
473         ptr = _talloc(NULL, 0);
474         if (ptr == NULL) return NULL;
475
476         va_start(ap, fmt);
477         name = talloc_set_name_v(ptr, fmt, ap);
478         va_end(ap);
479
480         if (name == NULL) {
481                 talloc_free(ptr);
482                 return NULL;
483         }
484
485         return ptr;
486 }
487
488 /*
489   this is a replacement for the Samba3 talloc_destroy_pool functionality. It
490   should probably not be used in new code. It's in here to keep the talloc
491   code consistent across Samba 3 and 4.
492 */
493 void talloc_free_children(void *ptr)
494 {
495         struct talloc_chunk *tc;
496
497         if (ptr == NULL) {
498                 return;
499         }
500
501         tc = talloc_chunk_from_ptr(ptr);
502
503         while (tc->child) {
504                 /* we need to work out who will own an abandoned child
505                    if it cannot be freed. In priority order, the first
506                    choice is owner of any remaining reference to this
507                    pointer, the second choice is our parent, and the
508                    final choice is the null context. */
509                 void *child = TC_PTR_FROM_CHUNK(tc->child);
510                 const void *new_parent = null_context;
511                 if (tc->child->refs) {
512                         struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
513                         if (p) new_parent = TC_PTR_FROM_CHUNK(p);
514                 }
515                 if (talloc_free(child) == -1) {
516                         if (new_parent == null_context) {
517                                 struct talloc_chunk *p = talloc_parent_chunk(ptr);
518                                 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
519                         }
520                         talloc_steal(new_parent, child);
521                 }
522         }
523 }
524
525 /* 
526    free a talloc pointer. This also frees all child pointers of this 
527    pointer recursively
528
529    return 0 if the memory is actually freed, otherwise -1. The memory
530    will not be freed if the ref_count is > 1 or the destructor (if
531    any) returns non-zero
532 */
533 int talloc_free(void *ptr)
534 {
535         struct talloc_chunk *tc;
536         int old_errno;
537
538         if (ptr == NULL) {
539                 return -1;
540         }
541
542         tc = talloc_chunk_from_ptr(ptr);
543
544         if (tc->refs) {
545                 int is_child;
546                 /* check this is a reference from a child or grantchild
547                  * back to it's parent or grantparent
548                  *
549                  * in that case we need to remove the reference and
550                  * call another instance of talloc_free() on the current
551                  * pointer.
552                  */
553                 is_child = talloc_is_parent(tc->refs, ptr);
554                 talloc_free(tc->refs);
555                 if (is_child) {
556                         return talloc_free(ptr);
557                 }
558                 return -1;
559         }
560
561         if (tc->flags & TALLOC_FLAG_LOOP) {
562                 /* we have a free loop - stop looping */
563                 return 0;
564         }
565
566         if (tc->destructor) {
567                 talloc_destructor_t d = tc->destructor;
568                 if (d == (talloc_destructor_t)-1) {
569                         return -1;
570                 }
571                 tc->destructor = (talloc_destructor_t)-1;
572                 if (d(ptr) == -1) {
573                         tc->destructor = d;
574                         return -1;
575                 }
576                 tc->destructor = NULL;
577         }
578
579         if (tc->parent) {
580                 _TLIST_REMOVE(tc->parent->child, tc);
581                 if (tc->parent->child) {
582                         tc->parent->child->parent = tc->parent;
583                 }
584         } else {
585                 if (tc->prev) tc->prev->next = tc->next;
586                 if (tc->next) tc->next->prev = tc->prev;
587         }
588
589         tc->flags |= TALLOC_FLAG_LOOP;
590         talloc_free_children(ptr);
591
592         tc->flags |= TALLOC_FLAG_FREE;
593         old_errno = errno;
594         free(tc);
595         errno = old_errno;
596         return 0;
597 }
598
599
600
601 /*
602   A talloc version of realloc. The context argument is only used if
603   ptr is NULL
604 */
605 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
606 {
607         struct talloc_chunk *tc;
608         void *new_ptr;
609
610         /* size zero is equivalent to free() */
611         if (size == 0) {
612                 talloc_free(ptr);
613                 return NULL;
614         }
615
616         if (size >= MAX_TALLOC_SIZE) {
617                 return NULL;
618         }
619
620         /* realloc(NULL) is equavalent to malloc() */
621         if (ptr == NULL) {
622                 return talloc_named_const(context, size, name);
623         }
624
625         tc = talloc_chunk_from_ptr(ptr);
626
627         /* don't allow realloc on referenced pointers */
628         if (tc->refs) {
629                 return NULL;
630         }
631
632         /* by resetting magic we catch users of the old memory */
633         tc->flags |= TALLOC_FLAG_FREE;
634
635 #if ALWAYS_REALLOC
636         new_ptr = malloc(size + TC_HDR_SIZE);
637         if (new_ptr) {
638                 memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE);
639                 free(tc);
640         }
641 #else
642         new_ptr = realloc(tc, size + TC_HDR_SIZE);
643 #endif
644         if (!new_ptr) { 
645                 tc->flags &= ~TALLOC_FLAG_FREE; 
646                 return NULL; 
647         }
648
649         tc = (struct talloc_chunk *)new_ptr;
650         tc->flags &= ~TALLOC_FLAG_FREE; 
651         if (tc->parent) {
652                 tc->parent->child = tc;
653         }
654         if (tc->child) {
655                 tc->child->parent = tc;
656         }
657
658         if (tc->prev) {
659                 tc->prev->next = tc;
660         }
661         if (tc->next) {
662                 tc->next->prev = tc;
663         }
664
665         tc->size = size;
666         talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
667
668         return TC_PTR_FROM_CHUNK(tc);
669 }
670
671 /* 
672    move a lump of memory from one talloc context to another return the
673    ptr on success, or NULL if it could not be transferred.
674    passing NULL as ptr will always return NULL with no side effects.
675 */
676 void *_talloc_steal(const void *new_ctx, const void *ptr)
677 {
678         struct talloc_chunk *tc, *new_tc;
679
680         if (!ptr) {
681                 return NULL;
682         }
683
684         if (new_ctx == NULL) {
685                 new_ctx = null_context;
686         }
687
688         tc = talloc_chunk_from_ptr(ptr);
689
690         if (new_ctx == NULL) {
691                 if (tc->parent) {
692                         _TLIST_REMOVE(tc->parent->child, tc);
693                         if (tc->parent->child) {
694                                 tc->parent->child->parent = tc->parent;
695                         }
696                 } else {
697                         if (tc->prev) tc->prev->next = tc->next;
698                         if (tc->next) tc->next->prev = tc->prev;
699                 }
700                 
701                 tc->parent = tc->next = tc->prev = NULL;
702                 return discard_const_p(void, ptr);
703         }
704
705         new_tc = talloc_chunk_from_ptr(new_ctx);
706
707         if (tc == new_tc || tc->parent == new_tc) {
708                 return discard_const_p(void, ptr);
709         }
710
711         if (tc->parent) {
712                 _TLIST_REMOVE(tc->parent->child, tc);
713                 if (tc->parent->child) {
714                         tc->parent->child->parent = tc->parent;
715                 }
716         } else {
717                 if (tc->prev) tc->prev->next = tc->next;
718                 if (tc->next) tc->next->prev = tc->prev;
719         }
720
721         tc->parent = new_tc;
722         if (new_tc->child) new_tc->child->parent = NULL;
723         _TLIST_ADD(new_tc->child, tc);
724
725         return discard_const_p(void, ptr);
726 }
727
728 /*
729   return the total size of a talloc pool (subtree)
730 */
731 size_t talloc_total_size(const void *ptr)
732 {
733         size_t total = 0;
734         struct talloc_chunk *c, *tc;
735
736         if (ptr == NULL) {
737                 ptr = null_context;
738         }
739         if (ptr == NULL) {
740                 return 0;
741         }
742
743         tc = talloc_chunk_from_ptr(ptr);
744
745         if (tc->flags & TALLOC_FLAG_LOOP) {
746                 return 0;
747         }
748
749         tc->flags |= TALLOC_FLAG_LOOP;
750
751         total = tc->size;
752         for (c=tc->child;c;c=c->next) {
753                 total += talloc_total_size(TC_PTR_FROM_CHUNK(c));
754         }
755
756         tc->flags &= ~TALLOC_FLAG_LOOP;
757
758         return total;
759 }
760
761 /*
762   return the total number of blocks in a talloc pool (subtree)
763 */
764 size_t talloc_total_blocks(const void *ptr)
765 {
766         size_t total = 0;
767         struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
768
769         if (tc->flags & TALLOC_FLAG_LOOP) {
770                 return 0;
771         }
772
773         tc->flags |= TALLOC_FLAG_LOOP;
774
775         total++;
776         for (c=tc->child;c;c=c->next) {
777                 total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
778         }
779
780         tc->flags &= ~TALLOC_FLAG_LOOP;
781
782         return total;
783 }
784
785 /*
786   return the number of external references to a pointer
787 */
788 static int talloc_reference_count(const void *ptr)
789 {
790         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
791         struct talloc_reference_handle *h;
792         int ret = 0;
793
794         for (h=tc->refs;h;h=h->next) {
795                 ret++;
796         }
797         return ret;
798 }
799
800 /*
801   report on memory usage by all children of a pointer, giving a full tree view
802 */
803 void talloc_report_depth(const void *ptr, FILE *f, int depth)
804 {
805         struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
806
807         if (tc->flags & TALLOC_FLAG_LOOP) {
808                 return;
809         }
810
811         tc->flags |= TALLOC_FLAG_LOOP;
812
813         for (c=tc->child;c;c=c->next) {
814                 if (c->name == TALLOC_MAGIC_REFERENCE) {
815                         struct talloc_reference_handle *handle =
816                                 (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
817                         const char *name2 = talloc_get_name(handle->ptr);
818                         fprintf(f, "%*sreference to: %s\n", depth*4, "", name2);
819                 } else {
820                         const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c));
821                         fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", 
822                                 depth*4, "",
823                                 name,
824                                 (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
825                                 (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)),
826                                 talloc_reference_count(TC_PTR_FROM_CHUNK(c)));
827                         talloc_report_depth(TC_PTR_FROM_CHUNK(c), f, depth+1);
828                 }
829         }
830         tc->flags &= ~TALLOC_FLAG_LOOP;
831 }
832
833 /*
834   report on memory usage by all children of a pointer, giving a full tree view
835 */
836 void talloc_report_full(const void *ptr, FILE *f)
837 {
838         if (ptr == NULL) {
839                 ptr = null_context;
840         }
841         if (ptr == NULL) return;
842
843         fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n", 
844                 talloc_get_name(ptr), 
845                 (unsigned long)talloc_total_size(ptr),
846                 (unsigned long)talloc_total_blocks(ptr));
847
848         talloc_report_depth(ptr, f, 1);
849         fflush(f);
850 }
851
852 /*
853   report on memory usage by all children of a pointer
854 */
855 void talloc_report(const void *ptr, FILE *f)
856 {
857         struct talloc_chunk *c, *tc;
858
859         if (ptr == NULL) {
860                 ptr = null_context;
861         }
862         if (ptr == NULL) return;
863        
864         fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n", 
865                 talloc_get_name(ptr), 
866                 (unsigned long)talloc_total_size(ptr),
867                 (unsigned long)talloc_total_blocks(ptr));
868
869         tc = talloc_chunk_from_ptr(ptr);
870
871         for (c=tc->child;c;c=c->next) {
872                 fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n", 
873                         talloc_get_name(TC_PTR_FROM_CHUNK(c)),
874                         (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
875                         (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)));
876         }
877         fflush(f);
878 }
879
880 /*
881   report on any memory hanging off the null context
882 */
883 static void talloc_report_null(void)
884 {
885         if (talloc_total_size(null_context) != 0) {
886                 talloc_report(null_context, stderr);
887         }
888 }
889
890 /*
891   report on any memory hanging off the null context
892 */
893 static void talloc_report_null_full(void)
894 {
895         if (talloc_total_size(null_context) != 0) {
896                 talloc_report_full(null_context, stderr);
897         }
898 }
899
900 /*
901   enable tracking of the NULL context
902 */
903 void talloc_enable_null_tracking(void)
904 {
905         if (null_context == NULL) {
906                 null_context = talloc_named_const(NULL, 0, "null_context");
907         }
908 }
909
910 /*
911   disable tracking of the NULL context
912 */
913 void talloc_disable_null_tracking(void)
914 {
915         talloc_free(null_context);
916         null_context = NULL;
917 }
918
919 /*
920   enable leak reporting on exit
921 */
922 void talloc_enable_leak_report(void)
923 {
924         talloc_enable_null_tracking();
925         atexit(talloc_report_null);
926 }
927
928 /*
929   enable full leak reporting on exit
930 */
931 void talloc_enable_leak_report_full(void)
932 {
933         talloc_enable_null_tracking();
934         atexit(talloc_report_null_full);
935 }
936
937 /* 
938    talloc and zero memory. 
939 */
940 void *_talloc_zero(const void *ctx, size_t size, const char *name)
941 {
942         void *p = talloc_named_const(ctx, size, name);
943
944         if (p) {
945                 memset(p, '\0', size);
946         }
947
948         return p;
949 }
950
951
952 /*
953   memdup with a talloc. 
954 */
955 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
956 {
957         void *newp = talloc_named_const(t, size, name);
958
959         if (newp) {
960                 memcpy(newp, p, size);
961         }
962
963         return newp;
964 }
965
966 /*
967   strdup with a talloc 
968 */
969 char *talloc_strdup(const void *t, const char *p)
970 {
971         char *ret;
972         if (!p) {
973                 return NULL;
974         }
975         ret = (char *)talloc_memdup(t, p, strlen(p) + 1);
976         if (ret) {
977                 talloc_set_name_const(ret, ret);
978         }
979         return ret;
980 }
981
982 /*
983  append to a talloced string 
984 */
985 char *talloc_append_string(const void *t, char *orig, const char *append)
986 {
987         char *ret;
988         size_t olen = strlen(orig);
989         size_t alenz;
990
991         if (!append)
992                 return orig;
993
994         alenz = strlen(append) + 1;
995
996         ret = talloc_realloc(t, orig, char, olen + alenz);
997         if (!ret)
998                 return NULL;
999
1000         /* append the string with the trailing \0 */
1001         memcpy(&ret[olen], append, alenz);
1002
1003         return ret;
1004 }
1005
1006 /*
1007   strndup with a talloc 
1008 */
1009 char *talloc_strndup(const void *t, const char *p, size_t n)
1010 {
1011         size_t len;
1012         char *ret;
1013
1014         for (len=0; len<n && p[len]; len++) ;
1015
1016         ret = (char *)_talloc(t, len + 1);
1017         if (!ret) { return NULL; }
1018         memcpy(ret, p, len);
1019         ret[len] = 0;
1020         talloc_set_name_const(ret, ret);
1021         return ret;
1022 }
1023
1024 #ifndef HAVE_VA_COPY
1025 #ifdef HAVE___VA_COPY
1026 #define va_copy(dest, src) __va_copy(dest, src)
1027 #else
1028 #define va_copy(dest, src) (dest) = (src)
1029 #endif
1030 #endif
1031
1032 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
1033 {       
1034         int len;
1035         char *ret;
1036         va_list ap2;
1037         char c;
1038         
1039         va_copy(ap2, ap);
1040
1041         /* this call looks strange, but it makes it work on older solaris boxes */
1042         if ((len = vsnprintf(&c, 1, fmt, ap2)) < 0) {
1043                 return NULL;
1044         }
1045
1046         ret = (char *)_talloc(t, len+1);
1047         if (ret) {
1048                 va_copy(ap2, ap);
1049                 vsnprintf(ret, len+1, fmt, ap2);
1050                 talloc_set_name_const(ret, ret);
1051         }
1052
1053         return ret;
1054 }
1055
1056
1057 /*
1058   Perform string formatting, and return a pointer to newly allocated
1059   memory holding the result, inside a memory pool.
1060  */
1061 char *talloc_asprintf(const void *t, const char *fmt, ...)
1062 {
1063         va_list ap;
1064         char *ret;
1065
1066         va_start(ap, fmt);
1067         ret = talloc_vasprintf(t, fmt, ap);
1068         va_end(ap);
1069         return ret;
1070 }
1071
1072
1073 /**
1074  * Realloc @p s to append the formatted result of @p fmt and @p ap,
1075  * and return @p s, which may have moved.  Good for gradually
1076  * accumulating output into a string buffer.
1077  **/
1078 char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1079 {       
1080         struct talloc_chunk *tc;
1081         int len, s_len;
1082         va_list ap2;
1083         char c;
1084
1085         if (s == NULL) {
1086                 return talloc_vasprintf(NULL, fmt, ap);
1087         }
1088
1089         tc = talloc_chunk_from_ptr(s);
1090
1091         va_copy(ap2, ap);
1092
1093         s_len = tc->size - 1;
1094         if ((len = vsnprintf(&c, 1, fmt, ap2)) <= 0) {
1095                 /* Either the vsnprintf failed or the format resulted in
1096                  * no characters being formatted. In the former case, we
1097                  * ought to return NULL, in the latter we ought to return
1098                  * the original string. Most current callers of this 
1099                  * function expect it to never return NULL.
1100                  */
1101                 return s;
1102         }
1103
1104         s = talloc_realloc(NULL, s, char, s_len + len+1);
1105         if (!s) return NULL;
1106
1107         va_copy(ap2, ap);
1108
1109         vsnprintf(s+s_len, len+1, fmt, ap2);
1110         talloc_set_name_const(s, s);
1111
1112         return s;
1113 }
1114
1115 /*
1116   Realloc @p s to append the formatted result of @p fmt and return @p
1117   s, which may have moved.  Good for gradually accumulating output
1118   into a string buffer.
1119  */
1120 char *talloc_asprintf_append(char *s, const char *fmt, ...)
1121 {
1122         va_list ap;
1123
1124         va_start(ap, fmt);
1125         s = talloc_vasprintf_append(s, fmt, ap);
1126         va_end(ap);
1127         return s;
1128 }
1129
1130 /*
1131   alloc an array, checking for integer overflow in the array size
1132 */
1133 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1134 {
1135         if (count >= MAX_TALLOC_SIZE/el_size) {
1136                 return NULL;
1137         }
1138         return talloc_named_const(ctx, el_size * count, name);
1139 }
1140
1141 /*
1142   alloc an zero array, checking for integer overflow in the array size
1143 */
1144 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1145 {
1146         if (count >= MAX_TALLOC_SIZE/el_size) {
1147                 return NULL;
1148         }
1149         return _talloc_zero(ctx, el_size * count, name);
1150 }
1151
1152
1153 /*
1154   realloc an array, checking for integer overflow in the array size
1155 */
1156 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
1157 {
1158         if (count >= MAX_TALLOC_SIZE/el_size) {
1159                 return NULL;
1160         }
1161         return _talloc_realloc(ctx, ptr, el_size * count, name);
1162 }
1163
1164 /*
1165   a function version of talloc_realloc(), so it can be passed as a function pointer
1166   to libraries that want a realloc function (a realloc function encapsulates
1167   all the basic capabilities of an allocation library, which is why this is useful)
1168 */
1169 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1170 {
1171         return _talloc_realloc(context, ptr, size, NULL);
1172 }
1173
1174
1175 static void talloc_autofree(void)
1176 {
1177         talloc_free(cleanup_context);
1178         cleanup_context = NULL;
1179 }
1180
1181 /*
1182   return a context which will be auto-freed on exit
1183   this is useful for reducing the noise in leak reports
1184 */
1185 void *talloc_autofree_context(void)
1186 {
1187         if (cleanup_context == NULL) {
1188                 cleanup_context = talloc_named_const(NULL, 0, "autofree_context");
1189                 atexit(talloc_autofree);
1190         }
1191         return cleanup_context;
1192 }
1193
1194 size_t talloc_get_size(const void *context)
1195 {
1196         struct talloc_chunk *tc;
1197
1198         if (context == NULL)
1199                 return 0;
1200
1201         tc = talloc_chunk_from_ptr(context);
1202
1203         return tc->size;
1204 }
1205
1206 /*
1207   find a parent of this context that has the given name, if any
1208 */
1209 void *talloc_find_parent_byname(const void *context, const char *name)
1210 {
1211         struct talloc_chunk *tc;
1212
1213         if (context == NULL) {
1214                 return NULL;
1215         }
1216
1217         tc = talloc_chunk_from_ptr(context);
1218         while (tc) {
1219                 if (tc->name && strcmp(tc->name, name) == 0) {
1220                         return TC_PTR_FROM_CHUNK(tc);
1221                 }
1222                 while (tc && tc->prev) tc = tc->prev;
1223                 if (tc) {
1224                         tc = tc->parent;
1225                 }
1226         }
1227         return NULL;
1228 }
1229
1230 /*
1231   show the parentage of a context
1232 */
1233 void talloc_show_parents(const void *context, FILE *file)
1234 {
1235         struct talloc_chunk *tc;
1236
1237         if (context == NULL) {
1238                 fprintf(file, "talloc no parents for NULL\n");
1239                 return;
1240         }
1241
1242         tc = talloc_chunk_from_ptr(context);
1243         fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
1244         while (tc) {
1245                 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
1246                 while (tc && tc->prev) tc = tc->prev;
1247                 if (tc) {
1248                         tc = tc->parent;
1249                 }
1250         }
1251 }
1252
1253 /*
1254   return 1 if ptr is a parent of context
1255 */
1256 int talloc_is_parent(const void *context, const void *ptr)
1257 {
1258         struct talloc_chunk *tc;
1259
1260         if (context == NULL) {
1261                 return 0;
1262         }
1263
1264         tc = talloc_chunk_from_ptr(context);
1265         while (tc) {
1266                 if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
1267                 while (tc && tc->prev) tc = tc->prev;
1268                 if (tc) {
1269                         tc = tc->parent;
1270                 }
1271         }
1272         return 0;
1273 }