source: branches/samba-3.5.x/lib/talloc/talloc.c@ 940

Last change on this file since 940 was 414, checked in by Herwig Bauernfeind, 15 years ago

Samba 3.5.0: Initial import

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