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