X-Git-Url: http://git.samba.org/samba.git/?p=jra%2Fsamba%2F.git;a=blobdiff_plain;f=source3%2Fregistry%2Freg_backend_db.c;h=6f4c614b9a5a003154092cce685668c254b4d912;hp=7513b3b2633d1ac2b5d84da0fb6b64b53fcc07c1;hb=0f41961e4ffaa602a5b19a1e0899bffa491c886f;hpb=4394c2dafb65c20a0cefa168b1b7c39abb2b493b diff --git a/source3/registry/reg_backend_db.c b/source3/registry/reg_backend_db.c index 7513b3b2633..6f4c614b9a5 100644 --- a/source3/registry/reg_backend_db.c +++ b/source3/registry/reg_backend_db.c @@ -28,6 +28,7 @@ static struct db_context *regdb = NULL; static int regdb_refcount; static bool regdb_key_exists(const char *key); +static bool regdb_key_is_base_key(const char *key); /* List the deepest path into the registry. All part components will be created.*/ @@ -389,14 +390,14 @@ WERROR regdb_init(void) return WERR_OK; } - regdb = db_open_trans(NULL, state_path("registry.tdb"), 0, + regdb = db_open(NULL, state_path("registry.tdb"), 0, REG_TDB_FLAGS, O_RDWR, 0600); if (!regdb) { - regdb = db_open_trans(NULL, state_path("registry.tdb"), 0, + regdb = db_open(NULL, state_path("registry.tdb"), 0, REG_TDB_FLAGS, O_RDWR|O_CREAT, 0600); if (!regdb) { werr = ntstatus_to_werror(map_nt_error_from_unix(errno)); - DEBUG(0,("regdb_init: Failed to open registry %s (%s)\n", + DEBUG(1,("regdb_init: Failed to open registry %s (%s)\n", state_path("registry.tdb"), strerror(errno) )); return werr; } @@ -415,7 +416,7 @@ WERROR regdb_init(void) vers_id, REGVER_V1)); status = dbwrap_trans_store_int32(regdb, vstring, REGVER_V1); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("regdb_init: error storing %s = %d: %s\n", + DEBUG(1, ("regdb_init: error storing %s = %d: %s\n", vstring, REGVER_V1, nt_errstr(status))); return ntstatus_to_werror(status); } else { @@ -443,7 +444,7 @@ WERROR regdb_open( void ) become_root(); - regdb = db_open_trans(NULL, state_path("registry.tdb"), 0, + regdb = db_open(NULL, state_path("registry.tdb"), 0, REG_TDB_FLAGS, O_RDWR, 0600); if ( !regdb ) { result = ntstatus_to_werror( map_nt_error_from_unix( errno ) ); @@ -582,6 +583,10 @@ bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr) TALLOC_CTX *ctx = talloc_stackframe(); NTSTATUS status; + if (!regdb_key_is_base_key(key) && !regdb_key_exists(key)) { + goto fail; + } + /* * fetch a list of the old subkeys so we can determine if anything has * changed @@ -631,15 +636,28 @@ bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr) regdb_fetch_keys(key, old_subkeys); - /* store the subkey list for the parent */ - - if (!regdb_store_keys_internal(key, ctr) ) { - DEBUG(0,("regdb_store_keys: Failed to store new subkey list " - "for parent [%s]\n", key)); - goto cancel; - } + /* + * Make the store operation as safe as possible without transactions: + * + * (1) For each subkey removed from ctr compared with old_subkeys: + * + * (a) First delete the value db entry. + * + * (b) Next delete the secdesc db record. + * + * (c) Then delete the subkey list entry. + * + * (2) Now write the list of subkeys of the parent key, + * deleting removed entries and adding new ones. + * + * (3) Finally create the subkey list entries for the added keys. + * + * This way if we crash half-way in between deleting the subkeys + * and storing the parent's list of subkeys, no old data can pop up + * out of the blue when re-adding keys later on. + */ - /* now delete removed keys */ + /* (1) delete removed keys' lists (values/secdesc/subkeys) */ num_subkeys = regsubkey_ctr_numkeys(old_subkeys); for (i=0; i [%s]\n", key ? key : "NULL")); if (!regdb_key_exists(key)) { - goto fail; + goto done; } ctr->seqnum = regdb_get_seqnum(); value = regdb_fetch_key_internal(frame, key); - buf = value.dptr; - buflen = value.dsize; - - if ( !buf ) { - DEBUG(5,("regdb_fetch_keys: tdb lookup failed to locate key [%s]\n", key)); - goto fail; + if (value.dptr == NULL) { + DEBUG(10, ("regdb_fetch_keys: no subkeys found for key [%s]\n", + key)); + ret = 0; + goto done; } + buf = value.dptr; + buflen = value.dsize; len = tdb_unpack( buf, buflen, "d", &num_items); for (i=0; i