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