diff options
-rw-r--r-- | lib/ldb/common/ldb_pack.c | 23 | ||||
-rw-r--r-- | lib/ldb/include/ldb_module.h | 9 | ||||
-rw-r--r-- | lib/ldb/ldb_tdb/ldb_cache.c | 45 | ||||
-rw-r--r-- | lib/ldb/ldb_tdb/ldb_tdb.c | 2 | ||||
-rw-r--r-- | lib/ldb/ldb_tdb/ldb_tdb.h | 1 |
5 files changed, 71 insertions, 9 deletions
diff --git a/lib/ldb/common/ldb_pack.c b/lib/ldb/common/ldb_pack.c index 448c577ae1b..286803f0b41 100644 --- a/lib/ldb/common/ldb_pack.c +++ b/lib/ldb/common/ldb_pack.c @@ -33,12 +33,6 @@ #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) { @@ -229,7 +223,7 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb, size_t remaining; size_t dn_len; unsigned int i, j; - unsigned format; + uint32_t format; unsigned int nelem = 0; size_t len; unsigned int found = 0; @@ -247,7 +241,10 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb, 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; if (nb_elements_in_db) { @@ -504,6 +501,16 @@ failed: 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 * diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h index c73fc37f3aa..8c47082690b 100644 --- a/lib/ldb/include/ldb_module.h +++ b/lib/ldb/include/ldb_module.h @@ -561,11 +561,20 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb, unsigned int flags, unsigned int *nb_elements_in_db); +int ldb_unpack_get_format(const struct ldb_val *data, + uint32_t *pack_format_version); + #define LDB_UNPACK_DATA_FLAG_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 +/* 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. diff --git a/lib/ldb/ldb_tdb/ldb_cache.c b/lib/ldb/ldb_tdb/ldb_cache.c index 1856fb13877..eb14a74e0a1 100644 --- a/lib/ldb/ldb_tdb/ldb_cache.c +++ b/lib/ldb/ldb_tdb/ldb_cache.c @@ -387,6 +387,13 @@ int ltdb_cache_reload(struct ldb_module *module) ltdb_cache_free(module); return ltdb_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 @@ -402,6 +409,9 @@ int ltdb_cache_load(struct ldb_module *module) const struct ldb_schema_attribute *a; bool have_write_txn = false; int r; + uint32_t pack_format_version; + struct ldb_val key_ldb; + struct TDB_DATA key; ldb = ldb_module_get_ctx(module); @@ -425,7 +435,40 @@ int ltdb_cache_load(struct ldb_module *module) if (r != LDB_SUCCESS) { goto failed; } - r= ltdb_search_dn1(module, baseinfo_dn, baseinfo, 0); + + key = ltdb_key_dn(module, baseinfo, baseinfo_dn); + if (!key.dptr) { + goto failed_and_unlock; + } + + key_ldb = (struct ldb_val){ + .data = key.dptr, + .length = key.dsize + }; + + /* Read packing format from first 4 bytes of @BASEINFO record */ + r = ltdb->kv_ops->fetch_and_parse(ltdb, key_ldb, + 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 != ltdb->pack_format_version) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Unexpected packing format. " + "Expected: %#010x, Got: %#010x", + pack_format_version, + ltdb->pack_format_version); + goto failed_and_unlock; + } + } + + /* Now fetch the whole @BASEINFO record */ + r = ltdb_search_dn1(module, baseinfo_dn, baseinfo, 0); if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) { goto failed_and_unlock; } diff --git a/lib/ldb/ldb_tdb/ldb_tdb.c b/lib/ldb/ldb_tdb/ldb_tdb.c index 337e7d2ee22..e3f552805c2 100644 --- a/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/lib/ldb/ldb_tdb/ldb_tdb.c @@ -2272,6 +2272,8 @@ int init_store(struct ltdb_private *ltdb, ltdb->sequence_number = 0; + ltdb->pack_format_version = LDB_PACKING_FORMAT; + ltdb->pid = getpid(); ltdb->module = ldb_module_new(ldb, ldb, name, <db_ops); diff --git a/lib/ldb/ldb_tdb/ldb_tdb.h b/lib/ldb/ldb_tdb/ldb_tdb.h index 2896c6376b8..6c50e2856dc 100644 --- a/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/lib/ldb/ldb_tdb/ldb_tdb.h @@ -42,6 +42,7 @@ struct ltdb_private { 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 */ |