r18435: added a function talloc_move() which is like talloc_steal(), but is
[samba.git] / source4 / 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         void *ret = _talloc_steal(new_ctx, *pptr);
747         (*pptr) = NULL;
748         return ret;
749 }
750
751 /*
752   return the total size of a talloc pool (subtree)
753 */
754 size_t talloc_total_size(const void *ptr)
755 {
756         size_t total = 0;
757         struct talloc_chunk *c, *tc;
758
759         if (ptr == NULL) {
760                 ptr = null_context;
761         }
762         if (ptr == NULL) {
763                 return 0;
764         }
765
766         tc = talloc_chunk_from_ptr(ptr);
767
768         if (tc->flags & TALLOC_FLAG_LOOP) {
769                 return 0;
770         }
771
772         tc->flags |= TALLOC_FLAG_LOOP;
773
774         total = tc->size;
775         for (c=tc->child;c;c=c->next) {
776                 total += talloc_total_size(TC_PTR_FROM_CHUNK(c));
777         }
778
779         tc->flags &= ~TALLOC_FLAG_LOOP;
780
781         return total;
782 }
783
784 /*
785   return the total number of blocks in a talloc pool (subtree)
786 */
787 size_t talloc_total_blocks(const void *ptr)
788 {
789         size_t total = 0;
790         struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
791
792         if (tc->flags & TALLOC_FLAG_LOOP) {
793                 return 0;
794         }
795
796         tc->flags |= TALLOC_FLAG_LOOP;
797
798         total++;
799         for (c=tc->child;c;c=c->next) {
800                 total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
801         }
802
803         tc->flags &= ~TALLOC_FLAG_LOOP;
804
805         return total;
806 }
807
808 /*
809   return the number of external references to a pointer
810 */
811 size_t talloc_reference_count(const void *ptr)
812 {
813         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
814         struct talloc_reference_handle *h;
815         size_t ret = 0;
816
817         for (h=tc->refs;h;h=h->next) {
818                 ret++;
819         }
820         return ret;
821 }
822
823 /*
824   report on memory usage by all children of a pointer, giving a full tree view
825 */
826 void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
827                             void (*callback)(const void *ptr,
828                                              int depth, int max_depth,
829                                              int is_ref,
830                                              void *private_data),
831                             void *private_data)
832 {
833         struct talloc_chunk *c, *tc;
834
835         if (ptr == NULL) {
836                 ptr = null_context;
837         }
838         if (ptr == NULL) return;
839
840         tc = talloc_chunk_from_ptr(ptr);
841
842         if (tc->flags & TALLOC_FLAG_LOOP) {
843                 return;
844         }
845
846         callback(ptr, depth, max_depth, 0, private_data);
847
848         if (max_depth >= 0 && depth >= max_depth) {
849                 return;
850         }
851
852         tc->flags |= TALLOC_FLAG_LOOP;
853         for (c=tc->child;c;c=c->next) {
854                 if (c->name == TALLOC_MAGIC_REFERENCE) {
855                         struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
856                         callback(h->ptr, depth + 1, max_depth, 1, private_data);
857                 } else {
858                         talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
859                 }
860         }
861         tc->flags &= ~TALLOC_FLAG_LOOP;
862 }
863
864 static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
865 {
866         const char *name = talloc_get_name(ptr);
867         FILE *f = (FILE *)_f;
868
869         if (is_ref) {
870                 fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
871                 return;
872         }
873
874         if (depth == 0) {
875                 fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n", 
876                         (max_depth < 0 ? "full " :""), name,
877                         (unsigned long)talloc_total_size(ptr),
878                         (unsigned long)talloc_total_blocks(ptr));
879                 return;
880         }
881
882         fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", 
883                 depth*4, "",
884                 name,
885                 (unsigned long)talloc_total_size(ptr),
886                 (unsigned long)talloc_total_blocks(ptr),
887                 (int)talloc_reference_count(ptr));
888 }
889
890 /*
891   report on memory usage by all children of a pointer, giving a full tree view
892 */
893 void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
894 {
895         talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
896         fflush(f);
897 }
898
899 /*
900   report on memory usage by all children of a pointer, giving a full tree view
901 */
902 void talloc_report_full(const void *ptr, FILE *f)
903 {
904         talloc_report_depth_file(ptr, 0, -1, f);
905 }
906
907 /*
908   report on memory usage by all children of a pointer
909 */
910 void talloc_report(const void *ptr, FILE *f)
911 {
912         talloc_report_depth_file(ptr, 0, 1, f);
913 }
914
915 /*
916   report on any memory hanging off the null context
917 */
918 static void talloc_report_null(void)
919 {
920         if (talloc_total_size(null_context) != 0) {
921                 talloc_report(null_context, stderr);
922         }
923 }
924
925 /*
926   report on any memory hanging off the null context
927 */
928 static void talloc_report_null_full(void)
929 {
930         if (talloc_total_size(null_context) != 0) {
931                 talloc_report_full(null_context, stderr);
932         }
933 }
934
935 /*
936   enable tracking of the NULL context
937 */
938 void talloc_enable_null_tracking(void)
939 {
940         if (null_context == NULL) {
941                 null_context = talloc_named_const(NULL, 0, "null_context");
942         }
943 }
944
945 /*
946   disable tracking of the NULL context
947 */
948 void talloc_disable_null_tracking(void)
949 {
950         talloc_free(null_context);
951         null_context = NULL;
952 }
953
954 /*
955   enable leak reporting on exit
956 */
957 void talloc_enable_leak_report(void)
958 {
959         talloc_enable_null_tracking();
960         atexit(talloc_report_null);
961 }
962
963 /*
964   enable full leak reporting on exit
965 */
966 void talloc_enable_leak_report_full(void)
967 {
968         talloc_enable_null_tracking();
969         atexit(talloc_report_null_full);
970 }
971
972 /* 
973    talloc and zero memory. 
974 */
975 void *_talloc_zero(const void *ctx, size_t size, const char *name)
976 {
977         void *p = talloc_named_const(ctx, size, name);
978
979         if (p) {
980                 memset(p, '\0', size);
981         }
982
983         return p;
984 }
985
986
987 /*
988   memdup with a talloc. 
989 */
990 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
991 {
992         void *newp = talloc_named_const(t, size, name);
993
994         if (newp) {
995                 memcpy(newp, p, size);
996         }
997
998         return newp;
999 }
1000
1001 /*
1002   strdup with a talloc 
1003 */
1004 char *talloc_strdup(const void *t, const char *p)
1005 {
1006         char *ret;
1007         if (!p) {
1008                 return NULL;
1009         }
1010         ret = (char *)talloc_memdup(t, p, strlen(p) + 1);
1011         if (ret) {
1012                 talloc_set_name_const(ret, ret);
1013         }
1014         return ret;
1015 }
1016
1017 /*
1018  append to a talloced string 
1019 */
1020 char *talloc_append_string(const void *t, char *orig, const char *append)
1021 {
1022         char *ret;
1023         size_t olen = strlen(orig);
1024         size_t alenz;
1025
1026         if (!append)
1027                 return orig;
1028
1029         alenz = strlen(append) + 1;
1030
1031         ret = talloc_realloc(t, orig, char, olen + alenz);
1032         if (!ret)
1033                 return NULL;
1034
1035         /* append the string with the trailing \0 */
1036         memcpy(&ret[olen], append, alenz);
1037
1038         return ret;
1039 }
1040
1041 /*
1042   strndup with a talloc 
1043 */
1044 char *talloc_strndup(const void *t, const char *p, size_t n)
1045 {
1046         size_t len;
1047         char *ret;
1048
1049         for (len=0; len<n && p[len]; len++) ;
1050
1051         ret = (char *)_talloc(t, len + 1);
1052         if (!ret) { return NULL; }
1053         memcpy(ret, p, len);
1054         ret[len] = 0;
1055         talloc_set_name_const(ret, ret);
1056         return ret;
1057 }
1058
1059 #ifndef HAVE_VA_COPY
1060 #ifdef HAVE___VA_COPY
1061 #define va_copy(dest, src) __va_copy(dest, src)
1062 #else
1063 #define va_copy(dest, src) (dest) = (src)
1064 #endif
1065 #endif
1066
1067 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
1068 {       
1069         int len;
1070         char *ret;
1071         va_list ap2;
1072         char c;
1073         
1074         va_copy(ap2, ap);
1075
1076         /* this call looks strange, but it makes it work on older solaris boxes */
1077         if ((len = vsnprintf(&c, 1, fmt, ap2)) < 0) {
1078                 return NULL;
1079         }
1080
1081         ret = (char *)_talloc(t, len+1);
1082         if (ret) {
1083                 va_copy(ap2, ap);
1084                 vsnprintf(ret, len+1, fmt, ap2);
1085                 talloc_set_name_const(ret, ret);
1086         }
1087
1088         return ret;
1089 }
1090
1091
1092 /*
1093   Perform string formatting, and return a pointer to newly allocated
1094   memory holding the result, inside a memory pool.
1095  */
1096 char *talloc_asprintf(const void *t, const char *fmt, ...)
1097 {
1098         va_list ap;
1099         char *ret;
1100
1101         va_start(ap, fmt);
1102         ret = talloc_vasprintf(t, fmt, ap);
1103         va_end(ap);
1104         return ret;
1105 }
1106
1107
1108 /**
1109  * Realloc @p s to append the formatted result of @p fmt and @p ap,
1110  * and return @p s, which may have moved.  Good for gradually
1111  * accumulating output into a string buffer.
1112  **/
1113 char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1114 {       
1115         struct talloc_chunk *tc;
1116         int len, s_len;
1117         va_list ap2;
1118         char c;
1119
1120         if (s == NULL) {
1121                 return talloc_vasprintf(NULL, fmt, ap);
1122         }
1123
1124         tc = talloc_chunk_from_ptr(s);
1125
1126         va_copy(ap2, ap);
1127
1128         s_len = tc->size - 1;
1129         if ((len = vsnprintf(&c, 1, fmt, ap2)) <= 0) {
1130                 /* Either the vsnprintf failed or the format resulted in
1131                  * no characters being formatted. In the former case, we
1132                  * ought to return NULL, in the latter we ought to return
1133                  * the original string. Most current callers of this 
1134                  * function expect it to never return NULL.
1135                  */
1136                 return s;
1137         }
1138
1139         s = talloc_realloc(NULL, s, char, s_len + len+1);
1140         if (!s) return NULL;
1141
1142         va_copy(ap2, ap);
1143
1144         vsnprintf(s+s_len, len+1, fmt, ap2);
1145         talloc_set_name_const(s, s);
1146
1147         return s;
1148 }
1149
1150 /*
1151   Realloc @p s to append the formatted result of @p fmt and return @p
1152   s, which may have moved.  Good for gradually accumulating output
1153   into a string buffer.
1154  */
1155 char *talloc_asprintf_append(char *s, const char *fmt, ...)
1156 {
1157         va_list ap;
1158
1159         va_start(ap, fmt);
1160         s = talloc_vasprintf_append(s, fmt, ap);
1161         va_end(ap);
1162         return s;
1163 }
1164
1165 /*
1166   alloc an array, checking for integer overflow in the array size
1167 */
1168 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1169 {
1170         if (count >= MAX_TALLOC_SIZE/el_size) {
1171                 return NULL;
1172         }
1173         return talloc_named_const(ctx, el_size * count, name);
1174 }
1175
1176 /*
1177   alloc an zero array, checking for integer overflow in the array size
1178 */
1179 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1180 {
1181         if (count >= MAX_TALLOC_SIZE/el_size) {
1182                 return NULL;
1183         }
1184         return _talloc_zero(ctx, el_size * count, name);
1185 }
1186
1187
1188 /*
1189   realloc an array, checking for integer overflow in the array size
1190 */
1191 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
1192 {
1193         if (count >= MAX_TALLOC_SIZE/el_size) {
1194                 return NULL;
1195         }
1196         return _talloc_realloc(ctx, ptr, el_size * count, name);
1197 }
1198
1199 /*
1200   a function version of talloc_realloc(), so it can be passed as a function pointer
1201   to libraries that want a realloc function (a realloc function encapsulates
1202   all the basic capabilities of an allocation library, which is why this is useful)
1203 */
1204 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1205 {
1206         return _talloc_realloc(context, ptr, size, NULL);
1207 }
1208
1209
1210 static void talloc_autofree(void)
1211 {
1212         talloc_free(cleanup_context);
1213         cleanup_context = NULL;
1214 }
1215
1216 /*
1217   return a context which will be auto-freed on exit
1218   this is useful for reducing the noise in leak reports
1219 */
1220 void *talloc_autofree_context(void)
1221 {
1222         if (cleanup_context == NULL) {
1223                 cleanup_context = talloc_named_const(NULL, 0, "autofree_context");
1224                 atexit(talloc_autofree);
1225         }
1226         return cleanup_context;
1227 }
1228
1229 size_t talloc_get_size(const void *context)
1230 {
1231         struct talloc_chunk *tc;
1232
1233         if (context == NULL)
1234                 return 0;
1235
1236         tc = talloc_chunk_from_ptr(context);
1237
1238         return tc->size;
1239 }
1240
1241 /*
1242   find a parent of this context that has the given name, if any
1243 */
1244 void *talloc_find_parent_byname(const void *context, const char *name)
1245 {
1246         struct talloc_chunk *tc;
1247
1248         if (context == NULL) {
1249                 return NULL;
1250         }
1251
1252         tc = talloc_chunk_from_ptr(context);
1253         while (tc) {
1254                 if (tc->name && strcmp(tc->name, name) == 0) {
1255                         return TC_PTR_FROM_CHUNK(tc);
1256                 }
1257                 while (tc && tc->prev) tc = tc->prev;
1258                 if (tc) {
1259                         tc = tc->parent;
1260                 }
1261         }
1262         return NULL;
1263 }
1264
1265 /*
1266   show the parentage of a context
1267 */
1268 void talloc_show_parents(const void *context, FILE *file)
1269 {
1270         struct talloc_chunk *tc;
1271
1272         if (context == NULL) {
1273                 fprintf(file, "talloc no parents for NULL\n");
1274                 return;
1275         }
1276
1277         tc = talloc_chunk_from_ptr(context);
1278         fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
1279         while (tc) {
1280                 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
1281                 while (tc && tc->prev) tc = tc->prev;
1282                 if (tc) {
1283                         tc = tc->parent;
1284                 }
1285         }
1286 }
1287
1288 /*
1289   return 1 if ptr is a parent of context
1290 */
1291 int talloc_is_parent(const void *context, const void *ptr)
1292 {
1293         struct talloc_chunk *tc;
1294
1295         if (context == NULL) {
1296                 return 0;
1297         }
1298
1299         tc = talloc_chunk_from_ptr(context);
1300         while (tc) {
1301                 if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
1302                 while (tc && tc->prev) tc = tc->prev;
1303                 if (tc) {
1304                         tc = tc->parent;
1305                 }
1306         }
1307         return 0;
1308 }