r17886: add talloc_ptrtype() and talloc_array_ptrtype(),
[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      ** 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 const void *null_context;
83 static void *cleanup_context;
84
85
86 struct talloc_reference_handle {
87         struct talloc_reference_handle *next, *prev;
88         void *ptr;
89 };
90
91 typedef int (*talloc_destructor_t)(void *);
92
93 struct talloc_chunk {
94         struct talloc_chunk *next, *prev;
95         struct talloc_chunk *parent, *child;
96         struct talloc_reference_handle *refs;
97         talloc_destructor_t destructor;
98         const char *name;
99         size_t size;
100         unsigned flags;
101 };
102
103 /* 16 byte alignment seems to keep everyone happy */
104 #define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
105 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
106
107 /* panic if we get a bad magic value */
108 static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
109 {
110         const char *pp = ptr;
111         struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
112         if ((tc->flags & ~0xF) != TALLOC_MAGIC) { 
113                 TALLOC_ABORT("Bad talloc magic value - unknown value"); 
114         }
115         if (tc->flags & TALLOC_FLAG_FREE) {
116                 TALLOC_ABORT("Bad talloc magic value - double free"); 
117         }
118         return tc;
119 }
120
121 /* hook into the front of the list */
122 #define _TLIST_ADD(list, p) \
123 do { \
124         if (!(list)) { \
125                 (list) = (p); \
126                 (p)->next = (p)->prev = NULL; \
127         } else { \
128                 (list)->prev = (p); \
129                 (p)->next = (list); \
130                 (p)->prev = NULL; \
131                 (list) = (p); \
132         }\
133 } while (0)
134
135 /* remove an element from a list - element doesn't have to be in list. */
136 #define _TLIST_REMOVE(list, p) \
137 do { \
138         if ((p) == (list)) { \
139                 (list) = (p)->next; \
140                 if (list) (list)->prev = NULL; \
141         } else { \
142                 if ((p)->prev) (p)->prev->next = (p)->next; \
143                 if ((p)->next) (p)->next->prev = (p)->prev; \
144         } \
145         if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
146 } while (0)
147
148
149 /*
150   return the parent chunk of a pointer
151 */
152 static struct talloc_chunk *talloc_parent_chunk(const void *ptr)
153 {
154         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
155         while (tc->prev) tc=tc->prev;
156         return tc->parent;
157 }
158
159 void *talloc_parent(const void *ptr)
160 {
161         struct talloc_chunk *tc = talloc_parent_chunk(ptr);
162         return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
163 }
164
165 /* 
166    Allocate a bit of memory as a child of an existing pointer
167 */
168 void *_talloc(const void *context, size_t size)
169 {
170         struct talloc_chunk *tc;
171
172         if (context == NULL) {
173                 context = null_context;
174         }
175
176         if (size >= MAX_TALLOC_SIZE) {
177                 return NULL;
178         }
179
180         tc = malloc(TC_HDR_SIZE+size);
181         if (tc == NULL) return NULL;
182
183         tc->size = size;
184         tc->flags = TALLOC_MAGIC;
185         tc->destructor = NULL;
186         tc->child = NULL;
187         tc->name = NULL;
188         tc->refs = NULL;
189
190         if (context) {
191                 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
192
193                 tc->parent = parent;
194
195                 if (parent->child) {
196                         parent->child->parent = NULL;
197                 }
198
199                 _TLIST_ADD(parent->child, tc);
200         } else {
201                 tc->next = tc->prev = tc->parent = NULL;
202         }
203
204         return TC_PTR_FROM_CHUNK(tc);
205 }
206
207
208 /*
209   setup a destructor to be called on free of a pointer
210   the destructor should return 0 on success, or -1 on failure.
211   if the destructor fails then the free is failed, and the memory can
212   be continued to be used
213 */
214 void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
215 {
216         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
217         tc->destructor = destructor;
218 }
219
220 /*
221   increase the reference count on a piece of memory. 
222 */
223 void talloc_increase_ref_count(const void *ptr)
224 {
225         talloc_reference(null_context, ptr);
226 }
227
228 /*
229   helper for talloc_reference()
230 */
231 static int talloc_reference_destructor(struct talloc_reference_handle *handle)
232 {
233         struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
234         _TLIST_REMOVE(ptr_tc->refs, handle);
235         return 0;
236 }
237
238 /*
239   make a secondary reference to a pointer, hanging off the given context.
240   the pointer remains valid until both the original caller and this given
241   context are freed.
242   
243   the major use for this is when two different structures need to reference the 
244   same underlying data, and you want to be able to free the two instances separately,
245   and in either order
246 */
247 void *talloc_reference(const void *context, const void *ptr)
248 {
249         struct talloc_chunk *tc;
250         struct talloc_reference_handle *handle;
251         if (ptr == NULL) return NULL;
252
253         tc = talloc_chunk_from_ptr(ptr);
254         handle = talloc_named_const(context, sizeof(*handle), TALLOC_MAGIC_REFERENCE);
255
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 = new_ptr;
650         tc->flags &= ~TALLOC_FLAG_FREE; 
651         if (tc->parent) {
652                 tc->parent->child = new_ptr;
653         }
654         if (tc->child) {
655                 tc->child->parent = new_ptr;
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 = TC_PTR_FROM_CHUNK(c);
816                         const char *name2 = talloc_get_name(handle->ptr);
817                         fprintf(f, "%*sreference to: %s\n", depth*4, "", name2);
818                 } else {
819                         const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c));
820                         fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", 
821                                 depth*4, "",
822                                 name,
823                                 (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
824                                 (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)),
825                                 talloc_reference_count(TC_PTR_FROM_CHUNK(c)));
826                         talloc_report_depth(TC_PTR_FROM_CHUNK(c), f, depth+1);
827                 }
828         }
829         tc->flags &= ~TALLOC_FLAG_LOOP;
830 }
831
832 /*
833   report on memory usage by all children of a pointer, giving a full tree view
834 */
835 void talloc_report_full(const void *ptr, FILE *f)
836 {
837         if (ptr == NULL) {
838                 ptr = null_context;
839         }
840         if (ptr == NULL) return;
841
842         fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n", 
843                 talloc_get_name(ptr), 
844                 (unsigned long)talloc_total_size(ptr),
845                 (unsigned long)talloc_total_blocks(ptr));
846
847         talloc_report_depth(ptr, f, 1);
848         fflush(f);
849 }
850
851 /*
852   report on memory usage by all children of a pointer
853 */
854 void talloc_report(const void *ptr, FILE *f)
855 {
856         struct talloc_chunk *c, *tc;
857
858         if (ptr == NULL) {
859                 ptr = null_context;
860         }
861         if (ptr == NULL) return;
862        
863         fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n", 
864                 talloc_get_name(ptr), 
865                 (unsigned long)talloc_total_size(ptr),
866                 (unsigned long)talloc_total_blocks(ptr));
867
868         tc = talloc_chunk_from_ptr(ptr);
869
870         for (c=tc->child;c;c=c->next) {
871                 fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n", 
872                         talloc_get_name(TC_PTR_FROM_CHUNK(c)),
873                         (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
874                         (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)));
875         }
876         fflush(f);
877 }
878
879 /*
880   report on any memory hanging off the null context
881 */
882 static void talloc_report_null(void)
883 {
884         if (talloc_total_size(null_context) != 0) {
885                 talloc_report(null_context, stderr);
886         }
887 }
888
889 /*
890   report on any memory hanging off the null context
891 */
892 static void talloc_report_null_full(void)
893 {
894         if (talloc_total_size(null_context) != 0) {
895                 talloc_report_full(null_context, stderr);
896         }
897 }
898
899 /*
900   enable tracking of the NULL context
901 */
902 void talloc_enable_null_tracking(void)
903 {
904         if (null_context == NULL) {
905                 null_context = talloc_named_const(NULL, 0, "null_context");
906         }
907 }
908
909 /*
910   enable leak reporting on exit
911 */
912 void talloc_enable_leak_report(void)
913 {
914         talloc_enable_null_tracking();
915         atexit(talloc_report_null);
916 }
917
918 /*
919   enable full leak reporting on exit
920 */
921 void talloc_enable_leak_report_full(void)
922 {
923         talloc_enable_null_tracking();
924         atexit(talloc_report_null_full);
925 }
926
927 /* 
928    talloc and zero memory. 
929 */
930 void *_talloc_zero(const void *ctx, size_t size, const char *name)
931 {
932         void *p = talloc_named_const(ctx, size, name);
933
934         if (p) {
935                 memset(p, '\0', size);
936         }
937
938         return p;
939 }
940
941
942 /*
943   memdup with a talloc. 
944 */
945 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
946 {
947         void *newp = talloc_named_const(t, size, name);
948
949         if (newp) {
950                 memcpy(newp, p, size);
951         }
952
953         return newp;
954 }
955
956 /*
957   strdup with a talloc 
958 */
959 char *talloc_strdup(const void *t, const char *p)
960 {
961         char *ret;
962         if (!p) {
963                 return NULL;
964         }
965         ret = talloc_memdup(t, p, strlen(p) + 1);
966         if (ret) {
967                 talloc_set_name_const(ret, ret);
968         }
969         return ret;
970 }
971
972 /*
973  append to a talloced string 
974 */
975 char *talloc_append_string(const void *t, char *orig, const char *append)
976 {
977         char *ret;
978         size_t olen = strlen(orig);
979         size_t alenz;
980
981         if (!append)
982                 return orig;
983
984         alenz = strlen(append) + 1;
985
986         ret = talloc_realloc(t, orig, char, olen + alenz);
987         if (!ret)
988                 return NULL;
989
990         /* append the string with the trailing \0 */
991         memcpy(&ret[olen], append, alenz);
992
993         return ret;
994 }
995
996 /*
997   strndup with a talloc 
998 */
999 char *talloc_strndup(const void *t, const char *p, size_t n)
1000 {
1001         size_t len;
1002         char *ret;
1003
1004         for (len=0; len<n && p[len]; len++) ;
1005
1006         ret = _talloc(t, len + 1);
1007         if (!ret) { return NULL; }
1008         memcpy(ret, p, len);
1009         ret[len] = 0;
1010         talloc_set_name_const(ret, ret);
1011         return ret;
1012 }
1013
1014 #ifndef HAVE_VA_COPY
1015 #ifdef HAVE___VA_COPY
1016 #define va_copy(dest, src) __va_copy(dest, src)
1017 #else
1018 #define va_copy(dest, src) (dest) = (src)
1019 #endif
1020 #endif
1021
1022 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
1023 {       
1024         int len;
1025         char *ret;
1026         va_list ap2;
1027         char c;
1028         
1029         va_copy(ap2, ap);
1030
1031         /* this call looks strange, but it makes it work on older solaris boxes */
1032         if ((len = vsnprintf(&c, 1, fmt, ap2)) < 0) {
1033                 return NULL;
1034         }
1035
1036         ret = _talloc(t, len+1);
1037         if (ret) {
1038                 va_copy(ap2, ap);
1039                 vsnprintf(ret, len+1, fmt, ap2);
1040                 talloc_set_name_const(ret, ret);
1041         }
1042
1043         return ret;
1044 }
1045
1046
1047 /*
1048   Perform string formatting, and return a pointer to newly allocated
1049   memory holding the result, inside a memory pool.
1050  */
1051 char *talloc_asprintf(const void *t, const char *fmt, ...)
1052 {
1053         va_list ap;
1054         char *ret;
1055
1056         va_start(ap, fmt);
1057         ret = talloc_vasprintf(t, fmt, ap);
1058         va_end(ap);
1059         return ret;
1060 }
1061
1062
1063 /**
1064  * Realloc @p s to append the formatted result of @p fmt and @p ap,
1065  * and return @p s, which may have moved.  Good for gradually
1066  * accumulating output into a string buffer.
1067  **/
1068 char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1069 {       
1070         struct talloc_chunk *tc;
1071         int len, s_len;
1072         va_list ap2;
1073         char c;
1074
1075         if (s == NULL) {
1076                 return talloc_vasprintf(NULL, fmt, ap);
1077         }
1078
1079         tc = talloc_chunk_from_ptr(s);
1080
1081         va_copy(ap2, ap);
1082
1083         s_len = tc->size - 1;
1084         if ((len = vsnprintf(&c, 1, fmt, ap2)) <= 0) {
1085                 /* Either the vsnprintf failed or the format resulted in
1086                  * no characters being formatted. In the former case, we
1087                  * ought to return NULL, in the latter we ought to return
1088                  * the original string. Most current callers of this 
1089                  * function expect it to never return NULL.
1090                  */
1091                 return s;
1092         }
1093
1094         s = talloc_realloc(NULL, s, char, s_len + len+1);
1095         if (!s) return NULL;
1096
1097         va_copy(ap2, ap);
1098
1099         vsnprintf(s+s_len, len+1, fmt, ap2);
1100         talloc_set_name_const(s, s);
1101
1102         return s;
1103 }
1104
1105 /*
1106   Realloc @p s to append the formatted result of @p fmt and return @p
1107   s, which may have moved.  Good for gradually accumulating output
1108   into a string buffer.
1109  */
1110 char *talloc_asprintf_append(char *s, const char *fmt, ...)
1111 {
1112         va_list ap;
1113
1114         va_start(ap, fmt);
1115         s = talloc_vasprintf_append(s, fmt, ap);
1116         va_end(ap);
1117         return s;
1118 }
1119
1120 /*
1121   alloc an array, checking for integer overflow in the array size
1122 */
1123 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1124 {
1125         if (count >= MAX_TALLOC_SIZE/el_size) {
1126                 return NULL;
1127         }
1128         return talloc_named_const(ctx, el_size * count, name);
1129 }
1130
1131 /*
1132   alloc an zero array, checking for integer overflow in the array size
1133 */
1134 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1135 {
1136         if (count >= MAX_TALLOC_SIZE/el_size) {
1137                 return NULL;
1138         }
1139         return _talloc_zero(ctx, el_size * count, name);
1140 }
1141
1142
1143 /*
1144   realloc an array, checking for integer overflow in the array size
1145 */
1146 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
1147 {
1148         if (count >= MAX_TALLOC_SIZE/el_size) {
1149                 return NULL;
1150         }
1151         return _talloc_realloc(ctx, ptr, el_size * count, name);
1152 }
1153
1154 /*
1155   a function version of talloc_realloc(), so it can be passed as a function pointer
1156   to libraries that want a realloc function (a realloc function encapsulates
1157   all the basic capabilities of an allocation library, which is why this is useful)
1158 */
1159 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1160 {
1161         return _talloc_realloc(context, ptr, size, NULL);
1162 }
1163
1164
1165 static void talloc_autofree(void)
1166 {
1167         talloc_free(cleanup_context);
1168         cleanup_context = NULL;
1169 }
1170
1171 /*
1172   return a context which will be auto-freed on exit
1173   this is useful for reducing the noise in leak reports
1174 */
1175 void *talloc_autofree_context(void)
1176 {
1177         if (cleanup_context == NULL) {
1178                 cleanup_context = talloc_named_const(NULL, 0, "autofree_context");
1179                 atexit(talloc_autofree);
1180         }
1181         return cleanup_context;
1182 }
1183
1184 size_t talloc_get_size(const void *context)
1185 {
1186         struct talloc_chunk *tc;
1187
1188         if (context == NULL)
1189                 return 0;
1190
1191         tc = talloc_chunk_from_ptr(context);
1192
1193         return tc->size;
1194 }
1195
1196 /*
1197   find a parent of this context that has the given name, if any
1198 */
1199 void *talloc_find_parent_byname(const void *context, const char *name)
1200 {
1201         struct talloc_chunk *tc;
1202
1203         if (context == NULL) {
1204                 return NULL;
1205         }
1206
1207         tc = talloc_chunk_from_ptr(context);
1208         while (tc) {
1209                 if (tc->name && strcmp(tc->name, name) == 0) {
1210                         return TC_PTR_FROM_CHUNK(tc);
1211                 }
1212                 while (tc && tc->prev) tc = tc->prev;
1213                 if (tc) {
1214                         tc = tc->parent;
1215                 }
1216         }
1217         return NULL;
1218 }
1219
1220 /*
1221   show the parentage of a context
1222 */
1223 void talloc_show_parents(const void *context, FILE *file)
1224 {
1225         struct talloc_chunk *tc;
1226
1227         if (context == NULL) {
1228                 fprintf(file, "talloc no parents for NULL\n");
1229                 return;
1230         }
1231
1232         tc = talloc_chunk_from_ptr(context);
1233         fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
1234         while (tc) {
1235                 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
1236                 while (tc && tc->prev) tc = tc->prev;
1237                 if (tc) {
1238                         tc = tc->parent;
1239                 }
1240         }
1241 }
1242
1243 /*
1244   return 1 if ptr is a parent of context
1245 */
1246 int talloc_is_parent(const void *context, const char *ptr)
1247 {
1248         struct talloc_chunk *tc;
1249
1250         if (context == NULL) {
1251                 return 0;
1252         }
1253
1254         tc = talloc_chunk_from_ptr(context);
1255         while (tc) {
1256                 if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
1257                 while (tc && tc->prev) tc = tc->prev;
1258                 if (tc) {
1259                         tc = tc->parent;
1260                 }
1261         }
1262         return 0;
1263 }