mirror of
https://github.com/samba-team/samba.git
synced 2024-12-24 21:34:56 +03:00
80f2b36efb
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>
262 lines
6.4 KiB
C
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;
|
|
}
|