diff options
Diffstat (limited to 'tool/sp_initdb/src')
-rw-r--r-- | tool/sp_initdb/src/sp_initdb.c | 157 | ||||
-rw-r--r-- | tool/sp_initdb/src/syspopup_parser.c | 390 | ||||
-rw-r--r-- | tool/sp_initdb/src/syspopup_parser_db.c | 211 | ||||
-rw-r--r-- | tool/sp_initdb/src/syspopup_type.c | 41 |
4 files changed, 799 insertions, 0 deletions
diff --git a/tool/sp_initdb/src/sp_initdb.c b/tool/sp_initdb/src/sp_initdb.c new file mode 100644 index 0000000..2eb519e --- /dev/null +++ b/tool/sp_initdb/src/sp_initdb.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2017 - 2019 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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. + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/smack.h> +#include <linux/limits.h> +#include <glib.h> +#include <system_info.h> + +#include "syspopup_private.h" +#include "syspopup_parser_db.h" +#include "syspopup_parser.h" +#include "syspopup_type.h" + +#define PATH_SYSPOPUP_DEFAULT "/usr/share/syspopup/default" + +#define PATH_SYSPOPUP "/usr/share/syspopup" + +#define ROOT_UID 0 + +static int __load_syspopup_info(const char *path, GList **syspopup_list) +{ + struct dirent *dentry = NULL; + char buf[PATH_MAX]; + char *ext; + DIR *dp; + + if (!path) + return -1; + + dp = opendir(path); + if (!dp) { + printf("Failed to open directory(%s). errno(%d)\n", + path, errno); + return -1; + } + + while ((dentry = readdir(dp)) != NULL) { + if (dentry->d_name[0] == '.') + continue; + + ext = strrchr(dentry->d_name, '.'); + if (ext && strcmp(ext, ".xml") == 0) { + snprintf(buf, sizeof(buf), "%s/%s", + path, dentry->d_name); + syspopup_parser_parse(buf, syspopup_list); + } + } + closedir(dp); + + return 0; +} + +static const char *__get_syspopup_path(void) +{ + static char path[PATH_MAX]; + char *profile = NULL; + + if (access(PATH_SYSPOPUP_DEFAULT, F_OK) == 0) + return PATH_SYSPOPUP_DEFAULT; + + system_info_get_platform_string("http://tizen.org/feature/profile", + &profile); + if (profile == NULL) { + printf("Failed to get profile info\n"); + snprintf(path, sizeof(path), "%s/mobile", PATH_SYSPOPUP); + return path; + } + + snprintf(path, sizeof(path), "%s/%s", PATH_SYSPOPUP, profile); + free(profile); + + return path; +} + +static int __init_db(void) +{ + GList *list = NULL; + int ret; + + ret = __load_syspopup_info(__get_syspopup_path(), &list); + if (ret < 0) + goto end; + + ret = syspopup_parser_db_open(); + if (ret < 0) + goto end; + + ret = syspopup_parser_db_insert(list); + +end: + syspopup_parser_db_close(); + + if (list) + g_list_free_full(list, (GDestroyNotify)syspopup_free); + + return ret; +} + +int main(int argc, char **argv) +{ + int ret; + GOptionContext *context; + GError *error = NULL; + gpointer opt_force = NULL; + GOptionEntry entries[] = { + {"force", 'f', 0, G_OPTION_ARG_NONE, &opt_force, + "Remove an existing db file and initialize it", NULL}, + {NULL} + }; + + if (getuid() != ROOT_UID) { + printf("This binary should be run as root user\n"); + return -1; + } + + context = g_option_context_new(NULL); + g_option_context_add_main_entries(context, entries, NULL); + if (!g_option_context_parse(context, &argc, &argv, &error)) { + printf("%s: %s\n", argv[0], error->message); + g_option_context_free(context); + g_clear_error(&error); + return -1; + } + g_option_context_free(context); + + if (opt_force) { + ret = syspopup_parser_db_unlink(); + if (ret < 0) + return -1; + } else { + if (syspopup_parser_db_exist()) { + printf("The db file already exists.\n"); + return 0; + } + } + + return __init_db(); +} diff --git a/tool/sp_initdb/src/syspopup_parser.c b/tool/sp_initdb/src/syspopup_parser.c new file mode 100644 index 0000000..1e74186 --- /dev/null +++ b/tool/sp_initdb/src/syspopup_parser.c @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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. + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> +#include <ctype.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/smack.h> + +#include <glib.h> +#include <libxml/parser.h> +#include <libxml/xmlschemas.h> + +#include "syspopup_private.h" +#include "syspopup_parser.h" +#include "syspopup_type.h" + +#define SCHEMA_FILE SYSCONFDIR "/syspopup/preload/manifest.xsd" + +typedef enum { + SYSPOPUP_ATTR_NONE, + SYSPOPUP_ATTR_NAME, + SYSPOPUP_ATTR_APPID, + SYSPOPUP_ATTR_PRIORITY, + SYSPOPUP_ATTR_FOCUS, + SYSPOPUP_ATTR_TIMEOUT, + SYSPOPUP_ATTR_TERM_ACTION, + SYSPOPUP_ATTR_ENDKEY_ACTION, + SYSPOPUP_ATTR_MAX, +} syspopup_attr_e; + +typedef int (*syspopup_parser_func)(xmlNodePtr node, void *user_data); + +static int __check_manifest_validation(const char *manifest) +{ + xmlSchemaParserCtxtPtr ctx; + xmlSchemaValidCtxtPtr vctx; + xmlSchemaPtr xschema; + int ret; + + if (!manifest) { + _E("Invalid parameter"); + return -1; + } + + ctx = xmlSchemaNewParserCtxt(SCHEMA_FILE); + if (!ctx) { + _E("xmlSchemaNewParserCtxt() is failed. manifest(%s)", + manifest); + return -1; + } + + xschema = xmlSchemaParse(ctx); + if (!xschema) { + _E("xmlSchemaParse() is failed. manifest(%s)", manifest); + xmlSchemaFreeParserCtxt(ctx); + return -1; + } + + vctx = xmlSchemaNewValidCtxt(xschema); + if (!vctx) { + _E("xmlSchemaNewValidCtxt() is failed. manifest(%s)", + manifest); + xmlSchemaFree(xschema); + xmlSchemaFreeParserCtxt(ctx); + return -1; + } + + xmlSchemaSetValidErrors(vctx, (xmlSchemaValidityErrorFunc)fprintf, + (xmlSchemaValidityWarningFunc)fprintf, stderr); + + ret = xmlSchemaValidateFile(vctx, manifest, 0); + if (ret == -1) { + _E("xmlSchemaValidateFile() is failed. manifest(%s)", manifest); + } else if (ret == 0) { + _D("Manifest is valid. manifest(%s)", manifest); + } else { + _E("Manifest Validation Failed with error code %d", ret); + ret = -1; + } + + xmlSchemaFreeValidCtxt(vctx); + xmlSchemaFree(xschema); + xmlSchemaFreeParserCtxt(ctx); + + return ret; +} + +static char *__get_attr(xmlNodePtr node, const char *name) +{ + xmlChar *val; + char *attr = NULL; + + val = xmlGetProp(node, (const xmlChar *)name); + if (val) { + attr = strdup((char *)val); + xmlFree(val); + } + + return attr; +} + +static int __syspopup_attr_name(xmlNodePtr node, void *user_data) +{ + syspopup_t *info = (syspopup_t *)user_data; + char *name; + + name = __get_attr(node, "name"); + if (!name) { + _E("Failed to get attribute name"); + return -1; + } + + info->name = name; + + return 0; +} + +static int __syspopup_attr_appid(xmlNodePtr node, void *user_data) +{ + syspopup_t *info = (syspopup_t *)user_data; + char *appid; + + appid = __get_attr(node, "appid"); + if (!appid) { + _E("Failed to get attribute appid"); + return -1; + } + + info->appid = appid; + + return 0; +} + +static int __priority_to_integer(const char *priority) +{ + if (!strcasecmp(priority, "default")) + return 0; + else if (!strcasecmp(priority, "medium")) + return 1; + else if (!strcasecmp(priority, "high")) + return 2; + else if (!strcasecmp(priority, "top")) + return 3; + + return -1; +} + +static int __syspopup_attr_priority(xmlNodePtr node, void *user_data) +{ + syspopup_t *info = (syspopup_t *)user_data; + char *priority; + + priority = __get_attr(node, "priority"); + if (!priority) { + _E("Failed to get attribute priority"); + return -1; + } + + info->priority = __priority_to_integer(priority); + if (info->priority < 0) { + _E("Priority(%s) attribute must be 'default' or 'medium' or " + "'high' or 'top'", priority); + free(priority); + return -1; + } + free(priority); + + return 0; +} + +static bool __is_boolean(const char *value) +{ + if (!strcasecmp(value, "true") || !strcasecmp(value, "false")) + return true; + + return false; +} + +static int __syspopup_attr_focus(xmlNodePtr node, void *user_data) +{ + syspopup_t *info = (syspopup_t *)user_data; + char *focus; + + focus = __get_attr(node, "focus"); + if (!focus) { + _E("Failed to get attribute focus"); + return -1; + } + + if (!__is_boolean(focus)) { + _E("focus(%s) attribute must be 'true' or 'false'", focus); + free(focus); + return -1; + } + + if (!strcasecmp(focus, "true")) + info->focus = 0; + else + info->focus = 1; + + free(focus); + + return 0; +} + +static int __syspopup_attr_timeout(xmlNodePtr node, void *user_data) +{ + syspopup_t *info = (syspopup_t *)user_data; + char *timeout; + + timeout = __get_attr(node, "timeout"); + if (!timeout) { + _E("Failed to get attribute timeout"); + return -1; + } + + info->timeout = atoi(timeout); + free(timeout); + + return 0; +} + +static int __action_to_integer(const char *action) +{ + if (!strcasecmp(action, "term")) + return 0; + else if (!strcasecmp(action, "hide")) + return 1; + else if (!strcasecmp(action, "ignore")) + return 2; + + return -1; +} + +static int __syspopup_attr_term_action(xmlNodePtr node, void *user_data) +{ + syspopup_t *info = (syspopup_t *)user_data; + char *term_action; + + term_action = __get_attr(node, "term-action"); + if (!term_action) { + _E("Failed to get attribute term-action"); + return -1; + } + + info->term_action = __action_to_integer(term_action); + if (info->term_action < 0) { + _E("term-action(%s) attribute must be 'term' or 'hide' or " + "'ignore'", term_action); + free(term_action); + return -1; + } + free(term_action); + + return 0; +} + +static int __syspopup_attr_endkey_action(xmlNodePtr node, void *user_data) +{ + syspopup_t *info = (syspopup_t *)user_data; + char *endkey_action; + + endkey_action = __get_attr(node, "endkey-action"); + if (!endkey_action) { + _E("Failed to get attribute term-action"); + return -1; + } + + info->endkey_action = __action_to_integer(endkey_action); + if (info->endkey_action < 0) { + _E("endkey-action(%s) attribute must be 'term' or 'hide' or " + "'ignore'", endkey_action); + free(endkey_action); + return -1; + } + free(endkey_action); + + return 0; +} + +static syspopup_parser_func __attr_table[] = { + [SYSPOPUP_ATTR_NAME] = __syspopup_attr_name, + [SYSPOPUP_ATTR_APPID] = __syspopup_attr_appid, + [SYSPOPUP_ATTR_PRIORITY] = __syspopup_attr_priority, + [SYSPOPUP_ATTR_FOCUS] = __syspopup_attr_focus, + [SYSPOPUP_ATTR_TIMEOUT] = __syspopup_attr_timeout, + [SYSPOPUP_ATTR_TERM_ACTION] = __syspopup_attr_term_action, + [SYSPOPUP_ATTR_ENDKEY_ACTION] = __syspopup_attr_endkey_action, +}; + +static int __parse_syspopup(xmlNodePtr node, syspopup_t **syspopup) +{ + syspopup_t *info; + int ret; + int i; + + info = calloc(1, sizeof(syspopup_t)); + if (!info) { + _E("Out of memory"); + return -1; + } + + for (i = SYSPOPUP_ATTR_NONE; i < SYSPOPUP_ATTR_MAX; i++) { + if (!__attr_table[i]) + continue; + + ret = __attr_table[i](node, info); + if (ret < 0) { + _E("Failed to parse attribute %d", i); + syspopup_free(info); + return -1; + } + } + + *syspopup = info; + + return 0; +} + +int syspopup_parser_parse(const char *manifest, GList **syspopup_list) +{ + GList *list = NULL; + xmlDocPtr doc; + xmlNodePtr root; + xmlNodePtr node; + syspopup_t *info; + int ret; + + if (!manifest || !syspopup_list) { + _E("Invalid parameter"); + return -1; + } + + ret = __check_manifest_validation(manifest); + if (ret < 0) + return -1; + + doc = xmlParseFile(manifest); + if (!doc) { + _E("Failed to parse %s", manifest); + return -1; + } + + root = xmlDocGetRootElement(doc); + if (!root) { + _E("Failed to get root element %s", manifest); + xmlFreeDoc(doc); + return -1; + } + + for (node = root->children; node; node = node->next) { + if (!node->name) + continue; + + if (strcmp((char *)node->name, "syspopup") != 0) + continue; + + info = NULL; + ret = __parse_syspopup(node, &info); + if (ret < 0) { + _E("Failed to parse syspopup"); + continue; + } + + list = g_list_append(list, info); + } + + *syspopup_list = list; + xmlFreeDoc(doc); + + return 0; +} diff --git a/tool/sp_initdb/src/syspopup_parser_db.c b/tool/sp_initdb/src/syspopup_parser_db.c new file mode 100644 index 0000000..9a98dc6 --- /dev/null +++ b/tool/sp_initdb/src/syspopup_parser_db.c @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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. + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/smack.h> +#include <errno.h> + +#include <glib.h> +#include <sqlite3.h> +#include <tzplatform_config.h> +#include <system_info.h> + +#include "syspopup_parser_db.h" +#include "syspopup_private.h" +#include "syspopup_type.h" + +#define CREATE_SYSPOPUP_INFO_TABLE \ + "PRAGMA journal_mode = PERSIST; " \ + "CREATE TABLE IF NOT EXISTS syspopup_info ( " \ + "id INTEGER PRIMARY KEY, " \ + "name TEXT UNIQUE NOT NULL, " \ + "prio INTEGER, " \ + "focus INTEGER, " \ + "timeout INTEGER, " \ + "term_act INTEGER, " \ + "endkey_act INTEGER, " \ + "pkgname TEXT NOT NULL);" + +#define QUERY_INSERT_SYSPOPUP_INFO \ + "INSERT OR REPLACE INTO syspopup_info " \ + "(name, prio, focus, timeout, term_act, endkey_act, pkgname) " \ + "VALUES(?, ?, ?, ?, ?, ?, ?);" + +#define BIND_TEXT(db, stmt, i, text) do { \ + if (sqlite3_bind_text(stmt, i, text, -1, SQLITE_STATIC) != SQLITE_OK) {\ + _E("sqlite3_bind_text() is failed. error(%s)", \ + sqlite3_errmsg(db)); \ + sqlite3_finalize(stmt); \ + return -1; \ + } \ +} while (0) + +#define BIND_INT(db, stmt, i, val) do { \ + if (sqlite3_bind_int(stmt, i, val) != SQLITE_OK) { \ + _E("sqlite3_bind_int() is failed. error(%s)", \ + sqlite3_errmsg(db)); \ + sqlite3_finalize(stmt); \ + return -1; \ + } \ +} while (0) + +#define PATH_DB tzplatform_mkpath(TZ_SYS_DB, ".syspopup.db") +#define PATH_DB_JOURNAL tzplatform_mkpath(TZ_SYS_DB, ".syspopup.db-journal") +#define DB_LABEL "User::Home" + +static sqlite3 *__db; + +bool syspopup_parser_db_exist(void) +{ + if (access(PATH_DB, F_OK) == 0) + return true; + + return false; +} + +int syspopup_parser_db_unlink(void) +{ + int ret; + + ret = access(PATH_DB, F_OK); + if (ret == 0) { + ret = unlink(PATH_DB); + if (ret != 0) { + _E("Failed to delete %s. errno(%d)", + PATH_DB, errno); + return -1; + } + } + + return 0; +} + +void syspopup_parser_db_close(void) +{ + if (__db == NULL) + return; + + sqlite3_close(__db); + __db = NULL; +} + +int syspopup_parser_db_open(void) +{ + int ret; + const char *query = CREATE_SYSPOPUP_INFO_TABLE; + char *err_msg = NULL; + + ret = sqlite3_open_v2(PATH_DB, &__db, + SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL); + if (ret != SQLITE_OK) { + _E("Failed to create syspopup db - ret(%d)", ret); + syspopup_parser_db_close(); + return -1; + } + + ret = sqlite3_exec(__db, query, NULL, NULL, &err_msg); + if (ret != SQLITE_OK) { + _E("Failed to create syspopup info table(%s)", err_msg); + sqlite3_free(err_msg); + syspopup_parser_db_close(); + return -1; + } + + ret = smack_setlabel(PATH_DB, DB_LABEL, SMACK_LABEL_ACCESS); + if (ret < 0) { + _E("Failed to set label"); + syspopup_parser_db_close(); + return -1; + } + + if (access(PATH_DB_JOURNAL, F_OK) == 0) { + ret = smack_setlabel(PATH_DB_JOURNAL, DB_LABEL, + SMACK_LABEL_ACCESS); + if (ret < 0) { + _E("Failed to set label of journal file"); + syspopup_parser_db_close(); + return -1; + } + } + + return 0; +} + +int syspopup_parser_db_insert(GList *syspopup_list) +{ + const char *query = QUERY_INSERT_SYSPOPUP_INFO; + sqlite3_stmt *stmt = NULL; + syspopup_t *info; + GList *iter; + int ret; + int idx; + + if (!syspopup_list) { + _E("Invalid parameter"); + return -1; + } + + ret = sqlite3_prepare_v2(__db, query, strlen(query), &stmt, NULL); + if (ret != SQLITE_OK) { + _E("sqlite3_prepare_v2() is failed. error(%s)", + sqlite3_errmsg(__db)); + return -1; + } + + iter = syspopup_list; + while (iter) { + info = (syspopup_t *)iter->data; + iter = g_list_next(iter); + if (!info) + continue; + + idx = 1; + BIND_TEXT(__db, stmt, idx++, info->name); + BIND_INT(__db, stmt, idx++, info->priority); + BIND_INT(__db, stmt, idx++, info->focus); + BIND_INT(__db, stmt, idx++, info->timeout); + BIND_INT(__db, stmt, idx++, info->term_action); + BIND_INT(__db, stmt, idx++, info->endkey_action); + BIND_TEXT(__db, stmt, idx++, info->appid); + + ret = sqlite3_step(stmt); + if (ret != SQLITE_DONE) { + _E("sqlite3_step() is failed. name[%s] appid[%s]", + info->name, info->appid); + ret = -1; + goto end; + } + + sqlite3_reset(stmt); + + _I("syspopup name[%s] appid[%s] priority[%d] focus[%d] " + "timeout[%d] term-action[%d] endkey-action[%d]", + info->name, info->appid, info->priority, + info->focus, info->timeout, info->term_action, + info->endkey_action); + } + + ret = 0; +end: + sqlite3_finalize(stmt); + + return ret; +} diff --git a/tool/sp_initdb/src/syspopup_type.c b/tool/sp_initdb/src/syspopup_type.c new file mode 100644 index 0000000..7949178 --- /dev/null +++ b/tool/sp_initdb/src/syspopup_type.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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. + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> +#include <ctype.h> +#include <unistd.h> +#include <sys/types.h> + +#include "syspopup_private.h" +#include "syspopup_type.h" + +void syspopup_free(syspopup_t *info) +{ + if (!info) + return; + + if (info->name) + free(info->name); + + if (info->appid) + free(info->appid); + + free(info); +} |