+/*
+ * Open sam.ldb.d/metadata.tdb.
+ */
+static int schema_metadata_open(struct ldb_module *module)
+{
+ struct schema_load_private_data *data = talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data);
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ TALLOC_CTX *tmp_ctx;
+ struct loadparm_context *lp_ctx;
+ const char *sam_name;
+ char *filename;
+ int open_flags;
+ struct stat statbuf;
+
+ if (!data) {
+ return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR,
+ "schema_load: metadata not initialized");
+ }
+ data->metadata = NULL;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ return ldb_module_oom(module);
+ }
+
+ sam_name = (const char *)ldb_get_opaque(ldb, "ldb_url");
+ if (strncmp("tdb://", sam_name, 6) == 0) {
+ sam_name += 6;
+ }
+ if (!sam_name) {
+ talloc_free(tmp_ctx);
+ return ldb_operr(ldb);
+ }
+ filename = talloc_asprintf(tmp_ctx, "%s.d/metadata.tdb", sam_name);
+ if (!filename) {
+ talloc_free(tmp_ctx);
+ return ldb_oom(ldb);
+ }
+
+ open_flags = O_RDWR;
+ if (stat(filename, &statbuf) != 0) {
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ lp_ctx = talloc_get_type_abort(ldb_get_opaque(ldb, "loadparm"),
+ struct loadparm_context);
+
+ data->metadata = tdb_wrap_open(data, filename, 10,
+ TDB_DEFAULT, open_flags, 0660,
+ lp_ctx);
+ if (data->metadata == NULL) {
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ talloc_free(tmp_ctx);
+ return LDB_SUCCESS;
+}
+
+static int schema_metadata_get_uint64(struct ldb_module *module,
+ const char *key, uint64_t *value,
+ uint64_t default_value)
+{
+ struct schema_load_private_data *data = talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data);
+ struct tdb_context *tdb;
+ TDB_DATA tdb_key, tdb_data;
+ char *value_str;
+ TALLOC_CTX *tmp_ctx;
+
+ if (!data || !data->metadata) {
+ return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR,
+ "schema: metadata tdb not initialized");
+ }
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ return ldb_module_oom(module);
+ }
+
+ tdb = data->metadata->tdb;
+
+ tdb_key.dptr = (uint8_t *)discard_const_p(char, key);
+ tdb_key.dsize = strlen(key);
+
+ tdb_data = tdb_fetch_compat(tdb, tdb_key);
+ if (!tdb_data.dptr) {
+ if (tdb_error(tdb) == TDB_ERR_NOEXIST) {
+ *value = default_value;
+ return LDB_SUCCESS;
+ } else {
+ return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR,
+ tdb_errorstr_compat(tdb));
+ }
+ }
+
+ value_str = talloc_strndup(tmp_ctx, (char *)tdb_data.dptr, tdb_data.dsize);
+ if (value_str == NULL) {
+ SAFE_FREE(tdb_data.dptr);
+ talloc_free(tmp_ctx);
+ return ldb_module_oom(module);
+ }
+
+ *value = strtoull(value_str, NULL, 10);
+
+ SAFE_FREE(tdb_data.dptr);
+ talloc_free(tmp_ctx);
+
+ return LDB_SUCCESS;
+}
+