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 83838170 : _PUBLIC_ PyTypeObject *pytalloc_GetObjectType(void)
35 : {
36 69629331 : static PyTypeObject *type = NULL;
37 69629331 : PyObject *mod;
38 :
39 83838170 : mod = PyImport_ImportModule("talloc");
40 83838170 : if (mod == NULL) {
41 0 : return NULL;
42 : }
43 :
44 83838170 : type = (PyTypeObject *)PyObject_GetAttrString(mod, "Object");
45 69629331 : Py_DECREF(mod);
46 :
47 83838170 : return type;
48 : }
49 :
50 255189362 : _PUBLIC_ PyTypeObject *pytalloc_GetBaseObjectType(void)
51 : {
52 213306913 : static PyTypeObject *type = NULL;
53 213306913 : PyObject *mod;
54 :
55 255189362 : mod = PyImport_ImportModule("talloc");
56 255189362 : if (mod == NULL) {
57 0 : return NULL;
58 : }
59 :
60 255189362 : type = (PyTypeObject *)PyObject_GetAttrString(mod, "BaseObject");
61 213306913 : Py_DECREF(mod);
62 :
63 255189362 : return type;
64 : }
65 :
66 5152212 : static PyTypeObject *pytalloc_GetGenericObjectType(void)
67 : {
68 4239041 : static PyTypeObject *type = NULL;
69 4239041 : PyObject *mod;
70 :
71 5152212 : mod = PyImport_ImportModule("talloc");
72 5152212 : if (mod == NULL) {
73 0 : return NULL;
74 : }
75 :
76 5152212 : type = (PyTypeObject *)PyObject_GetAttrString(mod, "GenericObject");
77 4239041 : Py_DECREF(mod);
78 :
79 5152212 : 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 18107684 : _PUBLIC_ PyObject *pytalloc_steal(PyTypeObject *py_type, void *ptr)
95 : {
96 18107684 : 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 65717446 : _PUBLIC_ PyObject *pytalloc_reference_ex(PyTypeObject *py_type,
112 : TALLOC_CTX *mem_ctx, void *ptr)
113 : {
114 65717446 : 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 83825260 : static PyObject *pytalloc_steal_or_reference(PyTypeObject *py_type,
123 : TALLOC_CTX *mem_ctx, void *ptr, bool steal)
124 : {
125 83825260 : bool ok = false;
126 83825260 : TALLOC_CTX *talloc_ctx = NULL;
127 83825260 : bool is_baseobject = false;
128 83825260 : PyObject *obj = NULL;
129 83825260 : PyTypeObject *BaseObjectType = NULL, *ObjectType = NULL;
130 :
131 83825260 : BaseObjectType = pytalloc_GetBaseObjectType();
132 83825260 : if (BaseObjectType == NULL) {
133 0 : goto err;
134 : }
135 83825260 : ObjectType = pytalloc_GetObjectType();
136 83825260 : if (ObjectType == NULL) {
137 0 : goto err;
138 : }
139 :
140 : /* this should have been tested by caller */
141 83825260 : if (mem_ctx == NULL) {
142 0 : return PyErr_NoMemory();
143 : }
144 :
145 83825260 : is_baseobject = PyType_IsSubtype(py_type, BaseObjectType);
146 83825260 : 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 83825260 : obj = py_type->tp_alloc(py_type, 0);
155 83825260 : if (obj == NULL) {
156 0 : goto err;
157 : }
158 :
159 83825260 : talloc_ctx = talloc_new(NULL);
160 83825260 : if (talloc_ctx == NULL) {
161 0 : PyErr_NoMemory();
162 0 : goto err;
163 : }
164 :
165 83825260 : if (steal) {
166 18107814 : ok = (talloc_steal(talloc_ctx, mem_ctx) != NULL);
167 : } else {
168 65717446 : ok = (talloc_reference(talloc_ctx, mem_ctx) != NULL);
169 : }
170 83825260 : if (!ok) {
171 0 : goto err;
172 : }
173 83825260 : talloc_set_name_const(talloc_ctx, py_type->tp_name);
174 :
175 83825260 : if (is_baseobject) {
176 83825251 : pytalloc_BaseObject *ret = (pytalloc_BaseObject*)obj;
177 83825251 : ret->talloc_ctx = talloc_ctx;
178 83825251 : ret->talloc_ptr_ctx = mem_ctx;
179 83825251 : 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 14206707 : 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 5152082 : _PUBLIC_ PyObject *pytalloc_GenericObject_reference_ex(TALLOC_CTX *mem_ctx, void *ptr)
208 : {
209 5152082 : PyTypeObject *tp = pytalloc_GetGenericObjectType();
210 5152082 : return pytalloc_reference_ex(tp, mem_ctx, ptr);
211 : }
212 :
213 53 : _PUBLIC_ int pytalloc_Check(PyObject *obj)
214 : {
215 53 : PyTypeObject *tp = pytalloc_GetObjectType();
216 :
217 53 : return PyObject_TypeCheck(obj, tp);
218 : }
219 :
220 171300866 : _PUBLIC_ int pytalloc_BaseObject_check(PyObject *obj)
221 : {
222 171300866 : PyTypeObject *tp = pytalloc_GetBaseObjectType();
223 :
224 171300866 : return PyObject_TypeCheck(obj, tp);
225 : }
226 :
227 5509658 : _PUBLIC_ size_t pytalloc_BaseObject_size(void)
228 : {
229 5509658 : return sizeof(pytalloc_BaseObject);
230 : }
231 :
232 694102 : static void *_pytalloc_get_checked_type(PyObject *py_obj, const char *type_name,
233 : bool check_only, const char *function)
234 : {
235 487186 : TALLOC_CTX *mem_ctx;
236 694102 : void *ptr = NULL;
237 487186 : void *type_obj;
238 :
239 694102 : mem_ctx = _pytalloc_get_mem_ctx(py_obj);
240 694102 : ptr = _pytalloc_get_ptr(py_obj);
241 :
242 694102 : 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 694102 : type_obj = talloc_check_name(ptr, type_name);
255 694102 : 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 206916 : 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 694102 : _PUBLIC_ void *_pytalloc_get_type(PyObject *py_obj, const char *type_name)
286 : {
287 694102 : return _pytalloc_get_checked_type(py_obj, type_name,
288 : false, /* not check_only */
289 : "pytalloc_get_type");
290 : }
291 :
292 146347643 : _PUBLIC_ void *_pytalloc_get_ptr(PyObject *py_obj)
293 : {
294 146347643 : if (pytalloc_BaseObject_check(py_obj)) {
295 146347594 : return ((pytalloc_BaseObject *)py_obj)->ptr;
296 : }
297 49 : if (pytalloc_Check(py_obj)) {
298 27 : return ((pytalloc_Object *)py_obj)->ptr;
299 : }
300 0 : return NULL;
301 : }
302 :
303 24953223 : _PUBLIC_ TALLOC_CTX *_pytalloc_get_mem_ctx(PyObject *py_obj)
304 : {
305 24953223 : if (pytalloc_BaseObject_check(py_obj)) {
306 24953219 : 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 63227 : _PUBLIC_ int pytalloc_BaseObject_PyType_Ready(PyTypeObject *type)
315 : {
316 63227 : PyTypeObject *talloc_type = pytalloc_GetBaseObjectType();
317 63227 : if (talloc_type == NULL) {
318 0 : return -1;
319 : }
320 :
321 63227 : type->tp_base = talloc_type;
322 63227 : type->tp_basicsize = pytalloc_BaseObject_size();
323 :
324 63227 : 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 : }
|