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