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