r2792: got rid of talloc_ldb_alloc() and instead created talloc_realloc_fn(),
[bbaumbach/samba-autobuild/.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 (context == NULL) {
277                 context = null_context;
278         }
279
280         if (talloc_unreference(context, ptr) == 0) {
281                 return 0;
282         }
283
284         if (context == NULL) {
285                 if (talloc_parent_chunk(ptr) != NULL) {
286                         return -1;
287                 }
288         } else {
289                 if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) {
290                         return -1;
291                 }
292         }
293         
294         tc_p = talloc_chunk_from_ptr(ptr);
295
296         if (tc_p->refs == NULL) {
297                 return talloc_free(ptr);
298         }
299
300         new_p = talloc_parent_chunk(tc_p->refs);
301         if (new_p) {
302                 new_parent = new_p+1;
303         } else {
304                 new_parent = NULL;
305         }
306
307         if (talloc_unreference(new_parent, ptr) != 0) {
308                 return -1;
309         }
310
311         talloc_steal(new_parent, ptr);
312
313         return 0;
314 }
315
316 /*
317   add a name to an existing pointer - va_list version
318 */
319 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
320
321 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
322 {
323         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
324         tc->name = talloc_vasprintf(ptr, fmt, ap);
325         if (tc->name) {
326                 talloc_set_name_const(tc->name, ".name");
327         }
328 }
329
330 /*
331   add a name to an existing pointer
332 */
333 void talloc_set_name(const void *ptr, const char *fmt, ...)
334 {
335         va_list ap;
336         va_start(ap, fmt);
337         talloc_set_name_v(ptr, fmt, ap);
338         va_end(ap);
339 }
340
341 /*
342    more efficient way to add a name to a pointer - the name must point to a 
343    true string constant
344 */
345 void talloc_set_name_const(const void *ptr, const char *name)
346 {
347         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
348         tc->name = name;
349 }
350
351 /*
352   create a named talloc pointer. Any talloc pointer can be named, and
353   talloc_named() operates just like talloc() except that it allows you
354   to name the pointer.
355 */
356 void *talloc_named(const void *context, size_t size, const char *fmt, ...)
357 {
358         va_list ap;
359         void *ptr;
360
361         ptr = _talloc(context, size);
362         if (ptr == NULL) return NULL;
363
364         va_start(ap, fmt);
365         talloc_set_name_v(ptr, fmt, ap);
366         va_end(ap);
367
368         return ptr;
369 }
370
371 /*
372   create a named talloc pointer. Any talloc pointer can be named, and
373   talloc_named() operates just like talloc() except that it allows you
374   to name the pointer.
375 */
376 void *talloc_named_const(const void *context, size_t size, const char *name)
377 {
378         void *ptr;
379
380         ptr = _talloc(context, size);
381         if (ptr == NULL) {
382                 return NULL;
383         }
384
385         talloc_set_name_const(ptr, name);
386
387         return ptr;
388 }
389
390 /*
391   return the name of a talloc ptr, or "UNNAMED"
392 */
393 const char *talloc_get_name(const void *ptr)
394 {
395         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
396         if (tc->name == TALLOC_MAGIC_REFERENCE) {
397                 return ".reference";
398         }
399         if (tc->name) {
400                 return tc->name;
401         }
402         return "UNNAMED";
403 }
404
405 /*
406   this is for compatibility with older versions of talloc
407 */
408 void *talloc_init(const char *fmt, ...)
409 {
410         va_list ap;
411         void *ptr;
412
413         ptr = _talloc(NULL, 0);
414         if (ptr == NULL) return NULL;
415
416         va_start(ap, fmt);
417         talloc_set_name_v(ptr, fmt, ap);
418         va_end(ap);
419
420         return ptr;
421 }
422
423
424 /* 
425    free a talloc pointer. This also frees all child pointers of this 
426    pointer recursively
427
428    return 0 if the memory is actually freed, otherwise -1. The memory
429    will not be freed if the ref_count is > 1 or the destructor (if
430    any) returns non-zero
431 */
432 int talloc_free(void *ptr)
433 {
434         struct talloc_chunk *tc;
435
436         if (ptr == NULL) {
437                 return -1;
438         }
439
440         tc = talloc_chunk_from_ptr(ptr);
441
442         if (tc->refs) {
443                 talloc_reference_destructor(tc->refs);
444                 return 0;
445         }
446
447         if (tc->destructor) {
448                 talloc_destructor_t d = tc->destructor;
449                 if (d == (talloc_destructor_t)-1) {
450                         return -1;
451                 }
452                 tc->destructor = (talloc_destructor_t)-1;
453                 if (d(ptr) == -1) {
454                         tc->destructor = d;
455                         return -1;
456                 }
457                 tc->destructor = NULL;
458         }
459
460         while (tc->child) {
461                 /* we need to work out who will own an abandoned child
462                    if it cannot be freed. In priority order, the first
463                    choice is owner of any remaining reference to this
464                    pointer, the second choice is our parent, and the
465                    final choice is the null context. */
466                 void *child = tc->child+1;
467                 const void *new_parent = null_context;
468                 if (tc->child->refs) {
469                         struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
470                         if (p) new_parent = p+1;
471                 }
472                 if (new_parent == null_context) {
473                         struct talloc_chunk *p = talloc_parent_chunk(ptr);
474                         if (p) new_parent = p+1;
475                 }
476                 talloc_free(talloc_steal(new_parent, child));
477         }
478
479         if (tc->parent) {
480                 _TLIST_REMOVE(tc->parent->child, tc);
481                 if (tc->parent->child) {
482                         tc->parent->child->parent = tc->parent;
483                 }
484         } else {
485                 if (tc->prev) tc->prev->next = tc->next;
486                 if (tc->next) tc->next->prev = tc->prev;
487         }
488
489         tc->magic = TALLOC_MAGIC_FREE;
490
491         free(tc);
492         return 0;
493 }
494
495
496
497 /*
498   A talloc version of realloc. The context argument is only used if
499   ptr is NULL
500 */
501 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
502 {
503         struct talloc_chunk *tc;
504         void *new_ptr;
505
506         /* size zero is equivalent to free() */
507         if (size == 0) {
508                 talloc_free(ptr);
509                 return NULL;
510         }
511
512         if (size >= MAX_TALLOC_SIZE) {
513                 return NULL;
514         }
515
516         /* realloc(NULL) is equavalent to malloc() */
517         if (ptr == NULL) {
518                 return talloc_named_const(context, size, name);
519         }
520
521         tc = talloc_chunk_from_ptr(ptr);
522
523         /* don't allow realloc on referenced pointers */
524         if (tc->refs) {
525                 return NULL;
526         }
527
528         /* by resetting magic we catch users of the old memory */
529         tc->magic = TALLOC_MAGIC_FREE;
530
531         new_ptr = realloc(tc, size + sizeof(*tc));
532         if (!new_ptr) { 
533                 tc->magic = TALLOC_MAGIC; 
534                 return NULL; 
535         }
536
537         tc = new_ptr;
538         tc->magic = TALLOC_MAGIC;
539         if (tc->parent) {
540                 tc->parent->child = new_ptr;
541         }
542
543         if (tc->prev) {
544                 tc->prev->next = tc;
545         }
546         if (tc->next) {
547                 tc->next->prev = tc;
548         }
549
550         tc->size = size;
551         talloc_set_name_const(tc+1, name);
552
553         return (void *)(tc+1);
554 }
555
556 /* 
557    move a lump of memory from one talloc context to another return the
558    ptr on success, or NULL if it could not be transferred
559 */
560 void *talloc_steal(const void *new_ctx, const void *ptr)
561 {
562         struct talloc_chunk *tc, *new_tc;
563
564         if (!ptr) {
565                 return NULL;
566         }
567
568         if (new_ctx == NULL) {
569                 new_ctx = null_context;
570         }
571
572         tc = talloc_chunk_from_ptr(ptr);
573
574         if (new_ctx == NULL) {
575                 if (tc->parent) {
576                         _TLIST_REMOVE(tc->parent->child, tc);
577                         if (tc->parent->child) {
578                                 tc->parent->child->parent = tc->parent;
579                         }
580                 } else {
581                         if (tc->prev) tc->prev->next = tc->next;
582                         if (tc->next) tc->next->prev = tc->prev;
583                 }
584                 
585                 tc->parent = tc->next = tc->prev = NULL;
586                 return discard_const_p(void, ptr);
587         }
588
589         new_tc = talloc_chunk_from_ptr(new_ctx);
590
591         if (tc == new_tc) {
592                 return discard_const_p(void, ptr);
593         }
594
595         if (tc->parent) {
596                 _TLIST_REMOVE(tc->parent->child, tc);
597                 if (tc->parent->child) {
598                         tc->parent->child->parent = tc->parent;
599                 }
600         } else {
601                 if (tc->prev) tc->prev->next = tc->next;
602                 if (tc->next) tc->next->prev = tc->prev;
603         }
604
605         tc->parent = new_tc;
606         if (new_tc->child) new_tc->child->parent = NULL;
607         _TLIST_ADD(new_tc->child, tc);
608
609         return discard_const_p(void, ptr);
610 }
611
612 /*
613   return the total size of a talloc pool (subtree)
614 */
615 off_t talloc_total_size(const void *ptr)
616 {
617         off_t total = 0;
618         struct talloc_chunk *c, *tc;
619         
620         if (ptr == NULL) {
621                 ptr = null_context;
622         }
623         if (ptr == NULL) {
624                 return 0;
625         }
626
627         tc = talloc_chunk_from_ptr(ptr);
628
629         total = tc->size;
630         for (c=tc->child;c;c=c->next) {
631                 total += talloc_total_size(c+1);
632         }
633         return total;
634 }
635
636 /*
637   return the total number of blocks in a talloc pool (subtree)
638 */
639 off_t talloc_total_blocks(const void *ptr)
640 {
641         off_t total = 0;
642         struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
643
644         total++;
645         for (c=tc->child;c;c=c->next) {
646                 total += talloc_total_blocks(c+1);
647         }
648         return total;
649 }
650
651 /*
652   return the number of external references to a pointer
653 */
654 static int talloc_reference_count(const void *ptr)
655 {
656         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
657         struct talloc_reference_handle *h;
658         int ret = 0;
659
660         for (h=tc->refs;h;h=h->next) {
661                 ret++;
662         }
663         return ret;
664 }
665
666 /*
667   report on memory usage by all children of a pointer, giving a full tree view
668 */
669 static void talloc_report_depth(const void *ptr, FILE *f, int depth)
670 {
671         struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
672
673         for (c=tc->child;c;c=c->next) {
674                 if (c->name == TALLOC_MAGIC_REFERENCE) {
675                         struct talloc_reference_handle *handle = (void *)(c+1);
676                         const char *name2 = talloc_get_name(handle->ptr);
677                         fprintf(f, "%*sreference to: %s\n", depth*4, "", name2);
678                 } else {
679                         const char *name = talloc_get_name(c+1);
680                         fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", 
681                                 depth*4, "",
682                                 name,
683                                 (unsigned long)talloc_total_size(c+1),
684                                 (unsigned long)talloc_total_blocks(c+1),
685                                 talloc_reference_count(c+1));
686                         talloc_report_depth(c+1, f, depth+1);
687                 }
688         }
689
690 }
691
692 /*
693   report on memory usage by all children of a pointer, giving a full tree view
694 */
695 void talloc_report_full(const void *ptr, FILE *f)
696 {
697         if (ptr == NULL) {
698                 ptr = null_context;
699         }
700         if (ptr == NULL) return;
701
702         fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n", 
703                 talloc_get_name(ptr), 
704                 (unsigned long)talloc_total_size(ptr),
705                 (unsigned long)talloc_total_blocks(ptr));
706
707         talloc_report_depth(ptr, f, 1);
708 }
709
710 /*
711   report on memory usage by all children of a pointer
712 */
713 void talloc_report(const void *ptr, FILE *f)
714 {
715         struct talloc_chunk *c, *tc;
716
717         if (ptr == NULL) {
718                 ptr = null_context;
719         }
720         if (ptr == NULL) return;
721        
722         fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n", 
723                 talloc_get_name(ptr), 
724                 (unsigned long)talloc_total_size(ptr),
725                 (unsigned long)talloc_total_blocks(ptr));
726
727         tc = talloc_chunk_from_ptr(ptr);
728
729         for (c=tc->child;c;c=c->next) {
730                 fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n", 
731                         talloc_get_name(c+1),
732                         (unsigned long)talloc_total_size(c+1),
733                         (unsigned long)talloc_total_blocks(c+1));
734         }
735
736 }
737
738 /*
739   report on any memory hanging off the null context
740 */
741 static void talloc_report_null(void)
742 {
743         if (talloc_total_size(null_context) != 0) {
744                 talloc_report(null_context, stderr);
745         }
746 }
747
748 /*
749   report on any memory hanging off the null context
750 */
751 static void talloc_report_null_full(void)
752 {
753         if (talloc_total_size(null_context) != 0) {
754                 talloc_report_full(null_context, stderr);
755         }
756 }
757
758 /*
759   enable leak reporting on exit
760 */
761 void talloc_enable_leak_report(void)
762 {
763         null_context = talloc_named_const(NULL, 0, "null_context");
764         atexit(talloc_report_null);
765 }
766
767 /*
768   enable full leak reporting on exit
769 */
770 void talloc_enable_leak_report_full(void)
771 {
772         null_context = talloc_named_const(NULL, 0, "null_context");
773         atexit(talloc_report_null_full);
774 }
775
776 /* 
777    talloc and zero memory. 
778 */
779 void *talloc_zero(const void *ctx, size_t size)
780 {
781         void *p = talloc(ctx, size);
782
783         if (p) {
784                 memset(p, '\0', size);
785         }
786
787         return p;
788 }
789
790
791 /*
792   memdup with a talloc. 
793 */
794 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
795 {
796         void *newp = talloc_named_const(t, size, name);
797
798         if (newp) {
799                 memcpy(newp, p, size);
800         }
801
802         return newp;
803 }
804
805 /*
806   strdup with a talloc 
807 */
808 char *talloc_strdup(const void *t, const char *p)
809 {
810         char *ret;
811         if (!p) {
812                 return NULL;
813         }
814         ret = talloc_memdup(t, p, strlen(p) + 1);
815         if (ret) {
816                 talloc_set_name_const(ret, ret);
817         }
818         return ret;
819 }
820
821 /*
822   strndup with a talloc 
823 */
824 char *talloc_strndup(const void *t, const char *p, size_t n)
825 {
826         size_t len;
827         char *ret;
828
829         for (len=0; p[len] && len<n; len++) ;
830
831         ret = talloc(t, len + 1);
832         if (!ret) { return NULL; }
833         memcpy(ret, p, len);
834         ret[len] = 0;
835         return ret;
836 }
837
838 #ifndef VA_COPY
839 #ifdef HAVE_VA_COPY
840 #define VA_COPY(dest, src) __va_copy(dest, src)
841 #else
842 #define VA_COPY(dest, src) (dest) = (src)
843 #endif
844 #endif
845
846 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
847 {       
848         int len;
849         char *ret;
850         va_list ap2;
851         
852         VA_COPY(ap2, ap);
853
854         len = vsnprintf(NULL, 0, fmt, ap2);
855
856         ret = talloc(t, len+1);
857         if (ret) {
858                 VA_COPY(ap2, ap);
859                 vsnprintf(ret, len+1, fmt, ap2);
860                 talloc_set_name_const(ret, ret);
861         }
862
863         return ret;
864 }
865
866
867 /*
868   Perform string formatting, and return a pointer to newly allocated
869   memory holding the result, inside a memory pool.
870  */
871 char *talloc_asprintf(const void *t, const char *fmt, ...)
872 {
873         va_list ap;
874         char *ret;
875
876         va_start(ap, fmt);
877         ret = talloc_vasprintf(t, fmt, ap);
878         va_end(ap);
879         return ret;
880 }
881
882
883 /**
884  * Realloc @p s to append the formatted result of @p fmt and @p ap,
885  * and return @p s, which may have moved.  Good for gradually
886  * accumulating output into a string buffer.
887  **/
888
889 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
890
891 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
892 {       
893         int len, s_len;
894         va_list ap2;
895
896         VA_COPY(ap2, ap);
897
898         if (s) {
899                 s_len = strlen(s);
900         } else {
901                 s_len = 0;
902         }
903         len = vsnprintf(NULL, 0, fmt, ap2);
904
905         s = talloc_realloc(NULL, s, s_len + len+1);
906         if (!s) return NULL;
907
908         VA_COPY(ap2, ap);
909
910         vsnprintf(s+s_len, len+1, fmt, ap2);
911         talloc_set_name_const(s, s);
912
913         return s;
914 }
915
916 /*
917   Realloc @p s to append the formatted result of @p fmt and return @p
918   s, which may have moved.  Good for gradually accumulating output
919   into a string buffer.
920  */
921 char *talloc_asprintf_append(char *s, const char *fmt, ...)
922 {
923         va_list ap;
924
925         va_start(ap, fmt);
926         s = talloc_vasprintf_append(s, fmt, ap);
927         va_end(ap);
928         return s;
929 }
930
931 /*
932   alloc an array, checking for integer overflow in the array size
933 */
934 void *talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
935 {
936         if (count >= MAX_TALLOC_SIZE/el_size) {
937                 return NULL;
938         }
939         return talloc_named_const(ctx, el_size * count, name);
940 }
941
942
943 /*
944   realloc an array, checking for integer overflow in the array size
945 */
946 void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
947 {
948         if (count >= MAX_TALLOC_SIZE/el_size) {
949                 return NULL;
950         }
951         ptr = talloc_realloc(ctx, ptr, el_size * count);
952         if (ptr) {
953                 talloc_set_name_const(ptr, name);
954         }
955         return ptr;
956 }
957
958 /*
959   a function version of talloc_realloc(), so it can be passed as a function pointer
960   to libraries that want a realloc function (a realloc function encapsulates
961   all the basic capabilities of an allocation library, which is why this is useful)
962 */
963 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
964 {
965         return _talloc_realloc(context, ptr, size, NULL);
966 }