dbcheck: added fix for incorrect RMD_FLAGS
authorAndrew Tridgell <tridge@samba.org>
Wed, 18 Apr 2012 05:46:14 +0000 (15:46 +1000)
committerAndrew Tridgell <tridge@samba.org>
Wed, 18 Apr 2012 07:19:41 +0000 (09:19 +0200)
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@samba.org>

Autobuild-User: Andrew Tridgell <tridge@samba.org>
Autobuild-Date: Wed Apr 18 09:19:41 CEST 2012 on sn-devel-104

source4/scripting/python/samba/dbchecker.py

index 27bdf3d6b23aac776ccce38c8104714d0f184f0a..7993b5467b05e2067273ba9f60b833635b5c14ae 100644 (file)
@@ -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=['*']):
@@ -282,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))
@@ -295,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
@@ -344,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