auth/gensec: make sure there's only one pending gensec_update_send() per context
[Samba.git] / lib / talloc / pytalloc_util.c
blob923fe5d634fd0c5f30c574fc06e3dc8788394ea7
1 /*
2 Unix SMB/CIFS implementation.
3 Python/Talloc glue
4 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <Python.h>
21 #include "replace.h"
22 #include <talloc.h>
23 #include "pytalloc.h"
24 #include <assert.h>
25 #include "pytalloc_private.h"
27 _PUBLIC_ PyTypeObject *pytalloc_GetObjectType(void)
29 static PyTypeObject *type = NULL;
30 PyObject *mod;
32 if (type != NULL) {
33 return type;
36 mod = PyImport_ImportModule("talloc");
37 if (mod == NULL) {
38 return NULL;
41 type = (PyTypeObject *)PyObject_GetAttrString(mod, "Object");
42 Py_DECREF(mod);
44 return type;
47 _PUBLIC_ PyTypeObject *pytalloc_GetBaseObjectType(void)
49 static PyTypeObject *type = NULL;
50 PyObject *mod;
52 if (type != NULL) {
53 return type;
56 mod = PyImport_ImportModule("talloc");
57 if (mod == NULL) {
58 return NULL;
61 type = (PyTypeObject *)PyObject_GetAttrString(mod, "BaseObject");
62 Py_DECREF(mod);
64 return type;
67 static PyTypeObject *pytalloc_GetGenericObjectType(void)
69 static PyTypeObject *type = NULL;
70 PyObject *mod;
72 if (type != NULL) {
73 return type;
76 mod = PyImport_ImportModule("talloc");
77 if (mod == NULL) {
78 return NULL;
81 type = (PyTypeObject *)PyObject_GetAttrString(mod, "GenericObject");
82 Py_DECREF(mod);
84 return type;
87 /**
88 * Import an existing talloc pointer into a Python object.
90 _PUBLIC_ PyObject *pytalloc_steal_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx,
91 void *ptr)
93 PyTypeObject *BaseObjectType = pytalloc_GetBaseObjectType();
94 PyTypeObject *ObjectType = pytalloc_GetObjectType();
96 if (mem_ctx == NULL) {
97 return PyErr_NoMemory();
100 if (PyType_IsSubtype(py_type, BaseObjectType)) {
101 pytalloc_BaseObject *ret
102 = (pytalloc_BaseObject *)py_type->tp_alloc(py_type, 0);
104 ret->talloc_ctx = talloc_new(NULL);
105 if (ret->talloc_ctx == NULL) {
106 return NULL;
110 * This allows us to keep multiple references to this object -
111 * we only reference this context, which is per ptr, not the
112 * talloc_ctx, which is per pytalloc_Object
114 if (talloc_steal(ret->talloc_ctx, mem_ctx) == NULL) {
115 return NULL;
117 ret->talloc_ptr_ctx = mem_ctx;
118 talloc_set_name_const(ret->talloc_ctx, py_type->tp_name);
119 ret->ptr = ptr;
120 return (PyObject *)ret;
122 } else if (PyType_IsSubtype(py_type, ObjectType)) {
123 pytalloc_Object *ret
124 = (pytalloc_Object *)py_type->tp_alloc(py_type, 0);
126 ret->talloc_ctx = talloc_new(NULL);
127 if (ret->talloc_ctx == NULL) {
128 return NULL;
131 if (talloc_steal(ret->talloc_ctx, mem_ctx) == NULL) {
132 return NULL;
134 talloc_set_name_const(ret->talloc_ctx, py_type->tp_name);
135 ret->ptr = ptr;
136 return (PyObject *)ret;
137 } else {
138 PyErr_SetString(PyExc_RuntimeError,
139 "pytalloc_steal_ex() called for object type "
140 "not based on talloc");
141 return NULL;
146 * Import an existing talloc pointer into a Python object.
148 _PUBLIC_ PyObject *pytalloc_steal(PyTypeObject *py_type, void *ptr)
150 return pytalloc_steal_ex(py_type, ptr, ptr);
155 * Import an existing talloc pointer into a Python object, leaving the
156 * original parent, and creating a reference to the object in the python
157 * object.
159 * We remember the object we hold the reference to (a
160 * possibly-non-talloc pointer), the existing parent (typically the
161 * start of the array) and the new referenced parent. That way we can
162 * cope with the fact that we will have multiple parents, one per time
163 * python sees the object.
165 _PUBLIC_ PyObject *pytalloc_reference_ex(PyTypeObject *py_type,
166 TALLOC_CTX *mem_ctx, void *ptr)
168 PyTypeObject *BaseObjectType = pytalloc_GetBaseObjectType();
169 PyTypeObject *ObjectType = pytalloc_GetObjectType();
171 if (mem_ctx == NULL) {
172 return PyErr_NoMemory();
175 if (PyType_IsSubtype(py_type, BaseObjectType)) {
176 pytalloc_BaseObject *ret
177 = (pytalloc_BaseObject *)py_type->tp_alloc(py_type, 0);
178 ret->talloc_ctx = talloc_new(NULL);
179 if (ret->talloc_ctx == NULL) {
180 return NULL;
182 if (talloc_reference(ret->talloc_ctx, mem_ctx) == NULL) {
183 return NULL;
185 talloc_set_name_const(ret->talloc_ctx, py_type->tp_name);
186 ret->talloc_ptr_ctx = mem_ctx;
187 ret->ptr = ptr;
188 return (PyObject *)ret;
189 } else if (PyType_IsSubtype(py_type, ObjectType)) {
190 pytalloc_Object *ret
191 = (pytalloc_Object *)py_type->tp_alloc(py_type, 0);
192 ret->talloc_ctx = talloc_new(NULL);
193 if (ret->talloc_ctx == NULL) {
194 return NULL;
196 if (talloc_reference(ret->talloc_ctx, mem_ctx) == NULL) {
197 return NULL;
199 talloc_set_name_const(ret->talloc_ctx, py_type->tp_name);
200 ret->ptr = ptr;
201 return (PyObject *)ret;
202 } else {
203 PyErr_SetString(PyExc_RuntimeError,
204 "pytalloc_reference_ex() called for object type "
205 "not based on talloc");
206 return NULL;
210 #if PY_MAJOR_VERSION < 3
212 static void py_cobject_talloc_free(void *ptr)
214 talloc_free(ptr);
217 _PUBLIC_ PyObject *pytalloc_CObject_FromTallocPtr(void *ptr)
219 if (ptr == NULL) {
220 Py_RETURN_NONE;
222 return PyCObject_FromVoidPtr(ptr, py_cobject_talloc_free);
225 #endif
228 * Wrap a generic talloc pointer into a talloc.GenericObject,
229 * this is a subclass of talloc.BaseObject.
231 _PUBLIC_ PyObject *pytalloc_GenericObject_steal_ex(TALLOC_CTX *mem_ctx, void *ptr)
233 PyTypeObject *tp = pytalloc_GetGenericObjectType();
234 return pytalloc_steal_ex(tp, mem_ctx, ptr);
238 * Wrap a generic talloc pointer into a talloc.GenericObject,
239 * this is a subclass of talloc.BaseObject.
241 _PUBLIC_ PyObject *pytalloc_GenericObject_reference_ex(TALLOC_CTX *mem_ctx, void *ptr)
243 PyTypeObject *tp = pytalloc_GetGenericObjectType();
244 return pytalloc_reference_ex(tp, mem_ctx, ptr);
247 _PUBLIC_ int pytalloc_Check(PyObject *obj)
249 PyTypeObject *tp = pytalloc_GetObjectType();
251 return PyObject_TypeCheck(obj, tp);
254 _PUBLIC_ int pytalloc_BaseObject_check(PyObject *obj)
256 PyTypeObject *tp = pytalloc_GetBaseObjectType();
258 return PyObject_TypeCheck(obj, tp);
261 _PUBLIC_ size_t pytalloc_BaseObject_size(void)
263 return sizeof(pytalloc_BaseObject);
266 static void *_pytalloc_get_checked_type(PyObject *py_obj, const char *type_name,
267 bool check_only, const char *function)
269 TALLOC_CTX *mem_ctx;
270 void *ptr = NULL;
271 void *type_obj = talloc_check_name(ptr, type_name);
273 mem_ctx = _pytalloc_get_mem_ctx(py_obj);
274 ptr = _pytalloc_get_ptr(py_obj);
276 if (mem_ctx != ptr) {
277 if (check_only) {
278 return NULL;
281 PyErr_Format(PyExc_TypeError, "%s: expected %s, "
282 "but the pointer is no talloc pointer, "
283 "pytalloc_get_ptr() would get the raw pointer.",
284 function, type_name);
285 return NULL;
288 type_obj = talloc_check_name(ptr, type_name);
289 if (type_obj == NULL) {
290 const char *name = NULL;
292 if (check_only) {
293 return NULL;
296 name = talloc_get_name(ptr);
297 PyErr_Format(PyExc_TypeError, "%s: expected %s, got %s",
298 function, type_name, name);
299 return NULL;
302 return ptr;
305 _PUBLIC_ int _pytalloc_check_type(PyObject *py_obj, const char *type_name)
307 void *ptr = NULL;
309 ptr = _pytalloc_get_checked_type(py_obj, type_name,
310 true, /* check_only */
311 "pytalloc_check_type");
312 if (ptr == NULL) {
313 return 0;
316 return 1;
319 _PUBLIC_ void *_pytalloc_get_type(PyObject *py_obj, const char *type_name)
321 return _pytalloc_get_checked_type(py_obj, type_name,
322 false, /* not check_only */
323 "pytalloc_get_type");
326 _PUBLIC_ void *_pytalloc_get_ptr(PyObject *py_obj)
328 if (pytalloc_BaseObject_check(py_obj)) {
329 return ((pytalloc_BaseObject *)py_obj)->ptr;
331 if (pytalloc_Check(py_obj)) {
332 return ((pytalloc_Object *)py_obj)->ptr;
334 return NULL;
337 _PUBLIC_ TALLOC_CTX *_pytalloc_get_mem_ctx(PyObject *py_obj)
339 if (pytalloc_BaseObject_check(py_obj)) {
340 return ((pytalloc_BaseObject *)py_obj)->talloc_ptr_ctx;
342 if (pytalloc_Check(py_obj)) {
343 return ((pytalloc_Object *)py_obj)->talloc_ctx;
345 return NULL;
348 _PUBLIC_ int pytalloc_BaseObject_PyType_Ready(PyTypeObject *type)
350 PyTypeObject *talloc_type = pytalloc_GetBaseObjectType();
351 if (talloc_type == NULL) {
352 PyErr_Format(PyExc_TypeError, "pytalloc: unable to get talloc.BaseObject type");
353 return -1;
356 type->tp_base = talloc_type;
357 type->tp_basicsize = pytalloc_BaseObject_size();
359 return PyType_Ready(type);