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