Samba 3: added Samba 3.0.24 sources
[tomato.git] / release / src / router / samba3 / source / lib / talloc.c
blob51087ef9791ddff39867b9bf896acb7dda4cc45a
1 /*
2 Samba Unix SMB/CIFS implementation.
4 Samba trivial allocation library - new interface
6 NOTE: Please read talloc_guide.txt for full documentation
8 Copyright (C) Andrew Tridgell 2004
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
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.
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.
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
30 inspired by http://swapped.cc/halloc/
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
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
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)
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
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
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
85 static const void *null_context;
86 static void *cleanup_context;
89 struct talloc_reference_handle {
90 struct talloc_reference_handle *next, *prev;
91 void *ptr;
94 typedef int (*talloc_destructor_t)(void *);
96 struct talloc_chunk {
97 struct talloc_chunk *next, *prev;
98 struct talloc_chunk *parent, *child;
99 struct talloc_reference_handle *refs;
100 talloc_destructor_t destructor;
101 const char *name;
102 size_t size;
103 unsigned flags;
106 /* 16 byte alignment seems to keep everyone happy */
107 #define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
108 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
110 /* panic if we get a bad magic value */
111 static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
113 const char *pp = ptr;
114 struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
115 if ((tc->flags & ~0xF) != TALLOC_MAGIC) {
116 TALLOC_ABORT("Bad talloc magic value - unknown value");
118 if (tc->flags & TALLOC_FLAG_FREE) {
119 TALLOC_ABORT("Bad talloc magic value - double free");
121 return tc;
124 /* hook into the front of the list */
125 #define _TLIST_ADD(list, p) \
126 do { \
127 if (!(list)) { \
128 (list) = (p); \
129 (p)->next = (p)->prev = NULL; \
130 } else { \
131 (list)->prev = (p); \
132 (p)->next = (list); \
133 (p)->prev = NULL; \
134 (list) = (p); \
136 } while (0)
138 /* remove an element from a list - element doesn't have to be in list. */
139 #define _TLIST_REMOVE(list, p) \
140 do { \
141 if ((p) == (list)) { \
142 (list) = (p)->next; \
143 if (list) (list)->prev = NULL; \
144 } else { \
145 if ((p)->prev) (p)->prev->next = (p)->next; \
146 if ((p)->next) (p)->next->prev = (p)->prev; \
148 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
149 } while (0)
153 return the parent chunk of a pointer
155 static struct talloc_chunk *talloc_parent_chunk(const void *ptr)
157 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
158 while (tc->prev) tc=tc->prev;
159 return tc->parent;
162 void *talloc_parent(const void *ptr)
164 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
165 return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
169 Allocate a bit of memory as a child of an existing pointer
171 void *_talloc(const void *context, size_t size)
173 struct talloc_chunk *tc;
175 if (context == NULL) {
176 context = null_context;
179 if (size >= MAX_TALLOC_SIZE) {
180 return NULL;
183 tc = malloc(TC_HDR_SIZE+size);
184 if (tc == NULL) return NULL;
186 tc->size = size;
187 tc->flags = TALLOC_MAGIC;
188 tc->destructor = NULL;
189 tc->child = NULL;
190 tc->name = NULL;
191 tc->refs = NULL;
193 if (context) {
194 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
196 tc->parent = parent;
198 if (parent->child) {
199 parent->child->parent = NULL;
202 _TLIST_ADD(parent->child, tc);
203 } else {
204 tc->next = tc->prev = tc->parent = NULL;
207 return TC_PTR_FROM_CHUNK(tc);
212 setup a destructor to be called on free of a pointer
213 the destructor should return 0 on success, or -1 on failure.
214 if the destructor fails then the free is failed, and the memory can
215 be continued to be used
217 void talloc_set_destructor(const void *ptr, int (*destructor)(void *))
219 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
220 tc->destructor = destructor;
224 increase the reference count on a piece of memory.
226 void talloc_increase_ref_count(const void *ptr)
228 talloc_reference(null_context, ptr);
232 helper for talloc_reference()
234 static int talloc_reference_destructor(void *ptr)
236 struct talloc_reference_handle *handle = ptr;
237 struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr);
238 struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr);
239 if (tc1->destructor != (talloc_destructor_t)-1) {
240 tc1->destructor = NULL;
242 _TLIST_REMOVE(tc2->refs, handle);
243 talloc_free(handle);
244 return 0;
248 make a secondary reference to a pointer, hanging off the given context.
249 the pointer remains valid until both the original caller and this given
250 context are freed.
252 the major use for this is when two different structures need to reference the
253 same underlying data, and you want to be able to free the two instances separately,
254 and in either order
256 void *talloc_reference(const void *context, const void *ptr)
258 struct talloc_chunk *tc;
259 struct talloc_reference_handle *handle;
260 if (ptr == NULL) return NULL;
262 tc = talloc_chunk_from_ptr(ptr);
263 handle = talloc_named_const(context, sizeof(*handle), TALLOC_MAGIC_REFERENCE);
265 if (handle == NULL) return NULL;
267 /* note that we hang the destructor off the handle, not the
268 main context as that allows the caller to still setup their
269 own destructor on the context if they want to */
270 talloc_set_destructor(handle, talloc_reference_destructor);
271 handle->ptr = discard_const_p(void, ptr);
272 _TLIST_ADD(tc->refs, handle);
273 return handle->ptr;
277 remove a secondary reference to a pointer. This undo's what
278 talloc_reference() has done. The context and pointer arguments
279 must match those given to a talloc_reference()
281 static int talloc_unreference(const void *context, const void *ptr)
283 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
284 struct talloc_reference_handle *h;
286 if (context == NULL) {
287 context = null_context;
290 for (h=tc->refs;h;h=h->next) {
291 struct talloc_chunk *p = talloc_parent_chunk(h);
292 if (p == NULL) {
293 if (context == NULL) break;
294 } else if (TC_PTR_FROM_CHUNK(p) == context) {
295 break;
298 if (h == NULL) {
299 return -1;
302 talloc_set_destructor(h, NULL);
303 _TLIST_REMOVE(tc->refs, h);
304 talloc_free(h);
305 return 0;
309 remove a specific parent context from a pointer. This is a more
310 controlled varient of talloc_free()
312 int talloc_unlink(const void *context, void *ptr)
314 struct talloc_chunk *tc_p, *new_p;
315 void *new_parent;
317 if (ptr == NULL) {
318 return -1;
321 if (context == NULL) {
322 context = null_context;
325 if (talloc_unreference(context, ptr) == 0) {
326 return 0;
329 if (context == NULL) {
330 if (talloc_parent_chunk(ptr) != NULL) {
331 return -1;
333 } else {
334 if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) {
335 return -1;
339 tc_p = talloc_chunk_from_ptr(ptr);
341 if (tc_p->refs == NULL) {
342 return talloc_free(ptr);
345 new_p = talloc_parent_chunk(tc_p->refs);
346 if (new_p) {
347 new_parent = TC_PTR_FROM_CHUNK(new_p);
348 } else {
349 new_parent = NULL;
352 if (talloc_unreference(new_parent, ptr) != 0) {
353 return -1;
356 talloc_steal(new_parent, ptr);
358 return 0;
362 add a name to an existing pointer - va_list version
364 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
366 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
368 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
369 tc->name = talloc_vasprintf(ptr, fmt, ap);
370 if (tc->name) {
371 talloc_set_name_const(tc->name, ".name");
376 add a name to an existing pointer
378 void talloc_set_name(const void *ptr, const char *fmt, ...)
380 va_list ap;
381 va_start(ap, fmt);
382 talloc_set_name_v(ptr, fmt, ap);
383 va_end(ap);
387 more efficient way to add a name to a pointer - the name must point to a
388 true string constant
390 void talloc_set_name_const(const void *ptr, const char *name)
392 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
393 tc->name = name;
397 create a named talloc pointer. Any talloc pointer can be named, and
398 talloc_named() operates just like talloc() except that it allows you
399 to name the pointer.
401 void *talloc_named(const void *context, size_t size, const char *fmt, ...)
403 va_list ap;
404 void *ptr;
406 ptr = _talloc(context, size);
407 if (ptr == NULL) return NULL;
409 va_start(ap, fmt);
410 talloc_set_name_v(ptr, fmt, ap);
411 va_end(ap);
413 return ptr;
417 create a named talloc pointer. Any talloc pointer can be named, and
418 talloc_named() operates just like talloc() except that it allows you
419 to name the pointer.
421 void *talloc_named_const(const void *context, size_t size, const char *name)
423 void *ptr;
425 ptr = _talloc(context, size);
426 if (ptr == NULL) {
427 return NULL;
430 talloc_set_name_const(ptr, name);
432 return ptr;
436 return the name of a talloc ptr, or "UNNAMED"
438 const char *talloc_get_name(const void *ptr)
440 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
441 if (tc->name == TALLOC_MAGIC_REFERENCE) {
442 return ".reference";
444 if (tc->name) {
445 return tc->name;
447 return "UNNAMED";
452 check if a pointer has the given name. If it does, return the pointer,
453 otherwise return NULL
455 void *talloc_check_name(const void *ptr, const char *name)
457 const char *pname;
458 if (ptr == NULL) return NULL;
459 pname = talloc_get_name(ptr);
460 if (pname == name || strcmp(pname, name) == 0) {
461 return discard_const_p(void, ptr);
463 return NULL;
468 this is for compatibility with older versions of talloc
470 void *talloc_init(const char *fmt, ...)
472 va_list ap;
473 void *ptr;
475 talloc_enable_null_tracking();
477 ptr = _talloc(NULL, 0);
478 if (ptr == NULL) return NULL;
480 va_start(ap, fmt);
481 talloc_set_name_v(ptr, fmt, ap);
482 va_end(ap);
484 return ptr;
488 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
489 should probably not be used in new code. It's in here to keep the talloc
490 code consistent across Samba 3 and 4.
492 void talloc_free_children(void *ptr)
494 struct talloc_chunk *tc;
496 if (ptr == NULL) {
497 return;
500 tc = talloc_chunk_from_ptr(ptr);
502 while (tc->child) {
503 /* we need to work out who will own an abandoned child
504 if it cannot be freed. In priority order, the first
505 choice is owner of any remaining reference to this
506 pointer, the second choice is our parent, and the
507 final choice is the null context. */
508 void *child = TC_PTR_FROM_CHUNK(tc->child);
509 const void *new_parent = null_context;
510 if (tc->child->refs) {
511 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
512 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
514 if (talloc_free(child) == -1) {
515 if (new_parent == null_context) {
516 struct talloc_chunk *p = talloc_parent_chunk(ptr);
517 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
519 talloc_steal(new_parent, child);
525 free a talloc pointer. This also frees all child pointers of this
526 pointer recursively
528 return 0 if the memory is actually freed, otherwise -1. The memory
529 will not be freed if the ref_count is > 1 or the destructor (if
530 any) returns non-zero
532 int talloc_free(void *ptr)
534 struct talloc_chunk *tc;
536 if (ptr == NULL) {
537 return -1;
540 tc = talloc_chunk_from_ptr(ptr);
542 if (tc->refs) {
543 int is_child;
544 struct talloc_reference_handle *handle = tc->refs;
545 is_child = talloc_is_parent(handle, handle->ptr);
546 talloc_reference_destructor(tc->refs);
547 if (is_child) {
548 return talloc_free(ptr);
550 return -1;
553 if (tc->flags & TALLOC_FLAG_LOOP) {
554 /* we have a free loop - stop looping */
555 return 0;
558 if (tc->destructor) {
559 talloc_destructor_t d = tc->destructor;
560 if (d == (talloc_destructor_t)-1) {
561 return -1;
563 tc->destructor = (talloc_destructor_t)-1;
564 if (d(ptr) == -1) {
565 tc->destructor = d;
566 return -1;
568 tc->destructor = NULL;
571 tc->flags |= TALLOC_FLAG_LOOP;
573 talloc_free_children(ptr);
575 if (tc->parent) {
576 _TLIST_REMOVE(tc->parent->child, tc);
577 if (tc->parent->child) {
578 tc->parent->child->parent = tc->parent;
580 } else {
581 if (tc->prev) tc->prev->next = tc->next;
582 if (tc->next) tc->next->prev = tc->prev;
585 tc->flags |= TALLOC_FLAG_FREE;
587 free(tc);
588 return 0;
594 A talloc version of realloc. The context argument is only used if
595 ptr is NULL
597 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
599 struct talloc_chunk *tc;
600 void *new_ptr;
602 /* size zero is equivalent to free() */
603 if (size == 0) {
604 talloc_free(ptr);
605 return NULL;
608 if (size >= MAX_TALLOC_SIZE) {
609 return NULL;
612 /* realloc(NULL) is equavalent to malloc() */
613 if (ptr == NULL) {
614 return talloc_named_const(context, size, name);
617 tc = talloc_chunk_from_ptr(ptr);
619 /* don't allow realloc on referenced pointers */
620 if (tc->refs) {
621 return NULL;
624 /* by resetting magic we catch users of the old memory */
625 tc->flags |= TALLOC_FLAG_FREE;
627 #if ALWAYS_REALLOC
628 new_ptr = malloc(size + TC_HDR_SIZE);
629 if (new_ptr) {
630 memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE);
631 free(tc);
633 #else
634 new_ptr = realloc(tc, size + TC_HDR_SIZE);
635 #endif
636 if (!new_ptr) {
637 tc->flags &= ~TALLOC_FLAG_FREE;
638 return NULL;
641 tc = new_ptr;
642 tc->flags &= ~TALLOC_FLAG_FREE;
643 if (tc->parent) {
644 tc->parent->child = new_ptr;
646 if (tc->child) {
647 tc->child->parent = new_ptr;
650 if (tc->prev) {
651 tc->prev->next = tc;
653 if (tc->next) {
654 tc->next->prev = tc;
657 tc->size = size;
658 talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
660 return TC_PTR_FROM_CHUNK(tc);
664 move a lump of memory from one talloc context to another return the
665 ptr on success, or NULL if it could not be transferred.
666 passing NULL as ptr will always return NULL with no side effects.
668 void *talloc_steal(const void *new_ctx, const void *ptr)
670 struct talloc_chunk *tc, *new_tc;
672 if (!ptr) {
673 return NULL;
676 if (new_ctx == NULL) {
677 new_ctx = null_context;
680 tc = talloc_chunk_from_ptr(ptr);
682 if (new_ctx == NULL) {
683 if (tc->parent) {
684 _TLIST_REMOVE(tc->parent->child, tc);
685 if (tc->parent->child) {
686 tc->parent->child->parent = tc->parent;
688 } else {
689 if (tc->prev) tc->prev->next = tc->next;
690 if (tc->next) tc->next->prev = tc->prev;
693 tc->parent = tc->next = tc->prev = NULL;
694 return discard_const_p(void, ptr);
697 new_tc = talloc_chunk_from_ptr(new_ctx);
699 if (tc == new_tc || tc->parent == new_tc) {
700 return discard_const_p(void, ptr);
703 if (tc->parent) {
704 _TLIST_REMOVE(tc->parent->child, tc);
705 if (tc->parent->child) {
706 tc->parent->child->parent = tc->parent;
708 } else {
709 if (tc->prev) tc->prev->next = tc->next;
710 if (tc->next) tc->next->prev = tc->prev;
713 tc->parent = new_tc;
714 if (new_tc->child) new_tc->child->parent = NULL;
715 _TLIST_ADD(new_tc->child, tc);
717 return discard_const_p(void, ptr);
721 return the total size of a talloc pool (subtree)
723 off_t talloc_total_size(const void *ptr)
725 off_t total = 0;
726 struct talloc_chunk *c, *tc;
728 if (ptr == NULL) {
729 ptr = null_context;
731 if (ptr == NULL) {
732 return 0;
735 tc = talloc_chunk_from_ptr(ptr);
737 if (tc->flags & TALLOC_FLAG_LOOP) {
738 return 0;
741 tc->flags |= TALLOC_FLAG_LOOP;
743 total = tc->size;
744 for (c=tc->child;c;c=c->next) {
745 total += talloc_total_size(TC_PTR_FROM_CHUNK(c));
748 tc->flags &= ~TALLOC_FLAG_LOOP;
750 return total;
754 return the total number of blocks in a talloc pool (subtree)
756 off_t talloc_total_blocks(const void *ptr)
758 off_t total = 0;
759 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
761 if (tc->flags & TALLOC_FLAG_LOOP) {
762 return 0;
765 tc->flags |= TALLOC_FLAG_LOOP;
767 total++;
768 for (c=tc->child;c;c=c->next) {
769 total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
772 tc->flags &= ~TALLOC_FLAG_LOOP;
774 return total;
778 return the number of external references to a pointer
780 static int talloc_reference_count(const void *ptr)
782 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
783 struct talloc_reference_handle *h;
784 int ret = 0;
786 for (h=tc->refs;h;h=h->next) {
787 ret++;
789 return ret;
793 report on memory usage by all children of a pointer, giving a full tree view
795 void talloc_report_depth(const void *ptr, FILE *f, int depth)
797 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
799 if (tc->flags & TALLOC_FLAG_LOOP) {
800 return;
803 tc->flags |= TALLOC_FLAG_LOOP;
805 for (c=tc->child;c;c=c->next) {
806 if (c->name == TALLOC_MAGIC_REFERENCE) {
807 struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c);
808 const char *name2 = talloc_get_name(handle->ptr);
809 fprintf(f, "%*sreference to: %s\n", depth*4, "", name2);
810 } else {
811 const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c));
812 fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n",
813 depth*4, "",
814 name,
815 (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
816 (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)),
817 talloc_reference_count(TC_PTR_FROM_CHUNK(c)));
818 talloc_report_depth(TC_PTR_FROM_CHUNK(c), f, depth+1);
821 tc->flags &= ~TALLOC_FLAG_LOOP;
825 report on memory usage by all children of a pointer, giving a full tree view
827 void talloc_report_full(const void *ptr, FILE *f)
829 if (ptr == NULL) {
830 ptr = null_context;
832 if (ptr == NULL) return;
834 fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n",
835 talloc_get_name(ptr),
836 (unsigned long)talloc_total_size(ptr),
837 (unsigned long)talloc_total_blocks(ptr));
839 talloc_report_depth(ptr, f, 1);
840 fflush(f);
844 report on memory usage by all children of a pointer
846 void talloc_report(const void *ptr, FILE *f)
848 struct talloc_chunk *c, *tc;
850 if (ptr == NULL) {
851 ptr = null_context;
853 if (ptr == NULL) return;
855 fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n",
856 talloc_get_name(ptr),
857 (unsigned long)talloc_total_size(ptr),
858 (unsigned long)talloc_total_blocks(ptr));
860 tc = talloc_chunk_from_ptr(ptr);
862 for (c=tc->child;c;c=c->next) {
863 fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n",
864 talloc_get_name(TC_PTR_FROM_CHUNK(c)),
865 (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
866 (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)));
868 fflush(f);
872 report on any memory hanging off the null context
874 static void talloc_report_null(void)
876 if (talloc_total_size(null_context) != 0) {
877 talloc_report(null_context, stderr);
882 report on any memory hanging off the null context
884 static void talloc_report_null_full(void)
886 if (talloc_total_size(null_context) != 0) {
887 talloc_report_full(null_context, stderr);
892 free allocated global memory
895 void talloc_nc_free(void)
897 if ( null_context )
898 talloc_free( (void*)null_context );
902 enable tracking of the NULL context
904 void talloc_enable_null_tracking(void)
906 if (null_context == NULL) {
907 null_context = talloc_named_const(NULL, 0, "null_context");
911 #ifdef _SAMBA_BUILD_
912 /* Ugly calls to Samba-specific sprintf_append... JRA. */
915 report on memory usage by all children of a pointer, giving a full tree view
917 static void talloc_report_depth_str(const void *ptr, char **pps, ssize_t *plen, size_t *pbuflen, int depth)
919 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
921 if (tc->flags & TALLOC_FLAG_LOOP) {
922 return;
925 tc->flags |= TALLOC_FLAG_LOOP;
927 for (c=tc->child;c;c=c->next) {
928 if (c->name == TALLOC_MAGIC_REFERENCE) {
929 struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c);
930 const char *name2 = talloc_get_name(handle->ptr);
932 sprintf_append(NULL, pps, plen, pbuflen,
933 "%*sreference to: %s\n", depth*4, "", name2);
935 } else {
936 const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c));
938 sprintf_append(NULL, pps, plen, pbuflen,
939 "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n",
940 depth*4, "",
941 name,
942 (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
943 (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)),
944 talloc_reference_count(TC_PTR_FROM_CHUNK(c)));
946 talloc_report_depth_str(TC_PTR_FROM_CHUNK(c), pps, plen, pbuflen, depth+1);
949 tc->flags &= ~TALLOC_FLAG_LOOP;
953 report on memory usage by all children of a pointer
955 char *talloc_describe_all(void)
957 ssize_t len = 0;
958 size_t buflen = 512;
959 char *s = NULL;
961 if (null_context == NULL) {
962 return NULL;
965 sprintf_append(NULL, &s, &len, &buflen,
966 "full talloc report on '%s' (total %lu bytes in %lu blocks)\n",
967 talloc_get_name(null_context),
968 (unsigned long)talloc_total_size(null_context),
969 (unsigned long)talloc_total_blocks(null_context));
971 if (!s) {
972 return NULL;
974 talloc_report_depth_str(null_context, &s, &len, &buflen, 1);
975 return s;
977 #endif
980 enable leak reporting on exit
982 void talloc_enable_leak_report(void)
984 talloc_enable_null_tracking();
985 atexit(talloc_report_null);
989 enable full leak reporting on exit
991 void talloc_enable_leak_report_full(void)
993 talloc_enable_null_tracking();
994 atexit(talloc_report_null_full);
998 talloc and zero memory.
1000 void *_talloc_zero(const void *ctx, size_t size, const char *name)
1002 void *p = talloc_named_const(ctx, size, name);
1004 if (p) {
1005 memset(p, '\0', size);
1008 return p;
1013 memdup with a talloc.
1015 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
1017 void *newp = talloc_named_const(t, size, name);
1019 if (newp) {
1020 memcpy(newp, p, size);
1023 return newp;
1027 strdup with a talloc
1029 char *talloc_strdup(const void *t, const char *p)
1031 char *ret;
1032 if (!p) {
1033 return NULL;
1035 ret = talloc_memdup(t, p, strlen(p) + 1);
1036 if (ret) {
1037 talloc_set_name_const(ret, ret);
1039 return ret;
1043 append to a talloced string
1045 char *talloc_append_string(const void *t, char *orig, const char *append)
1047 char *ret;
1048 size_t olen = strlen(orig);
1049 size_t alenz;
1051 if (!append)
1052 return orig;
1054 alenz = strlen(append) + 1;
1056 ret = talloc_realloc(t, orig, char, olen + alenz);
1057 if (!ret)
1058 return NULL;
1060 /* append the string with the trailing \0 */
1061 memcpy(&ret[olen], append, alenz);
1063 return ret;
1067 strndup with a talloc
1069 char *talloc_strndup(const void *t, const char *p, size_t n)
1071 size_t len;
1072 char *ret;
1074 for (len=0; len<n && p[len]; len++) ;
1076 ret = _talloc(t, len + 1);
1077 if (!ret) { return NULL; }
1078 memcpy(ret, p, len);
1079 ret[len] = 0;
1080 talloc_set_name_const(ret, ret);
1081 return ret;
1084 #ifndef VA_COPY
1085 #ifdef HAVE_VA_COPY
1086 #define VA_COPY(dest, src) va_copy(dest, src)
1087 #elif defined(HAVE___VA_COPY)
1088 #define VA_COPY(dest, src) __va_copy(dest, src)
1089 #else
1090 #define VA_COPY(dest, src) (dest) = (src)
1091 #endif
1092 #endif
1094 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
1096 int len;
1097 char *ret;
1098 va_list ap2;
1099 char c;
1101 VA_COPY(ap2, ap);
1103 /* this call looks strange, but it makes it work on older solaris boxes */
1104 if ((len = vsnprintf(&c, 1, fmt, ap2)) < 0) {
1105 return NULL;
1108 ret = _talloc(t, len+1);
1109 if (ret) {
1110 VA_COPY(ap2, ap);
1111 vsnprintf(ret, len+1, fmt, ap2);
1112 talloc_set_name_const(ret, ret);
1115 return ret;
1120 Perform string formatting, and return a pointer to newly allocated
1121 memory holding the result, inside a memory pool.
1123 char *talloc_asprintf(const void *t, const char *fmt, ...)
1125 va_list ap;
1126 char *ret;
1128 va_start(ap, fmt);
1129 ret = talloc_vasprintf(t, fmt, ap);
1130 va_end(ap);
1131 return ret;
1136 * Realloc @p s to append the formatted result of @p fmt and @p ap,
1137 * and return @p s, which may have moved. Good for gradually
1138 * accumulating output into a string buffer.
1141 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
1143 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1145 struct talloc_chunk *tc;
1146 int len, s_len;
1147 va_list ap2;
1149 if (s == NULL) {
1150 return talloc_vasprintf(NULL, fmt, ap);
1153 tc = talloc_chunk_from_ptr(s);
1155 VA_COPY(ap2, ap);
1157 s_len = tc->size - 1;
1158 if ((len = vsnprintf(NULL, 0, fmt, ap2)) <= 0) {
1159 /* Either the vsnprintf failed or the format resulted in
1160 * no characters being formatted. In the former case, we
1161 * ought to return NULL, in the latter we ought to return
1162 * the original string. Most current callers of this
1163 * function expect it to never return NULL.
1165 return s;
1168 s = talloc_realloc(NULL, s, char, s_len + len+1);
1169 if (!s) return NULL;
1171 VA_COPY(ap2, ap);
1173 vsnprintf(s+s_len, len+1, fmt, ap2);
1174 talloc_set_name_const(s, s);
1176 return s;
1180 Realloc @p s to append the formatted result of @p fmt and return @p
1181 s, which may have moved. Good for gradually accumulating output
1182 into a string buffer.
1184 char *talloc_asprintf_append(char *s, const char *fmt, ...)
1186 va_list ap;
1188 va_start(ap, fmt);
1189 s = talloc_vasprintf_append(s, fmt, ap);
1190 va_end(ap);
1191 return s;
1195 alloc an array, checking for integer overflow in the array size
1197 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1199 if (count >= MAX_TALLOC_SIZE/el_size) {
1200 return NULL;
1202 return talloc_named_const(ctx, el_size * count, name);
1206 alloc an zero array, checking for integer overflow in the array size
1208 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1210 if (count >= MAX_TALLOC_SIZE/el_size) {
1211 return NULL;
1213 return _talloc_zero(ctx, el_size * count, name);
1218 realloc an array, checking for integer overflow in the array size
1220 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
1222 if (count >= MAX_TALLOC_SIZE/el_size) {
1223 return NULL;
1225 return _talloc_realloc(ctx, ptr, el_size * count, name);
1229 a function version of talloc_realloc(), so it can be passed as a function pointer
1230 to libraries that want a realloc function (a realloc function encapsulates
1231 all the basic capabilities of an allocation library, which is why this is useful)
1233 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1235 return _talloc_realloc(context, ptr, size, NULL);
1239 static void talloc_autofree(void)
1241 talloc_free(cleanup_context);
1242 cleanup_context = NULL;
1246 return a context which will be auto-freed on exit
1247 this is useful for reducing the noise in leak reports
1249 void *talloc_autofree_context(void)
1251 if (cleanup_context == NULL) {
1252 cleanup_context = talloc_named_const(NULL, 0, "autofree_context");
1253 atexit(talloc_autofree);
1255 return cleanup_context;
1258 size_t talloc_get_size(const void *context)
1260 struct talloc_chunk *tc;
1262 if (context == NULL)
1263 return 0;
1265 tc = talloc_chunk_from_ptr(context);
1267 return tc->size;
1271 find a parent of this context that has the given name, if any
1273 void *talloc_find_parent_byname(const void *context, const char *name)
1275 struct talloc_chunk *tc;
1277 if (context == NULL) {
1278 return NULL;
1281 tc = talloc_chunk_from_ptr(context);
1282 while (tc) {
1283 if (tc->name && strcmp(tc->name, name) == 0) {
1284 return TC_PTR_FROM_CHUNK(tc);
1286 while (tc && tc->prev) tc = tc->prev;
1287 if (tc) {
1288 tc = tc->parent;
1292 return NULL;
1296 show the parentage of a context
1298 void talloc_show_parents(const void *context, FILE *file)
1300 struct talloc_chunk *tc;
1302 if (context == NULL) {
1303 fprintf(file, "talloc no parents for NULL\n");
1304 return;
1307 tc = talloc_chunk_from_ptr(context);
1308 fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
1309 while (tc) {
1310 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
1311 while (tc && tc->prev) tc = tc->prev;
1312 if (tc) {
1313 tc = tc->parent;
1319 return 1 if ptr is a parent of context
1321 int talloc_is_parent(const void *context, const char *ptr)
1323 struct talloc_chunk *tc;
1325 if (context == NULL) {
1326 return 0;
1329 tc = talloc_chunk_from_ptr(context);
1330 while (tc) {
1331 if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
1332 while (tc && tc->prev) tc = tc->prev;
1333 if (tc) {
1334 tc = tc->parent;
1337 return 0;