Merge branch 'v4-0-test' into id10ts-registry
authorJelmer Vernooij <jelmer@samba.org>
Sun, 2 Mar 2008 23:23:09 +0000 (00:23 +0100)
committerJelmer Vernooij <jelmer@samba.org>
Sun, 2 Mar 2008 23:23:09 +0000 (00:23 +0100)
(This used to be commit f98b59021a5ea39c7970ebc5520d17775e500b8c)

1  2 
source4/lib/registry/ldb.c
source4/lib/registry/regf.c
source4/lib/registry/tests/hive.c

index 31b78d82463aaf9e6eb72112b5e943b6b15778dd,dfd368ea80d06c588a14a3d2eaf3c7a0491dc033..a764ca6235322885b4d4049f4a0cfb2d66f41d72
@@@ -36,7 -36,9 +36,9 @@@ struct ldb_key_dat
        int subkey_count, value_count;
  };
  
- static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+ static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, 
+                                struct smb_iconv_convenience *iconv_convenience,
+                                struct ldb_message *msg,
                                 const char **name, uint32_t *type,
                                 DATA_BLOB *data)
  {
@@@ -57,7 -59,7 +59,7 @@@
        {
        case REG_SZ:
        case REG_EXPAND_SZ:
-               data->length = convert_string_talloc(mem_ctx, lp_iconv_convenience(global_loadparm), CH_UTF8, CH_UTF16,
+               data->length = convert_string_talloc(mem_ctx, iconv_convenience, CH_UTF8, CH_UTF16,
                                                     val->data, val->length,
                                                     (void **)&data->data);
                break;
@@@ -281,7 -283,7 +283,7 @@@ static WERROR ldb_get_value_by_id(TALLO
        if (idx >= kd->value_count)
                return WERR_NO_MORE_ITEMS;
  
-       reg_ldb_unpack_value(mem_ctx, kd->values[idx],
+       reg_ldb_unpack_value(mem_ctx, lp_iconv_convenience(global_loadparm), kd->values[idx],
                             name, data_type, data);
  
        return WERR_OK;
@@@ -310,7 -312,7 +312,7 @@@ static WERROR ldb_get_value(TALLOC_CTX 
        if (res->count == 0)
                return WERR_BADFILE;
  
-       reg_ldb_unpack_value(mem_ctx, res->msgs[0], NULL, data_type, data);
+       reg_ldb_unpack_value(mem_ctx, lp_iconv_convenience(global_loadparm), res->msgs[0], NULL, data_type, data);
  
        return WERR_OK;
  }
@@@ -440,6 -442,33 +442,6 @@@ static WERROR ldb_add_key(TALLOC_CTX *m
        return WERR_OK;
  }
  
 -static WERROR ldb_del_key(const struct hive_key *key, const char *name)
 -{
 -      int ret;
 -      struct ldb_key_data *parentkd = talloc_get_type(key, struct ldb_key_data);
 -      struct ldb_dn *ldap_path;
 -      TALLOC_CTX *mem_ctx = talloc_init("ldb_del_key");
 -
 -      ldap_path = reg_path_to_ldb(mem_ctx, key, name, NULL);
 -
 -      ret = ldb_delete(parentkd->ldb, ldap_path);
 -
 -      talloc_free(mem_ctx);
 -
 -      if (ret == LDB_ERR_NO_SUCH_OBJECT) {
 -              return WERR_BADFILE;
 -      } else if (ret != LDB_SUCCESS) {
 -              DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(parentkd->ldb)));
 -              return WERR_FOOBAR;
 -      }
 -
 -      /* reset cache */
 -      talloc_free(parentkd->subkeys);
 -      parentkd->subkeys = NULL;
 -
 -      return WERR_OK;
 -}
 -
  static WERROR ldb_del_value (struct hive_key *key, const char *child)
  {
        int ret;
        return WERR_OK;
  }
  
 +static WERROR ldb_del_key(const struct hive_key *key, const char *name)
 +{
 +      int i, ret;
 +      struct ldb_key_data *parentkd = talloc_get_type(key, struct ldb_key_data);
 +      struct ldb_dn *ldap_path;
 +      TALLOC_CTX *mem_ctx = talloc_init("ldb_del_key");
 +      struct ldb_context *c = parentkd->ldb;
 +      struct ldb_result *res_keys;
 +      struct ldb_result *res_vals;
 +      WERROR werr;
 +      struct hive_key *hk;
 +
 +      /* Verify key exists by opening it */
 +      werr = ldb_open_key(mem_ctx, key, name, &hk);
 +      if (!W_ERROR_IS_OK(werr)) {
 +              talloc_free(mem_ctx);
 +              return werr;
 +      }
 +
 +      ldap_path = reg_path_to_ldb(mem_ctx, key, name, NULL);
 +      if (!ldap_path) {
 +              talloc_free(mem_ctx);
 +              return WERR_FOOBAR;
 +      }
 +
 +      /* Search for subkeys */
 +      ret = ldb_search(c, ldap_path, LDB_SCOPE_ONELEVEL,
 +                       "(key=*)", NULL, &res_keys);
 +
 +      if (ret != LDB_SUCCESS) {
 +              DEBUG(0, ("Error getting subkeys for '%s': %s\n",
 +                    ldb_dn_get_linearized(ldap_path), ldb_errstring(c)));
 +              talloc_free(mem_ctx);
 +              return WERR_FOOBAR;
 +      }
 +
 +      /* Search for values */
 +      ret = ldb_search(c, ldap_path, LDB_SCOPE_ONELEVEL,
 +                       "(value=*)", NULL, &res_vals);
 +
 +      if (ret != LDB_SUCCESS) {
 +              DEBUG(0, ("Error getting values for '%s': %s\n",
 +                    ldb_dn_get_linearized(ldap_path), ldb_errstring(c)));
 +              talloc_free(mem_ctx);
 +              return WERR_FOOBAR;
 +      }
 +
 +      /* Start an explicit transaction */
 +      ret = ldb_transaction_start(c);
 +
 +      if (ret != LDB_SUCCESS) {
 +              DEBUG(0, ("ldb_transaction_start: %s\n", ldb_errstring(c)));
 +              talloc_free(mem_ctx);
 +              return WERR_FOOBAR;
 +      }
 +
 +      if (res_keys->count || res_vals->count)
 +      {
 +              /* Delete any subkeys */
 +              for (i = 0; i < res_keys->count; i++)
 +              {
 +                      werr = ldb_del_key(hk, ldb_msg_find_attr_as_string(
 +                                                      res_keys->msgs[i],
 +                                                      "key", NULL));
 +                      if (!W_ERROR_IS_OK(werr)) {
 +                              ret = ldb_transaction_cancel(c);
 +                              talloc_free(mem_ctx);
 +                              return werr;
 +                      }
 +              }
 +
 +              /* Delete any values */
 +              for (i = 0; i < res_vals->count; i++)
 +              {
 +                      werr = ldb_del_value(hk, ldb_msg_find_attr_as_string(
 +                                                      res_vals->msgs[i],
 +                                                      "value", NULL));
 +                      if (!W_ERROR_IS_OK(werr)) {
 +                              ret = ldb_transaction_cancel(c);
 +                              talloc_free(mem_ctx);
 +                              return werr;
 +                      }
 +              }
 +      }
 +
 +      /* Delete the key itself */
 +      ret = ldb_delete(c, ldap_path);
 +
 +      if (ret != LDB_SUCCESS)
 +      {
 +              DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(c)));
 +              ret = ldb_transaction_cancel(c);
 +              talloc_free(mem_ctx);
 +              return WERR_FOOBAR;
 +      }
 +
 +      /* Commit the transaction */
 +      ret = ldb_transaction_commit(c);
 +
 +      if (ret != LDB_SUCCESS)
 +      {
 +              DEBUG(0, ("ldb_transaction_commit: %s\n", ldb_errstring(c)));
 +              ret = ldb_transaction_cancel(c);
 +              talloc_free(mem_ctx);
 +              return WERR_FOOBAR;
 +      }
 +
 +      talloc_free(mem_ctx);
 +
 +      /* reset cache */
 +      talloc_free(parentkd->subkeys);
 +      parentkd->subkeys = NULL;
 +
 +      return WERR_OK;
 +}
 +
  static WERROR ldb_set_value(struct hive_key *parent,
                            const char *name, uint32_t type,
                            const DATA_BLOB data)
@@@ -696,7 -609,9 +698,9 @@@ static WERROR ldb_get_key_info(TALLOC_C
  
                        if (max_valbufsize != NULL) {
                                DATA_BLOB data;
-                               reg_ldb_unpack_value(mem_ctx, kd->values[i], NULL, 
+                               reg_ldb_unpack_value(mem_ctx, 
+                                                    lp_iconv_convenience(global_loadparm),
+                                                    kd->values[i], NULL, 
                                                     NULL, &data);
                                *max_valbufsize = MAX(*max_valbufsize, data.length);
                                talloc_free(data.data);
index 6a35799a7e12200f4d761ca105e4308cde1c45ef,cf3e564c0e2c6d1369dd33eb39a9d66eae445ec7..a192f3be4ddc14c656435552d22ce3b0ed7d356a
@@@ -1618,55 -1618,10 +1618,55 @@@ static WERROR regf_del_key(const struc
                return WERR_BADFILE;
        }
  
 -      if (key->nk->subkeys_offset != -1 ||
 -              key->nk->values_offset != -1) {
 -              DEBUG(0, ("Key '%s' is not empty.\n", name));
 -              return WERR_FILE_EXISTS;
 +      if (key->nk->subkeys_offset != -1) {
 +              char *sk_name;
 +              struct hive_key *sk = (struct hive_key *)key;
 +              int i = key->nk->num_subkeys;
 +              while (i--) {
 +                      /* Get subkey information. */
 +                      error = regf_get_subkey_by_index(parent_nk, sk, 0,
 +                                                       (const char **)&sk_name,
 +                                                       NULL, NULL);
 +                      if (!W_ERROR_IS_OK(error)) {
 +                              DEBUG(0, ("Can't retrieve subkey by index.\n"));
 +                              return error;
 +                      }
 +
 +                      /* Delete subkey. */
 +                      error = regf_del_key(sk, sk_name);
 +                      if (!W_ERROR_IS_OK(error)) {
 +                              DEBUG(0, ("Can't delete key '%s'.\n", sk_name));
 +                              return error;
 +                      }
 +
 +                      talloc_free(sk_name);
 +              }
 +      }
 +
 +      if (key->nk->values_offset != -1) {
 +              char *val_name;
 +              struct hive_key *sk = (struct hive_key *)key;
 +              DATA_BLOB data;
 +              int i = key->nk->num_values;
 +              while (i--) {
 +                      /* Get value information. */
 +                      error = regf_get_value(parent_nk, sk, 0,
 +                                             (const char **)&val_name,
 +                                             NULL, &data);
 +                      if (!W_ERROR_IS_OK(error)) {
 +                              DEBUG(0, ("Can't retrieve value by index.\n"));
 +                              return error;
 +                      }
 +
 +                      /* Delete value. */
 +                      error = regf_del_value(sk, val_name);
 +                      if (!W_ERROR_IS_OK(error)) {
 +                              DEBUG(0, ("Can't delete value '%s'.\n", val_name));
 +                              return error;
 +                      }
 +
 +                      talloc_free(val_name);
 +              }
        }
  
        /* Delete it from the subkey list. */
@@@ -1908,7 -1863,9 +1908,9 @@@ static WERROR regf_save_hbin(struct reg
        return WERR_OK;
  }
  
- WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, const char *location,
+ WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, 
+                           struct smb_iconv_convenience *iconv_convenience,
+                           const char *location,
                            int minor_version, struct hive_key **key)
  {
        struct regf_data *regf;
  
        regf = (struct regf_data *)talloc_zero(NULL, struct regf_data);
  
-       regf->iconv_convenience = lp_iconv_convenience(global_loadparm);
+       regf->iconv_convenience = iconv_convenience;
  
        W_ERROR_HAVE_NO_MEMORY(regf);
  
  }
  
  WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, const char *location, 
-                         struct loadparm_context *lp_ctx, struct hive_key **key)
+                         struct smb_iconv_convenience *iconv_convenience, struct hive_key **key)
  {
        struct regf_data *regf;
        struct regf_hdr *regf_hdr;
  
        regf = (struct regf_data *)talloc_zero(NULL, struct regf_data);
  
-       regf->iconv_convenience = lp_iconv_convenience(lp_ctx);
+       regf->iconv_convenience = iconv_convenience;
  
        W_ERROR_HAVE_NO_MEMORY(regf);
  
index 915782694f61de5bc9b83fa9bd99e0d34aa99c30,1dcb464d8015f2b808fc2af982a6bf1fd4c33cf0..1e56f125c5d168eac047c08a69328aff48881181
@@@ -25,6 -25,7 +25,7 @@@
  #include "torture/torture.h"
  #include "librpc/gen_ndr/winreg.h"
  #include "system/filesys.h"
+ #include "param/param.h"
  
  static bool test_del_nonexistant_key(struct torture_context *tctx,
                                     const void *test_data)
@@@ -110,38 -111,6 +111,38 @@@ static bool test_add_subkey(struct tort
        return true;
  }
  
 +static bool test_del_recursive(struct torture_context *tctx,
 +                             const void *test_data)
 +{
 +      WERROR error;
 +      struct hive_key *subkey;
 +      struct hive_key *subkey2;
 +      const struct hive_key *root = (const struct hive_key *)test_data;
 +      TALLOC_CTX *mem_ctx = tctx;
 +      uint32_t data = 42;
 +
 +      /* Create a new key under the root */
 +      error = hive_key_add_name(mem_ctx, root, "Parent Key", NULL,
 +                                NULL, &subkey);
 +      torture_assert_werr_ok(tctx, error, "hive_key_add_name");
 +
 +      /* Create a new key under "Parent Key" */
 +      error = hive_key_add_name(mem_ctx, subkey, "Child Key", NULL,
 +                                NULL, &subkey2);
 +      torture_assert_werr_ok(tctx, error, "hive_key_add_name");
 +
 +      /* Create a new value under "Child Key" */
 +      error = hive_key_set_value(subkey2, "Answer Recursive", REG_DWORD,
 +                             data_blob_talloc(mem_ctx, &data, sizeof(data)));
 +      torture_assert_werr_ok(tctx, error, "hive_key_set_value");
 +
 +      /* Deleting "Parent Key" will also delete "Child Key" and the value. */
 +      error = hive_key_del(root, "Parent Key");
 +      torture_assert_werr_ok(tctx, error, "hive_key_del");
 +
 +      return true;
 +}
 +
  static bool test_flush_key(struct torture_context *tctx, void *test_data)
  {
        struct hive_key *root = (struct hive_key *)test_data;
@@@ -304,11 -273,6 +305,11 @@@ static void tcase_add_tests(struct tort
                                                test_add_subkey);
        torture_tcase_add_simple_test(tcase, "flush_key",
                                                test_flush_key);
 +      /* test_del_recursive() test must run before test_keyinfo_root().
 +         test_keyinfo_root() checks the number of subkeys, which verifies
 +         the recursive delete worked properly. */
 +      torture_tcase_add_simple_test_const(tcase, "del_recursive",
 +                                              test_del_recursive);
        torture_tcase_add_simple_test_const(tcase, "get_info",
                                                test_keyinfo_root);
        torture_tcase_add_simple_test(tcase, "get_info_nums",
@@@ -386,7 -350,8 +387,8 @@@ static bool hive_setup_regf(struct tort
  
        rmdir(dirname);
  
-       error = reg_create_regf_file(tctx, dirname, 5, &key);
+       error = reg_create_regf_file(tctx, lp_iconv_convenience(tctx->lp_ctx),
+                                    dirname, 5, &key);
        if (!W_ERROR_IS_OK(error)) {
                fprintf(stderr, "Unable to create new regf file\n");
                return false;