}
return a->ldb_schema_attribute;
}
-
-static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schema *schema, bool write_attributes)
+/*
+ * Set the attribute handlers onto the LDB, and potentially write the
+ * @INDEXLIST, @IDXONE and @ATTRIBUTES records. The @ATTRIBUTES records
+ * are required so we can operate on a schema-less database (say the
+ * backend during emergency fixes) and during the schema load.
+ */
+static int dsdb_schema_set_indices_and_attributes(struct ldb_context *ldb, struct dsdb_schema *schema, bool write_indices_and_attributes)
{
int ret = LDB_SUCCESS;
struct ldb_result *res;
/* setup our own attribute name to schema handler */
ldb_schema_attribute_set_override_handler(ldb, dsdb_attribute_handler_override, schema);
- if (!write_attributes) {
+ if (!write_indices_and_attributes) {
return ret;
}
unsigned int num_int_id;
int ret;
+ for (i=0; i < schema->classes_to_remove_size; i++) {
+ DLIST_REMOVE(schema->classes, schema->classes_to_remove[i]);
+ TALLOC_FREE(schema->classes_to_remove[i]);
+ }
+ for (i=0; i < schema->attributes_to_remove_size; i++) {
+ DLIST_REMOVE(schema->attributes, schema->attributes_to_remove[i]);
+ TALLOC_FREE(schema->attributes_to_remove[i]);
+ }
+
+ TALLOC_FREE(schema->attributes_to_remove);
+ TALLOC_FREE(schema->classes_to_remove);
+
/* free all caches */
dsdb_sorted_accessors_free(schema);
}
/* Set the new attributes based on the new schema */
- ret = dsdb_schema_set_attributes(ldb, schema, true);
+ ret = dsdb_schema_set_indices_and_attributes(ldb, schema, true);
if (ret != LDB_SUCCESS) {
return ret;
}
/**
* Make this ldb use a specified schema, already fully calculated and belonging to another ldb
+ *
+ * The write_indices_and_attributes controls writing of the @ records
+ * because we cannot write to a database that does not yet exist on
+ * disk.
*/
int dsdb_reference_schema(struct ldb_context *ldb, struct dsdb_schema *schema,
- bool write_attributes)
+ bool write_indices_and_attributes)
{
int ret;
struct dsdb_schema *old_schema;
return ret;
}
- ret = dsdb_schema_set_attributes(ldb, schema, write_attributes);
+ ret = dsdb_schema_set_indices_and_attributes(ldb, schema, write_indices_and_attributes);
if (ret != LDB_SUCCESS) {
return ret;
}
}
/* Set the new attributes based on the new schema */
- ret = dsdb_schema_set_attributes(ldb, global_schema, false /* Don't write attributes, it's expensive */);
+ ret = dsdb_schema_set_indices_and_attributes(ldb, global_schema, false /* Don't write indices and attributes, it's expensive */);
if (ret == LDB_SUCCESS) {
/* Keep a reference to this schema, just in case the original copy is replaced */
if (talloc_reference(ldb, global_schema) == NULL) {
}
/**
- * Add an element to the schema (attribute or class) from an LDB message
+ * @brief Add a new element to the schema and checks if it's a duplicate
+ *
+ * This function will add a new element to the schema and checks for existing
+ * duplicates.
+ *
+ * @param[in] ldb A pointer to an LDB context
+ *
+ * @param[in] schema A pointer to the dsdb_schema where the element
+ * will be added.
+ *
+ * @param[in] msg The ldb_message object representing the element
+ * to add.
+ *
+ * @param[in] checkdups A boolean to indicate if checks for duplicates
+ * should be done.
+ *
+ * @return A WERROR code
*/
-WERROR dsdb_schema_set_el_from_ldb_msg(struct ldb_context *ldb, struct dsdb_schema *schema,
- struct ldb_message *msg)
+WERROR dsdb_schema_set_el_from_ldb_msg_dups(struct ldb_context *ldb, struct dsdb_schema *schema,
+ struct ldb_message *msg, bool checkdups)
{
+ const char* tstring;
+ time_t ts;
+ tstring = ldb_msg_find_attr_as_string(msg, "whenChanged", NULL);
+ /* keep a trace of the ts of the most recently changed object */
+ if (tstring) {
+ ts = ldb_string_to_time(tstring);
+ if (ts > schema->ts_last_change) {
+ schema->ts_last_change = ts;
+ }
+ }
if (samdb_find_attribute(ldb, msg,
"objectclass", "attributeSchema") != NULL) {
- return dsdb_attribute_from_ldb(ldb, schema, msg);
+
+ return dsdb_set_attribute_from_ldb_dups(ldb, schema, msg, checkdups);
} else if (samdb_find_attribute(ldb, msg,
"objectclass", "classSchema") != NULL) {
- return dsdb_class_from_ldb(schema, msg);
+ return dsdb_set_class_from_ldb_dups(schema, msg, checkdups);
}
-
/* Don't fail on things not classes or attributes */
return WERR_OK;
}
+WERROR dsdb_schema_set_el_from_ldb_msg(struct ldb_context *ldb,
+ struct dsdb_schema *schema,
+ struct ldb_message *msg)
+{
+ return dsdb_schema_set_el_from_ldb_msg_dups(ldb, schema, msg, false);
+}
+
/**
* Rather than read a schema from the LDB itself, read it from an ldif
* file. This allows schema to be loaded and used while adding the
goto nomem;
}
schema->fsmo.we_are_master = true;
+ schema->fsmo.update_allowed = true;
schema->fsmo.master_dn = ldb_dn_new(schema, ldb, "@PROVISION_SCHEMA_MASTER");
if (!schema->fsmo.master_dn) {
goto nomem;
goto failed;
}
+ schema->ts_last_change = 0;
/* load the attribute and class definitions out of df */
while ((ldif = ldb_ldif_read_string(ldb, &df))) {
talloc_steal(mem_ctx, ldif);