summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/reg_db.h1
-rw-r--r--source3/registry/reg_backend_db.c112
2 files changed, 107 insertions, 6 deletions
diff --git a/source3/include/reg_db.h b/source3/include/reg_db.h
index 5cafa0a5fb..774093d2b3 100644
--- a/source3/include/reg_db.h
+++ b/source3/include/reg_db.h
@@ -23,6 +23,7 @@
#define REG_TDB_FLAGS TDB_SEQNUM
#define REGVER_V1 1 /* first db version with write support */
+#define REGVER_V2 2 /* version 2 with normalized keys */
#define REG_VALUE_PREFIX "SAMBA_REGVAL"
#define REG_SECDESC_PREFIX "SAMBA_SECDESC"
diff --git a/source3/registry/reg_backend_db.c b/source3/registry/reg_backend_db.c
index 4e7f8554ea..9e6dbcbff3 100644
--- a/source3/registry/reg_backend_db.c
+++ b/source3/registry/reg_backend_db.c
@@ -21,6 +21,7 @@
/* Implementation of internal registry database functions. */
#include "includes.h"
+
#include "registry.h"
#include "reg_db.h"
#include "reg_util_internal.h"
@@ -387,10 +388,77 @@ done:
return werr;
}
+static int regdb_normalize_keynames_fn(struct db_record *rec,
+ void *private_data)
+{
+ TALLOC_CTX *mem_ctx = talloc_tos();
+ const char *keyname;
+ NTSTATUS status;
+
+ if (rec->key.dptr == NULL || rec->key.dsize == 0) {
+ return 0;
+ }
+
+ keyname = strchr((const char *) rec->key.dptr, '/');
+ if (keyname) {
+ struct db_record new_rec;
+
+ keyname = talloc_string_sub(mem_ctx,
+ (const char *) rec->key.dptr,
+ "/",
+ "\\");
+
+ DEBUG(2, ("regdb_normalize_keynames_fn: Convert %s to %s\n",
+ (const char *) rec->key.dptr,
+ keyname));
+
+ new_rec.value.dptr = rec->value.dptr;
+ new_rec.value.dsize = rec->value.dsize;
+ new_rec.key.dptr = (unsigned char *) keyname;
+ new_rec.key.dsize = strlen(keyname);
+ new_rec.private_data = rec->private_data;
+
+ /* Delete the original record and store the normalized key */
+ status = rec->delete_rec(rec);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("regdb_normalize_keynames_fn: "
+ "tdb_delete for [%s] failed!\n",
+ rec->key.dptr));
+ return 1;
+ }
+
+ status = rec->store(&new_rec, new_rec.value, TDB_REPLACE);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("regdb_normalize_keynames_fn: "
+ "failed to store new record for [%s]!\n",
+ keyname));
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static WERROR regdb_upgrade_to_version_2(void)
+{
+ TALLOC_CTX *mem_ctx;
+ int rc;
+
+ mem_ctx = talloc_stackframe();
+ if (mem_ctx == NULL) {
+ return WERR_NOMEM;
+ }
+
+ rc = regdb->traverse(regdb, regdb_normalize_keynames_fn, mem_ctx);
+
+ talloc_destroy(mem_ctx);
+ return (rc == -1 ? WERR_REG_IO_FAILURE : WERR_OK);
+}
+
/***********************************************************************
Open the registry database
***********************************************************************/
-
+
WERROR regdb_init(void)
{
const char *vstring = "INFO/version";
@@ -422,13 +490,12 @@ WERROR regdb_init(void)
regdb_refcount = 1;
vers_id = dbwrap_fetch_int32(regdb, vstring);
-
- if ( vers_id != REGVER_V1 ) {
+ if (vers_id == -1) {
NTSTATUS status;
- /* any upgrade code here if needed */
+
DEBUG(10, ("regdb_init: got %s = %d != %d\n", vstring,
- vers_id, REGVER_V1));
- status = dbwrap_trans_store_int32(regdb, vstring, REGVER_V1);
+ vers_id, REGVER_V2));
+ status = dbwrap_trans_store_int32(regdb, vstring, REGVER_V2);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("regdb_init: error storing %s = %d: %s\n",
vstring, REGVER_V1, nt_errstr(status)));
@@ -437,6 +504,39 @@ WERROR regdb_init(void)
DEBUG(10, ("regdb_init: stored %s = %d\n",
vstring, REGVER_V1));
}
+ vers_id = REGVER_V2;
+ }
+
+ if (vers_id != REGVER_V2) {
+ NTSTATUS status;
+
+ if (vers_id == REGVER_V1) {
+ if (regdb->transaction_start(regdb) != 0) {
+ return WERR_REG_IO_FAILURE;
+ }
+
+ werr = regdb_upgrade_to_version_2();
+ if (!W_ERROR_IS_OK(werr)) {
+ regdb->transaction_cancel(regdb);
+ return werr;
+ }
+
+ status = dbwrap_trans_store_int32(regdb, vstring, REGVER_V2);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("regdb_init: error storing %s = %d: %s\n",
+ vstring, REGVER_V1, nt_errstr(status)));
+ regdb->transaction_cancel(regdb);
+ return ntstatus_to_werror(status);
+ } else {
+ DEBUG(10, ("regdb_init: stored %s = %d\n",
+ vstring, REGVER_V1));
+ }
+ if (regdb->transaction_commit(regdb) != 0) {
+ return WERR_REG_IO_FAILURE;
+ }
+
+ vers_id = REGVER_V2;
+ }
}
return WERR_OK;