source: branches/samba-3.3.x/source/lib/talloc/talloc.c

Last change on this file was 206, checked in by Herwig Bauernfeind, 16 years ago

Import Samba 3.3 branch at 3.0.0 level (psmedley's port)

File size: 37.7 KB
Line 
1/*
2 Samba Unix SMB/CIFS implementation.
3
4 Samba trivial allocation library - new interface
5
6 NOTE: Please read talloc_guide.txt for full documentation
7
8 Copyright (C) Andrew Tridgell 2004
9 Copyright (C) Stefan Metzmacher 2006
10
11 ** NOTE! The following LGPL license applies to the talloc
12 ** library. This does NOT imply that all of Samba is released
13 ** under the LGPL
14
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.
19
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.
24
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/>.
27*/
28
29/*
30 inspired by http://swapped.cc/halloc/
31*/
32
33#ifdef _SAMBA_BUILD_
34#include "version.h"
35#if (SAMBA_VERSION_MAJOR<4)
36#include "includes.h"
37/* This is to circumvent SAMBA3's paranoid malloc checker. Here in this file
38 * we trust ourselves... */
39#ifdef malloc
40#undef malloc
41#endif
42#ifdef realloc
43#undef realloc
44#endif
45#define _TALLOC_SAMBA3
46#endif /* (SAMBA_VERSION_MAJOR<4) */
47#endif /* _SAMBA_BUILD_ */
48
49#ifndef _TALLOC_SAMBA3
50#include "replace.h"
51#include "talloc.h"
52#endif /* not _TALLOC_SAMBA3 */
53
54/* use this to force every realloc to change the pointer, to stress test
55 code that might not cope */
56#define ALWAYS_REALLOC 0
57
58
59#define MAX_TALLOC_SIZE 0x10000000
60#define TALLOC_MAGIC 0xe814ec70
61#define TALLOC_FLAG_FREE 0x01
62#define TALLOC_FLAG_LOOP 0x02
63#define TALLOC_FLAG_POOL 0x04 /* This is a talloc pool */
64#define TALLOC_FLAG_POOLMEM 0x08 /* This is allocated in a pool */
65#define TALLOC_MAGIC_REFERENCE ((const char *)1)
66
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
72
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
80
81/* these macros gain us a few percent of speed on gcc */
82#if (__GNUC__ >= 3)
83/* the strange !! is to ensure that __builtin_expect() takes either 0 or 1
84 as its first argument */
85#ifndef likely
86#define likely(x) __builtin_expect(!!(x), 1)
87#endif
88#ifndef unlikely
89#define unlikely(x) __builtin_expect(!!(x), 0)
90#endif
91#else
92#ifndef likely
93#define likely(x) (x)
94#endif
95#ifndef unlikely
96#define unlikely(x) (x)
97#endif
98#endif
99
100/* this null_context is only used if talloc_enable_leak_report() or
101 talloc_enable_leak_report_full() is called, otherwise it remains
102 NULL
103*/
104static void *null_context;
105static void *autofree_context;
106
107struct talloc_reference_handle {
108 struct talloc_reference_handle *next, *prev;
109 void *ptr;
110};
111
112typedef int (*talloc_destructor_t)(void *);
113
114struct talloc_chunk {
115 struct talloc_chunk *next, *prev;
116 struct talloc_chunk *parent, *child;
117 struct talloc_reference_handle *refs;
118 talloc_destructor_t destructor;
119 const char *name;
120 size_t size;
121 unsigned flags;
122
123 /*
124 * "pool" has dual use:
125 *
126 * For the talloc pool itself (i.e. TALLOC_FLAG_POOL is set), "pool"
127 * marks the end of the currently allocated area.
128 *
129 * For members of the pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool"
130 * is a pointer to the struct talloc_chunk of the pool that it was
131 * allocated from. This way children can quickly find the pool to chew
132 * from.
133 */
134 void *pool;
135};
136
137/* 16 byte alignment seems to keep everyone happy */
138#define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
139#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
140
141static void talloc_abort_double_free(void)
142{
143 TALLOC_ABORT("Bad talloc magic value - double free");
144}
145
146static void talloc_abort_unknown_value(void)
147{
148 TALLOC_ABORT("Bad talloc magic value - unknown value");
149}
150
151/* panic if we get a bad magic value */
152static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
153{
154 const char *pp = (const char *)ptr;
155 struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
156 if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) {
157 if (tc->flags & TALLOC_FLAG_FREE) {
158 talloc_abort_double_free();
159 } else {
160 talloc_abort_unknown_value();
161 }
162 }
163 return tc;
164}
165
166/* hook into the front of the list */
167#define _TLIST_ADD(list, p) \
168do { \
169 if (!(list)) { \
170 (list) = (p); \
171 (p)->next = (p)->prev = NULL; \
172 } else { \
173 (list)->prev = (p); \
174 (p)->next = (list); \
175 (p)->prev = NULL; \
176 (list) = (p); \
177 }\
178} while (0)
179
180/* remove an element from a list - element doesn't have to be in list. */
181#define _TLIST_REMOVE(list, p) \
182do { \
183 if ((p) == (list)) { \
184 (list) = (p)->next; \
185 if (list) (list)->prev = NULL; \
186 } else { \
187 if ((p)->prev) (p)->prev->next = (p)->next; \
188 if ((p)->next) (p)->next->prev = (p)->prev; \
189 } \
190 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
191} while (0)
192
193
194/*
195 return the parent chunk of a pointer
196*/
197static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr)
198{
199 struct talloc_chunk *tc;
200
201 if (unlikely(ptr == NULL)) {
202 return NULL;
203 }
204
205 tc = talloc_chunk_from_ptr(ptr);
206 while (tc->prev) tc=tc->prev;
207
208 return tc->parent;
209}
210
211void *talloc_parent(const void *ptr)
212{
213 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
214 return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
215}
216
217/*
218 find parents name
219*/
220const char *talloc_parent_name(const void *ptr)
221{
222 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
223 return tc? tc->name : NULL;
224}
225
226/*
227 A pool carries an in-pool object count count in the first 16 bytes.
228 bytes. This is done to support talloc_steal() to a parent outside of the
229 pool. The count includes the pool itself, so a talloc_free() on a pool will
230 only destroy the pool if the count has dropped to zero. A talloc_free() of a
231 pool member will reduce the count, and eventually also call free(3) on the
232 pool memory.
233
234 The object count is not put into "struct talloc_chunk" because it is only
235 relevant for talloc pools and the alignment to 16 bytes would increase the
236 memory footprint of each talloc chunk by those 16 bytes.
237*/
238
239#define TALLOC_POOL_HDR_SIZE 16
240
241static unsigned int *talloc_pool_objectcount(struct talloc_chunk *tc)
242{
243 return (unsigned int *)((char *)tc + sizeof(struct talloc_chunk));
244}
245
246/*
247 Allocate from a pool
248*/
249
250static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
251 size_t size)
252{
253 struct talloc_chunk *pool_ctx = NULL;
254 size_t space_left;
255 struct talloc_chunk *result;
256 size_t chunk_size;
257
258 if (parent == NULL) {
259 return NULL;
260 }
261
262 if (parent->flags & TALLOC_FLAG_POOL) {
263 pool_ctx = parent;
264 }
265 else if (parent->flags & TALLOC_FLAG_POOLMEM) {
266 pool_ctx = (struct talloc_chunk *)parent->pool;
267 }
268
269 if (pool_ctx == NULL) {
270 return NULL;
271 }
272
273 space_left = ((char *)pool_ctx + TC_HDR_SIZE + pool_ctx->size)
274 - ((char *)pool_ctx->pool);
275
276 /*
277 * Align size to 16 bytes
278 */
279 chunk_size = ((size + 15) & ~15);
280
281 if (space_left < chunk_size) {
282 return NULL;
283 }
284
285 result = (struct talloc_chunk *)pool_ctx->pool;
286
287#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
288 VALGRIND_MAKE_MEM_UNDEFINED(result, size);
289#endif
290
291 pool_ctx->pool = (void *)((char *)result + chunk_size);
292
293 result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM;
294 result->pool = pool_ctx;
295
296 *talloc_pool_objectcount(pool_ctx) += 1;
297
298 return result;
299}
300
301/*
302 Allocate a bit of memory as a child of an existing pointer
303*/
304static inline void *__talloc(const void *context, size_t size)
305{
306 struct talloc_chunk *tc = NULL;
307
308 if (unlikely(context == NULL)) {
309 context = null_context;
310 }
311
312 if (unlikely(size >= MAX_TALLOC_SIZE)) {
313 return NULL;
314 }
315
316 if (context != NULL) {
317 tc = talloc_alloc_pool(talloc_chunk_from_ptr(context),
318 TC_HDR_SIZE+size);
319 }
320
321 if (tc == NULL) {
322 tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size);
323 if (unlikely(tc == NULL)) return NULL;
324 tc->flags = TALLOC_MAGIC;
325 tc->pool = NULL;
326 }
327
328 tc->size = size;
329 tc->destructor = NULL;
330 tc->child = NULL;
331 tc->name = NULL;
332 tc->refs = NULL;
333
334 if (likely(context)) {
335 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
336
337 if (parent->child) {
338 parent->child->parent = NULL;
339 tc->next = parent->child;
340 tc->next->prev = tc;
341 } else {
342 tc->next = NULL;
343 }
344 tc->parent = parent;
345 tc->prev = NULL;
346 parent->child = tc;
347 } else {
348 tc->next = tc->prev = tc->parent = NULL;
349 }
350
351 return TC_PTR_FROM_CHUNK(tc);
352}
353
354/*
355 * Create a talloc pool
356 */
357
358void *talloc_pool(const void *context, size_t size)
359{
360 void *result = __talloc(context, size + TALLOC_POOL_HDR_SIZE);
361 struct talloc_chunk *tc;
362
363 if (unlikely(result == NULL)) {
364 return NULL;
365 }
366
367 tc = talloc_chunk_from_ptr(result);
368
369 tc->flags |= TALLOC_FLAG_POOL;
370 tc->pool = (char *)result + TALLOC_POOL_HDR_SIZE;
371
372 *talloc_pool_objectcount(tc) = 1;
373
374#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
375 VALGRIND_MAKE_MEM_NOACCESS(tc->pool, size);
376#endif
377
378 return result;
379}
380
381/*
382 setup a destructor to be called on free of a pointer
383 the destructor should return 0 on success, or -1 on failure.
384 if the destructor fails then the free is failed, and the memory can
385 be continued to be used
386*/
387void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
388{
389 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
390 tc->destructor = destructor;
391}
392
393/*
394 increase the reference count on a piece of memory.
395*/
396int talloc_increase_ref_count(const void *ptr)
397{
398 if (unlikely(!talloc_reference(null_context, ptr))) {
399 return -1;
400 }
401 return 0;
402}
403
404/*
405 helper for talloc_reference()
406
407 this is referenced by a function pointer and should not be inline
408*/
409static int talloc_reference_destructor(struct talloc_reference_handle *handle)
410{
411 struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
412 _TLIST_REMOVE(ptr_tc->refs, handle);
413 return 0;
414}
415
416/*
417 more efficient way to add a name to a pointer - the name must point to a
418 true string constant
419*/
420static inline void _talloc_set_name_const(const void *ptr, const char *name)
421{
422 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
423 tc->name = name;
424}
425
426/*
427 internal talloc_named_const()
428*/
429static inline void *_talloc_named_const(const void *context, size_t size, const char *name)
430{
431 void *ptr;
432
433 ptr = __talloc(context, size);
434 if (unlikely(ptr == NULL)) {
435 return NULL;
436 }
437
438 _talloc_set_name_const(ptr, name);
439
440 return ptr;
441}
442
443/*
444 make a secondary reference to a pointer, hanging off the given context.
445 the pointer remains valid until both the original caller and this given
446 context are freed.
447
448 the major use for this is when two different structures need to reference the
449 same underlying data, and you want to be able to free the two instances separately,
450 and in either order
451*/
452void *_talloc_reference(const void *context, const void *ptr)
453{
454 struct talloc_chunk *tc;
455 struct talloc_reference_handle *handle;
456 if (unlikely(ptr == NULL)) return NULL;
457
458 tc = talloc_chunk_from_ptr(ptr);
459 handle = (struct talloc_reference_handle *)_talloc_named_const(context,
460 sizeof(struct talloc_reference_handle),
461 TALLOC_MAGIC_REFERENCE);
462 if (unlikely(handle == NULL)) return NULL;
463
464 /* note that we hang the destructor off the handle, not the
465 main context as that allows the caller to still setup their
466 own destructor on the context if they want to */
467 talloc_set_destructor(handle, talloc_reference_destructor);
468 handle->ptr = discard_const_p(void, ptr);
469 _TLIST_ADD(tc->refs, handle);
470 return handle->ptr;
471}
472
473
474/*
475 internal talloc_free call
476*/
477static inline int _talloc_free(void *ptr)
478{
479 struct talloc_chunk *tc;
480
481 if (unlikely(ptr == NULL)) {
482 return -1;
483 }
484
485 tc = talloc_chunk_from_ptr(ptr);
486
487 if (unlikely(tc->refs)) {
488 int is_child;
489 /* check this is a reference from a child or grantchild
490 * back to it's parent or grantparent
491 *
492 * in that case we need to remove the reference and
493 * call another instance of talloc_free() on the current
494 * pointer.
495 */
496 is_child = talloc_is_parent(tc->refs, ptr);
497 _talloc_free(tc->refs);
498 if (is_child) {
499 return _talloc_free(ptr);
500 }
501 return -1;
502 }
503
504 if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) {
505 /* we have a free loop - stop looping */
506 return 0;
507 }
508
509 if (unlikely(tc->destructor)) {
510 talloc_destructor_t d = tc->destructor;
511 if (d == (talloc_destructor_t)-1) {
512 return -1;
513 }
514 tc->destructor = (talloc_destructor_t)-1;
515 if (d(ptr) == -1) {
516 tc->destructor = d;
517 return -1;
518 }
519 tc->destructor = NULL;
520 }
521
522 if (tc->parent) {
523 _TLIST_REMOVE(tc->parent->child, tc);
524 if (tc->parent->child) {
525 tc->parent->child->parent = tc->parent;
526 }
527 } else {
528 if (tc->prev) tc->prev->next = tc->next;
529 if (tc->next) tc->next->prev = tc->prev;
530 }
531
532 tc->flags |= TALLOC_FLAG_LOOP;
533
534 while (tc->child) {
535 /* we need to work out who will own an abandoned child
536 if it cannot be freed. In priority order, the first
537 choice is owner of any remaining reference to this
538 pointer, the second choice is our parent, and the
539 final choice is the null context. */
540 void *child = TC_PTR_FROM_CHUNK(tc->child);
541 const void *new_parent = null_context;
542 if (unlikely(tc->child->refs)) {
543 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
544 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
545 }
546 if (unlikely(_talloc_free(child) == -1)) {
547 if (new_parent == null_context) {
548 struct talloc_chunk *p = talloc_parent_chunk(ptr);
549 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
550 }
551 talloc_steal(new_parent, child);
552 }
553 }
554
555 tc->flags |= TALLOC_FLAG_FREE;
556
557 if (tc->flags & (TALLOC_FLAG_POOL|TALLOC_FLAG_POOLMEM)) {
558 struct talloc_chunk *pool;
559 unsigned int *pool_object_count;
560
561 pool = (tc->flags & TALLOC_FLAG_POOL)
562 ? tc : (struct talloc_chunk *)tc->pool;
563
564 pool_object_count = talloc_pool_objectcount(pool);
565
566 if (*pool_object_count == 0) {
567 TALLOC_ABORT("Pool object count zero!");
568 }
569
570 *pool_object_count -= 1;
571
572 if (*pool_object_count == 0) {
573 free(pool);
574 }
575 }
576 else {
577 free(tc);
578 }
579 return 0;
580}
581
582/*
583 move a lump of memory from one talloc context to another return the
584 ptr on success, or NULL if it could not be transferred.
585 passing NULL as ptr will always return NULL with no side effects.
586*/
587void *_talloc_steal(const void *new_ctx, const void *ptr)
588{
589 struct talloc_chunk *tc, *new_tc;
590
591 if (unlikely(!ptr)) {
592 return NULL;
593 }
594
595 if (unlikely(new_ctx == NULL)) {
596 new_ctx = null_context;
597 }
598
599 tc = talloc_chunk_from_ptr(ptr);
600
601 if (unlikely(new_ctx == NULL)) {
602 if (tc->parent) {
603 _TLIST_REMOVE(tc->parent->child, tc);
604 if (tc->parent->child) {
605 tc->parent->child->parent = tc->parent;
606 }
607 } else {
608 if (tc->prev) tc->prev->next = tc->next;
609 if (tc->next) tc->next->prev = tc->prev;
610 }
611
612 tc->parent = tc->next = tc->prev = NULL;
613 return discard_const_p(void, ptr);
614 }
615
616 new_tc = talloc_chunk_from_ptr(new_ctx);
617
618 if (unlikely(tc == new_tc || tc->parent == new_tc)) {
619 return discard_const_p(void, ptr);
620 }
621
622 if (tc->parent) {
623 _TLIST_REMOVE(tc->parent->child, tc);
624 if (tc->parent->child) {
625 tc->parent->child->parent = tc->parent;
626 }
627 } else {
628 if (tc->prev) tc->prev->next = tc->next;
629 if (tc->next) tc->next->prev = tc->prev;
630 }
631
632 tc->parent = new_tc;
633 if (new_tc->child) new_tc->child->parent = NULL;
634 _TLIST_ADD(new_tc->child, tc);
635
636 return discard_const_p(void, ptr);
637}
638
639
640
641/*
642 remove a secondary reference to a pointer. This undo's what
643 talloc_reference() has done. The context and pointer arguments
644 must match those given to a talloc_reference()
645*/
646static inline int talloc_unreference(const void *context, const void *ptr)
647{
648 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
649 struct talloc_reference_handle *h;
650
651 if (unlikely(context == NULL)) {
652 context = null_context;
653 }
654
655 for (h=tc->refs;h;h=h->next) {
656 struct talloc_chunk *p = talloc_parent_chunk(h);
657 if (p == NULL) {
658 if (context == NULL) break;
659 } else if (TC_PTR_FROM_CHUNK(p) == context) {
660 break;
661 }
662 }
663 if (h == NULL) {
664 return -1;
665 }
666
667 return _talloc_free(h);
668}
669
670/*
671 remove a specific parent context from a pointer. This is a more
672 controlled varient of talloc_free()
673*/
674int talloc_unlink(const void *context, void *ptr)
675{
676 struct talloc_chunk *tc_p, *new_p;
677 void *new_parent;
678
679 if (ptr == NULL) {
680 return -1;
681 }
682
683 if (context == NULL) {
684 context = null_context;
685 }
686
687 if (talloc_unreference(context, ptr) == 0) {
688 return 0;
689 }
690
691 if (context == NULL) {
692 if (talloc_parent_chunk(ptr) != NULL) {
693 return -1;
694 }
695 } else {
696 if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) {
697 return -1;
698 }
699 }
700
701 tc_p = talloc_chunk_from_ptr(ptr);
702
703 if (tc_p->refs == NULL) {
704 return _talloc_free(ptr);
705 }
706
707 new_p = talloc_parent_chunk(tc_p->refs);
708 if (new_p) {
709 new_parent = TC_PTR_FROM_CHUNK(new_p);
710 } else {
711 new_parent = NULL;
712 }
713
714 if (talloc_unreference(new_parent, ptr) != 0) {
715 return -1;
716 }
717
718 talloc_steal(new_parent, ptr);
719
720 return 0;
721}
722
723/*
724 add a name to an existing pointer - va_list version
725*/
726static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
727
728static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
729{
730 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
731 tc->name = talloc_vasprintf(ptr, fmt, ap);
732 if (likely(tc->name)) {
733 _talloc_set_name_const(tc->name, ".name");
734 }
735 return tc->name;
736}
737
738/*
739 add a name to an existing pointer
740*/
741const char *talloc_set_name(const void *ptr, const char *fmt, ...)
742{
743 const char *name;
744 va_list ap;
745 va_start(ap, fmt);
746 name = talloc_set_name_v(ptr, fmt, ap);
747 va_end(ap);
748 return name;
749}
750
751
752/*
753 create a named talloc pointer. Any talloc pointer can be named, and
754 talloc_named() operates just like talloc() except that it allows you
755 to name the pointer.
756*/
757void *talloc_named(const void *context, size_t size, const char *fmt, ...)
758{
759 va_list ap;
760 void *ptr;
761 const char *name;
762
763 ptr = __talloc(context, size);
764 if (unlikely(ptr == NULL)) return NULL;
765
766 va_start(ap, fmt);
767 name = talloc_set_name_v(ptr, fmt, ap);
768 va_end(ap);
769
770 if (unlikely(name == NULL)) {
771 _talloc_free(ptr);
772 return NULL;
773 }
774
775 return ptr;
776}
777
778/*
779 return the name of a talloc ptr, or "UNNAMED"
780*/
781const char *talloc_get_name(const void *ptr)
782{
783 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
784 if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
785 return ".reference";
786 }
787 if (likely(tc->name)) {
788 return tc->name;
789 }
790 return "UNNAMED";
791}
792
793
794/*
795 check if a pointer has the given name. If it does, return the pointer,
796 otherwise return NULL
797*/
798void *talloc_check_name(const void *ptr, const char *name)
799{
800 const char *pname;
801 if (unlikely(ptr == NULL)) return NULL;
802 pname = talloc_get_name(ptr);
803 if (likely(pname == name || strcmp(pname, name) == 0)) {
804 return discard_const_p(void, ptr);
805 }
806 return NULL;
807}
808
809
810/*
811 this is for compatibility with older versions of talloc
812*/
813void *talloc_init(const char *fmt, ...)
814{
815 va_list ap;
816 void *ptr;
817 const char *name;
818
819 /*
820 * samba3 expects talloc_report_depth_cb(NULL, ...)
821 * reports all talloc'ed memory, so we need to enable
822 * null_tracking
823 */
824 talloc_enable_null_tracking();
825
826 ptr = __talloc(NULL, 0);
827 if (unlikely(ptr == NULL)) return NULL;
828
829 va_start(ap, fmt);
830 name = talloc_set_name_v(ptr, fmt, ap);
831 va_end(ap);
832
833 if (unlikely(name == NULL)) {
834 _talloc_free(ptr);
835 return NULL;
836 }
837
838 return ptr;
839}
840
841/*
842 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
843 should probably not be used in new code. It's in here to keep the talloc
844 code consistent across Samba 3 and 4.
845*/
846void talloc_free_children(void *ptr)
847{
848 struct talloc_chunk *tc;
849
850 if (unlikely(ptr == NULL)) {
851 return;
852 }
853
854 tc = talloc_chunk_from_ptr(ptr);
855
856 while (tc->child) {
857 /* we need to work out who will own an abandoned child
858 if it cannot be freed. In priority order, the first
859 choice is owner of any remaining reference to this
860 pointer, the second choice is our parent, and the
861 final choice is the null context. */
862 void *child = TC_PTR_FROM_CHUNK(tc->child);
863 const void *new_parent = null_context;
864 if (unlikely(tc->child->refs)) {
865 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
866 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
867 }
868 if (unlikely(_talloc_free(child) == -1)) {
869 if (new_parent == null_context) {
870 struct talloc_chunk *p = talloc_parent_chunk(ptr);
871 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
872 }
873 talloc_steal(new_parent, child);
874 }
875 }
876
877 if ((tc->flags & TALLOC_FLAG_POOL)
878 && (*talloc_pool_objectcount(tc) == 1)) {
879 tc->pool = ((char *)tc + TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE);
880#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
881 VALGRIND_MAKE_MEM_NOACCESS(
882 tc->pool, tc->size - TALLOC_POOL_HDR_SIZE);
883#endif
884 }
885}
886
887/*
888 Allocate a bit of memory as a child of an existing pointer
889*/
890void *_talloc(const void *context, size_t size)
891{
892 return __talloc(context, size);
893}
894
895/*
896 externally callable talloc_set_name_const()
897*/
898void talloc_set_name_const(const void *ptr, const char *name)
899{
900 _talloc_set_name_const(ptr, name);
901}
902
903/*
904 create a named talloc pointer. Any talloc pointer can be named, and
905 talloc_named() operates just like talloc() except that it allows you
906 to name the pointer.
907*/
908void *talloc_named_const(const void *context, size_t size, const char *name)
909{
910 return _talloc_named_const(context, size, name);
911}
912
913/*
914 free a talloc pointer. This also frees all child pointers of this
915 pointer recursively
916
917 return 0 if the memory is actually freed, otherwise -1. The memory
918 will not be freed if the ref_count is > 1 or the destructor (if
919 any) returns non-zero
920*/
921int talloc_free(void *ptr)
922{
923 return _talloc_free(ptr);
924}
925
926
927
928/*
929 A talloc version of realloc. The context argument is only used if
930 ptr is NULL
931*/
932void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
933{
934 struct talloc_chunk *tc;
935 void *new_ptr;
936 bool malloced = false;
937
938 /* size zero is equivalent to free() */
939 if (unlikely(size == 0)) {
940 _talloc_free(ptr);
941 return NULL;
942 }
943
944 if (unlikely(size >= MAX_TALLOC_SIZE)) {
945 return NULL;
946 }
947
948 /* realloc(NULL) is equivalent to malloc() */
949 if (ptr == NULL) {
950 return _talloc_named_const(context, size, name);
951 }
952
953 tc = talloc_chunk_from_ptr(ptr);
954
955 /* don't allow realloc on referenced pointers */
956 if (unlikely(tc->refs)) {
957 return NULL;
958 }
959
960 /* don't shrink if we have less than 1k to gain */
961 if ((size < tc->size) && ((tc->size - size) < 1024)) {
962 tc->size = size;
963 return ptr;
964 }
965
966 /* by resetting magic we catch users of the old memory */
967 tc->flags |= TALLOC_FLAG_FREE;
968
969#if ALWAYS_REALLOC
970 new_ptr = malloc(size + TC_HDR_SIZE);
971 if (new_ptr) {
972 memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE);
973 free(tc);
974 }
975#else
976 if (tc->flags & TALLOC_FLAG_POOLMEM) {
977
978 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
979 *talloc_pool_objectcount((struct talloc_chunk *)
980 (tc->pool)) -= 1;
981
982 if (new_ptr == NULL) {
983 new_ptr = malloc(TC_HDR_SIZE+size);
984 malloced = true;
985 }
986
987 if (new_ptr) {
988 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
989 }
990 }
991 else {
992 new_ptr = realloc(tc, size + TC_HDR_SIZE);
993 }
994#endif
995 if (unlikely(!new_ptr)) {
996 tc->flags &= ~TALLOC_FLAG_FREE;
997 return NULL;
998 }
999
1000 tc = (struct talloc_chunk *)new_ptr;
1001 tc->flags &= ~TALLOC_FLAG_FREE;
1002 if (malloced) {
1003 tc->flags &= ~TALLOC_FLAG_POOLMEM;
1004 }
1005 if (tc->parent) {
1006 tc->parent->child = tc;
1007 }
1008 if (tc->child) {
1009 tc->child->parent = tc;
1010 }
1011
1012 if (tc->prev) {
1013 tc->prev->next = tc;
1014 }
1015 if (tc->next) {
1016 tc->next->prev = tc;
1017 }
1018
1019 tc->size = size;
1020 _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
1021
1022 return TC_PTR_FROM_CHUNK(tc);
1023}
1024
1025/*
1026 a wrapper around talloc_steal() for situations where you are moving a pointer
1027 between two structures, and want the old pointer to be set to NULL
1028*/
1029void *_talloc_move(const void *new_ctx, const void *_pptr)
1030{
1031 const void **pptr = discard_const_p(const void *,_pptr);
1032 void *ret = _talloc_steal(new_ctx, *pptr);
1033 (*pptr) = NULL;
1034 return ret;
1035}
1036
1037/*
1038 return the total size of a talloc pool (subtree)
1039*/
1040size_t talloc_total_size(const void *ptr)
1041{
1042 size_t total = 0;
1043 struct talloc_chunk *c, *tc;
1044
1045 if (ptr == NULL) {
1046 ptr = null_context;
1047 }
1048 if (ptr == NULL) {
1049 return 0;
1050 }
1051
1052 tc = talloc_chunk_from_ptr(ptr);
1053
1054 if (tc->flags & TALLOC_FLAG_LOOP) {
1055 return 0;
1056 }
1057
1058 tc->flags |= TALLOC_FLAG_LOOP;
1059
1060 total = tc->size;
1061 for (c=tc->child;c;c=c->next) {
1062 total += talloc_total_size(TC_PTR_FROM_CHUNK(c));
1063 }
1064
1065 tc->flags &= ~TALLOC_FLAG_LOOP;
1066
1067 return total;
1068}
1069
1070/*
1071 return the total number of blocks in a talloc pool (subtree)
1072*/
1073size_t talloc_total_blocks(const void *ptr)
1074{
1075 size_t total = 0;
1076 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
1077
1078 if (tc->flags & TALLOC_FLAG_LOOP) {
1079 return 0;
1080 }
1081
1082 tc->flags |= TALLOC_FLAG_LOOP;
1083
1084 total++;
1085 for (c=tc->child;c;c=c->next) {
1086 total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
1087 }
1088
1089 tc->flags &= ~TALLOC_FLAG_LOOP;
1090
1091 return total;
1092}
1093
1094/*
1095 return the number of external references to a pointer
1096*/
1097size_t talloc_reference_count(const void *ptr)
1098{
1099 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1100 struct talloc_reference_handle *h;
1101 size_t ret = 0;
1102
1103 for (h=tc->refs;h;h=h->next) {
1104 ret++;
1105 }
1106 return ret;
1107}
1108
1109/*
1110 report on memory usage by all children of a pointer, giving a full tree view
1111*/
1112void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
1113 void (*callback)(const void *ptr,
1114 int depth, int max_depth,
1115 int is_ref,
1116 void *private_data),
1117 void *private_data)
1118{
1119 struct talloc_chunk *c, *tc;
1120
1121 if (ptr == NULL) {
1122 ptr = null_context;
1123 }
1124 if (ptr == NULL) return;
1125
1126 tc = talloc_chunk_from_ptr(ptr);
1127
1128 if (tc->flags & TALLOC_FLAG_LOOP) {
1129 return;
1130 }
1131
1132 callback(ptr, depth, max_depth, 0, private_data);
1133
1134 if (max_depth >= 0 && depth >= max_depth) {
1135 return;
1136 }
1137
1138 tc->flags |= TALLOC_FLAG_LOOP;
1139 for (c=tc->child;c;c=c->next) {
1140 if (c->name == TALLOC_MAGIC_REFERENCE) {
1141 struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
1142 callback(h->ptr, depth + 1, max_depth, 1, private_data);
1143 } else {
1144 talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
1145 }
1146 }
1147 tc->flags &= ~TALLOC_FLAG_LOOP;
1148}
1149
1150static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
1151{
1152 const char *name = talloc_get_name(ptr);
1153 FILE *f = (FILE *)_f;
1154
1155 if (is_ref) {
1156 fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
1157 return;
1158 }
1159
1160 if (depth == 0) {
1161 fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
1162 (max_depth < 0 ? "full " :""), name,
1163 (unsigned long)talloc_total_size(ptr),
1164 (unsigned long)talloc_total_blocks(ptr));
1165 return;
1166 }
1167
1168 fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n",
1169 depth*4, "",
1170 name,
1171 (unsigned long)talloc_total_size(ptr),
1172 (unsigned long)talloc_total_blocks(ptr),
1173 (int)talloc_reference_count(ptr), ptr);
1174
1175#if 0
1176 fprintf(f, "content: ");
1177 if (talloc_total_size(ptr)) {
1178 int tot = talloc_total_size(ptr);
1179 int i;
1180
1181 for (i = 0; i < tot; i++) {
1182 if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
1183 fprintf(f, "%c", ((char *)ptr)[i]);
1184 } else {
1185 fprintf(f, "~%02x", ((char *)ptr)[i]);
1186 }
1187 }
1188 }
1189 fprintf(f, "\n");
1190#endif
1191}
1192
1193/*
1194 report on memory usage by all children of a pointer, giving a full tree view
1195*/
1196void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
1197{
1198 talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
1199 fflush(f);
1200}
1201
1202/*
1203 report on memory usage by all children of a pointer, giving a full tree view
1204*/
1205void talloc_report_full(const void *ptr, FILE *f)
1206{
1207 talloc_report_depth_file(ptr, 0, -1, f);
1208}
1209
1210/*
1211 report on memory usage by all children of a pointer
1212*/
1213void talloc_report(const void *ptr, FILE *f)
1214{
1215 talloc_report_depth_file(ptr, 0, 1, f);
1216}
1217
1218/*
1219 report on any memory hanging off the null context
1220*/
1221static void talloc_report_null(void)
1222{
1223 if (talloc_total_size(null_context) != 0) {
1224 talloc_report(null_context, stderr);
1225 }
1226}
1227
1228/*
1229 report on any memory hanging off the null context
1230*/
1231static void talloc_report_null_full(void)
1232{
1233 if (talloc_total_size(null_context) != 0) {
1234 talloc_report_full(null_context, stderr);
1235 }
1236}
1237
1238/*
1239 enable tracking of the NULL context
1240*/
1241void talloc_enable_null_tracking(void)
1242{
1243 if (null_context == NULL) {
1244 null_context = _talloc_named_const(NULL, 0, "null_context");
1245 }
1246}
1247
1248/*
1249 disable tracking of the NULL context
1250*/
1251void talloc_disable_null_tracking(void)
1252{
1253 _talloc_free(null_context);
1254 null_context = NULL;
1255}
1256
1257/*
1258 enable leak reporting on exit
1259*/
1260void talloc_enable_leak_report(void)
1261{
1262 talloc_enable_null_tracking();
1263 atexit(talloc_report_null);
1264}
1265
1266/*
1267 enable full leak reporting on exit
1268*/
1269void talloc_enable_leak_report_full(void)
1270{
1271 talloc_enable_null_tracking();
1272 atexit(talloc_report_null_full);
1273}
1274
1275/*
1276 talloc and zero memory.
1277*/
1278void *_talloc_zero(const void *ctx, size_t size, const char *name)
1279{
1280 void *p = _talloc_named_const(ctx, size, name);
1281
1282 if (p) {
1283 memset(p, '\0', size);
1284 }
1285
1286 return p;
1287}
1288
1289/*
1290 memdup with a talloc.
1291*/
1292void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
1293{
1294 void *newp = _talloc_named_const(t, size, name);
1295
1296 if (likely(newp)) {
1297 memcpy(newp, p, size);
1298 }
1299
1300 return newp;
1301}
1302
1303static inline char *__talloc_strlendup(const void *t, const char *p, size_t len)
1304{
1305 char *ret;
1306
1307 ret = (char *)__talloc(t, len + 1);
1308 if (unlikely(!ret)) return NULL;
1309
1310 memcpy(ret, p, len);
1311 ret[len] = 0;
1312
1313 _talloc_set_name_const(ret, ret);
1314 return ret;
1315}
1316
1317/*
1318 strdup with a talloc
1319*/
1320char *talloc_strdup(const void *t, const char *p)
1321{
1322 if (unlikely(!p)) return NULL;
1323 return __talloc_strlendup(t, p, strlen(p));
1324}
1325
1326/*
1327 strndup with a talloc
1328*/
1329char *talloc_strndup(const void *t, const char *p, size_t n)
1330{
1331 if (unlikely(!p)) return NULL;
1332 return __talloc_strlendup(t, p, strnlen(p, n));
1333}
1334
1335static inline char *__talloc_strlendup_append(char *s, size_t slen,
1336 const char *a, size_t alen)
1337{
1338 char *ret;
1339
1340 ret = talloc_realloc(NULL, s, char, slen + alen + 1);
1341 if (unlikely(!ret)) return NULL;
1342
1343 /* append the string and the trailing \0 */
1344 memcpy(&ret[slen], a, alen);
1345 ret[slen+alen] = 0;
1346
1347 _talloc_set_name_const(ret, ret);
1348 return ret;
1349}
1350
1351/*
1352 * Appends at the end of the string.
1353 */
1354char *talloc_strdup_append(char *s, const char *a)
1355{
1356 if (unlikely(!s)) {
1357 return talloc_strdup(NULL, a);
1358 }
1359
1360 if (unlikely(!a)) {
1361 return s;
1362 }
1363
1364 return __talloc_strlendup_append(s, strlen(s), a, strlen(a));
1365}
1366
1367/*
1368 * Appends at the end of the talloc'ed buffer,
1369 * not the end of the string.
1370 */
1371char *talloc_strdup_append_buffer(char *s, const char *a)
1372{
1373 size_t slen;
1374
1375 if (unlikely(!s)) {
1376 return talloc_strdup(NULL, a);
1377 }
1378
1379 if (unlikely(!a)) {
1380 return s;
1381 }
1382
1383 slen = talloc_get_size(s);
1384 if (likely(slen > 0)) {
1385 slen--;
1386 }
1387
1388 return __talloc_strlendup_append(s, slen, a, strlen(a));
1389}
1390
1391/*
1392 * Appends at the end of the string.
1393 */
1394char *talloc_strndup_append(char *s, const char *a, size_t n)
1395{
1396 if (unlikely(!s)) {
1397 return talloc_strdup(NULL, a);
1398 }
1399
1400 if (unlikely(!a)) {
1401 return s;
1402 }
1403
1404 return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n));
1405}
1406
1407/*
1408 * Appends at the end of the talloc'ed buffer,
1409 * not the end of the string.
1410 */
1411char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)
1412{
1413 size_t slen;
1414
1415 if (unlikely(!s)) {
1416 return talloc_strdup(NULL, a);
1417 }
1418
1419 if (unlikely(!a)) {
1420 return s;
1421 }
1422
1423 slen = talloc_get_size(s);
1424 if (likely(slen > 0)) {
1425 slen--;
1426 }
1427
1428 return __talloc_strlendup_append(s, slen, a, strnlen(a, n));
1429}
1430
1431#ifndef HAVE_VA_COPY
1432#ifdef HAVE___VA_COPY
1433#define va_copy(dest, src) __va_copy(dest, src)
1434#else
1435#define va_copy(dest, src) (dest) = (src)
1436#endif
1437#endif
1438
1439char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
1440{
1441 int len;
1442 char *ret;
1443 va_list ap2;
1444 char c;
1445
1446 /* this call looks strange, but it makes it work on older solaris boxes */
1447 va_copy(ap2, ap);
1448 len = vsnprintf(&c, 1, fmt, ap2);
1449 va_end(ap2);
1450 if (unlikely(len < 0)) {
1451 return NULL;
1452 }
1453
1454 ret = (char *)__talloc(t, len+1);
1455 if (unlikely(!ret)) return NULL;
1456
1457 va_copy(ap2, ap);
1458 vsnprintf(ret, len+1, fmt, ap2);
1459 va_end(ap2);
1460
1461 _talloc_set_name_const(ret, ret);
1462 return ret;
1463}
1464
1465
1466/*
1467 Perform string formatting, and return a pointer to newly allocated
1468 memory holding the result, inside a memory pool.
1469 */
1470char *talloc_asprintf(const void *t, const char *fmt, ...)
1471{
1472 va_list ap;
1473 char *ret;
1474
1475 va_start(ap, fmt);
1476 ret = talloc_vasprintf(t, fmt, ap);
1477 va_end(ap);
1478 return ret;
1479}
1480
1481static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
1482 const char *fmt, va_list ap)
1483 PRINTF_ATTRIBUTE(3,0);
1484
1485static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
1486 const char *fmt, va_list ap)
1487{
1488 ssize_t alen;
1489 va_list ap2;
1490 char c;
1491
1492 va_copy(ap2, ap);
1493 alen = vsnprintf(&c, 1, fmt, ap2);
1494 va_end(ap2);
1495
1496 if (alen <= 0) {
1497 /* Either the vsnprintf failed or the format resulted in
1498 * no characters being formatted. In the former case, we
1499 * ought to return NULL, in the latter we ought to return
1500 * the original string. Most current callers of this
1501 * function expect it to never return NULL.
1502 */
1503 return s;
1504 }
1505
1506 s = talloc_realloc(NULL, s, char, slen + alen + 1);
1507 if (!s) return NULL;
1508
1509 va_copy(ap2, ap);
1510 vsnprintf(s + slen, alen + 1, fmt, ap2);
1511 va_end(ap2);
1512
1513 _talloc_set_name_const(s, s);
1514 return s;
1515}
1516
1517/**
1518 * Realloc @p s to append the formatted result of @p fmt and @p ap,
1519 * and return @p s, which may have moved. Good for gradually
1520 * accumulating output into a string buffer. Appends at the end
1521 * of the string.
1522 **/
1523char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1524{
1525 if (unlikely(!s)) {
1526 return talloc_vasprintf(NULL, fmt, ap);
1527 }
1528
1529 return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap);
1530}
1531
1532/**
1533 * Realloc @p s to append the formatted result of @p fmt and @p ap,
1534 * and return @p s, which may have moved. Always appends at the
1535 * end of the talloc'ed buffer, not the end of the string.
1536 **/
1537char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)
1538{
1539 size_t slen;
1540
1541 if (unlikely(!s)) {
1542 return talloc_vasprintf(NULL, fmt, ap);
1543 }
1544
1545 slen = talloc_get_size(s);
1546 if (likely(slen > 0)) {
1547 slen--;
1548 }
1549
1550 return __talloc_vaslenprintf_append(s, slen, fmt, ap);
1551}
1552
1553/*
1554 Realloc @p s to append the formatted result of @p fmt and return @p
1555 s, which may have moved. Good for gradually accumulating output
1556 into a string buffer.
1557 */
1558char *talloc_asprintf_append(char *s, const char *fmt, ...)
1559{
1560 va_list ap;
1561
1562 va_start(ap, fmt);
1563 s = talloc_vasprintf_append(s, fmt, ap);
1564 va_end(ap);
1565 return s;
1566}
1567
1568/*
1569 Realloc @p s to append the formatted result of @p fmt and return @p
1570 s, which may have moved. Good for gradually accumulating output
1571 into a buffer.
1572 */
1573char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
1574{
1575 va_list ap;
1576
1577 va_start(ap, fmt);
1578 s = talloc_vasprintf_append_buffer(s, fmt, ap);
1579 va_end(ap);
1580 return s;
1581}
1582
1583/*
1584 alloc an array, checking for integer overflow in the array size
1585*/
1586void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1587{
1588 if (count >= MAX_TALLOC_SIZE/el_size) {
1589 return NULL;
1590 }
1591 return _talloc_named_const(ctx, el_size * count, name);
1592}
1593
1594/*
1595 alloc an zero array, checking for integer overflow in the array size
1596*/
1597void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1598{
1599 if (count >= MAX_TALLOC_SIZE/el_size) {
1600 return NULL;
1601 }
1602 return _talloc_zero(ctx, el_size * count, name);
1603}
1604
1605/*
1606 realloc an array, checking for integer overflow in the array size
1607*/
1608void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
1609{
1610 if (count >= MAX_TALLOC_SIZE/el_size) {
1611 return NULL;
1612 }
1613 return _talloc_realloc(ctx, ptr, el_size * count, name);
1614}
1615
1616/*
1617 a function version of talloc_realloc(), so it can be passed as a function pointer
1618 to libraries that want a realloc function (a realloc function encapsulates
1619 all the basic capabilities of an allocation library, which is why this is useful)
1620*/
1621void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1622{
1623 return _talloc_realloc(context, ptr, size, NULL);
1624}
1625
1626
1627static int talloc_autofree_destructor(void *ptr)
1628{
1629 autofree_context = NULL;
1630 return 0;
1631}
1632
1633static void talloc_autofree(void)
1634{
1635 _talloc_free(autofree_context);
1636}
1637
1638/*
1639 return a context which will be auto-freed on exit
1640 this is useful for reducing the noise in leak reports
1641*/
1642void *talloc_autofree_context(void)
1643{
1644 if (autofree_context == NULL) {
1645 autofree_context = _talloc_named_const(NULL, 0, "autofree_context");
1646 talloc_set_destructor(autofree_context, talloc_autofree_destructor);
1647 atexit(talloc_autofree);
1648 }
1649 return autofree_context;
1650}
1651
1652size_t talloc_get_size(const void *context)
1653{
1654 struct talloc_chunk *tc;
1655
1656 if (context == NULL)
1657 return 0;
1658
1659 tc = talloc_chunk_from_ptr(context);
1660
1661 return tc->size;
1662}
1663
1664/*
1665 find a parent of this context that has the given name, if any
1666*/
1667void *talloc_find_parent_byname(const void *context, const char *name)
1668{
1669 struct talloc_chunk *tc;
1670
1671 if (context == NULL) {
1672 return NULL;
1673 }
1674
1675 tc = talloc_chunk_from_ptr(context);
1676 while (tc) {
1677 if (tc->name && strcmp(tc->name, name) == 0) {
1678 return TC_PTR_FROM_CHUNK(tc);
1679 }
1680 while (tc && tc->prev) tc = tc->prev;
1681 if (tc) {
1682 tc = tc->parent;
1683 }
1684 }
1685 return NULL;
1686}
1687
1688/*
1689 show the parentage of a context
1690*/
1691void talloc_show_parents(const void *context, FILE *file)
1692{
1693 struct talloc_chunk *tc;
1694
1695 if (context == NULL) {
1696 fprintf(file, "talloc no parents for NULL\n");
1697 return;
1698 }
1699
1700 tc = talloc_chunk_from_ptr(context);
1701 fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
1702 while (tc) {
1703 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
1704 while (tc && tc->prev) tc = tc->prev;
1705 if (tc) {
1706 tc = tc->parent;
1707 }
1708 }
1709 fflush(file);
1710}
1711
1712/*
1713 return 1 if ptr is a parent of context
1714*/
1715int talloc_is_parent(const void *context, const void *ptr)
1716{
1717 struct talloc_chunk *tc;
1718
1719 if (context == NULL) {
1720 return 0;
1721 }
1722
1723 tc = talloc_chunk_from_ptr(context);
1724 while (tc) {
1725 if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
1726 while (tc && tc->prev) tc = tc->prev;
1727 if (tc) {
1728 tc = tc->parent;
1729 }
1730 }
1731 return 0;
1732}
Note: See TracBrowser for help on using the repository browser.