summaryrefslogtreecommitdiffstats
path: root/lib/talloc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 17:44:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 17:44:55 +0000
commitbfe2e03d5ecddce1b9666a58a57e66078a737ea1 (patch)
tree4a4130aca118d9aaaf1494e0e6a5015a0aa409b5 /lib/talloc
parentInitial commit. (diff)
downloadtevent-bfe2e03d5ecddce1b9666a58a57e66078a737ea1.tar.xz
tevent-bfe2e03d5ecddce1b9666a58a57e66078a737ea1.zip
Adding upstream version 0.14.1.upstream/0.14.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'lib/talloc')
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.0.6.sigs6
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.0.7.sigs6
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.0.8.sigs6
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.1.0.sigs6
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.1.1.sigs6
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.1.10.sigs16
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.1.11.sigs16
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.1.12.sigs16
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.1.13.sigs16
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.1.14.sigs16
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.1.15.sigs16
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.1.16.sigs16
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.1.2.sigs6
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.1.3.sigs6
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.1.4.sigs6
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.1.5.sigs6
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.1.6.sigs13
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.1.7.sigs13
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.1.8.sigs13
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.1.9.sigs16
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.2.0.sigs15
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.3.0.sigs16
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.3.1.sigs16
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.3.2.sigs16
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.3.3.sigs16
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.3.4.sigs16
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.3.5.sigs16
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.4.0.sigs16
-rw-r--r--lib/talloc/ABI/talloc-2.0.2.sigs62
-rw-r--r--lib/talloc/ABI/talloc-2.0.3.sigs62
-rw-r--r--lib/talloc/ABI/talloc-2.0.4.sigs62
-rw-r--r--lib/talloc/ABI/talloc-2.0.5.sigs62
-rw-r--r--lib/talloc/ABI/talloc-2.0.6.sigs62
-rw-r--r--lib/talloc/ABI/talloc-2.0.7.sigs62
-rw-r--r--lib/talloc/ABI/talloc-2.0.8.sigs63
-rw-r--r--lib/talloc/ABI/talloc-2.1.0.sigs64
-rw-r--r--lib/talloc/ABI/talloc-2.1.1.sigs64
-rw-r--r--lib/talloc/ABI/talloc-2.1.10.sigs65
-rw-r--r--lib/talloc/ABI/talloc-2.1.11.sigs65
-rw-r--r--lib/talloc/ABI/talloc-2.1.12.sigs65
-rw-r--r--lib/talloc/ABI/talloc-2.1.13.sigs65
-rw-r--r--lib/talloc/ABI/talloc-2.1.14.sigs65
-rw-r--r--lib/talloc/ABI/talloc-2.1.15.sigs65
-rw-r--r--lib/talloc/ABI/talloc-2.1.16.sigs65
-rw-r--r--lib/talloc/ABI/talloc-2.1.2.sigs64
-rw-r--r--lib/talloc/ABI/talloc-2.1.3.sigs64
-rw-r--r--lib/talloc/ABI/talloc-2.1.4.sigs65
-rw-r--r--lib/talloc/ABI/talloc-2.1.5.sigs65
-rw-r--r--lib/talloc/ABI/talloc-2.1.6.sigs65
-rw-r--r--lib/talloc/ABI/talloc-2.1.7.sigs65
-rw-r--r--lib/talloc/ABI/talloc-2.1.8.sigs65
-rw-r--r--lib/talloc/ABI/talloc-2.1.9.sigs65
-rw-r--r--lib/talloc/ABI/talloc-2.2.0.sigs65
-rw-r--r--lib/talloc/ABI/talloc-2.3.0.sigs65
-rw-r--r--lib/talloc/ABI/talloc-2.3.1.sigs65
-rw-r--r--lib/talloc/ABI/talloc-2.3.2.sigs65
-rw-r--r--lib/talloc/ABI/talloc-2.3.3.sigs65
-rw-r--r--lib/talloc/ABI/talloc-2.3.4.sigs65
-rw-r--r--lib/talloc/ABI/talloc-2.3.5.sigs66
-rw-r--r--lib/talloc/ABI/talloc-2.4.0.sigs66
-rw-r--r--lib/talloc/Makefile68
-rw-r--r--lib/talloc/NEWS13
-rw-r--r--lib/talloc/compat/talloc_compat1.c51
-rw-r--r--lib/talloc/compat/talloc_compat1.mk21
-rwxr-xr-xlib/talloc/configure28
-rw-r--r--lib/talloc/doc/context.pngbin0 -> 4715 bytes
-rw-r--r--lib/talloc/doc/context_tree.pngbin0 -> 6158 bytes
-rw-r--r--lib/talloc/doc/mainpage.dox111
-rw-r--r--lib/talloc/doc/stealing.pngbin0 -> 6994 bytes
-rw-r--r--lib/talloc/doc/tutorial_bestpractices.dox192
-rw-r--r--lib/talloc/doc/tutorial_context.dox198
-rw-r--r--lib/talloc/doc/tutorial_debugging.dox116
-rw-r--r--lib/talloc/doc/tutorial_destructors.dox82
-rw-r--r--lib/talloc/doc/tutorial_dts.dox109
-rw-r--r--lib/talloc/doc/tutorial_introduction.dox45
-rw-r--r--lib/talloc/doc/tutorial_pools.dox93
-rw-r--r--lib/talloc/doc/tutorial_stealing.dox55
-rw-r--r--lib/talloc/doc/tutorial_threads.dox203
-rw-r--r--lib/talloc/doxy.config1807
-rw-r--r--lib/talloc/man/talloc.3.xml814
-rw-r--r--lib/talloc/pytalloc-util.pc.in11
-rw-r--r--lib/talloc/pytalloc.c313
-rw-r--r--lib/talloc/pytalloc.h87
-rw-r--r--lib/talloc/pytalloc_guide.txt252
-rw-r--r--lib/talloc/pytalloc_private.h26
-rw-r--r--lib/talloc/pytalloc_util.c334
-rw-r--r--lib/talloc/talloc.c3072
-rw-r--r--lib/talloc/talloc.h1972
-rw-r--r--lib/talloc/talloc.pc.in11
-rw-r--r--lib/talloc/talloc_guide.txt768
-rw-r--r--lib/talloc/talloc_testsuite.h7
-rwxr-xr-xlib/talloc/test_magic_differs.sh16
-rw-r--r--lib/talloc/test_magic_differs_helper.c12
-rw-r--r--lib/talloc/test_pytalloc.c244
-rw-r--r--lib/talloc/test_pytalloc.py189
-rw-r--r--lib/talloc/testsuite.c2288
-rw-r--r--lib/talloc/testsuite_main.c36
-rw-r--r--lib/talloc/web/index.html51
-rw-r--r--lib/talloc/wscript199
99 files changed, 16300 insertions, 0 deletions
diff --git a/lib/talloc/ABI/pytalloc-util-2.0.6.sigs b/lib/talloc/ABI/pytalloc-util-2.0.6.sigs
new file mode 100644
index 0000000..961c1a8
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.0.6.sigs
@@ -0,0 +1,6 @@
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.0.7.sigs b/lib/talloc/ABI/pytalloc-util-2.0.7.sigs
new file mode 100644
index 0000000..961c1a8
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.0.7.sigs
@@ -0,0 +1,6 @@
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.0.8.sigs b/lib/talloc/ABI/pytalloc-util-2.0.8.sigs
new file mode 100644
index 0000000..961c1a8
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.0.8.sigs
@@ -0,0 +1,6 @@
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.1.0.sigs b/lib/talloc/ABI/pytalloc-util-2.1.0.sigs
new file mode 100644
index 0000000..961c1a8
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.1.0.sigs
@@ -0,0 +1,6 @@
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.1.1.sigs b/lib/talloc/ABI/pytalloc-util-2.1.1.sigs
new file mode 100644
index 0000000..961c1a8
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.1.1.sigs
@@ -0,0 +1,6 @@
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.1.10.sigs b/lib/talloc/ABI/pytalloc-util-2.1.10.sigs
new file mode 100644
index 0000000..9d4d4d1
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.1.10.sigs
@@ -0,0 +1,16 @@
+_pytalloc_check_type: int (PyObject *, const char *)
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.1.11.sigs b/lib/talloc/ABI/pytalloc-util-2.1.11.sigs
new file mode 100644
index 0000000..9d4d4d1
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.1.11.sigs
@@ -0,0 +1,16 @@
+_pytalloc_check_type: int (PyObject *, const char *)
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.1.12.sigs b/lib/talloc/ABI/pytalloc-util-2.1.12.sigs
new file mode 100644
index 0000000..9d4d4d1
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.1.12.sigs
@@ -0,0 +1,16 @@
+_pytalloc_check_type: int (PyObject *, const char *)
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.1.13.sigs b/lib/talloc/ABI/pytalloc-util-2.1.13.sigs
new file mode 100644
index 0000000..9d4d4d1
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.1.13.sigs
@@ -0,0 +1,16 @@
+_pytalloc_check_type: int (PyObject *, const char *)
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.1.14.sigs b/lib/talloc/ABI/pytalloc-util-2.1.14.sigs
new file mode 100644
index 0000000..9d4d4d1
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.1.14.sigs
@@ -0,0 +1,16 @@
+_pytalloc_check_type: int (PyObject *, const char *)
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.1.15.sigs b/lib/talloc/ABI/pytalloc-util-2.1.15.sigs
new file mode 100644
index 0000000..9d4d4d1
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.1.15.sigs
@@ -0,0 +1,16 @@
+_pytalloc_check_type: int (PyObject *, const char *)
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.1.16.sigs b/lib/talloc/ABI/pytalloc-util-2.1.16.sigs
new file mode 100644
index 0000000..9d4d4d1
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.1.16.sigs
@@ -0,0 +1,16 @@
+_pytalloc_check_type: int (PyObject *, const char *)
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.1.2.sigs b/lib/talloc/ABI/pytalloc-util-2.1.2.sigs
new file mode 100644
index 0000000..961c1a8
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.1.2.sigs
@@ -0,0 +1,6 @@
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.1.3.sigs b/lib/talloc/ABI/pytalloc-util-2.1.3.sigs
new file mode 100644
index 0000000..961c1a8
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.1.3.sigs
@@ -0,0 +1,6 @@
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.1.4.sigs b/lib/talloc/ABI/pytalloc-util-2.1.4.sigs
new file mode 100644
index 0000000..961c1a8
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.1.4.sigs
@@ -0,0 +1,6 @@
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.1.5.sigs b/lib/talloc/ABI/pytalloc-util-2.1.5.sigs
new file mode 100644
index 0000000..961c1a8
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.1.5.sigs
@@ -0,0 +1,6 @@
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.1.6.sigs b/lib/talloc/ABI/pytalloc-util-2.1.6.sigs
new file mode 100644
index 0000000..666fec0
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.1.6.sigs
@@ -0,0 +1,13 @@
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.1.7.sigs b/lib/talloc/ABI/pytalloc-util-2.1.7.sigs
new file mode 100644
index 0000000..666fec0
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.1.7.sigs
@@ -0,0 +1,13 @@
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.1.8.sigs b/lib/talloc/ABI/pytalloc-util-2.1.8.sigs
new file mode 100644
index 0000000..666fec0
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.1.8.sigs
@@ -0,0 +1,13 @@
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.1.9.sigs b/lib/talloc/ABI/pytalloc-util-2.1.9.sigs
new file mode 100644
index 0000000..9d4d4d1
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.1.9.sigs
@@ -0,0 +1,16 @@
+_pytalloc_check_type: int (PyObject *, const char *)
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.2.0.sigs b/lib/talloc/ABI/pytalloc-util-2.2.0.sigs
new file mode 100644
index 0000000..62f066f
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.2.0.sigs
@@ -0,0 +1,15 @@
+_pytalloc_check_type: int (PyObject *, const char *)
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_Check: int (PyObject *)
+pytalloc_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.3.0.sigs b/lib/talloc/ABI/pytalloc-util-2.3.0.sigs
new file mode 100644
index 0000000..6056577
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.3.0.sigs
@@ -0,0 +1,16 @@
+_pytalloc_check_type: int (PyObject *, const char *)
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_name: const char *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_Check: int (PyObject *)
+pytalloc_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.3.1.sigs b/lib/talloc/ABI/pytalloc-util-2.3.1.sigs
new file mode 100644
index 0000000..6056577
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.3.1.sigs
@@ -0,0 +1,16 @@
+_pytalloc_check_type: int (PyObject *, const char *)
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_name: const char *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_Check: int (PyObject *)
+pytalloc_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.3.2.sigs b/lib/talloc/ABI/pytalloc-util-2.3.2.sigs
new file mode 100644
index 0000000..6056577
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.3.2.sigs
@@ -0,0 +1,16 @@
+_pytalloc_check_type: int (PyObject *, const char *)
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_name: const char *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_Check: int (PyObject *)
+pytalloc_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.3.3.sigs b/lib/talloc/ABI/pytalloc-util-2.3.3.sigs
new file mode 100644
index 0000000..6056577
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.3.3.sigs
@@ -0,0 +1,16 @@
+_pytalloc_check_type: int (PyObject *, const char *)
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_name: const char *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_Check: int (PyObject *)
+pytalloc_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.3.4.sigs b/lib/talloc/ABI/pytalloc-util-2.3.4.sigs
new file mode 100644
index 0000000..6056577
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.3.4.sigs
@@ -0,0 +1,16 @@
+_pytalloc_check_type: int (PyObject *, const char *)
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_name: const char *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_Check: int (PyObject *)
+pytalloc_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.3.5.sigs b/lib/talloc/ABI/pytalloc-util-2.3.5.sigs
new file mode 100644
index 0000000..6056577
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.3.5.sigs
@@ -0,0 +1,16 @@
+_pytalloc_check_type: int (PyObject *, const char *)
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_name: const char *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_Check: int (PyObject *)
+pytalloc_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.4.0.sigs b/lib/talloc/ABI/pytalloc-util-2.4.0.sigs
new file mode 100644
index 0000000..6056577
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.4.0.sigs
@@ -0,0 +1,16 @@
+_pytalloc_check_type: int (PyObject *, const char *)
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_name: const char *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_Check: int (PyObject *)
+pytalloc_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/talloc-2.0.2.sigs b/lib/talloc/ABI/talloc-2.0.2.sigs
new file mode 100644
index 0000000..6e236d5
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.0.2.sigs
@@ -0,0 +1,62 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.0.3.sigs b/lib/talloc/ABI/talloc-2.0.3.sigs
new file mode 100644
index 0000000..6e236d5
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.0.3.sigs
@@ -0,0 +1,62 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.0.4.sigs b/lib/talloc/ABI/talloc-2.0.4.sigs
new file mode 100644
index 0000000..6e236d5
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.0.4.sigs
@@ -0,0 +1,62 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.0.5.sigs b/lib/talloc/ABI/talloc-2.0.5.sigs
new file mode 100644
index 0000000..6e236d5
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.0.5.sigs
@@ -0,0 +1,62 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.0.6.sigs b/lib/talloc/ABI/talloc-2.0.6.sigs
new file mode 100644
index 0000000..6e236d5
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.0.6.sigs
@@ -0,0 +1,62 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.0.7.sigs b/lib/talloc/ABI/talloc-2.0.7.sigs
new file mode 100644
index 0000000..6e236d5
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.0.7.sigs
@@ -0,0 +1,62 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.0.8.sigs b/lib/talloc/ABI/talloc-2.0.8.sigs
new file mode 100644
index 0000000..15a9e95
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.0.8.sigs
@@ -0,0 +1,63 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.1.0.sigs b/lib/talloc/ABI/talloc-2.1.0.sigs
new file mode 100644
index 0000000..eae12cc
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.1.0.sigs
@@ -0,0 +1,64 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.1.1.sigs b/lib/talloc/ABI/talloc-2.1.1.sigs
new file mode 100644
index 0000000..eae12cc
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.1.1.sigs
@@ -0,0 +1,64 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.1.10.sigs b/lib/talloc/ABI/talloc-2.1.10.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.1.10.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.1.11.sigs b/lib/talloc/ABI/talloc-2.1.11.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.1.11.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.1.12.sigs b/lib/talloc/ABI/talloc-2.1.12.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.1.12.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.1.13.sigs b/lib/talloc/ABI/talloc-2.1.13.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.1.13.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.1.14.sigs b/lib/talloc/ABI/talloc-2.1.14.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.1.14.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.1.15.sigs b/lib/talloc/ABI/talloc-2.1.15.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.1.15.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.1.16.sigs b/lib/talloc/ABI/talloc-2.1.16.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.1.16.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.1.2.sigs b/lib/talloc/ABI/talloc-2.1.2.sigs
new file mode 100644
index 0000000..eae12cc
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.1.2.sigs
@@ -0,0 +1,64 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.1.3.sigs b/lib/talloc/ABI/talloc-2.1.3.sigs
new file mode 100644
index 0000000..eae12cc
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.1.3.sigs
@@ -0,0 +1,64 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.1.4.sigs b/lib/talloc/ABI/talloc-2.1.4.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.1.4.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.1.5.sigs b/lib/talloc/ABI/talloc-2.1.5.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.1.5.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.1.6.sigs b/lib/talloc/ABI/talloc-2.1.6.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.1.6.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.1.7.sigs b/lib/talloc/ABI/talloc-2.1.7.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.1.7.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.1.8.sigs b/lib/talloc/ABI/talloc-2.1.8.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.1.8.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.1.9.sigs b/lib/talloc/ABI/talloc-2.1.9.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.1.9.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.2.0.sigs b/lib/talloc/ABI/talloc-2.2.0.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.2.0.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.3.0.sigs b/lib/talloc/ABI/talloc-2.3.0.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.3.0.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.3.1.sigs b/lib/talloc/ABI/talloc-2.3.1.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.3.1.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.3.2.sigs b/lib/talloc/ABI/talloc-2.3.2.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.3.2.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.3.3.sigs b/lib/talloc/ABI/talloc-2.3.3.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.3.3.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.3.4.sigs b/lib/talloc/ABI/talloc-2.3.4.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.3.4.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.3.5.sigs b/lib/talloc/ABI/talloc-2.3.5.sigs
new file mode 100644
index 0000000..ec3cee4
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.3.5.sigs
@@ -0,0 +1,66 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_addbuf: void (char **, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.4.0.sigs b/lib/talloc/ABI/talloc-2.4.0.sigs
new file mode 100644
index 0000000..ec3cee4
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.4.0.sigs
@@ -0,0 +1,66 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_addbuf: void (char **, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/Makefile b/lib/talloc/Makefile
new file mode 100644
index 0000000..db2275c
--- /dev/null
+++ b/lib/talloc/Makefile
@@ -0,0 +1,68 @@
+# simple makefile wrapper to run waf
+
+WAF_BIN=`PATH=buildtools/bin:../../buildtools/bin:$$PATH which waf`
+WAF_BINARY=$(PYTHON) $(WAF_BIN)
+WAF=PYTHONHASHSEED=1 WAF_MAKE=1 $(WAF_BINARY)
+
+all:
+ $(WAF) build
+
+install:
+ $(WAF) install
+
+uninstall:
+ $(WAF) uninstall
+
+test:
+ $(WAF) test $(TEST_OPTIONS)
+
+testenv:
+ $(WAF) test --testenv $(TEST_OPTIONS)
+
+quicktest:
+ $(WAF) test --quick $(TEST_OPTIONS)
+
+dist:
+ touch .tmplock
+ WAFLOCK=.tmplock $(WAF) dist
+
+distcheck:
+ touch .tmplock
+ WAFLOCK=.tmplock $(WAF) distcheck
+
+clean:
+ $(WAF) clean
+
+distclean:
+ $(WAF) distclean
+
+reconfigure: configure
+ $(WAF) reconfigure
+
+show_waf_options:
+ $(WAF) --help
+
+# some compatibility make targets
+everything: all
+
+testsuite: all
+
+check: test
+
+torture: all
+
+# this should do an install as well, once install is finished
+installcheck: test
+
+etags:
+ $(WAF) etags
+
+ctags:
+ $(WAF) ctags
+
+pydoctor:
+ $(WAF) pydoctor
+
+bin/%:: FORCE
+ $(WAF) --targets=`basename $@`
+FORCE:
diff --git a/lib/talloc/NEWS b/lib/talloc/NEWS
new file mode 100644
index 0000000..e5b3aa0
--- /dev/null
+++ b/lib/talloc/NEWS
@@ -0,0 +1,13 @@
+1.0.1 26 May 2007
+
+ BUGS
+
+ * Set name of correctly when using talloc_append_string() (metze)
+
+ LICENSE
+
+ * Change license of files in lib/replace to LGPL (was GPL). (jelmer)
+
+1.0.0 30 April 2007
+
+ Initial release.
diff --git a/lib/talloc/compat/talloc_compat1.c b/lib/talloc/compat/talloc_compat1.c
new file mode 100644
index 0000000..519e8c3
--- /dev/null
+++ b/lib/talloc/compat/talloc_compat1.c
@@ -0,0 +1,51 @@
+/*
+ Samba trivial allocation library - compat functions
+
+ Copyright (C) Stefan Metzmacher 2009
+
+ ** 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 3 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
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * This file contains only function to build a
+ * compat talloc.so.1 library on top of talloc.so.2
+ */
+
+#include "replace.h"
+#include "talloc.h"
+
+void *_talloc_reference(const void *context, const void *ptr);
+void *_talloc_reference(const void *context, const void *ptr) {
+ return _talloc_reference_loc(context, ptr,
+ "Called from talloc compat1 "
+ "_talloc_reference");
+}
+
+void *_talloc_steal(const void *new_ctx, const void *ptr);
+void *_talloc_steal(const void *new_ctx, const void *ptr)
+{
+ return talloc_reparent(talloc_parent(ptr), new_ctx, ptr);
+}
+
+#undef talloc_free
+int talloc_free(void *ptr);
+int talloc_free(void *ptr)
+{
+ return talloc_unlink(talloc_parent(ptr), ptr);
+}
+
diff --git a/lib/talloc/compat/talloc_compat1.mk b/lib/talloc/compat/talloc_compat1.mk
new file mode 100644
index 0000000..d1817f0
--- /dev/null
+++ b/lib/talloc/compat/talloc_compat1.mk
@@ -0,0 +1,21 @@
+talloccompatdir := $(tallocdir)/compat
+
+TALLOC_COMPAT1_VERSION_MAJOR = 1
+TALLOC_COMPAT1_OBJ = $(talloccompatdir)/talloc_compat1.o
+
+TALLOC_COMPAT1_SOLIB = libtalloc-compat1-$(TALLOC_VERSION).$(SHLIBEXT)
+TALLOC_COMPAT1_SONAME = libtalloc.$(SHLIBEXT).$(TALLOC_COMPAT1_VERSION_MAJOR)
+
+$(TALLOC_COMPAT1_SOLIB): $(TALLOC_COMPAT1_OBJ) $(TALLOC_SOLIB)
+ $(SHLD) $(SHLD_FLAGS) -o $@ $(TALLOC_COMPAT1_OBJ) \
+ $(TALLOC_SOLIB) $(SONAMEFLAG)$(TALLOC_COMPAT1_SONAME)
+
+all:: $(TALLOC_COMPAT1_SOLIB)
+
+install::
+ ${INSTALLCMD} -d $(DESTDIR)$(libdir)
+ ${INSTALLCMD} -m 755 $(TALLOC_COMPAT1_SOLIB) $(DESTDIR)$(libdir)
+
+clean::
+ rm -f $(TALLOC_COMPAT1_OBJ) $(TALLOC_COMPAT1_SOLIB)
+
diff --git a/lib/talloc/configure b/lib/talloc/configure
new file mode 100755
index 0000000..af76185
--- /dev/null
+++ b/lib/talloc/configure
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+PREVPATH=$(dirname $0)
+
+if [ -f $PREVPATH/../../buildtools/bin/waf ]; then
+ WAF=../../buildtools/bin/waf
+elif [ -f $PREVPATH/buildtools/bin/waf ]; then
+ WAF=./buildtools/bin/waf
+else
+ echo "replace: Unable to find waf"
+ exit 1
+fi
+
+# using JOBS=1 gives maximum compatibility with
+# systems like AIX which have broken threading in python
+JOBS=1
+export JOBS
+
+# Make sure we don't have any library preloaded.
+unset LD_PRELOAD
+
+# Make sure we get stable hashes
+PYTHONHASHSEED=1
+export PYTHONHASHSEED
+
+cd . || exit 1
+$PYTHON $WAF configure "$@" || exit 1
+cd $PREVPATH
diff --git a/lib/talloc/doc/context.png b/lib/talloc/doc/context.png
new file mode 100644
index 0000000..48a6ca0
--- /dev/null
+++ b/lib/talloc/doc/context.png
Binary files differ
diff --git a/lib/talloc/doc/context_tree.png b/lib/talloc/doc/context_tree.png
new file mode 100644
index 0000000..9723459
--- /dev/null
+++ b/lib/talloc/doc/context_tree.png
Binary files differ
diff --git a/lib/talloc/doc/mainpage.dox b/lib/talloc/doc/mainpage.dox
new file mode 100644
index 0000000..ece6ccb
--- /dev/null
+++ b/lib/talloc/doc/mainpage.dox
@@ -0,0 +1,111 @@
+/**
+ * @mainpage
+ *
+ * talloc is a hierarchical, reference counted memory pool system with
+ * destructors. It is the core memory allocator used in Samba.
+ *
+ * @section talloc_download Download
+ *
+ * You can download the latest releases of talloc from the
+ * <a href="http://samba.org/ftp/talloc" target="_blank">talloc directory</a>
+ * on the samba public source archive.
+ *
+ * @section main-tutorial Tutorial
+ *
+ * You should start by reading @subpage libtalloc_tutorial, then reading the documentation of
+ * the interesting functions as you go.
+
+ * @section talloc_bugs Discussion and bug reports
+ *
+ * talloc does not currently have its own mailing list or bug tracking system.
+ * For now, please use the
+ * <a href="https://lists.samba.org/mailman/listinfo/samba-technical" target="_blank">samba-technical</a>
+ * mailing list, and the
+ * <a href="http://bugzilla.samba.org/" target="_blank">Samba bugzilla</a>
+ * bug tracking system.
+ *
+ * @section talloc_devel Development
+ * You can download the latest code either via git or rsync.
+ *
+ * To fetch via git see the following guide:
+ *
+ * <a href="http://wiki.samba.org/index.php/Using_Git_for_Samba_Development" target="_blank">Using Git for Samba Development</a>
+ *
+ * Once you have cloned the tree switch to the master branch and cd into the
+ * lib/tevent directory.
+ *
+ * To fetch via rsync use this command:
+ *
+ * rsync -Pavz samba.org::ftp/unpacked/standalone_projects/lib/talloc .
+ *
+ * @section talloc_preample Preamble
+ *
+ * talloc is a hierarchical, reference counted memory pool system with
+ * destructors.
+ *
+ * Perhaps the biggest difference from other memory pool systems is that there
+ * is no distinction between a "talloc context" and a "talloc pointer". Any
+ * pointer returned from talloc() is itself a valid talloc context. This means
+ * you can do this:
+ *
+ * @code
+ * struct foo *X = talloc(mem_ctx, struct foo);
+ * X->name = talloc_strdup(X, "foo");
+ * @endcode
+ *
+ * The pointer X->name would be a "child" of the talloc context "X" which is
+ * itself a child of mem_ctx. So if you do talloc_free(mem_ctx) then it is all
+ * destroyed, whereas if you do talloc_free(X) then just X and X->name are
+ * destroyed, and if you do talloc_free(X->name) then just the name element of
+ * X is destroyed.
+ *
+ * If you think about this, then what this effectively gives you is an n-ary
+ * tree, where you can free any part of the tree with talloc_free().
+ *
+ * If you find this confusing, then run the testsuite to watch talloc in
+ * action. You may also like to add your own tests to testsuite.c to clarify
+ * how some particular situation is handled.
+ *
+ * @section talloc_performance Performance
+ *
+ * All the additional features of talloc() over malloc() do come at a price. We
+ * have a simple performance test in Samba4 that measures talloc() versus
+ * malloc() performance, and it seems that talloc() is about 4% slower than
+ * malloc() on my x86 Debian Linux box. For Samba, the great reduction in code
+ * complexity that we get by using talloc makes this worthwhile, especially as
+ * the total overhead of talloc/malloc in Samba is already quite small.
+ *
+ * @section talloc_named Named blocks
+ *
+ * Every talloc chunk has a name that can be used as a dynamic type-checking
+ * system. If for some reason like a callback function you had to cast a
+ * "struct foo *" to a "void *" variable, later you can safely reassign the
+ * "void *" pointer to a "struct foo *" by using the talloc_get_type() or
+ * talloc_get_type_abort() macros.
+ *
+ * @code
+ * struct foo *X = talloc_get_type_abort(ptr, struct foo);
+ * @endcode
+ *
+ * This will abort if "ptr" does not contain a pointer that has been created
+ * with talloc(mem_ctx, struct foo).
+ *
+ * @section talloc_threading Multi-threading
+ *
+ * talloc itself does not deal with threads. It is thread-safe (assuming the
+ * underlying "malloc" is), as long as each thread uses different memory
+ * contexts.
+ *
+ * If two threads uses the same context then they need to synchronize in order
+ * to be safe. In particular:
+ *
+ * - when using talloc_enable_leak_report(), giving directly NULL as a parent
+ * context implicitly refers to a hidden "null context" global variable, so
+ * this should not be used in a multi-threaded environment without proper
+ * synchronization. In threaded code turn off null tracking using
+ * talloc_disable_null_tracking().
+ * - the context returned by talloc_autofree_context() is also global so
+ * shouldn't be used by several threads simultaneously without
+ * synchronization.
+ *
+ */
diff --git a/lib/talloc/doc/stealing.png b/lib/talloc/doc/stealing.png
new file mode 100644
index 0000000..8833e06
--- /dev/null
+++ b/lib/talloc/doc/stealing.png
Binary files differ
diff --git a/lib/talloc/doc/tutorial_bestpractices.dox b/lib/talloc/doc/tutorial_bestpractices.dox
new file mode 100644
index 0000000..3634446
--- /dev/null
+++ b/lib/talloc/doc/tutorial_bestpractices.dox
@@ -0,0 +1,192 @@
+/**
+@page libtalloc_bestpractices Chapter 7: Best practises
+
+The following sections contain several best practices and good manners that were
+found by the <a href="http://www.samba.org">Samba</a> and
+<a href="https://fedorahosted.org/sssd">SSSD</a> developers over the years.
+These will help you to write code which is better, easier to debug and with as
+few (hopefully none) memory leaks as possible.
+
+@section bp-hierarchy Keep the context hierarchy steady
+
+The talloc is a hierarchy memory allocator. The hierarchy nature is what makes
+the programming more error proof. It makes the memory easier to manage and to
+free. Therefore, the first thing we should have on our mind is: always project
+your data structures into the talloc context hierarchy.
+
+That means if we have a structure, we should always use it as a parent context
+for its elements. This way we will not encounter any troubles when freeing the
+structure or when changing its parent. The same rule applies for arrays.
+
+For example, the structure <code>user</code> from section @ref context-hierarchy
+should be created with the context hierarchy illustrated on the next image.
+
+@image html context_tree.png
+
+@section bp-tmpctx Every function should use its own context
+
+It is a good practice to create a temporary talloc context at the function
+beginning and free the context just before the return statement. All the data
+must be allocated on this context or on its children. This ensures that no
+memory leaks are created as long as we do not forget to free the temporary
+context.
+
+This pattern applies to both situations - when a function does not return any
+dynamically allocated value and when it does. However, it needs a little
+extension for the latter case.
+
+@subsection bp-tmpctx-1 Functions that do not return any dynamically allocated
+value
+
+If the function does not return any value created on the heap, we will just obey
+the aforementioned pattern.
+
+@code
+int bar()
+{
+ int ret;
+ TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ /* allocate data on tmp_ctx or on its descendants */
+ ret = EOK;
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+@endcode
+
+@subsection bp-tmpctx-2 Functions returning dynamically allocated values
+
+If our function returns any dynamically allocated data, its first parameter
+should always be the destination talloc context. This context serves as a parent
+for the output values. But again, we will create the output values as the
+descendants of the temporary context. If everything goes well, we will change
+the parent of the output values from the temporary to the destination talloc
+context.
+
+This pattern ensures that if an error occurs (e.g. I/O error or insufficient
+amount of the memory), all allocated data is freed and no garbage appears on
+the destination context.
+
+@code
+int struct_foo_init(TALLOC_CTX *mem_ctx, struct foo **_foo)
+{
+ int ret;
+ struct foo *foo = NULL;
+ TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ foo = talloc_zero(tmp_ctx, struct foo);
+ /* ... */
+ *_foo = talloc_steal(mem_ctx, foo);
+ ret = EOK;
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+@endcode
+
+@section bp-null Allocate temporary contexts on NULL
+
+As it can be seen on the previous listing, instead of allocating the temporary
+context directly on <code>mem_ctx</code>, we created a new top level context
+using <code>NULL</code> as the parameter for <code>talloc_new()</code> function.
+Take a look at the following example:
+
+@code
+char *create_user_filter(TALLOC_CTX *mem_ctx,
+ uid_t uid, const char *username)
+{
+ char *filter = NULL;
+ char *sanitized_username = NULL;
+ /* tmp_ctx is a child of mem_ctx */
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ if (tmp_ctx == NULL) {
+ return NULL;
+ }
+
+ sanitized_username = sanitize_string(tmp_ctx, username);
+ if (sanitized_username == NULL) {
+ talloc_free(tmp_ctx);
+ return NULL;
+ }
+
+ filter = talloc_aprintf(tmp_ctx,"(|(uid=%llu)(uname=%s))",
+ uid, sanitized_username);
+ if (filter == NULL) {
+ return NULL; /* tmp_ctx is not freed */ (*@\label{lst:tmp-ctx-3:leak}@*)
+ }
+
+ /* filter becomes a child of mem_ctx */
+ filter = talloc_steal(mem_ctx, filter);
+ talloc_free(tmp_ctx);
+ return filter;
+}
+@endcode
+
+We forgot to free <code>tmp_ctx</code> before the <code>return</code> statement
+in the <code>filter == NULL</code> condition. However, it is created as a child
+of <code>mem_ctx</code> context and as such it will be freed as soon as the
+<code>mem_ctx</code> is freed. Therefore, no detectable memory leak is created.
+
+On the other hand, we do not have any way to access the allocated data
+and for all we know <code>mem_ctx</code> may exist for the lifetime of our
+application. For these reasons this should be considered as a memory leak. How
+can we detect if it is unreferenced but still attached to its parent context?
+The only way is to notice the mistake in the source code.
+
+But if we create the temporary context as a top level context, it will not be
+freed and memory diagnostic tools
+(e.g. <a href="http://valgrind.org">valgrind</a>) are able to do their job.
+
+@section bp-pool Temporary contexts and the talloc pool
+
+If we want to take the advantage of the talloc pool but also keep to the
+pattern introduced in the previous section, we are unable to do it directly. The
+best thing to do is to create a conditional build where we can decide how do we
+want to create the temporary context. For example, we can create the following
+macros:
+
+@code
+#ifdef USE_POOL_CONTEXT
+ #define CREATE_POOL_CTX(ctx, size) talloc_pool(ctx, size)
+ #define CREATE_TMP_CTX(ctx) talloc_new(ctx)
+#else
+ #define CREATE_POOL_CTX(ctx, size) talloc_new(ctx)
+ #define CREATE_TMP_CTX(ctx) talloc_new(NULL)
+#endif
+@endcode
+
+Now if our application is under development, we will build it with macro
+<code>USE_POOL_CONTEXT</code> undefined. This way, we can use memory diagnostic
+utilities to detect memory leaks.
+
+The release version will be compiled with the macro defined. This will enable
+pool contexts and therefore reduce the <code>malloc()</code> calls, which will
+end up in a little bit faster processing.
+
+@code
+int struct_foo_init(TALLOC_CTX *mem_ctx, struct foo **_foo)
+{
+ int ret;
+ struct foo *foo = NULL;
+ TALLOC_CTX *tmp_ctx = CREATE_TMP_CTX(mem_ctx);
+ /* ... */
+}
+
+errno_t handle_request(TALLOC_CTX mem_ctx)
+{
+ int ret;
+ struct foo *foo = NULL;
+ TALLOC_CTX *pool_ctx = CREATE_POOL_CTX(NULL, 1024);
+ ret = struct_foo_init(mem_ctx, &foo);
+ /* ... */
+}
+@endcode
+
+*/
diff --git a/lib/talloc/doc/tutorial_context.dox b/lib/talloc/doc/tutorial_context.dox
new file mode 100644
index 0000000..b8bfe26
--- /dev/null
+++ b/lib/talloc/doc/tutorial_context.dox
@@ -0,0 +1,198 @@
+/**
+@page libtalloc_context Chapter 1: Talloc context
+@section context Talloc context
+
+The talloc context is the most important part of this library and is
+responsible for every single feature of this memory allocator. It is a logical
+unit which represents a memory space managed by talloc.
+
+From the programmer's point of view, the talloc context is completely
+equivalent to a pointer that would be returned by the memory routines from the
+C standard library. This means that every context that is returned from the
+talloc library can be used directly in functions that do not use talloc
+internally. For example we can do the following:
+
+@code
+char *str1 = strdup("I am NOT a talloc context");
+char *str2 = talloc_strdup(NULL, "I AM a talloc context");
+
+printf("%d\n", strcmp(str1, str2) == 0);
+
+free(str1);
+talloc_free(str2); /* we can not use free() on str2 */
+@endcode
+
+This is possible because the context is internally handled as a special
+fixed-length structure called talloc chunk. Each chunk stores context metadata
+followed by the memory space requested by the programmer. When a talloc
+function returns a context (pointer), it will in fact return a pointer to the user
+space portion of the talloc chunk. If we to manipulate this context using
+talloc functions, the talloc library transforms the user-space pointer back to
+the starting address of the chunk. This is also the reason why we were unable
+to use <code>free(str2)</code> in the previous example - because
+<code>str2</code> does not point at the beginning of the allocated block of
+memory. This is illustrated on the next image:
+
+@image html context.png
+
+The type TALLOC_CTX is defined in talloc.h to identify a talloc context in
+function parameters. However, this type is just an alias for <code>void</code>
+and exists only for semantical reasons - thus we can differentiate between
+<code>void *</code> (arbitrary data) and <code>TALLOC_CTX *</code> (talloc
+context).
+
+@subsection metadata Context meta data
+
+Every talloc context carries several pieces of internal information along with
+the allocated memory:
+
+ - name - which is used in reports of context hierarchy and to simulate
+ a dynamic type system,
+ - size of the requested memory in bytes - this can be used to determine
+ the number of elements in arrays,
+ - attached destructor - which is executed just before the memory block is
+ about to be freed,
+ - references to the context
+ - children and parent contexts - create the hierarchical view on the
+ memory.
+
+@section context-hierarchy Hierarchy of talloc context
+
+Every talloc context contains information about its parent and children. Talloc
+uses this information to create a hierarchical model of memory or to be more
+precise, it creates an n-ary tree where each node represents a single talloc
+context. The root node of the tree is referred to as a top level context - a
+context without any parent.
+
+This approach has several advantages:
+
+ - as a consequence of freeing a talloc context, all of its children
+ will be properly deallocated as well,
+ - the parent of a context can be changed at any time, which
+ results in moving the whole subtree under another node,
+ - it creates a more natural way of managing data structures.
+
+@subsection Example
+
+We have a structure that stores basic information about a user - his/her name,
+identification number and groups he/she is a member of:
+
+@code
+struct user {
+ uid_t uid;
+ char *username;
+ size_t num_groups;
+ char **groups;
+};
+@endcode
+
+We will allocate this structure using talloc. The result will be the following
+context tree:
+
+@image html context_tree.png
+
+@code
+/* create new top level context */
+struct user *user = talloc(NULL, struct user);
+
+user->uid = 1000;
+user->num_groups = N;
+
+/* make user the parent of following contexts */
+user->username = talloc_strdup(user, "Test user");
+user->groups = talloc_array(user, char*, user->num_groups);
+
+for (i = 0; i < user->num_groups; i++) {
+ /* make user->groups the parent of following context */
+ user->groups[i] = talloc_asprintf(user->groups,
+ "Test group %d", i);
+}
+@endcode
+
+This way, we have gained a lot of additional capabilities, one of which is
+very simple deallocation of the structure and all of its elements.
+
+With the C standard library we need first to iterate over the array of groups
+and free every element separately. Then we must deallocate the array that stores
+them. Next we deallocate the username and as the last step free the structure
+itself. But with talloc, the only operation we need to execute is freeing the
+structure context. Its descendants will be freed automatically.
+
+@code
+talloc_free(user);
+@endcode
+
+@section keep-hierarchy Always keep the hieararchy steady!
+
+The talloc is a hierarchy memory allocator. The hierarchy nature is what makes
+the programming more error proof. It makes the memory easier to manage and to
+free. Therefore, the first thing we should have on our mind is: <strong>always
+project our data structures into the talloc context hierarchy</strong>.
+
+That means if we have a structure, we should always use it as a parent context
+for its elements. This way we will not encounter any troubles when freeing this
+structure or when changing its parent. The same rule applies for arrays.
+
+@section creating-context Creating a talloc context
+
+Here are the most important functions that create a new talloc context.
+
+@subsection type-safe Type-safe functions
+
+It allocates the size that is necessary for the given type and returns a new,
+properly-casted pointer. This is the preferred way to create a new context as
+we can rely on the compiler to detect type mismatches.
+
+The name of the context is automatically set to the name of the data type which
+is used to simulate a dynamic type system.
+
+@code
+struct user *user = talloc(ctx, struct user);
+
+/* initialize to default values */
+user->uid = 0;
+user->name = NULL;
+user->num_groups = 0;
+user->groups = NULL;
+
+/* or we can achieve the same result with */
+struct user *user_zero = talloc_zero(ctx, struct user);
+@endcode
+
+@subsection zero-length Zero-length contexts
+
+The zero-length context is basically a context without any special semantical
+meaning. We can use it the same way as any other context. The only difference
+is that it consists only of the meta data about the context. Therefore, it is
+strictly of type <code>TALLOC_CTX*</code>. It is often used in cases where we
+want to aggregate several data structures under one parent (zero-length)
+context, such as a temporary context to contain memory needed within a single
+function that is not interesting to the caller. Allocating on a zero-length
+temporary context will make clean-up of the function simpler.
+
+@code
+TALLOC_CTX *tmp_ctx = NULL;
+struct foo *foo = NULL;
+struct bar *bar = NULL;
+
+/* new zero-length top level context */
+tmp_ctx = talloc_new(NULL);
+if (tmp_ctx == NULL) {
+ return ENOMEM;
+}
+
+foo = talloc(tmp_ctx, struct foo);
+bar = talloc(tmp_ctx, struct bar);
+
+/* free everything at once */
+talloc_free(tmp_ctx);
+@endcode
+
+@subsection context-see-also See also
+
+- talloc_size()
+- talloc_named()
+- @ref talloc_array
+- @ref talloc_string
+
+*/
diff --git a/lib/talloc/doc/tutorial_debugging.dox b/lib/talloc/doc/tutorial_debugging.dox
new file mode 100644
index 0000000..aadbb0d
--- /dev/null
+++ b/lib/talloc/doc/tutorial_debugging.dox
@@ -0,0 +1,116 @@
+/**
+@page libtalloc_debugging Chapter 6: Debugging
+
+Although talloc makes memory management significantly easier than the C standard
+library, developers are still only humans and can make mistakes. Therefore, it
+can be handy to know some tools for the inspection of talloc memory usage.
+
+@section log-abort Talloc log and abort
+
+We have already encountered the abort function in section @ref dts.
+In that case it was used when a type mismatch was detected. However, talloc
+calls this abort function in several more situations:
+
+- when the provided pointer is not a valid talloc context,
+- when the meta data is invalid - probably due to memory corruption,
+- and when an access after free is detected.
+
+The third one is probably the most interesting. It can help us with detecting
+an attempt to double-free a context or any other manipulation with it via
+talloc functions (using it as a parent, stealing it, etc.).
+
+Before the context is freed talloc sets a flag in the meta data. This is then
+used to detect the access after free. It basically works on the assumption that
+the memory stays unchanged (at least for a while) even when it is properly
+deallocated. This will work even if the memory is filled with the value
+specified in <code>TALLOC_FREE_FILL</code> environment variable, because it
+fills only the data part and leaves the meta data intact.
+
+Apart from the abort function, talloc uses a log function to provide additional
+information to the aforementioned violations. To enable logging we shall set the
+log function with one of:
+
+- talloc_set_log_fn()
+- talloc_set_log_stderr()
+
+The following code is a sample output of accessing a context after it has been
+freed:
+
+@code
+talloc_set_log_stderr();
+TALLOC_CTX *ctx = talloc_new(NULL);
+
+talloc_free(ctx);
+talloc_free(ctx);
+
+results in:
+talloc: access after free error - first free may be at ../src/main.c:55
+Bad talloc magic value - access after free
+@endcode
+
+Another example is an invalid context:
+
+@code
+talloc_set_log_stderr();
+TALLOC_CTX *ctx = talloc_new(NULL);
+char *str = strdup("not a talloc context");
+talloc_steal(ctx, str);
+
+results in:
+Bad talloc magic value - unknown value
+@endcode
+
+@section reports Memory usage reports
+
+Talloc can print reports of memory usage of a specified talloc context to a
+file (to <code>stdout</code> or <code>stderr</code>). The report can be
+simple or full. The simple report provides information only about the context
+itself and its direct descendants. The full report goes recursively through the
+entire context tree. See:
+
+- talloc_report()
+- talloc_report_full()
+
+We will use the following code to retrieve the sample report:
+
+@code
+struct foo {
+ char *str;
+};
+
+TALLOC_CTX *ctx = talloc_new(NULL);
+char *str = talloc_strdup(ctx, "my string");
+struct foo *foo = talloc_zero(ctx, struct foo);
+foo->str = talloc_strdup(foo, "I am Foo");
+char *str2 = talloc_strdup(foo, "Foo is my parent");
+
+/* print full report */
+talloc_report_full(ctx, stdout);
+@endcode
+
+It will print a full report of <code>ctx</code> to the standard output.
+The message should be similar to:
+
+@code
+full talloc report on 'talloc_new: ../src/main.c:82' (total 46 bytes in 5 blocks)
+ struct foo contains 34 bytes in 3 blocks (ref 0) 0x1495130
+ Foo is my parent contains 17 bytes in 1 blocks (ref 0) 0x1495200
+ I am Foo contains 9 bytes in 1 blocks (ref 0) 0x1495190
+ my string contains 10 bytes in 1 blocks (ref 0) 0x14950c0
+@endcode
+
+We can notice in this report that something is wrong with the context containing
+<code>struct foo</code>. We know that the structure has only one string element.
+However, we can see in the report that it has two children. This indicates that
+we have either violated the memory hierarchy or forgotten to free it as
+temporary data. Looking into the code, we can see that <code>"Foo is my parent"
+</code> should be attached to <code>ctx</code>.
+
+See also:
+
+- talloc_enable_null_tracking()
+- talloc_disable_null_tracking()
+- talloc_enable_leak_report()
+- talloc_enable_leak_report_full()
+
+*/
diff --git a/lib/talloc/doc/tutorial_destructors.dox b/lib/talloc/doc/tutorial_destructors.dox
new file mode 100644
index 0000000..ed06387
--- /dev/null
+++ b/lib/talloc/doc/tutorial_destructors.dox
@@ -0,0 +1,82 @@
+/**
+@page libtalloc_destructors Chapter 4: Using destructors
+
+@section destructors Using destructors
+
+Destructors are well known methods in the world of object oriented programming.
+A destructor is a method of an object that is automatically run when the object
+is destroyed. It is usually used to return resources taken by the object back to
+the system (e.g. closing file descriptors, terminating connection to a database,
+deallocating memory).
+
+With talloc we can take the advantage of destructors even in C. We can easily
+attach our own destructor to a talloc context. When the context is freed, the
+destructor will run automatically.
+
+To attach/detach a destructor to a talloc context use: talloc_set_destructor().
+
+@section destructors-example Example
+
+Imagine that we have a dynamically created linked list. Before we deallocate an
+element of the list, we need to make sure that we have successfully removed it
+from the list. Normally, this would be done by two commands in the exact order:
+remove it from the list and then free the element. With talloc, we can do this
+at once by setting a destructor on the element which will remove it from the
+list and talloc_free() will do the rest.
+
+The destructor would be:
+
+@code
+int list_remove(void *ctx)
+{
+ struct list_el *el = NULL;
+ el = talloc_get_type_abort(ctx, struct list_el);
+ /* remove element from the list */
+}
+@endcode
+
+GCC version 3 and newer can check for the types during the compilation. So if
+it is our major compiler, we can use a more advanced destructor:
+
+@code
+int list_remove(struct list_el *el)
+{
+ /* remove element from the list */
+}
+@endcode
+
+Now we will assign the destructor to the list element. We can do this directly
+in the function that inserts it.
+
+@code
+struct list_el* list_insert(TALLOC_CTX *mem_ctx,
+ struct list_el *where,
+ void *ptr)
+{
+ struct list_el *el = talloc(mem_ctx, struct list_el);
+ el->data = ptr;
+ /* insert into list */
+
+ talloc_set_destructor(el, list_remove);
+ return el;
+}
+@endcode
+
+Because talloc is a hierarchical memory allocator, we can go a step further and
+free the data with the element as well:
+
+@code
+struct list_el* list_insert_free(TALLOC_CTX *mem_ctx,
+ struct list_el *where,
+ void *ptr)
+{
+ struct list_el *el = NULL;
+ el = list_insert(mem_ctx, where, ptr);
+
+ talloc_steal(el, ptr);
+
+ return el;
+}
+@endcode
+
+*/
diff --git a/lib/talloc/doc/tutorial_dts.dox b/lib/talloc/doc/tutorial_dts.dox
new file mode 100644
index 0000000..75b5172
--- /dev/null
+++ b/lib/talloc/doc/tutorial_dts.dox
@@ -0,0 +1,109 @@
+/**
+@page libtalloc_dts Chapter 3: Dynamic type system
+
+@section dts Dynamic type system
+
+Generic programming in the C language is very difficult. There is no inheritance
+nor templates known from object oriented languages. There is no dynamic type
+system. Therefore, generic programming in this language is usually done by
+type-casting a variable to <code>void*</code> and transferring it through
+a generic function to a specialized callback as illustrated on the next listing.
+
+@code
+void generic_function(callback_fn cb, void *pvt)
+{
+ /* do some stuff and call the callback */
+ cb(pvt);
+}
+
+void specific_callback(void *pvt)
+{
+ struct specific_struct *data;
+ data = (struct specific_struct*)pvt;
+ /* ... */
+}
+
+void specific_function()
+{
+ struct specific_struct data;
+ generic_function(callback, &data);
+}
+@endcode
+
+Unfortunately, the type information is lost as a result of this type cast. The
+compiler cannot check the type during the compilation nor are we able to do it
+at runtime. Providing an invalid data type to the callback will result in
+unexpected behaviour (not necessarily a crash) of the application. This mistake
+is usually hard to detect because it is not the first thing which comes the
+mind.
+
+As we already know, every talloc context contains a name. This name is available
+at any time and it can be used to determine the type of a context even if we
+lose the type of a variable.
+
+Although the name of the context can be set to any arbitrary string, the best
+way of using it to simulate the dynamic type system is to set it directly to the
+type of the variable.
+
+It is recommended to use one of talloc() and talloc_array() (or its
+variants) to create the context as they set its name to the name of the
+given type automatically.
+
+If we have a context with such as a name, we can use two similar functions that
+do both the type check and the type cast for us:
+
+- talloc_get_type()
+- talloc_get_type_abort()
+
+@section dts-examples Examples
+
+The following example will show how generic programming with talloc is handled -
+if we provide invalid data to the callback, the program will be aborted. This
+is a sufficient reaction for such an error in most applications.
+
+@code
+void foo_callback(void *pvt)
+{
+ struct foo *data = talloc_get_type_abort(pvt, struct foo);
+ /* ... */
+}
+
+int do_foo()
+{
+ struct foo *data = talloc_zero(NULL, struct foo);
+ /* ... */
+ return generic_function(foo_callback, data);
+}
+@endcode
+
+But what if we are creating a service application that should be running for the
+uptime of a server, we may want to abort the application during the development
+process (to make sure the error is not overlooked) and try to recover from the
+error in the customer release. This can be achieved by creating a custom abort
+function with a conditional build.
+
+@code
+void my_abort(const char *reason)
+{
+ fprintf(stderr, "talloc abort: %s\n", reason);
+#ifdef ABORT_ON_TYPE_MISMATCH
+ abort();
+#endif
+}
+@endcode
+
+The usage of talloc_get_type_abort() would be then:
+
+@code
+talloc_set_abort_fn(my_abort);
+
+TALLOC_CTX *ctx = talloc_new(NULL);
+char *str = talloc_get_type_abort(ctx, char);
+if (str == NULL) {
+ /* recovery code */
+}
+/* talloc abort: ../src/main.c:25: Type mismatch:
+ name[talloc_new: ../src/main.c:24] expected[char] */
+@endcode
+
+*/
diff --git a/lib/talloc/doc/tutorial_introduction.dox b/lib/talloc/doc/tutorial_introduction.dox
new file mode 100644
index 0000000..418c38b
--- /dev/null
+++ b/lib/talloc/doc/tutorial_introduction.dox
@@ -0,0 +1,45 @@
+/**
+@page libtalloc_tutorial The Tutorial
+@section introduction Introduction
+
+Talloc is a hierarchical, reference counted memory pool system with destructors.
+It is built atop the C standard library and it defines a set of utility
+functions that altogether simplifies allocation and deallocation of data,
+especially for complex structures that contain many dynamically allocated
+elements such as strings and arrays.
+
+The main goals of this library are: removing the needs for creating a cleanup
+function for every complex structure, providing a logical organization of
+allocated memory blocks and reducing the likelihood of creating memory leaks in
+long-running applications. All of this is achieved by allocating memory in a
+hierarchical structure of talloc contexts such that deallocating one context
+recursively frees all of its descendants as well.
+
+@section main-features Main features
+- An open source project
+- A hierarchical memory model
+- Natural projection of data structures into the memory space
+- Simplifies memory management of large data structures
+- Automatic execution of a destructor before the memory is freed
+- Simulates a dynamic type system
+- Implements a transparent memory pool
+
+@section toc Table of contents:
+
+@subpage libtalloc_context
+
+@subpage libtalloc_stealing
+
+@subpage libtalloc_dts
+
+@subpage libtalloc_destructors
+
+@subpage libtalloc_pools
+
+@subpage libtalloc_debugging
+
+@subpage libtalloc_bestpractices
+
+@subpage libtalloc_threads
+
+*/
diff --git a/lib/talloc/doc/tutorial_pools.dox b/lib/talloc/doc/tutorial_pools.dox
new file mode 100644
index 0000000..a0d1e1a
--- /dev/null
+++ b/lib/talloc/doc/tutorial_pools.dox
@@ -0,0 +1,93 @@
+/**
+@page libtalloc_pools Chapter 5: Memory pools
+
+@section pools Memory pools
+
+Allocation of a new memory is an expensive operation and large programs can
+contain thousands of calls of malloc() for a single computation, where every
+call allocates only a very small amount of the memory. This can result in an
+undesirable slowdown of the application. We can avoid this slowdown by
+decreasing the number of malloc() calls by using a memory pool.
+
+A memory pool is a preallocated memory space with a fixed size. If we need to
+allocate new data we will take the desired amount of the memory from the pool
+instead of requesting a new memory from the system. This is done by creating a
+pointer that points inside the preallocated memory. Such a pool must not be
+reallocated as it would change its location - pointers that were pointing
+inside the pool would become invalid. Therefore, a memory pool requires a very
+good estimate of the required memory space.
+
+The talloc library contains its own implementation of a memory pool. It is
+highly transparent for the programmer. The only thing that needs to be done is
+an initialization of a new pool context using talloc_pool() -
+which can be used in the same way as any other context.
+
+Refactoring of existing code (that uses talloc) to take the advantage of a
+memory pool is quite simple due to the following properties of the pool context:
+
+- if we are allocating data on a pool context, it takes the desired
+ amount of memory from the pool,
+- if the context is a descendant of the pool context, it takes the space
+ from the pool as well,
+- if the pool does not have sufficient portion of memory left, it will
+ create a new non-pool context, leaving the pool intact
+
+@code
+/* allocate 1KiB in a pool */
+TALLOC_CTX *pool_ctx = talloc_pool(NULL, 1024);
+
+/* Take 512B from the pool, 512B is left there */
+void *ptr = talloc_size(pool_ctx, 512);
+
+/* 1024B > 512B, this will create new talloc chunk outside
+ the pool */
+void *ptr2 = talloc_size(ptr, 1024);
+
+/* The pool still contains 512 free bytes
+ * this will take 200B from them. */
+void *ptr3 = talloc_size(ptr, 200);
+
+/* This will destroy context 'ptr3' but the memory
+ * is not freed, the available space in the pool
+ * will increase to 512B. */
+talloc_free(ptr3);
+
+/* This will free memory taken by 'pool_ctx'
+ * and 'ptr2' as well. */
+talloc_free(pool_ctx);
+@endcode
+
+The above given is very convenient, but there is one big issue to be kept in
+mind. If the parent of a talloc pool child is changed to a parent that is
+outside of this pool, the whole pool memory will not be freed until the child is
+freed. For this reason we must be very careful when stealing a descendant of a
+pool context.
+
+@code
+TALLOC_CTX *mem_ctx = talloc_new(NULL);
+TALLOC_CTX *pool_ctx = talloc_pool(NULL, 1024);
+struct foo *foo = talloc(pool_ctx, struct foo);
+
+/* mem_ctx is not in the pool */
+talloc_steal(mem_ctx, foo);
+
+/* pool_ctx is marked as freed but the memory is not
+ deallocated, accessing the pool_ctx again will cause
+ an error */
+talloc_free(pool_ctx);
+
+/* This deallocates the pool_ctx. */
+talloc_free(mem_ctx);
+@endcode
+
+It may often be better to copy the memory we want instead of stealing it to
+avoid this problem. If we do not need to retain the context name (to keep the
+type information), we can use talloc_memdup() to do this.
+
+Copying the memory out of the pool may, however, discard all the performance
+boost given by the pool, depending on the size of the copied memory. Therefore,
+the code should be well profiled before taking this path. In general, the
+golden rule is: if we need to steal from the pool context, we should not
+use a pool context.
+
+*/
diff --git a/lib/talloc/doc/tutorial_stealing.dox b/lib/talloc/doc/tutorial_stealing.dox
new file mode 100644
index 0000000..67eae1d
--- /dev/null
+++ b/lib/talloc/doc/tutorial_stealing.dox
@@ -0,0 +1,55 @@
+/**
+@page libtalloc_stealing Chapter 2: Stealing a context
+
+@section stealing Stealing a context
+
+Talloc has the ability to change the parent of a talloc context to another
+one. This operation is commonly referred to as stealing and it is one of
+the most important actions performed with talloc contexts.
+
+Stealing a context is necessary if we want the pointer to outlive the context it
+is created on. This has many possible use cases, for instance stealing a result
+of a database search to an in-memory cache context, changing the parent of a
+field of a generic structure to a more specific one or vice-versa. The most
+common scenario, at least in Samba, is to steal output data from a function-specific
+context to the output context given as an argument of that function.
+
+@code
+struct foo {
+ char *a1;
+ char *a2;
+ char *a3;
+};
+
+struct bar {
+ char *wurst;
+ struct foo *foo;
+};
+
+struct foo *foo = talloc_zero(ctx, struct foo);
+foo->a1 = talloc_strdup(foo, "a1");
+foo->a2 = talloc_strdup(foo, "a2");
+foo->a3 = talloc_strdup(foo, "a3");
+
+struct bar *bar = talloc_zero(NULL, struct bar);
+/* change parent of foo from ctx to bar */
+bar->foo = talloc_steal(bar, foo);
+
+/* or do the same but assign foo = NULL */
+bar->foo = talloc_move(bar, &foo);
+@endcode
+
+The talloc_move() function is similar to the talloc_steal() function but
+additionally sets the source pointer to NULL.
+
+In general, the source pointer itself is not changed (it only replaces the
+parent in the meta data). But the common usage is that the result is
+assigned to another variable, thus further accessing the pointer from the
+original variable should be avoided unless it is necessary. In this case
+talloc_move() is the preferred way of stealing a context. Additionally sets the
+source pointer to NULL, thus.protects the pointer from being accidentally freed
+and accessed using the old variable after its parent has been changed.
+
+@image html stealing.png
+
+*/
diff --git a/lib/talloc/doc/tutorial_threads.dox b/lib/talloc/doc/tutorial_threads.dox
new file mode 100644
index 0000000..111bbf5
--- /dev/null
+++ b/lib/talloc/doc/tutorial_threads.dox
@@ -0,0 +1,203 @@
+/**
+@page libtalloc_threads Chapter 8: Using threads with talloc
+
+@section Talloc and thread safety
+
+The talloc library is not internally thread-safe, in that accesses
+to variables on a talloc context are not controlled by mutexes or
+other thread-safe primitives.
+
+However, so long as talloc_disable_null_tracking() is called from
+the main thread to disable global variable access within talloc,
+then each thread can safely use its own top level talloc context
+allocated off the NULL context.
+
+For example:
+
+@code
+static void *thread_fn(void *arg)
+{
+ const char *ctx_name = (const char *)arg;
+ /*
+ * Create a new top level talloc hierarchy in
+ * this thread.
+ */
+ void *top_ctx = talloc_named_const(NULL, 0, "top");
+ if (top_ctx == NULL) {
+ return NULL;
+ }
+ sub_ctx = talloc_named_const(top_ctx, 100, ctx_name);
+ if (sub_ctx == NULL) {
+ return NULL;
+ }
+
+ /*
+ * Do more processing/talloc calls on top_ctx
+ * and its children.
+ */
+ ......
+
+ talloc_free(top_ctx);
+ return value;
+}
+@endcode
+
+is a perfectly safe use of talloc within a thread.
+
+The problem comes when one thread wishes to move some
+memory allocated on its local top level talloc context
+to another thread. Care must be taken to add data access
+exclusion to prevent memory corruption. One method would
+be to lock a mutex before any talloc call on each thread,
+but this would push the burden of total talloc thread-safety
+on the poor user of the library.
+
+A much easier way to transfer talloced memory between
+threads is by the use of an intermediate, mutex locked,
+intermediate variable.
+
+An example of this is below - taken from test code inside
+the talloc testsuite.
+
+The main thread creates 1000 sub-threads, and then accepts
+the transfer of some thread-talloc'ed memory onto its top
+level context from each thread in turn.
+
+A pthread mutex and condition variable are used to
+synchronize the transfer via the intermediate_ptr
+variable.
+
+@code
+/* Required sync variables. */
+static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t condvar = PTHREAD_COND_INITIALIZER;
+
+/* Intermediate talloc pointer for transfer. */
+static void *intermediate_ptr;
+
+/* Subthread. */
+static void *thread_fn(void *arg)
+{
+ int ret;
+ const char *ctx_name = (const char *)arg;
+ void *sub_ctx = NULL;
+ /*
+ * Do stuff that creates a new talloc hierarchy in
+ * this thread.
+ */
+ void *top_ctx = talloc_named_const(NULL, 0, "top");
+ if (top_ctx == NULL) {
+ return NULL;
+ }
+ sub_ctx = talloc_named_const(top_ctx, 100, ctx_name);
+ if (sub_ctx == NULL) {
+ return NULL;
+ }
+
+ /*
+ * Now transfer a pointer from our hierarchy
+ * onto the intermediate ptr.
+ */
+ ret = pthread_mutex_lock(&mtx);
+ if (ret != 0) {
+ talloc_free(top_ctx);
+ return NULL;
+ }
+
+ /* Wait for intermediate_ptr to be free. */
+ while (intermediate_ptr != NULL) {
+ ret = pthread_cond_wait(&condvar, &mtx);
+ if (ret != 0) {
+ talloc_free(top_ctx);
+ return NULL;
+ }
+ }
+
+ /* and move our memory onto it from our toplevel hierarchy. */
+ intermediate_ptr = talloc_move(NULL, &sub_ctx);
+
+ /* Tell the main thread it's ready for pickup. */
+ pthread_cond_broadcast(&condvar);
+ pthread_mutex_unlock(&mtx);
+
+ talloc_free(top_ctx);
+ return NULL;
+}
+
+/* Main thread. */
+
+#define NUM_THREADS 1000
+
+static bool test_pthread_talloc_passing(void)
+{
+ int i;
+ int ret;
+ char str_array[NUM_THREADS][20];
+ pthread_t thread_id;
+ void *mem_ctx;
+
+ /*
+ * Important ! Null tracking breaks threaded talloc.
+ * It *must* be turned off.
+ */
+ talloc_disable_null_tracking();
+
+ /* Main thread toplevel context. */
+ mem_ctx = talloc_named_const(NULL, 0, "toplevel");
+ if (mem_ctx == NULL) {
+ return false;
+ }
+
+ /*
+ * Spin off NUM_THREADS threads.
+ * They will use their own toplevel contexts.
+ */
+ for (i = 0; i < NUM_THREADS; i++) {
+ (void)snprintf(str_array[i],
+ 20,
+ "thread:%d",
+ i);
+ if (str_array[i] == NULL) {
+ return false;
+ }
+ ret = pthread_create(&thread_id,
+ NULL,
+ thread_fn,
+ str_array[i]);
+ if (ret != 0) {
+ return false;
+ }
+ }
+
+ /* Now wait for NUM_THREADS transfers of the talloc'ed memory. */
+ for (i = 0; i < NUM_THREADS; i++) {
+ ret = pthread_mutex_lock(&mtx);
+ if (ret != 0) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ /* Wait for intermediate_ptr to have our data. */
+ while (intermediate_ptr == NULL) {
+ ret = pthread_cond_wait(&condvar, &mtx);
+ if (ret != 0) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+ }
+
+ /* and move it onto our toplevel hierarchy. */
+ (void)talloc_move(mem_ctx, &intermediate_ptr);
+
+ /* Tell the sub-threads we're ready for another. */
+ pthread_cond_broadcast(&condvar);
+ pthread_mutex_unlock(&mtx);
+ }
+
+ /* Dump the hierarchy. */
+ talloc_report(mem_ctx, stdout);
+ talloc_free(mem_ctx);
+ return true;
+}
+@endcode
+*/
diff --git a/lib/talloc/doxy.config b/lib/talloc/doxy.config
new file mode 100644
index 0000000..0e27d61
--- /dev/null
+++ b/lib/talloc/doxy.config
@@ -0,0 +1,1807 @@
+# Doxyfile 1.8.0
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
+
+PROJECT_NAME = talloc
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = 2.0
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding
+# "class=itcl::class" will allow you to use the command class in the
+# itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this
+# tag. The format is ext=language, where ext is a file extension, and language
+# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
+# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
+# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
+# comments according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you
+# can mix doxygen, HTML, and XML commands with Markdown formatting.
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data fields will be shown inline in the documentation
+# of the scope in which they are defined (i.e. file, namespace, or group
+# documentation), provided this scope is documented. If set to NO (the default),
+# structs, classes, and unions are shown on a separate page (for HTML and Man
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE = 0
+
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
+# their name and scope. Since this can be an expensive process and often the
+# same symbol appear multiple times in the code, doxygen keeps a cache of
+# pre-resolved symbols. If the cache is too small doxygen will become slower.
+# If the cache is too large, memory is wasted. The cache size is given by this
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = NO
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = YES
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. The create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# requires the bibtex tool to be installed. See also
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
+# feature you need bibtex and perl available in the search path.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = . \
+ doc
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS = *.cpp \
+ *.cc \
+ *.c \
+ *.h \
+ *.hh \
+ *.hpp \
+ *.dox
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS = */.git/*
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH = doc
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+# for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is advised to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# style sheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the style sheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE =
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
+# at top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it. Since the tabs have the same information as the
+# navigation tree you can set this option to NO if you already set
+# GENERATE_TREEVIEW to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+# Since the tree basically has the same information as the tab index you
+# could consider to set DISABLE_INDEX to NO when enabling this option.
+
+GENERATE_TREEVIEW = NONE
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you may also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to
+# the MathJax Content Delivery Network so you can quickly see the result without
+# installing MathJax.
+# However, it is strongly recommended to install a local
+# copy of MathJax from http://www.mathjax.org before deployment.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvantages are that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load style sheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = YES
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = DOXYGEN \
+ PRINTF_ATTRIBUTE(x,y)=
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. For each
+# tag file the location of the external documentation should be added. The
+# format of a tag file without this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths
+# or URLs. Note that each tag file must have a unique name (where the name does
+# NOT include the path). If a tag file is not located in the directory in which
+# doxygen is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS = 0
+
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
+
+DOT_FONTNAME = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside
+# the class node. If there are many fields or methods and many nodes the
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
+# threshold limits the number of items for each type to make the size more
+# managable. Set this to 0 for no limit. Note that the threshold may be
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG = NO
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
diff --git a/lib/talloc/man/talloc.3.xml b/lib/talloc/man/talloc.3.xml
new file mode 100644
index 0000000..c51061f
--- /dev/null
+++ b/lib/talloc/man/talloc.3.xml
@@ -0,0 +1,814 @@
+<?xml version="1.0"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<refentry>
+ <refentryinfo><date>2015-04-10</date></refentryinfo>
+ <refmeta>
+ <refentrytitle>talloc</refentrytitle>
+ <manvolnum>3</manvolnum>
+ <refmiscinfo class="source">Samba</refmiscinfo>
+ <refmiscinfo class="manual">System Administration tools</refmiscinfo>
+ <refmiscinfo class="version">4.0</refmiscinfo>
+ </refmeta>
+ <refnamediv>
+ <refname>talloc</refname>
+<refpurpose>hierarchical reference counted memory pool system with destructors</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+<synopsis>#include &lt;talloc.h&gt;</synopsis>
+ </refsynopsisdiv>
+ <refsect1><title>DESCRIPTION</title>
+ <para>
+ If you are used to talloc from Samba3 then please read this
+ carefully, as talloc has changed a lot.
+ </para>
+ <para>
+ The new talloc is a hierarchical, reference counted memory pool
+ system with destructors. Quite a mouthful really, but not too bad
+ once you get used to it.
+ </para>
+ <para>
+ Perhaps the biggest change from Samba3 is that there is no
+ distinction between a "talloc context" and a "talloc pointer". Any
+ pointer returned from talloc() is itself a valid talloc context.
+ This means you can do this:
+ </para>
+ <programlisting>
+ struct foo *X = talloc(mem_ctx, struct foo);
+ X->name = talloc_strdup(X, "foo");
+ </programlisting>
+ <para>
+ and the pointer <literal role="code">X-&gt;name</literal>
+ would be a "child" of the talloc context <literal
+ role="code">X</literal> which is itself a child of
+ <literal role="code">mem_ctx</literal>. So if you do
+ <literal role="code">talloc_free(mem_ctx)</literal> then
+ it is all destroyed, whereas if you do <literal
+ role="code">talloc_free(X)</literal> then just <literal
+ role="code">X</literal> and <literal
+ role="code">X-&gt;name</literal> are destroyed, and if
+ you do <literal
+ role="code">talloc_free(X-&gt;name)</literal> then just
+ the name element of <literal role="code">X</literal> is
+ destroyed.
+ </para>
+ <para>
+ If you think about this, then what this effectively gives you is an
+ n-ary tree, where you can free any part of the tree with
+ talloc_free().
+ </para>
+ <para>
+ If you find this confusing, then I suggest you run the <literal
+ role="code">testsuite</literal> program to watch talloc
+ in action. You may also like to add your own tests to <literal
+ role="code">testsuite.c</literal> to clarify how some
+ particular situation is handled.
+ </para>
+ </refsect1>
+ <refsect1><title>TALLOC API</title>
+ <para>
+ The following is a complete guide to the talloc API. Read it all at
+ least twice.
+ </para>
+ <refsect2><title>(type *)talloc(const void *ctx, type);</title>
+ <para>
+ The talloc() macro is the core of the talloc library. It takes a
+ memory <emphasis role="italic">ctx</emphasis> and a <emphasis
+ role="italic">type</emphasis>, and returns a pointer to a new
+ area of memory of the given <emphasis
+ role="italic">type</emphasis>.
+ </para>
+ <para>
+ The returned pointer is itself a talloc context, so you can use
+ it as the <emphasis role="italic">ctx</emphasis> argument to more
+ calls to talloc() if you wish.
+ </para>
+ <para>
+ The returned pointer is a "child" of the supplied context. This
+ means that if you talloc_free() the <emphasis
+ role="italic">ctx</emphasis> then the new child disappears as
+ well. Alternatively you can free just the child.
+ </para>
+ <para>
+ The <emphasis role="italic">ctx</emphasis> argument to talloc()
+ can be NULL, in which case a new top level context is created.
+ </para>
+ </refsect2>
+ <refsect2><title>void *talloc_size(const void *ctx, size_t size);</title>
+ <para>
+ The function talloc_size() should be used when you don't have a
+ convenient type to pass to talloc(). Unlike talloc(), it is not
+ type safe (as it returns a void *), so you are on your own for
+ type checking.
+ </para>
+ </refsect2>
+ <refsect2><title>(typeof(ptr)) talloc_ptrtype(const void *ctx, ptr);</title>
+ <para>
+ The talloc_ptrtype() macro should be used when you have a pointer and
+ want to allocate memory to point at with this pointer. When compiling
+ with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_size()
+ and talloc_get_name() will return the current location in the source file.
+ and not the type.
+ </para>
+ </refsect2>
+ <refsect2><title>int talloc_free(void *ptr);</title>
+ <para>
+ The talloc_free() function frees a piece of talloc memory, and
+ all its children. You can call talloc_free() on any pointer
+ returned by talloc().
+ </para>
+ <para>
+ The return value of talloc_free() indicates success or failure,
+ with 0 returned for success and -1 for failure. The only
+ possible failure condition is if <emphasis
+ role="italic">ptr</emphasis> had a destructor attached to it and
+ the destructor returned -1. See <link
+ linkend="talloc_set_destructor"><quote>talloc_set_destructor()</quote></link>
+ for details on destructors.
+ </para>
+ <para>
+ If this pointer has an additional parent when talloc_free() is
+ called then the memory is not actually released, but instead the
+ most recently established parent is destroyed. See <link
+ linkend="talloc_reference"><quote>talloc_reference()</quote></link>
+ for details on establishing additional parents.
+ </para>
+ <para>
+ For more control on which parent is removed, see <link
+ linkend="talloc_unlink"><quote>talloc_unlink()</quote></link>.
+ </para>
+ <para>
+ talloc_free() operates recursively on its children.
+ </para>
+ <para>
+ From the 2.0 version of talloc, as a special case,
+ talloc_free() is refused on pointers that have more than one
+ parent, as talloc would have no way of knowing which parent
+ should be removed. To free a pointer that has more than one
+ parent please use talloc_unlink().
+ </para>
+ <para>
+ To help you find problems in your code caused by this behaviour, if
+ you do try and free a pointer with more than one parent then the
+ talloc logging function will be called to give output like this:
+ </para>
+ <para>
+ <screen format="linespecific">
+ ERROR: talloc_free with references at some_dir/source/foo.c:123
+ reference at some_dir/source/other.c:325
+ reference at some_dir/source/third.c:121
+ </screen>
+ </para>
+ <para>
+ Please see the documentation for talloc_set_log_fn() and
+ talloc_set_log_stderr() for more information on talloc logging
+ functions.
+ </para>
+ </refsect2>
+ <refsect2 id="talloc_reference"><title>void *talloc_reference(const void *ctx, const void *ptr);</title>
+ <para>
+ The talloc_reference() function makes <emphasis
+ role="italic">ctx</emphasis> an additional parent of <emphasis
+ role="italic">ptr</emphasis>.
+ </para>
+ <para>
+ The return value of talloc_reference() is always the original
+ pointer <emphasis role="italic">ptr</emphasis>, unless talloc ran
+ out of memory in creating the reference in which case it will
+ return NULL (each additional reference consumes around 48 bytes
+ of memory on intel x86 platforms).
+ </para>
+ <para>
+ If <emphasis role="italic">ptr</emphasis> is NULL, then the
+ function is a no-op, and simply returns NULL.
+ </para>
+ <para>
+ After creating a reference you can free it in one of the
+ following ways:
+ </para>
+ <para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ you can talloc_free() any parent of the original pointer.
+ That will reduce the number of parents of this pointer by 1,
+ and will cause this pointer to be freed if it runs out of
+ parents.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ you can talloc_free() the pointer itself if it has at maximum one
+ parent. This behaviour has been changed since the release of version
+ 2.0. Further information in the description of "talloc_free".
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ For more control on which parent to remove, see <link
+ linkend="talloc_unlink"><quote>talloc_unlink()</quote></link>.
+ </para>
+ </refsect2>
+ <refsect2 id="talloc_unlink"><title>int talloc_unlink(const void *ctx, void *ptr);</title>
+ <para>
+ The talloc_unlink() function removes a specific parent from
+ <emphasis role="italic">ptr</emphasis>. The <emphasis
+ role="italic">ctx</emphasis> passed must either be a context used
+ in talloc_reference() with this pointer, or must be a direct
+ parent of ptr.
+ </para>
+ <para>
+ Note that if the parent has already been removed using
+ talloc_free() then this function will fail and will return -1.
+ Likewise, if <emphasis role="italic">ptr</emphasis> is NULL, then
+ the function will make no modifications and return -1.
+ </para>
+ <para>
+ Usually you can just use talloc_free() instead of
+ talloc_unlink(), but sometimes it is useful to have the
+ additional control on which parent is removed.
+ </para>
+ </refsect2>
+ <refsect2 id="talloc_set_destructor"><title>void talloc_set_destructor(const void *ptr, int (*destructor)(void *));</title>
+ <para>
+ The function talloc_set_destructor() sets the <emphasis
+ role="italic">destructor</emphasis> for the pointer <emphasis
+ role="italic">ptr</emphasis>. A <emphasis
+ role="italic">destructor</emphasis> is a function that is called
+ when the memory used by a pointer is about to be released. The
+ destructor receives <emphasis role="italic">ptr</emphasis> as an
+ argument, and should return 0 for success and -1 for failure.
+ </para>
+ <para>
+ The <emphasis role="italic">destructor</emphasis> can do anything
+ it wants to, including freeing other pieces of memory. A common
+ use for destructors is to clean up operating system resources
+ (such as open file descriptors) contained in the structure the
+ destructor is placed on.
+ </para>
+ <para>
+ You can only place one destructor on a pointer. If you need more
+ than one destructor then you can create a zero-length child of
+ the pointer and place an additional destructor on that.
+ </para>
+ <para>
+ To remove a destructor call talloc_set_destructor() with NULL for
+ the destructor.
+ </para>
+ <para>
+ If your destructor attempts to talloc_free() the pointer that it
+ is the destructor for then talloc_free() will return -1 and the
+ free will be ignored. This would be a pointless operation
+ anyway, as the destructor is only called when the memory is just
+ about to go away.
+ </para>
+ </refsect2>
+ <refsect2><title>int talloc_increase_ref_count(const void *<emphasis role="italic">ptr</emphasis>);</title>
+ <para>
+ The talloc_increase_ref_count(<emphasis
+ role="italic">ptr</emphasis>) function is exactly equivalent to:
+ </para>
+ <programlisting>talloc_reference(NULL, ptr);</programlisting>
+ <para>
+ You can use either syntax, depending on which you think is
+ clearer in your code.
+ </para>
+ <para>
+ It returns 0 on success and -1 on failure.
+ </para>
+ </refsect2>
+ <refsect2><title>size_t talloc_reference_count(const void *<emphasis role="italic">ptr</emphasis>);</title>
+ <para>
+ Return the number of references to the pointer.
+ </para>
+ </refsect2>
+ <refsect2 id="talloc_set_name"><title>void talloc_set_name(const void *ptr, const char *fmt, ...);</title>
+ <para>
+ Each talloc pointer has a "name". The name is used principally
+ for debugging purposes, although it is also possible to set and
+ get the name on a pointer in as a way of "marking" pointers in
+ your code.
+ </para>
+ <para>
+ The main use for names on pointer is for "talloc reports". See
+ <link
+ linkend="talloc_report"><quote>talloc_report_depth_cb()</quote></link>,
+ <link
+ linkend="talloc_report"><quote>talloc_report_depth_file()</quote></link>,
+ <link
+ linkend="talloc_report"><quote>talloc_report()</quote></link>
+ <link
+ linkend="talloc_report"><quote>talloc_report()</quote></link>
+ and <link
+ linkend="talloc_report_full"><quote>talloc_report_full()</quote></link>
+ for details. Also see <link
+ linkend="talloc_enable_leak_report"><quote>talloc_enable_leak_report()</quote></link>
+ and <link
+ linkend="talloc_enable_leak_report_full"><quote>talloc_enable_leak_report_full()</quote></link>.
+ </para>
+ <para>
+ The talloc_set_name() function allocates memory as a child of the
+ pointer. It is logically equivalent to:
+ </para>
+ <programlisting>talloc_set_name_const(ptr, talloc_asprintf(ptr, fmt, ...));</programlisting>
+ <para>
+ Note that multiple calls to talloc_set_name() will allocate more
+ memory without releasing the name. All of the memory is released
+ when the ptr is freed using talloc_free().
+ </para>
+ </refsect2>
+ <refsect2><title>void talloc_set_name_const(const void *<emphasis role="italic">ptr</emphasis>, const char *<emphasis role="italic">name</emphasis>);</title>
+ <para>
+ The function talloc_set_name_const() is just like
+ talloc_set_name(), but it takes a string constant, and is much
+ faster. It is extensively used by the "auto naming" macros, such
+ as talloc_p().
+ </para>
+ <para>
+ This function does not allocate any memory. It just copies the
+ supplied pointer into the internal representation of the talloc
+ ptr. This means you must not pass a <emphasis
+ role="italic">name</emphasis> pointer to memory that will
+ disappear before <emphasis role="italic">ptr</emphasis> is freed
+ with talloc_free().
+ </para>
+ </refsect2>
+ <refsect2><title>void *talloc_named(const void *<emphasis role="italic">ctx</emphasis>, size_t <emphasis role="italic">size</emphasis>, const char *<emphasis role="italic">fmt</emphasis>, ...);</title>
+ <para>
+ The talloc_named() function creates a named talloc pointer. It
+ is equivalent to:
+ </para>
+ <programlisting>ptr = talloc_size(ctx, size);
+talloc_set_name(ptr, fmt, ....);</programlisting>
+ </refsect2>
+ <refsect2><title>void *talloc_named_const(const void *<emphasis role="italic">ctx</emphasis>, size_t <emphasis role="italic">size</emphasis>, const char *<emphasis role="italic">name</emphasis>);</title>
+ <para>
+ This is equivalent to:
+ </para>
+ <programlisting>ptr = talloc_size(ctx, size);
+talloc_set_name_const(ptr, name);</programlisting>
+ </refsect2>
+ <refsect2><title>const char *talloc_get_name(const void *<emphasis role="italic">ptr</emphasis>);</title>
+ <para>
+ This returns the current name for the given talloc pointer,
+ <emphasis role="italic">ptr</emphasis>. See <link
+ linkend="talloc_set_name"><quote>talloc_set_name()</quote></link>
+ for details.
+ </para>
+ </refsect2>
+ <refsect2><title>void *talloc_init(const char *<emphasis role="italic">fmt</emphasis>, ...);</title>
+ <para>
+ This function creates a zero length named talloc context as a top
+ level context. It is equivalent to:
+ </para>
+ <programlisting>talloc_named(NULL, 0, fmt, ...);</programlisting>
+ </refsect2>
+ <refsect2><title>void *talloc_new(void *<emphasis role="italic">ctx</emphasis>);</title>
+ <para>
+ This is a utility macro that creates a new memory context hanging
+ off an existing context, automatically naming it "talloc_new:
+ __location__" where __location__ is the source line it is called
+ from. It is particularly useful for creating a new temporary
+ working context.
+ </para>
+ </refsect2>
+ <refsect2><title>(<emphasis role="italic">type</emphasis> *)talloc_realloc(const void *<emphasis role="italic">ctx</emphasis>, void *<emphasis role="italic">ptr</emphasis>, <emphasis role="italic">type</emphasis>, <emphasis role="italic">count</emphasis>);</title>
+ <para>
+ The talloc_realloc() macro changes the size of a talloc pointer.
+ It has the following equivalences:
+ </para>
+ <programlisting>talloc_realloc(ctx, NULL, type, 1) ==> talloc(ctx, type);
+talloc_realloc(ctx, ptr, type, 0) ==> talloc_free(ptr);</programlisting>
+ <para>
+ The <emphasis role="italic">ctx</emphasis> argument is only used
+ if <emphasis role="italic">ptr</emphasis> is not NULL, otherwise
+ it is ignored.
+ </para>
+ <para>
+ talloc_realloc() returns the new pointer, or NULL on failure.
+ The call will fail either due to a lack of memory, or because the
+ pointer has more than one parent (see <link
+ linkend="talloc_reference"><quote>talloc_reference()</quote></link>).
+ </para>
+ </refsect2>
+ <refsect2><title>void *talloc_realloc_size(const void *ctx, void *ptr, size_t size);</title>
+ <para>
+ the talloc_realloc_size() function is useful when the type is not
+ known so the type-safe talloc_realloc() cannot be used.
+ </para>
+ </refsect2>
+ <refsect2><title>TYPE *talloc_steal(const void *<emphasis role="italic">new_ctx</emphasis>, const TYPE *<emphasis role="italic">ptr</emphasis>);</title>
+ <para>
+ The talloc_steal() function changes the parent context of a
+ talloc pointer. It is typically used when the context that the
+ pointer is currently a child of is going to be freed and you wish
+ to keep the memory for a longer time.
+ </para>
+ <para>
+ The talloc_steal() function returns the pointer that you pass it.
+ It does not have any failure modes.
+ </para>
+ <para>
+ It is possible to produce loops in the parent/child
+ relationship if you are not careful with talloc_steal(). No
+ guarantees are provided as to your sanity or the safety of your
+ data if you do this.
+ </para>
+ <para>
+ Note that if you try and call talloc_steal() on a pointer that has
+ more than one parent then the result is ambiguous. Talloc will choose
+ to remove the parent that is currently indicated by talloc_parent()
+ and replace it with the chosen parent. You will also get a message
+ like this via the talloc logging functions:
+ </para>
+ <para>
+ <screen format="linespecific">
+ WARNING: talloc_steal with references at some_dir/source/foo.c:123
+ reference at some_dir/source/other.c:325
+ reference at some_dir/source/third.c:121
+ </screen>
+ </para>
+ <para>
+ To unambiguously change the parent of a pointer please see
+ the
+ function <link linkend="talloc_reference"><quote>talloc_reparent()</quote></link>. See
+ the talloc_set_log_fn() documentation for more information
+ on talloc logging.
+ </para>
+ </refsect2>
+ <refsect2><title>TYPE *talloc_reparent(const void *<emphasis role="italic">old_parent</emphasis>, const void *<emphasis role="italic">new_parent</emphasis>, const TYPE *<emphasis role="italic">ptr</emphasis>);</title>
+ <para>
+ The talloc_reparent() function changes the parent context of a talloc
+ pointer. It is typically used when the context that the pointer is
+ currently a child of is going to be freed and you wish to keep the
+ memory for a longer time.
+ </para>
+ <para>
+ The talloc_reparent() function returns the pointer that you pass it. It
+ does not have any failure modes.
+ </para>
+ <para>
+ The difference between talloc_reparent() and talloc_steal() is that
+ talloc_reparent() can specify which parent you wish to change. This is
+ useful when a pointer has multiple parents via references.
+ </para>
+ </refsect2>
+ <refsect2><title>TYPE *talloc_move(const void *<emphasis role="italic">new_ctx</emphasis>, TYPE **<emphasis role="italic">ptr</emphasis>);</title>
+ <para>
+ The talloc_move() function is a wrapper around
+ talloc_steal() which zeros the source pointer after the
+ move. This avoids a potential source of bugs where a
+ programmer leaves a pointer in two structures, and uses the
+ pointer from the old structure after it has been moved to a
+ new one.
+ </para>
+ </refsect2>
+ <refsect2><title>size_t talloc_total_size(const void *<emphasis role="italic">ptr</emphasis>);</title>
+ <para>
+ The talloc_total_size() function returns the total size in bytes
+ used by this pointer and all child pointers. Mostly useful for
+ debugging.
+ </para>
+ <para>
+ Passing NULL is allowed, but it will only give a meaningful
+ result if talloc_enable_leak_report() or
+ talloc_enable_leak_report_full() has been called.
+ </para>
+ </refsect2>
+ <refsect2><title>size_t talloc_total_blocks(const void *<emphasis role="italic">ptr</emphasis>);</title>
+ <para>
+ The talloc_total_blocks() function returns the total memory block
+ count used by this pointer and all child pointers. Mostly useful
+ for debugging.
+ </para>
+ <para>
+ Passing NULL is allowed, but it will only give a meaningful
+ result if talloc_enable_leak_report() or
+ talloc_enable_leak_report_full() has been called.
+ </para>
+ </refsect2>
+ <refsect2 id="talloc_report"><title>void talloc_report(const void *ptr, FILE *f);</title>
+ <para>
+ The talloc_report() function prints a summary report of all
+ memory used by <emphasis role="italic">ptr</emphasis>. One line
+ of report is printed for each immediate child of ptr, showing the
+ total memory and number of blocks used by that child.
+ </para>
+ <para>
+ You can pass NULL for the pointer, in which case a report is
+ printed for the top level memory context, but only if
+ talloc_enable_leak_report() or talloc_enable_leak_report_full()
+ has been called.
+ </para>
+ </refsect2>
+ <refsect2 id="talloc_report_full"><title>void talloc_report_full(const void *<emphasis role="italic">ptr</emphasis>, FILE *<emphasis role="italic">f</emphasis>);</title>
+ <para>
+ This provides a more detailed report than talloc_report(). It
+ will recursively print the entire tree of memory referenced by
+ the pointer. References in the tree are shown by giving the name
+ of the pointer that is referenced.
+ </para>
+ <para>
+ You can pass NULL for the pointer, in which case a report is
+ printed for the top level memory context, but only if
+ talloc_enable_leak_report() or talloc_enable_leak_report_full()
+ has been called.
+ </para>
+ </refsect2>
+ <refsect2 id="talloc_report_depth_cb">
+ <funcsynopsis><funcprototype>
+ <funcdef>void <function>talloc_report_depth_cb</function></funcdef>
+ <paramdef><parameter>const void *ptr</parameter></paramdef>
+ <paramdef><parameter>int depth</parameter></paramdef>
+ <paramdef><parameter>int max_depth</parameter></paramdef>
+ <paramdef><parameter>void (*callback)(const void *ptr, int depth, int max_depth, int is_ref, void *priv)</parameter></paramdef>
+ <paramdef><parameter>void *priv</parameter></paramdef>
+ </funcprototype></funcsynopsis>
+ <para>
+ This provides a more flexible reports than talloc_report(). It
+ will recursively call the callback for the entire tree of memory
+ referenced by the pointer. References in the tree are passed with
+ <emphasis role="italic">is_ref = 1</emphasis> and the pointer that is referenced.
+ </para>
+ <para>
+ You can pass NULL for the pointer, in which case a report is
+ printed for the top level memory context, but only if
+ talloc_enable_leak_report() or talloc_enable_leak_report_full()
+ has been called.
+ </para>
+ <para>
+ The recursion is stopped when depth >= max_depth.
+ max_depth = -1 means only stop at leaf nodes.
+ </para>
+ </refsect2>
+ <refsect2 id="talloc_report_depth_file">
+ <funcsynopsis><funcprototype>
+ <funcdef>void <function>talloc_report_depth_file</function></funcdef>
+ <paramdef><parameter>const void *ptr</parameter></paramdef>
+ <paramdef><parameter>int depth</parameter></paramdef>
+ <paramdef><parameter>int max_depth</parameter></paramdef>
+ <paramdef><parameter>FILE *f</parameter></paramdef>
+ </funcprototype></funcsynopsis>
+ <para>
+ This provides a more flexible reports than talloc_report(). It
+ will let you specify the depth and max_depth.
+ </para>
+ </refsect2>
+ <refsect2 id="talloc_enable_leak_report"><title>void talloc_enable_leak_report(void);</title>
+ <para>
+ This enables calling of talloc_report(NULL, stderr) when the
+ program exits. In Samba4 this is enabled by using the
+ --leak-report command line option.
+ </para>
+ <para>
+ For it to be useful, this function must be called before any
+ other talloc function as it establishes a "null context" that
+ acts as the top of the tree. If you don't call this function
+ first then passing NULL to talloc_report() or
+ talloc_report_full() won't give you the full tree printout.
+ </para>
+ <para>
+ Here is a typical talloc report:
+ </para>
+ <screen format="linespecific">talloc report on 'null_context' (total 267 bytes in 15 blocks)
+libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks
+libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks
+iconv(UTF8,CP850) contains 42 bytes in 2 blocks
+libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks
+iconv(CP850,UTF8) contains 42 bytes in 2 blocks
+iconv(UTF8,UTF-16LE) contains 45 bytes in 2 blocks
+iconv(UTF-16LE,UTF8) contains 45 bytes in 2 blocks
+ </screen>
+ </refsect2>
+ <refsect2 id="talloc_enable_leak_report_full"><title>void talloc_enable_leak_report_full(void);</title>
+ <para>
+ This enables calling of talloc_report_full(NULL, stderr) when the
+ program exits. In Samba4 this is enabled by using the
+ --leak-report-full command line option.
+ </para>
+ <para>
+ For it to be useful, this function must be called before any
+ other talloc function as it establishes a "null context" that
+ acts as the top of the tree. If you don't call this function
+ first then passing NULL to talloc_report() or
+ talloc_report_full() won't give you the full tree printout.
+ </para>
+ <para>
+ Here is a typical full report:
+ </para>
+ <screen format="linespecific">full talloc report on 'root' (total 18 bytes in 8 blocks)
+p1 contains 18 bytes in 7 blocks (ref 0)
+ r1 contains 13 bytes in 2 blocks (ref 0)
+ reference to: p2
+ p2 contains 1 bytes in 1 blocks (ref 1)
+ x3 contains 1 bytes in 1 blocks (ref 0)
+ x2 contains 1 bytes in 1 blocks (ref 0)
+ x1 contains 1 bytes in 1 blocks (ref 0)
+ </screen>
+ </refsect2>
+ <refsect2><title>(<emphasis role="italic">type</emphasis> *)talloc_zero(const void *<emphasis role="italic">ctx</emphasis>, <emphasis role="italic">type</emphasis>);</title>
+ <para>
+ The talloc_zero() macro is equivalent to:
+ </para>
+ <programlisting>ptr = talloc(ctx, type);
+if (ptr) memset(ptr, 0, sizeof(type));</programlisting>
+ </refsect2>
+ <refsect2><title>void *talloc_zero_size(const void *<emphasis role="italic">ctx</emphasis>, size_t <emphasis role="italic">size</emphasis>)</title>
+ <para>
+ The talloc_zero_size() function is useful when you don't have a
+ known type.
+ </para>
+ </refsect2>
+ <refsect2><title>void *talloc_memdup(const void *<emphasis role="italic">ctx</emphasis>, const void *<emphasis role="italic">p</emphasis>, size_t size);</title>
+ <para>
+ The talloc_memdup() function is equivalent to:
+ </para>
+ <programlisting>ptr = talloc_size(ctx, size);
+if (ptr) memcpy(ptr, p, size);</programlisting>
+ </refsect2>
+ <refsect2><title>char *talloc_strdup(const void *<emphasis role="italic">ctx</emphasis>, const char *<emphasis role="italic">p</emphasis>);</title>
+ <para>
+ The talloc_strdup() function is equivalent to:
+ </para>
+ <programlisting>ptr = talloc_size(ctx, strlen(p)+1);
+if (ptr) memcpy(ptr, p, strlen(p)+1);</programlisting>
+ <para>
+ This function sets the name of the new pointer to the passed
+ string. This is equivalent to:
+ </para>
+ <programlisting>talloc_set_name_const(ptr, ptr)</programlisting>
+ </refsect2>
+ <refsect2><title>char *talloc_strndup(const void *<emphasis role="italic">t</emphasis>, const char *<emphasis role="italic">p</emphasis>, size_t <emphasis role="italic">n</emphasis>);</title>
+ <para>
+ The talloc_strndup() function is the talloc equivalent of the C
+ library function strndup(3).
+ </para>
+ <para>
+ This function sets the name of the new pointer to the passed
+ string. This is equivalent to:
+ </para>
+ <programlisting>talloc_set_name_const(ptr, ptr)</programlisting>
+ </refsect2>
+ <refsect2><title>char *talloc_vasprintf(const void *<emphasis role="italic">t</emphasis>, const char *<emphasis role="italic">fmt</emphasis>, va_list <emphasis role="italic">ap</emphasis>);</title>
+ <para>
+ The talloc_vasprintf() function is the talloc equivalent of the C
+ library function vasprintf(3).
+ </para>
+ <para>
+ This function sets the name of the new pointer to the new
+ string. This is equivalent to:
+ </para>
+ <programlisting>talloc_set_name_const(ptr, ptr)</programlisting>
+ </refsect2>
+ <refsect2><title>char *talloc_asprintf(const void *<emphasis role="italic">t</emphasis>, const char *<emphasis role="italic">fmt</emphasis>, ...);</title>
+ <para>
+ The talloc_asprintf() function is the talloc equivalent of the C
+ library function asprintf(3).
+ </para>
+ <para>
+ This function sets the name of the new pointer to the passed
+ string. This is equivalent to:
+ </para>
+ <programlisting>talloc_set_name_const(ptr, ptr)</programlisting>
+ </refsect2>
+ <refsect2><title>char *talloc_asprintf_append(char *s, const char *fmt, ...);</title>
+ <para>
+ The talloc_asprintf_append() function appends the given formatted
+ string to the given string.
+ </para>
+ <para>
+ This function sets the name of the new pointer to the new
+ string. This is equivalent to:
+ </para>
+ <programlisting>talloc_set_name_const(ptr, ptr)</programlisting>
+ </refsect2>
+ <refsect2><title>(type *)talloc_array(const void *ctx, type, unsigned int count);</title>
+ <para>
+ The talloc_array() macro is equivalent to:
+ </para>
+ <programlisting>(type *)talloc_size(ctx, sizeof(type) * count);</programlisting>
+ <para>
+ except that it provides integer overflow protection for the
+ multiply, returning NULL if the multiply overflows.
+ </para>
+ </refsect2>
+ <refsect2><title>void *talloc_array_size(const void *ctx, size_t size, unsigned int count);</title>
+ <para>
+ The talloc_array_size() function is useful when the type is not
+ known. It operates in the same way as talloc_array(), but takes a
+ size instead of a type.
+ </para>
+ </refsect2>
+ <refsect2><title>(typeof(ptr)) talloc_array_ptrtype(const void *ctx, ptr, unsigned int count);</title>
+ <para>
+ The talloc_ptrtype() macro should be used when you have a pointer to an array
+ and want to allocate memory of an array to point at with this pointer. When compiling
+ with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_array_size()
+ and talloc_get_name() will return the current location in the source file.
+ and not the type.
+ </para>
+ </refsect2>
+ <refsect2><title>void *talloc_realloc_fn(const void *ctx, void *ptr, size_t size)</title>
+ <para>
+ This is a non-macro version of talloc_realloc(), which is useful
+ as libraries sometimes want a realloc function pointer. A
+ realloc(3) implementation encapsulates the functionality of
+ malloc(3), free(3) and realloc(3) in one call, which is why it is
+ useful to be able to pass around a single function pointer.
+ </para>
+ </refsect2>
+ <refsect2><title>void *talloc_autofree_context(void);</title>
+ <para>
+ This is a handy utility function that returns a talloc context
+ which will be automatically freed on program exit. This can be
+ used to reduce the noise in memory leak reports.
+ </para>
+ </refsect2>
+ <refsect2><title>void *talloc_check_name(const void *ptr, const char *name);</title>
+ <para>
+ This function checks if a pointer has the specified <emphasis
+ role="italic">name</emphasis>. If it does then the pointer is
+ returned. It it doesn't then NULL is returned.
+ </para>
+ </refsect2>
+ <refsect2><title>(type *)talloc_get_type(const void *ptr, type);</title>
+ <para>
+ This macro allows you to do type checking on talloc pointers. It
+ is particularly useful for void* private pointers. It is
+ equivalent to this:
+ </para>
+ <programlisting>(type *)talloc_check_name(ptr, #type)</programlisting>
+ </refsect2>
+ <refsect2><title>talloc_set_type(const void *ptr, type);</title>
+ <para>
+ This macro allows you to force the name of a pointer to be a
+ particular <emphasis>type</emphasis>. This can be
+ used in conjunction with talloc_get_type() to do type checking on
+ void* pointers.
+ </para>
+ <para>
+ It is equivalent to this:
+ </para>
+ <programlisting>talloc_set_name_const(ptr, #type)</programlisting>
+ </refsect2>
+ <refsect2><title>talloc_set_log_fn(void (*log_fn)(const char *message));</title>
+ <para>
+ This function sets a logging function that talloc will use for
+ warnings and errors. By default talloc will not print any warnings or
+ errors.
+ </para>
+ </refsect2>
+ <refsect2><title>talloc_set_log_stderr(void);</title>
+ <para>
+ This sets the talloc log function to write log messages to stderr
+ </para>
+ </refsect2>
+ </refsect1>
+ <refsect1><title>PERFORMANCE</title>
+ <para>
+ All the additional features of talloc(3) over malloc(3) do come at a
+ price. We have a simple performance test in Samba4 that measures
+ talloc() versus malloc() performance, and it seems that talloc() is
+ about 10% slower than malloc() on my x86 Debian Linux box. For
+ Samba, the great reduction in code complexity that we get by using
+ talloc makes this worthwhile, especially as the total overhead of
+ talloc/malloc in Samba is already quite small.
+ </para>
+ </refsect1>
+ <refsect1><title>SEE ALSO</title>
+ <para>
+ malloc(3), strndup(3), vasprintf(3), asprintf(3),
+ <ulink url="http://talloc.samba.org/"/>
+ </para>
+ </refsect1>
+
+ <refsect1><title>AUTHOR</title>
+ <para> The original Samba software and related utilities were
+ created by Andrew Tridgell. Samba is now developed by the
+ Samba Team as an Open Source project similar to the way the
+ Linux kernel is developed.
+ </para>
+ </refsect1>
+
+ <refsect1><title>COPYRIGHT/LICENSE</title>
+ <para>
+ Copyright (C) Andrew Tridgell 2004
+ </para>
+ <para>
+ This program 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 3 of the
+ License, or (at your option) any later version.
+ </para>
+ <para>
+ 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.
+ </para>
+ <para>
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see http://www.gnu.org/licenses/.
+ </para>
+ </refsect1>
+</refentry>
diff --git a/lib/talloc/pytalloc-util.pc.in b/lib/talloc/pytalloc-util.pc.in
new file mode 100644
index 0000000..06f83e2
--- /dev/null
+++ b/lib/talloc/pytalloc-util.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: pytalloc-util@PYTHON_SO_ABI_FLAG@
+Description: Utility functions for using talloc objects with Python
+Version: @TALLOC_VERSION@
+Libs: @LIB_RPATH@ -L${libdir} -lpytalloc-util@PYTHON_LIBNAME_SO_ABI_FLAG@
+Cflags: -I${includedir}
+URL: http://talloc.samba.org/
diff --git a/lib/talloc/pytalloc.c b/lib/talloc/pytalloc.c
new file mode 100644
index 0000000..41decc4
--- /dev/null
+++ b/lib/talloc/pytalloc.c
@@ -0,0 +1,313 @@
+/*
+ Unix SMB/CIFS implementation.
+ Python Talloc Module
+ Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2010-2011
+
+ ** 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 3 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
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <Python.h>
+#include <talloc.h>
+#include <pytalloc.h>
+#include "pytalloc_private.h"
+
+static PyTypeObject TallocObject_Type;
+
+/* print a talloc tree report for a talloc python object */
+static PyObject *pytalloc_report_full(PyObject *self, PyObject *args)
+{
+ PyObject *py_obj = Py_None;
+
+ if (!PyArg_ParseTuple(args, "|O", &py_obj))
+ return NULL;
+
+ if (py_obj == Py_None) {
+ talloc_report_full(NULL, stdout);
+ } else {
+ talloc_report_full(pytalloc_get_mem_ctx(py_obj), stdout);
+ }
+ Py_RETURN_NONE;
+}
+
+/* enable null tracking */
+static PyObject *pytalloc_enable_null_tracking(PyObject *self,
+ PyObject *Py_UNUSED(ignored))
+{
+ talloc_enable_null_tracking();
+ Py_RETURN_NONE;
+}
+
+/* return the number of talloc blocks */
+static PyObject *pytalloc_total_blocks(PyObject *self, PyObject *args)
+{
+ PyObject *py_obj = Py_None;
+
+ if (!PyArg_ParseTuple(args, "|O", &py_obj))
+ return NULL;
+
+ if (py_obj == Py_None) {
+ return PyLong_FromLong(talloc_total_blocks(NULL));
+ }
+
+ return PyLong_FromLong(talloc_total_blocks(pytalloc_get_mem_ctx(py_obj)));
+}
+
+static PyMethodDef talloc_methods[] = {
+ { "report_full", (PyCFunction)pytalloc_report_full, METH_VARARGS,
+ "show a talloc tree for an object"},
+ { "enable_null_tracking", (PyCFunction)pytalloc_enable_null_tracking, METH_NOARGS,
+ "enable tracking of the NULL object"},
+ { "total_blocks", (PyCFunction)pytalloc_total_blocks, METH_VARARGS,
+ "return talloc block count"},
+ {0}
+};
+
+/**
+ * Default (but only slightly more useful than the default) implementation of Repr().
+ */
+static PyObject *pytalloc_default_repr(PyObject *obj)
+{
+ pytalloc_Object *talloc_obj = (pytalloc_Object *)obj;
+ PyTypeObject *type = (PyTypeObject*)PyObject_Type(obj);
+
+ return PyUnicode_FromFormat("<%s talloc object at %p>",
+ type->tp_name, talloc_obj->ptr);
+}
+
+/**
+ * Simple dealloc for talloc-wrapping PyObjects
+ */
+static void pytalloc_dealloc(PyObject* self)
+{
+ pytalloc_Object *obj = (pytalloc_Object *)self;
+ assert(talloc_unlink(NULL, obj->talloc_ctx) != -1);
+ obj->talloc_ctx = NULL;
+ self->ob_type->tp_free(self);
+}
+
+/**
+ * Default (but only slightly more useful than the default) implementation of cmp.
+ */
+#if PY_MAJOR_VERSION >= 3
+static PyObject *pytalloc_default_richcmp(PyObject *obj1, PyObject *obj2, int op)
+{
+ void *ptr1;
+ void *ptr2;
+ if (Py_TYPE(obj1) == Py_TYPE(obj2)) {
+ /* When types match, compare pointers */
+ ptr1 = pytalloc_get_ptr(obj1);
+ ptr2 = pytalloc_get_ptr(obj2);
+ } else if (PyObject_TypeCheck(obj2, &TallocObject_Type)) {
+ /* Otherwise, compare types */
+ ptr1 = Py_TYPE(obj1);
+ ptr2 = Py_TYPE(obj2);
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ switch (op) {
+ case Py_EQ: return PyBool_FromLong(ptr1 == ptr2);
+ case Py_NE: return PyBool_FromLong(ptr1 != ptr2);
+ case Py_LT: return PyBool_FromLong(ptr1 < ptr2);
+ case Py_GT: return PyBool_FromLong(ptr1 > ptr2);
+ case Py_LE: return PyBool_FromLong(ptr1 <= ptr2);
+ case Py_GE: return PyBool_FromLong(ptr1 >= ptr2);
+ }
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+}
+#else
+static int pytalloc_default_cmp(PyObject *_obj1, PyObject *_obj2)
+{
+ pytalloc_Object *obj1 = (pytalloc_Object *)_obj1,
+ *obj2 = (pytalloc_Object *)_obj2;
+ if (obj1->ob_type != obj2->ob_type)
+ return ((char *)obj1->ob_type - (char *)obj2->ob_type);
+
+ return ((char *)pytalloc_get_ptr(obj1) - (char *)pytalloc_get_ptr(obj2));
+}
+#endif
+
+static PyTypeObject TallocObject_Type = {
+ .tp_name = "talloc.Object",
+ .tp_doc = "Python wrapper for a talloc-maintained object.",
+ .tp_basicsize = sizeof(pytalloc_Object),
+ .tp_dealloc = (destructor)pytalloc_dealloc,
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ .tp_repr = pytalloc_default_repr,
+#if PY_MAJOR_VERSION >= 3
+ .tp_richcompare = pytalloc_default_richcmp,
+#else
+ .tp_compare = pytalloc_default_cmp,
+#endif
+};
+
+/**
+ * Default (but only slightly more useful than the default) implementation of Repr().
+ */
+static PyObject *pytalloc_base_default_repr(PyObject *obj)
+{
+ pytalloc_BaseObject *talloc_obj = (pytalloc_BaseObject *)obj;
+ PyTypeObject *type = (PyTypeObject*)PyObject_Type(obj);
+
+ return PyUnicode_FromFormat("<%s talloc based object at %p>",
+ type->tp_name, talloc_obj->ptr);
+}
+
+/**
+ * Simple dealloc for talloc-wrapping PyObjects
+ */
+static void pytalloc_base_dealloc(PyObject* self)
+{
+ pytalloc_BaseObject *obj = (pytalloc_BaseObject *)self;
+ assert(talloc_unlink(NULL, obj->talloc_ctx) != -1);
+ obj->talloc_ctx = NULL;
+ self->ob_type->tp_free(self);
+}
+
+/**
+ * Default (but only slightly more useful than the default) implementation of cmp.
+ */
+#if PY_MAJOR_VERSION >= 3
+static PyObject *pytalloc_base_default_richcmp(PyObject *obj1, PyObject *obj2, int op)
+{
+ void *ptr1;
+ void *ptr2;
+ if (Py_TYPE(obj1) == Py_TYPE(obj2)) {
+ /* When types match, compare pointers */
+ ptr1 = pytalloc_get_ptr(obj1);
+ ptr2 = pytalloc_get_ptr(obj2);
+ } else if (PyObject_TypeCheck(obj2, &TallocObject_Type)) {
+ /* Otherwise, compare types */
+ ptr1 = Py_TYPE(obj1);
+ ptr2 = Py_TYPE(obj2);
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ switch (op) {
+ case Py_EQ: return PyBool_FromLong(ptr1 == ptr2);
+ case Py_NE: return PyBool_FromLong(ptr1 != ptr2);
+ case Py_LT: return PyBool_FromLong(ptr1 < ptr2);
+ case Py_GT: return PyBool_FromLong(ptr1 > ptr2);
+ case Py_LE: return PyBool_FromLong(ptr1 <= ptr2);
+ case Py_GE: return PyBool_FromLong(ptr1 >= ptr2);
+ }
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+}
+#else
+static int pytalloc_base_default_cmp(PyObject *_obj1, PyObject *_obj2)
+{
+ pytalloc_BaseObject *obj1 = (pytalloc_BaseObject *)_obj1,
+ *obj2 = (pytalloc_BaseObject *)_obj2;
+ if (obj1->ob_type != obj2->ob_type)
+ return ((char *)obj1->ob_type - (char *)obj2->ob_type);
+
+ return ((char *)pytalloc_get_ptr(obj1) - (char *)pytalloc_get_ptr(obj2));
+}
+#endif
+
+static PyTypeObject TallocBaseObject_Type = {
+ .tp_name = "talloc.BaseObject",
+ .tp_doc = "Python wrapper for a talloc-maintained object.",
+ .tp_basicsize = sizeof(pytalloc_BaseObject),
+ .tp_dealloc = (destructor)pytalloc_base_dealloc,
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ .tp_repr = pytalloc_base_default_repr,
+#if PY_MAJOR_VERSION >= 3
+ .tp_richcompare = pytalloc_base_default_richcmp,
+#else
+ .tp_compare = pytalloc_base_default_cmp,
+#endif
+};
+
+static PyTypeObject TallocGenericObject_Type = {
+ .tp_name = "talloc.GenericObject",
+ .tp_doc = "Python wrapper for a talloc-maintained object.",
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ .tp_base = &TallocBaseObject_Type,
+ .tp_basicsize = sizeof(pytalloc_BaseObject),
+};
+
+#define MODULE_DOC PyDoc_STR("Python wrapping of talloc-maintained objects.")
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "talloc",
+ .m_doc = MODULE_DOC,
+ .m_size = -1,
+ .m_methods = talloc_methods,
+};
+#endif
+
+static PyObject *module_init(void);
+static PyObject *module_init(void)
+{
+ PyObject *m;
+
+ if (PyType_Ready(&TallocObject_Type) < 0)
+ return NULL;
+
+ if (PyType_Ready(&TallocBaseObject_Type) < 0)
+ return NULL;
+
+ if (PyType_Ready(&TallocGenericObject_Type) < 0)
+ return NULL;
+
+#if PY_MAJOR_VERSION >= 3
+ m = PyModule_Create(&moduledef);
+#else
+ m = Py_InitModule3("talloc", talloc_methods, MODULE_DOC);
+#endif
+ if (m == NULL)
+ return NULL;
+
+ Py_INCREF(&TallocObject_Type);
+ if (PyModule_AddObject(m, "Object", (PyObject *)&TallocObject_Type)) {
+ goto err;
+ }
+ Py_INCREF(&TallocBaseObject_Type);
+ if (PyModule_AddObject(m, "BaseObject", (PyObject *)&TallocBaseObject_Type)) {
+ goto err;
+ }
+ Py_INCREF(&TallocGenericObject_Type);
+ if (PyModule_AddObject(m, "GenericObject", (PyObject *)&TallocGenericObject_Type)) {
+ goto err;
+ }
+ return m;
+
+err:
+ Py_DECREF(m);
+ return NULL;
+}
+
+#if PY_MAJOR_VERSION >= 3
+PyMODINIT_FUNC PyInit_talloc(void);
+PyMODINIT_FUNC PyInit_talloc(void)
+{
+ return module_init();
+}
+#else
+void inittalloc(void);
+void inittalloc(void)
+{
+ module_init();
+}
+#endif
diff --git a/lib/talloc/pytalloc.h b/lib/talloc/pytalloc.h
new file mode 100644
index 0000000..c1f9b44
--- /dev/null
+++ b/lib/talloc/pytalloc.h
@@ -0,0 +1,87 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba utility functions
+ Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
+
+ ** 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 3 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
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _PYTALLOC_H_
+#define _PYTALLOC_H_
+
+#include <Python.h>
+#include <talloc.h>
+
+typedef struct {
+ PyObject_HEAD
+ TALLOC_CTX *talloc_ctx;
+ void *ptr; /* eg the array element */
+} pytalloc_Object;
+
+/* Return the PyTypeObject for pytalloc_Object. Returns a borrowed reference. */
+_PUBLIC_ PyTypeObject *pytalloc_GetObjectType(void);
+
+/* Return the PyTypeObject for pytalloc_BaseObject. Returns a borrowed reference. */
+_PUBLIC_ PyTypeObject *pytalloc_GetBaseObjectType(void);
+
+/* Check whether a specific object is a talloc Object. */
+_PUBLIC_ int pytalloc_Check(PyObject *);
+
+_PUBLIC_ int pytalloc_BaseObject_check(PyObject *);
+
+_PUBLIC_ int _pytalloc_check_type(PyObject *py_obj, const char *type_name);
+#define pytalloc_check_type(py_obj, type) \
+ _pytalloc_check_type((PyObject *)(py_obj), #type)
+
+/* Retrieve the pointer for a pytalloc_object. Like talloc_get_type()
+ * but for pytalloc_Objects. */
+_PUBLIC_ void *_pytalloc_get_type(PyObject *py_obj, const char *type_name);
+#define pytalloc_get_type(py_obj, type) ((type *)_pytalloc_get_type((PyObject *)(py_obj), #type))
+
+_PUBLIC_ void *_pytalloc_get_ptr(PyObject *py_obj);
+#define pytalloc_get_ptr(py_obj) _pytalloc_get_ptr((PyObject *)(py_obj))
+_PUBLIC_ TALLOC_CTX *_pytalloc_get_mem_ctx(PyObject *py_obj);
+#define pytalloc_get_mem_ctx(py_obj) _pytalloc_get_mem_ctx((PyObject *)(py_obj))
+
+_PUBLIC_ const char *_pytalloc_get_name(PyObject *py_obj);
+#define pytalloc_get_name(py_obj) _pytalloc_get_name((PyObject *)(py_obj))
+
+
+_PUBLIC_ PyObject *pytalloc_steal_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx, void *ptr);
+_PUBLIC_ PyObject *pytalloc_steal(PyTypeObject *py_type, void *ptr);
+_PUBLIC_ PyObject *pytalloc_reference_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx, void *ptr);
+#define pytalloc_reference(py_type, talloc_ptr) pytalloc_reference_ex(py_type, talloc_ptr, talloc_ptr)
+
+#define pytalloc_new(type, typeobj) pytalloc_steal(typeobj, talloc_zero(NULL, type))
+
+/*
+ * Wrap a generic talloc pointer into a talloc.GenericObject,
+ * this is a subclass of talloc.BaseObject.
+ */
+_PUBLIC_ PyObject *pytalloc_GenericObject_steal_ex(TALLOC_CTX *mem_ctx, void *ptr);
+#define pytalloc_GenericObject_steal(talloc_ptr) \
+ pytalloc_GenericObject_steal_ex(talloc_ptr, talloc_ptr)
+_PUBLIC_ PyObject *pytalloc_GenericObject_reference_ex(TALLOC_CTX *mem_ctx, void *ptr);
+#define pytalloc_GenericObject_reference(talloc_ptr) \
+ pytalloc_GenericObject_reference_ex(talloc_ptr, talloc_ptr)
+
+_PUBLIC_ size_t pytalloc_BaseObject_size(void);
+
+_PUBLIC_ int pytalloc_BaseObject_PyType_Ready(PyTypeObject *type);
+
+#endif /* _PYTALLOC_H_ */
diff --git a/lib/talloc/pytalloc_guide.txt b/lib/talloc/pytalloc_guide.txt
new file mode 100644
index 0000000..bd2b68c
--- /dev/null
+++ b/lib/talloc/pytalloc_guide.txt
@@ -0,0 +1,252 @@
+Using talloc in Samba4
+======================
+
+.. contents::
+
+Jelmer Vernooij
+August 2013
+
+The most current version of this document is available at
+ http://samba.org/ftp/unpacked/talloc/pytalloc_guide.txt
+
+pytalloc is a small library that provides glue for wrapping
+talloc-allocated objects from C in Python objects.
+
+What is pytalloc, and what is it not?
+-------------------------------------
+
+pytalloc is merely a helper library - it provides a convenient base type object
+for objects that wrap talloc-maintained memory in C. It won't write your
+bindings for you but it will make it easier to write C bindings that involve
+talloc, and take away some of the boiler plate.
+
+Python 3
+--------
+
+pytalloc can be used with Python 3. Usage from Python extension remains
+the same, but for the C utilities, the library to link to is tagged with
+Python's PEP3149 ABI tag, for example "pytalloc.cpython34m".
+To make a build for Python 3, configure with PYTHON=/usr/bin/python3.
+.
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+pytalloc_Object / pytalloc_BaseObject
+
+This is the new base class that all Python objects that wrap talloc pointers
+derive from. It is itself a subclass of the "Object" type that all objects
+in Python derive from.
+
+Note that you will almost never create objects of the pytalloc_Object type
+itself, as they are just opaque pointers that can not be accessed from
+Python. A common pattern is other objects that subclass pytalloc_Object and
+rely on it for their memory management.
+
+Each `pytalloc_Object` wraps two core of information - a talloc context
+and a pointer. The pointer is the actual data that is wrapped. The talloc
+context is used for memory management purposes only; when the wrapping Python object
+goes away, it unlinks the talloc context. The talloc context pointer and the ptr
+can (and often do) have the same value.
+
+Each pytalloc_Object has a custom __repr__ implementation that
+describes that it is a talloc object and the location of the
+pointer it is wrapping. it also has a custom __cmp__/__eq__/__neq__ method that
+compares the pointers the object is wrapping rather than the objects
+themselves (since there can be multiple objects that wrap the same talloc
+pointer).
+
+It is preferred to use pytalloc_BaseObject as this implementation
+exposes less in the C ABI and correctly supports pointers in C arrays
+in the way needed by PIDL.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+PyTypeObject *pytalloc_GetObjectType(void)
+
+Obtain a pointer to the PyTypeObject for `pytalloc_Object`. The
+reference counter for the object will be NOT incremented, so the
+caller MUST NOT decrement it when it no longer needs it (eg by using
+`Py_DECREF`).
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+PyTypeObject *pytalloc_GetBaseObjectType(void)
+
+Obtain a pointer to the PyTypeObject for `pytalloc_BaseObject`. The
+reference counter for the object will be NOT incremented, so the
+caller MUST NOT decrement it when it no longer needs it (eg by using
+`Py_DECREF`).
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+int pytalloc_BaseObject_PyType_Ready(PyTypeObject *type);
+
+Wrapper for PyType_Ready() that will set the correct values into
+the PyTypeObject to create a BaseObject
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-
+int pytalloc_Check(PyObject *)
+
+Check whether a specific object is a talloc Object. Returns non-zero if it is
+a pytalloc_Object and zero otherwise.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-
+int pytalloc_BaseObject_Check(PyObject *)
+
+Check whether a specific object is a talloc BaseObject. Returns non-zero if it is
+a pytalloc_BaseObject and zero otherwise.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+int pytalloc_check_type(PyObject *py_obj, type)
+
+Check if the object based on `pytalloc_*Object` py_obj. type should be a
+C type, similar to a type passed to `talloc_get_type`.
+This can be used as a check before using pytalloc_get_type()
+or an alternative codepath. Returns non-zero if it is
+an object of the expected type and zero otherwise.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+type *pytalloc_get_type(PyObject *py_obj, type)
+
+Retrieve the pointer from a `pytalloc_Object` py_obj. type should be a
+C type, similar to a type passed to `talloc_get_type`.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+pytalloc_get_ptr(PyObject *py_obj)
+
+Retrieve the pointer from a `pytalloc_Object` or `pytalloc_BaseObject`
+py_obj. There is no type checking - use `pytalloc_get_type` if
+possible.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+TALLOC_CTX *pytalloc_get_mem_ctx(PyObject *py_obj)
+
+Retrieve the talloc context associated with a pytalloc_Object or pytalloc_BaseObject.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+PyObject *pytalloc_steal_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx, void *ptr)
+
+Create a new Python wrapping object for a talloc pointer and context, with
+py_type as associated Python sub type object. This typically used
+when `mem_ctx` and `ptr` differ, e.g. a pointer to an array element.
+`pytalloc_get_ptr()` can be used to get the pointer out of the object again.
+
+This will *not* increment the reference counter for the talloc context,
+so the caller should make sure such an increment has happened. When the Python
+object goes away, it will unreference the talloc context.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+PyObject *pytalloc_steal(PyTypeObject *py_type, void *ptr)
+
+Create a new Python wrapping object for a talloc pointer and context, with
+py_type as associated Python sub type object. The pointer will also be used
+as the talloc context. `pytalloc_get_type()` can be used to get
+the pointer out of the object again.
+
+This will *not* increment the reference counter for the talloc context,
+so the caller should make sure such an increment has happened. When the Python
+object goes away, it will unreference the talloc context.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+PyObject *pytalloc_reference_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx, void *ptr)
+
+Create a new Python wrapping object for a talloc pointer and context, with
+py_type as associated Python sub type object. This typically used
+when `mem_ctx` and `ptr` differ, e.g. a pointer to an array element.
+`pytalloc_get_ptr()` can be used to get the pointer out of the object again.
+
+This will increment the reference counter for the talloc context.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+PyObject *pytalloc_reference(PyTypeObject *py_type, void *talloc_ptr)
+
+Create a new Python wrapping object for a talloc pointer, with
+py_type as associated Python sub type object. The pointer will also be used
+as the talloc context. `pytalloc_get_type()` can be used to get
+the pointer out of the object again.
+
+This will increment the reference counter for the talloc context.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+PyObject *pytalloc_new(type, PyTypeObject *typeobj)
+
+Create a new, empty pytalloc_Object with the specified Python type object. type
+should be a C type, similar to talloc_new().
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+PyObject *pytalloc_GenericObject_steal_ex(void *ptr)
+
+Create a new Python wrapping object for a generic talloc pointer,
+as sub type of `pytalloc_BaseObject`. This typically used
+when `mem_ctx` and `ptr` differ, e.g. a pointer to an array element.
+`pytalloc_get_ptr()` can be used to get the pointer out of the object again.
+
+This will *not* increment the reference counter for the talloc context,
+so the caller should make sure such an increment has happened. When the Python
+object goes away, it will unreference the talloc context.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+PyObject *pytalloc_GenericObject_steal(void *ptr)
+
+Create a new Python wrapping object for a generic talloc pointer,
+as sub type of `pytalloc_BaseObject`. The pointer will also be used
+as the talloc context. `pytalloc_get_type()` can be used to get
+the pointer out of the object again.
+
+This will *not* increment the reference counter for the talloc context,
+so the caller should make sure such an increment has happened. When the Python
+object goes away, it will unreference the talloc context.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+PyObject *pytalloc_GenericObject_reference_ex(void *ptr)
+
+Create a new Python wrapping object for a generic talloc pointer,
+as sub type of `pytalloc_BaseObject`. This typically used
+when `mem_ctx` and `ptr` differ, e.g. a pointer to an array element.
+`pytalloc_get_ptr()` can be used to get the pointer out of the object again.
+
+This will increment the reference counter for the talloc context.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+PyObject *pytalloc_GenericObject_reference(void *ptr)
+
+Create a new Python wrapping object for a generic talloc pointer,
+as sub type of `pytalloc_BaseObject`. The pointer will also be used
+as the talloc context. `pytalloc_get_type()` can be used to get
+the pointer out of the object again.
+
+This will increment the reference counter for the talloc context.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+DEPRECATED! PyObject *pytalloc_CObject_FromTallocPtr(void *);
+
+Create a new pytalloc_Object for an abitrary talloc-maintained C pointer. This will
+use a generic VoidPtr Python type, which just provides an opaque object in
+Python. The caller is responsible for incrementing the talloc reference count before calling
+this function - it will dereference the talloc pointer when it is garbage collected.
+
+This function is deprecated and only available on Python 2.
+Use pytalloc_GenericObject_{reference,steal}[_ex]() instead.
+
+Debug function for talloc in Python
+-----------------------------------
+
+The "talloc" module in Python provides a couple of functions that can be used
+to debug issues with objects wrapped by pytalloc.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+report_full(obj?)
+
+Print a full report on a specific object or on all allocated objects by Python.
+Same behaviour as the `talloc_report_full()` function that is provided by
+C talloc.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+enable_null_tracking()
+
+This enables tracking of the NULL memory context without enabling leak
+reporting on exit. Useful for when you want to do your own leak
+reporting call via talloc_report_null_full().
+
+This must be done in the top level script, not an imported module.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+pytalloc_total_blocks(obj?)
+
+Return the talloc block count for all allocated objects or a specific object if
+specified.
diff --git a/lib/talloc/pytalloc_private.h b/lib/talloc/pytalloc_private.h
new file mode 100644
index 0000000..b23cdfc
--- /dev/null
+++ b/lib/talloc/pytalloc_private.h
@@ -0,0 +1,26 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba utility functions
+ Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2016
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+typedef struct {
+ PyObject_HEAD
+ TALLOC_CTX *talloc_ctx;
+ TALLOC_CTX *talloc_ptr_ctx; /* eg the start of the array */
+ void *ptr; /* eg the array element */
+} pytalloc_BaseObject;
diff --git a/lib/talloc/pytalloc_util.c b/lib/talloc/pytalloc_util.c
new file mode 100644
index 0000000..1b7cfdd
--- /dev/null
+++ b/lib/talloc/pytalloc_util.c
@@ -0,0 +1,334 @@
+/*
+ Unix SMB/CIFS implementation.
+ Python/Talloc glue
+ Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
+
+ ** 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 3 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
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <Python.h>
+#include "replace.h"
+#include <talloc.h>
+#include "pytalloc.h"
+#include <assert.h>
+#include "pytalloc_private.h"
+
+static PyObject *pytalloc_steal_or_reference(PyTypeObject *py_type,
+ TALLOC_CTX *mem_ctx, void *ptr, bool steal);
+
+_PUBLIC_ PyTypeObject *pytalloc_GetObjectType(void)
+{
+ static PyTypeObject *type = NULL;
+ PyObject *mod;
+
+ mod = PyImport_ImportModule("talloc");
+ if (mod == NULL) {
+ return NULL;
+ }
+
+ type = (PyTypeObject *)PyObject_GetAttrString(mod, "Object");
+ Py_DECREF(mod);
+
+ return type;
+}
+
+_PUBLIC_ PyTypeObject *pytalloc_GetBaseObjectType(void)
+{
+ static PyTypeObject *type = NULL;
+ PyObject *mod;
+
+ mod = PyImport_ImportModule("talloc");
+ if (mod == NULL) {
+ return NULL;
+ }
+
+ type = (PyTypeObject *)PyObject_GetAttrString(mod, "BaseObject");
+ Py_DECREF(mod);
+
+ return type;
+}
+
+static PyTypeObject *pytalloc_GetGenericObjectType(void)
+{
+ static PyTypeObject *type = NULL;
+ PyObject *mod;
+
+ mod = PyImport_ImportModule("talloc");
+ if (mod == NULL) {
+ return NULL;
+ }
+
+ type = (PyTypeObject *)PyObject_GetAttrString(mod, "GenericObject");
+ Py_DECREF(mod);
+
+ return type;
+}
+
+/**
+ * Import an existing talloc pointer into a Python object.
+ */
+_PUBLIC_ PyObject *pytalloc_steal_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx,
+ void *ptr)
+{
+ return pytalloc_steal_or_reference(py_type, mem_ctx, ptr, true);
+}
+
+/**
+ * Import an existing talloc pointer into a Python object.
+ */
+_PUBLIC_ PyObject *pytalloc_steal(PyTypeObject *py_type, void *ptr)
+{
+ return pytalloc_steal_or_reference(py_type, ptr, ptr, true);
+}
+
+
+/**
+ * Import an existing talloc pointer into a Python object, leaving the
+ * original parent, and creating a reference to the object in the python
+ * object.
+ *
+ * We remember the object we hold the reference to (a
+ * possibly-non-talloc pointer), the existing parent (typically the
+ * start of the array) and the new referenced parent. That way we can
+ * cope with the fact that we will have multiple parents, one per time
+ * python sees the object.
+ */
+_PUBLIC_ PyObject *pytalloc_reference_ex(PyTypeObject *py_type,
+ TALLOC_CTX *mem_ctx, void *ptr)
+{
+ return pytalloc_steal_or_reference(py_type, mem_ctx, ptr, false);
+}
+
+
+/**
+ * Internal function that either steals or referecences the talloc
+ * pointer into a new talloc context.
+ */
+static PyObject *pytalloc_steal_or_reference(PyTypeObject *py_type,
+ TALLOC_CTX *mem_ctx, void *ptr, bool steal)
+{
+ bool ok = false;
+ TALLOC_CTX *talloc_ctx = NULL;
+ bool is_baseobject = false;
+ PyObject *obj = NULL;
+ PyTypeObject *BaseObjectType = NULL, *ObjectType = NULL;
+
+ BaseObjectType = pytalloc_GetBaseObjectType();
+ if (BaseObjectType == NULL) {
+ goto err;
+ }
+ ObjectType = pytalloc_GetObjectType();
+ if (ObjectType == NULL) {
+ goto err;
+ }
+
+ /* this should have been tested by caller */
+ if (mem_ctx == NULL) {
+ return PyErr_NoMemory();
+ }
+
+ is_baseobject = PyType_IsSubtype(py_type, BaseObjectType);
+ if (!is_baseobject) {
+ if (!PyType_IsSubtype(py_type, ObjectType)) {
+ PyErr_SetString(PyExc_TypeError,
+ "Expected type based on talloc");
+ return NULL;
+ }
+ }
+
+ obj = py_type->tp_alloc(py_type, 0);
+ if (obj == NULL) {
+ goto err;
+ }
+
+ talloc_ctx = talloc_new(NULL);
+ if (talloc_ctx == NULL) {
+ PyErr_NoMemory();
+ goto err;
+ }
+
+ if (steal) {
+ ok = (talloc_steal(talloc_ctx, mem_ctx) != NULL);
+ } else {
+ ok = (talloc_reference(talloc_ctx, mem_ctx) != NULL);
+ }
+ if (!ok) {
+ goto err;
+ }
+ talloc_set_name_const(talloc_ctx, py_type->tp_name);
+
+ if (is_baseobject) {
+ pytalloc_BaseObject *ret = (pytalloc_BaseObject*)obj;
+ ret->talloc_ctx = talloc_ctx;
+ ret->talloc_ptr_ctx = mem_ctx;
+ ret->ptr = ptr;
+ } else {
+ pytalloc_Object *ret = (pytalloc_Object*)obj;
+ ret->talloc_ctx = talloc_ctx;
+ ret->ptr = ptr;
+ }
+ return obj;
+
+err:
+ TALLOC_FREE(talloc_ctx);
+ Py_XDECREF(obj);
+ return NULL;
+}
+
+/*
+ * Wrap a generic talloc pointer into a talloc.GenericObject,
+ * this is a subclass of talloc.BaseObject.
+ */
+_PUBLIC_ PyObject *pytalloc_GenericObject_steal_ex(TALLOC_CTX *mem_ctx, void *ptr)
+{
+ PyTypeObject *tp = pytalloc_GetGenericObjectType();
+ return pytalloc_steal_ex(tp, mem_ctx, ptr);
+}
+
+/*
+ * Wrap a generic talloc pointer into a talloc.GenericObject,
+ * this is a subclass of talloc.BaseObject.
+ */
+_PUBLIC_ PyObject *pytalloc_GenericObject_reference_ex(TALLOC_CTX *mem_ctx, void *ptr)
+{
+ PyTypeObject *tp = pytalloc_GetGenericObjectType();
+ return pytalloc_reference_ex(tp, mem_ctx, ptr);
+}
+
+_PUBLIC_ int pytalloc_Check(PyObject *obj)
+{
+ PyTypeObject *tp = pytalloc_GetObjectType();
+
+ return PyObject_TypeCheck(obj, tp);
+}
+
+_PUBLIC_ int pytalloc_BaseObject_check(PyObject *obj)
+{
+ PyTypeObject *tp = pytalloc_GetBaseObjectType();
+
+ return PyObject_TypeCheck(obj, tp);
+}
+
+_PUBLIC_ size_t pytalloc_BaseObject_size(void)
+{
+ return sizeof(pytalloc_BaseObject);
+}
+
+static void *_pytalloc_get_checked_type(PyObject *py_obj, const char *type_name,
+ bool check_only, const char *function)
+{
+ TALLOC_CTX *mem_ctx;
+ void *ptr = NULL;
+ void *type_obj;
+
+ mem_ctx = _pytalloc_get_mem_ctx(py_obj);
+ ptr = _pytalloc_get_ptr(py_obj);
+
+ if (mem_ctx != ptr || ptr == NULL) {
+ if (check_only) {
+ return NULL;
+ }
+
+ PyErr_Format(PyExc_TypeError, "%s: expected %s, "
+ "but the pointer is no talloc pointer, "
+ "pytalloc_get_ptr() would get the raw pointer.",
+ function, type_name);
+ return NULL;
+ }
+
+ type_obj = talloc_check_name(ptr, type_name);
+ if (type_obj == NULL) {
+ const char *name = NULL;
+
+ if (check_only) {
+ return NULL;
+ }
+
+ name = talloc_get_name(ptr);
+ PyErr_Format(PyExc_TypeError, "%s: expected %s, got %s",
+ function, type_name, name);
+ return NULL;
+ }
+
+ return ptr;
+}
+
+_PUBLIC_ int _pytalloc_check_type(PyObject *py_obj, const char *type_name)
+{
+ void *ptr = NULL;
+
+ ptr = _pytalloc_get_checked_type(py_obj, type_name,
+ true, /* check_only */
+ "pytalloc_check_type");
+ if (ptr == NULL) {
+ return 0;
+ }
+
+ return 1;
+}
+
+_PUBLIC_ void *_pytalloc_get_type(PyObject *py_obj, const char *type_name)
+{
+ return _pytalloc_get_checked_type(py_obj, type_name,
+ false, /* not check_only */
+ "pytalloc_get_type");
+}
+
+_PUBLIC_ void *_pytalloc_get_ptr(PyObject *py_obj)
+{
+ if (pytalloc_BaseObject_check(py_obj)) {
+ return ((pytalloc_BaseObject *)py_obj)->ptr;
+ }
+ if (pytalloc_Check(py_obj)) {
+ return ((pytalloc_Object *)py_obj)->ptr;
+ }
+ return NULL;
+}
+
+_PUBLIC_ TALLOC_CTX *_pytalloc_get_mem_ctx(PyObject *py_obj)
+{
+ if (pytalloc_BaseObject_check(py_obj)) {
+ return ((pytalloc_BaseObject *)py_obj)->talloc_ptr_ctx;
+ }
+ if (pytalloc_Check(py_obj)) {
+ return ((pytalloc_Object *)py_obj)->talloc_ctx;
+ }
+ return NULL;
+}
+
+_PUBLIC_ int pytalloc_BaseObject_PyType_Ready(PyTypeObject *type)
+{
+ PyTypeObject *talloc_type = pytalloc_GetBaseObjectType();
+ if (talloc_type == NULL) {
+ return -1;
+ }
+
+ type->tp_base = talloc_type;
+ type->tp_basicsize = pytalloc_BaseObject_size();
+
+ return PyType_Ready(type);
+}
+
+_PUBLIC_ const char *_pytalloc_get_name(PyObject *obj)
+{
+ void *ptr = pytalloc_get_ptr(obj);
+ if (ptr == NULL) {
+ return "non-talloc object";
+ }
+ return talloc_get_name(ptr);
+}
diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c
new file mode 100644
index 0000000..41fa45b
--- /dev/null
+++ b/lib/talloc/talloc.c
@@ -0,0 +1,3072 @@
+/*
+ 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
+ Copyright (C) Stefan Metzmacher 2006
+
+ ** 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 3 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
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ inspired by http://swapped.cc/halloc/
+*/
+
+#include "replace.h"
+#include "talloc.h"
+
+#ifdef HAVE_SYS_AUXV_H
+#include <sys/auxv.h>
+#endif
+
+#if (TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR)
+#error "TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR"
+#endif
+
+#if (TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR)
+#error "TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR"
+#endif
+
+/* Special macros that are no-ops except when run under Valgrind on
+ * x86. They've moved a little bit from valgrind 1.0.4 to 1.9.4 */
+#ifdef HAVE_VALGRIND_MEMCHECK_H
+ /* memcheck.h includes valgrind.h */
+#include <valgrind/memcheck.h>
+#elif defined(HAVE_VALGRIND_H)
+#include <valgrind.h>
+#endif
+
+#define MAX_TALLOC_SIZE 0x10000000
+
+#define TALLOC_FLAG_FREE 0x01
+#define TALLOC_FLAG_LOOP 0x02
+#define TALLOC_FLAG_POOL 0x04 /* This is a talloc pool */
+#define TALLOC_FLAG_POOLMEM 0x08 /* This is allocated in a pool */
+
+/*
+ * Bits above this are random, used to make it harder to fake talloc
+ * headers during an attack. Try not to change this without good reason.
+ */
+#define TALLOC_FLAG_MASK 0x0F
+
+#define TALLOC_MAGIC_REFERENCE ((const char *)1)
+
+#define TALLOC_MAGIC_BASE 0xe814ec70
+#define TALLOC_MAGIC_NON_RANDOM ( \
+ ~TALLOC_FLAG_MASK & ( \
+ TALLOC_MAGIC_BASE + \
+ (TALLOC_BUILD_VERSION_MAJOR << 24) + \
+ (TALLOC_BUILD_VERSION_MINOR << 16) + \
+ (TALLOC_BUILD_VERSION_RELEASE << 8)))
+static unsigned int talloc_magic = TALLOC_MAGIC_NON_RANDOM;
+
+/* 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
+
+/* these macros gain us a few percent of speed on gcc */
+#if (__GNUC__ >= 3)
+/* the strange !! is to ensure that __builtin_expect() takes either 0 or 1
+ as its first argument */
+#ifndef likely
+#define likely(x) __builtin_expect(!!(x), 1)
+#endif
+#ifndef unlikely
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#endif
+#else
+#ifndef likely
+#define likely(x) (x)
+#endif
+#ifndef unlikely
+#define unlikely(x) (x)
+#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 void *null_context;
+static bool talloc_report_null;
+static bool talloc_report_null_full;
+static void *autofree_context;
+
+static void talloc_setup_atexit(void);
+
+/* used to enable fill of memory on free, which can be useful for
+ * catching use after free errors when valgrind is too slow
+ */
+static struct {
+ bool initialised;
+ bool enabled;
+ uint8_t fill_value;
+} talloc_fill;
+
+#define TALLOC_FILL_ENV "TALLOC_FREE_FILL"
+
+/*
+ * do not wipe the header, to allow the
+ * double-free logic to still work
+ */
+#define TC_INVALIDATE_FULL_FILL_CHUNK(_tc) do { \
+ if (unlikely(talloc_fill.enabled)) { \
+ size_t _flen = (_tc)->size; \
+ char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
+ memset(_fptr, talloc_fill.fill_value, _flen); \
+ } \
+} while (0)
+
+#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
+/* Mark the whole chunk as not accessable */
+#define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { \
+ size_t _flen = TC_HDR_SIZE + (_tc)->size; \
+ char *_fptr = (char *)(_tc); \
+ VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
+} while(0)
+#else
+#define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { } while (0)
+#endif
+
+#define TC_INVALIDATE_FULL_CHUNK(_tc) do { \
+ TC_INVALIDATE_FULL_FILL_CHUNK(_tc); \
+ TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc); \
+} while (0)
+
+#define TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \
+ if (unlikely(talloc_fill.enabled)) { \
+ size_t _flen = (_tc)->size - (_new_size); \
+ char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
+ _fptr += (_new_size); \
+ memset(_fptr, talloc_fill.fill_value, _flen); \
+ } \
+} while (0)
+
+#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
+/* Mark the unused bytes not accessable */
+#define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \
+ size_t _flen = (_tc)->size - (_new_size); \
+ char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
+ _fptr += (_new_size); \
+ VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
+} while (0)
+#else
+#define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
+#endif
+
+#define TC_INVALIDATE_SHRINK_CHUNK(_tc, _new_size) do { \
+ TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size); \
+ TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \
+} while (0)
+
+#define TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \
+ if (unlikely(talloc_fill.enabled)) { \
+ size_t _flen = (_tc)->size - (_new_size); \
+ char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
+ _fptr += (_new_size); \
+ memset(_fptr, talloc_fill.fill_value, _flen); \
+ } \
+} while (0)
+
+#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
+/* Mark the unused bytes as undefined */
+#define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \
+ size_t _flen = (_tc)->size - (_new_size); \
+ char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
+ _fptr += (_new_size); \
+ VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \
+} while (0)
+#else
+#define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
+#endif
+
+#define TC_UNDEFINE_SHRINK_CHUNK(_tc, _new_size) do { \
+ TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size); \
+ TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \
+} while (0)
+
+#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
+/* Mark the new bytes as undefined */
+#define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { \
+ size_t _old_used = TC_HDR_SIZE + (_tc)->size; \
+ size_t _new_used = TC_HDR_SIZE + (_new_size); \
+ size_t _flen = _new_used - _old_used; \
+ char *_fptr = _old_used + (char *)(_tc); \
+ VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \
+} while (0)
+#else
+#define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
+#endif
+
+#define TC_UNDEFINE_GROW_CHUNK(_tc, _new_size) do { \
+ TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size); \
+} while (0)
+
+struct talloc_reference_handle {
+ struct talloc_reference_handle *next, *prev;
+ void *ptr;
+ const char *location;
+};
+
+struct talloc_memlimit {
+ struct talloc_chunk *parent;
+ struct talloc_memlimit *upper;
+ size_t max_size;
+ size_t cur_size;
+};
+
+static inline bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size);
+static inline void talloc_memlimit_grow(struct talloc_memlimit *limit,
+ size_t size);
+static inline void talloc_memlimit_shrink(struct talloc_memlimit *limit,
+ size_t size);
+static inline void tc_memlimit_update_on_free(struct talloc_chunk *tc);
+
+static inline void _tc_set_name_const(struct talloc_chunk *tc,
+ const char *name);
+static struct talloc_chunk *_vasprintf_tc(const void *t,
+ const char *fmt,
+ va_list ap);
+
+typedef int (*talloc_destructor_t)(void *);
+
+struct talloc_pool_hdr;
+
+struct talloc_chunk {
+ /*
+ * flags includes the talloc magic, which is randomised to
+ * make overwrite attacks harder
+ */
+ unsigned flags;
+
+ /*
+ * If you have a logical tree like:
+ *
+ * <parent>
+ * / | \
+ * / | \
+ * / | \
+ * <child 1> <child 2> <child 3>
+ *
+ * The actual talloc tree is:
+ *
+ * <parent>
+ * |
+ * <child 1> - <child 2> - <child 3>
+ *
+ * The children are linked with next/prev pointers, and
+ * child 1 is linked to the parent with parent/child
+ * pointers.
+ */
+
+ struct talloc_chunk *next, *prev;
+ struct talloc_chunk *parent, *child;
+ struct talloc_reference_handle *refs;
+ talloc_destructor_t destructor;
+ const char *name;
+ size_t size;
+
+ /*
+ * limit semantics:
+ * if 'limit' is set it means all *new* children of the context will
+ * be limited to a total aggregate size ox max_size for memory
+ * allocations.
+ * cur_size is used to keep track of the current use
+ */
+ struct talloc_memlimit *limit;
+
+ /*
+ * For members of a pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool"
+ * is a pointer to the struct talloc_chunk of the pool that it was
+ * allocated from. This way children can quickly find the pool to chew
+ * from.
+ */
+ struct talloc_pool_hdr *pool;
+};
+
+union talloc_chunk_cast_u {
+ uint8_t *ptr;
+ struct talloc_chunk *chunk;
+};
+
+/* 16 byte alignment seems to keep everyone happy */
+#define TC_ALIGN16(s) (((s)+15)&~15)
+#define TC_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_chunk))
+#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
+
+_PUBLIC_ int talloc_version_major(void)
+{
+ return TALLOC_VERSION_MAJOR;
+}
+
+_PUBLIC_ int talloc_version_minor(void)
+{
+ return TALLOC_VERSION_MINOR;
+}
+
+_PUBLIC_ int talloc_test_get_magic(void)
+{
+ return talloc_magic;
+}
+
+static inline void _talloc_chunk_set_free(struct talloc_chunk *tc,
+ const char *location)
+{
+ /*
+ * Mark this memory as free, and also over-stamp the talloc
+ * magic with the old-style magic.
+ *
+ * Why? This tries to avoid a memory read use-after-free from
+ * disclosing our talloc magic, which would then allow an
+ * attacker to prepare a valid header and so run a destructor.
+ *
+ */
+ tc->flags = TALLOC_MAGIC_NON_RANDOM | TALLOC_FLAG_FREE
+ | (tc->flags & TALLOC_FLAG_MASK);
+
+ /* we mark the freed memory with where we called the free
+ * from. This means on a double free error we can report where
+ * the first free came from
+ */
+ if (location) {
+ tc->name = location;
+ }
+}
+
+static inline void _talloc_chunk_set_not_free(struct talloc_chunk *tc)
+{
+ /*
+ * Mark this memory as not free.
+ *
+ * Why? This is memory either in a pool (and so available for
+ * talloc's re-use or after the realloc(). We need to mark
+ * the memory as free() before any realloc() call as we can't
+ * write to the memory after that.
+ *
+ * We put back the normal magic instead of the 'not random'
+ * magic.
+ */
+
+ tc->flags = talloc_magic |
+ ((tc->flags & TALLOC_FLAG_MASK) & ~TALLOC_FLAG_FREE);
+}
+
+static void (*talloc_log_fn)(const char *message);
+
+_PUBLIC_ void talloc_set_log_fn(void (*log_fn)(const char *message))
+{
+ talloc_log_fn = log_fn;
+}
+
+#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
+#define CONSTRUCTOR __attribute__((constructor))
+#elif defined(HAVE_PRAGMA_INIT)
+#define CONSTRUCTOR
+#pragma init (talloc_lib_init)
+#endif
+#if defined(HAVE_CONSTRUCTOR_ATTRIBUTE) || defined(HAVE_PRAGMA_INIT)
+void talloc_lib_init(void) CONSTRUCTOR;
+void talloc_lib_init(void)
+{
+ uint32_t random_value;
+#if defined(HAVE_GETAUXVAL) && defined(AT_RANDOM)
+ uint8_t *p;
+ /*
+ * Use the kernel-provided random values used for
+ * ASLR. This won't change per-exec, which is ideal for us
+ */
+ p = (uint8_t *) getauxval(AT_RANDOM);
+ if (p) {
+ /*
+ * We get 16 bytes from getauxval. By calling rand(),
+ * a totally insecure PRNG, but one that will
+ * deterministically have a different value when called
+ * twice, we ensure that if two talloc-like libraries
+ * are somehow loaded in the same address space, that
+ * because we choose different bytes, we will keep the
+ * protection against collision of multiple talloc
+ * libs.
+ *
+ * This protection is important because the effects of
+ * passing a talloc pointer from one to the other may
+ * be very hard to determine.
+ */
+ int offset = rand() % (16 - sizeof(random_value));
+ memcpy(&random_value, p + offset, sizeof(random_value));
+ } else
+#endif
+ {
+ /*
+ * Otherwise, hope the location we are loaded in
+ * memory is randomised by someone else
+ */
+ random_value = ((uintptr_t)talloc_lib_init & 0xFFFFFFFF);
+ }
+ talloc_magic = random_value & ~TALLOC_FLAG_MASK;
+}
+#else
+#warning "No __attribute__((constructor)) support found on this platform, additional talloc security measures not available"
+#endif
+
+static void talloc_lib_atexit(void)
+{
+ TALLOC_FREE(autofree_context);
+
+ if (talloc_total_size(null_context) == 0) {
+ return;
+ }
+
+ if (talloc_report_null_full) {
+ talloc_report_full(null_context, stderr);
+ } else if (talloc_report_null) {
+ talloc_report(null_context, stderr);
+ }
+}
+
+static void talloc_setup_atexit(void)
+{
+ static bool done;
+
+ if (done) {
+ return;
+ }
+
+ atexit(talloc_lib_atexit);
+ done = true;
+}
+
+static void talloc_log(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
+static void talloc_log(const char *fmt, ...)
+{
+ va_list ap;
+ char *message;
+
+ if (!talloc_log_fn) {
+ return;
+ }
+
+ va_start(ap, fmt);
+ message = talloc_vasprintf(NULL, fmt, ap);
+ va_end(ap);
+
+ talloc_log_fn(message);
+ talloc_free(message);
+}
+
+static void talloc_log_stderr(const char *message)
+{
+ fprintf(stderr, "%s", message);
+}
+
+_PUBLIC_ void talloc_set_log_stderr(void)
+{
+ talloc_set_log_fn(talloc_log_stderr);
+}
+
+static void (*talloc_abort_fn)(const char *reason);
+
+_PUBLIC_ void talloc_set_abort_fn(void (*abort_fn)(const char *reason))
+{
+ talloc_abort_fn = abort_fn;
+}
+
+static void talloc_abort(const char *reason)
+{
+ talloc_log("%s\n", reason);
+
+ if (!talloc_abort_fn) {
+ TALLOC_ABORT(reason);
+ }
+
+ talloc_abort_fn(reason);
+}
+
+static void talloc_abort_access_after_free(void)
+{
+ talloc_abort("Bad talloc magic value - access after free");
+}
+
+static void talloc_abort_unknown_value(void)
+{
+ talloc_abort("Bad talloc magic value - unknown value");
+}
+
+/* panic if we get a bad magic value */
+static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
+{
+ const char *pp = (const char *)ptr;
+ struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
+ if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~TALLOC_FLAG_MASK)) != talloc_magic)) {
+ if ((tc->flags & (TALLOC_FLAG_FREE | ~TALLOC_FLAG_MASK))
+ == (TALLOC_MAGIC_NON_RANDOM | TALLOC_FLAG_FREE)) {
+ talloc_log("talloc: access after free error - first free may be at %s\n", tc->name);
+ talloc_abort_access_after_free();
+ return NULL;
+ }
+
+ talloc_abort_unknown_value();
+ return NULL;
+ }
+ 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 inline struct talloc_chunk *talloc_parent_chunk(const void *ptr)
+{
+ struct talloc_chunk *tc;
+
+ if (unlikely(ptr == NULL)) {
+ return NULL;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+ while (tc->prev) tc=tc->prev;
+
+ return tc->parent;
+}
+
+_PUBLIC_ void *talloc_parent(const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_parent_chunk(ptr);
+ return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
+}
+
+/*
+ find parents name
+*/
+_PUBLIC_ const char *talloc_parent_name(const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_parent_chunk(ptr);
+ return tc? tc->name : NULL;
+}
+
+/*
+ A pool carries an in-pool object count count in the first 16 bytes.
+ bytes. This is done to support talloc_steal() to a parent outside of the
+ pool. The count includes the pool itself, so a talloc_free() on a pool will
+ only destroy the pool if the count has dropped to zero. A talloc_free() of a
+ pool member will reduce the count, and eventually also call free(3) on the
+ pool memory.
+
+ The object count is not put into "struct talloc_chunk" because it is only
+ relevant for talloc pools and the alignment to 16 bytes would increase the
+ memory footprint of each talloc chunk by those 16 bytes.
+*/
+
+struct talloc_pool_hdr {
+ void *end;
+ unsigned int object_count;
+ size_t poolsize;
+};
+
+union talloc_pool_hdr_cast_u {
+ uint8_t *ptr;
+ struct talloc_pool_hdr *hdr;
+};
+
+#define TP_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_pool_hdr))
+
+static inline struct talloc_pool_hdr *talloc_pool_from_chunk(struct talloc_chunk *c)
+{
+ union talloc_chunk_cast_u tcc = { .chunk = c };
+ union talloc_pool_hdr_cast_u tphc = { tcc.ptr - TP_HDR_SIZE };
+ return tphc.hdr;
+}
+
+static inline struct talloc_chunk *talloc_chunk_from_pool(struct talloc_pool_hdr *h)
+{
+ union talloc_pool_hdr_cast_u tphc = { .hdr = h };
+ union talloc_chunk_cast_u tcc = { .ptr = tphc.ptr + TP_HDR_SIZE };
+ return tcc.chunk;
+}
+
+static inline void *tc_pool_end(struct talloc_pool_hdr *pool_hdr)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_pool(pool_hdr);
+ return (char *)tc + TC_HDR_SIZE + pool_hdr->poolsize;
+}
+
+static inline size_t tc_pool_space_left(struct talloc_pool_hdr *pool_hdr)
+{
+ return (char *)tc_pool_end(pool_hdr) - (char *)pool_hdr->end;
+}
+
+/* If tc is inside a pool, this gives the next neighbour. */
+static inline void *tc_next_chunk(struct talloc_chunk *tc)
+{
+ return (char *)tc + TC_ALIGN16(TC_HDR_SIZE + tc->size);
+}
+
+static inline void *tc_pool_first_chunk(struct talloc_pool_hdr *pool_hdr)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_pool(pool_hdr);
+ return tc_next_chunk(tc);
+}
+
+/* Mark the whole remaining pool as not accessable */
+static inline void tc_invalidate_pool(struct talloc_pool_hdr *pool_hdr)
+{
+ size_t flen = tc_pool_space_left(pool_hdr);
+
+ if (unlikely(talloc_fill.enabled)) {
+ memset(pool_hdr->end, talloc_fill.fill_value, flen);
+ }
+
+#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
+ VALGRIND_MAKE_MEM_NOACCESS(pool_hdr->end, flen);
+#endif
+}
+
+/*
+ Allocate from a pool
+*/
+
+static inline struct talloc_chunk *tc_alloc_pool(struct talloc_chunk *parent,
+ size_t size, size_t prefix_len)
+{
+ struct talloc_pool_hdr *pool_hdr = NULL;
+ union talloc_chunk_cast_u tcc;
+ size_t space_left;
+ struct talloc_chunk *result;
+ size_t chunk_size;
+
+ if (parent == NULL) {
+ return NULL;
+ }
+
+ if (parent->flags & TALLOC_FLAG_POOL) {
+ pool_hdr = talloc_pool_from_chunk(parent);
+ }
+ else if (parent->flags & TALLOC_FLAG_POOLMEM) {
+ pool_hdr = parent->pool;
+ }
+
+ if (pool_hdr == NULL) {
+ return NULL;
+ }
+
+ space_left = tc_pool_space_left(pool_hdr);
+
+ /*
+ * Align size to 16 bytes
+ */
+ chunk_size = TC_ALIGN16(size + prefix_len);
+
+ if (space_left < chunk_size) {
+ return NULL;
+ }
+
+ tcc = (union talloc_chunk_cast_u) {
+ .ptr = ((uint8_t *)pool_hdr->end) + prefix_len
+ };
+ result = tcc.chunk;
+
+#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
+ VALGRIND_MAKE_MEM_UNDEFINED(pool_hdr->end, chunk_size);
+#endif
+
+ pool_hdr->end = (void *)((char *)pool_hdr->end + chunk_size);
+
+ result->flags = talloc_magic | TALLOC_FLAG_POOLMEM;
+ result->pool = pool_hdr;
+
+ pool_hdr->object_count++;
+
+ return result;
+}
+
+/*
+ Allocate a bit of memory as a child of an existing pointer
+*/
+static inline void *__talloc_with_prefix(const void *context,
+ size_t size,
+ size_t prefix_len,
+ struct talloc_chunk **tc_ret)
+{
+ struct talloc_chunk *tc = NULL;
+ struct talloc_memlimit *limit = NULL;
+ size_t total_len = TC_HDR_SIZE + size + prefix_len;
+ struct talloc_chunk *parent = NULL;
+
+ if (unlikely(context == NULL)) {
+ context = null_context;
+ }
+
+ if (unlikely(size >= MAX_TALLOC_SIZE)) {
+ return NULL;
+ }
+
+ if (unlikely(total_len < TC_HDR_SIZE)) {
+ return NULL;
+ }
+
+ if (likely(context != NULL)) {
+ parent = talloc_chunk_from_ptr(context);
+
+ if (parent->limit != NULL) {
+ limit = parent->limit;
+ }
+
+ tc = tc_alloc_pool(parent, TC_HDR_SIZE+size, prefix_len);
+ }
+
+ if (tc == NULL) {
+ uint8_t *ptr = NULL;
+ union talloc_chunk_cast_u tcc;
+
+ /*
+ * Only do the memlimit check/update on actual allocation.
+ */
+ if (!talloc_memlimit_check(limit, total_len)) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ ptr = malloc(total_len);
+ if (unlikely(ptr == NULL)) {
+ return NULL;
+ }
+ tcc = (union talloc_chunk_cast_u) { .ptr = ptr + prefix_len };
+ tc = tcc.chunk;
+ tc->flags = talloc_magic;
+ tc->pool = NULL;
+
+ talloc_memlimit_grow(limit, total_len);
+ }
+
+ tc->limit = limit;
+ tc->size = size;
+ tc->destructor = NULL;
+ tc->child = NULL;
+ tc->name = NULL;
+ tc->refs = NULL;
+
+ if (likely(context != NULL)) {
+ if (parent->child) {
+ parent->child->parent = NULL;
+ tc->next = parent->child;
+ tc->next->prev = tc;
+ } else {
+ tc->next = NULL;
+ }
+ tc->parent = parent;
+ tc->prev = NULL;
+ parent->child = tc;
+ } else {
+ tc->next = tc->prev = tc->parent = NULL;
+ }
+
+ *tc_ret = tc;
+ return TC_PTR_FROM_CHUNK(tc);
+}
+
+static inline void *__talloc(const void *context,
+ size_t size,
+ struct talloc_chunk **tc)
+{
+ return __talloc_with_prefix(context, size, 0, tc);
+}
+
+/*
+ * Create a talloc pool
+ */
+
+static inline void *_talloc_pool(const void *context, size_t size)
+{
+ struct talloc_chunk *tc = NULL;
+ struct talloc_pool_hdr *pool_hdr;
+ void *result;
+
+ result = __talloc_with_prefix(context, size, TP_HDR_SIZE, &tc);
+
+ if (unlikely(result == NULL)) {
+ return NULL;
+ }
+
+ pool_hdr = talloc_pool_from_chunk(tc);
+
+ tc->flags |= TALLOC_FLAG_POOL;
+ tc->size = 0;
+
+ pool_hdr->object_count = 1;
+ pool_hdr->end = result;
+ pool_hdr->poolsize = size;
+
+ tc_invalidate_pool(pool_hdr);
+
+ return result;
+}
+
+_PUBLIC_ void *talloc_pool(const void *context, size_t size)
+{
+ return _talloc_pool(context, size);
+}
+
+/*
+ * Create a talloc pool correctly sized for a basic size plus
+ * a number of subobjects whose total size is given. Essentially
+ * a custom allocator for talloc to reduce fragmentation.
+ */
+
+_PUBLIC_ void *_talloc_pooled_object(const void *ctx,
+ size_t type_size,
+ const char *type_name,
+ unsigned num_subobjects,
+ size_t total_subobjects_size)
+{
+ size_t poolsize, subobjects_slack, tmp;
+ struct talloc_chunk *tc;
+ struct talloc_pool_hdr *pool_hdr;
+ void *ret;
+
+ poolsize = type_size + total_subobjects_size;
+
+ if ((poolsize < type_size) || (poolsize < total_subobjects_size)) {
+ goto overflow;
+ }
+
+ if (num_subobjects == UINT_MAX) {
+ goto overflow;
+ }
+ num_subobjects += 1; /* the object body itself */
+
+ /*
+ * Alignment can increase the pool size by at most 15 bytes per object
+ * plus alignment for the object itself
+ */
+ subobjects_slack = (TC_HDR_SIZE + TP_HDR_SIZE + 15) * num_subobjects;
+ if (subobjects_slack < num_subobjects) {
+ goto overflow;
+ }
+
+ tmp = poolsize + subobjects_slack;
+ if ((tmp < poolsize) || (tmp < subobjects_slack)) {
+ goto overflow;
+ }
+ poolsize = tmp;
+
+ ret = _talloc_pool(ctx, poolsize);
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ tc = talloc_chunk_from_ptr(ret);
+ tc->size = type_size;
+
+ pool_hdr = talloc_pool_from_chunk(tc);
+
+#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
+ VALGRIND_MAKE_MEM_UNDEFINED(pool_hdr->end, type_size);
+#endif
+
+ pool_hdr->end = ((char *)pool_hdr->end + TC_ALIGN16(type_size));
+
+ _tc_set_name_const(tc, type_name);
+ return ret;
+
+overflow:
+ return NULL;
+}
+
+/*
+ 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
+*/
+_PUBLIC_ 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.
+*/
+_PUBLIC_ int talloc_increase_ref_count(const void *ptr)
+{
+ if (unlikely(!talloc_reference(null_context, ptr))) {
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ helper for talloc_reference()
+
+ this is referenced by a function pointer and should not be inline
+*/
+static int talloc_reference_destructor(struct talloc_reference_handle *handle)
+{
+ struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
+ _TLIST_REMOVE(ptr_tc->refs, handle);
+ return 0;
+}
+
+/*
+ more efficient way to add a name to a pointer - the name must point to a
+ true string constant
+*/
+static inline void _tc_set_name_const(struct talloc_chunk *tc,
+ const char *name)
+{
+ tc->name = name;
+}
+
+/*
+ internal talloc_named_const()
+*/
+static inline void *_talloc_named_const(const void *context, size_t size, const char *name)
+{
+ void *ptr;
+ struct talloc_chunk *tc = NULL;
+
+ ptr = __talloc(context, size, &tc);
+ if (unlikely(ptr == NULL)) {
+ return NULL;
+ }
+
+ _tc_set_name_const(tc, name);
+
+ return ptr;
+}
+
+/*
+ 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
+*/
+_PUBLIC_ void *_talloc_reference_loc(const void *context, const void *ptr, const char *location)
+{
+ struct talloc_chunk *tc;
+ struct talloc_reference_handle *handle;
+ if (unlikely(ptr == NULL)) return NULL;
+
+ tc = talloc_chunk_from_ptr(ptr);
+ handle = (struct talloc_reference_handle *)_talloc_named_const(context,
+ sizeof(struct talloc_reference_handle),
+ TALLOC_MAGIC_REFERENCE);
+ if (unlikely(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);
+ handle->location = location;
+ _TLIST_ADD(tc->refs, handle);
+ return handle->ptr;
+}
+
+static void *_talloc_steal_internal(const void *new_ctx, const void *ptr);
+
+static inline void _tc_free_poolmem(struct talloc_chunk *tc,
+ const char *location)
+{
+ struct talloc_pool_hdr *pool;
+ struct talloc_chunk *pool_tc;
+ void *next_tc;
+
+ pool = tc->pool;
+ pool_tc = talloc_chunk_from_pool(pool);
+ next_tc = tc_next_chunk(tc);
+
+ _talloc_chunk_set_free(tc, location);
+
+ TC_INVALIDATE_FULL_CHUNK(tc);
+
+ if (unlikely(pool->object_count == 0)) {
+ talloc_abort("Pool object count zero!");
+ return;
+ }
+
+ pool->object_count--;
+
+ if (unlikely(pool->object_count == 1
+ && !(pool_tc->flags & TALLOC_FLAG_FREE))) {
+ /*
+ * if there is just one object left in the pool
+ * and pool->flags does not have TALLOC_FLAG_FREE,
+ * it means this is the pool itself and
+ * the rest is available for new objects
+ * again.
+ */
+ pool->end = tc_pool_first_chunk(pool);
+ tc_invalidate_pool(pool);
+ return;
+ }
+
+ if (unlikely(pool->object_count == 0)) {
+ /*
+ * we mark the freed memory with where we called the free
+ * from. This means on a double free error we can report where
+ * the first free came from
+ */
+ pool_tc->name = location;
+
+ if (pool_tc->flags & TALLOC_FLAG_POOLMEM) {
+ _tc_free_poolmem(pool_tc, location);
+ } else {
+ /*
+ * The tc_memlimit_update_on_free()
+ * call takes into account the
+ * prefix TP_HDR_SIZE allocated before
+ * the pool talloc_chunk.
+ */
+ tc_memlimit_update_on_free(pool_tc);
+ TC_INVALIDATE_FULL_CHUNK(pool_tc);
+ free(pool);
+ }
+ return;
+ }
+
+ if (pool->end == next_tc) {
+ /*
+ * if pool->pool still points to end of
+ * 'tc' (which is stored in the 'next_tc' variable),
+ * we can reclaim the memory of 'tc'.
+ */
+ pool->end = tc;
+ return;
+ }
+
+ /*
+ * Do nothing. The memory is just "wasted", waiting for the pool
+ * itself to be freed.
+ */
+}
+
+static inline void _tc_free_children_internal(struct talloc_chunk *tc,
+ void *ptr,
+ const char *location);
+
+static inline int _talloc_free_internal(void *ptr, const char *location);
+
+/*
+ internal free call that takes a struct talloc_chunk *.
+*/
+static inline int _tc_free_internal(struct talloc_chunk *tc,
+ const char *location)
+{
+ void *ptr_to_free;
+ void *ptr = TC_PTR_FROM_CHUNK(tc);
+
+ if (unlikely(tc->refs)) {
+ int is_child;
+ /* check if this is a reference from a child or
+ * grandchild back to it's parent or grandparent
+ *
+ * in that case we need to remove the reference and
+ * call another instance of talloc_free() on the current
+ * pointer.
+ */
+ is_child = talloc_is_parent(tc->refs, ptr);
+ _talloc_free_internal(tc->refs, location);
+ if (is_child) {
+ return _talloc_free_internal(ptr, location);
+ }
+ return -1;
+ }
+
+ if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) {
+ /* we have a free loop - stop looping */
+ return 0;
+ }
+
+ if (unlikely(tc->destructor)) {
+ talloc_destructor_t d = tc->destructor;
+
+ /*
+ * Protect the destructor against some overwrite
+ * attacks, by explicitly checking it has the right
+ * magic here.
+ */
+ if (talloc_chunk_from_ptr(ptr) != tc) {
+ /*
+ * This can't actually happen, the
+ * call itself will panic.
+ */
+ TALLOC_ABORT("talloc_chunk_from_ptr failed!");
+ }
+
+ if (d == (talloc_destructor_t)-1) {
+ return -1;
+ }
+ tc->destructor = (talloc_destructor_t)-1;
+ if (d(ptr) == -1) {
+ /*
+ * Only replace the destructor pointer if
+ * calling the destructor didn't modify it.
+ */
+ if (tc->destructor == (talloc_destructor_t)-1) {
+ tc->destructor = d;
+ }
+ return -1;
+ }
+ tc->destructor = 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->prev = tc->next = NULL;
+ }
+
+ tc->flags |= TALLOC_FLAG_LOOP;
+
+ _tc_free_children_internal(tc, ptr, location);
+
+ _talloc_chunk_set_free(tc, location);
+
+ if (tc->flags & TALLOC_FLAG_POOL) {
+ struct talloc_pool_hdr *pool;
+
+ pool = talloc_pool_from_chunk(tc);
+
+ if (unlikely(pool->object_count == 0)) {
+ talloc_abort("Pool object count zero!");
+ return 0;
+ }
+
+ pool->object_count--;
+
+ if (likely(pool->object_count != 0)) {
+ return 0;
+ }
+
+ /*
+ * With object_count==0, a pool becomes a normal piece of
+ * memory to free. If it's allocated inside a pool, it needs
+ * to be freed as poolmem, else it needs to be just freed.
+ */
+ ptr_to_free = pool;
+ } else {
+ ptr_to_free = tc;
+ }
+
+ if (tc->flags & TALLOC_FLAG_POOLMEM) {
+ _tc_free_poolmem(tc, location);
+ return 0;
+ }
+
+ tc_memlimit_update_on_free(tc);
+
+ TC_INVALIDATE_FULL_CHUNK(tc);
+ free(ptr_to_free);
+ return 0;
+}
+
+/*
+ internal talloc_free call
+*/
+static inline int _talloc_free_internal(void *ptr, const char *location)
+{
+ struct talloc_chunk *tc;
+
+ if (unlikely(ptr == NULL)) {
+ return -1;
+ }
+
+ /* possibly initialised the talloc fill value */
+ if (unlikely(!talloc_fill.initialised)) {
+ const char *fill = getenv(TALLOC_FILL_ENV);
+ if (fill != NULL) {
+ talloc_fill.enabled = true;
+ talloc_fill.fill_value = strtoul(fill, NULL, 0);
+ }
+ talloc_fill.initialised = true;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+ return _tc_free_internal(tc, location);
+}
+
+static inline size_t _talloc_total_limit_size(const void *ptr,
+ struct talloc_memlimit *old_limit,
+ struct talloc_memlimit *new_limit);
+
+/*
+ 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.
+*/
+static void *_talloc_steal_internal(const void *new_ctx, const void *ptr)
+{
+ struct talloc_chunk *tc, *new_tc;
+ size_t ctx_size = 0;
+
+ if (unlikely(!ptr)) {
+ return NULL;
+ }
+
+ if (unlikely(new_ctx == NULL)) {
+ new_ctx = null_context;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ if (tc->limit != NULL) {
+
+ ctx_size = _talloc_total_limit_size(ptr, NULL, NULL);
+
+ /* Decrement the memory limit from the source .. */
+ talloc_memlimit_shrink(tc->limit->upper, ctx_size);
+
+ if (tc->limit->parent == tc) {
+ tc->limit->upper = NULL;
+ } else {
+ tc->limit = NULL;
+ }
+ }
+
+ if (unlikely(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 (unlikely(tc == new_tc || tc->parent == 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->prev = tc->next = NULL;
+ }
+
+ tc->parent = new_tc;
+ if (new_tc->child) new_tc->child->parent = NULL;
+ _TLIST_ADD(new_tc->child, tc);
+
+ if (tc->limit || new_tc->limit) {
+ ctx_size = _talloc_total_limit_size(ptr, tc->limit,
+ new_tc->limit);
+ /* .. and increment it in the destination. */
+ if (new_tc->limit) {
+ talloc_memlimit_grow(new_tc->limit, ctx_size);
+ }
+ }
+
+ return discard_const_p(void, ptr);
+}
+
+/*
+ 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.
+*/
+_PUBLIC_ void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location)
+{
+ struct talloc_chunk *tc;
+
+ if (unlikely(ptr == NULL)) {
+ return NULL;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ if (unlikely(tc->refs != NULL) && talloc_parent(ptr) != new_ctx) {
+ struct talloc_reference_handle *h;
+
+ talloc_log("WARNING: talloc_steal with references at %s\n",
+ location);
+
+ for (h=tc->refs; h; h=h->next) {
+ talloc_log("\treference at %s\n",
+ h->location);
+ }
+ }
+
+#if 0
+ /* this test is probably too expensive to have on in the
+ normal build, but it useful for debugging */
+ if (talloc_is_parent(new_ctx, ptr)) {
+ talloc_log("WARNING: stealing into talloc child at %s\n", location);
+ }
+#endif
+
+ return _talloc_steal_internal(new_ctx, ptr);
+}
+
+/*
+ this is like a talloc_steal(), but you must supply the old
+ parent. This resolves the ambiguity in a talloc_steal() which is
+ called on a context that has more than one parent (via references)
+
+ The old parent can be either a reference or a parent
+*/
+_PUBLIC_ void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr)
+{
+ struct talloc_chunk *tc;
+ struct talloc_reference_handle *h;
+
+ if (unlikely(ptr == NULL)) {
+ return NULL;
+ }
+
+ if (old_parent == talloc_parent(ptr)) {
+ return _talloc_steal_internal(new_parent, ptr);
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+ for (h=tc->refs;h;h=h->next) {
+ if (talloc_parent(h) == old_parent) {
+ if (_talloc_steal_internal(new_parent, h) != h) {
+ return NULL;
+ }
+ return discard_const_p(void, ptr);
+ }
+ }
+
+ /* it wasn't a parent */
+ return NULL;
+}
+
+/*
+ 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 inline int talloc_unreference(const void *context, const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ struct talloc_reference_handle *h;
+
+ if (unlikely(context == NULL)) {
+ context = null_context;
+ }
+
+ for (h=tc->refs;h;h=h->next) {
+ struct talloc_chunk *p = talloc_parent_chunk(h);
+ if (p == NULL) {
+ if (context == NULL) break;
+ } else if (TC_PTR_FROM_CHUNK(p) == context) {
+ break;
+ }
+ }
+ if (h == NULL) {
+ return -1;
+ }
+
+ return _talloc_free_internal(h, __location__);
+}
+
+/*
+ remove a specific parent context from a pointer. This is a more
+ controlled variant of talloc_free()
+*/
+
+/* coverity[ -tainted_data_sink : arg-1 ] */
+_PUBLIC_ int talloc_unlink(const void *context, void *ptr)
+{
+ struct talloc_chunk *tc_p, *new_p, *tc_c;
+ 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) {
+ tc_c = talloc_chunk_from_ptr(context);
+ } else {
+ tc_c = NULL;
+ }
+ if (tc_c != talloc_parent_chunk(ptr)) {
+ return -1;
+ }
+
+ tc_p = talloc_chunk_from_ptr(ptr);
+
+ if (tc_p->refs == NULL) {
+ return _talloc_free_internal(ptr, __location__);
+ }
+
+ new_p = talloc_parent_chunk(tc_p->refs);
+ if (new_p) {
+ new_parent = TC_PTR_FROM_CHUNK(new_p);
+ } else {
+ new_parent = NULL;
+ }
+
+ if (talloc_unreference(new_parent, ptr) != 0) {
+ return -1;
+ }
+
+ _talloc_steal_internal(new_parent, ptr);
+
+ return 0;
+}
+
+/*
+ add a name to an existing pointer - va_list version
+*/
+static inline const char *tc_set_name_v(struct talloc_chunk *tc,
+ const char *fmt,
+ va_list ap) PRINTF_ATTRIBUTE(2,0);
+
+static inline const char *tc_set_name_v(struct talloc_chunk *tc,
+ const char *fmt,
+ va_list ap)
+{
+ struct talloc_chunk *name_tc = _vasprintf_tc(TC_PTR_FROM_CHUNK(tc),
+ fmt,
+ ap);
+ if (likely(name_tc)) {
+ tc->name = TC_PTR_FROM_CHUNK(name_tc);
+ _tc_set_name_const(name_tc, ".name");
+ } else {
+ tc->name = NULL;
+ }
+ return tc->name;
+}
+
+/*
+ add a name to an existing pointer
+*/
+_PUBLIC_ const char *talloc_set_name(const void *ptr, const char *fmt, ...)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ const char *name;
+ va_list ap;
+ va_start(ap, fmt);
+ name = tc_set_name_v(tc, fmt, ap);
+ va_end(ap);
+ return 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.
+*/
+_PUBLIC_ void *talloc_named(const void *context, size_t size, const char *fmt, ...)
+{
+ va_list ap;
+ void *ptr;
+ const char *name;
+ struct talloc_chunk *tc = NULL;
+
+ ptr = __talloc(context, size, &tc);
+ if (unlikely(ptr == NULL)) return NULL;
+
+ va_start(ap, fmt);
+ name = tc_set_name_v(tc, fmt, ap);
+ va_end(ap);
+
+ if (unlikely(name == NULL)) {
+ _talloc_free_internal(ptr, __location__);
+ return NULL;
+ }
+
+ return ptr;
+}
+
+/*
+ return the name of a talloc ptr, or "UNNAMED"
+*/
+static inline const char *__talloc_get_name(const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
+ return ".reference";
+ }
+ if (likely(tc->name)) {
+ return tc->name;
+ }
+ return "UNNAMED";
+}
+
+_PUBLIC_ const char *talloc_get_name(const void *ptr)
+{
+ return __talloc_get_name(ptr);
+}
+
+/*
+ check if a pointer has the given name. If it does, return the pointer,
+ otherwise return NULL
+*/
+_PUBLIC_ void *talloc_check_name(const void *ptr, const char *name)
+{
+ const char *pname;
+ if (unlikely(ptr == NULL)) return NULL;
+ pname = __talloc_get_name(ptr);
+ if (likely(pname == name || strcmp(pname, name) == 0)) {
+ return discard_const_p(void, ptr);
+ }
+ return NULL;
+}
+
+static void talloc_abort_type_mismatch(const char *location,
+ const char *name,
+ const char *expected)
+{
+ const char *reason;
+
+ reason = talloc_asprintf(NULL,
+ "%s: Type mismatch: name[%s] expected[%s]",
+ location,
+ name?name:"NULL",
+ expected);
+ if (!reason) {
+ reason = "Type mismatch";
+ }
+
+ talloc_abort(reason);
+}
+
+_PUBLIC_ void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)
+{
+ const char *pname;
+
+ if (unlikely(ptr == NULL)) {
+ talloc_abort_type_mismatch(location, NULL, name);
+ return NULL;
+ }
+
+ pname = __talloc_get_name(ptr);
+ if (likely(pname == name || strcmp(pname, name) == 0)) {
+ return discard_const_p(void, ptr);
+ }
+
+ talloc_abort_type_mismatch(location, pname, name);
+ return NULL;
+}
+
+/*
+ this is for compatibility with older versions of talloc
+*/
+_PUBLIC_ void *talloc_init(const char *fmt, ...)
+{
+ va_list ap;
+ void *ptr;
+ const char *name;
+ struct talloc_chunk *tc = NULL;
+
+ ptr = __talloc(NULL, 0, &tc);
+ if (unlikely(ptr == NULL)) return NULL;
+
+ va_start(ap, fmt);
+ name = tc_set_name_v(tc, fmt, ap);
+ va_end(ap);
+
+ if (unlikely(name == NULL)) {
+ _talloc_free_internal(ptr, __location__);
+ return NULL;
+ }
+
+ return ptr;
+}
+
+static inline void _tc_free_children_internal(struct talloc_chunk *tc,
+ void *ptr,
+ const char *location)
+{
+ 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_PTR_FROM_CHUNK(tc->child);
+ const void *new_parent = null_context;
+ if (unlikely(tc->child->refs)) {
+ struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
+ if (p) new_parent = TC_PTR_FROM_CHUNK(p);
+ }
+ if (unlikely(_tc_free_internal(tc->child, location) == -1)) {
+ if (talloc_parent_chunk(child) != tc) {
+ /*
+ * Destructor already reparented this child.
+ * No further reparenting needed.
+ */
+ continue;
+ }
+ if (new_parent == null_context) {
+ struct talloc_chunk *p = talloc_parent_chunk(ptr);
+ if (p) new_parent = TC_PTR_FROM_CHUNK(p);
+ }
+ _talloc_steal_internal(new_parent, child);
+ }
+ }
+}
+
+/*
+ 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.
+*/
+_PUBLIC_ void talloc_free_children(void *ptr)
+{
+ struct talloc_chunk *tc_name = NULL;
+ struct talloc_chunk *tc;
+
+ if (unlikely(ptr == NULL)) {
+ return;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ /* we do not want to free the context name if it is a child .. */
+ if (likely(tc->child)) {
+ for (tc_name = tc->child; tc_name; tc_name = tc_name->next) {
+ if (tc->name == TC_PTR_FROM_CHUNK(tc_name)) break;
+ }
+ if (tc_name) {
+ _TLIST_REMOVE(tc->child, tc_name);
+ if (tc->child) {
+ tc->child->parent = tc;
+ }
+ }
+ }
+
+ _tc_free_children_internal(tc, ptr, __location__);
+
+ /* .. so we put it back after all other children have been freed */
+ if (tc_name) {
+ if (tc->child) {
+ tc->child->parent = NULL;
+ }
+ tc_name->parent = tc;
+ _TLIST_ADD(tc->child, tc_name);
+ }
+}
+
+/*
+ Allocate a bit of memory as a child of an existing pointer
+*/
+_PUBLIC_ void *_talloc(const void *context, size_t size)
+{
+ struct talloc_chunk *tc;
+ return __talloc(context, size, &tc);
+}
+
+/*
+ externally callable talloc_set_name_const()
+*/
+_PUBLIC_ void talloc_set_name_const(const void *ptr, const char *name)
+{
+ _tc_set_name_const(talloc_chunk_from_ptr(ptr), 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.
+*/
+_PUBLIC_ void *talloc_named_const(const void *context, size_t size, const char *name)
+{
+ return _talloc_named_const(context, size, name);
+}
+
+/*
+ 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
+*/
+_PUBLIC_ int _talloc_free(void *ptr, const char *location)
+{
+ struct talloc_chunk *tc;
+
+ if (unlikely(ptr == NULL)) {
+ return -1;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ if (unlikely(tc->refs != NULL)) {
+ struct talloc_reference_handle *h;
+
+ if (talloc_parent(ptr) == null_context && tc->refs->next == NULL) {
+ /* in this case we do know which parent should
+ get this pointer, as there is really only
+ one parent */
+ return talloc_unlink(null_context, ptr);
+ }
+
+ talloc_log("ERROR: talloc_free with references at %s\n",
+ location);
+
+ for (h=tc->refs; h; h=h->next) {
+ talloc_log("\treference at %s\n",
+ h->location);
+ }
+ return -1;
+ }
+
+ return _talloc_free_internal(ptr, location);
+}
+
+
+
+/*
+ A talloc version of realloc. The context argument is only used if
+ ptr is NULL
+*/
+_PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
+{
+ struct talloc_chunk *tc;
+ void *new_ptr;
+ bool malloced = false;
+ struct talloc_pool_hdr *pool_hdr = NULL;
+ size_t old_size = 0;
+ size_t new_size = 0;
+
+ /* size zero is equivalent to free() */
+ if (unlikely(size == 0)) {
+ talloc_unlink(context, ptr);
+ return NULL;
+ }
+
+ if (unlikely(size >= MAX_TALLOC_SIZE)) {
+ return NULL;
+ }
+
+ /* realloc(NULL) is equivalent 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 (unlikely(tc->refs)) {
+ return NULL;
+ }
+
+ /* don't let anybody try to realloc a talloc_pool */
+ if (unlikely(tc->flags & TALLOC_FLAG_POOL)) {
+ return NULL;
+ }
+
+ /* handle realloc inside a talloc_pool */
+ if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) {
+ pool_hdr = tc->pool;
+ }
+
+ /* don't shrink if we have less than 1k to gain */
+ if (size < tc->size && tc->limit == NULL) {
+ if (pool_hdr) {
+ void *next_tc = tc_next_chunk(tc);
+ TC_INVALIDATE_SHRINK_CHUNK(tc, size);
+ tc->size = size;
+ if (next_tc == pool_hdr->end) {
+ /* note: tc->size has changed, so this works */
+ pool_hdr->end = tc_next_chunk(tc);
+ }
+ return ptr;
+ } else if ((tc->size - size) < 1024) {
+ /*
+ * if we call TC_INVALIDATE_SHRINK_CHUNK() here
+ * we would need to call TC_UNDEFINE_GROW_CHUNK()
+ * after each realloc call, which slows down
+ * testing a lot :-(.
+ *
+ * That is why we only mark memory as undefined here.
+ */
+ TC_UNDEFINE_SHRINK_CHUNK(tc, size);
+
+ /* do not shrink if we have less than 1k to gain */
+ tc->size = size;
+ return ptr;
+ }
+ } else if (tc->size == size) {
+ /*
+ * do not change the pointer if it is exactly
+ * the same size.
+ */
+ return ptr;
+ }
+
+ /*
+ * by resetting magic we catch users of the old memory
+ *
+ * We mark this memory as free, and also over-stamp the talloc
+ * magic with the old-style magic.
+ *
+ * Why? This tries to avoid a memory read use-after-free from
+ * disclosing our talloc magic, which would then allow an
+ * attacker to prepare a valid header and so run a destructor.
+ *
+ * What else? We have to re-stamp back a valid normal magic
+ * on this memory once realloc() is done, as it will have done
+ * a memcpy() into the new valid memory. We can't do this in
+ * reverse as that would be a real use-after-free.
+ */
+ _talloc_chunk_set_free(tc, NULL);
+
+ if (pool_hdr) {
+ struct talloc_chunk *pool_tc;
+ void *next_tc = tc_next_chunk(tc);
+ size_t old_chunk_size = TC_ALIGN16(TC_HDR_SIZE + tc->size);
+ size_t new_chunk_size = TC_ALIGN16(TC_HDR_SIZE + size);
+ size_t space_needed;
+ size_t space_left;
+ unsigned int chunk_count = pool_hdr->object_count;
+
+ pool_tc = talloc_chunk_from_pool(pool_hdr);
+ if (!(pool_tc->flags & TALLOC_FLAG_FREE)) {
+ chunk_count -= 1;
+ }
+
+ if (chunk_count == 1) {
+ /*
+ * optimize for the case where 'tc' is the only
+ * chunk in the pool.
+ */
+ char *start = tc_pool_first_chunk(pool_hdr);
+ space_needed = new_chunk_size;
+ space_left = (char *)tc_pool_end(pool_hdr) - start;
+
+ if (space_left >= space_needed) {
+ size_t old_used = TC_HDR_SIZE + tc->size;
+ size_t new_used = TC_HDR_SIZE + size;
+ new_ptr = start;
+
+#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
+ {
+ /*
+ * The area from
+ * start -> tc may have
+ * been freed and thus been marked as
+ * VALGRIND_MEM_NOACCESS. Set it to
+ * VALGRIND_MEM_UNDEFINED so we can
+ * copy into it without valgrind errors.
+ * We can't just mark
+ * new_ptr -> new_ptr + old_used
+ * as this may overlap on top of tc,
+ * (which is why we use memmove, not
+ * memcpy below) hence the MIN.
+ */
+ size_t undef_len = MIN((((char *)tc) - ((char *)new_ptr)),old_used);
+ VALGRIND_MAKE_MEM_UNDEFINED(new_ptr, undef_len);
+ }
+#endif
+
+ memmove(new_ptr, tc, old_used);
+
+ tc = (struct talloc_chunk *)new_ptr;
+ TC_UNDEFINE_GROW_CHUNK(tc, size);
+
+ /*
+ * first we do not align the pool pointer
+ * because we want to invalidate the padding
+ * too.
+ */
+ pool_hdr->end = new_used + (char *)new_ptr;
+ tc_invalidate_pool(pool_hdr);
+
+ /* now the aligned pointer */
+ pool_hdr->end = new_chunk_size + (char *)new_ptr;
+ goto got_new_ptr;
+ }
+
+ next_tc = NULL;
+ }
+
+ if (new_chunk_size == old_chunk_size) {
+ TC_UNDEFINE_GROW_CHUNK(tc, size);
+ _talloc_chunk_set_not_free(tc);
+ tc->size = size;
+ return ptr;
+ }
+
+ if (next_tc == pool_hdr->end) {
+ /*
+ * optimize for the case where 'tc' is the last
+ * chunk in the pool.
+ */
+ space_needed = new_chunk_size - old_chunk_size;
+ space_left = tc_pool_space_left(pool_hdr);
+
+ if (space_left >= space_needed) {
+ TC_UNDEFINE_GROW_CHUNK(tc, size);
+ _talloc_chunk_set_not_free(tc);
+ tc->size = size;
+ pool_hdr->end = tc_next_chunk(tc);
+ return ptr;
+ }
+ }
+
+ new_ptr = tc_alloc_pool(tc, size + TC_HDR_SIZE, 0);
+
+ if (new_ptr == NULL) {
+ /*
+ * Couldn't allocate from pool (pool size
+ * counts as already allocated for memlimit
+ * purposes). We must check memory limit
+ * before any real malloc.
+ */
+ if (tc->limit) {
+ /*
+ * Note we're doing an extra malloc,
+ * on top of the pool size, so account
+ * for size only, not the difference
+ * between old and new size.
+ */
+ if (!talloc_memlimit_check(tc->limit, size)) {
+ _talloc_chunk_set_not_free(tc);
+ errno = ENOMEM;
+ return NULL;
+ }
+ }
+ new_ptr = malloc(TC_HDR_SIZE+size);
+ malloced = true;
+ new_size = size;
+ }
+
+ if (new_ptr) {
+ memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
+
+ _tc_free_poolmem(tc, __location__ "_talloc_realloc");
+ }
+ }
+ else {
+ /* We're doing realloc here, so record the difference. */
+ old_size = tc->size;
+ new_size = size;
+ /*
+ * We must check memory limit
+ * before any real realloc.
+ */
+ if (tc->limit && (size > old_size)) {
+ if (!talloc_memlimit_check(tc->limit,
+ (size - old_size))) {
+ _talloc_chunk_set_not_free(tc);
+ errno = ENOMEM;
+ return NULL;
+ }
+ }
+ new_ptr = realloc(tc, size + TC_HDR_SIZE);
+ }
+got_new_ptr:
+
+ if (unlikely(!new_ptr)) {
+ /*
+ * Ok, this is a strange spot. We have to put back
+ * the old talloc_magic and any flags, except the
+ * TALLOC_FLAG_FREE as this was not free'ed by the
+ * realloc() call after all
+ */
+ _talloc_chunk_set_not_free(tc);
+ return NULL;
+ }
+
+ /*
+ * tc is now the new value from realloc(), the old memory we
+ * can't access any more and was preemptively marked as
+ * TALLOC_FLAG_FREE before the call. Now we mark it as not
+ * free again
+ */
+ tc = (struct talloc_chunk *)new_ptr;
+ _talloc_chunk_set_not_free(tc);
+ if (malloced) {
+ tc->flags &= ~TALLOC_FLAG_POOLMEM;
+ }
+ if (tc->parent) {
+ tc->parent->child = tc;
+ }
+ if (tc->child) {
+ tc->child->parent = tc;
+ }
+
+ if (tc->prev) {
+ tc->prev->next = tc;
+ }
+ if (tc->next) {
+ tc->next->prev = tc;
+ }
+
+ if (new_size > old_size) {
+ talloc_memlimit_grow(tc->limit, new_size - old_size);
+ } else if (new_size < old_size) {
+ talloc_memlimit_shrink(tc->limit, old_size - new_size);
+ }
+
+ tc->size = size;
+ _tc_set_name_const(tc, name);
+
+ return TC_PTR_FROM_CHUNK(tc);
+}
+
+/*
+ a wrapper around talloc_steal() for situations where you are moving a pointer
+ between two structures, and want the old pointer to be set to NULL
+*/
+_PUBLIC_ void *_talloc_move(const void *new_ctx, const void *_pptr)
+{
+ const void **pptr = discard_const_p(const void *,_pptr);
+ void *ret = talloc_steal(new_ctx, discard_const_p(void, *pptr));
+ (*pptr) = NULL;
+ return ret;
+}
+
+enum talloc_mem_count_type {
+ TOTAL_MEM_SIZE,
+ TOTAL_MEM_BLOCKS,
+ TOTAL_MEM_LIMIT,
+};
+
+static inline size_t _talloc_total_mem_internal(const void *ptr,
+ enum talloc_mem_count_type type,
+ struct talloc_memlimit *old_limit,
+ struct talloc_memlimit *new_limit)
+{
+ size_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);
+
+ if (old_limit || new_limit) {
+ if (tc->limit && tc->limit->upper == old_limit) {
+ tc->limit->upper = new_limit;
+ }
+ }
+
+ /* optimize in the memlimits case */
+ if (type == TOTAL_MEM_LIMIT &&
+ tc->limit != NULL &&
+ tc->limit != old_limit &&
+ tc->limit->parent == tc) {
+ return tc->limit->cur_size;
+ }
+
+ if (tc->flags & TALLOC_FLAG_LOOP) {
+ return 0;
+ }
+
+ tc->flags |= TALLOC_FLAG_LOOP;
+
+ if (old_limit || new_limit) {
+ if (old_limit == tc->limit) {
+ tc->limit = new_limit;
+ }
+ }
+
+ switch (type) {
+ case TOTAL_MEM_SIZE:
+ if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
+ total = tc->size;
+ }
+ break;
+ case TOTAL_MEM_BLOCKS:
+ total++;
+ break;
+ case TOTAL_MEM_LIMIT:
+ if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
+ /*
+ * Don't count memory allocated from a pool
+ * when calculating limits. Only count the
+ * pool itself.
+ */
+ if (!(tc->flags & TALLOC_FLAG_POOLMEM)) {
+ if (tc->flags & TALLOC_FLAG_POOL) {
+ /*
+ * If this is a pool, the allocated
+ * size is in the pool header, and
+ * remember to add in the prefix
+ * length.
+ */
+ struct talloc_pool_hdr *pool_hdr
+ = talloc_pool_from_chunk(tc);
+ total = pool_hdr->poolsize +
+ TC_HDR_SIZE +
+ TP_HDR_SIZE;
+ } else {
+ total = tc->size + TC_HDR_SIZE;
+ }
+ }
+ }
+ break;
+ }
+ for (c = tc->child; c; c = c->next) {
+ total += _talloc_total_mem_internal(TC_PTR_FROM_CHUNK(c), type,
+ old_limit, new_limit);
+ }
+
+ tc->flags &= ~TALLOC_FLAG_LOOP;
+
+ return total;
+}
+
+/*
+ return the total size of a talloc pool (subtree)
+*/
+_PUBLIC_ size_t talloc_total_size(const void *ptr)
+{
+ return _talloc_total_mem_internal(ptr, TOTAL_MEM_SIZE, NULL, NULL);
+}
+
+/*
+ return the total number of blocks in a talloc pool (subtree)
+*/
+_PUBLIC_ size_t talloc_total_blocks(const void *ptr)
+{
+ return _talloc_total_mem_internal(ptr, TOTAL_MEM_BLOCKS, NULL, NULL);
+}
+
+/*
+ return the number of external references to a pointer
+*/
+_PUBLIC_ size_t talloc_reference_count(const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ struct talloc_reference_handle *h;
+ size_t 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
+*/
+_PUBLIC_ void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
+ void (*callback)(const void *ptr,
+ int depth, int max_depth,
+ int is_ref,
+ void *private_data),
+ void *private_data)
+{
+ struct talloc_chunk *c, *tc;
+
+ if (ptr == NULL) {
+ ptr = null_context;
+ }
+ if (ptr == NULL) return;
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ if (tc->flags & TALLOC_FLAG_LOOP) {
+ return;
+ }
+
+ callback(ptr, depth, max_depth, 0, private_data);
+
+ if (max_depth >= 0 && depth >= max_depth) {
+ return;
+ }
+
+ tc->flags |= TALLOC_FLAG_LOOP;
+ for (c=tc->child;c;c=c->next) {
+ if (c->name == TALLOC_MAGIC_REFERENCE) {
+ struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
+ callback(h->ptr, depth + 1, max_depth, 1, private_data);
+ } else {
+ talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
+ }
+ }
+ tc->flags &= ~TALLOC_FLAG_LOOP;
+}
+
+static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
+{
+ const char *name = __talloc_get_name(ptr);
+ struct talloc_chunk *tc;
+ FILE *f = (FILE *)_f;
+
+ if (is_ref) {
+ fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
+ return;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+ if (tc->limit && tc->limit->parent == tc) {
+ fprintf(f, "%*s%-30s is a memlimit context"
+ " (max_size = %lu bytes, cur_size = %lu bytes)\n",
+ depth*4, "",
+ name,
+ (unsigned long)tc->limit->max_size,
+ (unsigned long)tc->limit->cur_size);
+ }
+
+ if (depth == 0) {
+ fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
+ (max_depth < 0 ? "full " :""), name,
+ (unsigned long)talloc_total_size(ptr),
+ (unsigned long)talloc_total_blocks(ptr));
+ return;
+ }
+
+ fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n",
+ depth*4, "",
+ name,
+ (unsigned long)talloc_total_size(ptr),
+ (unsigned long)talloc_total_blocks(ptr),
+ (int)talloc_reference_count(ptr), ptr);
+
+#if 0
+ fprintf(f, "content: ");
+ if (talloc_total_size(ptr)) {
+ int tot = talloc_total_size(ptr);
+ int i;
+
+ for (i = 0; i < tot; i++) {
+ if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
+ fprintf(f, "%c", ((char *)ptr)[i]);
+ } else {
+ fprintf(f, "~%02x", ((char *)ptr)[i]);
+ }
+ }
+ }
+ fprintf(f, "\n");
+#endif
+}
+
+/*
+ report on memory usage by all children of a pointer, giving a full tree view
+*/
+_PUBLIC_ void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
+{
+ if (f) {
+ talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
+ fflush(f);
+ }
+}
+
+/*
+ report on memory usage by all children of a pointer, giving a full tree view
+*/
+_PUBLIC_ void talloc_report_full(const void *ptr, FILE *f)
+{
+ talloc_report_depth_file(ptr, 0, -1, f);
+}
+
+/*
+ report on memory usage by all children of a pointer
+*/
+_PUBLIC_ void talloc_report(const void *ptr, FILE *f)
+{
+ talloc_report_depth_file(ptr, 0, 1, f);
+}
+
+/*
+ enable tracking of the NULL context
+*/
+_PUBLIC_ void talloc_enable_null_tracking(void)
+{
+ if (null_context == NULL) {
+ null_context = _talloc_named_const(NULL, 0, "null_context");
+ if (autofree_context != NULL) {
+ talloc_reparent(NULL, null_context, autofree_context);
+ }
+ }
+}
+
+/*
+ enable tracking of the NULL context, not moving the autofree context
+ into the NULL context. This is needed for the talloc testsuite
+*/
+_PUBLIC_ void talloc_enable_null_tracking_no_autofree(void)
+{
+ if (null_context == NULL) {
+ null_context = _talloc_named_const(NULL, 0, "null_context");
+ }
+}
+
+/*
+ disable tracking of the NULL context
+*/
+_PUBLIC_ void talloc_disable_null_tracking(void)
+{
+ if (null_context != NULL) {
+ /* we have to move any children onto the real NULL
+ context */
+ struct talloc_chunk *tc, *tc2;
+ tc = talloc_chunk_from_ptr(null_context);
+ for (tc2 = tc->child; tc2; tc2=tc2->next) {
+ if (tc2->parent == tc) tc2->parent = NULL;
+ if (tc2->prev == tc) tc2->prev = NULL;
+ }
+ for (tc2 = tc->next; tc2; tc2=tc2->next) {
+ if (tc2->parent == tc) tc2->parent = NULL;
+ if (tc2->prev == tc) tc2->prev = NULL;
+ }
+ tc->child = NULL;
+ tc->next = NULL;
+ }
+ talloc_free(null_context);
+ null_context = NULL;
+}
+
+/*
+ enable leak reporting on exit
+*/
+_PUBLIC_ void talloc_enable_leak_report(void)
+{
+ talloc_enable_null_tracking();
+ talloc_report_null = true;
+ talloc_setup_atexit();
+}
+
+/*
+ enable full leak reporting on exit
+*/
+_PUBLIC_ void talloc_enable_leak_report_full(void)
+{
+ talloc_enable_null_tracking();
+ talloc_report_null_full = true;
+ talloc_setup_atexit();
+}
+
+/*
+ talloc and zero memory.
+*/
+_PUBLIC_ 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.
+*/
+_PUBLIC_ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
+{
+ void *newp = NULL;
+
+ if (likely(size > 0) && unlikely(p == NULL)) {
+ return NULL;
+ }
+
+ newp = _talloc_named_const(t, size, name);
+ if (likely(newp != NULL) && likely(size > 0)) {
+ memcpy(newp, p, size);
+ }
+
+ return newp;
+}
+
+static inline char *__talloc_strlendup(const void *t, const char *p, size_t len)
+{
+ char *ret;
+ struct talloc_chunk *tc = NULL;
+
+ ret = (char *)__talloc(t, len + 1, &tc);
+ if (unlikely(!ret)) return NULL;
+
+ memcpy(ret, p, len);
+ ret[len] = 0;
+
+ _tc_set_name_const(tc, ret);
+ return ret;
+}
+
+/*
+ strdup with a talloc
+*/
+_PUBLIC_ char *talloc_strdup(const void *t, const char *p)
+{
+ if (unlikely(!p)) return NULL;
+ return __talloc_strlendup(t, p, strlen(p));
+}
+
+/*
+ strndup with a talloc
+*/
+_PUBLIC_ char *talloc_strndup(const void *t, const char *p, size_t n)
+{
+ if (unlikely(!p)) return NULL;
+ return __talloc_strlendup(t, p, strnlen(p, n));
+}
+
+static inline char *__talloc_strlendup_append(char *s, size_t slen,
+ const char *a, size_t alen)
+{
+ char *ret;
+
+ ret = talloc_realloc(NULL, s, char, slen + alen + 1);
+ if (unlikely(!ret)) return NULL;
+
+ /* append the string and the trailing \0 */
+ memcpy(&ret[slen], a, alen);
+ ret[slen+alen] = 0;
+
+ _tc_set_name_const(talloc_chunk_from_ptr(ret), ret);
+ return ret;
+}
+
+/*
+ * Appends at the end of the string.
+ */
+_PUBLIC_ char *talloc_strdup_append(char *s, const char *a)
+{
+ if (unlikely(!s)) {
+ return talloc_strdup(NULL, a);
+ }
+
+ if (unlikely(!a)) {
+ return s;
+ }
+
+ return __talloc_strlendup_append(s, strlen(s), a, strlen(a));
+}
+
+/*
+ * Appends at the end of the talloc'ed buffer,
+ * not the end of the string.
+ */
+_PUBLIC_ char *talloc_strdup_append_buffer(char *s, const char *a)
+{
+ size_t slen;
+
+ if (unlikely(!s)) {
+ return talloc_strdup(NULL, a);
+ }
+
+ if (unlikely(!a)) {
+ return s;
+ }
+
+ slen = talloc_get_size(s);
+ if (likely(slen > 0)) {
+ slen--;
+ }
+
+ return __talloc_strlendup_append(s, slen, a, strlen(a));
+}
+
+/*
+ * Appends at the end of the string.
+ */
+_PUBLIC_ char *talloc_strndup_append(char *s, const char *a, size_t n)
+{
+ if (unlikely(!s)) {
+ return talloc_strndup(NULL, a, n);
+ }
+
+ if (unlikely(!a)) {
+ return s;
+ }
+
+ return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n));
+}
+
+/*
+ * Appends at the end of the talloc'ed buffer,
+ * not the end of the string.
+ */
+_PUBLIC_ char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)
+{
+ size_t slen;
+
+ if (unlikely(!s)) {
+ return talloc_strndup(NULL, a, n);
+ }
+
+ if (unlikely(!a)) {
+ return s;
+ }
+
+ slen = talloc_get_size(s);
+ if (likely(slen > 0)) {
+ slen--;
+ }
+
+ return __talloc_strlendup_append(s, slen, a, strnlen(a, n));
+}
+
+#ifndef HAVE_VA_COPY
+#ifdef HAVE___VA_COPY
+#define va_copy(dest, src) __va_copy(dest, src)
+#else
+#define va_copy(dest, src) (dest) = (src)
+#endif
+#endif
+
+static struct talloc_chunk *_vasprintf_tc(const void *t,
+ const char *fmt,
+ va_list ap) PRINTF_ATTRIBUTE(2,0);
+
+static struct talloc_chunk *_vasprintf_tc(const void *t,
+ const char *fmt,
+ va_list ap)
+{
+ int vlen;
+ size_t len;
+ char *ret;
+ va_list ap2;
+ struct talloc_chunk *tc = NULL;
+ char buf[1024];
+
+ /* this call looks strange, but it makes it work on older solaris boxes */
+ va_copy(ap2, ap);
+ vlen = vsnprintf(buf, sizeof(buf), fmt, ap2);
+ va_end(ap2);
+ if (unlikely(vlen < 0)) {
+ return NULL;
+ }
+ len = vlen;
+ if (unlikely(len + 1 < len)) {
+ return NULL;
+ }
+
+ ret = (char *)__talloc(t, len+1, &tc);
+ if (unlikely(!ret)) return NULL;
+
+ if (len < sizeof(buf)) {
+ memcpy(ret, buf, len+1);
+ } else {
+ va_copy(ap2, ap);
+ vsnprintf(ret, len+1, fmt, ap2);
+ va_end(ap2);
+ }
+
+ _tc_set_name_const(tc, ret);
+ return tc;
+}
+
+_PUBLIC_ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
+{
+ struct talloc_chunk *tc = _vasprintf_tc(t, fmt, ap);
+ if (tc == NULL) {
+ return NULL;
+ }
+ return TC_PTR_FROM_CHUNK(tc);
+}
+
+
+/*
+ Perform string formatting, and return a pointer to newly allocated
+ memory holding the result, inside a memory pool.
+ */
+_PUBLIC_ 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;
+}
+
+static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
+ const char *fmt, va_list ap)
+ PRINTF_ATTRIBUTE(3,0);
+
+static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
+ const char *fmt, va_list ap)
+{
+ ssize_t alen;
+ va_list ap2;
+ char c;
+
+ va_copy(ap2, ap);
+ alen = vsnprintf(&c, 1, fmt, ap2);
+ va_end(ap2);
+
+ if (alen <= 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, slen + alen + 1);
+ if (!s) return NULL;
+
+ va_copy(ap2, ap);
+ vsnprintf(s + slen, alen + 1, fmt, ap2);
+ va_end(ap2);
+
+ _tc_set_name_const(talloc_chunk_from_ptr(s), s);
+ return s;
+}
+
+/**
+ * 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. Appends at the end
+ * of the string.
+ **/
+_PUBLIC_ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
+{
+ if (unlikely(!s)) {
+ return talloc_vasprintf(NULL, fmt, ap);
+ }
+
+ return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap);
+}
+
+/**
+ * Realloc @p s to append the formatted result of @p fmt and @p ap,
+ * and return @p s, which may have moved. Always appends at the
+ * end of the talloc'ed buffer, not the end of the string.
+ **/
+_PUBLIC_ char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)
+{
+ size_t slen;
+
+ if (unlikely(!s)) {
+ return talloc_vasprintf(NULL, fmt, ap);
+ }
+
+ slen = talloc_get_size(s);
+ if (likely(slen > 0)) {
+ slen--;
+ }
+
+ return __talloc_vaslenprintf_append(s, slen, fmt, ap);
+}
+
+/*
+ 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.
+ */
+_PUBLIC_ 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;
+}
+
+/*
+ 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 buffer.
+ */
+_PUBLIC_ char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ s = talloc_vasprintf_append_buffer(s, fmt, ap);
+ va_end(ap);
+ return s;
+}
+
+_PUBLIC_ void talloc_asprintf_addbuf(char **ps, const char *fmt, ...)
+{
+ va_list ap;
+ char *s = *ps;
+ char *t = NULL;
+
+ if (s == NULL) {
+ return;
+ }
+
+ va_start(ap, fmt);
+ t = talloc_vasprintf_append_buffer(s, fmt, ap);
+ va_end(ap);
+
+ if (t == NULL) {
+ /* signal failure to the next caller */
+ TALLOC_FREE(s);
+ *ps = NULL;
+ } else {
+ *ps = t;
+ }
+}
+
+/*
+ alloc an array, checking for integer overflow in the array size
+*/
+_PUBLIC_ 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
+*/
+_PUBLIC_ 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
+*/
+_PUBLIC_ 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)
+*/
+_PUBLIC_ void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
+{
+ return _talloc_realloc(context, ptr, size, NULL);
+}
+
+
+static int talloc_autofree_destructor(void *ptr)
+{
+ autofree_context = NULL;
+ return 0;
+}
+
+/*
+ return a context which will be auto-freed on exit
+ this is useful for reducing the noise in leak reports
+*/
+_PUBLIC_ void *talloc_autofree_context(void)
+{
+ if (autofree_context == NULL) {
+ autofree_context = _talloc_named_const(NULL, 0, "autofree_context");
+ talloc_set_destructor(autofree_context, talloc_autofree_destructor);
+ talloc_setup_atexit();
+ }
+ return autofree_context;
+}
+
+_PUBLIC_ 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;
+}
+
+/*
+ find a parent of this context that has the given name, if any
+*/
+_PUBLIC_ void *talloc_find_parent_byname(const void *context, const char *name)
+{
+ 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;
+ if (tc) {
+ tc = tc->parent;
+ }
+ }
+ return NULL;
+}
+
+/*
+ show the parentage of a context
+*/
+_PUBLIC_ 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;
+ if (tc) {
+ tc = tc->parent;
+ }
+ }
+ fflush(file);
+}
+
+/*
+ return 1 if ptr is a parent of context
+*/
+static int _talloc_is_parent(const void *context, const void *ptr, int depth)
+{
+ struct talloc_chunk *tc;
+
+ if (context == NULL) {
+ return 0;
+ }
+
+ tc = talloc_chunk_from_ptr(context);
+ while (tc) {
+ if (depth <= 0) {
+ return 0;
+ }
+ if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
+ while (tc && tc->prev) tc = tc->prev;
+ if (tc) {
+ tc = tc->parent;
+ depth--;
+ }
+ }
+ return 0;
+}
+
+/*
+ return 1 if ptr is a parent of context
+*/
+_PUBLIC_ int talloc_is_parent(const void *context, const void *ptr)
+{
+ return _talloc_is_parent(context, ptr, TALLOC_MAX_DEPTH);
+}
+
+/*
+ return the total size of memory used by this context and all children
+*/
+static inline size_t _talloc_total_limit_size(const void *ptr,
+ struct talloc_memlimit *old_limit,
+ struct talloc_memlimit *new_limit)
+{
+ return _talloc_total_mem_internal(ptr, TOTAL_MEM_LIMIT,
+ old_limit, new_limit);
+}
+
+static inline bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size)
+{
+ struct talloc_memlimit *l;
+
+ for (l = limit; l != NULL; l = l->upper) {
+ if (l->max_size != 0 &&
+ ((l->max_size <= l->cur_size) ||
+ (l->max_size - l->cur_size < size))) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*
+ Update memory limits when freeing a talloc_chunk.
+*/
+static void tc_memlimit_update_on_free(struct talloc_chunk *tc)
+{
+ size_t limit_shrink_size;
+
+ if (!tc->limit) {
+ return;
+ }
+
+ /*
+ * Pool entries don't count. Only the pools
+ * themselves are counted as part of the memory
+ * limits. Note that this also takes care of
+ * nested pools which have both flags
+ * TALLOC_FLAG_POOLMEM|TALLOC_FLAG_POOL set.
+ */
+ if (tc->flags & TALLOC_FLAG_POOLMEM) {
+ return;
+ }
+
+ /*
+ * If we are part of a memory limited context hierarchy
+ * we need to subtract the memory used from the counters
+ */
+
+ limit_shrink_size = tc->size+TC_HDR_SIZE;
+
+ /*
+ * If we're deallocating a pool, take into
+ * account the prefix size added for the pool.
+ */
+
+ if (tc->flags & TALLOC_FLAG_POOL) {
+ limit_shrink_size += TP_HDR_SIZE;
+ }
+
+ talloc_memlimit_shrink(tc->limit, limit_shrink_size);
+
+ if (tc->limit->parent == tc) {
+ free(tc->limit);
+ }
+
+ tc->limit = NULL;
+}
+
+/*
+ Increase memory limit accounting after a malloc/realloc.
+*/
+static void talloc_memlimit_grow(struct talloc_memlimit *limit,
+ size_t size)
+{
+ struct talloc_memlimit *l;
+
+ for (l = limit; l != NULL; l = l->upper) {
+ size_t new_cur_size = l->cur_size + size;
+ if (new_cur_size < l->cur_size) {
+ talloc_abort("logic error in talloc_memlimit_grow\n");
+ return;
+ }
+ l->cur_size = new_cur_size;
+ }
+}
+
+/*
+ Decrease memory limit accounting after a free/realloc.
+*/
+static void talloc_memlimit_shrink(struct talloc_memlimit *limit,
+ size_t size)
+{
+ struct talloc_memlimit *l;
+
+ for (l = limit; l != NULL; l = l->upper) {
+ if (l->cur_size < size) {
+ talloc_abort("logic error in talloc_memlimit_shrink\n");
+ return;
+ }
+ l->cur_size = l->cur_size - size;
+ }
+}
+
+_PUBLIC_ int talloc_set_memlimit(const void *ctx, size_t max_size)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ctx);
+ struct talloc_memlimit *orig_limit;
+ struct talloc_memlimit *limit = NULL;
+
+ if (tc->limit && tc->limit->parent == tc) {
+ tc->limit->max_size = max_size;
+ return 0;
+ }
+ orig_limit = tc->limit;
+
+ limit = malloc(sizeof(struct talloc_memlimit));
+ if (limit == NULL) {
+ return 1;
+ }
+ limit->parent = tc;
+ limit->max_size = max_size;
+ limit->cur_size = _talloc_total_limit_size(ctx, tc->limit, limit);
+
+ if (orig_limit) {
+ limit->upper = orig_limit;
+ } else {
+ limit->upper = NULL;
+ }
+
+ return 0;
+}
diff --git a/lib/talloc/talloc.h b/lib/talloc/talloc.h
new file mode 100644
index 0000000..c466c36
--- /dev/null
+++ b/lib/talloc/talloc.h
@@ -0,0 +1,1972 @@
+#ifndef _TALLOC_H_
+#define _TALLOC_H_
+/*
+ Unix SMB/CIFS implementation.
+ Samba temporary memory allocation functions
+
+ Copyright (C) Andrew Tridgell 2004-2005
+ Copyright (C) Stefan Metzmacher 2006
+
+ ** 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 3 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
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* for old gcc releases that don't have the feature test macro __has_attribute */
+#ifndef __has_attribute
+#define __has_attribute(x) 0
+#endif
+
+#ifndef _PUBLIC_
+#if __has_attribute(visibility)
+#define _PUBLIC_ __attribute__((visibility("default")))
+#else
+#define _PUBLIC_
+#endif
+#endif
+
+/**
+ * @defgroup talloc The talloc API
+ *
+ * talloc is a hierarchical, reference counted memory pool system with
+ * destructors. It is the core memory allocator used in Samba.
+ *
+ * @{
+ */
+
+#define TALLOC_VERSION_MAJOR 2
+#define TALLOC_VERSION_MINOR 4
+
+_PUBLIC_ int talloc_version_major(void);
+_PUBLIC_ int talloc_version_minor(void);
+/* This is mostly useful only for testing */
+_PUBLIC_ int talloc_test_get_magic(void);
+
+/**
+ * @brief Define a talloc parent type
+ *
+ * As talloc is a hierarchial memory allocator, every talloc chunk is a
+ * potential parent to other talloc chunks. So defining a separate type for a
+ * talloc chunk is not strictly necessary. TALLOC_CTX is defined nevertheless,
+ * as it provides an indicator for function arguments. You will frequently
+ * write code like
+ *
+ * @code
+ * struct foo *foo_create(TALLOC_CTX *mem_ctx)
+ * {
+ * struct foo *result;
+ * result = talloc(mem_ctx, struct foo);
+ * if (result == NULL) return NULL;
+ * ... initialize foo ...
+ * return result;
+ * }
+ * @endcode
+ *
+ * In this type of allocating functions it is handy to have a general
+ * TALLOC_CTX type to indicate which parent to put allocated structures on.
+ */
+typedef void TALLOC_CTX;
+
+/*
+ this uses a little trick to allow __LINE__ to be stringified
+*/
+#ifndef __location__
+#define __TALLOC_STRING_LINE1__(s) #s
+#define __TALLOC_STRING_LINE2__(s) __TALLOC_STRING_LINE1__(s)
+#define __TALLOC_STRING_LINE3__ __TALLOC_STRING_LINE2__(__LINE__)
+#define __location__ __FILE__ ":" __TALLOC_STRING_LINE3__
+#endif
+
+#ifndef TALLOC_DEPRECATED
+#define TALLOC_DEPRECATED 0
+#endif
+
+#ifndef PRINTF_ATTRIBUTE
+#if __has_attribute(format) || (__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
+
+#ifndef _DEPRECATED_
+#if __has_attribute(deprecated) || (__GNUC__ >= 3)
+#define _DEPRECATED_ __attribute__ ((deprecated))
+#else
+#define _DEPRECATED_
+#endif
+#endif
+#ifdef DOXYGEN
+
+/**
+ * @brief Create a new talloc context.
+ *
+ * The talloc() macro is the core of the talloc library. It takes a memory
+ * context and a type, and returns a pointer to a new area of memory of the
+ * given type.
+ *
+ * The returned pointer is itself a talloc context, so you can use it as the
+ * context argument to more calls to talloc if you wish.
+ *
+ * The returned pointer is a "child" of the supplied context. This means that if
+ * you talloc_free() the context then the new child disappears as well.
+ * Alternatively you can free just the child.
+ *
+ * @param[in] ctx A talloc context to create a new reference on or NULL to
+ * create a new top level context.
+ *
+ * @param[in] type The type of memory to allocate.
+ *
+ * @return A type casted talloc context or NULL on error.
+ *
+ * @code
+ * unsigned int *a, *b;
+ *
+ * a = talloc(NULL, unsigned int);
+ * b = talloc(a, unsigned int);
+ * @endcode
+ *
+ * @see talloc_zero
+ * @see talloc_array
+ * @see talloc_steal
+ * @see talloc_free
+ */
+_PUBLIC_ void *talloc(const void *ctx, #type);
+#else
+#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type)
+_PUBLIC_ void *_talloc(const void *context, size_t size);
+#endif
+
+/**
+ * @brief Create a new top level talloc context.
+ *
+ * This function creates a zero length named talloc context as a top level
+ * context. It is equivalent to:
+ *
+ * @code
+ * talloc_named(NULL, 0, fmt, ...);
+ * @endcode
+ * @param[in] fmt Format string for the name.
+ *
+ * @param[in] ... Additional printf-style arguments.
+ *
+ * @return The allocated memory chunk, NULL on error.
+ *
+ * @see talloc_named()
+ */
+_PUBLIC_ void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
+
+#ifdef DOXYGEN
+/**
+ * @brief Free a chunk of talloc memory.
+ *
+ * The talloc_free() function frees a piece of talloc memory, and all its
+ * children. You can call talloc_free() on any pointer returned by
+ * talloc().
+ *
+ * The return value of talloc_free() indicates success or failure, with 0
+ * returned for success and -1 for failure. A possible failure condition
+ * is if the pointer had a destructor attached to it and the destructor
+ * returned -1. See talloc_set_destructor() for details on
+ * destructors. Likewise, if "ptr" is NULL, then the function will make
+ * no modifications and return -1.
+ *
+ * From version 2.0 and onwards, as a special case, talloc_free() is
+ * refused on pointers that have more than one parent associated, as talloc
+ * would have no way of knowing which parent should be removed. This is
+ * different from older versions in the sense that always the reference to
+ * the most recently established parent has been destroyed. Hence to free a
+ * pointer that has more than one parent please use talloc_unlink().
+ *
+ * To help you find problems in your code caused by this behaviour, if
+ * you do try and free a pointer with more than one parent then the
+ * talloc logging function will be called to give output like this:
+ *
+ * @code
+ * ERROR: talloc_free with references at some_dir/source/foo.c:123
+ * reference at some_dir/source/other.c:325
+ * reference at some_dir/source/third.c:121
+ * @endcode
+ *
+ * Please see the documentation for talloc_set_log_fn() and
+ * talloc_set_log_stderr() for more information on talloc logging
+ * functions.
+ *
+ * If <code>TALLOC_FREE_FILL</code> environment variable is set,
+ * the memory occupied by the context is filled with the value of this variable.
+ * The value should be a numeric representation of the character you want to
+ * use.
+ *
+ * talloc_free() operates recursively on its children.
+ *
+ * @param[in] ptr The chunk to be freed.
+ *
+ * @return Returns 0 on success and -1 on error. A possible
+ * failure condition is if the pointer had a destructor
+ * attached to it and the destructor returned -1. Likewise,
+ * if "ptr" is NULL, then the function will make no
+ * modifications and returns -1.
+ *
+ * Example:
+ * @code
+ * unsigned int *a, *b;
+ * a = talloc(NULL, unsigned int);
+ * b = talloc(a, unsigned int);
+ *
+ * talloc_free(a); // Frees a and b
+ * @endcode
+ *
+ * @see talloc_set_destructor()
+ * @see talloc_unlink()
+ */
+_PUBLIC_ int talloc_free(void *ptr);
+#else
+#define talloc_free(ctx) _talloc_free(ctx, __location__)
+_PUBLIC_ int _talloc_free(void *ptr, const char *location);
+#endif
+
+/**
+ * @brief Free a talloc chunk's children.
+ *
+ * The function walks along the list of all children of a talloc context and
+ * talloc_free()s only the children, not the context itself.
+ *
+ * A NULL argument is handled as no-op.
+ *
+ * @param[in] ptr The chunk that you want to free the children of
+ * (NULL is allowed too)
+ */
+_PUBLIC_ void talloc_free_children(void *ptr);
+
+#ifdef DOXYGEN
+/**
+ * @brief Assign a destructor function to be called when a chunk is freed.
+ *
+ * The function talloc_set_destructor() sets the "destructor" for the pointer
+ * "ptr". A destructor is a function that is called when the memory used by a
+ * pointer is about to be released. The destructor receives the pointer as an
+ * argument, and should return 0 for success and -1 for failure.
+ *
+ * The destructor can do anything it wants to, including freeing other pieces
+ * of memory. A common use for destructors is to clean up operating system
+ * resources (such as open file descriptors) contained in the structure the
+ * destructor is placed on.
+ *
+ * You can only place one destructor on a pointer. If you need more than one
+ * destructor then you can create a zero-length child of the pointer and place
+ * an additional destructor on that.
+ *
+ * To remove a destructor call talloc_set_destructor() with NULL for the
+ * destructor.
+ *
+ * If your destructor attempts to talloc_free() the pointer that it is the
+ * destructor for then talloc_free() will return -1 and the free will be
+ * ignored. This would be a pointless operation anyway, as the destructor is
+ * only called when the memory is just about to go away.
+ *
+ * @param[in] ptr The talloc chunk to add a destructor to.
+ *
+ * @param[in] destructor The destructor function to be called. NULL to remove
+ * it.
+ *
+ * Example:
+ * @code
+ * static int destroy_fd(int *fd) {
+ * close(*fd);
+ * return 0;
+ * }
+ *
+ * int *open_file(const char *filename) {
+ * int *fd = talloc(NULL, int);
+ * *fd = open(filename, O_RDONLY);
+ * if (*fd < 0) {
+ * talloc_free(fd);
+ * return NULL;
+ * }
+ * // Whenever they free this, we close the file.
+ * talloc_set_destructor(fd, destroy_fd);
+ * return fd;
+ * }
+ * @endcode
+ *
+ * @see talloc()
+ * @see talloc_free()
+ */
+_PUBLIC_ void talloc_set_destructor(const void *ptr, int (*destructor)(void *));
+
+/**
+ * @brief Change a talloc chunk's parent.
+ *
+ * The talloc_steal() function changes the parent context of a talloc
+ * pointer. It is typically used when the context that the pointer is
+ * currently a child of is going to be freed and you wish to keep the
+ * memory for a longer time.
+ *
+ * To make the changed hierarchy less error-prone, you might consider to use
+ * talloc_move().
+ *
+ * If you try and call talloc_steal() on a pointer that has more than one
+ * parent then the result is ambiguous. Talloc will choose to remove the
+ * parent that is currently indicated by talloc_parent() and replace it with
+ * the chosen parent. You will also get a message like this via the talloc
+ * logging functions:
+ *
+ * @code
+ * WARNING: talloc_steal with references at some_dir/source/foo.c:123
+ * reference at some_dir/source/other.c:325
+ * reference at some_dir/source/third.c:121
+ * @endcode
+ *
+ * To unambiguously change the parent of a pointer please see the function
+ * talloc_reparent(). See the talloc_set_log_fn() documentation for more
+ * information on talloc logging.
+ *
+ * @param[in] new_ctx The new parent context.
+ *
+ * @param[in] ptr The talloc chunk to move.
+ *
+ * @return Returns the pointer that you pass it. It does not have
+ * any failure modes.
+ *
+ * @note It is possible to produce loops in the parent/child relationship
+ * if you are not careful with talloc_steal(). No guarantees are provided
+ * as to your sanity or the safety of your data if you do this.
+ */
+_PUBLIC_ void *talloc_steal(const void *new_ctx, const void *ptr);
+#else /* DOXYGEN */
+/* try to make talloc_set_destructor() and talloc_steal() type safe,
+ if we have a recent gcc */
+#if (__GNUC__ >= 3)
+#define _TALLOC_TYPEOF(ptr) __typeof__(ptr)
+#define talloc_set_destructor(ptr, function) \
+ do { \
+ int (*_talloc_destructor_fn)(_TALLOC_TYPEOF(ptr)) = (function); \
+ _talloc_set_destructor((ptr), (int (*)(void *))_talloc_destructor_fn); \
+ } while(0)
+/* this extremely strange macro is to avoid some braindamaged warning
+ stupidity in gcc 4.1.x */
+#define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal_loc((ctx),(ptr), __location__); __talloc_steal_ret; })
+#else /* __GNUC__ >= 3 */
+#define talloc_set_destructor(ptr, function) \
+ _talloc_set_destructor((ptr), (int (*)(void *))(function))
+#define _TALLOC_TYPEOF(ptr) void *
+#define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal_loc((ctx),(ptr), __location__)
+#endif /* __GNUC__ >= 3 */
+_PUBLIC_ void _talloc_set_destructor(const void *ptr, int (*_destructor)(void *));
+_PUBLIC_ void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location);
+#endif /* DOXYGEN */
+
+/**
+ * @brief Assign a name to a talloc chunk.
+ *
+ * Each talloc pointer has a "name". The name is used principally for
+ * debugging purposes, although it is also possible to set and get the name on
+ * a pointer in as a way of "marking" pointers in your code.
+ *
+ * The main use for names on pointer is for "talloc reports". See
+ * talloc_report() and talloc_report_full() for details. Also see
+ * talloc_enable_leak_report() and talloc_enable_leak_report_full().
+ *
+ * The talloc_set_name() function allocates memory as a child of the
+ * pointer. It is logically equivalent to:
+ *
+ * @code
+ * talloc_set_name_const(ptr, talloc_asprintf(ptr, fmt, ...));
+ * @endcode
+ *
+ * @param[in] ptr The talloc chunk to assign a name to.
+ *
+ * @param[in] fmt Format string for the name.
+ *
+ * @param[in] ... Add printf-style additional arguments.
+ *
+ * @return The assigned name, NULL on error.
+ *
+ * @note Multiple calls to talloc_set_name() will allocate more memory without
+ * releasing the name. All of the memory is released when the ptr is freed
+ * using talloc_free().
+ */
+_PUBLIC_ const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+
+#ifdef DOXYGEN
+/**
+ * @brief Change a talloc chunk's parent.
+ *
+ * This function has the same effect as talloc_steal(), and additionally sets
+ * the source pointer to NULL. You would use it like this:
+ *
+ * @code
+ * struct foo *X = talloc(tmp_ctx, struct foo);
+ * struct foo *Y;
+ * Y = talloc_move(new_ctx, &X);
+ * @endcode
+ *
+ * @param[in] new_ctx The new parent context.
+ *
+ * @param[in] pptr Pointer to a pointer to the talloc chunk to move.
+ *
+ * @return The pointer to the talloc chunk that moved.
+ * It does not have any failure modes.
+ *
+ */
+_PUBLIC_ void *talloc_move(const void *new_ctx, void **pptr);
+#else
+#define talloc_move(ctx, pptr) (_TALLOC_TYPEOF(*(pptr)))_talloc_move((ctx),(void *)(pptr))
+_PUBLIC_ void *_talloc_move(const void *new_ctx, const void *pptr);
+#endif
+
+/**
+ * @brief Assign a name to a talloc chunk.
+ *
+ * The function is just like talloc_set_name(), but it takes a string constant,
+ * and is much faster. It is extensively used by the "auto naming" macros, such
+ * as talloc_p().
+ *
+ * This function does not allocate any memory. It just copies the supplied
+ * pointer into the internal representation of the talloc ptr. This means you
+ * must not pass a name pointer to memory that will disappear before the ptr
+ * is freed with talloc_free().
+ *
+ * @param[in] ptr The talloc chunk to assign a name to.
+ *
+ * @param[in] name Format string for the name.
+ */
+_PUBLIC_ void talloc_set_name_const(const void *ptr, const char *name);
+
+/**
+ * @brief Create a named talloc chunk.
+ *
+ * The talloc_named() function creates a named talloc pointer. It is
+ * equivalent to:
+ *
+ * @code
+ * ptr = talloc_size(context, size);
+ * talloc_set_name(ptr, fmt, ....);
+ * @endcode
+ *
+ * @param[in] context The talloc context to hang the result off.
+ *
+ * @param[in] size Number of char's that you want to allocate.
+ *
+ * @param[in] fmt Format string for the name.
+ *
+ * @param[in] ... Additional printf-style arguments.
+ *
+ * @return The allocated memory chunk, NULL on error.
+ *
+ * @see talloc_set_name()
+ */
+_PUBLIC_ void *talloc_named(const void *context, size_t size,
+ const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
+
+/**
+ * @brief Basic routine to allocate a chunk of memory.
+ *
+ * This is equivalent to:
+ *
+ * @code
+ * ptr = talloc_size(context, size);
+ * talloc_set_name_const(ptr, name);
+ * @endcode
+ *
+ * @param[in] context The parent context.
+ *
+ * @param[in] size The number of char's that we want to allocate.
+ *
+ * @param[in] name The name the talloc block has.
+ *
+ * @return The allocated memory chunk, NULL on error.
+ */
+_PUBLIC_ void *talloc_named_const(const void *context, size_t size, const char *name);
+
+#ifdef DOXYGEN
+/**
+ * @brief Untyped allocation.
+ *
+ * The function should be used when you don't have a convenient type to pass to
+ * talloc(). Unlike talloc(), it is not type safe (as it returns a void *), so
+ * you are on your own for type checking.
+ *
+ * Best to use talloc() or talloc_array() instead.
+ *
+ * @param[in] ctx The talloc context to hang the result off.
+ *
+ * @param[in] size Number of char's that you want to allocate.
+ *
+ * @return The allocated memory chunk, NULL on error.
+ *
+ * Example:
+ * @code
+ * void *mem = talloc_size(NULL, 100);
+ * @endcode
+ */
+_PUBLIC_ void *talloc_size(const void *ctx, size_t size);
+#else
+#define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Allocate into a typed pointer.
+ *
+ * The talloc_ptrtype() macro should be used when you have a pointer and want
+ * to allocate memory to point at with this pointer. When compiling with
+ * gcc >= 3 it is typesafe. Note this is a wrapper of talloc_size() and
+ * talloc_get_name() will return the current location in the source file and
+ * not the type.
+ *
+ * @param[in] ctx The talloc context to hang the result off.
+ *
+ * @param[in] type The pointer you want to assign the result to.
+ *
+ * @return The properly casted allocated memory chunk, NULL on
+ * error.
+ *
+ * Example:
+ * @code
+ * unsigned int *a = talloc_ptrtype(NULL, a);
+ * @endcode
+ */
+_PUBLIC_ void *talloc_ptrtype(const void *ctx, #type);
+#else
+#define talloc_ptrtype(ctx, ptr) (_TALLOC_TYPEOF(ptr))talloc_size(ctx, sizeof(*(ptr)))
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Allocate a new 0-sized talloc chunk.
+ *
+ * This is a utility macro that creates a new memory context hanging off an
+ * existing context, automatically naming it "talloc_new: __location__" where
+ * __location__ is the source line it is called from. It is particularly
+ * useful for creating a new temporary working context.
+ *
+ * @param[in] ctx The talloc parent context.
+ *
+ * @return A new talloc chunk, NULL on error.
+ */
+_PUBLIC_ void *talloc_new(const void *ctx);
+#else
+#define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Allocate a 0-initizialized structure.
+ *
+ * The macro is equivalent to:
+ *
+ * @code
+ * ptr = talloc(ctx, type);
+ * if (ptr) memset(ptr, 0, sizeof(type));
+ * @endcode
+ *
+ * @param[in] ctx The talloc context to hang the result off.
+ *
+ * @param[in] type The type that we want to allocate.
+ *
+ * @return Pointer to a piece of memory, properly cast to 'type *',
+ * NULL on error.
+ *
+ * Example:
+ * @code
+ * unsigned int *a, *b;
+ * a = talloc_zero(NULL, unsigned int);
+ * b = talloc_zero(a, unsigned int);
+ * @endcode
+ *
+ * @see talloc()
+ * @see talloc_zero_size()
+ * @see talloc_zero_array()
+ */
+_PUBLIC_ void *talloc_zero(const void *ctx, #type);
+
+/**
+ * @brief Allocate untyped, 0-initialized memory.
+ *
+ * @param[in] ctx The talloc context to hang the result off.
+ *
+ * @param[in] size Number of char's that you want to allocate.
+ *
+ * @return The allocated memory chunk.
+ */
+_PUBLIC_ void *talloc_zero_size(const void *ctx, size_t size);
+#else
+#define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type)
+#define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__)
+_PUBLIC_ void *_talloc_zero(const void *ctx, size_t size, const char *name);
+#endif
+
+/**
+ * @brief Return the name of a talloc chunk.
+ *
+ * @param[in] ptr The talloc chunk.
+ *
+ * @return The current name for the given talloc pointer.
+ *
+ * @see talloc_set_name()
+ */
+_PUBLIC_ const char *talloc_get_name(const void *ptr);
+
+/**
+ * @brief Verify that a talloc chunk carries a specified name.
+ *
+ * This function checks if a pointer has the specified name. If it does
+ * then the pointer is returned.
+ *
+ * @param[in] ptr The talloc chunk to check.
+ *
+ * @param[in] name The name to check against.
+ *
+ * @return The pointer if the name matches, NULL if it doesn't.
+ */
+_PUBLIC_ void *talloc_check_name(const void *ptr, const char *name);
+
+/**
+ * @brief Get the parent chunk of a pointer.
+ *
+ * @param[in] ptr The talloc pointer to inspect.
+ *
+ * @return The talloc parent of ptr, NULL on error.
+ */
+_PUBLIC_ void *talloc_parent(const void *ptr);
+
+/**
+ * @brief Get a talloc chunk's parent name.
+ *
+ * @param[in] ptr The talloc pointer to inspect.
+ *
+ * @return The name of ptr's parent chunk.
+ */
+_PUBLIC_ const char *talloc_parent_name(const void *ptr);
+
+/**
+ * @brief Get the total size of a talloc chunk including its children.
+ *
+ * The function returns the total size in bytes used by this pointer and all
+ * child pointers. Mostly useful for debugging.
+ *
+ * Passing NULL is allowed, but it will only give a meaningful result if
+ * talloc_enable_leak_report() or talloc_enable_leak_report_full() has
+ * been called.
+ *
+ * @param[in] ptr The talloc chunk.
+ *
+ * @return The total size.
+ */
+_PUBLIC_ size_t talloc_total_size(const void *ptr);
+
+/**
+ * @brief Get the number of talloc chunks hanging off a chunk.
+ *
+ * The talloc_total_blocks() function returns the total memory block
+ * count used by this pointer and all child pointers. Mostly useful for
+ * debugging.
+ *
+ * Passing NULL is allowed, but it will only give a meaningful result if
+ * talloc_enable_leak_report() or talloc_enable_leak_report_full() has
+ * been called.
+ *
+ * @param[in] ptr The talloc chunk.
+ *
+ * @return The total size.
+ */
+_PUBLIC_ size_t talloc_total_blocks(const void *ptr);
+
+#ifdef DOXYGEN
+/**
+ * @brief Duplicate a memory area into a talloc chunk.
+ *
+ * The function is equivalent to:
+ *
+ * @code
+ * ptr = talloc_size(ctx, size);
+ * if (ptr) memcpy(ptr, p, size);
+ * @endcode
+ *
+ * @param[in] t The talloc context to hang the result off.
+ *
+ * @param[in] p The memory chunk you want to duplicate.
+ *
+ * @param[in] size Number of char's that you want copy.
+ *
+ * @return The allocated memory chunk.
+ *
+ * @see talloc_size()
+ */
+_PUBLIC_ void *talloc_memdup(const void *t, const void *p, size_t size);
+#else
+#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__)
+_PUBLIC_ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name);
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Assign a type to a talloc chunk.
+ *
+ * This macro allows you to force the name of a pointer to be of a particular
+ * type. This can be used in conjunction with talloc_get_type() to do type
+ * checking on void* pointers.
+ *
+ * It is equivalent to this:
+ *
+ * @code
+ * talloc_set_name_const(ptr, #type)
+ * @endcode
+ *
+ * @param[in] ptr The talloc chunk to assign the type to.
+ *
+ * @param[in] type The type to assign.
+ */
+_PUBLIC_ void talloc_set_type(const char *ptr, #type);
+
+/**
+ * @brief Get a typed pointer out of a talloc pointer.
+ *
+ * This macro allows you to do type checking on talloc pointers. It is
+ * particularly useful for void* private pointers. It is equivalent to
+ * this:
+ *
+ * @code
+ * (type *)talloc_check_name(ptr, #type)
+ * @endcode
+ *
+ * @param[in] ptr The talloc pointer to check.
+ *
+ * @param[in] type The type to check against.
+ *
+ * @return The properly casted pointer given by ptr, NULL on error.
+ */
+type *talloc_get_type(const void *ptr, #type);
+#else
+#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type)
+#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Safely turn a void pointer into a typed pointer.
+ *
+ * This macro is used together with talloc(mem_ctx, struct foo). If you had to
+ * assign the talloc chunk pointer to some void pointer variable,
+ * talloc_get_type_abort() is the recommended way to get the convert the void
+ * pointer back to a typed pointer.
+ *
+ * @param[in] ptr The void pointer to convert.
+ *
+ * @param[in] type The type that this chunk contains
+ *
+ * @return The same value as ptr, type-checked and properly cast.
+ */
+_PUBLIC_ void *talloc_get_type_abort(const void *ptr, #type);
+#else
+#ifdef TALLOC_GET_TYPE_ABORT_NOOP
+#define talloc_get_type_abort(ptr, type) (type *)(ptr)
+#else
+#define talloc_get_type_abort(ptr, type) (type *)_talloc_get_type_abort(ptr, #type, __location__)
+#endif
+_PUBLIC_ void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location);
+#endif
+
+/**
+ * @brief Find a parent context by name.
+ *
+ * Find a parent memory context of the current context that has the given
+ * name. This can be very useful in complex programs where it may be
+ * difficult to pass all information down to the level you need, but you
+ * know the structure you want is a parent of another context.
+ *
+ * @param[in] ctx The talloc chunk to start from.
+ *
+ * @param[in] name The name of the parent we look for.
+ *
+ * @return The memory context we are looking for, NULL if not
+ * found.
+ */
+_PUBLIC_ void *talloc_find_parent_byname(const void *ctx, const char *name);
+
+#ifdef DOXYGEN
+/**
+ * @brief Find a parent context by type.
+ *
+ * Find a parent memory context of the current context that has the given
+ * name. This can be very useful in complex programs where it may be
+ * difficult to pass all information down to the level you need, but you
+ * know the structure you want is a parent of another context.
+ *
+ * Like talloc_find_parent_byname() but takes a type, making it typesafe.
+ *
+ * @param[in] ptr The talloc chunk to start from.
+ *
+ * @param[in] type The type of the parent to look for.
+ *
+ * @return The memory context we are looking for, NULL if not
+ * found.
+ */
+_PUBLIC_ void *talloc_find_parent_bytype(const void *ptr, #type);
+#else
+#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type)
+#endif
+
+/**
+ * @brief Allocate a talloc pool.
+ *
+ * A talloc pool is a pure optimization for specific situations. In the
+ * release process for Samba 3.2 we found out that we had become considerably
+ * slower than Samba 3.0 was. Profiling showed that malloc(3) was a large CPU
+ * consumer in benchmarks. For Samba 3.2 we have internally converted many
+ * static buffers to dynamically allocated ones, so malloc(3) being beaten
+ * more was no surprise. But it made us slower.
+ *
+ * talloc_pool() is an optimization to call malloc(3) a lot less for the use
+ * pattern Samba has: The SMB protocol is mainly a request/response protocol
+ * where we have to allocate a certain amount of memory per request and free
+ * that after the SMB reply is sent to the client.
+ *
+ * talloc_pool() creates a talloc chunk that you can use as a talloc parent
+ * exactly as you would use any other ::TALLOC_CTX. The difference is that
+ * when you talloc a child of this pool, no malloc(3) is done. Instead, talloc
+ * just increments a pointer inside the talloc_pool. This also works
+ * recursively. If you use the child of the talloc pool as a parent for
+ * grand-children, their memory is also taken from the talloc pool.
+ *
+ * If there is not enough memory in the pool to allocate the new child,
+ * it will create a new talloc chunk as if the parent was a normal talloc
+ * context.
+ *
+ * If you talloc_free() children of a talloc pool, the memory is not given
+ * back to the system. Instead, free(3) is only called if the talloc_pool()
+ * itself is released with talloc_free().
+ *
+ * The downside of a talloc pool is that if you talloc_move() a child of a
+ * talloc pool to a talloc parent outside the pool, the whole pool memory is
+ * not free(3)'ed until that moved chunk is also talloc_free()ed.
+ *
+ * @param[in] context The talloc context to hang the result off.
+ *
+ * @param[in] size Size of the talloc pool.
+ *
+ * @return The allocated talloc pool, NULL on error.
+ */
+_PUBLIC_ void *talloc_pool(const void *context, size_t size);
+
+#ifdef DOXYGEN
+/**
+ * @brief Allocate a talloc object as/with an additional pool.
+ *
+ * This is like talloc_pool(), but's it's more flexible
+ * and allows an object to be a pool for its children.
+ *
+ * @param[in] ctx The talloc context to hang the result off.
+ *
+ * @param[in] type The type that we want to allocate.
+ *
+ * @param[in] num_subobjects The expected number of subobjects, which will
+ * be allocated within the pool. This allocates
+ * space for talloc_chunk headers.
+ *
+ * @param[in] total_subobjects_size The size that all subobjects can use in total.
+ *
+ *
+ * @return The allocated talloc object, NULL on error.
+ */
+_PUBLIC_ void *talloc_pooled_object(const void *ctx, #type,
+ unsigned num_subobjects,
+ size_t total_subobjects_size);
+#else
+#define talloc_pooled_object(_ctx, _type, \
+ _num_subobjects, \
+ _total_subobjects_size) \
+ (_type *)_talloc_pooled_object((_ctx), sizeof(_type), #_type, \
+ (_num_subobjects), \
+ (_total_subobjects_size))
+_PUBLIC_ void *_talloc_pooled_object(const void *ctx,
+ size_t type_size,
+ const char *type_name,
+ unsigned num_subobjects,
+ size_t total_subobjects_size);
+#endif
+
+/**
+ * @brief Free a talloc chunk and NULL out the pointer.
+ *
+ * TALLOC_FREE() frees a pointer and sets it to NULL. Use this if you want
+ * immediate feedback (i.e. crash) if you use a pointer after having free'ed
+ * it.
+ *
+ * @param[in] ctx The chunk to be freed.
+ */
+#define TALLOC_FREE(ctx) do { if (ctx != NULL) { talloc_free(ctx); ctx=NULL; } } while(0)
+
+/* @} ******************************************************************/
+
+/**
+ * \defgroup talloc_ref The talloc reference function.
+ * @ingroup talloc
+ *
+ * This module contains the definitions around talloc references
+ *
+ * @{
+ */
+
+/**
+ * @brief Increase the reference count of a talloc chunk.
+ *
+ * The talloc_increase_ref_count(ptr) function is exactly equivalent to:
+ *
+ * @code
+ * talloc_reference(NULL, ptr);
+ * @endcode
+ *
+ * You can use either syntax, depending on which you think is clearer in
+ * your code.
+ *
+ * @param[in] ptr The pointer to increase the reference count.
+ *
+ * @return 0 on success, -1 on error.
+ */
+_PUBLIC_ int talloc_increase_ref_count(const void *ptr);
+
+/**
+ * @brief Get the number of references to a talloc chunk.
+ *
+ * @param[in] ptr The pointer to retrieve the reference count from.
+ *
+ * @return The number of references.
+ */
+_PUBLIC_ size_t talloc_reference_count(const void *ptr);
+
+#ifdef DOXYGEN
+/**
+ * @brief Create an additional talloc parent to a pointer.
+ *
+ * The talloc_reference() function makes "context" an additional parent of
+ * ptr. Each additional reference consumes around 48 bytes of memory on intel
+ * x86 platforms.
+ *
+ * If ptr is NULL, then the function is a no-op, and simply returns NULL.
+ *
+ * After creating a reference you can free it in one of the following ways:
+ *
+ * - you can talloc_free() any parent of the original pointer. That
+ * will reduce the number of parents of this pointer by 1, and will
+ * cause this pointer to be freed if it runs out of parents.
+ *
+ * - you can talloc_free() the pointer itself if it has at maximum one
+ * parent. This behaviour has been changed since the release of version
+ * 2.0. Further information in the description of "talloc_free".
+ *
+ * For more control on which parent to remove, see talloc_unlink()
+ * @param[in] ctx The additional parent.
+ *
+ * @param[in] ptr The pointer you want to create an additional parent for.
+ *
+ * @return The original pointer 'ptr', NULL if talloc ran out of
+ * memory in creating the reference.
+ *
+ * @warning You should try to avoid using this interface. It turns a beautiful
+ * talloc-tree into a graph. It is often really hard to debug if you
+ * screw something up by accident.
+ *
+ * Example:
+ * @code
+ * unsigned int *a, *b, *c;
+ * a = talloc(NULL, unsigned int);
+ * b = talloc(NULL, unsigned int);
+ * c = talloc(a, unsigned int);
+ * // b also serves as a parent of c.
+ * talloc_reference(b, c);
+ * @endcode
+ *
+ * @see talloc_unlink()
+ */
+_PUBLIC_ void *talloc_reference(const void *ctx, const void *ptr);
+#else
+#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference_loc((ctx),(ptr), __location__)
+_PUBLIC_ void *_talloc_reference_loc(const void *context, const void *ptr, const char *location);
+#endif
+
+/**
+ * @brief Remove a specific parent from a talloc chunk.
+ *
+ * The function removes a specific parent from ptr. The context passed must
+ * either be a context used in talloc_reference() with this pointer, or must be
+ * a direct parent of ptr.
+ *
+ * You can just use talloc_free() instead of talloc_unlink() if there
+ * is at maximum one parent. This behaviour has been changed since the
+ * release of version 2.0. Further information in the description of
+ * "talloc_free".
+ *
+ * @param[in] context The talloc parent to remove.
+ *
+ * @param[in] ptr The talloc ptr you want to remove the parent from.
+ *
+ * @return 0 on success, -1 on error.
+ *
+ * @note If the parent has already been removed using talloc_free() then
+ * this function will fail and will return -1. Likewise, if ptr is NULL,
+ * then the function will make no modifications and return -1.
+ *
+ * @warning You should try to avoid using this interface. It turns a beautiful
+ * talloc-tree into a graph. It is often really hard to debug if you
+ * screw something up by accident.
+ *
+ * Example:
+ * @code
+ * unsigned int *a, *b, *c;
+ * a = talloc(NULL, unsigned int);
+ * b = talloc(NULL, unsigned int);
+ * c = talloc(a, unsigned int);
+ * // b also serves as a parent of c.
+ * talloc_reference(b, c);
+ * talloc_unlink(b, c);
+ * @endcode
+ */
+_PUBLIC_ int talloc_unlink(const void *context, void *ptr);
+
+/**
+ * @brief Provide a talloc context that is freed at program exit.
+ *
+ * This is a handy utility function that returns a talloc context
+ * which will be automatically freed on program exit. This can be used
+ * to reduce the noise in memory leak reports.
+ *
+ * Never use this in code that might be used in objects loaded with
+ * dlopen and unloaded with dlclose. talloc_autofree_context()
+ * internally uses atexit(3). Some platforms like modern Linux handles
+ * this fine, but for example FreeBSD does not deal well with dlopen()
+ * and atexit() used simultaneously: dlclose() does not clean up the
+ * list of atexit-handlers, so when the program exits the code that
+ * was registered from within talloc_autofree_context() is gone, the
+ * program crashes at exit.
+ *
+ * @return A talloc context, NULL on error.
+ */
+_PUBLIC_ void *talloc_autofree_context(void) _DEPRECATED_;
+
+/**
+ * @brief Get the size of a talloc chunk.
+ *
+ * This function lets you know the amount of memory allocated so far by
+ * this context. It does NOT account for subcontext memory.
+ * This can be used to calculate the size of an array.
+ *
+ * @param[in] ctx The talloc chunk.
+ *
+ * @return The size of the talloc chunk.
+ */
+_PUBLIC_ size_t talloc_get_size(const void *ctx);
+
+/**
+ * @brief Show the parentage of a context.
+ *
+ * @param[in] context The talloc context to look at.
+ *
+ * @param[in] file The output to use, a file, stdout or stderr.
+ */
+_PUBLIC_ void talloc_show_parents(const void *context, FILE *file);
+
+/**
+ * @brief Check if a context is parent of a talloc chunk.
+ *
+ * This checks if context is referenced in the talloc hierarchy above ptr.
+ *
+ * @param[in] context The assumed talloc context.
+ *
+ * @param[in] ptr The talloc chunk to check.
+ *
+ * @return Return 1 if this is the case, 0 if not.
+ */
+_PUBLIC_ int talloc_is_parent(const void *context, const void *ptr);
+
+/**
+ * @brief Change the parent context of a talloc pointer.
+ *
+ * The function changes the parent context of a talloc pointer. It is typically
+ * used when the context that the pointer is currently a child of is going to be
+ * freed and you wish to keep the memory for a longer time.
+ *
+ * The difference between talloc_reparent() and talloc_steal() is that
+ * talloc_reparent() can specify which parent you wish to change. This is
+ * useful when a pointer has multiple parents via references.
+ *
+ * @param[in] old_parent
+ * @param[in] new_parent
+ * @param[in] ptr
+ *
+ * @return Return the pointer you passed. It does not have any
+ * failure modes.
+ */
+_PUBLIC_ void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr);
+
+/* @} ******************************************************************/
+
+/**
+ * @defgroup talloc_array The talloc array functions
+ * @ingroup talloc
+ *
+ * Talloc contains some handy helpers for handling Arrays conveniently
+ *
+ * @{
+ */
+
+#ifdef DOXYGEN
+/**
+ * @brief Allocate an array.
+ *
+ * The macro is equivalent to:
+ *
+ * @code
+ * (type *)talloc_size(ctx, sizeof(type) * count);
+ * @endcode
+ *
+ * except that it provides integer overflow protection for the multiply,
+ * returning NULL if the multiply overflows.
+ *
+ * @param[in] ctx The talloc context to hang the result off.
+ *
+ * @param[in] type The type that we want to allocate.
+ *
+ * @param[in] count The number of 'type' elements you want to allocate.
+ *
+ * @return The allocated result, properly cast to 'type *', NULL on
+ * error.
+ *
+ * Example:
+ * @code
+ * unsigned int *a, *b;
+ * a = talloc_zero(NULL, unsigned int);
+ * b = talloc_array(a, unsigned int, 100);
+ * @endcode
+ *
+ * @see talloc()
+ * @see talloc_zero_array()
+ */
+_PUBLIC_ void *talloc_array(const void *ctx, #type, unsigned count);
+#else
+#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type)
+_PUBLIC_ void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name);
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Allocate an array.
+ *
+ * @param[in] ctx The talloc context to hang the result off.
+ *
+ * @param[in] size The size of an array element.
+ *
+ * @param[in] count The number of elements you want to allocate.
+ *
+ * @return The allocated result, NULL on error.
+ */
+_PUBLIC_ void *talloc_array_size(const void *ctx, size_t size, unsigned count);
+#else
+#define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Allocate an array into a typed pointer.
+ *
+ * The macro should be used when you have a pointer to an array and want to
+ * allocate memory of an array to point at with this pointer. When compiling
+ * with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_array_size()
+ * and talloc_get_name() will return the current location in the source file
+ * and not the type.
+ *
+ * @param[in] ctx The talloc context to hang the result off.
+ *
+ * @param[in] ptr The pointer you want to assign the result to.
+ *
+ * @param[in] count The number of elements you want to allocate.
+ *
+ * @return The allocated memory chunk, properly casted. NULL on
+ * error.
+ */
+void *talloc_array_ptrtype(const void *ctx, const void *ptr, unsigned count);
+#else
+#define talloc_array_ptrtype(ctx, ptr, count) (_TALLOC_TYPEOF(ptr))talloc_array_size(ctx, sizeof(*(ptr)), count)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Get the number of elements in a talloc'ed array.
+ *
+ * A talloc chunk carries its own size, so for talloc'ed arrays it is not
+ * necessary to store the number of elements explicitly.
+ *
+ * @param[in] ctx The allocated array.
+ *
+ * @return The number of elements in ctx.
+ */
+size_t talloc_array_length(const void *ctx);
+#else
+#define talloc_array_length(ctx) (talloc_get_size(ctx)/sizeof(*ctx))
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Allocate a zero-initialized array
+ *
+ * @param[in] ctx The talloc context to hang the result off.
+ *
+ * @param[in] type The type that we want to allocate.
+ *
+ * @param[in] count The number of "type" elements you want to allocate.
+ *
+ * @return The allocated result casted to "type *", NULL on error.
+ *
+ * The talloc_zero_array() macro is equivalent to:
+ *
+ * @code
+ * ptr = talloc_array(ctx, type, count);
+ * if (ptr) memset(ptr, 0, sizeof(type) * count);
+ * @endcode
+ */
+void *talloc_zero_array(const void *ctx, #type, unsigned count);
+#else
+#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type)
+_PUBLIC_ void *_talloc_zero_array(const void *ctx,
+ size_t el_size,
+ unsigned count,
+ const char *name);
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Change the size of a talloc array.
+ *
+ * The macro changes the size of a talloc pointer. The 'count' argument is the
+ * number of elements of type 'type' that you want the resulting pointer to
+ * hold.
+ *
+ * talloc_realloc() has the following equivalences:
+ *
+ * @code
+ * talloc_realloc(ctx, NULL, type, 1) ==> talloc(ctx, type);
+ * talloc_realloc(ctx, NULL, type, N) ==> talloc_array(ctx, type, N);
+ * talloc_realloc(ctx, ptr, type, 0) ==> talloc_free(ptr);
+ * @endcode
+ *
+ * The "context" argument is only used if "ptr" is NULL, otherwise it is
+ * ignored.
+ *
+ * @param[in] ctx The parent context used if ptr is NULL.
+ *
+ * @param[in] ptr The chunk to be resized.
+ *
+ * @param[in] type The type of the array element inside ptr.
+ *
+ * @param[in] count The intended number of array elements.
+ *
+ * @return The new array, NULL on error. The call will fail either
+ * due to a lack of memory, or because the pointer has more
+ * than one parent (see talloc_reference()).
+ */
+_PUBLIC_ void *talloc_realloc(const void *ctx, void *ptr, #type, size_t count);
+#else
+#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type)
+_PUBLIC_ void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name);
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Untyped realloc to change the size of a talloc array.
+ *
+ * The macro is useful when the type is not known so the typesafe
+ * talloc_realloc() cannot be used.
+ *
+ * @param[in] ctx The parent context used if 'ptr' is NULL.
+ *
+ * @param[in] ptr The chunk to be resized.
+ *
+ * @param[in] size The new chunk size.
+ *
+ * @return The new array, NULL on error.
+ */
+void *talloc_realloc_size(const void *ctx, void *ptr, size_t size);
+#else
+#define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__)
+_PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name);
+#endif
+
+/**
+ * @brief Provide a function version of talloc_realloc_size.
+ *
+ * This is a non-macro version of talloc_realloc(), which is useful as
+ * libraries sometimes want a ralloc function pointer. A realloc()
+ * implementation encapsulates the functionality of malloc(), free() and
+ * realloc() in one call, which is why it is useful to be able to pass around
+ * a single function pointer.
+ *
+ * @param[in] context The parent context used if ptr is NULL.
+ *
+ * @param[in] ptr The chunk to be resized.
+ *
+ * @param[in] size The new chunk size.
+ *
+ * @return The new chunk, NULL on error.
+ */
+_PUBLIC_ void *talloc_realloc_fn(const void *context, void *ptr, size_t size);
+
+/* @} ******************************************************************/
+
+/**
+ * @defgroup talloc_string The talloc string functions.
+ * @ingroup talloc
+ *
+ * talloc string allocation and manipulation functions.
+ * @{
+ */
+
+/**
+ * @brief Duplicate a string into a talloc chunk.
+ *
+ * This function is equivalent to:
+ *
+ * @code
+ * ptr = talloc_size(ctx, strlen(p)+1);
+ * if (ptr) memcpy(ptr, p, strlen(p)+1);
+ * @endcode
+ *
+ * This functions sets the name of the new pointer to the passed
+ * string. This is equivalent to:
+ *
+ * @code
+ * talloc_set_name_const(ptr, ptr)
+ * @endcode
+ *
+ * @param[in] t The talloc context to hang the result off.
+ *
+ * @param[in] p The string you want to duplicate.
+ *
+ * @return The duplicated string, NULL on error.
+ */
+_PUBLIC_ char *talloc_strdup(const void *t, const char *p);
+
+/**
+ * @brief Append a string to given string.
+ *
+ * The destination string is reallocated to take
+ * <code>strlen(s) + strlen(a) + 1</code> characters.
+ *
+ * This functions sets the name of the new pointer to the new
+ * string. This is equivalent to:
+ *
+ * @code
+ * talloc_set_name_const(ptr, ptr)
+ * @endcode
+ *
+ * If <code>s == NULL</code> then new context is created.
+ *
+ * @param[in] s The destination to append to.
+ *
+ * @param[in] a The string you want to append.
+ *
+ * @return The concatenated strings, NULL on error.
+ *
+ * @see talloc_strdup()
+ * @see talloc_strdup_append_buffer()
+ */
+_PUBLIC_ char *talloc_strdup_append(char *s, const char *a);
+
+/**
+ * @brief Append a string to a given buffer.
+ *
+ * This is a more efficient version of talloc_strdup_append(). It determines the
+ * length of the destination string by the size of the talloc context.
+ *
+ * Use this very carefully as it produces a different result than
+ * talloc_strdup_append() when a zero character is in the middle of the
+ * destination string.
+ *
+ * @code
+ * char *str_a = talloc_strdup(NULL, "hello world");
+ * char *str_b = talloc_strdup(NULL, "hello world");
+ * str_a[5] = str_b[5] = '\0'
+ *
+ * char *app = talloc_strdup_append(str_a, ", hello");
+ * char *buf = talloc_strdup_append_buffer(str_b, ", hello");
+ *
+ * printf("%s\n", app); // hello, hello (app = "hello, hello")
+ * printf("%s\n", buf); // hello (buf = "hello\0world, hello")
+ * @endcode
+ *
+ * If <code>s == NULL</code> then new context is created.
+ *
+ * @param[in] s The destination buffer to append to.
+ *
+ * @param[in] a The string you want to append.
+ *
+ * @return The concatenated strings, NULL on error.
+ *
+ * @see talloc_strdup()
+ * @see talloc_strdup_append()
+ * @see talloc_array_length()
+ */
+_PUBLIC_ char *talloc_strdup_append_buffer(char *s, const char *a);
+
+/**
+ * @brief Duplicate a length-limited string into a talloc chunk.
+ *
+ * This function is the talloc equivalent of the C library function strndup(3).
+ *
+ * This functions sets the name of the new pointer to the passed string. This is
+ * equivalent to:
+ *
+ * @code
+ * talloc_set_name_const(ptr, ptr)
+ * @endcode
+ *
+ * @param[in] t The talloc context to hang the result off.
+ *
+ * @param[in] p The string you want to duplicate.
+ *
+ * @param[in] n The maximum string length to duplicate.
+ *
+ * @return The duplicated string, NULL on error.
+ */
+_PUBLIC_ char *talloc_strndup(const void *t, const char *p, size_t n);
+
+/**
+ * @brief Append at most n characters of a string to given string.
+ *
+ * The destination string is reallocated to take
+ * <code>strlen(s) + strnlen(a, n) + 1</code> characters.
+ *
+ * This functions sets the name of the new pointer to the new
+ * string. This is equivalent to:
+ *
+ * @code
+ * talloc_set_name_const(ptr, ptr)
+ * @endcode
+ *
+ * If <code>s == NULL</code> then new context is created.
+ *
+ * @param[in] s The destination string to append to.
+ *
+ * @param[in] a The source string you want to append.
+ *
+ * @param[in] n The number of characters you want to append from the
+ * string.
+ *
+ * @return The concatenated strings, NULL on error.
+ *
+ * @see talloc_strndup()
+ * @see talloc_strndup_append_buffer()
+ */
+_PUBLIC_ char *talloc_strndup_append(char *s, const char *a, size_t n);
+
+/**
+ * @brief Append at most n characters of a string to given buffer
+ *
+ * This is a more efficient version of talloc_strndup_append(). It determines
+ * the length of the destination string by the size of the talloc context.
+ *
+ * Use this very carefully as it produces a different result than
+ * talloc_strndup_append() when a zero character is in the middle of the
+ * destination string.
+ *
+ * @code
+ * char *str_a = talloc_strdup(NULL, "hello world");
+ * char *str_b = talloc_strdup(NULL, "hello world");
+ * str_a[5] = str_b[5] = '\0'
+ *
+ * char *app = talloc_strndup_append(str_a, ", hello", 7);
+ * char *buf = talloc_strndup_append_buffer(str_b, ", hello", 7);
+ *
+ * printf("%s\n", app); // hello, hello (app = "hello, hello")
+ * printf("%s\n", buf); // hello (buf = "hello\0world, hello")
+ * @endcode
+ *
+ * If <code>s == NULL</code> then new context is created.
+ *
+ * @param[in] s The destination buffer to append to.
+ *
+ * @param[in] a The source string you want to append.
+ *
+ * @param[in] n The number of characters you want to append from the
+ * string.
+ *
+ * @return The concatenated strings, NULL on error.
+ *
+ * @see talloc_strndup()
+ * @see talloc_strndup_append()
+ * @see talloc_array_length()
+ */
+_PUBLIC_ char *talloc_strndup_append_buffer(char *s, const char *a, size_t n);
+
+/**
+ * @brief Format a string given a va_list.
+ *
+ * This function is the talloc equivalent of the C library function
+ * vasprintf(3).
+ *
+ * This functions sets the name of the new pointer to the new string. This is
+ * equivalent to:
+ *
+ * @code
+ * talloc_set_name_const(ptr, ptr)
+ * @endcode
+ *
+ * @param[in] t The talloc context to hang the result off.
+ *
+ * @param[in] fmt The format string.
+ *
+ * @param[in] ap The parameters used to fill fmt.
+ *
+ * @return The formatted string, NULL on error.
+ */
+_PUBLIC_ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+
+/**
+ * @brief Format a string given a va_list and append it to the given destination
+ * string.
+ *
+ * @param[in] s The destination string to append to.
+ *
+ * @param[in] fmt The format string.
+ *
+ * @param[in] ap The parameters used to fill fmt.
+ *
+ * @return The formatted string, NULL on error.
+ *
+ * @see talloc_vasprintf()
+ */
+_PUBLIC_ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+
+/**
+ * @brief Format a string given a va_list and append it to the given destination
+ * buffer.
+ *
+ * @param[in] s The destination buffer to append to.
+ *
+ * @param[in] fmt The format string.
+ *
+ * @param[in] ap The parameters used to fill fmt.
+ *
+ * @return The formatted string, NULL on error.
+ *
+ * @see talloc_vasprintf()
+ */
+_PUBLIC_ char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+
+/**
+ * @brief Build up a string buffer, handle allocation failure
+ *
+ * @param[in] ps Pointer to the talloc'ed string to be extended
+ * @param[in] fmt The format string
+ * @param[in] ... The parameters used to fill fmt.
+ *
+ * This does nothing if *ps is NULL and sets *ps to NULL if the
+ * intermediate reallocation fails. Useful when building up a string
+ * step by step, no intermediate NULL checks are required.
+ */
+_PUBLIC_ void talloc_asprintf_addbuf(char **ps, const char *fmt, ...) \
+ PRINTF_ATTRIBUTE(2,3);
+
+/**
+ * @brief Format a string.
+ *
+ * This function is the talloc equivalent of the C library function asprintf(3).
+ *
+ * This functions sets the name of the new pointer to the new string. This is
+ * equivalent to:
+ *
+ * @code
+ * talloc_set_name_const(ptr, ptr)
+ * @endcode
+ *
+ * @param[in] t The talloc context to hang the result off.
+ *
+ * @param[in] fmt The format string.
+ *
+ * @param[in] ... The parameters used to fill fmt.
+ *
+ * @return The formatted string, NULL on error.
+ */
+_PUBLIC_ char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+
+/**
+ * @brief Append a formatted string to another string.
+ *
+ * This function appends the given formatted string to the given string. Use
+ * this variant when the string in the current talloc buffer may have been
+ * truncated in length.
+ *
+ * This functions sets the name of the new pointer to the new
+ * string. This is equivalent to:
+ *
+ * @code
+ * talloc_set_name_const(ptr, ptr)
+ * @endcode
+ *
+ * If <code>s == NULL</code> then new context is created.
+ *
+ * @param[in] s The string to append to.
+ *
+ * @param[in] fmt The format string.
+ *
+ * @param[in] ... The parameters used to fill fmt.
+ *
+ * @return The formatted string, NULL on error.
+ */
+_PUBLIC_ char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+
+/**
+ * @brief Append a formatted string to another string.
+ *
+ * This is a more efficient version of talloc_asprintf_append(). It determines
+ * the length of the destination string by the size of the talloc context.
+ *
+ * Use this very carefully as it produces a different result than
+ * talloc_asprintf_append() when a zero character is in the middle of the
+ * destination string.
+ *
+ * @code
+ * char *str_a = talloc_strdup(NULL, "hello world");
+ * char *str_b = talloc_strdup(NULL, "hello world");
+ * str_a[5] = str_b[5] = '\0'
+ *
+ * char *app = talloc_asprintf_append(str_a, "%s", ", hello");
+ * char *buf = talloc_strdup_append_buffer(str_b, "%s", ", hello");
+ *
+ * printf("%s\n", app); // hello, hello (app = "hello, hello")
+ * printf("%s\n", buf); // hello (buf = "hello\0world, hello")
+ * @endcode
+ *
+ * If <code>s == NULL</code> then new context is created.
+ *
+ * @param[in] s The string to append to
+ *
+ * @param[in] fmt The format string.
+ *
+ * @param[in] ... The parameters used to fill fmt.
+ *
+ * @return The formatted string, NULL on error.
+ *
+ * @see talloc_asprintf()
+ * @see talloc_asprintf_append()
+ */
+_PUBLIC_ char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+
+/* @} ******************************************************************/
+
+/**
+ * @defgroup talloc_debug The talloc debugging support functions
+ * @ingroup talloc
+ *
+ * To aid memory debugging, talloc contains routines to inspect the currently
+ * allocated memory hierarchy.
+ *
+ * @{
+ */
+
+/**
+ * @brief Walk a complete talloc hierarchy.
+ *
+ * This provides a more flexible reports than talloc_report(). It
+ * will recursively call the callback for the entire tree of memory
+ * referenced by the pointer. References in the tree are passed with
+ * is_ref = 1 and the pointer that is referenced.
+ *
+ * You can pass NULL for the pointer, in which case a report is
+ * printed for the top level memory context, but only if
+ * talloc_enable_leak_report() or talloc_enable_leak_report_full()
+ * has been called.
+ *
+ * The recursion is stopped when depth >= max_depth.
+ * max_depth = -1 means only stop at leaf nodes.
+ *
+ * @param[in] ptr The talloc chunk.
+ *
+ * @param[in] depth Internal parameter to control recursion. Call with 0.
+ *
+ * @param[in] max_depth Maximum recursion level.
+ *
+ * @param[in] callback Function to be called on every chunk.
+ *
+ * @param[in] private_data Private pointer passed to callback.
+ */
+_PUBLIC_ void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
+ void (*callback)(const void *ptr,
+ int depth, int max_depth,
+ int is_ref,
+ void *private_data),
+ void *private_data);
+
+/**
+ * @brief Print a talloc hierarchy.
+ *
+ * This provides a more flexible reports than talloc_report(). It
+ * will let you specify the depth and max_depth.
+ *
+ * @param[in] ptr The talloc chunk.
+ *
+ * @param[in] depth Internal parameter to control recursion. Call with 0.
+ *
+ * @param[in] max_depth Maximum recursion level.
+ *
+ * @param[in] f The file handle to print to.
+ */
+_PUBLIC_ void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f);
+
+/**
+ * @brief Print a summary report of all memory used by ptr.
+ *
+ * This provides a more detailed report than talloc_report(). It will
+ * recursively print the entire tree of memory referenced by the
+ * pointer. References in the tree are shown by giving the name of the
+ * pointer that is referenced.
+ *
+ * You can pass NULL for the pointer, in which case a report is printed
+ * for the top level memory context, but only if
+ * talloc_enable_leak_report() or talloc_enable_leak_report_full() has
+ * been called.
+ *
+ * @param[in] ptr The talloc chunk.
+ *
+ * @param[in] f The file handle to print to.
+ *
+ * Example:
+ * @code
+ * unsigned int *a, *b;
+ * a = talloc(NULL, unsigned int);
+ * b = talloc(a, unsigned int);
+ * fprintf(stderr, "Dumping memory tree for a:\n");
+ * talloc_report_full(a, stderr);
+ * @endcode
+ *
+ * @see talloc_report()
+ */
+_PUBLIC_ void talloc_report_full(const void *ptr, FILE *f);
+
+/**
+ * @brief Print a summary report of all memory used by ptr.
+ *
+ * This function prints a summary report of all memory used by ptr. One line of
+ * report is printed for each immediate child of ptr, showing the total memory
+ * and number of blocks used by that child.
+ *
+ * You can pass NULL for the pointer, in which case a report is printed
+ * for the top level memory context, but only if talloc_enable_leak_report()
+ * or talloc_enable_leak_report_full() has been called.
+ *
+ * @param[in] ptr The talloc chunk.
+ *
+ * @param[in] f The file handle to print to.
+ *
+ * Example:
+ * @code
+ * unsigned int *a, *b;
+ * a = talloc(NULL, unsigned int);
+ * b = talloc(a, unsigned int);
+ * fprintf(stderr, "Summary of memory tree for a:\n");
+ * talloc_report(a, stderr);
+ * @endcode
+ *
+ * @see talloc_report_full()
+ */
+_PUBLIC_ void talloc_report(const void *ptr, FILE *f);
+
+/**
+ * @brief Enable tracking the use of NULL memory contexts.
+ *
+ * This enables tracking of the NULL memory context without enabling leak
+ * reporting on exit. Useful for when you want to do your own leak
+ * reporting call via talloc_report_null_full();
+ */
+_PUBLIC_ void talloc_enable_null_tracking(void);
+
+/**
+ * @brief Enable tracking the use of NULL memory contexts.
+ *
+ * This enables tracking of the NULL memory context without enabling leak
+ * reporting on exit. Useful for when you want to do your own leak
+ * reporting call via talloc_report_null_full();
+ */
+_PUBLIC_ void talloc_enable_null_tracking_no_autofree(void);
+
+/**
+ * @brief Disable tracking of the NULL memory context.
+ *
+ * This disables tracking of the NULL memory context.
+ */
+_PUBLIC_ void talloc_disable_null_tracking(void);
+
+/**
+ * @brief Enable leak report when a program exits.
+ *
+ * This enables calling of talloc_report(NULL, stderr) when the program
+ * exits. In Samba4 this is enabled by using the --leak-report command
+ * line option.
+ *
+ * For it to be useful, this function must be called before any other
+ * talloc function as it establishes a "null context" that acts as the
+ * top of the tree. If you don't call this function first then passing
+ * NULL to talloc_report() or talloc_report_full() won't give you the
+ * full tree printout.
+ *
+ * Here is a typical talloc report:
+ *
+ * @code
+ * talloc report on 'null_context' (total 267 bytes in 15 blocks)
+ * libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks
+ * libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks
+ * iconv(UTF8,CP850) contains 42 bytes in 2 blocks
+ * libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks
+ * iconv(CP850,UTF8) contains 42 bytes in 2 blocks
+ * iconv(UTF8,UTF-16LE) contains 45 bytes in 2 blocks
+ * iconv(UTF-16LE,UTF8) contains 45 bytes in 2 blocks
+ * @endcode
+ */
+_PUBLIC_ void talloc_enable_leak_report(void);
+
+/**
+ * @brief Enable full leak report when a program exits.
+ *
+ * This enables calling of talloc_report_full(NULL, stderr) when the
+ * program exits. In Samba4 this is enabled by using the
+ * --leak-report-full command line option.
+ *
+ * For it to be useful, this function must be called before any other
+ * talloc function as it establishes a "null context" that acts as the
+ * top of the tree. If you don't call this function first then passing
+ * NULL to talloc_report() or talloc_report_full() won't give you the
+ * full tree printout.
+ *
+ * Here is a typical full report:
+ *
+ * @code
+ * full talloc report on 'root' (total 18 bytes in 8 blocks)
+ * p1 contains 18 bytes in 7 blocks (ref 0)
+ * r1 contains 13 bytes in 2 blocks (ref 0)
+ * reference to: p2
+ * p2 contains 1 bytes in 1 blocks (ref 1)
+ * x3 contains 1 bytes in 1 blocks (ref 0)
+ * x2 contains 1 bytes in 1 blocks (ref 0)
+ * x1 contains 1 bytes in 1 blocks (ref 0)
+ * @endcode
+ */
+_PUBLIC_ void talloc_enable_leak_report_full(void);
+
+/**
+ * @brief Set a custom "abort" function that is called on serious error.
+ *
+ * The default "abort" function is <code>abort()</code>.
+ *
+ * The "abort" function is called when:
+ *
+ * <ul>
+ * <li>talloc_get_type_abort() fails</li>
+ * <li>the provided pointer is not a valid talloc context</li>
+ * <li>when the context meta data are invalid</li>
+ * <li>when access after free is detected</li>
+ * </ul>
+ *
+ * Example:
+ *
+ * @code
+ * void my_abort(const char *reason)
+ * {
+ * fprintf(stderr, "talloc abort: %s\n", reason);
+ * abort();
+ * }
+ *
+ * talloc_set_abort_fn(my_abort);
+ * @endcode
+ *
+ * @param[in] abort_fn The new "abort" function.
+ *
+ * @see talloc_set_log_fn()
+ * @see talloc_get_type()
+ */
+_PUBLIC_ void talloc_set_abort_fn(void (*abort_fn)(const char *reason));
+
+/**
+ * @brief Set a logging function.
+ *
+ * @param[in] log_fn The logging function.
+ *
+ * @see talloc_set_log_stderr()
+ * @see talloc_set_abort_fn()
+ */
+_PUBLIC_ void talloc_set_log_fn(void (*log_fn)(const char *message));
+
+/**
+ * @brief Set stderr as the output for logs.
+ *
+ * @see talloc_set_log_fn()
+ * @see talloc_set_abort_fn()
+ */
+_PUBLIC_ void talloc_set_log_stderr(void);
+
+/**
+ * @brief Set a max memory limit for the current context hierarchy
+ * This affects all children of this context and constrain any
+ * allocation in the hierarchy to never exceed the limit set.
+ * The limit can be removed by setting 0 (unlimited) as the
+ * max_size by calling the function again on the same context.
+ * Memory limits can also be nested, meaning a child can have
+ * a stricter memory limit than a parent.
+ * Memory limits are enforced only at memory allocation time.
+ * Stealing a context into a 'limited' hierarchy properly
+ * updates memory usage but does *not* cause failure if the
+ * move causes the new parent to exceed its limits. However
+ * any further allocation on that hierarchy will then fail.
+ *
+ * @warning talloc memlimit functionality is deprecated. Please
+ * consider using cgroup memory limits instead.
+ *
+ * @param[in] ctx The talloc context to set the limit on
+ * @param[in] max_size The (new) max_size
+ */
+_PUBLIC_ int talloc_set_memlimit(const void *ctx, size_t max_size) _DEPRECATED_;
+
+/* @} ******************************************************************/
+
+#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)
+#define talloc_append_string(c, s, a) (s?talloc_strdup_append(s,a):talloc_strdup(c, a))
+#endif
+
+#ifndef TALLOC_MAX_DEPTH
+#define TALLOC_MAX_DEPTH 10000
+#endif
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif
diff --git a/lib/talloc/talloc.pc.in b/lib/talloc/talloc.pc.in
new file mode 100644
index 0000000..437281a
--- /dev/null
+++ b/lib/talloc/talloc.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: talloc
+Description: A hierarchical pool based memory system with destructors
+Version: @TALLOC_VERSION@
+Libs: @LIB_RPATH@ -L${libdir} -ltalloc
+Cflags: -I${includedir}
+URL: http://talloc.samba.org/
diff --git a/lib/talloc/talloc_guide.txt b/lib/talloc/talloc_guide.txt
new file mode 100644
index 0000000..dedda6c
--- /dev/null
+++ b/lib/talloc/talloc_guide.txt
@@ -0,0 +1,768 @@
+Using talloc in Samba4
+======================
+
+.. contents::
+
+Andrew Tridgell
+August 2009
+
+The most current version of this document is available at
+ http://samba.org/ftp/unpacked/talloc/talloc_guide.txt
+
+If you are used to the "old" talloc from Samba3 before 3.0.20 then please read
+this carefully, as talloc has changed a lot. With 3.0.20 (or 3.0.14?) the
+Samba4 talloc has been ported back to Samba3, so this guide applies to both.
+
+The new talloc is a hierarchical, reference counted memory pool system
+with destructors. Quite a mouthful really, but not too bad once you
+get used to it.
+
+Perhaps the biggest change from Samba3 is that there is no distinction
+between a "talloc context" and a "talloc pointer". Any pointer
+returned from talloc() is itself a valid talloc context. This means
+you can do this::
+
+ struct foo *X = talloc(mem_ctx, struct foo);
+ X->name = talloc_strdup(X, "foo");
+
+and the pointer X->name would be a "child" of the talloc context "X"
+which is itself a child of "mem_ctx". So if you do talloc_free(mem_ctx)
+then it is all destroyed, whereas if you do talloc_free(X) then just X
+and X->name are destroyed, and if you do talloc_free(X->name) then
+just the name element of X is destroyed.
+
+If you think about this, then what this effectively gives you is an
+n-ary tree, where you can free any part of the tree with
+talloc_free().
+
+If you find this confusing, then I suggest you run the testsuite to
+watch talloc in action. You may also like to add your own tests to
+testsuite.c to clarify how some particular situation is handled.
+
+
+Performance
+-----------
+
+All the additional features of talloc() over malloc() do come at a
+price. We have a simple performance test in Samba4 that measures
+talloc() versus malloc() performance, and it seems that talloc() is
+about 4% slower than malloc() on my x86 Debian Linux box. For Samba,
+the great reduction in code complexity that we get by using talloc
+makes this worthwhile, especially as the total overhead of
+talloc/malloc in Samba is already quite small.
+
+
+talloc API
+----------
+
+The following is a complete guide to the talloc API. Read it all at
+least twice.
+
+Multi-threading
+---------------
+
+talloc itself does not deal with threads. It is thread-safe (assuming
+the underlying "malloc" is), as long as each thread uses different
+memory contexts.
+If two threads use the same context then they need to synchronize in
+order to be safe. In particular:
+- when using talloc_enable_leak_report(), giving directly NULL as a
+parent context implicitly refers to a hidden "null context" global
+variable, so this should not be used in a multi-threaded environment
+without proper synchronization. In threaded code turn off null tracking using
+talloc_disable_null_tracking(). ;
+- the context returned by talloc_autofree_context() is also global so
+shouldn't be used by several threads simultaneously without
+synchronization.
+
+talloc and shared objects
+-------------------------
+
+talloc can be used in shared objects. Special care needs to be taken
+to never use talloc_autofree_context() in code that might be loaded
+with dlopen() and unloaded with dlclose(), as talloc_autofree_context()
+internally uses atexit(3). Some platforms like modern Linux handles
+this fine, but for example FreeBSD does not deal well with dlopen()
+and atexit() used simultaneously: dlclose() does not clean up the list
+of atexit-handlers, so when the program exits the code that was
+registered from within talloc_autofree_context() is gone, the program
+crashes at exit.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(type *)talloc(const void *context, type);
+
+The talloc() macro is the core of the talloc library. It takes a
+memory context and a type, and returns a pointer to a new area of
+memory of the given type.
+
+The returned pointer is itself a talloc context, so you can use it as
+the context argument to more calls to talloc if you wish.
+
+The returned pointer is a "child" of the supplied context. This means
+that if you talloc_free() the context then the new child disappears as
+well. Alternatively you can free just the child.
+
+The context argument to talloc() can be NULL, in which case a new top
+level context is created.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_size(const void *context, size_t size);
+
+The function talloc_size() should be used when you don't have a
+convenient type to pass to talloc(). Unlike talloc(), it is not type
+safe (as it returns a void *), so you are on your own for type checking.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(typeof(ptr)) talloc_ptrtype(const void *ctx, ptr);
+
+The talloc_ptrtype() macro should be used when you have a pointer and
+want to allocate memory to point at with this pointer. When compiling
+with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_size()
+and talloc_get_name() will return the current location in the source file.
+and not the type.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+int talloc_free(void *ptr);
+
+The talloc_free() function frees a piece of talloc memory, and all its
+children. You can call talloc_free() on any pointer returned by
+talloc().
+
+The return value of talloc_free() indicates success or failure, with 0
+returned for success and -1 for failure. A possible failure condition
+is if the pointer had a destructor attached to it and the destructor
+returned -1. See talloc_set_destructor() for details on
+destructors. Likewise, if "ptr" is NULL, then the function will make
+no modifications and returns -1.
+
+From version 2.0 and onwards, as a special case, talloc_free() is
+refused on pointers that have more than one parent associated, as talloc
+would have no way of knowing which parent should be removed. This is
+different from older versions in the sense that always the reference to
+the most recently established parent has been destroyed. Hence to free a
+pointer that has more than one parent please use talloc_unlink().
+
+To help you find problems in your code caused by this behaviour, if
+you do try and free a pointer with more than one parent then the
+talloc logging function will be called to give output like this:
+
+ ERROR: talloc_free with references at some_dir/source/foo.c:123
+ reference at some_dir/source/other.c:325
+ reference at some_dir/source/third.c:121
+
+Please see the documentation for talloc_set_log_fn() and
+talloc_set_log_stderr() for more information on talloc logging
+functions.
+
+talloc_free() operates recursively on its children.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_free_children(void *ptr);
+
+The talloc_free_children() walks along the list of all children of a
+talloc context and talloc_free()s only the children, not the context
+itself.
+
+A NULL argument is handled as no-op.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_reference(const void *context, const void *ptr);
+
+The talloc_reference() function makes "context" an additional parent
+of "ptr".
+
+The return value of talloc_reference() is always the original pointer
+"ptr", unless talloc ran out of memory in creating the reference in
+which case it will return NULL (each additional reference consumes
+around 48 bytes of memory on intel x86 platforms).
+
+If "ptr" is NULL, then the function is a no-op, and simply returns NULL.
+
+After creating a reference you can free it in one of the following
+ways:
+
+ - you can talloc_free() any parent of the original pointer. That
+ will reduce the number of parents of this pointer by 1, and will
+ cause this pointer to be freed if it runs out of parents.
+
+ - you can talloc_free() the pointer itself if it has at maximum one
+ parent. This behaviour has been changed since the release of version
+ 2.0. Further information in the description of "talloc_free".
+
+For more control on which parent to remove, see talloc_unlink()
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+int talloc_unlink(const void *context, void *ptr);
+
+The talloc_unlink() function removes a specific parent from ptr. The
+context passed must either be a context used in talloc_reference()
+with this pointer, or must be a direct parent of ptr.
+
+Note that if the parent has already been removed using talloc_free()
+then this function will fail and will return -1. Likewise, if "ptr"
+is NULL, then the function will make no modifications and return -1.
+
+You can just use talloc_free() instead of talloc_unlink() if there
+is at maximum one parent. This behaviour has been changed since the
+release of version 2.0. Further information in the description of
+"talloc_free".
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_set_destructor(const void *ptr, int (*destructor)(void *));
+
+The function talloc_set_destructor() sets the "destructor" for the
+pointer "ptr". A destructor is a function that is called when the
+memory used by a pointer is about to be released. The destructor
+receives the pointer as an argument, and should return 0 for success
+and -1 for failure.
+
+The destructor can do anything it wants to, including freeing other
+pieces of memory. A common use for destructors is to clean up
+operating system resources (such as open file descriptors) contained
+in the structure the destructor is placed on.
+
+You can only place one destructor on a pointer. If you need more than
+one destructor then you can create a zero-length child of the pointer
+and place an additional destructor on that.
+
+To remove a destructor call talloc_set_destructor() with NULL for the
+destructor.
+
+If your destructor attempts to talloc_free() the pointer that it is
+the destructor for then talloc_free() will return -1 and the free will
+be ignored. This would be a pointless operation anyway, as the
+destructor is only called when the memory is just about to go away.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+int talloc_increase_ref_count(const void *ptr);
+
+The talloc_increase_ref_count(ptr) function is exactly equivalent to:
+
+ talloc_reference(NULL, ptr);
+
+You can use either syntax, depending on which you think is clearer in
+your code.
+
+It returns 0 on success and -1 on failure.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+size_t talloc_reference_count(const void *ptr);
+
+Return the number of references to the pointer.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_set_name(const void *ptr, const char *fmt, ...);
+
+Each talloc pointer has a "name". The name is used principally for
+debugging purposes, although it is also possible to set and get the
+name on a pointer in as a way of "marking" pointers in your code.
+
+The main use for names on pointer is for "talloc reports". See
+talloc_report() and talloc_report_full() for details. Also see
+talloc_enable_leak_report() and talloc_enable_leak_report_full().
+
+The talloc_set_name() function allocates memory as a child of the
+pointer. It is logically equivalent to:
+ talloc_set_name_const(ptr, talloc_asprintf(ptr, fmt, ...));
+
+Note that multiple calls to talloc_set_name() will allocate more
+memory without releasing the name. All of the memory is released when
+the ptr is freed using talloc_free().
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_set_name_const(const void *ptr, const char *name);
+
+The function talloc_set_name_const() is just like talloc_set_name(),
+but it takes a string constant, and is much faster. It is extensively
+used by the "auto naming" macros, such as talloc_p().
+
+This function does not allocate any memory. It just copies the
+supplied pointer into the internal representation of the talloc
+ptr. This means you must not pass a name pointer to memory that will
+disappear before the ptr is freed with talloc_free().
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_named(const void *context, size_t size, const char *fmt, ...);
+
+The talloc_named() function creates a named talloc pointer. It is
+equivalent to:
+
+ ptr = talloc_size(context, size);
+ talloc_set_name(ptr, fmt, ....);
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_named_const(const void *context, size_t size, const char *name);
+
+This is equivalent to::
+
+ ptr = talloc_size(context, size);
+ talloc_set_name_const(ptr, name);
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+const char *talloc_get_name(const void *ptr);
+
+This returns the current name for the given talloc pointer. See
+talloc_set_name() for details.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_init(const char *fmt, ...);
+
+This function creates a zero length named talloc context as a top
+level context. It is equivalent to::
+
+ talloc_named(NULL, 0, fmt, ...);
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_new(void *ctx);
+
+This is a utility macro that creates a new memory context hanging
+off an exiting context, automatically naming it "talloc_new: __location__"
+where __location__ is the source line it is called from. It is
+particularly useful for creating a new temporary working context.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(type *)talloc_realloc(const void *context, void *ptr, type, count);
+
+The talloc_realloc() macro changes the size of a talloc
+pointer. The "count" argument is the number of elements of type "type"
+that you want the resulting pointer to hold.
+
+talloc_realloc() has the following equivalences::
+
+ talloc_realloc(context, NULL, type, 1) ==> talloc(context, type);
+ talloc_realloc(context, NULL, type, N) ==> talloc_array(context, type, N);
+ talloc_realloc(context, ptr, type, 0) ==> talloc_free(ptr);
+
+The "context" argument is only used if "ptr" is NULL, otherwise it is
+ignored.
+
+talloc_realloc() returns the new pointer, or NULL on failure. The call
+will fail either due to a lack of memory, or because the pointer has
+more than one parent (see talloc_reference()).
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_realloc_size(const void *context, void *ptr, size_t size);
+
+the talloc_realloc_size() function is useful when the type is not
+known so the typesafe talloc_realloc() cannot be used.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_steal(const void *new_ctx, const void *ptr);
+
+The talloc_steal() function changes the parent context of a talloc
+pointer. It is typically used when the context that the pointer is
+currently a child of is going to be freed and you wish to keep the
+memory for a longer time.
+
+The talloc_steal() function returns the pointer that you pass it. It
+does not have any failure modes.
+
+NOTE: It is possible to produce loops in the parent/child relationship
+if you are not careful with talloc_steal(). No guarantees are provided
+as to your sanity or the safety of your data if you do this.
+
+talloc_steal (new_ctx, NULL) will return NULL with no sideeffects.
+
+Note that if you try and call talloc_steal() on a pointer that has
+more than one parent then the result is ambiguous. Talloc will choose
+to remove the parent that is currently indicated by talloc_parent()
+and replace it with the chosen parent. You will also get a message
+like this via the talloc logging functions:
+
+ WARNING: talloc_steal with references at some_dir/source/foo.c:123
+ reference at some_dir/source/other.c:325
+ reference at some_dir/source/third.c:121
+
+To unambiguously change the parent of a pointer please see the
+function talloc_reparent(). See the talloc_set_log_fn() documentation
+for more information on talloc logging.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr);
+
+The talloc_reparent() function changes the parent context of a talloc
+pointer. It is typically used when the context that the pointer is
+currently a child of is going to be freed and you wish to keep the
+memory for a longer time.
+
+The talloc_reparent() function returns the pointer that you pass it. It
+does not have any failure modes.
+
+The difference between talloc_reparent() and talloc_steal() is that
+talloc_reparent() can specify which parent you wish to change. This is
+useful when a pointer has multiple parents via references.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_parent(const void *ptr);
+
+The talloc_parent() function returns the current talloc parent. This
+is usually the pointer under which this memory was originally created,
+but it may have changed due to a talloc_steal() or talloc_reparent()
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+size_t talloc_total_size(const void *ptr);
+
+The talloc_total_size() function returns the total size in bytes used
+by this pointer and all child pointers. Mostly useful for debugging.
+
+Passing NULL is allowed, but it will only give a meaningful result if
+talloc_enable_leak_report() or talloc_enable_leak_report_full() has
+been called.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+size_t talloc_total_blocks(const void *ptr);
+
+The talloc_total_blocks() function returns the total memory block
+count used by this pointer and all child pointers. Mostly useful for
+debugging.
+
+Passing NULL is allowed, but it will only give a meaningful result if
+talloc_enable_leak_report() or talloc_enable_leak_report_full() has
+been called.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
+ void (*callback)(const void *ptr,
+ int depth, int max_depth,
+ int is_ref,
+ void *priv),
+ void *priv);
+
+This provides a more flexible reports than talloc_report(). It
+will recursively call the callback for the entire tree of memory
+referenced by the pointer. References in the tree are passed with
+is_ref = 1 and the pointer that is referenced.
+
+You can pass NULL for the pointer, in which case a report is
+printed for the top level memory context, but only if
+talloc_enable_leak_report() or talloc_enable_leak_report_full()
+has been called.
+
+The recursion is stopped when depth >= max_depth.
+max_depth = -1 means only stop at leaf nodes.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f);
+
+This provides a more flexible reports than talloc_report(). It
+will let you specify the depth and max_depth.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_report(const void *ptr, FILE *f);
+
+The talloc_report() function prints a summary report of all memory
+used by ptr. One line of report is printed for each immediate child of
+ptr, showing the total memory and number of blocks used by that child.
+
+You can pass NULL for the pointer, in which case a report is printed
+for the top level memory context, but only if
+talloc_enable_leak_report() or talloc_enable_leak_report_full() has
+been called.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_report_full(const void *ptr, FILE *f);
+
+This provides a more detailed report than talloc_report(). It will
+recursively print the entire tree of memory referenced by the
+pointer. References in the tree are shown by giving the name of the
+pointer that is referenced.
+
+You can pass NULL for the pointer, in which case a report is printed
+for the top level memory context, but only if
+talloc_enable_leak_report() or talloc_enable_leak_report_full() has
+been called.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_enable_leak_report(void);
+
+This enables calling of talloc_report(NULL, stderr) when the program
+exits. In Samba4 this is enabled by using the --leak-report command
+line option.
+
+For it to be useful, this function must be called before any other
+talloc function as it establishes a "null context" that acts as the
+top of the tree. If you don't call this function first then passing
+NULL to talloc_report() or talloc_report_full() won't give you the
+full tree printout.
+
+Here is a typical talloc report:
+
+talloc report on 'null_context' (total 267 bytes in 15 blocks)
+ libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks
+ libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks
+ iconv(UTF8,CP850) contains 42 bytes in 2 blocks
+ libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks
+ iconv(CP850,UTF8) contains 42 bytes in 2 blocks
+ iconv(UTF8,UTF-16LE) contains 45 bytes in 2 blocks
+ iconv(UTF-16LE,UTF8) contains 45 bytes in 2 blocks
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_enable_leak_report_full(void);
+
+This enables calling of talloc_report_full(NULL, stderr) when the
+program exits. In Samba4 this is enabled by using the
+--leak-report-full command line option.
+
+For it to be useful, this function must be called before any other
+talloc function as it establishes a "null context" that acts as the
+top of the tree. If you don't call this function first then passing
+NULL to talloc_report() or talloc_report_full() won't give you the
+full tree printout.
+
+Here is a typical full report:
+
+full talloc report on 'root' (total 18 bytes in 8 blocks)
+ p1 contains 18 bytes in 7 blocks (ref 0)
+ r1 contains 13 bytes in 2 blocks (ref 0)
+ reference to: p2
+ p2 contains 1 bytes in 1 blocks (ref 1)
+ x3 contains 1 bytes in 1 blocks (ref 0)
+ x2 contains 1 bytes in 1 blocks (ref 0)
+ x1 contains 1 bytes in 1 blocks (ref 0)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_enable_null_tracking(void);
+
+This enables tracking of the NULL memory context without enabling leak
+reporting on exit. Useful for when you want to do your own leak
+reporting call via talloc_report_null_full();
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_disable_null_tracking(void);
+
+This disables tracking of the NULL memory context.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(type *)talloc_zero(const void *ctx, type);
+
+The talloc_zero() macro is equivalent to::
+
+ ptr = talloc(ctx, type);
+ if (ptr) memset(ptr, 0, sizeof(type));
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_zero_size(const void *ctx, size_t size)
+
+The talloc_zero_size() function is useful when you don't have a known type
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_memdup(const void *ctx, const void *p, size_t size);
+
+The talloc_memdup() function is equivalent to::
+
+ ptr = talloc_size(ctx, size);
+ if (ptr) memcpy(ptr, p, size);
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_strdup(const void *ctx, const char *p);
+
+The talloc_strdup() function is equivalent to::
+
+ ptr = talloc_size(ctx, strlen(p)+1);
+ if (ptr) memcpy(ptr, p, strlen(p)+1);
+
+This functions sets the name of the new pointer to the passed
+string. This is equivalent to::
+
+ talloc_set_name_const(ptr, ptr)
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_strndup(const void *t, const char *p, size_t n);
+
+The talloc_strndup() function is the talloc equivalent of the C
+library function strndup()
+
+This functions sets the name of the new pointer to the passed
+string. This is equivalent to:
+ talloc_set_name_const(ptr, ptr)
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_append_string(const void *t, char *orig, const char *append);
+
+The talloc_append_string() function appends the given formatted
+string to the given string.
+
+This function sets the name of the new pointer to the new
+string. This is equivalent to::
+
+ talloc_set_name_const(ptr, ptr)
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_vasprintf(const void *t, const char *fmt, va_list ap);
+
+The talloc_vasprintf() function is the talloc equivalent of the C
+library function vasprintf()
+
+This functions sets the name of the new pointer to the new
+string. This is equivalent to::
+
+ talloc_set_name_const(ptr, ptr)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_asprintf(const void *t, const char *fmt, ...);
+
+The talloc_asprintf() function is the talloc equivalent of the C
+library function asprintf()
+
+This functions sets the name of the new pointer to the new
+string. This is equivalent to::
+
+ talloc_set_name_const(ptr, ptr)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_asprintf_append(char *s, const char *fmt, ...);
+
+The talloc_asprintf_append() function appends the given formatted
+string to the given string.
+Use this variant when the string in the current talloc buffer may
+have been truncated in length.
+
+This functions sets the name of the new pointer to the new
+string. This is equivalent to::
+
+ talloc_set_name_const(ptr, ptr)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...);
+
+The talloc_asprintf_append() function appends the given formatted
+string to the end of the currently allocated talloc buffer.
+Use this variant when the string in the current talloc buffer has
+not been changed.
+
+This functions sets the name of the new pointer to the new
+string. This is equivalent to::
+
+ talloc_set_name_const(ptr, ptr)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+((type *)talloc_array(const void *ctx, type, unsigned int count);
+
+The talloc_array() macro is equivalent to::
+
+ (type *)talloc_size(ctx, sizeof(type) * count);
+
+except that it provides integer overflow protection for the multiply,
+returning NULL if the multiply overflows.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_array_size(const void *ctx, size_t size, unsigned int count);
+
+The talloc_array_size() function is useful when the type is not
+known. It operates in the same way as talloc_array(), but takes a size
+instead of a type.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(typeof(ptr)) talloc_array_ptrtype(const void *ctx, ptr, unsigned int count);
+
+The talloc_ptrtype() macro should be used when you have a pointer to an array
+and want to allocate memory of an array to point at with this pointer. When compiling
+with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_array_size()
+and talloc_get_name() will return the current location in the source file.
+and not the type.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_realloc_fn(const void *ctx, void *ptr, size_t size);
+
+This is a non-macro version of talloc_realloc(), which is useful
+as libraries sometimes want a ralloc function pointer. A realloc()
+implementation encapsulates the functionality of malloc(), free() and
+realloc() in one call, which is why it is useful to be able to pass
+around a single function pointer.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_autofree_context(void);
+
+This is a handy utility function that returns a talloc context
+which will be automatically freed on program exit. This can be used
+to reduce the noise in memory leak reports.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_check_name(const void *ptr, const char *name);
+
+This function checks if a pointer has the specified name. If it does
+then the pointer is returned. It it doesn't then NULL is returned.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(type *)talloc_get_type(const void *ptr, type);
+
+This macro allows you to do type checking on talloc pointers. It is
+particularly useful for void* private pointers. It is equivalent to
+this::
+
+ (type *)talloc_check_name(ptr, #type)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+talloc_set_type(const void *ptr, type);
+
+This macro allows you to force the name of a pointer to be of a
+particular type. This can be used in conjunction with
+talloc_get_type() to do type checking on void* pointers.
+
+It is equivalent to this::
+
+ talloc_set_name_const(ptr, #type)
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+talloc_get_size(const void *ctx);
+
+This function lets you know the amount of memory allocated so far by
+this context. It does NOT account for subcontext memory.
+This can be used to calculate the size of an array.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_find_parent_byname(const void *ctx, const char *name);
+
+Find a parent memory context of the current context that has the given
+name. This can be very useful in complex programs where it may be
+difficult to pass all information down to the level you need, but you
+know the structure you want is a parent of another context.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(type *)talloc_find_parent_bytype(ctx, type);
+
+Like talloc_find_parent_byname() but takes a type, making it typesafe.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_set_log_fn(void (*log_fn)(const char *message));
+
+This function sets a logging function that talloc will use for
+warnings and errors. By default talloc will not print any warnings or
+errors.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_set_log_stderr(void)
+
+This sets the talloc log function to write log messages to stderr.
diff --git a/lib/talloc/talloc_testsuite.h b/lib/talloc/talloc_testsuite.h
new file mode 100644
index 0000000..acb9701
--- /dev/null
+++ b/lib/talloc/talloc_testsuite.h
@@ -0,0 +1,7 @@
+#ifndef __LIB_TALLOC_TALLOC_TESTSUITE_H__
+#define __LIB_TALLOC_TALLOC_TESTSUITE_H__
+
+struct torture_context;
+bool torture_local_talloc(struct torture_context *tctx);
+
+#endif
diff --git a/lib/talloc/test_magic_differs.sh b/lib/talloc/test_magic_differs.sh
new file mode 100755
index 0000000..1b6ba2e
--- /dev/null
+++ b/lib/talloc/test_magic_differs.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+# This test ensures that two different talloc processes do not use the same
+# magic value to lessen the opportunity for transferrable attacks.
+
+echo "test: magic differs"
+
+helper=$1
+m1=$($helper)
+m2=$($helper)
+
+if [ $m1 -eq $m2 ]; then
+ echo "failure: magic remained the same between executions ($m1 vs $m2)"
+ exit 1
+fi
+
+echo "success: magic differs"
diff --git a/lib/talloc/test_magic_differs_helper.c b/lib/talloc/test_magic_differs_helper.c
new file mode 100644
index 0000000..6798827
--- /dev/null
+++ b/lib/talloc/test_magic_differs_helper.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include "talloc.h"
+
+/*
+ * This program is called by a testing shell script in order to ensure that
+ * if the library is loaded into different processes it uses different magic
+ * values in order to thwart security attacks.
+ */
+int main(int argc, char *argv[]) {
+ printf("%i\n", talloc_test_get_magic());
+ return 0;
+}
diff --git a/lib/talloc/test_pytalloc.c b/lib/talloc/test_pytalloc.c
new file mode 100644
index 0000000..3b0484b
--- /dev/null
+++ b/lib/talloc/test_pytalloc.c
@@ -0,0 +1,244 @@
+/*
+ Samba Unix SMB/CIFS implementation.
+
+ C utilities for the pytalloc test suite.
+ Provides the "_test_pytalloc" Python module.
+
+ NOTE: Please read talloc_guide.txt for full documentation
+
+ Copyright (C) Petr Viktorin 2015
+
+ ** 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 3 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
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <Python.h>
+#include <talloc.h>
+#include <pytalloc.h>
+
+static PyObject *testpytalloc_new(PyTypeObject *mod,
+ PyObject *Py_UNUSED(ignored))
+{
+ char *obj = talloc_strdup(NULL, "This is a test string");;
+ return pytalloc_steal(pytalloc_GetObjectType(), obj);
+}
+
+static PyObject *testpytalloc_get_object_type(PyObject *mod,
+ PyObject *Py_UNUSED(ignored))
+{
+ PyObject *type = (PyObject *)pytalloc_GetObjectType();
+ Py_INCREF(type);
+ return type;
+}
+
+static PyObject *testpytalloc_base_new(PyTypeObject *mod,
+ PyObject *Py_UNUSED(ignored))
+{
+ char *obj = talloc_strdup(NULL, "This is a test string for a BaseObject");;
+ return pytalloc_steal(pytalloc_GetBaseObjectType(), obj);
+}
+
+static PyObject *testpytalloc_base_get_object_type(PyObject *mod,
+ PyObject *Py_UNUSED(ignored))
+{
+ PyObject *type = (PyObject *)pytalloc_GetBaseObjectType();
+ Py_INCREF(type);
+ return type;
+}
+
+static PyObject *testpytalloc_reference(PyObject *mod, PyObject *args) {
+ PyObject *source = NULL;
+ void *ptr;
+
+ if (!PyArg_ParseTuple(args, "O!", pytalloc_GetObjectType(), &source))
+ return NULL;
+
+ ptr = pytalloc_get_ptr(source);
+ return pytalloc_reference_ex(pytalloc_GetObjectType(), ptr, ptr);
+}
+
+static PyObject *testpytalloc_base_reference(PyObject *mod, PyObject *args) {
+ PyObject *source = NULL;
+ void *mem_ctx;
+
+ if (!PyArg_ParseTuple(args, "O!", pytalloc_GetBaseObjectType(), &source)) {
+ return NULL;
+ }
+ mem_ctx = pytalloc_get_mem_ctx(source);
+ return pytalloc_reference_ex(pytalloc_GetBaseObjectType(), mem_ctx, mem_ctx);
+}
+
+static PyMethodDef test_talloc_methods[] = {
+ { "new", (PyCFunction)testpytalloc_new, METH_NOARGS,
+ "create a talloc Object with a testing string"},
+ { "get_object_type", (PyCFunction)testpytalloc_get_object_type, METH_NOARGS,
+ "call pytalloc_GetObjectType"},
+ { "base_new", (PyCFunction)testpytalloc_base_new, METH_NOARGS,
+ "create a talloc BaseObject with a testing string"},
+ { "base_get_object_type", (PyCFunction)testpytalloc_base_get_object_type, METH_NOARGS,
+ "call pytalloc_GetBaseObjectType"},
+ { "reference", (PyCFunction)testpytalloc_reference, METH_VARARGS,
+ "call pytalloc_reference_ex"},
+ { "base_reference", (PyCFunction)testpytalloc_base_reference, METH_VARARGS,
+ "call pytalloc_reference_ex"},
+ {0}
+};
+
+static PyTypeObject DObject_Type;
+
+static int dobject_destructor(void *ptr)
+{
+ PyObject *destructor_func = *talloc_get_type(ptr, PyObject*);
+ PyObject *ret;
+ ret = PyObject_CallObject(destructor_func, NULL);
+ Py_DECREF(destructor_func);
+ if (ret == NULL) {
+ PyErr_Print();
+ } else {
+ Py_DECREF(ret);
+ }
+ return 0;
+}
+
+static PyObject *dobject_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ PyObject *destructor_func = NULL;
+ PyObject **obj;
+
+ if (!PyArg_ParseTuple(args, "O", &destructor_func))
+ return NULL;
+ Py_INCREF(destructor_func);
+
+ obj = talloc(NULL, PyObject*);
+ *obj = destructor_func;
+
+ talloc_set_destructor((void*)obj, dobject_destructor);
+ return pytalloc_steal(&DObject_Type, obj);
+}
+
+static PyTypeObject DObject_Type = {
+ .tp_name = "_test_pytalloc.DObject",
+ .tp_basicsize = sizeof(pytalloc_Object),
+ .tp_methods = NULL,
+ .tp_new = dobject_new,
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_doc = "test talloc object that calls a function when underlying data is freed\n",
+};
+
+static PyTypeObject DBaseObject_Type;
+
+static int d_base_object_destructor(void *ptr)
+{
+ PyObject *destructor_func = *talloc_get_type(ptr, PyObject*);
+ PyObject *ret;
+ ret = PyObject_CallObject(destructor_func, NULL);
+ Py_DECREF(destructor_func);
+ if (ret == NULL) {
+ PyErr_Print();
+ } else {
+ Py_DECREF(ret);
+ }
+ return 0;
+}
+
+static PyObject *d_base_object_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ PyObject *destructor_func = NULL;
+ PyObject **obj;
+
+ if (!PyArg_ParseTuple(args, "O", &destructor_func))
+ return NULL;
+ Py_INCREF(destructor_func);
+
+ obj = talloc(NULL, PyObject*);
+ *obj = destructor_func;
+
+ talloc_set_destructor((void*)obj, d_base_object_destructor);
+ return pytalloc_steal(&DBaseObject_Type, obj);
+}
+
+static PyTypeObject DBaseObject_Type = {
+ .tp_name = "_test_pytalloc.DBaseObject",
+ .tp_methods = NULL,
+ .tp_new = d_base_object_new,
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_doc = "test talloc object that calls a function when underlying data is freed\n",
+};
+
+#define MODULE_DOC PyDoc_STR("Test utility module for pytalloc")
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "_test_pytalloc",
+ .m_doc = PyDoc_STR("Test utility module for pytalloc"),
+ .m_size = -1,
+ .m_methods = test_talloc_methods,
+};
+#endif
+
+static PyObject *module_init(void);
+static PyObject *module_init(void)
+{
+ PyObject *m;
+
+ DObject_Type.tp_base = pytalloc_GetObjectType();
+ if (PyType_Ready(&DObject_Type) < 0) {
+ return NULL;
+ }
+
+ DBaseObject_Type.tp_basicsize = pytalloc_BaseObject_size();
+ DBaseObject_Type.tp_base = pytalloc_GetBaseObjectType();
+ if (PyType_Ready(&DBaseObject_Type) < 0) {
+ return NULL;
+ }
+
+#if PY_MAJOR_VERSION >= 3
+ m = PyModule_Create(&moduledef);
+#else
+ m = Py_InitModule3("_test_pytalloc", test_talloc_methods, MODULE_DOC);
+#endif
+
+ if (m == NULL) {
+ return NULL;
+ }
+
+ Py_INCREF(&DObject_Type);
+ Py_INCREF(DObject_Type.tp_base);
+ PyModule_AddObject(m, "DObject", (PyObject *)&DObject_Type);
+
+ Py_INCREF(&DBaseObject_Type);
+ Py_INCREF(DBaseObject_Type.tp_base);
+ PyModule_AddObject(m, "DBaseObject", (PyObject *)&DBaseObject_Type);
+
+ return m;
+}
+
+
+#if PY_MAJOR_VERSION >= 3
+PyMODINIT_FUNC PyInit__test_pytalloc(void);
+PyMODINIT_FUNC PyInit__test_pytalloc(void)
+{
+ return module_init();
+}
+#else
+void init_test_pytalloc(void);
+void init_test_pytalloc(void)
+{
+ module_init();
+}
+#endif
diff --git a/lib/talloc/test_pytalloc.py b/lib/talloc/test_pytalloc.py
new file mode 100644
index 0000000..809510f
--- /dev/null
+++ b/lib/talloc/test_pytalloc.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+# Simple tests for the talloc python bindings.
+# Copyright (C) 2015 Petr Viktorin <pviktori@redhat.com>
+
+import unittest
+import subprocess
+import sys
+import gc
+
+import talloc
+import _test_pytalloc
+
+
+def dummy_func():
+ pass
+
+
+class TallocTests(unittest.TestCase):
+
+ def test_report_full(self):
+ # report_full is hardcoded to print to stdout, so use a subprocess
+ process = subprocess.Popen([
+ sys.executable, '-c',
+ """if True:
+ import talloc, _test_pytalloc
+ obj = _test_pytalloc.new()
+ talloc.report_full(obj)
+ """
+ ], stdout=subprocess.PIPE)
+ output, stderr = process.communicate()
+ output = str(output)
+ self.assertTrue("full talloc report on 'talloc.Object" in output)
+ self.assertTrue("This is a test string" in output)
+
+ def test_totalblocks(self):
+ obj = _test_pytalloc.new()
+ # Two blocks: the string, and the name
+ self.assertEqual(talloc.total_blocks(obj), 2)
+
+ def test_repr(self):
+ obj = _test_pytalloc.new()
+ prefix = '<talloc.Object talloc object at'
+ self.assertTrue(repr(obj).startswith(prefix))
+ self.assertEqual(repr(obj), str(obj))
+
+ def test_base_repr(self):
+ obj = _test_pytalloc.base_new()
+ prefix = '<talloc.BaseObject talloc based object at'
+ self.assertTrue(repr(obj).startswith(prefix))
+ self.assertEqual(repr(obj), str(obj))
+
+ def test_destructor(self):
+ # Check correct lifetime of the talloc'd data
+ lst = []
+ obj = _test_pytalloc.DObject(lambda: lst.append('dead'))
+ self.assertEqual(lst, [])
+ del obj
+ gc.collect()
+ self.assertEqual(lst, ['dead'])
+
+ def test_base_destructor(self):
+ # Check correct lifetime of the talloc'd data
+ lst = []
+ obj = _test_pytalloc.DBaseObject(lambda: lst.append('dead'))
+ self.assertEqual(lst, [])
+ del obj
+ gc.collect()
+ self.assertEqual(lst, ['dead'])
+
+
+class TallocComparisonTests(unittest.TestCase):
+
+ def test_compare_same(self):
+ obj1 = _test_pytalloc.new()
+ self.assertTrue(obj1 == obj1)
+ self.assertFalse(obj1 != obj1)
+ self.assertTrue(obj1 <= obj1)
+ self.assertFalse(obj1 < obj1)
+ self.assertTrue(obj1 >= obj1)
+ self.assertFalse(obj1 > obj1)
+
+ def test_compare_different(self):
+ # object comparison is consistent
+ obj1, obj2 = sorted([
+ _test_pytalloc.new(),
+ _test_pytalloc.new()])
+ self.assertFalse(obj1 == obj2)
+ self.assertTrue(obj1 != obj2)
+ self.assertTrue(obj1 <= obj2)
+ self.assertTrue(obj1 < obj2)
+ self.assertFalse(obj1 >= obj2)
+ self.assertFalse(obj1 > obj2)
+
+ def test_compare_different_types(self):
+ # object comparison falls back to comparing types
+ if sys.version_info >= (3, 0):
+ # In Python 3, types are unorderable -- nothing to test
+ return
+ if talloc.Object < _test_pytalloc.DObject:
+ obj1 = _test_pytalloc.new()
+ obj2 = _test_pytalloc.DObject(dummy_func)
+ else:
+ obj2 = _test_pytalloc.new()
+ obj1 = _test_pytalloc.DObject(dummy_func)
+ self.assertFalse(obj1 == obj2)
+ self.assertTrue(obj1 != obj2)
+ self.assertTrue(obj1 <= obj2)
+ self.assertTrue(obj1 < obj2)
+ self.assertFalse(obj1 >= obj2)
+ self.assertFalse(obj1 > obj2)
+
+
+class TallocBaseComparisonTests(unittest.TestCase):
+
+ def test_compare_same(self):
+ obj1 = _test_pytalloc.base_new()
+ self.assertTrue(obj1 == obj1)
+ self.assertFalse(obj1 != obj1)
+ self.assertTrue(obj1 <= obj1)
+ self.assertFalse(obj1 < obj1)
+ self.assertTrue(obj1 >= obj1)
+ self.assertFalse(obj1 > obj1)
+
+ def test_compare_different(self):
+ # object comparison is consistent
+ obj1, obj2 = sorted([
+ _test_pytalloc.base_new(),
+ _test_pytalloc.base_new()])
+ self.assertFalse(obj1 == obj2)
+ self.assertTrue(obj1 != obj2)
+ self.assertTrue(obj1 <= obj2)
+ self.assertTrue(obj1 < obj2)
+ self.assertFalse(obj1 >= obj2)
+ self.assertFalse(obj1 > obj2)
+
+ def test_compare_different_types(self):
+ # object comparison falls back to comparing types
+ if sys.version_info >= (3, 0):
+ # In Python 3, types are unorderable -- nothing to test
+ return
+ if talloc.BaseObject < _test_pytalloc.DBaseObject:
+ obj1 = _test_pytalloc.base_new()
+ obj2 = _test_pytalloc.DBaseObject(dummy_func)
+ else:
+ obj2 = _test_pytalloc.base_new()
+ obj1 = _test_pytalloc.DBaseObject(dummy_func)
+ self.assertFalse(obj1 == obj2)
+ self.assertTrue(obj1 != obj2)
+ self.assertTrue(obj1 <= obj2)
+ self.assertTrue(obj1 < obj2)
+ self.assertFalse(obj1 >= obj2)
+ self.assertFalse(obj1 > obj2)
+
+
+class TallocUtilTests(unittest.TestCase):
+
+ def test_get_type(self):
+ self.assertTrue(talloc.Object is _test_pytalloc.get_object_type())
+
+ def test_reference(self):
+ # Check correct lifetime of the talloc'd data with multiple references
+ lst = []
+ obj = _test_pytalloc.DObject(lambda: lst.append('dead'))
+ ref = _test_pytalloc.reference(obj)
+ del obj
+ gc.collect()
+ self.assertEqual(lst, [])
+ del ref
+ gc.collect()
+ self.assertEqual(lst, ['dead'])
+
+ def test_get_base_type(self):
+ self.assertTrue(talloc.BaseObject is _test_pytalloc.base_get_object_type())
+
+ def test_base_reference(self):
+ # Check correct lifetime of the talloc'd data with multiple references
+ lst = []
+ obj = _test_pytalloc.DBaseObject(lambda: lst.append('dead'))
+ ref = _test_pytalloc.base_reference(obj)
+ del obj
+ gc.collect()
+ self.assertEqual(lst, [])
+ del ref
+ gc.collect()
+ self.assertEqual(lst, ['dead'])
+
+
+if __name__ == '__main__':
+ unittest.TestProgram()
diff --git a/lib/talloc/testsuite.c b/lib/talloc/testsuite.c
new file mode 100644
index 0000000..282ebc6
--- /dev/null
+++ b/lib/talloc/testsuite.c
@@ -0,0 +1,2288 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ local testing of talloc routines.
+
+ Copyright (C) Andrew Tridgell 2004
+
+ ** 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 3 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
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "system/time.h"
+#include <talloc.h>
+
+#ifdef HAVE_PTHREAD
+#include <pthread.h>
+#endif
+
+#include <unistd.h>
+#include <sys/wait.h>
+
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+#include <assert.h>
+
+#include "talloc_testsuite.h"
+
+static struct timeval private_timeval_current(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return tv;
+}
+
+static double private_timeval_elapsed(struct timeval *tv)
+{
+ struct timeval tv2 = private_timeval_current();
+ return (tv2.tv_sec - tv->tv_sec) +
+ (tv2.tv_usec - tv->tv_usec)*1.0e-6;
+}
+
+#define torture_assert(test, expr, str) if (!(expr)) { \
+ printf("failure: %s [\n%s: Expression %s failed: %s\n]\n", \
+ test, __location__, #expr, str); \
+ return false; \
+}
+
+#define torture_assert_str_equal(test, arg1, arg2, desc) \
+ if (arg1 == NULL && arg2 == NULL) { /* OK, both NULL == equal */ \
+ } else if (arg1 == NULL || arg2 == NULL) { \
+ return false; \
+ } else if (strcmp(arg1, arg2)) { \
+ printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \
+ test, __location__, arg1, arg2, desc); \
+ return false; \
+ }
+
+#define CHECK_SIZE(test, ptr, tsize) do { \
+ if (talloc_total_size(ptr) != (tsize)) { \
+ printf("failed: %s [\n%s: wrong '%s' tree size: got %u expected %u\n]\n", \
+ test, __location__, #ptr, \
+ (unsigned)talloc_total_size(ptr), \
+ (unsigned)tsize); \
+ talloc_report_full(ptr, stdout); \
+ return false; \
+ } \
+} while (0)
+
+#define CHECK_BLOCKS(test, ptr, tblocks) do { \
+ if (talloc_total_blocks(ptr) != (tblocks)) { \
+ printf("failed: %s [\n%s: wrong '%s' tree blocks: got %u expected %u\n]\n", \
+ test, __location__, #ptr, \
+ (unsigned)talloc_total_blocks(ptr), \
+ (unsigned)tblocks); \
+ talloc_report_full(ptr, stdout); \
+ return false; \
+ } \
+} while (0)
+
+#define CHECK_PARENT(test, ptr, parent) do { \
+ if (talloc_parent(ptr) != (parent)) { \
+ printf("failed: %s [\n%s: '%s' has wrong parent: got %p expected %p\n]\n", \
+ test, __location__, #ptr, \
+ talloc_parent(ptr), \
+ (parent)); \
+ talloc_report_full(ptr, stdout); \
+ talloc_report_full(parent, stdout); \
+ talloc_report_full(NULL, stdout); \
+ return false; \
+ } \
+} while (0)
+
+static unsigned int test_abort_count;
+
+#if 0
+static void test_abort_fn(const char *reason)
+{
+ printf("# test_abort_fn(%s)\n", reason);
+ test_abort_count++;
+}
+
+static void test_abort_start(void)
+{
+ test_abort_count = 0;
+ talloc_set_abort_fn(test_abort_fn);
+}
+#endif
+
+static void test_abort_stop(void)
+{
+ test_abort_count = 0;
+ talloc_set_abort_fn(NULL);
+}
+
+static void test_log_stdout(const char *message)
+{
+ fprintf(stdout, "%s", message);
+}
+
+/*
+ test references
+*/
+static bool test_ref1(void)
+{
+ void *root, *p1, *p2, *ref, *r1;
+
+ printf("test: ref1\n# SINGLE REFERENCE FREE\n");
+
+ root = talloc_named_const(NULL, 0, "root");
+ p1 = talloc_named_const(root, 1, "p1");
+ p2 = talloc_named_const(p1, 1, "p2");
+ talloc_named_const(p1, 1, "x1");
+ talloc_named_const(p1, 2, "x2");
+ talloc_named_const(p1, 3, "x3");
+
+ r1 = talloc_named_const(root, 1, "r1");
+ ref = talloc_reference(r1, p2);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref1", p1, 5);
+ CHECK_BLOCKS("ref1", p2, 1);
+ CHECK_BLOCKS("ref1", ref, 1);
+ CHECK_BLOCKS("ref1", r1, 2);
+
+ fprintf(stderr, "Freeing p2\n");
+ talloc_unlink(r1, p2);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref1", p1, 5);
+ CHECK_BLOCKS("ref1", p2, 1);
+ CHECK_BLOCKS("ref1", r1, 1);
+
+ fprintf(stderr, "Freeing p1\n");
+ talloc_free(p1);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref1", r1, 1);
+
+ fprintf(stderr, "Freeing r1\n");
+ talloc_free(r1);
+ talloc_report_full(NULL, stderr);
+
+ fprintf(stderr, "Testing NULL\n");
+ if (talloc_reference(root, NULL)) {
+ return false;
+ }
+
+ CHECK_BLOCKS("ref1", root, 1);
+
+ CHECK_SIZE("ref1", root, 0);
+
+ talloc_free(root);
+ printf("success: ref1\n");
+ return true;
+}
+
+/*
+ test references
+*/
+static bool test_ref2(void)
+{
+ void *root, *p1, *p2, *ref, *r1;
+
+ printf("test: ref2\n# DOUBLE REFERENCE FREE\n");
+ root = talloc_named_const(NULL, 0, "root");
+ p1 = talloc_named_const(root, 1, "p1");
+ talloc_named_const(p1, 1, "x1");
+ talloc_named_const(p1, 1, "x2");
+ talloc_named_const(p1, 1, "x3");
+ p2 = talloc_named_const(p1, 1, "p2");
+
+ r1 = talloc_named_const(root, 1, "r1");
+ ref = talloc_reference(r1, p2);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref2", p1, 5);
+ CHECK_BLOCKS("ref2", p2, 1);
+ CHECK_BLOCKS("ref2", r1, 2);
+
+ fprintf(stderr, "Freeing ref\n");
+ talloc_unlink(r1, ref);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref2", p1, 5);
+ CHECK_BLOCKS("ref2", p2, 1);
+ CHECK_BLOCKS("ref2", r1, 1);
+
+ fprintf(stderr, "Freeing p2\n");
+ talloc_free(p2);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref2", p1, 4);
+ CHECK_BLOCKS("ref2", r1, 1);
+
+ fprintf(stderr, "Freeing p1\n");
+ talloc_free(p1);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref2", r1, 1);
+
+ fprintf(stderr, "Freeing r1\n");
+ talloc_free(r1);
+ talloc_report_full(root, stderr);
+
+ CHECK_SIZE("ref2", root, 0);
+
+ talloc_free(root);
+ printf("success: ref2\n");
+ return true;
+}
+
+/*
+ test references
+*/
+static bool test_ref3(void)
+{
+ void *root, *p1, *p2, *ref, *r1;
+
+ printf("test: ref3\n# PARENT REFERENCE FREE\n");
+
+ root = talloc_named_const(NULL, 0, "root");
+ p1 = talloc_named_const(root, 1, "p1");
+ p2 = talloc_named_const(root, 1, "p2");
+ r1 = talloc_named_const(p1, 1, "r1");
+ ref = talloc_reference(p2, r1);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref3", p1, 2);
+ CHECK_BLOCKS("ref3", p2, 2);
+ CHECK_BLOCKS("ref3", r1, 1);
+ CHECK_BLOCKS("ref3", ref, 1);
+
+ fprintf(stderr, "Freeing p1\n");
+ talloc_free(p1);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref3", p2, 2);
+ CHECK_BLOCKS("ref3", r1, 1);
+
+ fprintf(stderr, "Freeing p2\n");
+ talloc_free(p2);
+ talloc_report_full(root, stderr);
+
+ CHECK_SIZE("ref3", root, 0);
+
+ talloc_free(root);
+
+ printf("success: ref3\n");
+ return true;
+}
+
+/*
+ test references
+*/
+static bool test_ref4(void)
+{
+ void *root, *p1, *p2, *ref, *r1;
+
+ printf("test: ref4\n# REFERRER REFERENCE FREE\n");
+
+ root = talloc_named_const(NULL, 0, "root");
+ p1 = talloc_named_const(root, 1, "p1");
+ talloc_named_const(p1, 1, "x1");
+ talloc_named_const(p1, 1, "x2");
+ talloc_named_const(p1, 1, "x3");
+ p2 = talloc_named_const(p1, 1, "p2");
+
+ r1 = talloc_named_const(root, 1, "r1");
+ ref = talloc_reference(r1, p2);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref4", p1, 5);
+ CHECK_BLOCKS("ref4", p2, 1);
+ CHECK_BLOCKS("ref4", ref, 1);
+ CHECK_BLOCKS("ref4", r1, 2);
+
+ fprintf(stderr, "Freeing r1\n");
+ talloc_free(r1);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref4", p1, 5);
+ CHECK_BLOCKS("ref4", p2, 1);
+
+ fprintf(stderr, "Freeing p2\n");
+ talloc_free(p2);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref4", p1, 4);
+
+ fprintf(stderr, "Freeing p1\n");
+ talloc_free(p1);
+ talloc_report_full(root, stderr);
+
+ CHECK_SIZE("ref4", root, 0);
+
+ talloc_free(root);
+
+ printf("success: ref4\n");
+ return true;
+}
+
+
+/*
+ test references
+*/
+static bool test_unlink1(void)
+{
+ void *root, *p1, *p2, *ref, *r1;
+
+ printf("test: unlink\n# UNLINK\n");
+
+ root = talloc_named_const(NULL, 0, "root");
+ p1 = talloc_named_const(root, 1, "p1");
+ talloc_named_const(p1, 1, "x1");
+ talloc_named_const(p1, 1, "x2");
+ talloc_named_const(p1, 1, "x3");
+ p2 = talloc_named_const(p1, 1, "p2");
+
+ r1 = talloc_named_const(p1, 1, "r1");
+ ref = talloc_reference(r1, p2);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("unlink", p1, 7);
+ CHECK_BLOCKS("unlink", p2, 1);
+ CHECK_BLOCKS("unlink", ref, 1);
+ CHECK_BLOCKS("unlink", r1, 2);
+
+ fprintf(stderr, "Unreferencing r1\n");
+ talloc_unlink(r1, p2);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("unlink", p1, 6);
+ CHECK_BLOCKS("unlink", p2, 1);
+ CHECK_BLOCKS("unlink", r1, 1);
+
+ fprintf(stderr, "Freeing p1\n");
+ talloc_free(p1);
+ talloc_report_full(root, stderr);
+
+ CHECK_SIZE("unlink", root, 0);
+
+ talloc_free(root);
+
+ printf("success: unlink\n");
+ return true;
+}
+
+static int fail_destructor(void *ptr)
+{
+ return -1;
+}
+
+/*
+ miscellaneous tests to try to get a higher test coverage percentage
+*/
+static bool test_misc(void)
+{
+ void *root, *p1;
+ char *p2;
+ double *d;
+ const char *name;
+
+ printf("test: misc\n# MISCELLANEOUS\n");
+
+ root = talloc_new(NULL);
+
+ p1 = talloc_size(root, 0x7fffffff);
+ torture_assert("misc", !p1, "failed: large talloc allowed\n");
+
+ p1 = talloc_strdup(root, "foo");
+ talloc_increase_ref_count(p1);
+ talloc_increase_ref_count(p1);
+ talloc_increase_ref_count(p1);
+ CHECK_BLOCKS("misc", p1, 1);
+ CHECK_BLOCKS("misc", root, 2);
+ talloc_unlink(NULL, p1);
+ CHECK_BLOCKS("misc", p1, 1);
+ CHECK_BLOCKS("misc", root, 2);
+ talloc_unlink(NULL, p1);
+ CHECK_BLOCKS("misc", p1, 1);
+ CHECK_BLOCKS("misc", root, 2);
+ p2 = talloc_strdup(p1, "foo");
+ torture_assert("misc", talloc_unlink(root, p2) == -1,
+ "failed: talloc_unlink() of non-reference context should return -1\n");
+ torture_assert("misc", talloc_unlink(p1, p2) == 0,
+ "failed: talloc_unlink() of parent should succeed\n");
+ talloc_unlink(NULL, p1);
+ CHECK_BLOCKS("misc", p1, 1);
+ CHECK_BLOCKS("misc", root, 2);
+
+ name = talloc_set_name(p1, "my name is %s", "foo");
+ torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo",
+ "failed: wrong name after talloc_set_name(my name is foo)");
+ torture_assert_str_equal("misc", talloc_get_name(p1), name,
+ "failed: wrong name after talloc_set_name(my name is foo)");
+ CHECK_BLOCKS("misc", p1, 2);
+ CHECK_BLOCKS("misc", root, 3);
+
+ talloc_set_name_const(p1, NULL);
+ torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED",
+ "failed: wrong name after talloc_set_name(NULL)");
+ CHECK_BLOCKS("misc", p1, 2);
+ CHECK_BLOCKS("misc", root, 3);
+
+ torture_assert("misc", talloc_free(NULL) == -1,
+ "talloc_free(NULL) should give -1\n");
+
+ talloc_set_destructor(p1, fail_destructor);
+ torture_assert("misc", talloc_free(p1) == -1,
+ "Failed destructor should cause talloc_free to fail\n");
+ talloc_set_destructor(p1, NULL);
+
+ talloc_report(root, stderr);
+
+
+ p2 = (char *)talloc_zero_size(p1, 20);
+ torture_assert("misc", p2[19] == 0, "Failed to give zero memory\n");
+ talloc_free(p2);
+
+ torture_assert("misc", talloc_strdup(root, NULL) == NULL,
+ "failed: strdup on NULL should give NULL\n");
+
+ p2 = talloc_strndup(p1, "foo", 2);
+ torture_assert("misc", strcmp("fo", p2) == 0,
+ "strndup doesn't work\n");
+ p2 = talloc_asprintf_append_buffer(p2, "o%c", 'd');
+ torture_assert("misc", strcmp("food", p2) == 0,
+ "talloc_asprintf_append_buffer doesn't work\n");
+ CHECK_BLOCKS("misc", p2, 1);
+ CHECK_BLOCKS("misc", p1, 3);
+
+ p2 = talloc_asprintf_append_buffer(NULL, "hello %s", "world");
+ torture_assert("misc", strcmp("hello world", p2) == 0,
+ "talloc_asprintf_append_buffer doesn't work\n");
+ CHECK_BLOCKS("misc", p2, 1);
+ CHECK_BLOCKS("misc", p1, 3);
+ talloc_free(p2);
+
+ d = talloc_array(p1, double, 0x20000000);
+ torture_assert("misc", !d, "failed: integer overflow not detected\n");
+
+ d = talloc_realloc(p1, d, double, 0x20000000);
+ torture_assert("misc", !d, "failed: integer overflow not detected\n");
+
+ talloc_free(p1);
+ CHECK_BLOCKS("misc", root, 1);
+
+ p1 = talloc_named(root, 100, "%d bytes", 100);
+ CHECK_BLOCKS("misc", p1, 2);
+ CHECK_BLOCKS("misc", root, 3);
+ talloc_unlink(root, p1);
+
+ p1 = talloc_init("%d bytes", 200);
+ p2 = talloc_asprintf(p1, "my test '%s'", "string");
+ torture_assert_str_equal("misc", p2, "my test 'string'",
+ "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"");
+ CHECK_BLOCKS("misc", p1, 3);
+ CHECK_SIZE("misc", p2, 17);
+ CHECK_BLOCKS("misc", root, 1);
+ talloc_unlink(NULL, p1);
+
+ p1 = talloc_named_const(root, 10, "p1");
+ p2 = (char *)talloc_named_const(root, 20, "p2");
+ (void)talloc_reference(p1, p2);
+ talloc_report_full(root, stderr);
+ talloc_unlink(root, p2);
+ talloc_report_full(root, stderr);
+ CHECK_BLOCKS("misc", p2, 1);
+ CHECK_BLOCKS("misc", p1, 2);
+ CHECK_BLOCKS("misc", root, 3);
+ talloc_unlink(p1, p2);
+ talloc_unlink(root, p1);
+
+ p1 = talloc_named_const(root, 10, "p1");
+ p2 = (char *)talloc_named_const(root, 20, "p2");
+ (void)talloc_reference(NULL, p2);
+ talloc_report_full(root, stderr);
+ talloc_unlink(root, p2);
+ talloc_report_full(root, stderr);
+ CHECK_BLOCKS("misc", p2, 1);
+ CHECK_BLOCKS("misc", p1, 1);
+ CHECK_BLOCKS("misc", root, 2);
+ talloc_unlink(NULL, p2);
+ talloc_unlink(root, p1);
+
+ /* Test that talloc_unlink is a no-op */
+
+ torture_assert("misc", talloc_unlink(root, NULL) == -1,
+ "failed: talloc_unlink(root, NULL) == -1\n");
+
+ talloc_report(root, stderr);
+ talloc_report(NULL, stderr);
+
+ CHECK_SIZE("misc", root, 0);
+
+ talloc_free(root);
+
+ CHECK_SIZE("misc", NULL, 0);
+
+ talloc_enable_null_tracking_no_autofree();
+ talloc_enable_leak_report();
+ talloc_enable_leak_report_full();
+
+ printf("success: misc\n");
+
+ return true;
+}
+
+
+/*
+ test realloc
+*/
+static bool test_realloc(void)
+{
+ void *root, *p1, *p2;
+
+ printf("test: realloc\n# REALLOC\n");
+
+ root = talloc_new(NULL);
+
+ p1 = talloc_size(root, 10);
+ CHECK_SIZE("realloc", p1, 10);
+
+ p1 = talloc_realloc_size(NULL, p1, 20);
+ CHECK_SIZE("realloc", p1, 20);
+
+ talloc_new(p1);
+
+ p2 = talloc_realloc_size(p1, NULL, 30);
+
+ talloc_new(p1);
+
+ p2 = talloc_realloc_size(p1, p2, 40);
+
+ CHECK_SIZE("realloc", p2, 40);
+ CHECK_SIZE("realloc", root, 60);
+ CHECK_BLOCKS("realloc", p1, 4);
+
+ p1 = talloc_realloc_size(NULL, p1, 20);
+ CHECK_SIZE("realloc", p1, 60);
+
+ talloc_increase_ref_count(p2);
+ torture_assert("realloc", talloc_realloc_size(NULL, p2, 5) == NULL,
+ "failed: talloc_realloc() on a referenced pointer should fail\n");
+ CHECK_BLOCKS("realloc", p1, 4);
+
+ talloc_realloc_size(NULL, p2, 0);
+ talloc_realloc_size(NULL, p2, 0);
+ CHECK_BLOCKS("realloc", p1, 4);
+ talloc_realloc_size(p1, p2, 0);
+ CHECK_BLOCKS("realloc", p1, 3);
+
+ torture_assert("realloc", talloc_realloc_size(NULL, p1, 0x7fffffff) == NULL,
+ "failed: oversize talloc should fail\n");
+
+ talloc_realloc_size(NULL, p1, 0);
+ CHECK_BLOCKS("realloc", root, 4);
+ talloc_realloc_size(root, p1, 0);
+ CHECK_BLOCKS("realloc", root, 1);
+
+ CHECK_SIZE("realloc", root, 0);
+
+ talloc_free(root);
+
+ printf("success: realloc\n");
+
+ return true;
+}
+
+/*
+ test realloc with a child
+*/
+static bool test_realloc_child(void)
+{
+ void *root;
+ struct el2 {
+ const char *name;
+ } *el2, *el2_2, *el2_3, **el_list_save;
+ struct el1 {
+ int count;
+ struct el2 **list, **list2, **list3;
+ } *el1;
+
+ printf("test: REALLOC WITH CHILD\n");
+
+ root = talloc_new(NULL);
+
+ el1 = talloc(root, struct el1);
+ el1->list = talloc(el1, struct el2 *);
+ el1->list[0] = talloc(el1->list, struct el2);
+ el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
+
+ el1->list2 = talloc(el1, struct el2 *);
+ el1->list2[0] = talloc(el1->list2, struct el2);
+ el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2");
+
+ el1->list3 = talloc(el1, struct el2 *);
+ el1->list3[0] = talloc(el1->list3, struct el2);
+ el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
+
+ el2 = talloc(el1->list, struct el2);
+ CHECK_PARENT("el2", el2, el1->list);
+ el2_2 = talloc(el1->list2, struct el2);
+ CHECK_PARENT("el2", el2_2, el1->list2);
+ el2_3 = talloc(el1->list3, struct el2);
+ CHECK_PARENT("el2", el2_3, el1->list3);
+
+ el_list_save = el1->list;
+ el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
+ if (el1->list == el_list_save) {
+ printf("failure: talloc_realloc didn't move pointer");
+ return false;
+ }
+
+ CHECK_PARENT("el1_after_realloc", el1->list, el1);
+ el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
+ CHECK_PARENT("el1_after_realloc", el1->list2, el1);
+ el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
+ CHECK_PARENT("el1_after_realloc", el1->list3, el1);
+
+ CHECK_PARENT("el2", el2, el1->list);
+ CHECK_PARENT("el2", el2_2, el1->list2);
+ CHECK_PARENT("el2", el2_3, el1->list3);
+
+ /* Finally check realloc with multiple children */
+ el1 = talloc_realloc(root, el1, struct el1, 100);
+ CHECK_PARENT("el1->list", el1->list, el1);
+ CHECK_PARENT("el1->list2", el1->list2, el1);
+ CHECK_PARENT("el1->list3", el1->list3, el1);
+
+ talloc_free(root);
+
+ printf("success: REALLOC WITH CHILD\n");
+ return true;
+}
+
+/*
+ test type checking
+*/
+static bool test_type(void)
+{
+ void *root;
+ struct el1 {
+ int count;
+ };
+ struct el2 {
+ int count;
+ };
+ struct el1 *el1;
+
+ printf("test: type\n# talloc type checking\n");
+
+ root = talloc_new(NULL);
+
+ el1 = talloc(root, struct el1);
+
+ el1->count = 1;
+
+ torture_assert("type", talloc_get_type(el1, struct el1) == el1,
+ "type check failed on el1\n");
+ torture_assert("type", talloc_get_type(el1, struct el2) == NULL,
+ "type check failed on el1 with el2\n");
+ talloc_set_type(el1, struct el2);
+ torture_assert("type", talloc_get_type(el1, struct el2) == (struct el2 *)el1,
+ "type set failed on el1 with el2\n");
+
+ talloc_free(root);
+
+ printf("success: type\n");
+ return true;
+}
+
+/*
+ test steal
+*/
+static bool test_steal(void)
+{
+ void *root, *p1, *p2;
+
+ printf("test: steal\n# STEAL\n");
+
+ root = talloc_new(NULL);
+
+ p1 = talloc_array(root, char, 10);
+ CHECK_SIZE("steal", p1, 10);
+
+ p2 = talloc_realloc(root, NULL, char, 20);
+ CHECK_SIZE("steal", p1, 10);
+ CHECK_SIZE("steal", root, 30);
+
+ torture_assert("steal", talloc_steal(p1, NULL) == NULL,
+ "failed: stealing NULL should give NULL\n");
+
+ torture_assert("steal", talloc_steal(p1, p1) == p1,
+ "failed: stealing to ourselves is a nop\n");
+ CHECK_BLOCKS("steal", root, 3);
+ CHECK_SIZE("steal", root, 30);
+
+ talloc_steal(NULL, p1);
+ talloc_steal(NULL, p2);
+ CHECK_BLOCKS("steal", root, 1);
+ CHECK_SIZE("steal", root, 0);
+
+ talloc_free(p1);
+ talloc_steal(root, p2);
+ CHECK_BLOCKS("steal", root, 2);
+ CHECK_SIZE("steal", root, 20);
+
+ talloc_free(p2);
+
+ CHECK_BLOCKS("steal", root, 1);
+ CHECK_SIZE("steal", root, 0);
+
+ talloc_free(root);
+
+ p1 = talloc_size(NULL, 3);
+ talloc_report_full(NULL, stderr);
+ CHECK_SIZE("steal", NULL, 3);
+ talloc_free(p1);
+
+ printf("success: steal\n");
+ return true;
+}
+
+/*
+ test move
+*/
+static bool test_move(void)
+{
+ void *root;
+ struct t_move {
+ char *p;
+ int *x;
+ } *t1, *t2;
+
+ printf("test: move\n# MOVE\n");
+
+ root = talloc_new(NULL);
+
+ t1 = talloc(root, struct t_move);
+ t2 = talloc(root, struct t_move);
+ t1->p = talloc_strdup(t1, "foo");
+ t1->x = talloc(t1, int);
+ *t1->x = 42;
+
+ t2->p = talloc_move(t2, &t1->p);
+ t2->x = talloc_move(t2, &t1->x);
+ torture_assert("move", t1->p == NULL && t1->x == NULL &&
+ strcmp(t2->p, "foo") == 0 && *t2->x == 42,
+ "talloc move failed");
+
+ talloc_free(root);
+
+ printf("success: move\n");
+
+ return true;
+}
+
+/*
+ test talloc_realloc_fn
+*/
+static bool test_realloc_fn(void)
+{
+ void *root, *p1;
+
+ printf("test: realloc_fn\n# talloc_realloc_fn\n");
+
+ root = talloc_new(NULL);
+
+ p1 = talloc_realloc_fn(root, NULL, 10);
+ CHECK_BLOCKS("realloc_fn", root, 2);
+ CHECK_SIZE("realloc_fn", root, 10);
+ p1 = talloc_realloc_fn(root, p1, 20);
+ CHECK_BLOCKS("realloc_fn", root, 2);
+ CHECK_SIZE("realloc_fn", root, 20);
+ p1 = talloc_realloc_fn(root, p1, 0);
+ CHECK_BLOCKS("realloc_fn", root, 1);
+ CHECK_SIZE("realloc_fn", root, 0);
+
+ talloc_free(root);
+
+ printf("success: realloc_fn\n");
+ return true;
+}
+
+
+static bool test_unref_reparent(void)
+{
+ void *root, *p1, *p2, *c1;
+
+ printf("test: unref_reparent\n# UNREFERENCE AFTER PARENT FREED\n");
+
+ root = talloc_named_const(NULL, 0, "root");
+ p1 = talloc_named_const(root, 1, "orig parent");
+ p2 = talloc_named_const(root, 1, "parent by reference");
+
+ c1 = talloc_named_const(p1, 1, "child");
+ talloc_reference(p2, c1);
+
+ CHECK_PARENT("unref_reparent", c1, p1);
+
+ talloc_free(p1);
+
+ CHECK_PARENT("unref_reparent", c1, p2);
+
+ talloc_unlink(p2, c1);
+
+ CHECK_SIZE("unref_reparent", root, 1);
+
+ talloc_free(p2);
+ talloc_free(root);
+
+ printf("success: unref_reparent\n");
+ return true;
+}
+
+/*
+ measure the speed of talloc versus malloc
+*/
+static bool test_speed(void)
+{
+ void *ctx = talloc_new(NULL);
+ unsigned count;
+ const int loop = 1000;
+ int i;
+ struct timeval tv;
+
+ printf("test: speed\n# TALLOC VS MALLOC SPEED\n");
+
+ tv = private_timeval_current();
+ count = 0;
+ do {
+ void *p1, *p2, *p3;
+ for (i=0;i<loop;i++) {
+ p1 = talloc_size(ctx, loop % 100);
+ p2 = talloc_strdup(p1, "foo bar");
+ p3 = talloc_size(p1, 300);
+ (void)p2;
+ (void)p3;
+ talloc_free(p1);
+ }
+ count += 3 * loop;
+ } while (private_timeval_elapsed(&tv) < 5.0);
+
+ fprintf(stderr, "talloc: %.0f ops/sec\n", count/private_timeval_elapsed(&tv));
+
+ talloc_free(ctx);
+
+ ctx = talloc_pool(NULL, 1024);
+
+ tv = private_timeval_current();
+ count = 0;
+ do {
+ void *p1, *p2, *p3;
+ for (i=0;i<loop;i++) {
+ p1 = talloc_size(ctx, loop % 100);
+ p2 = talloc_strdup(p1, "foo bar");
+ p3 = talloc_size(p1, 300);
+ (void)p2;
+ (void)p3;
+ talloc_free(p1);
+ }
+ count += 3 * loop;
+ } while (private_timeval_elapsed(&tv) < 5.0);
+
+ talloc_free(ctx);
+
+ fprintf(stderr, "talloc_pool: %.0f ops/sec\n", count/private_timeval_elapsed(&tv));
+
+ tv = private_timeval_current();
+ count = 0;
+ do {
+ void *p1, *p2, *p3;
+ for (i=0;i<loop;i++) {
+ p1 = malloc(loop % 100);
+ p2 = strdup("foo bar");
+ p3 = malloc(300);
+ free(p1);
+ free(p2);
+ free(p3);
+ }
+ count += 3 * loop;
+ } while (private_timeval_elapsed(&tv) < 5.0);
+ fprintf(stderr, "malloc: %.0f ops/sec\n", count/private_timeval_elapsed(&tv));
+
+ printf("success: speed\n");
+
+ return true;
+}
+
+static bool test_lifeless(void)
+{
+ void *top = talloc_new(NULL);
+ char *parent, *child;
+ void *child_owner = talloc_new(NULL);
+
+ printf("test: lifeless\n# TALLOC_UNLINK LOOP\n");
+
+ parent = talloc_strdup(top, "parent");
+ child = talloc_strdup(parent, "child");
+ (void)talloc_reference(child, parent);
+ (void)talloc_reference(child_owner, child);
+ talloc_report_full(top, stderr);
+ talloc_unlink(top, parent);
+ talloc_unlink(top, child);
+ talloc_report_full(top, stderr);
+ talloc_free(top);
+ talloc_free(child_owner);
+ talloc_free(child);
+
+ printf("success: lifeless\n");
+ return true;
+}
+
+static int loop_destructor_count;
+
+static int test_loop_destructor(char *ptr)
+{
+ loop_destructor_count++;
+ return 0;
+}
+
+static bool test_loop(void)
+{
+ void *top = talloc_new(NULL);
+ char *parent;
+ struct req1 {
+ char *req2, *req3;
+ } *req1;
+
+ printf("test: loop\n# TALLOC LOOP DESTRUCTION\n");
+
+ parent = talloc_strdup(top, "parent");
+ req1 = talloc(parent, struct req1);
+ req1->req2 = talloc_strdup(req1, "req2");
+ talloc_set_destructor(req1->req2, test_loop_destructor);
+ req1->req3 = talloc_strdup(req1, "req3");
+ (void)talloc_reference(req1->req3, req1);
+ talloc_report_full(top, stderr);
+ talloc_free(parent);
+ talloc_report_full(top, stderr);
+ talloc_report_full(NULL, stderr);
+ talloc_free(top);
+
+ torture_assert("loop", loop_destructor_count == 1,
+ "FAILED TO FIRE LOOP DESTRUCTOR\n");
+ loop_destructor_count = 0;
+
+ printf("success: loop\n");
+ return true;
+}
+
+static int realloc_parent_destructor_count;
+
+static int test_realloc_parent_destructor(char *ptr)
+{
+ realloc_parent_destructor_count++;
+ return 0;
+}
+
+static bool test_realloc_on_destructor_parent(void)
+{
+ void *top = talloc_new(NULL);
+ char *parent;
+ char *a, *b, *C, *D;
+ realloc_parent_destructor_count = 0;
+
+ printf("test: free_for_exit\n# TALLOC FREE FOR EXIT\n");
+
+ parent = talloc_strdup(top, "parent");
+ a = talloc_strdup(parent, "a");
+ b = talloc_strdup(a, "b");
+ C = talloc_strdup(a, "C");
+ D = talloc_strdup(b, "D");
+ talloc_set_destructor(D, test_realloc_parent_destructor);
+ /* Capitalised ones have destructors.
+ *
+ * parent --> a -> b -> D
+ * -> c
+ */
+
+ a = talloc_realloc(parent, a, char, 2048);
+
+ torture_assert("check talloc_realloc", a != NULL, "talloc_realloc failed");
+
+ talloc_set_destructor(C, test_realloc_parent_destructor);
+ /*
+ * parent --> a[2048] -> b -> D
+ * -> C
+ *
+ */
+
+ talloc_free(parent);
+
+ torture_assert("check destructor realloc_parent_destructor",
+ realloc_parent_destructor_count == 2,
+ "FAILED TO FIRE free_for_exit_destructor\n");
+
+
+ printf("success: free_for_exit\n");
+ talloc_free(top); /* make ASAN happy */
+
+ return true;
+}
+
+static int fail_destructor_str(char *ptr)
+{
+ return -1;
+}
+
+static bool test_free_parent_deny_child(void)
+{
+ void *top = talloc_new(NULL);
+ char *level1;
+ char *level2;
+ char *level3;
+
+ printf("test: free_parent_deny_child\n# TALLOC FREE PARENT DENY CHILD\n");
+
+ level1 = talloc_strdup(top, "level1");
+ level2 = talloc_strdup(level1, "level2");
+ level3 = talloc_strdup(level2, "level3");
+
+ talloc_set_destructor(level3, fail_destructor_str);
+ talloc_free(level1);
+ talloc_set_destructor(level3, NULL);
+
+ CHECK_PARENT("free_parent_deny_child", level3, top);
+
+ talloc_free(top);
+
+ printf("success: free_parent_deny_child\n");
+ return true;
+}
+
+struct new_parent {
+ void *new_parent;
+ char val[20];
+};
+
+static int reparenting_destructor(struct new_parent *np)
+{
+ talloc_set_destructor(np, NULL);
+ (void)talloc_move(np->new_parent, &np);
+ return -1;
+}
+
+static bool test_free_parent_reparent_child(void)
+{
+ void *top = talloc_new(NULL);
+ char *level1;
+ char *alternate_level1;
+ char *level2;
+ struct new_parent *level3;
+
+ printf("test: free_parent_reparent_child\n# "
+ "TALLOC FREE PARENT REPARENT CHILD\n");
+
+ level1 = talloc_strdup(top, "level1");
+ alternate_level1 = talloc_strdup(top, "alternate_level1");
+ level2 = talloc_strdup(level1, "level2");
+ level3 = talloc(level2, struct new_parent);
+ level3->new_parent = alternate_level1;
+ memset(level3->val, 'x', sizeof(level3->val));
+
+ talloc_set_destructor(level3, reparenting_destructor);
+ talloc_free(level1);
+
+ CHECK_PARENT("free_parent_reparent_child",
+ level3, alternate_level1);
+
+ talloc_free(top);
+
+ printf("success: free_parent_reparent_child\n");
+ return true;
+}
+
+static bool test_free_parent_reparent_child_in_pool(void)
+{
+ void *top = talloc_new(NULL);
+ char *level1;
+ char *alternate_level1;
+ char *level2;
+ void *pool;
+ struct new_parent *level3;
+
+ printf("test: free_parent_reparent_child_in_pool\n# "
+ "TALLOC FREE PARENT REPARENT CHILD IN POOL\n");
+
+ pool = talloc_pool(top, 1024);
+ level1 = talloc_strdup(pool, "level1");
+ alternate_level1 = talloc_strdup(top, "alternate_level1");
+ level2 = talloc_strdup(level1, "level2");
+ level3 = talloc(level2, struct new_parent);
+ level3->new_parent = alternate_level1;
+ memset(level3->val, 'x', sizeof(level3->val));
+
+ talloc_set_destructor(level3, reparenting_destructor);
+ talloc_free(level1);
+ talloc_set_destructor(level3, NULL);
+
+ CHECK_PARENT("free_parent_reparent_child_in_pool",
+ level3, alternate_level1);
+
+ /* Even freeing alternate_level1 should leave pool alone. */
+ talloc_free(alternate_level1);
+ talloc_free(top);
+
+ printf("success: free_parent_reparent_child_in_pool\n");
+ return true;
+}
+
+
+static bool test_talloc_ptrtype(void)
+{
+ void *top = talloc_new(NULL);
+ struct struct1 {
+ int foo;
+ int bar;
+ } *s1, *s2, **s3, ***s4;
+ const char *location1;
+ const char *location2;
+ const char *location3;
+ const char *location4;
+
+ printf("test: ptrtype\n# TALLOC PTRTYPE\n");
+
+ s1 = talloc_ptrtype(top, s1);location1 = __location__;
+
+ if (talloc_get_size(s1) != sizeof(struct struct1)) {
+ printf("failure: ptrtype [\n"
+ "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n"
+ "]\n", (unsigned long)talloc_get_size(s1),
+ (unsigned long)sizeof(struct struct1));
+ return false;
+ }
+
+ if (strcmp(location1, talloc_get_name(s1)) != 0) {
+ printf("failure: ptrtype [\n"
+ "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
+ talloc_get_name(s1), location1);
+ return false;
+ }
+
+ s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__;
+
+ if (talloc_get_size(s2) != (sizeof(struct struct1) * 10)) {
+ printf("failure: ptrtype [\n"
+ "talloc_array_ptrtype() allocated the wrong size "
+ "%lu (should be %lu)\n]\n",
+ (unsigned long)talloc_get_size(s2),
+ (unsigned long)(sizeof(struct struct1)*10));
+ return false;
+ }
+
+ if (strcmp(location2, talloc_get_name(s2)) != 0) {
+ printf("failure: ptrtype [\n"
+ "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
+ talloc_get_name(s2), location2);
+ return false;
+ }
+
+ s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__;
+
+ if (talloc_get_size(s3) != (sizeof(struct struct1 *) * 10)) {
+ printf("failure: ptrtype [\n"
+ "talloc_array_ptrtype() allocated the wrong size "
+ "%lu (should be %lu)\n]\n",
+ (unsigned long)talloc_get_size(s3),
+ (unsigned long)(sizeof(struct struct1 *)*10));
+ return false;
+ }
+
+ torture_assert_str_equal("ptrtype", location3, talloc_get_name(s3),
+ "talloc_array_ptrtype() sets the wrong name");
+
+ s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__;
+
+ if (talloc_get_size(s4) != (sizeof(struct struct1 **) * 10)) {
+ printf("failure: ptrtype [\n"
+ "talloc_array_ptrtype() allocated the wrong size "
+ "%lu (should be %lu)\n]\n",
+ (unsigned long)talloc_get_size(s4),
+ (unsigned long)(sizeof(struct struct1 **)*10));
+ return false;
+ }
+
+ torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4),
+ "talloc_array_ptrtype() sets the wrong name");
+
+ talloc_free(top);
+
+ printf("success: ptrtype\n");
+ return true;
+}
+
+static int _test_talloc_free_in_destructor(void **ptr)
+{
+ talloc_free(*ptr);
+ return 0;
+}
+
+static bool test_talloc_free_in_destructor(void)
+{
+ void *level0;
+ void *level1;
+ void *level2;
+ void *level3;
+ void *level4;
+ void **level5;
+
+ printf("test: free_in_destructor\n# TALLOC FREE IN DESTRUCTOR\n");
+
+ level0 = talloc_new(NULL);
+ level1 = talloc_new(level0);
+ level2 = talloc_new(level1);
+ level3 = talloc_new(level2);
+ level4 = talloc_new(level3);
+ level5 = talloc(level4, void *);
+
+ *level5 = level3;
+ (void)talloc_reference(level0, level3);
+ (void)talloc_reference(level3, level3);
+ (void)talloc_reference(level5, level3);
+
+ talloc_set_destructor(level5, _test_talloc_free_in_destructor);
+
+ talloc_free(level1);
+
+ talloc_free(level0);
+
+ talloc_free(level3); /* make ASAN happy */
+
+ printf("success: free_in_destructor\n");
+ return true;
+}
+
+static bool test_autofree(void)
+{
+#if _SAMBA_BUILD_ < 4
+ /* autofree test would kill smbtorture */
+ void *p;
+ printf("test: autofree\n# TALLOC AUTOFREE CONTEXT\n");
+
+ p = talloc_autofree_context();
+ talloc_free(p);
+
+ p = talloc_autofree_context();
+ talloc_free(p);
+
+ printf("success: autofree\n");
+#endif
+ return true;
+}
+
+static bool test_pool(void)
+{
+ void *pool;
+ void *p1, *p2, *p3, *p4;
+ void *p2_2;
+
+ pool = talloc_pool(NULL, 1024);
+
+ p1 = talloc_size(pool, 80);
+ memset(p1, 0x11, talloc_get_size(p1));
+ p2 = talloc_size(pool, 20);
+ memset(p2, 0x11, talloc_get_size(p2));
+ p3 = talloc_size(p1, 50);
+ memset(p3, 0x11, talloc_get_size(p3));
+ p4 = talloc_size(p3, 1000);
+ memset(p4, 0x11, talloc_get_size(p4));
+
+ p2_2 = talloc_realloc_size(pool, p2, 20+1);
+ torture_assert("pool realloc 20+1", p2_2 == p2, "failed: pointer changed");
+ memset(p2, 0x11, talloc_get_size(p2));
+ p2_2 = talloc_realloc_size(pool, p2, 20-1);
+ torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
+ memset(p2, 0x11, talloc_get_size(p2));
+ p2_2 = talloc_realloc_size(pool, p2, 20-1);
+ torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
+ memset(p2, 0x11, talloc_get_size(p2));
+
+ talloc_free(p3);
+
+ /* this should reclaim the memory of p4 and p3 */
+ p2_2 = talloc_realloc_size(pool, p2, 400);
+ torture_assert("pool realloc 400", p2_2 == p2, "failed: pointer changed");
+ memset(p2, 0x11, talloc_get_size(p2));
+
+ talloc_free(p1);
+
+ /* this should reclaim the memory of p1 */
+ p2_2 = talloc_realloc_size(pool, p2, 800);
+ torture_assert("pool realloc 800", p2_2 == p1, "failed: pointer not changed");
+ p2 = p2_2;
+ memset(p2, 0x11, talloc_get_size(p2));
+
+ /* this should do a malloc */
+ p2_2 = talloc_realloc_size(pool, p2, 1800);
+ torture_assert("pool realloc 1800", p2_2 != p2, "failed: pointer not changed");
+ p2 = p2_2;
+ memset(p2, 0x11, talloc_get_size(p2));
+
+ /* this should reclaim the memory from the pool */
+ p3 = talloc_size(pool, 80);
+ torture_assert("pool alloc 80", p3 == p1, "failed: pointer changed");
+ memset(p3, 0x11, talloc_get_size(p3));
+
+ talloc_free(p2);
+ talloc_free(p3);
+
+ p1 = talloc_size(pool, 80);
+ memset(p1, 0x11, talloc_get_size(p1));
+ p2 = talloc_size(pool, 20);
+ memset(p2, 0x11, talloc_get_size(p2));
+
+ talloc_free(p1);
+
+ p2_2 = talloc_realloc_size(pool, p2, 20-1);
+ torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
+ memset(p2, 0x11, talloc_get_size(p2));
+ p2_2 = talloc_realloc_size(pool, p2, 20-1);
+ torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
+ memset(p2, 0x11, talloc_get_size(p2));
+
+ /* this should do a malloc */
+ p2_2 = talloc_realloc_size(pool, p2, 1800);
+ torture_assert("pool realloc 1800", p2_2 != p2, "failed: pointer not changed");
+ p2 = p2_2;
+ memset(p2, 0x11, talloc_get_size(p2));
+
+ /* this should reclaim the memory from the pool */
+ p3 = talloc_size(pool, 800);
+ torture_assert("pool alloc 800", p3 == p1, "failed: pointer changed");
+ memset(p3, 0x11, talloc_get_size(p3));
+
+ talloc_free(pool);
+
+ return true;
+}
+
+static bool test_pool_steal(void)
+{
+ void *root;
+ void *pool;
+ void *p1, *p2;
+ void *p1_2, *p2_2;
+ size_t hdr;
+ size_t ofs1, ofs2;
+
+ root = talloc_new(NULL);
+ pool = talloc_pool(root, 1024);
+
+ p1 = talloc_size(pool, 4 * 16);
+ torture_assert("pool allocate 4 * 16", p1 != NULL, "failed ");
+ memset(p1, 0x11, talloc_get_size(p1));
+ p2 = talloc_size(pool, 4 * 16);
+ torture_assert("pool allocate 4 * 16", p2 > p1, "failed: !(p2 > p1) ");
+ memset(p2, 0x11, talloc_get_size(p2));
+
+ ofs1 = PTR_DIFF(p2, p1);
+ hdr = ofs1 - talloc_get_size(p1);
+
+ talloc_steal(root, p1);
+ talloc_steal(root, p2);
+
+ talloc_free(pool);
+
+ p1_2 = p1;
+
+ p1_2 = talloc_realloc_size(root, p1, 5 * 16);
+ torture_assert("pool realloc 5 * 16", p1_2 > p2, "failed: pointer not changed");
+ memset(p1_2, 0x11, talloc_get_size(p1_2));
+ ofs1 = PTR_DIFF(p1_2, p2);
+ ofs2 = talloc_get_size(p2) + hdr;
+
+ torture_assert("pool realloc ", ofs1 == ofs2, "failed: pointer offset unexpected");
+
+ p2_2 = talloc_realloc_size(root, p2, 3 * 16);
+ torture_assert("pool realloc 5 * 16", p2_2 == p2, "failed: pointer changed");
+ memset(p2_2, 0x11, talloc_get_size(p2_2));
+
+ talloc_free(p1_2);
+
+ p2_2 = p2;
+
+ /* now we should reclaim the full pool */
+ p2_2 = talloc_realloc_size(root, p2, 8 * 16);
+ torture_assert("pool realloc 8 * 16", p2_2 == p1, "failed: pointer not expected");
+ p2 = p2_2;
+ memset(p2_2, 0x11, talloc_get_size(p2_2));
+
+ /* now we malloc and free the full pool space */
+ p2_2 = talloc_realloc_size(root, p2, 2 * 1024);
+ torture_assert("pool realloc 2 * 1024", p2_2 != p1, "failed: pointer not expected");
+ memset(p2_2, 0x11, talloc_get_size(p2_2));
+
+ talloc_free(p2_2);
+
+ talloc_free(root);
+
+ return true;
+}
+
+static bool test_pool_nest(void)
+{
+ void *p1, *p2, *p3;
+ void *e = talloc_new(NULL);
+
+ p1 = talloc_pool(NULL, 1024);
+ torture_assert("talloc_pool", p1 != NULL, "failed");
+
+ p2 = talloc_pool(p1, 500);
+ torture_assert("talloc_pool", p2 != NULL, "failed");
+
+ p3 = talloc_size(p2, 10);
+
+ talloc_steal(e, p3);
+
+ talloc_free(p2);
+
+ talloc_free(p3);
+
+ talloc_free(p1);
+
+ talloc_free(e); /* make ASAN happy */
+
+ return true;
+}
+
+struct pooled {
+ char *s1;
+ char *s2;
+ char *s3;
+};
+
+static bool test_pooled_object(void)
+{
+ struct pooled *p;
+ const char *s1 = "hello";
+ const char *s2 = "world";
+ const char *s3 = "";
+
+ p = talloc_pooled_object(NULL, struct pooled, 3,
+ strlen(s1)+strlen(s2)+strlen(s3)+3);
+
+ if (talloc_get_size(p) != sizeof(struct pooled)) {
+ return false;
+ }
+
+ p->s1 = talloc_strdup(p, s1);
+
+ TALLOC_FREE(p->s1);
+ p->s1 = talloc_strdup(p, s2);
+ TALLOC_FREE(p->s1);
+
+ p->s1 = talloc_strdup(p, s1);
+ p->s2 = talloc_strdup(p, s2);
+ p->s3 = talloc_strdup(p, s3);
+
+ TALLOC_FREE(p);
+ return true;
+}
+
+static bool test_free_ref_null_context(void)
+{
+ void *p1, *p2, *p3;
+ int ret;
+
+ talloc_disable_null_tracking();
+ p1 = talloc_new(NULL);
+ p2 = talloc_new(NULL);
+
+ p3 = talloc_reference(p2, p1);
+ torture_assert("reference", p3 == p1, "failed: reference on null");
+
+ ret = talloc_free(p1);
+ torture_assert("ref free with null parent", ret == 0, "failed: free with null parent");
+ talloc_free(p2);
+
+ talloc_enable_null_tracking_no_autofree();
+ p1 = talloc_new(NULL);
+ p2 = talloc_new(NULL);
+
+ p3 = talloc_reference(p2, p1);
+ torture_assert("reference", p3 == p1, "failed: reference on null");
+
+ ret = talloc_free(p1);
+ torture_assert("ref free with null tracked parent", ret == 0, "failed: free with null parent");
+ talloc_free(p2);
+
+ return true;
+}
+
+static bool test_rusty(void)
+{
+ void *root;
+ char *p1;
+
+ talloc_enable_null_tracking();
+ root = talloc_new(NULL);
+ p1 = talloc_strdup(root, "foo");
+ talloc_increase_ref_count(p1);
+ talloc_report_full(root, stdout);
+ talloc_free(root);
+ CHECK_BLOCKS("null_context", NULL, 2);
+ talloc_free(p1); /* make ASAN happy */
+
+ return true;
+}
+
+static bool test_free_children(void)
+{
+ void *root;
+ char *p1, *p2;
+ const char *name, *name2;
+
+ talloc_enable_null_tracking();
+ root = talloc_new(NULL);
+ p1 = talloc_strdup(root, "foo1");
+ p2 = talloc_strdup(p1, "foo2");
+ (void)p2;
+
+ talloc_set_name(p1, "%s", "testname");
+ talloc_free_children(p1);
+ /* check its still a valid talloc ptr */
+ talloc_get_size(talloc_get_name(p1));
+ if (strcmp(talloc_get_name(p1), "testname") != 0) {
+ return false;
+ }
+
+ talloc_set_name(p1, "%s", "testname");
+ name = talloc_get_name(p1);
+ talloc_free_children(p1);
+ /* check its still a valid talloc ptr */
+ talloc_get_size(talloc_get_name(p1));
+ torture_assert("name", name == talloc_get_name(p1), "name ptr changed");
+ torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname") == 0,
+ "wrong name");
+ CHECK_BLOCKS("name1", p1, 2);
+
+ /* note that this does not free the old child name */
+ talloc_set_name_const(p1, "testname2");
+ name2 = talloc_get_name(p1);
+ /* but this does */
+ talloc_free_children(p1);
+ (void)name2;
+ torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname2") == 0,
+ "wrong name");
+ CHECK_BLOCKS("name1", p1, 1);
+
+ talloc_report_full(root, stdout);
+ talloc_free(root);
+ return true;
+}
+
+static bool test_memlimit(void)
+{
+ void *root;
+ char *l1, *l2, *l3, *l4, *l5, *t;
+ char *pool;
+ int i;
+
+ printf("test: memlimit\n# MEMORY LIMITS\n");
+
+ printf("==== talloc_new(NULL)\n");
+ root = talloc_new(NULL);
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_size(root, 2048)\n");
+ l1 = talloc_size(root, 2048);
+ torture_assert("memlimit", l1 != NULL,
+ "failed: alloc should not fail due to memory limit\n");
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_free(l1)\n");
+ talloc_free(l1);
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_strdup(root, level 1)\n");
+ l1 = talloc_strdup(root, "level 1");
+ torture_assert("memlimit", l1 != NULL,
+ "failed: alloc should not fail due to memory limit\n");
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_set_memlimit(l1, 2048)\n");
+ torture_assert("memlimit", talloc_set_memlimit(l1, 2048) == 0,
+ "failed: setting memlimit should never fail\n");
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_size(root, 2048)\n");
+ l2 = talloc_size(l1, 2048);
+ torture_assert("memlimit", l2 == NULL,
+ "failed: alloc should fail due to memory limit\n");
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_strdup(l1, level 2)\n");
+ l2 = talloc_strdup(l1, "level 2");
+ torture_assert("memlimit", l2 != NULL,
+ "failed: alloc should not fail due to memory limit\n");
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_free(l2)\n");
+ talloc_free(l2);
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_size(NULL, 2048)\n");
+ l2 = talloc_size(NULL, 2048);
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_steal(l1, l2)\n");
+ talloc_steal(l1, l2);
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_strdup(l2, level 3)\n");
+ l3 = talloc_strdup(l2, "level 3");
+ torture_assert("memlimit", l3 == NULL,
+ "failed: alloc should fail due to memory limit\n");
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_free(l2)\n");
+ talloc_free(l2);
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_strdup(NULL, level 2)\n");
+ l2 = talloc_strdup(NULL, "level 2");
+ talloc_steal(l1, l2);
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_strdup(l2, level 3)\n");
+ l3 = talloc_strdup(l2, "level 3");
+ torture_assert("memlimit", l3 != NULL,
+ "failed: alloc should not fail due to memory limit\n");
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_set_memlimit(l3, 1024)\n");
+ torture_assert("memlimit", talloc_set_memlimit(l3, 1024) == 0,
+ "failed: setting memlimit should never fail\n");
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_strdup(l3, level 4)\n");
+ l4 = talloc_strdup(l3, "level 4");
+ torture_assert("memlimit", l4 != NULL,
+ "failed: alloc should not fail due to memory limit\n");
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_set_memlimit(l4, 512)\n");
+ torture_assert("memlimit", talloc_set_memlimit(l4, 512) == 0,
+ "failed: setting memlimit should never fail\n");
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_strdup(l4, level 5)\n");
+ l5 = talloc_strdup(l4, "level 5");
+ torture_assert("memlimit", l5 != NULL,
+ "failed: alloc should not fail due to memory limit\n");
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_realloc(NULL, l5, char, 600)\n");
+ t = talloc_realloc(NULL, l5, char, 600);
+ torture_assert("memlimit", t == NULL,
+ "failed: alloc should fail due to memory limit\n");
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_realloc(NULL, l5, char, 5)\n");
+ l5 = talloc_realloc(NULL, l5, char, 5);
+ torture_assert("memlimit", l5 != NULL,
+ "failed: alloc should not fail due to memory limit\n");
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_strdup(l3, level 4)\n");
+ l4 = talloc_strdup(l3, "level 4");
+ torture_assert("memlimit", l4 != NULL,
+ "failed: alloc should not fail due to memory limit\n");
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_set_memlimit(l4, 512)\n");
+ torture_assert("memlimit", talloc_set_memlimit(l4, 512) == 0,
+ "failed: setting memlimit should never fail\n");
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_strdup(l4, level 5)\n");
+ l5 = talloc_strdup(l4, "level 5");
+ torture_assert("memlimit", l5 != NULL,
+ "failed: alloc should not fail due to memory limit\n");
+
+ talloc_report_full(root, stdout);
+
+ printf("==== Make new temp context and steal l5\n");
+ t = talloc_new(root);
+ talloc_steal(t, l5);
+
+ talloc_report_full(root, stdout);
+
+ printf("==== talloc_size(t, 2048)\n");
+ l1 = talloc_size(t, 2048);
+ torture_assert("memlimit", l1 != NULL,
+ "failed: alloc should not fail due to memory limit\n");
+
+ talloc_report_full(root, stdout);
+ talloc_free(root);
+
+ /* Test memlimits with pools. */
+ printf("==== talloc_pool(NULL, 10*1024)\n");
+ pool = talloc_pool(NULL, 10*1024);
+ torture_assert("memlimit", pool != NULL,
+ "failed: alloc should not fail due to memory limit\n");
+
+ printf("==== talloc_set_memlimit(pool, 10*1024)\n");
+ talloc_set_memlimit(pool, 10*1024);
+ for (i = 0; i < 9; i++) {
+ printf("==== talloc_size(pool, 1024) %i/10\n", i + 1);
+ l1 = talloc_size(pool, 1024);
+ torture_assert("memlimit", l1 != NULL,
+ "failed: alloc should not fail due to memory limit\n");
+ talloc_report_full(pool, stdout);
+ }
+ /* The next alloc should fail. */
+ printf("==== talloc_size(pool, 1024) 10/10\n");
+ l2 = talloc_size(pool, 1024);
+ torture_assert("memlimit", l2 == NULL,
+ "failed: alloc should fail due to memory limit\n");
+
+ talloc_report_full(pool, stdout);
+
+ /* Moving one of the children shouldn't change the limit,
+ as it's still inside the pool. */
+
+ printf("==== talloc_new(NULL)\n");
+ root = talloc_new(NULL);
+
+ printf("==== talloc_steal(root, l1)\n");
+ talloc_steal(root, l1);
+
+ printf("==== talloc_size(pool, 1024)\n");
+ l2 = talloc_size(pool, 1024);
+ torture_assert("memlimit", l2 == NULL,
+ "failed: alloc should fail due to memory limit\n");
+
+ printf("==== talloc_free_children(pool)\n");
+ talloc_free(l1);
+ talloc_free_children(pool);
+
+ printf("==== talloc_size(pool, 1024)\n");
+ l1 = talloc_size(pool, 1024);
+
+ /* try reallocs of increasing size */
+ for (i = 1; i < 9; i++) {
+ printf("==== talloc_realloc_size(NULL, l1, %i*1024) %i/10\n", i, i + 1);
+ l1 = talloc_realloc_size(NULL, l1, i*1024);
+ torture_assert("memlimit", l1 != NULL,
+ "failed: realloc should not fail due to memory limit\n");
+ talloc_report_full(pool, stdout);
+ }
+ /* The next alloc should fail. */
+ printf("==== talloc_realloc_size(NULL, l1, 10*1024) 10/10\n");
+ l2 = talloc_realloc_size(NULL, l1, 10*1024);
+ torture_assert("memlimit", l2 == NULL,
+ "failed: realloc should fail due to memory limit\n");
+
+ /* Increase the memlimit */
+ printf("==== talloc_set_memlimit(pool, 11*1024)\n");
+ talloc_set_memlimit(pool, 11*1024);
+
+ /* The final realloc should still fail
+ as the entire realloced chunk needs to be moved out of the pool */
+ printf("==== talloc_realloc_size(NULL, l1, 10*1024) 10/10\n");
+ l2 = talloc_realloc_size(NULL, l1, 10*1024);
+ torture_assert("memlimit", l2 == NULL,
+ "failed: realloc should fail due to memory limit\n");
+
+ talloc_report_full(pool, stdout);
+
+ printf("==== talloc_set_memlimit(pool, 21*1024)\n");
+ talloc_set_memlimit(pool, 21*1024);
+
+ /* There's now sufficient space to move the chunk out of the pool */
+ printf("==== talloc_realloc_size(NULL, l1, 10*1024) 10/10\n");
+ l2 = talloc_realloc_size(NULL, l1, 10*1024);
+ torture_assert("memlimit", l2 != NULL,
+ "failed: realloc should not fail due to memory limit\n");
+
+ talloc_report_full(pool, stdout);
+
+ /* ...which should mean smaller allocations can now occur within the pool */
+ printf("==== talloc_size(pool, 9*1024)\n");
+ l1 = talloc_size(pool, 9*1024);
+ torture_assert("memlimit", l1 != NULL,
+ "failed: new allocations should be allowed in the pool\n");
+
+ talloc_report_full(pool, stdout);
+
+ /* But reallocs bigger than the pool will still fail */
+ printf("==== talloc_realloc_size(NULL, l1, 10*1024)\n");
+ l2 = talloc_realloc_size(NULL, l1, 10*1024);
+ torture_assert("memlimit", l2 == NULL,
+ "failed: realloc should fail due to memory limit\n");
+
+ talloc_report_full(pool, stdout);
+
+ /* ..as well as allocs */
+ printf("==== talloc_size(pool, 1024)\n");
+ l1 = talloc_size(pool, 1024);
+ torture_assert("memlimit", l1 == NULL,
+ "failed: alloc should fail due to memory limit\n");
+
+ talloc_report_full(pool, stdout);
+
+ printf("==== talloc_free_children(pool)\n");
+ talloc_free_children(pool);
+
+ printf("==== talloc_set_memlimit(pool, 1024)\n");
+ talloc_set_memlimit(pool, 1024);
+
+ /* We should still be able to allocate up to the pool limit
+ because the memlimit only applies to new heap allocations */
+ printf("==== talloc_size(pool, 9*1024)\n");
+ l1 = talloc_size(pool, 9*1024);
+ torture_assert("memlimit", l1 != NULL,
+ "failed: alloc should not fail due to memory limit\n");
+
+ talloc_report_full(pool, stdout);
+
+ l1 = talloc_size(pool, 1024);
+ torture_assert("memlimit", l1 == NULL,
+ "failed: alloc should fail due to memory limit\n");
+
+ talloc_report_full(pool, stdout);
+
+ printf("==== talloc_free_children(pool)\n");
+ talloc_free_children(pool);
+
+ printf("==== talloc_set_memlimit(pool, 10*1024)\n");
+ talloc_set_memlimit(pool, 10*1024);
+
+ printf("==== talloc_size(pool, 1024)\n");
+ l1 = talloc_size(pool, 1024);
+ torture_assert("memlimit", l1 != NULL,
+ "failed: alloc should not fail due to memory limit\n");
+
+ talloc_report_full(pool, stdout);
+
+ talloc_free(pool);
+ talloc_free(root);
+ printf("success: memlimit\n");
+
+ return true;
+}
+
+#ifdef HAVE_PTHREAD
+
+#define NUM_THREADS 100
+
+/* Sync variables. */
+static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t condvar = PTHREAD_COND_INITIALIZER;
+static void *intermediate_ptr;
+
+/* Subthread. */
+static void *thread_fn(void *arg)
+{
+ int ret;
+ const char *ctx_name = (const char *)arg;
+ void *sub_ctx = NULL;
+ /*
+ * Do stuff that creates a new talloc hierarchy in
+ * this thread.
+ */
+ void *top_ctx = talloc_named_const(NULL, 0, "top");
+ if (top_ctx == NULL) {
+ return NULL;
+ }
+ sub_ctx = talloc_named_const(top_ctx, 100, ctx_name);
+ if (sub_ctx == NULL) {
+ return NULL;
+ }
+
+ /*
+ * Now transfer a pointer from our hierarchy
+ * onto the intermediate ptr.
+ */
+ ret = pthread_mutex_lock(&mtx);
+ if (ret != 0) {
+ talloc_free(top_ctx);
+ return NULL;
+ }
+ /* Wait for intermediate_ptr to be free. */
+ while (intermediate_ptr != NULL) {
+ ret = pthread_cond_wait(&condvar, &mtx);
+ if (ret != 0) {
+ talloc_free(top_ctx);
+ ret = pthread_mutex_unlock(&mtx);
+ assert(ret == 0);
+ return NULL;
+ }
+ }
+
+ /* and move our memory onto it from our toplevel hierarchy. */
+ intermediate_ptr = talloc_move(NULL, &sub_ctx);
+
+ /* Tell the main thread it's ready for pickup. */
+ pthread_cond_broadcast(&condvar);
+ ret = pthread_mutex_unlock(&mtx);
+ assert(ret == 0);
+
+ talloc_free(top_ctx);
+ return NULL;
+}
+
+/* Main thread. */
+static bool test_pthread_talloc_passing(void)
+{
+ int i;
+ int ret;
+ char str_array[NUM_THREADS][20];
+ pthread_t thread_id;
+ void *mem_ctx;
+
+ /*
+ * Important ! Null tracking breaks threaded talloc.
+ * It *must* be turned off.
+ */
+ talloc_disable_null_tracking();
+
+ printf("test: pthread_talloc_passing\n# PTHREAD TALLOC PASSING\n");
+
+ /* Main thread toplevel context. */
+ mem_ctx = talloc_named_const(NULL, 0, "toplevel");
+ if (mem_ctx == NULL) {
+ printf("failed to create toplevel context\n");
+ return false;
+ }
+
+ /*
+ * Spin off NUM_THREADS threads.
+ * They will use their own toplevel contexts.
+ */
+ for (i = 0; i < NUM_THREADS; i++) {
+ ret = snprintf(str_array[i],
+ 20,
+ "thread:%d",
+ i);
+ if (ret < 0) {
+ printf("snprintf %d failed\n", i);
+ return false;
+ }
+ ret = pthread_create(&thread_id,
+ NULL,
+ thread_fn,
+ str_array[i]);
+ if (ret != 0) {
+ printf("failed to create thread %d (%d)\n", i, ret);
+ return false;
+ }
+ }
+
+ printf("Created %d threads\n", NUM_THREADS);
+
+ /* Now wait for NUM_THREADS transfers of the talloc'ed memory. */
+ for (i = 0; i < NUM_THREADS; i++) {
+ ret = pthread_mutex_lock(&mtx);
+ if (ret != 0) {
+ printf("pthread_mutex_lock %d failed (%d)\n", i, ret);
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ /* Wait for intermediate_ptr to have our data. */
+ while (intermediate_ptr == NULL) {
+ ret = pthread_cond_wait(&condvar, &mtx);
+ if (ret != 0) {
+ printf("pthread_cond_wait %d failed (%d)\n", i,
+ ret);
+ talloc_free(mem_ctx);
+ ret = pthread_mutex_unlock(&mtx);
+ assert(ret == 0);
+ }
+ }
+
+ /* and move it onto our toplevel hierarchy. */
+ (void)talloc_move(mem_ctx, &intermediate_ptr);
+
+ /* Tell the sub-threads we're ready for another. */
+ pthread_cond_broadcast(&condvar);
+ ret = pthread_mutex_unlock(&mtx);
+ assert(ret == 0);
+ }
+
+ CHECK_SIZE("pthread_talloc_passing", mem_ctx, NUM_THREADS * 100);
+#if 1
+ /* Dump the hierarchy. */
+ talloc_report(mem_ctx, stdout);
+#endif
+ talloc_free(mem_ctx);
+ printf("success: pthread_talloc_passing\n");
+ return true;
+}
+#endif
+
+static void test_magic_protection_abort(const char *reason)
+{
+ /* exit with errcode 42 to communicate successful test to the parent process */
+ if (strcmp(reason, "Bad talloc magic value - unknown value") == 0) {
+ _exit(42);
+ } else {
+ printf("talloc aborted for an unexpected reason\n");
+ }
+}
+
+static int test_magic_protection_destructor(int *ptr)
+{
+ _exit(404); /* Not 42 */
+}
+
+static bool test_magic_protection(void)
+{
+ void *pool = talloc_pool(NULL, 1024);
+ int *p1, *p2;
+ pid_t pid;
+ int exit_status;
+
+ printf("test: magic_protection\n");
+ p1 = talloc(pool, int);
+ p2 = talloc(pool, int);
+
+ /* To avoid complaints from the compiler assign values to the p1 & p2. */
+ *p1 = 6;
+ *p2 = 9;
+
+ pid = fork();
+ if (pid == 0) {
+ talloc_set_abort_fn(test_magic_protection_abort);
+ talloc_set_destructor(p2, test_magic_protection_destructor);
+
+ /*
+ * Simulate a security attack
+ * by triggering a buffer overflow in memset to overwrite the
+ * constructor in the next pool chunk.
+ *
+ * Real attacks would attempt to set a real destructor.
+ */
+ memset(p1, '\0', 32);
+
+ /* Then the attack takes effect when the memory's freed. */
+ talloc_free(pool);
+
+ /* Never reached. Make compilers happy */
+ return true;
+ }
+
+ while (wait(&exit_status) != pid);
+
+ talloc_free(pool); /* make ASAN happy */
+
+ if (!WIFEXITED(exit_status)) {
+ printf("Child exited through unexpected abnormal means\n");
+ return false;
+ }
+ if (WEXITSTATUS(exit_status) != 42) {
+ printf("Child exited with wrong exit status\n");
+ return false;
+ }
+ if (WIFSIGNALED(exit_status)) {
+ printf("Child received unexpected signal\n");
+ return false;
+ }
+
+ printf("success: magic_protection\n");
+ return true;
+}
+
+static void test_magic_free_protection_abort(const char *reason)
+{
+ /* exit with errcode 42 to communicate successful test to the parent process */
+ if (strcmp(reason, "Bad talloc magic value - access after free") == 0) {
+ _exit(42);
+ }
+ /* not 42 */
+ _exit(404);
+}
+
+static bool test_magic_free_protection(void)
+{
+ void *pool = talloc_pool(NULL, 1024);
+ int *p1, *p2, *p3;
+ pid_t pid;
+ int exit_status;
+
+ printf("test: magic_free_protection\n");
+ p1 = talloc(pool, int);
+ p2 = talloc(pool, int);
+
+ /* To avoid complaints from the compiler assign values to the p1 & p2. */
+ *p1 = 6;
+ *p2 = 9;
+
+ p3 = talloc_realloc(pool, p2, int, 2048);
+ torture_assert("pool realloc 2048",
+ p3 != p2,
+ "failed: pointer not changed");
+
+ /*
+ * Now access the memory in the pool after the realloc(). It
+ * should be marked as free, so use of the old pointer should
+ * trigger the abort function
+ */
+ pid = fork();
+ if (pid == 0) {
+ talloc_set_abort_fn(test_magic_free_protection_abort);
+
+ talloc_get_name(p2);
+
+ /* Never reached. Make compilers happy */
+ return true;
+ }
+
+ while (wait(&exit_status) != pid);
+
+ if (!WIFEXITED(exit_status)) {
+ printf("Child exited through unexpected abnormal means\n");
+ return false;
+ }
+ if (WEXITSTATUS(exit_status) != 42) {
+ printf("Child exited with wrong exit status\n");
+ return false;
+ }
+ if (WIFSIGNALED(exit_status)) {
+ printf("Child received unexpected signal\n");
+ return false;
+ }
+
+ talloc_free(pool);
+
+ printf("success: magic_free_protection\n");
+ return true;
+}
+
+static void test_reset(void)
+{
+ talloc_set_log_fn(test_log_stdout);
+ test_abort_stop();
+ talloc_disable_null_tracking();
+ talloc_enable_null_tracking_no_autofree();
+}
+
+bool torture_local_talloc(struct torture_context *tctx)
+{
+ bool ret = true;
+
+ setlinebuf(stdout);
+
+ test_reset();
+ ret &= test_pooled_object();
+ test_reset();
+ ret &= test_pool_nest();
+ test_reset();
+ ret &= test_ref1();
+ test_reset();
+ ret &= test_ref2();
+ test_reset();
+ ret &= test_ref3();
+ test_reset();
+ ret &= test_ref4();
+ test_reset();
+ ret &= test_unlink1();
+ test_reset();
+ ret &= test_misc();
+ test_reset();
+ ret &= test_realloc();
+ test_reset();
+ ret &= test_realloc_child();
+ test_reset();
+ ret &= test_steal();
+ test_reset();
+ ret &= test_move();
+ test_reset();
+ ret &= test_unref_reparent();
+ test_reset();
+ ret &= test_realloc_fn();
+ test_reset();
+ ret &= test_type();
+ test_reset();
+ ret &= test_lifeless();
+ test_reset();
+ ret &= test_loop();
+ test_reset();
+ ret &= test_free_parent_deny_child();
+ test_reset();
+ ret &= test_realloc_on_destructor_parent();
+ test_reset();
+ ret &= test_free_parent_reparent_child();
+ test_reset();
+ ret &= test_free_parent_reparent_child_in_pool();
+ test_reset();
+ ret &= test_talloc_ptrtype();
+ test_reset();
+ ret &= test_talloc_free_in_destructor();
+ test_reset();
+ ret &= test_pool();
+ test_reset();
+ ret &= test_pool_steal();
+ test_reset();
+ ret &= test_free_ref_null_context();
+ test_reset();
+ ret &= test_rusty();
+ test_reset();
+ ret &= test_free_children();
+ test_reset();
+ ret &= test_memlimit();
+#ifdef HAVE_PTHREAD
+ test_reset();
+ ret &= test_pthread_talloc_passing();
+#endif
+
+
+ if (ret) {
+ test_reset();
+ ret &= test_speed();
+ }
+ test_reset();
+ ret &= test_autofree();
+ test_reset();
+ ret &= test_magic_protection();
+ test_reset();
+ ret &= test_magic_free_protection();
+
+ test_reset();
+ talloc_disable_null_tracking();
+ return ret;
+}
diff --git a/lib/talloc/testsuite_main.c b/lib/talloc/testsuite_main.c
new file mode 100644
index 0000000..50ce0f8
--- /dev/null
+++ b/lib/talloc/testsuite_main.c
@@ -0,0 +1,36 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ local testing of talloc routines.
+
+ Copyright (C) Andrew Tridgell 2004
+
+ ** 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 3 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
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+
+#include "talloc_testsuite.h"
+
+int main(void)
+{
+ bool ret = torture_local_talloc(NULL);
+ if (!ret)
+ return -1;
+ return 0;
+}
diff --git a/lib/talloc/web/index.html b/lib/talloc/web/index.html
new file mode 100644
index 0000000..388ec2c
--- /dev/null
+++ b/lib/talloc/web/index.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<HTML>
+<HEAD>
+<TITLE>talloc</TITLE>
+</HEAD>
+<BODY BGCOLOR="#ffffff" TEXT="#000000" VLINK="#292555" LINK="#292555" ALINK="#cc0033">
+
+<h1>talloc</h1>
+
+talloc is a hierarchical pool based memory allocator with
+destructors. It is the core memory allocator used in Samba, and has
+made a huge difference in many aspects of Samba4 development.<p>
+
+To get started with talloc, I would recommend you read the <a
+href="http://samba.org/ftp/unpacked/talloc/talloc_guide.txt">talloc guide</a>.
+
+<h2>Download</h2>
+You can download the latest releases of talloc from the <a
+href="http://samba.org/ftp/talloc">talloc directory</a> on the samba public
+source archive.
+
+<h2>Discussion and bug reports</h2>
+
+talloc does not currently have its own mailing list or bug tracking
+system. For now, please use the <a
+href="https://lists.samba.org/mailman/listinfo/samba-technical">samba-technical</a>
+mailing list, and the <a href="http://bugzilla.samba.org/">Samba
+bugzilla</a> bug tracking system.
+
+<h2>Development</h2>
+
+You can download the latest code either via git or rsync.<br>
+<br>
+To fetch via git see the following guide:<br>
+<a href="http://wiki.samba.org/index.php/Using_Git_for_Samba_Development">Using Git for Samba Development</a><br>
+Once you have cloned the tree switch to the master branch and cd into the lib/talloc directory.<br>
+<br>
+To fetch via rsync use this command:
+
+<pre>
+ rsync -Pavz samba.org::ftp/unpacked/standalone_projects/lib/talloc .
+</pre>
+
+<hr>
+<tiny>
+<a href="http://samba.org/~tridge/">Andrew Tridgell</a><br>
+talloc AT tridgell.net
+</tiny>
+
+</BODY>
+</HTML>
diff --git a/lib/talloc/wscript b/lib/talloc/wscript
new file mode 100644
index 0000000..1c54a7c
--- /dev/null
+++ b/lib/talloc/wscript
@@ -0,0 +1,199 @@
+#!/usr/bin/env python
+
+APPNAME = 'talloc'
+VERSION = '2.4.0'
+
+import os
+import sys
+
+# find the buildtools directory
+top = '.'
+while not os.path.exists(top+'/buildtools') and len(top.split('/')) < 5:
+ top = top + '/..'
+sys.path.insert(0, top + '/buildtools/wafsamba')
+
+out = 'bin'
+
+import wafsamba
+from wafsamba import samba_dist, samba_utils
+from waflib import Logs, Options, Context
+
+# setup what directories to put in a tarball
+samba_dist.DIST_DIRS("""lib/talloc:. lib/replace:lib/replace
+buildtools:buildtools third_party/waf:third_party/waf""")
+
+
+def options(opt):
+ opt.BUILTIN_DEFAULT('replace')
+ opt.PRIVATE_EXTENSION_DEFAULT('talloc', noextension='talloc')
+ opt.RECURSE('lib/replace')
+ if opt.IN_LAUNCH_DIR():
+ opt.add_option('--enable-talloc-compat1',
+ help=("Build talloc 1.x.x compat library [False]"),
+ action="store_true", dest='TALLOC_COMPAT1', default=False)
+
+
+def configure(conf):
+ conf.RECURSE('lib/replace')
+
+ conf.env.standalone_talloc = conf.IN_LAUNCH_DIR()
+
+ conf.define('TALLOC_BUILD_VERSION_MAJOR', int(VERSION.split('.')[0]))
+ conf.define('TALLOC_BUILD_VERSION_MINOR', int(VERSION.split('.')[1]))
+ conf.define('TALLOC_BUILD_VERSION_RELEASE', int(VERSION.split('.')[2]))
+
+ conf.env.TALLOC_COMPAT1 = False
+ if conf.env.standalone_talloc:
+ conf.env.TALLOC_COMPAT1 = Options.options.TALLOC_COMPAT1
+ conf.env.PKGCONFIGDIR = '${LIBDIR}/pkgconfig'
+ conf.env.TALLOC_VERSION = VERSION
+
+ conf.CHECK_XSLTPROC_MANPAGES()
+
+ conf.CHECK_HEADERS('sys/auxv.h')
+ conf.CHECK_FUNCS('getauxval')
+
+ conf.SAMBA_CONFIG_H()
+
+ conf.SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS()
+
+ conf.SAMBA_CHECK_PYTHON()
+ conf.SAMBA_CHECK_PYTHON_HEADERS()
+
+ if not conf.env.standalone_talloc:
+ if conf.CHECK_BUNDLED_SYSTEM_PKG('talloc', minversion=VERSION,
+ implied_deps='replace'):
+ conf.define('USING_SYSTEM_TALLOC', 1)
+
+ if conf.env.disable_python:
+ using_system_pytalloc_util = False
+ else:
+ using_system_pytalloc_util = True
+ name = 'pytalloc-util' + conf.all_envs['default']['PYTHON_SO_ABI_FLAG']
+ if not conf.CHECK_BUNDLED_SYSTEM_PKG(name, minversion=VERSION,
+ implied_deps='talloc replace'):
+ using_system_pytalloc_util = False
+
+ if using_system_pytalloc_util:
+ conf.define('USING_SYSTEM_PYTALLOC_UTIL', 1)
+
+
+def build(bld):
+ bld.RECURSE('lib/replace')
+
+ if bld.env.standalone_talloc:
+ private_library = False
+
+ # should we also install the symlink to libtalloc1.so here?
+ bld.SAMBA_LIBRARY('talloc-compat1-%s' % (VERSION),
+ 'compat/talloc_compat1.c',
+ public_deps='talloc',
+ soname='libtalloc.so.1',
+ pc_files=[],
+ public_headers=[],
+ enabled=bld.env.TALLOC_COMPAT1)
+
+ testsuite_deps = 'talloc'
+ if bld.CONFIG_SET('HAVE_PTHREAD'):
+ testsuite_deps += ' pthread'
+
+ bld.SAMBA_BINARY('talloc_testsuite',
+ 'testsuite_main.c testsuite.c',
+ testsuite_deps,
+ install=False)
+
+ bld.SAMBA_BINARY('talloc_test_magic_differs_helper',
+ 'test_magic_differs_helper.c',
+ 'talloc', install=False)
+
+ else:
+ private_library = True
+
+ if not bld.CONFIG_SET('USING_SYSTEM_TALLOC'):
+
+ bld.SAMBA_LIBRARY('talloc',
+ 'talloc.c',
+ deps='replace',
+ provide_builtin_linking=True,
+ abi_directory='ABI',
+ abi_match='talloc* _talloc*',
+ hide_symbols=True,
+ vnum=VERSION,
+ public_headers=('' if private_library else 'talloc.h'),
+ pc_files='talloc.pc',
+ public_headers_install=not private_library,
+ private_library=private_library,
+ manpages='man/talloc.3')
+
+ if not bld.CONFIG_SET('USING_SYSTEM_PYTALLOC_UTIL'):
+ name = bld.pyembed_libname('pytalloc-util')
+
+ bld.SAMBA_LIBRARY(name,
+ source='pytalloc_util.c',
+ public_deps='talloc',
+ pyembed=True,
+ vnum=VERSION,
+ hide_symbols=True,
+ abi_directory='ABI',
+ abi_match='pytalloc_* _pytalloc_*',
+ private_library=private_library,
+ public_headers=('' if private_library else 'pytalloc.h'),
+ pc_files='pytalloc-util.pc',
+ enabled=bld.PYTHON_BUILD_IS_ENABLED()
+ )
+ bld.SAMBA_PYTHON('pytalloc',
+ 'pytalloc.c',
+ deps='talloc ' + name,
+ enabled=bld.PYTHON_BUILD_IS_ENABLED(),
+ realname='talloc.so')
+
+ bld.SAMBA_PYTHON('test_pytalloc',
+ 'test_pytalloc.c',
+ deps=name,
+ enabled=bld.PYTHON_BUILD_IS_ENABLED(),
+ realname='_test_pytalloc.so',
+ install=False)
+
+
+def testonly(ctx):
+ '''run talloc testsuite'''
+ import samba_utils
+
+ samba_utils.ADD_LD_LIBRARY_PATH('bin/shared')
+ samba_utils.ADD_LD_LIBRARY_PATH('bin/shared/private')
+
+ cmd = os.path.join(Context.g_module.out, 'talloc_testsuite')
+ ret = samba_utils.RUN_COMMAND(cmd)
+ print("testsuite returned %d" % ret)
+ magic_helper_cmd = os.path.join(Context.g_module.out, 'talloc_test_magic_differs_helper')
+ magic_cmd = os.path.join(Context.g_module.top, 'lib', 'talloc',
+ 'test_magic_differs.sh')
+ if not os.path.exists(magic_cmd):
+ magic_cmd = os.path.join(Context.g_module.top, 'test_magic_differs.sh')
+
+ magic_ret = samba_utils.RUN_COMMAND(magic_cmd + " " + magic_helper_cmd)
+ print("magic differs test returned %d" % magic_ret)
+ pyret = samba_utils.RUN_PYTHON_TESTS(['test_pytalloc.py'])
+ print("python testsuite returned %d" % pyret)
+ sys.exit(ret or magic_ret or pyret)
+
+# WAF doesn't build the unit tests for this, maybe because they don't link with talloc?
+# This forces it
+def test(ctx):
+ Options.commands.append('build')
+ Options.commands.append('testonly')
+
+def dist():
+ '''makes a tarball for distribution'''
+ samba_dist.dist()
+
+def reconfigure(ctx):
+ '''reconfigure if config scripts have changed'''
+ samba_utils.reconfigure(ctx)
+
+
+def pydoctor(ctx):
+ '''build python apidocs'''
+ cmd='PYTHONPATH=bin/python pydoctor --project-name=talloc --project-url=http://talloc.samba.org/ --make-html --docformat=restructuredtext --introspect-c-modules --add-module bin/python/talloc.*'
+ print("Running: %s" % cmd)
+ os.system(cmd)