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