ldb:ldb_pack.c - remove superflous "message->elements = NULL"
[abartlet/samba.git/.git] / source4 / lib / ldb / ldb_tdb / ldb_pack.c
index 0ebf62df8d117963411d961d71bca59275d21141..396b80ae4504c59a04a3f31e19641f98d6578d37 100644 (file)
@@ -10,7 +10,7 @@
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
-   version 2 of the License, or (at your option) any later version.
+   version 3 of the License, or (at your option) any later version.
 
    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,8 +18,7 @@
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with this library; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
 
 /*
  *  Author: Andrew Tridgell
  */
 
-#include "includes.h"
-#include "ldb/include/ldb.h"
-#include "ldb/include/ldb_private.h"
-#include "ldb/ldb_tdb/ldb_tdb.h"
+#include "ldb_tdb.h"
 
 /* change this if the data format ever changes */
 #define LTDB_PACKING_FORMAT 0x26011967
@@ -44,7 +40,7 @@
 #define LTDB_PACKING_FORMAT_NODN 0x26011966
 
 /* use a portable integer format */
-static void put_uint32(uint32 *p, int ofs, unsigned int val)
+static void put_uint32(uint8_t *p, int ofs, unsigned int val)
 {
        p += ofs;
        p[0] = val&0xFF;
@@ -53,12 +49,23 @@ static void put_uint32(uint32 *p, int ofs, unsigned int val)
        p[3] = (val>>24) & 0xFF;
 }
 
-static unsigned int pull_uint32(uint32 *p, int ofs)
+static unsigned int pull_uint32(uint8_t *p, int ofs)
 {
        p += ofs;
        return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
 }
 
+static int attribute_storable_values(const struct ldb_message_element *el)
+{
+       if (el->num_values == 0) return 0;
+
+       if (ldb_attr_cmp(el->name, "dn") == 0) return 0;
+
+       if (ldb_attr_cmp(el->name, "distinguishedName") == 0) return 0;
+
+       return el->num_values;
+}
+
 /*
   pack a ldb message into a linear buffer in a TDB_DATA
 
@@ -71,27 +78,33 @@ int ltdb_pack_data(struct ldb_module *module,
                   const struct ldb_message *message,
                   struct TDB_DATA *data)
 {
-       struct ldb_context *ldb = module->ldb;
+       struct ldb_context *ldb;
        unsigned int i, j, real_elements=0;
        size_t size;
-       char *p;
+       const char *dn;
+       uint8_t *p;
        size_t len;
 
-       for (i=0;i<message->num_elements;i++) {
-               if (message->elements[i].num_values != 0) {
-                       real_elements++;
-               }
+       ldb = ldb_module_get_ctx(module);
+
+       dn = ldb_dn_get_linearized(message->dn);
+       if (dn == NULL) {
+               errno = ENOMEM;
+               return -1;
        }
 
        /* work out how big it needs to be */
        size = 8;
 
-       size += 1 + strlen(message->dn);
+       size += 1 + strlen(dn);
 
        for (i=0;i<message->num_elements;i++) {
-               if (message->elements[i].num_values == 0) {
+               if (attribute_storable_values(&message->elements[i]) == 0) {
                        continue;
                }
+
+               real_elements++;
+
                size += 1 + strlen(message->elements[i].name) + 4;
                for (j=0;j<message->elements[i].num_values;j++) {
                        size += 4 + message->elements[i].values[j].length + 1;
@@ -99,7 +112,7 @@ int ltdb_pack_data(struct ldb_module *module,
        }
 
        /* allocate it */
-       data->dptr = ldb_malloc(ldb, size);
+       data->dptr = talloc_array(ldb, uint8_t, size);
        if (!data->dptr) {
                errno = ENOMEM;
                return -1;
@@ -113,12 +126,12 @@ int ltdb_pack_data(struct ldb_module *module,
 
        /* the dn needs to be packed so we can be case preserving
           while hashing on a case folded dn */
-       len = strlen(message->dn);
-       memcpy(p, message->dn, len+1);
+       len = strlen(dn);
+       memcpy(p, dn, len+1);
        p += len + 1;
        
        for (i=0;i<message->num_elements;i++) {
-               if (message->elements[i].num_values == 0) {
+               if (attribute_storable_values(&message->elements[i]) == 0) {
                        continue;
                }
                len = strlen(message->elements[i].name);
@@ -138,43 +151,23 @@ int ltdb_pack_data(struct ldb_module *module,
        return 0;
 }
 
-/*
-  free the memory allocated from a ltdb_unpack_data()
-*/
-void ltdb_unpack_data_free(struct ldb_module *module,
-                          struct ldb_message *message)
-{
-       struct ldb_context *ldb = module->ldb;
-       unsigned int i;
-
-       for (i=0;i<message->num_elements;i++) {
-               if (message->elements[i].values) ldb_free(ldb, message->elements[i].values);
-       }
-       if (message->elements) ldb_free(ldb, message->elements);
-}
-
-
 /*
   unpack a ldb message from a linear buffer in TDB_DATA
 
-  note that this does not fill in the class and key elements
-
-  caller frees. Memory for the elements[] and values[] arrays are
-  malloced, but the memory for the elements is re-used from the
-  TDB_DATA data. This means the caller only has to free the elements
-  and values arrays. This can be done with ltdb_unpack_data_free()
+  Free with ltdb_unpack_data_free()
 */
 int ltdb_unpack_data(struct ldb_module *module,
                     const struct TDB_DATA *data,
                     struct ldb_message *message)
 {
-       struct ldb_context *ldb = module->ldb;
-       char *p;
+       struct ldb_context *ldb;
+       uint8_t *p;
        unsigned int remaining;
        unsigned int i, j;
        unsigned format;
        size_t len;
 
+       ldb = ldb_module_get_ctx(module);
        message->elements = NULL;
 
        p = data->dptr;
@@ -195,12 +188,16 @@ int ltdb_unpack_data(struct ldb_module *module,
                break;
 
        case LTDB_PACKING_FORMAT:
-               len = strnlen(p, remaining);
+               len = strnlen((char *)p, remaining);
                if (len == remaining) {
                        errno = EIO;
                        goto failed;
                }
-               message->dn = p;
+               message->dn = ldb_dn_new(message, ldb, (char *)p);
+               if (message->dn == NULL) {
+                       errno = ENOMEM;
+                       goto failed;
+               }
                remaining -= len + 1;
                p += len + 1;
                break;
@@ -211,7 +208,6 @@ int ltdb_unpack_data(struct ldb_module *module,
        }
 
        if (message->num_elements == 0) {
-               message->elements = NULL;
                return 0;
        }
        
@@ -220,8 +216,7 @@ int ltdb_unpack_data(struct ldb_module *module,
                goto failed;
        }
 
-       message->elements = ldb_malloc_array_p(ldb, struct ldb_message_element,
-                                              message->num_elements);
+       message->elements = talloc_array(message, struct ldb_message_element, message->num_elements);
        if (!message->elements) {
                errno = ENOMEM;
                goto failed;
@@ -235,21 +230,29 @@ int ltdb_unpack_data(struct ldb_module *module,
                        errno = EIO;
                        goto failed;
                }
-               len = strnlen(p, remaining-6);
+               len = strnlen((char *)p, remaining-6);
                if (len == remaining-6) {
                        errno = EIO;
                        goto failed;
                }
+               if (len == 0) {
+                       errno = EIO;
+                       goto failed;
+               }
                message->elements[i].flags = 0;
-               message->elements[i].name = p;
+               message->elements[i].name = talloc_strndup(message->elements, (char *)p, len);
+               if (message->elements[i].name == NULL) {
+                       errno = ENOMEM;
+                       goto failed;
+               }
                remaining -= len + 1;
                p += len + 1;
                message->elements[i].num_values = pull_uint32(p, 0);
                message->elements[i].values = NULL;
                if (message->elements[i].num_values != 0) {
-                       message->elements[i].values = ldb_malloc_array_p(ldb,
-                                                                        struct ldb_val, 
-                                                                        message->elements[i].num_values);
+                       message->elements[i].values = talloc_array(message->elements,
+                                                                    struct ldb_val, 
+                                                                    message->elements[i].num_values);
                        if (!message->elements[i].values) {
                                errno = ENOMEM;
                                goto failed;
@@ -265,7 +268,14 @@ int ltdb_unpack_data(struct ldb_module *module,
                        }
 
                        message->elements[i].values[j].length = len;
-                       message->elements[i].values[j].data = p+4;
+                       message->elements[i].values[j].data = talloc_size(message->elements[i].values, len+1);
+                       if (message->elements[i].values[j].data == NULL) {
+                               errno = ENOMEM;
+                               goto failed;
+                       }
+                       memcpy(message->elements[i].values[j].data, p+4, len);
+                       message->elements[i].values[j].data[len] = 0;
+       
                        remaining -= len+4+1;
                        p += len+4+1;
                }
@@ -273,13 +283,12 @@ int ltdb_unpack_data(struct ldb_module *module,
 
        if (remaining != 0) {
                ldb_debug(ldb, LDB_DEBUG_ERROR, 
-                         "Error: %d bytes unread in ltdb_unpack_data\n", remaining);
+                         "Error: %d bytes unread in ltdb_unpack_data", remaining);
        }
 
        return 0;
 
 failed:
-       ltdb_unpack_data_free(module, message);
-
+       talloc_free(message->elements);
        return -1;
 }