summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorJeremy Kerr <jk@ozlabs.org>2008-12-15 15:22:34 +1100
committerJeremy Kerr <jk@ozlabs.org>2008-12-15 15:22:34 +1100
commit32e6a41f33e5576716b351bd473a27939fe94fa1 (patch)
tree0d6b75ac0a02d2496416095405cb9498777c3beb /lib
parent000a92b4fa909c432732ac3ed8f28eeeaeac70ee (diff)
downloadtalos-petitboot-32e6a41f33e5576716b351bd473a27939fe94fa1.tar.gz
talos-petitboot-32e6a41f33e5576716b351bd473a27939fe94fa1.zip
Initial support for multiple UIs
Move the device discovery code from separate udev helpers to a single process to listen on two sockets: one SOCK_DGRAM for incoming udev events, and one SOCK_STREAM for UIs to connect. Initial support for client/server infrastructure, still need to wire-up the udev messages. Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/list/list.c24
-rw-r--r--lib/list/list.h39
-rw-r--r--lib/pb-protocol/pb-protocol.c307
-rw-r--r--lib/pb-protocol/pb-protocol.h57
-rw-r--r--lib/talloc/talloc.c1130
-rw-r--r--lib/talloc/talloc.h137
6 files changed, 1694 insertions, 0 deletions
diff --git a/lib/list/list.c b/lib/list/list.c
new file mode 100644
index 0000000..d9bc532
--- /dev/null
+++ b/lib/list/list.c
@@ -0,0 +1,24 @@
+
+#include "list/list.h"
+
+void list_init(struct list *list)
+{
+ list->head.next = &list->head;
+ list->head.prev = &list->head;
+}
+
+void list_add(struct list *list, struct list_item *new)
+{
+ new->next = list->head.next;
+ new->prev = &list->head;
+
+ list->head.next->prev = new;
+ list->head.next = new;
+}
+
+void list_remove(struct list_item *item)
+{
+ item->next->prev = item->prev;
+ item->prev->next = item->next;
+}
+
diff --git a/lib/list/list.h b/lib/list/list.h
new file mode 100644
index 0000000..3858cf6
--- /dev/null
+++ b/lib/list/list.h
@@ -0,0 +1,39 @@
+#ifndef _LIST_H
+#define _LIST_H
+
+struct list_item {
+ struct list_item *prev, *next;
+};
+
+struct list {
+ struct list_item head;
+};
+
+#ifndef container_of
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+#endif
+
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+#define list_for_each(list, pos) \
+ for (pos = (list)->head.next; pos != ((list)->head); pos = pos->next)
+
+#define list_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+#define list_for_each_entry(list, pos, member) \
+ for (pos = list_entry((list)->head.next, typeof(*pos), member); \
+ &pos->member != &(list)->head; \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+void list_init(struct list *list);
+
+void list_add(struct list *list, struct list_item *item);
+
+void list_remove(struct list_item *item);
+
+#endif /* _LIST_H */
diff --git a/lib/pb-protocol/pb-protocol.c b/lib/pb-protocol/pb-protocol.c
new file mode 100644
index 0000000..2fd76c5
--- /dev/null
+++ b/lib/pb-protocol/pb-protocol.c
@@ -0,0 +1,307 @@
+
+#include <string.h>
+#include <stdint.h>
+#include <asm/byteorder.h>
+
+#include <talloc/talloc.h>
+
+#include "pb-protocol.h"
+
+
+/* Message format:
+ *
+ * 4-byte action, determines the remaining message content
+ * 4-byte total payload len
+ * - not including action and payload len header
+ *
+ * action = 0x1: device add message
+ * payload:
+ * 4-byte len, id
+ * 4-byte len, name
+ * 4-byte len, description
+ * 4-byte len, icon_file
+ *
+ * 4-byte option count
+ * for each option:
+ * 4-byte len, id
+ * 4-byte len, name
+ * 4-byte len, description
+ * 4-byte len, icon_file
+ * 4-byte len, boot_image_file
+ * 4-byte len, initrd_file
+ * 4-byte len, boot_args
+ *
+ * action = 0x2: device remove message
+ * payload:
+ * 4-byte len, id
+ */
+
+
+/* Write a string into the buffer, starting at pos.
+ *
+ * Returns the total length used for the write, including length header.
+ */
+int pb_protocol_serialise_string(char *pos, const char *str)
+{
+ int len = 0;
+
+ if (str)
+ len = strlen(str);
+
+ *(uint32_t *)pos = __cpu_to_be32(len);
+ pos += sizeof(uint32_t);
+
+ memcpy(pos, str, len);
+
+ return len + sizeof(uint32_t);
+}
+
+/* Read a string from a buffer, allocating the new string as necessary.
+ *
+ * @param[in] ctx The talloc context to base the allocation on
+ * @param[in,out] pos Where to start reading
+ * @param[in,out] len The amount of data remaining in the buffer
+ * @param[out] str Pointer to resuling string
+ * @return zero on success, non-zero on failure
+ */
+static int read_string(void *ctx, char **pos, int *len, char **str)
+{
+ uint32_t str_len, read_len;
+
+ if (*len < sizeof(uint32_t))
+ return -1;
+
+ str_len = __be32_to_cpu(*(uint32_t *)(*pos));
+ read_len = sizeof(uint32_t);
+
+ if (read_len + str_len > *len)
+ return -1;
+
+ if (str_len == 0)
+ *str = NULL;
+ else
+ *str = talloc_strndup(ctx, *pos + read_len, str_len);
+
+ read_len += str_len;
+
+ /* all ok, update the caller's pointers */
+ *pos += read_len;
+ *len -= read_len;
+
+ return 0;
+}
+
+char *pb_protocol_deserialise_string(void *ctx,
+ struct pb_protocol_message *message)
+{
+ char *buf, *str;
+ int len;
+
+ len = message->payload_len;
+ buf = message->payload;
+
+ if (read_string(ctx, &buf, &len, &str))
+ return NULL;
+
+ return str;
+}
+
+static int optional_strlen(const char *str)
+{
+ if (!str)
+ return 0;
+ return strlen(str);
+}
+
+int pb_protocol_device_len(struct device *dev)
+{
+ int len, i;
+
+ len = 4 + optional_strlen(dev->id) +
+ 4 + optional_strlen(dev->name) +
+ 4 + optional_strlen(dev->description) +
+ 4 + optional_strlen(dev->icon_file) +
+ 4;
+
+ for (i = 0; i < dev->n_options; i++) {
+ struct boot_option *opt = &dev->options[i];
+ len += 4 + optional_strlen(opt->id) +
+ 4 + optional_strlen(opt->name) +
+ 4 + optional_strlen(opt->description) +
+ 4 + optional_strlen(opt->icon_file) +
+ 4 + optional_strlen(opt->boot_image_file) +
+ 4 + optional_strlen(opt->initrd_file) +
+ 4 + optional_strlen(opt->boot_args);
+ }
+
+ return len;
+}
+
+int pb_protocol_serialise_device(struct device *dev, char *buf, int buf_len)
+{
+ char *pos;
+ int i;
+
+ pos = buf;
+
+ /* construct payload into buffer */
+ pos += pb_protocol_serialise_string(pos, dev->id);
+ pos += pb_protocol_serialise_string(pos, dev->name);
+ pos += pb_protocol_serialise_string(pos, dev->description);
+ pos += pb_protocol_serialise_string(pos, dev->icon_file);
+
+ /* write option count */
+ *(uint32_t *)pos = __cpu_to_be32(dev->n_options);
+ pos += sizeof(uint32_t);
+
+ /* write each option */
+ for (i = 0; i < dev->n_options; i++) {
+ struct boot_option *opt = &dev->options[i];
+ pos += pb_protocol_serialise_string(pos, opt->id);
+ pos += pb_protocol_serialise_string(pos, opt->name);
+ pos += pb_protocol_serialise_string(pos, opt->description);
+ pos += pb_protocol_serialise_string(pos, opt->icon_file);
+ pos += pb_protocol_serialise_string(pos, opt->boot_image_file);
+ pos += pb_protocol_serialise_string(pos, opt->initrd_file);
+ pos += pb_protocol_serialise_string(pos, opt->boot_args);
+ }
+
+ return 0;
+}
+
+int pb_protocol_write_message(int fd, struct pb_protocol_message *message)
+{
+ int total_len, rc;
+ char *pos;
+
+ total_len = sizeof(*message) + message->payload_len;
+
+ message->payload_len = __cpu_to_be32(message->payload_len);
+ message->action = __cpu_to_be32(message->action);
+
+ for (pos = (void *)message; total_len;) {
+ rc = write(fd, pos, total_len);
+
+ if (rc <= 0)
+ break;
+
+ total_len -= rc;
+ pos += rc;
+ }
+
+ talloc_free(message);
+
+ return total_len ? -1 : 0;
+}
+
+struct pb_protocol_message *pb_protocol_create_message(void *ctx,
+ int action, int payload_len)
+{
+ struct pb_protocol_message *message;
+
+ if (payload_len > PB_PROTOCOL_MAX_PAYLOAD_SIZE)
+ return NULL;
+
+ message = talloc_size(ctx, sizeof(*message) + payload_len);
+
+ /* we convert these to big-endian in write_message() */
+ message->action = action;
+ message->payload_len = payload_len;
+
+ return message;
+
+}
+
+struct pb_protocol_message *pb_protocol_read_message(void *ctx, int fd)
+{
+ struct pb_protocol_message *message, m;
+ int rc, len;
+
+ /* use the stack for the initial 8-byte read */
+
+ rc = read(fd, &m, sizeof(m));
+ if (rc != sizeof(m))
+ return NULL;
+
+ m.payload_len = __be32_to_cpu(m.payload_len);
+ m.action = __be32_to_cpu(m.action);
+
+ if (m.payload_len > PB_PROTOCOL_MAX_PAYLOAD_SIZE)
+ return NULL;
+
+ message = talloc_size(ctx, sizeof(m) + m.payload_len);
+ memcpy(message, &m, sizeof(m));
+
+ for (len = 0; len < m.payload_len;) {
+ rc = read(fd, message->payload + len, m.payload_len - len);
+
+ if (rc <= 0) {
+ talloc_free(message);
+ return NULL;
+ }
+
+ len += rc;
+ }
+
+ return message;
+}
+
+
+struct device *pb_protocol_deserialise_device(void *ctx,
+ struct pb_protocol_message *message)
+{
+ struct device *dev;
+ char *pos;
+ int i, len;
+
+ len = message->payload_len;
+ pos = message->payload;
+
+ dev = talloc(ctx, struct device);
+
+ if (read_string(dev, &pos, &len, &dev->id))
+ goto out_err;
+
+ if (read_string(dev, &pos, &len, &dev->name))
+ goto out_err;
+
+ if (read_string(dev, &pos, &len, &dev->description))
+ goto out_err;
+
+ if (read_string(dev, &pos, &len, &dev->icon_file))
+ goto out_err;
+
+ dev->n_options = __be32_to_cpu(*(uint32_t *)pos);
+ dev->options = talloc_array(dev, struct boot_option, dev->n_options);
+ pos += sizeof(uint32_t);
+
+ for (i = 0; i < dev->n_options; i++) {
+ struct boot_option *opt = &dev->options[i];
+
+ if (read_string(opt, &pos, &len, &opt->id))
+ goto out_err;
+ if (read_string(opt, &pos, &len, &opt->name))
+ goto out_err;
+ if (read_string(opt, &pos, &len,
+ &opt->description))
+ goto out_err;
+ if (read_string(opt, &pos, &len,
+ &opt->icon_file))
+ goto out_err;
+ if (read_string(opt, &pos, &len,
+ &opt->boot_image_file))
+ goto out_err;
+ if (read_string(opt, &pos, &len,
+ &opt->initrd_file))
+ goto out_err;
+ if (read_string(opt, &pos, &len,
+ &opt->boot_args))
+ goto out_err;
+ }
+
+ return dev;
+
+out_err:
+ talloc_free(dev);
+ return NULL;
+}
diff --git a/lib/pb-protocol/pb-protocol.h b/lib/pb-protocol/pb-protocol.h
new file mode 100644
index 0000000..7b557d6
--- /dev/null
+++ b/lib/pb-protocol/pb-protocol.h
@@ -0,0 +1,57 @@
+#ifndef _PB_PROTOCOL_H
+#define _PB_PROTOCOL_H
+
+#include <stdint.h>
+
+#define PB_SOCKET_PATH "/tmp/petitboot.ui"
+
+#define PB_PROTOCOL_MAX_PAYLOAD_SIZE 4096
+
+enum pb_protocol_action {
+ PB_PROTOCOL_ACTION_ADD = 0x1,
+ PB_PROTOCOL_ACTION_REMOVE = 0x2,
+};
+
+struct pb_protocol_message {
+ uint32_t action;
+ uint32_t payload_len;
+ char payload[];
+};
+
+struct device {
+ char *id;
+ char *name;
+ char *description;
+ char *icon_file;
+
+ struct boot_option {
+ char *id;
+ char *name;
+ char *description;
+ char *icon_file;
+ char *boot_image_file;
+ char *initrd_file;
+ char *boot_args;
+ } *options;
+ int n_options;
+};
+
+int pb_protocol_device_len(struct device *dev);
+
+int pb_protocol_serialise_string(char *pos, const char *str);
+char *pb_protocol_deserialise_string(void *ctx,
+ struct pb_protocol_message *message);
+
+int pb_protocol_serialise_device(struct device *dev, char *buf, int buf_len);
+
+int pb_protocol_write_message(int fd, struct pb_protocol_message *message);
+
+struct pb_protocol_message *pb_protocol_create_message(void *ctx,
+ int action, int payload_len);
+
+struct pb_protocol_message *pb_protocol_read_message(void *ctx, int fd);
+
+struct device *pb_protocol_deserialise_device(void *ctx,
+ struct pb_protocol_message *message);
+
+#endif /* _PB_PROTOCOL_H */
diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c
new file mode 100644
index 0000000..c660870
--- /dev/null
+++ b/lib/talloc/talloc.c
@@ -0,0 +1,1130 @@
+/*
+ Samba Unix SMB/CIFS implementation.
+
+ Samba trivial allocation library - new interface
+
+ 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,
+ 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.
+*/
+
+/*
+ inspired by http://swapped.cc/halloc/
+*/
+
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* nfsim additions */
+#define HAVE_SYS_TYPES_H
+#define HAVE_UNISTD_H
+#define HAVE_STDARG_H
+#define HAVE_STDINT_H
+#define HAVE_VA_COPY
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#include "talloc.h"
+
+/* use this to force every realloc to change the pointer, to stress test
+ code that might not cope */
+#define ALWAYS_REALLOC 0
+
+
+#define MAX_TALLOC_SIZE 0x10000000
+#define TALLOC_MAGIC 0xe814ec4f
+#define TALLOC_MAGIC_FREE 0x7faebef3
+#define TALLOC_MAGIC_REFERENCE ((const char *)1)
+
+/* by default we abort when given a bad pointer (such as when talloc_free() is
+ * called on a pointer that came from malloc() */
+#ifndef TALLOC_ABORT
+#define TALLOC_ABORT(reason) abort()
+#endif
+
+#ifndef discard_const_p
+#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
+# define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
+#else
+# define discard_const_p(type, ptr) ((type *)(ptr))
+#endif
+#endif
+
+/* this null_context is only used if talloc_enable_leak_report() or
+ talloc_enable_leak_report_full() is called, otherwise it remains
+ NULL
+*/
+static const void *null_context;
+static void *cleanup_context;
+
+
+struct talloc_reference_handle {
+ struct talloc_reference_handle *next, *prev;
+ void *ptr;
+};
+
+typedef int (*talloc_destructor_t)(void *);
+
+struct talloc_chunk {
+ struct talloc_chunk *next, *prev;
+ struct talloc_chunk *parent, *child;
+ struct talloc_reference_handle *refs;
+ size_t size;
+ talloc_destructor_t destructor;
+ const char *name;
+ union {
+ unsigned magic;
+ double align_dummy;
+ } u;
+};
+
+/* 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->u.magic != TALLOC_MAGIC) {
+ if (tc->u.magic == TALLOC_MAGIC_FREE) {
+ TALLOC_ABORT("Bad talloc magic value - double free");
+ } else {
+ TALLOC_ABORT("Bad talloc magic value - unknown value");
+ }
+ }
+
+ return tc;
+}
+
+/* hook into the front of the list */
+#define _TLIST_ADD(list, p) \
+do { \
+ if (!(list)) { \
+ (list) = (p); \
+ (p)->next = (p)->prev = NULL; \
+ } else { \
+ (list)->prev = (p); \
+ (p)->next = (list); \
+ (p)->prev = NULL; \
+ (list) = (p); \
+ }\
+} while (0)
+
+/* remove an element from a list - element doesn't have to be in list. */
+#define _TLIST_REMOVE(list, p) \
+do { \
+ if ((p) == (list)) { \
+ (list) = (p)->next; \
+ if (list) (list)->prev = NULL; \
+ } else { \
+ if ((p)->prev) (p)->prev->next = (p)->next; \
+ if ((p)->next) (p)->next->prev = (p)->prev; \
+ } \
+ if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
+} while (0)
+
+
+/*
+ return the parent chunk of a pointer
+*/
+static struct talloc_chunk *talloc_parent_chunk(const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ while (tc->prev) tc=tc->prev;
+ return tc->parent;
+}
+
+void *talloc_parent(const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_parent_chunk(ptr);
+ return (void *)(tc+1);
+}
+
+/*
+ Allocate a bit of memory as a child of an existing pointer
+*/
+void *_talloc(const void *context, size_t size)
+{
+ struct talloc_chunk *tc;
+
+ if (context == NULL) {
+ context = null_context;
+ }
+
+ if (size >= MAX_TALLOC_SIZE) {
+ return NULL;
+ }
+
+ tc = malloc(sizeof(*tc)+size);
+ if (tc == NULL) return NULL;
+
+ tc->size = size;
+ tc->u.magic = TALLOC_MAGIC;
+ tc->destructor = NULL;
+ tc->child = NULL;
+ tc->name = NULL;
+ tc->refs = NULL;
+
+ if (context) {
+ struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
+
+ tc->parent = parent;
+
+ if (parent->child) {
+ parent->child->parent = NULL;
+ }
+
+ _TLIST_ADD(parent->child, tc);
+ } else {
+ tc->next = tc->prev = tc->parent = NULL;
+ }
+
+ return (void *)(tc+1);
+}
+
+
+/*
+ setup a destructor to be called on free of a pointer
+ the destructor should return 0 on success, or -1 on failure.
+ if the destructor fails then the free is failed, and the memory can
+ be continued to be used
+*/
+void talloc_set_destructor(const void *ptr, int (*destructor)(void *))
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ tc->destructor = destructor;
+}
+
+/*
+ increase the reference count on a piece of memory.
+*/
+void talloc_increase_ref_count(const void *ptr)
+{
+ talloc_reference(null_context, ptr);
+}
+
+/*
+ helper for talloc_reference()
+*/
+static int talloc_reference_destructor(void *ptr)
+{
+ struct talloc_reference_handle *handle = ptr;
+ struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr);
+ struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr);
+ if (tc1->destructor != (talloc_destructor_t)-1) {
+ tc1->destructor = NULL;
+ }
+ _TLIST_REMOVE(tc2->refs, handle);
+ talloc_free(handle);
+ return 0;
+}
+
+/*
+ make a secondary reference to a pointer, hanging off the given context.
+ the pointer remains valid until both the original caller and this given
+ context are freed.
+
+ the major use for this is when two different structures need to reference the
+ same underlying data, and you want to be able to free the two instances
+ separately, and in either order
+*/
+void *talloc_reference(const void *context, const void *ptr)
+{
+ struct talloc_chunk *tc;
+ struct talloc_reference_handle *handle;
+ if (ptr == NULL) return NULL;
+
+ tc = talloc_chunk_from_ptr(ptr);
+ handle = talloc_named_const(context, sizeof(*handle),
+ TALLOC_MAGIC_REFERENCE);
+
+ if (handle == NULL) return NULL;
+
+ /* note that we hang the destructor off the handle, not the
+ main context as that allows the caller to still setup their
+ own destructor on the context if they want to */
+ talloc_set_destructor(handle, talloc_reference_destructor);
+ handle->ptr = discard_const_p(void, ptr);
+ _TLIST_ADD(tc->refs, handle);
+ return handle->ptr;
+}
+
+/*
+ remove a secondary reference to a pointer. This undo's what
+ talloc_reference() has done. The context and pointer arguments
+ must match those given to a talloc_reference()
+*/
+static int talloc_unreference(const void *context, const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ struct talloc_reference_handle *h;
+
+ if (context == NULL) {
+ context = null_context;
+ }
+
+ 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 (h == NULL) {
+ return -1;
+ }
+
+ talloc_set_destructor(h, NULL);
+ _TLIST_REMOVE(tc->refs, h);
+ talloc_free(h);
+ return 0;
+}
+
+/*
+ remove a specific parent context from a pointer. This is a more
+ controlled varient of talloc_free()
+*/
+int talloc_unlink(const void *context, void *ptr)
+{
+ struct talloc_chunk *tc_p, *new_p;
+ void *new_parent;
+
+ if (ptr == NULL) {
+ return -1;
+ }
+
+ if (context == NULL) {
+ context = null_context;
+ }
+
+ if (talloc_unreference(context, ptr) == 0) {
+ return 0;
+ }
+
+ if (context == NULL) {
+ if (talloc_parent_chunk(ptr) != NULL) {
+ return -1;
+ }
+ } else {
+ if (talloc_chunk_from_ptr(context)
+ != talloc_parent_chunk(ptr)) {
+ return -1;
+ }
+ }
+
+ tc_p = talloc_chunk_from_ptr(ptr);
+
+ if (tc_p->refs == NULL) {
+ return talloc_free(ptr);
+ }
+
+ new_p = talloc_parent_chunk(tc_p->refs);
+ if (new_p) {
+ new_parent = new_p+1;
+ } else {
+ new_parent = NULL;
+ }
+
+ if (talloc_unreference(new_parent, ptr) != 0) {
+ return -1;
+ }
+
+ talloc_steal(new_parent, ptr);
+
+ return 0;
+}
+
+/*
+ add a name to an existing pointer - va_list version
+*/
+static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
+ PRINTF_ATTRIBUTE(2,0);
+
+static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ tc->name = talloc_vasprintf(ptr, fmt, ap);
+ if (tc->name) {
+ talloc_set_name_const(tc->name, ".name");
+ }
+}
+
+/*
+ add a name to an existing pointer
+*/
+void talloc_set_name(const void *ptr, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ talloc_set_name_v(ptr, fmt, ap);
+ va_end(ap);
+}
+
+/*
+ more efficient way to add a name to a pointer - the name must point to a
+ true string constant
+*/
+void talloc_set_name_const(const void *ptr, const char *name)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ tc->name = name;
+}
+
+/*
+ create a named talloc pointer. Any talloc pointer can be named, and
+ talloc_named() operates just like talloc() except that it allows you
+ to name the pointer.
+*/
+void *talloc_named(const void *context, size_t size, const char *fmt, ...)
+{
+ va_list ap;
+ void *ptr;
+
+ ptr = _talloc(context, size);
+ if (ptr == NULL) return NULL;
+
+ va_start(ap, fmt);
+ talloc_set_name_v(ptr, fmt, ap);
+ va_end(ap);
+
+ return ptr;
+}
+
+/*
+ create a named talloc pointer. Any talloc pointer can be named, and
+ talloc_named() operates just like talloc() except that it allows you
+ to name the pointer.
+*/
+void *talloc_named_const(const void *context, size_t size, const char *name)
+{
+ void *ptr;
+
+ ptr = _talloc(context, size);
+ if (ptr == NULL) {
+ return NULL;
+ }
+
+ talloc_set_name_const(ptr, name);
+
+ return ptr;
+}
+
+/*
+ return the name of a talloc ptr, or "UNNAMED"
+*/
+const char *talloc_get_name(const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ if (tc->name == TALLOC_MAGIC_REFERENCE) {
+ return ".reference";
+ }
+ if (tc->name) {
+ return tc->name;
+ }
+ return "UNNAMED";
+}
+
+
+/*
+ check if a pointer has the given name. If it does, return the pointer,
+ otherwise return NULL
+*/
+void *talloc_check_name(const void *ptr, const char *name)
+{
+ const char *pname;
+ if (ptr == NULL) return NULL;
+ pname = talloc_get_name(ptr);
+ if (pname == name || strcmp(pname, name) == 0) {
+ return discard_const_p(void, ptr);
+ }
+ return NULL;
+}
+
+
+/*
+ this is for compatibility with older versions of talloc
+*/
+void *talloc_init(const char *fmt, ...)
+{
+ va_list ap;
+ void *ptr;
+
+ ptr = _talloc(NULL, 0);
+ if (ptr == NULL) return NULL;
+
+ va_start(ap, fmt);
+ talloc_set_name_v(ptr, fmt, ap);
+ va_end(ap);
+
+ return ptr;
+}
+
+/*
+ this is a replacement for the Samba3 talloc_destroy_pool functionality. It
+ should probably not be used in new code. It's in here to keep the talloc
+ code consistent across Samba 3 and 4.
+*/
+static void talloc_free_children(void *ptr)
+{
+ struct talloc_chunk *tc;
+
+ if (ptr == NULL) {
+ return;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ while (tc->child) {
+ /* we need to work out who will own an abandoned child
+ if it cannot be freed. In priority order, the first
+ 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;
+ 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 (talloc_free(child) == -1) {
+ if (new_parent == null_context) {
+ struct talloc_chunk *p =
+ talloc_parent_chunk(ptr);
+ if (p) new_parent = p+1;
+ }
+ talloc_steal(new_parent, child);
+ }
+ }
+}
+
+/*
+ free a talloc pointer. This also frees all child pointers of this
+ pointer recursively
+
+ return 0 if the memory is actually freed, otherwise -1. The memory
+ will not be freed if the ref_count is > 1 or the destructor (if
+ any) returns non-zero
+*/
+int talloc_free(void *ptr)
+{
+ struct talloc_chunk *tc;
+
+ if (ptr == NULL) {
+ return -1;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ if (tc->refs) {
+ talloc_reference_destructor(tc->refs);
+ return -1;
+ }
+
+ if (tc->destructor) {
+ talloc_destructor_t d = tc->destructor;
+ if (d == (talloc_destructor_t)-1) {
+ return -1;
+ }
+ tc->destructor = (talloc_destructor_t)-1;
+ if (d(ptr) == -1) {
+ tc->destructor = d;
+ return -1;
+ }
+ tc->destructor = NULL;
+ }
+
+ talloc_free_children(ptr);
+
+ if (tc->parent) {
+ _TLIST_REMOVE(tc->parent->child, tc);
+ if (tc->parent->child) {
+ tc->parent->child->parent = tc->parent;
+ }
+ } else {
+ if (tc->prev) tc->prev->next = tc->next;
+ if (tc->next) tc->next->prev = tc->prev;
+ }
+
+ tc->u.magic = TALLOC_MAGIC_FREE;
+
+ free(tc);
+ return 0;
+}
+
+
+
+/*
+ A talloc version of realloc. The context argument is only used if
+ ptr is NULL
+*/
+void *_talloc_realloc(const void *context, void *ptr, size_t size,
+ const char *name)
+{
+ struct talloc_chunk *tc;
+ void *new_ptr;
+
+ /* size zero is equivalent to free() */
+ if (size == 0) {
+ talloc_free(ptr);
+ return NULL;
+ }
+
+ if (size >= MAX_TALLOC_SIZE) {
+ return NULL;
+ }
+
+ /* realloc(NULL) is equavalent to malloc() */
+ if (ptr == NULL) {
+ return talloc_named_const(context, size, name);
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ /* don't allow realloc on referenced pointers */
+ if (tc->refs) {
+ return NULL;
+ }
+
+ /* by resetting magic we catch users of the old memory */
+ tc->u.magic = TALLOC_MAGIC_FREE;
+
+#if ALWAYS_REALLOC
+ new_ptr = malloc(size + sizeof(*tc));
+ if (new_ptr) {
+ memcpy(new_ptr, tc, tc->size + sizeof(*tc));
+ free(tc);
+ }
+#else
+ new_ptr = realloc(tc, size + sizeof(*tc));
+#endif
+ if (!new_ptr) {
+ tc->u.magic = TALLOC_MAGIC;
+ return NULL;
+ }
+
+ tc = new_ptr;
+ tc->u.magic = TALLOC_MAGIC;
+ if (tc->parent) {
+ tc->parent->child = new_ptr;
+ }
+ if (tc->child) {
+ tc->child->parent = new_ptr;
+ }
+
+ if (tc->prev) {
+ tc->prev->next = tc;
+ }
+ if (tc->next) {
+ tc->next->prev = tc;
+ }
+
+ tc->size = size;
+ talloc_set_name_const(tc+1, name);
+
+ return (void *)(tc+1);
+}
+
+/*
+ move a lump of memory from one talloc context to another return the
+ ptr on success, or NULL if it could not be transferred.
+ passing NULL as ptr will always return NULL with no side effects.
+*/
+void *talloc_steal(const void *new_ctx, const void *ptr)
+{
+ struct talloc_chunk *tc, *new_tc;
+
+ if (!ptr) {
+ return NULL;
+ }
+
+ if (new_ctx == NULL) {
+ new_ctx = null_context;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ if (new_ctx == NULL) {
+ if (tc->parent) {
+ _TLIST_REMOVE(tc->parent->child, tc);
+ if (tc->parent->child) {
+ tc->parent->child->parent = tc->parent;
+ }
+ } else {
+ if (tc->prev) tc->prev->next = tc->next;
+ if (tc->next) tc->next->prev = tc->prev;
+ }
+
+ tc->parent = tc->next = tc->prev = NULL;
+ return discard_const_p(void, ptr);
+ }
+
+ new_tc = talloc_chunk_from_ptr(new_ctx);
+
+ if (tc == new_tc) {
+ return discard_const_p(void, ptr);
+ }
+
+ if (tc->parent) {
+ _TLIST_REMOVE(tc->parent->child, tc);
+ if (tc->parent->child) {
+ tc->parent->child->parent = tc->parent;
+ }
+ } else {
+ if (tc->prev) tc->prev->next = tc->next;
+ if (tc->next) tc->next->prev = tc->prev;
+ }
+
+ tc->parent = new_tc;
+ if (new_tc->child) new_tc->child->parent = NULL;
+ _TLIST_ADD(new_tc->child, tc);
+
+ return discard_const_p(void, ptr);
+}
+
+/*
+ return the total size of a talloc pool (subtree)
+*/
+off_t talloc_total_size(const void *ptr)
+{
+ off_t total = 0;
+ struct talloc_chunk *c, *tc;
+
+ if (ptr == NULL) {
+ ptr = null_context;
+ }
+ if (ptr == NULL) {
+ return 0;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ total = tc->size;
+ for (c=tc->child;c;c=c->next) {
+ total += talloc_total_size(c+1);
+ }
+ return total;
+}
+
+/*
+ return the total number of blocks in a talloc pool (subtree)
+*/
+off_t talloc_total_blocks(const void *ptr)
+{
+ off_t total = 0;
+ struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
+
+ total++;
+ for (c=tc->child;c;c=c->next) {
+ total += talloc_total_blocks(c+1);
+ }
+ return total;
+}
+
+/*
+ return the number of external references to a pointer
+*/
+static int talloc_reference_count(const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ struct talloc_reference_handle *h;
+ int ret = 0;
+
+ for (h=tc->refs;h;h=h->next) {
+ ret++;
+ }
+ return ret;
+}
+
+/*
+ report on memory usage by all children of a pointer, giving a full tree view
+*/
+void talloc_report_depth(const void *ptr, FILE *f, int depth)
+{
+ struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
+
+ for (c=tc->child;c;c=c->next) {
+ if (c->name == TALLOC_MAGIC_REFERENCE) {
+ struct talloc_reference_handle *handle = (void *)(c+1);
+ 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);
+ 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);
+ }
+ }
+
+}
+
+/*
+ report on memory usage by all children of a pointer, giving a full tree view
+*/
+void talloc_report_full(const void *ptr, FILE *f)
+{
+ if (ptr == NULL) {
+ ptr = null_context;
+ }
+ if (ptr == NULL) return;
+
+ fprintf(f, "full talloc report on '%s' "
+ "(total %lu bytes in %lu blocks)\n",
+ talloc_get_name(ptr),
+ (unsigned long)talloc_total_size(ptr),
+ (unsigned long)talloc_total_blocks(ptr));
+
+ talloc_report_depth(ptr, f, 1);
+ fflush(f);
+}
+
+/*
+ report on memory usage by all children of a pointer
+*/
+void talloc_report(const void *ptr, FILE *f)
+{
+ struct talloc_chunk *c, *tc;
+
+ if (ptr == NULL) {
+ ptr = null_context;
+ }
+ if (ptr == NULL) return;
+
+ fprintf(f, "talloc report on '%s' (total %lu bytes in %lu blocks)\n",
+ talloc_get_name(ptr),
+ (unsigned long)talloc_total_size(ptr),
+ (unsigned long)talloc_total_blocks(ptr));
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ 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));
+ }
+ fflush(f);
+}
+
+/*
+ report on any memory hanging off the null context
+*/
+static void talloc_report_null(void)
+{
+ if (talloc_total_size(null_context) != 0) {
+ talloc_report(null_context, stderr);
+ }
+}
+
+/*
+ report on any memory hanging off the null context
+*/
+static void talloc_report_null_full(void)
+{
+ if (talloc_total_size(null_context) != 0) {
+ talloc_report_full(null_context, stderr);
+ }
+}
+
+/*
+ enable tracking of the NULL context
+*/
+void talloc_enable_null_tracking(void)
+{
+ if (null_context == NULL) {
+ null_context = talloc_named_const(NULL, 0, "null_context");
+ }
+}
+
+/*
+ enable leak reporting on exit
+*/
+void talloc_enable_leak_report(void)
+{
+ talloc_enable_null_tracking();
+ atexit(talloc_report_null);
+}
+
+/*
+ enable full leak reporting on exit
+*/
+void talloc_enable_leak_report_full(void)
+{
+ talloc_enable_null_tracking();
+ atexit(talloc_report_null_full);
+}
+
+/*
+ talloc and zero memory.
+*/
+void *_talloc_zero(const void *ctx, size_t size, const char *name)
+{
+ void *p = talloc_named_const(ctx, size, name);
+
+ if (p) {
+ memset(p, '\0', size);
+ }
+
+ return p;
+}
+
+
+/*
+ memdup with a talloc.
+*/
+void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
+{
+ void *newp = talloc_named_const(t, size, name);
+
+ if (newp) {
+ memcpy(newp, p, size);
+ }
+
+ return newp;
+}
+
+/*
+ strdup with a talloc
+*/
+char *talloc_strdup(const void *t, const char *p)
+{
+ char *ret;
+ if (!p) {
+ return NULL;
+ }
+ ret = talloc_memdup(t, p, strlen(p) + 1);
+ if (ret) {
+ talloc_set_name_const(ret, ret);
+ }
+ return ret;
+}
+
+/*
+ strndup with a talloc
+*/
+char *talloc_strndup(const void *t, const char *p, size_t n)
+{
+ size_t len;
+ char *ret;
+
+ for (len=0; len<n && p[len]; len++) ;
+
+ ret = _talloc(t, len + 1);
+ if (!ret) { return NULL; }
+ memcpy(ret, p, len);
+ ret[len] = 0;
+ talloc_set_name_const(ret, ret);
+ return ret;
+}
+
+#ifndef VA_COPY
+#ifdef HAVE_VA_COPY
+#define VA_COPY(dest, src) va_copy(dest, src)
+#elif defined(HAVE___VA_COPY)
+#define VA_COPY(dest, src) __va_copy(dest, src)
+#else
+#define VA_COPY(dest, src) (dest) = (src)
+#endif
+#endif
+
+char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
+{
+ int len;
+ char *ret;
+ va_list ap2;
+
+ VA_COPY(ap2, ap);
+
+ len = vsnprintf(NULL, 0, fmt, ap2);
+
+ ret = _talloc(t, len+1);
+ if (ret) {
+ VA_COPY(ap2, ap);
+ vsnprintf(ret, len+1, fmt, ap2);
+ talloc_set_name_const(ret, ret);
+ }
+
+ return ret;
+}
+
+
+/*
+ Perform string formatting, and return a pointer to newly allocated
+ memory holding the result, inside a memory pool.
+ */
+char *talloc_asprintf(const void *t, const char *fmt, ...)
+{
+ va_list ap;
+ char *ret;
+
+ va_start(ap, fmt);
+ ret = talloc_vasprintf(t, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+
+/**
+ * Realloc @p s to append the formatted result of @p fmt and @p ap,
+ * and return @p s, which may have moved. Good for gradually
+ * accumulating output into a string buffer.
+ **/
+
+static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
+ PRINTF_ATTRIBUTE(2,0);
+
+static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
+{
+ struct talloc_chunk *tc;
+ int len, s_len;
+ va_list ap2;
+
+ if (s == NULL) {
+ return talloc_vasprintf(NULL, fmt, ap);
+ }
+
+ tc = talloc_chunk_from_ptr(s);
+
+ VA_COPY(ap2, ap);
+
+ s_len = tc->size - 1;
+ len = vsnprintf(NULL, 0, fmt, ap2);
+
+ s = talloc_realloc(NULL, s, char, s_len + len+1);
+ if (!s) return NULL;
+
+ VA_COPY(ap2, ap);
+
+ vsnprintf(s+s_len, len+1, fmt, ap2);
+ talloc_set_name_const(s, s);
+
+ return s;
+}
+
+/*
+ Realloc @p s to append the formatted result of @p fmt and return @p
+ s, which may have moved. Good for gradually accumulating output
+ into a string buffer.
+ */
+char *talloc_asprintf_append(char *s, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ s = talloc_vasprintf_append(s, fmt, ap);
+ va_end(ap);
+ return s;
+}
+
+/*
+ alloc an array, checking for integer overflow in the array size
+*/
+void *_talloc_array(const void *ctx, size_t el_size, unsigned count,
+ const char *name)
+{
+ if (count >= MAX_TALLOC_SIZE/el_size) {
+ return NULL;
+ }
+ return talloc_named_const(ctx, el_size * count, name);
+}
+
+/*
+ alloc an zero array, checking for integer overflow in the array size
+*/
+void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count,
+ const char *name)
+{
+ if (count >= MAX_TALLOC_SIZE/el_size) {
+ return NULL;
+ }
+ return _talloc_zero(ctx, el_size * count, name);
+}
+
+
+/*
+ realloc an array, checking for integer overflow in the array size
+*/
+void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size,
+ unsigned count, const char *name)
+{
+ if (count >= MAX_TALLOC_SIZE/el_size) {
+ return NULL;
+ }
+ return _talloc_realloc(ctx, ptr, el_size * count, name);
+}
+
+/*
+ a function version of talloc_realloc(), so it can be passed as a function
+ pointer to libraries that want a realloc function (a realloc function
+ encapsulates all the basic capabilities of an allocation library, which is
+ why this is useful)
+*/
+void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
+{
+ return _talloc_realloc(context, ptr, size, NULL);
+}
+
+
+static void talloc_autofree(void)
+{
+ talloc_free(cleanup_context);
+ cleanup_context = NULL;
+}
+
+/*
+ return a context which will be auto-freed on exit
+ this is useful for reducing the noise in leak reports
+*/
+void *talloc_autofree_context(void)
+{
+ if (cleanup_context == NULL) {
+ cleanup_context = talloc_named_const(NULL, 0,
+ "autofree_context");
+ atexit(talloc_autofree);
+ }
+ return cleanup_context;
+}
+
+size_t talloc_get_size(const void *context)
+{
+ struct talloc_chunk *tc;
+
+ if (context == NULL)
+ return 0;
+
+ tc = talloc_chunk_from_ptr(context);
+
+ return tc->size;
+}
diff --git a/lib/talloc/talloc.h b/lib/talloc/talloc.h
new file mode 100644
index 0000000..15a1eb6
--- /dev/null
+++ b/lib/talloc/talloc.h
@@ -0,0 +1,137 @@
+#ifndef _TALLOC_H_
+#define _TALLOC_H_
+/*
+ Unix SMB/CIFS implementation.
+ Samba temporary memory allocation functions
+
+ 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.
+
+ This program 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.
+*/
+
+/* petitboot additions */
+#include <stdarg.h>
+#include <stdio.h>
+#include <unistd.h>
+
+/* this is only needed for compatibility with the old talloc */
+typedef void TALLOC_CTX;
+
+/*
+ this uses a little trick to allow __LINE__ to be stringified
+*/
+#define _STRING_LINE_(s) #s
+#define _STRING_LINE2_(s) _STRING_LINE_(s)
+#define __LINESTR__ _STRING_LINE2_(__LINE__)
+#define __location__ __FILE__ ":" __LINESTR__
+
+#ifndef TALLOC_DEPRECATED
+#define TALLOC_DEPRECATED 0
+#endif
+
+/* useful macros for creating type checked pointers */
+#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type)
+#define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__)
+
+#define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__)
+
+#define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type)
+#define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__)
+
+#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type)
+#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type)
+#define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__)
+
+#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type)
+#define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__)
+
+#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__)
+
+#define malloc_p(type) (type *)malloc(sizeof(type))
+#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)
+
+#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__)
+
+#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type)
+#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type)
+
+
+#if TALLOC_DEPRECATED
+#define talloc_zero_p(ctx, type) talloc_zero(ctx, type)
+#define talloc_p(ctx, type) talloc(ctx, type)
+#define talloc_array_p(ctx, type, count) talloc_array(ctx, type, count)
+#define talloc_realloc_p(ctx, p, type, count) talloc_realloc(ctx, p, type, count)
+#define talloc_destroy(ctx) talloc_free(ctx)
+#endif
+
+#ifndef PRINTF_ATTRIBUTE
+#if (__GNUC__ >= 3)
+/** Use gcc attribute to check printf fns. a1 is the 1-based index of
+ * the parameter containing the format, and a2 the index of the first
+ * argument. Note that some gcc 2.x versions don't handle this
+ * properly **/
+#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
+#else
+#define PRINTF_ATTRIBUTE(a1, a2)
+#endif
+#endif
+
+
+/* The following definitions come from talloc.c */
+void *_talloc(const void *context, size_t size);
+void talloc_set_destructor(const void *ptr, int (*destructor)(void *));
+void talloc_increase_ref_count(const void *ptr);
+void *talloc_reference(const void *context, const void *ptr);
+int talloc_unlink(const void *context, void *ptr);
+void talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+void talloc_set_name_const(const void *ptr, const char *name);
+void *talloc_named(const void *context, size_t size,
+ const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
+void *talloc_named_const(const void *context, size_t size, const char *name);
+const char *talloc_get_name(const void *ptr);
+void *talloc_check_name(const void *ptr, const char *name);
+void talloc_report_depth(const void *ptr, FILE *f, int depth);
+void *talloc_parent(const void *ptr);
+void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
+int talloc_free(void *ptr);
+void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name);
+void *talloc_steal(const void *new_ctx, const void *ptr);
+off_t talloc_total_size(const void *ptr);
+off_t talloc_total_blocks(const void *ptr);
+void talloc_report_full(const void *ptr, FILE *f);
+void talloc_report(const void *ptr, FILE *f);
+void talloc_enable_null_tracking(void);
+void talloc_enable_leak_report(void);
+void talloc_enable_leak_report_full(void);
+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_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,
+ const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name);
+void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name);
+void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name);
+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);
+
+#endif
+
OpenPOWER on IntegriCloud