[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Thu May 23 06:19:02 MDT 2013


The branch, master has been updated
       via  e24fe57 libnet-vampire: make use of dsdb_repl_resolve_working_schema()
       via  24fb281 dsdb-repl: merge the logic from libnet_vampire_cb_apply_schema()
       via  9af430e dsdb-repl: split out dsdb_repl_resolve_working_schema
       via  d36e911 selftest: Improve test coverage of DRS (bug #8680)
       via  640c2ff dsdb-drs: when replicating schema object checks ask for removal of previous version if exists (bug #8680)
       via  c7d4b87 libnet-vampire: add attributes and classes from the replicated schema to the bootstrap schema (bug #8680)
       via  fe85bc1 dsdb-schema: make deduplication of class and schema possible (bug #8680)
       via  c524be1 dsdb-schema: schema_fill_possible_inferiors() should rebuild everthing
      from  bea2af9 Revert my accidental commit.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit e24fe5705e3c4d33705ebb584ea2009bb4a1a82c
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri May 17 23:18:55 2013 +0200

    libnet-vampire: make use of dsdb_repl_resolve_working_schema()
    
    Pair-Programmed-With: Matthieu Patou <mat at matws.net>
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Thu May 23 14:18:03 CEST 2013 on sn-devel-104

commit 24fb281ea7983a42ba94b664530170e2401523f7
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri May 17 23:18:41 2013 +0200

    dsdb-repl: merge the logic from libnet_vampire_cb_apply_schema()
    
    This way libnet_vampire_cb_apply_schema() is able to use
    dsdb_repl_resolve_working_schema().
    
    Pair-Programmed-With: Matthieu Patou <mat at matws.net>
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 9af430ec0be46d0a616faee3552600219bc57097
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri May 17 23:02:03 2013 +0200

    dsdb-repl: split out dsdb_repl_resolve_working_schema
    
    This can be reused later in other places.
    
    Pair-Programmed-With: Matthieu Patou <mat at matws.net>
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit d36e9118cbf9deb01c6ee9af6790ce35bb3b936a
Author: Matthieu Patou <mat at matws.net>
Date:   Thu Apr 18 22:03:23 2013 -0700

    selftest: Improve test coverage of DRS (bug #8680)
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>
    
    Signed-off-by: Matthieu Patou <mat at matws.net>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 640c2ff57518a5711e795e6cc9f48ae29d379a01
Author: Matthieu Patou <mat at matws.net>
Date:   Sun Jan 27 15:43:07 2013 -0800

    dsdb-drs: when replicating schema object checks ask for removal of previous version if exists (bug #8680)
    
    Signed-off-by: Matthieu Patou <mat at matws.net>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit c7d4b87512eabbff5172716a755a3cd61fe5476b
Author: Matthieu Patou <mat at matws.net>
Date:   Sun Oct 7 21:46:38 2012 -0700

    libnet-vampire: add attributes and classes from the replicated schema to the bootstrap schema (bug #8680)
    
    Replicated schema might have attributes and auxilary classes  on some
    critical classes (ie.  top, user, computer ) that are not in the bootstrap
    schema. Without those new attributes and classes, bootstrap schema is
    unable to translate those critical classes in the schema constructed
    from the replicated data. Without thoses classes new schema is useless
    and can't be indexed properly.
    
    In order to overcome this problem, we put all new attributes and classes
    definitions into the bootstrap schema so that foundations classes can be
    translated.
    
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
    
    Signed-off-by: Matthieu Patou <mat at matws.net>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit fe85bc1fb9ab2f891a9fd46bd8e00325622d39cf
Author: Matthieu Patou <mat at matws.net>
Date:   Sat Jan 26 23:42:10 2013 -0800

    dsdb-schema: make deduplication of class and schema possible (bug #8680)
    
    When a class or an attribute is replicated it might already exists in
    the existing schema, so while replicating the new version of this object
    we want to get rid of the old version of the object is the current
    validating schema so that we don't end up having duplicates.
    
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
    
    Signed-off-by: Matthieu Patou <mat at matws.net>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit c524be17815e92ce9fcdd0565e76b026e483cc9d
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu May 23 08:46:31 2013 +0200

    dsdb-schema: schema_fill_possible_inferiors() should rebuild everthing
    
    commit cd7f3fd07215a7b8372b6b623faed02ae1310cb1 reverted the change
    of commit c2853f55fc603d4875bb1e50a1cbf409df0421ea.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 selftest/skip                          |    2 -
 source4/dsdb/repl/replicated_objects.c |  271 ++++++++++++++++++++++++-------
 source4/dsdb/schema/schema.h           |    5 +
 source4/dsdb/schema/schema_inferiors.c |    4 +-
 source4/dsdb/schema/schema_init.c      |   72 ++++++++-
 source4/dsdb/schema/schema_set.c       |   46 +++++-
 source4/libnet/libnet_vampire.c        |  125 +++------------
 source4/selftest/tests.py              |   51 +++---
 8 files changed, 373 insertions(+), 203 deletions(-)


Changeset truncated at 500 lines:

diff --git a/selftest/skip b/selftest/skip
index 6ea9b25..0b8468d 100644
--- a/selftest/skip
+++ b/selftest/skip
@@ -103,8 +103,6 @@ bench # don't run benchmarks in our selftest
 # ktutil might not be installed or from mit...
 # we should build a samba4ktutil and use that instead
 ^samba4.blackbox.ktpass # this test isn't portable ...
-^samba4.drs.repl_schema.python # flakey test
-^samba4.drs.delete_object.python # flakey test
 ^samba4.rpc.unixinfo # This contains a server-side getpwuid call which hangs the server when nss_winbindd is in use
 ^samba.tests.dcerpc.unix  # This contains a server-side getpwuid call which hangs the server when nss_winbindd is in use
 base.dir2 # This test spins on modern ext4, so we have to skip it
diff --git a/source4/dsdb/repl/replicated_objects.c b/source4/dsdb/repl/replicated_objects.c
index 29b494b..b0abc1a 100644
--- a/source4/dsdb/repl/replicated_objects.c
+++ b/source4/dsdb/repl/replicated_objects.c
@@ -31,35 +31,95 @@
 #include "libcli/auth/libcli_auth.h"
 #include "param/param.h"
 
-/**
- * Multi-pass working schema creation
- * Function will:
- *  - shallow copy initial schema supplied
- *  - create a working schema in multiple passes
- *    until all objects are resolved
- * Working schema is a schema with Attributes, Classes
- * and indexes, but w/o subClassOf, possibleSupperiors etc.
- * It is to be used just us cache for converting attribute values.
- */
-WERROR dsdb_repl_make_working_schema(struct ldb_context *ldb,
-				     const struct dsdb_schema *initial_schema,
-				     const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr,
-				     uint32_t object_count,
-				     const struct drsuapi_DsReplicaObjectListItemEx *first_object,
-				     const DATA_BLOB *gensec_skey,
-				     TALLOC_CTX *mem_ctx,
-				     struct dsdb_schema **_schema_out)
+static WERROR dsdb_repl_merge_working_schema(struct ldb_context *ldb,
+					     struct dsdb_schema *dest_schema,
+					     const struct dsdb_schema *ref_schema)
+{
+	const struct dsdb_class *cur_class = NULL;
+	const struct dsdb_attribute *cur_attr = NULL;
+	int ret;
+
+	for (cur_class = ref_schema->classes;
+	     cur_class;
+	     cur_class = cur_class->next)
+	{
+		const struct dsdb_class *tmp1;
+		struct dsdb_class *tmp2;
+
+		tmp1 = dsdb_class_by_governsID_id(dest_schema,
+						  cur_class->governsID_id);
+		if (tmp1 != NULL) {
+			continue;
+		}
+
+		/*
+		 * Do a shallow copy so that original next and prev are
+		 * not modified, we don't need to do a deep copy
+		 * as the rest won't be modified and this is for
+		 * a short lived object.
+		 */
+		tmp2 = talloc(dest_schema->classes, struct dsdb_class);
+		if (tmp2 == NULL) {
+			return WERR_NOMEM;
+		}
+		*tmp2 = *cur_class;
+		DLIST_ADD(dest_schema->classes, tmp2);
+	}
+
+	for (cur_attr = ref_schema->attributes;
+	     cur_attr;
+	     cur_attr = cur_attr->next)
+	{
+		const struct dsdb_attribute *tmp1;
+		struct dsdb_attribute *tmp2;
+
+		tmp1 = dsdb_attribute_by_attributeID_id(dest_schema,
+						cur_attr->attributeID_id);
+		if (tmp1 != NULL) {
+			continue;
+		}
+
+		/*
+		 * Do a shallow copy so that original next and prev are
+		 * not modified, we don't need to do a deep copy
+		 * as the rest won't be modified and this is for
+		 * a short lived object.
+		 */
+		tmp2 = talloc(dest_schema->attributes, struct dsdb_attribute);
+		if (tmp2 == NULL) {
+			return WERR_NOMEM;
+		}
+		*tmp2 = *cur_attr;
+		DLIST_ADD(dest_schema->attributes, tmp2);
+	}
+
+	ret = dsdb_setup_sorted_accessors(ldb, dest_schema);
+	if (LDB_SUCCESS != ret) {
+		DEBUG(0,("Failed to add new attribute to reference schema!\n"));
+		return WERR_INTERNAL_ERROR;
+	}
+
+	return WERR_OK;
+}
+
+WERROR dsdb_repl_resolve_working_schema(struct ldb_context *ldb,
+					TALLOC_CTX *mem_ctx,
+					struct dsdb_schema_prefixmap *pfm_remote,
+					uint32_t cycle_before_switching,
+					struct dsdb_schema *initial_schema,
+					struct dsdb_schema *resulting_schema,
+					uint32_t object_count,
+					const struct drsuapi_DsReplicaObjectListItemEx *first_object)
 {
 	struct schema_list {
 		struct schema_list *next, *prev;
 		const struct drsuapi_DsReplicaObjectListItemEx *obj;
 	};
-
-	WERROR werr;
-	struct dsdb_schema_prefixmap *pfm_remote;
 	struct schema_list *schema_list = NULL, *schema_list_item, *schema_list_next_item;
+	WERROR werr;
 	struct dsdb_schema *working_schema;
 	const struct drsuapi_DsReplicaObjectListItemEx *cur;
+	DATA_BLOB empty_key = data_blob_null;
 	int ret, pass_no;
 	uint32_t ignore_attids[] = {
 			DRSUAPI_ATTID_auxiliaryClass,
@@ -70,46 +130,56 @@ WERROR dsdb_repl_make_working_schema(struct ldb_context *ldb,
 			DRSUAPI_ATTID_INVALID
 	};
 
-	/* make a copy of the iniatial_scheam so we don't mess with it */
-	working_schema = dsdb_schema_copy_shallow(mem_ctx, ldb, initial_schema);
-	if (!working_schema) {
-		DEBUG(0,(__location__ ": schema copy failed!\n"));
-		return WERR_NOMEM;
-	}
-
-	/* we are going to need remote prefixMap for decoding */
-	werr = dsdb_schema_pfm_from_drsuapi_pfm(mapping_ctr, true,
-						mem_ctx, &pfm_remote, NULL);
-	if (!W_ERROR_IS_OK(werr)) {
-		DEBUG(0,(__location__ ": Failed to decode remote prefixMap: %s",
-			 win_errstr(werr)));
-		return werr;
-	}
-
 	/* create a list of objects yet to be converted */
 	for (cur = first_object; cur; cur = cur->next_object) {
 		schema_list_item = talloc(mem_ctx, struct schema_list);
+		if (schema_list_item == NULL) {
+			return WERR_NOMEM;
+		}
+
 		schema_list_item->obj = cur;
 		DLIST_ADD_END(schema_list, schema_list_item, struct schema_list);
 	}
 
 	/* resolve objects until all are resolved and in local schema */
 	pass_no = 1;
+	working_schema = initial_schema;
 
 	while (schema_list) {
 		uint32_t converted_obj_count = 0;
 		uint32_t failed_obj_count = 0;
-		TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
-		W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
 
-		for (schema_list_item = schema_list; schema_list_item; schema_list_item=schema_list_next_item) {
+		if (resulting_schema != working_schema) {
+			/*
+			 * If the selfmade schema is not the schema used to
+			 * translate and validate replicated object,
+			 * Which means that we are using the bootstrap schema
+			 * Then we add attributes and classes that were already
+			 * translated to the working schema, the idea is that
+			 * we might need to add new attributes and classes
+			 * to be able to translate critical replicated objects
+			 * and without that we wouldn't be able to translate them
+			 */
+			werr = dsdb_repl_merge_working_schema(ldb,
+							working_schema,
+							resulting_schema);
+			if (!W_ERROR_IS_OK(werr)) {
+				return werr;
+			}
+		}
+
+		for (schema_list_item = schema_list;
+		     schema_list_item;
+		     schema_list_item=schema_list_next_item) {
 			struct dsdb_extended_replicated_object object;
 
 			cur = schema_list_item->obj;
 
-			/* Save the next item, now we have saved out
+			/*
+			 * Save the next item, now we have saved out
 			 * the current one, so we can DLIST_REMOVE it
-			 * safely */
+			 * safely
+			 */
 			schema_list_next_item = schema_list_item->next;
 
 			/*
@@ -117,14 +187,17 @@ WERROR dsdb_repl_make_working_schema(struct ldb_context *ldb,
 			 * schema we have so far. It's ok if we fail to convert
 			 * an object. We should convert more objects on next pass.
 			 */
-			werr = dsdb_convert_object_ex(ldb, working_schema, pfm_remote,
-						      cur, gensec_skey,
+			werr = dsdb_convert_object_ex(ldb, working_schema,
+						      pfm_remote,
+						      cur, &empty_key,
 						      ignore_attids,
 						      0,
-						      tmp_ctx, &object);
+						      schema_list_item, &object);
 			if (!W_ERROR_IS_OK(werr)) {
-				DEBUG(4,("debug: Failed to convert schema object %s into ldb msg, will try during next loop\n",
-					  cur->object.identifier->dn));
+				DEBUG(4,("debug: Failed to convert schema "
+					 "object %s into ldb msg, "
+					 "will try during next loop\n",
+					 cur->object.identifier->dn));
 
 				failed_obj_count++;
 			} else {
@@ -132,41 +205,117 @@ WERROR dsdb_repl_make_working_schema(struct ldb_context *ldb,
 				 * Convert the schema from ldb_message format
 				 * (OIDs as OID strings) into schema, using
 				 * the remote prefixMap
+				 *
+				 * It's not likely, but possible to get the
+				 * same object twice and we should keep
+				 * the last instance.
 				 */
-				werr = dsdb_schema_set_el_from_ldb_msg(ldb,
-								       working_schema,
-								       object.msg);
+				werr = dsdb_schema_set_el_from_ldb_msg_dups(ldb,
+								resulting_schema,
+								object.msg,
+								true);
 				if (!W_ERROR_IS_OK(werr)) {
-					DEBUG(4,("debug: failed to convert object %s into a schema element, will try during next loop: %s\n",
+					DEBUG(4,("debug: failed to convert "
+						 "object %s into a schema element, "
+						 "will try during next loop: %s\n",
 						 ldb_dn_get_linearized(object.msg->dn),
 						 win_errstr(werr)));
 					failed_obj_count++;
 				} else {
+					DEBUG(8,("Converted object %s into a schema element\n",
+						 ldb_dn_get_linearized(object.msg->dn)));
 					DLIST_REMOVE(schema_list, schema_list_item);
-					talloc_free(schema_list_item);
+					TALLOC_FREE(schema_list_item);
 					converted_obj_count++;
 				}
 			}
 		}
-		talloc_free(tmp_ctx);
 
 		DEBUG(4,("Schema load pass %d: converted %d, %d of %d objects left to be converted.\n",
 			 pass_no, converted_obj_count, failed_obj_count, object_count));
-		pass_no++;
 
 		/* check if we converted any objects in this pass */
 		if (converted_obj_count == 0) {
-			DEBUG(0,("Can't continue Schema load: didn't manage to convert any objects: all %d remaining of %d objects failed to convert\n", failed_obj_count, object_count));
+			DEBUG(0,("Can't continue Schema load: "
+				 "didn't manage to convert any objects: "
+				 "all %d remaining of %d objects "
+				 "failed to convert\n",
+				 failed_obj_count, object_count));
 			return WERR_INTERNAL_ERROR;
 		}
 
-		/* rebuild indexes */
-		ret = dsdb_setup_sorted_accessors(ldb, working_schema);
-		if (LDB_SUCCESS != ret) {
-			DEBUG(0,("Failed to create schema-cache indexes!\n"));
-			return WERR_INTERNAL_ERROR;
+		/*
+		 * Don't try to load the schema if there is missing object
+		 * _and_ we are on the first pass as some critical objects
+		 * might be missing.
+		 */
+		if (failed_obj_count == 0 || pass_no > cycle_before_switching) {
+			/* prepare for another cycle */
+			working_schema = resulting_schema;
+
+			ret = dsdb_setup_sorted_accessors(ldb, working_schema);
+			if (LDB_SUCCESS != ret) {
+				DEBUG(0,("Failed to create schema-cache indexes!\n"));
+				return WERR_INTERNAL_ERROR;
+			}
 		}
-	};
+		pass_no++;
+	}
+
+	return WERR_OK;
+}
+
+/**
+ * Multi-pass working schema creation
+ * Function will:
+ *  - shallow copy initial schema supplied
+ *  - create a working schema in multiple passes
+ *    until all objects are resolved
+ * Working schema is a schema with Attributes, Classes
+ * and indexes, but w/o subClassOf, possibleSupperiors etc.
+ * It is to be used just us cache for converting attribute values.
+ */
+WERROR dsdb_repl_make_working_schema(struct ldb_context *ldb,
+				     const struct dsdb_schema *initial_schema,
+				     const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr,
+				     uint32_t object_count,
+				     const struct drsuapi_DsReplicaObjectListItemEx *first_object,
+				     const DATA_BLOB *gensec_skey,
+				     TALLOC_CTX *mem_ctx,
+				     struct dsdb_schema **_schema_out)
+{
+	WERROR werr;
+	struct dsdb_schema_prefixmap *pfm_remote;
+	struct dsdb_schema *working_schema;
+
+	/* make a copy of the iniatial_scheam so we don't mess with it */
+	working_schema = dsdb_schema_copy_shallow(mem_ctx, ldb, initial_schema);
+	if (!working_schema) {
+		DEBUG(0,(__location__ ": schema copy failed!\n"));
+		return WERR_NOMEM;
+	}
+
+	/* we are going to need remote prefixMap for decoding */
+	werr = dsdb_schema_pfm_from_drsuapi_pfm(mapping_ctr, true,
+						mem_ctx, &pfm_remote, NULL);
+	if (!W_ERROR_IS_OK(werr)) {
+		DEBUG(0,(__location__ ": Failed to decode remote prefixMap: %s",
+			 win_errstr(werr)));
+		return werr;
+	}
+
+	werr = dsdb_repl_resolve_working_schema(ldb, mem_ctx,
+						pfm_remote,
+						0, /* cycle_before_switching */
+						working_schema,
+						working_schema,
+						object_count,
+						first_object);
+	if (!W_ERROR_IS_OK(werr)) {
+		DEBUG(0, ("%s: dsdb_repl_resolve_working_schema() failed: %s",
+			  __location__, win_errstr(werr)));
+		return werr;
+	}
 
 	*_schema_out = working_schema;
 
diff --git a/source4/dsdb/schema/schema.h b/source4/dsdb/schema/schema.h
index 66df1c5..538b858 100644
--- a/source4/dsdb/schema/schema.h
+++ b/source4/dsdb/schema/schema.h
@@ -221,6 +221,11 @@ struct dsdb_schema {
 	struct dsdb_attribute *attributes;
 	struct dsdb_class *classes;
 
+	struct dsdb_attribute **attributes_to_remove;
+	uint32_t attributes_to_remove_size;
+	struct dsdb_class **classes_to_remove;
+	uint32_t classes_to_remove_size;
+
 	/* lists of classes sorted by various attributes, for faster
 	   access */
 	uint32_t num_classes;
diff --git a/source4/dsdb/schema/schema_inferiors.c b/source4/dsdb/schema/schema_inferiors.c
index 4d09521..56f5733 100644
--- a/source4/dsdb/schema/schema_inferiors.c
+++ b/source4/dsdb/schema/schema_inferiors.c
@@ -201,8 +201,8 @@ static void schema_fill_possible_inferiors(const struct dsdb_schema *schema,
 					   struct dsdb_class *schema_class)
 {
 	struct dsdb_class *c2;
-	const char** poss_inf = schema_class->possibleInferiors;
-	const char** sys_poss_inf = schema_class->systemPossibleInferiors;
+	const char **poss_inf = NULL;
+	const char **sys_poss_inf = NULL;
 
 	for (c2 = schema->classes; c2; c2 = c2->next) {
 		const char **superiors = schema_posssuperiors(schema, c2);
diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c
index 752d4f5..efbd38a 100644
--- a/source4/dsdb/schema/schema_init.c
+++ b/source4/dsdb/schema/schema_init.c
@@ -699,9 +699,10 @@ WERROR dsdb_attribute_from_ldb(const struct dsdb_schema *schema,
 	return WERR_OK;
 }
 
-WERROR dsdb_set_attribute_from_ldb(struct ldb_context *ldb,
-			       struct dsdb_schema *schema,
-			       struct ldb_message *msg)
+WERROR dsdb_set_attribute_from_ldb_dups(struct ldb_context *ldb,
+					struct dsdb_schema *schema,
+					struct ldb_message *msg,
+					bool checkdups)
 {
 	WERROR status;
 	struct dsdb_attribute *attr = talloc_zero(schema, struct dsdb_attribute);
@@ -729,12 +730,44 @@ WERROR dsdb_set_attribute_from_ldb(struct ldb_context *ldb,
 		return WERR_DS_ATT_SCHEMA_REQ_SYNTAX;
 	}
 
+	if (checkdups) {
+		const struct dsdb_attribute *a2;
+		struct dsdb_attribute **a;
+		uint32_t i;
+
+		a2 = dsdb_attribute_by_attributeID_id(schema,
+						      attr->attributeID_id);
+		if (a2 == NULL) {
+			goto done;
+		}
+
+		i = schema->attributes_to_remove_size;
+		a = talloc_realloc(schema, schema->attributes_to_remove,
+				   struct dsdb_attribute *, i + 1);
+		if (a == NULL) {
+			return WERR_NOMEM;
+		}
+		/* Mark the old attribute as to be removed */
+		a[i] = discard_const_p(struct dsdb_attribute, a2);
+		schema->attributes_to_remove = a;
+		schema->attributes_to_remove_size++;
+	}
+
+done:
 	DLIST_ADD(schema->attributes, attr);
 	return WERR_OK;
 }
 
-WERROR dsdb_set_class_from_ldb(struct dsdb_schema *schema,
-			   struct ldb_message *msg)
+WERROR dsdb_set_attribute_from_ldb(struct ldb_context *ldb,
+				   struct dsdb_schema *schema,
+				   struct ldb_message *msg)
+{
+	return dsdb_set_attribute_from_ldb_dups(ldb, schema, msg, false);
+}
+
+WERROR dsdb_set_class_from_ldb_dups(struct dsdb_schema *schema,
+				    struct ldb_message *msg,
+				    bool checkdups)
 {
 	WERROR status;
 	struct dsdb_class *obj = talloc_zero(schema, struct dsdb_class);
@@ -792,10 +825,39 @@ WERROR dsdb_set_class_from_ldb(struct dsdb_schema *schema,
 	GET_BOOL_LDB(msg, "isDefunct", obj, isDefunct, false);
 	GET_BOOL_LDB(msg, "systemOnly", obj, systemOnly, false);
 
+	if (checkdups) {
+		const struct dsdb_class *c2;
+		struct dsdb_class **c;
+		uint32_t i;
+
+		c2 = dsdb_class_by_governsID_id(schema, obj->governsID_id);
+		if (c2 == NULL) {
+			goto done;
+		}
+
+		i = schema->classes_to_remove_size;
+		c = talloc_realloc(schema, schema->classes_to_remove,
+				   struct dsdb_class *, i + 1);
+		if (c == NULL) {
+			return WERR_NOMEM;
+		}
+		/* Mark the old class to be removed */
+		c[i] = discard_const_p(struct dsdb_class, c2);
+		schema->classes_to_remove = c;
+		schema->classes_to_remove_size++;
+	}
+
+done:
 	DLIST_ADD(schema->classes, obj);
 	return WERR_OK;
 }
 
+WERROR dsdb_set_class_from_ldb(struct dsdb_schema *schema,
+			       struct ldb_message *msg)
+{
+	return dsdb_set_class_from_ldb_dups(schema, msg, false);
+}
+


-- 
Samba Shared Repository


More information about the samba-cvs mailing list