24 RCSID(
"$Id: 4625ca1d38d3341c6b8475f480310ff3fb369d01 $")
26 #include <freeradius-devel/util/atexit.h>
27 #include <freeradius-devel/util/debug.h>
28 #include <freeradius-devel/util/dlist.h>
29 #include <freeradius-devel/util/sbuff.h>
30 #include <freeradius-devel/util/strerror.h>
31 #include <freeradius-devel/util/syserror.h>
58 tmp = talloc(NULL,
bool);
59 null_ctx = talloc_parent(tmp);
71 talloc_set_destructor(d->
ds, NULL);
83 talloc_set_destructor(ds->
d, NULL);
145 talloc_set_destructor(d->
ds, NULL);
149 talloc_set_destructor(d, NULL);
207 rounded =
ROUND_UP(size, alignment);
208 if (rounded == 0) rounded = alignment;
210 array_size = rounded + alignment;
237 pool = talloc_pool(NULL, 1024);
243 chunk = talloc_size(pool, 1);
244 if (
unlikely(chunk == NULL))
goto oom;
250 if (!
fr_cond_assert((chunk > pool) && ((uintptr_t)chunk < ((uintptr_t)pool + 1024)))) {
264 t_hdr_size = (uintptr_t)chunk - (uintptr_t)pool;
277 static pthread_once_t once_control = PTHREAD_ONCE_INIT;
314 size_t rounded, alloced, page_size = (
size_t)getpagesize();
320 size += (hdr_size * headers);
330 if (size % page_size == 0) {
333 rounded =
ROUND_UP(size, page_size);
342 alloced = rounded + page_size;
343 pool = talloc_pool(ctx, alloced);
355 if ((uintptr_t)pool % page_size != 0) {
365 pad_size = ((uintptr_t)
next - (uintptr_t)pool);
366 if (pad_size > hdr_size) {
367 pad_size -= hdr_size;
372 padding = talloc_size(pool, pad_size);
387 fr_assert(((uintptr_t)*start % page_size) == 0);
394 fr_assert(((uintptr_t)*end_len % page_size) == 0);
404 fr_assert(((uintptr_t)*start + *end_len) <= ((uintptr_t)pool + alloced));
449 n = talloc_strdup(ctx, p);
451 talloc_set_type(
n,
char);
473 n = talloc_strndup(ctx, p, talloc_array_length(p) - 1);
475 talloc_set_type(
n,
char);
498 n = talloc_vasprintf(ctx,
fmt, ap);
501 talloc_set_type(
n,
char);
523 n = talloc_vasprintf(ctx,
fmt, ap);
525 talloc_set_type(
n,
char);
539 size_t inlen = talloc_array_length(
in);
543 p = talloc_array(ctx,
char,
inlen);
568 p = talloc_array(ctx,
char,
inlen + 1);
598 to_len = talloc_array_length(to);
599 if (to[to_len - 1] ==
'\0') to_len--;
602 n = talloc_realloc_size(ctx, to, to_len + from_len + 1);
604 fr_strerror_printf(
"Extending bstr buffer to %zu bytes failed", to_len + from_len + 1);
608 memcpy(
n + to_len, from, from_len);
609 n[to_len + from_len] =
'\0';
610 talloc_set_type(
n,
char);
633 n = talloc_array(ctx,
char,
inlen);
638 n = talloc_realloc_size(ctx,
in,
inlen + 1);
642 talloc_set_type(
n,
char);
662 size_t to_len, from_len, total_len;
665 if (!to || !from)
return NULL;
667 to_len = talloc_array_length(to);
668 from_len = talloc_array_length(from);
669 total_len = to_len + (from_len - 1);
671 out = talloc_realloc(ctx, to,
char, total_len);
672 if (!
out)
return NULL;
674 memcpy(
out + (to_len - 1), from, from_len);
675 out[total_len - 1] =
'\0';
698 va_list ap_val, ap_len;
701 size_t to_len, total_len = 0;
704 if (!to)
return NULL;
707 va_copy(ap_len, ap_val);
709 total_len += to_len = talloc_array_length(to) - 1;
714 for (i = 0; i < argc; i++) {
717 arg = va_arg(ap_len,
char *);
720 total_len += (talloc_array_length(arg) - 1);
726 if (total_len == to_len) {
732 out = talloc_realloc(ctx, to,
char, total_len + 1);
733 if (!
out)
goto finish;
740 for (i = 0; i < argc; i++) {
744 arg = va_arg(ap_val,
char *);
747 len = talloc_array_length(arg) - 1;
776 a_len = talloc_array_length(a);
777 b_len = talloc_array_length(b);
779 if (a_len > b_len)
return +1;
780 if (a_len < b_len)
return -1;
782 return memcmp(a, b, a_len);
800 a_len = talloc_array_length(a);
801 b_len = talloc_array_length(b);
803 if (a_len > b_len)
return +1;
804 if (a_len < b_len)
return -1;
806 return memcmp(a, b, a_len);
827 memcpy(&to_free, &ptr,
sizeof(to_free));
829 ref_count = talloc_reference_count(to_free);
830 if (ref_count == 0) {
833 talloc_unlink(talloc_parent(ptr), to_free);
859 if (!
array)
return NULL;
861 len = talloc_array_length(
array);
862 ctx = talloc_parent(
array);
863 size = talloc_get_size(
array) / talloc_array_length(
array);
865 new = _talloc_realloc_array(ctx,
array, size, len + 1, talloc_get_name(
array));
866 if (!
new)
return NULL;
889 if (!
array)
return NULL;
891 len = talloc_array_length(
array);
892 ctx = talloc_parent(
array);
893 size = talloc_get_size(
array) / talloc_array_length(
array);
895 if ((len - 1) == 0)
return NULL;
897 if (
array[len - 1] != NULL)
return NULL;
899 new = _talloc_realloc_array(ctx,
array, size, len - 1, talloc_get_name(
array));
900 if (!
new)
return NULL;
917 size_t len = talloc_array_length(
array);
918 char const *
const * p;
919 char const *
const * end;
921 .name = __FUNCTION__,
925 if (sep) e_rules.subs[(
uint8_t)*sep] = *sep;
932 if (sep && ((p + 1) < end)) {
945 talloc_set_destructor(af, NULL);
1010 while (list->
next != NULL) {
1043 if (!child)
return NULL;
1057 if (!child)
return NULL;
static int const char * fmt
unsigned int fr_atexit_global_disarm(bool uctx_scope, fr_atexit_t func, void const *uctx)
Remove a specific global destructor (without executing it)
#define fr_atexit_thread_local_disarm(...)
#define fr_atexit_global(_func, _uctx)
Add a free function to the global free list.
#define fr_atexit_thread_local(_name, _free, _uctx)
fr_dcursor_eval_t void const * uctx
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define ROUND_UP(_num, _mul)
Round up - Works in all cases, but is slower.
static size_t array[MY_ARRAY_SIZE]
ssize_t fr_sbuff_in_strcpy(fr_sbuff_t *sbuff, char const *str)
Copy bytes into the sbuff up to the first \0.
ssize_t fr_sbuff_in_escape(fr_sbuff_t *sbuff, char const *in, size_t inlen, fr_sbuff_escape_rules_t const *e_rules)
Print an escaped string to an sbuff.
#define FR_SBUFF_RETURN(_func, _sbuff,...)
#define FR_SBUFF(_sbuff_or_marker)
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
TALLOC_CTX * talloc_autofree_context_thread_local(void)
Get a thread-safe autofreed ctx that will be freed when the thread or process exits.
static int _talloc_destructor_fire(fr_talloc_destructor_t *d)
Called with the fire_ctx is freed.
char * talloc_bstrdup(TALLOC_CTX *ctx, char const *in)
Binary safe strdup function.
TALLOC_CHILD_CTX * talloc_child_ctx_init(TALLOC_CTX *ctx)
Allocate and initialize a TALLOC_CHILD_CTX.
static int _talloc_link_ctx_free(UNUSED void *parent, void *child)
char * talloc_typed_vasprintf(TALLOC_CTX *ctx, char const *fmt, va_list ap)
Call talloc vasprintf, setting the type on the new chunk correctly.
static TALLOC_CTX * global_ctx
uint8_t * talloc_typed_memdup(TALLOC_CTX *ctx, uint8_t const *in, size_t inlen)
Call talloc_memdup, setting the type on the new chunk correctly.
static int _autofree_on_exit(void *af)
Callback to free the autofree ctx on global exit.
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
char * talloc_buffer_append_variadic_buffer(TALLOC_CTX *ctx, char *to, int argc,...)
Concatenate to + ...
void * talloc_null_ctx(void)
Retrieve the current talloc NULL ctx.
struct talloc_child_ctx_s * next
char * talloc_buffer_append_buffer(TALLOC_CTX *ctx, char *to, char const *from)
Concatenate to + from.
fr_slen_t talloc_array_concat(fr_sbuff_t *out, char const *const *array, char const *sep)
Concat an array of strings (not NULL terminated), with a string separator.
ssize_t talloc_hdr_size(void)
Calculate the size of the talloc chunk header.
static int _autofree_thread_local_destructor(TALLOC_CTX *af)
Ensures in the autofree ctx is manually freed, things don't explode atexit.
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
int talloc_memcmp_array(uint8_t const *a, uint8_t const *b)
Compares two talloced uint8_t arrays with memcmp.
TALLOC_CHILD_CTX * talloc_child_ctx_alloc(TALLOC_CHILD_CTX *parent)
Allocate a TALLOC_CHILD_CTX from a parent.
TALLOC_CTX * talloc_autofree_context_global(void)
char * talloc_bstr_realloc(TALLOC_CTX *ctx, char *in, size_t inlen)
Trim a bstr (char) buffer.
static int _talloc_destructor_disarm(fr_talloc_destructor_disarm_t *ds)
Called when the disarm_ctx ctx is freed.
TALLOC_CTX * talloc_page_aligned_pool(TALLOC_CTX *ctx, void **start, size_t *end_len, unsigned int headers, size_t size)
Return a page aligned talloc memory pool.
int talloc_link_ctx(TALLOC_CTX *parent, TALLOC_CTX *child)
Link two different parent and child contexts, so the child is freed before the parent.
char * talloc_bstr_append(TALLOC_CTX *ctx, char *to, char const *from, size_t from_len)
Append a bstr to a bstr.
static void _talloc_hdr_size(void)
Calculate the size of talloc chunk headers, once, on startup.
static _Thread_local TALLOC_CTX * thread_local_ctx
char * talloc_typed_strdup_buffer(TALLOC_CTX *ctx, char const *p)
Call talloc_strndup, setting the type on the new chunk correctly.
void ** talloc_array_null_strip(void **array)
Remove a NULL termination pointer from an array of pointers.
static size_t t_hdr_size
How big the chunk header is.
TALLOC_CTX * talloc_aligned_array(TALLOC_CTX *ctx, void **start, size_t alignment, size_t size)
Return a page aligned talloc memory array.
static int _child_ctx_free(TALLOC_CHILD_CTX *list)
void ** talloc_array_null_terminate(void **array)
Add a NULL pointer to an array of pointers.
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
void talloc_free_data(void *data)
A wrapper that can be passed to tree or hash alloc functions that take a fr_free_t.
int talloc_decrease_ref_count(void const *ptr)
Decrease the reference count on a ptr.
void talloc_destructor_disarm(fr_talloc_destructor_t *d)
Disarm a destructor and free all memory allocated in the trigger ctxs.
fr_talloc_destructor_t * talloc_destructor_add(TALLOC_CTX *fire_ctx, TALLOC_CTX *disarm_ctx, fr_talloc_free_func_t func, void const *uctx)
Add an additional destructor to a talloc chunk.
int talloc_memcmp_bstr(char const *a, char const *b)
Compares two talloced char arrays with memcmp.
static int _autofree_global_destructor(TALLOC_CTX *af)
Ensures in the autofree ctx is manually freed, things don't explode atexit.
Functions which we wish were included in the standard talloc distribution.
fr_talloc_free_func_t func
Free function.
fr_talloc_destructor_t * d
Destructor to disarm.
static TALLOC_CTX * talloc_init_const(char const *name)
Allocate a top level chunk with a constant name.
void * uctx
uctx to pass to free function.
int(* fr_talloc_free_func_t)(void *fire_ctx, void *uctx)
fr_talloc_destructor_disarm_t * ds
Chunk to free.
Structure to record a destructor to disarm if a child talloc chunk is freed.
Structure to record a destructor operation on a specific talloc chunk.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)
FR_SBUFF_SET_RETURN(sbuff, &our_sbuff)
static size_t char fr_sbuff_t size_t inlen
static size_t char ** out