int pkgmgrinfo_updateinfo_usr_foreach_updateinfo(uid_t uid, pkgmgrinfo_foreach_updateinfo_cb callback, void *user_data);
/**
+ * @fn int pkgmgrinfo_plugininfo_is_executed(const char *pkgid, const char *appid, const char *plugin_type, const char *plugin_name, bool *is_executed);
+ * @brief This API checkes whether given plugin had been executed with given package ID and application ID or not.
+ *
+ * @par This API is for package-manager client application
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in] pkgid package ID
+ * @param[in] appid application ID
+ * @param[in] plugin_type plugin type to be checked
+ * @param[in] plugin_name plugin name to be checked
+ * @param[out] is_executed check result
+ * @return 0 if success, error code(<0) if fail
+ * @retval PMINFO_R_OK success
+ * @retval PMINFO_R_EINVAL invalid argument
+ * @retval PMINFO_R_ERROR internal error
+ * @code
+static bool check_execute_info(const char *pkgid, const char *appid, const char *plugin_type, const char *plugin_name)
+{
+ int ret = 0;
+ bool is_executed;
+
+ ret = pkgmgrinfo_plugininfo_is_executed(pkgid, appid, plugin_type, plugin_name, &is_executed);
+ if (ret != PMINFO_R_OK)
+ return -1;
+ printf("is checked is [%d]\n", is_executed);
+ return 0;
+}
+ * @endcode
+ */
+int pkgmgrinfo_plugininfo_is_executed(const char *pkgid, const char *appid,
+ const char *plugin_type, const char *plugin_name, bool *is_executed);
+
+/**
+ * @fn int pkgmgrinfo_plugininfo_foreach_plugininfo(const char *pkgid, const char *plugin_type, const char *plugin_name, pkgmgrinfo_plugin_list_cb plugin_list_cb, void *user_data);
+ * @brief This API retrieve the previous plugin execution info and invoke callbacks each of it.
+ *
+ * @par This API is for package-manager client application
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in] pkgid package ID
+ * @param[in] plugin_type type of plugin
+ * @param[in] plugin_name name of plugin
+ * @param[in] plugin_list_cb callback to be invoked for each plugin execution info
+ * @param[out] user_data user data to be passed to callback
+ * @return 0 if success, error code(<0) if fail
+ * @retval PMINFO_R_OK success
+ * @retval PMINFO_R_EINVAL invalid argument
+ * @retval PMINFO_R_ERROR internal error
+ * @code
+static int foreach_pkg_plugininfo(const char *pkgid, const char *plugin_type, const char *plugin_name, pkgmgrinfo_plugin_list_cb callback)
+{
+ int ret = 0;
+
+ ret = pkgmgrinfo_plugininfo_foreach_plugininfo(pkgid, plugin_type, plugin_name, callback, NULL);
+ if (ret != PMINFO_R_OK)
+ return -1;
+ return 0;
+}
+ * @endcode
+ */
+int pkgmgrinfo_plugininfo_foreach_plugininfo(const char *pkgid,
+ const char *plugin_type, const char *plugin_name,
+ pkgmgrinfo_plugin_list_cb plugin_list_cb, void *user_data);
+
+/**
* @fn int pkgmgrinfo_appinfo_get_launch_mode(pkgmgrinfo_appinfo_h handle, char **mode)
* @brief This API gets the launch mode of package from the package ID
*
int pkgmgrinfo_pkginfo_foreach_appdefined_privilege(pkgmgrinfo_pkginfo_h handle,
pkgmgrinfo_pkg_appdefined_privilege_list_cb privilege_func, void *user_data);
+/**
+ * @fn int pkgmgrinfo_pkginfo_foreach_plugin(pkgmgrinfo_pkginfo_h handle,
+ pkgmgrinfo_plugin_list_cb plugin_func, void *user_data);
+ * @brief This API gets the list of plugin execution info for a particular package
+ *
+ * @par This API is for package-manager client application
+ * @par Sync (or) Async : Synchronous API
+ * @param[in] handle pointer to the package info handle.
+ * @param[in] plugin_func callback function for list
+ * @param[in] user_data user data to be passed to callback function
+ * @return 0 if success, error code(<0) if fail
+ * @retval PMINFO_R_OK success
+ * @retval PMINFO_R_EINVAL invalid argument
+ * @retval PMINFO_R_ERROR internal error
+ * @pre pkgmgrinfo_pkginfo_get_pkginfo()
+ * @post pkgmgrinfo_pkginfo_destroy_pkginfo()
+ * @code
+int plugin_func(const char *pkgid, const char *appid,
+ const char *plugin_type, const char *plugin_name,
+ void *user_data)
+{
+ printf("appid : %s, type : %s, name : %s\n", appid, plugin_type, plugin_name);
+
+ return 0;
+}
+
+static int list_plugin(const char *package)
+{
+ int ret = 0;
+ pkgmgrinfo_pkginfo_h handle;
+ ret = pkgmgrinfo_pkginfo_get_pkginfo(package, &handle);
+ if (ret != PMINFO_R_OK)
+ return -1;
+ ret = pkgmgrinfo_pkginfo_foreach_plugin(handle, plugin_func, NULL);
+ if (ret != PMINFO_R_OK) {
+ pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+ return -1;
+ }
+ pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+ return 0;
+}
+ * @endcode
+ */
+int pkgmgrinfo_pkginfo_foreach_plugin(pkgmgrinfo_pkginfo_h handle,
+ pkgmgrinfo_plugin_list_cb plugin_func, void *user_data);
+
/* TODO: add doxygen comment here */
int pkgmgrinfo_pkginfo_is_for_all_users(pkgmgrinfo_pkginfo_h handle, bool *for_all_users);
char *text;
} compatibility_x;
+typedef struct plugin_x {
+ char *pkgid;
+ char *appid;
+ char *plugin_type;
+ char *plugin_name;
+} plugin_x;
+
typedef struct datacontrol_x {
char *providerid;
char *access;
GList *compatibility; /**< package compatibility, element*/
GList *deviceprofile; /**< package device profile, element*/
GList *dependencies; /**< package dependencies, element*/
+ GList *plugin; /**< plugin execution list, no xml part*/
} package_x;
typedef struct updateinfo_x {
void *user_data);
/**
+ * @fn int (*pkgmgrinfo_plugin_list_cb) (const char *pkgid, const char *appid, const char *plugin_type, const char *plugin_name, void *user_data);
+ *
+ * @brief Specifies the type of function passed to pkgmgrinfo_plugininfo_foreach_plugininfo()
+ *
+ * @param[in] pkgid the name of the package
+ * @param[in] appid the name of the application
+ * @param[in] plugin_type the type of the executed plugin
+ * @param[in] plugin_name the name of the executed plugin
+ * @param[in] user_data user data passed to pkgmgrinfo_plugininfo_foreach_plugininfo()
+ *
+ * @return 0 if success, negative value(<0) if fail. Callback is not called if return value is negative.\n
+ *
+ * @see pkgmgrinfo_plugininfo_foreach_plugininfo()
+ */
+typedef int (*pkgmgrinfo_plugin_list_cb) (const char *pkgid, const char *appid,
+ const char *plugin_type, const char *plugin_name,
+ void *user_data);
+
+/**
* @fn int (*pkgmgrinfo_app_metadata_list_cb) (const char *metadata_key, const char *metadata_value, void *user_data)
*
* @brief Specifies the type of function passed to pkgmgrinfo_appinfo_foreach_metadata()
*/
int pkgmgr_parser_unregister_all_pkg_update_info_in_db(void);
+/**
+ * @fn int pkgmgr_parser_register_pkg_plugin_info_in_usr_db(manifest_x *mfx, uid_t uid)
+ * @brief This API registers package plugin execution information
+ *
+ * @par This API is only for internal usage
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in] mfx manifest structure pointer which contains plugin execution info
+ * @return 0 if success, error code(<0) if fail
+ * @pre None
+ * @post None
+ * @code
+static int register_pkg_plugin_info(manifest_x *mfx)
+{
+ int ret = 0;
+ ret = pkgmgr_parser_register_pkg_plugin_info_in_db(mfx);
+ if (ret < 0)
+ return -1;
+ return 0;
+}
+ * @endcode
+ */
+int pkgmgr_parser_register_pkg_plugin_info_in_db(manifest_x *mfx);
+int pkgmgr_parser_register_pkg_plugin_info_in_usr_db(manifest_x *mfx, uid_t uid);
+
+/**
+ * @fn int pkgmgr_parser_update_pkg_plugin_info_in_usr_db(manifest_x *mfx, uid_t uid)
+ * @brief This API updates package plugin execution information
+ *
+ * @par This API is only for internal usage
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in] mfx manifest structure pointer which contains plugin execution info
+ * @return 0 if success, error code(<0) if fail
+ * @pre None
+ * @post None
+ * @code
+static int update_pkg_plugin_info(manifest_x *mfx)
+{
+ int ret = 0;
+ ret = pkgmgr_parser_update_pkg_plugin_info_in_db(mfx);
+ if (ret < 0)
+ return -1;
+ return 0;
+}
+ * @endcode
+ */
+int pkgmgr_parser_update_pkg_plugin_info_in_db(manifest_x *mfx);
+int pkgmgr_parser_update_pkg_plugin_info_in_usr_db(manifest_x *mfx, uid_t uid);
+
+/**
+ * @fn int pkgmgr_parser_unregister_pkg_plugin_info_in_usr_db(const char *pkgid, uid_t uid)
+ * @brief This API unregisters package plugin execution information
+ *
+ * @par This API is only for internal usage
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in] pkgid package ID
+ * @return 0 if success, error code(<0) if fail
+ * @pre None
+ * @post None
+ * @code
+static int unregister_pkg_plugin_info(const char *pkgid)
+{
+ int ret = 0;
+ ret = pkgmgr_parser_unregister_pkg_plugin_info_in_db(pkgid);
+ if (ret < 0)
+ return -1;
+ return 0;
+}
+ * @endcode
+ */
+int pkgmgr_parser_unregister_pkg_plugin_info_in_db(const char *pkgid);
+int pkgmgr_parser_unregister_pkg_plugin_info_in_usr_db(const char *pkgid, uid_t uid);
+
int pkgmgr_parser_create_and_initialize_db(uid_t uid);
int pkgmgr_parser_initialize_parser_db(uid_t uid);
int pkgmgr_parser_initialize_cert_db(void);
QUERY_CREATE_TRIGGER_UPDATE_PACKAGE_APP_INFO_FOR_UID,
QUERY_CREATE_TABLE_PACKAGE_APP_SPLASH_SCREEN,
QUERY_CREATE_TABLE_PACKAGE_DEPENDENCY_INFO,
+ QUERY_CREATE_TABLE_PACKAGE_PLUGIN_INFO,
NULL,
};
return 0;
}
+static int __insert_package_plugin_execution_info(sqlite3 *db,
+ manifest_x *mfx)
+{
+ static const char query[] =
+ "INSERT INTO package_plugin_info "
+ "(pkgid, appid, plugin_type, plugin_name) "
+ "VALUES (?, ?, ?, ?)";
+ int ret;
+ sqlite3_stmt *stmt;
+ int idx;
+ GList *tmp;
+ plugin_x *plugin;
+
+ if (!mfx->plugin)
+ return 0;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ for (tmp = mfx->plugin; tmp; tmp = tmp->next) {
+ plugin = (plugin_x *)tmp->data;
+ if (plugin == NULL)
+ continue;
+
+ idx = 1;
+ __BIND_TEXT(db, stmt, idx++, plugin->pkgid);
+ __BIND_TEXT(db, stmt, idx++, plugin->appid);
+ __BIND_TEXT(db, stmt, idx++, plugin->plugin_type);
+ __BIND_TEXT(db, stmt, idx++, plugin->plugin_name);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ _LOGE("step failed: %s", sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+ sqlite3_reset(stmt);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return 0;
+}
+
+static int __delete_package_plugin_execution_info(sqlite3 *db,
+ const char *pkgid)
+{
+ static const char query[] =
+ "DELETE FROM package_plugin_info WHERE pkgid=?";
+ int ret;
+ sqlite3_stmt *stmt;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ __BIND_TEXT(db, stmt, 1, pkgid);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ _LOGE("step failed: %s", sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+
+ sqlite3_finalize(stmt);
+
+ return 0;
+}
+
static int __insert_package_appdefined_privilege_info(sqlite3 *db,
manifest_x *mfx)
{
return pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(
__getuid());
}
+
+API int pkgmgr_parser_register_pkg_plugin_info_in_usr_db(
+ manifest_x *mfx, uid_t uid)
+{
+ int ret;
+ const char *dbpath;
+ sqlite3 *db;
+
+ if (!mfx)
+ return PM_PARSER_R_EINVAL;
+ dbpath = __get_parser_db_path(uid);
+ ret = __open_db(uid, dbpath, &db, SQLITE_OPEN_READWRITE);
+ if (ret != SQLITE_OK) {
+ _LOGE("open db failed: %d", ret);
+ return PM_PARSER_R_ERROR;
+ }
+
+ __BEGIN_TRANSACTION(db);
+ __DO_TRANSACTION(db, __insert_package_plugin_execution_info(db, mfx));
+ __END_TRANSACTION(db);
+
+ sqlite3_close_v2(db);
+
+ return PM_PARSER_R_OK;
+}
+
+API int pkgmgr_parser_register_pkg_plugin_info_in_db(manifest_x *mfx)
+{
+ return pkgmgr_parser_register_pkg_plugin_info_in_usr_db(mfx, __getuid());
+}
+
+API int pkgmgr_parser_update_pkg_plugin_info_in_usr_db(
+ manifest_x *mfx, uid_t uid)
+{
+ int ret;
+ const char *dbpath;
+ sqlite3 *db;
+
+ if (!mfx)
+ return PM_PARSER_R_EINVAL;
+ dbpath = __get_parser_db_path(uid);
+ ret = __open_db(uid, dbpath, &db, SQLITE_OPEN_READWRITE);
+ if (ret != SQLITE_OK) {
+ _LOGE("open db failed: %d", ret);
+ return PM_PARSER_R_ERROR;
+ }
+
+ __BEGIN_TRANSACTION(db);
+ __DO_TRANSACTION(db, __delete_package_plugin_execution_info(db, mfx->package));
+ __DO_TRANSACTION(db, __insert_package_plugin_execution_info(db, mfx));
+ __END_TRANSACTION(db);
+
+ sqlite3_close_v2(db);
+
+ return PM_PARSER_R_OK;
+}
+
+API int pkgmgr_parser_update_pkg_plugin_info_in_db(manifest_x *mfx)
+{
+ return pkgmgr_parser_update_pkg_plugin_info_in_usr_db(mfx, __getuid());
+}
+
+API int pkgmgr_parser_unregister_pkg_plugin_info_in_usr_db(
+ const char *pkgid, uid_t uid)
+{
+ int ret;
+ const char *dbpath;
+ sqlite3 *db;
+
+ dbpath = __get_parser_db_path(uid);
+ ret = __open_db(uid, dbpath, &db, SQLITE_OPEN_READWRITE);
+ if (ret != SQLITE_OK) {
+ _LOGE("open db failed: %d", ret);
+ return PM_PARSER_R_ERROR;
+ }
+
+ __BEGIN_TRANSACTION(db);
+ __DO_TRANSACTION(db, __delete_package_plugin_execution_info(db, pkgid));
+ __END_TRANSACTION(db);
+
+ sqlite3_close_v2(db);
+
+ return PM_PARSER_R_OK;
+}
+
+API int pkgmgr_parser_unregister_pkg_plugin_info_in_db(const char *pkgid)
+{
+ return pkgmgr_parser_unregister_pkg_plugin_info_in_usr_db(pkgid, __getuid());
+}
\ No newline at end of file
" FOREIGN KEY(package)\n" \
" REFERENCES package_info(package) ON DELETE CASCADE)"
+#define QUERY_CREATE_TABLE_PACKAGE_PLUGIN_INFO \
+ "CREATE TABLE IF NOT EXISTS package_plugin_info (\n" \
+ " pkgid TEXT NOT NULL,\n" \
+ " appid TEXT,\n" \
+ " plugin_type TEXT NOT NULL,\n" \
+ " plugin_name TEXT NOT NULL)"
+
/* FIXME: duplicated at pkgmgrinfo_db.c */
#define QUERY_CREATE_TABLE_PACKAGE_CERT_INDEX_INFO \
"CREATE TABLE IF NOT EXISTS package_cert_index_info (\n" \
free((void *)compatibility);
}
+static void __ps_free_plugin_info(gpointer data)
+{
+ plugin_x *plugin = (plugin_x *)data;
+ if (plugin == NULL)
+ return;
+ if (plugin->pkgid)
+ free((void *)plugin->pkgid);
+ if (plugin->appid)
+ free((void *)plugin->appid);
+ if (plugin->plugin_type)
+ free((void *)plugin->plugin_type);
+ if (plugin->plugin_name)
+ free((void *)plugin->plugin_name);
+ free((void *)plugin);
+}
+
static void __ps_free_appcontrol(gpointer data)
{
appcontrol_x *appcontrol = (appcontrol_x *)data;
g_list_free_full(package->deviceprofile, free);
/*Free Dependencies*/
g_list_free_full(package->dependencies, __ps_free_dependency);
+ /*Free Plugin execution history*/
+ g_list_free_full(package->plugin, __ps_free_plugin_info);
free((void *)package);
}
return PMINFO_R_OK;
}
+static int _pkginfo_get_plugin_execution_info(sqlite3 *db, const char *pkgid,
+ GList **plugins)
+{
+ static const char query_raw[] =
+ "SELECT appid, plugin_type, plugin_name FROM package_plugin_info "
+ "WHERE pkgid=%Q";
+ int ret;
+ char *query;
+ sqlite3_stmt *stmt;
+ plugin_x *plugin;
+
+ query = sqlite3_mprintf(query_raw, pkgid);
+ if (query == NULL) {
+ LOGE("out of memory");
+ return PMINFO_R_ERROR;
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query),
+ &stmt, NULL);
+ sqlite3_free(query);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return PMINFO_R_ERROR;
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ plugin = calloc(1, sizeof(plugin_x));
+ if (!plugin) {
+ LOGE("out of memory");
+ sqlite3_finalize(stmt);
+ return PMINFO_R_ERROR;
+ }
+ plugin->pkgid = strdup(pkgid);
+ _save_column_str(stmt, 0, &plugin->appid);
+ _save_column_str(stmt, 1, &plugin->plugin_type);
+ _save_column_str(stmt, 2, &plugin->plugin_name);
+ *plugins = g_list_append(*plugins,
+ (gpointer)plugin);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return PMINFO_R_OK;
+}
+
static int _pkginfo_get_privilege(sqlite3 *db, const char *pkgid,
GList **privileges)
{
info->for_all_users =
strdup((uid != global_user_uid) ? "false" : "true");
+ if (_pkginfo_get_plugin_execution_info(db, info->package, &info->plugin)) {
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+
if (flag & PMINFO_PKGINFO_GET_AUTHOR) {
/* TODO : author should be retrieved at package_localized_info */
author = calloc(1, sizeof(author_x));
return PMINFO_R_OK;
}
+API int pkgmgrinfo_pkginfo_foreach_plugin(pkgmgrinfo_pkginfo_h handle,
+ pkgmgrinfo_plugin_list_cb plugin_func, void *user_data)
+{
+ retvm_if(handle == NULL, PMINFO_R_EINVAL, "pkginfo handle is NULL");
+ retvm_if(plugin_func == NULL, PMINFO_R_EINVAL,
+ "Callback function is NULL");
+ int ret;
+ plugin_x *plugin;
+ GList *tmp;
+ pkgmgr_pkginfo_x *info = (pkgmgr_pkginfo_x *)handle;
+
+ if (info->pkg_info == NULL)
+ return PMINFO_R_ERROR;
+
+ for (tmp = info->pkg_info->plugin; tmp; tmp = tmp->next) {
+ plugin = (plugin_x *)tmp->data;
+ if (plugin == NULL)
+ continue;
+ ret = plugin_func(plugin->pkgid, plugin->appid,
+ plugin->plugin_type, plugin->plugin_name, user_data);
+ if (ret < 0)
+ return PMINFO_R_OK;
+ }
+
+ return PMINFO_R_OK;
+}
+
API int pkgmgrinfo_pkginfo_foreach_appdefined_privilege(
pkgmgrinfo_pkginfo_h handle,
pkgmgrinfo_pkg_appdefined_privilege_list_cb privilege_func,
--- /dev/null
+/*
+ * pkgmgr-info
+ *
+ * Copyright (c) 2000 - 2019 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Junghyun Yeon <jungh.yeon@samsung.com>, Sangyoon Jang <jeremy.jang@samsung.com>
+ *
+ * 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 <stdlib.h>
+#include <stdbool.h>
+#include <sqlite3.h>
+
+#include "pkgmgrinfo_private.h"
+#include "pkgmgrinfo_debug.h"
+#include "pkgmgr-info.h"
+
+static void _free_plugin(gpointer data)
+{
+ plugin_x *plugin = (plugin_x *)data;
+ if (plugin == NULL)
+ return;
+ if (plugin->appid)
+ free((void *)plugin->appid);
+ free((void *)plugin);
+}
+
+API int pkgmgrinfo_plugininfo_foreach_plugininfo(const char *pkgid,
+ const char *plugin_type, const char *plugin_name,
+ pkgmgrinfo_plugin_list_cb plugin_list_cb, void *user_data)
+{
+ int ret;
+ int idx = 0;
+ char *dbpath;
+ const char *appid;
+ sqlite3 *db;
+ sqlite3_stmt *stmt = NULL;
+ plugin_x *plugin;
+ GList *plugin_list = NULL;
+ GList *tmp_list;
+
+ static const char query[] =
+ "SELECT appid FROM "
+ "package_plugin_info WHERE pkgid=? AND "
+ "plugin_type=? AND plugin_name=?";
+
+ if (!pkgid || !plugin_type || !plugin_name || !plugin_list_cb) {
+ _LOGE("Invalid parameter");
+ return PMINFO_R_EINVAL;
+ }
+
+ dbpath = getUserPkgParserDBPathUID(_getuid());
+ if (dbpath == NULL) {
+ _LOGE("Failed to get db path");
+ return PMINFO_R_ERROR;
+ }
+
+ ret = __open_db(dbpath, &db, SQLITE_OPEN_READONLY);
+ if (ret != SQLITE_OK) {
+ _LOGD("failed to open db(%s): %d", dbpath, ret);
+ free(dbpath);
+ return PMINFO_R_ERROR;
+ }
+ free(dbpath);
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+
+ ret = sqlite3_bind_text(stmt, ++idx, pkgid, -1, SQLITE_STATIC);
+ if (ret != SQLITE_OK) {
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+
+ ret = sqlite3_bind_text(stmt, ++idx, plugin_type, -1, SQLITE_STATIC);
+ if (ret != SQLITE_OK) {
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ ret = sqlite3_bind_text(stmt, ++idx, plugin_name, -1, SQLITE_STATIC);
+ if (ret != SQLITE_OK) {
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ plugin = calloc(1, sizeof(plugin_x));
+ if (plugin == NULL) {
+ _LOGE("out of memory");
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ idx = 0;
+ appid = (const char *)sqlite3_column_text(stmt, idx++);
+ if (appid) {
+ plugin->appid = strdup(appid);
+ }
+ plugin_list = g_list_append(plugin_list, plugin);
+ }
+
+ for (tmp_list = plugin_list; tmp_list != NULL; tmp_list = tmp_list->next) {
+ plugin = (plugin_x *)tmp_list->data;
+ if (!plugin)
+ continue;
+ ret = plugin_list_cb(pkgid, plugin->appid, plugin_type,
+ plugin_name, user_data);
+ if (ret != 0)
+ break;
+ }
+ g_list_free_full(plugin_list, _free_plugin);
+
+catch:
+ sqlite3_finalize(stmt);
+ sqlite3_close_v2(db);
+
+ return ret;
+
+}
\ No newline at end of file