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 3 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, see <http://www.gnu.org/licenses/>.
30 inspired by http://swapped.cc/halloc/
33 /* Commented out for building within Chromium */
34 /* #include "replace.h" */
37 #ifdef TALLOC_BUILD_VERSION_MAJOR
38 #if (TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR)
39 #error "TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR"
43 #ifdef TALLOC_BUILD_VERSION_MINOR
44 #if (TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR)
45 #error "TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR"
49 /* use this to force every realloc to change the pointer, to stress test
50 code that might not cope */
51 #define ALWAYS_REALLOC 0
54 #define MAX_TALLOC_SIZE 0x10000000
55 #define TALLOC_MAGIC_BASE 0xe814ec70
56 #define TALLOC_MAGIC ( \
58 (TALLOC_VERSION_MAJOR << 12) + \
59 (TALLOC_VERSION_MINOR << 4) \
62 #define TALLOC_FLAG_FREE 0x01
63 #define TALLOC_FLAG_LOOP 0x02
64 #define TALLOC_FLAG_POOL 0x04 /* This is a talloc pool */
65 #define TALLOC_FLAG_POOLMEM 0x08 /* This is allocated in a pool */
66 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
68 /* by default we abort when given a bad pointer (such as when talloc_free() is called
69 on a pointer that came from malloc() */
71 #define TALLOC_ABORT(reason) abort()
74 #ifndef discard_const_p
75 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
76 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
78 # define discard_const_p(type, ptr) ((type *)(ptr))
82 /* these macros gain us a few percent of speed on gcc */
84 /* the strange !! is to ensure that __builtin_expect() takes either 0 or 1
85 as its first argument */
87 #define likely(x) __builtin_expect(!!(x), 1)
90 #define unlikely(x) __builtin_expect(!!(x), 0)
97 #define unlikely(x) (x)
101 /* inline isn't supported in C files in Visual Studio 2008 on Windows */
105 #define INLINE inline
108 /* this null_context is only used if talloc_enable_leak_report() or
109 talloc_enable_leak_report_full() is called, otherwise it remains
112 static void *null_context
;
113 static void *autofree_context
;
115 struct talloc_reference_handle
{
116 struct talloc_reference_handle
*next
, *prev
;
118 const char *location
;
121 typedef int (*talloc_destructor_t
)(void *);
123 struct talloc_chunk
{
124 struct talloc_chunk
*next
, *prev
;
125 struct talloc_chunk
*parent
, *child
;
126 struct talloc_reference_handle
*refs
;
127 talloc_destructor_t destructor
;
133 * "pool" has dual use:
135 * For the talloc pool itself (i.e. TALLOC_FLAG_POOL is set), "pool"
136 * marks the end of the currently allocated area.
138 * For members of the pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool"
139 * is a pointer to the struct talloc_chunk of the pool that it was
140 * allocated from. This way children can quickly find the pool to chew
146 /* 16 byte alignment seems to keep everyone happy */
147 #define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
148 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
150 int talloc_version_major(void)
152 return TALLOC_VERSION_MAJOR
;
155 int talloc_version_minor(void)
157 return TALLOC_VERSION_MINOR
;
160 static void (*talloc_log_fn
)(const char *message
);
162 void talloc_set_log_fn(void (*log_fn
)(const char *message
))
164 talloc_log_fn
= log_fn
;
167 static void talloc_log(const char *fmt
, ...) PRINTF_ATTRIBUTE(1,2);
168 static void talloc_log(const char *fmt
, ...)
173 if (!talloc_log_fn
) {
178 message
= talloc_vasprintf(NULL
, fmt
, ap
);
181 talloc_log_fn(message
);
182 talloc_free(message
);
185 static void talloc_log_stderr(const char *message
)
187 fprintf(stderr
, "%s", message
);
190 void talloc_set_log_stderr(void)
192 talloc_set_log_fn(talloc_log_stderr
);
195 static void (*talloc_abort_fn
)(const char *reason
);
197 void talloc_set_abort_fn(void (*abort_fn
)(const char *reason
))
199 talloc_abort_fn
= abort_fn
;
202 static void talloc_abort(const char *reason
)
204 talloc_log("%s\n", reason
);
206 if (!talloc_abort_fn
) {
207 TALLOC_ABORT(reason
);
210 talloc_abort_fn(reason
);
213 static void talloc_abort_magic(unsigned magic
)
215 unsigned striped
= magic
- TALLOC_MAGIC_BASE
;
216 unsigned major
= (striped
& 0xFFFFF000) >> 12;
217 unsigned minor
= (striped
& 0x00000FF0) >> 4;
218 talloc_log("Bad talloc magic[0x%08X/%u/%u] expected[0x%08X/%u/%u]\n",
220 TALLOC_MAGIC
, TALLOC_VERSION_MAJOR
, TALLOC_VERSION_MINOR
);
221 talloc_abort("Bad talloc magic value - wrong talloc version used/mixed");
224 static void talloc_abort_double_free(void)
226 talloc_abort("Bad talloc magic value - double free");
229 static void talloc_abort_unknown_value(void)
231 talloc_abort("Bad talloc magic value - unknown value");
234 /* panic if we get a bad magic value */
235 static INLINE
struct talloc_chunk
*talloc_chunk_from_ptr(const void *ptr
)
237 const char *pp
= (const char *)ptr
;
238 struct talloc_chunk
*tc
= discard_const_p(struct talloc_chunk
, pp
- TC_HDR_SIZE
);
239 if (unlikely((tc
->flags
& (TALLOC_FLAG_FREE
| ~0xF)) != TALLOC_MAGIC
)) {
240 if ((tc
->flags
& (~0xFFF)) == TALLOC_MAGIC_BASE
) {
241 talloc_abort_magic(tc
->flags
& (~0xF));
245 if (tc
->flags
& TALLOC_FLAG_FREE
) {
246 talloc_log("talloc: double free error - first free may be at %s\n", tc
->name
);
247 talloc_abort_double_free();
250 talloc_abort_unknown_value();
257 /* hook into the front of the list */
258 #define _TLIST_ADD(list, p) \
262 (p)->next = (p)->prev = NULL; \
264 (list)->prev = (p); \
265 (p)->next = (list); \
271 /* remove an element from a list - element doesn't have to be in list. */
272 #define _TLIST_REMOVE(list, p) \
274 if ((p) == (list)) { \
275 (list) = (p)->next; \
276 if (list) (list)->prev = NULL; \
278 if ((p)->prev) (p)->prev->next = (p)->next; \
279 if ((p)->next) (p)->next->prev = (p)->prev; \
281 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
286 return the parent chunk of a pointer
288 static INLINE
struct talloc_chunk
*talloc_parent_chunk(const void *ptr
)
290 struct talloc_chunk
*tc
;
292 if (unlikely(ptr
== NULL
)) {
296 tc
= talloc_chunk_from_ptr(ptr
);
297 while (tc
->prev
) tc
=tc
->prev
;
302 void *talloc_parent(const void *ptr
)
304 struct talloc_chunk
*tc
= talloc_parent_chunk(ptr
);
305 return tc
? TC_PTR_FROM_CHUNK(tc
) : NULL
;
311 const char *talloc_parent_name(const void *ptr
)
313 struct talloc_chunk
*tc
= talloc_parent_chunk(ptr
);
314 return tc
? tc
->name
: NULL
;
318 A pool carries an in-pool object count count in the first 16 bytes.
319 bytes. This is done to support talloc_steal() to a parent outside of the
320 pool. The count includes the pool itself, so a talloc_free() on a pool will
321 only destroy the pool if the count has dropped to zero. A talloc_free() of a
322 pool member will reduce the count, and eventually also call free(3) on the
325 The object count is not put into "struct talloc_chunk" because it is only
326 relevant for talloc pools and the alignment to 16 bytes would increase the
327 memory footprint of each talloc chunk by those 16 bytes.
330 #define TALLOC_POOL_HDR_SIZE 16
332 static unsigned int *talloc_pool_objectcount(struct talloc_chunk
*tc
)
334 return (unsigned int *)((char *)tc
+ sizeof(struct talloc_chunk
));
341 static struct talloc_chunk
*talloc_alloc_pool(struct talloc_chunk
*parent
,
344 struct talloc_chunk
*pool_ctx
= NULL
;
346 struct talloc_chunk
*result
;
349 if (parent
== NULL
) {
353 if (parent
->flags
& TALLOC_FLAG_POOL
) {
356 else if (parent
->flags
& TALLOC_FLAG_POOLMEM
) {
357 pool_ctx
= (struct talloc_chunk
*)parent
->pool
;
360 if (pool_ctx
== NULL
) {
364 space_left
= ((char *)pool_ctx
+ TC_HDR_SIZE
+ pool_ctx
->size
)
365 - ((char *)pool_ctx
->pool
);
368 * Align size to 16 bytes
370 chunk_size
= ((size
+ 15) & ~15);
372 if (space_left
< chunk_size
) {
376 result
= (struct talloc_chunk
*)pool_ctx
->pool
;
378 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
379 VALGRIND_MAKE_MEM_UNDEFINED(result
, size
);
382 pool_ctx
->pool
= (void *)((char *)result
+ chunk_size
);
384 result
->flags
= TALLOC_MAGIC
| TALLOC_FLAG_POOLMEM
;
385 result
->pool
= pool_ctx
;
387 *talloc_pool_objectcount(pool_ctx
) += 1;
393 Allocate a bit of memory as a child of an existing pointer
395 static INLINE
void *__talloc(const void *context
, size_t size
)
397 struct talloc_chunk
*tc
= NULL
;
399 if (unlikely(context
== NULL
)) {
400 context
= null_context
;
403 if (unlikely(size
>= MAX_TALLOC_SIZE
)) {
407 if (context
!= NULL
) {
408 tc
= talloc_alloc_pool(talloc_chunk_from_ptr(context
),
413 tc
= (struct talloc_chunk
*)malloc(TC_HDR_SIZE
+size
);
414 if (unlikely(tc
== NULL
)) return NULL
;
415 tc
->flags
= TALLOC_MAGIC
;
420 tc
->destructor
= NULL
;
425 if (likely(context
)) {
426 struct talloc_chunk
*parent
= talloc_chunk_from_ptr(context
);
429 parent
->child
->parent
= NULL
;
430 tc
->next
= parent
->child
;
439 tc
->next
= tc
->prev
= tc
->parent
= NULL
;
442 return TC_PTR_FROM_CHUNK(tc
);
446 * Create a talloc pool
449 void *talloc_pool(const void *context
, size_t size
)
451 void *result
= __talloc(context
, size
+ TALLOC_POOL_HDR_SIZE
);
452 struct talloc_chunk
*tc
;
454 if (unlikely(result
== NULL
)) {
458 tc
= talloc_chunk_from_ptr(result
);
460 tc
->flags
|= TALLOC_FLAG_POOL
;
461 tc
->pool
= (char *)result
+ TALLOC_POOL_HDR_SIZE
;
463 *talloc_pool_objectcount(tc
) = 1;
465 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
466 VALGRIND_MAKE_MEM_NOACCESS(tc
->pool
, size
);
473 setup a destructor to be called on free of a pointer
474 the destructor should return 0 on success, or -1 on failure.
475 if the destructor fails then the free is failed, and the memory can
476 be continued to be used
478 void _talloc_set_destructor(const void *ptr
, int (*destructor
)(void *))
480 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
481 tc
->destructor
= destructor
;
485 increase the reference count on a piece of memory.
487 int talloc_increase_ref_count(const void *ptr
)
489 if (unlikely(!talloc_reference(null_context
, ptr
))) {
496 helper for talloc_reference()
498 this is referenced by a function pointer and should not be inline
500 static int talloc_reference_destructor(struct talloc_reference_handle
*handle
)
502 struct talloc_chunk
*ptr_tc
= talloc_chunk_from_ptr(handle
->ptr
);
503 _TLIST_REMOVE(ptr_tc
->refs
, handle
);
508 more efficient way to add a name to a pointer - the name must point to a
511 static INLINE
void _talloc_set_name_const(const void *ptr
, const char *name
)
513 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
518 internal talloc_named_const()
520 static INLINE
void *_talloc_named_const(const void *context
, size_t size
, const char *name
)
524 ptr
= __talloc(context
, size
);
525 if (unlikely(ptr
== NULL
)) {
529 _talloc_set_name_const(ptr
, name
);
535 make a secondary reference to a pointer, hanging off the given context.
536 the pointer remains valid until both the original caller and this given
539 the major use for this is when two different structures need to reference the
540 same underlying data, and you want to be able to free the two instances separately,
543 void *_talloc_reference_loc(const void *context
, const void *ptr
, const char *location
)
545 struct talloc_chunk
*tc
;
546 struct talloc_reference_handle
*handle
;
547 if (unlikely(ptr
== NULL
)) return NULL
;
549 tc
= talloc_chunk_from_ptr(ptr
);
550 handle
= (struct talloc_reference_handle
*)_talloc_named_const(context
,
551 sizeof(struct talloc_reference_handle
),
552 TALLOC_MAGIC_REFERENCE
);
553 if (unlikely(handle
== NULL
)) return NULL
;
555 /* note that we hang the destructor off the handle, not the
556 main context as that allows the caller to still setup their
557 own destructor on the context if they want to */
558 talloc_set_destructor(handle
, talloc_reference_destructor
);
559 handle
->ptr
= discard_const_p(void, ptr
);
560 handle
->location
= location
;
561 _TLIST_ADD(tc
->refs
, handle
);
565 static void *_talloc_steal_internal(const void *new_ctx
, const void *ptr
);
568 internal talloc_free call
570 static INLINE
int _talloc_free_internal(void *ptr
, const char *location
)
572 struct talloc_chunk
*tc
;
574 if (unlikely(ptr
== NULL
)) {
578 tc
= talloc_chunk_from_ptr(ptr
);
580 if (unlikely(tc
->refs
)) {
582 /* check this is a reference from a child or grantchild
583 * back to it's parent or grantparent
585 * in that case we need to remove the reference and
586 * call another instance of talloc_free() on the current
589 is_child
= talloc_is_parent(tc
->refs
, ptr
);
590 _talloc_free_internal(tc
->refs
, location
);
592 return _talloc_free_internal(ptr
, location
);
597 if (unlikely(tc
->flags
& TALLOC_FLAG_LOOP
)) {
598 /* we have a free loop - stop looping */
602 if (unlikely(tc
->destructor
)) {
603 talloc_destructor_t d
= tc
->destructor
;
604 if (d
== (talloc_destructor_t
)-1) {
607 tc
->destructor
= (talloc_destructor_t
)-1;
612 tc
->destructor
= NULL
;
616 _TLIST_REMOVE(tc
->parent
->child
, tc
);
617 if (tc
->parent
->child
) {
618 tc
->parent
->child
->parent
= tc
->parent
;
621 if (tc
->prev
) tc
->prev
->next
= tc
->next
;
622 if (tc
->next
) tc
->next
->prev
= tc
->prev
;
625 tc
->flags
|= TALLOC_FLAG_LOOP
;
628 /* we need to work out who will own an abandoned child
629 if it cannot be freed. In priority order, the first
630 choice is owner of any remaining reference to this
631 pointer, the second choice is our parent, and the
632 final choice is the null context. */
633 void *child
= TC_PTR_FROM_CHUNK(tc
->child
);
634 const void *new_parent
= null_context
;
635 if (unlikely(tc
->child
->refs
)) {
636 struct talloc_chunk
*p
= talloc_parent_chunk(tc
->child
->refs
);
637 if (p
) new_parent
= TC_PTR_FROM_CHUNK(p
);
639 if (unlikely(_talloc_free_internal(child
, location
) == -1)) {
640 if (new_parent
== null_context
) {
641 struct talloc_chunk
*p
= talloc_parent_chunk(ptr
);
642 if (p
) new_parent
= TC_PTR_FROM_CHUNK(p
);
644 _talloc_steal_internal(new_parent
, child
);
648 tc
->flags
|= TALLOC_FLAG_FREE
;
650 /* we mark the freed memory with where we called the free
651 * from. This means on a double free error we can report where
652 * the first free came from
656 if (tc
->flags
& (TALLOC_FLAG_POOL
|TALLOC_FLAG_POOLMEM
)) {
657 struct talloc_chunk
*pool
;
658 unsigned int *pool_object_count
;
660 pool
= (tc
->flags
& TALLOC_FLAG_POOL
)
661 ? tc
: (struct talloc_chunk
*)tc
->pool
;
663 pool_object_count
= talloc_pool_objectcount(pool
);
665 if (*pool_object_count
== 0) {
666 talloc_abort("Pool object count zero!");
670 *pool_object_count
-= 1;
672 if (*pool_object_count
== 0) {
683 move a lump of memory from one talloc context to another return the
684 ptr on success, or NULL if it could not be transferred.
685 passing NULL as ptr will always return NULL with no side effects.
687 static void *_talloc_steal_internal(const void *new_ctx
, const void *ptr
)
689 struct talloc_chunk
*tc
, *new_tc
;
691 if (unlikely(!ptr
)) {
695 if (unlikely(new_ctx
== NULL
)) {
696 new_ctx
= null_context
;
699 tc
= talloc_chunk_from_ptr(ptr
);
701 if (unlikely(new_ctx
== NULL
)) {
703 _TLIST_REMOVE(tc
->parent
->child
, tc
);
704 if (tc
->parent
->child
) {
705 tc
->parent
->child
->parent
= tc
->parent
;
708 if (tc
->prev
) tc
->prev
->next
= tc
->next
;
709 if (tc
->next
) tc
->next
->prev
= tc
->prev
;
712 tc
->parent
= tc
->next
= tc
->prev
= NULL
;
713 return discard_const_p(void, ptr
);
716 new_tc
= talloc_chunk_from_ptr(new_ctx
);
718 if (unlikely(tc
== new_tc
|| tc
->parent
== new_tc
)) {
719 return discard_const_p(void, ptr
);
723 _TLIST_REMOVE(tc
->parent
->child
, tc
);
724 if (tc
->parent
->child
) {
725 tc
->parent
->child
->parent
= tc
->parent
;
728 if (tc
->prev
) tc
->prev
->next
= tc
->next
;
729 if (tc
->next
) tc
->next
->prev
= tc
->prev
;
733 if (new_tc
->child
) new_tc
->child
->parent
= NULL
;
734 _TLIST_ADD(new_tc
->child
, tc
);
736 return discard_const_p(void, ptr
);
740 move a lump of memory from one talloc context to another return the
741 ptr on success, or NULL if it could not be transferred.
742 passing NULL as ptr will always return NULL with no side effects.
744 void *_talloc_steal_loc(const void *new_ctx
, const void *ptr
, const char *location
)
746 struct talloc_chunk
*tc
;
748 if (unlikely(ptr
== NULL
)) {
752 tc
= talloc_chunk_from_ptr(ptr
);
754 if (unlikely(tc
->refs
!= NULL
) && talloc_parent(ptr
) != new_ctx
) {
755 struct talloc_reference_handle
*h
;
757 talloc_log("WARNING: talloc_steal with references at %s\n",
760 for (h
=tc
->refs
; h
; h
=h
->next
) {
761 talloc_log("\treference at %s\n",
766 return _talloc_steal_internal(new_ctx
, ptr
);
770 this is like a talloc_steal(), but you must supply the old
771 parent. This resolves the ambiguity in a talloc_steal() which is
772 called on a context that has more than one parent (via references)
774 The old parent can be either a reference or a parent
776 void *talloc_reparent(const void *old_parent
, const void *new_parent
, const void *ptr
)
778 struct talloc_chunk
*tc
;
779 struct talloc_reference_handle
*h
;
781 if (unlikely(ptr
== NULL
)) {
785 if (old_parent
== talloc_parent(ptr
)) {
786 return _talloc_steal_internal(new_parent
, ptr
);
789 tc
= talloc_chunk_from_ptr(ptr
);
790 for (h
=tc
->refs
;h
;h
=h
->next
) {
791 if (talloc_parent(h
) == old_parent
) {
792 if (_talloc_steal_internal(new_parent
, h
) != h
) {
795 return discard_const_p(void, ptr
);
799 /* it wasn't a parent */
804 remove a secondary reference to a pointer. This undo's what
805 talloc_reference() has done. The context and pointer arguments
806 must match those given to a talloc_reference()
808 static INLINE
int talloc_unreference(const void *context
, const void *ptr
)
810 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
811 struct talloc_reference_handle
*h
;
813 if (unlikely(context
== NULL
)) {
814 context
= null_context
;
817 for (h
=tc
->refs
;h
;h
=h
->next
) {
818 struct talloc_chunk
*p
= talloc_parent_chunk(h
);
820 if (context
== NULL
) break;
821 } else if (TC_PTR_FROM_CHUNK(p
) == context
) {
829 return _talloc_free_internal(h
, __location__
);
833 remove a specific parent context from a pointer. This is a more
834 controlled varient of talloc_free()
836 int talloc_unlink(const void *context
, void *ptr
)
838 struct talloc_chunk
*tc_p
, *new_p
;
845 if (context
== NULL
) {
846 context
= null_context
;
849 if (talloc_unreference(context
, ptr
) == 0) {
853 if (context
== NULL
) {
854 if (talloc_parent_chunk(ptr
) != NULL
) {
858 if (talloc_chunk_from_ptr(context
) != talloc_parent_chunk(ptr
)) {
863 tc_p
= talloc_chunk_from_ptr(ptr
);
865 if (tc_p
->refs
== NULL
) {
866 return _talloc_free_internal(ptr
, __location__
);
869 new_p
= talloc_parent_chunk(tc_p
->refs
);
871 new_parent
= TC_PTR_FROM_CHUNK(new_p
);
876 if (talloc_unreference(new_parent
, ptr
) != 0) {
880 _talloc_steal_internal(new_parent
, ptr
);
886 add a name to an existing pointer - va_list version
888 static INLINE
const char *talloc_set_name_v(const void *ptr
, const char *fmt
, va_list ap
) PRINTF_ATTRIBUTE(2,0);
890 static INLINE
const char *talloc_set_name_v(const void *ptr
, const char *fmt
, va_list ap
)
892 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
893 tc
->name
= talloc_vasprintf(ptr
, fmt
, ap
);
894 if (likely(tc
->name
)) {
895 _talloc_set_name_const(tc
->name
, ".name");
901 add a name to an existing pointer
903 const char *talloc_set_name(const void *ptr
, const char *fmt
, ...)
908 name
= talloc_set_name_v(ptr
, fmt
, ap
);
915 create a named talloc pointer. Any talloc pointer can be named, and
916 talloc_named() operates just like talloc() except that it allows you
919 void *talloc_named(const void *context
, size_t size
, const char *fmt
, ...)
925 ptr
= __talloc(context
, size
);
926 if (unlikely(ptr
== NULL
)) return NULL
;
929 name
= talloc_set_name_v(ptr
, fmt
, ap
);
932 if (unlikely(name
== NULL
)) {
933 _talloc_free_internal(ptr
, __location__
);
941 return the name of a talloc ptr, or "UNNAMED"
943 const char *talloc_get_name(const void *ptr
)
945 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
946 if (unlikely(tc
->name
== TALLOC_MAGIC_REFERENCE
)) {
949 if (likely(tc
->name
)) {
957 check if a pointer has the given name. If it does, return the pointer,
958 otherwise return NULL
960 void *talloc_check_name(const void *ptr
, const char *name
)
963 if (unlikely(ptr
== NULL
)) return NULL
;
964 pname
= talloc_get_name(ptr
);
965 if (likely(pname
== name
|| strcmp(pname
, name
) == 0)) {
966 return discard_const_p(void, ptr
);
971 static void talloc_abort_type_missmatch(const char *location
,
973 const char *expected
)
977 reason
= talloc_asprintf(NULL
,
978 "%s: Type mismatch: name[%s] expected[%s]",
983 reason
= "Type mismatch";
986 talloc_abort(reason
);
989 void *_talloc_get_type_abort(const void *ptr
, const char *name
, const char *location
)
993 if (unlikely(ptr
== NULL
)) {
994 talloc_abort_type_missmatch(location
, NULL
, name
);
998 pname
= talloc_get_name(ptr
);
999 if (likely(pname
== name
|| strcmp(pname
, name
) == 0)) {
1000 return discard_const_p(void, ptr
);
1003 talloc_abort_type_missmatch(location
, pname
, name
);
1008 this is for compatibility with older versions of talloc
1010 void *talloc_init(const char *fmt
, ...)
1017 * samba3 expects talloc_report_depth_cb(NULL, ...)
1018 * reports all talloc'ed memory, so we need to enable
1021 talloc_enable_null_tracking();
1023 ptr
= __talloc(NULL
, 0);
1024 if (unlikely(ptr
== NULL
)) return NULL
;
1027 name
= talloc_set_name_v(ptr
, fmt
, ap
);
1030 if (unlikely(name
== NULL
)) {
1031 _talloc_free_internal(ptr
, __location__
);
1039 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
1040 should probably not be used in new code. It's in here to keep the talloc
1041 code consistent across Samba 3 and 4.
1043 void talloc_free_children(void *ptr
)
1045 struct talloc_chunk
*tc
;
1047 if (unlikely(ptr
== NULL
)) {
1051 tc
= talloc_chunk_from_ptr(ptr
);
1054 /* we need to work out who will own an abandoned child
1055 if it cannot be freed. In priority order, the first
1056 choice is owner of any remaining reference to this
1057 pointer, the second choice is our parent, and the
1058 final choice is the null context. */
1059 void *child
= TC_PTR_FROM_CHUNK(tc
->child
);
1060 const void *new_parent
= null_context
;
1061 if (unlikely(tc
->child
->refs
)) {
1062 struct talloc_chunk
*p
= talloc_parent_chunk(tc
->child
->refs
);
1063 if (p
) new_parent
= TC_PTR_FROM_CHUNK(p
);
1065 if (unlikely(talloc_free(child
) == -1)) {
1066 if (new_parent
== null_context
) {
1067 struct talloc_chunk
*p
= talloc_parent_chunk(ptr
);
1068 if (p
) new_parent
= TC_PTR_FROM_CHUNK(p
);
1070 _talloc_steal_internal(new_parent
, child
);
1074 if ((tc
->flags
& TALLOC_FLAG_POOL
)
1075 && (*talloc_pool_objectcount(tc
) == 1)) {
1076 tc
->pool
= ((char *)tc
+ TC_HDR_SIZE
+ TALLOC_POOL_HDR_SIZE
);
1077 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
1078 VALGRIND_MAKE_MEM_NOACCESS(
1079 tc
->pool
, tc
->size
- TALLOC_POOL_HDR_SIZE
);
1085 Allocate a bit of memory as a child of an existing pointer
1087 void *_talloc(const void *context
, size_t size
)
1089 return __talloc(context
, size
);
1093 externally callable talloc_set_name_const()
1095 void talloc_set_name_const(const void *ptr
, const char *name
)
1097 _talloc_set_name_const(ptr
, name
);
1101 create a named talloc pointer. Any talloc pointer can be named, and
1102 talloc_named() operates just like talloc() except that it allows you
1103 to name the pointer.
1105 void *talloc_named_const(const void *context
, size_t size
, const char *name
)
1107 return _talloc_named_const(context
, size
, name
);
1111 free a talloc pointer. This also frees all child pointers of this
1114 return 0 if the memory is actually freed, otherwise -1. The memory
1115 will not be freed if the ref_count is > 1 or the destructor (if
1116 any) returns non-zero
1118 int _talloc_free(void *ptr
, const char *location
)
1120 struct talloc_chunk
*tc
;
1122 if (unlikely(ptr
== NULL
)) {
1126 tc
= talloc_chunk_from_ptr(ptr
);
1128 if (unlikely(tc
->refs
!= NULL
)) {
1129 struct talloc_reference_handle
*h
;
1131 talloc_log("ERROR: talloc_free with references at %s\n",
1134 for (h
=tc
->refs
; h
; h
=h
->next
) {
1135 talloc_log("\treference at %s\n",
1141 return _talloc_free_internal(ptr
, location
);
1145 static INLINE
size_t min_size(size_t a
, size_t b
)
1147 return a
> b
? b
: a
;
1151 A talloc version of realloc. The context argument is only used if
1154 void *_talloc_realloc(const void *context
, void *ptr
, size_t size
, const char *name
)
1156 struct talloc_chunk
*tc
;
1160 /* size zero is equivalent to free() */
1161 if (unlikely(size
== 0)) {
1162 talloc_unlink(context
, ptr
);
1166 if (unlikely(size
>= MAX_TALLOC_SIZE
)) {
1170 /* realloc(NULL) is equivalent to malloc() */
1172 return _talloc_named_const(context
, size
, name
);
1175 tc
= talloc_chunk_from_ptr(ptr
);
1177 /* don't allow realloc on referenced pointers */
1178 if (unlikely(tc
->refs
)) {
1182 /* don't let anybody try to realloc a talloc_pool */
1183 if (unlikely(tc
->flags
& TALLOC_FLAG_POOL
)) {
1187 /* don't shrink if we have less than 1k to gain */
1188 if ((size
< tc
->size
) && ((tc
->size
- size
) < 1024)) {
1193 /* by resetting magic we catch users of the old memory */
1194 tc
->flags
|= TALLOC_FLAG_FREE
;
1197 new_ptr
= malloc(size
+ TC_HDR_SIZE
);
1199 memcpy(new_ptr
, tc
, tc
->size
+ TC_HDR_SIZE
);
1203 if (tc
->flags
& TALLOC_FLAG_POOLMEM
) {
1205 new_ptr
= talloc_alloc_pool(tc
, size
+ TC_HDR_SIZE
);
1206 *talloc_pool_objectcount((struct talloc_chunk
*)
1209 if (new_ptr
== NULL
) {
1210 new_ptr
= malloc(TC_HDR_SIZE
+size
);
1215 memcpy(new_ptr
, tc
, min_size(tc
->size
,size
) + TC_HDR_SIZE
);
1219 new_ptr
= realloc(tc
, size
+ TC_HDR_SIZE
);
1222 if (unlikely(!new_ptr
)) {
1223 tc
->flags
&= ~TALLOC_FLAG_FREE
;
1227 tc
= (struct talloc_chunk
*)new_ptr
;
1228 tc
->flags
&= ~TALLOC_FLAG_FREE
;
1230 tc
->flags
&= ~TALLOC_FLAG_POOLMEM
;
1233 tc
->parent
->child
= tc
;
1236 tc
->child
->parent
= tc
;
1240 tc
->prev
->next
= tc
;
1243 tc
->next
->prev
= tc
;
1247 _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc
), name
);
1249 return TC_PTR_FROM_CHUNK(tc
);
1253 a wrapper around talloc_steal() for situations where you are moving a pointer
1254 between two structures, and want the old pointer to be set to NULL
1256 void *_talloc_move(const void *new_ctx
, const void *_pptr
)
1258 const void **pptr
= discard_const_p(const void *,_pptr
);
1259 void *ret
= talloc_steal(new_ctx
, discard_const_p(void, *pptr
));
1265 return the total size of a talloc pool (subtree)
1267 size_t talloc_total_size(const void *ptr
)
1270 struct talloc_chunk
*c
, *tc
;
1279 tc
= talloc_chunk_from_ptr(ptr
);
1281 if (tc
->flags
& TALLOC_FLAG_LOOP
) {
1285 tc
->flags
|= TALLOC_FLAG_LOOP
;
1287 if (likely(tc
->name
!= TALLOC_MAGIC_REFERENCE
)) {
1290 for (c
=tc
->child
;c
;c
=c
->next
) {
1291 total
+= talloc_total_size(TC_PTR_FROM_CHUNK(c
));
1294 tc
->flags
&= ~TALLOC_FLAG_LOOP
;
1300 return the total number of blocks in a talloc pool (subtree)
1302 size_t talloc_total_blocks(const void *ptr
)
1305 struct talloc_chunk
*c
, *tc
;
1314 tc
= talloc_chunk_from_ptr(ptr
);
1316 if (tc
->flags
& TALLOC_FLAG_LOOP
) {
1320 tc
->flags
|= TALLOC_FLAG_LOOP
;
1323 for (c
=tc
->child
;c
;c
=c
->next
) {
1324 total
+= talloc_total_blocks(TC_PTR_FROM_CHUNK(c
));
1327 tc
->flags
&= ~TALLOC_FLAG_LOOP
;
1333 return the number of external references to a pointer
1335 size_t talloc_reference_count(const void *ptr
)
1337 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
1338 struct talloc_reference_handle
*h
;
1341 for (h
=tc
->refs
;h
;h
=h
->next
) {
1348 report on memory usage by all children of a pointer, giving a full tree view
1350 void talloc_report_depth_cb(const void *ptr
, int depth
, int max_depth
,
1351 void (*callback
)(const void *ptr
,
1352 int depth
, int max_depth
,
1354 void *private_data
),
1357 struct talloc_chunk
*c
, *tc
;
1362 if (ptr
== NULL
) return;
1364 tc
= talloc_chunk_from_ptr(ptr
);
1366 if (tc
->flags
& TALLOC_FLAG_LOOP
) {
1370 callback(ptr
, depth
, max_depth
, 0, private_data
);
1372 if (max_depth
>= 0 && depth
>= max_depth
) {
1376 tc
->flags
|= TALLOC_FLAG_LOOP
;
1377 for (c
=tc
->child
;c
;c
=c
->next
) {
1378 if (c
->name
== TALLOC_MAGIC_REFERENCE
) {
1379 struct talloc_reference_handle
*h
= (struct talloc_reference_handle
*)TC_PTR_FROM_CHUNK(c
);
1380 callback(h
->ptr
, depth
+ 1, max_depth
, 1, private_data
);
1382 talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c
), depth
+ 1, max_depth
, callback
, private_data
);
1385 tc
->flags
&= ~TALLOC_FLAG_LOOP
;
1388 static void talloc_report_depth_FILE_helper(const void *ptr
, int depth
, int max_depth
, int is_ref
, void *_f
)
1390 const char *name
= talloc_get_name(ptr
);
1391 FILE *f
= (FILE *)_f
;
1394 fprintf(f
, "%*sreference to: %s\n", depth
*4, "", name
);
1399 fprintf(f
,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
1400 (max_depth
< 0 ? "full " :""), name
,
1401 (unsigned long)talloc_total_size(ptr
),
1402 (unsigned long)talloc_total_blocks(ptr
));
1406 fprintf(f
, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n",
1409 (unsigned long)talloc_total_size(ptr
),
1410 (unsigned long)talloc_total_blocks(ptr
),
1411 (int)talloc_reference_count(ptr
), ptr
);
1414 fprintf(f
, "content: ");
1415 if (talloc_total_size(ptr
)) {
1416 int tot
= talloc_total_size(ptr
);
1419 for (i
= 0; i
< tot
; i
++) {
1420 if ((((char *)ptr
)[i
] > 31) && (((char *)ptr
)[i
] < 126)) {
1421 fprintf(f
, "%c", ((char *)ptr
)[i
]);
1423 fprintf(f
, "~%02x", ((char *)ptr
)[i
]);
1432 report on memory usage by all children of a pointer, giving a full tree view
1434 void talloc_report_depth_file(const void *ptr
, int depth
, int max_depth
, FILE *f
)
1437 talloc_report_depth_cb(ptr
, depth
, max_depth
, talloc_report_depth_FILE_helper
, f
);
1443 report on memory usage by all children of a pointer, giving a full tree view
1445 void talloc_report_full(const void *ptr
, FILE *f
)
1447 talloc_report_depth_file(ptr
, 0, -1, f
);
1451 report on memory usage by all children of a pointer
1453 void talloc_report(const void *ptr
, FILE *f
)
1455 talloc_report_depth_file(ptr
, 0, 1, f
);
1459 report on any memory hanging off the null context
1461 static void talloc_report_null(void)
1463 if (talloc_total_size(null_context
) != 0) {
1464 talloc_report(null_context
, stderr
);
1469 report on any memory hanging off the null context
1471 static void talloc_report_null_full(void)
1473 if (talloc_total_size(null_context
) != 0) {
1474 talloc_report_full(null_context
, stderr
);
1479 enable tracking of the NULL context
1481 void talloc_enable_null_tracking(void)
1483 if (null_context
== NULL
) {
1484 null_context
= _talloc_named_const(NULL
, 0, "null_context");
1485 if (autofree_context
!= NULL
) {
1486 talloc_reparent(NULL
, null_context
, autofree_context
);
1492 enable tracking of the NULL context, not moving the autofree context
1493 into the NULL context. This is needed for the talloc testsuite
1495 void talloc_enable_null_tracking_no_autofree(void)
1497 if (null_context
== NULL
) {
1498 null_context
= _talloc_named_const(NULL
, 0, "null_context");
1503 disable tracking of the NULL context
1505 void talloc_disable_null_tracking(void)
1507 if (null_context
!= NULL
) {
1508 /* we have to move any children onto the real NULL
1510 struct talloc_chunk
*tc
, *tc2
;
1511 tc
= talloc_chunk_from_ptr(null_context
);
1512 for (tc2
= tc
->child
; tc2
; tc2
=tc2
->next
) {
1513 if (tc2
->parent
== tc
) tc2
->parent
= NULL
;
1514 if (tc2
->prev
== tc
) tc2
->prev
= NULL
;
1516 for (tc2
= tc
->next
; tc2
; tc2
=tc2
->next
) {
1517 if (tc2
->parent
== tc
) tc2
->parent
= NULL
;
1518 if (tc2
->prev
== tc
) tc2
->prev
= NULL
;
1523 talloc_free(null_context
);
1524 null_context
= NULL
;
1528 enable leak reporting on exit
1530 void talloc_enable_leak_report(void)
1532 talloc_enable_null_tracking();
1533 atexit(talloc_report_null
);
1537 enable full leak reporting on exit
1539 void talloc_enable_leak_report_full(void)
1541 talloc_enable_null_tracking();
1542 atexit(talloc_report_null_full
);
1546 talloc and zero memory.
1548 void *_talloc_zero(const void *ctx
, size_t size
, const char *name
)
1550 void *p
= _talloc_named_const(ctx
, size
, name
);
1553 memset(p
, '\0', size
);
1560 memdup with a talloc.
1562 void *_talloc_memdup(const void *t
, const void *p
, size_t size
, const char *name
)
1564 void *newp
= _talloc_named_const(t
, size
, name
);
1567 memcpy(newp
, p
, size
);
1573 static INLINE
char *__talloc_strlendup(const void *t
, const char *p
, size_t len
)
1577 ret
= (char *)__talloc(t
, len
+ 1);
1578 if (unlikely(!ret
)) return NULL
;
1580 memcpy(ret
, p
, len
);
1583 _talloc_set_name_const(ret
, ret
);
1588 strdup with a talloc
1590 char *talloc_strdup(const void *t
, const char *p
)
1592 if (unlikely(!p
)) return NULL
;
1593 return __talloc_strlendup(t
, p
, strlen(p
));
1596 #ifndef HAVE_STRNLEN
1597 static size_t strnlen(const char* s
, size_t n
)
1599 if (unlikely(!s
)) return 0;
1601 while (i
< n
&& *s
++ != '\0')
1608 strndup with a talloc
1610 char *talloc_strndup(const void *t
, const char *p
, size_t n
)
1612 if (unlikely(!p
)) return NULL
;
1613 return __talloc_strlendup(t
, p
, strnlen(p
, n
));
1616 static INLINE
char *__talloc_strlendup_append(char *s
, size_t slen
,
1617 const char *a
, size_t alen
)
1621 ret
= talloc_realloc(NULL
, s
, char, slen
+ alen
+ 1);
1622 if (unlikely(!ret
)) return NULL
;
1624 /* append the string and the trailing \0 */
1625 memcpy(&ret
[slen
], a
, alen
);
1628 _talloc_set_name_const(ret
, ret
);
1633 * Appends at the end of the string.
1635 char *talloc_strdup_append(char *s
, const char *a
)
1638 return talloc_strdup(NULL
, a
);
1645 return __talloc_strlendup_append(s
, strlen(s
), a
, strlen(a
));
1649 * Appends at the end of the talloc'ed buffer,
1650 * not the end of the string.
1652 char *talloc_strdup_append_buffer(char *s
, const char *a
)
1657 return talloc_strdup(NULL
, a
);
1664 slen
= talloc_get_size(s
);
1665 if (likely(slen
> 0)) {
1669 return __talloc_strlendup_append(s
, slen
, a
, strlen(a
));
1673 * Appends at the end of the string.
1675 char *talloc_strndup_append(char *s
, const char *a
, size_t n
)
1678 return talloc_strdup(NULL
, a
);
1685 return __talloc_strlendup_append(s
, strlen(s
), a
, strnlen(a
, n
));
1689 * Appends at the end of the talloc'ed buffer,
1690 * not the end of the string.
1692 char *talloc_strndup_append_buffer(char *s
, const char *a
, size_t n
)
1697 return talloc_strdup(NULL
, a
);
1704 slen
= talloc_get_size(s
);
1705 if (likely(slen
> 0)) {
1709 return __talloc_strlendup_append(s
, slen
, a
, strnlen(a
, n
));
1712 #ifndef HAVE_VA_COPY
1713 #ifdef HAVE___VA_COPY
1714 #define va_copy(dest, src) __va_copy(dest, src)
1716 #define va_copy(dest, src) (dest) = (src)
1720 char *talloc_vasprintf(const void *t
, const char *fmt
, va_list ap
)
1727 len
= vsnprintf(NULL
, 0, fmt
, ap2
);
1729 if (unlikely(len
< 0)) {
1733 ret
= (char *)__talloc(t
, len
+1);
1734 if (unlikely(!ret
)) return NULL
;
1737 vsnprintf(ret
, len
+1, fmt
, ap2
);
1740 _talloc_set_name_const(ret
, ret
);
1746 Perform string formatting, and return a pointer to newly allocated
1747 memory holding the result, inside a memory pool.
1749 char *talloc_asprintf(const void *t
, const char *fmt
, ...)
1755 ret
= talloc_vasprintf(t
, fmt
, ap
);
1760 static INLINE
char *__talloc_vaslenprintf_append(char *s
, size_t slen
,
1761 const char *fmt
, va_list ap
)
1762 PRINTF_ATTRIBUTE(3,0);
1764 static INLINE
char *__talloc_vaslenprintf_append(char *s
, size_t slen
,
1765 const char *fmt
, va_list ap
)
1767 /* ssize_t isn't present on Windows. */
1776 alen
= vsnprintf(NULL
, 0, fmt
, ap2
);
1780 /* Either the vsnprintf failed or the format resulted in
1781 * no characters being formatted. In the former case, we
1782 * ought to return NULL, in the latter we ought to return
1783 * the original string. Most current callers of this
1784 * function expect it to never return NULL.
1789 s
= talloc_realloc(NULL
, s
, char, slen
+ alen
+ 1);
1790 if (!s
) return NULL
;
1793 vsnprintf(s
+ slen
, alen
+ 1, fmt
, ap2
);
1796 _talloc_set_name_const(s
, s
);
1801 * Realloc @p s to append the formatted result of @p fmt and @p ap,
1802 * and return @p s, which may have moved. Good for gradually
1803 * accumulating output into a string buffer. Appends at the end
1806 char *talloc_vasprintf_append(char *s
, const char *fmt
, va_list ap
)
1809 return talloc_vasprintf(NULL
, fmt
, ap
);
1812 return __talloc_vaslenprintf_append(s
, strlen(s
), fmt
, ap
);
1816 * Realloc @p s to append the formatted result of @p fmt and @p ap,
1817 * and return @p s, which may have moved. Always appends at the
1818 * end of the talloc'ed buffer, not the end of the string.
1820 char *talloc_vasprintf_append_buffer(char *s
, const char *fmt
, va_list ap
)
1825 return talloc_vasprintf(NULL
, fmt
, ap
);
1828 slen
= talloc_get_size(s
);
1829 if (likely(slen
> 0)) {
1833 return __talloc_vaslenprintf_append(s
, slen
, fmt
, ap
);
1837 Realloc @p s to append the formatted result of @p fmt and return @p
1838 s, which may have moved. Good for gradually accumulating output
1839 into a string buffer.
1841 char *talloc_asprintf_append(char *s
, const char *fmt
, ...)
1846 s
= talloc_vasprintf_append(s
, fmt
, ap
);
1852 Realloc @p s to append the formatted result of @p fmt and return @p
1853 s, which may have moved. Good for gradually accumulating output
1856 char *talloc_asprintf_append_buffer(char *s
, const char *fmt
, ...)
1861 s
= talloc_vasprintf_append_buffer(s
, fmt
, ap
);
1867 alloc an array, checking for integer overflow in the array size
1869 void *_talloc_array(const void *ctx
, size_t el_size
, unsigned count
, const char *name
)
1871 if (count
>= MAX_TALLOC_SIZE
/el_size
) {
1874 return _talloc_named_const(ctx
, el_size
* count
, name
);
1878 alloc an zero array, checking for integer overflow in the array size
1880 void *_talloc_zero_array(const void *ctx
, size_t el_size
, unsigned count
, const char *name
)
1882 if (count
>= MAX_TALLOC_SIZE
/el_size
) {
1885 return _talloc_zero(ctx
, el_size
* count
, name
);
1889 realloc an array, checking for integer overflow in the array size
1891 void *_talloc_realloc_array(const void *ctx
, void *ptr
, size_t el_size
, unsigned count
, const char *name
)
1893 if (count
>= MAX_TALLOC_SIZE
/el_size
) {
1896 return _talloc_realloc(ctx
, ptr
, el_size
* count
, name
);
1900 a function version of talloc_realloc(), so it can be passed as a function pointer
1901 to libraries that want a realloc function (a realloc function encapsulates
1902 all the basic capabilities of an allocation library, which is why this is useful)
1904 void *talloc_realloc_fn(const void *context
, void *ptr
, size_t size
)
1906 return _talloc_realloc(context
, ptr
, size
, NULL
);
1910 static int talloc_autofree_destructor(void *ptr
)
1912 autofree_context
= NULL
;
1916 static void talloc_autofree(void)
1918 talloc_free(autofree_context
);
1922 return a context which will be auto-freed on exit
1923 this is useful for reducing the noise in leak reports
1925 void *talloc_autofree_context(void)
1927 if (autofree_context
== NULL
) {
1928 autofree_context
= _talloc_named_const(NULL
, 0, "autofree_context");
1929 talloc_set_destructor(autofree_context
, talloc_autofree_destructor
);
1930 atexit(talloc_autofree
);
1932 return autofree_context
;
1935 size_t talloc_get_size(const void *context
)
1937 struct talloc_chunk
*tc
;
1939 if (context
== NULL
) {
1940 context
= null_context
;
1942 if (context
== NULL
) {
1946 tc
= talloc_chunk_from_ptr(context
);
1952 find a parent of this context that has the given name, if any
1954 void *talloc_find_parent_byname(const void *context
, const char *name
)
1956 struct talloc_chunk
*tc
;
1958 if (context
== NULL
) {
1962 tc
= talloc_chunk_from_ptr(context
);
1964 if (tc
->name
&& strcmp(tc
->name
, name
) == 0) {
1965 return TC_PTR_FROM_CHUNK(tc
);
1967 while (tc
&& tc
->prev
) tc
= tc
->prev
;
1976 show the parentage of a context
1978 void talloc_show_parents(const void *context
, FILE *file
)
1980 struct talloc_chunk
*tc
;
1982 if (context
== NULL
) {
1983 fprintf(file
, "talloc no parents for NULL\n");
1987 tc
= talloc_chunk_from_ptr(context
);
1988 fprintf(file
, "talloc parents of '%s'\n", talloc_get_name(context
));
1990 fprintf(file
, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc
)));
1991 while (tc
&& tc
->prev
) tc
= tc
->prev
;
2000 return 1 if ptr is a parent of context
2002 int talloc_is_parent(const void *context
, const void *ptr
)
2004 struct talloc_chunk
*tc
;
2006 if (context
== NULL
) {
2010 tc
= talloc_chunk_from_ptr(context
);
2012 if (TC_PTR_FROM_CHUNK(tc
) == ptr
) return 1;
2013 while (tc
&& tc
->prev
) tc
= tc
->prev
;