[SCM] Samba Shared Repository - branch master updated

Ralph Böhme slow at samba.org
Sat Mar 29 08:26:02 UTC 2025


The branch, master has been updated
       via  a65a9e2e34c samba-tool backup restore: cope with no sysvol
       via  6cafe36740c samba-tool testparm: avoid lowering debug level
       via  000dcc26542 samba-tool testparm: drop unsupported options
       via  c14e9e9121a samba-tool gpo: use a real XML parser to check entity validity
       via  ea0c84b18ed samba-tool gpo: separate function for dtd header generation
       via  2f2dac30943 pytest: source_tree_topdir() checks more thoroughly
       via  24fb3bb8744 python: make source_tree_topdir() test-only
       via  38d113a4d31 python: remove unused in_source_tree() function
       via  93a6d36239d vfs: Fix Bug 15791, vfs_acl_tdb unlinkat()
       via  93bc238aa91 vfs: Fix a lock order violation in unlinkat_acl_tdb()
      from  4272586b30e vfs_vxfs: pathref fixes

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit a65a9e2e34cf02cd10ec9028782f7a43dc6cfebb
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Mar 26 15:55:33 2025 +1300

    samba-tool backup restore: cope with no sysvol
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15661
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    
    Autobuild-User(master): Ralph Böhme <slow at samba.org>
    Autobuild-Date(master): Sat Mar 29 08:25:39 UTC 2025 on atb-devel-224

commit 6cafe36740cfcc4d63a56dabf703f259968108e3
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Mar 19 13:53:37 2025 +1300

    samba-tool testparm: avoid lowering debug level
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 000dcc26542c4efe49ee516379ee8a6e497b70ac
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Mar 19 13:52:34 2025 +1300

    samba-tool testparm: drop unsupported options
    
    These have been useless since 2011.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit c14e9e9121a5d123234c989a6998e6b225c83294
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Mar 19 13:16:12 2025 +1300

    samba-tool gpo: use a real XML parser to check entity validity
    
    The expat parser comes with the Python standard library, so we can use
    it to check the entities work, rather than relying on a fragile
    regular expression.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit ea0c84b18ed5290c940de78a50dbd5664ab07ee7
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Mar 19 12:50:31 2025 +1300

    samba-tool gpo: separate function for dtd header generation
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 2f2dac309430346438b047302f8778b5410be3e5
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Mar 20 16:43:41 2025 +1300

    pytest: source_tree_topdir() checks more thoroughly
    
    We are more certain of how many ../ steps we are from top than we are
    that the existence of a thing called 'source4' is a definite sign
    that this is a full source tree. So we check fewer depths and more
    subdirectories.
    
    This also modernises the return type to be a pathlib.Path, which works
    without change for current callers.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 24fb3bb87449dd2d4e8df2b48637c59adf63022a
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Mar 19 12:04:26 2025 +1300

    python: make source_tree_topdir() test-only
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 38d113a4d319e4424bdc5315aef27a6120add39b
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Mar 19 12:00:02 2025 +1300

    python: remove unused in_source_tree() function
    
    We don't use it and don't want non-tests changing their behaviour
    based on this kind of thing anyway.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 93a6d36239dd2ce2b3863945f8b9b59cb6aa911a
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Jan 28 14:03:49 2025 +0100

    vfs: Fix Bug 15791, vfs_acl_tdb unlinkat()
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=15791
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 93bc238aa91ec8041648d17e11bf235132974eda
Author: Volker Lendecke <vl at samba.org>
Date:   Wed Feb 26 16:04:01 2025 +0100

    vfs: Fix a lock order violation in unlinkat_acl_tdb()
    
    unlinkat is called when the share mode record is locked.
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=15791
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 python/samba/__init__.py             | 19 -------------
 python/samba/netcmd/domain/backup.py |  7 +++--
 python/samba/netcmd/gpo.py           | 55 +++++++++++++++++++++---------------
 python/samba/netcmd/testparm.py      | 15 ++--------
 python/samba/tests/__init__.py       | 16 ++++++++++-
 python/samba/tests/dns_forwarder.py  |  4 +--
 python/samba/tests/docs.py           |  2 +-
 python/samba/tests/samba_tool/gpo.py |  3 +-
 source3/modules/vfs_acl_tdb.c        | 51 ++++++++++++++++++---------------
 9 files changed, 89 insertions(+), 83 deletions(-)


Changeset truncated at 500 lines:

diff --git a/python/samba/__init__.py b/python/samba/__init__.py
index 538237a6331..dd3a44ad350 100644
--- a/python/samba/__init__.py
+++ b/python/samba/__init__.py
@@ -31,25 +31,6 @@ from samba import _glue
 from samba._ldb import Ldb as _Ldb
 
 
-def source_tree_topdir():
-    """Return the top level source directory."""
-    paths = ["../../..", "../../../.."]
-    for p in paths:
-        topdir = os.path.normpath(os.path.join(os.path.dirname(__file__), p))
-        if os.path.exists(os.path.join(topdir, 'source4')):
-            return topdir
-    raise RuntimeError("unable to find top level source directory")
-
-
-def in_source_tree():
-    """Return True if we are running from within the samba source tree"""
-    try:
-        topdir = source_tree_topdir()
-    except RuntimeError:
-        return False
-    return True
-
-
 class Ldb(_Ldb):
     """Simple Samba-specific LDB subclass that takes care
     of setting up the modules dir, credentials pointers, etc.
diff --git a/python/samba/netcmd/domain/backup.py b/python/samba/netcmd/domain/backup.py
index 1769909fb93..5ad9987eec6 100644
--- a/python/samba/netcmd/domain/backup.py
+++ b/python/samba/netcmd/domain/backup.py
@@ -691,8 +691,11 @@ class cmd_domain_backup_restore(cmd_fsmo_seize):
         dest_sysvol_dir = lp.get('path', 'sysvol')
         if not os.path.exists(dest_sysvol_dir):
             os.makedirs(dest_sysvol_dir)
-        backup_restore(sysvol_tar, dest_sysvol_dir, samdb, smbconf)
-        os.remove(sysvol_tar)
+        if os.path.isfile(sysvol_tar):
+            backup_restore(sysvol_tar, dest_sysvol_dir, samdb, smbconf)
+            os.remove(sysvol_tar)
+        else:
+            logger.notice("back-up has no sysvol data")
 
         # fix up any stale links to the old DCs we just removed
         logger.info("Fixing up any remaining references to the old DCs...")
diff --git a/python/samba/netcmd/gpo.py b/python/samba/netcmd/gpo.py
index ada5f142a6f..a8e28274c75 100644
--- a/python/samba/netcmd/gpo.py
+++ b/python/samba/netcmd/gpo.py
@@ -24,6 +24,7 @@ import samba.getopt as options
 import ldb
 import re
 import xml.etree.ElementTree as ET
+from xml.parsers import expat
 import shutil
 import tempfile
 
@@ -1633,35 +1634,45 @@ class cmd_restore(cmd_create):
                             self.outf.write('WARNING: Error during parsing for %s\n' % l_name)
                             self.outf.write('WARNING: Falling back to simple copy-restore.\n')
 
-    def run(self, displayname, backup, H=None, tmpdir=None, entities=None, sambaopts=None, credopts=None,
-            versionopts=None, restore_metadata=None):
+    @staticmethod
+    def generate_dtd_header(entities):
+        # The entities file is a list of XML entities in the form
+        #  <!ENTITY entity "value">
+        #  <!ENTITY entity2 "another value">
+        #
+        # which go within a <!DOCTYPE x [...]> block.
+        #
+        # We check that they are valid in this context using the
+        # Python standard library expat parser.
+        if entities is None:
+            return ""
 
-        dtd_header = ''
+        try:
+            with open(entities) as f:
+                contents = f.read().strip()
+        except:
+            raise CommandError(f"Could not open entities file: '{entities}'")
 
-        if not os.path.exists(backup):
-            raise CommandError("Backup directory does not exist %s" % backup)
+        dtd_header = f'<!DOCTYPE foobar [\n{contents}\n]>\n'
 
-        if entities is not None:
-            # DOCTYPE name is meant to match root element, but ElementTree does
-            # not seem to care, so this seems to be enough.
+        p = expat.ParserCreate()
+        try:
+            p.Parse(dtd_header + '<dummy/>', True)
+        except expat.ExpatError as e:
+            raise CommandError("Entities file does not appear to "
+                               "conform to format\n"
+                               'e.g. <!ENTITY entity "value">\n'
+                               f'Expat error message: {e}')
 
-            dtd_header = '<!DOCTYPE foobar [\n'
+        return dtd_header
 
-            if not os.path.exists(entities):
-                raise CommandError("Entities file does not exist %s" %
-                                   entities)
-            with open(entities, 'r') as entities_file:
-                entities_content = entities_file.read()
+    def run(self, displayname, backup, H=None, tmpdir=None, entities=None, sambaopts=None, credopts=None,
+            versionopts=None, restore_metadata=None):
 
-                # Do a basic regex test of the entities file format
-                if re.match(r'(\s*<!ENTITY\s+[a-zA-Z0-9_]+\s+.*?>)+\s*\Z',
-                            entities_content, flags=re.MULTILINE|re.DOTALL) is None:
-                    raise CommandError("Entities file does not appear to "
-                                       "conform to format\n"
-                                       'e.g. <!ENTITY entity "value">')
-                dtd_header += entities_content.strip()
+        if not os.path.exists(backup):
+            raise CommandError("Backup directory does not exist %s" % backup)
 
-            dtd_header += '\n]>\n'
+        dtd_header = self.generate_dtd_header(entities)
 
         super().run(displayname, H, tmpdir, sambaopts, credopts, versionopts)
 
diff --git a/python/samba/netcmd/testparm.py b/python/samba/netcmd/testparm.py
index cd854feee9c..a2c51432288 100644
--- a/python/samba/netcmd/testparm.py
+++ b/python/samba/netcmd/testparm.py
@@ -62,23 +62,13 @@ class cmd_testparm(Command):
                help="Suppress prompt for enter"),
         Option("-v", "--verbose", action="store_true",
                default=False, help="Show default options too"),
-        # We need support for smb.conf macros before this will work again
-        Option("--server", type=str, help="Set %L macro to servername"),
-        # These are harder to do with the new code structure
-        Option("--show-all-parameters", action="store_true", default=False,
-               help="Show the parameters, type, possible values")
     ]
 
     takes_args = []
 
     def run(self, sambaopts, versionopts, section_name=None,
             parameter_name=None, client_ip=None, client_name=None,
-            verbose=False, suppress_prompt=None, show_all_parameters=False,
-            server=None):
-        if server:
-            raise NotImplementedError("--server not yet implemented")
-        if show_all_parameters:
-            raise NotImplementedError("--show-all-parameters not yet implemented")
+            verbose=False, suppress_prompt=None):
         if client_name is not None and client_ip is None:
             raise CommandError("Both a DNS name and an IP address are "
                                "required for the host access check")
@@ -89,7 +79,8 @@ class cmd_testparm(Command):
             raise CommandError(err)
 
         # We need this to force the output
-        samba.set_debug_level(2)
+        if samba.get_debug_level() < 2:
+            samba.set_debug_level(2)
 
         logger = self.get_logger("testparm")
 
diff --git a/python/samba/tests/__init__.py b/python/samba/tests/__init__.py
index 6af0940e8e4..a5b6cb658eb 100644
--- a/python/samba/tests/__init__.py
+++ b/python/samba/tests/__init__.py
@@ -52,7 +52,7 @@ import samba.dcerpc.dcerpc
 import samba.dcerpc.epmapper
 
 from unittest import SkipTest
-
+from pathlib import Path
 
 BINDIR = os.path.abspath(os.path.join(os.path.dirname(__file__),
                                       "../../../../bin"))
@@ -65,6 +65,20 @@ LDB_ERR_LUT = {v: k for k, v in vars(ldb).items() if k.startswith('ERR_')}
 RE_CAMELCASE = re.compile(r"([_\-])+")
 
 
+def source_tree_topdir():
+    """Return the top level source directory if this seems to be a
+    full source tree. Otherwise raise FileNotFoundError."""
+    topdir = Path(__file__) / "../../../.."
+    topdir = topdir.resolve()
+
+    for dirpath in ('source4', 'docs-xml', 'python/samba/tests'):
+        d = topdir / dirpath
+        if not d.is_dir():
+            raise FileNotFoundError(f"missing or not a directory: {d}")
+
+    return topdir
+
+
 def ldb_err(v):
     if isinstance(v, ldb.LdbError):
         v = v.args[0]
diff --git a/python/samba/tests/dns_forwarder.py b/python/samba/tests/dns_forwarder.py
index 86b553e53e4..3af8085a649 100644
--- a/python/samba/tests/dns_forwarder.py
+++ b/python/samba/tests/dns_forwarder.py
@@ -24,7 +24,7 @@ import time
 import errno
 import samba.ndr as ndr
 from samba import credentials
-from samba.tests import TestCase
+from samba.tests import TestCase, source_tree_topdir
 from samba.dcerpc import dns
 from samba.tests.subunitrun import SubunitOptions, TestProgram
 import samba.getopt as options
@@ -170,7 +170,7 @@ class TestDnsForwarding(DNSTest):
     def start_toy_server(self, host, port, id):
         python = sys.executable
         p = subprocess.Popen([python,
-                              os.path.join(samba.source_tree_topdir(),
+                              os.path.join(source_tree_topdir(),
                                            'python/samba/tests/'
                                            'dns_forwarder_helpers/server.py'),
                              host, str(port), id])
diff --git a/python/samba/tests/docs.py b/python/samba/tests/docs.py
index 66189277260..e52a97ed629 100644
--- a/python/samba/tests/docs.py
+++ b/python/samba/tests/docs.py
@@ -240,7 +240,7 @@ class SmbDotConfTests(TestCase):
         finally:
             f.close()
 
-        self.topdir = os.path.abspath(samba.source_tree_topdir())
+        self.topdir = os.path.abspath(samba.tests.source_tree_topdir())
 
         try:
             self.documented = set(get_documented_parameters(self.topdir))
diff --git a/python/samba/tests/samba_tool/gpo.py b/python/samba/tests/samba_tool/gpo.py
index 3f1111f8002..3e3334be6ca 100644
--- a/python/samba/tests/samba_tool/gpo.py
+++ b/python/samba/tests/samba_tool/gpo.py
@@ -21,6 +21,7 @@
 import os, pwd, grp
 import ldb
 import samba
+from samba.tests import source_tree_topdir
 from samba.tests.samba_tool.base import SambaToolCmdTest
 import shutil
 from samba.netcmd.gpo import get_gpo_dn, get_gpo_info
@@ -1879,7 +1880,7 @@ class GpoCmdTestCase(SambaToolCmdTest):
         except IndexError:
             self.fail("Failed to find GUID in output: %s" % out)
 
-        self.backup_path = os.path.join(samba.source_tree_topdir(), 'source4',
+        self.backup_path = os.path.join(source_tree_topdir(), 'source4',
                                         'selftest', 'provisions',
                                         'generalized-gpo-backup')
 
diff --git a/source3/modules/vfs_acl_tdb.c b/source3/modules/vfs_acl_tdb.c
index f2d2692159f..b054f159f87 100644
--- a/source3/modules/vfs_acl_tdb.c
+++ b/source3/modules/vfs_acl_tdb.c
@@ -58,7 +58,7 @@ static bool acl_tdb_init(void)
 
 	become_root();
 	acl_db = db_open(NULL, dbname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600,
-			 DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
+			 DBWRAP_LOCK_ORDER_2, DBWRAP_FLAG_NONE);
 	unbecome_root();
 
 	if (acl_db == NULL) {
@@ -195,38 +195,43 @@ static int unlinkat_acl_tdb(vfs_handle_struct *handle,
 			const struct smb_filename *smb_fname,
 			int flags)
 {
-	struct smb_filename *smb_fname_tmp = NULL;
-	struct db_context *db = acl_db;
-	int ret = -1;
-
-	smb_fname_tmp = cp_smb_filename_nostream(talloc_tos(), smb_fname);
-	if (smb_fname_tmp == NULL) {
-		errno = ENOMEM;
-		goto out;
-	}
+	struct stat_ex st = {};
+	int ret;
 
-	ret = vfs_stat(handle->conn, smb_fname_tmp);
-	if (ret == -1) {
-		goto out;
+	if (!is_named_stream(smb_fname)) {
+		if (VALID_STAT(smb_fname->st)) {
+			st = smb_fname->st;
+		} else {
+			ret = SMB_VFS_NEXT_FSTATAT(handle,
+						   dirfsp,
+						   smb_fname,
+						   &st,
+						   AT_SYMLINK_NOFOLLOW);
+			if (ret == -1) {
+				return ret;
+			}
+		}
 	}
 
 	if (flags & AT_REMOVEDIR) {
-		ret = rmdir_acl_common(handle,
-				dirfsp,
-				smb_fname_tmp);
+		ret = rmdir_acl_common(handle, dirfsp, smb_fname);
 	} else {
-		ret = unlink_acl_common(handle,
-				dirfsp,
-				smb_fname_tmp,
-				flags);
+		ret = unlink_acl_common(handle, dirfsp, smb_fname, flags);
 	}
 
 	if (ret == -1) {
-		goto out;
+		return -1;
 	}
 
-	acl_tdb_delete(handle, db, &smb_fname_tmp->st);
- out:
+	if (is_named_stream(smb_fname)) {
+		/*
+		 * ACLs only stored for basenames
+		 */
+		return ret;
+	}
+
+	acl_tdb_delete(handle, acl_db, &st);
+
 	return ret;
 }
 


-- 
Samba Shared Repository



More information about the samba-cvs mailing list