summaryrefslogtreecommitdiffstats
path: root/source3/lib/smbconf/pys3smbconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/lib/smbconf/pys3smbconf.c')
-rw-r--r--source3/lib/smbconf/pys3smbconf.c212
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;
+}