]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/overlays/unique.c
fix ITS#3788: don't free slapo-rwm callback, rather reuse it
[openldap] / servers / slapd / overlays / unique.c
index c3b280d4c3adf2ac4efb3843fc3e9a26205f1598..79e7db9403785bd5c59f1218097b9ec2eb872d6d 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2004 The OpenLDAP Foundation.
+ * Copyright 2004-2005 The OpenLDAP Foundation.
  * Portions Copyright 2004 Symas Corporation.
  * All rights reserved.
  *
@@ -46,6 +46,7 @@ typedef struct unique_data_s {
 } unique_data;
 
 typedef struct unique_counter_s {
+       struct berval *ndn;
        int count;
 } unique_counter;
 
@@ -113,7 +114,7 @@ static int unique_config(
                        for(up = ud->attrs; up; up = up->next)
                            if(!strcmp(argv[i], up->attr->ad_cname.bv_val)) {
                                Debug(LDAP_DEBUG_ANY,
-                                       "%s: line %d: duplicate attribute <s>, ignored\n",
+                                       "%s: line %d: duplicate attribute <%s>, ignored\n",
                                        fname, lineno, argv[i]);
                                continue;
                        }
@@ -231,39 +232,155 @@ static int count_attr_cb(
        SlapReply *rs
 )
 {
+       unique_counter *uc;
+
        /* because you never know */
        if(!op || !rs) return(0);
 
        /* Only search entries are interesting */
        if(rs->sr_type != REP_SEARCH) return(0);
 
+       uc = op->o_callback->sc_private;
+
+       /* Ignore the current entry */
+       if ( dn_match( uc->ndn, &rs->sr_entry->e_nname )) return(0);
+
        Debug(LDAP_DEBUG_TRACE, "==> count_attr_cb <%s>\n",
                rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN", 0, 0);
 
-       ((unique_counter*)op->o_callback->sc_private)->count++;
+       uc->count++;
 
        return(0);
 }
 
-/* XXX extraneous (slap_response*) to avoid compiler warning */
+static int count_filter_len(
+       unique_data *ud,
+       AttributeDescription *ad,
+       BerVarray b,
+       int ks
+)
+{
+       unique_attrs *up;
+       int i;
 
-static int unique_add(
+       while(!is_at_operational(ad->ad_type)) {
+               if(ud->ignore) {
+                       for(up = ud->ignore; up; up = up->next)
+                               if(ad == up->attr) break;
+                       if(up) break;
+               }
+               if(ud->attrs) {
+                       for(up = ud->attrs; up; up = up->next)
+                               if(ad == up->attr) break;
+                       if(!up) break;
+               }
+               if(b && b[0].bv_val) for(i = 0; b[i].bv_val; i++)
+                       ks += b[i].bv_len + ad->ad_cname.bv_len + STRLENOF( "(=)" );
+               else if(ud->strict)
+                       ks += ad->ad_cname.bv_len + STRLENOF( "(=*)" ); /* (attr=*) */
+               break;
+       }
+       return ks;
+}
+
+static char *build_filter(
+       unique_data *ud,
+       AttributeDescription *ad,
+       BerVarray b,
+       char *kp
+)
+{
+       unique_attrs *up;
+       int i;
+
+       while(!is_at_operational(ad->ad_type)) {
+               if(ud->ignore) {
+                       for(up = ud->ignore; up; up = up->next)
+                               if(ad == up->attr) break;
+                       if(up) break;
+               }
+               if(ud->attrs) {
+                       for(up = ud->attrs; up; up = up->next)
+                               if(ad == up->attr) break;
+                       if(!up) break;
+               }
+               if(b && b[0].bv_val) for(i = 0; b[i].bv_val; i++)
+                       kp += sprintf(kp, "(%s=%s)", ad->ad_cname.bv_val, b[i].bv_val);
+               else if(ud->strict)
+                       kp += sprintf(kp, "(%s=*)", ad->ad_cname.bv_val);
+               break;
+       }
+       return kp;
+}
+
+static int unique_search(
        Operation *op,
-       SlapReply *rs
+       Operation *nop,
+       SlapReply *rs,
+       char *key
 )
 {
-       Operation nop = *op;
+       slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+       unique_data *ud = on->on_bi.bi_private;
        SlapReply nrs = { REP_RESULT };
        slap_callback cb = { NULL, NULL, NULL, NULL }; /* XXX */
+       unique_counter uq = { NULL, 0 };
+       int rc;
+
+       nop->ors_filter = str2filter_x(nop, key);
+       ber_str2bv(key, 0, 0, &nop->ors_filterstr);
+
+       cb.sc_response  = (slap_response*)count_attr_cb;
+       cb.sc_private   = &uq;
+       nop->o_callback = &cb;
+       nop->o_tag      = LDAP_REQ_SEARCH;
+       nop->ors_scope  = LDAP_SCOPE_SUBTREE;
+       nop->ors_deref  = LDAP_DEREF_NEVER;
+       nop->ors_limit  = NULL;
+       nop->ors_slimit = SLAP_NO_LIMIT;
+       nop->ors_tlimit = SLAP_NO_LIMIT;
+       nop->ors_attrs  = slap_anlist_no_attrs;
+       nop->ors_attrsonly = 1;
+
+       uq.ndn = &op->o_req_ndn;
+
+       nop->o_req_ndn  = ud->dn;
+       nop->o_ndn = op->o_bd->be_rootndn;
+
+       rc = nop->o_bd->be_search(nop, &nrs);
+       filter_free_x(nop, nop->ors_filter);
+       ch_free( key );
+
+       if(rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT) {
+               op->o_bd->bd_info = (BackendInfo *) on->on_info;
+               send_ldap_error(op, rs, rc, "unique_search failed");
+               return(rs->sr_err);
+       }
+
+       Debug(LDAP_DEBUG_TRACE, "=> unique_search found %d records\n", uq.count, 0, 0);
+
+       if(uq.count) {
+               op->o_bd->bd_info = (BackendInfo *) on->on_info;
+               send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION,
+                       "some attributes not unique");
+               return(rs->sr_err);
+       }
+
+       return(SLAP_CB_CONTINUE);
+}
+
+static int unique_add(
+       Operation *op,
+       SlapReply *rs
+)
+{
        slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+       unique_data *ud = on->on_bi.bi_private;
+       Operation nop = *op;
 
        Attribute *a;
-       BerVarray b = NULL;
        char *key, *kp;
-       int i, rc, ks = 16;
-       unique_attrs *up;
-       unique_counter uq = { 0 };
-       unique_data *ud = on->on_bi.bi_private;
+       int ks = 16;
 
        Debug(LDAP_DEBUG_TRACE, "==> unique_add <%s>\n", op->o_req_dn.bv_val, 0, 0);
 
@@ -296,21 +413,7 @@ static int unique_add(
                        "unique_add() got null op.ora_e.e_attrs");
                return(rs->sr_err);
        } else for(; a; a = a->a_next) {
-               if(is_at_operational(a->a_desc->ad_type)) continue;
-               if(ud->ignore) {
-                       for(up = ud->ignore; up; up = up->next)
-                               if(a->a_desc == up->attr) break;
-                       if(up) continue;
-               }
-               if(ud->attrs) {
-                       for(up = ud->attrs; up; up = up->next)
-                               if(a->a_desc == up->attr) break;
-                       if(!up) continue;
-               }
-               if((b = a->a_vals) && b[0].bv_val) for(i = 0; b[i].bv_val; i++)
-                       ks += b[i].bv_len + a->a_desc->ad_cname.bv_len + 3;
-               else if(ud->strict)
-                       ks += a->a_desc->ad_cname.bv_len + 4;   /* (attr=*) */
+               ks = count_filter_len(ud, a->a_desc, a->a_vals, ks);
        }
 
        key = ch_malloc(ks);
@@ -318,61 +421,14 @@ static int unique_add(
        kp = key + sprintf(key, "(|");
 
        for(a = op->ora_e->e_attrs; a; a = a->a_next) {
-               if(is_at_operational(a->a_desc->ad_type)) continue;
-               if(ud->ignore) {
-                       for(up = ud->ignore; up; up = up->next)
-                               if(a->a_desc == up->attr) break;
-                       if(up) continue;
-               }
-               if(ud->attrs) {
-                       for(up = ud->attrs; up; up = up->next)
-                               if(a->a_desc == up->attr) break;
-                       if(!up) continue;
-               }
-               if((b = a->a_vals) && b[0].bv_val) for(i = 0; b[i].bv_val; i++)
-                       kp += sprintf(kp, "(%s=%s)", a->a_desc->ad_cname.bv_val, b[i].bv_val);
-               else if(ud->strict)
-                       kp += sprintf(kp, "(%s=*)", a->a_desc->ad_cname.bv_val);
+               kp = build_filter(ud, a->a_desc, a->a_vals, kp);
        }
 
-       kp += sprintf(kp, ")");
+       sprintf(kp, ")");
 
        Debug(LDAP_DEBUG_TRACE, "=> unique_add %s\n", key, 0, 0);
 
-       nop.ors_filter = str2filter_x(&nop, key);
-       ber_str2bv(key, 0, 0, &nop.ors_filterstr);
-
-       cb.sc_response  = (slap_response*)count_attr_cb;
-       cb.sc_private   = &uq;
-       nop.o_callback  = &cb;
-       nop.o_tag       = LDAP_REQ_SEARCH;
-       nop.ors_scope   = LDAP_SCOPE_SUBTREE;
-       nop.ors_deref   = LDAP_DEREF_NEVER;
-       nop.ors_slimit  = SLAP_NO_LIMIT;
-       nop.ors_tlimit  = SLAP_NO_LIMIT;
-       nop.o_req_ndn   = ud->dn;
-       nop.o_ndn = op->o_bd->be_rootndn;
-
-       rc = nop.o_bd->be_search(&nop, &nrs);
-       filter_free_x(&nop, nop.ors_filter);
-       ch_free( key );
-
-       if(rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT) {
-               op->o_bd->bd_info = (BackendInfo *) on->on_info;
-               send_ldap_error(op, rs, rc, "unique_add search failed");
-               return(rs->sr_err);
-       }
-
-       Debug(LDAP_DEBUG_TRACE, "=> unique_add found %d records\n", uq.count, 0, 0);
-
-       if(uq.count) {
-               op->o_bd->bd_info = (BackendInfo *) on->on_info;
-               send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION,
-                       "some attributes not unique");
-               return(rs->sr_err);
-       }
-
-       return(SLAP_CB_CONTINUE);
+       return unique_search(op, &nop, rs, key);
 }
 
 
@@ -381,18 +437,13 @@ static int unique_modify(
        SlapReply *rs
 )
 {
-       Operation nop = *op;
-       SlapReply nrs = { REP_RESULT };
-       slap_callback cb = { NULL, (slap_response*)count_attr_cb, NULL, NULL };
        slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+       unique_data *ud = on->on_bi.bi_private;
+       Operation nop = *op;
 
-       BerVarray b = NULL;
        Modifications *m;
        char *key, *kp;
-       int i, rc, ks = 16;             /* a handful of extra bytes */
-       unique_attrs *up;
-       unique_counter uq = { 0 };
-       unique_data *ud = on->on_bi.bi_private;
+       int ks = 16;            /* a handful of extra bytes */
 
        Debug(LDAP_DEBUG_TRACE, "==> unique_modify <%s>\n", op->o_req_dn.bv_val, 0, 0);
 
@@ -424,22 +475,8 @@ static int unique_modify(
                        "unique_modify() got null op.orm_modlist");
                return(rs->sr_err);
        } else for(; m; m = m->sml_next) {
-               if(is_at_operational(m->sml_desc->ad_type) ||
-                       ((m->sml_op & LDAP_MOD_OP) == LDAP_MOD_DELETE)) continue;
-               if(ud->ignore) {
-                       for(up = ud->ignore; up; up = up->next)
-                               if(m->sml_desc == up->attr) break;
-                       if(up) continue;
-               }
-               if(ud->attrs) {
-                       for(up = ud->attrs; up; up = up->next)
-                               if(m->sml_desc == up->attr) break;
-                       if(!up) continue;
-               }
-               if((b = m->sml_values) && b[0].bv_val) for(i = 0; b[i].bv_val; i++)
-                       ks += b[i].bv_len + m->sml_desc->ad_cname.bv_len + 3;
-               else if(ud->strict)
-                       ks += m->sml_desc->ad_cname.bv_len + 4; /* (attr=*) */
+               if ((m->sml_op & LDAP_MOD_OP) == LDAP_MOD_DELETE) continue;
+               ks = count_filter_len(ud, m->sml_desc, m->sml_values, ks);
        }
 
        key = ch_malloc(ks);
@@ -447,62 +484,15 @@ static int unique_modify(
        kp = key + sprintf(key, "(|");
 
        for(m = op->orm_modlist; m; m = m->sml_next) {
-               if(is_at_operational(m->sml_desc->ad_type) ||
-                       ((m->sml_op & LDAP_MOD_OP) == LDAP_MOD_DELETE)) continue;
-               if(ud->ignore) {
-                       for(up = ud->ignore; up; up = up->next)
-                               if(m->sml_desc == up->attr) break;
-                       if(up) continue;
-               }
-               if(ud->attrs) {
-                       for(up = ud->attrs; up; up = up->next)
-                               if(m->sml_desc == up->attr) break;
-                       if(!up) continue;
-               }
-               if((b = m->sml_values) && b[0].bv_val) for(i = 0; b[i].bv_val; i++)
-                       kp += sprintf(kp, "(%s=%s)", m->sml_desc->ad_cname.bv_val, b[i].bv_val);
-               else if(ud->strict)
-                       kp += sprintf(kp, "(%s=*)", m->sml_desc->ad_cname.bv_val);
+               if ((m->sml_op & LDAP_MOD_OP) == LDAP_MOD_DELETE) continue;
+               kp = build_filter(ud, m->sml_desc, m->sml_values, kp);
        }
 
-       kp += sprintf(kp, ")");
+       sprintf(kp, ")");
 
        Debug(LDAP_DEBUG_TRACE, "=> unique_modify %s\n", key, 0, 0);
 
-       nop.ors_filter = str2filter_x(&nop, key);
-       ber_str2bv(key, 0, 0, &nop.ors_filterstr);
-
-       cb.sc_response  = (slap_response*)count_attr_cb;
-       cb.sc_private   = &uq;
-       nop.o_callback  = &cb;
-       nop.o_tag       = LDAP_REQ_SEARCH;
-       nop.ors_scope   = LDAP_SCOPE_SUBTREE;
-       nop.ors_deref   = LDAP_DEREF_NEVER;
-       nop.ors_slimit  = SLAP_NO_LIMIT;
-       nop.ors_tlimit  = SLAP_NO_LIMIT;
-       nop.o_req_ndn   = ud->dn;
-       nop.o_ndn = op->o_bd->be_rootndn;
-
-       rc = nop.o_bd->be_search(&nop, &nrs);
-       ch_free( key );
-
-       if(rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT) {
-               op->o_bd->bd_info = (BackendInfo *) on->on_info;
-               send_ldap_error(op, rs, rc, "unique_modify search failed");
-               return(rs->sr_err);
-       }
-
-       Debug(LDAP_DEBUG_TRACE, "=> unique_modify found %d records\n", uq.count, 0, 0);
-
-       if(uq.count) {
-               op->o_bd->bd_info = (BackendInfo *) on->on_info;
-               send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION,
-                       "some attributes not unique");
-               return(rs->sr_err);
-       }
-
-       return(SLAP_CB_CONTINUE);
-
+       return unique_search(op, &nop, rs, key);
 }
 
 
@@ -511,17 +501,14 @@ static int unique_modrdn(
        SlapReply *rs
 )
 {
-       Operation nop = *op;
-       SlapReply nrs = { REP_RESULT };
-       slap_callback cb = { NULL, (slap_response*)count_attr_cb, NULL, NULL };
        slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+       unique_data *ud = on->on_bi.bi_private;
+       Operation nop = *op;
 
        char *key, *kp;
        int i, rc, ks = 16;             /* a handful of extra bytes */
-       unique_attrs *up;
-       unique_counter uq = { 0 };
-       unique_data *ud = on->on_bi.bi_private;
        LDAPRDN newrdn;
+       struct berval bv[2];
 
        Debug(LDAP_DEBUG_TRACE, "==> unique_modrdn <%s> <%s>\n",
                op->o_req_dn.bv_val, op->orr_newrdn.bv_val, 0);
@@ -559,79 +546,27 @@ static int unique_modrdn(
                newrdn[i]->la_private = ad;
        }
 
+       bv[1].bv_val = NULL;
+       bv[1].bv_len = 0;
+
        for(i = 0; newrdn[i]; i++) {
-               AttributeDescription *ad = newrdn[i]->la_private;
-               if(ud->ignore) {
-                       for(up = ud->ignore; up; up = up->next)
-                               if(ad == up->attr) break;
-                       if(up) continue;
-               }
-               if(ud->attrs) {
-                       for(up = ud->attrs; up; up = up->next)
-                               if(ad == up->attr) break;
-                       if(!up) continue;
-               }
-               ks += newrdn[i]->la_value.bv_len + ad->ad_cname.bv_len + 3;
+               bv[0] = newrdn[i]->la_value;
+               ks = count_filter_len(ud, newrdn[i]->la_private, bv, ks);
        }
 
        key = ch_malloc(ks);
        kp = key + sprintf(key, "(|");
 
        for(i = 0; newrdn[i]; i++) {
-               AttributeDescription *ad = newrdn[i]->la_private;
-               if(ud->ignore) {
-                       for(up = ud->ignore; up; up = up->next)
-                               if(ad == up->attr) break;
-                       if(up) continue;
-               }
-               if(ud->attrs) {
-                       for(up = ud->attrs; up; up = up->next)
-                               if(ad == up->attr) break;
-                       if(!up) continue;
-               }
-               kp += sprintf(kp, "(%s=%s)", ad->ad_cname.bv_val,
-                       newrdn[i]->la_value.bv_val);
+               bv[0] = newrdn[i]->la_value;
+               kp = build_filter(ud, newrdn[i]->la_private, bv, kp);
        }
 
-       kp += sprintf(kp, ")");
-
+       sprintf(kp, ")");
 
        Debug(LDAP_DEBUG_TRACE, "=> unique_modrdn %s\n", key, 0, 0);
 
-       nop.ors_filter = str2filter_x(&nop, key);
-       ber_str2bv(key, 0, 0, &nop.ors_filterstr);
-
-       cb.sc_response  = (slap_response*)count_attr_cb;
-       cb.sc_private   = &uq;
-       nop.o_callback  = &cb;
-       nop.o_tag       = LDAP_REQ_SEARCH;
-       nop.ors_scope   = LDAP_SCOPE_SUBTREE;
-       nop.ors_deref   = LDAP_DEREF_NEVER;
-       nop.ors_slimit  = SLAP_NO_LIMIT;
-       nop.ors_tlimit  = SLAP_NO_LIMIT;
-       nop.o_req_ndn   = ud->dn;
-       nop.o_ndn = op->o_bd->be_rootndn;
-
-       rc = nop.o_bd->be_search(&nop, &nrs);
-       ch_free( key );
-       ldap_rdnfree_x( newrdn, op->o_tmpmemctx );
-
-       if(rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT) {
-               op->o_bd->bd_info = (BackendInfo *) on->on_info;
-               send_ldap_error(op, rs, rc, "unique_modrdn search failed");
-               return(rs->sr_err);
-       }
-
-       Debug(LDAP_DEBUG_TRACE, "=> unique_modrdn found %d records\n", uq.count, 0, 0);
-
-       if(uq.count) {
-               op->o_bd->bd_info = (BackendInfo *) on->on_info;
-               send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION,
-                       "some attributes not unique");
-               return(rs->sr_err);
-       }
-
-       return(SLAP_CB_CONTINUE);
+       return unique_search(op, &nop, rs, key);
 }
 
 /*