s4:schema Add some error checking to the schema load
[ira/wip.git] / source4 / dsdb / schema / schema_set.c
index 9f23088c977819c80585e66ad7a41dba6faed72b..9f22b3233407a4b37651ee95e737ac5d97994709 100644 (file)
@@ -21,7 +21,7 @@
 */
 
 #include "includes.h"
-#include "dlinklist.h"
+#include "lib/util/dlinklist.h"
 #include "dsdb/samdb/samdb.h"
 #include "lib/ldb/include/ldb_module.h"
 #include "param/param.h"
@@ -57,7 +57,6 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem
        ldb_schema_attribute_set_override_handler(ldb, dsdb_attribute_handler_override, schema);
 
        if (!write_attributes) {
-               talloc_free(mem_ctx);
                return ret;
        }
 
@@ -87,6 +86,11 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem
                goto op_error;
        }
 
+       ret = ldb_msg_add_string(msg_idx, "@IDXONE", "1");
+       if (ret != LDB_SUCCESS) {
+               goto op_error;
+       }
+
        for (attr = schema->attributes; attr; attr = attr->next) {
                const char *syntax = attr->syntax->ldb_syntax;
                
@@ -131,11 +135,11 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem
                
                mod_msg = ldb_msg_diff(ldb, res->msgs[0], msg);
                if (mod_msg->num_elements > 0) {
-                       ret = ldb_modify(ldb, mod_msg);
+                       ret = samdb_replace(ldb, mem_ctx, mod_msg);
                }
        }
 
-       if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
+       if (ret == LDB_ERR_OPERATIONS_ERROR || ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
                /* We might be on a read-only DB */
                ret = LDB_SUCCESS;
        }
@@ -150,7 +154,7 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem
        if (ret == LDB_ERR_NO_SUCH_OBJECT) {
                ret = ldb_add(ldb, msg_idx);
        } else if (ret != LDB_SUCCESS) {
-       } else if (res->count != 1) {
+       } else if (res_idx->count != 1) {
                ret = ldb_add(ldb, msg_idx);
        } else {
                ret = LDB_SUCCESS;
@@ -159,10 +163,10 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem
 
                mod_msg = ldb_msg_diff(ldb, res_idx->msgs[0], msg_idx);
                if (mod_msg->num_elements > 0) {
-                       ret = ldb_modify(ldb, mod_msg);
+                       ret = samdb_replace(ldb, mem_ctx, mod_msg);
                }
        }
-       if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
+       if (ret == LDB_ERR_OPERATIONS_ERROR || ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
                /* We might be on a read-only DB */
                ret = LDB_SUCCESS;
        }
@@ -310,6 +314,23 @@ failed:
        return LDB_ERR_OPERATIONS_ERROR;
 }
 
+int dsdb_setup_schema_inversion(struct ldb_context *ldb, struct dsdb_schema *schema)
+{
+       /* Walk the list of schema classes */
+
+       /*  For each subClassOf, add us to subclasses of the parent */
+
+       /* collect these subclasses into a recursive list of total subclasses, preserving order */
+
+       /* For each subclass under 'top', write the index from it's
+        * order as an integer in the dsdb_class (for sorting
+        * objectClass lists efficiently) */
+
+       /* Walk the list of scheam classes */
+       
+       /*  Create a 'total possible superiors' on each class */
+       return LDB_SUCCESS;
+}
 
 /**
  * Attach the schema to an opaque pointer on the ldb, so ldb modules
@@ -325,6 +346,11 @@ int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema)
                return ret;
        }
 
+       ret = schema_fill_constructed(schema);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+
        ret = ldb_set_opaque(ldb, "dsdb_schema", schema);
        if (ret != LDB_SUCCESS) {
                return ret;
@@ -347,34 +373,43 @@ int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema)
 static struct dsdb_schema *global_schema;
 
 /**
- * Make this ldb use the 'global' schema, setup to avoid having multiple copies in this process
+ * Make this ldb use a specified schema, already fully calculated and belonging to another ldb
  */
-int dsdb_set_global_schema(struct ldb_context *ldb)
+int dsdb_reference_schema(struct ldb_context *ldb, struct dsdb_schema *schema,
+                         bool write_attributes)
 {
        int ret;
-       if (!global_schema) {
-               return LDB_SUCCESS;
-       }
-
-       ret = ldb_set_opaque(ldb, "dsdb_schema", global_schema);
+       ret = ldb_set_opaque(ldb, "dsdb_schema", schema);
        if (ret != LDB_SUCCESS) {
                return ret;
        }
 
        /* Set the new attributes based on the new schema */
-       ret = dsdb_schema_set_attributes(ldb, global_schema, false);
+       ret = dsdb_schema_set_attributes(ldb, schema, write_attributes);
        if (ret != LDB_SUCCESS) {
                return ret;
        }
 
-       /* Keep a reference to this schema, just incase the global copy is replaced */
-       if (talloc_reference(ldb, global_schema) == NULL) {
+       /* Keep a reference to this schema, just incase the original copy is replaced */
+       if (talloc_reference(ldb, schema) == NULL) {
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
        return LDB_SUCCESS;
 }
 
+/**
+ * Make this ldb use the 'global' schema, setup to avoid having multiple copies in this process
+ */
+int dsdb_set_global_schema(struct ldb_context *ldb)
+{
+       if (!global_schema) {
+               return LDB_SUCCESS;
+       }
+
+       return dsdb_reference_schema(ldb, global_schema, false /* Don't write attributes, it's expensive */);
+}
+
 /**
  * Find the schema object for this ldb
  */
@@ -410,10 +445,12 @@ void dsdb_make_schema_global(struct ldb_context *ldb)
        }
 
        if (global_schema) {
-               talloc_unlink(talloc_autofree_context(), schema);
+               talloc_unlink(talloc_autofree_context(), global_schema);
        }
 
-       talloc_steal(talloc_autofree_context(), schema);
+       /* we want the schema to be around permanently */
+       talloc_reparent(talloc_parent(schema), talloc_autofree_context(), schema);
+
        global_schema = schema;
 
        dsdb_set_global_schema(ldb);
@@ -426,7 +463,7 @@ void dsdb_make_schema_global(struct ldb_context *ldb)
  * schema itself to the directory.
  */
 
-WERROR dsdb_attach_schema_from_ldif(struct ldb_context *ldb, const char *pf, const char *df)
+WERROR dsdb_set_schema_from_ldif(struct ldb_context *ldb, const char *pf, const char *df)
 {
        struct ldb_ldif *ldif;
        struct ldb_message *msg;
@@ -521,7 +558,7 @@ WERROR dsdb_attach_schema_from_ldif(struct ldb_context *ldb, const char *pf, con
                                goto failed;
                        }
 
-                       DLIST_ADD_END(schema->attributes, sa, struct dsdb_attribute *);
+                       DLIST_ADD(schema->attributes, sa);
                } else if (is_sc) {
                        struct dsdb_class *sc;
 
@@ -535,7 +572,7 @@ WERROR dsdb_attach_schema_from_ldif(struct ldb_context *ldb, const char *pf, con
                                goto failed;
                        }
 
-                       DLIST_ADD_END(schema->classes, sc, struct dsdb_class *);
+                       DLIST_ADD(schema->classes, sc);
                }
        }