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 83679679 : _PUBLIC_ PyTypeObject *pytalloc_GetObjectType(void)
35 : {
36 69546513 : static PyTypeObject *type = NULL;
37 69546513 : PyObject *mod;
38 :
39 83679679 : mod = PyImport_ImportModule("talloc");
40 83679679 : if (mod == NULL) {
41 0 : return NULL;
42 : }
43 :
44 83679679 : type = (PyTypeObject *)PyObject_GetAttrString(mod, "Object");
45 69546513 : Py_DECREF(mod);
46 :
47 83679679 : return type;
48 : }
49 :
50 254725880 : _PUBLIC_ PyTypeObject *pytalloc_GetBaseObjectType(void)
51 : {
52 213061506 : static PyTypeObject *type = NULL;
53 213061506 : PyObject *mod;
54 :
55 254725880 : mod = PyImport_ImportModule("talloc");
56 254725880 : if (mod == NULL) {
57 0 : return NULL;
58 : }
59 :
60 254725880 : type = (PyTypeObject *)PyObject_GetAttrString(mod, "BaseObject");
61 213061506 : Py_DECREF(mod);
62 :
63 254725880 : return type;
64 : }
65 :
66 5144566 : static PyTypeObject *pytalloc_GetGenericObjectType(void)
67 : {
68 4235427 : static PyTypeObject *type = NULL;
69 4235427 : PyObject *mod;
70 :
71 5144566 : mod = PyImport_ImportModule("talloc");
72 5144566 : if (mod == NULL) {
73 0 : return NULL;
74 : }
75 :
76 5144566 : type = (PyTypeObject *)PyObject_GetAttrString(mod, "GenericObject");
77 4235427 : Py_DECREF(mod);
78 :
79 5144566 : 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 18075008 : _PUBLIC_ PyObject *pytalloc_steal(PyTypeObject *py_type, void *ptr)
95 : {
96 18075008 : 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 65591845 : _PUBLIC_ PyObject *pytalloc_reference_ex(PyTypeObject *py_type,
112 : TALLOC_CTX *mem_ctx, void *ptr)
113 : {
114 65591845 : 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 83666983 : static PyObject *pytalloc_steal_or_reference(PyTypeObject *py_type,
123 : TALLOC_CTX *mem_ctx, void *ptr, bool steal)
124 : {
125 83666983 : bool ok = false;
126 83666983 : TALLOC_CTX *talloc_ctx = NULL;
127 83666983 : bool is_baseobject = false;
128 83666983 : PyObject *obj = NULL;
129 83666983 : PyTypeObject *BaseObjectType = NULL, *ObjectType = NULL;
130 :
131 83666983 : BaseObjectType = pytalloc_GetBaseObjectType();
132 83666983 : if (BaseObjectType == NULL) {
133 0 : goto err;
134 : }
135 83666983 : ObjectType = pytalloc_GetObjectType();
136 83666983 : if (ObjectType == NULL) {
137 0 : goto err;
138 : }
139 :
140 : /* this should have been tested by caller */
141 83666983 : if (mem_ctx == NULL) {
142 0 : return PyErr_NoMemory();
143 : }
144 :
145 83666983 : is_baseobject = PyType_IsSubtype(py_type, BaseObjectType);
146 83666983 : 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 83666983 : obj = py_type->tp_alloc(py_type, 0);
155 83666983 : if (obj == NULL) {
156 0 : goto err;
157 : }
158 :
159 83666983 : talloc_ctx = talloc_new(NULL);
160 83666983 : if (talloc_ctx == NULL) {
161 0 : PyErr_NoMemory();
162 0 : goto err;
163 : }
164 :
165 83666983 : if (steal) {
166 18075138 : ok = (talloc_steal(talloc_ctx, mem_ctx) != NULL);
167 : } else {
168 65591845 : ok = (talloc_reference(talloc_ctx, mem_ctx) != NULL);
169 : }
170 83666983 : if (!ok) {
171 0 : goto err;
172 : }
173 83666983 : talloc_set_name_const(talloc_ctx, py_type->tp_name);
174 :
175 83666983 : if (is_baseobject) {
176 83666974 : pytalloc_BaseObject *ret = (pytalloc_BaseObject*)obj;
177 83666974 : ret->talloc_ctx = talloc_ctx;
178 83666974 : ret->talloc_ptr_ctx = mem_ctx;
179 83666974 : 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 14131044 : 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 5144436 : _PUBLIC_ PyObject *pytalloc_GenericObject_reference_ex(TALLOC_CTX *mem_ctx, void *ptr)
208 : {
209 5144436 : PyTypeObject *tp = pytalloc_GetGenericObjectType();
210 5144436 : 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 170989935 : _PUBLIC_ int pytalloc_BaseObject_check(PyObject *obj)
221 : {
222 170989935 : PyTypeObject *tp = pytalloc_GetBaseObjectType();
223 :
224 170989935 : return PyObject_TypeCheck(obj, tp);
225 : }
226 :
227 5570230 : _PUBLIC_ size_t pytalloc_BaseObject_size(void)
228 : {
229 5570230 : return sizeof(pytalloc_BaseObject);
230 : }
231 :
232 686613 : static void *_pytalloc_get_checked_type(PyObject *py_obj, const char *type_name,
233 : bool check_only, const char *function)
234 : {
235 482457 : TALLOC_CTX *mem_ctx;
236 686613 : void *ptr = NULL;
237 482457 : void *type_obj;
238 :
239 686613 : mem_ctx = _pytalloc_get_mem_ctx(py_obj);
240 686613 : ptr = _pytalloc_get_ptr(py_obj);
241 :
242 686613 : 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 686613 : type_obj = talloc_check_name(ptr, type_name);
255 686613 : 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 204156 : 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 686613 : _PUBLIC_ void *_pytalloc_get_type(PyObject *py_obj, const char *type_name)
286 : {
287 686613 : return _pytalloc_get_checked_type(py_obj, type_name,
288 : false, /* not check_only */
289 : "pytalloc_get_type");
290 : }
291 :
292 146084612 : _PUBLIC_ void *_pytalloc_get_ptr(PyObject *py_obj)
293 : {
294 146084612 : if (pytalloc_BaseObject_check(py_obj)) {
295 146084585 : 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 24905323 : _PUBLIC_ TALLOC_CTX *_pytalloc_get_mem_ctx(PyObject *py_obj)
304 : {
305 24905323 : if (pytalloc_BaseObject_check(py_obj)) {
306 24905319 : 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 68953 : _PUBLIC_ int pytalloc_BaseObject_PyType_Ready(PyTypeObject *type)
315 : {
316 68953 : PyTypeObject *talloc_type = pytalloc_GetBaseObjectType();
317 68953 : if (talloc_type == NULL) {
318 0 : return -1;
319 : }
320 :
321 68953 : type->tp_base = talloc_type;
322 68953 : type->tp_basicsize = pytalloc_BaseObject_size();
323 :
324 68953 : 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 : }
|