s3:registry: create the empty list of subkeys of the new key in regdb_create_subkey
[metze/samba/wip.git] / source3 / registry / reg_backend_db.c
index cd57868efa89229b7d0cbe6e3a762396c93aea53..34c25d83576f619056a4a2bb3d670a29767fd751 100644 (file)
@@ -30,6 +30,7 @@
 #include "nt_printing.h"
 #include "util_tdb.h"
 #include "dbwrap.h"
+#include "../libcli/security/secdesc.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_REGISTRY
@@ -481,7 +482,7 @@ static WERROR regdb_upgrade_v1_to_v2(void)
 
        talloc_destroy(mem_ctx);
 
-       if (rc == -1) {
+       if (rc < 0) {
                return WERR_REG_IO_FAILURE;
        }
 
@@ -711,6 +712,13 @@ static WERROR regdb_delete_subkeylist(struct db_context *db, const char *keyname
        return regdb_delete_key_with_prefix(db, keyname, NULL);
 }
 
+static WERROR regdb_delete_sorted_subkeys(struct db_context *db,
+                                         const char *keyname)
+{
+       return regdb_delete_key_with_prefix(db, keyname, REG_SORTED_SUBKEYS_PREFIX);
+}
+
+
 static WERROR regdb_delete_key_lists(struct db_context *db, const char *keyname)
 {
        WERROR werr;
@@ -729,6 +737,14 @@ static WERROR regdb_delete_key_lists(struct db_context *db, const char *keyname)
                goto done;
        }
 
+       werr = regdb_delete_sorted_subkeys(db, keyname);
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(1, (__location__ " Deleting %s\\%s failed: %s\n",
+                         REG_SORTED_SUBKEYS_PREFIX, keyname,
+                         win_errstr(werr)));
+               goto done;
+       }
+
        werr = regdb_delete_subkeylist(db, keyname);
        if (!W_ERROR_IS_OK(werr)) {
                DEBUG(1, (__location__ " Deleting %s failed: %s\n",
@@ -831,12 +847,6 @@ static WERROR regdb_store_keys_internal2(struct db_context *db,
        dbuf.dsize = len;
        werr = ntstatus_to_werror(dbwrap_store_bystring(db, keyname, dbuf,
                                                        TDB_REPLACE));
-       W_ERROR_NOT_OK_GOTO_DONE(werr);
-
-       /*
-        * recreate the sorted subkey cache for regdb_key_exists()
-        */
-       werr = ntstatus_to_werror(create_sorted_subkeys(keyname));
 
 done:
        TALLOC_FREE(ctx);
@@ -844,6 +854,53 @@ done:
        return werr;
 }
 
+/**
+ * Utility function to store a new empty list of
+ * subkeys of given key specified as parent and subkey name
+ * (thereby creating the key).
+ * If the subkey list does already exist, it is not modified.
+ *
+ * Must be called from within a transaction.
+ */
+static WERROR regdb_store_subkey_list(struct db_context *db, const char *parent,
+                                     const char *key)
+{
+       WERROR werr;
+       char *path = NULL;
+       struct regsubkey_ctr *subkeys = NULL;
+       TALLOC_CTX *frame = talloc_stackframe();
+
+       path = talloc_asprintf(frame, "%s\\%s", parent, key);
+       if (!path) {
+               werr = WERR_NOMEM;
+               goto done;
+       }
+
+       werr = regsubkey_ctr_init(frame, &subkeys);
+       W_ERROR_NOT_OK_GOTO_DONE(werr);
+
+       werr = regdb_fetch_keys_internal(db, path, subkeys);
+       if (W_ERROR_IS_OK(werr)) {
+               /* subkey list exists already - don't modify */
+               goto done;
+       }
+
+       werr = regsubkey_ctr_reinit(subkeys);
+       W_ERROR_NOT_OK_GOTO_DONE(werr);
+
+       /* create a record with 0 subkeys */
+       werr = regdb_store_keys_internal2(db, path, subkeys);
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(0, ("regdb_store_keys: Failed to store new record for "
+                         "key [%s]: %s\n", path, win_errstr(werr)));
+               goto done;
+       }
+
+done:
+       talloc_free(frame);
+       return werr;
+}
+
 /***********************************************************************
  Store the new subkey record and create any child key records that
  do not currently exist
@@ -861,7 +918,7 @@ static NTSTATUS regdb_store_keys_action(struct db_context *db,
        WERROR werr;
        int num_subkeys, i;
        char *path = NULL;
-       struct regsubkey_ctr *subkeys = NULL, *old_subkeys = NULL;
+       struct regsubkey_ctr *old_subkeys = NULL;
        char *oldkeyname = NULL;
        TALLOC_CTX *mem_ctx = talloc_stackframe();
 
@@ -944,44 +1001,13 @@ static NTSTATUS regdb_store_keys_action(struct db_context *db,
 
        num_subkeys = regsubkey_ctr_numkeys(store_ctx->ctr);
 
-       if (num_subkeys == 0) {
-               werr = regsubkey_ctr_init(mem_ctx, &subkeys);
-               W_ERROR_NOT_OK_GOTO_DONE(werr);
-
-               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",
-                                store_ctx->key, win_errstr(werr)));
-                       goto done;
-               }
-               TALLOC_FREE(subkeys);
-       }
-
        for (i=0; i<num_subkeys; i++) {
-               path = talloc_asprintf(mem_ctx, "%s\\%s", store_ctx->key,
-                               regsubkey_ctr_specific_key(store_ctx->ctr, i));
-               if (!path) {
-                       werr = WERR_NOMEM;
-                       goto done;
-               }
-               werr = regsubkey_ctr_init(mem_ctx, &subkeys);
-               W_ERROR_NOT_OK_GOTO_DONE(werr);
+               const char *subkey;
 
-               werr = regdb_fetch_keys_internal(db, path, subkeys);
-               if (!W_ERROR_IS_OK(werr)) {
-                       /* create a record with 0 subkeys */
-                       werr = regdb_store_keys_internal2(db, path, subkeys);
-                       if (!W_ERROR_IS_OK(werr)) {
-                               DEBUG(0,("regdb_store_keys: Failed to store "
-                                        "new record for key [%s]: %s\n", path,
-                                        win_errstr(werr)));
-                               goto done;
-                       }
-               }
+               subkey = regsubkey_ctr_specific_key(store_ctx->ctr, i);
 
-               TALLOC_FREE(subkeys);
-               TALLOC_FREE(path);
+               werr = regdb_store_subkey_list(db, store_ctx->key, subkey);
+               W_ERROR_NOT_OK_GOTO_DONE(werr);
        }
 
        werr = WERR_OK;
@@ -1001,7 +1027,7 @@ static bool regdb_store_keys_internal(struct db_context *db, const char *key,
        bool ret = false;
        struct regdb_store_keys_context store_ctx;
 
-       if (!regdb_key_is_base_key(key) && !regdb_key_exists(db, key)) {
+       if (!regdb_key_exists(db, key)) {
                goto done;
        }
 
@@ -1104,6 +1130,8 @@ static NTSTATUS regdb_create_subkey_action(struct db_context *db,
                         win_errstr(werr)));
        }
 
+       werr = regdb_store_subkey_list(db, create_ctx->key, create_ctx->subkey);
+
 done:
        talloc_free(mem_ctx);
        return werror_to_ntstatus(werr);
@@ -1116,7 +1144,7 @@ static WERROR regdb_create_subkey(const char *key, const char *subkey)
        TALLOC_CTX *mem_ctx = talloc_stackframe();
        struct regdb_create_subkey_context create_ctx;
 
-       if (!regdb_key_is_base_key(key) && !regdb_key_exists(regdb, key)) {
+       if (!regdb_key_exists(regdb, key)) {
                werr = WERR_NOT_FOUND;
                goto done;
        }
@@ -1197,7 +1225,7 @@ static WERROR regdb_delete_subkey(const char *key, const char *subkey)
        struct regdb_delete_subkey_context delete_ctx;
        TALLOC_CTX *mem_ctx = talloc_stackframe();
 
-       if (!regdb_key_is_base_key(key) && !regdb_key_exists(regdb, key)) {
+       if (!regdb_key_exists(regdb, key)) {
                werr = WERR_NOT_FOUND;
                goto done;
        }
@@ -1300,7 +1328,7 @@ done:
 
 static int cmp_keynames(char **p1, char **p2)
 {
-       return StrCaseCmp(*p1, *p2);
+       return strcasecmp_m(*p1, *p2);
 }
 
 struct create_sorted_subkeys_context {
@@ -1517,6 +1545,11 @@ static bool scan_parent_subkeys(struct db_context *db, const char *parent,
                        goto fail;
                }
 
+               DEBUG(2, (__location__ " WARNING: recreating the sorted "
+                         "subkeys cache for key '%s' from scan_parent_subkeys "
+                         "this should not happen (too frequently)...\n",
+                         path));
+
                status = create_sorted_subkeys_internal(path, key);
                if (!NT_STATUS_IS_OK(status)) {
                        res = db->transaction_cancel(db);
@@ -1814,7 +1847,7 @@ static bool regdb_store_values_internal(struct db_context *db, const char *key,
                goto done;
        }
 
-       data.dptr = TALLOC_ARRAY(ctx, uint8, len);
+       data.dptr = talloc_array(ctx, uint8, len);
        data.dsize = len;
 
        len = regdb_pack_values(values, data.dptr, data.dsize);