summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packaging/capi-appfw-application.spec4
-rw-r--r--preference/CMakeLists.txt8
-rw-r--r--preference/pref_dump.sh16
-rwxr-xr-xpreference/preference_tool.c800
4 files changed, 826 insertions, 2 deletions
diff --git a/packaging/capi-appfw-application.spec b/packaging/capi-appfw-application.spec
index d58f574..2621015 100644
--- a/packaging/capi-appfw-application.spec
+++ b/packaging/capi-appfw-application.spec
@@ -59,7 +59,9 @@ cp LICENSE %{buildroot}%{_datadir}/license/%{name}
%{_libdir}/libcapi-appfw-app-common.so.*
%{_libdir}/libcapi-appfw-preference.so.*
%{_libdir}/libcapi-appfw-event.so.*
-
+%{_bindir}/preference_tool
+%attr(0700,root,root) /usr/bin/preference_tool
+%attr(755,root,root) /opt/etc/dump.d/module.d/pref_dump.sh
%{_datadir}/license/%{name}
%files devel
diff --git a/preference/CMakeLists.txt b/preference/CMakeLists.txt
index 21da809..25e6787 100644
--- a/preference/CMakeLists.txt
+++ b/preference/CMakeLists.txt
@@ -35,6 +35,12 @@ add_library(${fw_name} SHARED
preference_inoti.c
)
+add_executable(preference_tool
+ preference_tool.c
+ )
+TARGET_LINK_LIBRARIES(preference_tool ${fw_name} -pie)
+INSTALL(TARGETS preference_tool DESTINATION bin)
+
TARGET_LINK_LIBRARIES(${fw_name} capi-appfw-app-common ${${fw_name}_LDFLAGS})
SET_TARGET_PROPERTIES(${fw_name}
@@ -62,5 +68,5 @@ CONFIGURE_FILE(
@ONLY
)
INSTALL(FILES ${CMAKE_SOURCE_DIR}/${fw_name}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
-
+INSTALL(FILES pref_dump.sh DESTINATION /opt/etc/dump.d/module.d)
diff --git a/preference/pref_dump.sh b/preference/pref_dump.sh
new file mode 100644
index 0000000..575ebc9
--- /dev/null
+++ b/preference/pref_dump.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+PREF_DUMP=$1/pref
+/bin/mkdir -p $PREF_DUMP
+
+for file in `/usr/bin/find /opt/usr/apps/ -name *.pref`
+do
+ chsmack $file >> $PREF_DUMP/pref_value
+ chsmack $file/* >> $PREF_DUMP/pref_value
+ ls -alZ $file >> $PREF_DUMP/pref_value
+ PKG_ID=`echo "$file" | awk -F'/' '{print $5}'`
+ /usr/bin/preference_tool get $PKG_ID >> $PREF_DUMP/pref_value
+ mkdir -p $PREF_DUMP/$PKG_ID
+ cp -rf --preserve=all $file/* $PREF_DUMP/$PKG_ID
+ echo "===============================================" >> $PREF_DUMP/pref_value
+done
diff --git a/preference/preference_tool.c b/preference/preference_tool.c
new file mode 100755
index 0000000..093391e
--- /dev/null
+++ b/preference/preference_tool.c
@@ -0,0 +1,800 @@
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <wordexp.h>
+#include <sqlite3.h>
+#include <glib.h>
+
+#include <app_internal.h>
+#include <app_preference.h>
+#include <app_preference_internal.h>
+
+#define PREF_F_KEY_NAME "pref_key"
+#define PREF_F_TYPE_NAME "pref_type"
+#define PREF_F_DATA_NAME "pref_data"
+#define PREF_TBL_NAME "pref"
+
+#define DELIMITER 29
+#define HISTORY "/opt/var/kdb/.restore/.history/preference"
+
+typedef enum {
+ PREFERENCE_OLD_TYPE_INT = 1,
+ PREFERENCE_OLD_TYPE_BOOLEAN,
+ PREFERENCE_OLD_TYPE_DOUBLE,
+ PREFERENCE_OLD_TYPE_STRING
+} old_preference_type_e;
+
+typedef enum {
+ PREFERENCE_OP_RESTORE = 1,
+ PREFERENCE_OP_NEW_CREATE
+} preference_op_type;
+
+static sqlite3 *pref_db;
+
+static void _finish(void *data)
+{
+ if (pref_db != NULL) {
+ sqlite3_close(pref_db);
+ pref_db = NULL;
+ }
+}
+
+static int _busy_handler(void *pData, int count)
+{
+ if (count < 5) {
+ printf("Busy Handler Called!: PID(%d) / CNT(%d)\n",
+ getpid(), count + 1);
+ usleep((count + 1) * 100000);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int _initialize(const char *db_path)
+{
+ int ret;
+ char *path = strdup(db_path);
+
+ if (!path) {
+ printf("error, strdup(): Insufficient memory available\n");
+ return -1;
+ }
+
+ ret = sqlite3_open(path, &pref_db);
+ if (ret != SQLITE_OK) {
+ printf("error, fail to open db\n");
+ pref_db = NULL;
+ free(path);
+ return -1;
+ }
+
+ ret = sqlite3_busy_handler(pref_db, _busy_handler, NULL);
+ if (ret != SQLITE_OK)
+ printf("error, fail to resigter busy handler\n");
+ app_finalizer_add(_finish, NULL);
+ free(path);
+
+ return 0;
+}
+
+static int __system(const char *cmd)
+{
+ int status;
+ pid_t cpid;
+ wordexp_t p;
+ char **w;
+
+ cpid = fork();
+ if (cpid < 0) {
+ perror("fork");
+ return -1;
+ }
+
+ if (cpid == 0) {
+ /* child */
+ wordexp(cmd, &p, 0);
+ w = p.we_wordv;
+
+ execv(w[0], (char * const *)w);
+
+ wordfree(&p);
+
+ _exit(-1);
+ } else {
+ /* parent */
+ if (waitpid(cpid, &status, 0) == -1) {
+ perror("waitpid failed\n");
+ return -1;
+ }
+
+ if (WIFSIGNALED(status)) {
+ printf("signal(%d)\n", WTERMSIG(status));
+ perror("exit by signal\n");
+ return -1;
+ }
+
+ if (!WIFEXITED(status)) {
+ perror("exit abnormally\n");
+ return -1;
+ }
+
+ if (WIFEXITED(status) && WEXITSTATUS(status)) {
+ perror("child return error\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int is_exist_package(const char *pkgid)
+{
+ char pkg_path[PATH_MAX];
+
+ snprintf(pkg_path, sizeof(pkg_path), "/opt/usr/apps/%s", pkgid);
+ if (access(pkg_path, F_OK) == -1) {
+ printf("package(%s) is not exist.\n", pkgid);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int is_exist_data_dir_in_package(const char *pkgid)
+{
+ char pkg_data_path[PATH_MAX];
+
+ snprintf(pkg_data_path, sizeof(pkg_data_path),
+ "/opt/usr/apps/%s/data/", pkgid);
+ if (access(pkg_data_path, F_OK) == -1) {
+ printf("Data directory is not exist in package(%s).\n", pkgid);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int _make_key_path(const char *pkgid, const char *keyname, char *path)
+{
+ const char *key;
+ gchar *convert_key;
+ char pref_dir[PATH_MAX];
+ char cmd[PATH_MAX];
+ mode_t dir_mode = 0664 | 0111;
+
+ snprintf(pref_dir, sizeof(pref_dir), "/opt/usr/apps/%s/data/.pref",
+ pkgid);
+ if (access(pref_dir, F_OK) == -1) {
+ if (mkdir(pref_dir, dir_mode) < 0) {
+ if (is_exist_package(pkgid) < 0)
+ return -1;
+
+ if (is_exist_data_dir_in_package(pkgid) < 0)
+ return -1;
+
+ printf("pref_dir making failed.(%d/%s)\n",
+ errno, strerror(errno));
+ return -1;
+ }
+ if (chown(pref_dir, 5000, 5000) < 0) {
+ printf("chown() failed(%d/%s)\n",
+ errno, strerror(errno));
+ return -1;
+ }
+ }
+
+ snprintf(cmd, sizeof(cmd), "/usr/bin/chsmack -a \"%s\" %s",
+ pkgid, pref_dir);
+ if (__system(cmd)) {
+ printf("[pref] cmd error()\n");
+ return -1;
+ }
+
+ convert_key = g_compute_checksum_for_string(G_CHECKSUM_SHA1,
+ keyname, strlen(keyname));
+ if (convert_key == NULL) {
+ LOGE("fail to convert");
+ return PREFERENCE_ERROR_IO_ERROR;
+ }
+
+ key = (const char *)convert_key;
+ snprintf(path, PATH_MAX, "%s/%s", pref_dir, key);
+ g_free(convert_key);
+
+ return 0;
+}
+
+static int _get_key_name(const char *keyfile, char **keyname)
+{
+ int read_size = 0;
+ size_t keyname_len = 0;
+ char *convert_key = NULL;
+ FILE *fp = NULL;
+
+ fp = fopen(keyfile, "r");
+ if (fp == NULL)
+ return PREFERENCE_ERROR_FILE_OPEN;
+
+ read_size = fread((void *)&keyname_len, sizeof(int), 1, fp);
+ if (read_size <= 0 || keyname_len > PREFERENCE_KEY_PATH_LEN) {
+ fclose(fp);
+ return PREFERENCE_ERROR_FILE_FREAD;
+ }
+
+ convert_key = (char *)calloc(1, keyname_len + 1);
+ if (convert_key == NULL) {
+ LOGE("memory alloc failed");
+ fclose(fp);
+ return PREFERENCE_ERROR_OUT_OF_MEMORY;
+ }
+
+ read_size = fread((void *)convert_key, keyname_len, 1, fp);
+ if (read_size <= 0) {
+ free(convert_key);
+ fclose(fp);
+ return PREFERENCE_ERROR_FILE_FREAD;
+ }
+
+ *keyname = convert_key;
+
+ fclose(fp);
+
+ return PREFERENCE_ERROR_NONE;
+}
+
+static int _create_key(const char *path, const char *pkgid)
+{
+ int fd;
+ char cmd[1024];
+
+ fd = open(path, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
+ if (fd == -1) {
+ printf("[error] %d(%s)\n", errno, strerror(errno));
+ return -1;
+ }
+ if (fchown(fd, 5000, 5000) < 0) {
+ printf("fchown() failed(%d/%s)\n", errno, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ snprintf(cmd, sizeof(cmd), "/usr/bin/chsmack -a \"%s\" %s",
+ pkgid, path);
+ if (__system(cmd)) {
+ printf("[pref]create_key: cmd error()\n");
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ return 0;
+}
+
+static int _create_new_preference_key(preference_op_type OP, const char *pkgid,
+ const char *key, const char *type, const char *value)
+{
+ FILE *fp;
+ int ret;
+ char key_path[PATH_MAX] = {0,};
+ size_t keyname_len;
+ int type_i;
+ int temp_i;
+ double temp_d;
+ locale_t loc;
+
+ _make_key_path(pkgid, key, key_path);
+retry:
+ fp = fopen(key_path, "r+");
+ if (fp == NULL) {
+ if (_create_key(key_path, pkgid) == -1) {
+ printf("preference key failed to create.(%d/%s)\n",
+ errno, strerror(errno));
+ return -1;
+ }
+
+ goto retry;
+ }
+
+ /* write keyname and size */
+ keyname_len = strlen(key);
+ ret = fwrite((void *)&keyname_len, sizeof(int), 1, fp);
+ if (ret <= 0) {
+ printf("preference write key name length error(%d/%s)\n",
+ errno, strerror(errno));
+ fclose(fp);
+ return -1;
+ }
+
+ ret = fwrite((void *)key, keyname_len, 1, fp);
+ if (ret <= 0) {
+ printf("preference write key name length error(%d/%s)\n",
+ errno, strerror(errno));
+ fclose(fp);
+ return -1;
+ }
+
+ loc = newlocale(LC_NUMERIC_MASK, "C", NULL);
+ uselocale(loc);
+
+ if (OP == PREFERENCE_OP_RESTORE) {
+ type_i = atoi(type);
+ switch (type_i) {
+ case PREFERENCE_OLD_TYPE_INT:
+ type_i = PREFERENCE_TYPE_INT;
+ break;
+ case PREFERENCE_OLD_TYPE_DOUBLE:
+ type_i = PREFERENCE_TYPE_DOUBLE;
+ break;
+ case PREFERENCE_OLD_TYPE_BOOLEAN:
+ type_i = PREFERENCE_TYPE_BOOLEAN;
+ break;
+ case PREFERENCE_OLD_TYPE_STRING:
+ type_i = PREFERENCE_TYPE_STRING;
+ break;
+ default:
+ break;
+ }
+ } else { /* OP is PREFERENCE_OP_NEW_CREATE.*/
+ if (strcmp(type, "int") == 0) {
+ type_i = PREFERENCE_TYPE_INT;
+ } else if (strcmp(type, "double") == 0) {
+ type_i = PREFERENCE_TYPE_DOUBLE;
+ } else if (strcmp(type, "bool") == 0) {
+ type_i = PREFERENCE_TYPE_BOOLEAN;
+ } else if (strcmp(type, "string") == 0) {
+ type_i = PREFERENCE_TYPE_STRING;
+ } else {
+ printf("key type is invalid.int|double|bool|string\n");
+ fclose(fp);
+ return -1;
+ }
+ }
+
+ ret = fwrite((void *)&type_i, sizeof(int), 1, fp);
+ if (ret <= 0) {
+ if (!errno) {
+ printf("number of written item is 0. try again\n");
+ errno = EAGAIN;
+ }
+ }
+
+ switch (type_i) {
+ case PREFERENCE_TYPE_INT:
+ temp_i = atoi(value);
+ ret = fwrite((void *)&temp_i, sizeof(int), 1, fp);
+ if (ret <= 0) {
+ printf("failed. fwrite() %d\n", ret);
+ } else {
+ printf("[SET][key]:%s [type]int[value]:%d\n",
+ key, temp_i);
+ }
+ break;
+ case PREFERENCE_TYPE_DOUBLE:
+ temp_d = atof(value);
+ ret = fwrite((void *)&temp_d, sizeof(double), 1, fp);
+ if (ret <= 0) {
+ printf("failed. fwrite() %d\n", ret);
+ } else {
+ printf("[SET][key]:%s[type]double[value]:%f\n",
+ key, temp_d);
+ }
+ break;
+ case PREFERENCE_TYPE_BOOLEAN:
+ temp_i = atoi(value);
+ ret = fwrite((void *)&temp_i, sizeof(int), 1, fp);
+ if (ret <= 0) {
+ printf("failed. fwrite() %d\n", ret);
+ } else {
+ printf("[SET][key]:%s [type]bool[value]:%d\n",
+ key, temp_i);
+ }
+ break;
+ case PREFERENCE_TYPE_STRING:
+ printf("[SET][key]:%s [type] string [value] %s\n",
+ key, value);
+ ret = fprintf(fp, "%s", value);
+ if (ftruncate(fileno(fp), ret) == -1) {
+ printf("[error] ftruncate failed %s(%s)\n",
+ key_path, value);
+ }
+ break;
+ default:
+ break;
+ }
+
+ uselocale(LC_GLOBAL_LOCALE);
+ fflush(fp);
+ if (fp) {
+ ret = fdatasync(fileno(fp));
+ fclose(fp);
+ }
+
+ return 0;
+}
+
+static int _print_pref_value_from_file_path(const char *path,
+ const char *keyname)
+{
+ FILE *fp;
+ int type = 0;
+ int read_size;
+ size_t keyname_len = 0;
+ int ret;
+ int value_int = 0;
+ double value_dbl = 0;
+ char file_buf[BUF_LEN] = {0,};
+ char *value_str = NULL;
+ int value_size = 0;
+
+ fp = fopen(path, "r");
+ if (fp == NULL) {
+ printf("fopen() failed.(%d/%s).fp is null.\n",
+ errno, strerror(errno));
+ return -1;
+ }
+
+ read_size = fread((void *)&keyname_len, sizeof(int), 1, fp);
+ if ((read_size <= 0) || (read_size > sizeof(int))) {
+ printf("key(%s) name length read error(%d)\n", keyname, errno);
+ fclose(fp);
+ return -1;
+ }
+
+ ret = fseek(fp, keyname_len, SEEK_CUR);
+ if (ret) {
+ printf("key(%s) name seek error(%d)\n", keyname, errno);
+ fclose(fp);
+ return -1;
+ }
+
+ /* read data type */
+ read_size = fread((void *)&type, sizeof(int), 1, fp);
+ if ((read_size <= 0) || (read_size > sizeof(int))) {
+ printf("key(%s) type read error(%d)\n", keyname, errno);
+ fclose(fp);
+ return -1;
+ }
+
+ /* read data value */
+ switch (type) {
+ case PREFERENCE_TYPE_INT:
+ read_size = fread((void *)&value_int, sizeof(int),
+ 1, fp);
+ if ((read_size <= 0) || (read_size > sizeof(int))) {
+ if (!ferror(fp)) {
+ printf("number of read items wrong.err: %d\n",
+ errno);
+ }
+ } else {
+ printf("[key] %s [type] int [value] %d\n",
+ keyname, value_int);
+ }
+ break;
+ case PREFERENCE_TYPE_DOUBLE:
+ read_size = fread((void *)&value_dbl, sizeof(double),
+ 1, fp);
+ if ((read_size <= 0) || (read_size > sizeof(double))) {
+ if (!ferror(fp)) {
+ printf("number of read items wrong.err:%d\n",
+ errno);
+ }
+ } else {
+ printf("[key] %s [type] double [value] %f\n",
+ keyname, value_dbl);
+ }
+ break;
+ case PREFERENCE_TYPE_BOOLEAN:
+ read_size = fread((void *)&value_int, sizeof(int),
+ 1, fp);
+ if ((read_size <= 0) || (read_size > sizeof(int))) {
+ if (!ferror(fp)) {
+ printf("number of read items wrong.err:%d\n",
+ errno);
+ }
+ } else {
+ printf("[key] %s [type] bool [value] %d\n",
+ keyname, value_int);
+ }
+ break;
+ case PREFERENCE_TYPE_STRING:
+ while (fgets(file_buf, sizeof(file_buf), fp)) {
+ if (value_str) {
+ value_size += strlen(file_buf);
+ value_str = (char *)realloc(value_str,
+ value_size);
+ if (value_str == NULL)
+ break;
+
+ strncat(value_str, file_buf, strlen(file_buf));
+ } else {
+ value_size = strlen(file_buf) + 1;
+ value_str = (char *)malloc(value_size);
+ if (value_str == NULL)
+ break;
+
+ memset(value_str, 0x00, value_size);
+ strncpy(value_str, file_buf, strlen(file_buf));
+ }
+ }
+
+ if (ferror(fp)) {
+ printf("error, fgets() failed.\n");
+ } else {
+ if (value_str) {
+ printf("[key] %s [type] string [value] %s\n",
+ keyname, value_str);
+ } else {
+ printf("[key] %s [value] NULL\n", keyname);
+ }
+ }
+ if (value_str)
+ free(value_str);
+ break;
+ default:
+ break;
+ }
+ fclose(fp);
+
+ return 0;
+}
+
+static int _restore(const char *pkgid)
+{
+ int ret;
+ char *query;
+ sqlite3_stmt *stmt = NULL;
+ const char *tmp_key;
+ const char *tmp_type;
+ const char *tmp_value;
+
+ query = sqlite3_mprintf("SELECT * FROM %s;", PREF_TBL_NAME);
+ if (query == NULL) {
+ printf("error, query is null\n");
+ return -1;
+ }
+
+ /*prepare query*/
+ ret = sqlite3_prepare_v2(pref_db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ printf("error, sqlite3_prepare_v2 failed(%d)\n", ret);
+ return -1;
+ }
+
+ while (1) {
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW) {
+ tmp_key = (const char *)sqlite3_column_text(stmt, 0);
+ tmp_type = (const char *)sqlite3_column_text(stmt, 1);
+ tmp_value = (const char *)sqlite3_column_text(stmt, 2);
+
+ printf("col[key]:%s\ncol[type]:%s\ncol[value]:%s\n",
+ tmp_key, tmp_type, tmp_value);
+
+ /*key create*/
+ ret = _create_new_preference_key(PREFERENCE_OP_RESTORE,
+ pkgid, tmp_key, tmp_type, tmp_value);
+ if (ret < 0) {
+ printf("create new prefer key failed (%d)\n",
+ ret);
+ return -1;
+ }
+ } else {
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
+static int _remove_old_db(const char *db_path)
+{
+ int ret;
+ char journal_path[PATH_MAX];
+ char *path = strdup(db_path);
+
+ if (!path) {
+ printf("error, strdup(): Insufficient memory available\n");
+ return -1;
+ }
+
+ ret = remove(path);
+ if (ret < 0) {
+ printf("error, remove(%d/%s)\n", errno, strerror(errno));
+ free(path);
+ return -1;
+ }
+
+ snprintf(journal_path, sizeof(journal_path), "%s-journal", path);
+
+ if (access(journal_path, F_OK) == 0) {
+ ret = remove(journal_path);
+ if (ret < 0) {
+ printf("error, remove(%d/%s)\n", errno,
+ strerror(errno));
+ free(path);
+ return -1;
+ }
+ }
+ free(path);
+
+ return 0;
+}
+
+static void _print_help(void)
+{
+ printf("\n[Set preference value]\n");
+ printf("preference_tool set <pkgid> <key_name> <type> <value>\n");
+ printf("ex) preference_tool set ");
+ printf("org.tizen.preferencetest test_key string value\n\n");
+
+ printf("[Get preference value]\n");
+ printf("preference_tool get <pkgid>\n");
+ printf("ex) preference_tool get org.tizen.preferencetest\n\n");
+ printf("preference_tool get <pkgid> <key>\n");
+ printf("ex) preference_tool get ");
+ printf("org.tizen.preferencetest test_key\n\n");
+}
+
+static void _preference_set_key(const char *pkgid, const char *key,
+ const char *type, const char *value)
+{
+ _create_new_preference_key(PREFERENCE_OP_NEW_CREATE,
+ pkgid, key, type, value);
+}
+
+static void _print_preference_key(const char *pkgid, const char *key)
+{
+ char key_path[PATH_MAX] = {0,};
+
+ _make_key_path(pkgid, key, key_path);
+ _print_pref_value_from_file_path(key_path, key);
+}
+
+static void _print_preference_in_package(const char *pkgid)
+{
+ char pref_dir[PATH_MAX];
+ DIR *dir;
+ int dfd;
+ struct stat st;
+ int res;
+ struct dirent *ent = NULL;
+ const char *name;
+ char *keyname = NULL;
+ char file_full_path[PATH_MAX];
+
+ snprintf(pref_dir, sizeof(pref_dir), "/opt/usr/apps/%s/data/.pref",
+ pkgid);
+
+ dir = opendir(pref_dir);
+ if (dir == NULL) {
+ printf("Is not exist preference key in %s.\n", pkgid);
+ return;
+ }
+
+ dfd = dirfd(dir);
+ res = fstat(dfd, &st);
+ if (res < 0) {
+ printf("fstat() failed. path: %s, errno: %d(%s)\n",
+ pref_dir, errno, strerror(errno));
+ closedir(dir);
+ return;
+ }
+
+ while ((ent = readdir(dir))) {
+ name = ent->d_name;
+ if (name[0] == '.') {
+ if (name[1] == '\0')
+ continue;
+ if ((name[1] == '.') && (name[2] == '\0'))
+ continue;
+ }
+
+ snprintf(file_full_path, sizeof(file_full_path), "%s/%s",
+ pref_dir, name);
+ _get_key_name(file_full_path, &keyname);
+ _print_pref_value_from_file_path(file_full_path, keyname);
+ if (keyname) {
+ free(keyname);
+ keyname = NULL;
+ }
+ }
+ closedir(dir);
+}
+
+static void write_history(const char *str)
+{
+ FILE *fp = NULL;
+ int ret = 0;
+
+ fp = fopen(HISTORY, "a");
+ if (fp == NULL) {
+ printf("fopen() failed. FOTA history log (%d/%s)",
+ errno, strerror(errno));
+ return;
+ }
+
+ ret = fwrite((void *)str, strlen(str) + 1, 1, fp);
+ if (ret <= 0) {
+ printf("fwrite() failed. FOTA history log (%d/%s)",
+ errno, strerror(errno));
+ }
+ fclose(fp);
+}
+
+int main(int argc, char *argv[])
+{
+ int res;
+
+ if (getuid() != 0) {
+ printf("[pref] Only root user can use.\n");
+ return -1;
+ }
+
+ if (argc < 3) {
+ _print_help();
+ return -1;
+ }
+
+ if (strcmp(argv[1], "restore") == 0 && argc == 4) {
+ printf("[ start ] ----------------------------------------\n");
+ printf("Db file path:%s\n\n", argv[2]);
+
+ res = _initialize(argv[2]);
+ if (res < 0) {
+ printf("failed. _initialize(%d)\n", res);
+ return -1;
+ }
+
+ res = _restore(argv[3]);
+ if (res < 0) {
+ printf("failed. _restore(%d)\n", res);
+ write_history("\t\t- restore failed.\n");
+ printf("restore failed.\n");
+ return -1;
+ }
+
+ res = _remove_old_db(argv[2]);
+ if (res < 0) {
+ printf("failed. _remove_old_db(%d)\n", res);
+ return -1;
+ }
+
+ printf("-------------------------------------------------\n");
+ printf("done\n\n");
+ write_history("\t\t+ restore success.\n");
+ } else if (strcmp(argv[1], "get") == 0 || strcmp(argv[1], "GET") == 0) {
+ if (is_exist_package(argv[2]) < 0)
+ return -1;
+
+ if (is_exist_data_dir_in_package(argv[2]) < 0)
+ return -1;
+
+ if (argv[3])
+ _print_preference_key(argv[2], argv[3]);
+ else
+ _print_preference_in_package(argv[2]);
+ } else if (strcmp(argv[1], "set") == 0 || strcmp(argv[1], "SET") == 0) {
+ if (is_exist_package(argv[2]) < 0)
+ return -1;
+
+ if (is_exist_data_dir_in_package(argv[2]) < 0)
+ return -1;
+
+ if (argv[2] && argv[3] && argv[4] && argv[5])
+ _preference_set_key(argv[2], argv[3], argv[4], argv[5]);
+ else
+ _print_help();
+ } else {
+ _print_help();
+ }
+
+ return 0;
+}