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 const void **pptr = (const void **)_pptr;
747 void *ret = _talloc_steal(new_ctx, *pptr);
753 return the total size of a talloc pool (subtree)
755 size_t talloc_total_size(const void *ptr)
758 struct talloc_chunk *c, *tc;
767 tc = talloc_chunk_from_ptr(ptr);
769 if (tc->flags & TALLOC_FLAG_LOOP) {
773 tc->flags |= TALLOC_FLAG_LOOP;
776 for (c=tc->child;c;c=c->next) {
777 total += talloc_total_size(TC_PTR_FROM_CHUNK(c));
780 tc->flags &= ~TALLOC_FLAG_LOOP;
786 return the total number of blocks in a talloc pool (subtree)
788 size_t talloc_total_blocks(const void *ptr)
791 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
793 if (tc->flags & TALLOC_FLAG_LOOP) {
797 tc->flags |= TALLOC_FLAG_LOOP;
800 for (c=tc->child;c;c=c->next) {
801 total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
804 tc->flags &= ~TALLOC_FLAG_LOOP;
810 return the number of external references to a pointer
812 size_t talloc_reference_count(const void *ptr)
814 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
815 struct talloc_reference_handle *h;
818 for (h=tc->refs;h;h=h->next) {
825 report on memory usage by all children of a pointer, giving a full tree view
827 void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
828 void (*callback)(const void *ptr,
829 int depth, int max_depth,
834 struct talloc_chunk *c, *tc;
839 if (ptr == NULL) return;
841 tc = talloc_chunk_from_ptr(ptr);
843 if (tc->flags & TALLOC_FLAG_LOOP) {
847 callback(ptr, depth, max_depth, 0, private_data);
849 if (max_depth >= 0 && depth >= max_depth) {
853 tc->flags |= TALLOC_FLAG_LOOP;
854 for (c=tc->child;c;c=c->next) {
855 if (c->name == TALLOC_MAGIC_REFERENCE) {
856 struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
857 callback(h->ptr, depth + 1, max_depth, 1, private_data);
859 talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
862 tc->flags &= ~TALLOC_FLAG_LOOP;
865 static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
867 const char *name = talloc_get_name(ptr);
868 FILE *f = (FILE *)_f;
871 fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
876 fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
877 (max_depth < 0 ? "full " :""), name,
878 (unsigned long)talloc_total_size(ptr),
879 (unsigned long)talloc_total_blocks(ptr));
883 fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n",
886 (unsigned long)talloc_total_size(ptr),
887 (unsigned long)talloc_total_blocks(ptr),
888 (int)talloc_reference_count(ptr));
892 report on memory usage by all children of a pointer, giving a full tree view
894 void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
896 talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
901 report on memory usage by all children of a pointer, giving a full tree view
903 void talloc_report_full(const void *ptr, FILE *f)
905 talloc_report_depth_file(ptr, 0, -1, f);
909 report on memory usage by all children of a pointer
911 void talloc_report(const void *ptr, FILE *f)
913 talloc_report_depth_file(ptr, 0, 1, f);
917 report on any memory hanging off the null context
919 static void talloc_report_null(void)
921 if (talloc_total_size(null_context) != 0) {
922 talloc_report(null_context, stderr);
927 report on any memory hanging off the null context
929 static void talloc_report_null_full(void)
931 if (talloc_total_size(null_context) != 0) {
932 talloc_report_full(null_context, stderr);
937 enable tracking of the NULL context
939 void talloc_enable_null_tracking(void)
941 if (null_context == NULL) {
942 null_context = talloc_named_const(NULL, 0, "null_context");
947 disable tracking of the NULL context
949 void talloc_disable_null_tracking(void)
951 talloc_free(null_context);
956 enable leak reporting on exit
958 void talloc_enable_leak_report(void)
960 talloc_enable_null_tracking();
961 atexit(talloc_report_null);
965 enable full leak reporting on exit
967 void talloc_enable_leak_report_full(void)
969 talloc_enable_null_tracking();
970 atexit(talloc_report_null_full);
974 talloc and zero memory.
976 void *_talloc_zero(const void *ctx, size_t size, const char *name)
978 void *p = talloc_named_const(ctx, size, name);
981 memset(p, '\0', size);
989 memdup with a talloc.
991 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
993 void *newp = talloc_named_const(t, size, name);
996 memcpy(newp, p, size);
1003 strdup with a talloc
1005 char *talloc_strdup(const void *t, const char *p)
1011 ret = (char *)talloc_memdup(t, p, strlen(p) + 1);
1013 talloc_set_name_const(ret, ret);
1019 append to a talloced string
1021 char *talloc_append_string(const void *t, char *orig, const char *append)
1024 size_t olen = strlen(orig);
1030 alenz = strlen(append) + 1;
1032 ret = talloc_realloc(t, orig, char, olen + alenz);
1036 /* append the string with the trailing \0 */
1037 memcpy(&ret[olen], append, alenz);
1043 strndup with a talloc
1045 char *talloc_strndup(const void *t, const char *p, size_t n)
1050 for (len=0; len<n && p[len]; len++) ;
1052 ret = (char *)_talloc(t, len + 1);
1053 if (!ret) { return NULL; }
1054 memcpy(ret, p, len);
1056 talloc_set_name_const(ret, ret);
1060 #ifndef HAVE_VA_COPY
1061 #ifdef HAVE___VA_COPY
1062 #define va_copy(dest, src) __va_copy(dest, src)
1064 #define va_copy(dest, src) (dest) = (src)
1068 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
1077 /* this call looks strange, but it makes it work on older solaris boxes */
1078 if ((len = vsnprintf(&c, 1, fmt, ap2)) < 0) {
1082 ret = (char *)_talloc(t, len+1);
1085 vsnprintf(ret, len+1, fmt, ap2);
1086 talloc_set_name_const(ret, ret);
1094 Perform string formatting, and return a pointer to newly allocated
1095 memory holding the result, inside a memory pool.
1097 char *talloc_asprintf(const void *t, const char *fmt, ...)
1103 ret = talloc_vasprintf(t, fmt, ap);
1110 * Realloc @p s to append the formatted result of @p fmt and @p ap,
1111 * and return @p s, which may have moved. Good for gradually
1112 * accumulating output into a string buffer.
1114 char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1116 struct talloc_chunk *tc;
1122 return talloc_vasprintf(NULL, fmt, ap);
1125 tc = talloc_chunk_from_ptr(s);
1129 s_len = tc->size - 1;
1130 if ((len = vsnprintf(&c, 1, fmt, ap2)) <= 0) {
1131 /* Either the vsnprintf failed or the format resulted in
1132 * no characters being formatted. In the former case, we
1133 * ought to return NULL, in the latter we ought to return
1134 * the original string. Most current callers of this
1135 * function expect it to never return NULL.
1140 s = talloc_realloc(NULL, s, char, s_len + len+1);
1141 if (!s) return NULL;
1145 vsnprintf(s+s_len, len+1, fmt, ap2);
1146 talloc_set_name_const(s, s);
1152 Realloc @p s to append the formatted result of @p fmt and return @p
1153 s, which may have moved. Good for gradually accumulating output
1154 into a string buffer.
1156 char *talloc_asprintf_append(char *s, const char *fmt, ...)
1161 s = talloc_vasprintf_append(s, fmt, ap);
1167 alloc an array, checking for integer overflow in the array size
1169 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1171 if (count >= MAX_TALLOC_SIZE/el_size) {
1174 return talloc_named_const(ctx, el_size * count, name);
1178 alloc an zero array, checking for integer overflow in the array size
1180 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1182 if (count >= MAX_TALLOC_SIZE/el_size) {
1185 return _talloc_zero(ctx, el_size * count, name);
1190 realloc an array, checking for integer overflow in the array size
1192 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
1194 if (count >= MAX_TALLOC_SIZE/el_size) {
1197 return _talloc_realloc(ctx, ptr, el_size * count, name);
1201 a function version of talloc_realloc(), so it can be passed as a function pointer
1202 to libraries that want a realloc function (a realloc function encapsulates
1203 all the basic capabilities of an allocation library, which is why this is useful)
1205 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1207 return _talloc_realloc(context, ptr, size, NULL);
1211 static void talloc_autofree(void)
1213 talloc_free(cleanup_context);
1214 cleanup_context = NULL;
1218 return a context which will be auto-freed on exit
1219 this is useful for reducing the noise in leak reports
1221 void *talloc_autofree_context(void)
1223 if (cleanup_context == NULL) {
1224 cleanup_context = talloc_named_const(NULL, 0, "autofree_context");
1225 atexit(talloc_autofree);
1227 return cleanup_context;
1230 size_t talloc_get_size(const void *context)
1232 struct talloc_chunk *tc;
1234 if (context == NULL)
1237 tc = talloc_chunk_from_ptr(context);
1243 find a parent of this context that has the given name, if any
1245 void *talloc_find_parent_byname(const void *context, const char *name)
1247 struct talloc_chunk *tc;
1249 if (context == NULL) {
1253 tc = talloc_chunk_from_ptr(context);
1255 if (tc->name && strcmp(tc->name, name) == 0) {
1256 return TC_PTR_FROM_CHUNK(tc);
1258 while (tc && tc->prev) tc = tc->prev;
1267 show the parentage of a context
1269 void talloc_show_parents(const void *context, FILE *file)
1271 struct talloc_chunk *tc;
1273 if (context == NULL) {
1274 fprintf(file, "talloc no parents for NULL\n");
1278 tc = talloc_chunk_from_ptr(context);
1279 fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
1281 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
1282 while (tc && tc->prev) tc = tc->prev;
1290 return 1 if ptr is a parent of context
1292 int talloc_is_parent(const void *context, const void *ptr)
1294 struct talloc_chunk *tc;
1296 if (context == NULL) {
1300 tc = talloc_chunk_from_ptr(context);
1302 if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
1303 while (tc && tc->prev) tc = tc->prev;