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