The branch, master has been updated via e26a01a48c4 pidl: avoid py compile issues with --pidl-developer via b2a2eeb6f99 tevent/pytevent: remove no-op define via 8f2f3b00c2f tevent/pytevent: remove py2 ifdefs via c0ef6ca98bb tdb/pytdb: remove useless HAVE_ITER non-flag via f5555e0ee4c tdb/pytdb: remove py ifdefs via 310eafdb7b3 s4/ndr/py_security: remove python 2 ifdefs via ddbe69afbd1 s4/ndr/py_misc: remove python 2 ifdefs via 38d0147f6a5 ldb/pyldb: remove py2 ifdefs via 5723737ebb1 gp: Test samba-tool gpo cse register/unregister/list via 3eee4415bca gp: samba-tool gpo cse register/unregister/list from 851127f5c9a Python: remove pydoctor
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit e26a01a48c4a6ca6f9424ced72eda68e6eb1e7e3 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Fri Dec 9 10:36:30 2022 +1300 pidl: avoid py compile issues with --pidl-developer We get these warnings-as-errors: librpc/gen_ndr/py_netlogon.c:61903:53: error: stray ‘\’ in program 61903 | PyErr_Format(PyExc_TypeError, "Expected type %s",\ //<PIDL> Parse::Pidl::Samba4::Python::ConvertObjectFromPythonData lib/Parse/Pidl/Samba4/Python.pm:2005 but the '\' is unnecessary and unconventional anyway, since we're in a function argument list. Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Autobuild-User(master): Andrew Bartlett <abart...@samba.org> Autobuild-Date(master): Fri Feb 3 03:27:54 UTC 2023 on atb-devel-224 commit b2a2eeb6f99a7e10412317964de1d50802f4ddf4 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Wed Feb 1 13:19:56 2023 +1300 tevent/pytevent: remove no-op define Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 8f2f3b00c2fb3aade9f136d758e76d4ce9601ae2 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Wed Feb 1 13:17:21 2023 +1300 tevent/pytevent: remove py2 ifdefs Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit c0ef6ca98bb9d494c5810313d8ab30b149e82953 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Wed Feb 1 13:08:27 2023 +1300 tdb/pytdb: remove useless HAVE_ITER non-flag Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit f5555e0ee4cdc1ee50788d5d727f50cb8abde476 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Wed Feb 1 13:06:24 2023 +1300 tdb/pytdb: remove py ifdefs This already would not compile with Python 2, because Py_TPFLAGS_HAVE_ITER is not defined Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 310eafdb7b3b594c3e2340520b4eadd1fa813497 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Wed Feb 1 12:55:18 2023 +1300 s4/ndr/py_security: remove python 2 ifdefs Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit ddbe69afbd1b93f69d8ed21b08ad03925de1db73 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Wed Feb 1 12:54:49 2023 +1300 s4/ndr/py_misc: remove python 2 ifdefs Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 38d0147f6a535b09a5b59f0aba8af23c9e0d2115 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Wed Feb 1 12:52:59 2023 +1300 ldb/pyldb: remove py2 ifdefs Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 5723737ebb12d1f6d13863b685bbbd362026dc69 Author: David Mulder <dmul...@samba.org> Date: Fri Jan 13 09:07:38 2023 -0700 gp: Test samba-tool gpo cse register/unregister/list Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 3eee4415bca6645e35da93d15d399ac85db9c126 Author: David Mulder <dmul...@samba.org> Date: Fri Jan 13 09:05:26 2023 -0700 gp: samba-tool gpo cse register/unregister/list Add samba-tool commands for managing registration of Client Side Extensions. Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> ----------------------------------------------------------------------- Summary of changes: lib/ldb/pyldb.c | 22 ------- lib/tdb/pytdb.c | 48 +-------------- lib/tevent/pytevent.c | 17 ------ pidl/lib/Parse/Pidl/Samba4/Python.pm | 8 +-- python/samba/netcmd/gpo.py | 110 +++++++++++++++++++++++++++++++++++ python/samba/tests/samba_tool/gpo.py | 35 +++++++++++ source4/librpc/ndr/py_misc.c | 24 -------- source4/librpc/ndr/py_security.c | 24 -------- 8 files changed, 150 insertions(+), 138 deletions(-) Changeset truncated at 500 lines: diff --git a/lib/ldb/pyldb.c b/lib/ldb/pyldb.c index 238a7550deb..7a95a58fa67 100644 --- a/lib/ldb/pyldb.c +++ b/lib/ldb/pyldb.c @@ -84,8 +84,6 @@ static struct ldb_message_element *PyObject_AsMessageElement( const char *attr_name); static PyTypeObject PyLdbBytesType; -#if PY_MAJOR_VERSION >= 3 - #define PYARG_STR_UNI "es" static PyObject *PyLdbBytes_FromStringAndSize(const char *msg, int size) @@ -97,12 +95,6 @@ static PyObject *PyLdbBytes_FromStringAndSize(const char *msg, int size) Py_DECREF(args); return result; } -#else -#define PyLdbBytes_FromStringAndSize PyString_FromStringAndSize - -#define PYARG_STR_UNI "et" - -#endif static PyObject *richcmp(int cmp_val, int op) { @@ -4348,7 +4340,6 @@ static PyMethodDef py_ldb_global_methods[] = { #define MODULE_DOC "An interface to LDB, a LDAP-like API that can either to talk an embedded database (TDB-based) or a standards-compliant LDAP server." -#if PY_MAJOR_VERSION >= 3 static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, .m_name = "ldb", @@ -4356,7 +4347,6 @@ static struct PyModuleDef moduledef = { .m_size = -1, .m_methods = py_ldb_global_methods, }; -#endif static PyObject* module_init(void) { @@ -4394,11 +4384,7 @@ static PyObject* module_init(void) if (PyType_Ready(&PyLdbControl) < 0) return NULL; -#if PY_MAJOR_VERSION >= 3 m = PyModule_Create(&moduledef); -#else - m = Py_InitModule3("ldb", py_ldb_global_methods, MODULE_DOC); -#endif if (m == NULL) return NULL; @@ -4520,16 +4506,8 @@ static PyObject* module_init(void) return m; } -#if PY_MAJOR_VERSION >= 3 PyMODINIT_FUNC PyInit_ldb(void); PyMODINIT_FUNC PyInit_ldb(void) { return module_init(); } -#else -void initldb(void); -void initldb(void) -{ - module_init(); -} -#endif diff --git a/lib/tdb/pytdb.c b/lib/tdb/pytdb.c index e2f8ace227f..85df1b18621 100644 --- a/lib/tdb/pytdb.c +++ b/lib/tdb/pytdb.c @@ -31,10 +31,6 @@ /* Include tdb headers */ #include <tdb.h> -#if PY_MAJOR_VERSION >= 3 -#define Py_TPFLAGS_HAVE_ITER 0 -#endif - /* discard signature of 'func' in favour of 'target_sig' */ #define PY_DISCARD_FUNC_SIG(target_sig, func) (target_sig)(void(*)(void))func @@ -337,26 +333,6 @@ static int obj_contains(PyTdbObject *self, PyObject *py_key) return 0; } -#if PY_MAJOR_VERSION < 3 -static PyObject *obj_has_key(PyTdbObject *self, PyObject *args) -{ - int ret; - PyObject *py_key; - PyErr_TDB_RAISE_IF_CLOSED(self); - - if (!PyArg_ParseTuple(args, "O", &py_key)) - return NULL; - - ret = obj_contains(self, py_key); - if (ret == -1) - return NULL; - if (ret) - Py_RETURN_TRUE; - Py_RETURN_FALSE; - -} -#endif - static PyObject *obj_store(PyTdbObject *self, PyObject *args) { TDB_DATA key, value; @@ -566,21 +542,13 @@ static PyMethodDef tdb_object_methods[] = { "Return the next key in this database." }, { "delete", (PyCFunction)obj_delete, METH_VARARGS, "S.delete(key) -> None\n" "Delete an entry." }, -#if PY_MAJOR_VERSION < 3 - { "has_key", (PyCFunction)obj_has_key, METH_VARARGS, "S.has_key(key) -> None\n" - "Check whether key exists in this database." }, -#endif { "store", (PyCFunction)obj_store, METH_VARARGS, "S.store(key, data, flag=REPLACE) -> None" "Store data." }, { "storev", (PyCFunction)obj_storev, METH_VARARGS, "S.storev(key, data, flag=REPLACE) -> None" "Store several data." }, { "add_flags", (PyCFunction)obj_add_flags, METH_VARARGS, "S.add_flags(flags) -> None" }, { "remove_flags", (PyCFunction)obj_remove_flags, METH_VARARGS, "S.remove_flags(flags) -> None" }, -#if PY_MAJOR_VERSION >= 3 { "keys", (PyCFunction)tdb_object_iter, METH_NOARGS, "S.keys() -> iterator" }, -#else - { "iterkeys", (PyCFunction)tdb_object_iter, METH_NOARGS, "S.iterkeys() -> iterator" }, -#endif { "clear", (PyCFunction)obj_clear, METH_NOARGS, "S.clear() -> None\n" "Wipe the entire database." }, { "repack", (PyCFunction)obj_repack, METH_NOARGS, "S.repack() -> None\n" @@ -784,7 +752,7 @@ static PyTypeObject PyTdb = { .tp_dealloc = (destructor)tdb_object_dealloc, .tp_as_mapping = &tdb_object_mapping, .tp_as_sequence = &tdb_object_seq, - .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_ITER, + .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, .tp_iter = PY_DISCARD_FUNC_SIG(getiterfunc,tdb_object_iter), }; @@ -801,7 +769,6 @@ static PyMethodDef tdb_methods[] = { #define MODULE_DOC "simple key-value database that supports multiple writers." -#if PY_MAJOR_VERSION >= 3 static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, .m_name = "tdb", @@ -809,7 +776,6 @@ static struct PyModuleDef moduledef = { .m_size = -1, .m_methods = tdb_methods, }; -#endif PyObject* module_init(void); PyObject* module_init(void) @@ -822,11 +788,7 @@ PyObject* module_init(void) if (PyType_Ready(&PyTdbIterator) < 0) return NULL; -#if PY_MAJOR_VERSION >= 3 m = PyModule_Create(&moduledef); -#else - m = Py_InitModule3("tdb", tdb_methods, MODULE_DOC); -#endif if (m == NULL) return NULL; @@ -861,16 +823,8 @@ PyObject* module_init(void) } -#if PY_MAJOR_VERSION >= 3 PyMODINIT_FUNC PyInit_tdb(void); PyMODINIT_FUNC PyInit_tdb(void) { return module_init(); } -#else -void inittdb(void); -void inittdb(void) -{ - module_init(); -} -#endif diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c index 6e8c8b72e1c..1af6f16c0fb 100644 --- a/lib/tevent/pytevent.c +++ b/lib/tevent/pytevent.c @@ -26,9 +26,6 @@ #include "replace.h" #include <tevent.h> -#if PY_MAJOR_VERSION >= 3 -#define PyLong_FromLong PyLong_FromLong -#endif /* discard signature of 'func' in favour of 'target_sig' */ #define PY_DISCARD_FUNC_SIG(target_sig, func) (target_sig)(void(*)(void))func @@ -736,7 +733,6 @@ static PyMethodDef tevent_methods[] = { #define MODULE_DOC PyDoc_STR("Python wrapping of talloc-maintained objects.") -#if PY_MAJOR_VERSION >= 3 static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, .m_name = "_tevent", @@ -744,7 +740,6 @@ static struct PyModuleDef moduledef = { .m_size = -1, .m_methods = tevent_methods, }; -#endif PyObject * module_init(void); PyObject * module_init(void) @@ -769,11 +764,7 @@ PyObject * module_init(void) if (PyType_Ready(&TeventFd_Type) < 0) return NULL; -#if PY_MAJOR_VERSION >= 3 m = PyModule_Create(&moduledef); -#else - m = Py_InitModule3("_tevent", tevent_methods, MODULE_DOC); -#endif if (m == NULL) return NULL; @@ -800,16 +791,8 @@ PyObject * module_init(void) return m; } -#if PY_MAJOR_VERSION >= 3 PyMODINIT_FUNC PyInit__tevent(void); PyMODINIT_FUNC PyInit__tevent(void) { return module_init(); } -#else -void init_tevent(void); -void init_tevent(void) -{ - module_init(); -} -#endif diff --git a/pidl/lib/Parse/Pidl/Samba4/Python.pm b/pidl/lib/Parse/Pidl/Samba4/Python.pm index 5c4d3e8e087..03a901cc24d 100644 --- a/pidl/lib/Parse/Pidl/Samba4/Python.pm +++ b/pidl/lib/Parse/Pidl/Samba4/Python.pm @@ -1747,7 +1747,7 @@ sub ConvertObjectFromPythonData($$$$$$;$$) $self->pidl("}"); $self->pidl("if (test_var > uint_max) {"); $self->indent; - $self->pidl("PyErr_Format(PyExc_OverflowError, \"Expected type %s within range 0 - %llu, got %llu\",\\"); + $self->pidl("PyErr_Format(PyExc_OverflowError, \"Expected type %s within range 0 - %llu, got %llu\","); $self->pidl(" PyLong_Type.tp_name, uint_max, test_var);"); $self->pidl($fail); $self->deindent; @@ -1756,7 +1756,7 @@ sub ConvertObjectFromPythonData($$$$$$;$$) $self->deindent; $self->pidl("} else {"); $self->indent; - $self->pidl("PyErr_Format(PyExc_TypeError, \"Expected type %s\",\\"); + $self->pidl("PyErr_Format(PyExc_TypeError, \"Expected type %s\","); $self->pidl(" PyLong_Type.tp_name);"); $self->pidl($fail); $self->deindent; @@ -1786,7 +1786,7 @@ sub ConvertObjectFromPythonData($$$$$$;$$) $self->pidl("}"); $self->pidl("if (test_var < int_min || test_var > int_max) {"); $self->indent; - $self->pidl("PyErr_Format(PyExc_OverflowError, \"Expected type %s within range %lld - %lld, got %lld\",\\"); + $self->pidl("PyErr_Format(PyExc_OverflowError, \"Expected type %s within range %lld - %lld, got %lld\","); $self->pidl(" PyLong_Type.tp_name, int_min, int_max, test_var);"); $self->pidl($fail); $self->deindent; @@ -1795,7 +1795,7 @@ sub ConvertObjectFromPythonData($$$$$$;$$) $self->deindent; $self->pidl("} else {"); $self->indent; - $self->pidl("PyErr_Format(PyExc_TypeError, \"Expected type %s\",\\"); + $self->pidl("PyErr_Format(PyExc_TypeError, \"Expected type %s\","); $self->pidl(" PyLong_Type.tp_name);"); $self->pidl($fail); $self->deindent; diff --git a/python/samba/netcmd/gpo.py b/python/samba/netcmd/gpo.py index bfd3e0f05f7..340f8f55e5e 100644 --- a/python/samba/netcmd/gpo.py +++ b/python/samba/netcmd/gpo.py @@ -84,6 +84,8 @@ from samba.netcmd.gpcommon import ( ) from samba.policies import RegistryGroupPolicies from samba.dcerpc.misc import REG_MULTI_SZ +from samba.gp.gpclass import register_gp_extension, list_gp_extensions, \ + unregister_gp_extension def gpo_flags_string(value): @@ -4273,6 +4275,113 @@ samba-tool gpo manage access remove {31B2F340-016D-11D2-945F-00C04FB984F9} allow "not have sufficient privileges") raise +class cmd_cse_register(Command): + """Register a Client Side Extension (CSE) on the current host + +This command takes a CSE filename as an arguement, and registers it for +applying policy on the current host. This is not necessary for CSEs which +are distributed with the current version of Samba, but is useful for installing +experimental CSEs or custom built CSEs. + +Example: +samba-tool gpo cse register ./gp_chromium_ext.py gp_chromium_ext --machine + """ + + synopsis = "%prog <cse_file> <cse_name> [options]" + + takes_optiongroups = { + "sambaopts": options.SambaOptions, + "versionopts": options.VersionOptions, + } + + takes_options = [ + Option("--machine", default=False, action='store_true', + help="Whether to register the CSE as Machine policy"), + Option("--user", default=False, action='store_true', + help="Whether to register the CSE as User policy"), + ] + + takes_args = ["cse_file", "cse_name"] + + def run(self, cse_file, cse_name, machine=False, user=False, + sambaopts=None, versionopts=None): + self.lp = sambaopts.get_loadparm() + + if machine == False and user == False: + raise CommandError("Either --machine or --user must be selected") + + ext_guid = "{%s}" % str(uuid.uuid4()) + ext_path = os.path.realpath(cse_file) + ret = register_gp_extension(ext_guid, cse_name, ext_path, + smb_conf=self.lp.configfile, + machine=machine, user=user) + if not ret: + raise CommandError('Failed to register CSE "%s"' % cse_name) + +class cmd_cse_list(Command): + """List the registered Client Side Extensions (CSEs) on the current host + +This command lists the currently registered CSEs on the host. + +Example: +samba-tool gpo cse list + """ + + synopsis = "%prog [options]" + + takes_optiongroups = { + "sambaopts": options.SambaOptions, + "versionopts": options.VersionOptions, + } + + def run(self, sambaopts=None, versionopts=None): + self.lp = sambaopts.get_loadparm() + + cses = list_gp_extensions(self.lp.configfile) + for guid, gp_ext in cses.items(): + self.outf.write("UniqueGUID : %s\n" % guid) + self.outf.write("FileName : %s\n" % gp_ext['DllName']) + self.outf.write("ProcessGroupPolicy : %s\n" % \ + gp_ext['ProcessGroupPolicy']) + self.outf.write("MachinePolicy : %s\n" % \ + str(gp_ext['MachinePolicy'])) + self.outf.write("UserPolicy : %s\n\n" % \ + str(gp_ext['UserPolicy'])) + +class cmd_cse_unregister(Command): + """Unregister a Client Side Extension (CSE) from the current host + +This command takes a unique GUID as an arguement (representing a registered +CSE), and unregisters it for applying policy on the current host. Use the +`samba-tool gpo cse list` command to determine the unique GUIDs of CSEs. + +Example: +samba-tool gpo cse unregister {3F60F344-92BF-11ED-A1EB-0242AC120002} + """ + + synopsis = "%prog <guid> [options]" + + takes_optiongroups = { + "sambaopts": options.SambaOptions, + "versionopts": options.VersionOptions, + } + + takes_args = ["guid"] + + def run(self, guid, sambaopts=None, versionopts=None): + self.lp = sambaopts.get_loadparm() + + ret = unregister_gp_extension(guid, self.lp.configfile) + if not ret: + raise CommandError('Failed to unregister CSE "%s"' % guid) + +class cmd_cse(SuperCommand): + """Manage Client Side Extensions""" + subcommands = {} + subcommands["register"] = cmd_cse_register() + subcommands["list"] = cmd_cse_list() + subcommands["unregister"] = cmd_cse_unregister() + class cmd_access(SuperCommand): """Manage Host Access Group Policy Objects""" subcommands = {} @@ -4317,3 +4426,4 @@ class cmd_gpo(SuperCommand): subcommands["restore"] = cmd_restore() subcommands["admxload"] = cmd_admxload() subcommands["manage"] = cmd_manage() + subcommands["cse"] = cmd_cse() diff --git a/python/samba/tests/samba_tool/gpo.py b/python/samba/tests/samba_tool/gpo.py index ae19a573711..d192c1b8115 100644 --- a/python/samba/tests/samba_tool/gpo.py +++ b/python/samba/tests/samba_tool/gpo.py @@ -34,6 +34,8 @@ from io import StringIO import xml.etree.ElementTree as etree from tempfile import NamedTemporaryFile from time import sleep +import re +from samba.gp.gpclass import check_guid gpo_load_json = \ b""" @@ -1658,6 +1660,39 @@ class GpoCmdTestCase(SambaToolCmdTest): self.assertNotIn(ext_guids[0], out, 'Machine extension not unloaded') self.assertNotIn(ext_guids[1], out, 'User extension not unloaded') + def test_cse_register_unregister_list(self): + with NamedTemporaryFile() as f: + (result, out, err) = self.runsublevelcmd("gpo", ("cse", + "register"), + f.name, 'gp_test_ext', + '--machine') + self.assertCmdSuccess(result, out, err, 'CSE register failed') + + (result, out, err) = self.runsublevelcmd("gpo", ("cse", + "list")) + self.assertIn(f.name, out, 'The test cse was not found') + self.assertIn('ProcessGroupPolicy : gp_test_ext', out, + 'The test cse was not found') + self.assertIn('MachinePolicy : True', out, + 'The test cse was not enabled') + self.assertIn('UserPolicy : False', out, + 'The test cse should not have User policy enabled') + cse_ext = re.findall('^UniqueGUID\s+:\s+(.*)', out) + self.assertEquals(len(cse_ext), 1, + 'The test cse GUID was not found') + cse_ext = cse_ext[0] + self.assertTrue(check_guid(cse_ext), + 'The test cse GUID was not formatted correctly') + + (result, out, err) = self.runsublevelcmd("gpo", ("cse", + "unregister"), + cse_ext) + self.assertCmdSuccess(result, out, err, 'CSE unregister failed') + + (result, out, err) = self.runsublevelcmd("gpo", ("cse", + "list")) + self.assertNotIn(f.name, out, 'The test cse was still found') + def setUp(self): """set up a temporary GPO to work with""" super(GpoCmdTestCase, self).setUp() diff --git a/source4/librpc/ndr/py_misc.c b/source4/librpc/ndr/py_misc.c index ea2092a5182..99100875689 100644 --- a/source4/librpc/ndr/py_misc.c +++ b/source4/librpc/ndr/py_misc.c @@ -21,7 +21,6 @@ #include "python/py3compat.h" #include "librpc/gen_ndr/misc.h" -#if PY_MAJOR_VERSION >= 3 static PyObject *py_GUID_richcmp(PyObject *py_self, PyObject *py_other, int op) { int ret; @@ -45,25 +44,6 @@ static PyObject *py_GUID_richcmp(PyObject *py_self, PyObject *py_other, int op) Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } -#else -static int py_GUID_cmp(PyObject *py_self, PyObject *py_other) -{ - int ret; - struct GUID *self = pytalloc_get_ptr(py_self), *other; - other = pytalloc_get_ptr(py_other); - if (other == NULL) - return -1; - - ret = GUID_compare(self, other); - if (ret < 0) { -- Samba Shared Repository