vc_config_enabled_cb enabled_cb;
} vc_config_client_s;
+/* for engine directory monitoring */
+typedef struct {
+ Ecore_Fd_Handler* dir_fd_handler;
+ int dir_fd;
+ int dir_wd;
+} vc_engine_inotify_s;
const char* vc_config_tag()
{
static int g_fd_lang;
static int g_wd_lang;
+static GList* g_ino_list = NULL;
+
static pthread_mutex_t vc_config_mgr_mutex = PTHREAD_MUTEX_INITIALIZER;
-int __vc_config_mgr_print_engine_info();
+static int __vc_config_mgr_register_engine_config_updated_event(const char* path);
+static int __vc_config_mgr_unregister_engine_config_updated_event();
+int __vc_config_mgr_print_engine_info();
int __vc_config_mgr_print_client_info();
int vc_config_convert_error_code(vc_config_error_e code)
return VC_ERROR_OPERATION_FAILED;
}
+int __vc_config_release_client(int uid)
+{
+ GSList *iter = NULL;
+ vc_config_client_s* temp_client = NULL;
+
+ if (0 < g_slist_length(g_config_client_list)) {
+ /* Check uid */
+ iter = g_slist_nth(g_config_client_list, 0);
+
+ while (NULL != iter) {
+ temp_client = iter->data;
+
+ if (NULL != temp_client) {
+ if (uid == temp_client->uid) {
+ g_config_client_list = g_slist_remove(g_config_client_list, temp_client);
+ free(temp_client);
+ break;
+ }
+ }
+
+ iter = g_slist_next(iter);
+ }
+ }
+
+ SLOG(LOG_DEBUG, vc_config_tag(), "Client count (%d)", g_slist_length(g_config_client_list));
+
+ return g_slist_length(g_config_client_list);
+}
+
+void __vc_config_release_engine()
+{
+ GSList *iter = NULL;
+ vc_engine_info_s *engine_info = NULL;
+
+ if (0 < g_slist_length(g_engine_list)) {
+
+ /* Get a first item */
+ iter = g_slist_nth(g_engine_list, 0);
+
+ while (NULL != iter) {
+ engine_info = iter->data;
+
+ if (NULL != engine_info) {
+ g_engine_list = g_slist_remove(g_engine_list, engine_info);
+
+ vc_parser_free_engine_info(engine_info);
+ }
+
+ iter = g_slist_nth(g_engine_list, 0);
+ }
+ }
+
+ return;
+}
+
+int __vc_config_mgr_get_engine_info()
+{
+ DIR *dp = NULL;
+ struct dirent *dirp = NULL;
+
+ char filepath[512] = {'\0',};
+ int filesize;
+ vc_engine_info_s* info = NULL;
+
+ __vc_config_release_engine();
+ g_engine_list = NULL;
+ __vc_config_mgr_unregister_engine_config_updated_event();
+
+ /* Copy default info directory to download directory */
+ dp = opendir(VC_DEFAULT_ENGINE_INFO);
+ if (NULL == dp) {
+ SLOG(LOG_DEBUG, vc_config_tag(), "[CONFIG] No default directory : %s", VC_DEFAULT_ENGINE_INFO);
+ } else {
+ do {
+ dirp = readdir(dp);
+
+ if (NULL != dirp) {
+ if (!strcmp(".", dirp->d_name) || !strcmp("..", dirp->d_name))
+ continue;
+
+ filesize = strlen(VC_DEFAULT_ENGINE_INFO) + strlen(dirp->d_name) + 2;
+ if (filesize >= 512) {
+ SECURE_SLOG(LOG_ERROR, vc_config_tag(), "[CONFIG ERROR] File path is too long : %s", dirp->d_name);
+ closedir(dp);
+ return -1;
+ }
+
+ memset(filepath, '\0', 512);
+ snprintf(filepath, 512, "%s/%s", VC_DEFAULT_ENGINE_INFO, dirp->d_name);
+
+ SECURE_SLOG(LOG_DEBUG, vc_config_tag(), "[CONFIG] Filepath(%s)", filepath);
+
+ char dest[512] = {'\0',};
+ snprintf(dest, 512, "%s/%s", VC_DOWNLOAD_ENGINE_INFO, dirp->d_name);
+
+ if (0 != access(dest, F_OK)) {
+ if (0 != vc_parser_copy_xml(filepath, dest)) {
+ SLOG(LOG_ERROR, vc_config_tag(), "[CONFIG ERROR] Fail to copy engine info");
+ }
+ }
+ }
+ } while (NULL != dirp);
+
+ closedir(dp);
+ }
+
+ /* Get engine info from default engine directory */
+ dp = opendir(VC_DOWNLOAD_ENGINE_INFO);
+ if (NULL == dp) {
+ SLOG(LOG_DEBUG, vc_config_tag(), "[CONFIG] No downloadable directory : %s", VC_DOWNLOAD_ENGINE_INFO);
+ } else {
+ do {
+ dirp = readdir(dp);
+
+ if (NULL != dirp) {
+ if (!strcmp(".", dirp->d_name) || !strcmp("..", dirp->d_name))
+ continue;
+
+ filesize = strlen(VC_DOWNLOAD_ENGINE_INFO) + strlen(dirp->d_name) + 2;
+ if (filesize >= 512) {
+ SECURE_SLOG(LOG_ERROR, vc_config_tag(), "[CONFIG ERROR] File path is too long : %s", dirp->d_name);
+ closedir(dp);
+ return -1;
+ }
+
+ memset(filepath, '\0', 512);
+ snprintf(filepath, 512, "%s/%s", VC_DOWNLOAD_ENGINE_INFO, dirp->d_name);
+
+ SECURE_SLOG(LOG_DEBUG, vc_config_tag(), "[CONFIG] Filepath(%s)", filepath);
+
+ if (0 == vc_parser_get_engine_info(filepath, &info)) {
+ g_engine_list = g_slist_append(g_engine_list, info);
+ if (0 != __vc_config_mgr_register_engine_config_updated_event(filepath)) {
+ SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to register engine config updated event");
+ }
+ }
+ }
+ } while (NULL != dirp);
+
+ closedir(dp);
+ }
+
+ if (0 >= g_slist_length(g_engine_list)) {
+ SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] No engine");
+ return -1;
+ }
+
+ return 0;
+}
+
+static Eina_Bool __vc_config_mgr_engine_config_inotify_event_callback(void* data, Ecore_Fd_Handler *fd_handler)
+{
+ SLOG(LOG_DEBUG, vc_config_tag(), "@@@ Engine config updated callback event");
+
+ vc_engine_inotify_s *ino = (vc_engine_inotify_s *)data;
+ int dir_fd = ino->dir_fd;
+
+ int length;
+ struct inotify_event event;
+ memset(&event, '\0', sizeof(struct inotify_event));
+
+ length = read(dir_fd, &event, sizeof(struct inotify_event));
+ if (0 > length) {
+ SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty Inotify event");
+ SLOG(LOG_DEBUG, vc_config_tag(), "@@@");
+ return ECORE_CALLBACK_DONE;
+ }
+
+ if (IN_CLOSE_WRITE == event.mask) {
+ int ret = __vc_config_mgr_get_engine_info();
+ if (0 != ret) {
+ SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to get engine info when config updated");
+ }
+ __vc_config_mgr_print_engine_info();
+ bool support = vc_config_check_default_language_is_valid(g_config_info->language);
+ if (false == support) {
+ SLOG(LOG_DEBUG, vc_config_tag(), "[ERROR] Default language is valid");
+ char* temp_lang = NULL;
+ ret = __vc_config_mgr_select_lang(g_config_info->engine_id, &temp_lang);
+ if (0 != ret) {
+ SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to get language");
+ }
+
+ ret = vc_config_mgr_set_default_language(temp_lang);
+ if (0 != ret) {
+ SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to set language");
+ } else {
+ SLOG(LOG_DEBUG, vc_config_tag(), "[DEBUG] Saved default language : lang(%s)", g_config_info->language);
+ }
+ if (NULL != temp_lang) {
+ free(temp_lang);
+ temp_lang = NULL;
+ }
+ }
+ } else {
+ SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Undefined event");
+ }
+
+ SLOG(LOG_DEBUG, vc_config_tag(), "@@@");
+
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static int __vc_config_mgr_register_engine_config_updated_event(const char* path)
+{
+ if (NULL == path) {
+ SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Path is NULL");
+ return -1;
+ }
+
+ /* For engine directory monitoring */
+ vc_engine_inotify_s *ino = (vc_engine_inotify_s *)calloc(1, sizeof(vc_engine_inotify_s));
+ if (NULL == ino) {
+ SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to allocate memory");
+ return -1;
+ }
+
+ ino->dir_fd = inotify_init();
+ if (ino->dir_fd < 0) {
+ SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to init inotify");
+ free(ino);
+ ino = NULL;
+
+ return -1;
+ }
+
+ ino->dir_wd = inotify_add_watch(ino->dir_fd, path, IN_CLOSE_WRITE);
+ SLOG(LOG_DEBUG, vc_config_tag(), "Add inotify watch(%s)", path);
+ if (ino->dir_wd < 0) {
+ SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to add watch");
+ free(ino);
+ ino = NULL;
+ return -1;
+ }
+
+ ino->dir_fd_handler = ecore_main_fd_handler_add(ino->dir_fd, ECORE_FD_READ, (Ecore_Fd_Cb)__vc_config_mgr_engine_config_inotify_event_callback, (void *)ino, NULL, NULL);
+ if (NULL == ino->dir_fd_handler) {
+ SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to add fd handler");
+ free(ino);
+ ino = NULL;
+ return -1;
+ }
+
+ /* Set non-blocking mode of file */
+ int value;
+ value = fcntl(ino->dir_fd, F_GETFL, 0);
+ value |= O_NONBLOCK;
+
+ if (0 > fcntl(ino->dir_fd, F_SETFL, value)) {
+ SLOG(LOG_WARN, vc_config_tag(), "[WARNING] Fail to set non-block mode");
+ }
+
+ g_ino_list = g_list_append(g_ino_list, ino);
+
+ return 0;
+}
+
+static int __vc_config_mgr_unregister_engine_config_updated_event()
+{
+ /* delete all inotify variable */
+ if (0 < g_list_length(g_ino_list)) {
+ GList *iter = NULL;
+ iter = g_list_first(g_ino_list);
+
+ while (NULL != iter) {
+ vc_engine_inotify_s *tmp = iter->data;
+
+ if (NULL != tmp) {
+ ecore_main_fd_handler_del(tmp->dir_fd_handler);
+ inotify_rm_watch(tmp->dir_fd, tmp->dir_wd);
+ close(tmp->dir_fd);
+
+ free(tmp);
+ tmp = NULL;
+ }
+
+ g_ino_list = g_list_remove_link(g_ino_list, iter);
+
+ iter = g_list_first(g_ino_list);
+ }
+ }
+
+ return 0;
+}
+
+
+
+
+
Eina_Bool vc_config_mgr_inotify_event_cb(void* data, Ecore_Fd_Handler *fd_handler)
{
SLOG(LOG_DEBUG, vc_config_tag(), "@@@ Config changed callback event");
}
/* Get file name from default engine directory */
- DIR *dp = NULL;
- struct dirent *dirp;
-
g_engine_list = NULL;
if (0 != access(VC_CONFIG_BASE, F_OK)) {
if (0 != mkdir(VC_CONFIG_BASE, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to make directory : %s", VC_CONFIG_BASE);
+ __vc_config_release_client(uid);
pthread_mutex_unlock(&vc_config_mgr_mutex);
return -1;
} else {
if (0 != access(VC_RUNTIME_INFO_ROOT, F_OK)) {
if (0 != mkdir(VC_RUNTIME_INFO_ROOT, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to make directory : %s", VC_RUNTIME_INFO_ROOT);
+ __vc_config_release_client(uid);
pthread_mutex_unlock(&vc_config_mgr_mutex);
return -1;
} else {
}
}
- dp = opendir(VC_DEFAULT_ENGINE_INFO);
- if (NULL != dp) {
- do {
- dirp = readdir(dp);
-
- if (NULL != dirp) {
- if (!strcmp(".", dirp->d_name) || !strcmp("..", dirp->d_name))
- continue;
-
- vc_engine_info_s* info = NULL;
- char* filepath = NULL;
- int filesize = 0;
-
- filesize = strlen(VC_DEFAULT_ENGINE_INFO) + strlen(dirp->d_name) + 5;
- filepath = (char*)calloc(filesize, sizeof(char));
-
- if (NULL != filepath) {
- snprintf(filepath, filesize, "%s/%s", VC_DEFAULT_ENGINE_INFO, dirp->d_name);
- } else {
- SLOG(LOG_ERROR, vc_config_tag(), "[Engine Agent ERROR] Memory not enough!!");
- continue;
- }
-
- if (0 == vc_parser_get_engine_info(filepath, &info)) {
- g_engine_list = g_slist_append(g_engine_list, info);
- }
-
- if (NULL != filepath) {
- free(filepath);
- filepath = NULL;
- }
- }
- } while (NULL != dirp);
+ if (0 != access(VC_DOWNLOAD_BASE, F_OK)) {
+ if (0 != mkdir(VC_DOWNLOAD_BASE, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
+ SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to make directory : %s", VC_DOWNLOAD_BASE);
+ __vc_config_release_client(uid);
+ pthread_mutex_unlock(&vc_config_mgr_mutex);
+ return -1;
+ } else {
+ SLOG(LOG_DEBUG, vc_config_tag(), "Success to make directory : %s", VC_DOWNLOAD_BASE);
+ }
+ }
+ if (0 != access(VC_DOWNLOAD_ENGINE_INFO, F_OK)) {
+ if (0 != mkdir(VC_DOWNLOAD_ENGINE_INFO, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
+ SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to make directory : %s", VC_DOWNLOAD_ENGINE_INFO);
+ __vc_config_release_client(uid);
+ pthread_mutex_unlock(&vc_config_mgr_mutex);
+ return -1;
+ } else {
+ SLOG(LOG_DEBUG, vc_config_tag(), "Success to make directory : %s", VC_DOWNLOAD_ENGINE_INFO);
+ }
+ }
- closedir(dp);
- } else {
- SLOG(LOG_WARN, vc_config_tag(), "[Engine Agent WARNING] Fail to open default directory");
+ if (0 != __vc_config_mgr_get_engine_info()) {
+ SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to get engine info");
+ __vc_config_release_client(uid);
+ __vc_config_release_engine();
+ pthread_mutex_unlock(&vc_config_mgr_mutex);
+ return VC_CONFIG_ERROR_ENGINE_NOT_FOUND;
}
__vc_config_mgr_print_engine_info();
if (0 != vc_parser_load_config(&g_config_info)) {
SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to parse configure information");
+ __vc_config_release_client(uid);
+ __vc_config_release_engine();
pthread_mutex_unlock(&vc_config_mgr_mutex);
return -1;
}
if (0 != __vc_config_mgr_check_engine_is_valid(g_config_info->engine_id)) {
SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to get default engine");
+ __vc_config_release_client(uid);
+ __vc_config_release_engine();
vc_parser_unload_config(g_config_info);
pthread_mutex_unlock(&vc_config_mgr_mutex);
return VC_CONFIG_ERROR_ENGINE_NOT_FOUND;
char* tmp_language;
if (0 != __vc_config_mgr_select_lang(g_config_info->engine_id, &tmp_language)) {
SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to select language");
+ __vc_config_release_client(uid);
+ __vc_config_release_engine();
vc_parser_unload_config(g_config_info);
pthread_mutex_unlock(&vc_config_mgr_mutex);
return -1;
if (0 != vc_parser_set_language(tmp_language)) {
free(tmp_language);
SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to save config");
+ __vc_config_release_client(uid);
+ __vc_config_release_engine();
vc_parser_unload_config(g_config_info);
pthread_mutex_unlock(&vc_config_mgr_mutex);
return -1;
temp_client = (vc_config_client_s*)calloc(1, sizeof(vc_config_client_s));
if (NULL == temp_client) {
SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to allocate memory");
+ __vc_config_release_client(uid);
+ __vc_config_release_engine();
vc_parser_unload_config(g_config_info);
pthread_mutex_unlock(&vc_config_mgr_mutex);
return VC_ERROR_OUT_OF_MEMORY;
int vc_config_mgr_finalize(int uid)
{
- GSList *iter = NULL;
- vc_config_client_s* temp_client = NULL;
-
SLOG(LOG_INFO, vc_config_tag(), "[WARNING] Enter critical section");
- pthread_mutex_lock(&vc_config_mgr_mutex);
- if (0 < g_slist_length(g_config_client_list)) {
- /* Check uid */
- iter = g_slist_nth(g_config_client_list, 0);
-
- while (NULL != iter) {
- temp_client = iter->data;
-
- if (NULL != temp_client) {
- if (uid == temp_client->uid) {
- g_config_client_list = g_slist_remove(g_config_client_list, temp_client);
- free(temp_client);
- break;
- }
- }
-
- iter = g_slist_next(iter);
- }
- }
+ pthread_mutex_lock(&vc_config_mgr_mutex);
- if (0 < g_slist_length(g_config_client_list)) {
- SLOG(LOG_DEBUG, vc_config_tag(), "Client count (%d)", g_slist_length(g_config_client_list));
+ if (0 < __vc_config_release_client(uid)) {
pthread_mutex_unlock(&vc_config_mgr_mutex);
-
+ SLOG(LOG_DEBUG, vc_config_tag(), "[WARNING] Leave critical section");
+
if (0 != pthread_mutex_destroy(&vc_config_mgr_mutex)) {
SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to destroy vc_config_mgr_mutex.");
}
-
return 0;
}
- vc_engine_info_s *engine_info = NULL;
-
- if (0 < g_slist_length(g_engine_list)) {
-
- /* Get a first item */
- iter = g_slist_nth(g_engine_list, 0);
-
- while (NULL != iter) {
- engine_info = iter->data;
-
- if (NULL != engine_info) {
- g_engine_list = g_slist_remove(g_engine_list, engine_info);
-
- vc_parser_free_engine_info(engine_info);
- }
-
- iter = g_slist_nth(g_engine_list, 0);
- }
- }
-
+ __vc_config_release_engine();
+
vconf_ignore_key_changed(VCONFKEY_LANGSET, __vc_config_language_changed_cb);
vc_parser_unload_config(g_config_info);
--- /dev/null
+//
+// Copyright (c) 2016 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <app_manager.h>
+#include <dlog.h>
+#include <errno.h>
+#include <glib.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <pkgmgr-info.h>
+#include <pkgmgr_installer_info.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <tzplatform_config.h>
+#include <systemd/sd-login.h>
+
+#include <gum/gum-user.h>
+#include <gum/gum-user-service.h>
+#include <gum/common/gum-user-types.h>
+
+/* Define EXPORT_API */
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "vc-engine-parser"
+
+#define VC_TAG_ENGINE_BASE "voice-control-engine"
+#define VC_TAG_ENGINE_NAME "name"
+#define VC_TAG_ENGINE_ID "id"
+#define VC_TAG_ENGINE_SETTING "setting"
+#define VC_TAG_ENGINE_LANGUAGE_SET "languages"
+#define VC_TAG_ENGINE_LANGUAGE "lang"
+#define VC_TAG_ENGINE_NON_FIXED_SUPPORT "non-fixed-support"
+#define VC_TAG_ENGINE_CREDENTIAL "credential"
+
+#define VC_CONFIG_BASE tzplatform_mkpath(TZ_USER_HOME, "share/.voice")
+#define VC_HOME tzplatform_mkpath(TZ_USER_HOME, "share/.voice/vc")
+#define VC_ENGINE_BASE tzplatform_mkpath(TZ_USER_HOME, "share/.voice/vc/1.0")
+#define VC_ENGINE_INFO tzplatform_mkpath(TZ_USER_SHARE, ".voice/vc/1.0/engine-info")
+
+#define VC_GLOBAL_CONFIG_BASE "/etc/skel/share/.voice"
+#define VC_GLOBAL_HOME "/etc/skel/share/.voice/vc"
+#define VC_GLOBAL_ENGINE_BASE "/etc/skel/share/.voice/vc/1.0"
+#define VC_GLOBAL_ENGINE_INFO "/etc/skel/share/.voice/vc/1.0/engine-info"
+
+#define VC_METADATA_LANGUAGE "http://tizen.org/metadata/vc-engine/language"
+#define VC_METADATA_NON_FIXED_SUPPORT "http://tizen.org/metadata/vc-engine/non-fixed-support"
+#define VC_METADATA_CREDENTIAL_REQUIRED "http://tizen.org/metadata/vc-engine/credential-required"
+#define VC_METADATA_ENGINE_SETTING "http://tizen.org/metadata/vc-engine/setting"
+#define VC_METADATA_ENGINE_NAME "http://tizen.org/metadata/vc-engine/name"
+
+/* Define Macro */
+#define FREE(x) { if (NULL != x) { free(x); x = NULL; } }
+#define G_FREE(x) { if (NULL != x) { g_free(x); x = NULL; } }
+
+typedef struct metadata {
+ const char *key;
+ const char *value;
+} metadata;
+
+static xmlDocPtr g_doc;
+GumUser *g_guser = NULL;
+uid_t g_uid = 301; // app_fw
+gid_t g_gid = 301; // app_fw
+GumUserType g_ut = GUM_USERTYPE_NONE;
+gchar *g_user_type = NULL;
+
+char *g_dir_config_base = NULL;
+char *g_dir_home = NULL;
+char *g_dir_engine_base = NULL;
+char *g_dir_engine_info = NULL;
+
+
+static int __create_engine_info_xml(const char *pkgid)
+{
+ LOGD("=== Create engine info doc");
+ g_doc = xmlNewDoc((xmlChar*)"1.0");
+ if (NULL == g_doc) {
+ LOGE("[ERROR] Fail to new doc");
+ return -1;
+ }
+ LOGD("===");
+ return 0;
+}
+
+static int __save_engine_info_xml(const char *pkgid, gchar *ut, uid_t uid, gid_t gid)
+{
+ LOGD("=== Save engine info doc");
+ char *dir_config_base = NULL;
+ char *dir_home = NULL;
+ char *dir_engine_base = NULL;
+ char *dir_engine_info = NULL;
+
+ if (NULL == ut || (NULL != ut && 0 == strcmp(ut, "none"))) {
+ LOGE("[ERROR] Usertype is NONE");
+ return -1;
+ }
+
+ uid_t globalapp_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
+ uid_t tmp_uid = 0;
+ gid_t tmp_gid = 0;
+ LOGD("uid(%d)", uid);
+
+ if (globalapp_uid == uid) {
+ /* Global app */
+ dir_config_base = strdup(VC_GLOBAL_CONFIG_BASE);
+ dir_home = strdup(VC_GLOBAL_HOME);
+ dir_engine_base = strdup(VC_GLOBAL_ENGINE_BASE);
+ dir_engine_info = strdup(VC_GLOBAL_ENGINE_INFO);
+ tmp_uid = 301; // app_fw
+ tmp_gid = 301; // app_fw
+ } else {
+ /* User app, Guest app, Security app */
+ if (NULL != g_dir_config_base)
+ dir_config_base = strdup(g_dir_config_base);
+ if (NULL != g_dir_home)
+ dir_home = strdup(g_dir_home);
+ if (NULL != g_dir_engine_base)
+ dir_engine_base = strdup(g_dir_engine_base);
+ if (NULL != g_dir_engine_info)
+ dir_engine_info = strdup(g_dir_engine_info);
+ tmp_uid = uid;
+ tmp_gid = gid;
+ }
+
+ if (NULL == dir_config_base || NULL == dir_home || NULL == dir_engine_base || NULL == dir_engine_info) {
+ LOGE("[ERROR] Fail to allocate memory");
+ FREE(dir_config_base)
+ FREE(dir_home)
+ FREE(dir_engine_base)
+ FREE(dir_engine_info)
+ return -1;
+ }
+
+ LOGD("[DEBUG] dir_engine_info(%s)", dir_engine_info);
+
+ /* Make directories */
+ int fd = -1;
+// if (0 != access(dir_config_base, F_OK)) {
+ fd = open(dir_config_base, O_DIRECTORY);
+ if (-1 == fd) {
+ LOGE("[INFO] No directory : %s, errno : %d", dir_config_base, errno);
+ if (0 != mkdir(dir_config_base, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
+ LOGE("[ERROR] Fail to make directory : %s, errno : %d", dir_config_base, errno);
+ FREE(dir_config_base)
+ FREE(dir_home)
+ FREE(dir_engine_base)
+ FREE(dir_engine_info)
+ return -1;
+ } else {
+ LOGD("Success to make directory : %s", dir_config_base);
+ if (0 != chown(dir_config_base, tmp_uid, tmp_gid)) {
+ LOGD("[ERROR] Fail to change user and group, errno : %d", errno);
+ } else {
+ LOGD("[DEBUG] Success to change user and group");
+ }
+ }
+ } else {
+ close(fd);
+ }
+
+// if (0 != access(dir_home, F_OK)) {
+ fd = open(dir_home, O_DIRECTORY);
+ if (-1 == fd) {
+ LOGE("[INFO] No directory : %s, errno : %d", dir_home, errno);
+ if (0 != mkdir(dir_home, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
+ LOGE("[ERROR] Fail to make directory : %s, errno : %d", dir_home, errno);
+ FREE(dir_config_base)
+ FREE(dir_home)
+ FREE(dir_engine_base)
+ FREE(dir_engine_info)
+ return -1;
+ } else {
+ LOGD("Success to make directory : %s", dir_home);
+ if (0 != chown(dir_home, tmp_uid, tmp_gid)) {
+ LOGD("[ERROR] Fail to change user and group, errno : %d", errno);
+ } else {
+ LOGD("[DEBUG] Success to change user and group");
+ }
+ }
+ } else {
+ close(fd);
+ }
+
+// if (0 != access(dir_engine_base, F_OK)) {
+ fd = open(dir_engine_base, O_DIRECTORY);
+ if (-1 == fd) {
+ LOGE("[INFO] No directory : %s, errno : %d", dir_engine_base, errno);
+ if (0 != mkdir(dir_engine_base, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
+ LOGE("[ERROR] Fail to make directory : %s, errno : %d", dir_engine_base, errno);
+ FREE(dir_config_base)
+ FREE(dir_home)
+ FREE(dir_engine_base)
+ FREE(dir_engine_info)
+ return -1;
+ } else {
+ LOGD("Success to make directory : %s", dir_engine_base);
+ if (0 != chown(dir_engine_base, tmp_uid, tmp_gid)) {
+ LOGD("[ERROR] Fail to change user and group, errno : %d", errno);
+ } else {
+ LOGD("[DEBUG] Success to change user and group");
+ }
+ }
+ } else {
+ close(fd);
+ }
+
+// if (0 != access(dir_engine_info, F_OK)) {
+ fd = open(dir_engine_info, O_DIRECTORY);
+ if (-1 == fd) {
+ LOGE("[INFO] No directory : %s, errno : %d", dir_engine_info, errno);
+ if (0 != mkdir(dir_engine_info, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
+ LOGE("[ERROR] Fail to make directory : %s, errno : %d", dir_engine_info, errno);
+ FREE(dir_config_base)
+ FREE(dir_home)
+ FREE(dir_engine_base)
+ FREE(dir_engine_info)
+ return -1;
+ } else {
+ LOGD("Success to make directory : %s", dir_engine_info);
+ if (0 != chown(dir_engine_info, tmp_uid, tmp_gid)) {
+ LOGD("[ERROR] Fail to change user and group, errno : %d", errno);
+ } else {
+ LOGD("[DEBUG] Success to change user and group");
+ }
+ }
+ } else {
+ close(fd);
+ }
+
+ char path[256] = {'\0',};
+ snprintf(path, 256, "%s/%s.xml", dir_engine_info, pkgid);
+ int ret = xmlSaveFormatFile(path, g_doc, 1);
+ LOGD("xmlSaveFile (%d)", ret);
+ if (0 == ret) {
+ if (0 != chown(path, tmp_uid, tmp_gid)) {
+ LOGD("[ERROR] Fail to change user and group");
+ } else {
+ LOGD("[DEBUG] Success to change user and group");
+ }
+ }
+
+ FREE(dir_config_base)
+ FREE(dir_home)
+ FREE(dir_engine_base)
+ FREE(dir_engine_info)
+
+ LOGD("===");
+
+ return 0;
+}
+
+static int __remove_engine_info_xml(const char *pkgid, gchar *ut, uid_t uid)
+{
+ LOGD("=== Remove engine info doc");
+ char *dir_engine_info = NULL;
+
+ if (NULL == ut || (NULL != ut && 0 == strcmp(ut, "none"))) {
+ LOGE("[ERROR] Usertype is NONE");
+ return -1;
+ }
+
+ uid_t globalapp_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
+
+ LOGD("uid(%d)", uid);
+
+ if (globalapp_uid == uid) {
+ /* Global app */
+ dir_engine_info = strdup(VC_GLOBAL_ENGINE_INFO);
+ } else {
+ /* User app, Guest app, Security app */
+ if (NULL != g_dir_engine_info)
+ dir_engine_info = strdup(g_dir_engine_info);
+ }
+
+ if (NULL == dir_engine_info) {
+ LOGE("[ERROR] Fail to allocate memory");
+ return -1;
+ }
+
+ LOGD("[DEBUG] dir_engine_info(%s)", dir_engine_info);
+
+ char path[256] = {'\0',};
+ snprintf(path, 256, "%s/%s.xml", dir_engine_info, pkgid);
+ if (0 == access(path, F_OK)) {
+ LOGD("Remove engine info xml(%s)", path);
+ if (0 != remove(path)) {
+ LOGE("[ERROR] Fail to emove engine info xml(%s)", path);
+ }
+ }
+
+ FREE(dir_engine_info)
+
+ LOGD("===");
+
+ return 0;
+}
+
+static void __insert_language_from_metadata(xmlNodePtr root, const char *language)
+{
+ LOGD("==== Insert language");
+ char* lang = NULL;
+
+ if (NULL == root || NULL == language) {
+ LOGE("Invalid parameter, root(%p), language(%s)", root, language);
+ return;
+ }
+
+ char *tmp_lang, *tmp_free;
+ tmp_free = tmp_lang = strdup(language);
+ xmlNodePtr languages_node = NULL;
+ xmlNodePtr lang_node = NULL;
+
+ languages_node = xmlNewNode(NULL, (const xmlChar*)VC_TAG_ENGINE_LANGUAGE_SET);
+
+ lang = strsep(&tmp_lang, ",");
+ while (NULL != lang) {
+ LOGD("lang (%s)", lang);
+ lang_node = xmlNewNode(NULL, (const xmlChar*)VC_TAG_ENGINE_LANGUAGE);
+ xmlNodeSetContent(lang_node, (const xmlChar*)lang);
+ xmlAddChild(languages_node, lang_node);
+ lang = strsep(&tmp_lang, ",");
+ }
+ xmlAddChild(root, languages_node);
+
+ FREE(tmp_free)
+}
+
+static int __write_metadata_inxml(const char *pkgid, const char *appid, GList *list)
+{
+ GList *iter = NULL;
+ metadata *md = NULL;
+
+ __create_engine_info_xml(pkgid);
+
+ xmlNodePtr root = NULL;
+ xmlNodePtr cur = NULL;
+
+ root = xmlNewNode(NULL, (const xmlChar*)VC_TAG_ENGINE_BASE);
+
+ if (NULL == root) {
+ LOGE("[ERROR] Fail to get new node");
+// xmlFreeDoc(g_doc);
+ return -1;
+ }
+ xmlDocSetRootElement(g_doc, root);
+
+ iter = g_list_first(list);
+ while (NULL != iter) {
+ md = (metadata *)iter->data;
+ if (NULL != md && NULL != md->key && NULL != md->value) {
+ LOGD(" - key(%s) value(%s)", md->key, md->value);
+ if (!strcmp(md->key, VC_METADATA_LANGUAGE)) {
+ __insert_language_from_metadata(root, md->value);
+ } else if (!strcmp(md->key, VC_METADATA_NON_FIXED_SUPPORT)) {
+ cur = xmlNewNode(NULL, (const xmlChar*)VC_TAG_ENGINE_NON_FIXED_SUPPORT);
+ xmlNodeSetContent(cur, (const xmlChar*)md->value);
+ xmlAddChild(root, cur);
+ } else if (!strcmp(md->key, VC_METADATA_CREDENTIAL_REQUIRED)) {
+ cur = xmlNewNode(NULL, (const xmlChar*)VC_TAG_ENGINE_CREDENTIAL);
+ xmlNodeSetContent(cur, (const xmlChar*)md->value);
+ xmlAddChild(root, cur);
+ } else if (!strcmp(md->key, VC_METADATA_ENGINE_SETTING)) {
+ cur = xmlNewNode(NULL, (const xmlChar*)VC_TAG_ENGINE_SETTING);
+ xmlNodeSetContent(cur, (const xmlChar*)md->value);
+ xmlAddChild(root, cur);
+ } else if (!strcmp(md->key, VC_METADATA_ENGINE_NAME)) {
+ cur = xmlNewNode(NULL, (const xmlChar*)VC_TAG_ENGINE_NAME);
+ xmlNodeSetContent(cur, (const xmlChar*)md->value);
+ xmlAddChild(root, cur);
+ } else {
+ LOGW("[WARNING] Unknown metadata type");
+ }
+ }
+ iter = g_list_next(iter);
+ }
+
+ cur = xmlNewNode(NULL, (const xmlChar*)VC_TAG_ENGINE_ID);
+ xmlNodeSetContent(cur, (const xmlChar*)appid);
+ xmlAddChild(root, cur);
+
+ LOGD("");
+ return 0;
+}
+
+EXPORT_API
+int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *list)
+{
+ LOGD("METADATA INSTALL");
+ LOGD("pkgid(%s) appid(%s) list(%d)", pkgid, appid, g_list_length(list));
+
+ int ret = -1;
+ ret = pkgmgr_installer_info_get_target_uid(&g_uid);
+ if (ret < 0) {
+ LOGE("[ERROR] Fail to get target uid");
+ return 0;
+ } else {
+ LOGD("uid(%d)", g_uid);
+ printf("[Parser Debug][DEBUG] uid(%d)", g_uid);
+ }
+
+ uid_t globalapp_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
+ if (globalapp_uid == g_uid) {
+ g_user_type = g_strdup("admin");
+ } else {
+ g_guser = gum_user_get_sync(g_uid, FALSE);
+ if (NULL == g_guser) {
+ LOGE("[ERROR] g_guser is NULL");
+ return -1;
+ }
+
+ g_object_get(G_OBJECT(g_guser), "gid", &g_gid, NULL);
+ g_object_get(G_OBJECT(g_guser), "usertype", &g_ut, NULL);
+ g_user_type = g_strdup(gum_user_type_to_string(g_ut));
+ }
+
+ if (NULL == g_user_type) {
+ LOGE("[ERROR] Fail to allocate memory");
+ if (NULL != g_guser) {
+ g_object_unref(g_guser);
+ g_guser = NULL;
+ }
+ return -1;
+ }
+
+ if (0 == strcmp(g_user_type, "none")) {
+ /* GUM_USERTYPE_NONE */
+ LOGE("[ERROR] Fail to get target uid");
+ g_object_unref(g_guser);
+ g_guser = NULL;
+ G_FREE(g_user_type)
+ return -1;
+ }
+
+ if (globalapp_uid == g_uid) {
+ /* global directory */
+ LOGD("[DEBUG] usertype: %s", g_user_type);
+ if (0 >= g_list_length(list)) {
+ LOGE("[ERROR] No Engine Metadata");
+ G_FREE(g_user_type)
+ return 0;
+ }
+
+ if (0 != __write_metadata_inxml(pkgid, appid, list)) {
+ LOGE("[ERROR] Fail to write metadata in the xml");
+ xmlFreeDoc(g_doc);
+ G_FREE(g_user_type)
+ return -1;
+ }
+
+ /* Save in /etc/skel/share/ */
+ g_dir_config_base = strdup(VC_GLOBAL_CONFIG_BASE);
+ g_dir_home = strdup(VC_GLOBAL_HOME);
+ g_dir_engine_base = strdup(VC_GLOBAL_ENGINE_BASE);
+ g_dir_engine_info = strdup(VC_GLOBAL_ENGINE_INFO);
+
+ if (NULL == g_dir_config_base || NULL == g_dir_home || NULL == g_dir_engine_base || NULL == g_dir_engine_info) {
+ LOGE("[ERROR] Fail to allocate memory");
+ FREE(g_dir_config_base)
+ FREE(g_dir_home)
+ FREE(g_dir_engine_base)
+ FREE(g_dir_engine_info)
+ xmlFreeDoc(g_doc);
+ G_FREE(g_user_type)
+ return -1;
+ }
+
+ if (0 != __save_engine_info_xml(pkgid, g_user_type, g_uid, g_gid)) {
+ LOGE("[ERROR] Fail to make engine info file");
+ xmlFreeDoc(g_doc);
+ G_FREE(g_user_type)
+ return -1;
+ }
+
+ /* Get user data by using libgum */
+
+ GumUserService *gus = NULL;
+ GumUserList *users = NULL;
+ GumUserList *iter = NULL;
+ GumUser *user = NULL;
+ gchar **query;
+ GumUserType gumut = GUM_USERTYPE_NONE;
+ gchar *user_type = NULL;
+
+ uid_t uid;
+ gid_t gid;
+ gchar *home_dir = NULL;
+
+ gus = gum_user_service_create_sync(TRUE);
+ if (!gus) {
+ LOGE("Failed to create gum user service");
+ G_FREE(g_user_type)
+ return -1;
+ }
+
+ query = g_strsplit("admin,normal", ",", -1);
+
+ users = gum_user_service_get_user_list_sync(gus, (const gchar *const *)query);
+ g_strfreev(query);
+
+ if (!users) {
+ LOGD("NO users");
+ g_object_unref(gus);
+ gus = NULL;
+ G_FREE(g_user_type)
+ return 0;
+ }
+
+ /* Make new user list */
+
+ iter = users;
+ while (iter != NULL) {
+ user = (GumUser*) iter->data;
+ g_object_get(G_OBJECT(user), "uid", &uid, NULL);
+ G_FREE(home_dir)
+
+ g_object_get(G_OBJECT(user), "gid", &gid, NULL);
+ g_object_get(G_OBJECT(user), "homedir", &home_dir, NULL);
+ g_object_get(G_OBJECT(user), "usertype", &gumut, NULL);
+ user_type = g_strdup(gum_user_type_to_string(gumut));
+ if (NULL == user_type) {
+ gum_user_service_list_free(users);
+ G_FREE(home_dir)
+ g_object_unref(gus);
+ gus = NULL;
+ return -1;
+ }
+
+ LOGD("[DEBUG] user info");
+ if (NULL != home_dir) {
+ LOGD("[DEBUG] uid(%d), gid(%d), user_type(%s), home_dir(%s)", uid, gid, user_type, home_dir);
+
+ g_dir_config_base = (char*)calloc(strlen(home_dir) + 14, sizeof(char));
+ g_dir_home = (char*)calloc(strlen(home_dir) + 17, sizeof(char));
+ g_dir_engine_base = (char*)calloc(strlen(home_dir) + 21, sizeof(char));
+ g_dir_engine_info = (char*)calloc(strlen(home_dir) + 33, sizeof(char));
+
+ if (NULL == g_dir_config_base || NULL == g_dir_home || NULL == g_dir_engine_base || NULL == g_dir_engine_info) {
+ LOGE("[ERROR] Fail to allocate memory");
+ FREE(g_dir_config_base)
+ FREE(g_dir_home)
+ FREE(g_dir_engine_base)
+ FREE(g_dir_engine_info)
+ gum_user_service_list_free(users);
+ g_object_unref(gus);
+ gus = NULL;
+ G_FREE(user_type)
+ G_FREE(home_dir)
+ return -1;
+ }
+ snprintf(g_dir_config_base, strlen(home_dir) + 14, "%s/share/.voice", home_dir);
+ snprintf(g_dir_home, strlen(home_dir) + 17, "%s/share/.voice/vc", home_dir);
+ snprintf(g_dir_engine_base, strlen(home_dir) + 21, "%s/share/.voice/vc/1.0", home_dir);
+ snprintf(g_dir_engine_info, strlen(home_dir) + 33, "%s/share/.voice/vc/1.0/engine-info", home_dir);
+
+ LOGD("[DEBUG] g_dir_engine_info(%s)", g_dir_engine_info);
+
+ if (0 != __save_engine_info_xml(pkgid, user_type, uid, gid)) {
+ LOGE("[ERROR] Fail to make engine info file");
+ }
+
+ FREE(g_dir_config_base)
+ FREE(g_dir_home)
+ FREE(g_dir_engine_base)
+ FREE(g_dir_engine_info)
+
+ G_FREE(home_dir)
+ }
+
+ G_FREE(user_type)
+ iter = g_list_next(iter);
+ }
+
+ gum_user_service_list_free(users);
+ g_object_unref(gus);
+ gus = NULL;
+ } else {
+ /* user directory */
+ LOGD("[DEBUG] usertype: %s", g_user_type);
+
+ ret = tzplatform_set_user(g_uid);
+ if (ret < 0) {
+ LOGE("[ERROR] Invalid uid");
+ g_object_unref(g_guser);
+ g_guser = NULL;
+ G_FREE(g_user_type)
+ return 0;
+ } else {
+ LOGD("TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/"));
+ printf("[Parser Debug][DEBUG] TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/"));
+ }
+
+ if (0 >= g_list_length(list)) {
+ LOGE("[ERROR] No Engine Metadata");
+ g_object_unref(g_guser);
+ g_guser = NULL;
+ G_FREE(g_user_type)
+ return 0;
+ }
+
+ if (0 != __write_metadata_inxml(pkgid, appid, list)) {
+ LOGE("[ERROR] Fail to write metadata in the xml");
+ xmlFreeDoc(g_doc);
+ g_object_unref(g_guser);
+ g_guser = NULL;
+ G_FREE(g_user_type)
+ return -1;
+ }
+
+ g_dir_config_base = strdup(VC_CONFIG_BASE);
+ g_dir_home = strdup(VC_HOME);
+ g_dir_engine_base = strdup(VC_ENGINE_BASE);
+ g_dir_engine_info = strdup(VC_ENGINE_INFO);
+
+ if (NULL == g_dir_config_base || NULL == g_dir_home || NULL == g_dir_engine_base || NULL == g_dir_engine_info) {
+ LOGE("[ERROR] Fail to allocate memory");
+ FREE(g_dir_config_base)
+ FREE(g_dir_home)
+ FREE(g_dir_engine_base)
+ FREE(g_dir_engine_info)
+ xmlFreeDoc(g_doc);
+ g_object_unref(g_guser);
+ g_guser = NULL;
+ G_FREE(g_user_type)
+ return -1;
+ }
+
+ if (0 != __save_engine_info_xml(pkgid, g_user_type, g_uid, g_gid)) {
+ LOGE("[ERROR] Fail to make engine info file");
+ xmlFreeDoc(g_doc);
+ if (NULL != g_guser) {
+ g_object_unref(g_guser);
+ g_guser = NULL;
+ }
+ G_FREE(g_user_type)
+ return -1;
+ }
+ }
+
+ xmlFreeDoc(g_doc);
+ if (NULL != g_guser) {
+ g_object_unref(g_guser);
+ g_guser = NULL;
+ }
+ G_FREE(g_user_type)
+
+ FREE(g_dir_config_base)
+ FREE(g_dir_home)
+ FREE(g_dir_engine_base)
+ FREE(g_dir_engine_info)
+
+ return 0;
+}
+
+EXPORT_API
+int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList *list)
+{
+ LOGD("METADATA UNINSTALL");
+ LOGD("pkgid(%s) appid(%s) list(%d)", pkgid, appid, g_list_length(list));
+
+ int ret = -1;
+ ret = pkgmgr_installer_info_get_target_uid(&g_uid);
+ if (ret < 0) {
+ LOGE("[ERROR] Fail to get target uid");
+ return 0;
+ } else {
+ LOGD("uid(%d)", g_uid);
+ printf("[Parser Debug][DEBUG] uid(%d)", g_uid);
+ }
+
+ uid_t globalapp_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
+ if (globalapp_uid == g_uid) {
+ g_user_type = g_strdup("admin");
+ } else {
+ g_guser = gum_user_get_sync(g_uid, FALSE);
+ if (NULL == g_guser) {
+ LOGE("[ERROR] g_guser is NULL");
+ return -1;
+ }
+
+ g_object_get(G_OBJECT(g_guser), "usertype", &g_ut, NULL);
+ g_user_type = g_strdup(gum_user_type_to_string(g_ut));
+ }
+
+ if (NULL == g_user_type) {
+ LOGE("[ERROR] Fail to allocate memory");
+ if (NULL != g_guser) {
+ g_object_unref(g_guser);
+ g_guser = NULL;
+ }
+ return -1;
+ }
+
+ if (0 == strcmp(g_user_type, "none")) {
+ /* GUM_USERTYPE_NONE */
+ LOGE("[ERROR] Fail to get target uid");
+ g_object_unref(g_guser);
+ g_guser = NULL;
+ G_FREE(g_user_type)
+ return -1;
+ }
+
+ if (globalapp_uid == g_uid) {
+ /* global directory */
+ LOGD("[DEBUG] usertype: %s", g_user_type);
+
+ /* Remove files in /etc/skel/share/ */
+ g_dir_engine_info = strdup(VC_GLOBAL_ENGINE_INFO);
+ if (NULL == g_dir_engine_info) {
+ LOGE("[ERROR] Fail to allocate memory");
+ G_FREE(g_user_type)
+ return -1;
+ }
+
+ if (0 != __remove_engine_info_xml(pkgid, g_user_type, g_uid)) {
+ LOGE("[ERROR] Fail to remove engine info file");
+ }
+
+ /* Get user data by using libgum */
+
+ GumUserService *gus = NULL;
+ GumUserList *users = NULL;
+ GumUserList *iter = NULL;
+ GumUser *user = NULL;
+ gchar **query;
+ GumUserType gumut = GUM_USERTYPE_NONE;
+ gchar *user_type = NULL;
+
+ uid_t uid;
+ gchar *home_dir = NULL;
+
+ GList *md_iter = NULL;
+ metadata *md = NULL;
+
+ gus = gum_user_service_create_sync(TRUE);
+ if (!gus) {
+ LOGE("Failed to create gum user service");
+ G_FREE(g_user_type)
+ return -1;
+ }
+
+ query = g_strsplit("admin,normal", ",", -1);
+
+ users = gum_user_service_get_user_list_sync(gus, (const gchar *const *)query);
+ g_strfreev(query);
+
+ if (!users) {
+ LOGD("NO users");
+ g_object_unref(gus);
+ gus = NULL;
+ G_FREE(g_user_type)
+ return 0;
+ }
+
+ /* Make new user list */
+
+ iter = users;
+ while (iter != NULL) {
+ user = (GumUser*) iter->data;
+ g_object_get(G_OBJECT(user), "uid", &uid, NULL);
+ G_FREE(home_dir)
+ g_object_get(G_OBJECT(user), "homedir", &home_dir, NULL);
+ g_object_get(G_OBJECT(user), "usertype", &gumut, NULL);
+ user_type = g_strdup(gum_user_type_to_string(gumut));
+ if (NULL == user_type) {
+ gum_user_service_list_free(users);
+ G_FREE(home_dir)
+ g_object_unref(gus);
+ gus = NULL;
+ return -1;
+ }
+
+ if (NULL != home_dir) {
+ g_dir_engine_info = (char*)calloc(strlen(home_dir) + 33, sizeof(char));
+ if (NULL == g_dir_engine_info) {
+ gum_user_service_list_free(users);
+ G_FREE(home_dir)
+ g_object_unref(gus);
+ gus = NULL;
+ G_FREE(user_type)
+ return -1;
+ }
+
+ snprintf(g_dir_engine_info, strlen(home_dir) + 33, "%s/share/.voice/vc/1.0/engine-info", home_dir);
+
+ md_iter = g_list_first(list);
+ while (NULL != md_iter) {
+ md = (metadata *)md_iter->data;
+ LOGD(" - key(%s) value(%s)", md->key, md->value);
+ md_iter = g_list_next(md_iter);
+ }
+
+ if (0 != __remove_engine_info_xml(pkgid, user_type, uid)) {
+ LOGE("[ERROR] Fail to remove engine info file");
+ }
+
+ G_FREE(home_dir)
+ G_FREE(g_dir_engine_info)
+ }
+ G_FREE(user_type)
+
+ LOGD("Finish release memory");
+ iter = g_list_next(iter);
+ LOGD("Finish next iter");
+ }
+
+ gum_user_service_list_free(users);
+ g_object_unref(gus);
+ gus = NULL;
+ } else {
+ /* user directory */
+ LOGD("[DEBUG] usertype: %s", g_user_type);
+
+ ret = tzplatform_set_user(g_uid);
+ if (ret < 0) {
+ LOGE("[ERROR] Invalid uid");
+ g_object_unref(g_guser);
+ g_guser = NULL;
+ G_FREE(g_user_type)
+ return -1;
+ } else {
+ LOGD("TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/"));
+ printf("[Parser Debug][DEBUG] TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/"));
+ }
+
+ g_dir_engine_info = strdup(VC_ENGINE_INFO);
+ if (NULL == g_dir_engine_info) {
+ LOGE("[ERROR] Fail to allocate memory");
+ g_object_unref(g_guser);
+ g_guser = NULL;
+ G_FREE(g_user_type)
+ return -1;
+ }
+
+ if (0 != __remove_engine_info_xml(pkgid, g_user_type, g_uid)) {
+ LOGE("[ERROR] Fail to remove engine info file");
+ }
+
+ }
+
+ if (NULL != g_guser) {
+ g_object_unref(g_guser);
+ g_guser = NULL;
+ }
+ G_FREE(g_user_type)
+
+ FREE(g_dir_engine_info)
+
+ LOGD("");
+ return 0;
+}
+
+EXPORT_API
+int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgid, const char *appid, GList *list)
+{
+ LOGD("METADATA UPGRADE");
+ LOGD("pkgid(%s) appid(%s) list(%d)", pkgid, appid, g_list_length(list));
+
+ PKGMGR_MDPARSER_PLUGIN_UNINSTALL(pkgid, appid, list);
+ PKGMGR_MDPARSER_PLUGIN_INSTALL(pkgid, appid, list);
+
+ LOGD("");
+ return 0;
+}