2 * Unix SMB/CIFS implementation.
3 * libsmbconf - Samba configuration library - Python bindings
5 * Copyright (C) John Mulligan <phlogistonjohn@asynchrono.us> 2022
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.
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.
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/>.
21 #include "lib/replace/system/python.h"
23 #include "python/py3compat.h"
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"
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.
35 #define SMBCONF_MOD "samba.smbconf"
38 * Return a new but uninitialized SMBConf python object via
39 * the python API of the (other) smbconf module.
41 static PyObject
*py_new_SMBConf(PyObject
* smbconf_mod
)
44 PyObject
*method
= PyObject_GetAttrString(smbconf_mod
, "SMBConf");
49 obj
= PyObject_CallObject(method
, NULL
);
55 * Raise a new SMBConfError python exception given a error code.
56 * This uses the python API of the (other) smbconf module.
58 static PyObject
*py_raise_SMBConfError(PyObject
* smbconf_mod
, sbcErr err
)
62 PyObject_GetAttrString(smbconf_mod
, "_smbconf_error");
67 obj
= PyObject_CallFunction(method
, "i", err
);
72 static PyObject
*py_init_reg(PyObject
* module
, PyObject
* args
)
75 PyObject
*smbconf_mod
= NULL
;
77 struct smbconf_ctx
*conf_ctx
= NULL
;
78 TALLOC_CTX
*mem_ctx
= NULL
;
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.
88 if (!PyArg_ParseTuple(args
, "z", &path
)) {
92 smbconf_mod
= PyImport_ImportModule(SMBCONF_MOD
);
93 if (smbconf_mod
== NULL
) {
97 obj
= py_new_SMBConf(smbconf_mod
);
99 Py_CLEAR(smbconf_mod
);
103 mem_ctx
= ((py_SMBConf_Object
*) obj
)->mem_ctx
;
104 err
= smbconf_init_reg(mem_ctx
, &conf_ctx
, path
);
105 if (err
!= SBC_ERR_OK
) {
106 py_raise_SMBConfError(smbconf_mod
, err
);
108 Py_CLEAR(smbconf_mod
);
111 ((py_SMBConf_Object
*) obj
)->conf_ctx
= conf_ctx
;
113 Py_DECREF(smbconf_mod
);
117 static PyObject
*py_init_str(PyObject
* module
, PyObject
* args
)
119 PyObject
*obj
= NULL
;
120 PyObject
*smbconf_mod
= NULL
;
122 struct smbconf_ctx
*conf_ctx
= NULL
;
123 TALLOC_CTX
*mem_ctx
= NULL
;
126 if (!PyArg_ParseTuple(args
, "s", &path
)) {
130 smbconf_mod
= PyImport_ImportModule(SMBCONF_MOD
);
131 if (smbconf_mod
== NULL
) {
135 obj
= py_new_SMBConf(smbconf_mod
);
137 Py_CLEAR(smbconf_mod
);
141 mem_ctx
= ((py_SMBConf_Object
*) obj
)->mem_ctx
;
142 err
= smbconf_init(mem_ctx
, &conf_ctx
, path
);
143 if (err
!= SBC_ERR_OK
) {
144 py_raise_SMBConfError(smbconf_mod
, err
);
146 Py_CLEAR(smbconf_mod
);
149 ((py_SMBConf_Object
*) obj
)->conf_ctx
= conf_ctx
;
151 Py_DECREF(smbconf_mod
);
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");
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"
171 " c1 = samba.samba3.smbconfig.init(\"file:/tmp/smb.conf\")\n"
172 " c2 = samba.samba3.smbconfig.init(\"registry:\")\n");
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.
181 static PyMethodDef pys3smbconf_methods
[] = {
182 { "init_reg", (PyCFunction
) py_init_reg
, METH_VARARGS
,
184 { "init", (PyCFunction
) py_init_str
, METH_VARARGS
,
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");
196 static struct PyModuleDef moduledef
= {
197 PyModuleDef_HEAD_INIT
,
199 .m_doc
= py_s3smbconf_doc
,
201 .m_methods
= pys3smbconf_methods
,
204 MODULE_INIT_FUNC(smbconf
)
206 PyObject
*m
= PyModule_Create(&moduledef
);