r6828: More portability fixes
[kamenim/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 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #ifdef HAVE_SYS_TYPES_H
39 #include <sys/types.h>
40 #endif
41
42 #ifdef HAVE_UNISTD_H
43 #include <unistd.h>
44 #endif
45
46 #ifdef HAVE_STDARG_H
47 #include <stdarg.h>
48 #else
49 #include <varargs.h>
50 #endif
51
52 #ifdef HAVE_STDINT_H
53 #include <stdint.h>
54 #endif
55
56 #include "talloc.h"
57
58 /* use this to force every realloc to change the pointer, to stress test
59    code that might not cope */
60 #define ALWAYS_REALLOC 0
61
62
63 #define MAX_TALLOC_SIZE 0x10000000
64 #define TALLOC_MAGIC 0xe814ec4f
65 #define TALLOC_MAGIC_FREE 0x7faebef3
66 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
67
68 /* by default we abort when given a bad pointer (such as when talloc_free() is called 
69    on a pointer that came from malloc() */
70 #ifndef TALLOC_ABORT
71 #define TALLOC_ABORT(reason) abort()
72 #endif
73
74 #ifndef discard_const_p
75 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
76 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
77 #else
78 # define discard_const_p(type, ptr) ((type *)(ptr))
79 #endif
80 #endif
81
82 /* this null_context is only used if talloc_enable_leak_report() or
83    talloc_enable_leak_report_full() is called, otherwise it remains
84    NULL
85 */
86 static const void *null_context;
87 static void *cleanup_context;
88
89
90 struct talloc_reference_handle {
91         struct talloc_reference_handle *next, *prev;
92         void *ptr;
93 };
94
95 typedef int (*talloc_destructor_t)(void *);
96
97 struct talloc_chunk {
98         struct talloc_chunk *next, *prev;
99         struct talloc_chunk *parent, *child;
100         struct talloc_reference_handle *refs;
101         size_t size;
102         unsigned magic;
103         talloc_destructor_t destructor;
104         const char *name;
105 };
106
107 /* panic if we get a bad magic value */
108 static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
109 {
110         struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1;
111         if (tc->magic != TALLOC_MAGIC) { 
112                 if (tc->magic == TALLOC_MAGIC_FREE) {
113                         TALLOC_ABORT("Bad talloc magic value - double free"); 
114                 } else {
115                         TALLOC_ABORT("Bad talloc magic value - unknown value"); 
116                 }
117         }
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->magic = 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->destructor) {
540                 talloc_destructor_t d = tc->destructor;
541                 if (d == (talloc_destructor_t)-1) {
542                         return -1;
543                 }
544                 tc->destructor = (talloc_destructor_t)-1;
545                 if (d(ptr) == -1) {
546                         tc->destructor = d;
547                         return -1;
548                 }
549                 tc->destructor = NULL;
550         }
551
552         talloc_free_children(ptr);
553
554         if (tc->parent) {
555                 _TLIST_REMOVE(tc->parent->child, tc);
556                 if (tc->parent->child) {
557                         tc->parent->child->parent = tc->parent;
558                 }
559         } else {
560                 if (tc->prev) tc->prev->next = tc->next;
561                 if (tc->next) tc->next->prev = tc->prev;
562         }
563
564         tc->magic = TALLOC_MAGIC_FREE;
565
566         free(tc);
567         return 0;
568 }
569
570
571
572 /*
573   A talloc version of realloc. The context argument is only used if
574   ptr is NULL
575 */
576 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
577 {
578         struct talloc_chunk *tc;
579         void *new_ptr;
580
581         /* size zero is equivalent to free() */
582         if (size == 0) {
583                 talloc_free(ptr);
584                 return NULL;
585         }
586
587         if (size >= MAX_TALLOC_SIZE) {
588                 return NULL;
589         }
590
591         /* realloc(NULL) is equavalent to malloc() */
592         if (ptr == NULL) {
593                 return talloc_named_const(context, size, name);
594         }
595
596         tc = talloc_chunk_from_ptr(ptr);
597
598         /* don't allow realloc on referenced pointers */
599         if (tc->refs) {
600                 return NULL;
601         }
602
603         /* by resetting magic we catch users of the old memory */
604         tc->magic = TALLOC_MAGIC_FREE;
605
606 #if ALWAYS_REALLOC
607         new_ptr = malloc(size + sizeof(*tc));
608         if (new_ptr) {
609                 memcpy(new_ptr, tc, tc->size + sizeof(*tc));
610                 free(tc);
611         }
612 #else
613         new_ptr = realloc(tc, size + sizeof(*tc));
614 #endif
615         if (!new_ptr) { 
616                 tc->magic = TALLOC_MAGIC; 
617                 return NULL; 
618         }
619
620         tc = new_ptr;
621         tc->magic = TALLOC_MAGIC;
622         if (tc->parent) {
623                 tc->parent->child = new_ptr;
624         }
625         if (tc->child) {
626                 tc->child->parent = new_ptr;
627         }
628
629         if (tc->prev) {
630                 tc->prev->next = tc;
631         }
632         if (tc->next) {
633                 tc->next->prev = tc;
634         }
635
636         tc->size = size;
637         talloc_set_name_const(tc+1, name);
638
639         return (void *)(tc+1);
640 }
641
642 /* 
643    move a lump of memory from one talloc context to another return the
644    ptr on success, or NULL if it could not be transferred.
645    passing NULL as ptr will always return NULL with no side effects.
646 */
647 void *talloc_steal(const void *new_ctx, const void *ptr)
648 {
649         struct talloc_chunk *tc, *new_tc;
650
651         if (!ptr) {
652                 return NULL;
653         }
654
655         if (new_ctx == NULL) {
656                 new_ctx = null_context;
657         }
658
659         tc = talloc_chunk_from_ptr(ptr);
660
661         if (new_ctx == NULL) {
662                 if (tc->parent) {
663                         _TLIST_REMOVE(tc->parent->child, tc);
664                         if (tc->parent->child) {
665                                 tc->parent->child->parent = tc->parent;
666                         }
667                 } else {
668                         if (tc->prev) tc->prev->next = tc->next;
669                         if (tc->next) tc->next->prev = tc->prev;
670                 }
671                 
672                 tc->parent = tc->next = tc->prev = NULL;
673                 return discard_const_p(void, ptr);
674         }
675
676         new_tc = talloc_chunk_from_ptr(new_ctx);
677
678         if (tc == new_tc) {
679                 return discard_const_p(void, ptr);
680         }
681
682         if (tc->parent) {
683                 _TLIST_REMOVE(tc->parent->child, tc);
684                 if (tc->parent->child) {
685                         tc->parent->child->parent = tc->parent;
686                 }
687         } else {
688                 if (tc->prev) tc->prev->next = tc->next;
689                 if (tc->next) tc->next->prev = tc->prev;
690         }
691
692         tc->parent = new_tc;
693         if (new_tc->child) new_tc->child->parent = NULL;
694         _TLIST_ADD(new_tc->child, tc);
695
696         return discard_const_p(void, ptr);
697 }
698
699 /*
700   return the total size of a talloc pool (subtree)
701 */
702 off_t talloc_total_size(const void *ptr)
703 {
704         off_t total = 0;
705         struct talloc_chunk *c, *tc;
706         
707         if (ptr == NULL) {
708                 ptr = null_context;
709         }
710         if (ptr == NULL) {
711                 return 0;
712         }
713
714         tc = talloc_chunk_from_ptr(ptr);
715
716         total = tc->size;
717         for (c=tc->child;c;c=c->next) {
718                 total += talloc_total_size(c+1);
719         }
720         return total;
721 }
722
723 /*
724   return the total number of blocks in a talloc pool (subtree)
725 */
726 off_t talloc_total_blocks(const void *ptr)
727 {
728         off_t total = 0;
729         struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
730
731         total++;
732         for (c=tc->child;c;c=c->next) {
733                 total += talloc_total_blocks(c+1);
734         }
735         return total;
736 }
737
738 /*
739   return the number of external references to a pointer
740 */
741 static int talloc_reference_count(const void *ptr)
742 {
743         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
744         struct talloc_reference_handle *h;
745         int ret = 0;
746
747         for (h=tc->refs;h;h=h->next) {
748                 ret++;
749         }
750         return ret;
751 }
752
753 /*
754   report on memory usage by all children of a pointer, giving a full tree view
755 */
756 void talloc_report_depth(const void *ptr, FILE *f, int depth)
757 {
758         struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
759
760         for (c=tc->child;c;c=c->next) {
761                 if (c->name == TALLOC_MAGIC_REFERENCE) {
762                         struct talloc_reference_handle *handle = (void *)(c+1);
763                         const char *name2 = talloc_get_name(handle->ptr);
764                         fprintf(f, "%*sreference to: %s\n", depth*4, "", name2);
765                 } else {
766                         const char *name = talloc_get_name(c+1);
767                         fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", 
768                                 depth*4, "",
769                                 name,
770                                 (unsigned long)talloc_total_size(c+1),
771                                 (unsigned long)talloc_total_blocks(c+1),
772                                 talloc_reference_count(c+1));
773                         talloc_report_depth(c+1, f, depth+1);
774                 }
775         }
776
777 }
778
779 /*
780   report on memory usage by all children of a pointer, giving a full tree view
781 */
782 void talloc_report_full(const void *ptr, FILE *f)
783 {
784         if (ptr == NULL) {
785                 ptr = null_context;
786         }
787         if (ptr == NULL) return;
788
789         fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n", 
790                 talloc_get_name(ptr), 
791                 (unsigned long)talloc_total_size(ptr),
792                 (unsigned long)talloc_total_blocks(ptr));
793
794         talloc_report_depth(ptr, f, 1);
795         fflush(f);
796 }
797
798 /*
799   report on memory usage by all children of a pointer
800 */
801 void talloc_report(const void *ptr, FILE *f)
802 {
803         struct talloc_chunk *c, *tc;
804
805         if (ptr == NULL) {
806                 ptr = null_context;
807         }
808         if (ptr == NULL) return;
809        
810         fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n", 
811                 talloc_get_name(ptr), 
812                 (unsigned long)talloc_total_size(ptr),
813                 (unsigned long)talloc_total_blocks(ptr));
814
815         tc = talloc_chunk_from_ptr(ptr);
816
817         for (c=tc->child;c;c=c->next) {
818                 fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n", 
819                         talloc_get_name(c+1),
820                         (unsigned long)talloc_total_size(c+1),
821                         (unsigned long)talloc_total_blocks(c+1));
822         }
823         fflush(f);
824 }
825
826 /*
827   report on any memory hanging off the null context
828 */
829 static void talloc_report_null(void)
830 {
831         if (talloc_total_size(null_context) != 0) {
832                 talloc_report(null_context, stderr);
833         }
834 }
835
836 /*
837   report on any memory hanging off the null context
838 */
839 static void talloc_report_null_full(void)
840 {
841         if (talloc_total_size(null_context) != 0) {
842                 talloc_report_full(null_context, stderr);
843         }
844 }
845
846 /*
847   enable tracking of the NULL context
848 */
849 void talloc_enable_null_tracking(void)
850 {
851         if (null_context == NULL) {
852                 null_context = talloc_named_const(NULL, 0, "null_context");
853         }
854 }
855
856 /*
857   enable leak reporting on exit
858 */
859 void talloc_enable_leak_report(void)
860 {
861         talloc_enable_null_tracking();
862         atexit(talloc_report_null);
863 }
864
865 /*
866   enable full leak reporting on exit
867 */
868 void talloc_enable_leak_report_full(void)
869 {
870         talloc_enable_null_tracking();
871         atexit(talloc_report_null_full);
872 }
873
874 /* 
875    talloc and zero memory. 
876 */
877 void *_talloc_zero(const void *ctx, size_t size, const char *name)
878 {
879         void *p = talloc_named_const(ctx, size, name);
880
881         if (p) {
882                 memset(p, '\0', size);
883         }
884
885         return p;
886 }
887
888
889 /*
890   memdup with a talloc. 
891 */
892 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
893 {
894         void *newp = talloc_named_const(t, size, name);
895
896         if (newp) {
897                 memcpy(newp, p, size);
898         }
899
900         return newp;
901 }
902
903 /*
904   strdup with a talloc 
905 */
906 char *talloc_strdup(const void *t, const char *p)
907 {
908         char *ret;
909         if (!p) {
910                 return NULL;
911         }
912         ret = talloc_memdup(t, p, strlen(p) + 1);
913         if (ret) {
914                 talloc_set_name_const(ret, ret);
915         }
916         return ret;
917 }
918
919 /*
920   strndup with a talloc 
921 */
922 char *talloc_strndup(const void *t, const char *p, size_t n)
923 {
924         size_t len;
925         char *ret;
926
927         for (len=0; len<n && p[len]; len++) ;
928
929         ret = _talloc(t, len + 1);
930         if (!ret) { return NULL; }
931         memcpy(ret, p, len);
932         ret[len] = 0;
933         talloc_set_name_const(ret, ret);
934         return ret;
935 }
936
937 #ifndef VA_COPY
938 #ifdef HAVE_VA_COPY
939 #define VA_COPY(dest, src) va_copy(dest, src)
940 #elif defined(HAVE___VA_COPY)
941 #define VA_COPY(dest, src) __va_copy(dest, src)
942 #else
943 #define VA_COPY(dest, src) (dest) = (src)
944 #endif
945 #endif
946
947 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
948 {       
949         int len;
950         char *ret;
951         va_list ap2;
952         
953         VA_COPY(ap2, ap);
954
955         len = vsnprintf(NULL, 0, fmt, ap2);
956
957         ret = _talloc(t, len+1);
958         if (ret) {
959                 VA_COPY(ap2, ap);
960                 vsnprintf(ret, len+1, fmt, ap2);
961                 talloc_set_name_const(ret, ret);
962         }
963
964         return ret;
965 }
966
967
968 /*
969   Perform string formatting, and return a pointer to newly allocated
970   memory holding the result, inside a memory pool.
971  */
972 char *talloc_asprintf(const void *t, const char *fmt, ...)
973 {
974         va_list ap;
975         char *ret;
976
977         va_start(ap, fmt);
978         ret = talloc_vasprintf(t, fmt, ap);
979         va_end(ap);
980         return ret;
981 }
982
983
984 /**
985  * Realloc @p s to append the formatted result of @p fmt and @p ap,
986  * and return @p s, which may have moved.  Good for gradually
987  * accumulating output into a string buffer.
988  **/
989
990 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
991
992 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
993 {       
994         struct talloc_chunk *tc;
995         int len, s_len;
996         va_list ap2;
997
998         if (s == NULL) {
999                 return talloc_vasprintf(NULL, fmt, ap);
1000         }
1001
1002         tc = talloc_chunk_from_ptr(s);
1003
1004         VA_COPY(ap2, ap);
1005
1006         s_len = tc->size - 1;
1007         len = vsnprintf(NULL, 0, fmt, ap2);
1008
1009         s = talloc_realloc(NULL, s, char, s_len + len+1);
1010         if (!s) return NULL;
1011
1012         VA_COPY(ap2, ap);
1013
1014         vsnprintf(s+s_len, len+1, fmt, ap2);
1015         talloc_set_name_const(s, s);
1016
1017         return s;
1018 }
1019
1020 /*
1021   Realloc @p s to append the formatted result of @p fmt and return @p
1022   s, which may have moved.  Good for gradually accumulating output
1023   into a string buffer.
1024  */
1025 char *talloc_asprintf_append(char *s, const char *fmt, ...)
1026 {
1027         va_list ap;
1028
1029         va_start(ap, fmt);
1030         s = talloc_vasprintf_append(s, fmt, ap);
1031         va_end(ap);
1032         return s;
1033 }
1034
1035 /*
1036   alloc an array, checking for integer overflow in the array size
1037 */
1038 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1039 {
1040         if (count >= MAX_TALLOC_SIZE/el_size) {
1041                 return NULL;
1042         }
1043         return talloc_named_const(ctx, el_size * count, name);
1044 }
1045
1046 /*
1047   alloc an zero array, checking for integer overflow in the array size
1048 */
1049 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1050 {
1051         if (count >= MAX_TALLOC_SIZE/el_size) {
1052                 return NULL;
1053         }
1054         return _talloc_zero(ctx, el_size * count, name);
1055 }
1056
1057
1058 /*
1059   realloc an array, checking for integer overflow in the array size
1060 */
1061 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
1062 {
1063         if (count >= MAX_TALLOC_SIZE/el_size) {
1064                 return NULL;
1065         }
1066         return _talloc_realloc(ctx, ptr, el_size * count, name);
1067 }
1068
1069 /*
1070   a function version of talloc_realloc(), so it can be passed as a function pointer
1071   to libraries that want a realloc function (a realloc function encapsulates
1072   all the basic capabilities of an allocation library, which is why this is useful)
1073 */
1074 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1075 {
1076         return _talloc_realloc(context, ptr, size, NULL);
1077 }
1078
1079
1080 static void talloc_autofree(void)
1081 {
1082         talloc_free(cleanup_context);
1083         cleanup_context = NULL;
1084 }
1085
1086 /*
1087   return a context which will be auto-freed on exit
1088   this is useful for reducing the noise in leak reports
1089 */
1090 void *talloc_autofree_context(void)
1091 {
1092         if (cleanup_context == NULL) {
1093                 cleanup_context = talloc_named_const(NULL, 0, "autofree_context");
1094                 atexit(talloc_autofree);
1095         }
1096         return cleanup_context;
1097 }
1098
1099 size_t talloc_get_size(const void *context)
1100 {
1101         struct talloc_chunk *tc;
1102
1103         if (context == NULL)
1104                 return 0;
1105
1106         tc = talloc_chunk_from_ptr(context);
1107
1108         return tc->size;
1109 }