]> git.ozlabs.org Git - ccan/blob - ccan/talloc/talloc.c
tdb2: tdb_expand on empty database now tested.
[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_ATTRIBUTE(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 **pptr = ptr;
805
806         *pptr = talloc_named_const(ctx, size, name);
807         if (unlikely(!*pptr))
808                 return;
809
810         child = talloc(*pptr, void **);
811         if (unlikely(!child)) {
812                 talloc_free(*pptr);
813                 *pptr = NULL;
814                 return;
815         }
816         *child = pptr;
817         talloc_set_name_const(child, "talloc_set destructor");
818         talloc_set_destructor(child, talloc_destroy_pointer);
819 }
820
821 /*
822   externally callable talloc_set_name_const()
823 */
824 void talloc_set_name_const(const void *ptr, const char *name)
825 {
826         _talloc_set_name_const(ptr, name);
827 }
828
829 /*
830   create a named talloc pointer. Any talloc pointer can be named, and
831   talloc_named() operates just like talloc() except that it allows you
832   to name the pointer.
833 */
834 void *talloc_named_const(const void *context, size_t size, const char *name)
835 {
836         void *p;
837         lock(context);
838         p = _talloc_named_const(context, size, name);
839         unlock();
840         return p;
841 }
842
843 /* 
844    free a talloc pointer. This also frees all child pointers of this 
845    pointer recursively
846
847    return 0 if the memory is actually freed, otherwise -1. The memory
848    will not be freed if the ref_count is > 1 or the destructor (if
849    any) returns non-zero
850 */
851 int talloc_free(const void *ptr)
852 {
853         int saved_errno = errno, ret;
854
855         lock(ptr);
856         ret = _talloc_free(discard_const_p(void, ptr));
857         unlock();
858         if (ret == 0)
859                 errno = saved_errno;
860         return ret;
861 }
862
863
864
865 /*
866   A talloc version of realloc. The context argument is only used if
867   ptr is NULL
868 */
869 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
870 {
871         struct talloc_chunk *tc;
872         void *new_ptr;
873
874         /* size zero is equivalent to free() */
875         if (unlikely(size == 0)) {
876                 talloc_free(ptr);
877                 return NULL;
878         }
879
880         if (unlikely(size >= MAX_TALLOC_SIZE)) {
881                 return NULL;
882         }
883
884         /* realloc(NULL) is equivalent to malloc() */
885         if (ptr == NULL) {
886                 return talloc_named_const(context, size, name);
887         }
888
889         tc = talloc_chunk_from_ptr(ptr);
890
891         /* don't allow realloc on referenced pointers */
892         if (unlikely(tc->refs)) {
893                 return NULL;
894         }
895
896         lock(ptr);
897         if (unlikely(tc->flags & TALLOC_FLAG_EXT_ALLOC)) {
898                 /* need to get parent before setting free flag. */
899                 void *parent = talloc_parent_nolock(ptr);
900                 tc->flags |= TALLOC_FLAG_FREE;
901                 new_ptr = tc_external_realloc(parent, tc, size + TC_HDR_SIZE);
902         } else {
903                 /* by resetting magic we catch users of the old memory */
904                 tc->flags |= TALLOC_FLAG_FREE;
905
906 #if ALWAYS_REALLOC
907                 new_ptr = malloc(size + TC_HDR_SIZE);
908                 if (new_ptr) {
909                         memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE);
910                         free(tc);
911                 }
912 #else
913                 new_ptr = realloc(tc, size + TC_HDR_SIZE);
914 #endif
915         }
916
917         if (unlikely(!new_ptr)) {       
918                 tc->flags &= ~TALLOC_FLAG_FREE; 
919                 unlock();
920                 return NULL; 
921         }
922
923         tc = (struct talloc_chunk *)new_ptr;
924         tc->flags &= ~TALLOC_FLAG_FREE; 
925         if (tc->parent) {
926                 tc->parent->child = tc;
927         }
928         if (tc->child) {
929                 tc->child->parent = tc;
930         }
931
932         if (tc->prev) {
933                 tc->prev->next = tc;
934         }
935         if (tc->next) {
936                 tc->next->prev = tc;
937         }
938
939         tc->size = size;
940         _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
941         unlock();
942
943         return TC_PTR_FROM_CHUNK(tc);
944 }
945
946 /*
947   a wrapper around talloc_steal() for situations where you are moving a pointer
948   between two structures, and want the old pointer to be set to NULL
949 */
950 void *_talloc_move(const void *new_ctx, const void *_pptr)
951 {
952         const void **pptr = discard_const_p(const void *,_pptr);
953         void *ret = _talloc_steal(new_ctx, *pptr);
954         (*pptr) = NULL;
955         return ret;
956 }
957
958 /*
959   return the total size of a talloc pool (subtree)
960 */
961 static size_t _talloc_total_size(const void *ptr)
962 {
963         size_t total = 0;
964         struct talloc_chunk *c, *tc;
965
966         tc = talloc_chunk_from_ptr(ptr);
967
968         if (tc->flags & TALLOC_FLAG_LOOP) {
969                 return 0;
970         }
971
972         tc->flags |= TALLOC_FLAG_LOOP;
973
974         total = tc->size;
975         for (c=tc->child;c;c=c->next) {
976                 total += _talloc_total_size(TC_PTR_FROM_CHUNK(c));
977         }
978
979         tc->flags &= ~TALLOC_FLAG_LOOP;
980
981         return total;
982 }
983
984 size_t talloc_total_size(const void *ptr)
985 {
986         size_t total;
987
988         if (ptr == NULL) {
989                 ptr = null_context;
990         }
991         if (ptr == NULL) {
992                 return 0;
993         }
994
995         lock(ptr);
996         total = _talloc_total_size(ptr);
997         unlock();
998         return total;
999 }       
1000
1001 /*
1002   return the total number of blocks in a talloc pool (subtree)
1003 */
1004 static size_t _talloc_total_blocks(const void *ptr)
1005 {
1006         size_t total = 0;
1007         struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
1008
1009         if (tc->flags & TALLOC_FLAG_LOOP) {
1010                 return 0;
1011         }
1012
1013         tc->flags |= TALLOC_FLAG_LOOP;
1014
1015         total++;
1016         for (c=tc->child;c;c=c->next) {
1017                 total += _talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
1018         }
1019
1020         tc->flags &= ~TALLOC_FLAG_LOOP;
1021
1022         return total;
1023 }
1024
1025 size_t talloc_total_blocks(const void *ptr)
1026 {
1027         size_t total;
1028
1029         lock(ptr);
1030         total = _talloc_total_blocks(ptr);
1031         unlock();
1032
1033         return total;
1034 }
1035
1036 static size_t _talloc_reference_count(const void *ptr)
1037 {
1038         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1039         struct talloc_reference_handle *h;
1040         size_t ret = 0;
1041
1042         for (h=tc->refs;h;h=h->next) {
1043                 ret++;
1044         }
1045         return ret;
1046 }
1047
1048 /*
1049   return the number of external references to a pointer
1050 */
1051 size_t talloc_reference_count(const void *ptr)
1052 {
1053         size_t ret;
1054
1055         lock(talloc_chunk_from_ptr(ptr));
1056         ret = _talloc_reference_count(ptr);
1057         unlock();
1058         return ret;
1059 }
1060
1061 /*
1062   report on memory usage by all children of a pointer, giving a full tree view
1063 */
1064 static void _talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
1065                             void (*callback)(const void *ptr,
1066                                              int depth, int max_depth,
1067                                              int is_ref,
1068                                              void *private_data),
1069                             void *private_data)
1070 {
1071         struct talloc_chunk *c, *tc;
1072
1073         tc = talloc_chunk_from_ptr(ptr);
1074
1075         if (tc->flags & TALLOC_FLAG_LOOP) {
1076                 return;
1077         }
1078
1079         callback(ptr, depth, max_depth, 0, private_data);
1080
1081         if (max_depth >= 0 && depth >= max_depth) {
1082                 return;
1083         }
1084
1085         tc->flags |= TALLOC_FLAG_LOOP;
1086         for (c=tc->child;c;c=c->next) {
1087                 if (c->name == TALLOC_MAGIC_REFERENCE) {
1088                         struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
1089                         callback(h->ptr, depth + 1, max_depth, 1, private_data);
1090                 } else {
1091                         _talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
1092                 }
1093         }
1094         tc->flags &= ~TALLOC_FLAG_LOOP;
1095 }
1096
1097 void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
1098                             void (*callback)(const void *ptr,
1099                                              int depth, int max_depth,
1100                                              int is_ref,
1101                                              void *private_data),
1102                             void *private_data)
1103 {
1104         if (ptr == NULL) {
1105                 ptr = null_context;
1106         }
1107         if (ptr == NULL) return;
1108
1109         lock(ptr);
1110         _talloc_report_depth_cb(ptr, depth, max_depth, callback, private_data);
1111         unlock();
1112 }
1113
1114 static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
1115 {
1116         const char *name = talloc_get_name(ptr);
1117         FILE *f = (FILE *)_f;
1118
1119         if (is_ref) {
1120                 fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
1121                 return;
1122         }
1123
1124         if (depth == 0) {
1125                 fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n", 
1126                         (max_depth < 0 ? "full " :""), name,
1127                         (unsigned long)_talloc_total_size(ptr),
1128                         (unsigned long)_talloc_total_blocks(ptr));
1129                 return;
1130         }
1131
1132         fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n", 
1133                 depth*4, "",
1134                 name,
1135                 (unsigned long)_talloc_total_size(ptr),
1136                 (unsigned long)_talloc_total_blocks(ptr),
1137                 (int)_talloc_reference_count(ptr), ptr);
1138
1139 #if 0
1140         fprintf(f, "content: ");
1141         if (talloc_total_size(ptr)) {
1142                 int tot = talloc_total_size(ptr);
1143                 int i;
1144
1145                 for (i = 0; i < tot; i++) {
1146                         if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
1147                                 fprintf(f, "%c", ((char *)ptr)[i]);
1148                         } else {
1149                                 fprintf(f, "~%02x", ((char *)ptr)[i]);
1150                         }
1151                 }
1152         }
1153         fprintf(f, "\n");
1154 #endif
1155 }
1156
1157 /*
1158   report on memory usage by all children of a pointer, giving a full tree view
1159 */
1160 void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
1161 {
1162         talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
1163         fflush(f);
1164 }
1165
1166 /*
1167   report on memory usage by all children of a pointer, giving a full tree view
1168 */
1169 void talloc_report_full(const void *ptr, FILE *f)
1170 {
1171         talloc_report_depth_file(ptr, 0, -1, f);
1172 }
1173
1174 /*
1175   report on memory usage by all children of a pointer
1176 */
1177 void talloc_report(const void *ptr, FILE *f)
1178 {
1179         talloc_report_depth_file(ptr, 0, 1, f);
1180 }
1181
1182 /*
1183   report on any memory hanging off the null context
1184 */
1185 static void talloc_report_null(void)
1186 {
1187         if (talloc_total_size(null_context) != 0) {
1188                 talloc_report(null_context, stderr);
1189         }
1190 }
1191
1192 /*
1193   report on any memory hanging off the null context
1194 */
1195 static void talloc_report_null_full(void)
1196 {
1197         if (talloc_total_size(null_context) != 0) {
1198                 talloc_report_full(null_context, stderr);
1199         }
1200 }
1201
1202 /*
1203   enable tracking of the NULL context
1204 */
1205 void talloc_enable_null_tracking(void)
1206 {
1207         if (null_context == NULL) {
1208                 null_context = _talloc_named_const(NULL, 0, "null_context");
1209         }
1210 }
1211
1212 /*
1213   disable tracking of the NULL context
1214 */
1215 void talloc_disable_null_tracking(void)
1216 {
1217         _talloc_free(null_context);
1218         null_context = NULL;
1219 }
1220
1221 /*
1222   enable leak reporting on exit
1223 */
1224 void talloc_enable_leak_report(void)
1225 {
1226         talloc_enable_null_tracking();
1227         atexit(talloc_report_null);
1228 }
1229
1230 /*
1231   enable full leak reporting on exit
1232 */
1233 void talloc_enable_leak_report_full(void)
1234 {
1235         talloc_enable_null_tracking();
1236         atexit(talloc_report_null_full);
1237 }
1238
1239 /* 
1240    talloc and zero memory. 
1241 */
1242 void *_talloc_zero(const void *ctx, size_t size, const char *name)
1243 {
1244         void *p;
1245
1246         lock(ctx);
1247         p = _talloc_named_const(ctx, size, name);
1248         unlock();
1249
1250         if (p) {
1251                 memset(p, '\0', size);
1252         }
1253
1254         return p;
1255 }
1256
1257 /*
1258   memdup with a talloc. 
1259 */
1260 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
1261 {
1262         void *newp;
1263
1264         lock(t);
1265         newp = _talloc_named_const(t, size, name);
1266         unlock();
1267
1268         if (likely(newp)) {
1269                 memcpy(newp, p, size);
1270         }
1271
1272         return newp;
1273 }
1274
1275 /*
1276   strdup with a talloc 
1277 */
1278 char *talloc_strdup(const void *t, const char *p)
1279 {
1280         char *ret;
1281         if (!p) {
1282                 return NULL;
1283         }
1284         ret = (char *)talloc_memdup(t, p, strlen(p) + 1);
1285         if (likely(ret)) {
1286                 _talloc_set_name_const(ret, ret);
1287         }
1288         return ret;
1289 }
1290
1291 /*
1292  append to a talloced string 
1293 */
1294 char *talloc_append_string(char *orig, const char *append)
1295 {
1296         char *ret;
1297         size_t olen = strlen(orig);
1298         size_t alenz;
1299
1300         if (!append)
1301                 return orig;
1302
1303         alenz = strlen(append) + 1;
1304
1305         ret = talloc_realloc(NULL, orig, char, olen + alenz);
1306         if (!ret)
1307                 return NULL;
1308
1309         /* append the string with the trailing \0 */
1310         memcpy(&ret[olen], append, alenz);
1311
1312         _talloc_set_name_const(ret, ret);
1313
1314         return ret;
1315 }
1316
1317 /*
1318   strndup with a talloc 
1319 */
1320 char *talloc_strndup(const void *t, const char *p, size_t n)
1321 {
1322         size_t len;
1323         char *ret;
1324
1325         for (len=0; len<n && p[len]; len++) ;
1326
1327         lock(t);
1328         ret = (char *)__talloc(t, len + 1);
1329         unlock();
1330         if (!ret) { return NULL; }
1331         memcpy(ret, p, len);
1332         ret[len] = 0;
1333         _talloc_set_name_const(ret, ret);
1334         return ret;
1335 }
1336
1337 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
1338 {       
1339         int len;
1340         char *ret;
1341         va_list ap2;
1342         char c;
1343         
1344         /* this call looks strange, but it makes it work on older solaris boxes */
1345         va_copy(ap2, ap);
1346         len = vsnprintf(&c, 1, fmt, ap2);
1347         va_end(ap2);
1348         if (len < 0) {
1349                 return NULL;
1350         }
1351
1352         lock(t);
1353         ret = (char *)__talloc(t, len+1);
1354         unlock();
1355         if (ret) {
1356                 va_copy(ap2, ap);
1357                 vsnprintf(ret, len+1, fmt, ap2);
1358                 va_end(ap2);
1359                 _talloc_set_name_const(ret, ret);
1360         }
1361
1362         return ret;
1363 }
1364
1365
1366 /*
1367   Perform string formatting, and return a pointer to newly allocated
1368   memory holding the result, inside a memory pool.
1369  */
1370 char *talloc_asprintf(const void *t, const char *fmt, ...)
1371 {
1372         va_list ap;
1373         char *ret;
1374
1375         va_start(ap, fmt);
1376         ret = talloc_vasprintf(t, fmt, ap);
1377         va_end(ap);
1378         return ret;
1379 }
1380
1381
1382 /**
1383  * Realloc @p s to append the formatted result of @p fmt and @p ap,
1384  * and return @p s, which may have moved.  Good for gradually
1385  * accumulating output into a string buffer.
1386  **/
1387 char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1388 {       
1389         struct talloc_chunk *tc;
1390         int len, s_len;
1391         va_list ap2;
1392         char c;
1393
1394         if (s == NULL) {
1395                 return talloc_vasprintf(NULL, fmt, ap);
1396         }
1397
1398         tc = talloc_chunk_from_ptr(s);
1399
1400         s_len = tc->size - 1;
1401
1402         va_copy(ap2, ap);
1403         len = vsnprintf(&c, 1, fmt, ap2);
1404         va_end(ap2);
1405
1406         if (len <= 0) {
1407                 /* Either the vsnprintf failed or the format resulted in
1408                  * no characters being formatted. In the former case, we
1409                  * ought to return NULL, in the latter we ought to return
1410                  * the original string. Most current callers of this 
1411                  * function expect it to never return NULL.
1412                  */
1413                 return s;
1414         }
1415
1416         s = talloc_realloc(NULL, s, char, s_len + len+1);
1417         if (!s) return NULL;
1418
1419         va_copy(ap2, ap);
1420         vsnprintf(s+s_len, len+1, fmt, ap2);
1421         va_end(ap2);
1422         _talloc_set_name_const(s, s);
1423
1424         return s;
1425 }
1426
1427 /*
1428   Realloc @p s to append the formatted result of @p fmt and return @p
1429   s, which may have moved.  Good for gradually accumulating output
1430   into a string buffer.
1431  */
1432 char *talloc_asprintf_append(char *s, const char *fmt, ...)
1433 {
1434         va_list ap;
1435
1436         va_start(ap, fmt);
1437         s = talloc_vasprintf_append(s, fmt, ap);
1438         va_end(ap);
1439         return s;
1440 }
1441
1442 /*
1443   alloc an array, checking for integer overflow in the array size
1444 */
1445 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1446 {
1447         void *p;
1448
1449         if (count >= MAX_TALLOC_SIZE/el_size) {
1450                 return NULL;
1451         }
1452         lock(ctx);
1453         p = _talloc_named_const(ctx, el_size * count, name);
1454         unlock();
1455         return p;
1456 }
1457
1458 /*
1459   alloc an zero array, checking for integer overflow in the array size
1460 */
1461 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1462 {
1463         void *p;
1464
1465         if (count >= MAX_TALLOC_SIZE/el_size) {
1466                 return NULL;
1467         }
1468         p = _talloc_zero(ctx, el_size * count, name);
1469         return p;
1470 }
1471
1472 /*
1473   realloc an array, checking for integer overflow in the array size
1474 */
1475 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
1476 {
1477         if (count >= MAX_TALLOC_SIZE/el_size) {
1478                 return NULL;
1479         }
1480         return _talloc_realloc(ctx, ptr, el_size * count, name);
1481 }
1482
1483 /*
1484   a function version of talloc_realloc(), so it can be passed as a function pointer
1485   to libraries that want a realloc function (a realloc function encapsulates
1486   all the basic capabilities of an allocation library, which is why this is useful)
1487 */
1488 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1489 {
1490         return _talloc_realloc(context, ptr, size, NULL);
1491 }
1492
1493
1494 static int talloc_autofree_destructor(void *ptr)
1495 {
1496         autofree_context = NULL;
1497         return 0;
1498 }
1499
1500 static void talloc_autofree(void)
1501 {
1502         if (autofree_context && *autofree_context == getpid())
1503                 talloc_free(autofree_context);
1504 }
1505
1506 /*
1507   return a context which will be auto-freed on exit
1508   this is useful for reducing the noise in leak reports
1509 */
1510 void *talloc_autofree_context(void)
1511 {
1512         if (autofree_context == NULL || *autofree_context != getpid()) {
1513                 autofree_context = talloc(NULL, pid_t);
1514                 *autofree_context = getpid();
1515                 talloc_set_name_const(autofree_context, "autofree_context");
1516                 
1517                 talloc_set_destructor(autofree_context, talloc_autofree_destructor);
1518                 atexit(talloc_autofree);
1519         }
1520         return autofree_context;
1521 }
1522
1523 size_t talloc_get_size(const void *context)
1524 {
1525         struct talloc_chunk *tc;
1526
1527         if (context == NULL)
1528                 return 0;
1529
1530         tc = talloc_chunk_from_ptr(context);
1531
1532         return tc->size;
1533 }
1534
1535 /*
1536   find a parent of this context that has the given name, if any
1537 */
1538 void *talloc_find_parent_byname(const void *context, const char *name)
1539 {
1540         struct talloc_chunk *tc;
1541
1542         if (context == NULL) {
1543                 return NULL;
1544         }
1545
1546         lock(context);
1547         tc = talloc_chunk_from_ptr(context);
1548         while (tc) {
1549                 if (tc->name && strcmp(tc->name, name) == 0) {
1550                         unlock();
1551                         return TC_PTR_FROM_CHUNK(tc);
1552                 }
1553                 while (tc && tc->prev) tc = tc->prev;
1554                 if (tc) {
1555                         tc = tc->parent;
1556                 }
1557         }
1558         unlock();
1559         return NULL;
1560 }
1561
1562 /*
1563   show the parentage of a context
1564 */
1565 void talloc_show_parents(const void *context, FILE *file)
1566 {
1567         struct talloc_chunk *tc;
1568
1569         if (context == NULL) {
1570                 fprintf(file, "talloc no parents for NULL\n");
1571                 return;
1572         }
1573
1574         lock(context);
1575         tc = talloc_chunk_from_ptr(context);
1576         fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
1577         while (tc) {
1578                 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
1579                 while (tc && tc->prev) tc = tc->prev;
1580                 if (tc) {
1581                         tc = tc->parent;
1582                 }
1583         }
1584         unlock();
1585         fflush(file);
1586 }
1587
1588 int talloc_is_parent(const void *context, const void *ptr)
1589 {
1590         int ret;
1591         lock(context);
1592         ret = _talloc_is_parent(context, ptr);
1593         unlock();
1594         return ret;
1595 }
1596
1597 void *talloc_add_external(const void *ctx,
1598                           void *(*realloc)(const void *, void *, size_t),
1599                           void (*lock)(const void *p),
1600                           void (*unlock)(void))
1601 {
1602         struct talloc_chunk *tc, *parent;
1603         void *p;
1604
1605         if (tc_external_realloc && tc_external_realloc != realloc)
1606                 TALLOC_ABORT("talloc_add_external realloc replaced");
1607         tc_external_realloc = realloc;
1608
1609         if (unlikely(ctx == NULL)) {
1610                 ctx = null_context;
1611                 parent = NULL;
1612         } else
1613                 parent = talloc_chunk_from_ptr(ctx);    
1614
1615         tc = tc_external_realloc(ctx, NULL, TC_HDR_SIZE);
1616         p = init_talloc(parent, tc, 0, 1);
1617         tc_lock = lock;
1618         tc_unlock = unlock;
1619
1620         return p;
1621 }