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