s4-dsdb: Add @BL_lastKnownParent backlink as soon as the lastKnownParent is added
authorMatthieu Patou <mat@matws.net>
Sun, 22 May 2011 18:24:01 +0000 (22:24 +0400)
committerMatthieu Patou <mat@matws.net>
Sun, 24 Jul 2011 10:26:03 +0000 (14:26 +0400)
This has to be done that way otherwise we face problem in rename while
trying to fix backlinks.

source4/dsdb/samdb/ldb_modules/linked_attributes.c

index a57977b42836d7864b7d612cfac85bb9fa9e04d5..c4eb1f23fc22b071bfc80b286f9923aaeb53b711 100644 (file)
@@ -624,7 +624,59 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques
                                                continue;
                                        }
                                }
+                               if (((el->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_ADD) &&
+                                               ldb_attr_cmp(schema_attr->lDAPDisplayName, "lastKnownParent") == 0) {
+                                       /*
+                                        * Normaly we don't add backlink before the commit.
+                                        * But for lastKnownParent we need to do it right now.
+                                        * That's due to the fact that the parent can be "renamed" too (due to delete)
+                                        * but as the @BL_lastKnownParent is not present in the parent
+                                        * attribute lastKnownParent in the current element won't
+                                        * be fixed by linked_attributes_fix_links when
+                                        * processing the parent.
+                                        * Later on when linked_attributes_fix_links will try to
+                                        * fix lastKnowParent but will fail to find the target object
+                                        * (it has been renamed).
+                                        * The problem is limited to this attribute as it's the
+                                        * only one that can be created just before the parent will be renamed.
+                                        */
+
+                                       struct ldb_message_element *ret_el;
+                                       struct ldb_message *msg = ldb_msg_new(ac);
+                                       if (msg == NULL) {
+                                               return ldb_oom(ldb);
+                                       }
+
+                                       msg->dn = ldb_dn_copy(ac, tmp_dn->dn);
+                                       if (msg->dn == NULL) {
+                                               return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR,
+                                                               "Can't copy target dn");
+                                       }
 
+                                       ret = ldb_msg_add_empty(msg, "@BL_lastKnownParent", LDB_FLAG_MOD_ADD, &ret_el);
+                                       if (ret != LDB_SUCCESS) {
+                                               return ldb_error(ldb,ret, "Can't add @BL_lastKnownParent");
+                                       }
+
+                                       ret_el->values = talloc_array(msg, struct ldb_val, 1);
+                                       if (!ret_el->values) {
+                                               return ldb_oom(ldb);
+                                       }
+
+                                       ret_el->num_values = 1;
+                                       ret_el->values[0] = data_blob_string_const(ldb_dn_get_extended_linearized(msg, req->op.mod.message->dn, 1));
+                                       ret_el->flags |= LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK;
+                                       ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, ac->req);
+
+                                       if (ret != LDB_SUCCESS) {
+                                               ldb_debug(ldb, LDB_DEBUG_WARNING,
+                                                               __location__ ": failed to apply linked attribute change @BL_lastKnownParent '%s'\n",
+                                                               ldb_errstring(ldb));
+                                               return ldb_error(ldb, ret, "Add of @BL_lastKnownParent failed");
+                                       }
+                                       continue;
+
+                               }
                                ret = la_store_op(ac, LA_OP_ADD,
                                                  tmp_dn->dn,
                                                  attr_name);