LCOV - code coverage report
Current view: top level - lib/smbconf - pysmbconf.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 275 374 73.5 %
Date: 2024-05-31 13:13:24 Functions: 23 24 95.8 %

          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 "lib/smbconf/smbconf_txt.h"
      27             : #include "lib/smbconf/pysmbconf.h"
      28             : 
      29             : static PyObject *PyExc_SMBConfError;
      30             : 
      31           6 : static void py_raise_SMBConfError(sbcErr err)
      32             : {
      33           6 :         PyObject *v = NULL;
      34           6 :         PyObject *args = NULL;
      35             : 
      36             :         /*
      37             :          * TODO: have the exception type accept arguments in new/init
      38             :          */
      39           6 :         args = Py_BuildValue("(is)", err, sbcErrorString(err));
      40           6 :         if (args == NULL) {
      41           0 :                 PyErr_Format(PyExc_SMBConfError, "[%d]: %s", err,
      42             :                              sbcErrorString(err));
      43           0 :                 return;
      44             :         }
      45           6 :         v = PyObject_Call(PyExc_SMBConfError, args, NULL);
      46           6 :         if (v == NULL) {
      47           0 :                 Py_CLEAR(args);
      48           0 :                 return;
      49             :         }
      50             :         /*
      51             :          * It's clearer to set an explicit error_code attribute for use in calling
      52             :          * code to check what kind of SMBConfError was raised.
      53             :          */
      54           6 :         if (PyObject_SetAttrString(v, "error_code", PyTuple_GetItem(args, 0)) == -1) {
      55           0 :                 Py_CLEAR(v);
      56           0 :                 Py_CLEAR(args);
      57           0 :                 return;
      58             :         }
      59           6 :         Py_CLEAR(args);
      60           6 :         PyErr_SetObject((PyObject *) Py_TYPE(v), v);
      61           6 :         Py_DECREF(v);
      62             : }
      63             : 
      64             : /*
      65             :  * py_from_smbconf_service returns a python tuple that is basically equivalent
      66             :  * to the struct smbconf_service type content-wise.
      67             :  */
      68          16 : static PyObject *py_from_smbconf_service(struct smbconf_service *svc)
      69             : {
      70          16 :         uint32_t count;
      71          16 :         PyObject *plist = PyList_New(svc->num_params);
      72          16 :         if (plist == NULL) {
      73             :                 return NULL;
      74             :         }
      75             : 
      76          55 :         for (count = 0; count < svc->num_params; count++) {
      77          78 :                 PyObject *pt = Py_BuildValue("(ss)",
      78          39 :                                              svc->param_names[count],
      79          39 :                                              svc->param_values[count]);
      80          39 :                 if (pt == NULL) {
      81           0 :                         Py_CLEAR(plist);
      82           0 :                         return NULL;
      83             :                 }
      84          39 :                 if (PyList_SetItem(plist, count, pt) < 0) {
      85           0 :                         Py_CLEAR(pt);
      86           0 :                         Py_CLEAR(plist);
      87           0 :                         return NULL;
      88             :                 }
      89             :         }
      90          16 :         return Py_BuildValue("(sO)", svc->name, plist);
      91             : }
      92             : 
      93          22 : static PyObject *obj_new(PyTypeObject * type, PyObject * args, PyObject * kwds)
      94             : {
      95          22 :         py_SMBConf_Object *self = (py_SMBConf_Object *) type->tp_alloc(type, 0);
      96          22 :         if (self == NULL) {
      97             :                 return NULL;
      98             :         }
      99             : 
     100          22 :         self->mem_ctx = talloc_new(NULL);
     101          22 :         if (self->mem_ctx == NULL) {
     102           0 :                 Py_DECREF(self);
     103           0 :                 return NULL;
     104             :         }
     105             : 
     106             :         return (PyObject *) self;
     107             : }
     108             : 
     109          22 : static void obj_dealloc(py_SMBConf_Object * self)
     110             : {
     111          22 :         if (self->conf_ctx != NULL) {
     112          20 :                 smbconf_shutdown(self->conf_ctx);
     113             :         }
     114          22 :         talloc_free(self->mem_ctx);
     115          22 :         Py_TYPE(self)->tp_free((PyObject *) self);
     116          22 : }
     117             : 
     118          28 : static bool obj_ready(py_SMBConf_Object * self)
     119             : {
     120          28 :         if (self->conf_ctx == NULL) {
     121           4 :                 PyErr_Format(PyExc_RuntimeError,
     122             :                              "attempt to use an uninitialized SMBConf object");
     123           4 :                 return false;
     124             :         }
     125             :         return true;
     126             : }
     127             : 
     128           2 : static PyObject *obj_requires_messaging(py_SMBConf_Object * self,
     129             :                                         PyObject * Py_UNUSED(ignored))
     130             : {
     131           2 :         if (!obj_ready(self)) {
     132           1 :                 return NULL;
     133             :         }
     134           1 :         if (smbconf_backend_requires_messaging(self->conf_ctx)) {
     135           0 :                 Py_RETURN_TRUE;
     136             :         }
     137           1 :         Py_RETURN_FALSE;
     138             : }
     139             : 
     140           5 : static PyObject *obj_is_writable(py_SMBConf_Object * self,
     141             :                                  PyObject * Py_UNUSED(ignored))
     142             : {
     143           5 :         if (!obj_ready(self)) {
     144           1 :                 return NULL;
     145             :         }
     146           4 :         if (smbconf_is_writeable(self->conf_ctx)) {
     147           2 :                 Py_RETURN_TRUE;
     148             :         }
     149           2 :         Py_RETURN_FALSE;
     150             : }
     151             : 
     152           7 : static PyObject *obj_share_names(py_SMBConf_Object * self,
     153             :                                  PyObject * Py_UNUSED(ignored))
     154             : {
     155           7 :         sbcErr err;
     156           7 :         uint32_t count;
     157           7 :         uint32_t num_shares;
     158           7 :         char **share_names = NULL;
     159           7 :         PyObject *slist = NULL;
     160           7 :         TALLOC_CTX *mem_ctx = NULL;
     161             : 
     162           7 :         if (!obj_ready(self)) {
     163           1 :                 return NULL;
     164             :         }
     165             : 
     166           6 :         mem_ctx = talloc_new(self->mem_ctx);
     167           6 :         if (mem_ctx == NULL) {
     168           0 :                 PyErr_NoMemory();
     169           0 :                 return NULL;
     170             :         }
     171             : 
     172           6 :         err =
     173           6 :             smbconf_get_share_names(self->conf_ctx, mem_ctx, &num_shares,
     174             :                                     &share_names);
     175           6 :         if (err != SBC_ERR_OK) {
     176           0 :                 talloc_free(mem_ctx);
     177           0 :                 py_raise_SMBConfError(err);
     178           0 :                 return NULL;
     179             :         }
     180             : 
     181           6 :         slist = PyList_New(num_shares);
     182           6 :         if (slist == NULL) {
     183           0 :                 talloc_free(mem_ctx);
     184           0 :                 return NULL;
     185             :         }
     186          18 :         for (count = 0; count < num_shares; count++) {
     187          12 :                 PyObject *ustr = PyUnicode_FromString(share_names[count]);
     188          12 :                 if (ustr == NULL) {
     189           0 :                         Py_CLEAR(slist);
     190           0 :                         talloc_free(mem_ctx);
     191           0 :                         return NULL;
     192             :                 }
     193          12 :                 if (PyList_SetItem(slist, count, ustr) < 0) {
     194           0 :                         Py_CLEAR(ustr);
     195           0 :                         Py_CLEAR(slist);
     196           0 :                         talloc_free(mem_ctx);
     197           0 :                         return NULL;
     198             :                 }
     199             :         }
     200           6 :         talloc_free(mem_ctx);
     201           6 :         return slist;
     202             : }
     203             : 
     204          13 : static PyObject *obj_get_share(py_SMBConf_Object * self, PyObject * args)
     205             : {
     206          13 :         sbcErr err;
     207          13 :         char *servicename = NULL;
     208          13 :         struct smbconf_service *svc = NULL;
     209          13 :         PyObject *plist = NULL;
     210          13 :         TALLOC_CTX *mem_ctx = NULL;
     211             : 
     212          13 :         if (!PyArg_ParseTuple(args, "s", &servicename)) {
     213             :                 return NULL;
     214             :         }
     215             : 
     216          13 :         if (!obj_ready(self)) {
     217           1 :                 return NULL;
     218             :         }
     219             : 
     220          12 :         mem_ctx = talloc_new(self->mem_ctx);
     221          12 :         if (mem_ctx == NULL) {
     222           0 :                 PyErr_NoMemory();
     223           0 :                 return NULL;
     224             :         }
     225             : 
     226          12 :         err = smbconf_get_share(self->conf_ctx, mem_ctx, servicename, &svc);
     227          12 :         if (err != SBC_ERR_OK) {
     228           1 :                 talloc_free(mem_ctx);
     229           1 :                 py_raise_SMBConfError(err);
     230           1 :                 return NULL;
     231             :         }
     232             :         /*
     233             :          * if py_from_smbconf_service returns NULL, then an exception should
     234             :          * already be set. No special error handling needed.
     235             :          */
     236          11 :         plist = py_from_smbconf_service(svc);
     237          11 :         talloc_free(mem_ctx);
     238          11 :         return plist;
     239             : }
     240             : 
     241           1 : static PyObject *obj_get_config(py_SMBConf_Object * self,
     242             :                                 PyObject * Py_UNUSED(ignored))
     243             : {
     244           1 :         sbcErr err;
     245           1 :         PyObject *svclist = NULL;
     246           1 :         TALLOC_CTX *mem_ctx = NULL;
     247           1 :         uint32_t count;
     248           1 :         uint32_t num_shares;
     249           1 :         struct smbconf_service **svcs = NULL;
     250             : 
     251           1 :         if (!obj_ready(self)) {
     252           0 :                 return NULL;
     253             :         }
     254             : 
     255           1 :         mem_ctx = talloc_new(self->mem_ctx);
     256           1 :         if (mem_ctx == NULL) {
     257           0 :                 PyErr_NoMemory();
     258           0 :                 return NULL;
     259             :         }
     260             : 
     261           1 :         err = smbconf_get_config(self->conf_ctx, mem_ctx, &num_shares, &svcs);
     262           1 :         if (err != SBC_ERR_OK) {
     263           0 :                 talloc_free(mem_ctx);
     264           0 :                 py_raise_SMBConfError(err);
     265           0 :                 return NULL;
     266             :         }
     267             : 
     268           1 :         svclist = PyList_New(num_shares);
     269           1 :         if (svclist == NULL) {
     270           0 :                 talloc_free(mem_ctx);
     271           0 :                 return NULL;
     272             :         }
     273           6 :         for (count = 0; count < num_shares; count++) {
     274           5 :                 PyObject *svcobj = py_from_smbconf_service(svcs[count]);
     275           5 :                 if (svcobj == NULL) {
     276           0 :                         Py_CLEAR(svclist);
     277           0 :                         talloc_free(mem_ctx);
     278           0 :                         return NULL;
     279             :                 }
     280           5 :                 if (PyList_SetItem(svclist, count, svcobj) < 0) {
     281           0 :                         Py_CLEAR(svcobj);
     282           0 :                         Py_CLEAR(svclist);
     283           0 :                         talloc_free(mem_ctx);
     284           0 :                         return NULL;
     285             :                 }
     286             :         }
     287             : 
     288           1 :         talloc_free(mem_ctx);
     289           1 :         return svclist;
     290             : }
     291             : 
     292           7 : static PyObject *obj_create_share(py_SMBConf_Object * self, PyObject * args)
     293             : {
     294           7 :         sbcErr err;
     295           7 :         char *servicename = NULL;
     296             : 
     297           7 :         if (!PyArg_ParseTuple(args, "s", &servicename)) {
     298             :                 return NULL;
     299             :         }
     300             : 
     301           7 :         err = smbconf_create_share(self->conf_ctx, servicename);
     302           7 :         if (err != SBC_ERR_OK) {
     303           1 :                 py_raise_SMBConfError(err);
     304           1 :                 return NULL;
     305             :         }
     306           6 :         Py_RETURN_NONE;
     307             : }
     308             : 
     309          11 : static PyObject *obj_drop(py_SMBConf_Object * self,
     310             :                           PyObject * Py_UNUSED(ignored))
     311             : {
     312          11 :         sbcErr err;
     313             : 
     314          11 :         err = smbconf_drop(self->conf_ctx);
     315          11 :         if (err != SBC_ERR_OK) {
     316           0 :                 py_raise_SMBConfError(err);
     317           0 :                 return NULL;
     318             :         }
     319          11 :         Py_RETURN_NONE;
     320             : }
     321             : 
     322           2 : static PyObject *obj_set_parameter(py_SMBConf_Object * self, PyObject * args)
     323             : {
     324           2 :         sbcErr err;
     325           2 :         char *servicename = NULL;
     326           2 :         char *param = NULL;
     327           2 :         char *val = NULL;
     328             : 
     329           2 :         if (!PyArg_ParseTuple(args, "sss", &servicename, &param, &val)) {
     330             :                 return NULL;
     331             :         }
     332             : 
     333           2 :         err = smbconf_set_parameter(self->conf_ctx, servicename, param, val);
     334           2 :         if (err != SBC_ERR_OK) {
     335           0 :                 py_raise_SMBConfError(err);
     336           0 :                 return NULL;
     337             :         }
     338           2 :         Py_RETURN_NONE;
     339             : }
     340             : 
     341          11 : static PyObject *obj_set_global_parameter(py_SMBConf_Object * self,
     342             :                                           PyObject * args)
     343             : {
     344          11 :         sbcErr err;
     345          11 :         char *param = NULL;
     346          11 :         char *val = NULL;
     347             : 
     348          11 :         if (!PyArg_ParseTuple(args, "ss", &param, &val)) {
     349             :                 return NULL;
     350             :         }
     351             : 
     352          11 :         err = smbconf_set_global_parameter(self->conf_ctx, param, val);
     353          11 :         if (err != SBC_ERR_OK) {
     354           1 :                 py_raise_SMBConfError(err);
     355           1 :                 return NULL;
     356             :         }
     357          10 :         Py_RETURN_NONE;
     358             : }
     359             : 
     360           1 : static PyObject *obj_delete_share(py_SMBConf_Object * self, PyObject * args)
     361             : {
     362           1 :         sbcErr err;
     363           1 :         char *servicename = NULL;
     364             : 
     365           1 :         if (!PyArg_ParseTuple(args, "s", &servicename)) {
     366             :                 return NULL;
     367             :         }
     368             : 
     369           1 :         err = smbconf_delete_share(self->conf_ctx, servicename);
     370           1 :         if (err != SBC_ERR_OK) {
     371           0 :                 py_raise_SMBConfError(err);
     372           0 :                 return NULL;
     373             :         }
     374           1 :         Py_RETURN_NONE;
     375             : }
     376             : 
     377          28 : static char *py_get_kv_str(TALLOC_CTX * mem_ctx, PyObject * obj, Py_ssize_t idx)
     378             : {
     379          28 :         char *ss = NULL;
     380          28 :         PyObject *pystr = PySequence_GetItem(obj, idx);
     381          28 :         if (pystr == NULL) {
     382             :                 return NULL;
     383             :         }
     384          28 :         if (!PyUnicode_Check(pystr)) {
     385           1 :                 PyErr_SetString(PyExc_TypeError, "keys/values expect a str");
     386           1 :                 Py_CLEAR(pystr);
     387           1 :                 return NULL;
     388             :         }
     389          27 :         ss = talloc_strdup(mem_ctx, PyUnicode_AsUTF8(pystr));
     390          27 :         Py_CLEAR(pystr);
     391             :         return ss;
     392             : }
     393             : 
     394          11 : static PyObject *obj_create_set_share(py_SMBConf_Object * self, PyObject * args)
     395             : {
     396          11 :         sbcErr err;
     397          11 :         char *servicename = NULL;
     398          11 :         PyObject *kvs = NULL;
     399          11 :         Py_ssize_t size, idx;
     400          11 :         struct smbconf_service *tmp_service = NULL;
     401          11 :         TALLOC_CTX *tmp_ctx = talloc_new(self->mem_ctx);
     402             : 
     403          11 :         if (!PyArg_ParseTuple(args, "sO", &servicename, &kvs)) {
     404           0 :                 talloc_free(tmp_ctx);
     405           0 :                 return NULL;
     406             :         }
     407             : 
     408          11 :         if (PySequence_Check(kvs) == 0) {
     409           1 :                 PyErr_SetString(PyExc_TypeError,
     410             :                                 "a sequence object is required");
     411           1 :                 talloc_free(tmp_ctx);
     412           1 :                 return NULL;
     413             :         }
     414             : 
     415          10 :         size = PySequence_Size(kvs);
     416          10 :         if (size == -1) {
     417           0 :                 PyErr_SetString(PyExc_ValueError, "failed to get size");
     418           0 :                 talloc_free(tmp_ctx);
     419           0 :                 return NULL;
     420             :         }
     421             : 
     422          10 :         tmp_service = talloc_zero(tmp_ctx, struct smbconf_service);
     423          10 :         if (tmp_service == NULL) {
     424           0 :                 PyErr_NoMemory();
     425           0 :                 talloc_free(tmp_ctx);
     426           0 :                 return NULL;
     427             :         }
     428             : 
     429          10 :         tmp_service->name = talloc_strdup(tmp_service, servicename);
     430          10 :         if (tmp_service->name == NULL) {
     431           0 :                 PyErr_NoMemory();
     432           0 :                 talloc_free(tmp_ctx);
     433           0 :                 return NULL;
     434             :         }
     435          10 :         tmp_service->num_params = (uint32_t) size;
     436          10 :         tmp_service->param_names = talloc_array(tmp_ctx, char *, size);
     437          10 :         if (tmp_service->param_names == NULL) {
     438           0 :                 PyErr_NoMemory();
     439           0 :                 talloc_free(tmp_ctx);
     440           0 :                 return NULL;
     441             :         }
     442          10 :         tmp_service->param_values = talloc_array(tmp_ctx, char *, size);
     443          10 :         if (tmp_service->param_values == NULL) {
     444           0 :                 PyErr_NoMemory();
     445           0 :                 talloc_free(tmp_ctx);
     446           0 :                 return NULL;
     447             :         }
     448             : 
     449          23 :         for (idx = 0; idx < size; idx++) {
     450          16 :                 char *tmp_str = NULL;
     451          16 :                 PyObject *tmp_pair = PySequence_GetItem(kvs, idx);
     452          16 :                 if (tmp_pair == NULL) {
     453           0 :                         talloc_free(tmp_ctx);
     454           0 :                         return NULL;
     455             :                 }
     456          16 :                 if (PySequence_Size(tmp_pair) != 2) {
     457           2 :                         PyErr_SetString(PyExc_ValueError,
     458             :                                         "expecting two-item tuples");
     459           2 :                         Py_CLEAR(tmp_pair);
     460           2 :                         talloc_free(tmp_ctx);
     461           2 :                         return NULL;
     462             :                 }
     463             : 
     464             :                 /* fetch key */
     465          14 :                 tmp_str = py_get_kv_str(tmp_ctx, tmp_pair, 0);
     466          14 :                 if (tmp_str == NULL) {
     467           0 :                         Py_CLEAR(tmp_pair);
     468           0 :                         talloc_free(tmp_ctx);
     469           0 :                         return NULL;
     470             :                 }
     471          14 :                 tmp_service->param_names[idx] = tmp_str;
     472             : 
     473             :                 /* fetch value */
     474          14 :                 tmp_str = py_get_kv_str(tmp_ctx, tmp_pair, 1);
     475          14 :                 if (tmp_str == NULL) {
     476           1 :                         Py_CLEAR(tmp_pair);
     477           1 :                         talloc_free(tmp_ctx);
     478           1 :                         return NULL;
     479             :                 }
     480          13 :                 tmp_service->param_values[idx] = tmp_str;
     481             : 
     482          13 :                 Py_CLEAR(tmp_pair);
     483             :         }
     484             : 
     485           7 :         err = smbconf_create_set_share(self->conf_ctx, tmp_service);
     486           7 :         if (err != SBC_ERR_OK) {
     487           2 :                 py_raise_SMBConfError(err);
     488           2 :                 talloc_free(tmp_ctx);
     489           2 :                 return NULL;
     490             :         }
     491           5 :         talloc_free(tmp_ctx);
     492           5 :         Py_RETURN_NONE;
     493             : }
     494             : 
     495           1 : static PyObject *obj_delete_parameter(py_SMBConf_Object * self, PyObject * args)
     496             : {
     497           1 :         sbcErr err;
     498           1 :         char *servicename = NULL;
     499           1 :         char *param_name = NULL;
     500             : 
     501           1 :         if (!PyArg_ParseTuple(args, "ss", &servicename, &param_name)) {
     502             :                 return NULL;
     503             :         }
     504             : 
     505           1 :         err = smbconf_delete_parameter(self->conf_ctx, servicename, param_name);
     506           1 :         if (err != SBC_ERR_OK) {
     507           0 :                 py_raise_SMBConfError(err);
     508           0 :                 return NULL;
     509             :         }
     510           1 :         Py_RETURN_NONE;
     511             : }
     512             : 
     513           2 : static PyObject *obj_delete_global_parameter(py_SMBConf_Object * self,
     514             :                                              PyObject * args)
     515             : {
     516           2 :         sbcErr err;
     517           2 :         char *param_name = NULL;
     518             : 
     519           2 :         if (!PyArg_ParseTuple(args, "s", &param_name)) {
     520             :                 return NULL;
     521             :         }
     522             : 
     523           2 :         err = smbconf_delete_global_parameter(self->conf_ctx, param_name);
     524           2 :         if (err != SBC_ERR_OK) {
     525           0 :                 py_raise_SMBConfError(err);
     526           0 :                 return NULL;
     527             :         }
     528           2 :         Py_RETURN_NONE;
     529             : }
     530             : 
     531           4 : static PyObject *obj_transaction_start(py_SMBConf_Object * self,
     532             :                                        PyObject * Py_UNUSED(ignored))
     533             : {
     534           4 :         sbcErr err = smbconf_transaction_start(self->conf_ctx);
     535           4 :         if (err != SBC_ERR_OK) {
     536           0 :                 py_raise_SMBConfError(err);
     537           0 :                 return NULL;
     538             :         }
     539           4 :         Py_RETURN_NONE;
     540             : }
     541             : 
     542           2 : static PyObject *obj_transaction_commit(py_SMBConf_Object * self,
     543             :                                         PyObject * Py_UNUSED(ignored))
     544             : {
     545           2 :         sbcErr err = smbconf_transaction_commit(self->conf_ctx);
     546           2 :         if (err != SBC_ERR_OK) {
     547           0 :                 py_raise_SMBConfError(err);
     548           0 :                 return NULL;
     549             :         }
     550           2 :         Py_RETURN_NONE;
     551             : }
     552             : 
     553           2 : static PyObject *obj_transaction_cancel(py_SMBConf_Object * self,
     554             :                                         PyObject * Py_UNUSED(ignored))
     555             : {
     556           2 :         sbcErr err = smbconf_transaction_cancel(self->conf_ctx);
     557           2 :         if (err != SBC_ERR_OK) {
     558           0 :                 py_raise_SMBConfError(err);
     559           0 :                 return NULL;
     560             :         }
     561           2 :         Py_RETURN_NONE;
     562             : }
     563             : 
     564             : PyDoc_STRVAR(obj_requires_messaging_doc,
     565             : "requires_messaging() -> bool\n"
     566             : "\n"
     567             : "Returns true if the backend requires interprocess messaging.\n");
     568             : 
     569             : PyDoc_STRVAR(obj_is_writable_doc,
     570             : "is_writeable() -> bool\n"
     571             : "\n"
     572             : "Returns true if the SMBConf object's backend is writable.\n");
     573             : 
     574             : PyDoc_STRVAR(obj_share_names_doc,
     575             : "share_names() -> list[str]\n"
     576             : "\n"
     577             : "Return a list of the share names currently configured.\n"
     578             : "Includes the global section as a share name.\n");
     579             : 
     580             : PyDoc_STRVAR(obj_get_share_doc,
     581             : "get_share() -> (str, list[(str, str)])\n"
     582             : "\n"
     583             : "Given the name of a share, return a tuple of \n"
     584             : "(share_name, share_parms) where share_params is a list of\n"
     585             : "(param_name, param_value) tuples.\n"
     586             : "The term global can be specified to get global section parameters.\n");
     587             : 
     588             : PyDoc_STRVAR(obj_get_config_doc,
     589             : "get_config() -> list[(str, list[(str, str)])]\n"
     590             : "Return a list of tuples for every section/share of the current\n"
     591             : "configuration. Each tuple in the list is the same as described\n"
     592             : "for get_share().\n");
     593             : 
     594             : PyDoc_STRVAR(obj_create_share_doc,
     595             : "create_share(name: str) -> None\n"
     596             : "Create a new empty share in the configuration. The share\n"
     597             : "name must not exist or an error will be raised.\n");
     598             : 
     599             : PyDoc_STRVAR(obj_drop_doc,
     600             : "drop() -> None\n"
     601             : "Drop the entire configuration, resetting it to an empty state.\n");
     602             : 
     603             : PyDoc_STRVAR(obj_set_parameter_doc,
     604             : "set_parameter(str, str, str) -> None\n"
     605             : "Set a configuration parameter. Specify service name, parameter name,\n"
     606             : "and parameter value.\n");
     607             : 
     608             : PyDoc_STRVAR(obj_set_global_parameter_doc,
     609             : "set_global_parameter(str, str) -> None\n"
     610             : "Set a global configuration parameter. Specify the parameter name\n"
     611             : "and parameter value.\n");
     612             : 
     613             : PyDoc_STRVAR(obj_delete_share_doc,
     614             : "delete_share(str) -> None\n"
     615             : "Delete a service from the configuration.\n");
     616             : 
     617             : PyDoc_STRVAR(obj_create_set_share_doc,
     618             : "create_set_share(str, [(str, str)...]) -> None\n"
     619             : "Create and set the definition of a service.\n");
     620             : 
     621             : PyDoc_STRVAR(obj_delete_parameter_doc,
     622             : "delete_parameter(str, str) -> None\n"
     623             : "Delete a single configuration parameter.\n");
     624             : 
     625             : PyDoc_STRVAR(obj_delete_global_parameter_doc,
     626             : "delete_parameter(str, str) -> None\n"
     627             : "Delete a single global configuration parameter.\n");
     628             : 
     629             : PyDoc_STRVAR(obj_transaction_start_doc,
     630             : "transaction_start() -> None\n"
     631             : "Start a transaction.\n"
     632             : "Transactions allow making compound sets of changes atomically.\n");
     633             : 
     634             : PyDoc_STRVAR(obj_transaction_commit_doc,
     635             : "transaction_commit() -> None\n"
     636             : "Commit the transaction.\n");
     637             : 
     638             : PyDoc_STRVAR(obj_transaction_cancel_doc,
     639             : "transaction_cancel() -> None\n"
     640             : "Cancel the transaction.\n");
     641             : 
     642             : static PyMethodDef py_smbconf_obj_methods[] = {
     643             :         { "requires_messaging", (PyCFunction) obj_requires_messaging,
     644             :          METH_NOARGS, obj_requires_messaging_doc },
     645             :         { "is_writeable", (PyCFunction) obj_is_writable, METH_NOARGS,
     646             :          obj_is_writable_doc },
     647             :         { "share_names", (PyCFunction) obj_share_names, METH_NOARGS,
     648             :          obj_share_names_doc },
     649             :         { "get_share", (PyCFunction) obj_get_share, METH_VARARGS,
     650             :          obj_get_share_doc },
     651             :         { "get_config", (PyCFunction) obj_get_config, METH_NOARGS,
     652             :          obj_get_config_doc },
     653             :         { "create_share", (PyCFunction) obj_create_share, METH_VARARGS,
     654             :          obj_create_share_doc },
     655             :         { "create_set_share", (PyCFunction) obj_create_set_share, METH_VARARGS,
     656             :          obj_create_set_share_doc },
     657             :         { "drop", (PyCFunction) obj_drop, METH_NOARGS,
     658             :          obj_drop_doc },
     659             :         { "set_parameter", (PyCFunction) obj_set_parameter, METH_VARARGS,
     660             :          obj_set_parameter_doc },
     661             :         { "set_global_parameter", (PyCFunction) obj_set_global_parameter,
     662             :          METH_VARARGS, obj_set_global_parameter_doc },
     663             :         { "delete_share", (PyCFunction) obj_delete_share, METH_VARARGS,
     664             :          obj_delete_share_doc },
     665             :         { "delete_parameter", (PyCFunction) obj_delete_parameter, METH_VARARGS,
     666             :          obj_delete_parameter_doc },
     667             :         { "delete_global_parameter", (PyCFunction) obj_delete_global_parameter,
     668             :          METH_VARARGS, obj_delete_global_parameter_doc },
     669             :         { "transaction_start", (PyCFunction) obj_transaction_start, METH_NOARGS,
     670             :          obj_transaction_start_doc },
     671             :         { "transaction_commit", (PyCFunction) obj_transaction_commit,
     672             :          METH_NOARGS, obj_transaction_commit_doc },
     673             :         { "transaction_cancel", (PyCFunction) obj_transaction_cancel,
     674             :          METH_NOARGS, obj_transaction_cancel_doc },
     675             :         { 0 },
     676             : };
     677             : 
     678             : PyDoc_STRVAR(py_SMBConf_type_doc,
     679             : "SMBConf objects provide uniform access to Samba configuration backends.\n"
     680             : "\n"
     681             : "The SMBConf type should not be instantiated directly. Rather, use a\n"
     682             : "backend specific init function like init_txt.\n");
     683             : 
     684             : static PyTypeObject py_SMBConf_Type = {
     685             :         PyVarObject_HEAD_INIT(NULL, 0)
     686             :         .tp_name = "smbconf.SMBConf",
     687             :         .tp_doc = py_SMBConf_type_doc,
     688             :         .tp_basicsize = sizeof(py_SMBConf_Object),
     689             :         .tp_methods = py_smbconf_obj_methods,
     690             :         .tp_new = obj_new,
     691             :         .tp_dealloc = (destructor) obj_dealloc,
     692             : };
     693             : 
     694           8 : static PyObject *py_init_txt(PyObject * module, PyObject * args)
     695             : {
     696           8 :         py_SMBConf_Object *obj;
     697           8 :         sbcErr err;
     698           8 :         char *path = NULL;
     699           8 :         struct smbconf_ctx *conf_ctx = NULL;
     700             : 
     701           8 :         if (!PyArg_ParseTuple(args, "s", &path)) {
     702             :                 return NULL;
     703             :         }
     704             : 
     705           8 :         obj = (py_SMBConf_Object *) obj_new(&py_SMBConf_Type, NULL, NULL);
     706           8 :         if (obj == NULL) {
     707             :                 return NULL;
     708             :         }
     709             : 
     710           8 :         err = smbconf_init_txt(obj->mem_ctx, &conf_ctx, path);
     711           8 :         if (err != SBC_ERR_OK) {
     712           1 :                 Py_DECREF(obj);
     713           1 :                 py_raise_SMBConfError(err);
     714           1 :                 return NULL;
     715             :         }
     716           7 :         obj->conf_ctx = conf_ctx;
     717           7 :         return (PyObject *) obj;
     718             : }
     719             : 
     720           0 : static PyObject *py_smbconf_error(PyObject * module, PyObject * args)
     721             : {
     722           0 :         sbcErr errcode;
     723             : 
     724           0 :         if (!PyArg_ParseTuple(args, "i", &errcode)) {
     725             :                 return NULL;
     726             :         }
     727             : 
     728             :         /* this always raises an exception. it doesn't return the exception. */
     729           0 :         py_raise_SMBConfError(errcode);
     730           0 :         return NULL;
     731             : }
     732             : 
     733             : static PyMethodDef pysmbconf_methods[] = {
     734             :         { "init_txt", (PyCFunction) py_init_txt, METH_VARARGS,
     735             :          "Return an SMBConf object for the given text config file." },
     736             :         { "_smbconf_error", (PyCFunction) py_smbconf_error, METH_VARARGS,
     737             :          "Raise an SMBConfError based on the given error code." },
     738             :         { 0 },
     739             : };
     740             : 
     741             : PyDoc_STRVAR(py_smbconf_doc,
     742             : "The smbconf module is a wrapper for Samba's smbconf library.\n"
     743             : "This library supports common functions to access the contents\n"
     744             : "of a configuration backend, such as the text-based smb.conf file\n"
     745             : "or the read-write registry backend.\n"
     746             : "The read-only functions on the SMBConf type function on both backend\n"
     747             : "types. Future, write based functions need a writable backend (registry).\n"
     748             : "\n"
     749             : "Note that the registry backend will be provided by a different\n"
     750             : "library module from the source3 tree (implementation TBD).\n");
     751             : 
     752             : static struct PyModuleDef moduledef = {
     753             :         PyModuleDef_HEAD_INIT,
     754             :         .m_name = "smbconf",
     755             :         .m_doc = py_smbconf_doc,
     756             :         .m_size = -1,
     757             :         .m_methods = pysmbconf_methods,
     758             : };
     759             : 
     760           1 : MODULE_INIT_FUNC(smbconf)
     761             : {
     762           1 :         PyObject *m = PyModule_Create(&moduledef);
     763           1 :         if (m == NULL) {
     764             :                 return NULL;
     765             :         }
     766             : 
     767           1 :         if (PyType_Ready(&py_SMBConf_Type) < 0) {
     768           0 :                 Py_DECREF(m);
     769           0 :                 return NULL;
     770             :         }
     771           1 :         Py_INCREF(&py_SMBConf_Type);
     772           1 :         if (PyModule_AddObject(m, "SMBConf", (PyObject *) & py_SMBConf_Type) <
     773             :             0) {
     774           0 :                 Py_DECREF(&py_SMBConf_Type);
     775           0 :                 Py_DECREF(m);
     776           0 :                 return NULL;
     777             :         }
     778             : 
     779           2 :         PyExc_SMBConfError =
     780           1 :             PyErr_NewException(discard_const_p(char, "smbconf.SMBConfError"),
     781             :                                NULL, NULL);
     782           1 :         if (PyExc_SMBConfError == NULL) {
     783           0 :                 Py_DECREF(m);
     784           0 :                 return NULL;
     785             :         }
     786           1 :         Py_INCREF(PyExc_SMBConfError);
     787           1 :         if (PyModule_AddObject(m, "SMBConfError", PyExc_SMBConfError) < 0) {
     788           0 :                 Py_DECREF(PyExc_SMBConfError);
     789           0 :                 Py_DECREF(m);
     790           0 :                 return NULL;
     791             :         }
     792             : 
     793             : /*
     794             :  * ADD_FLAGS macro borrowed from source3/libsmb/pylibsmb.c
     795             :  */
     796             : #define ADD_FLAGS(val)  PyModule_AddObject(m, #val, PyLong_FromLong(val))
     797             : 
     798           1 :         ADD_FLAGS(SBC_ERR_OK);
     799           1 :         ADD_FLAGS(SBC_ERR_NOT_IMPLEMENTED);
     800           1 :         ADD_FLAGS(SBC_ERR_NOT_SUPPORTED);
     801           1 :         ADD_FLAGS(SBC_ERR_UNKNOWN_FAILURE);
     802           1 :         ADD_FLAGS(SBC_ERR_NOMEM);
     803           1 :         ADD_FLAGS(SBC_ERR_INVALID_PARAM);
     804           1 :         ADD_FLAGS(SBC_ERR_BADFILE);
     805           1 :         ADD_FLAGS(SBC_ERR_NO_SUCH_SERVICE);
     806           1 :         ADD_FLAGS(SBC_ERR_IO_FAILURE);
     807           1 :         ADD_FLAGS(SBC_ERR_CAN_NOT_COMPLETE);
     808           1 :         ADD_FLAGS(SBC_ERR_NO_MORE_ITEMS);
     809           1 :         ADD_FLAGS(SBC_ERR_FILE_EXISTS);
     810           1 :         ADD_FLAGS(SBC_ERR_ACCESS_DENIED);
     811             : 
     812           1 :         return m;
     813             : }

Generated by: LCOV version 1.14