r2649: - used some cpp tricks to make users of talloc() and talloc_realloc()
[Samba/gebeck_regimport.git] / source4 / lib / talloc.c
blobc08495aae40d2c65d19a1d6ce4a3c97935f93579
1 /*
2 Samba Unix SMB/CIFS implementation.
4 Samba temporary memory allocation functions - new interface
6 Copyright (C) Andrew Tridgell 2004
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.
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.
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.
24 inspired by http://swapped.cc/halloc/
27 #include "includes.h"
29 #undef talloc
30 #define talloc(ctx, size) _talloc(ctx, size)
32 #define MAX_TALLOC_SIZE 0x10000000
33 #define TALLOC_MAGIC 0xe814ec4f
34 #define TALLOC_MAGIC_FREE 0x7faebef3
36 static void *null_context;
38 struct talloc_chunk {
39 struct talloc_chunk *next, *prev;
40 struct talloc_chunk *parent, *child;
41 size_t size;
42 uint_t magic;
43 uint_t ref_count;
44 int (*destructor)(void *);
45 const char *name;
48 /* panic if we get a bad magic value */
49 static struct talloc_chunk *talloc_chunk_from_ptr(void *ptr)
51 struct talloc_chunk *tc = ((struct talloc_chunk *)ptr)-1;
52 if (tc->magic != TALLOC_MAGIC) {
53 if (tc->magic == TALLOC_MAGIC_FREE) {
54 smb_panic("Bad talloc magic value - double free\n");
55 } else {
56 smb_panic("Bad talloc magic value\n");
59 return tc;
62 /*
63 Allocate a bit of memory as a child of an existing pointer
65 void *_talloc(void *context, size_t size)
67 struct talloc_chunk *tc;
69 if (context == NULL) {
70 context = null_context;
73 if (size >= MAX_TALLOC_SIZE) {
74 return NULL;
77 tc = malloc(sizeof(*tc)+size);
78 if (tc == NULL) {
79 return NULL;
82 tc->size = size;
83 tc->magic = TALLOC_MAGIC;
84 tc->ref_count = 1;
85 tc->destructor = NULL;
86 tc->child = NULL;
87 tc->name = NULL;
89 if (context) {
90 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
92 tc->parent = parent;
94 if (parent->child) {
95 parent->child->parent = NULL;
98 DLIST_ADD(parent->child, tc);
99 } else {
100 tc->next = tc->prev = tc->parent = NULL;
103 return (void *)(tc+1);
108 setup a destructor to be called on free of a pointer
109 the destructor should return 0 on success, or -1 on failure.
110 if the destructor fails then the free is failed, and the memory can
111 be continued to be used
113 void talloc_set_destructor(void *ptr, int (*destructor)(void *))
115 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
116 tc->destructor = destructor;
120 increase the reference count on a piece of memory. To decrease the
121 reference count call talloc_free(), which will free the memory if
122 the reference count reaches zero
124 void talloc_increase_ref_count(void *ptr)
126 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
127 tc->ref_count++;
132 add a name to an existing pointer - va_list version
134 static void talloc_set_name_v(void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
136 static void talloc_set_name_v(void *ptr, const char *fmt, va_list ap)
138 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
139 tc->name = talloc_vasprintf(ptr, fmt, ap);
143 add a name to an existing pointer
145 void talloc_set_name(void *ptr, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3)
147 va_list ap;
148 va_start(ap, fmt);
149 talloc_set_name_v(ptr, fmt, ap);
150 va_end(ap);
154 more efficient way to add a name to a pointer - the name must point to a
155 true string constant
157 void talloc_set_name_const(void *ptr, const char *name)
159 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
160 tc->name = name;
164 create a named talloc pointer. Any talloc pointer can be named, and
165 talloc_named() operates just like talloc() except that it allows you
166 to name the pointer.
168 void *talloc_named(void *context, size_t size,
169 const char *fmt, ...) _PRINTF_ATTRIBUTE(3,4)
171 va_list ap;
172 void *ptr;
174 ptr = talloc(context, size);
175 if (ptr == NULL) {
176 return NULL;
179 va_start(ap, fmt);
180 talloc_set_name_v(ptr, fmt, ap);
181 va_end(ap);
183 return ptr;
187 create a named talloc pointer. Any talloc pointer can be named, and
188 talloc_named() operates just like talloc() except that it allows you
189 to name the pointer.
191 void *talloc_named_const(void *context, size_t size, const char *name)
193 void *ptr;
195 ptr = talloc(context, size);
196 if (ptr == NULL) {
197 return NULL;
200 talloc_set_name_const(ptr, name);
202 return ptr;
206 return the name of a talloc ptr, or "UNNAMED"
208 const char *talloc_get_name(void *ptr)
210 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
211 if (tc->name) {
212 return tc->name;
214 return "UNNAMED";
218 this is for compatibility with older versions of talloc
220 void *talloc_init(const char *fmt, ...) _PRINTF_ATTRIBUTE(1,2)
222 va_list ap;
223 void *ptr;
225 ptr = talloc(NULL, 0);
226 if (ptr == NULL) {
227 return NULL;
230 va_start(ap, fmt);
231 talloc_set_name_v(ptr, fmt, ap);
232 va_end(ap);
234 return ptr;
240 free a talloc pointer. This also frees all child pointers of this
241 pointer recursively
243 return 0 if the memory is actually freed, otherwise -1. The memory
244 will not be freed if the ref_count is > 1 or the destructor (if
245 any) returns non-zero
247 int talloc_free(void *ptr)
249 struct talloc_chunk *tc;
251 if (ptr == NULL) {
252 return -1;
255 tc = talloc_chunk_from_ptr(ptr);
257 tc->ref_count--;
258 if (tc->ref_count != 0) {
259 return -1;
262 if (tc->destructor && tc->destructor(ptr) == -1) {
263 tc->ref_count++;
264 return -1;
267 while (tc->child) {
268 if (talloc_free(tc->child + 1) != 0) {
269 tc->child->parent = NULL;
270 break;
274 if (tc->parent) {
275 DLIST_REMOVE(tc->parent->child, tc);
276 if (tc->parent->child) {
277 tc->parent->child->parent = tc->parent;
279 } else {
280 if (tc->prev) tc->prev->next = tc->next;
281 if (tc->next) tc->next->prev = tc->prev;
284 tc->magic = TALLOC_MAGIC_FREE;
286 free(tc);
287 return 0;
293 A talloc version of realloc
295 void *_talloc_realloc(void *ptr, size_t size, const char *name)
297 struct talloc_chunk *tc;
298 void *new_ptr;
300 /* size zero is equivalent to free() */
301 if (size == 0) {
302 talloc_free(ptr);
303 return NULL;
306 /* realloc(NULL) is equavalent to malloc() */
307 if (ptr == NULL) {
308 return talloc_named_const(NULL, size, name);
311 tc = talloc_chunk_from_ptr(ptr);
313 /* by resetting magic we catch users of the old memory */
314 tc->magic = TALLOC_MAGIC_FREE;
316 new_ptr = realloc(tc, size + sizeof(*tc));
317 if (!new_ptr) {
318 tc->magic = TALLOC_MAGIC;
319 return NULL;
322 tc = new_ptr;
323 tc->magic = TALLOC_MAGIC;
324 if (tc->parent) {
325 tc->parent->child = new_ptr;
328 if (tc->prev) {
329 tc->prev->next = tc;
331 if (tc->next) {
332 tc->next->prev = tc;
335 tc->size = size;
336 talloc_set_name_const(tc+1, name);
338 return (void *)(tc+1);
342 move a lump of memory from one talloc context to another return the
343 ptr on success, or NUL if it could not be transferred
345 void *talloc_steal(void *new_ctx, void *ptr)
347 struct talloc_chunk *tc, *new_tc;
349 if (!ptr) {
350 return NULL;
353 tc = talloc_chunk_from_ptr(ptr);
354 new_tc = talloc_chunk_from_ptr(new_ctx);
356 if (tc == new_tc) {
357 return ptr;
360 if (tc->parent) {
361 DLIST_REMOVE(tc->parent->child, tc);
362 if (tc->parent->child) {
363 tc->parent->child->parent = tc->parent;
365 } else {
366 if (tc->prev) tc->prev->next = tc->next;
367 if (tc->next) tc->next->prev = tc->prev;
370 tc->parent = new_tc;
371 if (new_tc->child) new_tc->child->parent = NULL;
372 DLIST_ADD(new_tc->child, tc);
374 return ptr;
378 return the total size of a talloc pool (subtree)
380 static off_t talloc_total_size(void *ptr)
382 off_t total = 0;
383 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
385 total = tc->size;
386 for (c=tc->child;c;c=c->next) {
387 total += talloc_total_size(c+1);
389 return total;
393 return the total number of blocks in a talloc pool (subtree)
395 static off_t talloc_total_blocks(void *ptr)
397 off_t total = 0;
398 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
400 total++;
401 for (c=tc->child;c;c=c->next) {
402 total += talloc_total_blocks(c+1);
404 return total;
408 report on memory usage by all children of a pointer
410 void talloc_report(void *ptr, FILE *f)
412 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
414 fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n",
415 talloc_get_name(ptr),
416 (unsigned long)talloc_total_size(ptr),
417 (unsigned long)talloc_total_blocks(ptr));
419 for (c=tc->child;c;c=c->next) {
420 fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n",
421 talloc_get_name(c+1),
422 (unsigned long)talloc_total_size(c+1),
423 (unsigned long)talloc_total_blocks(c+1));
429 report on any memory hanging off the null context
431 static void talloc_report_all(void)
433 talloc_report(null_context, stderr);
437 enable leak reporting on exit
439 void talloc_enable_leak_check(void)
441 null_context = talloc_named(NULL, 0, "null_context");
442 atexit(talloc_report_all);
446 talloc and zero memory.
448 void *talloc_zero(void *t, size_t size)
450 void *p = talloc(t, size);
452 if (p) {
453 memset(p, '\0', size);
456 return p;
461 memdup with a talloc.
463 void *talloc_memdup(void *t, const void *p, size_t size)
465 void *newp = talloc(t,size);
467 if (newp) {
468 memcpy(newp, p, size);
471 return newp;
475 strdup with a talloc
477 char *talloc_strdup(void *t, const char *p)
479 if (!p) {
480 return NULL;
482 return talloc_memdup(t, p, strlen(p) + 1);
486 strndup with a talloc
488 char *talloc_strndup(void *t, const char *p, size_t n)
490 size_t len = strnlen(p, n);
491 char *ret;
493 ret = talloc(t, len + 1);
494 if (!ret) { return NULL; }
495 memcpy(ret, p, len);
496 ret[len] = 0;
497 return ret;
500 char *talloc_vasprintf(void *t, const char *fmt, va_list ap) _PRINTF_ATTRIBUTE(2,0)
502 int len;
503 char *ret;
504 va_list ap2;
506 VA_COPY(ap2, ap);
508 len = vsnprintf(NULL, 0, fmt, ap2);
510 ret = talloc(t, len+1);
511 if (ret) {
512 VA_COPY(ap2, ap);
513 vsnprintf(ret, len+1, fmt, ap2);
516 return ret;
521 Perform string formatting, and return a pointer to newly allocated
522 memory holding the result, inside a memory pool.
524 char *talloc_asprintf(void *t, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3)
526 va_list ap;
527 char *ret;
529 va_start(ap, fmt);
530 ret = talloc_vasprintf(t, fmt, ap);
531 va_end(ap);
532 return ret;
537 * Realloc @p s to append the formatted result of @p fmt and @p ap,
538 * and return @p s, which may have moved. Good for gradually
539 * accumulating output into a string buffer.
542 static char *talloc_vasprintf_append(char *s,
543 const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
545 static char *talloc_vasprintf_append(char *s,
546 const char *fmt, va_list ap)
548 int len, s_len;
549 va_list ap2;
551 VA_COPY(ap2, ap);
553 if (s) {
554 s_len = strlen(s);
555 } else {
556 s_len = 0;
558 len = vsnprintf(NULL, 0, fmt, ap2);
560 s = talloc_realloc(s, s_len + len+1);
561 if (!s) return NULL;
563 VA_COPY(ap2, ap);
565 vsnprintf(s+s_len, len+1, fmt, ap2);
567 return s;
571 Realloc @p s to append the formatted result of @p fmt and return @p
572 s, which may have moved. Good for gradually accumulating output
573 into a string buffer.
575 char *talloc_asprintf_append(char *s,
576 const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3)
578 va_list ap;
580 va_start(ap, fmt);
581 s = talloc_vasprintf_append(s, fmt, ap);
582 va_end(ap);
583 return s;
587 alloc an array, checking for integer overflow in the array size
589 void *talloc_array(void *ctx, size_t el_size, uint_t count, const char *name)
591 if (count == 0 ||
592 count >= MAX_TALLOC_SIZE/el_size) {
593 return NULL;
595 return talloc_named_const(ctx, el_size * count, name);
600 realloc an array, checking for integer overflow in the array size
602 void *talloc_realloc_array(void *ptr, size_t el_size, uint_t count, const char *name)
604 if (count == 0 ||
605 count >= MAX_TALLOC_SIZE/el_size) {
606 return NULL;
608 ptr = talloc_realloc(ptr, el_size * count);
609 if (ptr) {
610 talloc_set_name_const(ptr, name);
612 return ptr;
616 a alloc function for ldb that uses talloc
618 void *talloc_ldb_alloc(void *context, void *ptr, size_t size)
620 if (ptr == NULL) {
621 return talloc(context, size);
623 if (size == 0) {
624 talloc_free(ptr);
625 return NULL;
627 return talloc_realloc(ptr, size);