[SCM] Samba Shared Repository - branch v3-6-test updated

Karolin Seeger kseeger at samba.org
Thu May 10 05:55:46 MDT 2012


The branch, v3-6-test has been updated
       via  6eae984 s3:auth/server_info: the primary rid should be in the groups rid array (bug #8798)
       via  32cf92f s3:registry: return error when Key does not exist in regdb_fetch_values_internal() (cherry picked from commit 8a723ddfc1645e52830fb5f47a34f032f9c38931)
       via  2b29bfc s3:registry: replace call to reg_openkey() in reg_createkey() by accesscheck. (cherry picked from commit c1cc15c33be8926ffef173b514d0fb260292d9a3)
       via  404c9ce s3:registry: remove a superfluous fill_subkey_cache() in reg_createkey()
       via  98c9642 s3:registry: use fill_subkey_cache to check exsistence in regkey_open_onelevel().
       via  0150336 s3:registry: let fill_subkey_cache return WERR_BADFILE when the subkey list could not be loaded
       via  086c1e9 s3:registry: convert reg_openkey() to use talloc instead of SMB_STRDUP etc (cherry picked from commit 42dd99d85ca04c10691f78d6340c6b702ade974b)
       via  7a36a22 s3:registry untangle an assignment from the check in regkey_open_onelevel() (cherry picked from commit 12b7b4f0a7d8607dc206c32a3822d5678c14d43b)
       via  e4fc313 s3:registry: untangle assignment from check in regkey_open_onelevel() (cherry picked from commit 52d3c5c14898b5f2514d1512289370eb6f6fd369)
       via  521c7ea s3:registry: fix seqnum race in regdb_fetch_keys_internal
       via  2517f43 s3:registry avoid pruning the sequencenumber while flushing the regsubkey_ctr
       via  11413a9 s3:registry: fix seqnum race in fetch_values_internal
       via  96f08f6 s3:registry: update the seqnum in the subkey cache at the end of regval_store_keys
       via  f4d800d s3:registry:db: update the value container seqnum after storing/deleting to prevent next read from going to disk if possible
       via  8980168 s3:registry: wrap reg_deletekey() into a transaction
       via  14d9621 s3:registry: wrap reg_createkey() in a transaction
       via  95ba1aa s3:registry: untangle assignments from checks in reg_createkey() (cherry picked from commit 4ac9625fe42ded0717aafdf6eec4c1b2217c3c68)
       via  d67b181 s3:registry: wrap reg_deletevalue() in a transaction
       via  866faf7 s3:registry: untangle assignment from check in reg_deletevalue() (cherry picked from commit 585746338bda22ff8337d41c8cc50533c5facf56)
       via  e2d0876 s3:registry: fix race in reg_setvalue that could lead to data corruption
       via  a5025e2 s3:registry: untangle assignment from check and add a debugmessage in reg_setvalue() (cherry picked from commit a81d399456eb86ffb60bed8704cd8c7864b742db)
       via  488b946 s3:registry: don't leak the old contents when updating the value cache (cherry picked from commit 0bf44361caace3a4974dafa305033fb926d0f6d6)
       via  b6aaf6b s3:registry: fix debug message in regdb_store_values_internal() (cherry picked from commit c46403f74116708f2f8b1d531f5881bb9d7f2a84)
       via  bdbfde8 s3:registry: improve log message in regdb_unpack_values() (cherry picked from commit ae441d97cdbe8e35cd342ba979bacc3757c06cb7)
       via  6413d23 s3:registry: fix a debug message typo (cherry picked from commit 9f82e1175f28bdc1c09e7bd795699b29049a77e3)
       via  18d3d3f s3:registry: add a new function regval_ctr_value_byname()
       via  b712448 s3:registry: rename regval_ctr_key_exists() to regval_ctr_value_exists() (cherry picked from commit 60cdf3c8b5bbda9434f0d8a05fc581ab41b42d5c)
       via  4cfbe63 s4:torture:rpc:spoolss: also initialize driverName before checking it in test_PrinterData_DsSpooler() (cherry picked from commit 46428f96a4089925355b4eeebebb8d7f27e2ec0b)
       via  b356e42 s3:registry:reg_api: fix reg_queryvalue to not fail when values are modified while it runs (cherry picked from commit 5d26120b5ab180212d570dd256e8989e0c80224d)
       via  f2ab037 s3:registry: implement values_need_update and subkeys_need_update in the smbconf backend
      from  da5c342 Fix bug 8920, null dereference

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-6-test


- Log -----------------------------------------------------------------
commit 6eae984cfc3ceb0661f7993c9274e048c6eda6e0
Author: Alejandro Escanero Blanco <aescanero at gmail.com>
Date:   Wed May 9 11:35:51 2012 +0200

    s3:auth/server_info: the primary rid should be in the groups rid array (bug #8798)
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    
    Autobuild-User: Stefan Metzmacher <metze at samba.org>
    Autobuild-Date: Wed May  9 19:36:01 CEST 2012 on sn-devel-104
    (cherry picked from commit 6132cf2a5cd77c79546a2d6cc3fbf3c93f54183b)

commit 32cf92f2388c0fc26e24c3174fab43089bffba03
Author: Michael Adam <obnox at samba.org>
Date:   Fri May 4 18:01:00 2012 +0200

    s3:registry: return error when Key does not exist in regdb_fetch_values_internal() (cherry picked from commit 8a723ddfc1645e52830fb5f47a34f032f9c38931)

commit 2b29bfcf593aa8a80e1e4cab1d344f5a70036c6e
Author: Michael Adam <obnox at samba.org>
Date:   Mon Apr 23 16:44:15 2012 +0200

    s3:registry: replace call to reg_openkey() in reg_createkey() by accesscheck. (cherry picked from commit c1cc15c33be8926ffef173b514d0fb260292d9a3)

commit 404c9cec7e538a8301ad1a57f04ec4f4f05e80e1
Author: Michael Adam <obnox at samba.org>
Date:   Mon Apr 23 16:13:29 2012 +0200

    s3:registry: remove a superfluous fill_subkey_cache() in reg_createkey()
    
    Pair-Programmed-With: Gregor Beck <gbeck at sernet.de>
    (cherry picked from commit 03ae7117df2ae42213a3ef9a5ea3adad2bf264e0)

commit 98c96425420485ae1609a16a88d8af4310fa85d6
Author: Michael Adam <obnox at samba.org>
Date:   Mon Apr 23 16:07:21 2012 +0200

    s3:registry: use fill_subkey_cache to check exsistence in regkey_open_onelevel().
    
    Pair-Programmed-With: Gregor Beck <gbeck at sernet.de>
    (cherry picked from commit af9d70fbce541c382a5fc54b1cc1af9b0b60a692)

commit 015033657a9b4bf0de043cbc00e1513616c2d714
Author: Michael Adam <obnox at samba.org>
Date:   Mon Apr 23 16:05:33 2012 +0200

    s3:registry: let fill_subkey_cache return WERR_BADFILE when the subkey list could not be loaded
    
    WERR_NO_MORE_ITEMS seems inappropriate.
    
    Pair-Programmed-With: Gregor Beck <gbeck at sernet.de>
    (cherry picked from commit 4b3dca83bf0da405524a64ca19771fd747ebe267)

commit 086c1e96b412688691639e89eb6cb947710eedb0
Author: Michael Adam <obnox at samba.org>
Date:   Mon Apr 23 15:47:33 2012 +0200

    s3:registry: convert reg_openkey() to use talloc instead of SMB_STRDUP etc (cherry picked from commit 42dd99d85ca04c10691f78d6340c6b702ade974b)

commit 7a36a22f00d8b5024df04932eb60ec9ffa5c2932
Author: Michael Adam <obnox at samba.org>
Date:   Mon Apr 23 15:30:38 2012 +0200

    s3:registry untangle an assignment from the check in regkey_open_onelevel() (cherry picked from commit 12b7b4f0a7d8607dc206c32a3822d5678c14d43b)

commit e4fc313293c35dda0ff35392dbcdccbfda0e1d24
Author: Michael Adam <obnox at samba.org>
Date:   Mon Apr 23 15:29:41 2012 +0200

    s3:registry: untangle assignment from check in regkey_open_onelevel() (cherry picked from commit 52d3c5c14898b5f2514d1512289370eb6f6fd369)

commit 521c7ea32d36263d218d98fc31420afc1b7cb0e1
Author: Michael Adam <obnox at samba.org>
Date:   Wed Apr 11 15:51:40 2012 +0200

    s3:registry: fix seqnum race in regdb_fetch_keys_internal
    
    This prevents race between fetching seqnum and key content.
    
    Because there is currently no way to atomically fetch the
    record along with the seqnum, I use a loop.
    This is far from optimal and should should ideally be done
    differently. But for now it fixes the race.
    (cherry picked from commit 66fcac5e479a530091ecb43d9f8cf90f4351ad17)

commit 2517f435574876ad44bf0212f507114a610f2377
Author: Gregor Beck <gbeck at sernet.de>
Date:   Wed Jul 13 16:51:54 2011 +0200

    s3:registry avoid pruning the sequencenumber while flushing the regsubkey_ctr
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    
    Autobuild-User: Stefan Metzmacher <metze at samba.org>
    Autobuild-Date: Fri Jul 15 08:34:47 CEST 2011 on sn-devel-104
    (cherry picked from commit 5049e3e142977a4c3d0f5a0fd9c06429f4d85bed)

commit 11413a95a2db14ef14a8f8f4fcb1f11adf44e7a0
Author: Michael Adam <obnox at samba.org>
Date:   Wed Apr 11 15:48:02 2012 +0200

    s3:registry: fix seqnum race in fetch_values_internal
    
    This prevents race between fetching seqnum and key content.
    
    Because there is currently no way to atomically fetch the
    record along with the seqnum, I use a loop.
    This is far from optimal and should should ideally be done
    differently. But for now it fixes the race.
    (cherry picked from commit 13bccba3c2f6e6fdda2b4a40dd4b1e250a98a7ef)
    
    Conflicts:
    
    	source3/registry/reg_backend_db.c

commit 96f08f6d43cb9bebda175efd5719ca15549a5b99
Author: Michael Adam <obnox at samba.org>
Date:   Wed Apr 11 16:02:44 2012 +0200

    s3:registry: update the seqnum in the subkey cache at the end of regval_store_keys
    
    The purpose is to prevent next reads from going to disk.
    
    Note that this will currently only be effective with local tdbs, not
    with ctdb: For tdb, store and delete bump the seqnum while transaction
    commit does not. For ctdb, transaction commit bumps the seqnum, while
    store and delete don't... This needs fixing (in ctdb).
    (cherry picked from commit 16d83149c1b5620598edd37bbd1a73bebec82b6e)

commit f4d800d8d010e638d37d993d8eef00645398f811
Author: Michael Adam <obnox at samba.org>
Date:   Wed Apr 11 15:38:29 2012 +0200

    s3:registry:db: update the value container seqnum after storing/deleting to prevent next read from going to disk if possible
    
    Note that this will currently only be effective in the local TDB implementation.
    For CTDB, this wont work since seqnum currently works differently there (needs
    fixing): For tdb, store and delete operations bump the db seqnum, while
    transaction commits don't. For ctdb, the seqnum is bumped by the transaction
    commit but not by store and delete operations.
    (cherry picked from commit 13347d11c0e918f82e7e3c21125acc5e241d389f)

commit 8980168a16463e1d4fabd5a96f8385882aa0fe7b
Author: Michael Adam <obnox at samba.org>
Date:   Thu Apr 12 22:53:24 2012 +0200

    s3:registry: wrap reg_deletekey() into a transaction
    
    This is wrong layering but fixes a race condition.
    (cherry picked from commit e3ad0456515c97f6697190c86b8cec4af8e1e190)

commit 14d9621c39c67872316c6d4f11387b7c3a6dbb00
Author: Michael Adam <obnox at samba.org>
Date:   Thu Apr 12 22:17:35 2012 +0200

    s3:registry: wrap reg_createkey() in a transaction
    
    This is wrong layering (calling into regdb_transaction* in the reg_api code)
    but fixes a potential race. It makes the multi-step create procedure atomic.
    
    This should completely be done in the backend.
    (cherry picked from commit 65d9b116d0283b010e9e3c9ecf185ca42850838e)

commit 95ba1aa132e6097a0d35cbc05296427aebdf21b1
Author: Michael Adam <obnox at samba.org>
Date:   Thu Apr 12 17:58:26 2012 +0200

    s3:registry: untangle assignments from checks in reg_createkey() (cherry picked from commit 4ac9625fe42ded0717aafdf6eec4c1b2217c3c68)

commit d67b1813ac563f79ed055a7e918c5f293a7069fc
Author: Michael Adam <obnox at samba.org>
Date:   Thu Apr 12 17:52:43 2012 +0200

    s3:registry: wrap reg_deletevalue() in a transaction
    
    This is at the wrong layer, but if fixes a race potentially causing
    data corruption by concurrent access.
    (cherry picked from commit c1208c4a9c10b03579dca3bcd304709e631d3c25)

commit 866faf77f92c17e7dbb21686601c7e45a3f406cd
Author: Michael Adam <obnox at samba.org>
Date:   Thu Apr 12 17:46:02 2012 +0200

    s3:registry: untangle assignment from check in reg_deletevalue() (cherry picked from commit 585746338bda22ff8337d41c8cc50533c5facf56)

commit e2d087619076e8c7ec9e46e63037753d8c07138f
Author: Michael Adam <obnox at samba.org>
Date:   Thu Apr 12 13:38:32 2012 +0200

    s3:registry: fix race in reg_setvalue that could lead to data corruption
    
    (there was no lock around fetching the values and storing them)
    
    The layering is wrong in that it uses regdb transactions in reg_api
    (cherry picked from commit 9220377ceebf05e756fd108cbd30b503598e0fb8)

commit a5025e27890a96b11d8d2119ca72a27b929aa2bc
Author: Michael Adam <obnox at samba.org>
Date:   Fri Apr 20 15:19:47 2012 +0200

    s3:registry: untangle assignment from check and add a debugmessage in reg_setvalue() (cherry picked from commit a81d399456eb86ffb60bed8704cd8c7864b742db)

commit 488b94637952de1cc6251f2d4267ee361b041a0e
Author: Michael Adam <obnox at samba.org>
Date:   Thu Apr 12 08:18:04 2012 +0200

    s3:registry: don't leak the old contents when updating the value cache (cherry picked from commit 0bf44361caace3a4974dafa305033fb926d0f6d6)

commit b6aaf6b043699cd2d518100ac2934190e3d51639
Author: Michael Adam <obnox at samba.org>
Date:   Fri Mar 30 15:39:58 2012 +0200

    s3:registry: fix debug message in regdb_store_values_internal() (cherry picked from commit c46403f74116708f2f8b1d531f5881bb9d7f2a84)

commit bdbfde84e2b722cc8697228d8abdb0663f4addd7
Author: Michael Adam <obnox at samba.org>
Date:   Fri Mar 30 15:35:14 2012 +0200

    s3:registry: improve log message in regdb_unpack_values() (cherry picked from commit ae441d97cdbe8e35cd342ba979bacc3757c06cb7)

commit 6413d234911ab9211cf05b89412162d864b89c0a
Author: Michael Adam <obnox at samba.org>
Date:   Fri Mar 30 15:14:01 2012 +0200

    s3:registry: fix a debug message typo (cherry picked from commit 9f82e1175f28bdc1c09e7bd795699b29049a77e3)

commit 18d3d3f34c355b182bdb0327a8e4d890965f1594
Author: Michael Adam <obnox at samba.org>
Date:   Fri Mar 30 14:39:50 2012 +0200

    s3:registry: add a new function regval_ctr_value_byname()
    
    This is like regval_ctr_key_exists() but does not return bool,
    but the regval_blob instead, if found, and NULL if not found.
    (cherry picked from commit b037d5461a7a9a2e51a3dd2794fcc47dfcff4468)

commit b712448006fe5d31d9c8db164ffd7b0f0ee1191f
Author: Michael Adam <obnox at samba.org>
Date:   Fri Mar 30 14:33:39 2012 +0200

    s3:registry: rename regval_ctr_key_exists() to regval_ctr_value_exists() (cherry picked from commit 60cdf3c8b5bbda9434f0d8a05fc581ab41b42d5c)

commit 4cfbe636d4398e4486a6e402a86e53b77f4aaaf9
Author: Michael Adam <obnox at samba.org>
Date:   Fri Mar 30 01:00:51 2012 +0200

    s4:torture:rpc:spoolss: also initialize driverName before checking it in test_PrinterData_DsSpooler() (cherry picked from commit 46428f96a4089925355b4eeebebb8d7f27e2ec0b)

commit b356e42c0828049af8b8f3b5b977aee89c086db6
Author: Michael Adam <obnox at samba.org>
Date:   Fri Mar 30 00:10:14 2012 +0200

    s3:registry:reg_api: fix reg_queryvalue to not fail when values are modified while it runs (cherry picked from commit 5d26120b5ab180212d570dd256e8989e0c80224d)

commit f2ab0372049f839c9201bc326030163996dec769
Author: Michael Adam <obnox at samba.org>
Date:   Sat May 5 02:12:25 2012 +0200

    s3:registry: implement values_need_update and subkeys_need_update in the smbconf backend
    
    It simply calls to the regdb functions.
    This fixes a caching issue uncovered by recent changes.
    (cherry picked from commit bff7589818e602ace6cd0a4125d5f6a2ba97cded)

-----------------------------------------------------------------------

Summary of changes:
 source3/auth/server_info.c             |    5 -
 source3/registry/reg_api.c             |  256 ++++++++++++++++++++++++--------
 source3/registry/reg_backend_db.c      |   85 +++++++++--
 source3/registry/reg_backend_smbconf.c |   11 ++
 source3/registry/reg_objects.c         |   20 +++-
 source3/registry/reg_objects.h         |    4 +-
 source4/torture/rpc/spoolss.c          |    1 +
 7 files changed, 300 insertions(+), 82 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/auth/server_info.c b/source3/auth/server_info.c
index 5b8ae1b..2e94e46 100644
--- a/source3/auth/server_info.c
+++ b/source3/auth/server_info.c
@@ -273,11 +273,6 @@ static NTSTATUS group_sids_to_info3(struct netr_SamInfo3 *info3,
 	for (i = 0; i < num_sids; i++) {
 		ok = sid_peek_check_rid(domain_sid, &sids[i], &rid);
 		if (ok) {
-
-			/* if it is the primary gid, skip it, we
-			 * obviously already have it */
-			if (info3->base.primary_gid == rid) continue;
-
 			/* store domain group rid */
 			groups->rids[groups->count].rid = rid;
 			groups->rids[groups->count].attributes = attributes;
diff --git a/source3/registry/reg_api.c b/source3/registry/reg_api.c
index 935d244..55e364f 100644
--- a/source3/registry/reg_api.c
+++ b/source3/registry/reg_api.c
@@ -89,6 +89,7 @@ static WERROR fill_value_cache(struct registry_key *key)
 		}
 	}
 
+	TALLOC_FREE(key->values);
 	werr = regval_ctr_init(key, &(key->values));
 	W_ERROR_NOT_OK_RETURN(werr);
 
@@ -115,7 +116,7 @@ static WERROR fill_subkey_cache(struct registry_key *key)
 
 	if (fetch_reg_keys(key->key, key->subkeys) == -1) {
 		TALLOC_FREE(key->subkeys);
-		return WERR_NO_MORE_ITEMS;
+		return WERR_BADFILE;
 	}
 
 	return WERR_OK;
@@ -136,7 +137,6 @@ static WERROR regkey_open_onelevel(TALLOC_CTX *mem_ctx,
 	WERROR     	result = WERR_OK;
 	struct registry_key *regkey;
 	struct registry_key_handle *key;
-	struct regsubkey_ctr	*subkeys = NULL;
 
 	DEBUG(7,("regkey_open_onelevel: name = [%s]\n", name));
 
@@ -150,7 +150,8 @@ static WERROR regkey_open_onelevel(TALLOC_CTX *mem_ctx,
 		goto done;
 	}
 
-	if ( !(W_ERROR_IS_OK(result = regdb_open())) ) {
+	result = regdb_open();
+	if (!(W_ERROR_IS_OK(result))) {
 		goto done;
 	}
 
@@ -193,28 +194,21 @@ static WERROR regkey_open_onelevel(TALLOC_CTX *mem_ctx,
 
 	/* Look up the table of registry I/O operations */
 
-	if ( !(key->ops = reghook_cache_find( key->name )) ) {
+	key->ops = reghook_cache_find( key->name );
+	if (key->ops == NULL) {
 		DEBUG(0,("reg_open_onelevel: Failed to assign "
 			 "registry_ops to [%s]\n", key->name ));
 		result = WERR_BADFILE;
 		goto done;
 	}
 
-	/* check if the path really exists; failed is indicated by -1 */
-	/* if the subkey count failed, bail out */
+	/* FIXME: Existence is currently checked by fetching the subkeys */
 
-	result = regsubkey_ctr_init(key, &subkeys);
+	result = fill_subkey_cache(regkey);
 	if (!W_ERROR_IS_OK(result)) {
 		goto done;
 	}
 
-	if ( fetch_reg_keys( key, subkeys ) == -1 )  {
-		result = WERR_BADFILE;
-		goto done;
-	}
-
-	TALLOC_FREE( subkeys );
-
 	if ( !regkey_access_check( key, access_desired, &key->access_granted,
 				   token ) ) {
 		result = WERR_ACCESS_DENIED;
@@ -256,13 +250,15 @@ WERROR reg_openkey(TALLOC_CTX *mem_ctx, struct registry_key *parent,
 {
 	struct registry_key *direct_parent = parent;
 	WERROR err;
-	char *p, *path, *to_free;
+	char *p, *path;
 	size_t len;
+	TALLOC_CTX *frame = talloc_stackframe();
 
-	if (!(path = SMB_STRDUP(name))) {
-		return WERR_NOMEM;
+	path = talloc_strdup(frame, name);
+	if (path == NULL) {
+		err = WERR_NOMEM;
+		goto error;
 	}
-	to_free = path;
 
 	len = strlen(path);
 
@@ -274,22 +270,19 @@ WERROR reg_openkey(TALLOC_CTX *mem_ctx, struct registry_key *parent,
 		char *name_component;
 		struct registry_key *tmp;
 
-		if (!(name_component = SMB_STRNDUP(path, (p - path)))) {
+		name_component = talloc_strndup(frame, path, (p - path));
+		if (name_component == NULL) {
 			err = WERR_NOMEM;
 			goto error;
 		}
 
-		err = regkey_open_onelevel(mem_ctx, direct_parent,
+		err = regkey_open_onelevel(frame, direct_parent,
 					   name_component, parent->token,
 					   KEY_ENUMERATE_SUB_KEYS, &tmp);
-		SAFE_FREE(name_component);
 
 		if (!W_ERROR_IS_OK(err)) {
 			goto error;
 		}
-		if (direct_parent != parent) {
-			TALLOC_FREE(direct_parent);
-		}
 
 		direct_parent = tmp;
 		path = p+1;
@@ -297,11 +290,9 @@ WERROR reg_openkey(TALLOC_CTX *mem_ctx, struct registry_key *parent,
 
 	err = regkey_open_onelevel(mem_ctx, direct_parent, path, parent->token,
 				   desired_access, pkey);
- error:
-	if (direct_parent != parent) {
-		TALLOC_FREE(direct_parent);
-	}
-	SAFE_FREE(to_free);
+
+error:
+	talloc_free(frame);
 	return err;
 }
 
@@ -375,6 +366,43 @@ WERROR reg_enumvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
 	return WERR_OK;
 }
 
+static WERROR reg_enumvalue_nocachefill(TALLOC_CTX *mem_ctx,
+					struct registry_key *key,
+					uint32 idx, char **pname,
+					struct registry_value **pval)
+{
+	struct registry_value *val;
+	struct regval_blob *blob;
+
+	if (!(key->key->access_granted & KEY_QUERY_VALUE)) {
+		return WERR_ACCESS_DENIED;
+	}
+
+	if (idx >= regval_ctr_numvals(key->values)) {
+		return WERR_NO_MORE_ITEMS;
+	}
+
+	blob = regval_ctr_specific_value(key->values, idx);
+
+	val = talloc_zero(mem_ctx, struct registry_value);
+	if (val == NULL) {
+		return WERR_NOMEM;
+	}
+
+	val->type = regval_type(blob);
+	val->data = data_blob_talloc(mem_ctx, regval_data_p(blob), regval_size(blob));
+
+	if (pname
+	    && !(*pname = talloc_strdup(
+			 mem_ctx, regval_name(blob)))) {
+		TALLOC_FREE(val);
+		return WERR_NOMEM;
+	}
+
+	*pval = val;
+	return WERR_OK;
+}
+
 WERROR reg_queryvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
 		      const char *name, struct registry_value **pval)
 {
@@ -393,7 +421,14 @@ WERROR reg_queryvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
 		struct regval_blob *blob;
 		blob = regval_ctr_specific_value(key->values, i);
 		if (strequal(regval_name(blob), name)) {
-			return reg_enumvalue(mem_ctx, key, i, NULL, pval);
+			/*
+			 * don't use reg_enumvalue here:
+			 * re-reading the values from the disk
+			 * would change the indexing and break
+			 * this function.
+			 */
+			return reg_enumvalue_nocachefill(mem_ctx, key, i,
+							 NULL, pval);
 		}
 	}
 
@@ -522,14 +557,26 @@ WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent,
 	TALLOC_CTX *mem_ctx;
 	char *path, *end;
 	WERROR err;
+	uint32_t access_granted;
 
-	if (!(mem_ctx = talloc_new(ctx))) return WERR_NOMEM;
+	mem_ctx = talloc_new(ctx);
+	if (mem_ctx == NULL) {
+		return WERR_NOMEM;
+	}
 
-	if (!(path = talloc_strdup(mem_ctx, subkeypath))) {
+	path = talloc_strdup(mem_ctx, subkeypath);
+	if (path == NULL) {
 		err = WERR_NOMEM;
 		goto done;
 	}
 
+	err = regdb_transaction_start();
+	if (!W_ERROR_IS_OK(err)) {
+		DEBUG(0, ("reg_createkey: failed to start transaction: %s\n",
+			  win_errstr(err)));
+		goto done;
+	}
+
 	while ((end = strchr(path, '\\')) != NULL) {
 		struct registry_key *tmp;
 		enum winreg_CreateAction action;
@@ -539,7 +586,7 @@ WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent,
 		err = reg_createkey(mem_ctx, key, path,
 				    KEY_ENUMERATE_SUB_KEYS, &tmp, &action);
 		if (!W_ERROR_IS_OK(err)) {
-			goto done;
+			goto trans_done;
 		}
 
 		if (key != parent) {
@@ -560,24 +607,25 @@ WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent,
 		if (paction != NULL) {
 			*paction = REG_OPENED_EXISTING_KEY;
 		}
-		goto done;
+		goto trans_done;
 	}
 
 	if (!W_ERROR_EQUAL(err, WERR_BADFILE)) {
 		/*
 		 * Something but "notfound" has happened, so bail out
 		 */
-		goto done;
+		goto trans_done;
 	}
 
 	/*
-	 * We have to make a copy of the current key, as we opened it only
-	 * with ENUM_SUBKEY access.
+	 * We may (e.g. in the iteration) have opened the key with ENUM_SUBKEY.
+	 * Instead of re-opening the key with CREATE_SUB_KEY, we simply
+	 * duplicate the access check here and skip the expensive full open.
 	 */
-
-	err = reg_openkey(mem_ctx, key, "", KEY_CREATE_SUB_KEY,
-			  &create_parent);
-	if (!W_ERROR_IS_OK(err)) {
+	if (!regkey_access_check(key->key, KEY_CREATE_SUB_KEY, &access_granted,
+				 key->token))
+	{
+		err = WERR_ACCESS_DENIED;
 		goto done;
 	}
 
@@ -585,21 +633,33 @@ WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent,
 	 * Actually create the subkey
 	 */
 
-	err = fill_subkey_cache(create_parent);
-	if (!W_ERROR_IS_OK(err)) goto done;
-
 	err = create_reg_subkey(key->key, path);
-	W_ERROR_NOT_OK_GOTO_DONE(err);
+	if (!W_ERROR_IS_OK(err)) {
+		goto trans_done;
+	}
 
 	/*
 	 * Now open the newly created key
 	 */
 
-	err = reg_openkey(ctx, create_parent, path, desired_access, pkey);
+	err = reg_openkey(ctx, key, path, desired_access, pkey);
 	if (W_ERROR_IS_OK(err) && (paction != NULL)) {
 		*paction = REG_CREATED_NEW_KEY;
 	}
 
+trans_done:
+	if (W_ERROR_IS_OK(err)) {
+		err = regdb_transaction_commit();
+		if (!W_ERROR_IS_OK(err)) {
+			DEBUG(0, ("reg_createkey: Error committing transaction: %s\n", win_errstr(err)));
+		}
+	} else {
+		WERROR err1 = regdb_transaction_cancel();
+		if (!W_ERROR_IS_OK(err1)) {
+			DEBUG(0, ("reg_createkey: Error cancelling transaction: %s\n", win_errstr(err1)));
+		}
+	}
+
  done:
 	TALLOC_FREE(mem_ctx);
 	return err;
@@ -622,12 +682,19 @@ WERROR reg_deletekey(struct registry_key *parent, const char *path)
 	err = reg_openkey(mem_ctx, parent, name, REG_KEY_READ, &key);
 	W_ERROR_NOT_OK_GOTO_DONE(err);
 
+	err = regdb_transaction_start();
+	if (!W_ERROR_IS_OK(err)) {
+		DEBUG(0, ("reg_deletekey: Error starting transaction: %s\n",
+			  win_errstr(err)));
+		goto done;
+	}
+
 	err = fill_subkey_cache(key);
-	W_ERROR_NOT_OK_GOTO_DONE(err);
+	W_ERROR_NOT_OK_GOTO(err, trans_done);
 
 	if (regsubkey_ctr_numkeys(key->subkeys) > 0) {
 		err = WERR_ACCESS_DENIED;
-		goto done;
+		goto trans_done;
 	}
 
 	/* no subkeys - proceed with delete */
@@ -637,7 +704,7 @@ WERROR reg_deletekey(struct registry_key *parent, const char *path)
 
 		err = reg_openkey(mem_ctx, parent, name,
 				  KEY_CREATE_SUB_KEY, &tmp_key);
-		W_ERROR_NOT_OK_GOTO_DONE(err);
+		W_ERROR_NOT_OK_GOTO(err, trans_done);
 
 		parent = tmp_key;
 		name = end+1;
@@ -645,11 +712,24 @@ WERROR reg_deletekey(struct registry_key *parent, const char *path)
 
 	if (name[0] == '\0') {
 		err = WERR_INVALID_PARAM;
-		goto done;
+		goto trans_done;
 	}
 
 	err = delete_reg_subkey(parent->key, name);
 
+trans_done:
+	if (W_ERROR_IS_OK(err)) {
+		err = regdb_transaction_commit();
+		if (!W_ERROR_IS_OK(err)) {
+			DEBUG(0, ("reg_deletekey: Error committing transaction: %s\n", win_errstr(err)));
+		}
+	} else {
+		WERROR err1 = regdb_transaction_cancel();
+		if (!W_ERROR_IS_OK(err1)) {
+			DEBUG(0, ("reg_deletekey: Error cancelling transaction: %s\n", win_errstr(err1)));
+		}
+	}
+
 done:
 	TALLOC_FREE(mem_ctx);
 	return err;
@@ -666,17 +746,28 @@ WERROR reg_setvalue(struct registry_key *key, const char *name,
 		return WERR_ACCESS_DENIED;
 	}
 
-	if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
+	err = regdb_transaction_start();
+	if (!W_ERROR_IS_OK(err)) {
+		DEBUG(0, ("reg_setvalue: Failed to start transaction: %s\n",
+			  win_errstr(err)));
 		return err;
 	}
 
+	err = fill_value_cache(key);
+	if (!W_ERROR_IS_OK(err)) {
+		DEBUG(0, ("reg_setvalue: Error filling value cache: %s\n", win_errstr(err)));
+		goto done;
+	}
+
 	existing = regval_ctr_getvalue(key->values, name);
 
 	if ((existing != NULL) &&
 	    (regval_size(existing) == val->data.length) &&
 	    (memcmp(regval_data_p(existing), val->data.data,
-		    val->data.length) == 0)) {
-		return WERR_OK;
+		    val->data.length) == 0))
+	{
+		err = WERR_OK;
+		goto done;
 	}
 
 	res = regval_ctr_addvalue(key->values, name, val->type,
@@ -684,15 +775,33 @@ WERROR reg_setvalue(struct registry_key *key, const char *name,
 
 	if (res == 0) {
 		TALLOC_FREE(key->values);
-		return WERR_NOMEM;
+		err = WERR_NOMEM;
+		goto done;
 	}
 
 	if (!store_reg_values(key->key, key->values)) {
 		TALLOC_FREE(key->values);
-		return WERR_REG_IO_FAILURE;
+		DEBUG(0, ("reg_setvalue: store_reg_values failed\n"));
+		err = WERR_REG_IO_FAILURE;
+		goto done;
 	}
 
-	return WERR_OK;
+	err = WERR_OK;
+
+done:
+	if (W_ERROR_IS_OK(err)) {
+		err = regdb_transaction_commit();
+		if (!W_ERROR_IS_OK(err)) {
+			DEBUG(0, ("reg_setvalue: Error committing transaction: %s\n", win_errstr(err)));
+		}
+	} else {
+		WERROR err1 = regdb_transaction_cancel();
+		if (!W_ERROR_IS_OK(err1)) {
+			DEBUG(0, ("reg_setvalue: Error cancelling transaction: %s\n", win_errstr(err1)));
+		}
+	}
+
+	return err;
 }
 
 static WERROR reg_value_exists(struct registry_key *key, const char *name)
@@ -716,23 +825,50 @@ WERROR reg_deletevalue(struct registry_key *key, const char *name)
 		return WERR_ACCESS_DENIED;
 	}
 
-	if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
+	err = regdb_transaction_start();
+	if (!W_ERROR_IS_OK(err)) {
+		DEBUG(0, ("reg_deletevalue: Failed to start transaction: %s\n",
+			  win_errstr(err)));
 		return err;
 	}
 
+	err = fill_value_cache(key);
+	if (!W_ERROR_IS_OK(err)) {
+		DEBUG(0, ("reg_deletevalue; Error filling value cache: %s\n",
+			  win_errstr(err)));
+		goto done;
+	}
+
 	err = reg_value_exists(key, name);
 	if (!W_ERROR_IS_OK(err)) {
-		return err;
+		goto done;
 	}
 
 	regval_ctr_delvalue(key->values, name);
 
 	if (!store_reg_values(key->key, key->values)) {
 		TALLOC_FREE(key->values);
-		return WERR_REG_IO_FAILURE;
+		err = WERR_REG_IO_FAILURE;
+		DEBUG(0, ("reg_deletevalue: store_reg_values failed\n"));
+		goto done;
 	}
 
-	return WERR_OK;
+	err = WERR_OK;
+
+done:
+	if (W_ERROR_IS_OK(err)) {
+		err = regdb_transaction_commit();
+		if (!W_ERROR_IS_OK(err)) {
+			DEBUG(0, ("reg_deletevalue: Error committing transaction: %s\n", win_errstr(err)));
+		}
+	} else {
+		WERROR err1 = regdb_transaction_cancel();
+		if (!W_ERROR_IS_OK(err1)) {
+			DEBUG(0, ("reg_deletevalue: Error cancelling transaction: %s\n", win_errstr(err1)));
+		}
+	}
+
+	return err;
 }
 


-- 
Samba Shared Repository


More information about the samba-cvs mailing list