diff options
| -rw-r--r-- | source3/registry/reg_backend_db.c | 198 | 
1 files changed, 102 insertions, 96 deletions
diff --git a/source3/registry/reg_backend_db.c b/source3/registry/reg_backend_db.c index 6bf98d4c75..5c714a40b4 100644 --- a/source3/registry/reg_backend_db.c +++ b/source3/registry/reg_backend_db.c @@ -725,76 +725,32 @@ done:   do not currently exist   ***********************************************************************/ -static bool regdb_store_keys_internal(struct db_context *db, const char *key, -				      struct regsubkey_ctr *ctr) +struct regdb_store_keys_context { +	const char *key; +	struct regsubkey_ctr *ctr; +}; + +static NTSTATUS regdb_store_keys_action(struct db_context *db, +					void *private_data)  { -	int num_subkeys, old_num_subkeys, i; +	struct regdb_store_keys_context *store_ctx; +	WERROR werr; +	int num_subkeys, i;  	char *path = NULL;  	struct regsubkey_ctr *subkeys = NULL, *old_subkeys = NULL;  	char *oldkeyname = NULL; -	TALLOC_CTX *ctx = talloc_stackframe(); -	WERROR werr; -	bool ret = false; - -	if (!regdb_key_is_base_key(key) && !regdb_key_exists(db, key)) { -		goto done; -	} - -	/* -	 * fetch a list of the old subkeys so we can determine if anything has -	 * changed -	 */ - -	werr = regsubkey_ctr_init(ctx, &old_subkeys); -	if (!W_ERROR_IS_OK(werr)) { -		DEBUG(0,("regdb_store_keys: talloc() failure!\n")); -		goto done; -	} - -	regdb_fetch_keys_internal(db, key, old_subkeys); - -	num_subkeys = regsubkey_ctr_numkeys(ctr); -	old_num_subkeys = regsubkey_ctr_numkeys(old_subkeys); -	if ((num_subkeys && old_num_subkeys) && -	    (num_subkeys == old_num_subkeys)) { - -		for (i = 0; i < num_subkeys; i++) { -			if (strcmp(regsubkey_ctr_specific_key(ctr, i), -				   regsubkey_ctr_specific_key(old_subkeys, i)) -			    != 0) -			{ -				break; -			} -		} -		if (i == num_subkeys) { -			/* -			 * Nothing changed, no point to even start a tdb -			 * transaction -			 */ - -			ret = true; -			goto done; -		} -	} - -	TALLOC_FREE(old_subkeys); +	TALLOC_CTX *mem_ctx = talloc_stackframe(); -	if (db->transaction_start(db) != 0) { -		DEBUG(0, ("regdb_store_keys: transaction_start failed\n")); -		goto done; -	} +	store_ctx = (struct regdb_store_keys_context *)private_data;  	/*  	 * Re-fetch the old keys inside the transaction  	 */ -	werr = regsubkey_ctr_init(ctx, &old_subkeys); -	if (!W_ERROR_IS_OK(werr)) { -		DEBUG(0,("regdb_store_keys: talloc() failure!\n")); -		goto cancel; -	} +	werr = regsubkey_ctr_init(mem_ctx, &old_subkeys); +	W_ERROR_NOT_OK_GOTO_DONE(werr); -	regdb_fetch_keys_internal(db, key, old_subkeys); +	regdb_fetch_keys_internal(db, store_ctx->key, old_subkeys);  	/*  	 * Make the store operation as safe as possible without transactions: @@ -823,21 +779,22 @@ static bool regdb_store_keys_internal(struct db_context *db, const char *key,  	for (i=0; i<num_subkeys; i++) {  		oldkeyname = regsubkey_ctr_specific_key(old_subkeys, i); -		if (regsubkey_ctr_key_exists(ctr, oldkeyname)) { +		if (regsubkey_ctr_key_exists(store_ctx->ctr, oldkeyname)) {  			/*  			 * It's still around, don't delete  			 */ -  			continue;  		} -		path = talloc_asprintf(ctx, "%s/%s", key, oldkeyname); +		path = talloc_asprintf(mem_ctx, "%s/%s", store_ctx->key, +				       oldkeyname);  		if (!path) { -			goto cancel; +			werr = WERR_NOMEM; +			goto done;  		}  		werr = regdb_delete_key_lists(db, path); -		W_ERROR_NOT_OK_GOTO(werr, cancel); +		W_ERROR_NOT_OK_GOTO_DONE(werr);  		TALLOC_FREE(path);  	} @@ -846,47 +803,41 @@ static bool regdb_store_keys_internal(struct db_context *db, const char *key,  	/* (2) store the subkey list for the parent */ -	werr = regdb_store_keys_internal2(db, key, ctr); +	werr = regdb_store_keys_internal2(db, store_ctx->key, store_ctx->ctr);  	if (!W_ERROR_IS_OK(werr)) {  		DEBUG(0,("regdb_store_keys: Failed to store new subkey list " -			 "for parent [%s]: %s\n", key, win_errstr(werr))); -		goto cancel; +			 "for parent [%s]: %s\n", store_ctx->key, +			 win_errstr(werr))); +		goto done;  	}  	/* (3) now create records for any subkeys that don't already exist */ -	num_subkeys = regsubkey_ctr_numkeys(ctr); +	num_subkeys = regsubkey_ctr_numkeys(store_ctx->ctr);  	if (num_subkeys == 0) { -		werr = regsubkey_ctr_init(ctx, &subkeys); -		if (!W_ERROR_IS_OK(werr)) { -			DEBUG(0,("regdb_store_keys: talloc() failure!\n")); -			goto cancel; -		} +		werr = regsubkey_ctr_init(mem_ctx, &subkeys); +		W_ERROR_NOT_OK_GOTO_DONE(werr); -		werr = regdb_store_keys_internal2(db, key, subkeys); +		werr = regdb_store_keys_internal2(db, store_ctx->key, subkeys);  		if (!W_ERROR_IS_OK(werr)) {  			DEBUG(0,("regdb_store_keys: Failed to store " -				 "new record for key [%s]: %s\n", key, -				 win_errstr(werr))); -			goto cancel; +				 "new record for key [%s]: %s\n", +				 store_ctx->key, win_errstr(werr))); +			goto done;  		}  		TALLOC_FREE(subkeys); -  	}  	for (i=0; i<num_subkeys; i++) { -		path = talloc_asprintf(ctx, "%s/%s", -					key, -					regsubkey_ctr_specific_key(ctr, i)); +		path = talloc_asprintf(mem_ctx, "%s/%s", store_ctx->key, +				regsubkey_ctr_specific_key(store_ctx->ctr, i));  		if (!path) { -			goto cancel; -		} -		werr = regsubkey_ctr_init(ctx, &subkeys); -		if (!W_ERROR_IS_OK(werr)) { -			DEBUG(0,("regdb_store_keys: talloc() failure!\n")); -			goto cancel; +			werr = WERR_NOMEM; +			goto done;  		} +		werr = regsubkey_ctr_init(mem_ctx, &subkeys); +		W_ERROR_NOT_OK_GOTO_DONE(werr);  		if (regdb_fetch_keys_internal(db, path, subkeys) == -1) {  			/* create a record with 0 subkeys */ @@ -895,7 +846,7 @@ static bool regdb_store_keys_internal(struct db_context *db, const char *key,  				DEBUG(0,("regdb_store_keys: Failed to store "  					 "new record for key [%s]: %s\n", path,  					 win_errstr(werr))); -				goto cancel; +				goto done;  			}  		} @@ -903,20 +854,75 @@ static bool regdb_store_keys_internal(struct db_context *db, const char *key,  		TALLOC_FREE(path);  	} -	if (db->transaction_commit(db) != 0) { -		DEBUG(0, ("regdb_store_keys: Could not commit transaction\n")); +	werr = WERR_OK; + +done: +	talloc_free(mem_ctx); +	return werror_to_ntstatus(werr); +} + +static bool regdb_store_keys_internal(struct db_context *db, const char *key, +				      struct regsubkey_ctr *ctr) +{ +	int num_subkeys, old_num_subkeys, i; +	struct regsubkey_ctr *old_subkeys = NULL; +	TALLOC_CTX *ctx = talloc_stackframe(); +	WERROR werr; +	bool ret = false; +	struct regdb_store_keys_context store_ctx; + +	if (!regdb_key_is_base_key(key) && !regdb_key_exists(db, key)) {  		goto done;  	} -	ret = true; -	goto done; +	/* +	 * fetch a list of the old subkeys so we can determine if anything has +	 * changed +	 */ -cancel: -	ret = false; -	if (db->transaction_cancel(db) != 0) { -		smb_panic("regdb_store_keys: transaction_cancel failed\n"); +	werr = regsubkey_ctr_init(ctx, &old_subkeys); +	if (!W_ERROR_IS_OK(werr)) { +		DEBUG(0,("regdb_store_keys: talloc() failure!\n")); +		goto done;  	} +	regdb_fetch_keys_internal(db, key, old_subkeys); + +	num_subkeys = regsubkey_ctr_numkeys(ctr); +	old_num_subkeys = regsubkey_ctr_numkeys(old_subkeys); +	if ((num_subkeys && old_num_subkeys) && +	    (num_subkeys == old_num_subkeys)) { + +		for (i = 0; i < num_subkeys; i++) { +			if (strcmp(regsubkey_ctr_specific_key(ctr, i), +				   regsubkey_ctr_specific_key(old_subkeys, i)) +			    != 0) +			{ +				break; +			} +		} +		if (i == num_subkeys) { +			/* +			 * Nothing changed, no point to even start a tdb +			 * transaction +			 */ + +			ret = true; +			goto done; +		} +	} + +	TALLOC_FREE(old_subkeys); + +	store_ctx.key = key; +	store_ctx.ctr = ctr; + +	werr = ntstatus_to_werror(dbwrap_trans_do(db, +						  regdb_store_keys_action, +						  &store_ctx)); + +	ret = W_ERROR_IS_OK(werr); +  done:  	TALLOC_FREE(ctx);  | 
