Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Python/Talloc glue
4 : Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
5 :
6 : ** NOTE! The following LGPL license applies to the talloc
7 : ** library. This does NOT imply that all of Samba is released
8 : ** under the LGPL
9 :
10 : This library is free software; you can redistribute it and/or
11 : modify it under the terms of the GNU Lesser General Public
12 : License as published by the Free Software Foundation; either
13 : version 3 of the License, or (at your option) any later version.
14 :
15 : This library is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 : Lesser General Public License for more details.
19 :
20 : You should have received a copy of the GNU Lesser General Public
21 : License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 : */
23 :
24 : #include <Python.h>
25 : #include "replace.h"
26 : #include <talloc.h>
27 : #include "pytalloc.h"
28 : #include <assert.h>
29 : #include "pytalloc_private.h"
30 :
31 : static PyObject *pytalloc_steal_or_reference(PyTypeObject *py_type,
32 : TALLOC_CTX *mem_ctx, void *ptr, bool steal);
33 :
34 51089695 : _PUBLIC_ PyTypeObject *pytalloc_GetObjectType(void)
35 : {
36 4786366 : static PyTypeObject *type = NULL;
37 4786366 : PyObject *mod;
38 :
39 51089695 : mod = PyImport_ImportModule("talloc");
40 51089695 : if (mod == NULL) {
41 : return NULL;
42 : }
43 :
44 51089695 : type = (PyTypeObject *)PyObject_GetAttrString(mod, "Object");
45 51089695 : Py_DECREF(mod);
46 :
47 51089695 : return type;
48 : }
49 :
50 156448285 : _PUBLIC_ PyTypeObject *pytalloc_GetBaseObjectType(void)
51 : {
52 14446826 : static PyTypeObject *type = NULL;
53 14446826 : PyObject *mod;
54 :
55 156448285 : mod = PyImport_ImportModule("talloc");
56 156448285 : if (mod == NULL) {
57 : return NULL;
58 : }
59 :
60 156448285 : type = (PyTypeObject *)PyObject_GetAttrString(mod, "BaseObject");
61 156448285 : Py_DECREF(mod);
62 :
63 156448285 : return type;
64 : }
65 :
66 3006966 : static PyTypeObject *pytalloc_GetGenericObjectType(void)
67 : {
68 303658 : static PyTypeObject *type = NULL;
69 303658 : PyObject *mod;
70 :
71 3006966 : mod = PyImport_ImportModule("talloc");
72 3006966 : if (mod == NULL) {
73 : return NULL;
74 : }
75 :
76 3006966 : type = (PyTypeObject *)PyObject_GetAttrString(mod, "GenericObject");
77 3006966 : Py_DECREF(mod);
78 :
79 3006966 : return type;
80 : }
81 :
82 : /**
83 : * Import an existing talloc pointer into a Python object.
84 : */
85 124 : _PUBLIC_ PyObject *pytalloc_steal_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx,
86 : void *ptr)
87 : {
88 124 : return pytalloc_steal_or_reference(py_type, mem_ctx, ptr, true);
89 : }
90 :
91 : /**
92 : * Import an existing talloc pointer into a Python object.
93 : */
94 11179461 : _PUBLIC_ PyObject *pytalloc_steal(PyTypeObject *py_type, void *ptr)
95 : {
96 11179461 : return pytalloc_steal_or_reference(py_type, ptr, ptr, true);
97 : }
98 :
99 :
100 : /**
101 : * Import an existing talloc pointer into a Python object, leaving the
102 : * original parent, and creating a reference to the object in the python
103 : * object.
104 : *
105 : * We remember the object we hold the reference to (a
106 : * possibly-non-talloc pointer), the existing parent (typically the
107 : * start of the array) and the new referenced parent. That way we can
108 : * cope with the fact that we will have multiple parents, one per time
109 : * python sees the object.
110 : */
111 39902509 : _PUBLIC_ PyObject *pytalloc_reference_ex(PyTypeObject *py_type,
112 : TALLOC_CTX *mem_ctx, void *ptr)
113 : {
114 39902509 : return pytalloc_steal_or_reference(py_type, mem_ctx, ptr, false);
115 : }
116 :
117 :
118 : /**
119 : * Internal function that either steals or referecences the talloc
120 : * pointer into a new talloc context.
121 : */
122 51082094 : static PyObject *pytalloc_steal_or_reference(PyTypeObject *py_type,
123 : TALLOC_CTX *mem_ctx, void *ptr, bool steal)
124 : {
125 51082094 : bool ok = false;
126 51082094 : TALLOC_CTX *talloc_ctx = NULL;
127 51082094 : bool is_baseobject = false;
128 51082094 : PyObject *obj = NULL;
129 51082094 : PyTypeObject *BaseObjectType = NULL, *ObjectType = NULL;
130 :
131 51082094 : BaseObjectType = pytalloc_GetBaseObjectType();
132 51082094 : if (BaseObjectType == NULL) {
133 0 : goto err;
134 : }
135 51082094 : ObjectType = pytalloc_GetObjectType();
136 51082094 : if (ObjectType == NULL) {
137 0 : goto err;
138 : }
139 :
140 : /* this should have been tested by caller */
141 51082094 : if (mem_ctx == NULL) {
142 0 : return PyErr_NoMemory();
143 : }
144 :
145 51082094 : is_baseobject = PyType_IsSubtype(py_type, BaseObjectType);
146 51082094 : if (!is_baseobject) {
147 9 : if (!PyType_IsSubtype(py_type, ObjectType)) {
148 0 : PyErr_SetString(PyExc_TypeError,
149 : "Expected type based on talloc");
150 0 : return NULL;
151 : }
152 : }
153 :
154 51082094 : obj = py_type->tp_alloc(py_type, 0);
155 51082094 : if (obj == NULL) {
156 0 : goto err;
157 : }
158 :
159 51082094 : talloc_ctx = talloc_new(NULL);
160 51082094 : if (talloc_ctx == NULL) {
161 0 : PyErr_NoMemory();
162 0 : goto err;
163 : }
164 :
165 51082094 : if (steal) {
166 11179585 : ok = (talloc_steal(talloc_ctx, mem_ctx) != NULL);
167 : } else {
168 39902509 : ok = (talloc_reference(talloc_ctx, mem_ctx) != NULL);
169 : }
170 51082094 : if (!ok) {
171 0 : goto err;
172 : }
173 51082094 : talloc_set_name_const(talloc_ctx, py_type->tp_name);
174 :
175 51082094 : if (is_baseobject) {
176 51082085 : pytalloc_BaseObject *ret = (pytalloc_BaseObject*)obj;
177 51082085 : ret->talloc_ctx = talloc_ctx;
178 51082085 : ret->talloc_ptr_ctx = mem_ctx;
179 51082085 : ret->ptr = ptr;
180 : } else {
181 9 : pytalloc_Object *ret = (pytalloc_Object*)obj;
182 9 : ret->talloc_ctx = talloc_ctx;
183 9 : ret->ptr = ptr;
184 : }
185 : return obj;
186 :
187 0 : err:
188 0 : TALLOC_FREE(talloc_ctx);
189 0 : Py_XDECREF(obj);
190 : return NULL;
191 : }
192 :
193 : /*
194 : * Wrap a generic talloc pointer into a talloc.GenericObject,
195 : * this is a subclass of talloc.BaseObject.
196 : */
197 124 : _PUBLIC_ PyObject *pytalloc_GenericObject_steal_ex(TALLOC_CTX *mem_ctx, void *ptr)
198 : {
199 124 : PyTypeObject *tp = pytalloc_GetGenericObjectType();
200 124 : return pytalloc_steal_ex(tp, mem_ctx, ptr);
201 : }
202 :
203 : /*
204 : * Wrap a generic talloc pointer into a talloc.GenericObject,
205 : * this is a subclass of talloc.BaseObject.
206 : */
207 3006842 : _PUBLIC_ PyObject *pytalloc_GenericObject_reference_ex(TALLOC_CTX *mem_ctx, void *ptr)
208 : {
209 3006842 : PyTypeObject *tp = pytalloc_GetGenericObjectType();
210 3006842 : return pytalloc_reference_ex(tp, mem_ctx, ptr);
211 : }
212 :
213 29 : _PUBLIC_ int pytalloc_Check(PyObject *obj)
214 : {
215 29 : PyTypeObject *tp = pytalloc_GetObjectType();
216 :
217 29 : return PyObject_TypeCheck(obj, tp);
218 : }
219 :
220 105327144 : _PUBLIC_ int pytalloc_BaseObject_check(PyObject *obj)
221 : {
222 105327144 : PyTypeObject *tp = pytalloc_GetBaseObjectType();
223 :
224 105327144 : return PyObject_TypeCheck(obj, tp);
225 : }
226 :
227 2729220 : _PUBLIC_ size_t pytalloc_BaseObject_size(void)
228 : {
229 2729220 : return sizeof(pytalloc_BaseObject);
230 : }
231 :
232 402030 : static void *_pytalloc_get_checked_type(PyObject *py_obj, const char *type_name,
233 : bool check_only, const char *function)
234 : {
235 78454 : TALLOC_CTX *mem_ctx;
236 402030 : void *ptr = NULL;
237 78454 : void *type_obj;
238 :
239 402030 : mem_ctx = _pytalloc_get_mem_ctx(py_obj);
240 402030 : ptr = _pytalloc_get_ptr(py_obj);
241 :
242 402030 : if (mem_ctx != ptr || ptr == NULL) {
243 0 : if (check_only) {
244 : return NULL;
245 : }
246 :
247 0 : PyErr_Format(PyExc_TypeError, "%s: expected %s, "
248 : "but the pointer is no talloc pointer, "
249 : "pytalloc_get_ptr() would get the raw pointer.",
250 : function, type_name);
251 0 : return NULL;
252 : }
253 :
254 402030 : type_obj = talloc_check_name(ptr, type_name);
255 402030 : if (type_obj == NULL) {
256 0 : const char *name = NULL;
257 :
258 0 : if (check_only) {
259 : return NULL;
260 : }
261 :
262 0 : name = talloc_get_name(ptr);
263 0 : PyErr_Format(PyExc_TypeError, "%s: expected %s, got %s",
264 : function, type_name, name);
265 0 : return NULL;
266 : }
267 :
268 : return ptr;
269 : }
270 :
271 0 : _PUBLIC_ int _pytalloc_check_type(PyObject *py_obj, const char *type_name)
272 : {
273 0 : void *ptr = NULL;
274 :
275 0 : ptr = _pytalloc_get_checked_type(py_obj, type_name,
276 : true, /* check_only */
277 : "pytalloc_check_type");
278 0 : if (ptr == NULL) {
279 0 : return 0;
280 : }
281 :
282 0 : return 1;
283 : }
284 :
285 402030 : _PUBLIC_ void *_pytalloc_get_type(PyObject *py_obj, const char *type_name)
286 : {
287 402030 : return _pytalloc_get_checked_type(py_obj, type_name,
288 : false, /* not check_only */
289 : "pytalloc_get_type");
290 : }
291 :
292 89728188 : _PUBLIC_ void *_pytalloc_get_ptr(PyObject *py_obj)
293 : {
294 89728188 : if (pytalloc_BaseObject_check(py_obj)) {
295 89728161 : return ((pytalloc_BaseObject *)py_obj)->ptr;
296 : }
297 27 : if (pytalloc_Check(py_obj)) {
298 27 : return ((pytalloc_Object *)py_obj)->ptr;
299 : }
300 : return NULL;
301 : }
302 :
303 15598956 : _PUBLIC_ TALLOC_CTX *_pytalloc_get_mem_ctx(PyObject *py_obj)
304 : {
305 15598956 : if (pytalloc_BaseObject_check(py_obj)) {
306 15598954 : return ((pytalloc_BaseObject *)py_obj)->talloc_ptr_ctx;
307 : }
308 2 : if (pytalloc_Check(py_obj)) {
309 2 : return ((pytalloc_Object *)py_obj)->talloc_ctx;
310 : }
311 : return NULL;
312 : }
313 :
314 39038 : _PUBLIC_ int pytalloc_BaseObject_PyType_Ready(PyTypeObject *type)
315 : {
316 39038 : PyTypeObject *talloc_type = pytalloc_GetBaseObjectType();
317 39038 : if (talloc_type == NULL) {
318 : return -1;
319 : }
320 :
321 39038 : type->tp_base = talloc_type;
322 39038 : type->tp_basicsize = pytalloc_BaseObject_size();
323 :
324 39038 : return PyType_Ready(type);
325 : }
326 :
327 0 : _PUBLIC_ const char *_pytalloc_get_name(PyObject *obj)
328 : {
329 0 : void *ptr = pytalloc_get_ptr(obj);
330 0 : if (ptr == NULL) {
331 : return "non-talloc object";
332 : }
333 0 : return talloc_get_name(ptr);
334 : }
|