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