r12312: Reformatting and a trivial change: is_share_read_only_for_user only uses
[Samba/nascimento.git] / source3 / lib / talloc.c
blob00f889d682c830dafa7d56daf59db7f51666630e
1 /*
2 Samba Unix SMB/CIFS implementation.
4 Samba trivial allocation library - new interface
6 NOTE: Please read talloc_guide.txt for full documentation
8 Copyright (C) Andrew Tridgell 2004
10 ** NOTE! The following LGPL license applies to the talloc
11 ** library. This does NOT imply that all of Samba is released
12 ** under the LGPL
14 This library is free software; you can redistribute it and/or
15 modify it under the terms of the GNU Lesser General Public
16 License as published by the Free Software Foundation; either
17 version 2 of the License, or (at your option) any later version.
19 This library is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 Lesser General Public License for more details.
24 You should have received a copy of the GNU Lesser General Public
25 License along with this library; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 inspired by http://swapped.cc/halloc/
33 #ifdef _SAMBA_BUILD_
34 #include "includes.h"
35 #if ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9))
36 /* This is to circumvent SAMBA3's paranoid malloc checker. Here in this file
37 * we trust ourselves... */
38 #ifdef malloc
39 #undef malloc
40 #endif
41 #ifdef realloc
42 #undef realloc
43 #endif
44 #endif
45 #else
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <stdarg.h>
50 #include <stdint.h>
51 #include "talloc.h"
52 /* assume a modern system */
53 #define HAVE_VA_COPY
54 #endif
56 /* use this to force every realloc to change the pointer, to stress test
57 code that might not cope */
58 #define ALWAYS_REALLOC 0
61 #define MAX_TALLOC_SIZE 0x10000000
62 #define TALLOC_MAGIC 0xe814ec70
63 #define TALLOC_FLAG_FREE 0x01
64 #define TALLOC_FLAG_LOOP 0x02
65 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
67 /* by default we abort when given a bad pointer (such as when talloc_free() is called
68 on a pointer that came from malloc() */
69 #ifndef TALLOC_ABORT
70 #define TALLOC_ABORT(reason) abort()
71 #endif
73 #ifndef discard_const_p
74 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
75 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
76 #else
77 # define discard_const_p(type, ptr) ((type *)(ptr))
78 #endif
79 #endif
81 /* this null_context is only used if talloc_enable_leak_report() or
82 talloc_enable_leak_report_full() is called, otherwise it remains
83 NULL
85 static const void *null_context;
86 static void *cleanup_context;
89 struct talloc_reference_handle {
90 struct talloc_reference_handle *next, *prev;
91 void *ptr;
94 typedef int (*talloc_destructor_t)(void *);
96 struct talloc_chunk {
97 struct talloc_chunk *next, *prev;
98 struct talloc_chunk *parent, *child;
99 struct talloc_reference_handle *refs;
100 talloc_destructor_t destructor;
101 const char *name;
102 size_t size;
103 unsigned flags;
106 /* 16 byte alignment seems to keep everyone happy */
107 #define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
108 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
110 /* panic if we get a bad magic value */
111 static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
113 const char *pp = ptr;
114 struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
115 if ((tc->flags & ~0xF) != TALLOC_MAGIC) {
116 TALLOC_ABORT("Bad talloc magic value - unknown value");
118 if (tc->flags & TALLOC_FLAG_FREE) {
119 TALLOC_ABORT("Bad talloc magic value - double free");
121 return tc;
124 /* hook into the front of the list */
125 #define _TLIST_ADD(list, p) \
126 do { \
127 if (!(list)) { \
128 (list) = (p); \
129 (p)->next = (p)->prev = NULL; \
130 } else { \
131 (list)->prev = (p); \
132 (p)->next = (list); \
133 (p)->prev = NULL; \
134 (list) = (p); \
136 } while (0)
138 /* remove an element from a list - element doesn't have to be in list. */
139 #define _TLIST_REMOVE(list, p) \
140 do { \
141 if ((p) == (list)) { \
142 (list) = (p)->next; \
143 if (list) (list)->prev = NULL; \
144 } else { \
145 if ((p)->prev) (p)->prev->next = (p)->next; \
146 if ((p)->next) (p)->next->prev = (p)->prev; \
148 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
149 } while (0)
153 return the parent chunk of a pointer
155 static struct talloc_chunk *talloc_parent_chunk(const void *ptr)
157 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
158 while (tc->prev) tc=tc->prev;
159 return tc->parent;
162 void *talloc_parent(const void *ptr)
164 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
165 return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
169 Allocate a bit of memory as a child of an existing pointer
171 void *_talloc(const void *context, size_t size)
173 struct talloc_chunk *tc;
175 if (context == NULL) {
176 context = null_context;
179 if (size >= MAX_TALLOC_SIZE) {
180 return NULL;
183 tc = malloc(TC_HDR_SIZE+size);
184 if (tc == NULL) return NULL;
186 tc->size = size;
187 tc->flags = TALLOC_MAGIC;
188 tc->destructor = NULL;
189 tc->child = NULL;
190 tc->name = NULL;
191 tc->refs = NULL;
193 if (context) {
194 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
196 tc->parent = parent;
198 if (parent->child) {
199 parent->child->parent = NULL;
202 _TLIST_ADD(parent->child, tc);
203 } else {
204 tc->next = tc->prev = tc->parent = NULL;
207 return TC_PTR_FROM_CHUNK(tc);
212 setup a destructor to be called on free of a pointer
213 the destructor should return 0 on success, or -1 on failure.
214 if the destructor fails then the free is failed, and the memory can
215 be continued to be used
217 void talloc_set_destructor(const void *ptr, int (*destructor)(void *))
219 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
220 tc->destructor = destructor;
224 increase the reference count on a piece of memory.
226 void talloc_increase_ref_count(const void *ptr)
228 talloc_reference(null_context, ptr);
232 helper for talloc_reference()
234 static int talloc_reference_destructor(void *ptr)
236 struct talloc_reference_handle *handle = ptr;
237 struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr);
238 struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr);
239 if (tc1->destructor != (talloc_destructor_t)-1) {
240 tc1->destructor = NULL;
242 _TLIST_REMOVE(tc2->refs, handle);
243 talloc_free(handle);
244 return 0;
248 make a secondary reference to a pointer, hanging off the given context.
249 the pointer remains valid until both the original caller and this given
250 context are freed.
252 the major use for this is when two different structures need to reference the
253 same underlying data, and you want to be able to free the two instances separately,
254 and in either order
256 void *talloc_reference(const void *context, const void *ptr)
258 struct talloc_chunk *tc;
259 struct talloc_reference_handle *handle;
260 if (ptr == NULL) return NULL;
262 tc = talloc_chunk_from_ptr(ptr);
263 handle = talloc_named_const(context, sizeof(*handle), TALLOC_MAGIC_REFERENCE);
265 if (handle == NULL) return NULL;
267 /* note that we hang the destructor off the handle, not the
268 main context as that allows the caller to still setup their
269 own destructor on the context if they want to */
270 talloc_set_destructor(handle, talloc_reference_destructor);
271 handle->ptr = discard_const_p(void, ptr);
272 _TLIST_ADD(tc->refs, handle);
273 return handle->ptr;
277 remove a secondary reference to a pointer. This undo's what
278 talloc_reference() has done. The context and pointer arguments
279 must match those given to a talloc_reference()
281 static int talloc_unreference(const void *context, const void *ptr)
283 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
284 struct talloc_reference_handle *h;
286 if (context == NULL) {
287 context = null_context;
290 for (h=tc->refs;h;h=h->next) {
291 struct talloc_chunk *p = talloc_parent_chunk(h);
292 if ((p==NULL && context==NULL) || TC_PTR_FROM_CHUNK(p) == context) break;
294 if (h == NULL) {
295 return -1;
298 talloc_set_destructor(h, NULL);
299 _TLIST_REMOVE(tc->refs, h);
300 talloc_free(h);
301 return 0;
305 remove a specific parent context from a pointer. This is a more
306 controlled varient of talloc_free()
308 int talloc_unlink(const void *context, void *ptr)
310 struct talloc_chunk *tc_p, *new_p;
311 void *new_parent;
313 if (ptr == NULL) {
314 return -1;
317 if (context == NULL) {
318 context = null_context;
321 if (talloc_unreference(context, ptr) == 0) {
322 return 0;
325 if (context == NULL) {
326 if (talloc_parent_chunk(ptr) != NULL) {
327 return -1;
329 } else {
330 if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) {
331 return -1;
335 tc_p = talloc_chunk_from_ptr(ptr);
337 if (tc_p->refs == NULL) {
338 return talloc_free(ptr);
341 new_p = talloc_parent_chunk(tc_p->refs);
342 if (new_p) {
343 new_parent = TC_PTR_FROM_CHUNK(new_p);
344 } else {
345 new_parent = NULL;
348 if (talloc_unreference(new_parent, ptr) != 0) {
349 return -1;
352 talloc_steal(new_parent, ptr);
354 return 0;
358 add a name to an existing pointer - va_list version
360 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
362 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
364 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
365 tc->name = talloc_vasprintf(ptr, fmt, ap);
366 if (tc->name) {
367 talloc_set_name_const(tc->name, ".name");
372 add a name to an existing pointer
374 void talloc_set_name(const void *ptr, const char *fmt, ...)
376 va_list ap;
377 va_start(ap, fmt);
378 talloc_set_name_v(ptr, fmt, ap);
379 va_end(ap);
383 more efficient way to add a name to a pointer - the name must point to a
384 true string constant
386 void talloc_set_name_const(const void *ptr, const char *name)
388 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
389 tc->name = name;
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
395 to name the pointer.
397 void *talloc_named(const void *context, size_t size, const char *fmt, ...)
399 va_list ap;
400 void *ptr;
402 ptr = _talloc(context, size);
403 if (ptr == NULL) return NULL;
405 va_start(ap, fmt);
406 talloc_set_name_v(ptr, fmt, ap);
407 va_end(ap);
409 return ptr;
413 create a named talloc pointer. Any talloc pointer can be named, and
414 talloc_named() operates just like talloc() except that it allows you
415 to name the pointer.
417 void *talloc_named_const(const void *context, size_t size, const char *name)
419 void *ptr;
421 ptr = _talloc(context, size);
422 if (ptr == NULL) {
423 return NULL;
426 talloc_set_name_const(ptr, name);
428 return ptr;
432 return the name of a talloc ptr, or "UNNAMED"
434 const char *talloc_get_name(const void *ptr)
436 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
437 if (tc->name == TALLOC_MAGIC_REFERENCE) {
438 return ".reference";
440 if (tc->name) {
441 return tc->name;
443 return "UNNAMED";
448 check if a pointer has the given name. If it does, return the pointer,
449 otherwise return NULL
451 void *talloc_check_name(const void *ptr, const char *name)
453 const char *pname;
454 if (ptr == NULL) return NULL;
455 pname = talloc_get_name(ptr);
456 if (pname == name || strcmp(pname, name) == 0) {
457 return discard_const_p(void, ptr);
459 return NULL;
464 this is for compatibility with older versions of talloc
466 void *talloc_init(const char *fmt, ...)
468 va_list ap;
469 void *ptr;
471 talloc_enable_null_tracking();
473 ptr = _talloc(NULL, 0);
474 if (ptr == NULL) return NULL;
476 va_start(ap, fmt);
477 talloc_set_name_v(ptr, fmt, ap);
478 va_end(ap);
480 return ptr;
484 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
485 should probably not be used in new code. It's in here to keep the talloc
486 code consistent across Samba 3 and 4.
488 void talloc_free_children(void *ptr)
490 struct talloc_chunk *tc;
492 if (ptr == NULL) {
493 return;
496 tc = talloc_chunk_from_ptr(ptr);
498 while (tc->child) {
499 /* we need to work out who will own an abandoned child
500 if it cannot be freed. In priority order, the first
501 choice is owner of any remaining reference to this
502 pointer, the second choice is our parent, and the
503 final choice is the null context. */
504 void *child = TC_PTR_FROM_CHUNK(tc->child);
505 const void *new_parent = null_context;
506 if (tc->child->refs) {
507 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
508 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
510 if (talloc_free(child) == -1) {
511 if (new_parent == null_context) {
512 struct talloc_chunk *p = talloc_parent_chunk(ptr);
513 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
515 talloc_steal(new_parent, child);
521 free a talloc pointer. This also frees all child pointers of this
522 pointer recursively
524 return 0 if the memory is actually freed, otherwise -1. The memory
525 will not be freed if the ref_count is > 1 or the destructor (if
526 any) returns non-zero
528 int talloc_free(void *ptr)
530 struct talloc_chunk *tc;
532 if (ptr == NULL) {
533 return -1;
536 tc = talloc_chunk_from_ptr(ptr);
538 if (tc->refs) {
539 talloc_reference_destructor(tc->refs);
540 return -1;
543 if (tc->flags & TALLOC_FLAG_LOOP) {
544 /* we have a free loop - stop looping */
545 return 0;
548 if (tc->destructor) {
549 talloc_destructor_t d = tc->destructor;
550 if (d == (talloc_destructor_t)-1) {
551 return -1;
553 tc->destructor = (talloc_destructor_t)-1;
554 if (d(ptr) == -1) {
555 tc->destructor = d;
556 return -1;
558 tc->destructor = NULL;
561 tc->flags |= TALLOC_FLAG_LOOP;
563 talloc_free_children(ptr);
565 if (tc->parent) {
566 _TLIST_REMOVE(tc->parent->child, tc);
567 if (tc->parent->child) {
568 tc->parent->child->parent = tc->parent;
570 } else {
571 if (tc->prev) tc->prev->next = tc->next;
572 if (tc->next) tc->next->prev = tc->prev;
575 tc->flags |= TALLOC_FLAG_FREE;
577 free(tc);
578 return 0;
584 A talloc version of realloc. The context argument is only used if
585 ptr is NULL
587 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
589 struct talloc_chunk *tc;
590 void *new_ptr;
592 /* size zero is equivalent to free() */
593 if (size == 0) {
594 talloc_free(ptr);
595 return NULL;
598 if (size >= MAX_TALLOC_SIZE) {
599 return NULL;
602 /* realloc(NULL) is equavalent to malloc() */
603 if (ptr == NULL) {
604 return talloc_named_const(context, size, name);
607 tc = talloc_chunk_from_ptr(ptr);
609 /* don't allow realloc on referenced pointers */
610 if (tc->refs) {
611 return NULL;
614 /* by resetting magic we catch users of the old memory */
615 tc->flags |= TALLOC_FLAG_FREE;
617 #if ALWAYS_REALLOC
618 new_ptr = malloc(size + TC_HDR_SIZE);
619 if (new_ptr) {
620 memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE);
621 free(tc);
623 #else
624 new_ptr = realloc(tc, size + TC_HDR_SIZE);
625 #endif
626 if (!new_ptr) {
627 tc->flags &= ~TALLOC_FLAG_FREE;
628 return NULL;
631 tc = new_ptr;
632 tc->flags &= ~TALLOC_FLAG_FREE;
633 if (tc->parent) {
634 tc->parent->child = new_ptr;
636 if (tc->child) {
637 tc->child->parent = new_ptr;
640 if (tc->prev) {
641 tc->prev->next = tc;
643 if (tc->next) {
644 tc->next->prev = tc;
647 tc->size = size;
648 talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
650 return TC_PTR_FROM_CHUNK(tc);
654 move a lump of memory from one talloc context to another return the
655 ptr on success, or NULL if it could not be transferred.
656 passing NULL as ptr will always return NULL with no side effects.
658 void *talloc_steal(const void *new_ctx, const void *ptr)
660 struct talloc_chunk *tc, *new_tc;
662 if (!ptr) {
663 return NULL;
666 if (new_ctx == NULL) {
667 new_ctx = null_context;
670 tc = talloc_chunk_from_ptr(ptr);
672 if (new_ctx == NULL) {
673 if (tc->parent) {
674 _TLIST_REMOVE(tc->parent->child, tc);
675 if (tc->parent->child) {
676 tc->parent->child->parent = tc->parent;
678 } else {
679 if (tc->prev) tc->prev->next = tc->next;
680 if (tc->next) tc->next->prev = tc->prev;
683 tc->parent = tc->next = tc->prev = NULL;
684 return discard_const_p(void, ptr);
687 new_tc = talloc_chunk_from_ptr(new_ctx);
689 if (tc == new_tc) {
690 return discard_const_p(void, ptr);
693 if (tc->parent) {
694 _TLIST_REMOVE(tc->parent->child, tc);
695 if (tc->parent->child) {
696 tc->parent->child->parent = tc->parent;
698 } else {
699 if (tc->prev) tc->prev->next = tc->next;
700 if (tc->next) tc->next->prev = tc->prev;
703 tc->parent = new_tc;
704 if (new_tc->child) new_tc->child->parent = NULL;
705 _TLIST_ADD(new_tc->child, tc);
707 return discard_const_p(void, ptr);
711 return the total size of a talloc pool (subtree)
713 off_t talloc_total_size(const void *ptr)
715 off_t total = 0;
716 struct talloc_chunk *c, *tc;
718 if (ptr == NULL) {
719 ptr = null_context;
721 if (ptr == NULL) {
722 return 0;
725 tc = talloc_chunk_from_ptr(ptr);
727 if (tc->flags & TALLOC_FLAG_LOOP) {
728 return 0;
731 tc->flags |= TALLOC_FLAG_LOOP;
733 total = tc->size;
734 for (c=tc->child;c;c=c->next) {
735 total += talloc_total_size(TC_PTR_FROM_CHUNK(c));
738 tc->flags &= ~TALLOC_FLAG_LOOP;
740 return total;
744 return the total number of blocks in a talloc pool (subtree)
746 off_t talloc_total_blocks(const void *ptr)
748 off_t total = 0;
749 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
751 if (tc->flags & TALLOC_FLAG_LOOP) {
752 return 0;
755 tc->flags |= TALLOC_FLAG_LOOP;
757 total++;
758 for (c=tc->child;c;c=c->next) {
759 total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
762 tc->flags &= ~TALLOC_FLAG_LOOP;
764 return total;
768 return the number of external references to a pointer
770 static int talloc_reference_count(const void *ptr)
772 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
773 struct talloc_reference_handle *h;
774 int ret = 0;
776 for (h=tc->refs;h;h=h->next) {
777 ret++;
779 return ret;
783 report on memory usage by all children of a pointer, giving a full tree view
785 void talloc_report_depth(const void *ptr, FILE *f, int depth)
787 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
789 if (tc->flags & TALLOC_FLAG_LOOP) {
790 return;
793 tc->flags |= TALLOC_FLAG_LOOP;
795 for (c=tc->child;c;c=c->next) {
796 if (c->name == TALLOC_MAGIC_REFERENCE) {
797 struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c);
798 const char *name2 = talloc_get_name(handle->ptr);
799 fprintf(f, "%*sreference to: %s\n", depth*4, "", name2);
800 } else {
801 const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c));
802 fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n",
803 depth*4, "",
804 name,
805 (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
806 (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)),
807 talloc_reference_count(TC_PTR_FROM_CHUNK(c)));
808 talloc_report_depth(TC_PTR_FROM_CHUNK(c), f, depth+1);
811 tc->flags &= ~TALLOC_FLAG_LOOP;
815 report on memory usage by all children of a pointer, giving a full tree view
817 void talloc_report_full(const void *ptr, FILE *f)
819 if (ptr == NULL) {
820 ptr = null_context;
822 if (ptr == NULL) return;
824 fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n",
825 talloc_get_name(ptr),
826 (unsigned long)talloc_total_size(ptr),
827 (unsigned long)talloc_total_blocks(ptr));
829 talloc_report_depth(ptr, f, 1);
830 fflush(f);
834 report on memory usage by all children of a pointer
836 void talloc_report(const void *ptr, FILE *f)
838 struct talloc_chunk *c, *tc;
840 if (ptr == NULL) {
841 ptr = null_context;
843 if (ptr == NULL) return;
845 fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n",
846 talloc_get_name(ptr),
847 (unsigned long)talloc_total_size(ptr),
848 (unsigned long)talloc_total_blocks(ptr));
850 tc = talloc_chunk_from_ptr(ptr);
852 for (c=tc->child;c;c=c->next) {
853 fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n",
854 talloc_get_name(TC_PTR_FROM_CHUNK(c)),
855 (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
856 (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)));
858 fflush(f);
862 report on any memory hanging off the null context
864 static void talloc_report_null(void)
866 if (talloc_total_size(null_context) != 0) {
867 talloc_report(null_context, stderr);
872 report on any memory hanging off the null context
874 static void talloc_report_null_full(void)
876 if (talloc_total_size(null_context) != 0) {
877 talloc_report_full(null_context, stderr);
882 enable tracking of the NULL context
884 void talloc_enable_null_tracking(void)
886 if (null_context == NULL) {
887 null_context = talloc_named_const(NULL, 0, "null_context");
891 #ifdef _SAMBA_BUILD_
892 /* Ugly calls to Samba-specific sprintf_append... JRA. */
895 report on memory usage by all children of a pointer, giving a full tree view
897 static void talloc_report_depth_str(const void *ptr, char **pps, ssize_t *plen, size_t *pbuflen, int depth)
899 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
901 if (tc->flags & TALLOC_FLAG_LOOP) {
902 return;
905 tc->flags |= TALLOC_FLAG_LOOP;
907 for (c=tc->child;c;c=c->next) {
908 if (c->name == TALLOC_MAGIC_REFERENCE) {
909 struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c);
910 const char *name2 = talloc_get_name(handle->ptr);
912 sprintf_append(NULL, pps, plen, pbuflen,
913 "%*sreference to: %s\n", depth*4, "", name2);
915 } else {
916 const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c));
918 sprintf_append(NULL, pps, plen, pbuflen,
919 "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n",
920 depth*4, "",
921 name,
922 (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
923 (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)),
924 talloc_reference_count(TC_PTR_FROM_CHUNK(c)));
926 talloc_report_depth_str(TC_PTR_FROM_CHUNK(c), pps, plen, pbuflen, depth+1);
929 tc->flags &= ~TALLOC_FLAG_LOOP;
933 report on memory usage by all children of a pointer
935 char *talloc_describe_all(void)
937 ssize_t len = 0;
938 size_t buflen = 512;
939 char *s = NULL;
941 if (null_context == NULL) {
942 return NULL;
945 sprintf_append(NULL, &s, &len, &buflen,
946 "full talloc report on '%s' (total %lu bytes in %lu blocks)\n",
947 talloc_get_name(null_context),
948 (unsigned long)talloc_total_size(null_context),
949 (unsigned long)talloc_total_blocks(null_context));
951 if (!s) {
952 return NULL;
954 talloc_report_depth_str(null_context, &s, &len, &buflen, 1);
955 return s;
957 #endif
960 enable leak reporting on exit
962 void talloc_enable_leak_report(void)
964 talloc_enable_null_tracking();
965 atexit(talloc_report_null);
969 enable full leak reporting on exit
971 void talloc_enable_leak_report_full(void)
973 talloc_enable_null_tracking();
974 atexit(talloc_report_null_full);
978 talloc and zero memory.
980 void *_talloc_zero(const void *ctx, size_t size, const char *name)
982 void *p = talloc_named_const(ctx, size, name);
984 if (p) {
985 memset(p, '\0', size);
988 return p;
993 memdup with a talloc.
995 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
997 void *newp = talloc_named_const(t, size, name);
999 if (newp) {
1000 memcpy(newp, p, size);
1003 return newp;
1007 strdup with a talloc
1009 char *talloc_strdup(const void *t, const char *p)
1011 char *ret;
1012 if (!p) {
1013 return NULL;
1015 ret = talloc_memdup(t, p, strlen(p) + 1);
1016 if (ret) {
1017 talloc_set_name_const(ret, ret);
1019 return ret;
1023 append to a talloced string
1025 char *talloc_append_string(const void *t, char *orig, const char *append)
1027 char *ret;
1028 size_t olen = strlen(orig);
1029 size_t alenz = strlen(append) + 1;
1031 if (!append)
1032 return orig;
1034 ret = talloc_realloc(t, orig, char, olen + alenz);
1035 if (!ret)
1036 return NULL;
1038 /* append the string with the trailing \0 */
1039 memcpy(&ret[olen], append, alenz);
1041 return ret;
1045 strndup with a talloc
1047 char *talloc_strndup(const void *t, const char *p, size_t n)
1049 size_t len;
1050 char *ret;
1052 for (len=0; len<n && p[len]; len++) ;
1054 ret = _talloc(t, len + 1);
1055 if (!ret) { return NULL; }
1056 memcpy(ret, p, len);
1057 ret[len] = 0;
1058 talloc_set_name_const(ret, ret);
1059 return ret;
1062 #ifndef VA_COPY
1063 #ifdef HAVE_VA_COPY
1064 #define VA_COPY(dest, src) va_copy(dest, src)
1065 #elif defined(HAVE___VA_COPY)
1066 #define VA_COPY(dest, src) __va_copy(dest, src)
1067 #else
1068 #define VA_COPY(dest, src) (dest) = (src)
1069 #endif
1070 #endif
1072 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
1074 int len;
1075 char *ret;
1076 va_list ap2;
1078 VA_COPY(ap2, ap);
1080 len = vsnprintf(NULL, 0, fmt, ap2);
1082 ret = _talloc(t, len+1);
1083 if (ret) {
1084 VA_COPY(ap2, ap);
1085 vsnprintf(ret, len+1, fmt, ap2);
1086 talloc_set_name_const(ret, ret);
1089 return 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, ...)
1099 va_list ap;
1100 char *ret;
1102 va_start(ap, fmt);
1103 ret = talloc_vasprintf(t, fmt, ap);
1104 va_end(ap);
1105 return ret;
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.
1115 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
1117 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1119 struct talloc_chunk *tc;
1120 int len, s_len;
1121 va_list ap2;
1123 if (s == NULL) {
1124 return talloc_vasprintf(NULL, fmt, ap);
1127 tc = talloc_chunk_from_ptr(s);
1129 VA_COPY(ap2, ap);
1131 s_len = tc->size - 1;
1132 len = vsnprintf(NULL, 0, fmt, ap2);
1134 s = talloc_realloc(NULL, s, char, s_len + len+1);
1135 if (!s) return NULL;
1137 VA_COPY(ap2, ap);
1139 vsnprintf(s+s_len, len+1, fmt, ap2);
1140 talloc_set_name_const(s, s);
1142 return s;
1146 Realloc @p s to append the formatted result of @p fmt and return @p
1147 s, which may have moved. Good for gradually accumulating output
1148 into a string buffer.
1150 char *talloc_asprintf_append(char *s, const char *fmt, ...)
1152 va_list ap;
1154 va_start(ap, fmt);
1155 s = talloc_vasprintf_append(s, fmt, ap);
1156 va_end(ap);
1157 return s;
1161 alloc an array, checking for integer overflow in the array size
1163 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1165 if (count >= MAX_TALLOC_SIZE/el_size) {
1166 return NULL;
1168 return talloc_named_const(ctx, el_size * count, name);
1172 alloc an zero array, checking for integer overflow in the array size
1174 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1176 if (count >= MAX_TALLOC_SIZE/el_size) {
1177 return NULL;
1179 return _talloc_zero(ctx, el_size * count, name);
1184 realloc an array, checking for integer overflow in the array size
1186 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
1188 if (count >= MAX_TALLOC_SIZE/el_size) {
1189 return NULL;
1191 return _talloc_realloc(ctx, ptr, el_size * count, name);
1195 a function version of talloc_realloc(), so it can be passed as a function pointer
1196 to libraries that want a realloc function (a realloc function encapsulates
1197 all the basic capabilities of an allocation library, which is why this is useful)
1199 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1201 return _talloc_realloc(context, ptr, size, NULL);
1205 static void talloc_autofree(void)
1207 talloc_free(cleanup_context);
1208 cleanup_context = NULL;
1212 return a context which will be auto-freed on exit
1213 this is useful for reducing the noise in leak reports
1215 void *talloc_autofree_context(void)
1217 if (cleanup_context == NULL) {
1218 cleanup_context = talloc_named_const(NULL, 0, "autofree_context");
1219 atexit(talloc_autofree);
1221 return cleanup_context;
1224 size_t talloc_get_size(const void *context)
1226 struct talloc_chunk *tc;
1228 if (context == NULL)
1229 return 0;
1231 tc = talloc_chunk_from_ptr(context);
1233 return tc->size;
1237 find a parent of this context that has the given name, if any
1239 void *talloc_find_parent_byname(const void *context, const char *name)
1241 struct talloc_chunk *tc;
1243 if (context == NULL) {
1244 return NULL;
1247 tc = talloc_chunk_from_ptr(context);
1248 while (tc) {
1249 if (tc->name && strcmp(tc->name, name) == 0) {
1250 return TC_PTR_FROM_CHUNK(tc);
1252 while (tc && tc->prev) tc = tc->prev;
1253 tc = tc->parent;
1255 return NULL;
1259 show the parentage of a context
1261 void talloc_show_parents(const void *context, FILE *file)
1263 struct talloc_chunk *tc;
1265 if (context == NULL) {
1266 fprintf(file, "talloc no parents for NULL\n");
1267 return;
1270 tc = talloc_chunk_from_ptr(context);
1271 fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
1272 while (tc) {
1273 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
1274 while (tc && tc->prev) tc = tc->prev;
1275 tc = tc->parent;