From 399c7160d56866725d8931a2f816de3b6a995704 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 21 Sep 2009 19:26:59 -0700 Subject: [PATCH] s4:ldb Add 'single-value' support to LDB. This is currently only triggered via Samba4's schema code. --- source4/dsdb/schema/schema_init.c | 4 ++++ source4/lib/ldb/include/ldb.h | 5 ++++ source4/lib/ldb/ldb_tdb/ldb_tdb.c | 49 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c index fa1953a14fd..8bb54f47f4e 100644 --- a/source4/dsdb/schema/schema_init.c +++ b/source4/dsdb/schema/schema_init.c @@ -653,6 +653,10 @@ static int dsdb_schema_setup_ldb_schema_attribute(struct ldb_context *ldb, if (dsdb_schema_unique_attribute(a->name)) { a->flags |= LDB_ATTR_FLAG_UNIQUE_INDEX; } + if (attr->isSingleValued) { + a->flags |= LDB_ATTR_FLAG_SINGLE_VALUE; + } + return LDB_SUCCESS; } diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 0378697f4b0..fa531b26f27 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -392,6 +392,11 @@ const struct ldb_dn_extended_syntax *ldb_dn_extended_syntax_by_name(struct ldb_c */ #define LDB_ATTR_FLAG_UNIQUE_INDEX (1<<3) +/* + when this is set, attempts to create two attribute values for this attribute on a single DN will return LDB_ERR_CONSTRAINT_VIOLATION + */ +#define LDB_ATTR_FLAG_SINGLE_VALUE (1<<4) + /** LDAP attribute syntax for a DN diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index d4f7b452cb4..e569a5a2a89 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -254,7 +254,7 @@ static int ltdb_add_internal(struct ldb_module *module, const struct ldb_message *msg) { struct ldb_context *ldb = ldb_module_get_ctx(module); - int ret; + int ret, i; ret = ltdb_check_special_dn(module, msg); if (ret != LDB_SUCCESS) { @@ -265,6 +265,24 @@ static int ltdb_add_internal(struct ldb_module *module, return LDB_ERR_OPERATIONS_ERROR; } + for (i=0;inum_elements;i++) { + struct ldb_message_element *el = &msg->elements[i]; + const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(ldb, el->name); + + if (el->num_values == 0) { + ldb_asprintf_errstring(ldb, "attribute %s on %s speicified, but with 0 values (illigal)", + el->name, ldb_dn_get_linearized(msg->dn)); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) { + if (el->num_values > 1) { + ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s speicified more than once", + el->name, ldb_dn_get_linearized(msg->dn)); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + } + } + ret = ltdb_store(module, msg, TDB_INSERT); if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) { @@ -602,15 +620,28 @@ int ltdb_modify_internal(struct ldb_module *module, struct ldb_message_element *el2; struct ldb_val *vals; const char *dn; - + const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(ldb, el->name); switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) { case LDB_FLAG_MOD_ADD: + /* add this element to the message. fail if it already exists */ idx = find_element(msg2, el->name); + if (el->num_values == 0) { + ldb_asprintf_errstring(ldb, "attribute %s on %s speicified, but with 0 values (illigal)", + el->name, ldb_dn_get_linearized(msg->dn)); + return LDB_ERR_CONSTRAINT_VIOLATION; + } if (idx == -1) { + if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) { + if (el->num_values > 1) { + ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s speicified more than once", + el->name, ldb_dn_get_linearized(msg->dn)); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + } if (msg_add_element(ldb, msg2, el) != 0) { ret = LDB_ERR_OTHER; goto failed; @@ -618,6 +649,13 @@ int ltdb_modify_internal(struct ldb_module *module, continue; } + /* If this is an add, then if it already + * exists in the object, then we violoate the + * single-value rule */ + if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) { + return LDB_ERR_CONSTRAINT_VIOLATION; + } + el2 = &msg2->elements[idx]; /* An attribute with this name already exists, @@ -657,6 +695,13 @@ int ltdb_modify_internal(struct ldb_module *module, break; case LDB_FLAG_MOD_REPLACE: + if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) { + if (el->num_values > 1) { + ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s speicified more than once", + el->name, ldb_dn_get_linearized(msg->dn)); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + } /* replace all elements of this attribute name with the elements listed. The attribute not existing is not an error */ msg_delete_attribute(module, ldb, msg2, el->name); -- 2.11.4.GIT