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