s4-ldb: Refactor ldb_msg_canonicalize() to be based on ldb_msg_canonicalize_ex()...
[kamenim/samba.git] / source4 / lib / ldb / common / ldb_msg.c
index 75c616572077a1aa6023719e21fe2e4585c45f40..4b3271166c462e1ceb33df479f57151ce65fde31 100644 (file)
@@ -186,15 +186,21 @@ int ldb_msg_add(struct ldb_message *msg,
                const struct ldb_message_element *el, 
                int flags)
 {
+       int ret;
+       struct ldb_message_element *el_new;
        /* We have to copy this, just in case *el is a pointer into
         * what ldb_msg_add_empty() is about to realloc() */
        struct ldb_message_element el_copy = *el;
-       if (ldb_msg_add_empty(msg, el->name, flags, NULL) != LDB_SUCCESS) {
-               return LDB_ERR_OPERATIONS_ERROR;
+
+       ret = _ldb_msg_add_el(msg, &el_new);
+       if (ret != LDB_SUCCESS) {
+               return ret;
        }
 
-       msg->elements[msg->num_elements-1] = el_copy;
-       msg->elements[msg->num_elements-1].flags = flags;
+       el_new->flags      = flags;
+       el_new->name       = el_copy.name;
+       el_new->num_values = el_copy.num_values;
+       el_new->values     = el_copy.values;
 
        return LDB_SUCCESS;
 }
@@ -570,36 +576,62 @@ failed:
 }
 
 
-/*
 canonicalise a message, merging elements of the same name
-*/
+/**
* Canonicalize a message, merging elements of the same name
+ */
 struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, 
                                         const struct ldb_message *msg)
+{
+       int ret;
+       struct ldb_message *msg2;
+
+       /* allocate msg2 message in NULL context
+        * so it should appear as 'leaked' in talloc reports */
+       ret = ldb_msg_canonicalize_ex(ldb, msg, (TALLOC_CTX*)NULL, &msg2);
+       if (ret != LDB_SUCCESS) {
+               return NULL;
+       }
+
+       return msg2;
+}
+
+/**
+ * Canonicalize a message, merging elements of the same name
+ */
+int ldb_msg_canonicalize_ex(struct ldb_context *ldb,
+                           const struct ldb_message *msg,
+                           TALLOC_CTX *mem_ctx,
+                           struct ldb_message **_msg_out)
 {
        unsigned int i;
        struct ldb_message *msg2;
 
-       msg2 = ldb_msg_copy(ldb, msg);
-       if (msg2 == NULL) return NULL;
+       msg2 = ldb_msg_copy(mem_ctx, msg);
+       if (msg2 == NULL) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
 
        ldb_msg_sort_elements(msg2);
 
-       for (i=1;i<msg2->num_elements;i++) {
+       for (i=1; i < msg2->num_elements; i++) {
                struct ldb_message_element *el1 = &msg2->elements[i-1];
                struct ldb_message_element *el2 = &msg2->elements[i];
+
                if (ldb_msg_element_compare_name(el1, el2) == 0) {
-                       el1->values = talloc_realloc(msg2->elements, el1->values, struct ldb_val, 
-                                                      el1->num_values + el2->num_values);
+                       el1->values = talloc_realloc(msg2->elements,
+                                                    el1->values, struct ldb_val,
+                                                    el1->num_values + el2->num_values);
                        if (el1->num_values + el2->num_values > 0 && el1->values == NULL) {
-                               return NULL;
+                               talloc_free(msg2);
+                               return LDB_ERR_OPERATIONS_ERROR;
                        }
                        memcpy(el1->values + el1->num_values,
                               el2->values,
                               sizeof(struct ldb_val) * el2->num_values);
                        el1->num_values += el2->num_values;
                        talloc_free(discard_const_p(char, el2->name));
-                       if (i+1<msg2->num_elements) {
-                               memmove(el2, el2+1, sizeof(struct ldb_message_element) * 
+                       if ((i+1) < msg2->num_elements) {
+                               memmove(el2, el2+1, sizeof(struct ldb_message_element) *
                                        (msg2->num_elements - (i+1)));
                        }
                        msg2->num_elements--;
@@ -607,7 +639,8 @@ struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
                }
        }
 
-       return msg2;
+       *_msg_out = msg2;
+       return LDB_SUCCESS;
 }
 
 
@@ -671,17 +704,15 @@ int ldb_msg_diff_ex(struct ldb_context *ldb,
        mod->num_elements = 0;
        mod->elements = NULL;
 
-       /* canonicalize msg2 so we have no
-        * repeated elements */
-       msg2 = ldb_msg_canonicalize(ldb, msg2);
-       if (msg2 == NULL) {
+       /* Canonicalize msg2 so we have no repeated elements
+        * Resulting message is allocated in mod's mem context,
+        * as we are going to move some elements from msg2 to
+        * mod object later */
+       ldb_res = ldb_msg_canonicalize_ex(ldb, msg2, (TALLOC_CTX*)mod, &msg2);
+       if (ldb_res != LDB_SUCCESS) {
                goto failed;
        }
 
-       /* steal msg2 into mod context as it is
-        * allocated in ldb's context */
-       talloc_steal(mod, msg2);
-
        /* look in msg2 to find elements that need to be added
           or modified */
        for (i=0;i<msg2->num_elements;i++) {