[SCM] Samba Shared Repository - branch master updated

Andrew Tridgell tridge at samba.org
Wed Apr 18 01:20:02 MDT 2012


The branch, master has been updated
       via  c69c07e dbcheck: added fix for incorrect RMD_FLAGS
       via  997a22e dsdb: added SHOW_DELETED to samldb_member_check()
       via  2eb899d replace: added ENOATTR define if undefined
       via  8c9c6f8 s4:dbchecker.py - integrate the "objectClass" fixing code
       via  a2a9c33 s4:dsdb/pydsdb.c - call the "objectClass" normalisation code from Python
       via  27bcf7a LDB:ldb_tdb/ldb_tdb.c - allow LDB modify replaces with different value ordering
       via  9deb650 ldb: added ldb_msg_element_equal_ordered()
      from  010f2b8 Add docs for aio_linux vfs module.

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


- Log -----------------------------------------------------------------
commit c69c07efeccffec9848e6040b7934ee866b91e7e
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Apr 18 15:46:14 2012 +1000

    dbcheck: added fix for incorrect RMD_FLAGS
    
    this fixes the case where a DN link has RMD_FLAGS=0 for a link inside
    a deleted object
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User: Andrew Tridgell <tridge at samba.org>
    Autobuild-Date: Wed Apr 18 09:19:41 CEST 2012 on sn-devel-104

commit 997a22e7bf0711ce209885c408c6dd26391d7e16
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Apr 18 15:45:31 2012 +1000

    dsdb: added SHOW_DELETED to samldb_member_check()
    
    when dbcheck is fixing DNs, it will sometimes operated on a deleted DN
    link
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit 2eb899de6a2bdf1aac1c1f010a6d2b5b02f9de39
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Apr 18 14:35:17 2012 +1000

    replace: added ENOATTR define if undefined
    
    this fixes the build of the tdb xattr wrapper code on systems without
    xattr headers
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit 8c9c6f869d7f6e991806be344f582191d701b77c
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Wed Apr 11 17:18:37 2012 +0200

    s4:dbchecker.py - integrate the "objectClass" fixing code
    
    Signed-off-by: Andrew Tridgell <tridge at samba.org>

commit a2a9c334c10b259d070a984a61656ae76a95a643
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Wed Apr 11 16:06:03 2012 +0200

    s4:dsdb/pydsdb.c - call the "objectClass" normalisation code from Python
    
    This allows the dbchecker to fix ordering/inconsistency problems with
    the mentioned attribute.
    
    Signed-off-by: Andrew Tridgell <tridge at samba.org>

commit 27bcf7a0b6ab3a4c74129e3952c1bf14b8017b86
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Wed Apr 11 21:09:38 2012 +0200

    LDB:ldb_tdb/ldb_tdb.c - allow LDB modify replaces with different value ordering
    
    This is essential for fixing up wrong ordered "objectClass" attributes.
    
    Signed-off-by: Andrew Tridgell <tridge at samba.org>

commit 9deb650fa2b93338ca91ccc96a940d670d29cbee
Author: Andrew Tridgell <tridge at samba.org>
Date:   Tue Apr 17 14:01:08 2012 +1000

    ldb: added ldb_msg_element_equal_ordered()
    
    this gives us a order sensitive msg element comparison. We need this
    to allow dbcheck to fix the order of objectClass attributes.

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

Summary of changes:
 lib/ldb/ABI/{ldb-1.1.5.sigs => ldb-1.1.6.sigs}     |    1 +
 ...pyldb-util-1.1.2.sigs => pyldb-util-1.1.6.sigs} |    0
 lib/ldb/common/ldb_msg.c                           |   20 ++++++
 lib/ldb/include/ldb_module.h                       |    5 ++
 lib/ldb/ldb_tdb/ldb_tdb.c                          |   13 +++-
 lib/ldb/wscript                                    |    2 +-
 lib/replace/system/filesys.h                       |    8 +++
 source4/dsdb/pydsdb.c                              |   14 +++++
 source4/dsdb/samdb/ldb_modules/samldb.c            |    2 +-
 source4/scripting/python/samba/dbchecker.py        |   62 ++++++++++++++++++++
 10 files changed, 122 insertions(+), 5 deletions(-)
 copy lib/ldb/ABI/{ldb-1.1.5.sigs => ldb-1.1.6.sigs} (99%)
 copy lib/ldb/ABI/{pyldb-util-1.1.2.sigs => pyldb-util-1.1.6.sigs} (100%)


Changeset truncated at 500 lines:

diff --git a/lib/ldb/ABI/ldb-1.1.5.sigs b/lib/ldb/ABI/ldb-1.1.6.sigs
similarity index 99%
copy from lib/ldb/ABI/ldb-1.1.5.sigs
copy to lib/ldb/ABI/ldb-1.1.6.sigs
index cc0f859..f90fa13 100644
--- a/lib/ldb/ABI/ldb-1.1.5.sigs
+++ b/lib/ldb/ABI/ldb-1.1.6.sigs
@@ -157,6 +157,7 @@ ldb_msg_diff: struct ldb_message *(struct ldb_context *, struct ldb_message *, s
 ldb_msg_difference: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message *, struct ldb_message *, struct ldb_message **)
 ldb_msg_element_compare: int (struct ldb_message_element *, struct ldb_message_element *)
 ldb_msg_element_compare_name: int (struct ldb_message_element *, struct ldb_message_element *)
+ldb_msg_element_equal_ordered: bool (const struct ldb_message_element *, const struct ldb_message_element *)
 ldb_msg_find_attr_as_bool: int (const struct ldb_message *, const char *, int)
 ldb_msg_find_attr_as_dn: struct ldb_dn *(struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, const char *)
 ldb_msg_find_attr_as_double: double (const struct ldb_message *, const char *, double)
diff --git a/lib/ldb/ABI/pyldb-util-1.1.2.sigs b/lib/ldb/ABI/pyldb-util-1.1.6.sigs
similarity index 100%
copy from lib/ldb/ABI/pyldb-util-1.1.2.sigs
copy to lib/ldb/ABI/pyldb-util-1.1.6.sigs
diff --git a/lib/ldb/common/ldb_msg.c b/lib/ldb/common/ldb_msg.c
index c17e5f3..35c568a 100644
--- a/lib/ldb/common/ldb_msg.c
+++ b/lib/ldb/common/ldb_msg.c
@@ -360,6 +360,26 @@ int ldb_msg_element_compare(struct ldb_message_element *el1,
 }
 
 /*
+  compare two ldb_message_element structures.
+  Different ordering is considered a mismatch
+*/
+bool ldb_msg_element_equal_ordered(const struct ldb_message_element *el1,
+				   const struct ldb_message_element *el2)
+{
+	unsigned i;
+	if (el1->num_values != el2->num_values) {
+		return false;
+	}
+	for (i=0;i<el1->num_values;i++) {
+		if (ldb_val_equal_exact(&el1->values[i],
+					&el2->values[i]) != 1) {
+			return false;
+		}
+	}
+	return true;
+}
+
+/*
   compare two ldb_message_element structures
   comparing by element name
 */
diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h
index 4ecddc4..389e8ce 100644
--- a/lib/ldb/include/ldb_module.h
+++ b/lib/ldb/include/ldb_module.h
@@ -359,4 +359,9 @@ int ldb_parse_tree_walk(struct ldb_parse_tree *tree,
 			int (*callback)(struct ldb_parse_tree *tree, void *),
 			void *private_context);
 
+/* compare two message elements with ordering - used by modify */
+bool ldb_msg_element_equal_ordered(const struct ldb_message_element *el1,
+				   const struct ldb_message_element *el2);
+
+
 #endif
diff --git a/lib/ldb/ldb_tdb/ldb_tdb.c b/lib/ldb/ldb_tdb/ldb_tdb.c
index ebde8a3..5324c9b 100644
--- a/lib/ldb/ldb_tdb/ldb_tdb.c
+++ b/lib/ldb/ldb_tdb/ldb_tdb.c
@@ -845,11 +845,18 @@ int ltdb_modify_internal(struct ldb_module *module,
 			if (idx != -1) {
 				j = (unsigned int) idx;
 				el2 = &(msg2->elements[j]);
-				if (ldb_msg_element_compare(el, el2) == 0) {
-					/* we are replacing with the same values */
+
+				/* we consider two elements to be
+				 * equal only if the order
+				 * matches. This allows dbcheck to
+				 * fix the ordering on attributes
+				 * where order matters, such as
+				 * objectClass
+				 */
+				if (ldb_msg_element_equal_ordered(el, el2)) {
 					continue;
 				}
-			
+
 				/* Delete the attribute if it exists in the DB */
 				if (msg_delete_attribute(module, ldb, msg2,
 							 el->name) != 0) {
diff --git a/lib/ldb/wscript b/lib/ldb/wscript
index 620d2cf..f62bdec 100755
--- a/lib/ldb/wscript
+++ b/lib/ldb/wscript
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 APPNAME = 'ldb'
-VERSION = '1.1.5'
+VERSION = '1.1.6'
 
 blddir = 'bin'
 
diff --git a/lib/replace/system/filesys.h b/lib/replace/system/filesys.h
index e2c3c1d..2393068 100644
--- a/lib/replace/system/filesys.h
+++ b/lib/replace/system/filesys.h
@@ -200,4 +200,12 @@
 # define uwrap_enabled() 0
 #endif /* UID_WRAPPER */
 
+/*
+   this allows us to use a uniform error handling for our xattr
+   wrappers
+*/
+#ifndef ENOATTR
+#define ENOATTR ENODATA
+#endif
+
 #endif
diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c
index 762a03d..d3486a4 100644
--- a/source4/dsdb/pydsdb.c
+++ b/source4/dsdb/pydsdb.c
@@ -569,6 +569,7 @@ static PyObject *py_dsdb_DsReplicaAttribute(PyObject *self, PyObject *args)
 		PyObject *item = PyList_GetItem(el_list, i);
 		if (!PyString_Check(item)) {
 			PyErr_Format(PyExc_TypeError, "ldif_elements should be strings");
+			talloc_free(tmp_ctx);
 			return NULL;
 		}
 		el->values[i].data = (uint8_t *)PyString_AsString(item);
@@ -663,12 +664,25 @@ static PyObject *py_dsdb_normalise_attributes(PyObject *self, PyObject *args)
 		PyObject *item = PyList_GetItem(el_list, i);
 		if (!PyString_Check(item)) {
 			PyErr_Format(PyExc_TypeError, "ldif_elements should be strings");
+			talloc_free(tmp_ctx);
 			return NULL;
 		}
 		el->values[i].data = (uint8_t *)PyString_AsString(item);
 		el->values[i].length = PyString_Size(item);
 	}
 
+	/* Normalise "objectClass" attribute if needed */
+	if (ldb_attr_cmp(a->lDAPDisplayName, "objectClass") == 0) {
+		int iret;
+		iret = dsdb_sort_objectClass_attr(ldb, schema, tmp_ctx, el,
+						 tmp_ctx, el);
+		if (iret != LDB_SUCCESS) {
+			PyErr_SetString(PyExc_RuntimeError, ldb_errstring(ldb));
+			talloc_free(tmp_ctx);
+			return NULL;
+		}
+	}
+
 	/* first run ldb_to_drsuapi, then convert back again. This has
 	 * the effect of normalising the attributes
 	 */
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index 79ab1f8..390d921 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -1683,7 +1683,7 @@ static int samldb_member_check(struct samldb_ctx *ac)
 	/* Fetch information from the existing object */
 
 	ret = dsdb_module_search(ac->module, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs,
-				 DSDB_FLAG_NEXT_MODULE, ac->req, NULL);
+				 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED, ac->req, NULL);
 	if (ret != LDB_SUCCESS) {
 		return ret;
 	}
diff --git a/source4/scripting/python/samba/dbchecker.py b/source4/scripting/python/samba/dbchecker.py
index d866b3c..7993b54 100644
--- a/source4/scripting/python/samba/dbchecker.py
+++ b/source4/scripting/python/samba/dbchecker.py
@@ -48,6 +48,7 @@ class dbcheck(object):
         self.fix_time_metadata = False
         self.fix_all_missing_backlinks = False
         self.fix_all_orphaned_backlinks = False
+        self.fix_rmd_flags = False
         self.in_transaction = in_transaction
 
     def check_database(self, DN=None, scope=ldb.SCOPE_SUBTREE, controls=[], attrs=['*']):
@@ -163,6 +164,26 @@ class dbcheck(object):
                           validate=False):
             self.report("Normalised attribute %s" % attrname)
 
+    def err_normalise_mismatch_replace(self, dn, attrname, values):
+        '''fix attribute normalisation errors'''
+        normalised = self.samdb.dsdb_normalise_attributes(self.samdb_schema, attrname, values)
+        self.report("ERROR: Normalisation error for attribute '%s' in '%s'" % (attrname, dn))
+        self.report("Values/Order of values do/does not match: %s/%s!" % (values, list(normalised)))
+        if list(normalised) == values:
+            return
+        if not self.confirm_all("Fix normalisation for '%s' from '%s'?" % (attrname, dn), 'fix_all_normalisation'):
+            self.report("Not fixing attribute '%s'" % attrname)
+            return
+
+        m = ldb.Message()
+        m.dn = dn
+        m[attrname] = ldb.MessageElement(normalised, ldb.FLAG_MOD_REPLACE, attrname)
+
+        if self.do_modify(m, ["relax:0", "show_recycled:1"],
+                          "Failed to normalise attribute %s" % attrname,
+                          validate=False):
+            self.report("Normalised attribute %s" % attrname)
+
     def is_deleted_objects_dn(self, dsdb_dn):
         '''see if a dsdb_Dn is the special Deleted Objects DN'''
         return dsdb_dn.prefix == "B:32:18E2EA80684F11D2B9AA00C04F79F805:"
@@ -262,6 +283,20 @@ class dbcheck(object):
                           "Failed to fix missing backlink %s" % backlink_name):
             self.report("Fixed missing backlink %s" % (backlink_name))
 
+    def err_incorrect_rmd_flags(self, obj, attrname, revealed_dn):
+        '''handle a incorrect RMD_FLAGS value'''
+        rmd_flags = int(revealed_dn.dn.get_extended_component("RMD_FLAGS"))
+        self.report("ERROR: incorrect RMD_FLAGS value %u for attribute '%s' in %s for link %s" % (rmd_flags, attrname, obj.dn, revealed_dn.dn.extended_str()))
+        if not self.confirm_all('Fix incorrect RMD_FLAGS %u' % rmd_flags, 'fix_rmd_flags'):
+            self.report("Not fixing incorrect RMD_FLAGS %u" % rmd_flags)
+            return
+        m = ldb.Message()
+        m.dn = obj.dn
+        m['old_value'] = ldb.MessageElement(str(revealed_dn), ldb.FLAG_MOD_DELETE, attrname)
+        if self.do_modify(m, ["show_recycled:1", "reveal_internals:0", "show_deleted:0"],
+                          "Failed to fix incorrect RMD_FLAGS %u" % rmd_flags):
+            self.report("Fixed incorrect RMD_FLAGS %u" % (rmd_flags))
+
     def err_orphaned_backlink(self, obj, attrname, val, link_name, target_dn):
         '''handle a orphaned backlink value'''
         self.report("ERROR: orphaned backlink attribute '%s' in %s for link %s in %s" % (attrname, obj.dn, link_name, target_dn))
@@ -275,6 +310,18 @@ class dbcheck(object):
                           "Failed to fix orphaned backlink %s" % link_name):
             self.report("Fixed orphaned backlink %s" % (link_name))
 
+    def find_revealed_link(self, dn, attrname, guid):
+        '''return a revealed link in an object'''
+        res = self.samdb.search(base=dn, scope=ldb.SCOPE_BASE, attrs=[attrname],
+                                controls=["show_deleted:0", "extended_dn:0", "reveal_internals:0"])
+        syntax_oid = self.samdb_schema.get_syntax_oid_from_lDAPDisplayName(attrname)
+        for val in res[0][attrname]:
+            dsdb_dn = dsdb_Dn(self.samdb, val, syntax_oid)
+            guid2 = dsdb_dn.dn.get_extended_component("GUID")
+            if guid == guid2:
+                return dsdb_dn
+        return None
+
     def check_dn(self, obj, attrname, syntax_oid):
         '''check a DN attribute for correctness'''
         error_count = 0
@@ -324,6 +371,14 @@ class dbcheck(object):
                                             res[0].dn, "incorrect string version of DN")
                 continue
 
+            if is_deleted and not target_is_deleted and reverse_link_name is not None:
+                revealed_dn = self.find_revealed_link(obj.dn, attrname, guid)
+                rmd_flags = revealed_dn.dn.get_extended_component("RMD_FLAGS")
+                if rmd_flags != None and (int(rmd_flags) & 1) == 0:
+                    # the RMD_FLAGS for this link should be 1, as the target is deleted
+                    self.err_incorrect_rmd_flags(obj, attrname, revealed_dn)
+                    continue
+
             # check the reverse_link is correct if there should be one
             if reverse_link_name is not None:
                 match_count = 0
@@ -422,6 +477,13 @@ class dbcheck(object):
                 got_repl_property_meta_data = True
                 continue
 
+            if str(attrname).lower() == 'objectclass':
+                normalised = self.samdb.dsdb_normalise_attributes(self.samdb_schema, attrname, list(obj[attrname]))
+                if list(normalised) != list(obj[attrname]):
+                    self.err_normalise_mismatch_replace(dn, attrname, list(obj[attrname]))
+                    error_count += 1
+                continue
+
             # check for empty attributes
             for val in obj[attrname]:
                 if val == '':


-- 
Samba Shared Repository


More information about the samba-cvs mailing list