mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
Import the current version of talloc from the Samba 3 source base. This gives
us greater confidence that our talloc implementation is "known good". Remove the OOM handling from consider_message: talloc_set_fail_handler is no longer supported. Signed-off-by: Ewan Mellor <ewan@xensource.com>
This commit is contained in:
1 parent
64444a6982
commit
1bac3b49cd
4 files changed
+278
-133
No files matched your search
@@ -0,0 +1,5 @@
|
||||
The following files are imported from the Samba project. We use the versions
|
||||
from Samba 3, the current stable branch.
|
||||
|
||||
talloc.c: samba-trunk/source/lib/talloc.c r14291 2006-03-13 04:27:47 +0000
|
||||
talloc.h: samba-trunk/source/include/talloc.h r11986 2005-12-01 00:43:36 +0000
|
||||
+250
-98
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
Samba Unix SMB/CIFS implementation.
|
||||
|
||||
Samba trivial allocation library - new interface
|
||||
@@ -6,27 +6,30 @@
|
||||
NOTE: Please read talloc_guide.txt for full documentation
|
||||
|
||||
Copyright (C) Andrew Tridgell 2004
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
|
||||
** NOTE! The following LGPL license applies to the talloc
|
||||
** library. This does NOT imply that all of Samba is released
|
||||
** under the LGPL
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
inspired by http://swapped.cc/halloc/
|
||||
*/
|
||||
|
||||
|
||||
#ifdef _SAMBA_BUILD_
|
||||
#include "includes.h"
|
||||
#if ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9))
|
||||
@@ -52,15 +55,13 @@
|
||||
|
||||
/* use this to force every realloc to change the pointer, to stress test
|
||||
code that might not cope */
|
||||
#ifdef TESTING
|
||||
#define ALWAYS_REALLOC 1
|
||||
void *test_malloc(size_t size);
|
||||
#define malloc test_malloc
|
||||
#endif
|
||||
#define ALWAYS_REALLOC 0
|
||||
|
||||
|
||||
#define MAX_TALLOC_SIZE 0x10000000
|
||||
#define TALLOC_MAGIC 0xe814ec4f
|
||||
#define TALLOC_MAGIC_FREE 0x7faebef3
|
||||
#define TALLOC_MAGIC 0xe814ec70
|
||||
#define TALLOC_FLAG_FREE 0x01
|
||||
#define TALLOC_FLAG_LOOP 0x02
|
||||
#define TALLOC_MAGIC_REFERENCE ((const char *)1)
|
||||
|
||||
/* by default we abort when given a bad pointer (such as when talloc_free() is called
|
||||
@@ -83,8 +84,7 @@ void *test_malloc(size_t size);
|
||||
*/
|
||||
static const void *null_context;
|
||||
static void *cleanup_context;
|
||||
static int (*malloc_fail_handler)(void *);
|
||||
static void *malloc_fail_data;
|
||||
|
||||
|
||||
struct talloc_reference_handle {
|
||||
struct talloc_reference_handle *next, *prev;
|
||||
@@ -97,24 +97,27 @@ struct talloc_chunk {
|
||||
struct talloc_chunk *next, *prev;
|
||||
struct talloc_chunk *parent, *child;
|
||||
struct talloc_reference_handle *refs;
|
||||
size_t size;
|
||||
unsigned magic;
|
||||
talloc_destructor_t destructor;
|
||||
const char *name;
|
||||
size_t size;
|
||||
unsigned flags;
|
||||
};
|
||||
|
||||
/* 16 byte alignment seems to keep everyone happy */
|
||||
#define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
|
||||
#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
|
||||
|
||||
/* panic if we get a bad magic value */
|
||||
static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
|
||||
{
|
||||
struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1;
|
||||
if (tc->magic != TALLOC_MAGIC) {
|
||||
if (tc->magic == TALLOC_MAGIC_FREE) {
|
||||
TALLOC_ABORT("Bad talloc magic value - double free");
|
||||
} else {
|
||||
TALLOC_ABORT("Bad talloc magic value - unknown value");
|
||||
}
|
||||
const char *pp = ptr;
|
||||
struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
|
||||
if ((tc->flags & ~0xF) != TALLOC_MAGIC) {
|
||||
TALLOC_ABORT("Bad talloc magic value - unknown value");
|
||||
}
|
||||
if (tc->flags & TALLOC_FLAG_FREE) {
|
||||
TALLOC_ABORT("Bad talloc magic value - double free");
|
||||
}
|
||||
|
||||
return tc;
|
||||
}
|
||||
|
||||
@@ -159,7 +162,7 @@ static struct talloc_chunk *talloc_parent_chunk(const void *ptr)
|
||||
void *talloc_parent(const void *ptr)
|
||||
{
|
||||
struct talloc_chunk *tc = talloc_parent_chunk(ptr);
|
||||
return (void *)(tc+1);
|
||||
return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -177,17 +180,11 @@ void *_talloc(const void *context, size_t size)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tc = malloc(sizeof(*tc)+size);
|
||||
if (tc == NULL) {
|
||||
if (malloc_fail_handler)
|
||||
if (malloc_fail_handler(malloc_fail_data))
|
||||
tc = malloc(sizeof(*tc)+size);
|
||||
if (!tc)
|
||||
return NULL;
|
||||
}
|
||||
tc = malloc(TC_HDR_SIZE+size);
|
||||
if (tc == NULL) return NULL;
|
||||
|
||||
tc->size = size;
|
||||
tc->magic = TALLOC_MAGIC;
|
||||
tc->flags = TALLOC_MAGIC;
|
||||
tc->destructor = NULL;
|
||||
tc->child = NULL;
|
||||
tc->name = NULL;
|
||||
@@ -207,7 +204,7 @@ void *_talloc(const void *context, size_t size)
|
||||
tc->next = tc->prev = tc->parent = NULL;
|
||||
}
|
||||
|
||||
return (void *)(tc+1);
|
||||
return TC_PTR_FROM_CHUNK(tc);
|
||||
}
|
||||
|
||||
|
||||
@@ -292,7 +289,11 @@ static int talloc_unreference(const void *context, const void *ptr)
|
||||
|
||||
for (h=tc->refs;h;h=h->next) {
|
||||
struct talloc_chunk *p = talloc_parent_chunk(h);
|
||||
if ((p==NULL && context==NULL) || p+1 == context) break;
|
||||
if (p == NULL) {
|
||||
if (context == NULL) break;
|
||||
} else if (TC_PTR_FROM_CHUNK(p) == context) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (h == NULL) {
|
||||
return -1;
|
||||
@@ -343,7 +344,7 @@ int talloc_unlink(const void *context, void *ptr)
|
||||
|
||||
new_p = talloc_parent_chunk(tc_p->refs);
|
||||
if (new_p) {
|
||||
new_parent = new_p+1;
|
||||
new_parent = TC_PTR_FROM_CHUNK(new_p);
|
||||
} else {
|
||||
new_parent = NULL;
|
||||
}
|
||||
@@ -471,6 +472,8 @@ void *talloc_init(const char *fmt, ...)
|
||||
va_list ap;
|
||||
void *ptr;
|
||||
|
||||
talloc_enable_null_tracking();
|
||||
|
||||
ptr = _talloc(NULL, 0);
|
||||
if (ptr == NULL) return NULL;
|
||||
|
||||
@@ -502,16 +505,16 @@ void talloc_free_children(void *ptr)
|
||||
choice is owner of any remaining reference to this
|
||||
pointer, the second choice is our parent, and the
|
||||
final choice is the null context. */
|
||||
void *child = tc->child+1;
|
||||
void *child = TC_PTR_FROM_CHUNK(tc->child);
|
||||
const void *new_parent = null_context;
|
||||
if (tc->child->refs) {
|
||||
struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
|
||||
if (p) new_parent = p+1;
|
||||
if (p) new_parent = TC_PTR_FROM_CHUNK(p);
|
||||
}
|
||||
if (talloc_free(child) == -1) {
|
||||
if (new_parent == null_context) {
|
||||
struct talloc_chunk *p = talloc_parent_chunk(ptr);
|
||||
if (p) new_parent = p+1;
|
||||
if (p) new_parent = TC_PTR_FROM_CHUNK(p);
|
||||
}
|
||||
talloc_steal(new_parent, child);
|
||||
}
|
||||
@@ -541,6 +544,11 @@ int talloc_free(void *ptr)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tc->flags & TALLOC_FLAG_LOOP) {
|
||||
/* we have a free loop - stop looping */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tc->destructor) {
|
||||
talloc_destructor_t d = tc->destructor;
|
||||
if (d == (talloc_destructor_t)-1) {
|
||||
@@ -554,6 +562,8 @@ int talloc_free(void *ptr)
|
||||
tc->destructor = NULL;
|
||||
}
|
||||
|
||||
tc->flags |= TALLOC_FLAG_LOOP;
|
||||
|
||||
talloc_free_children(ptr);
|
||||
|
||||
if (tc->parent) {
|
||||
@@ -566,7 +576,7 @@ int talloc_free(void *ptr)
|
||||
if (tc->next) tc->next->prev = tc->prev;
|
||||
}
|
||||
|
||||
tc->magic = TALLOC_MAGIC_FREE;
|
||||
tc->flags |= TALLOC_FLAG_FREE;
|
||||
|
||||
free(tc);
|
||||
return 0;
|
||||
@@ -606,36 +616,24 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n
|
||||
}
|
||||
|
||||
/* by resetting magic we catch users of the old memory */
|
||||
tc->magic = TALLOC_MAGIC_FREE;
|
||||
tc->flags |= TALLOC_FLAG_FREE;
|
||||
|
||||
#if ALWAYS_REALLOC
|
||||
new_ptr = malloc(size + sizeof(*tc));
|
||||
if (!new_ptr) {
|
||||
tc->magic = TALLOC_MAGIC;
|
||||
if (malloc_fail_handler)
|
||||
if (malloc_fail_handler(malloc_fail_data))
|
||||
new_ptr = malloc(size + sizeof(*tc));
|
||||
}
|
||||
new_ptr = malloc(size + TC_HDR_SIZE);
|
||||
if (new_ptr) {
|
||||
memcpy(new_ptr, tc, tc->size + sizeof(*tc));
|
||||
memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE);
|
||||
free(tc);
|
||||
}
|
||||
#else
|
||||
new_ptr = realloc(tc, size + sizeof(*tc));
|
||||
if (!new_ptr) {
|
||||
tc->magic = TALLOC_MAGIC;
|
||||
if (malloc_fail_handler)
|
||||
if (malloc_fail_handler(malloc_fail_data))
|
||||
new_ptr = realloc(tc, size + sizeof(*tc));
|
||||
}
|
||||
new_ptr = realloc(tc, size + TC_HDR_SIZE);
|
||||
#endif
|
||||
if (!new_ptr) {
|
||||
tc->magic = TALLOC_MAGIC;
|
||||
tc->flags &= ~TALLOC_FLAG_FREE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tc = new_ptr;
|
||||
tc->magic = TALLOC_MAGIC;
|
||||
tc->flags &= ~TALLOC_FLAG_FREE;
|
||||
if (tc->parent) {
|
||||
tc->parent->child = new_ptr;
|
||||
}
|
||||
@@ -651,9 +649,9 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n
|
||||
}
|
||||
|
||||
tc->size = size;
|
||||
talloc_set_name_const(tc+1, name);
|
||||
talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
|
||||
|
||||
return (void *)(tc+1);
|
||||
return TC_PTR_FROM_CHUNK(tc);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -730,10 +728,19 @@ off_t talloc_total_size(const void *ptr)
|
||||
|
||||
tc = talloc_chunk_from_ptr(ptr);
|
||||
|
||||
if (tc->flags & TALLOC_FLAG_LOOP) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
tc->flags |= TALLOC_FLAG_LOOP;
|
||||
|
||||
total = tc->size;
|
||||
for (c=tc->child;c;c=c->next) {
|
||||
total += talloc_total_size(c+1);
|
||||
total += talloc_total_size(TC_PTR_FROM_CHUNK(c));
|
||||
}
|
||||
|
||||
tc->flags &= ~TALLOC_FLAG_LOOP;
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
@@ -743,20 +750,21 @@ off_t talloc_total_size(const void *ptr)
|
||||
off_t talloc_total_blocks(const void *ptr)
|
||||
{
|
||||
off_t total = 0;
|
||||
struct talloc_chunk *c, *tc;
|
||||
struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
|
||||
|
||||
if (ptr == NULL) {
|
||||
ptr = null_context;
|
||||
}
|
||||
if (ptr == NULL) {
|
||||
if (tc->flags & TALLOC_FLAG_LOOP) {
|
||||
return 0;
|
||||
}
|
||||
tc = talloc_chunk_from_ptr(ptr);
|
||||
|
||||
tc->flags |= TALLOC_FLAG_LOOP;
|
||||
|
||||
total++;
|
||||
for (c=tc->child;c;c=c->next) {
|
||||
total += talloc_total_blocks(c+1);
|
||||
total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
|
||||
}
|
||||
|
||||
tc->flags &= ~TALLOC_FLAG_LOOP;
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
@@ -782,23 +790,29 @@ void talloc_report_depth(const void *ptr, FILE *f, int depth)
|
||||
{
|
||||
struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
|
||||
|
||||
if (tc->flags & TALLOC_FLAG_LOOP) {
|
||||
return;
|
||||
}
|
||||
|
||||
tc->flags |= TALLOC_FLAG_LOOP;
|
||||
|
||||
for (c=tc->child;c;c=c->next) {
|
||||
if (c->name == TALLOC_MAGIC_REFERENCE) {
|
||||
struct talloc_reference_handle *handle = (void *)(c+1);
|
||||
struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c);
|
||||
const char *name2 = talloc_get_name(handle->ptr);
|
||||
fprintf(f, "%*sreference to: %s\n", depth*4, "", name2);
|
||||
} else {
|
||||
const char *name = talloc_get_name(c+1);
|
||||
const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c));
|
||||
fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n",
|
||||
depth*4, "",
|
||||
name,
|
||||
(unsigned long)talloc_total_size(c+1),
|
||||
(unsigned long)talloc_total_blocks(c+1),
|
||||
talloc_reference_count(c+1));
|
||||
talloc_report_depth(c+1, f, depth+1);
|
||||
(unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
|
||||
(unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)),
|
||||
talloc_reference_count(TC_PTR_FROM_CHUNK(c)));
|
||||
talloc_report_depth(TC_PTR_FROM_CHUNK(c), f, depth+1);
|
||||
}
|
||||
}
|
||||
|
||||
tc->flags &= ~TALLOC_FLAG_LOOP;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -841,9 +855,9 @@ void talloc_report(const void *ptr, FILE *f)
|
||||
|
||||
for (c=tc->child;c;c=c->next) {
|
||||
fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n",
|
||||
talloc_get_name(c+1),
|
||||
(unsigned long)talloc_total_size(c+1),
|
||||
(unsigned long)talloc_total_blocks(c+1));
|
||||
talloc_get_name(TC_PTR_FROM_CHUNK(c)),
|
||||
(unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
|
||||
(unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)));
|
||||
}
|
||||
fflush(f);
|
||||
}
|
||||
@@ -878,6 +892,74 @@ void talloc_enable_null_tracking(void)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _SAMBA_BUILD_
|
||||
/* Ugly calls to Samba-specific sprintf_append... JRA. */
|
||||
|
||||
/*
|
||||
report on memory usage by all children of a pointer, giving a full tree view
|
||||
*/
|
||||
static void talloc_report_depth_str(const void *ptr, char **pps, ssize_t *plen, size_t *pbuflen, int depth)
|
||||
{
|
||||
struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
|
||||
|
||||
if (tc->flags & TALLOC_FLAG_LOOP) {
|
||||
return;
|
||||
}
|
||||
|
||||
tc->flags |= TALLOC_FLAG_LOOP;
|
||||
|
||||
for (c=tc->child;c;c=c->next) {
|
||||
if (c->name == TALLOC_MAGIC_REFERENCE) {
|
||||
struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c);
|
||||
const char *name2 = talloc_get_name(handle->ptr);
|
||||
|
||||
sprintf_append(NULL, pps, plen, pbuflen,
|
||||
"%*sreference to: %s\n", depth*4, "", name2);
|
||||
|
||||
} else {
|
||||
const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c));
|
||||
|
||||
sprintf_append(NULL, pps, plen, pbuflen,
|
||||
"%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n",
|
||||
depth*4, "",
|
||||
name,
|
||||
(unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
|
||||
(unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)),
|
||||
talloc_reference_count(TC_PTR_FROM_CHUNK(c)));
|
||||
|
||||
talloc_report_depth_str(TC_PTR_FROM_CHUNK(c), pps, plen, pbuflen, depth+1);
|
||||
}
|
||||
}
|
||||
tc->flags &= ~TALLOC_FLAG_LOOP;
|
||||
}
|
||||
|
||||
/*
|
||||
report on memory usage by all children of a pointer
|
||||
*/
|
||||
char *talloc_describe_all(void)
|
||||
{
|
||||
ssize_t len = 0;
|
||||
size_t buflen = 512;
|
||||
char *s = NULL;
|
||||
|
||||
if (null_context == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sprintf_append(NULL, &s, &len, &buflen,
|
||||
"full talloc report on '%s' (total %lu bytes in %lu blocks)\n",
|
||||
talloc_get_name(null_context),
|
||||
(unsigned long)talloc_total_size(null_context),
|
||||
(unsigned long)talloc_total_blocks(null_context));
|
||||
|
||||
if (!s) {
|
||||
return NULL;
|
||||
}
|
||||
talloc_report_depth_str(null_context, &s, &len, &buflen, 1);
|
||||
return s;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
enable leak reporting on exit
|
||||
*/
|
||||
@@ -941,6 +1023,30 @@ char *talloc_strdup(const void *t, const char *p)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
append to a talloced string
|
||||
*/
|
||||
char *talloc_append_string(const void *t, char *orig, const char *append)
|
||||
{
|
||||
char *ret;
|
||||
size_t olen = strlen(orig);
|
||||
size_t alenz;
|
||||
|
||||
if (!append)
|
||||
return orig;
|
||||
|
||||
alenz = strlen(append) + 1;
|
||||
|
||||
ret = talloc_realloc(t, orig, char, olen + alenz);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
|
||||
/* append the string with the trailing \0 */
|
||||
memcpy(&ret[olen], append, alenz);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
strndup with a talloc
|
||||
*/
|
||||
@@ -949,7 +1055,7 @@ char *talloc_strndup(const void *t, const char *p, size_t n)
|
||||
size_t len;
|
||||
char *ret;
|
||||
|
||||
for (len=0; p[len] && len<n; len++) ;
|
||||
for (len=0; len<n && p[len]; len++) ;
|
||||
|
||||
ret = _talloc(t, len + 1);
|
||||
if (!ret) { return NULL; }
|
||||
@@ -974,10 +1080,14 @@ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
|
||||
int len;
|
||||
char *ret;
|
||||
va_list ap2;
|
||||
char c;
|
||||
|
||||
VA_COPY(ap2, ap);
|
||||
|
||||
len = vsnprintf(NULL, 0, fmt, ap2);
|
||||
/* this call looks strange, but it makes it work on older solaris boxes */
|
||||
if ((len = vsnprintf(&c, 1, fmt, ap2)) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = _talloc(t, len+1);
|
||||
if (ret) {
|
||||
@@ -1029,7 +1139,15 @@ static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
|
||||
VA_COPY(ap2, ap);
|
||||
|
||||
s_len = tc->size - 1;
|
||||
len = vsnprintf(NULL, 0, fmt, ap2);
|
||||
if ((len = vsnprintf(NULL, 0, fmt, ap2)) <= 0) {
|
||||
/* Either the vsnprintf failed or the format resulted in
|
||||
* no characters being formatted. In the former case, we
|
||||
* ought to return NULL, in the latter we ought to return
|
||||
* the original string. Most current callers of this
|
||||
* function expect it to never return NULL.
|
||||
*/
|
||||
return s;
|
||||
}
|
||||
|
||||
s = talloc_realloc(NULL, s, char, s_len + len+1);
|
||||
if (!s) return NULL;
|
||||
@@ -1133,11 +1251,45 @@ size_t talloc_get_size(const void *context)
|
||||
return tc->size;
|
||||
}
|
||||
|
||||
talloc_fail_handler *talloc_set_fail_handler(talloc_fail_handler *handler,
|
||||
void *data)
|
||||
/*
|
||||
find a parent of this context that has the given name, if any
|
||||
*/
|
||||
void *talloc_find_parent_byname(const void *context, const char *name)
|
||||
{
|
||||
talloc_fail_handler *old = malloc_fail_handler;
|
||||
malloc_fail_handler = handler;
|
||||
malloc_fail_data = data;
|
||||
return old;
|
||||
struct talloc_chunk *tc;
|
||||
|
||||
if (context == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tc = talloc_chunk_from_ptr(context);
|
||||
while (tc) {
|
||||
if (tc->name && strcmp(tc->name, name) == 0) {
|
||||
return TC_PTR_FROM_CHUNK(tc);
|
||||
}
|
||||
while (tc && tc->prev) tc = tc->prev;
|
||||
tc = tc->parent;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
show the parentage of a context
|
||||
*/
|
||||
void talloc_show_parents(const void *context, FILE *file)
|
||||
{
|
||||
struct talloc_chunk *tc;
|
||||
|
||||
if (context == NULL) {
|
||||
fprintf(file, "talloc no parents for NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
tc = talloc_chunk_from_ptr(context);
|
||||
fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
|
||||
while (tc) {
|
||||
fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
|
||||
while (tc && tc->prev) tc = tc->prev;
|
||||
tc = tc->parent;
|
||||
}
|
||||
}
|
||||
+23
-13
@@ -6,19 +6,23 @@
|
||||
|
||||
Copyright (C) Andrew Tridgell 2004-2005
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
** NOTE! The following LGPL license applies to the talloc
|
||||
** library. This does NOT imply that all of Samba is released
|
||||
** under the LGPL
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* this is only needed for compatibility with the old talloc */
|
||||
@@ -58,13 +62,18 @@ typedef void TALLOC_CTX;
|
||||
#define malloc_array_p(type, count) (type *)realloc_array(NULL, sizeof(type), count)
|
||||
#define realloc_p(p, type, count) (type *)realloc_array(p, sizeof(type), count)
|
||||
|
||||
#if 0
|
||||
/* Not correct for Samba3. */
|
||||
#define data_blob(ptr, size) data_blob_named(ptr, size, "DATA_BLOB: "__location__)
|
||||
#define data_blob_talloc(ctx, ptr, size) data_blob_talloc_named(ctx, ptr, size, "DATA_BLOB: "__location__)
|
||||
#define data_blob_dup_talloc(ctx, blob) data_blob_talloc_named(ctx, (blob)->data, (blob)->length, "DATA_BLOB: "__location__)
|
||||
#endif
|
||||
|
||||
#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type)
|
||||
#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type)
|
||||
|
||||
#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type)
|
||||
|
||||
|
||||
#if TALLOC_DEPRECATED
|
||||
#define talloc_zero_p(ctx, type) talloc_zero(ctx, type)
|
||||
@@ -117,6 +126,7 @@ void *_talloc_zero(const void *ctx, size_t size, const char *name);
|
||||
void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name);
|
||||
char *talloc_strdup(const void *t, const char *p);
|
||||
char *talloc_strndup(const void *t, const char *p, size_t n);
|
||||
char *talloc_append_string(const void *t, char *orig, const char *append);
|
||||
char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
|
||||
char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
|
||||
char *talloc_asprintf_append(char *s,
|
||||
@@ -127,8 +137,8 @@ void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned
|
||||
void *talloc_realloc_fn(const void *context, void *ptr, size_t size);
|
||||
void *talloc_autofree_context(void);
|
||||
size_t talloc_get_size(const void *ctx);
|
||||
void *talloc_find_parent_byname(const void *ctx, const char *name);
|
||||
void talloc_show_parents(const void *context, FILE *file);
|
||||
|
||||
typedef int talloc_fail_handler(void *);
|
||||
talloc_fail_handler *talloc_set_fail_handler(talloc_fail_handler *, void *);
|
||||
#endif
|
||||
|
||||
@@ -1231,39 +1231,17 @@ static void process_message(struct connection *conn, struct buffered_data *in)
|
||||
conn->transaction = NULL;
|
||||
}
|
||||
|
||||
static int out_of_mem(void *data)
|
||||
{
|
||||
longjmp(*(jmp_buf *)data, 1);
|
||||
}
|
||||
|
||||
static void consider_message(struct connection *conn)
|
||||
{
|
||||
jmp_buf talloc_fail;
|
||||
|
||||
if (verbose)
|
||||
xprintf("Got message %s len %i from %p\n",
|
||||
sockmsg_string(conn->in->hdr.msg.type),
|
||||
conn->in->hdr.msg.len, conn);
|
||||
|
||||
/* For simplicity, we kill the connection on OOM. */
|
||||
talloc_set_fail_handler(out_of_mem, &talloc_fail);
|
||||
if (setjmp(talloc_fail)) {
|
||||
talloc_free(conn);
|
||||
goto end;
|
||||
}
|
||||
|
||||
process_message(conn, conn->in);
|
||||
|
||||
talloc_free(conn->in);
|
||||
conn->in = new_buffer(conn);
|
||||
|
||||
end:
|
||||
talloc_set_fail_handler(NULL, NULL);
|
||||
if (talloc_total_blocks(NULL)
|
||||
!= talloc_total_blocks(talloc_autofree_context()) + 1) {
|
||||
talloc_report_full(NULL, stderr);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/* Errors in reading or allocating here mean we get out of sync, so we
|
||||
|
||||