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