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