#include "ldb_private.h"
-/* change this if the data format ever changes */
-#define LDB_PACKING_FORMAT 0x26011967
-
-/* old packing formats */
-#define LDB_PACKING_FORMAT_NODN 0x26011966
-
/* use a portable integer format */
static void put_uint32(uint8_t *p, int ofs, unsigned int val)
{
size_t remaining;
size_t dn_len;
unsigned int i, j;
- unsigned format;
+ uint32_t format;
unsigned int nelem = 0;
size_t len;
struct ldb_val *ldb_val_single_array = NULL;
goto failed;
}
- format = pull_uint32(p, 0);
+ if (ldb_unpack_get_format(data, &format) != LDB_SUCCESS) {
+ errno = EIO;
+ goto failed;
+ }
message->num_elements = pull_uint32(p, 4);
p += 8;
return -1;
}
+int ldb_unpack_get_format(const struct ldb_val *data,
+ uint32_t *pack_format_version)
+{
+ if (data->length < 4) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ *pack_format_version = pull_uint32(data->data, 0);
+ return LDB_SUCCESS;
+}
+
/*
* Unpack a ldb message from a linear buffer in ldb_val
*
struct ldb_message *message,
unsigned int flags);
+int ldb_unpack_get_format(const struct ldb_val *data,
+ uint32_t *pack_format_version);
+
/* currently unused (was NO_DATA_ALLOC) 0x0001 */
#define LDB_UNPACK_DATA_FLAG_NO_DN 0x0002
#define LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC 0x0004
#define LDB_UNPACK_DATA_FLAG_NO_ATTRS 0x0008
#define LDB_UNPACK_DATA_FLAG_READ_LOCKED 0x0010
+/* In-use packing formats */
+#define LDB_PACKING_FORMAT 0x26011967
+
+/* Old packing formats */
+#define LDB_PACKING_FORMAT_NODN 0x26011966
+
/**
Forces a specific ldb handle to use the global event context.
ldb_kv->sequence_number = 0;
+ ldb_kv->pack_format_version = LDB_PACKING_FORMAT;
+
ldb_kv->pid = getpid();
ldb_kv->module = ldb_module_new(ldb, ldb, name, &ldb_kv_ops);
unsigned int connect_flags;
unsigned long long sequence_number;
+ uint32_t pack_format_version;
/* the low level tdb seqnum - used to avoid loading BASEINFO when
possible */
ldb_kv_cache_free(module);
return ldb_kv_cache_load(module);
}
+static int get_pack_format_version(struct ldb_val key,
+ struct ldb_val data,
+ void *private_data)
+{
+ uint32_t *v = (uint32_t *) private_data;
+ return ldb_unpack_get_format(&data, v);
+}
/*
load the cache records
const struct ldb_schema_attribute *a;
bool have_write_txn = false;
int r;
+ uint32_t pack_format_version;
+ struct ldb_val key;
ldb = ldb_module_get_ctx(module);
if (r != LDB_SUCCESS) {
goto failed;
}
+
+ key = ldb_kv_key_dn(module, baseinfo, baseinfo_dn);
+ if (!key.data) {
+ goto failed_and_unlock;
+ }
+
+ /* Read packing format from first 4 bytes of @BASEINFO record */
+ r = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key,
+ get_pack_format_version,
+ &pack_format_version);
+
+ if (r != LDB_ERR_NO_SUCH_OBJECT) {
+ if (r != LDB_SUCCESS) {
+ goto failed_and_unlock;
+ }
+
+ /* Make sure the database has the right format */
+ if (pack_format_version != ldb_kv->pack_format_version) {
+ ldb_debug(ldb, LDB_DEBUG_ERROR,
+ "Unexpected packing format. "
+ "Expected: %#010x, Got: %#010x",
+ pack_format_version,
+ ldb_kv->pack_format_version);
+ goto failed_and_unlock;
+ }
+ }
+
+ /* Now fetch the whole @BASEINFO record */
r = ldb_kv_search_dn1(module, baseinfo_dn, baseinfo, 0);
if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) {
goto failed_and_unlock;