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