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
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/
40 #if defined(HAVE_STDARG_H)
42 #elif defined (HAVE_VARARGS_H)
45 #error "no var arg header"
50 /* use this to force every realloc to change the pointer, to stress test
51 code that might not cope */
52 #define ALWAYS_REALLOC 0
55 #define MAX_TALLOC_SIZE 0x10000000
56 #define TALLOC_MAGIC 0xe814ec70
57 #define TALLOC_FLAG_FREE 0x01
58 #define TALLOC_FLAG_LOOP 0x02
59 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
61 /* by default we abort when given a bad pointer (such as when talloc_free() is called
62 on a pointer that came from malloc() */
64 #define TALLOC_ABORT(reason) abort()
67 #ifndef discard_const_p
68 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
69 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
71 # define discard_const_p(type, ptr) ((type *)(ptr))
75 /* this null_context is only used if talloc_enable_leak_report() or
76 talloc_enable_leak_report_full() is called, otherwise it remains
79 static const void *null_context;
80 static void *cleanup_context;
83 struct talloc_reference_handle {
84 struct talloc_reference_handle *next, *prev;
88 typedef int (*talloc_destructor_t)(void *);
91 struct talloc_chunk *next, *prev;
92 struct talloc_chunk *parent, *child;
93 struct talloc_reference_handle *refs;
94 talloc_destructor_t destructor;
100 /* 16 byte alignment seems to keep everyone happy */
101 #define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
102 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
104 /* panic if we get a bad magic value */
105 static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
107 const char *pp = ptr;
108 struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
109 if ((tc->flags & ~0xF) != TALLOC_MAGIC) {
110 TALLOC_ABORT("Bad talloc magic value - unknown value");
112 if (tc->flags & TALLOC_FLAG_FREE) {
113 TALLOC_ABORT("Bad talloc magic value - double free");
118 /* hook into the front of the list */
119 #define _TLIST_ADD(list, p) \
123 (p)->next = (p)->prev = NULL; \
125 (list)->prev = (p); \
126 (p)->next = (list); \
132 /* remove an element from a list - element doesn't have to be in list. */
133 #define _TLIST_REMOVE(list, p) \
135 if ((p) == (list)) { \
136 (list) = (p)->next; \
137 if (list) (list)->prev = NULL; \
139 if ((p)->prev) (p)->prev->next = (p)->next; \
140 if ((p)->next) (p)->next->prev = (p)->prev; \
142 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
147 return the parent chunk of a pointer
149 static struct talloc_chunk *talloc_parent_chunk(const void *ptr)
151 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
152 while (tc->prev) tc=tc->prev;
156 void *talloc_parent(const void *ptr)
158 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
159 return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
163 Allocate a bit of memory as a child of an existing pointer
165 void *_talloc(const void *context, size_t size)
167 struct talloc_chunk *tc;
169 if (context == NULL) {
170 context = null_context;
173 if (size >= MAX_TALLOC_SIZE) {
177 tc = malloc(TC_HDR_SIZE+size);
178 if (tc == NULL) return NULL;
181 tc->flags = TALLOC_MAGIC;
182 tc->destructor = NULL;
188 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
193 parent->child->parent = NULL;
196 _TLIST_ADD(parent->child, tc);
198 tc->next = tc->prev = tc->parent = NULL;
201 return TC_PTR_FROM_CHUNK(tc);
206 setup a destructor to be called on free of a pointer
207 the destructor should return 0 on success, or -1 on failure.
208 if the destructor fails then the free is failed, and the memory can
209 be continued to be used
211 void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
213 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
214 tc->destructor = destructor;
218 increase the reference count on a piece of memory.
220 void talloc_increase_ref_count(const void *ptr)
222 talloc_reference(null_context, ptr);
226 helper for talloc_reference()
228 static int talloc_reference_destructor(struct talloc_reference_handle *handle)
230 struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
231 _TLIST_REMOVE(ptr_tc->refs, handle);
236 make a secondary reference to a pointer, hanging off the given context.
237 the pointer remains valid until both the original caller and this given
240 the major use for this is when two different structures need to reference the
241 same underlying data, and you want to be able to free the two instances separately,
244 void *talloc_reference(const void *context, const void *ptr)
246 struct talloc_chunk *tc;
247 struct talloc_reference_handle *handle;
248 if (ptr == NULL) return NULL;
250 tc = talloc_chunk_from_ptr(ptr);
251 handle = talloc_named_const(context, sizeof(*handle), TALLOC_MAGIC_REFERENCE);
253 if (handle == NULL) return NULL;
255 /* note that we hang the destructor off the handle, not the
256 main context as that allows the caller to still setup their
257 own destructor on the context if they want to */
258 talloc_set_destructor(handle, talloc_reference_destructor);
259 handle->ptr = discard_const_p(void, ptr);
260 _TLIST_ADD(tc->refs, handle);
265 remove a secondary reference to a pointer. This undo's what
266 talloc_reference() has done. The context and pointer arguments
267 must match those given to a talloc_reference()
269 static int talloc_unreference(const void *context, const void *ptr)
271 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
272 struct talloc_reference_handle *h;
274 if (context == NULL) {
275 context = null_context;
278 for (h=tc->refs;h;h=h->next) {
279 struct talloc_chunk *p = talloc_parent_chunk(h);
281 if (context == NULL) break;
282 } else if (TC_PTR_FROM_CHUNK(p) == context) {
290 return talloc_free(h);
294 remove a specific parent context from a pointer. This is a more
295 controlled varient of talloc_free()
297 int talloc_unlink(const void *context, void *ptr)
299 struct talloc_chunk *tc_p, *new_p;
306 if (context == NULL) {
307 context = null_context;
310 if (talloc_unreference(context, ptr) == 0) {
314 if (context == NULL) {
315 if (talloc_parent_chunk(ptr) != NULL) {
319 if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) {
324 tc_p = talloc_chunk_from_ptr(ptr);
326 if (tc_p->refs == NULL) {
327 return talloc_free(ptr);
330 new_p = talloc_parent_chunk(tc_p->refs);
332 new_parent = TC_PTR_FROM_CHUNK(new_p);
337 if (talloc_unreference(new_parent, ptr) != 0) {
341 talloc_steal(new_parent, ptr);
347 add a name to an existing pointer - va_list version
349 static const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
351 static const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
353 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
354 tc->name = talloc_vasprintf(ptr, fmt, ap);
356 talloc_set_name_const(tc->name, ".name");
362 add a name to an existing pointer
364 const char *talloc_set_name(const void *ptr, const char *fmt, ...)
369 name = talloc_set_name_v(ptr, fmt, ap);
375 more efficient way to add a name to a pointer - the name must point to a
378 void talloc_set_name_const(const void *ptr, const char *name)
380 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
385 create a named talloc pointer. Any talloc pointer can be named, and
386 talloc_named() operates just like talloc() except that it allows you
389 void *talloc_named(const void *context, size_t size, const char *fmt, ...)
395 ptr = _talloc(context, size);
396 if (ptr == NULL) return NULL;
399 name = talloc_set_name_v(ptr, fmt, ap);
411 create a named talloc pointer. Any talloc pointer can be named, and
412 talloc_named() operates just like talloc() except that it allows you
415 void *talloc_named_const(const void *context, size_t size, const char *name)
419 ptr = _talloc(context, size);
424 talloc_set_name_const(ptr, name);
430 return the name of a talloc ptr, or "UNNAMED"
432 const char *talloc_get_name(const void *ptr)
434 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
435 if (tc->name == TALLOC_MAGIC_REFERENCE) {
446 check if a pointer has the given name. If it does, return the pointer,
447 otherwise return NULL
449 void *talloc_check_name(const void *ptr, const char *name)
452 if (ptr == NULL) return NULL;
453 pname = talloc_get_name(ptr);
454 if (pname == name || strcmp(pname, name) == 0) {
455 return discard_const_p(void, ptr);
462 this is for compatibility with older versions of talloc
464 void *talloc_init(const char *fmt, ...)
470 ptr = _talloc(NULL, 0);
471 if (ptr == NULL) return NULL;
474 name = talloc_set_name_v(ptr, fmt, ap);
486 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
487 should probably not be used in new code. It's in here to keep the talloc
488 code consistent across Samba 3 and 4.
490 void talloc_free_children(void *ptr)
492 struct talloc_chunk *tc;
498 tc = talloc_chunk_from_ptr(ptr);
501 /* we need to work out who will own an abandoned child
502 if it cannot be freed. In priority order, the first
503 choice is owner of any remaining reference to this
504 pointer, the second choice is our parent, and the
505 final choice is the null context. */
506 void *child = TC_PTR_FROM_CHUNK(tc->child);
507 const void *new_parent = null_context;
508 if (tc->child->refs) {
509 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
510 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
512 if (talloc_free(child) == -1) {
513 if (new_parent == null_context) {
514 struct talloc_chunk *p = talloc_parent_chunk(ptr);
515 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
517 talloc_steal(new_parent, child);
523 free a talloc pointer. This also frees all child pointers of this
526 return 0 if the memory is actually freed, otherwise -1. The memory
527 will not be freed if the ref_count is > 1 or the destructor (if
528 any) returns non-zero
530 int talloc_free(void *ptr)
532 struct talloc_chunk *tc;
539 tc = talloc_chunk_from_ptr(ptr);
543 /* check this is a reference from a child or grantchild
544 * back to it's parent or grantparent
546 * in that case we need to remove the reference and
547 * call another instance of talloc_free() on the current
550 is_child = talloc_is_parent(tc->refs, ptr);
551 talloc_free(tc->refs);
553 return talloc_free(ptr);
558 if (tc->flags & TALLOC_FLAG_LOOP) {
559 /* we have a free loop - stop looping */
563 if (tc->destructor) {
564 talloc_destructor_t d = tc->destructor;
565 if (d == (talloc_destructor_t)-1) {
568 tc->destructor = (talloc_destructor_t)-1;
573 tc->destructor = NULL;
577 _TLIST_REMOVE(tc->parent->child, tc);
578 if (tc->parent->child) {
579 tc->parent->child->parent = tc->parent;
582 if (tc->prev) tc->prev->next = tc->next;
583 if (tc->next) tc->next->prev = tc->prev;
586 tc->flags |= TALLOC_FLAG_LOOP;
587 talloc_free_children(ptr);
589 tc->flags |= TALLOC_FLAG_FREE;
599 A talloc version of realloc. The context argument is only used if
602 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
604 struct talloc_chunk *tc;
607 /* size zero is equivalent to free() */
613 if (size >= MAX_TALLOC_SIZE) {
617 /* realloc(NULL) is equavalent to malloc() */
619 return talloc_named_const(context, size, name);
622 tc = talloc_chunk_from_ptr(ptr);
624 /* don't allow realloc on referenced pointers */
629 /* by resetting magic we catch users of the old memory */
630 tc->flags |= TALLOC_FLAG_FREE;
633 new_ptr = malloc(size + TC_HDR_SIZE);
635 memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE);
639 new_ptr = realloc(tc, size + TC_HDR_SIZE);
642 tc->flags &= ~TALLOC_FLAG_FREE;
647 tc->flags &= ~TALLOC_FLAG_FREE;
649 tc->parent->child = new_ptr;
652 tc->child->parent = new_ptr;
663 talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
665 return TC_PTR_FROM_CHUNK(tc);
669 move a lump of memory from one talloc context to another return the
670 ptr on success, or NULL if it could not be transferred.
671 passing NULL as ptr will always return NULL with no side effects.
673 void *_talloc_steal(const void *new_ctx, const void *ptr)
675 struct talloc_chunk *tc, *new_tc;
681 if (new_ctx == NULL) {
682 new_ctx = null_context;
685 tc = talloc_chunk_from_ptr(ptr);
687 if (new_ctx == NULL) {
689 _TLIST_REMOVE(tc->parent->child, tc);
690 if (tc->parent->child) {
691 tc->parent->child->parent = tc->parent;
694 if (tc->prev) tc->prev->next = tc->next;
695 if (tc->next) tc->next->prev = tc->prev;
698 tc->parent = tc->next = tc->prev = NULL;
699 return discard_const_p(void, ptr);
702 new_tc = talloc_chunk_from_ptr(new_ctx);
704 if (tc == new_tc || tc->parent == new_tc) {
705 return discard_const_p(void, ptr);
709 _TLIST_REMOVE(tc->parent->child, tc);
710 if (tc->parent->child) {
711 tc->parent->child->parent = tc->parent;
714 if (tc->prev) tc->prev->next = tc->next;
715 if (tc->next) tc->next->prev = tc->prev;
719 if (new_tc->child) new_tc->child->parent = NULL;
720 _TLIST_ADD(new_tc->child, tc);
722 return discard_const_p(void, ptr);
726 return the total size of a talloc pool (subtree)
728 size_t talloc_total_size(const void *ptr)
731 struct talloc_chunk *c, *tc;
740 tc = talloc_chunk_from_ptr(ptr);
742 if (tc->flags & TALLOC_FLAG_LOOP) {
746 tc->flags |= TALLOC_FLAG_LOOP;
749 for (c=tc->child;c;c=c->next) {
750 total += talloc_total_size(TC_PTR_FROM_CHUNK(c));
753 tc->flags &= ~TALLOC_FLAG_LOOP;
759 return the total number of blocks in a talloc pool (subtree)
761 size_t talloc_total_blocks(const void *ptr)
764 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
766 if (tc->flags & TALLOC_FLAG_LOOP) {
770 tc->flags |= TALLOC_FLAG_LOOP;
773 for (c=tc->child;c;c=c->next) {
774 total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
777 tc->flags &= ~TALLOC_FLAG_LOOP;
783 return the number of external references to a pointer
785 static int talloc_reference_count(const void *ptr)
787 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
788 struct talloc_reference_handle *h;
791 for (h=tc->refs;h;h=h->next) {
798 report on memory usage by all children of a pointer, giving a full tree view
800 void talloc_report_depth(const void *ptr, FILE *f, int depth)
802 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
804 if (tc->flags & TALLOC_FLAG_LOOP) {
808 tc->flags |= TALLOC_FLAG_LOOP;
810 for (c=tc->child;c;c=c->next) {
811 if (c->name == TALLOC_MAGIC_REFERENCE) {
812 struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c);
813 const char *name2 = talloc_get_name(handle->ptr);
814 fprintf(f, "%*sreference to: %s\n", depth*4, "", name2);
816 const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c));
817 fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n",
820 (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
821 (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)),
822 talloc_reference_count(TC_PTR_FROM_CHUNK(c)));
823 talloc_report_depth(TC_PTR_FROM_CHUNK(c), f, depth+1);
826 tc->flags &= ~TALLOC_FLAG_LOOP;
830 report on memory usage by all children of a pointer, giving a full tree view
832 void talloc_report_full(const void *ptr, FILE *f)
837 if (ptr == NULL) return;
839 fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n",
840 talloc_get_name(ptr),
841 (unsigned long)talloc_total_size(ptr),
842 (unsigned long)talloc_total_blocks(ptr));
844 talloc_report_depth(ptr, f, 1);
849 report on memory usage by all children of a pointer
851 void talloc_report(const void *ptr, FILE *f)
853 struct talloc_chunk *c, *tc;
858 if (ptr == NULL) return;
860 fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n",
861 talloc_get_name(ptr),
862 (unsigned long)talloc_total_size(ptr),
863 (unsigned long)talloc_total_blocks(ptr));
865 tc = talloc_chunk_from_ptr(ptr);
867 for (c=tc->child;c;c=c->next) {
868 fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n",
869 talloc_get_name(TC_PTR_FROM_CHUNK(c)),
870 (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
871 (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)));
877 report on any memory hanging off the null context
879 static void talloc_report_null(void)
881 if (talloc_total_size(null_context) != 0) {
882 talloc_report(null_context, stderr);
887 report on any memory hanging off the null context
889 static void talloc_report_null_full(void)
891 if (talloc_total_size(null_context) != 0) {
892 talloc_report_full(null_context, stderr);
897 enable tracking of the NULL context
899 void talloc_enable_null_tracking(void)
901 if (null_context == NULL) {
902 null_context = talloc_named_const(NULL, 0, "null_context");
907 enable leak reporting on exit
909 void talloc_enable_leak_report(void)
911 talloc_enable_null_tracking();
912 atexit(talloc_report_null);
916 enable full leak reporting on exit
918 void talloc_enable_leak_report_full(void)
920 talloc_enable_null_tracking();
921 atexit(talloc_report_null_full);
925 talloc and zero memory.
927 void *_talloc_zero(const void *ctx, size_t size, const char *name)
929 void *p = talloc_named_const(ctx, size, name);
932 memset(p, '\0', size);
940 memdup with a talloc.
942 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
944 void *newp = talloc_named_const(t, size, name);
947 memcpy(newp, p, size);
956 char *talloc_strdup(const void *t, const char *p)
962 ret = talloc_memdup(t, p, strlen(p) + 1);
964 talloc_set_name_const(ret, ret);
970 append to a talloced string
972 char *talloc_append_string(const void *t, char *orig, const char *append)
975 size_t olen = strlen(orig);
981 alenz = strlen(append) + 1;
983 ret = talloc_realloc(t, orig, char, olen + alenz);
987 /* append the string with the trailing \0 */
988 memcpy(&ret[olen], append, alenz);
994 strndup with a talloc
996 char *talloc_strndup(const void *t, const char *p, size_t n)
1001 for (len=0; len<n && p[len]; len++) ;
1003 ret = _talloc(t, len + 1);
1004 if (!ret) { return NULL; }
1005 memcpy(ret, p, len);
1007 talloc_set_name_const(ret, ret);
1011 #ifndef HAVE_VA_COPY
1012 #ifdef HAVE___VA_COPY
1013 #define va_copy(dest, src) __va_copy(dest, src)
1015 #define va_copy(dest, src) (dest) = (src)
1019 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
1028 /* this call looks strange, but it makes it work on older solaris boxes */
1029 if ((len = vsnprintf(&c, 1, fmt, ap2)) < 0) {
1033 ret = _talloc(t, len+1);
1036 vsnprintf(ret, len+1, fmt, ap2);
1037 talloc_set_name_const(ret, ret);
1045 Perform string formatting, and return a pointer to newly allocated
1046 memory holding the result, inside a memory pool.
1048 char *talloc_asprintf(const void *t, const char *fmt, ...)
1054 ret = talloc_vasprintf(t, fmt, ap);
1061 * Realloc @p s to append the formatted result of @p fmt and @p ap,
1062 * and return @p s, which may have moved. Good for gradually
1063 * accumulating output into a string buffer.
1065 char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1067 struct talloc_chunk *tc;
1073 return talloc_vasprintf(NULL, fmt, ap);
1076 tc = talloc_chunk_from_ptr(s);
1080 s_len = tc->size - 1;
1081 if ((len = vsnprintf(&c, 1, fmt, ap2)) <= 0) {
1082 /* Either the vsnprintf failed or the format resulted in
1083 * no characters being formatted. In the former case, we
1084 * ought to return NULL, in the latter we ought to return
1085 * the original string. Most current callers of this
1086 * function expect it to never return NULL.
1091 s = talloc_realloc(NULL, s, char, s_len + len+1);
1092 if (!s) return NULL;
1096 vsnprintf(s+s_len, len+1, fmt, ap2);
1097 talloc_set_name_const(s, s);
1103 Realloc @p s to append the formatted result of @p fmt and return @p
1104 s, which may have moved. Good for gradually accumulating output
1105 into a string buffer.
1107 char *talloc_asprintf_append(char *s, const char *fmt, ...)
1112 s = talloc_vasprintf_append(s, fmt, ap);
1118 alloc an array, checking for integer overflow in the array size
1120 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1122 if (count >= MAX_TALLOC_SIZE/el_size) {
1125 return talloc_named_const(ctx, el_size * count, name);
1129 alloc an zero array, checking for integer overflow in the array size
1131 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1133 if (count >= MAX_TALLOC_SIZE/el_size) {
1136 return _talloc_zero(ctx, el_size * count, name);
1141 realloc an array, checking for integer overflow in the array size
1143 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
1145 if (count >= MAX_TALLOC_SIZE/el_size) {
1148 return _talloc_realloc(ctx, ptr, el_size * count, name);
1152 a function version of talloc_realloc(), so it can be passed as a function pointer
1153 to libraries that want a realloc function (a realloc function encapsulates
1154 all the basic capabilities of an allocation library, which is why this is useful)
1156 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1158 return _talloc_realloc(context, ptr, size, NULL);
1162 static void talloc_autofree(void)
1164 talloc_free(cleanup_context);
1165 cleanup_context = NULL;
1169 return a context which will be auto-freed on exit
1170 this is useful for reducing the noise in leak reports
1172 void *talloc_autofree_context(void)
1174 if (cleanup_context == NULL) {
1175 cleanup_context = talloc_named_const(NULL, 0, "autofree_context");
1176 atexit(talloc_autofree);
1178 return cleanup_context;
1181 size_t talloc_get_size(const void *context)
1183 struct talloc_chunk *tc;
1185 if (context == NULL)
1188 tc = talloc_chunk_from_ptr(context);
1194 find a parent of this context that has the given name, if any
1196 void *talloc_find_parent_byname(const void *context, const char *name)
1198 struct talloc_chunk *tc;
1200 if (context == NULL) {
1204 tc = talloc_chunk_from_ptr(context);
1206 if (tc->name && strcmp(tc->name, name) == 0) {
1207 return TC_PTR_FROM_CHUNK(tc);
1209 while (tc && tc->prev) tc = tc->prev;
1218 show the parentage of a context
1220 void talloc_show_parents(const void *context, FILE *file)
1222 struct talloc_chunk *tc;
1224 if (context == NULL) {
1225 fprintf(file, "talloc no parents for NULL\n");
1229 tc = talloc_chunk_from_ptr(context);
1230 fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
1232 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
1233 while (tc && tc->prev) tc = tc->prev;
1241 return 1 if ptr is a parent of context
1243 int talloc_is_parent(const void *context, const char *ptr)
1245 struct talloc_chunk *tc;
1247 if (context == NULL) {
1251 tc = talloc_chunk_from_ptr(context);
1253 if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
1254 while (tc && tc->prev) tc = tc->prev;