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