From fe4720fe7d4098b799bf8cf385eddbbec605dec2 Mon Sep 17 00:00:00 2001 From: Jiwoong Im Date: Mon, 1 Jun 2015 14:23:24 +0900 Subject: [PATCH] support resource manager API. Provides interfaces to check and insert resource.xml and get resource data of specific package from db. JIRA ticket : TC-2491 Change-Id: Ibd30c9840af30e877caec8d2cf4ba73c72092b45 Signed-off-by: Jiwoong Im --- CMakeLists.txt | 7 +- include/pkgmgrinfo_resource.h | 70 ++++++ packaging/pkgmgr-info.spec | 4 + parser/CMakeLists.txt | 10 +- parser/pkgmgr_parser.h | 8 + parser/pkgmgr_parser_db.c | 23 ++ parser/pkgmgr_parser_resource.c | 476 +++++++++++++++++++++++++++++++++++ parser/pkgmgr_parser_resource.h | 106 ++++++++ parser/pkgmgr_parser_resource_db.c | 504 +++++++++++++++++++++++++++++++++++++ parser/pkgmgr_parser_resource_db.h | 20 ++ parser/res.xsd.in | 33 +++ src/pkgmgrinfo_resource.c | 12 + 12 files changed, 1267 insertions(+), 6 deletions(-) create mode 100755 include/pkgmgrinfo_resource.h create mode 100755 parser/pkgmgr_parser_resource.c create mode 100755 parser/pkgmgr_parser_resource.h create mode 100755 parser/pkgmgr_parser_resource_db.c create mode 100755 parser/pkgmgr_parser_resource_db.h create mode 100755 parser/res.xsd.in create mode 100644 src/pkgmgrinfo_resource.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b9f75d..450a6a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,14 +18,14 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/src ${CMAKE_ ### Required packages INCLUDE(FindPkgConfig) -pkg_check_modules(pkgs REQUIRED glib-2.0 dlog vconf sqlite3 db-util libxml-2.0 dbus-1 dbus-glib-1 libtzplatform-config libsmack) +pkg_check_modules(pkgs REQUIRED glib-2.0 dlog vconf sqlite3 db-util libxml-2.0 dbus-1 dbus-glib-1 libtzplatform-config libsmack bundle) FOREACH(flag ${pkgs_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") ENDFOREACH(flag) -pkg_check_modules(libpkgs REQUIRED glib-2.0 dlog vconf sqlite3 db-util libxml-2.0 dbus-1 dbus-glib-1 libtzplatform-config libsmack) +pkg_check_modules(libpkgs REQUIRED glib-2.0 dlog vconf sqlite3 db-util libxml-2.0 dbus-1 dbus-glib-1 libtzplatform-config libsmack bundle) FOREACH(flag ${libpkgs_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") @@ -46,7 +46,7 @@ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") add_subdirectory(parser) ## build pkgmgr-info library -add_library(pkgmgr-info SHARED src/pkgmgr-info.c src/pkgmgr-info-internal.c) +add_library(pkgmgr-info SHARED src/pkgmgr-info.c src/pkgmgr-info-internal.c src/pkgmgrinfo_resource.c) SET_TARGET_PROPERTIES(pkgmgr-info PROPERTIES SOVERSION ${VERSION_MAJOR}) @@ -62,6 +62,7 @@ configure_file(tag_parser_list.txt.in tag_parser_list.txt @ONLY) INSTALL(TARGETS pkgmgr-info DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/pkgmgr-info.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/pkgmgr-info.h DESTINATION include) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/pkgmgrinfo_resource.h DESTINATION include) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/parser_path.conf DESTINATION ${SYSCONFDIR}/package-manager/) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/mdparser_list.txt DESTINATION ${SYSCONFDIR}/package-manager/parserlib/metadata) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/category_parser_list.txt DESTINATION ${SYSCONFDIR}/package-manager/parserlib/category) diff --git a/include/pkgmgrinfo_resource.h b/include/pkgmgrinfo_resource.h new file mode 100755 index 0000000..95d2b17 --- /dev/null +++ b/include/pkgmgrinfo_resource.h @@ -0,0 +1,70 @@ +#ifndef __PKGMGRINFO_RESOURCE_H_ +#define __PKGMGRINFO_RESOURCE_H_ + +#include +#include + +#define RSC_GROUP_TYPE_IMAGE "image" +#define RSC_GROUP_TYPE_LAYOUT "layout" +#define RSC_GROUP_TYPE_SOUND "sound" +#define RSC_GROUP_TYPE_BIN "bin" + +#define RSC_NODE_ATTR_SCREEN_DPI "screen-dpi" +#define RSC_NODE_ATTR_SCREEN_DPI_RANGE "screen-dpi-range" +#define RSC_NODE_ATTR_SCREEN_WIDTH_RANGE "screen-width-range" +#define RSC_NODE_ATTR_SCREEN_LARGE "screen-large" +#define RSC_NODE_ATTR_SCREEN_BPP "screen-bpp" +#define RSC_NODE_ATTR_PLATFORM_VER "platform-version" +#define RSC_NODE_ATTR_LANGUAGE "language" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + char *folder; + bundle *attr; +} resource_node_t; + +typedef struct { + char *folder; + char *type; + GList *node_list; +} resource_group_t; + +typedef struct { + char *package; + GList *group_list; +} resource_data_t; + +/** + * @fn int pkgmgrinfo_resource_close(resource_data_t data) + * @brief This API frees given data and its own variables + * + * @par This API is for capi-appfw-application. + * @par Sync (or) Async : Synchronous API + * + * @param[in] data structure of resource_data_t + * @return 0 on succeed and -1 on failure, -2 on invalid parameter + */ +int pkgmgrinfo_resource_close(resource_data_t *data); + +/** + * @fn int pkgmgrinfo_resource_open(const char *package, resource_data_t **data) + * @brief This API will get resource data of specific package from db + * + * @par This API is for capi-appfw-application. + * @par Sync (or) Async : Synchronous API + * + * @param[in] package packageID + * @param[out]data resource_data type structure. it will filled with resource data + * @return 0 on succeed and -1 on failure, -2 on invalid parameter + */ +int pkgmgrinfo_resource_open(const char *package, resource_data_t **data); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/packaging/pkgmgr-info.spec b/packaging/pkgmgr-info.spec index 16a87b2..4fb3c65 100644 --- a/packaging/pkgmgr-info.spec +++ b/packaging/pkgmgr-info.spec @@ -16,6 +16,7 @@ BuildRequires: pkgconfig(dbus-1) BuildRequires: pkgconfig(dbus-glib-1) BuildRequires: pkgconfig(libtzplatform-config) BuildRequires: pkgconfig(libsmack) +BuildRequires: pkgconfig(bundle) %description Packager Manager infomation api for packaging @@ -76,6 +77,7 @@ chsmack -a '*' %{TZ_SYS_RW_PACKAGES} %manifest %{name}.manifest %defattr(-,root,root,-) %{_includedir}/pkgmgr-info.h +%{_includedir}/pkgmgrinfo_resource.h %{_libdir}/pkgconfig/pkgmgr-info.pc %{_libdir}/libpkgmgr-info.so @@ -86,6 +88,7 @@ chsmack -a '*' %{TZ_SYS_RW_PACKAGES} %config %{_sysconfdir}/package-manager/preload/preload_list.txt %config %{_sysconfdir}/package-manager/preload/manifest.xsd %config %{_sysconfdir}/package-manager/preload/xml.xsd +%config %{_sysconfdir}/package-manager/preload/res.xsd %config %{_sysconfdir}/package-manager/parser_path.conf %config %{_sysconfdir}/package-manager/parserlib/metadata/mdparser_list.txt %config %{_sysconfdir}/package-manager/parserlib/category/category_parser_list.txt @@ -96,5 +99,6 @@ chsmack -a '*' %{TZ_SYS_RW_PACKAGES} %defattr(-,root,root,-) %{_includedir}/pkgmgr/pkgmgr_parser.h %{_includedir}/pkgmgr/pkgmgr_parser_db.h +%{_includedir}/pkgmgr/pkgmgr_parser_resource.h %{_libdir}/pkgconfig/pkgmgr-parser.pc %{_libdir}/libpkgmgr_parser.so diff --git a/parser/CMakeLists.txt b/parser/CMakeLists.txt index 8904ecc..54075ca 100644 --- a/parser/CMakeLists.txt +++ b/parser/CMakeLists.txt @@ -26,7 +26,7 @@ message(STATUS "version/major : ${VERSION} / ${VERSION_MAJOR}") ### Get required CFLAGS, LDFLAGS from pkg-config include(FindPkgConfig) -pkg_check_modules(parser_pkgs REQUIRED dlog libxml-2.0 glib-2.0 sqlite3 db-util vconf) +pkg_check_modules(parser_pkgs REQUIRED dlog libxml-2.0 glib-2.0 sqlite3 db-util vconf bundle) foreach(flag ${parser_pkgs_CFLAGS}) set(parser_pkgs_CFLAGS_str "${parser_pkgs_CFLAGS_str} ${flag}") @@ -45,7 +45,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) ## pkgmgr_parser object (by sewook.park) # This library is for installer backend -add_library(pkgmgr_parser SHARED pkgmgr_parser.c pkgmgr_parser_db.c pkgmgr_parser_signature.c) +add_library(pkgmgr_parser SHARED pkgmgr_parser.c pkgmgr_parser_db.c pkgmgr_parser_signature.c pkgmgr_parser_resource_db.c pkgmgr_parser_resource.c) #add_library(pkgmgr_parser SHARED pkgmgr_parser.c) set_target_properties(pkgmgr_parser PROPERTIES SOVERSION ${VERSION_MAJOR}) set_target_properties(pkgmgr_parser PROPERTIES VERSION ${VERSION}) @@ -57,6 +57,7 @@ configure_file(pkgmgr-parser.pc.in ${CMAKE_CURRENT_BINARY_DIR}/pkgmgr-parser.pc configure_file(preload_list.txt.in preload_list.txt @ONLY) configure_file(manifest.xsd.in manifest.xsd @ONLY) configure_file(xml.xsd.in xml.xsd @ONLY) +configure_file(res.xsd.in res.xsd @ONLY) ## Install INSTALL(TARGETS @@ -69,7 +70,9 @@ INSTALL(FILES INSTALL(FILES pkgmgr_parser_db.h DESTINATION include/pkgmgr) - +INSTALL(FILES + pkgmgr_parser_resource.h + DESTINATION include/pkgmgr) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/pkgmgr-parser.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) @@ -77,3 +80,4 @@ INSTALL(FILES INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/preload_list.txt DESTINATION ${SYSCONFDIR}/package-manager/preload/) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/manifest.xsd DESTINATION ${SYSCONFDIR}/package-manager/preload/) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/xml.xsd DESTINATION ${SYSCONFDIR}/package-manager/preload/) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/res.xsd DESTINATION ${SYSCONFDIR}/package-manager/preload/) diff --git a/parser/pkgmgr_parser.h b/parser/pkgmgr_parser.h index cbbf806..6328f73 100644 --- a/parser/pkgmgr_parser.h +++ b/parser/pkgmgr_parser.h @@ -59,6 +59,14 @@ extern "C" { #define PKGMGR_PARSER_EMPTY_STR "" #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER) +/** + * @brief API return values + */ +enum { + PM_PARSER_R_EINVAL = -2, /**< Invalid argument */ + PM_PARSER_R_ERROR = -1, /**< General error */ + PM_PARSER_R_OK = 0 /**< General success */ +}; /** * @brief List definitions. diff --git a/parser/pkgmgr_parser_db.c b/parser/pkgmgr_parser_db.c index 83383f5..b34ae43 100644 --- a/parser/pkgmgr_parser_db.c +++ b/parser/pkgmgr_parser_db.c @@ -255,6 +255,18 @@ sqlite3 *pkgmgr_cert_db; "FOREIGN KEY(app_id) " \ "REFERENCES package_app_info(app_id) " \ "ON DELETE CASCADE)" +#define QUERY_CREATE_TABLE_PACKAGE_RESOURCE_INFO "CREATE TABLE IF NOT EXISTS package_resource_info" \ + "(pkg_id text NOT NULL," \ + "group_folder text NOT NULL," \ + "group_type text NOT NULL," \ + "PRIMARY KEY(pkg_id, group_type))" + +#define QUERY_CREATE_TABLE_PACKAGE_RESOURCE_DATA "CREATE TABLE IF NOT EXISTS package_resource_data" \ + "(id integer REFERENCES package_resource_info(rowid)," \ + "node_folder text NOT NULL," \ + "attr_name text NOT NULL," \ + "attr_value test NOT NULL," \ + "PRIMARY KEY(id, node_folder, attr_name))" static int __insert_uiapplication_info(manifest_x *mfx); static int __insert_serviceapplication_info(manifest_x *mfx); @@ -2172,6 +2184,17 @@ API int pkgmgr_parser_initialize_db(void) _LOGD("package cert index info DB initialization failed\n"); return ret; } + /*resource DB*/ + ret = __initialize_db(pkgmgr_parser_db, QUERY_CREATE_TABLE_PACKAGE_RESOURCE_INFO); + if (ret == -1) { + _LOGD("package resource info DB initialization failed\n"); + return ret; + } + ret = __initialize_db(pkgmgr_parser_db, QUERY_CREATE_TABLE_PACKAGE_RESOURCE_DATA); + if (ret == -1) { + _LOGD("package resource data DB initialization failed\n"); + return ret; + } return 0; } diff --git a/parser/pkgmgr_parser_resource.c b/parser/pkgmgr_parser_resource.c new file mode 100755 index 0000000..e749ffd --- /dev/null +++ b/parser/pkgmgr_parser_resource.c @@ -0,0 +1,476 @@ +/* + * pkgmgr-info + * + * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee , Shobhit Srivastava + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pkgmgr-info.h" +#include "pkgmgr-info-debug.h" +#include "pkgmgr_parser_resource.h" +#include "pkgmgr_parser_resource_db.h" +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "PKGMGR_PARSER" + +#define XMLCHAR(s) (const xmlChar *)s +#define ASCII(s) (char *)s + +#define FREE_AND_NULL(ptr) do { \ + if (ptr) { \ + free((void *)ptr); \ + ptr = NULL; \ + } \ + } while (0) + + +#define RSC_XML_QUALIFIER "res" +#define RSC_GROUP_NAME_SEPERATOR '-' +#define RSC_GROUP "group" +#define RSC_GROUP_ATTR_FOLDER "folder" +#define RSC_GROUP_ATTR_TYPE "type" +#define RSC_NODE "node" +#define RSC_MANIFEST_SCHEMA_FILE "/etc/package-manager/preload/res.xsd" + +static int __next_child_element(xmlTextReaderPtr reader, int depth) +{ + int ret = xmlTextReaderRead(reader); + int cur = xmlTextReaderDepth(reader); + while (ret == 1) { + switch (xmlTextReaderNodeType(reader)) { + case XML_READER_TYPE_ELEMENT: + if (cur == depth + 1) + return 1; + break; + case XML_READER_TYPE_TEXT: + /*text is handled by each function separately*/ + if (cur == depth + 1) + return 0; + break; + case XML_READER_TYPE_END_ELEMENT: + if (cur == depth) + return 0; + break; + default: + if (cur <= depth) + return 0; + break; + } + ret = xmlTextReaderRead(reader); + cur = xmlTextReaderDepth(reader); + } + return ret; +} + +static void _free_node_list(void *data, void *user_data) +{ + resource_node_t *tmp_node = (resource_node_t *)data; + + if (tmp_node == NULL) { + _LOGE("node list's element is NULL"); + return; + } + + FREE_AND_NULL(tmp_node->folder); + if (tmp_node->attr != NULL) { + bundle_free(tmp_node->attr); + tmp_node->attr = NULL; + } +} + +static void _free_group_list(void *data, void *user_data) +{ + resource_group_t *tmp_group = (resource_group_t *)data; + + if (tmp_group == NULL) { + _LOGE("group list's element is NULL"); + return; + } + + FREE_AND_NULL(tmp_group->folder); + FREE_AND_NULL(tmp_group->type); + + g_list_free_full(tmp_group->node_list, (GDestroyNotify)_free_node_list); +} + +static void __save_resource_attribute_into_bundle(xmlTextReaderPtr reader, char *attribute, bundle **b) +{ + xmlChar *attr_val = xmlTextReaderGetAttribute(reader, XMLCHAR(attribute)); + + if (attr_val) + bundle_add_str(*b, attribute, (char *)attr_val); +} + +static void __save_resource_attribute(xmlTextReaderPtr reader, char *attribute, char **xml_attribute, char *default_value) +{ + xmlChar *attrib_val = xmlTextReaderGetAttribute(reader, XMLCHAR(attribute)); + + if (attrib_val) + *xml_attribute = strdup(ASCII(attrib_val)); + else { + if (default_value != NULL) + *xml_attribute = strdup(default_value); + } +} + + +static void __psp_process_node(xmlTextReaderPtr reader, resource_node_t **res_node) +{ + char *node_folder = NULL; + + __save_resource_attribute(reader, "folder", &node_folder, NULL); + bundle *b = NULL; + (*res_node)->folder = node_folder; + + /*retrieve node's attribute and put it into bundle*/ + b = bundle_create(); + + __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_SCREEN_DPI, &b); + __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_SCREEN_DPI_RANGE, &b); + __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_SCREEN_WIDTH_RANGE, &b); + __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_SCREEN_LARGE, &b); + __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_SCREEN_BPP, &b); + __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_PLATFORM_VER, &b); + __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_LANGUAGE, &b); + + (*res_node)->attr = b; +} + +static int __psp_process_group(xmlTextReaderPtr reader, resource_group_t **res_group, char *group_type) +{ + int depth = -1; + int ret = -1; + resource_group_t *tmp_group = NULL; + resource_node_t *res_node = NULL; + const xmlChar *node; + char *folder = NULL; + + if (reader == NULL || *res_group == NULL || group_type == NULL) { + _LOGE("invalid parameter"); + return PMINFO_R_EINVAL; + } + + tmp_group = *res_group; + /*handle group's own attribute*/ + __save_resource_attribute(reader, RSC_GROUP_ATTR_FOLDER, &folder, NULL); + tmp_group->folder = folder; + tmp_group->type = group_type; + + depth = xmlTextReaderDepth(reader); + while ((ret = __next_child_element(reader, depth))) { + node = xmlTextReaderConstName(reader); + if (!node) { + _LOGE("xmlTextReaderConstName value is NULL"); + return PMINFO_R_ERROR; + } + + res_node = NULL; + if (!strcmp(ASCII(node), RSC_NODE)) { + res_node = malloc(sizeof(resource_node_t)); + if (res_node == NULL) { + _LOGE("malloc failed"); + return -1; + } + tmp_group->node_list = g_list_append(tmp_group->node_list, res_node); + __psp_process_node(reader, &res_node); + } else { + _LOGE("unidentified node has found[%s]", ASCII(node)); + return PMINFO_R_ERROR; + } + } + return ret; +} + +static int __is_group(char *node, char **type) +{ + char *tmp = NULL; + + if (node == NULL) { + _LOGE("node is null"); + return PMINFO_R_EINVAL; + } + + tmp = strchr(node, RSC_GROUP_NAME_SEPERATOR); + tmp = tmp + 1; /*remove dash seperator*/ + if (!strcmp(tmp, PKGMGR_RSC_GROUP_TYPE_IMAGE)) + *type = strdup(tmp); + else if (!strcmp(tmp, PKGMGR_RSC_GROUP_TYPE_LAYOUT)) + *type = strdup(tmp); + else if (!strcmp(tmp, PKGMGR_RSC_GROUP_TYPE_SOUND)) + *type = strdup(tmp); + else if (!strcmp(tmp, PKGMGR_RSC_GROUP_TYPE_BIN)) + *type = strdup(tmp); + else + return PMINFO_R_ERROR; + + if (*type == NULL) { + _LOGE("strdup failed with node[%s]", node); + return PMINFO_R_ERROR; + } + + return PMINFO_R_OK; +} + +static int __start_resource_process(xmlTextReaderPtr reader, GList **list) +{ + GList *tmp_list = NULL; + const xmlChar *node; + char *group_type = NULL; + int ret = -1; + int depth = -1; + resource_group_t *res_group = NULL; + + if (reader == NULL) { + _LOGE("reader is null"); + return PMINFO_R_EINVAL; + } + + depth = xmlTextReaderDepth(reader); + while ((ret = __next_child_element(reader, depth))) { + node = xmlTextReaderConstName(reader); + if (!node) { + _LOGE("xmlTextReaderConstName value is null"); + return -1; + } + + group_type = NULL; + ret = __is_group(ASCII(node), &group_type); + if (ret) { + _LOGE("unidentified node[%s] has found with error[%d]", ASCII(node), ret); + return ret; + } + res_group = NULL; + res_group = malloc(sizeof(resource_group_t)); + if (res_group == NULL) { + _LOGE("malloc failed"); + return -1; + } + memset(res_group, '\0', sizeof(resource_group_t)); + tmp_list = g_list_append(tmp_list, res_group); + ret = __psp_process_group(reader, &res_group, group_type); + if (ret != 0) { + FREE_AND_NULL(res_group); + return PMINFO_R_ERROR; + } + } + + *list = g_list_first(tmp_list); + return ret; +} + +static int __process_resource_manifest(xmlTextReaderPtr reader, resource_data_t *data) +{ + const xmlChar *node; + int ret = PMINFO_R_ERROR; + + if (reader == NULL) + return PMINFO_R_ERROR; + + ret = __next_child_element(reader, -1); + if (ret) { + node = xmlTextReaderConstName(reader); + retvm_if(!node, PMINFO_R_ERROR, "xmlTextReaderConstName value is NULL\n"); + + if (!strcmp(ASCII(node), RSC_XML_QUALIFIER)) { + ret = __start_resource_process(reader, &data->group_list); + if (data->group_list == NULL) + _LOGE("__process_resource_manifest about to end but group list is null[%d]", ret); + } else { + _LOGE("no manifest element[res] has found"); + return PMINFO_R_ERROR; + } + } + return ret; +} + +static resource_data_t *_pkgmgr_resource_parser_process_manifest_xml(const char *manifest) +{ + xmlTextReaderPtr reader; + resource_data_t *rsc_data = NULL; + + reader = xmlReaderForFile(manifest, NULL, 0); + if (reader) { + rsc_data = malloc(sizeof(resource_data_t)); + if (rsc_data == NULL) { + _LOGE("memory allocation failed"); + return NULL; + } + + memset(rsc_data, '\0', sizeof(resource_data_t)); + if (__process_resource_manifest(reader, rsc_data) < 0) { + _LOGE("parsing failed with given manifest[%s]", manifest); + if (pkgmgr_resource_parser_close(rsc_data) != 0) + _LOGE("closing failed"); + rsc_data = NULL; + } else + _LOGE("parsing succeed"); + + xmlFreeTextReader(reader); + } else { + _LOGE("creating xmlreader failed"); + FREE_AND_NULL(rsc_data); + } + return rsc_data; +} + +API int pkgmgr_resource_parser_open_from_db(const char *package, resource_data_t **data) +{ + resource_data_t *rsc_data = NULL; + int ret = -1; + + if (package == NULL || strlen(package) == 0) { + _LOGE("invalid parameter"); + return PMINFO_R_EINVAL; + } + + ret = pkgmgr_parser_resource_db_load(package, &rsc_data); + if (ret != 0) { + _LOGE("get resource data from db failed"); + return ret; + } + + *data = rsc_data; + return ret; +} + +API int pkgmgr_resource_parser_open(const char *fname, const char *package, resource_data_t **data) +{ + resource_data_t *rsc_data = NULL; + int ret = PMINFO_R_ERROR; + + if (fname == NULL || access(fname, R_OK) != 0) { + _LOGE("filename is null or cannot access file"); + return PMINFO_R_EINVAL; + } + xmlInitParser(); + rsc_data = _pkgmgr_resource_parser_process_manifest_xml(fname); + if (rsc_data == NULL) { + _LOGE("parsing failed"); + goto catch; + } + rsc_data->package = strdup(package); + + *data = rsc_data; + ret = PMINFO_R_OK; +catch: + xmlCleanupParser(); + return ret; +} + +API int pkgmgr_resource_parser_close(resource_data_t *data) +{ + if (data == NULL) { + _LOGE("parameter is NULL"); + return PMINFO_R_EINVAL; + } + + FREE_AND_NULL(data->package); + g_list_free_full(data->group_list, (GDestroyNotify)_free_group_list); + + return PMINFO_R_OK; +} + +API int pkgmgr_resource_parser_insert_into_db(resource_data_t *data) +{ + if (data == NULL) { + _LOGE("parameter is NULL"); + return PMINFO_R_EINVAL; + } + + return pkgmgr_parser_resource_db_save(data->package, data); +} + +API int pkgmgr_resource_parser_delete_from_db(const char *package) +{ + if (package == NULL) { + _LOGE("parameter is NULL"); + return PMINFO_R_EINVAL; + } + + return pkgmgr_parser_resource_db_remove(package); +} + +API int pkgmgr_resource_parser_check_xml_validation(const char *xmlfile) +{ + if (xmlfile == NULL) { + _LOGE("manifest file is NULL\n"); + return PM_PARSER_R_EINVAL; + } + int ret = PM_PARSER_R_OK; + xmlSchemaParserCtxtPtr ctx = NULL; + xmlSchemaValidCtxtPtr vctx = NULL; + xmlSchemaPtr xschema = NULL; + ctx = xmlSchemaNewParserCtxt(RSC_MANIFEST_SCHEMA_FILE); + if (ctx == NULL) { + _LOGE("xmlSchemaNewParserCtxt() Failed\n"); + return PM_PARSER_R_ERROR; + } + xschema = xmlSchemaParse(ctx); + if (xschema == NULL) { + _LOGE("xmlSchemaParse() Failed\n"); + ret = PM_PARSER_R_ERROR; + goto cleanup; + } + vctx = xmlSchemaNewValidCtxt(xschema); + if (vctx == NULL) { + _LOGE("xmlSchemaNewValidCtxt() Failed\n"); + return PM_PARSER_R_ERROR; + } + xmlSchemaSetValidErrors(vctx, (xmlSchemaValidityErrorFunc) fprintf, (xmlSchemaValidityWarningFunc) fprintf, stderr); + ret = xmlSchemaValidateFile(vctx, xmlfile, 0); + if (ret == -1) { + _LOGE("xmlSchemaValidateFile() failed\n"); + ret = PM_PARSER_R_ERROR; + goto cleanup; + } else if (ret == 0) { + _LOGE("Manifest is Valid\n"); + ret = PM_PARSER_R_OK; + goto cleanup; + } else { + _LOGE("Manifest Validation Failed with error code %d\n", ret); + ret = PM_PARSER_R_ERROR; + goto cleanup; + } + +cleanup: + if(vctx != NULL) + xmlSchemaFreeValidCtxt(vctx); + + if(ctx != NULL) + xmlSchemaFreeParserCtxt(ctx); + + if(xschema != NULL) + xmlSchemaFree(xschema); + + return ret; +} diff --git a/parser/pkgmgr_parser_resource.h b/parser/pkgmgr_parser_resource.h new file mode 100755 index 0000000..6f9d6bc --- /dev/null +++ b/parser/pkgmgr_parser_resource.h @@ -0,0 +1,106 @@ +#ifndef __PKGMGR_PARSER_RESOURCE_H_ +#define __PKGMGR_PARSER_RESOURCE_H_ + +#include +#include +#include "pkgmgr_parser.h" +#include "pkgmgrinfo_resource.h" + +#define PKGMGR_RSC_GROUP_TYPE_IMAGE "image" +#define PKGMGR_RSC_GROUP_TYPE_LAYOUT "layout" +#define PKGMGR_RSC_GROUP_TYPE_SOUND "sound" +#define PKGMGR_RSC_GROUP_TYPE_BIN "bin" + +#define RSC_NODE_ATTR_SCREEN_DPI "screen-dpi" +#define RSC_NODE_ATTR_SCREEN_DPI_RANGE "screen-dpi-range" +#define RSC_NODE_ATTR_SCREEN_WIDTH_RANGE "screen-width-range" +#define RSC_NODE_ATTR_SCREEN_LARGE "screen-large" +#define RSC_NODE_ATTR_SCREEN_BPP "screen-bpp" +#define RSC_NODE_ATTR_PLATFORM_VER "platform-version" +#define RSC_NODE_ATTR_LANGUAGE "language" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @fn int *pkgmgr_resource_parser_open(const char *fname, const char *package, resource_data_t **data) + * @brief This API initialize parses res.xml which identified by fname and package and put it into data. + * + * @par This API is for package-manager installer backends. + * @par Sync (or) Async : Synchronous API + * + * @param[in] fname pointer to xml filename + * @param[in] pacakage pointer to packageID + * @param[out]data pointer of pointer to resource_data type structure. + * @return 0 on succeed and -1 on failure, -2 on invalid parameter + */ +API int pkgmgr_resource_parser_open(const char *fname, const char *package, resource_data_t **data); + +/** + * @fn int pkgmgr_resource_parser_close(resource_data_t data) + * @brief This API frees given data and its own variables + * + * @par This API is for package-manager installer backends. + * @par Sync (or) Async : Synchronous API + * + * @param[in] data structure of resource_data_t + * @return 0 on succeed and -1 on failure, -2 on invalid parameter + */ +API int pkgmgr_resource_parser_close(resource_data_t *data); + +/** + * @fn int pkgmgr_resource_parser_insert_into_db(resource_data_t *data) + * @brief This API will put given data into db + * + * @par This API is for package-manager installer backends. + * @par Sync (or) Async : Synchronous API + * + * @param[in] data structure to be inserted into db + * @return 0 on succeed and -1 on failure, -2 on invalid parameter + */ +API int pkgmgr_resource_parser_insert_into_db(resource_data_t *data); + +/** + * @fn int pkgmgr_resource_parser_open_from_db(const char *package, resource_data_t **data) + * @brief This API will get resource data of specific package from db + * + * @par This API is for applications. + * @par Sync (or) Async : Synchronous API + * + * @param[in] package packageID + * @param[out]data resource_data type structure. it will filled with resource data + * @return 0 on succeed and -1 on failure, -2 on invalid parameter + */ +API int pkgmgr_resource_parser_open_from_db(const char *package, resource_data_t **data); + +/** + * @fn int pkgmgr_resource_parser_check_xml_validation(const char *xmlfile) + * @brief This API will validates given resource manifest file + * + * @par This API is for package-manager installer backends. + * @par Sync (or) Async : Synchronous API + * + * @param[in] manifest manifest filepath to be validated + * @return 0 on succeed and -1 on failure, -2 on invalid parameter + */ +API int pkgmgr_resource_parser_check_xml_validation(const char *xmlfile); + +/** + * @fn int pkgmgr_resource_parser_delete_from_db(const char *package) + * @brief This API will remove resource data from package_resource_info, package_resource_data + * + * @par This API is for package-manager installer backends. + * @par Sync (or) Async : Synchronous API + * + * @param[in] package packageID + * @return 0 on succeed and -1 on failure, -2 on invalid parameter + */ +API int pkgmgr_resource_parser_delete_from_db(const char *package); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/parser/pkgmgr_parser_resource_db.c b/parser/pkgmgr_parser_resource_db.c new file mode 100755 index 0000000..1c0dec3 --- /dev/null +++ b/parser/pkgmgr_parser_resource_db.c @@ -0,0 +1,504 @@ +/* + * pkgmgr-info + * + * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee , Shobhit Srivastava + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pkgmgr-info.h" +#include "pkgmgr-info-debug.h" +#include "pkgmgr_parser_db.h" +#include "pkgmgr_parser_internal.h" +#include "pkgmgr_parser_resource.h" +#include "pkgmgr_parser_resource_db.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "PKGMGR_PARSER" + +#define BUF_SIZE 1024 +#define PKGMGR_PARSER_DB_FILE tzplatform_mkpath(TZ_USER_DB, ".pkgmgr_parser.db") + +enum { + NODE_ATTR_MIN = 0, + NODE_ATTR_SCREEN_DPI, + NODE_ATTR_SCREEN_DPI_RANGE, + NODE_ATTR_SCREEN_WIDTH_RANGE, + NODE_ATTR_SCREEN_LARGE, + NODE_ATTR_SCREEN_BPP, + NODE_ATTR_PLATFORM_VER, + NODE_ATTR_LANGUAGE, + NODE_ATTR_MAX, +}; + +static int _get_attr_val(bundle *b, char **attr_name, const char **attr_val, int attr_index) +{ + char *buf = NULL; + if (b == NULL) { + _LOGE("bundle is null"); + return PMINFO_R_EINVAL; + } + + buf = malloc(BUF_SIZE); + if (buf == NULL) { + _LOGE("malloc failed"); + return PMINFO_R_ERROR; + } + memset(buf, '\0', BUF_SIZE); + switch (attr_index) { + case NODE_ATTR_SCREEN_DPI: + snprintf(buf, BUF_SIZE, "%s", RSC_NODE_ATTR_SCREEN_DPI); + *attr_val = bundle_get_val(b, RSC_NODE_ATTR_SCREEN_DPI); + break; + case NODE_ATTR_SCREEN_DPI_RANGE: + snprintf(buf, BUF_SIZE, "%s", RSC_NODE_ATTR_SCREEN_DPI_RANGE); + *attr_val = bundle_get_val(b, RSC_NODE_ATTR_SCREEN_DPI_RANGE); + break; + case NODE_ATTR_SCREEN_WIDTH_RANGE: + snprintf(buf, BUF_SIZE, "%s", RSC_NODE_ATTR_SCREEN_WIDTH_RANGE); + *attr_val = bundle_get_val(b, RSC_NODE_ATTR_SCREEN_WIDTH_RANGE); + break; + case NODE_ATTR_SCREEN_LARGE: + snprintf(buf, BUF_SIZE, "%s", RSC_NODE_ATTR_SCREEN_LARGE); + *attr_val = bundle_get_val(b, RSC_NODE_ATTR_SCREEN_LARGE); + break; + case NODE_ATTR_SCREEN_BPP: + snprintf(buf, BUF_SIZE, "%s", RSC_NODE_ATTR_SCREEN_BPP); + *attr_val = bundle_get_val(b, RSC_NODE_ATTR_SCREEN_BPP); + break; + case NODE_ATTR_PLATFORM_VER: + snprintf(buf, BUF_SIZE, "%s", RSC_NODE_ATTR_PLATFORM_VER); + *attr_val = bundle_get_val(b, RSC_NODE_ATTR_PLATFORM_VER); + break; + case NODE_ATTR_LANGUAGE: + snprintf(buf, BUF_SIZE, "%s", RSC_NODE_ATTR_LANGUAGE); + *attr_val = bundle_get_val(b, RSC_NODE_ATTR_LANGUAGE); + break; + default: + _LOGE("unidentified index[%d]", attr_index); + free(buf); + buf = NULL; + return PMINFO_R_ERROR; + } + + if (buf != NULL && strlen(buf) != 0) + *attr_name = buf; + + return PMINFO_R_OK; +} + +static int _insert_node_data_into_db(sqlite3 *pkginfo, const char *package, char *group_type, GList *node_list) +{ + char *query = NULL; + resource_node_t *rsc_node = NULL; + GList *tmp_node_list = NULL; + bundle *b = NULL; + const char *attr_val = NULL; + char *attr_name = NULL; + int i; + int ret = -1; + + if (pkginfo == NULL || package == NULL || strlen(package) == 0 || group_type == NULL || strlen(group_type) == 0 || node_list == NULL) + return PMINFO_R_EINVAL; + + tmp_node_list = g_list_first(node_list); + + if (tmp_node_list == NULL) { + _LOGE("list is null"); + return PMINFO_R_ERROR; + } + + while (tmp_node_list != NULL) { + rsc_node = (resource_node_t *)tmp_node_list->data; + if (rsc_node == NULL) { + _LOGE("node is null"); + return PMINFO_R_ERROR; + } + + /*get bundle for each nodes*/ + b = rsc_node->attr; + if (b == NULL) { + _LOGE("bundle is null"); + return PMINFO_R_ERROR; + } + + for (i = NODE_ATTR_MIN + 1; i < NODE_ATTR_MAX; i++) { + ret = _get_attr_val(b, &attr_name, &attr_val, i); + if (ret != 0) { + _LOGE("get attribute from bundle failed"); + return ret; + } + + if (attr_name == NULL || attr_val == NULL) + continue; + query = sqlite3_mprintf("insert into package_resource_data(id, node_folder, attr_name, attr_value) VALUES(" \ + "(select rowid from package_resource_info where pkg_id=%Q and group_type=%Q), %Q, %Q, %Q)", package, group_type, rsc_node->folder, attr_name, attr_val); + + /*Begin transaction*/ + ret = sqlite3_exec(pkginfo, query, NULL, NULL, NULL); + if (ret != SQLITE_OK) + _LOGE("Failed to insert into package_resource_data, attr_name[%s], attr_val[%s]", attr_name, attr_val); + sqlite3_free(query); + query = NULL; + free(attr_name); + attr_name = NULL; + attr_val = NULL; + } + tmp_node_list = g_list_next(tmp_node_list); + } + + return ret; +} + +int pkgmgr_parser_resource_db_remove(const char *package) +{ + sqlite3 *pkginfo = NULL; + char *query = NULL; + int ret = -1; + + if (package == NULL) { + _LOGE("parameter is NULL"); + return PMINFO_R_EINVAL; + } + + /*db open*/ + ret = db_util_open(PKGMGR_PARSER_DB_FILE, &pkginfo, 0); + retvm_if(ret != SQLITE_OK, PMINFO_R_ERROR, "connect db [%s] failed!", PKGMGR_PARSER_DB_FILE); + + /*Begin transaction*/ + ret = sqlite3_exec(pkginfo, "BEGIN EXCLUSIVE", NULL, NULL, NULL); + tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Failed to begin transaction\n"); + _LOGD("Transaction Begin\n"); + + /*delete data from package_resource_data*/ + query = sqlite3_mprintf("delete from package_resource_data where id in (select rowid from package_resource_info where pkg_id=%Q)", package); + ret = sqlite3_exec(pkginfo, query, NULL, NULL, NULL); + tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Failed to delete from package_resource_info"); + sqlite3_free(query); + query = NULL; + + /*delete data from package_resource_info*/ + query = sqlite3_mprintf("delete from package_resource_info where pkg_id=%Q", package); + ret = sqlite3_exec(pkginfo, query, NULL, NULL, NULL); + tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Failed to delete from package_resource_info"); + + /*Commit transaction*/ + ret = sqlite3_exec(pkginfo, "COMMIT", NULL, NULL, NULL); + if (ret != SQLITE_OK) { + _LOGE("Failed to commit transaction. Rollback now\n"); + ret = sqlite3_exec(pkginfo, "ROLLBACK", NULL, NULL, NULL); + tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Don't execute query = %s\n", query); + } + _LOGD("Transaction Commit and End\n"); + + ret = PMINFO_R_OK; +catch: + sqlite3_close(pkginfo); + sqlite3_free(query); + + return ret; +} + +int pkgmgr_parser_resource_db_save(const char *package, resource_data_t *data) +{ + sqlite3 *pkginfo = NULL; + char *query = NULL; + int ret = -1; + GList *group_list = NULL; + GList *node_list = NULL; + resource_group_t *rsc_group = NULL; + + if (package == NULL || strlen(package) == 0 || data == NULL) { + _LOGE("invalid parameter"); + return -1; + } + + ret = pkgmgr_parser_check_and_create_db(getuid()); + if (ret == 0) + ret = pkgmgr_parser_initialize_db(); + if (ret < 0) { + _LOGE("db initialization failed"); + goto catch; + } + + + group_list = g_list_first(data->group_list); + /*db open*/ + ret = db_util_open(PKGMGR_PARSER_DB_FILE, &pkginfo, 0); + retvm_if(ret != SQLITE_OK, PMINFO_R_ERROR, "connect db [%s] failed!", PKGMGR_PARSER_DB_FILE); + + /*Begin transaction*/ + ret = sqlite3_exec(pkginfo, "BEGIN EXCLUSIVE", NULL, NULL, NULL); + tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Failed to begin transaction\n"); + _LOGD("Transaction Begin\n"); + + while (group_list != NULL) { + rsc_group = NULL; + node_list = NULL; + + rsc_group = (resource_group_t *)group_list->data; + node_list = g_list_first(rsc_group->node_list); + + if (rsc_group == NULL || node_list == NULL) { + _LOGE("value is null"); + ret = -1; + goto catch; + } + + query = sqlite3_mprintf("insert into package_resource_info(pkg_id, group_folder, group_type) VALUES(%Q, %Q, %Q)", \ + package, rsc_group->folder, rsc_group->type); + + /*Begin transaction*/ + ret = sqlite3_exec(pkginfo, query, NULL, NULL, NULL); + tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Failed to insert into package_resource_info"); + sqlite3_free(query); + query = NULL; + + ret = _insert_node_data_into_db(pkginfo, package, rsc_group->type, node_list); + + group_list = g_list_next(group_list); + } + + /*Commit transaction*/ + ret = sqlite3_exec(pkginfo, "COMMIT", NULL, NULL, NULL); + if (ret != SQLITE_OK) { + _LOGE("Failed to commit transaction. Rollback now\n"); + ret = sqlite3_exec(pkginfo, "ROLLBACK", NULL, NULL, NULL); + tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Don't execute query = %s\n", query); + } + _LOGD("Transaction Commit and End\n"); + + ret = PMINFO_R_OK; + + +catch: + pkgmgr_parser_close_db(); + sqlite3_close(pkginfo); + sqlite3_free(query); + + return ret; + +} + +static gint _find_group_type(void *group, void *data) +{ + resource_group_t *rsc_group = (resource_group_t *)group; + + return strcmp(rsc_group->type, (char *)data); +} + +static gint _find_node_folder(void *node, void *data) +{ + resource_node_t *rsc_node = (resource_node_t *)node; + char *str = (char *)data; + + return strcmp(rsc_node->folder, str); +} + +static int _init_node(char *node_folder, resource_node_t **rsc_node) +{ + resource_node_t *tmp_node = NULL; + + if (node_folder == NULL) { + _LOGE("invalid parameter"); + return PMINFO_R_EINVAL; + } + + tmp_node = malloc(sizeof(resource_node_t)); + if (tmp_node == NULL) { + _LOGE("malloc failed"); + return PMINFO_R_ERROR; + } + + tmp_node->folder = strdup(node_folder); + tmp_node->attr = bundle_create(); + *rsc_node = tmp_node; + + return PMINFO_R_OK; +} + +static int _init_group(char *group_type, resource_group_t **rsc_group) +{ + resource_group_t *tmp_group = NULL; + + if (group_type == NULL) { + _LOGE("invalid parameter"); + return PMINFO_R_EINVAL; + } + + tmp_group = malloc(sizeof(resource_group_t)); + if (tmp_group == NULL) { + _LOGE("malloc failed"); + return PMINFO_R_ERROR; + } + + tmp_group->type = strdup(group_type); + tmp_group->node_list = NULL; + *rsc_group = tmp_group; + + return PMINFO_R_OK; +} + +int pkgmgr_parser_resource_db_load(const char *package, resource_data_t **data) +{ + sqlite3 *pkginfo = NULL; + sqlite3_stmt *stmt = NULL; + char *query = NULL; + char *colname = NULL; + char *group_type = NULL; + char *group_folder = NULL; + char *node_folder = NULL; + char *attr_name = NULL; + char *attr_value = NULL; + int ret = -1; + int cols = 0; + int i; + resource_data_t *rsc_data = NULL; + resource_group_t *rsc_group = NULL; + resource_node_t *rsc_node = NULL; + GList *group_list = NULL; + GList *node_list = NULL; + GList *tmp_group_list = NULL; + GList *tmp_node_list = NULL; + + ret = db_util_open(PKGMGR_PARSER_DB_FILE, &pkginfo, 0); + retvm_if(ret != SQLITE_OK, PMINFO_R_ERROR, "connect db [%s] failed!", PKGMGR_PARSER_DB_FILE); + query = sqlite3_mprintf("select " \ + "package_resource_info.group_type, package_resource_info.group_folder, package_resource_data.node_folder, package_resource_data.attr_name, package_resource_data.attr_value " \ + "from package_resource_info, package_resource_data where " \ + "package_resource_info.rowid=package_resource_data.id and " \ + "package_resource_info.pkg_id=%Q order by package_resource_data.rowid asc", \ + package); + ret = sqlite3_prepare_v2(pkginfo, query, strlen(query), &stmt, NULL); + tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "sqlite3_prepare_v2 query = %s\n", query); + cols = sqlite3_column_count(stmt); + + while (1) { + ret = sqlite3_step(stmt); + if (ret != SQLITE_ROW) + break; + tmp_group_list = NULL; + tmp_node_list = NULL; + rsc_group = NULL; + rsc_node = NULL; + + for (i = 0; i < cols; i++) { + colname = (char *)sqlite3_column_name(stmt, i); + if (strcmp(colname, "group_type") == 0) { + /*group_type*/ + group_type = (char *)sqlite3_column_text(stmt, i); + tmp_group_list = g_list_find_custom(group_list, group_type, (GCompareFunc)_find_group_type); + if (tmp_group_list == NULL) { + ret = _init_group(group_type, &rsc_group); + if (ret != PMINFO_R_OK) { + _LOGE("group initialization failed[%d]", ret); + goto catch; + } + group_list = g_list_append(group_list, rsc_group); + node_list = NULL; + } else { + rsc_group = (resource_group_t *)tmp_group_list->data; + node_list = rsc_group->node_list; + } + } else if (strcmp(colname, "group_folder") == 0) { + /*group_folder*/ + group_folder = (char *)sqlite3_column_text(stmt, i); + if (rsc_group->folder != NULL && strcmp(rsc_group->folder, group_folder) == 0) + continue; + else if (rsc_group != NULL && group_folder != NULL) + rsc_group->folder = strdup(group_folder); + else { + _LOGE("rsc_group and group_folder should not be null"); + ret = PMINFO_R_ERROR; + goto catch; + } + } else if (strcmp(colname, "node_folder") == 0) { + /*node_folder*/ + node_folder = (char *)sqlite3_column_text(stmt, i); + tmp_node_list = g_list_find_custom(node_list, node_folder, (GCompareFunc)_find_node_folder); + if (tmp_node_list == NULL) { + ret = _init_node(node_folder, &rsc_node); + /*initialize new node*/ + if (ret != PMINFO_R_OK) { + _LOGE("node initialization failed[%d]", ret); + goto catch; + } + node_list = g_list_append(node_list, rsc_node); + if (rsc_group->node_list == NULL) + rsc_group->node_list = node_list; + } else + rsc_node = (resource_node_t *)tmp_node_list->data; + } else if (strcmp(colname, "attr_name") == 0) { + /*attr_name*/ + attr_name = (char *)sqlite3_column_text(stmt, i); + } else if (strcmp(colname, "attr_value") == 0) { + /*attr_value*/ + attr_value = (char *)sqlite3_column_text(stmt, i); + if (rsc_node != NULL && attr_name != NULL && attr_value != NULL) { + if (rsc_node->attr != NULL) + bundle_add(rsc_node->attr, attr_name, attr_value); + else { + _LOGE("bundle is not initialized"); + ret = PMINFO_R_ERROR; + goto catch; + } + } else { + _LOGE("error happened"); + ret = PMINFO_R_ERROR; + goto catch; + } + } else { + /*error handling*/ + _LOGE("unexpected column name detected:[%s]", colname); + ret = PMINFO_R_ERROR; + goto catch; + } + } + } + if (ret == SQLITE_DONE) + ret = PMINFO_R_OK; + + rsc_data = malloc(sizeof(resource_data_t)); + if (rsc_data == NULL) { + _LOGD("malloc failed"); + ret = PMINFO_R_ERROR; + goto catch; + } + rsc_data->group_list = group_list; + rsc_data->package = strdup(package); + /*set return data*/ + *data = rsc_data; +catch: + sqlite3_close(pkginfo); + sqlite3_free(query); + + return ret; +} diff --git a/parser/pkgmgr_parser_resource_db.h b/parser/pkgmgr_parser_resource_db.h new file mode 100755 index 0000000..4476b7c --- /dev/null +++ b/parser/pkgmgr_parser_resource_db.h @@ -0,0 +1,20 @@ +#ifndef __PKGMGR_PARSER_RESOURCE_DB_H_ +#define __PKGMGR_PARSER_RESOURCE_DB_H_ + +#include "pkgmgrinfo_resource.h" +#include "pkgmgr_parser.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int pkgmgr_parser_resource_db_save(const char *package, resource_data_t *data); +int pkgmgr_parser_resource_db_load(const char *package, resource_data_t **data); +int pkgmgr_parser_resource_db_remove(const char *package); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/parser/res.xsd.in b/parser/res.xsd.in new file mode 100755 index 0000000..fed6b3f --- /dev/null +++ b/parser/res.xsd.in @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/pkgmgrinfo_resource.c b/src/pkgmgrinfo_resource.c new file mode 100644 index 0000000..35f76f6 --- /dev/null +++ b/src/pkgmgrinfo_resource.c @@ -0,0 +1,12 @@ +#include "pkgmgr_parser_resource.h" + +API int pkgmgrinfo_resource_open(const char *package, resource_data_t **data) +{ + return pkgmgr_resource_parser_open_from_db(package, data); +} + +API int pkgmgrinfo_resource_close(resource_data_t *data) +{ + return pkgmgr_resource_parser_close(data); +} + -- 2.7.4