dsdb-schema: make deduplication of class and schema possible (bug #8680)
[obnox/samba/samba-obnox.git] / source4 / dsdb / schema / schema_init.c
index 752d4f57dd1c7dde8bb218d47c59c42e087955ea..efbd38a4ba39540c994f52152d75b4a58d6e6c3f 100644 (file)
@@ -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);
+}
+
 #define dsdb_oom(error_string, mem_ctx) *error_string = talloc_asprintf(mem_ctx, "dsdb out of memory at %s:%d\n", __FILE__, __LINE__)
 
 /*