]> git.ozlabs.org Git - ccan/blob - ccan/talloc/talloc.c
str: provide checks for ctype.h char functions, and strstr and strchr functions.
[ccan] / ccan / talloc / talloc.c
1 /* 
2    Samba Unix SMB/CIFS implementation.
3
4    Samba trivial allocation library - new interface
5
6    NOTE: Please read talloc_guide.txt for full documentation
7
8    Copyright (C) Andrew Tridgell 2004
9    Copyright (C) Stefan Metzmacher 2006
10    
11      ** NOTE! The following LGPL license applies to the talloc
12      ** library. This does NOT imply that all of Samba is released
13      ** under the LGPL
14    
15    This library is free software; you can redistribute it and/or
16    modify it under the terms of the GNU Lesser General Public
17    License as published by the Free Software Foundation; either
18    version 2 of the License, or (at your option) any later version.
19
20    This library is distributed in the hope that it will be useful,
21    but WITHOUT ANY WARRANTY; without even the implied warranty of
22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23    Lesser General Public License for more details.
24
25    You should have received a copy of the GNU Lesser General Public
26    License along with this library; if not, write to the Free Software
27    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28 */
29
30 /*
31   inspired by http://swapped.cc/halloc/
32 */
33
34 #include "talloc.h"
35 #include <string.h>
36 #include <stdint.h>
37 #include <errno.h>
38 #include <sys/types.h>
39 #include <unistd.h>
40
41 /* use this to force every realloc to change the pointer, to stress test
42    code that might not cope */
43 #define ALWAYS_REALLOC 0
44
45
46 #define MAX_TALLOC_SIZE 0x7FFFFFFF
47 #define TALLOC_MAGIC 0xe814ec70
48 #define TALLOC_FLAG_FREE 0x01
49 #define TALLOC_FLAG_LOOP 0x02
50 #define TALLOC_FLAG_EXT_ALLOC 0x04
51 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
52
53 /* by default we abort when given a bad pointer (such as when talloc_free() is called 
54    on a pointer that came from malloc() */
55 #ifndef TALLOC_ABORT
56 #define TALLOC_ABORT(reason) abort()
57 #endif
58
59 #ifndef discard_const_p
60 #if defined(INTPTR_MIN)
61 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
62 #else
63 # define discard_const_p(type, ptr) ((type *)(ptr))
64 #endif
65 #endif
66
67 /* these macros gain us a few percent of speed on gcc */
68 #if HAVE_BUILTIN_EXPECT
69 /* the strange !! is to ensure that __builtin_expect() takes either 0 or 1
70    as its first argument */
71 #define likely(x)   __builtin_expect(!!(x), 1)
72 #define unlikely(x) __builtin_expect(!!(x), 0)
73 #else
74 #define likely(x) x
75 #define unlikely(x) x
76 #endif
77
78 /* this null_context is only used if talloc_enable_leak_report() or
79    talloc_enable_leak_report_full() is called, otherwise it remains
80    NULL
81 */
82 static void *null_context;
83 static pid_t *autofree_context;
84
85 static void *(*tc_malloc)(size_t size) = malloc;
86 static void (*tc_free)(void *ptr) = free;
87 static void *(*tc_realloc)(void *ptr, size_t size) = realloc;
88
89 static void *(*tc_external_realloc)(const void *parent, void *ptr, size_t size);
90 static void (*tc_lock)(const void *ctx);
91 static void (*tc_unlock)(void);
92
93 struct talloc_reference_handle {
94         struct talloc_reference_handle *next, *prev;
95         void *ptr;
96 };
97
98 typedef int (*talloc_destructor_t)(void *);
99
100 struct talloc_chunk {
101         struct talloc_chunk *next, *prev;
102         struct talloc_chunk *parent, *child;
103         struct talloc_reference_handle *refs;
104         talloc_destructor_t destructor;
105         const char *name;
106         size_t size;
107         unsigned flags;
108 };
109
110 /* 16 byte alignment seems to keep everyone happy */
111 #define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
112 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
113
114 /* panic if we get a bad magic value */
115 static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
116 {
117         const char *pp = (const char *)ptr;
118         struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
119         if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) { 
120                 if (tc->flags & TALLOC_FLAG_FREE) {
121                         TALLOC_ABORT("Bad talloc magic value - double free"); 
122                 } else {
123                         TALLOC_ABORT("Bad talloc magic value - unknown value"); 
124                 }
125         }
126         return tc;
127 }
128
129 /* hook into the front of the list */
130 #define _TLIST_ADD(list, p) \
131 do { \
132         if (!(list)) { \
133                 (list) = (p); \
134                 (p)->next = (p)->prev = NULL; \
135         } else { \
136                 (list)->prev = (p); \
137                 (p)->next = (list); \
138                 (p)->prev = NULL; \
139                 (list) = (p); \
140         }\
141 } while (0)
142
143 /* remove an element from a list - element doesn't have to be in list. */
144 #define _TLIST_REMOVE(list, p) \
145 do { \
146         if ((p) == (list)) { \
147                 (list) = (p)->next; \
148                 if (list) (list)->prev = NULL; \
149         } else { \
150                 if ((p)->prev) (p)->prev->next = (p)->next; \
151                 if ((p)->next) (p)->next->prev = (p)->prev; \
152         } \
153         if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
154 } while (0)
155
156 static int locked;
157 static inline void lock(const void *p)
158 {
159         if (tc_lock && p) {
160                 struct talloc_chunk *tc = talloc_chunk_from_ptr(p);
161
162                 if (tc->flags & TALLOC_FLAG_EXT_ALLOC) {
163                         if (locked)
164                                 TALLOC_ABORT("nested locking");
165                         tc_lock(tc);
166                         locked = 1;
167                 }
168         }
169 }
170
171 static inline void unlock(void)
172 {
173         if (locked) {
174                 tc_unlock();
175                 locked = 0;
176         }
177 }
178
179 /*
180   return the parent chunk of a pointer
181 */
182 static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr)
183 {
184         struct talloc_chunk *tc;
185
186         if (unlikely(ptr == NULL)) {
187                 return NULL;
188         }
189
190         tc = talloc_chunk_from_ptr(ptr);
191         while (tc->prev) tc=tc->prev;
192
193         return tc->parent;
194 }
195
196 /* This version doesn't do locking, so you must already have it. */
197 static void *talloc_parent_nolock(const void *ptr)
198 {
199         struct talloc_chunk *tc;
200
201         tc = talloc_parent_chunk(ptr);
202         return tc ? TC_PTR_FROM_CHUNK(tc) : NULL;
203 }
204
205 void *talloc_parent(const void *ptr)
206 {
207         void *parent;
208
209         lock(ptr);
210         parent = talloc_parent_nolock(ptr);
211         unlock();
212         return parent;
213 }
214
215 /*
216   find parents name
217 */
218 const char *talloc_parent_name(const void *ptr)
219 {
220         struct talloc_chunk *tc;
221
222         lock(ptr);
223         tc = talloc_parent_chunk(ptr);
224         unlock();
225
226         return tc? tc->name : NULL;
227 }
228
229 static void *init_talloc(struct talloc_chunk *parent,
230                          struct talloc_chunk *tc,
231                          size_t size, int external)
232 {
233         if (unlikely(tc == NULL))
234                 return NULL;
235
236         tc->size = size;
237         tc->flags = TALLOC_MAGIC;
238         if (external)
239                 tc->flags |= TALLOC_FLAG_EXT_ALLOC;
240         tc->destructor = NULL;
241         tc->child = NULL;
242         tc->name = NULL;
243         tc->refs = NULL;
244
245         if (likely(parent)) {
246                 if (parent->child) {
247                         parent->child->parent = NULL;
248                         tc->next = parent->child;
249                         tc->next->prev = tc;
250                 } else {
251                         tc->next = NULL;
252                 }
253                 tc->parent = parent;
254                 tc->prev = NULL;
255                 parent->child = tc;
256         } else {
257                 tc->next = tc->prev = tc->parent = NULL;
258         }
259
260         return TC_PTR_FROM_CHUNK(tc);
261 }
262
263 /* 
264    Allocate a bit of memory as a child of an existing pointer
265 */
266 static inline void *__talloc(const void *context, size_t size)
267 {
268         struct talloc_chunk *tc;
269         struct talloc_chunk *parent = NULL;
270         int external = 0;
271
272         if (unlikely(context == NULL)) {
273                 context = null_context;
274         }
275
276         if (unlikely(size >= MAX_TALLOC_SIZE)) {
277                 return NULL;
278         }
279
280         if (likely(context)) {
281                 parent = talloc_chunk_from_ptr(context);
282                 if (unlikely(parent->flags & TALLOC_FLAG_EXT_ALLOC)) {
283                         tc = tc_external_realloc(context, NULL,
284                                                  TC_HDR_SIZE+size);
285                         external = 1;
286                         goto alloc_done;
287                 }
288         }
289
290         tc = (struct talloc_chunk *)tc_malloc(TC_HDR_SIZE+size);
291 alloc_done:
292         return init_talloc(parent, tc, size, external);
293 }
294
295 /*
296   setup a destructor to be called on free of a pointer
297   the destructor should return 0 on success, or -1 on failure.
298   if the destructor fails then the free is failed, and the memory can
299   be continued to be used
300 */
301 void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
302 {
303         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
304         tc->destructor = destructor;
305 }
306
307 /*
308   increase the reference count on a piece of memory. 
309 */
310 int talloc_increase_ref_count(const void *ptr)
311 {
312         if (unlikely(!talloc_reference(null_context, ptr))) {
313                 return -1;
314         }
315         return 0;
316 }
317
318 /*
319   helper for talloc_reference()
320
321   this is referenced by a function pointer and should not be inline
322 */
323 static int talloc_reference_destructor(struct talloc_reference_handle *handle)
324 {
325         struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
326         _TLIST_REMOVE(ptr_tc->refs, handle);
327         return 0;
328 }
329
330 /*
331    more efficient way to add a name to a pointer - the name must point to a 
332    true string constant
333 */
334 static inline void _talloc_set_name_const(const void *ptr, const char *name)
335 {
336         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
337         tc->name = name;
338 }
339
340 /*
341   internal talloc_named_const()
342 */
343 static inline void *_talloc_named_const(const void *context, size_t size, const char *name)
344 {
345         void *ptr;
346
347         ptr = __talloc(context, size);
348         if (unlikely(ptr == NULL)) {
349                 return NULL;
350         }
351
352         _talloc_set_name_const(ptr, name);
353
354         return ptr;
355 }
356
357 /*
358   make a secondary reference to a pointer, hanging off the given context.
359   the pointer remains valid until both the original caller and this given
360   context are freed.
361   
362   the major use for this is when two different structures need to reference the 
363   same underlying data, and you want to be able to free the two instances separately,
364   and in either order
365 */
366 void *_talloc_reference(const void *context, const void *ptr)
367 {
368         struct talloc_chunk *tc;
369         struct talloc_reference_handle *handle;
370         if (unlikely(ptr == NULL)) return NULL;
371
372         lock(context);
373         tc = talloc_chunk_from_ptr(ptr);
374         handle = (struct talloc_reference_handle *)_talloc_named_const(context,
375                                                    sizeof(struct talloc_reference_handle),
376                                                    TALLOC_MAGIC_REFERENCE);
377         if (unlikely(handle == NULL)) {
378                 unlock();
379                 return NULL;
380         }
381
382         /* note that we hang the destructor off the handle, not the
383            main context as that allows the caller to still setup their
384            own destructor on the context if they want to */
385         talloc_set_destructor(handle, talloc_reference_destructor);
386         handle->ptr = discard_const_p(void, ptr);
387         _TLIST_ADD(tc->refs, handle);
388         unlock();
389         return handle->ptr;
390 }
391
392 /*
393   return 1 if ptr is a parent of context
394 */
395 static int _talloc_is_parent(const void *context, const void *ptr)
396 {
397         struct talloc_chunk *tc;
398
399         if (context == NULL) {
400                 return 0;
401         }
402
403         tc = talloc_chunk_from_ptr(context);
404         while (tc) {
405                 if (TC_PTR_FROM_CHUNK(tc) == ptr) {
406                         return 1;
407                 }
408                 while (tc && tc->prev) tc = tc->prev;
409                 if (tc) {
410                         tc = tc->parent;
411                 }
412         }
413         return 0;
414 }
415
416 /* 
417    move a lump of memory from one talloc context to another return the
418    ptr on success, or NULL if it could not be transferred.
419    passing NULL as ptr will always return NULL with no side effects.
420 */
421 static void *__talloc_steal(const void *new_ctx, const void *ptr)
422 {
423         struct talloc_chunk *tc, *new_tc;
424
425         if (unlikely(!ptr)) {
426                 return NULL;
427         }
428
429         if (unlikely(new_ctx == NULL)) {
430                 new_ctx = null_context;
431         }
432
433         tc = talloc_chunk_from_ptr(ptr);
434
435         if (unlikely(new_ctx == NULL)) {
436                 if (tc->parent) {
437                         _TLIST_REMOVE(tc->parent->child, tc);
438                         if (tc->parent->child) {
439                                 tc->parent->child->parent = tc->parent;
440                         }
441                 } else {
442                         if (tc->prev) tc->prev->next = tc->next;
443                         if (tc->next) tc->next->prev = tc->prev;
444                 }
445                 
446                 tc->parent = tc->next = tc->prev = NULL;
447                 return discard_const_p(void, ptr);
448         }
449
450         new_tc = talloc_chunk_from_ptr(new_ctx);
451
452         if (unlikely(tc == new_tc || tc->parent == new_tc)) {
453                 return discard_const_p(void, ptr);
454         }
455
456         if (tc->parent) {
457                 _TLIST_REMOVE(tc->parent->child, tc);
458                 if (tc->parent->child) {
459                         tc->parent->child->parent = tc->parent;
460                 }
461         } else {
462                 if (tc->prev) tc->prev->next = tc->next;
463                 if (tc->next) tc->next->prev = tc->prev;
464         }
465
466         tc->parent = new_tc;
467         if (new_tc->child) new_tc->child->parent = NULL;
468         _TLIST_ADD(new_tc->child, tc);
469
470         return discard_const_p(void, ptr);
471 }
472
473 /* 
474    internal talloc_free call
475 */
476 static inline int _talloc_free(const void *ptr)
477 {
478         struct talloc_chunk *tc;
479         void *oldparent = NULL;
480
481         if (unlikely(ptr == NULL)) {
482                 return -1;
483         }
484
485         tc = talloc_chunk_from_ptr(ptr);
486
487         if (unlikely(tc->refs)) {
488                 int is_child;
489                 /* check this is a reference from a child or grantchild
490                  * back to it's parent or grantparent
491                  *
492                  * in that case we need to remove the reference and
493                  * call another instance of talloc_free() on the current
494                  * pointer.
495                  */
496                 is_child = _talloc_is_parent(tc->refs, ptr);
497                 _talloc_free(tc->refs);
498                 if (is_child) {
499                         return _talloc_free(ptr);
500                 }
501                 return -1;
502         }
503
504         if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) {
505                 /* we have a free loop - stop looping */
506                 return 0;
507         }
508
509         if (unlikely(tc->destructor)) {
510                 talloc_destructor_t d = tc->destructor;
511                 if (d == (talloc_destructor_t)-1) {
512                         return -1;
513                 }
514                 tc->destructor = (talloc_destructor_t)-1;
515                 if (d(discard_const_p(void, ptr)) == -1) {
516                         tc->destructor = d;
517                         return -1;
518                 }
519                 tc->destructor = NULL;
520         }
521
522         if (unlikely(tc->flags & TALLOC_FLAG_EXT_ALLOC))
523                 oldparent = talloc_parent_nolock(ptr);
524
525         if (tc->parent) {
526                 _TLIST_REMOVE(tc->parent->child, tc);
527                 if (tc->parent->child) {
528                         tc->parent->child->parent = tc->parent;
529                 }
530         } else {
531                 if (tc->prev) tc->prev->next = tc->next;
532                 if (tc->next) tc->next->prev = tc->prev;
533         }
534
535         tc->flags |= TALLOC_FLAG_LOOP;
536
537         while (tc->child) {
538                 /* we need to work out who will own an abandoned child
539                    if it cannot be freed. In priority order, the first
540                    choice is owner of any remaining reference to this
541                    pointer, the second choice is our parent, and the
542                    final choice is the null context. */
543                 void *child = TC_PTR_FROM_CHUNK(tc->child);
544                 const void *new_parent = null_context;
545                 struct talloc_chunk *old_parent = NULL;
546                 if (unlikely(tc->child->refs)) {
547                         struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
548                         if (p) new_parent = TC_PTR_FROM_CHUNK(p);
549                 }
550                 /* finding the parent here is potentially quite
551                    expensive, but the alternative, which is to change
552                    talloc to always have a valid tc->parent pointer,
553                    makes realloc more expensive where there are a
554                    large number of children.
555
556                    The reason we need the parent pointer here is that
557                    if _talloc_free_internal() fails due to references
558                    or a failing destructor we need to re-parent, but
559                    the free call can invalidate the prev pointer.
560                 */
561                 if (new_parent == null_context && (tc->child->refs || tc->child->destructor)) {
562                         old_parent = talloc_parent_chunk(ptr);
563                 }
564                 if (unlikely(_talloc_free(child) == -1)) {
565                         if (new_parent == null_context) {
566                                 struct talloc_chunk *p = old_parent;
567                                 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
568                         }
569                         __talloc_steal(new_parent, child);
570                 }
571         }
572
573         tc->flags |= TALLOC_FLAG_FREE;
574
575         if (unlikely(tc->flags & TALLOC_FLAG_EXT_ALLOC))
576                 tc_external_realloc(oldparent, tc, 0);
577         else
578                 tc_free(tc);
579
580         return 0;
581 }
582
583 void *_talloc_steal(const void *new_ctx, const void *ptr)
584 {
585         void *p;
586
587         lock(new_ctx);
588         p = __talloc_steal(new_ctx, ptr);
589         unlock();
590         return p;
591 }
592
593 /*
594   remove a secondary reference to a pointer. This undo's what
595   talloc_reference() has done. The context and pointer arguments
596   must match those given to a talloc_reference()
597 */
598 static inline int talloc_unreference(const void *context, const void *ptr)
599 {
600         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
601         struct talloc_reference_handle *h;
602
603         if (unlikely(context == NULL)) {
604                 context = null_context;
605         }
606
607         for (h=tc->refs;h;h=h->next) {
608                 struct talloc_chunk *p = talloc_parent_chunk(h);
609                 if (p == NULL) {
610                         if (context == NULL) break;
611                 } else if (TC_PTR_FROM_CHUNK(p) == context) {
612                         break;
613                 }
614         }
615         if (h == NULL) {
616                 return -1;
617         }
618
619         return _talloc_free(h);
620 }
621
622 /*
623   remove a specific parent context from a pointer. This is a more
624   controlled varient of talloc_free()
625 */
626 int talloc_unlink(const void *context, void *ptr)
627 {
628         struct talloc_chunk *tc_p, *new_p;
629         void *new_parent;
630
631         if (ptr == NULL) {
632                 return -1;
633         }
634
635         if (context == NULL) {
636                 context = null_context;
637         }
638
639         lock(context);
640         if (talloc_unreference(context, ptr) == 0) {
641                 unlock();
642                 return 0;
643         }
644
645         if (context == NULL) {
646                 if (talloc_parent_chunk(ptr) != NULL) {
647                         unlock();
648                         return -1;
649                 }
650         } else {
651                 if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) {
652                         unlock();
653                         return -1;
654                 }
655         }
656         
657         tc_p = talloc_chunk_from_ptr(ptr);
658
659         if (tc_p->refs == NULL) {
660                 int ret = _talloc_free(ptr);
661                 unlock();
662                 return ret;
663         }
664
665         new_p = talloc_parent_chunk(tc_p->refs);
666         if (new_p) {
667                 new_parent = TC_PTR_FROM_CHUNK(new_p);
668         } else {
669                 new_parent = NULL;
670         }
671
672         if (talloc_unreference(new_parent, ptr) != 0) {
673                 unlock();
674                 return -1;
675         }
676
677         __talloc_steal(new_parent, ptr);
678         unlock();
679
680         return 0;
681 }
682
683 /*
684   add a name to an existing pointer - va_list version
685 */
686 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_FMT(2,0);
687
688 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
689 {
690         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
691         tc->name = talloc_vasprintf(ptr, fmt, ap);
692         if (likely(tc->name)) {
693                 _talloc_set_name_const(tc->name, ".name");
694         }
695         return tc->name;
696 }
697
698 /*
699   add a name to an existing pointer
700 */
701 const char *talloc_set_name(const void *ptr, const char *fmt, ...)
702 {
703         const char *name;
704         va_list ap;
705         va_start(ap, fmt);
706         name = talloc_set_name_v(ptr, fmt, ap);
707         va_end(ap);
708         return name;
709 }
710
711
712 /*
713   create a named talloc pointer. Any talloc pointer can be named, and
714   talloc_named() operates just like talloc() except that it allows you
715   to name the pointer.
716 */
717 void *talloc_named(const void *context, size_t size, const char *fmt, ...)
718 {
719         va_list ap;
720         void *ptr;
721         const char *name;
722
723         lock(context);
724         ptr = __talloc(context, size);
725         unlock();
726         if (unlikely(ptr == NULL)) return NULL;
727
728         va_start(ap, fmt);
729         name = talloc_set_name_v(ptr, fmt, ap);
730         va_end(ap);
731
732         if (unlikely(name == NULL)) {
733                 talloc_free(ptr);
734                 return NULL;
735         }
736
737         return ptr;
738 }
739
740 /*
741   return the name of a talloc ptr, or "UNNAMED"
742 */
743 const char *talloc_get_name(const void *ptr)
744 {
745         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
746         if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
747                 return ".reference";
748         }
749         if (likely(tc->name)) {
750                 return tc->name;
751         }
752         return "UNNAMED";
753 }
754
755
756 /*
757   check if a pointer has the given name. If it does, return the pointer,
758   otherwise return NULL
759 */
760 void *talloc_check_name(const void *ptr, const char *name)
761 {
762         const char *pname;
763         if (unlikely(ptr == NULL)) return NULL;
764         pname = talloc_get_name(ptr);
765         if (likely(pname == name || strcmp(pname, name) == 0)) {
766                 return discard_const_p(void, ptr);
767         }
768         return NULL;
769 }
770
771
772 /*
773   this is for compatibility with older versions of talloc
774 */
775 void *talloc_init(const char *fmt, ...)
776 {
777         va_list ap;
778         void *ptr;
779         const char *name;
780
781         /*
782          * samba3 expects talloc_report_depth_cb(NULL, ...)
783          * reports all talloc'ed memory, so we need to enable
784          * null_tracking
785          */
786         talloc_enable_null_tracking();
787
788         ptr = __talloc(NULL, 0);
789         if (unlikely(ptr == NULL)) return NULL;
790
791         va_start(ap, fmt);
792         name = talloc_set_name_v(ptr, fmt, ap);
793         va_end(ap);
794
795         if (unlikely(name == NULL)) {
796                 talloc_free(ptr);
797                 return NULL;
798         }
799
800         return ptr;
801 }
802
803 /* 
804    Allocate a bit of memory as a child of an existing pointer
805 */
806 void *_talloc(const void *context, size_t size)
807 {
808         return __talloc(context, size);
809 }
810
811 static int talloc_destroy_pointer(void ***pptr)
812 {
813         if ((uintptr_t)**pptr < getpagesize())
814                 TALLOC_ABORT("Double free or invalid talloc_set?");
815         /* Invalidate pointer so it can't be used again. */
816         **pptr = (void *)1;
817         return 0;
818 }
819
820 void _talloc_set(void *ptr, const void *ctx, size_t size, const char *name)
821 {
822         void ***child;
823         void *p;
824
825         p = talloc_named_const(ctx, size, name);
826         if (unlikely(!p))
827                 goto set_ptr;
828
829         child = talloc(p, void **);
830         if (unlikely(!child)) {
831                 talloc_free(p);
832                 p = NULL;
833                 goto set_ptr;
834         }
835         *child = ptr;
836         talloc_set_name_const(child, "talloc_set destructor");
837         talloc_set_destructor(child, talloc_destroy_pointer);
838
839 set_ptr:
840         /* memcpy rather than cast avoids aliasing problems. */
841         memcpy(ptr, &p, sizeof(p));
842 }
843
844 /*
845   externally callable talloc_set_name_const()
846 */
847 void talloc_set_name_const(const void *ptr, const char *name)
848 {
849         _talloc_set_name_const(ptr, name);
850 }
851
852 /*
853   create a named talloc pointer. Any talloc pointer can be named, and
854   talloc_named() operates just like talloc() except that it allows you
855   to name the pointer.
856 */
857 void *talloc_named_const(const void *context, size_t size, const char *name)
858 {
859         void *p;
860         lock(context);
861         p = _talloc_named_const(context, size, name);
862         unlock();
863         return p;
864 }
865
866 /* 
867    free a talloc pointer. This also frees all child pointers of this 
868    pointer recursively
869
870    return 0 if the memory is actually freed, otherwise -1. The memory
871    will not be freed if the ref_count is > 1 or the destructor (if
872    any) returns non-zero
873 */
874 int talloc_free(const void *ptr)
875 {
876         int saved_errno = errno, ret;
877
878         lock(ptr);
879         ret = _talloc_free(discard_const_p(void, ptr));
880         unlock();
881         if (ret == 0)
882                 errno = saved_errno;
883         return ret;
884 }
885
886
887
888 /*
889   A talloc version of realloc. The context argument is only used if
890   ptr is NULL
891 */
892 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
893 {
894         struct talloc_chunk *tc;
895         void *new_ptr;
896
897         /* size zero is equivalent to free() */
898         if (unlikely(size == 0)) {
899                 talloc_free(ptr);
900                 return NULL;
901         }
902
903         if (unlikely(size >= MAX_TALLOC_SIZE)) {
904                 return NULL;
905         }
906
907         /* realloc(NULL) is equivalent to malloc() */
908         if (ptr == NULL) {
909                 return talloc_named_const(context, size, name);
910         }
911
912         tc = talloc_chunk_from_ptr(ptr);
913
914         /* don't allow realloc on referenced pointers */
915         if (unlikely(tc->refs)) {
916                 return NULL;
917         }
918
919         lock(ptr);
920         if (unlikely(tc->flags & TALLOC_FLAG_EXT_ALLOC)) {
921                 /* need to get parent before setting free flag. */
922                 void *parent = talloc_parent_nolock(ptr);
923                 tc->flags |= TALLOC_FLAG_FREE;
924                 new_ptr = tc_external_realloc(parent, tc, size + TC_HDR_SIZE);
925         } else {
926                 /* by resetting magic we catch users of the old memory */
927                 tc->flags |= TALLOC_FLAG_FREE;
928
929 #if ALWAYS_REALLOC
930                 new_ptr = tc_malloc(size + TC_HDR_SIZE);
931                 if (new_ptr) {
932                         memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE);
933                         tc_free(tc);
934                 }
935 #else
936                 new_ptr = tc_realloc(tc, size + TC_HDR_SIZE);
937 #endif
938         }
939
940         if (unlikely(!new_ptr)) {       
941                 tc->flags &= ~TALLOC_FLAG_FREE; 
942                 unlock();
943                 return NULL; 
944         }
945
946         tc = (struct talloc_chunk *)new_ptr;
947         tc->flags &= ~TALLOC_FLAG_FREE; 
948         if (tc->parent) {
949                 tc->parent->child = tc;
950         }
951         if (tc->child) {
952                 tc->child->parent = tc;
953         }
954
955         if (tc->prev) {
956                 tc->prev->next = tc;
957         }
958         if (tc->next) {
959                 tc->next->prev = tc;
960         }
961
962         tc->size = size;
963         _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
964         unlock();
965
966         return TC_PTR_FROM_CHUNK(tc);
967 }
968
969 /*
970   a wrapper around talloc_steal() for situations where you are moving a pointer
971   between two structures, and want the old pointer to be set to NULL
972 */
973 void *_talloc_move(const void *new_ctx, const void *_pptr)
974 {
975         const void **pptr = discard_const_p(const void *,_pptr);
976         void *ret = _talloc_steal(new_ctx, *pptr);
977         (*pptr) = NULL;
978         return ret;
979 }
980
981 /*
982   return the total size of a talloc pool (subtree)
983 */
984 static size_t _talloc_total_size(const void *ptr)
985 {
986         size_t total = 0;
987         struct talloc_chunk *c, *tc;
988
989         tc = talloc_chunk_from_ptr(ptr);
990
991         if (tc->flags & TALLOC_FLAG_LOOP) {
992                 return 0;
993         }
994
995         tc->flags |= TALLOC_FLAG_LOOP;
996
997         total = tc->size;
998         for (c=tc->child;c;c=c->next) {
999                 total += _talloc_total_size(TC_PTR_FROM_CHUNK(c));
1000         }
1001
1002         tc->flags &= ~TALLOC_FLAG_LOOP;
1003
1004         return total;
1005 }
1006
1007 size_t talloc_total_size(const void *ptr)
1008 {
1009         size_t total;
1010
1011         if (ptr == NULL) {
1012                 ptr = null_context;
1013         }
1014         if (ptr == NULL) {
1015                 return 0;
1016         }
1017
1018         lock(ptr);
1019         total = _talloc_total_size(ptr);
1020         unlock();
1021         return total;
1022 }       
1023
1024 /*
1025   return the total number of blocks in a talloc pool (subtree)
1026 */
1027 static size_t _talloc_total_blocks(const void *ptr)
1028 {
1029         size_t total = 0;
1030         struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
1031
1032         if (tc->flags & TALLOC_FLAG_LOOP) {
1033                 return 0;
1034         }
1035
1036         tc->flags |= TALLOC_FLAG_LOOP;
1037
1038         total++;
1039         for (c=tc->child;c;c=c->next) {
1040                 total += _talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
1041         }
1042
1043         tc->flags &= ~TALLOC_FLAG_LOOP;
1044
1045         return total;
1046 }
1047
1048 size_t talloc_total_blocks(const void *ptr)
1049 {
1050         size_t total;
1051
1052         lock(ptr);
1053         total = _talloc_total_blocks(ptr);
1054         unlock();
1055
1056         return total;
1057 }
1058
1059 static size_t _talloc_reference_count(const void *ptr)
1060 {
1061         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1062         struct talloc_reference_handle *h;
1063         size_t ret = 0;
1064
1065         for (h=tc->refs;h;h=h->next) {
1066                 ret++;
1067         }
1068         return ret;
1069 }
1070
1071 /*
1072   return the number of external references to a pointer
1073 */
1074 size_t talloc_reference_count(const void *ptr)
1075 {
1076         size_t ret;
1077
1078         lock(talloc_chunk_from_ptr(ptr));
1079         ret = _talloc_reference_count(ptr);
1080         unlock();
1081         return ret;
1082 }
1083
1084 /*
1085   report on memory usage by all children of a pointer, giving a full tree view
1086 */
1087 static void _talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
1088                             void (*callback)(const void *ptr,
1089                                              int depth, int max_depth,
1090                                              int is_ref,
1091                                              void *private_data),
1092                             void *private_data)
1093 {
1094         struct talloc_chunk *c, *tc;
1095
1096         tc = talloc_chunk_from_ptr(ptr);
1097
1098         if (tc->flags & TALLOC_FLAG_LOOP) {
1099                 return;
1100         }
1101
1102         callback(ptr, depth, max_depth, 0, private_data);
1103
1104         if (max_depth >= 0 && depth >= max_depth) {
1105                 return;
1106         }
1107
1108         tc->flags |= TALLOC_FLAG_LOOP;
1109         for (c=tc->child;c;c=c->next) {
1110                 if (c->name == TALLOC_MAGIC_REFERENCE) {
1111                         struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
1112                         callback(h->ptr, depth + 1, max_depth, 1, private_data);
1113                 } else {
1114                         _talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
1115                 }
1116         }
1117         tc->flags &= ~TALLOC_FLAG_LOOP;
1118 }
1119
1120 void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
1121                             void (*callback)(const void *ptr,
1122                                              int depth, int max_depth,
1123                                              int is_ref,
1124                                              void *private_data),
1125                             void *private_data)
1126 {
1127         if (ptr == NULL) {
1128                 ptr = null_context;
1129         }
1130         if (ptr == NULL) return;
1131
1132         lock(ptr);
1133         _talloc_report_depth_cb(ptr, depth, max_depth, callback, private_data);
1134         unlock();
1135 }
1136
1137 static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
1138 {
1139         const char *name = talloc_get_name(ptr);
1140         FILE *f = (FILE *)_f;
1141
1142         if (is_ref) {
1143                 fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
1144                 return;
1145         }
1146
1147         if (depth == 0) {
1148                 fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n", 
1149                         (max_depth < 0 ? "full " :""), name,
1150                         (unsigned long)_talloc_total_size(ptr),
1151                         (unsigned long)_talloc_total_blocks(ptr));
1152                 return;
1153         }
1154
1155         fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n", 
1156                 depth*4, "",
1157                 name,
1158                 (unsigned long)_talloc_total_size(ptr),
1159                 (unsigned long)_talloc_total_blocks(ptr),
1160                 (int)_talloc_reference_count(ptr), ptr);
1161
1162 #if 0
1163         fprintf(f, "content: ");
1164         if (talloc_total_size(ptr)) {
1165                 int tot = talloc_total_size(ptr);
1166                 int i;
1167
1168                 for (i = 0; i < tot; i++) {
1169                         if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
1170                                 fprintf(f, "%c", ((char *)ptr)[i]);
1171                         } else {
1172                                 fprintf(f, "~%02x", ((char *)ptr)[i]);
1173                         }
1174                 }
1175         }
1176         fprintf(f, "\n");
1177 #endif
1178 }
1179
1180 /*
1181   report on memory usage by all children of a pointer, giving a full tree view
1182 */
1183 void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
1184 {
1185         talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
1186         fflush(f);
1187 }
1188
1189 /*
1190   report on memory usage by all children of a pointer, giving a full tree view
1191 */
1192 void talloc_report_full(const void *ptr, FILE *f)
1193 {
1194         talloc_report_depth_file(ptr, 0, -1, f);
1195 }
1196
1197 /*
1198   report on memory usage by all children of a pointer
1199 */
1200 void talloc_report(const void *ptr, FILE *f)
1201 {
1202         talloc_report_depth_file(ptr, 0, 1, f);
1203 }
1204
1205 /*
1206   report on any memory hanging off the null context
1207 */
1208 static void talloc_report_null(void)
1209 {
1210         if (talloc_total_size(null_context) != 0) {
1211                 talloc_report(null_context, stderr);
1212         }
1213 }
1214
1215 /*
1216   report on any memory hanging off the null context
1217 */
1218 static void talloc_report_null_full(void)
1219 {
1220         if (talloc_total_size(null_context) != 0) {
1221                 talloc_report_full(null_context, stderr);
1222         }
1223 }
1224
1225 /*
1226   enable tracking of the NULL context
1227 */
1228 void talloc_enable_null_tracking(void)
1229 {
1230         if (null_context == NULL) {
1231                 null_context = _talloc_named_const(NULL, 0, "null_context");
1232         }
1233 }
1234
1235 /*
1236   disable tracking of the NULL context
1237 */
1238 void talloc_disable_null_tracking(void)
1239 {
1240         _talloc_free(null_context);
1241         null_context = NULL;
1242 }
1243
1244 /*
1245   enable leak reporting on exit
1246 */
1247 void talloc_enable_leak_report(void)
1248 {
1249         talloc_enable_null_tracking();
1250         atexit(talloc_report_null);
1251 }
1252
1253 /*
1254   enable full leak reporting on exit
1255 */
1256 void talloc_enable_leak_report_full(void)
1257 {
1258         talloc_enable_null_tracking();
1259         atexit(talloc_report_null_full);
1260 }
1261
1262 /* 
1263    talloc and zero memory. 
1264 */
1265 void *_talloc_zero(const void *ctx, size_t size, const char *name)
1266 {
1267         void *p;
1268
1269         lock(ctx);
1270         p = _talloc_named_const(ctx, size, name);
1271         unlock();
1272
1273         if (p) {
1274                 memset(p, '\0', size);
1275         }
1276
1277         return p;
1278 }
1279
1280 /*
1281   memdup with a talloc. 
1282 */
1283 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
1284 {
1285         void *newp;
1286
1287         lock(t);
1288         newp = _talloc_named_const(t, size, name);
1289         unlock();
1290
1291         if (likely(newp)) {
1292                 memcpy(newp, p, size);
1293         }
1294
1295         return newp;
1296 }
1297
1298 /*
1299   strdup with a talloc 
1300 */
1301 char *talloc_strdup(const void *t, const char *p)
1302 {
1303         char *ret;
1304         if (!p) {
1305                 return NULL;
1306         }
1307         ret = (char *)talloc_memdup(t, p, strlen(p) + 1);
1308         if (likely(ret)) {
1309                 _talloc_set_name_const(ret, ret);
1310         }
1311         return ret;
1312 }
1313
1314 /*
1315  append to a talloced string 
1316 */
1317 char *talloc_append_string(char *orig, const char *append)
1318 {
1319         char *ret;
1320         size_t olen = strlen(orig);
1321         size_t alenz;
1322
1323         if (!append)
1324                 return orig;
1325
1326         alenz = strlen(append) + 1;
1327
1328         ret = talloc_realloc(NULL, orig, char, olen + alenz);
1329         if (!ret)
1330                 return NULL;
1331
1332         /* append the string with the trailing \0 */
1333         memcpy(&ret[olen], append, alenz);
1334
1335         _talloc_set_name_const(ret, ret);
1336
1337         return ret;
1338 }
1339
1340 /*
1341   strndup with a talloc 
1342 */
1343 char *talloc_strndup(const void *t, const char *p, size_t n)
1344 {
1345         size_t len;
1346         char *ret;
1347
1348         for (len=0; len<n && p[len]; len++) ;
1349
1350         lock(t);
1351         ret = (char *)__talloc(t, len + 1);
1352         unlock();
1353         if (!ret) { return NULL; }
1354         memcpy(ret, p, len);
1355         ret[len] = 0;
1356         _talloc_set_name_const(ret, ret);
1357         return ret;
1358 }
1359
1360 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
1361 {       
1362         int len;
1363         char *ret;
1364         va_list ap2;
1365         char c;
1366         
1367         /* this call looks strange, but it makes it work on older solaris boxes */
1368         va_copy(ap2, ap);
1369         len = vsnprintf(&c, 1, fmt, ap2);
1370         va_end(ap2);
1371         if (len < 0) {
1372                 return NULL;
1373         }
1374
1375         lock(t);
1376         ret = (char *)__talloc(t, len+1);
1377         unlock();
1378         if (ret) {
1379                 va_copy(ap2, ap);
1380                 vsnprintf(ret, len+1, fmt, ap2);
1381                 va_end(ap2);
1382                 _talloc_set_name_const(ret, ret);
1383         }
1384
1385         return ret;
1386 }
1387
1388
1389 /*
1390   Perform string formatting, and return a pointer to newly allocated
1391   memory holding the result, inside a memory pool.
1392  */
1393 char *talloc_asprintf(const void *t, const char *fmt, ...)
1394 {
1395         va_list ap;
1396         char *ret;
1397
1398         va_start(ap, fmt);
1399         ret = talloc_vasprintf(t, fmt, ap);
1400         va_end(ap);
1401         return ret;
1402 }
1403
1404
1405 /**
1406  * Realloc @p s to append the formatted result of @p fmt and @p ap,
1407  * and return @p s, which may have moved.  Good for gradually
1408  * accumulating output into a string buffer.
1409  **/
1410 char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1411 {       
1412         struct talloc_chunk *tc;
1413         int len, s_len;
1414         va_list ap2;
1415         char c;
1416
1417         if (s == NULL) {
1418                 return talloc_vasprintf(NULL, fmt, ap);
1419         }
1420
1421         tc = talloc_chunk_from_ptr(s);
1422
1423         s_len = tc->size - 1;
1424
1425         va_copy(ap2, ap);
1426         len = vsnprintf(&c, 1, fmt, ap2);
1427         va_end(ap2);
1428
1429         if (len <= 0) {
1430                 /* Either the vsnprintf failed or the format resulted in
1431                  * no characters being formatted. In the former case, we
1432                  * ought to return NULL, in the latter we ought to return
1433                  * the original string. Most current callers of this 
1434                  * function expect it to never return NULL.
1435                  */
1436                 return s;
1437         }
1438
1439         s = talloc_realloc(NULL, s, char, s_len + len+1);
1440         if (!s) return NULL;
1441
1442         va_copy(ap2, ap);
1443         vsnprintf(s+s_len, len+1, fmt, ap2);
1444         va_end(ap2);
1445         _talloc_set_name_const(s, s);
1446
1447         return s;
1448 }
1449
1450 /*
1451   Realloc @p s to append the formatted result of @p fmt and return @p
1452   s, which may have moved.  Good for gradually accumulating output
1453   into a string buffer.
1454  */
1455 char *talloc_asprintf_append(char *s, const char *fmt, ...)
1456 {
1457         va_list ap;
1458
1459         va_start(ap, fmt);
1460         s = talloc_vasprintf_append(s, fmt, ap);
1461         va_end(ap);
1462         return s;
1463 }
1464
1465 /*
1466   alloc an array, checking for integer overflow in the array size
1467 */
1468 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1469 {
1470         void *p;
1471
1472         if (count >= MAX_TALLOC_SIZE/el_size) {
1473                 return NULL;
1474         }
1475         lock(ctx);
1476         p = _talloc_named_const(ctx, el_size * count, name);
1477         unlock();
1478         return p;
1479 }
1480
1481 /*
1482   alloc an zero array, checking for integer overflow in the array size
1483 */
1484 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1485 {
1486         void *p;
1487
1488         if (count >= MAX_TALLOC_SIZE/el_size) {
1489                 return NULL;
1490         }
1491         p = _talloc_zero(ctx, el_size * count, name);
1492         return p;
1493 }
1494
1495 /*
1496   realloc an array, checking for integer overflow in the array size
1497 */
1498 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
1499 {
1500         if (count >= MAX_TALLOC_SIZE/el_size) {
1501                 return NULL;
1502         }
1503         return _talloc_realloc(ctx, ptr, el_size * count, name);
1504 }
1505
1506 /*
1507   a function version of talloc_realloc(), so it can be passed as a function pointer
1508   to libraries that want a realloc function (a realloc function encapsulates
1509   all the basic capabilities of an allocation library, which is why this is useful)
1510 */
1511 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1512 {
1513         return _talloc_realloc(context, ptr, size, NULL);
1514 }
1515
1516
1517 static int talloc_autofree_destructor(void *ptr)
1518 {
1519         autofree_context = NULL;
1520         return 0;
1521 }
1522
1523 static void talloc_autofree(void)
1524 {
1525         if (autofree_context && *autofree_context == getpid())
1526                 talloc_free(autofree_context);
1527 }
1528
1529 /*
1530   return a context which will be auto-freed on exit
1531   this is useful for reducing the noise in leak reports
1532 */
1533 void *talloc_autofree_context(void)
1534 {
1535         if (autofree_context == NULL || *autofree_context != getpid()) {
1536                 autofree_context = talloc(NULL, pid_t);
1537                 *autofree_context = getpid();
1538                 talloc_set_name_const(autofree_context, "autofree_context");
1539                 
1540                 talloc_set_destructor(autofree_context, talloc_autofree_destructor);
1541                 atexit(talloc_autofree);
1542         }
1543         return autofree_context;
1544 }
1545
1546 size_t talloc_get_size(const void *context)
1547 {
1548         struct talloc_chunk *tc;
1549
1550         if (context == NULL)
1551                 return 0;
1552
1553         tc = talloc_chunk_from_ptr(context);
1554
1555         return tc->size;
1556 }
1557
1558 /*
1559   find a parent of this context that has the given name, if any
1560 */
1561 void *talloc_find_parent_byname(const void *context, const char *name)
1562 {
1563         struct talloc_chunk *tc;
1564
1565         if (context == NULL) {
1566                 return NULL;
1567         }
1568
1569         lock(context);
1570         tc = talloc_chunk_from_ptr(context);
1571         while (tc) {
1572                 if (tc->name && strcmp(tc->name, name) == 0) {
1573                         unlock();
1574                         return TC_PTR_FROM_CHUNK(tc);
1575                 }
1576                 while (tc && tc->prev) tc = tc->prev;
1577                 if (tc) {
1578                         tc = tc->parent;
1579                 }
1580         }
1581         unlock();
1582         return NULL;
1583 }
1584
1585 /*
1586   show the parentage of a context
1587 */
1588 void talloc_show_parents(const void *context, FILE *file)
1589 {
1590         struct talloc_chunk *tc;
1591
1592         if (context == NULL) {
1593                 fprintf(file, "talloc no parents for NULL\n");
1594                 return;
1595         }
1596
1597         lock(context);
1598         tc = talloc_chunk_from_ptr(context);
1599         fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
1600         while (tc) {
1601                 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
1602                 while (tc && tc->prev) tc = tc->prev;
1603                 if (tc) {
1604                         tc = tc->parent;
1605                 }
1606         }
1607         unlock();
1608         fflush(file);
1609 }
1610
1611 int talloc_is_parent(const void *context, const void *ptr)
1612 {
1613         int ret;
1614         lock(context);
1615         ret = _talloc_is_parent(context, ptr);
1616         unlock();
1617         return ret;
1618 }
1619
1620 void talloc_set_allocator(void *(*malloc)(size_t size),
1621                           void (*free)(void *ptr),
1622                           void *(*realloc)(void *ptr, size_t size))
1623 {
1624         tc_malloc = malloc;
1625         tc_free = free;
1626         tc_realloc = realloc;
1627 }
1628
1629 void *talloc_add_external(const void *ctx,
1630                           void *(*realloc)(const void *, void *, size_t),
1631                           void (*lock)(const void *p),
1632                           void (*unlock)(void))
1633 {
1634         struct talloc_chunk *tc, *parent;
1635         void *p;
1636
1637         if (tc_external_realloc && tc_external_realloc != realloc)
1638                 TALLOC_ABORT("talloc_add_external realloc replaced");
1639         tc_external_realloc = realloc;
1640
1641         if (unlikely(ctx == NULL)) {
1642                 ctx = null_context;
1643                 parent = NULL;
1644         } else
1645                 parent = talloc_chunk_from_ptr(ctx);    
1646
1647         tc = tc_external_realloc(ctx, NULL, TC_HDR_SIZE);
1648         p = init_talloc(parent, tc, 0, 1);
1649         tc_lock = lock;
1650         tc_unlock = unlock;
1651
1652         return p;
1653 }