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