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