LCOV - code coverage report
Current view: top level - source3/lib/smbconf - pys3smbconf.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 43 63 68.3 %
Date: 2024-04-21 15:09:00 Functions: 4 5 80.0 %

          Line data    Source code
       1             : /*
       2             :  *  Unix SMB/CIFS implementation.
       3             :  *  libsmbconf - Samba configuration library - Python bindings
       4             :  *
       5             :  *  Copyright (C) John Mulligan <phlogistonjohn@asynchrono.us> 2022
       6             :  *
       7             :  *  This program is free software; you can redistribute it and/or modify
       8             :  *  it under the terms of the GNU General Public License as published by
       9             :  *  the Free Software Foundation; either version 3 of the License, or
      10             :  *  (at your option) any later version.
      11             :  *
      12             :  *  This program is distributed in the hope that it will be useful,
      13             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  *  GNU General Public License for more details.
      16             :  *
      17             :  *  You should have received a copy of the GNU General Public License
      18             :  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include "lib/replace/system/python.h"
      22             : #include "includes.h"
      23             : #include "python/py3compat.h"
      24             : 
      25             : #include "lib/smbconf/smbconf.h"
      26             : #include "source3/lib/smbconf/smbconf_reg.h"
      27             : #include "source3/lib/smbconf/smbconf_init.h"
      28             : #include "lib/smbconf/pysmbconf.h"
      29             : 
      30             : /*
      31             :  * The name of the other, general, smbconf module that implements
      32             :  * the common type. We import this module by name to access
      33             :  * its methods by the python API.
      34             :  */
      35             : #define SMBCONF_MOD "samba.smbconf"
      36             : 
      37             : /*
      38             :  * Return a new but uninitialized SMBConf python object via
      39             :  * the python API of the (other) smbconf module.
      40             :  */
      41          13 : static PyObject *py_new_SMBConf(PyObject * smbconf_mod)
      42             : {
      43          13 :         PyObject *obj = NULL;
      44          13 :         PyObject *method = PyObject_GetAttrString(smbconf_mod, "SMBConf");
      45          13 :         if (method == NULL) {
      46             :                 return NULL;
      47             :         }
      48             : 
      49          13 :         obj = PyObject_CallObject(method, NULL);
      50          13 :         Py_CLEAR(method);
      51             :         return obj;
      52             : }
      53             : 
      54             : /*
      55             :  * Raise a new SMBConfError python exception given a error code.
      56             :  * This uses the python API of the (other) smbconf module.
      57             :  */
      58           0 : static PyObject *py_raise_SMBConfError(PyObject * smbconf_mod, sbcErr err)
      59             : {
      60           0 :         PyObject *obj = NULL;
      61           0 :         PyObject *method =
      62           0 :             PyObject_GetAttrString(smbconf_mod, "_smbconf_error");
      63           0 :         if (method == NULL) {
      64             :                 return NULL;
      65             :         }
      66             : 
      67           0 :         obj = PyObject_CallFunction(method, "i", err);
      68           0 :         Py_CLEAR(method);
      69             :         return obj;
      70             : }
      71             : 
      72          11 : static PyObject *py_init_reg(PyObject * module, PyObject * args)
      73             : {
      74          11 :         PyObject *obj = NULL;
      75          11 :         PyObject *smbconf_mod = NULL;
      76          11 :         char *path = NULL;
      77          11 :         struct smbconf_ctx *conf_ctx = NULL;
      78          11 :         TALLOC_CTX *mem_ctx = NULL;
      79          11 :         sbcErr err;
      80             : 
      81             :         /*
      82             :          * The path here is _NOT_ the path to a file in the file
      83             :          * system. It's a special HK registry thingy. But passing
      84             :          * a null string to smbconf_init_reg populates it with
      85             :          * a functional default value. So we allow the python
      86             :          * caller to pass None and convert to NULL.
      87             :          */
      88          11 :         if (!PyArg_ParseTuple(args, "z", &path)) {
      89             :                 return NULL;
      90             :         }
      91             : 
      92          11 :         smbconf_mod = PyImport_ImportModule(SMBCONF_MOD);
      93          11 :         if (smbconf_mod == NULL) {
      94             :                 return NULL;
      95             :         }
      96             : 
      97          11 :         obj = py_new_SMBConf(smbconf_mod);
      98          11 :         if (obj == NULL) {
      99           0 :                 Py_CLEAR(smbconf_mod);
     100           0 :                 return NULL;
     101             :         }
     102             : 
     103          11 :         mem_ctx = ((py_SMBConf_Object *) obj)->mem_ctx;
     104          11 :         err = smbconf_init_reg(mem_ctx, &conf_ctx, path);
     105          11 :         if (err != SBC_ERR_OK) {
     106           0 :                 py_raise_SMBConfError(smbconf_mod, err);
     107           0 :                 Py_CLEAR(obj);
     108           0 :                 Py_CLEAR(smbconf_mod);
     109           0 :                 return NULL;
     110             :         }
     111          11 :         ((py_SMBConf_Object *) obj)->conf_ctx = conf_ctx;
     112             : 
     113          11 :         Py_DECREF(smbconf_mod);
     114             :         return obj;
     115             : }
     116             : 
     117           2 : static PyObject *py_init_str(PyObject * module, PyObject * args)
     118             : {
     119           2 :         PyObject *obj = NULL;
     120           2 :         PyObject *smbconf_mod = NULL;
     121           2 :         char *path = NULL;
     122           2 :         struct smbconf_ctx *conf_ctx = NULL;
     123           2 :         TALLOC_CTX *mem_ctx = NULL;
     124           2 :         sbcErr err;
     125             : 
     126           2 :         if (!PyArg_ParseTuple(args, "s", &path)) {
     127             :                 return NULL;
     128             :         }
     129             : 
     130           2 :         smbconf_mod = PyImport_ImportModule(SMBCONF_MOD);
     131           2 :         if (smbconf_mod == NULL) {
     132             :                 return NULL;
     133             :         }
     134             : 
     135           2 :         obj = py_new_SMBConf(smbconf_mod);
     136           2 :         if (obj == NULL) {
     137           0 :                 Py_CLEAR(smbconf_mod);
     138           0 :                 return NULL;
     139             :         }
     140             : 
     141           2 :         mem_ctx = ((py_SMBConf_Object *) obj)->mem_ctx;
     142           2 :         err = smbconf_init(mem_ctx, &conf_ctx, path);
     143           2 :         if (err != SBC_ERR_OK) {
     144           0 :                 py_raise_SMBConfError(smbconf_mod, err);
     145           0 :                 Py_CLEAR(obj);
     146           0 :                 Py_CLEAR(smbconf_mod);
     147           0 :                 return NULL;
     148             :         }
     149           2 :         ((py_SMBConf_Object *) obj)->conf_ctx = conf_ctx;
     150             : 
     151           2 :         Py_DECREF(smbconf_mod);
     152             :         return obj;
     153             : }
     154             : 
     155             : PyDoc_STRVAR(py_init_reg_doc,
     156             : "Return an SMBConf object using the registry based configuration.\n"
     157             : "The path argument provided must either be None to use the\n"
     158             : "default path or a path within the registry. It must start with\n"
     159             : "the characters 'HK' if provided. It is *not* a path to a\n"
     160             : "file or database in the file system.\n");
     161             : 
     162             : PyDoc_STRVAR(py_init_str_doc,
     163             : "Return an SMBConf object opened using one of the backends\n"
     164             : "supported by Samba.\n"
     165             : "The provided string argument must be in the form \"backend:path\".\n"
     166             : "The backend portion is to be the name of a supported backend\n"
     167             : "such as 'file', or 'registry'. The path following the colon is\n"
     168             : "backend specific. In the case of the file backend this is the path\n"
     169             : "to a configuration file.\n"
     170             : "Examples:\n"
     171             : "    c1 = samba.samba3.smbconfig.init(\"file:/tmp/smb.conf\")\n"
     172             : "    c2 = samba.samba3.smbconfig.init(\"registry:\")\n");
     173             : /*
     174             :  * The major advantage of having this `init` function in the
     175             :  * python wrapper is that if a backend is added without
     176             :  * explicit changes to the python wrapper libs, it should still
     177             :  * be able to access that backend through the general init
     178             :  * function. The value add is not huge but more like insurance.
     179             :  */
     180             : 
     181             : static PyMethodDef pys3smbconf_methods[] = {
     182             :         { "init_reg", (PyCFunction) py_init_reg, METH_VARARGS,
     183             :          py_init_reg_doc },
     184             :         { "init", (PyCFunction) py_init_str, METH_VARARGS,
     185             :          py_init_str_doc },
     186             :         { 0 },
     187             : };
     188             : 
     189             : PyDoc_STRVAR(py_s3smbconf_doc,
     190             : "The s3smbconf module is a wrapper for Samba's 'source3' smbconf library.\n"
     191             : "This library provides functions to use configuration backends that are\n"
     192             : "specific to the file server suite of components within Samba.\n"
     193             : "This includes functions to access the registry backend of the\n"
     194             : "smbconf subsystem. This backend is read-write.\n");
     195             : 
     196             : static struct PyModuleDef moduledef = {
     197             :         PyModuleDef_HEAD_INIT,
     198             :         .m_name = "smbconf",
     199             :         .m_doc = py_s3smbconf_doc,
     200             :         .m_size = -1,
     201             :         .m_methods = pys3smbconf_methods,
     202             : };
     203             : 
     204           1 : MODULE_INIT_FUNC(smbconf)
     205             : {
     206           1 :         PyObject *m = PyModule_Create(&moduledef);
     207           1 :         if (m == NULL) {
     208           0 :                 return NULL;
     209             :         }
     210             : 
     211             :         return m;
     212             : }

Generated by: LCOV version 1.14