source: win32/libtalloc-2.0.1/src/talloc.c@ 266

Last change on this file since 266 was 195, checked in by tim, 15 years ago

removed talloc from mainline build tree, opting instead to depend upon libtalloc-dev

win32 builds depend up on modified libtalloc stored outside of trunk

miscellaneous other build fixes

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