diff options
Diffstat (limited to '')
-rw-r--r-- | source3/lib/smbconf/pys3smbconf.c | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/source3/lib/smbconf/pys3smbconf.c b/source3/lib/smbconf/pys3smbconf.c new file mode 100644 index 0000000..09d4881 --- /dev/null +++ b/source3/lib/smbconf/pys3smbconf.c @@ -0,0 +1,212 @@ +/* + * Unix SMB/CIFS implementation. + * libsmbconf - Samba configuration library - Python bindings + * + * Copyright (C) John Mulligan <phlogistonjohn@asynchrono.us> 2022 + * + * 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 "lib/replace/system/python.h" +#include "includes.h" +#include "python/py3compat.h" + +#include "lib/smbconf/smbconf.h" +#include "source3/lib/smbconf/smbconf_reg.h" +#include "source3/lib/smbconf/smbconf_init.h" +#include "lib/smbconf/pysmbconf.h" + +/* + * The name of the other, general, smbconf module that implements + * the common type. We import this module by name to access + * its methods by the python API. + */ +#define SMBCONF_MOD "samba.smbconf" + +/* + * Return a new but uninitialized SMBConf python object via + * the python API of the (other) smbconf module. + */ +static PyObject *py_new_SMBConf(PyObject * smbconf_mod) +{ + PyObject *obj = NULL; + PyObject *method = PyObject_GetAttrString(smbconf_mod, "SMBConf"); + if (method == NULL) { + return NULL; + } + + obj = PyObject_CallObject(method, NULL); + Py_CLEAR(method); + return obj; +} + +/* + * Raise a new SMBConfError python exception given a error code. + * This uses the python API of the (other) smbconf module. + */ +static PyObject *py_raise_SMBConfError(PyObject * smbconf_mod, sbcErr err) +{ + PyObject *obj = NULL; + PyObject *method = + PyObject_GetAttrString(smbconf_mod, "_smbconf_error"); + if (method == NULL) { + return NULL; + } + + obj = PyObject_CallFunction(method, "i", err); + Py_CLEAR(method); + return obj; +} + +static PyObject *py_init_reg(PyObject * module, PyObject * args) +{ + PyObject *obj = NULL; + PyObject *smbconf_mod = NULL; + char *path = NULL; + struct smbconf_ctx *conf_ctx = NULL; + TALLOC_CTX *mem_ctx = NULL; + sbcErr err; + + /* + * The path here is _NOT_ the path to a file in the file + * system. It's a special HK registry thingy. But passing + * a null string to smbconf_init_reg populates it with + * a functional default value. So we allow the python + * caller to pass None and convert to NULL. + */ + if (!PyArg_ParseTuple(args, "z", &path)) { + return NULL; + } + + smbconf_mod = PyImport_ImportModule(SMBCONF_MOD); + if (smbconf_mod == NULL) { + return NULL; + } + + obj = py_new_SMBConf(smbconf_mod); + if (obj == NULL) { + Py_CLEAR(smbconf_mod); + return NULL; + } + + mem_ctx = ((py_SMBConf_Object *) obj)->mem_ctx; + err = smbconf_init_reg(mem_ctx, &conf_ctx, path); + if (err != SBC_ERR_OK) { + py_raise_SMBConfError(smbconf_mod, err); + Py_CLEAR(obj); + Py_CLEAR(smbconf_mod); + return NULL; + } + ((py_SMBConf_Object *) obj)->conf_ctx = conf_ctx; + + Py_DECREF(smbconf_mod); + return obj; +} + +static PyObject *py_init_str(PyObject * module, PyObject * args) +{ + PyObject *obj = NULL; + PyObject *smbconf_mod = NULL; + char *path = NULL; + struct smbconf_ctx *conf_ctx = NULL; + TALLOC_CTX *mem_ctx = NULL; + sbcErr err; + + if (!PyArg_ParseTuple(args, "s", &path)) { + return NULL; + } + + smbconf_mod = PyImport_ImportModule(SMBCONF_MOD); + if (smbconf_mod == NULL) { + return NULL; + } + + obj = py_new_SMBConf(smbconf_mod); + if (obj == NULL) { + Py_CLEAR(smbconf_mod); + return NULL; + } + + mem_ctx = ((py_SMBConf_Object *) obj)->mem_ctx; + err = smbconf_init(mem_ctx, &conf_ctx, path); + if (err != SBC_ERR_OK) { + py_raise_SMBConfError(smbconf_mod, err); + Py_CLEAR(obj); + Py_CLEAR(smbconf_mod); + return NULL; + } + ((py_SMBConf_Object *) obj)->conf_ctx = conf_ctx; + + Py_DECREF(smbconf_mod); + return obj; +} + +PyDoc_STRVAR(py_init_reg_doc, +"Return an SMBConf object using the registry based configuration.\n" +"The path argument provided must either be None to use the\n" +"default path or a path within the registry. It must start with\n" +"the characters 'HK' if provided. It is *not* a path to a\n" +"file or database in the file system.\n"); + +PyDoc_STRVAR(py_init_str_doc, +"Return an SMBConf object opened using one of the backends\n" +"supported by Samba.\n" +"The provided string argument must be in the form \"backend:path\".\n" +"The backend portion is to be the name of a supported backend\n" +"such as 'file', or 'registry'. The path following the colon is\n" +"backend specific. In the case of the file backend this is the path\n" +"to a configuration file.\n" +"Examples:\n" +" c1 = samba.samba3.smbconfig.init(\"file:/tmp/smb.conf\")\n" +" c2 = samba.samba3.smbconfig.init(\"registry:\")\n"); +/* + * The major advantage of having this `init` function in the + * python wrapper is that if a backend is added without + * explicit changes to the python wrapper libs, it should still + * be able to access that backend through the general init + * function. The value add is not huge but more like insurance. + */ + +static PyMethodDef pys3smbconf_methods[] = { + { "init_reg", (PyCFunction) py_init_reg, METH_VARARGS, + py_init_reg_doc }, + { "init", (PyCFunction) py_init_str, METH_VARARGS, + py_init_str_doc }, + { 0 }, +}; + +PyDoc_STRVAR(py_s3smbconf_doc, +"The s3smbconf module is a wrapper for Samba's 'source3' smbconf library.\n" +"This library provides functions to use configuration backends that are\n" +"specific to the file server suite of components within Samba.\n" +"This includes functions to access the registry backend of the\n" +"smbconf subsystem. This backend is read-write.\n"); + +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + .m_name = "smbconf", + .m_doc = py_s3smbconf_doc, + .m_size = -1, + .m_methods = pys3smbconf_methods, +}; + +MODULE_INIT_FUNC(smbconf) +{ + PyObject *m = PyModule_Create(&moduledef); + if (m == NULL) { + return NULL; + } + + return m; +} |