LDB:common - Change counters to "unsigned" where appropriate
[kamenim/samba.git] / source4 / lib / ldb / common / ldb_dn.c
index 3721fa733352de3e7c7009271591d3bfd6686d9f..d91e9d9fa9bbbcb1da602d84a854776a8cfa78d3 100644 (file)
@@ -103,7 +103,13 @@ struct ldb_dn *ldb_dn_from_ldb_val(void *mem_ctx,
        dn = talloc_zero(mem_ctx, struct ldb_dn);
        LDB_DN_NULL_FAILED(dn);
 
-       dn->ldb = ldb;
+       dn->ldb = talloc_get_type(ldb, struct ldb_context);
+       if (dn->ldb == NULL) {
+               /* the caller probably got the arguments to
+                  ldb_dn_new() mixed up */
+               talloc_free(dn);
+               return NULL;
+       }
 
        if (strdn->data && strdn->length) {
                const char *data = (const char *)strdn->data;
@@ -185,7 +191,7 @@ static int ldb_dn_escape_internal(char *dst, const char *src, int len)
 {
        const char *p, *s;
        char *d;
-       int l;
+       size_t l;
 
        p = s = src;
        d = dst;
@@ -232,7 +238,7 @@ static int ldb_dn_escape_internal(char *dst, const char *src, int len)
                        /* any others get \XX form */
                        unsigned char v;
                        const char *hexbytes = "0123456789ABCDEF";
-                       v = *(unsigned char *)p;
+                       v = *(const unsigned char *)p;
                        *d++ = '\\';
                        *d++ = hexbytes[v>>4];
                        *d++ = hexbytes[v&0xF];
@@ -291,8 +297,9 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
        bool in_quote = false;
        bool is_oid = false;
        bool escape = false;
-       unsigned x;
-       int l, ret;
+       unsigned int x;
+       size_t l;
+       int ret;
        char *parse_dn;
        bool is_index;
 
@@ -327,8 +334,8 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
        /* make sure we free this if alloced previously before replacing */
        talloc_free(dn->components);
 
-       talloc_free(dn->ext_components);
-       dn->ext_components = NULL;
+       LDB_FREE(dn->ext_components);
+       dn->ext_comp_num = 0;
 
        /* in the common case we have 3 or more components */
        /* make sure all components are zeroed, other functions depend on it */
@@ -734,7 +741,8 @@ bool ldb_dn_validate(struct ldb_dn *dn)
 
 const char *ldb_dn_get_linearized(struct ldb_dn *dn)
 {
-       int i, len;
+       unsigned int i;
+       size_t len;
        char *d, *n;
 
        if ( ! dn || ( dn->invalid)) return NULL;
@@ -789,11 +797,18 @@ const char *ldb_dn_get_linearized(struct ldb_dn *dn)
        return dn->linearized;
 }
 
+static int ldb_dn_extended_component_compare(const void *p1, const void *p2)
+{
+       const struct ldb_dn_ext_component *ec1 = (const struct ldb_dn_ext_component *)p1;
+       const struct ldb_dn_ext_component *ec2 = (const struct ldb_dn_ext_component *)p2;
+       return strcmp(ec1->name, ec2->name);
+}
+
 char *ldb_dn_get_extended_linearized(void *mem_ctx, struct ldb_dn *dn, int mode)
 {
        const char *linearized = ldb_dn_get_linearized(dn);
-       char *p;
-       int i;
+       char *p = NULL;
+       unsigned int i;
 
        if (!linearized) {
                return NULL;
@@ -807,6 +822,13 @@ char *ldb_dn_get_extended_linearized(void *mem_ctx, struct ldb_dn *dn, int mode)
                return NULL;
        }
 
+       /* sort the extended components by name. The idea is to make
+        * the resulting DNs consistent, plus to ensure that we put
+        * 'DELETED' first, so it can be very quickly recognised
+        */
+       TYPESAFE_QSORT(dn->ext_components, dn->ext_comp_num,
+                      ldb_dn_extended_component_compare);
+
        for (i = 0; i < dn->ext_comp_num; i++) {
                const struct ldb_dn_extended_syntax *ext_syntax;
                const char *name = dn->ext_components[i].name;
@@ -859,6 +881,23 @@ char *ldb_dn_get_extended_linearized(void *mem_ctx, struct ldb_dn *dn, int mode)
        return p;
 }
 
+/*
+  filter out all but an acceptable list of extended DN components
+ */
+void ldb_dn_extended_filter(struct ldb_dn *dn, const char * const *accept)
+{
+       unsigned int i;
+       for (i=0; i<dn->ext_comp_num; i++) {
+               if (!ldb_attr_in_list(accept, dn->ext_components[i].name)) {
+                       memmove(&dn->ext_components[i],
+                               &dn->ext_components[i+1],
+                               (dn->ext_comp_num-(i+1))*sizeof(dn->ext_components[0]));
+                       dn->ext_comp_num--;
+                       i--;
+               }
+       }
+       LDB_FREE(dn->ext_linearized);
+}
 
 
 char *ldb_dn_alloc_linearized(void *mem_ctx, struct ldb_dn *dn)
@@ -873,7 +912,8 @@ char *ldb_dn_alloc_linearized(void *mem_ctx, struct ldb_dn *dn)
 
 static bool ldb_dn_casefold_internal(struct ldb_dn *dn)
 {
-       int i, ret;
+       unsigned int i;
+       int ret;
 
        if ( ! dn || dn->invalid) return false;
 
@@ -918,7 +958,8 @@ failed:
 
 const char *ldb_dn_get_casefold(struct ldb_dn *dn)
 {
-       int i, len;
+       unsigned int i;
+       size_t len;
        char *d, *n;
 
        if (dn->casefold) return dn->casefold;
@@ -988,7 +1029,7 @@ char *ldb_dn_alloc_casefold(void *mem_ctx, struct ldb_dn *dn)
 int ldb_dn_compare_base(struct ldb_dn *base, struct ldb_dn *dn)
 {
        int ret;
-       int n_base, n_dn;
+       long long int n_base, n_dn;
 
        if ( ! base || base->invalid) return 1;
        if ( ! dn || dn->invalid) return -1;
@@ -1074,7 +1115,8 @@ int ldb_dn_compare_base(struct ldb_dn *base, struct ldb_dn *dn)
 
 int ldb_dn_compare(struct ldb_dn *dn0, struct ldb_dn *dn1)
 {
-       int i, ret;
+       unsigned int i;
+       int ret;
 
        if (( ! dn0) || dn0->invalid || ! dn1 || dn1->invalid) {
                return -1;
@@ -1232,7 +1274,7 @@ struct ldb_dn *ldb_dn_copy(void *mem_ctx, struct ldb_dn *dn)
        *new_dn = *dn;
 
        if (dn->components) {
-               int i;
+               unsigned int i;
 
                new_dn->components =
                        talloc_zero_array(new_dn,
@@ -1255,7 +1297,7 @@ struct ldb_dn *ldb_dn_copy(void *mem_ctx, struct ldb_dn *dn)
        }
 
        if (dn->ext_components) {
-               int i;
+               unsigned int i;
 
                new_dn->ext_components =
                        talloc_zero_array(new_dn,
@@ -1321,7 +1363,7 @@ bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base)
        }
 
        if (dn->components) {
-               int i;
+               unsigned int i;
 
                if ( ! ldb_dn_validate(base)) {
                        return false;
@@ -1388,9 +1430,7 @@ bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base)
 
        /* Wipe the ext_linearized DN,
         * the GUID and SID are almost certainly no longer valid */
-       if (dn->ext_linearized) {
-               LDB_FREE(dn->ext_linearized);
-       }
+       LDB_FREE(dn->ext_linearized);
 
        LDB_FREE(dn->ext_components);
        dn->ext_comp_num = 0;
@@ -1445,7 +1485,8 @@ bool ldb_dn_add_child(struct ldb_dn *dn, struct ldb_dn *child)
        }
 
        if (dn->components) {
-               int n, i, j;
+               unsigned int n;
+               long long int i, j;
 
                if ( ! ldb_dn_validate(child)) {
                        return false;
@@ -1553,7 +1594,7 @@ bool ldb_dn_add_child_fmt(struct ldb_dn *dn, const char *child_fmt, ...)
 
 bool ldb_dn_remove_base_components(struct ldb_dn *dn, unsigned int num)
 {
-       int i;
+       long long int i;
 
        if ( ! ldb_dn_validate(dn)) {
                return false;
@@ -1596,7 +1637,7 @@ bool ldb_dn_remove_base_components(struct ldb_dn *dn, unsigned int num)
 
 bool ldb_dn_remove_child_components(struct ldb_dn *dn, unsigned int num)
 {
-       int i, j;
+       unsigned int i, j;
 
        if ( ! ldb_dn_validate(dn)) {
                return false;
@@ -1671,7 +1712,7 @@ struct ldb_dn *ldb_dn_get_parent(void *mem_ctx, struct ldb_dn *dn)
 
 */
 static char *ldb_dn_canonical(void *mem_ctx, struct ldb_dn *dn, int ex_format) {
-       int i;
+       long long int i;
        TALLOC_CTX *tmpctx;
        char *cracked = NULL;
        const char *format = (ex_format ? "\n" : "/" );
@@ -1683,7 +1724,7 @@ static char *ldb_dn_canonical(void *mem_ctx, struct ldb_dn *dn, int ex_format) {
        tmpctx = talloc_new(mem_ctx);
 
        /* Walk backwards down the DN, grabbing 'dc' components at first */
-       for (i = dn->comp_num - 1 ; i >= 0; i--) {
+       for (i = dn->comp_num - 1; i >= 0; i--) {
                if (ldb_attr_cmp(dn->components[i].name, "dc") != 0) {
                        break;
                }
@@ -1816,7 +1857,7 @@ int ldb_dn_set_component(struct ldb_dn *dn, int num,
        dn->components[num].value = v;
 
        if (dn->valid_case) {
-               int i;
+               unsigned int i;
                for (i = 0; i < dn->comp_num; i++) {
                        LDB_FREE(dn->components[i].cf_name);
                        LDB_FREE(dn->components[i].cf_value.data);
@@ -1838,7 +1879,7 @@ int ldb_dn_set_component(struct ldb_dn *dn, int num,
 const struct ldb_val *ldb_dn_get_extended_component(struct ldb_dn *dn,
                                                    const char *name)
 {
-       int i;
+       unsigned int i;
        if ( ! ldb_dn_validate(dn)) {
                return NULL;
        }
@@ -1854,7 +1895,8 @@ int ldb_dn_set_extended_component(struct ldb_dn *dn,
                                  const char *name, const struct ldb_val *val)
 {
        struct ldb_dn_ext_component *p;
-       int i;
+       unsigned int i;
+       struct ldb_val v2;
 
        if ( ! ldb_dn_validate(dn)) {
                return LDB_ERR_OTHER;
@@ -1878,7 +1920,7 @@ int ldb_dn_set_extended_component(struct ldb_dn *dn,
                                        ldb_dn_mark_invalid(dn);
                                        return LDB_ERR_OPERATIONS_ERROR;
                                }
-
+                               return LDB_SUCCESS;
                        } else {
                                if (i != (dn->ext_comp_num - 1)) {
                                        memmove(&dn->ext_components[i],
@@ -1898,9 +1940,17 @@ int ldb_dn_set_extended_component(struct ldb_dn *dn,
                                }
                                return LDB_SUCCESS;
                        }
+                       LDB_FREE(dn->ext_linearized);
                }
        }
 
+       if (val == NULL) {
+               /* removing a value that doesn't exist is not an error */
+               return LDB_SUCCESS;
+       }
+
+       v2 = *val;
+
        p = dn->ext_components
                = talloc_realloc(dn,
                                 dn->ext_components,
@@ -1911,7 +1961,7 @@ int ldb_dn_set_extended_component(struct ldb_dn *dn,
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       p[dn->ext_comp_num].value = ldb_val_dup(dn->ext_components, val);
+       p[dn->ext_comp_num].value = ldb_val_dup(dn->ext_components, &v2);
        p[dn->ext_comp_num].name = talloc_strdup(p, name);
 
        if (!dn->ext_components[i].name || !dn->ext_components[i].value.data) {
@@ -1928,6 +1978,7 @@ void ldb_dn_remove_extended_components(struct ldb_dn *dn)
 {
        dn->ext_comp_num = 0;
        LDB_FREE(dn->ext_components);
+       LDB_FREE(dn->ext_linearized);
 }
 
 bool ldb_dn_is_valid(struct ldb_dn *dn)
@@ -1963,3 +2014,26 @@ bool ldb_dn_is_null(struct ldb_dn *dn)
        return false;
 }
 
+/*
+  this updates dn->components, taking the components from ref_dn.
+  This is used by code that wants to update the DN path of a DN
+  while not impacting on the extended DN components
+ */
+int ldb_dn_update_components(struct ldb_dn *dn, const struct ldb_dn *ref_dn)
+{
+       dn->components = talloc_realloc(dn, dn->components,
+                                       struct ldb_dn_component, ref_dn->comp_num);
+       if (!dn->components) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       memcpy(dn->components, ref_dn->components,
+              sizeof(struct ldb_dn_component)*ref_dn->comp_num);
+       dn->comp_num = ref_dn->comp_num;
+
+       talloc_free(dn->linearized);
+       talloc_free(dn->ext_linearized);
+       dn->ext_linearized = NULL;
+       dn->linearized = NULL;
+
+       return LDB_SUCCESS;
+}