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;
}
}
-/*
- 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--;
}
}
- return msg2;
+ *_msg_out = msg2;
+ return LDB_SUCCESS;
}
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++) {