Add PS3 timeout option
[petitboot] / lib / 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
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 /*
26   inspired by http://swapped.cc/halloc/
27 */
28
29
30 #include "config.h"
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 /* nfsim additions */
37 #define HAVE_SYS_TYPES_H
38 #define HAVE_UNISTD_H
39 #define HAVE_STDARG_H
40 #define HAVE_STDINT_H
41 #define HAVE_VA_COPY
42
43 #ifdef HAVE_SYS_TYPES_H
44 #include <sys/types.h>
45 #endif
46
47 #ifdef HAVE_UNISTD_H
48 #include <unistd.h>
49 #endif
50
51 #ifdef HAVE_STDARG_H
52 #include <stdarg.h>
53 #else
54 #include <varargs.h>
55 #endif
56
57 #ifdef HAVE_STDINT_H
58 #include <stdint.h>
59 #endif
60
61 #include "talloc.h"
62
63 /* use this to force every realloc to change the pointer, to stress test
64    code that might not cope */
65 #define ALWAYS_REALLOC 0
66
67
68 #define MAX_TALLOC_SIZE 0x10000000
69 #define TALLOC_MAGIC 0xe814ec4f
70 #define TALLOC_MAGIC_FREE 0x7faebef3
71 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
72
73 /* by default we abort when given a bad pointer (such as when talloc_free() is
74  * called on a pointer that came from malloc() */
75 #ifndef TALLOC_ABORT
76 #define TALLOC_ABORT(reason) abort()
77 #endif
78
79 #ifndef discard_const_p
80 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
81 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
82 #else
83 # define discard_const_p(type, ptr) ((type *)(ptr))
84 #endif
85 #endif
86
87 /* this null_context is only used if talloc_enable_leak_report() or
88    talloc_enable_leak_report_full() is called, otherwise it remains
89    NULL
90 */
91 static const void *null_context;
92 static void *cleanup_context;
93
94
95 struct talloc_reference_handle {
96         struct talloc_reference_handle *next, *prev;
97         void *ptr;
98 };
99
100 typedef int (*talloc_destructor_t)(void *);
101
102 struct talloc_chunk {
103         struct talloc_chunk *next, *prev;
104         struct talloc_chunk *parent, *child;
105         struct talloc_reference_handle *refs;
106         size_t size;
107         talloc_destructor_t destructor;
108         const char *name;
109         union {
110                 unsigned magic;
111                 double align_dummy;
112         } u;
113 };
114
115 /* panic if we get a bad magic value */
116 static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
117 {
118         struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1;
119         if (tc->u.magic != TALLOC_MAGIC) {
120                 if (tc->u.magic == TALLOC_MAGIC_FREE) {
121                         TALLOC_ABORT("Bad talloc magic value - double free");
122                 } else {
123                         TALLOC_ABORT("Bad talloc magic value - unknown value");
124                 }
125         }
126
127         return tc;
128 }
129
130 /* hook into the front of the list */
131 #define _TLIST_ADD(list, p) \
132 do { \
133         if (!(list)) { \
134                 (list) = (p); \
135                 (p)->next = (p)->prev = NULL; \
136         } else { \
137                 (list)->prev = (p); \
138                 (p)->next = (list); \
139                 (p)->prev = NULL; \
140                 (list) = (p); \
141         }\
142 } while (0)
143
144 /* remove an element from a list - element doesn't have to be in list. */
145 #define _TLIST_REMOVE(list, p) \
146 do { \
147         if ((p) == (list)) { \
148                 (list) = (p)->next; \
149                 if (list) (list)->prev = NULL; \
150         } else { \
151                 if ((p)->prev) (p)->prev->next = (p)->next; \
152                 if ((p)->next) (p)->next->prev = (p)->prev; \
153         } \
154         if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
155 } while (0)
156
157
158 /*
159   return the parent chunk of a pointer
160 */
161 static struct talloc_chunk *talloc_parent_chunk(const void *ptr)
162 {
163         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
164         while (tc->prev) tc=tc->prev;
165         return tc->parent;
166 }
167
168 void *talloc_parent(const void *ptr)
169 {
170         struct talloc_chunk *tc = talloc_parent_chunk(ptr);
171         return (void *)(tc+1);
172 }
173
174 /*
175    Allocate a bit of memory as a child of an existing pointer
176 */
177 void *_talloc(const void *context, size_t size)
178 {
179         struct talloc_chunk *tc;
180
181         if (context == NULL) {
182                 context = null_context;
183         }
184
185         if (size >= MAX_TALLOC_SIZE) {
186                 return NULL;
187         }
188
189         tc = malloc(sizeof(*tc)+size);
190         if (tc == NULL) return NULL;
191
192         tc->size = size;
193         tc->u.magic = TALLOC_MAGIC;
194         tc->destructor = NULL;
195         tc->child = NULL;
196         tc->name = NULL;
197         tc->refs = NULL;
198
199         if (context) {
200                 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
201
202                 tc->parent = parent;
203
204                 if (parent->child) {
205                         parent->child->parent = NULL;
206                 }
207
208                 _TLIST_ADD(parent->child, tc);
209         } else {
210                 tc->next = tc->prev = tc->parent = NULL;
211         }
212
213         return (void *)(tc+1);
214 }
215
216
217 /*
218   setup a destructor to be called on free of a pointer
219   the destructor should return 0 on success, or -1 on failure.
220   if the destructor fails then the free is failed, and the memory can
221   be continued to be used
222 */
223 void talloc_set_destructor(const void *ptr, int (*destructor)(void *))
224 {
225         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
226         tc->destructor = destructor;
227 }
228
229 /*
230   increase the reference count on a piece of memory.
231 */
232 void talloc_increase_ref_count(const void *ptr)
233 {
234         talloc_reference(null_context, ptr);
235 }
236
237 /*
238   helper for talloc_reference()
239 */
240 static int talloc_reference_destructor(void *ptr)
241 {
242         struct talloc_reference_handle *handle = ptr;
243         struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr);
244         struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr);
245         if (tc1->destructor != (talloc_destructor_t)-1) {
246                 tc1->destructor = NULL;
247         }
248         _TLIST_REMOVE(tc2->refs, handle);
249         talloc_free(handle);
250         return 0;
251 }
252
253 /*
254   make a secondary reference to a pointer, hanging off the given context.
255   the pointer remains valid until both the original caller and this given
256   context are freed.
257
258   the major use for this is when two different structures need to reference the
259   same underlying data, and you want to be able to free the two instances
260   separately, and in either order
261 */
262 void *talloc_reference(const void *context, const void *ptr)
263 {
264         struct talloc_chunk *tc;
265         struct talloc_reference_handle *handle;
266         if (ptr == NULL) return NULL;
267
268         tc = talloc_chunk_from_ptr(ptr);
269         handle = talloc_named_const(context, sizeof(*handle),
270                         TALLOC_MAGIC_REFERENCE);
271
272         if (handle == NULL) return NULL;
273
274         /* note that we hang the destructor off the handle, not the
275            main context as that allows the caller to still setup their
276            own destructor on the context if they want to */
277         talloc_set_destructor(handle, talloc_reference_destructor);
278         handle->ptr = discard_const_p(void, ptr);
279         _TLIST_ADD(tc->refs, handle);
280         return handle->ptr;
281 }
282
283 /*
284   remove a secondary reference to a pointer. This undo's what
285   talloc_reference() has done. The context and pointer arguments
286   must match those given to a talloc_reference()
287 */
288 static int talloc_unreference(const void *context, const void *ptr)
289 {
290         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
291         struct talloc_reference_handle *h;
292
293         if (context == NULL) {
294                 context = null_context;
295         }
296
297         for (h=tc->refs;h;h=h->next) {
298                 struct talloc_chunk *p = talloc_parent_chunk(h);
299                 if ((p==NULL && context==NULL) || p+1 == context) break;
300         }
301         if (h == NULL) {
302                 return -1;
303         }
304
305         talloc_set_destructor(h, NULL);
306         _TLIST_REMOVE(tc->refs, h);
307         talloc_free(h);
308         return 0;
309 }
310
311 /*
312   remove a specific parent context from a pointer. This is a more
313   controlled varient of talloc_free()
314 */
315 int talloc_unlink(const void *context, void *ptr)
316 {
317         struct talloc_chunk *tc_p, *new_p;
318         void *new_parent;
319
320         if (ptr == NULL) {
321                 return -1;
322         }
323
324         if (context == NULL) {
325                 context = null_context;
326         }
327
328         if (talloc_unreference(context, ptr) == 0) {
329                 return 0;
330         }
331
332         if (context == NULL) {
333                 if (talloc_parent_chunk(ptr) != NULL) {
334                         return -1;
335                 }
336         } else {
337                 if (talloc_chunk_from_ptr(context)
338                                 != talloc_parent_chunk(ptr)) {
339                         return -1;
340                 }
341         }
342
343         tc_p = talloc_chunk_from_ptr(ptr);
344
345         if (tc_p->refs == NULL) {
346                 return talloc_free(ptr);
347         }
348
349         new_p = talloc_parent_chunk(tc_p->refs);
350         if (new_p) {
351                 new_parent = new_p+1;
352         } else {
353                 new_parent = NULL;
354         }
355
356         if (talloc_unreference(new_parent, ptr) != 0) {
357                 return -1;
358         }
359
360         talloc_steal(new_parent, ptr);
361
362         return 0;
363 }
364
365 /*
366   add a name to an existing pointer - va_list version
367 */
368 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
369         PRINTF_ATTRIBUTE(2,0);
370
371 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
372 {
373         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
374         tc->name = talloc_vasprintf(ptr, fmt, ap);
375         if (tc->name) {
376                 talloc_set_name_const(tc->name, ".name");
377         }
378 }
379
380 /*
381   add a name to an existing pointer
382 */
383 void talloc_set_name(const void *ptr, const char *fmt, ...)
384 {
385         va_list ap;
386         va_start(ap, fmt);
387         talloc_set_name_v(ptr, fmt, ap);
388         va_end(ap);
389 }
390
391 /*
392    more efficient way to add a name to a pointer - the name must point to a
393    true string constant
394 */
395 void talloc_set_name_const(const void *ptr, const char *name)
396 {
397         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
398         tc->name = name;
399 }
400
401 /*
402   create a named talloc pointer. Any talloc pointer can be named, and
403   talloc_named() operates just like talloc() except that it allows you
404   to name the pointer.
405 */
406 void *talloc_named(const void *context, size_t size, const char *fmt, ...)
407 {
408         va_list ap;
409         void *ptr;
410
411         ptr = _talloc(context, size);
412         if (ptr == NULL) return NULL;
413
414         va_start(ap, fmt);
415         talloc_set_name_v(ptr, fmt, ap);
416         va_end(ap);
417
418         return ptr;
419 }
420
421 /*
422   create a named talloc pointer. Any talloc pointer can be named, and
423   talloc_named() operates just like talloc() except that it allows you
424   to name the pointer.
425 */
426 void *talloc_named_const(const void *context, size_t size, const char *name)
427 {
428         void *ptr;
429
430         ptr = _talloc(context, size);
431         if (ptr == NULL) {
432                 return NULL;
433         }
434
435         talloc_set_name_const(ptr, name);
436
437         return ptr;
438 }
439
440 /*
441   return the name of a talloc ptr, or "UNNAMED"
442 */
443 const char *talloc_get_name(const void *ptr)
444 {
445         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
446         if (tc->name == TALLOC_MAGIC_REFERENCE) {
447                 return ".reference";
448         }
449         if (tc->name) {
450                 return tc->name;
451         }
452         return "UNNAMED";
453 }
454
455
456 /*
457   check if a pointer has the given name. If it does, return the pointer,
458   otherwise return NULL
459 */
460 void *talloc_check_name(const void *ptr, const char *name)
461 {
462         const char *pname;
463         if (ptr == NULL) return NULL;
464         pname = talloc_get_name(ptr);
465         if (pname == name || strcmp(pname, name) == 0) {
466                 return discard_const_p(void, ptr);
467         }
468         return NULL;
469 }
470
471
472 /*
473   this is for compatibility with older versions of talloc
474 */
475 void *talloc_init(const char *fmt, ...)
476 {
477         va_list ap;
478         void *ptr;
479
480         ptr = _talloc(NULL, 0);
481         if (ptr == NULL) return NULL;
482
483         va_start(ap, fmt);
484         talloc_set_name_v(ptr, fmt, ap);
485         va_end(ap);
486
487         return ptr;
488 }
489
490 /*
491   this is a replacement for the Samba3 talloc_destroy_pool functionality. It
492   should probably not be used in new code. It's in here to keep the talloc
493   code consistent across Samba 3 and 4.
494 */
495 static void talloc_free_children(void *ptr)
496 {
497         struct talloc_chunk *tc;
498
499         if (ptr == NULL) {
500                 return;
501         }
502
503         tc = talloc_chunk_from_ptr(ptr);
504
505         while (tc->child) {
506                 /* we need to work out who will own an abandoned child
507                    if it cannot be freed. In priority order, the first
508                    choice is owner of any remaining reference to this
509                    pointer, the second choice is our parent, and the
510                    final choice is the null context. */
511                 void *child = tc->child+1;
512                 const void *new_parent = null_context;
513                 if (tc->child->refs) {
514                         struct talloc_chunk *p =
515                                 talloc_parent_chunk(tc->child->refs);
516                         if (p) new_parent = p+1;
517                 }
518                 if (talloc_free(child) == -1) {
519                         if (new_parent == null_context) {
520                                 struct talloc_chunk *p =
521                                         talloc_parent_chunk(ptr);
522                                 if (p) new_parent = p+1;
523                         }
524                         talloc_steal(new_parent, child);
525                 }
526         }
527 }
528
529 /*
530    free a talloc pointer. This also frees all child pointers of this
531    pointer recursively
532
533    return 0 if the memory is actually freed, otherwise -1. The memory
534    will not be freed if the ref_count is > 1 or the destructor (if
535    any) returns non-zero
536 */
537 int talloc_free(void *ptr)
538 {
539         struct talloc_chunk *tc;
540
541         if (ptr == NULL) {
542                 return -1;
543         }
544
545         tc = talloc_chunk_from_ptr(ptr);
546
547         if (tc->refs) {
548                 talloc_reference_destructor(tc->refs);
549                 return -1;
550         }
551
552         if (tc->destructor) {
553                 talloc_destructor_t d = tc->destructor;
554                 if (d == (talloc_destructor_t)-1) {
555                         return -1;
556                 }
557                 tc->destructor = (talloc_destructor_t)-1;
558                 if (d(ptr) == -1) {
559                         tc->destructor = d;
560                         return -1;
561                 }
562                 tc->destructor = NULL;
563         }
564
565         talloc_free_children(ptr);
566
567         if (tc->parent) {
568                 _TLIST_REMOVE(tc->parent->child, tc);
569                 if (tc->parent->child) {
570                         tc->parent->child->parent = tc->parent;
571                 }
572         } else {
573                 if (tc->prev) tc->prev->next = tc->next;
574                 if (tc->next) tc->next->prev = tc->prev;
575         }
576
577         tc->u.magic = TALLOC_MAGIC_FREE;
578
579         free(tc);
580         return 0;
581 }
582
583
584
585 /*
586   A talloc version of realloc. The context argument is only used if
587   ptr is NULL
588 */
589 void *_talloc_realloc(const void *context, void *ptr, size_t size,
590                 const char *name)
591 {
592         struct talloc_chunk *tc;
593         void *new_ptr;
594
595         /* size zero is equivalent to free() */
596         if (size == 0) {
597                 talloc_free(ptr);
598                 return NULL;
599         }
600
601         if (size >= MAX_TALLOC_SIZE) {
602                 return NULL;
603         }
604
605         /* realloc(NULL) is equavalent to malloc() */
606         if (ptr == NULL) {
607                 return talloc_named_const(context, size, name);
608         }
609
610         tc = talloc_chunk_from_ptr(ptr);
611
612         /* don't allow realloc on referenced pointers */
613         if (tc->refs) {
614                 return NULL;
615         }
616
617         /* by resetting magic we catch users of the old memory */
618         tc->u.magic = TALLOC_MAGIC_FREE;
619
620 #if ALWAYS_REALLOC
621         new_ptr = malloc(size + sizeof(*tc));
622         if (new_ptr) {
623                 memcpy(new_ptr, tc, tc->size + sizeof(*tc));
624                 free(tc);
625         }
626 #else
627         new_ptr = realloc(tc, size + sizeof(*tc));
628 #endif
629         if (!new_ptr) {
630                 tc->u.magic = TALLOC_MAGIC;
631                 return NULL;
632         }
633
634         tc = new_ptr;
635         tc->u.magic = TALLOC_MAGIC;
636         if (tc->parent) {
637                 tc->parent->child = new_ptr;
638         }
639         if (tc->child) {
640                 tc->child->parent = new_ptr;
641         }
642
643         if (tc->prev) {
644                 tc->prev->next = tc;
645         }
646         if (tc->next) {
647                 tc->next->prev = tc;
648         }
649
650         tc->size = size;
651         talloc_set_name_const(tc+1, name);
652
653         return (void *)(tc+1);
654 }
655
656 /*
657    move a lump of memory from one talloc context to another return the
658    ptr on success, or NULL if it could not be transferred.
659    passing NULL as ptr will always return NULL with no side effects.
660 */
661 void *talloc_steal(const void *new_ctx, const void *ptr)
662 {
663         struct talloc_chunk *tc, *new_tc;
664
665         if (!ptr) {
666                 return NULL;
667         }
668
669         if (new_ctx == NULL) {
670                 new_ctx = null_context;
671         }
672
673         tc = talloc_chunk_from_ptr(ptr);
674
675         if (new_ctx == NULL) {
676                 if (tc->parent) {
677                         _TLIST_REMOVE(tc->parent->child, tc);
678                         if (tc->parent->child) {
679                                 tc->parent->child->parent = tc->parent;
680                         }
681                 } else {
682                         if (tc->prev) tc->prev->next = tc->next;
683                         if (tc->next) tc->next->prev = tc->prev;
684                 }
685
686                 tc->parent = tc->next = tc->prev = NULL;
687                 return discard_const_p(void, ptr);
688         }
689
690         new_tc = talloc_chunk_from_ptr(new_ctx);
691
692         if (tc == new_tc) {
693                 return discard_const_p(void, ptr);
694         }
695
696         if (tc->parent) {
697                 _TLIST_REMOVE(tc->parent->child, tc);
698                 if (tc->parent->child) {
699                         tc->parent->child->parent = tc->parent;
700                 }
701         } else {
702                 if (tc->prev) tc->prev->next = tc->next;
703                 if (tc->next) tc->next->prev = tc->prev;
704         }
705
706         tc->parent = new_tc;
707         if (new_tc->child) new_tc->child->parent = NULL;
708         _TLIST_ADD(new_tc->child, tc);
709
710         return discard_const_p(void, ptr);
711 }
712
713 /*
714   return the total size of a talloc pool (subtree)
715 */
716 off_t talloc_total_size(const void *ptr)
717 {
718         off_t total = 0;
719         struct talloc_chunk *c, *tc;
720
721         if (ptr == NULL) {
722                 ptr = null_context;
723         }
724         if (ptr == NULL) {
725                 return 0;
726         }
727
728         tc = talloc_chunk_from_ptr(ptr);
729
730         total = tc->size;
731         for (c=tc->child;c;c=c->next) {
732                 total += talloc_total_size(c+1);
733         }
734         return total;
735 }
736
737 /*
738   return the total number of blocks in a talloc pool (subtree)
739 */
740 off_t talloc_total_blocks(const void *ptr)
741 {
742         off_t total = 0;
743         struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
744
745         total++;
746         for (c=tc->child;c;c=c->next) {
747                 total += talloc_total_blocks(c+1);
748         }
749         return total;
750 }
751
752 /*
753   return the number of external references to a pointer
754 */
755 static int talloc_reference_count(const void *ptr)
756 {
757         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
758         struct talloc_reference_handle *h;
759         int ret = 0;
760
761         for (h=tc->refs;h;h=h->next) {
762                 ret++;
763         }
764         return ret;
765 }
766
767 /*
768   report on memory usage by all children of a pointer, giving a full tree view
769 */
770 void talloc_report_depth(const void *ptr, FILE *f, int depth)
771 {
772         struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
773
774         for (c=tc->child;c;c=c->next) {
775                 if (c->name == TALLOC_MAGIC_REFERENCE) {
776                         struct talloc_reference_handle *handle = (void *)(c+1);
777                         const char *name2 = talloc_get_name(handle->ptr);
778                         fprintf(f, "%*sreference to: %s\n", depth*4, "", name2);
779                 } else {
780                         const char *name = talloc_get_name(c+1);
781                         fprintf(f, "%*s%-30s contains %6lu bytes "
782                                         "in %3lu blocks (ref %d)\n",
783                                 depth * 4, "", name,
784                                 (unsigned long)talloc_total_size(c+1),
785                                 (unsigned long)talloc_total_blocks(c+1),
786                                 talloc_reference_count(c+1));
787                         talloc_report_depth(c+1, f, depth+1);
788                 }
789         }
790
791 }
792
793 /*
794   report on memory usage by all children of a pointer, giving a full tree view
795 */
796 void talloc_report_full(const void *ptr, FILE *f)
797 {
798         if (ptr == NULL) {
799                 ptr = null_context;
800         }
801         if (ptr == NULL) return;
802
803         fprintf(f, "full talloc report on '%s' "
804                         "(total %lu bytes in %lu blocks)\n",
805                 talloc_get_name(ptr),
806                 (unsigned long)talloc_total_size(ptr),
807                 (unsigned long)talloc_total_blocks(ptr));
808
809         talloc_report_depth(ptr, f, 1);
810         fflush(f);
811 }
812
813 /*
814   report on memory usage by all children of a pointer
815 */
816 void talloc_report(const void *ptr, FILE *f)
817 {
818         struct talloc_chunk *c, *tc;
819
820         if (ptr == NULL) {
821                 ptr = null_context;
822         }
823         if (ptr == NULL) return;
824
825         fprintf(f, "talloc report on '%s' (total %lu bytes in %lu blocks)\n",
826                 talloc_get_name(ptr),
827                 (unsigned long)talloc_total_size(ptr),
828                 (unsigned long)talloc_total_blocks(ptr));
829
830         tc = talloc_chunk_from_ptr(ptr);
831
832         for (c=tc->child;c;c=c->next) {
833                 fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n",
834                         talloc_get_name(c+1),
835                         (unsigned long)talloc_total_size(c+1),
836                         (unsigned long)talloc_total_blocks(c+1));
837         }
838         fflush(f);
839 }
840
841 /*
842   report on any memory hanging off the null context
843 */
844 static void talloc_report_null(void)
845 {
846         if (talloc_total_size(null_context) != 0) {
847                 talloc_report(null_context, stderr);
848         }
849 }
850
851 /*
852   report on any memory hanging off the null context
853 */
854 static void talloc_report_null_full(void)
855 {
856         if (talloc_total_size(null_context) != 0) {
857                 talloc_report_full(null_context, stderr);
858         }
859 }
860
861 /*
862   enable tracking of the NULL context
863 */
864 void talloc_enable_null_tracking(void)
865 {
866         if (null_context == NULL) {
867                 null_context = talloc_named_const(NULL, 0, "null_context");
868         }
869 }
870
871 /*
872   enable leak reporting on exit
873 */
874 void talloc_enable_leak_report(void)
875 {
876         talloc_enable_null_tracking();
877         atexit(talloc_report_null);
878 }
879
880 /*
881   enable full leak reporting on exit
882 */
883 void talloc_enable_leak_report_full(void)
884 {
885         talloc_enable_null_tracking();
886         atexit(talloc_report_null_full);
887 }
888
889 /*
890    talloc and zero memory.
891 */
892 void *_talloc_zero(const void *ctx, size_t size, const char *name)
893 {
894         void *p = talloc_named_const(ctx, size, name);
895
896         if (p) {
897                 memset(p, '\0', size);
898         }
899
900         return p;
901 }
902
903
904 /*
905   memdup with a talloc.
906 */
907 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
908 {
909         void *newp = talloc_named_const(t, size, name);
910
911         if (newp) {
912                 memcpy(newp, p, size);
913         }
914
915         return newp;
916 }
917
918 /*
919   strdup with a talloc
920 */
921 char *talloc_strdup(const void *t, const char *p)
922 {
923         char *ret;
924         if (!p) {
925                 return NULL;
926         }
927         ret = talloc_memdup(t, p, strlen(p) + 1);
928         if (ret) {
929                 talloc_set_name_const(ret, ret);
930         }
931         return ret;
932 }
933
934 /*
935   strndup with a talloc
936 */
937 char *talloc_strndup(const void *t, const char *p, size_t n)
938 {
939         size_t len;
940         char *ret;
941
942         for (len=0; len<n && p[len]; len++) ;
943
944         ret = _talloc(t, len + 1);
945         if (!ret) { return NULL; }
946         memcpy(ret, p, len);
947         ret[len] = 0;
948         talloc_set_name_const(ret, ret);
949         return ret;
950 }
951
952 #ifndef VA_COPY
953 #ifdef HAVE_VA_COPY
954 #define VA_COPY(dest, src) va_copy(dest, src)
955 #elif defined(HAVE___VA_COPY)
956 #define VA_COPY(dest, src) __va_copy(dest, src)
957 #else
958 #define VA_COPY(dest, src) (dest) = (src)
959 #endif
960 #endif
961
962 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
963 {
964         int len;
965         char *ret;
966         va_list ap2;
967
968         VA_COPY(ap2, ap);
969
970         len = vsnprintf(NULL, 0, fmt, ap2);
971
972         ret = _talloc(t, len+1);
973         if (ret) {
974                 VA_COPY(ap2, ap);
975                 vsnprintf(ret, len+1, fmt, ap2);
976                 talloc_set_name_const(ret, ret);
977         }
978
979         return ret;
980 }
981
982
983 /*
984   Perform string formatting, and return a pointer to newly allocated
985   memory holding the result, inside a memory pool.
986  */
987 char *talloc_asprintf(const void *t, const char *fmt, ...)
988 {
989         va_list ap;
990         char *ret;
991
992         va_start(ap, fmt);
993         ret = talloc_vasprintf(t, fmt, ap);
994         va_end(ap);
995         return ret;
996 }
997
998
999 /**
1000  * Realloc @p s to append the formatted result of @p fmt and @p ap,
1001  * and return @p s, which may have moved.  Good for gradually
1002  * accumulating output into a string buffer.
1003  **/
1004
1005 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1006         PRINTF_ATTRIBUTE(2,0);
1007
1008 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1009 {
1010         struct talloc_chunk *tc;
1011         int len, s_len;
1012         va_list ap2;
1013
1014         if (s == NULL) {
1015                 return talloc_vasprintf(NULL, fmt, ap);
1016         }
1017
1018         tc = talloc_chunk_from_ptr(s);
1019
1020         VA_COPY(ap2, ap);
1021
1022         s_len = tc->size - 1;
1023         len = vsnprintf(NULL, 0, fmt, ap2);
1024
1025         s = talloc_realloc(NULL, s, char, s_len + len+1);
1026         if (!s) return NULL;
1027
1028         VA_COPY(ap2, ap);
1029
1030         vsnprintf(s+s_len, len+1, fmt, ap2);
1031         talloc_set_name_const(s, s);
1032
1033         return s;
1034 }
1035
1036 /*
1037   Realloc @p s to append the formatted result of @p fmt and return @p
1038   s, which may have moved.  Good for gradually accumulating output
1039   into a string buffer.
1040  */
1041 char *talloc_asprintf_append(char *s, const char *fmt, ...)
1042 {
1043         va_list ap;
1044
1045         va_start(ap, fmt);
1046         s = talloc_vasprintf_append(s, fmt, ap);
1047         va_end(ap);
1048         return s;
1049 }
1050
1051 /*
1052   alloc an array, checking for integer overflow in the array size
1053 */
1054 void *_talloc_array(const void *ctx, size_t el_size, unsigned count,
1055                 const char *name)
1056 {
1057         if (count >= MAX_TALLOC_SIZE/el_size) {
1058                 return NULL;
1059         }
1060         return talloc_named_const(ctx, el_size * count, name);
1061 }
1062
1063 /*
1064   alloc an zero array, checking for integer overflow in the array size
1065 */
1066 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count,
1067                 const char *name)
1068 {
1069         if (count >= MAX_TALLOC_SIZE/el_size) {
1070                 return NULL;
1071         }
1072         return _talloc_zero(ctx, el_size * count, name);
1073 }
1074
1075
1076 /*
1077   realloc an array, checking for integer overflow in the array size
1078 */
1079 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size,
1080                 unsigned count, const char *name)
1081 {
1082         if (count >= MAX_TALLOC_SIZE/el_size) {
1083                 return NULL;
1084         }
1085         return _talloc_realloc(ctx, ptr, el_size * count, name);
1086 }
1087
1088 /*
1089   a function version of talloc_realloc(), so it can be passed as a function
1090   pointer to libraries that want a realloc function (a realloc function
1091   encapsulates all the basic capabilities of an allocation library, which is
1092   why this is useful)
1093 */
1094 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1095 {
1096         return _talloc_realloc(context, ptr, size, NULL);
1097 }
1098
1099
1100 static void talloc_autofree(void)
1101 {
1102         talloc_free(cleanup_context);
1103         cleanup_context = NULL;
1104 }
1105
1106 /*
1107   return a context which will be auto-freed on exit
1108   this is useful for reducing the noise in leak reports
1109 */
1110 void *talloc_autofree_context(void)
1111 {
1112         if (cleanup_context == NULL) {
1113                 cleanup_context = talloc_named_const(NULL, 0,
1114                                 "autofree_context");
1115                 atexit(talloc_autofree);
1116         }
1117         return cleanup_context;
1118 }
1119
1120 size_t talloc_get_size(const void *context)
1121 {
1122         struct talloc_chunk *tc;
1123
1124         if (context == NULL)
1125                 return 0;
1126
1127         tc = talloc_chunk_from_ptr(context);
1128
1129         return tc->size;
1130 }