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/
29 #define MAX_TALLOC_SIZE 0x10000000
30 #define TALLOC_MAGIC 0xe814ec4f
31 #define TALLOC_MAGIC_FREE 0x7faebef3
34 struct talloc_chunk *next, *prev;
35 struct talloc_chunk *parent, *child;
39 int (*destructor)(void *);
43 /* panic if we get a bad magic value */
44 static struct talloc_chunk *talloc_chunk_from_ptr(void *ptr)
46 struct talloc_chunk *tc = ((struct talloc_chunk *)ptr)-1;
47 if (tc->magic != TALLOC_MAGIC) {
48 if (tc->magic == TALLOC_MAGIC_FREE) {
49 smb_panic("Bad talloc magic value - double free\n");
51 smb_panic("Bad talloc magic value\n");
58 Allocate a bit of memory as a child of an existing pointer
60 void *talloc(void *context, size_t size)
62 struct talloc_chunk *tc;
64 if (size >= MAX_TALLOC_SIZE) {
68 tc = malloc(sizeof(*tc)+size);
74 tc->magic = TALLOC_MAGIC;
76 tc->destructor = NULL;
81 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
86 parent->child->parent = NULL;
89 DLIST_ADD(parent->child, tc);
91 tc->next = tc->prev = tc->parent = NULL;
94 return (void *)(tc+1);
99 setup a destructor to be called on free of a pointer
100 the destructor should return 0 on success, or -1 on failure.
101 if the destructor fails then the free is failed, and the memory can
102 be continued to be used
104 void talloc_set_destructor(void *ptr, int (*destructor)(void *))
106 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
107 tc->destructor = destructor;
111 increase the reference count on a piece of memory. To decrease the
112 reference count call talloc_free(), which will free the memory if
113 the reference count reaches zero
115 void talloc_increase_ref_count(void *ptr)
117 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
123 add a name to an existing pointer - va_list version
125 static void talloc_set_name_v(void *ptr, const char *fmt, va_list ap)
127 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
128 vasprintf(&tc->name, fmt, ap);
132 add a name to an existing pointer
134 void talloc_set_name(void *ptr, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3)
138 talloc_set_name_v(ptr, fmt, ap);
143 create a named talloc pointer. Any talloc pointer can be named, and
144 talloc_named() operates just like talloc() except that it allows you
147 void *talloc_named(void *context, size_t size,
148 const char *fmt, ...) _PRINTF_ATTRIBUTE(3,4)
153 ptr = talloc(context, size);
159 talloc_set_name_v(ptr, fmt, ap);
166 this is for compatibility with older versions of talloc
168 void *talloc_init(const char *fmt, ...) _PRINTF_ATTRIBUTE(1,2)
173 ptr = talloc(NULL, 0);
179 talloc_set_name_v(ptr, fmt, ap);
188 free a talloc pointer. This also frees all child pointers of this
191 return 0 if the memory is actually freed, otherwise -1. The memory
192 will not be freed if the ref_count is > 1 or the destructor (if
193 any) returns non-zero
195 int talloc_free(void *ptr)
197 struct talloc_chunk *tc;
203 tc = talloc_chunk_from_ptr(ptr);
206 if (tc->ref_count != 0) {
210 if (tc->destructor && tc->destructor(ptr) == -1) {
216 if (talloc_free(tc->child + 1) != 0) {
217 tc->child->parent = NULL;
223 DLIST_REMOVE(tc->parent->child, tc);
224 if (tc->parent->child) {
225 tc->parent->child->parent = tc->parent;
228 if (tc->prev) tc->prev->next = tc->next;
229 if (tc->next) tc->next->prev = tc->prev;
232 tc->magic = TALLOC_MAGIC_FREE;
233 if (tc->name) free(tc->name);
242 A talloc version of realloc
244 void *talloc_realloc(void *ptr, size_t size)
246 struct talloc_chunk *tc;
249 /* size zero is equivalent to free() */
255 /* realloc(NULL) is equavalent to malloc() */
257 return talloc(NULL, size);
260 tc = talloc_chunk_from_ptr(ptr);
262 /* by resetting magic we catch users of the old memory */
263 tc->magic = TALLOC_MAGIC_FREE;
265 new_ptr = realloc(tc, size + sizeof(*tc));
267 tc->magic = TALLOC_MAGIC;
272 tc->magic = TALLOC_MAGIC;
274 tc->parent->child = new_ptr;
286 return (void *)(tc+1);
290 move a lump of memory from one talloc context to another return the
291 ptr on success, or NUL if it could not be transferred
293 void *talloc_steal(void *new_ctx, void *ptr)
295 struct talloc_chunk *tc, *new_tc;
301 tc = talloc_chunk_from_ptr(ptr);
302 new_tc = talloc_chunk_from_ptr(new_ctx);
309 DLIST_REMOVE(tc->parent->child, tc);
310 if (tc->parent->child) {
311 tc->parent->child->parent = tc->parent;
314 if (tc->prev) tc->prev->next = tc->next;
315 if (tc->next) tc->next->prev = tc->prev;
319 if (new_tc->child) new_tc->child->parent = NULL;
320 DLIST_ADD(new_tc->child, tc);
326 return the total size of a talloc pool (subtree)
328 off_t talloc_total_size(void *ptr)
331 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
334 for (c=tc->child;c;c=c->next) {
335 total += talloc_total_size(c+1);
342 talloc and zero memory.
344 void *talloc_zero(void *t, size_t size)
346 void *p = talloc(t, size);
349 memset(p, '\0', size);
357 memdup with a talloc.
359 void *talloc_memdup(void *t, const void *p, size_t size)
361 void *newp = talloc(t,size);
364 memcpy(newp, p, size);
373 char *talloc_strdup(void *t, const char *p)
378 return talloc_memdup(t, p, strlen(p) + 1);
382 strndup with a talloc
384 char *talloc_strndup(void *t, const char *p, size_t n)
386 size_t len = strnlen(p, n);
389 ret = talloc(t, len + 1);
390 if (!ret) { return NULL; }
396 char *talloc_vasprintf(void *t, const char *fmt, va_list ap)
404 len = vsnprintf(NULL, 0, fmt, ap2);
406 ret = talloc(t, len+1);
409 vsnprintf(ret, len+1, fmt, ap2);
417 Perform string formatting, and return a pointer to newly allocated
418 memory holding the result, inside a memory pool.
420 char *talloc_asprintf(void *t, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3)
426 ret = talloc_vasprintf(t, fmt, ap);
433 * Realloc @p s to append the formatted result of @p fmt and @p ap,
434 * and return @p s, which may have moved. Good for gradually
435 * accumulating output into a string buffer.
437 char *talloc_vasprintf_append(char *s,
438 const char *fmt, va_list ap)
450 len = vsnprintf(NULL, 0, fmt, ap2);
452 s = talloc_realloc(s, s_len + len+1);
457 vsnprintf(s+s_len, len+1, fmt, ap2);
463 Realloc @p s to append the formatted result of @p fmt and return @p
464 s, which may have moved. Good for gradually accumulating output
465 into a string buffer.
467 char *talloc_asprintf_append(char *s,
468 const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3)
473 s = talloc_vasprintf_append(s, fmt, ap);
479 alloc an array, checking for integer overflow in the array size
481 void *talloc_array(void *ctx, size_t el_size, uint_t count)
484 count >= MAX_TALLOC_SIZE/el_size) {
487 return talloc(ctx, el_size * count);
492 realloc an array, checking for integer overflow in the array size
494 void *talloc_realloc_array(void *ptr, size_t el_size, uint_t count)
497 count >= MAX_TALLOC_SIZE/el_size) {
500 return talloc_realloc(ptr, el_size * count);
504 a alloc function for ldb that uses talloc
506 void *talloc_ldb_alloc(void *context, void *ptr, size_t size)
509 return talloc(context, size);
515 return talloc_realloc(ptr, size);