1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-24 21:34:56 +03:00
samba-mirror/lib/talloc/pytalloc_util.c
Andrew Bartlett 80f2b36efb pytalloc: Add new BaseObject
This new object not only avoids the ABI issues of talloc.Object
it stores one more pointer, being the start of the array, and
so can be used to fix the PIDL bindings/talloc refcount issue.

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
2016-03-08 01:58:26 +01:00

262 lines
6.4 KiB
C

/*
Unix SMB/CIFS implementation.
Python/Talloc glue
Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Python.h>
#include "replace.h"
#include <talloc.h>
#include "pytalloc.h"
#include <assert.h>
#include "pytalloc_private.h"
_PUBLIC_ PyTypeObject *pytalloc_GetObjectType(void)
{
static PyTypeObject *type = NULL;
PyObject *mod;
if (type != NULL) {
return type;
}
mod = PyImport_ImportModule("talloc");
if (mod == NULL) {
return NULL;
}
type = (PyTypeObject *)PyObject_GetAttrString(mod, "Object");
Py_DECREF(mod);
return type;
}
_PUBLIC_ PyTypeObject *pytalloc_GetBaseObjectType(void)
{
static PyTypeObject *type = NULL;
PyObject *mod;
if (type != NULL) {
return type;
}
mod = PyImport_ImportModule("talloc");
if (mod == NULL) {
return NULL;
}
type = (PyTypeObject *)PyObject_GetAttrString(mod, "BaseObject");
Py_DECREF(mod);
return type;
}
/**
* Import an existing talloc pointer into a Python object.
*/
_PUBLIC_ PyObject *pytalloc_steal_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx,
void *ptr)
{
PyTypeObject *BaseObjectType = pytalloc_GetBaseObjectType();
PyTypeObject *ObjectType = pytalloc_GetObjectType();
if (mem_ctx == NULL) {
return PyErr_NoMemory();
}
if (PyType_IsSubtype(py_type, BaseObjectType)) {
pytalloc_BaseObject *ret
= (pytalloc_BaseObject *)py_type->tp_alloc(py_type, 0);
ret->talloc_ctx = talloc_new(NULL);
if (ret->talloc_ctx == NULL) {
return NULL;
}
/*
* This allows us to keep multiple references to this object -
* we only reference this context, which is per ptr, not the
* talloc_ctx, which is per pytalloc_Object
*/
if (talloc_steal(ret->talloc_ctx, mem_ctx) == NULL) {
return NULL;
}
ret->talloc_ptr_ctx = mem_ctx;
talloc_set_name_const(ret->talloc_ctx, py_type->tp_name);
ret->ptr = ptr;
return (PyObject *)ret;
} else if (PyType_IsSubtype(py_type, ObjectType)) {
pytalloc_Object *ret
= (pytalloc_Object *)py_type->tp_alloc(py_type, 0);
ret->talloc_ctx = talloc_new(NULL);
if (ret->talloc_ctx == NULL) {
return NULL;
}
if (talloc_steal(ret->talloc_ctx, mem_ctx) == NULL) {
return NULL;
}
talloc_set_name_const(ret->talloc_ctx, py_type->tp_name);
ret->ptr = ptr;
return (PyObject *)ret;
} else {
PyErr_SetString(PyExc_RuntimeError,
"pytalloc_steal_ex() called for object type "
"not based on talloc");
return NULL;
}
}
/**
* Import an existing talloc pointer into a Python object.
*/
_PUBLIC_ PyObject *pytalloc_steal(PyTypeObject *py_type, void *ptr)
{
return pytalloc_steal_ex(py_type, ptr, ptr);
}
/**
* Import an existing talloc pointer into a Python object, leaving the
* original parent, and creating a reference to the object in the python
* object.
*
* We remember the object we hold the reference to (a
* possibly-non-talloc pointer), the existing parent (typically the
* start of the array) and the new referenced parent. That way we can
* cope with the fact that we will have multiple parents, one per time
* python sees the object.
*/
_PUBLIC_ PyObject *pytalloc_reference_ex(PyTypeObject *py_type,
TALLOC_CTX *mem_ctx, void *ptr)
{
PyTypeObject *BaseObjectType = pytalloc_GetBaseObjectType();
PyTypeObject *ObjectType = pytalloc_GetObjectType();
if (mem_ctx == NULL) {
return PyErr_NoMemory();
}
if (PyType_IsSubtype(py_type, BaseObjectType)) {
pytalloc_BaseObject *ret
= (pytalloc_BaseObject *)py_type->tp_alloc(py_type, 0);
ret->talloc_ctx = talloc_new(NULL);
if (ret->talloc_ctx == NULL) {
return NULL;
}
if (talloc_reference(ret->talloc_ctx, mem_ctx) == NULL) {
return NULL;
}
talloc_set_name_const(ret->talloc_ctx, py_type->tp_name);
ret->talloc_ptr_ctx = mem_ctx;
ret->ptr = ptr;
return (PyObject *)ret;
} else if (PyType_IsSubtype(py_type, ObjectType)) {
pytalloc_Object *ret
= (pytalloc_Object *)py_type->tp_alloc(py_type, 0);
ret->talloc_ctx = talloc_new(NULL);
if (ret->talloc_ctx == NULL) {
return NULL;
}
if (talloc_reference(ret->talloc_ctx, mem_ctx) == NULL) {
return NULL;
}
talloc_set_name_const(ret->talloc_ctx, py_type->tp_name);
ret->ptr = ptr;
return (PyObject *)ret;
} else {
PyErr_SetString(PyExc_RuntimeError,
"pytalloc_reference_ex() called for object type "
"not based on talloc");
return NULL;
}
}
#if PY_MAJOR_VERSION < 3
static void py_cobject_talloc_free(void *ptr)
{
talloc_free(ptr);
}
_PUBLIC_ PyObject *pytalloc_CObject_FromTallocPtr(void *ptr)
{
if (ptr == NULL) {
Py_RETURN_NONE;
}
return PyCObject_FromVoidPtr(ptr, py_cobject_talloc_free);
}
#endif
_PUBLIC_ int pytalloc_Check(PyObject *obj)
{
PyTypeObject *tp = pytalloc_GetObjectType();
return PyObject_TypeCheck(obj, tp);
}
_PUBLIC_ int pytalloc_BaseObject_check(PyObject *obj)
{
PyTypeObject *tp = pytalloc_GetBaseObjectType();
return PyObject_TypeCheck(obj, tp);
}
_PUBLIC_ size_t pytalloc_BaseObject_size(void)
{
return sizeof(pytalloc_BaseObject);
}
_PUBLIC_ void *_pytalloc_get_type(PyObject *py_obj, const char *type_name)
{
void *ptr = _pytalloc_get_ptr(py_obj);
void *type_obj = talloc_check_name(ptr, type_name);
if (type_obj == NULL) {
const char *name = talloc_get_name(ptr);
PyErr_Format(PyExc_TypeError, "pytalloc: expected %s, got %s",
type_name, name);
return NULL;
}
return ptr;
}
_PUBLIC_ void *_pytalloc_get_ptr(PyObject *py_obj)
{
if (pytalloc_BaseObject_check(py_obj)) {
return ((pytalloc_BaseObject *)py_obj)->ptr;
}
if (pytalloc_Check(py_obj)) {
return ((pytalloc_Object *)py_obj)->ptr;
}
return NULL;
}
_PUBLIC_ TALLOC_CTX *_pytalloc_get_mem_ctx(PyObject *py_obj)
{
if (pytalloc_BaseObject_check(py_obj)) {
return ((pytalloc_BaseObject *)py_obj)->talloc_ptr_ctx;
}
if (pytalloc_Check(py_obj)) {
return ((pytalloc_Object *)py_obj)->talloc_ctx;
}
return NULL;
}