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