Add dump command in vconftool 73/180373/3
authorjusung son <jusung07.son@samsung.com>
Tue, 29 May 2018 00:55:50 +0000 (09:55 +0900)
committerjusung son <jusung07.son@samsung.com>
Tue, 29 May 2018 01:32:46 +0000 (01:32 +0000)
Change-Id: I285ace5ad1f01c311e47bc47fc19e2f2464e335e
Signed-off-by: jusung son <jusung07.son@samsung.com>
backend/sqlite.c
client/c_direct.c
client/c_direct.h
client/c_main.c
common/backend.h
common/direct.c
common/direct.h
vconf-compat/vconftool [changed mode: 0755->0644]

index 78a1c5c..7368f98 100644 (file)
@@ -487,6 +487,135 @@ end:
        return ret;
 }
 
+
+static int get_dump(const char *dbpath, char ***keys, void ***values, int **value_len, unsigned int *klen)
+{
+       sqlite3 *db;
+       int sql_ret;
+       int ret = 0;
+       int index;
+       const char list_query[] = "select * from buxton ORDER BY key";
+       const char count_query[] = "select count(key) from buxton";
+       sqlite3_stmt *stmt;
+       int key_count = 0;
+       char **key_list = NULL;
+       void **value_list = NULL;
+       int *value_len_list = NULL;
+
+       if (!dbpath || !*dbpath || !keys || !values || !value_len) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       db = open_sqlite3(dbpath, true);
+       if (!db)
+               return -1;
+
+       sql_ret = sqlite3_prepare_v2(db, count_query, strlen(count_query),
+                       &stmt, NULL);
+       if (sql_ret != SQLITE_OK) {
+               bxt_err("prepare error, ret = %d, extended = %d\n",
+                               sql_ret, sqlite3_extended_errcode(db));
+               return -1;
+       }
+
+       sql_ret = sqlite3_step(stmt);
+       if (sql_ret == SQLITE_ROW) {
+               key_count = (int)sqlite3_column_int(stmt, 0);
+       } else {
+               bxt_err("sqlite3_step error, ret = %d, extended = %d\n",
+                               sql_ret, sqlite3_extended_errcode(db));
+               ret = -1;
+               goto end;
+       }
+
+       sqlite3_finalize(stmt);
+       stmt = NULL;
+
+       sql_ret = sqlite3_prepare_v2(db, list_query, strlen(list_query),
+                       &stmt, NULL);
+       if (sql_ret != SQLITE_OK) {
+               bxt_err("prepare error, ret = %d, extended = %d\n",
+                               sql_ret, sqlite3_extended_errcode(db));
+               ret = -1;
+               goto end;
+       }
+
+       key_list = calloc(key_count + 1, sizeof(char *));
+       value_list = calloc(key_count + 1, sizeof(void *));
+       value_len_list = calloc(key_count + 1, sizeof(int));
+
+       if (!key_list || !value_list || !value_len_list) {
+               bxt_err("calloc error OOM");
+               ret = -1;
+               goto end;
+       }
+
+       for (index = 0; index < key_count; index++) {
+               sql_ret = sqlite3_step(stmt);
+               if (sql_ret != SQLITE_ROW) {
+                       bxt_err("sqlite3_step error, ret = %d, extended = %d index = %d , count = %d",
+                               sql_ret, sqlite3_extended_errcode(db), index, key_count);
+                       ret = -1;
+                       goto end;
+               }
+
+               key_list[index] = strdup((char *)sqlite3_column_text(stmt, 0));
+               value_len_list[index] = sqlite3_column_bytes(stmt, 1);
+               if (value_len_list[index] > 0) {
+                       value_list[index] = malloc(sizeof(void *) * (value_len_list[index] + 1));
+                       if (value_list[index] == NULL) {
+                               bxt_err("malloc error");
+                               ret = -1;
+                               goto end;
+                       }
+                       memcpy(value_list[index], (void *)sqlite3_column_blob(stmt, 1), value_len_list[index]);
+               } else {
+                       value_list[index] = NULL;
+               }
+       }
+
+       *keys = key_list;
+       *values = value_list;
+       *value_len = value_len_list;
+       *klen = key_count;
+
+end:
+       if (stmt != NULL) {
+               sql_ret = sqlite3_finalize(stmt);
+               if (sql_ret != SQLITE_OK) {
+                       bxt_err("Sqlite3 error [%d] : <%s> finalizing statement\n", sql_ret,
+                                       sqlite3_errmsg(db));
+                       ret = -1;
+               }
+       }
+
+       if (ret != 0) {
+               if (key_list) {
+                       for (index = 0; index < key_count; index++) {
+                               if (key_list[index])
+                                       free(key_list[index]);
+                       }
+                       free(key_list);
+               }
+
+               if (value_list) {
+                       for (index = 0; index < key_count; index++) {
+                               if (value_list[index])
+                                       free(value_list[index]);
+                       }
+                       free(value_list);
+               }
+
+               if (value_len_list)
+                       free(value_len_list);
+       }
+
+       bxt_dbg("dump '%s'", dbpath);
+
+       return ret;
+}
+
 static void module_exit(void)
 {
        g_hash_table_destroy(dbs);
@@ -518,5 +647,6 @@ DEFINE_BUXTON_BACKEND = {
        .get_value = get_value,
        .unset_value = unset_value,
        .list_keys = list_keys,
+       .get_dump = get_dump,
 };
 
index 469b595..451d051 100644 (file)
 #include "c_log.h"
 #include "c_common.h"
 #include "c_direct.h"
+#include <inttypes.h>
 
 #define BUFFER_SIZE 1024
 
 static const char *confpath;
+static const char const *type_names[BUXTON_TYPE_MAX] = {
+       [BUXTON_TYPE_UNKNOWN]   = "Unknown",
+       [BUXTON_TYPE_STRING]    = "String",
+       [BUXTON_TYPE_INT32]     = "Int32",
+       [BUXTON_TYPE_UINT32]    = "UInt32",
+       [BUXTON_TYPE_INT64]     = "Int64",
+       [BUXTON_TYPE_UINT64]    = "UInt64",
+       [BUXTON_TYPE_DOUBLE]    = "Double",
+       [BUXTON_TYPE_BOOLEAN]   = "Boolean",
+};
 
 void c_direct_set_conf(const char *conf)
 {
@@ -529,3 +540,75 @@ int c_direct_remove_garbage(const struct buxton_layer *layer,
 
        return 0;
 }
+
+int c_direct_dump(const struct buxton_layer *layer,
+               UNUSED const char *key, UNUSED const char *value,
+               UNUSED const char *rpriv, UNUSED const char *wpriv)
+{
+       int r, key_len, i;
+       struct buxton_value *value_list;
+       char **key_list;
+       char err_buf[BUFFER_SIZE];
+
+       if (!layer) {
+               errno = EINVAL;
+               strerror_r(errno, err_buf, sizeof(err_buf));
+               bxt_err("List: Layer '%s': %s",
+                               layer ? buxton_layer_get_name(layer) : "",
+                               err_buf);
+               return -1;
+       }
+
+       r = c_init();
+       if (r == -1)
+               return -1;
+
+       r = direct_dump(layer, &key_list, &value_list, &key_len);
+
+       c_exit();
+
+       if (r == -1) {
+               strerror_r(errno, err_buf, sizeof(err_buf));
+               bxt_err("List: Layer '%s': %s", buxton_layer_get_name(layer),
+                               err_buf);
+               return -1;
+       }
+
+       for (i = 0 ; i < key_len; i++) {
+               printf("%s, value = ", key_list[i]);
+
+               switch (value_list[i].type) {
+               case BUXTON_TYPE_STRING:
+                       printf("%s (%s)\n", value_list[i].value.s, type_names[value_list[i].type]);
+                       free(value_list[i].value.s);
+                       break;
+               case BUXTON_TYPE_INT32:
+                       printf("%d (%s)\n", value_list[i].value.i, type_names[value_list[i].type]);
+                       break;
+               case BUXTON_TYPE_UINT32:
+                       printf("%u (%s)\n", value_list[i].value.u, type_names[value_list[i].type]);
+                       break;
+               case BUXTON_TYPE_INT64:
+                       printf("%" PRId64 " (%s)\n", value_list[i].value.i64, type_names[value_list[i].type]);
+                       break;
+               case BUXTON_TYPE_UINT64:
+                       printf("%" PRIu64 " (%s)\n", value_list[i].value.u64, type_names[value_list[i].type]);
+                       break;
+               case BUXTON_TYPE_DOUBLE:
+                       printf("%lf (%s)\n", value_list[i].value.d, type_names[value_list[i].type]);
+                       break;
+               case BUXTON_TYPE_BOOLEAN:
+                       printf("%s (%s)\n", value_list[i].value.b ? "True" : "False", type_names[value_list[i].type]);
+                       break;
+               default:
+                       printf("Unknown type\n");
+                       break;
+               }
+       }
+
+       buxton_free_keys(key_list);
+       free(value_list);
+
+       return 0;
+}
+
index 1a9a178..9c0a0ed 100644 (file)
@@ -93,4 +93,7 @@ int c_direct_create_bool(const struct buxton_layer *layer,
 int c_direct_remove_garbage(UNUSED const struct buxton_layer *layer,
                UNUSED const char *key, UNUSED const char *value,
                UNUSED const char *rpriv, UNUSED const char *wpriv);
+int c_direct_dump(const struct buxton_layer *layer,
+               UNUSED const char *key, UNUSED const char *value,
+               UNUSED const char *rpriv, UNUSED const char *wpriv);
 
index dcd63a8..344a816 100644 (file)
@@ -254,6 +254,14 @@ static const struct command const commands[] = {
                .func    = c_direct_remove_garbage,
                .dfunc   = c_direct_remove_garbage,
        },
+       {
+               .name    = "dump",
+               .summary = "Dump for a layer",
+               .nargs   = 1,
+               .usage   = "LAYER",
+               .func    = c_direct_dump,
+               .dfunc   = c_direct_dump,
+       },
 };
 
 static const struct command *find_comm(const char *name)
index f3c29c3..7db0627 100644 (file)
@@ -38,6 +38,8 @@ typedef int (*backend_get_value)(const char *dbpath,
 typedef int (*backend_unset_value)(const char *dbpath, const char *key);
 typedef int (*backend_list_keys)(const char *dbpath,
                char ***keys, unsigned int *klen, bool readonly);
+typedef int (*backend_get_dump)(const char *dbpath,
+               char ***keys, void ***values, int **value_len, unsigned int *klen);
 
 struct backend {
        const char *name;
@@ -52,6 +54,7 @@ struct backend {
        backend_get_value get_value;
        backend_unset_value unset_value;
        backend_list_keys list_keys;
+       backend_get_dump get_dump;
 
        void *reserved[7];
 };
index fc38989..e953459 100644 (file)
@@ -488,6 +488,115 @@ int direct_list(const struct buxton_layer *layer,
        return 0;
 }
 
+int direct_dump(const struct buxton_layer *layer,
+               char ***key_list, struct buxton_value **value_list, int *len)
+{
+       int ret;
+       const struct layer *ly;
+       const struct backend *backend;
+       char path[FILENAME_MAX];
+       unsigned int base_len, nomal_len;
+       int i, j;
+       struct buxton_value *_value_list = NULL;
+       char **base_keys = NULL, **normal_keys = NULL;
+       void **base_values = NULL, **normal_values = NULL;
+       int *base_value_len = NULL, *normal_value_len = NULL;
+       void *tmp;
+       int len_tmp;
+
+       if (!layer || !key_list || !value_list || !len) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       ly = conf_get_layer(layer->name);
+       if (!ly)
+               return -1;
+
+       backend = backend_get(ly->backend);
+       assert(backend);
+
+       if (!backend->get_dump) {
+               bxt_err("dump: backend '%s' has no list func",
+                               backend->name);
+               return -1;
+       }
+
+       ret = get_path(layer->uid, BUXTON_LAYER_BASE,
+                       ly, path, sizeof(path));
+       if (ret == -1)
+               return -1;
+
+       /*base_keys is sorted data */
+       ret = backend->get_dump(path, &base_keys, &base_values, &base_value_len, &base_len);
+       if (ret == -1) {
+               bxt_err("dump: get_dump failed");
+               return -1;
+       }
+
+       ret = get_path(layer->uid, BUXTON_LAYER_NORMAL,
+                       ly, path, sizeof(path));
+       if (ret == -1) {
+               buxton_free_keys(base_keys);
+               buxton_free_keys((char **)base_values);
+               goto out;
+       }
+
+       /* normal_keys is sorted data */
+       ret = backend->get_dump(path, &normal_keys, &normal_values, &normal_value_len, &nomal_len);
+       if (ret == -1) {
+               bxt_err("dump: get_dump failed");
+               goto out;
+       }
+
+       _value_list = calloc(base_len, sizeof(struct buxton_value));
+       if (_value_list == NULL) {
+               bxt_err("dump: calloc failed");
+               ret = -1;
+               goto out;
+       }
+
+       for (i = 0, j = 0; i < base_len; i++) {
+               if (j < nomal_len) {
+                       if (strcmp(base_keys[i], normal_keys[j]) == 0) {
+                               tmp = normal_values[j];
+                               len_tmp = normal_value_len[j];
+                               j++;
+                       } else {
+                               tmp = base_values[i];
+                               len_tmp = base_value_len[i];
+                       }
+               } else {
+                       tmp = base_values[i];
+                       len_tmp = base_value_len[i];
+               }
+               ret = deserialz_data((uint8_t *)tmp, len_tmp, NULL, NULL, &_value_list[i]);
+               if (ret == -1) {
+                       bxt_err("dump: deserialz_data failed %s ", base_keys[i]);
+                       goto out;
+               }
+       }
+
+       *key_list = base_keys;
+       *value_list = _value_list;
+       *len = base_len;
+
+out:
+       buxton_free_keys((char **)base_values);
+       buxton_free_keys(normal_keys);
+       buxton_free_keys((char **)normal_values);
+       free(base_value_len);
+       free(normal_value_len);
+
+       if (ret != 0) {
+               buxton_free_keys(base_keys);
+
+               if (_value_list)
+                       free(_value_list);
+       }
+       return ret;
+}
+
 int direct_get_priv(const struct buxton_layer *layer,
                const char *key, enum buxton_priv_type type, char **priv)
 {
index ac0ef0a..380877c 100644 (file)
@@ -43,3 +43,6 @@ int direct_set_priv(const struct buxton_layer *layer,
                const char *key, enum buxton_priv_type type, const char *priv);
 
 int direct_remove_db(const struct buxton_layer *layer);
+
+int direct_dump(const struct buxton_layer *layer,
+               char ***key_list, struct buxton_value **value_list, int *len);
old mode 100755 (executable)
new mode 100644 (file)
index 833b46c..acf6ad6
@@ -97,6 +97,15 @@ do_get() {
        fi
 }
 
+do_dump() {
+       [ -z "${OPT_KEY}" ] && echo "Invalid key name" && usage
+
+       LAYER=`get_layer ${OPT_KEY}`
+
+       dbg ${BUXTONTOOL} ${OPT_DIRECT} dump ${LAYER}
+       ${BUXTONTOOL} ${OPT_DIRECT} dump ${LAYER}
+}
+
 do_unset() {
        [ -z "${OPT_KEY}" ] && echo "Invalid key name" && usage
 
@@ -323,6 +332,7 @@ set)   do_set ;;
 unset) do_unset ;;
 backup) do_backup ;;
 restore) do_restore ;;
+dump) do_dump ;;
 *)     usage ;;
 esac