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