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 "lib/replace/system/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 83678010 : _PUBLIC_ PyTypeObject *pytalloc_GetObjectType(void)
35 : {
36 69546190 : static PyTypeObject *type = NULL;
37 69546190 : PyObject *mod;
38 :
39 83678010 : mod = PyImport_ImportModule("talloc");
40 83678010 : if (mod == NULL) {
41 0 : return NULL;
42 : }
43 :
44 83678010 : type = (PyTypeObject *)PyObject_GetAttrString(mod, "Object");
45 69546190 : Py_DECREF(mod);
46 :
47 83678010 : return type;
48 : }
49 :
50 254718214 : _PUBLIC_ PyTypeObject *pytalloc_GetBaseObjectType(void)
51 : {
52 213057566 : static PyTypeObject *type = NULL;
53 213057566 : PyObject *mod;
54 :
55 254718214 : mod = PyImport_ImportModule("talloc");
56 254718214 : if (mod == NULL) {
57 0 : return NULL;
58 : }
59 :
60 254718214 : type = (PyTypeObject *)PyObject_GetAttrString(mod, "BaseObject");
61 213057566 : Py_DECREF(mod);
62 :
63 254718214 : return type;
64 : }
65 :
66 5143756 : static PyTypeObject *pytalloc_GetGenericObjectType(void)
67 : {
68 4235013 : static PyTypeObject *type = NULL;
69 4235013 : PyObject *mod;
70 :
71 5143756 : mod = PyImport_ImportModule("talloc");
72 5143756 : if (mod == NULL) {
73 0 : return NULL;
74 : }
75 :
76 5143756 : type = (PyTypeObject *)PyObject_GetAttrString(mod, "GenericObject");
77 4235013 : Py_DECREF(mod);
78 :
79 5143756 : return type;
80 : }
81 :
82 : /**
83 : * Import an existing talloc pointer into a Python object.
84 : */
85 130 : _PUBLIC_ PyObject *pytalloc_steal_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx,
86 : void *ptr)
87 : {
88 130 : 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 18074625 : _PUBLIC_ PyObject *pytalloc_steal(PyTypeObject *py_type, void *ptr)
95 : {
96 18074625 : 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 65590569 : _PUBLIC_ PyObject *pytalloc_reference_ex(PyTypeObject *py_type,
112 : TALLOC_CTX *mem_ctx, void *ptr)
113 : {
114 65590569 : return pytalloc_steal_or_reference(py_type, mem_ctx, ptr, false);
115 : }
116 :
117 :
118 : /**
119 : * Internal function that either steals or references the talloc
120 : * pointer into a new talloc context.
121 : */
122 83665324 : static PyObject *pytalloc_steal_or_reference(PyTypeObject *py_type,
123 : TALLOC_CTX *mem_ctx, void *ptr, bool steal)
124 : {
125 83665324 : bool ok = false;
126 83665324 : TALLOC_CTX *talloc_ctx = NULL;
127 83665324 : bool is_baseobject = false;
128 83665324 : PyObject *obj = NULL;
129 83665324 : PyTypeObject *BaseObjectType = NULL, *ObjectType = NULL;
130 :
131 83665324 : BaseObjectType = pytalloc_GetBaseObjectType();
132 83665324 : if (BaseObjectType == NULL) {
133 0 : goto err;
134 : }
135 83665324 : ObjectType = pytalloc_GetObjectType();
136 83665324 : if (ObjectType == NULL) {
137 0 : goto err;
138 : }
139 :
140 : /* this should have been tested by caller */
141 83665324 : if (mem_ctx == NULL) {
142 0 : return PyErr_NoMemory();
143 : }
144 :
145 83665324 : is_baseobject = PyType_IsSubtype(py_type, BaseObjectType);
146 83665324 : 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 83665324 : obj = py_type->tp_alloc(py_type, 0);
155 83665324 : if (obj == NULL) {
156 0 : goto err;
157 : }
158 :
159 83665324 : talloc_ctx = talloc_new(NULL);
160 83665324 : if (talloc_ctx == NULL) {
161 0 : PyErr_NoMemory();
162 0 : goto err;
163 : }
164 :
165 83665324 : if (steal) {
166 18074755 : ok = (talloc_steal(talloc_ctx, mem_ctx) != NULL);
167 : } else {
168 65590569 : ok = (talloc_reference(talloc_ctx, mem_ctx) != NULL);
169 : }
170 83665324 : if (!ok) {
171 0 : goto err;
172 : }
173 83665324 : talloc_set_name_const(talloc_ctx, py_type->tp_name);
174 :
175 83665324 : if (is_baseobject) {
176 83665315 : pytalloc_BaseObject *ret = (pytalloc_BaseObject*)obj;
177 83665315 : ret->talloc_ctx = talloc_ctx;
178 83665315 : ret->talloc_ptr_ctx = mem_ctx;
179 83665315 : 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 14129695 : return obj;
186 :
187 0 : err:
188 0 : TALLOC_FREE(talloc_ctx);
189 0 : Py_XDECREF(obj);
190 0 : 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 130 : _PUBLIC_ PyObject *pytalloc_GenericObject_steal_ex(TALLOC_CTX *mem_ctx, void *ptr)
198 : {
199 130 : PyTypeObject *tp = pytalloc_GetGenericObjectType();
200 130 : 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 5143626 : _PUBLIC_ PyObject *pytalloc_GenericObject_reference_ex(TALLOC_CTX *mem_ctx, void *ptr)
208 : {
209 5143626 : PyTypeObject *tp = pytalloc_GetGenericObjectType();
210 5143626 : return pytalloc_reference_ex(tp, mem_ctx, ptr);
211 : }
212 :
213 31 : _PUBLIC_ int pytalloc_Check(PyObject *obj)
214 : {
215 31 : PyTypeObject *tp = pytalloc_GetObjectType();
216 :
217 31 : return PyObject_TypeCheck(obj, tp);
218 : }
219 :
220 170984041 : _PUBLIC_ int pytalloc_BaseObject_check(PyObject *obj)
221 : {
222 170984041 : PyTypeObject *tp = pytalloc_GetBaseObjectType();
223 :
224 170984041 : return PyObject_TypeCheck(obj, tp);
225 : }
226 :
227 5561476 : _PUBLIC_ size_t pytalloc_BaseObject_size(void)
228 : {
229 5561476 : return sizeof(pytalloc_BaseObject);
230 : }
231 :
232 686464 : static void *_pytalloc_get_checked_type(PyObject *py_obj, const char *type_name,
233 : bool check_only, const char *function)
234 : {
235 482262 : TALLOC_CTX *mem_ctx;
236 686464 : void *ptr = NULL;
237 482262 : void *type_obj;
238 :
239 686464 : mem_ctx = _pytalloc_get_mem_ctx(py_obj);
240 686464 : ptr = _pytalloc_get_ptr(py_obj);
241 :
242 686464 : if (mem_ctx != ptr || ptr == NULL) {
243 0 : if (check_only) {
244 0 : 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 686464 : type_obj = talloc_check_name(ptr, type_name);
255 686464 : if (type_obj == NULL) {
256 0 : const char *name = NULL;
257 :
258 0 : if (check_only) {
259 0 : 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 204202 : 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 686464 : _PUBLIC_ void *_pytalloc_get_type(PyObject *py_obj, const char *type_name)
286 : {
287 686464 : return _pytalloc_get_checked_type(py_obj, type_name,
288 : false, /* not check_only */
289 : "pytalloc_get_type");
290 : }
291 :
292 146079625 : _PUBLIC_ void *_pytalloc_get_ptr(PyObject *py_obj)
293 : {
294 146079625 : if (pytalloc_BaseObject_check(py_obj)) {
295 146079598 : return ((pytalloc_BaseObject *)py_obj)->ptr;
296 : }
297 27 : if (pytalloc_Check(py_obj)) {
298 27 : return ((pytalloc_Object *)py_obj)->ptr;
299 : }
300 0 : return NULL;
301 : }
302 :
303 24904416 : _PUBLIC_ TALLOC_CTX *_pytalloc_get_mem_ctx(PyObject *py_obj)
304 : {
305 24904416 : if (pytalloc_BaseObject_check(py_obj)) {
306 24904412 : return ((pytalloc_BaseObject *)py_obj)->talloc_ptr_ctx;
307 : }
308 4 : if (pytalloc_Check(py_obj)) {
309 2 : return ((pytalloc_Object *)py_obj)->talloc_ctx;
310 : }
311 1 : return NULL;
312 : }
313 :
314 68840 : _PUBLIC_ int pytalloc_BaseObject_PyType_Ready(PyTypeObject *type)
315 : {
316 68840 : PyTypeObject *talloc_type = pytalloc_GetBaseObjectType();
317 68840 : if (talloc_type == NULL) {
318 0 : return -1;
319 : }
320 :
321 68840 : type->tp_base = talloc_type;
322 68840 : type->tp_basicsize = pytalloc_BaseObject_size();
323 :
324 68840 : 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 0 : return "non-talloc object";
332 : }
333 0 : return talloc_get_name(ptr);
334 : }
|