summaryrefslogtreecommitdiff
path: root/tool/sp_initdb/src
diff options
context:
space:
mode:
Diffstat (limited to 'tool/sp_initdb/src')
-rw-r--r--tool/sp_initdb/src/sp_initdb.c157
-rw-r--r--tool/sp_initdb/src/syspopup_parser.c390
-rw-r--r--tool/sp_initdb/src/syspopup_parser_db.c211
-rw-r--r--tool/sp_initdb/src/syspopup_type.c41
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);
+}