param: Add non-global smb.cfg option (support 2 different smb.confs)
authorAaron Haslett <aaronhaslett@catalyst.net.nz>
Mon, 30 Apr 2018 23:10:36 +0000 (11:10 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 28 Jun 2018 01:34:27 +0000 (03:34 +0200)
The default behaviour is that there is only a single global underlying
LoadParm object. E.g. if you create 2 different LoadParm objects in
python, they both modify the same underlying object.

This patch adds a mechanism to override this and create a separate
non-global LoadParm object. The use-case is the backup tool, where we
want to manipulate 2 different smb.conf files (the one used to create
the backup, and the smb.conf in the backup itself).

Signed-off-by: Aaron Haslett <aaronhaslett@catalyst.net.nz>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
lib/param/loadparm.c
source4/param/pyparam.c

index 3b7f8053e4aeba3f74798a71047e1ed2b4cb77e9..9684a52952b070753b71087bdf24c5570493426b 100644 (file)
@@ -3148,7 +3148,8 @@ bool lpcfg_load_default(struct loadparm_context *lp_ctx)
  *
  * Return True on success, False on failure.
  */
-bool lpcfg_load(struct loadparm_context *lp_ctx, const char *filename)
+static bool lpcfg_load_internal(struct loadparm_context *lp_ctx,
+                               const char *filename, bool set_global)
 {
        char *n2;
        bool bRetval;
@@ -3183,7 +3184,7 @@ bool lpcfg_load(struct loadparm_context *lp_ctx, const char *filename)
           for a missing smb.conf */
        reload_charcnv(lp_ctx);
 
-       if (bRetval == true) {
+       if (bRetval == true && set_global) {
                /* set this up so that any child python tasks will
                   find the right smb.conf */
                setenv("SMB_CONF_PATH", filename, 1);
@@ -3197,6 +3198,16 @@ bool lpcfg_load(struct loadparm_context *lp_ctx, const char *filename)
        return bRetval;
 }
 
+bool lpcfg_load_no_global(struct loadparm_context *lp_ctx, const char *filename)
+{
+    return lpcfg_load_internal(lp_ctx, filename, false);
+}
+
+bool lpcfg_load(struct loadparm_context *lp_ctx, const char *filename)
+{
+    return lpcfg_load_internal(lp_ctx, filename, true);
+}
+
 /**
  * Return the max number of services.
  */
index e7e908fcac34fe0203dc41c3d0f1268556375dd3..11257c356aa2150404ea9f43f0b92ee73b06f95a 100644 (file)
@@ -445,7 +445,52 @@ static PyGetSetDef py_lp_ctx_getset[] = {
 
 static PyObject *py_lp_ctx_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
-       return pytalloc_reference(type, loadparm_init_global(false));
+       const char *kwnames[] = {"filename_for_non_global_lp", NULL};
+       PyObject *lp_ctx;
+       const char *non_global_conf = NULL;
+       struct loadparm_context *ctx;
+
+       if (!PyArg_ParseTupleAndKeywords(args,
+                                        kwargs,
+                                        "|s",
+                                        discard_const_p(char *,
+                                                        kwnames),
+                                        &non_global_conf)) {
+               return NULL;
+       }
+
+       /*
+        * by default, any LoadParm python objects map to a single global
+        * underlying object. The filename_for_non_global_lp arg overrides this
+        * default behaviour and creates a separate underlying LoadParm object.
+        */
+       if (non_global_conf != NULL) {
+               bool ok;
+               ctx = loadparm_init(NULL);
+               if (ctx == NULL) {
+                       PyErr_NoMemory();
+                       return NULL;
+               }
+
+               lp_ctx = pytalloc_reference(type, ctx);
+               if (lp_ctx == NULL) {
+                       PyErr_NoMemory();
+                       return NULL;
+               }
+
+               ok = lpcfg_load_no_global(
+                       PyLoadparmContext_AsLoadparmContext(lp_ctx),
+                       non_global_conf);
+               if (!ok) {
+                       PyErr_Format(PyExc_ValueError,
+                                    "Could not load non-global conf %s",
+                                    non_global_conf);
+                       return NULL;
+               }
+               return lp_ctx;
+       } else{
+               return pytalloc_reference(type, loadparm_init_global(false));
+       }
 }
 
 static Py_ssize_t py_lp_ctx_len(PyObject *self)