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
9 Copyright (C) Stefan Metzmacher 2006
11 ** NOTE! The following LGPL license applies to the talloc
12 ** library. This does NOT imply that all of Samba is released
15 This library is free software; you can redistribute it and/or
16 modify it under the terms of the GNU Lesser General Public
17 License as published by the Free Software Foundation; either
18 version 2 of the License, or (at your option) any later version.
20 This library is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 Lesser General Public License for more details.
25 You should have received a copy of the GNU Lesser General Public
26 License along with this library; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 inspired by http://swapped.cc/halloc/
36 #if (SAMBA_VERSION_MAJOR<4)
38 /* This is to circumvent SAMBA3's paranoid malloc checker. Here in this file
39 * we trust ourselves... */
46 #define _TALLOC_SAMBA3
47 #endif /* (SAMBA_VERSION_MAJOR<4) */
48 #endif /* _SAMBA_BUILD_ */
50 #ifndef _TALLOC_SAMBA3
53 #endif /* not _TALLOC_SAMBA3 */
55 /* use this to force every realloc to change the pointer, to stress test
56 code that might not cope */
57 #define ALWAYS_REALLOC 0
60 #define MAX_TALLOC_SIZE 0x10000000
61 #define TALLOC_MAGIC 0xe814ec70
62 #define TALLOC_FLAG_FREE 0x01
63 #define TALLOC_FLAG_LOOP 0x02
64 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
66 /* by default we abort when given a bad pointer (such as when talloc_free() is called
67 on a pointer that came from malloc() */
69 #define TALLOC_ABORT(reason) abort()
72 #ifndef discard_const_p
73 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
74 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
76 # define discard_const_p(type, ptr) ((type *)(ptr))
80 /* this null_context is only used if talloc_enable_leak_report() or
81 talloc_enable_leak_report_full() is called, otherwise it remains
84 static void *null_context;
85 static void *cleanup_context;
87 struct talloc_reference_handle {
88 struct talloc_reference_handle *next, *prev;
92 typedef int (*talloc_destructor_t)(void *);
95 struct talloc_chunk *next, *prev;
96 struct talloc_chunk *parent, *child;
97 struct talloc_reference_handle *refs;
98 talloc_destructor_t destructor;
104 /* 16 byte alignment seems to keep everyone happy */
105 #define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
106 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
108 /* panic if we get a bad magic value */
109 static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
111 const char *pp = (const char *)ptr;
112 struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
113 if ((tc->flags & ~0xF) != TALLOC_MAGIC) {
114 TALLOC_ABORT("Bad talloc magic value - unknown value");
116 if (tc->flags & TALLOC_FLAG_FREE) {
117 TALLOC_ABORT("Bad talloc magic value - double free");
122 /* hook into the front of the list */
123 #define _TLIST_ADD(list, p) \
127 (p)->next = (p)->prev = NULL; \
129 (list)->prev = (p); \
130 (p)->next = (list); \
136 /* remove an element from a list - element doesn't have to be in list. */
137 #define _TLIST_REMOVE(list, p) \
139 if ((p) == (list)) { \
140 (list) = (p)->next; \
141 if (list) (list)->prev = NULL; \
143 if ((p)->prev) (p)->prev->next = (p)->next; \
144 if ((p)->next) (p)->next->prev = (p)->prev; \
146 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
151 return the parent chunk of a pointer
153 static struct talloc_chunk *talloc_parent_chunk(const void *ptr)
155 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
156 while (tc->prev) tc=tc->prev;
160 void *talloc_parent(const void *ptr)
162 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
163 return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
167 Allocate a bit of memory as a child of an existing pointer
169 void *_talloc(const void *context, size_t size)
171 struct talloc_chunk *tc;
173 if (context == NULL) {
174 context = null_context;
177 if (size >= MAX_TALLOC_SIZE) {
181 tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size);
182 if (tc == NULL) return NULL;
185 tc->flags = TALLOC_MAGIC;
186 tc->destructor = NULL;
192 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
197 parent->child->parent = NULL;
200 _TLIST_ADD(parent->child, tc);
202 tc->next = tc->prev = tc->parent = NULL;
205 return TC_PTR_FROM_CHUNK(tc);
210 setup a destructor to be called on free of a pointer
211 the destructor should return 0 on success, or -1 on failure.
212 if the destructor fails then the free is failed, and the memory can
213 be continued to be used
215 void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
217 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
218 tc->destructor = destructor;
222 increase the reference count on a piece of memory.
224 int talloc_increase_ref_count(const void *ptr)
226 if (!talloc_reference(null_context, ptr)) {
233 helper for talloc_reference()
235 static int talloc_reference_destructor(struct talloc_reference_handle *handle)
237 struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
238 _TLIST_REMOVE(ptr_tc->refs, handle);
243 make a secondary reference to a pointer, hanging off the given context.
244 the pointer remains valid until both the original caller and this given
247 the major use for this is when two different structures need to reference the
248 same underlying data, and you want to be able to free the two instances separately,
251 void *_talloc_reference(const void *context, const void *ptr)
253 struct talloc_chunk *tc;
254 struct talloc_reference_handle *handle;
255 if (ptr == NULL) return NULL;
257 tc = talloc_chunk_from_ptr(ptr);
258 handle = (struct talloc_reference_handle *)talloc_named_const(context,
259 sizeof(struct talloc_reference_handle),
260 TALLOC_MAGIC_REFERENCE);
261 if (handle == NULL) return NULL;
263 /* note that we hang the destructor off the handle, not the
264 main context as that allows the caller to still setup their
265 own destructor on the context if they want to */
266 talloc_set_destructor(handle, talloc_reference_destructor);
267 handle->ptr = discard_const_p(void, ptr);
268 _TLIST_ADD(tc->refs, handle);
273 remove a secondary reference to a pointer. This undo's what
274 talloc_reference() has done. The context and pointer arguments
275 must match those given to a talloc_reference()
277 static int talloc_unreference(const void *context, const void *ptr)
279 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
280 struct talloc_reference_handle *h;
282 if (context == NULL) {
283 context = null_context;
286 for (h=tc->refs;h;h=h->next) {
287 struct talloc_chunk *p = talloc_parent_chunk(h);
289 if (context == NULL) break;
290 } else if (TC_PTR_FROM_CHUNK(p) == context) {
298 return talloc_free(h);
302 remove a specific parent context from a pointer. This is a more
303 controlled varient of talloc_free()
305 int talloc_unlink(const void *context, void *ptr)
307 struct talloc_chunk *tc_p, *new_p;
314 if (context == NULL) {
315 context = null_context;
318 if (talloc_unreference(context, ptr) == 0) {
322 if (context == NULL) {
323 if (talloc_parent_chunk(ptr) != NULL) {
327 if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) {
332 tc_p = talloc_chunk_from_ptr(ptr);
334 if (tc_p->refs == NULL) {
335 return talloc_free(ptr);
338 new_p = talloc_parent_chunk(tc_p->refs);
340 new_parent = TC_PTR_FROM_CHUNK(new_p);
345 if (talloc_unreference(new_parent, ptr) != 0) {
349 talloc_steal(new_parent, ptr);
355 add a name to an existing pointer - va_list version
357 static const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
359 static const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
361 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
362 tc->name = talloc_vasprintf(ptr, fmt, ap);
364 talloc_set_name_const(tc->name, ".name");
370 add a name to an existing pointer
372 const char *talloc_set_name(const void *ptr, const char *fmt, ...)
377 name = talloc_set_name_v(ptr, fmt, ap);
383 more efficient way to add a name to a pointer - the name must point to a
386 void talloc_set_name_const(const void *ptr, const char *name)
388 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
393 create a named talloc pointer. Any talloc pointer can be named, and
394 talloc_named() operates just like talloc() except that it allows you
397 void *talloc_named(const void *context, size_t size, const char *fmt, ...)
403 ptr = _talloc(context, size);
404 if (ptr == NULL) return NULL;
407 name = talloc_set_name_v(ptr, fmt, ap);
419 create a named talloc pointer. Any talloc pointer can be named, and
420 talloc_named() operates just like talloc() except that it allows you
423 void *talloc_named_const(const void *context, size_t size, const char *name)
427 ptr = _talloc(context, size);
432 talloc_set_name_const(ptr, name);
438 return the name of a talloc ptr, or "UNNAMED"
440 const char *talloc_get_name(const void *ptr)
442 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
443 if (tc->name == TALLOC_MAGIC_REFERENCE) {
454 check if a pointer has the given name. If it does, return the pointer,
455 otherwise return NULL
457 void *talloc_check_name(const void *ptr, const char *name)
460 if (ptr == NULL) return NULL;
461 pname = talloc_get_name(ptr);
462 if (pname == name || strcmp(pname, name) == 0) {
463 return discard_const_p(void, ptr);
470 this is for compatibility with older versions of talloc
472 void *talloc_init(const char *fmt, ...)
479 * samba3 expects talloc_report_depth_cb(NULL, ...)
480 * reports all talloc'ed memory, so we need to enable
483 talloc_enable_null_tracking();
485 ptr = _talloc(NULL, 0);
486 if (ptr == NULL) return NULL;
489 name = talloc_set_name_v(ptr, fmt, ap);
501 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
502 should probably not be used in new code. It's in here to keep the talloc
503 code consistent across Samba 3 and 4.
505 void talloc_free_children(void *ptr)
507 struct talloc_chunk *tc;
513 tc = talloc_chunk_from_ptr(ptr);
516 /* we need to work out who will own an abandoned child
517 if it cannot be freed. In priority order, the first
518 choice is owner of any remaining reference to this
519 pointer, the second choice is our parent, and the
520 final choice is the null context. */
521 void *child = TC_PTR_FROM_CHUNK(tc->child);
522 const void *new_parent = null_context;
523 if (tc->child->refs) {
524 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
525 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
527 if (talloc_free(child) == -1) {
528 if (new_parent == null_context) {
529 struct talloc_chunk *p = talloc_parent_chunk(ptr);
530 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
532 talloc_steal(new_parent, child);
538 free a talloc pointer. This also frees all child pointers of this
541 return 0 if the memory is actually freed, otherwise -1. The memory
542 will not be freed if the ref_count is > 1 or the destructor (if
543 any) returns non-zero
545 int talloc_free(void *ptr)
547 struct talloc_chunk *tc;
554 tc = talloc_chunk_from_ptr(ptr);
558 /* check this is a reference from a child or grantchild
559 * back to it's parent or grantparent
561 * in that case we need to remove the reference and
562 * call another instance of talloc_free() on the current
565 is_child = talloc_is_parent(tc->refs, ptr);
566 talloc_free(tc->refs);
568 return talloc_free(ptr);
573 if (tc->flags & TALLOC_FLAG_LOOP) {
574 /* we have a free loop - stop looping */
578 if (tc->destructor) {
579 talloc_destructor_t d = tc->destructor;
580 if (d == (talloc_destructor_t)-1) {
583 tc->destructor = (talloc_destructor_t)-1;
588 tc->destructor = NULL;
592 _TLIST_REMOVE(tc->parent->child, tc);
593 if (tc->parent->child) {
594 tc->parent->child->parent = tc->parent;
597 if (tc->prev) tc->prev->next = tc->next;
598 if (tc->next) tc->next->prev = tc->prev;
601 tc->flags |= TALLOC_FLAG_LOOP;
602 talloc_free_children(ptr);
604 tc->flags |= TALLOC_FLAG_FREE;
614 A talloc version of realloc. The context argument is only used if
617 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
619 struct talloc_chunk *tc;
622 /* size zero is equivalent to free() */
628 if (size >= MAX_TALLOC_SIZE) {
632 /* realloc(NULL) is equavalent to malloc() */
634 return talloc_named_const(context, size, name);
637 tc = talloc_chunk_from_ptr(ptr);
639 /* don't allow realloc on referenced pointers */
644 /* by resetting magic we catch users of the old memory */
645 tc->flags |= TALLOC_FLAG_FREE;
648 new_ptr = malloc(size + TC_HDR_SIZE);
650 memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE);
654 new_ptr = realloc(tc, size + TC_HDR_SIZE);
657 tc->flags &= ~TALLOC_FLAG_FREE;
661 tc = (struct talloc_chunk *)new_ptr;
662 tc->flags &= ~TALLOC_FLAG_FREE;
664 tc->parent->child = tc;
667 tc->child->parent = tc;
678 talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
680 return TC_PTR_FROM_CHUNK(tc);
684 move a lump of memory from one talloc context to another return the
685 ptr on success, or NULL if it could not be transferred.
686 passing NULL as ptr will always return NULL with no side effects.
688 void *_talloc_steal(const void *new_ctx, const void *ptr)
690 struct talloc_chunk *tc, *new_tc;
696 if (new_ctx == NULL) {
697 new_ctx = null_context;
700 tc = talloc_chunk_from_ptr(ptr);
702 if (new_ctx == NULL) {
704 _TLIST_REMOVE(tc->parent->child, tc);
705 if (tc->parent->child) {
706 tc->parent->child->parent = tc->parent;
709 if (tc->prev) tc->prev->next = tc->next;
710 if (tc->next) tc->next->prev = tc->prev;
713 tc->parent = tc->next = tc->prev = NULL;
714 return discard_const_p(void, ptr);
717 new_tc = talloc_chunk_from_ptr(new_ctx);
719 if (tc == new_tc || tc->parent == new_tc) {
720 return discard_const_p(void, ptr);
724 _TLIST_REMOVE(tc->parent->child, tc);
725 if (tc->parent->child) {
726 tc->parent->child->parent = tc->parent;
729 if (tc->prev) tc->prev->next = tc->next;
730 if (tc->next) tc->next->prev = tc->prev;
734 if (new_tc->child) new_tc->child->parent = NULL;
735 _TLIST_ADD(new_tc->child, tc);
737 return discard_const_p(void, ptr);
741 a wrapper around talloc_steal() for situations where you are moving a pointer
742 between two structures, and want the old pointer to be set to NULL
744 void *_talloc_move(const void *new_ctx, const void **pptr)
746 void *ret = _talloc_steal(new_ctx, *pptr);
752 return the total size of a talloc pool (subtree)
754 size_t talloc_total_size(const void *ptr)
757 struct talloc_chunk *c, *tc;
766 tc = talloc_chunk_from_ptr(ptr);
768 if (tc->flags & TALLOC_FLAG_LOOP) {
772 tc->flags |= TALLOC_FLAG_LOOP;
775 for (c=tc->child;c;c=c->next) {
776 total += talloc_total_size(TC_PTR_FROM_CHUNK(c));
779 tc->flags &= ~TALLOC_FLAG_LOOP;
785 return the total number of blocks in a talloc pool (subtree)
787 size_t talloc_total_blocks(const void *ptr)
790 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
792 if (tc->flags & TALLOC_FLAG_LOOP) {
796 tc->flags |= TALLOC_FLAG_LOOP;
799 for (c=tc->child;c;c=c->next) {
800 total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
803 tc->flags &= ~TALLOC_FLAG_LOOP;
809 return the number of external references to a pointer
811 size_t talloc_reference_count(const void *ptr)
813 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
814 struct talloc_reference_handle *h;
817 for (h=tc->refs;h;h=h->next) {
824 report on memory usage by all children of a pointer, giving a full tree view
826 void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
827 void (*callback)(const void *ptr,
828 int depth, int max_depth,
833 struct talloc_chunk *c, *tc;
838 if (ptr == NULL) return;
840 tc = talloc_chunk_from_ptr(ptr);
842 if (tc->flags & TALLOC_FLAG_LOOP) {
846 callback(ptr, depth, max_depth, 0, private_data);
848 if (max_depth >= 0 && depth >= max_depth) {
852 tc->flags |= TALLOC_FLAG_LOOP;
853 for (c=tc->child;c;c=c->next) {
854 if (c->name == TALLOC_MAGIC_REFERENCE) {
855 struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
856 callback(h->ptr, depth + 1, max_depth, 1, private_data);
858 talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
861 tc->flags &= ~TALLOC_FLAG_LOOP;
864 static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
866 const char *name = talloc_get_name(ptr);
867 FILE *f = (FILE *)_f;
870 fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
875 fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
876 (max_depth < 0 ? "full " :""), name,
877 (unsigned long)talloc_total_size(ptr),
878 (unsigned long)talloc_total_blocks(ptr));
882 fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n",
885 (unsigned long)talloc_total_size(ptr),
886 (unsigned long)talloc_total_blocks(ptr),
887 (int)talloc_reference_count(ptr));
891 report on memory usage by all children of a pointer, giving a full tree view
893 void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
895 talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
900 report on memory usage by all children of a pointer, giving a full tree view
902 void talloc_report_full(const void *ptr, FILE *f)
904 talloc_report_depth_file(ptr, 0, -1, f);
908 report on memory usage by all children of a pointer
910 void talloc_report(const void *ptr, FILE *f)
912 talloc_report_depth_file(ptr, 0, 1, f);
916 report on any memory hanging off the null context
918 static void talloc_report_null(void)
920 if (talloc_total_size(null_context) != 0) {
921 talloc_report(null_context, stderr);
926 report on any memory hanging off the null context
928 static void talloc_report_null_full(void)
930 if (talloc_total_size(null_context) != 0) {
931 talloc_report_full(null_context, stderr);
936 enable tracking of the NULL context
938 void talloc_enable_null_tracking(void)
940 if (null_context == NULL) {
941 null_context = talloc_named_const(NULL, 0, "null_context");
946 disable tracking of the NULL context
948 void talloc_disable_null_tracking(void)
950 talloc_free(null_context);
955 enable leak reporting on exit
957 void talloc_enable_leak_report(void)
959 talloc_enable_null_tracking();
960 atexit(talloc_report_null);
964 enable full leak reporting on exit
966 void talloc_enable_leak_report_full(void)
968 talloc_enable_null_tracking();
969 atexit(talloc_report_null_full);
973 talloc and zero memory.
975 void *_talloc_zero(const void *ctx, size_t size, const char *name)
977 void *p = talloc_named_const(ctx, size, name);
980 memset(p, '\0', size);
988 memdup with a talloc.
990 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
992 void *newp = talloc_named_const(t, size, name);
995 memcpy(newp, p, size);
1002 strdup with a talloc
1004 char *talloc_strdup(const void *t, const char *p)
1010 ret = (char *)talloc_memdup(t, p, strlen(p) + 1);
1012 talloc_set_name_const(ret, ret);
1018 append to a talloced string
1020 char *talloc_append_string(const void *t, char *orig, const char *append)
1023 size_t olen = strlen(orig);
1029 alenz = strlen(append) + 1;
1031 ret = talloc_realloc(t, orig, char, olen + alenz);
1035 /* append the string with the trailing \0 */
1036 memcpy(&ret[olen], append, alenz);
1042 strndup with a talloc
1044 char *talloc_strndup(const void *t, const char *p, size_t n)
1049 for (len=0; len<n && p[len]; len++) ;
1051 ret = (char *)_talloc(t, len + 1);
1052 if (!ret) { return NULL; }
1053 memcpy(ret, p, len);
1055 talloc_set_name_const(ret, ret);
1059 #ifndef HAVE_VA_COPY
1060 #ifdef HAVE___VA_COPY
1061 #define va_copy(dest, src) __va_copy(dest, src)
1063 #define va_copy(dest, src) (dest) = (src)
1067 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
1076 /* this call looks strange, but it makes it work on older solaris boxes */
1077 if ((len = vsnprintf(&c, 1, fmt, ap2)) < 0) {
1081 ret = (char *)_talloc(t, len+1);
1084 vsnprintf(ret, len+1, fmt, ap2);
1085 talloc_set_name_const(ret, ret);
1093 Perform string formatting, and return a pointer to newly allocated
1094 memory holding the result, inside a memory pool.
1096 char *talloc_asprintf(const void *t, const char *fmt, ...)
1102 ret = talloc_vasprintf(t, fmt, ap);
1109 * Realloc @p s to append the formatted result of @p fmt and @p ap,
1110 * and return @p s, which may have moved. Good for gradually
1111 * accumulating output into a string buffer.
1113 char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1115 struct talloc_chunk *tc;
1121 return talloc_vasprintf(NULL, fmt, ap);
1124 tc = talloc_chunk_from_ptr(s);
1128 s_len = tc->size - 1;
1129 if ((len = vsnprintf(&c, 1, fmt, ap2)) <= 0) {
1130 /* Either the vsnprintf failed or the format resulted in
1131 * no characters being formatted. In the former case, we
1132 * ought to return NULL, in the latter we ought to return
1133 * the original string. Most current callers of this
1134 * function expect it to never return NULL.
1139 s = talloc_realloc(NULL, s, char, s_len + len+1);
1140 if (!s) return NULL;
1144 vsnprintf(s+s_len, len+1, fmt, ap2);
1145 talloc_set_name_const(s, s);
1151 Realloc @p s to append the formatted result of @p fmt and return @p
1152 s, which may have moved. Good for gradually accumulating output
1153 into a string buffer.
1155 char *talloc_asprintf_append(char *s, const char *fmt, ...)
1160 s = talloc_vasprintf_append(s, fmt, ap);
1166 alloc an array, checking for integer overflow in the array size
1168 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1170 if (count >= MAX_TALLOC_SIZE/el_size) {
1173 return talloc_named_const(ctx, el_size * count, name);
1177 alloc an zero array, checking for integer overflow in the array size
1179 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1181 if (count >= MAX_TALLOC_SIZE/el_size) {
1184 return _talloc_zero(ctx, el_size * count, name);
1189 realloc an array, checking for integer overflow in the array size
1191 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
1193 if (count >= MAX_TALLOC_SIZE/el_size) {
1196 return _talloc_realloc(ctx, ptr, el_size * count, name);
1200 a function version of talloc_realloc(), so it can be passed as a function pointer
1201 to libraries that want a realloc function (a realloc function encapsulates
1202 all the basic capabilities of an allocation library, which is why this is useful)
1204 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1206 return _talloc_realloc(context, ptr, size, NULL);
1210 static void talloc_autofree(void)
1212 talloc_free(cleanup_context);
1213 cleanup_context = NULL;
1217 return a context which will be auto-freed on exit
1218 this is useful for reducing the noise in leak reports
1220 void *talloc_autofree_context(void)
1222 if (cleanup_context == NULL) {
1223 cleanup_context = talloc_named_const(NULL, 0, "autofree_context");
1224 atexit(talloc_autofree);
1226 return cleanup_context;
1229 size_t talloc_get_size(const void *context)
1231 struct talloc_chunk *tc;
1233 if (context == NULL)
1236 tc = talloc_chunk_from_ptr(context);
1242 find a parent of this context that has the given name, if any
1244 void *talloc_find_parent_byname(const void *context, const char *name)
1246 struct talloc_chunk *tc;
1248 if (context == NULL) {
1252 tc = talloc_chunk_from_ptr(context);
1254 if (tc->name && strcmp(tc->name, name) == 0) {
1255 return TC_PTR_FROM_CHUNK(tc);
1257 while (tc && tc->prev) tc = tc->prev;
1266 show the parentage of a context
1268 void talloc_show_parents(const void *context, FILE *file)
1270 struct talloc_chunk *tc;
1272 if (context == NULL) {
1273 fprintf(file, "talloc no parents for NULL\n");
1277 tc = talloc_chunk_from_ptr(context);
1278 fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
1280 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
1281 while (tc && tc->prev) tc = tc->prev;
1289 return 1 if ptr is a parent of context
1291 int talloc_is_parent(const void *context, const void *ptr)
1293 struct talloc_chunk *tc;
1295 if (context == NULL) {
1299 tc = talloc_chunk_from_ptr(context);
1301 if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
1302 while (tc && tc->prev) tc = tc->prev;