r19731: Modify the ldb_map infrustructure to always map from requested
[kamenim/samba.git] / source4 / lib / ldb / common / ldb_msg.c
index d40dcde010ace2c7c180139eec421d642cd10545..65d1ecacb7a98ee502a5e94ccd99587371af9bfd 100644 (file)
@@ -119,19 +119,22 @@ struct ldb_val ldb_val_dup(void *mem_ctx, const struct ldb_val *v)
 /*
   add an empty element to a message
 */
-int ldb_msg_add_empty(struct ldb_message *msg, const char *attr_name, int flags)
+int ldb_msg_add_empty( struct ldb_message *msg,
+                       const char *attr_name,
+                       int flags,
+                       struct ldb_message_element **return_el)
 {
        struct ldb_message_element *els;
 
        if (! ldb_valid_attr_name(attr_name)) {
-               return -1;
+               return LDB_ERR_OPERATIONS_ERROR;
        }
 
        els = talloc_realloc(msg, msg->elements, 
                             struct ldb_message_element, msg->num_elements+1);
        if (!els) {
                errno = ENOMEM;
-               return -1;
+               return LDB_ERR_OPERATIONS_ERROR;
        }
 
        els[msg->num_elements].values = NULL;
@@ -140,13 +143,17 @@ int ldb_msg_add_empty(struct ldb_message *msg, const char *attr_name, int flags)
        els[msg->num_elements].name = talloc_strdup(els, attr_name);
        if (!els[msg->num_elements].name) {
                errno = ENOMEM;
-               return -1;
+               return LDB_ERR_OPERATIONS_ERROR;
        }
 
        msg->elements = els;
        msg->num_elements++;
 
-       return 0;
+       if (return_el) {
+               *return_el = &els[msg->num_elements-1];
+       }
+
+       return LDB_SUCCESS;
 }
 
 /*
@@ -156,14 +163,14 @@ int ldb_msg_add(struct ldb_message *msg,
                const struct ldb_message_element *el, 
                int flags)
 {
-       if (ldb_msg_add_empty(msg, el->name, flags) != 0) {
-               return -1;
+       if (ldb_msg_add_empty(msg, el->name, flags, NULL) != 0) {
+               return LDB_ERR_OPERATIONS_ERROR;
        }
 
        msg->elements[msg->num_elements-1] = *el;
        msg->elements[msg->num_elements-1].flags = flags;
 
-       return 0;
+       return LDB_SUCCESS;
 }
 
 /*
@@ -171,30 +178,35 @@ int ldb_msg_add(struct ldb_message *msg,
 */
 int ldb_msg_add_value(struct ldb_message *msg, 
                      const char *attr_name,
-                     const struct ldb_val *val)
+                     const struct ldb_val *val,
+                     struct ldb_message_element **return_el)
 {
        struct ldb_message_element *el;
        struct ldb_val *vals;
+       int ret;
 
        el = ldb_msg_find_element(msg, attr_name);
        if (!el) {
-               ldb_msg_add_empty(msg, attr_name, 0);
-               el = ldb_msg_find_element(msg, attr_name);
-       }
-       if (!el) {
-               return -1;
+               ret = ldb_msg_add_empty(msg, attr_name, 0, &el);
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
        }
 
        vals = talloc_realloc(msg, el->values, struct ldb_val, el->num_values+1);
        if (!vals) {
                errno = ENOMEM;
-               return -1;
+               return LDB_ERR_OPERATIONS_ERROR;
        }
        el->values = vals;
        el->values[el->num_values] = *val;
        el->num_values++;
 
-       return 0;
+       if (return_el) {
+               *return_el = el;
+       }
+
+       return LDB_SUCCESS;
 }
 
 
@@ -206,10 +218,10 @@ int ldb_msg_add_steal_value(struct ldb_message *msg,
                            struct ldb_val *val)
 {
        int ret;
-       ret = ldb_msg_add_value(msg, attr_name, val);
+       struct ldb_message_element *el;
+
+       ret = ldb_msg_add_value(msg, attr_name, val, &el);
        if (ret == LDB_SUCCESS) {
-               struct ldb_message_element *el;
-               el = ldb_msg_find_element(msg, attr_name);
                talloc_steal(el->values, val->data);
        }
        return ret;
@@ -227,7 +239,12 @@ int ldb_msg_add_string(struct ldb_message *msg,
        val.data = discard_const_p(uint8_t, str);
        val.length = strlen(str);
 
-       return ldb_msg_add_value(msg, attr_name, &val);
+       if (val.length == 0) {
+               /* allow empty strings as non-existant attributes */
+               return LDB_SUCCESS;
+       }
+
+       return ldb_msg_add_value(msg, attr_name, &val, NULL);
 }
 
 /*
@@ -258,7 +275,7 @@ int ldb_msg_add_fmt(struct ldb_message *msg,
        str = talloc_vasprintf(msg, fmt, ap);
        va_end(ap);
 
-       if (str == NULL) return -1;
+       if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
 
        val.data   = (uint8_t *)str;
        val.length = strlen(str);
@@ -374,10 +391,10 @@ int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
        if (!v || !v->data) {
                return default_value;
        }
-       if (strcasecmp(v->data, "FALSE") == 0) {
+       if (strcasecmp((const char *)v->data, "FALSE") == 0) {
                return 0;
        }
-       if (strcasecmp(v->data, "TRUE") == 0) {
+       if (strcasecmp((const char *)v->data, "TRUE") == 0) {
                return 1;
        }
        return default_value;
@@ -571,7 +588,7 @@ struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
                if (!el) {
                        if (ldb_msg_add_empty(mod, 
                                              msg1->elements[i].name,
-                                             LDB_FLAG_MOD_DELETE) != 0) {
+                                             LDB_FLAG_MOD_DELETE, NULL) != 0) {
                                return NULL;
                        }
                }
@@ -591,11 +608,6 @@ int ldb_msg_sanity_check(struct ldb_context *ldb,
                ldb_set_errstring(ldb, "ldb message lacks a DN!");
                return LDB_ERR_INVALID_DN_SYNTAX;
        }
-       if (msg->dn->comp_num == 0) {
-               /* root dse has empty dn */
-               ldb_set_errstring(ldb, "DN on new ldb message is '' (not permitted)!");
-               return LDB_ERR_ENTRY_ALREADY_EXISTS;
-       }
 
        /* basic syntax checks */
        for (i = 0; i < msg->num_elements; i++) {
@@ -642,7 +654,7 @@ const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
 
 /*
   copy an attribute list. This only copies the array, not the elements
-  (ie. the elements are left as the same pointers)
+  (ie. the elements are left as the same pointers).  The new attribute is added to the list.
 */
 const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
 {
@@ -684,13 +696,13 @@ int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *r
 {
        struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
        if (el == NULL) {
-               return 0;
+               return LDB_SUCCESS;
        }
        el->name = talloc_strdup(msg->elements, replace);
        if (el->name == NULL) {
-               return -1;
+               return LDB_ERR_OPERATIONS_ERROR;
        }
-       return 0;
+       return LDB_SUCCESS;
 }
 
 
@@ -701,10 +713,10 @@ int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *rep
 {
        struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
        if (el == NULL) {
-               return 0;
+               return LDB_SUCCESS;
        }
        if (ldb_msg_add(msg, el, 0) != 0) {
-               return -1;
+               return LDB_ERR_OPERATIONS_ERROR;
        }
        return ldb_msg_rename_attr(msg, attr, replace);
 }
@@ -725,6 +737,18 @@ void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
        }
 }
 
+/*
+  remove the specified element in a search result
+*/
+void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
+{
+       int n = (el - msg->elements);
+       if (n != msg->num_elements-1) {
+               memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
+       }
+       msg->num_elements--;
+}
+
 /*
   return a LDAP formatted time string
 */
@@ -792,7 +816,7 @@ int ldb_msg_check_string_attribute(const struct ldb_message *msg, const char *na
        if (el == NULL)
                return 0;
 
-       val.data = discard_const(value);
+       val.data = discard_const_p(uint8_t, value);
        val.length = strlen(value);
 
        if (ldb_msg_find_val(el, &val))