LCOV - code coverage report
Current view: top level - lib/talloc - pytalloc_util.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 102 132 77.3 %
Date: 2021-09-23 10:06:22 Functions: 17 19 89.5 %

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

Generated by: LCOV version 1.13