d0056d7b2aa137e5f846243e6c7049b0c7a41bf9
[bbaumbach/samba-autobuild/.git] / source4 / lib / talloc.c
1 /* 
2    Samba Unix SMB/CIFS implementation.
3
4    Samba temporary memory allocation functions - new interface
5
6    Copyright (C) Andrew Tridgell 2004
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 /*
24   inspired by http://swapped.cc/halloc/
25 */
26
27 #include "includes.h"
28
29 #define MAX_TALLOC_SIZE 0x10000000
30 #define TALLOC_MAGIC 0xe814ec4f
31 #define TALLOC_MAGIC_FREE 0x7faebef3
32
33 static const void *null_context;
34
35 struct talloc_reference_handle {
36         struct talloc_reference_handle *next, *prev;
37         void *ptr;
38 };
39
40 typedef int (*talloc_destructor_t)(void *);
41
42 struct talloc_chunk {
43         struct talloc_chunk *next, *prev;
44         struct talloc_chunk *parent, *child;
45         struct talloc_reference_handle *refs;
46         size_t size;
47         uint_t magic;
48         talloc_destructor_t destructor;
49         const char *name;
50 };
51
52 /* panic if we get a bad magic value */
53 static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
54 {
55         struct talloc_chunk *tc = ((struct talloc_chunk *)discard_const(ptr))-1;
56         if (tc->magic != TALLOC_MAGIC) {
57                 if (tc->magic == TALLOC_MAGIC_FREE) {
58                         smb_panic("Bad talloc magic value - double free\n");
59                 } else {
60                         smb_panic("Bad talloc magic value\n");
61                 }
62         }
63         return tc;
64 }
65
66 /* 
67    Allocate a bit of memory as a child of an existing pointer
68 */
69 void *_talloc(const void *context, size_t size)
70 {
71         struct talloc_chunk *tc;
72
73         if (context == NULL) {
74                 context = null_context;
75         }
76
77         if (size >= MAX_TALLOC_SIZE) {
78                 return NULL;
79         }
80
81         tc = malloc(sizeof(*tc)+size);
82         if (tc == NULL) {
83                 return NULL;
84         }
85
86         tc->size = size;
87         tc->magic = TALLOC_MAGIC;
88         tc->destructor = NULL;
89         tc->child = NULL;
90         tc->name = NULL;
91         tc->refs = NULL;
92
93         if (context) {
94                 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
95
96                 tc->parent = parent;
97
98                 if (parent->child) {
99                         parent->child->parent = NULL;
100                 }
101
102                 DLIST_ADD(parent->child, tc);
103         } else {
104                 tc->next = tc->prev = tc->parent = NULL;
105         }
106
107         return (void *)(tc+1);
108 }
109
110
111 /*
112   setup a destructor to be called on free of a pointer
113   the destructor should return 0 on success, or -1 on failure.
114   if the destructor fails then the free is failed, and the memory can
115   be continued to be used
116 */
117 void talloc_set_destructor(const void *ptr, int (*destructor)(void *))
118 {
119         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
120         tc->destructor = destructor;
121 }
122
123 /*
124   increase the reference count on a piece of memory. 
125 */
126 void talloc_increase_ref_count(const void *ptr)
127 {
128         talloc_reference(null_context, ptr);
129 }
130
131 /*
132   helper for talloc_reference()
133 */
134 static int talloc_reference_destructor(void *ptr)
135 {
136         struct talloc_reference_handle *handle = ptr;
137         struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr);
138         struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr);
139         if (tc1->destructor != (talloc_destructor_t)-1) {
140                 tc1->destructor = NULL;
141         }
142         DLIST_REMOVE(tc2->refs, handle);
143         talloc_free(handle);
144         return 0;
145 }
146
147 /*
148   make a secondary reference to a pointer, hanging off the given context.
149   the pointer remains valid until both the original caller and this given
150   context are freed.
151   
152   the major use for this is when two different structures need to reference the 
153   same underlying data, and you want to be able to free the two instances separately,
154   and in either order
155 */
156 void *talloc_reference(const void *context, const void *ptr)
157 {
158         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
159         struct talloc_reference_handle *handle;
160         handle = talloc_named_const(context, sizeof(*handle), ".reference");
161         if (handle == NULL) {
162                 return NULL;
163         }
164         /* note that we hang the destructor off the handle, not the
165            main context as that allows the caller to still setup their
166            own destructor on the context if they want to */
167         talloc_set_destructor(handle, talloc_reference_destructor);
168         handle->ptr = discard_const(ptr);
169         DLIST_ADD(tc->refs, handle);
170         return handle->ptr;
171 }
172
173
174 /*
175   add a name to an existing pointer - va_list version
176 */
177 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
178
179 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
180 {
181         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
182         tc->name = talloc_vasprintf(ptr, fmt, ap);
183         if (tc->name) {
184                 talloc_set_name_const(tc->name, ".name");
185         }
186 }
187
188 /*
189   add a name to an existing pointer
190 */
191 void talloc_set_name(const void *ptr, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3)
192 {
193         va_list ap;
194         va_start(ap, fmt);
195         talloc_set_name_v(ptr, fmt, ap);
196         va_end(ap);
197 }
198
199 /*
200    more efficient way to add a name to a pointer - the name must point to a 
201    true string constant
202 */
203 void talloc_set_name_const(const void *ptr, const char *name)
204 {
205         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
206         tc->name = name;
207 }
208
209 /*
210   create a named talloc pointer. Any talloc pointer can be named, and
211   talloc_named() operates just like talloc() except that it allows you
212   to name the pointer.
213 */
214 void *talloc_named(const void *context, size_t size, 
215                    const char *fmt, ...) _PRINTF_ATTRIBUTE(3,4)
216 {
217         va_list ap;
218         void *ptr;
219
220         ptr = _talloc(context, size);
221         if (ptr == NULL) {
222                 return NULL;
223         }
224
225         va_start(ap, fmt);
226         talloc_set_name_v(ptr, fmt, ap);
227         va_end(ap);
228
229         return ptr;
230 }
231
232 /*
233   create a named talloc pointer. Any talloc pointer can be named, and
234   talloc_named() operates just like talloc() except that it allows you
235   to name the pointer.
236 */
237 void *talloc_named_const(const void *context, size_t size, const char *name)
238 {
239         void *ptr;
240
241         ptr = _talloc(context, size);
242         if (ptr == NULL) {
243                 return NULL;
244         }
245
246         talloc_set_name_const(ptr, name);
247
248         return ptr;
249 }
250
251 /*
252   return the name of a talloc ptr, or "UNNAMED"
253 */
254 const char *talloc_get_name(const void *ptr)
255 {
256         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
257         if (tc->name) {
258                 return tc->name;
259         }
260         return "UNNAMED";
261 }
262
263 /*
264   this is for compatibility with older versions of talloc
265 */
266 void *talloc_init(const char *fmt, ...) _PRINTF_ATTRIBUTE(1,2)
267 {
268         va_list ap;
269         void *ptr;
270
271         ptr = _talloc(NULL, 0);
272         if (ptr == NULL) {
273                 return NULL;
274         }
275
276         va_start(ap, fmt);
277         talloc_set_name_v(ptr, fmt, ap);
278         va_end(ap);
279
280         return ptr;
281 }
282
283
284 /* 
285    free a talloc pointer. This also frees all child pointers of this 
286    pointer recursively
287
288    return 0 if the memory is actually freed, otherwise -1. The memory
289    will not be freed if the ref_count is > 1 or the destructor (if
290    any) returns non-zero
291 */
292 int talloc_free(void *ptr)
293 {
294         struct talloc_chunk *tc;
295
296         if (ptr == NULL) {
297                 return -1;
298         }
299
300         tc = talloc_chunk_from_ptr(ptr);
301
302         if (tc->refs) {
303                 talloc_reference_destructor(tc->refs);
304                 return 0;
305         }
306
307         if (tc->destructor) {
308                 talloc_destructor_t d = tc->destructor;
309                 if (d == (talloc_destructor_t)-1) {
310                         return -1;
311                 }
312                 tc->destructor = (talloc_destructor_t)-1;
313                 if (d(ptr) == -1) {
314                         tc->destructor = d;
315                         return -1;
316                 }
317                 tc->destructor = NULL;
318         }
319
320         while (tc->child) {
321                 talloc_free(talloc_steal(tc->parent?tc->parent+1:null_context, 
322                                          tc->child+1));
323         }
324
325         if (tc->parent) {
326                 DLIST_REMOVE(tc->parent->child, tc);
327                 if (tc->parent->child) {
328                         tc->parent->child->parent = tc->parent;
329                 }
330         } else {
331                 if (tc->prev) tc->prev->next = tc->next;
332                 if (tc->next) tc->next->prev = tc->prev;
333         }
334
335         tc->magic = TALLOC_MAGIC_FREE;
336
337         free(tc);
338         return 0;
339 }
340
341
342
343 /*
344   A talloc version of realloc. The context argument is only used if
345   ptr is NULL
346 */
347 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
348 {
349         struct talloc_chunk *tc;
350         void *new_ptr;
351
352         /* size zero is equivalent to free() */
353         if (size == 0) {
354                 talloc_free(ptr);
355                 return NULL;
356         }
357
358         /* realloc(NULL) is equavalent to malloc() */
359         if (ptr == NULL) {
360                 return talloc_named_const(context, size, name);
361         }
362
363         tc = talloc_chunk_from_ptr(ptr);
364
365         /* don't allow realloc on referenced pointers */
366         if (tc->refs) {
367                 return NULL;
368         }
369
370         /* by resetting magic we catch users of the old memory */
371         tc->magic = TALLOC_MAGIC_FREE;
372
373         new_ptr = realloc(tc, size + sizeof(*tc));
374         if (!new_ptr) {
375                 tc->magic = TALLOC_MAGIC;
376                 return NULL;
377         }
378
379         tc = new_ptr;
380         tc->magic = TALLOC_MAGIC;
381         if (tc->parent) {
382                 tc->parent->child = new_ptr;
383         }
384
385         if (tc->prev) {
386                 tc->prev->next = tc;
387         }
388         if (tc->next) {
389                 tc->next->prev = tc;
390         }
391
392         tc->size = size;
393         talloc_set_name_const(tc+1, name);
394
395         return (void *)(tc+1);
396 }
397
398 /* 
399    move a lump of memory from one talloc context to another return the
400    ptr on success, or NULL if it could not be transferred
401 */
402 void *talloc_steal(const void *new_ctx, const void *ptr)
403 {
404         struct talloc_chunk *tc, *new_tc;
405
406         if (!ptr) {
407                 return NULL;
408         }
409
410         tc = talloc_chunk_from_ptr(ptr);
411
412         if (new_ctx == NULL) {
413                 if (tc->parent) {
414                         DLIST_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(ptr);
425         }
426
427         new_tc = talloc_chunk_from_ptr(new_ctx);
428
429         if (tc == new_tc) {
430                 return discard_const(ptr);
431         }
432
433         if (tc->parent) {
434                 DLIST_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         DLIST_ADD(new_tc->child, tc);
446
447         return discard_const(ptr);
448 }
449
450 /*
451   return the total size of a talloc pool (subtree)
452 */
453 off_t talloc_total_size(const void *ptr)
454 {
455         off_t total = 0;
456         struct talloc_chunk *c, *tc;
457         
458         if (ptr == NULL) {
459                 ptr = null_context;
460         }
461         if (ptr == NULL) {
462                 return 0;
463         }
464
465         tc = talloc_chunk_from_ptr(ptr);
466
467         total = tc->size;
468         for (c=tc->child;c;c=c->next) {
469                 total += talloc_total_size(c+1);
470         }
471         return total;
472 }
473
474 /*
475   return the total number of blocks in a talloc pool (subtree)
476 */
477 static off_t talloc_total_blocks(const void *ptr)
478 {
479         off_t total = 0;
480         struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
481
482         total++;
483         for (c=tc->child;c;c=c->next) {
484                 total += talloc_total_blocks(c+1);
485         }
486         return total;
487 }
488
489 /*
490   return the number of external references to a pointer
491 */
492 static int talloc_reference_count(const void *ptr)
493 {
494         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
495         struct talloc_reference_handle *h;
496         int ret = 0;
497
498         for (h=tc->refs;h;h=h->next) {
499                 ret++;
500         }
501         return ret;
502 }
503
504 /*
505   report on memory usage by all children of a pointer, giving a full tree view
506 */
507 static void talloc_report_depth(const void *ptr, FILE *f, int depth)
508 {
509         struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
510
511         for (c=tc->child;c;c=c->next) {
512                 const char *name = talloc_get_name(c+1);
513                 if (strcmp(name, ".reference") == 0) {
514                         struct talloc_reference_handle *handle = (void *)(c+1);
515                         const char *name2 = talloc_get_name(handle->ptr);
516                         fprintf(f, "%*sreference to: %s\n", depth*4, "", name2);
517                 } else {
518                         fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", 
519                                 depth*4, "",
520                                 name,
521                                 (unsigned long)talloc_total_size(c+1),
522                                 (unsigned long)talloc_total_blocks(c+1),
523                                 talloc_reference_count(c+1));
524                         talloc_report_depth(c+1, f, depth+1);
525                 }
526         }
527
528 }
529
530 /*
531   report on memory usage by all children of a pointer, giving a full tree view
532 */
533 void talloc_report_full(const void *ptr, FILE *f)
534 {
535         if (ptr == NULL) {
536                 ptr = null_context;
537         }
538         if (ptr == NULL) return;
539
540         fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n", 
541                 talloc_get_name(ptr), 
542                 (unsigned long)talloc_total_size(ptr),
543                 (unsigned long)talloc_total_blocks(ptr));
544
545         talloc_report_depth(ptr, f, 1);
546 }
547
548 /*
549   report on memory usage by all children of a pointer
550 */
551 void talloc_report(const void *ptr, FILE *f)
552 {
553         struct talloc_chunk *c, *tc;
554
555         if (ptr == NULL) {
556                 ptr = null_context;
557         }
558         if (ptr == NULL) return;
559        
560         fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n", 
561                 talloc_get_name(ptr), 
562                 (unsigned long)talloc_total_size(ptr),
563                 (unsigned long)talloc_total_blocks(ptr));
564
565         tc = talloc_chunk_from_ptr(ptr);
566
567         for (c=tc->child;c;c=c->next) {
568                 fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n", 
569                         talloc_get_name(c+1),
570                         (unsigned long)talloc_total_size(c+1),
571                         (unsigned long)talloc_total_blocks(c+1));
572         }
573
574 }
575
576 /*
577   report on any memory hanging off the null context
578 */
579 static void talloc_report_null(void)
580 {
581         if (talloc_total_size(null_context) == 0) {
582                 return;
583         }
584         talloc_report(null_context, stderr);
585 }
586
587 /*
588   report on any memory hanging off the null context
589 */
590 static void talloc_report_null_full(void)
591 {
592         if (talloc_total_size(null_context) == 0) {
593                 return;
594         }
595         talloc_report_full(null_context, stderr);
596 }
597
598 /*
599   enable leak reporting on exit
600 */
601 void talloc_enable_leak_report(void)
602 {
603         null_context = talloc_named_const(NULL, 0, "null_context");
604         atexit(talloc_report_null);
605 }
606
607 /*
608   enable full leak reporting on exit
609 */
610 void talloc_enable_leak_report_full(void)
611 {
612         null_context = talloc_named_const(NULL, 0, "null_context");
613         atexit(talloc_report_null_full);
614 }
615
616 /* 
617    talloc and zero memory. 
618 */
619 void *talloc_zero(const void *ctx, size_t size)
620 {
621         void *p = talloc(ctx, size);
622
623         if (p) {
624                 memset(p, '\0', size);
625         }
626
627         return p;
628 }
629
630
631 /*
632   memdup with a talloc. 
633 */
634 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
635 {
636         void *newp = talloc_named_const(t, size, name);
637
638         if (newp) {
639                 memcpy(newp, p, size);
640         }
641
642         return newp;
643 }
644
645 /*
646   strdup with a talloc 
647 */
648 char *talloc_strdup(const void *t, const char *p)
649 {
650         char *ret;
651         if (!p) {
652                 return NULL;
653         }
654         ret = talloc_memdup(t, p, strlen(p) + 1);
655         if (ret) {
656                 talloc_set_name_const(ret, ret);
657         }
658         return ret;
659 }
660
661 /*
662   strndup with a talloc 
663 */
664 char *talloc_strndup(const void *t, const char *p, size_t n)
665 {
666         size_t len = strnlen(p, n);
667         char *ret;
668
669         ret = talloc(t, len + 1);
670         if (!ret) { return NULL; }
671         memcpy(ret, p, len);
672         ret[len] = 0;
673         return ret;
674 }
675
676 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) _PRINTF_ATTRIBUTE(2,0)
677 {       
678         int len;
679         char *ret;
680         va_list ap2;
681         
682         VA_COPY(ap2, ap);
683
684         len = vsnprintf(NULL, 0, fmt, ap2);
685
686         ret = talloc(t, len+1);
687         if (ret) {
688                 VA_COPY(ap2, ap);
689                 vsnprintf(ret, len+1, fmt, ap2);
690                 talloc_set_name_const(ret, ret);
691         }
692
693         return ret;
694 }
695
696
697 /*
698   Perform string formatting, and return a pointer to newly allocated
699   memory holding the result, inside a memory pool.
700  */
701 char *talloc_asprintf(const void *t, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3)
702 {
703         va_list ap;
704         char *ret;
705
706         va_start(ap, fmt);
707         ret = talloc_vasprintf(t, fmt, ap);
708         va_end(ap);
709         return ret;
710 }
711
712
713 /**
714  * Realloc @p s to append the formatted result of @p fmt and @p ap,
715  * and return @p s, which may have moved.  Good for gradually
716  * accumulating output into a string buffer.
717  **/
718
719 static char *talloc_vasprintf_append(char *s,
720                                      const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
721
722 static char *talloc_vasprintf_append(char *s,
723                                      const char *fmt, va_list ap)
724 {       
725         int len, s_len;
726         va_list ap2;
727
728         VA_COPY(ap2, ap);
729
730         if (s) {
731                 s_len = strlen(s);
732         } else {
733                 s_len = 0;
734         }
735         len = vsnprintf(NULL, 0, fmt, ap2);
736
737         s = talloc_realloc(NULL, s, s_len + len+1);
738         if (!s) return NULL;
739
740         VA_COPY(ap2, ap);
741
742         vsnprintf(s+s_len, len+1, fmt, ap2);
743         talloc_set_name_const(s, s);
744
745         return s;
746 }
747
748 /*
749   Realloc @p s to append the formatted result of @p fmt and return @p
750   s, which may have moved.  Good for gradually accumulating output
751   into a string buffer.
752  */
753 char *talloc_asprintf_append(char *s,
754                              const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3)
755 {
756         va_list ap;
757
758         va_start(ap, fmt);
759         s = talloc_vasprintf_append(s, fmt, ap);
760         va_end(ap);
761         return s;
762 }
763
764 /*
765   alloc an array, checking for integer overflow in the array size
766 */
767 void *talloc_array(const void *ctx, size_t el_size, uint_t count, const char *name)
768 {
769         if (count == 0 ||
770             count >= MAX_TALLOC_SIZE/el_size) {
771                 return NULL;
772         }
773         return talloc_named_const(ctx, el_size * count, name);
774 }
775
776
777 /*
778   realloc an array, checking for integer overflow in the array size
779 */
780 void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, uint_t count, const char *name)
781 {
782         if (count == 0 ||
783             count >= MAX_TALLOC_SIZE/el_size) {
784                 return NULL;
785         }
786         ptr = talloc_realloc(ctx, ptr, el_size * count);
787         if (ptr) {
788                 talloc_set_name_const(ptr, name);
789         }
790         return ptr;
791 }
792
793 /*
794   a alloc function for ldb that uses talloc
795 */
796 void *talloc_ldb_alloc(void *context, void *ptr, size_t size)
797 {
798         if (ptr == NULL) {
799                 return talloc(context, size);
800         }
801         if (size == 0) {
802                 talloc_free(ptr);
803                 return NULL;
804         }
805         return talloc_realloc(context, ptr, size);
806 }