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