r3926: fix compiler warnings
[samba.git] / source / lib / ldb / ldb_ldap / ldb_ldap.c
index 26c29122adc4c16ec5186889b966dbbaacdabc87..b9c3865acc5e596454cef1a2bf715e25c3e8e89f 100644 (file)
@@ -33,6 +33,8 @@
  */
 
 #include "includes.h"
+#include "ldb/include/ldb.h"
+#include "ldb/include/ldb_private.h"
 #include "ldb/ldb_ldap/ldb_ldap.h"
 
 #if 0
@@ -68,33 +70,72 @@ static const char *lldb_option_find(const struct lldb_private *lldb, const char
 /*
   close/free the connection
 */
-static int lldb_close(struct ldb_context *ldb)
+static int lldb_close(struct ldb_module *module)
 {
        int i, ret = 0;
-       struct lldb_private *lldb = ldb->private_data;
+       struct ldb_context *ldb = module->ldb;
+       struct lldb_private *lldb = module->private_data;
 
        if (ldap_unbind(lldb->ldap) != LDAP_SUCCESS) {
                ret = -1;
        }
 
+       ldb_set_alloc(ldb, NULL, NULL);
+
        if (lldb->options) {
                for (i=0;lldb->options[i];i++) {
-                       free(lldb->options[i]);
+                       ldb_free(ldb, lldb->options[i]);
                }
-               free(lldb->options);
+               ldb_free(ldb, lldb->options);
        }
-       free(lldb);
+       ldb_free(ldb, lldb);
        free(ldb);
 
        return ret;
 }
 
+/*
+  rename a record
+*/
+static int lldb_rename(struct ldb_module *module, const char *olddn, const char *newdn)
+{
+       struct ldb_context *ldb = module->ldb;
+       struct lldb_private *lldb = module->private_data;
+       int ret = 0;
+       char *newrdn, *p;
+       const char *parentdn = "";
+
+       /* ignore ltdb specials */
+       if (olddn[0] == '@' ||newdn[0] == '@') {
+               return 0;
+       }
+
+       newrdn = ldb_strdup(ldb, newdn);
+       if (!newrdn) {
+               return -1;
+       }
+
+       p = strchr(newrdn, ',');
+       if (p) {
+               *p++ = '\0';
+               parentdn = p;
+       }
+
+       lldb->last_rc = ldap_rename_s(lldb->ldap, olddn, newrdn, parentdn, 1, NULL, NULL);
+       ldb_free(ldb, newrdn);
+       if (lldb->last_rc != LDAP_SUCCESS) {
+               ret = -1;
+       }
+
+       return ret;
+}
+
 /*
   delete a record
 */
-static int lldb_delete(struct ldb_context *ldb, const char *dn)
+static int lldb_delete(struct ldb_module *module, const char *dn)
 {
-       struct lldb_private *lldb = ldb->private_data;
+       struct lldb_private *lldb = module->private_data;
        int ret = 0;
 
        /* ignore ltdb specials */
@@ -115,34 +156,35 @@ static int lldb_delete(struct ldb_context *ldb, const char *dn)
 */
 static int lldb_msg_free(struct ldb_context *ldb, struct ldb_message *msg)
 {
-       int i, j;
-       free(msg->dn);
+       unsigned int i, j;
+       ldb_free(ldb, msg->dn);
        for (i=0;i<msg->num_elements;i++) {
-               free(msg->elements[i].name);
+               ldb_free(ldb, msg->elements[i].name);
                for (j=0;j<msg->elements[i].num_values;j++) {
                        if (msg->elements[i].values[j].data) {
-                               free(msg->elements[i].values[j].data);
+                               ldb_free(ldb, msg->elements[i].values[j].data);
                        }
                }
-               free(msg->elements[i].values);
+               ldb_free(ldb, msg->elements[i].values);
        }
-       if (msg->elements) free(msg->elements);
-       free(msg);
+       if (msg->elements) ldb_free(ldb, msg->elements);
+       ldb_free(ldb, msg);
        return 0;
 }
 
 /*
   free a search result
 */
-static int lldb_search_free(struct ldb_context *ldb, struct ldb_message **res)
+static int lldb_search_free(struct ldb_module *module, struct ldb_message **res)
 {
+       struct ldb_context *ldb = module->ldb;
        int i;
        for (i=0;res[i];i++) {
                if (lldb_msg_free(ldb, res[i]) != 0) {
                        return -1;
                }
        }
-       free(res);
+       ldb_free(ldb, res);
        return 0;
 }
 
@@ -150,7 +192,8 @@ static int lldb_search_free(struct ldb_context *ldb, struct ldb_message **res)
 /*
   add a single set of ldap message values to a ldb_message
 */
-static int lldb_add_msg_attr(struct ldb_message *msg, 
+static int lldb_add_msg_attr(struct ldb_context *ldb,
+                            struct ldb_message *msg, 
                             const char *attr, struct berval **bval)
 {
        int count, i;
@@ -162,8 +205,8 @@ static int lldb_add_msg_attr(struct ldb_message *msg,
                return -1;
        }
 
-       el = realloc_p(msg->elements, struct ldb_message_element, 
-                      msg->num_elements + 1);
+       el = ldb_realloc_p(ldb, msg->elements, struct ldb_message_element, 
+                          msg->num_elements + 1);
        if (!el) {
                errno = ENOMEM;
                return -1;
@@ -173,7 +216,7 @@ static int lldb_add_msg_attr(struct ldb_message *msg,
 
        el = &msg->elements[msg->num_elements];
 
-       el->name = strdup(attr);
+       el->name = ldb_strdup(ldb, attr);
        if (!el->name) {
                errno = ENOMEM;
                return -1;
@@ -181,14 +224,14 @@ static int lldb_add_msg_attr(struct ldb_message *msg,
        el->flags = 0;
 
        el->num_values = 0;
-       el->values = malloc_array_p(struct ldb_val, count);
+       el->values = ldb_malloc_array_p(ldb, struct ldb_val, count);
        if (!el->values) {
                errno = ENOMEM;
                return -1;
        }
 
        for (i=0;i<count;i++) {
-               el->values[i].data = malloc(bval[i]->bv_len);
+               el->values[i].data = ldb_malloc(ldb, bval[i]->bv_len);
                if (!el->values[i].data) {
                        return -1;
                }
@@ -205,16 +248,23 @@ static int lldb_add_msg_attr(struct ldb_message *msg,
 /*
   search for matching records
 */
-static int lldb_search(struct ldb_context *ldb, const char *base,
+static int lldb_search(struct ldb_module *module, const char *base,
                       enum ldb_scope scope, const char *expression,
                       const char * const *attrs, struct ldb_message ***res)
 {
-       struct lldb_private *lldb = ldb->private_data;
+       struct ldb_context *ldb = module->ldb;
+       struct lldb_private *lldb = module->private_data;
        int count, msg_count;
        LDAPMessage *ldapres, *msg;
 
+       if (base == NULL) {
+               base = "";
+       }
+
        lldb->last_rc = ldap_search_s(lldb->ldap, base, (int)scope, 
-                                     expression, attrs, 0, &ldapres);
+                                     expression, 
+                                     discard_const_p(char *, attrs), 
+                                     0, &ldapres);
        if (lldb->last_rc != LDAP_SUCCESS) {
                return -1;
        }
@@ -225,7 +275,7 @@ static int lldb_search(struct ldb_context *ldb, const char *base,
                return count;
        }
 
-       (*res) = malloc_array_p(struct ldb_message *, count+1);
+       (*res) = ldb_malloc_array_p(ldb, struct ldb_message *, count+1);
        if (! *res) {
                ldap_msgfree(ldapres);
                errno = ENOMEM;
@@ -245,11 +295,11 @@ static int lldb_search(struct ldb_context *ldb, const char *base,
 
                if (msg_count == count) {
                        /* hmm, got too many? */
-                       fprintf(stderr,"Too many messages?!\n");
+                       ldb_debug(ldb, LDB_DEBUG_FATAL, "Fatal: ldap message count inconsistent\n");
                        break;
                }
 
-               (*res)[msg_count] = malloc_p(struct ldb_message);
+               (*res)[msg_count] = ldb_malloc_p(ldb, struct ldb_message);
                if (!(*res)[msg_count]) {
                        goto failed;
                }
@@ -260,7 +310,7 @@ static int lldb_search(struct ldb_context *ldb, const char *base,
                        goto failed;
                }
 
-               (*res)[msg_count]->dn = strdup(dn);
+               (*res)[msg_count]->dn = ldb_strdup(ldb, dn);
                ldap_memfree(dn);
                if (!(*res)[msg_count]->dn) {
                        goto failed;
@@ -279,7 +329,7 @@ static int lldb_search(struct ldb_context *ldb, const char *base,
                        bval = ldap_get_values_len(lldb->ldap, msg, attr);
 
                        if (bval) {
-                               lldb_add_msg_attr((*res)[msg_count], attr, bval);
+                               lldb_add_msg_attr(ldb, (*res)[msg_count], attr, bval);
                                ldap_value_free_len(bval);
                        }                                         
                        
@@ -295,7 +345,7 @@ static int lldb_search(struct ldb_context *ldb, const char *base,
        return msg_count;
 
 failed:
-       if (*res) lldb_search_free(ldb, *res);
+       if (*res) lldb_search_free(module, *res);
        return -1;
 }
 
@@ -303,7 +353,7 @@ failed:
 /*
   free a set of mods from lldb_msg_to_mods()
 */
-static void lldb_mods_free(LDAPMod **mods)
+static void lldb_mods_free(struct ldb_context *ldb, LDAPMod **mods)
 {
        int i, j;
 
@@ -312,13 +362,13 @@ static void lldb_mods_free(LDAPMod **mods)
        for (i=0;mods[i];i++) {
                if (mods[i]->mod_vals.modv_bvals) {
                        for (j=0;mods[i]->mod_vals.modv_bvals[j];j++) {
-                               free(mods[i]->mod_vals.modv_bvals[j]);
+                               ldb_free(ldb, mods[i]->mod_vals.modv_bvals[j]);
                        }
-                       free(mods[i]->mod_vals.modv_bvals);
+                       ldb_free(ldb, mods[i]->mod_vals.modv_bvals);
                }
-               free(mods[i]);
+               ldb_free(ldb, mods[i]);
        }
-       free(mods);
+       ldb_free(ldb, mods);
 }
 
 
@@ -326,13 +376,15 @@ static void lldb_mods_free(LDAPMod **mods)
   convert a ldb_message structure to a list of LDAPMod structures
   ready for ldap_add() or ldap_modify()
 */
-static LDAPMod **lldb_msg_to_mods(const struct ldb_message *msg, int use_flags)
+static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb,
+                                 const struct ldb_message *msg, int use_flags)
 {
        LDAPMod **mods;
-       int i, j, num_mods = 0;
+       unsigned int i, j;
+       int num_mods = 0;
 
        /* allocate maximum number of elements needed */
-       mods = malloc_array_p(LDAPMod *, msg->num_elements+1);
+       mods = ldb_malloc_array_p(ldb, LDAPMod *, msg->num_elements+1);
        if (!mods) {
                errno = ENOMEM;
                return NULL;
@@ -342,7 +394,7 @@ static LDAPMod **lldb_msg_to_mods(const struct ldb_message *msg, int use_flags)
        for (i=0;i<msg->num_elements;i++) {
                const struct ldb_message_element *el = &msg->elements[i];
 
-               mods[num_mods] = malloc_p(LDAPMod);
+               mods[num_mods] = ldb_malloc_p(ldb, LDAPMod);
                if (!mods[num_mods]) {
                        goto failed;
                }
@@ -362,14 +414,15 @@ static LDAPMod **lldb_msg_to_mods(const struct ldb_message *msg, int use_flags)
                        }
                }
                mods[num_mods]->mod_type = el->name;
-               mods[num_mods]->mod_vals.modv_bvals = malloc_array_p(struct berval *, 
-                                                                    1+el->num_values);
+               mods[num_mods]->mod_vals.modv_bvals = ldb_malloc_array_p(ldb, 
+                                                                        struct berval *,
+                                                                        1+el->num_values);
                if (!mods[num_mods]->mod_vals.modv_bvals) {
                        goto failed;
                }
 
                for (j=0;j<el->num_values;j++) {
-                       mods[num_mods]->mod_vals.modv_bvals[j] = malloc_p(struct berval);
+                       mods[num_mods]->mod_vals.modv_bvals[j] = ldb_malloc_p(ldb, struct berval);
                        if (!mods[num_mods]->mod_vals.modv_bvals[j]) {
                                goto failed;
                        }
@@ -383,7 +436,7 @@ static LDAPMod **lldb_msg_to_mods(const struct ldb_message *msg, int use_flags)
        return mods;
 
 failed:
-       lldb_mods_free(mods);
+       lldb_mods_free(ldb, mods);
        return NULL;
 }
 
@@ -391,9 +444,10 @@ failed:
 /*
   add a record
 */
-static int lldb_add(struct ldb_context *ldb, const struct ldb_message *msg)
+static int lldb_add(struct ldb_module *module, const struct ldb_message *msg)
 {
-       struct lldb_private *lldb = ldb->private_data;
+       struct ldb_context *ldb = module->ldb;
+       struct lldb_private *lldb = module->private_data;
        LDAPMod **mods;
        int ret = 0;
 
@@ -402,14 +456,14 @@ static int lldb_add(struct ldb_context *ldb, const struct ldb_message *msg)
                return 0;
        }
 
-       mods = lldb_msg_to_mods(msg, 0);
+       mods = lldb_msg_to_mods(ldb, msg, 0);
 
        lldb->last_rc = ldap_add_s(lldb->ldap, msg->dn, mods);
        if (lldb->last_rc != LDAP_SUCCESS) {
                ret = -1;
        }
 
-       lldb_mods_free(mods);
+       lldb_mods_free(ldb, mods);
 
        return ret;
 }
@@ -418,9 +472,10 @@ static int lldb_add(struct ldb_context *ldb, const struct ldb_message *msg)
 /*
   modify a record
 */
-static int lldb_modify(struct ldb_context *ldb, const struct ldb_message *msg)
+static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg)
 {
-       struct lldb_private *lldb = ldb->private_data;
+       struct ldb_context *ldb = module->ldb;
+       struct lldb_private *lldb = module->private_data;
        LDAPMod **mods;
        int ret = 0;
 
@@ -429,36 +484,65 @@ static int lldb_modify(struct ldb_context *ldb, const struct ldb_message *msg)
                return 0;
        }
 
-       mods = lldb_msg_to_mods(msg, 1);
+       mods = lldb_msg_to_mods(ldb, msg, 1);
 
        lldb->last_rc = ldap_modify_s(lldb->ldap, msg->dn, mods);
        if (lldb->last_rc != LDAP_SUCCESS) {
                ret = -1;
        }
 
-       lldb_mods_free(mods);
+       lldb_mods_free(ldb, mods);
+
+       return ret;
+}
+
+static int lldb_lock(struct ldb_module *module, const char *lockname)
+{
+       int ret = 0;
+
+       if (lockname == NULL) {
+               return -1;
+       }
+
+       /* TODO implement a local locking mechanism here */
 
        return ret;
 }
 
+static int lldb_unlock(struct ldb_module *module, const char *lockname)
+{
+       int ret = 0;
+
+       if (lockname == NULL) {
+               return -1;
+       }
+
+       /* TODO implement a local unlocking mechanism here */
+
+       return ret;
+}
 
 /*
   return extended error information
 */
-static const char *lldb_errstring(struct ldb_context *ldb)
+static const char *lldb_errstring(struct ldb_module *module)
 {
-       struct lldb_private *lldb = ldb->private_data;
+       struct lldb_private *lldb = module->private_data;
        return ldap_err2string(lldb->last_rc);
 }
 
 
-static const struct ldb_backend_ops lldb_ops = {
+static const struct ldb_module_ops lldb_ops = {
+       "ldap",
        lldb_close, 
        lldb_search,
        lldb_search_free,
        lldb_add,
        lldb_modify,
        lldb_delete,
+       lldb_rename,
+       lldb_lock,
+       lldb_unlock,
        lldb_errstring
 };
 
@@ -472,17 +556,17 @@ struct ldb_context *lldb_connect(const char *url,
 {
        struct ldb_context *ldb = NULL;
        struct lldb_private *lldb = NULL;
-       int i;
+       int i, version = 3;
 
-       ldb = malloc_p(struct ldb_context);
+       ldb = calloc(1, sizeof(struct ldb_context));
        if (!ldb) {
                errno = ENOMEM;
                goto failed;
        }
 
-       lldb = malloc_p(struct lldb_private);
+       lldb = ldb_malloc_p(ldb, struct lldb_private);
        if (!lldb) {
-               free(ldb);
+               ldb_free(ldb, ldb);
                errno = ENOMEM;
                goto failed;
        }
@@ -495,22 +579,35 @@ struct ldb_context *lldb_connect(const char *url,
                goto failed;
        }
 
-       ldb->ops = &lldb_ops;
-       ldb->private_data = lldb;
+       lldb->last_rc = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
+       if (lldb->last_rc != LDAP_SUCCESS) {
+               goto failed;
+       }
+
+       ldb->modules = ldb_malloc_p(ldb, struct ldb_module);
+       if (!ldb->modules) {
+               ldb_free(ldb, ldb);
+               errno = ENOMEM;
+               goto failed;
+       }
+       ldb->modules->ldb = ldb;
+       ldb->modules->prev = ldb->modules->next = NULL;
+       ldb->modules->private_data = lldb;
+       ldb->modules->ops = &lldb_ops;
 
        if (options) {
                /* take a copy of the options array, so we don't have to rely
                   on the caller keeping it around (it might be dynamic) */
                for (i=0;options[i];i++) ;
 
-               lldb->options = malloc_array_p(char *, i+1);
+               lldb->options = ldb_malloc_array_p(ldb, char *, i+1);
                if (!lldb->options) {
                        goto failed;
                }
                
                for (i=0;options[i];i++) {
                        lldb->options[i+1] = NULL;
-                       lldb->options[i] = strdup(options[i]);
+                       lldb->options[i] = ldb_strdup(ldb, options[i]);
                        if (!lldb->options[i]) {
                                goto failed;
                        }
@@ -522,14 +619,14 @@ struct ldb_context *lldb_connect(const char *url,
 failed:
        if (lldb && lldb->options) {
                for (i=0;lldb->options[i];i++) {
-                       free(lldb->options[i]);
+                       ldb_free(ldb, lldb->options[i]);
                }
-               free(lldb->options);
+               ldb_free(ldb, lldb->options);
        }
        if (lldb && lldb->ldap) {
                ldap_unbind(lldb->ldap);
        }
-       if (lldb) free(lldb);
+       ldb_free(ldb, lldb);
        if (ldb) free(ldb);
        return NULL;
 }