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);
.get_value = get_value,
.unset_value = unset_value,
.list_keys = list_keys,
+ .get_dump = get_dump,
};
#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)
{
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;
+}
+
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);
.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)
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;
backend_get_value get_value;
backend_unset_value unset_value;
backend_list_keys list_keys;
+ backend_get_dump get_dump;
void *reserved[7];
};
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)
{
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);
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
unset) do_unset ;;
backup) do_backup ;;
restore) do_restore ;;
+dump) do_dump ;;
*) usage ;;
esac