X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fpkgmgrinfo_pkginfo.c;h=d7a6a52696a559acb9d748e87c508f0796783f76;hb=b2280aa76ba825de25ea726614a25be31f7e05cb;hp=a9ba8db81d6635089251af7f71877c2af96d8e02;hpb=296b836f2187cedf267ad21b78aea105d6ba6e7e;p=platform%2Fcore%2Fappfw%2Fpkgmgr-info.git diff --git a/src/pkgmgrinfo_pkginfo.c b/src/pkgmgrinfo_pkginfo.c index a9ba8db..d7a6a52 100644 --- a/src/pkgmgrinfo_pkginfo.c +++ b/src/pkgmgrinfo_pkginfo.c @@ -181,6 +181,51 @@ static int _pkginfo_add_description_info_into_list(const char *locale, 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) { @@ -219,6 +264,85 @@ static int _pkginfo_get_privilege(sqlite3 *db, const char *pkgid, return PMINFO_R_OK; } +static int _pkginfo_get_appdefined_privilege(sqlite3 *db, const char *pkgid, + GList **privileges) +{ + static const char query_raw[] = + "SELECT DISTINCT privilege, license, type FROM " + "package_appdefined_privilege_info WHERE package=%Q"; + int ret; + char *query; + sqlite3_stmt *stmt; + appdefined_privilege_x *privilege; + + 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) { + privilege = calloc(1, sizeof(appdefined_privilege_x)); + if (!privilege) { + LOGE("failed to alloc memory"); + sqlite3_finalize(stmt); + return PMINFO_R_ERROR; + } + _save_column_str(stmt, 0, &privilege->value); + _save_column_str(stmt, 1, &privilege->license); + _save_column_str(stmt, 2, &privilege->type); + *privileges = g_list_append(*privileges, + (gpointer)privilege); + } + + sqlite3_finalize(stmt); + + return PMINFO_R_OK; +} + +static int _pkginfo_get_dependency(sqlite3 *db, const char *pkgid, + GList **dependencies) +{ + static const char query[] = + "SELECT DISTINCT depends_on, type, required_version " + "FROM package_dependency_info WHERE package=?"; + int ret; + sqlite3_stmt *stmt; + dependency_x *dependency; + + ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); + if (ret != SQLITE_OK) { + LOGE("prepare failed: %s", sqlite3_errmsg(db)); + return PMINFO_R_ERROR; + } + + while (sqlite3_step(stmt) == SQLITE_ROW) { + dependency = calloc(1, sizeof(dependency_x)); + if (!dependency) { + LOGE("failed to alloc memory"); + sqlite3_finalize(stmt); + return PMINFO_R_ERROR; + } + _save_column_str(stmt, 0, &dependency->depends_on); + _save_column_str(stmt, 1, &dependency->type); + _save_column_str(stmt, 2, &dependency->required_version); + *dependencies = g_list_append(*dependencies, + (gpointer)dependency); + } + + sqlite3_finalize(stmt); + + return PMINFO_R_OK; +} + static const char join_localized_info[] = " LEFT OUTER JOIN package_localized_info" " ON pi.package=package_localized_info.package" @@ -234,39 +358,32 @@ static int _get_filtered_query(pkgmgrinfo_filter_x *filter, char buf[MAX_QUERY_LEN] = { '\0' }; char buf2[MAX_QUERY_LEN] = { '\0' }; char *condition = NULL; - size_t len = 0; GSList *list = NULL; if (filter == NULL) return PMINFO_R_OK; - strncat(buf, " WHERE 1=1 ", MAX_QUERY_LEN - len - 1); - len += strlen(" WHERE 1=1 "); + snprintf(buf, sizeof(buf), "%s", " WHERE 1=1 "); for (list = filter->list; list; list = list->next) { joined |= __get_filter_condition(list->data, uid, &condition, bind_params); if (condition == NULL) continue; - strncat(buf, " AND ", MAX_QUERY_LEN - len - 1); - len += strlen(" AND "); + strncat(buf, " AND ", sizeof(buf) - strlen(buf) - 1); - strncat(buf, condition, sizeof(buf) - len - 1); - len += strlen(condition); + strncat(buf, condition, sizeof(buf) - strlen(buf) - 1); free(condition); condition = NULL; } if (joined & E_PMINFO_PKGINFO_JOIN_LOCALIZED_INFO) { - strncat(buf2, join_localized_info, MAX_QUERY_LEN - len - 1); - len += strlen(join_localized_info); + strncat(buf2, join_localized_info, sizeof(buf2) - strlen(buf2) - 1); *bind_params = g_list_append(*bind_params, strdup(locale)); } - if (joined & E_PMINFO_PKGINFO_JOIN_PRIVILEGE_INFO) { - strncat(buf2, join_privilege_info, MAX_QUERY_LEN - len - 1); - len += strlen(join_privilege_info); - } - strncat(buf2, buf, MAX_QUERY_LEN - len - 1); + if (joined & E_PMINFO_PKGINFO_JOIN_PRIVILEGE_INFO) + strncat(buf2, join_privilege_info, sizeof(buf2) - strlen(buf2) - 1); + strncat(buf2, buf, sizeof(buf2) - strlen(buf2) - 1); *query = strdup(buf2); if (*query == NULL) @@ -365,7 +482,6 @@ static int _pkginfo_get_packages(uid_t uid, const char *locale, static const char query_from_clause[] = " FROM package_info as pi"; int ret = PMINFO_R_ERROR; int idx = 0; - int query_len = 0; char *dbpath; char *tmp_record = NULL; char *constraints = NULL; @@ -385,7 +501,7 @@ static int _pkginfo_get_packages(uid_t uid, const char *locale, ret = __open_db(dbpath, &db, SQLITE_OPEN_READONLY); if (ret != SQLITE_OK) { - _LOGD("failed to open db: %d", ret); + _LOGD("failed to open db(%s): %d", dbpath, ret); free(dbpath); return PMINFO_R_ERROR; } @@ -403,34 +519,25 @@ static int _pkginfo_get_packages(uid_t uid, const char *locale, is_check_storage = __check_package_storage_status(tmp_filter); - query_len = strlen(query_raw); snprintf(query, MAX_QUERY_LEN - 1, "%s", query_raw); - if (flag & PMINFO_APPINFO_GET_BASICINFO) { - strncat(query, query_basic, MAX_QUERY_LEN - query_len - 1); - query_len += strlen(query_basic); - } - if (flag & PMINFO_PKGINFO_GET_AUTHOR) { - strncat(query, query_author, MAX_QUERY_LEN - query_len - 1); - query_len += strlen(query_author); - } + if (flag & PMINFO_APPINFO_GET_BASICINFO) + strncat(query, query_basic, sizeof(query) - strlen(query) - 1); + if (flag & PMINFO_PKGINFO_GET_AUTHOR) + strncat(query, query_author, sizeof(query) - strlen(query) - 1); if (flag & PMINFO_PKGINFO_GET_LABEL) { - strncat(query, query_label, MAX_QUERY_LEN - query_len - 1); - query_len += strlen(query_label); + strncat(query, query_label, sizeof(query) - strlen(query) - 1); bind_params = g_list_append(bind_params, strdup(locale)); } if (flag & PMINFO_PKGINFO_GET_ICON) { - strncat(query, query_icon, MAX_QUERY_LEN - query_len - 1); - query_len += strlen(query_icon); + strncat(query, query_icon, sizeof(query) - strlen(query) - 1); bind_params = g_list_append(bind_params, strdup(locale)); } if (flag & PMINFO_PKGINFO_GET_DESCRIPTION) { - strncat(query, query_description, MAX_QUERY_LEN - query_len - 1); - query_len += strlen(query_description); + strncat(query, query_description, sizeof(query) - strlen(query) - 1); bind_params = g_list_append(bind_params, strdup(locale)); } - strncat(query, query_from_clause, MAX_QUERY_LEN - query_len - 1); - query_len += strlen(query_from_clause); + strncat(query, query_from_clause, sizeof(query) - strlen(query) - 1); ret = _get_filtered_query(tmp_filter, locale, uid, &constraints, &bind_params); if (ret != PMINFO_R_OK) { @@ -439,7 +546,7 @@ static int _pkginfo_get_packages(uid_t uid, const char *locale, } if (constraints) - strncat(query, constraints, MAX_QUERY_LEN - query_len - 1); + strncat(query, constraints, sizeof(query) - strlen(query) - 1); ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); if (ret != SQLITE_OK) { @@ -494,6 +601,11 @@ static int _pkginfo_get_packages(uid_t uid, const char *locale, 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)); @@ -544,6 +656,22 @@ static int _pkginfo_get_packages(uid_t uid, const char *locale, } } + if (flag & PMINFO_PKGINFO_GET_APPDEFINED_PRIVILEGE) { + if (_pkginfo_get_appdefined_privilege(db, info->package, + &info->appdefined_privileges)) { + ret = PMINFO_R_ERROR; + goto catch; + } + } + + if (flag & PMINFO_PKGINFO_GET_DEPENDENCY) { + if (_pkginfo_get_dependency(db, info->package, + &info->dependencies)) { + ret = PMINFO_R_ERROR; + goto catch; + } + } + if (is_check_storage && __pkginfo_check_installed_storage(info) != PMINFO_R_OK) { ret = PMINFO_R_ERROR; @@ -559,6 +687,9 @@ static int _pkginfo_get_packages(uid_t uid, const char *locale, ret = PMINFO_R_OK; catch: + sqlite3_finalize(stmt); + sqlite3_close_v2(db); + if (constraints) free(constraints); @@ -569,9 +700,6 @@ catch: pkgmgrinfo_pkginfo_filter_destroy(tmp_filter); g_list_free_full(bind_params, free); - sqlite3_close_v2(db); - if (stmt) - sqlite3_finalize(stmt); return ret; } @@ -607,13 +735,23 @@ static int _pkginfo_get_filtered_foreach_pkginfo(uid_t uid, if (ret != PMINFO_R_OK) { _LOGE("Failed to create filter"); g_hash_table_destroy(list); + free(locale); return PMINFO_R_ERROR; } } - if (__check_disable_filter_exist(tmp_filter) == false) - pkgmgrinfo_pkginfo_filter_add_bool(tmp_filter, + if (__check_disable_filter_exist(tmp_filter) == false) { + ret = pkgmgrinfo_pkginfo_filter_add_bool(tmp_filter, PMINFO_PKGINFO_PROP_PACKAGE_DISABLE, false); + if (ret != PMINFO_R_OK) { + _LOGE("Failed to add filter"); + g_hash_table_destroy(list); + free(locale); + if (filter == NULL) + pkgmgrinfo_pkginfo_filter_destroy(tmp_filter); + return PMINFO_R_ERROR; + } + } ret = _pkginfo_get_packages(uid, locale, tmp_filter, flag | PMINFO_PKGINFO_GET_BASICINFO, list); @@ -665,7 +803,8 @@ static int _pkgmgrinfo_get_pkginfo(const char *pkgid, uid_t uid, if (locale == NULL) return PMINFO_R_ERROR; - list = g_hash_table_new(g_str_hash, g_str_equal); + list = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, + __free_packages); if (list == NULL) { free(locale); return PMINFO_R_ERROR; @@ -677,8 +816,14 @@ static int _pkgmgrinfo_get_pkginfo(const char *pkgid, uid_t uid, ret = _pkginfo_get_packages(GLOBAL_USER, locale, filter, PMINFO_PKGINFO_GET_ALL, list); + if (ret != PMINFO_R_OK) { + g_hash_table_destroy(list); + free(locale); + return ret; + } + if (!g_hash_table_size(list)) { - _LOGI("pkginfo for [%s] is not existed for user [%d]", + _LOGD("pkginfo for [%s] is not existed for user [%d]", pkgid, uid); g_hash_table_destroy(list); free(locale); @@ -698,6 +843,7 @@ static int _pkgmgrinfo_get_pkginfo(const char *pkgid, uid_t uid, info->locale = locale; /* just free list only */ + g_hash_table_steal(list, (gconstpointer)pkgid); g_hash_table_destroy(list); *handle = info; @@ -786,7 +932,8 @@ API int pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo(const char *pkgid, return PMINFO_R_ERROR; } - list = g_hash_table_new(g_str_hash, g_str_equal); + list = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, + __free_packages); if (list == NULL) { pkgmgrinfo_pkginfo_filter_destroy(filter); free(locale); @@ -807,7 +954,7 @@ API int pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo(const char *pkgid, } if (!g_hash_table_size(list)) { - _LOGI("disabled pkginfo for [%s] is not existed for user [%d]", + _LOGD("disabled pkginfo for [%s] is not existed for user [%d]", pkgid, uid); g_hash_table_destroy(list); free(locale); @@ -827,6 +974,7 @@ API int pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo(const char *pkgid, info->locale = locale; /* just free list only */ + g_hash_table_steal(list, (gconstpointer)pkgid); g_hash_table_destroy(list); *handle = info; @@ -1319,6 +1467,8 @@ API int pkgmgrinfo_pkginfo_get_installed_storage(pkgmgrinfo_pkginfo_h handle, pk *storage = PMINFO_INTERNAL_STORAGE; else if (strcmp(info->pkg_info->installed_storage, "installed_external") == 0) *storage = PMINFO_EXTERNAL_STORAGE; + else if (strcmp(info->pkg_info->installed_storage, "installed_extended") == 0) + *storage = PMINFO_EXTENDED_STORAGE; else return PMINFO_R_ERROR; @@ -1529,8 +1679,6 @@ API int pkgmgrinfo_pkginfo_is_movable(pkgmgrinfo_pkginfo_h handle, bool *movable val = (char *)info->pkg_info->installlocation; if (strcmp(val, "internal-only") == 0) *movable = 0; - else if (strcmp(val, "prefer-external") == 0) - *movable = 1; else *movable = 1; @@ -1901,6 +2049,7 @@ API int pkgmgrinfo_pkginfo_foreach_privilege(pkgmgrinfo_pkginfo_h handle, retvm_if(privilege_func == NULL, PMINFO_R_EINVAL, "Callback function is NULL"); int ret; privilege_x *privilege; + appdefined_privilege_x *appdefined_privilege; GList *tmp; pkgmgr_pkginfo_x *info = (pkgmgr_pkginfo_x *)handle; @@ -1913,11 +2062,261 @@ API int pkgmgrinfo_pkginfo_foreach_privilege(pkgmgrinfo_pkginfo_h handle, continue; ret = privilege_func(privilege->value, user_data); if (ret < 0) + return PMINFO_R_OK; + } + + for (tmp = info->pkg_info->appdefined_privileges; tmp; + tmp = tmp->next) { + appdefined_privilege = (appdefined_privilege_x *)tmp->data; + if (appdefined_privilege == NULL) + continue; + ret = privilege_func(appdefined_privilege->value, user_data); + if (ret < 0) + return PMINFO_R_OK; + } + 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, + void *user_data) +{ + retvm_if(handle == NULL, PMINFO_R_EINVAL, "pkginfo handle is NULL"); + retvm_if(privilege_func == NULL, PMINFO_R_EINVAL, + "Callback function is NULL"); + int ret; + appdefined_privilege_x *privilege; + GList *tmp; + pkgmgr_pkginfo_x *info = (pkgmgr_pkginfo_x *)handle; + + if (info->pkg_info == NULL) + return PMINFO_R_ERROR; + + for (tmp = info->pkg_info->appdefined_privileges; tmp; + tmp = tmp->next) { + privilege = (appdefined_privilege_x *)tmp->data; + if (privilege == NULL) + continue; + ret = privilege_func(privilege->value, privilege->license, + user_data); + if (ret < 0) break; } return PMINFO_R_OK; } +API int pkgmgrinfo_pkginfo_foreach_dependency(pkgmgrinfo_pkginfo_h handle, + pkgmgrinfo_pkg_dependency_list_cb dependency_cb, + void *user_data) +{ + int ret; + pkgmgr_pkginfo_x *info = (pkgmgr_pkginfo_x *)handle; + GList *tmp; + dependency_x *dependency; + + if (handle == NULL || dependency_cb == NULL) { + LOGE("invalid parameter"); + return PMINFO_R_EINVAL; + } + + if (info->pkg_info == NULL) + return PMINFO_R_ERROR; + + for (tmp = info->pkg_info->dependencies; tmp; tmp = tmp->next) { + dependency = (dependency_x *)tmp->data; + if (dependency == NULL) + continue; + ret = dependency_cb(dependency->depends_on, dependency->type, + dependency->required_version, user_data); + if (ret < 0) + break; + } + + return PMINFO_R_OK; +} + +struct required_by { + char *pkgid; + char *type; + char *version; +}; + +static int _get_required_by(sqlite3 *db, const char *pkgid, GQueue **queue, + GHashTable **table, GList **pkg_list) +{ + static const char query[] = + "SELECT package, type, required_version " + "FROM package_dependency_info WHERE depends_on=?"; + int ret; + sqlite3_stmt *stmt; + struct required_by *req; + + /* already checked */ + if (!g_hash_table_insert(*table, strdup(pkgid), GINT_TO_POINTER(1))) + return PMINFO_R_OK; + + ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); + if (ret != SQLITE_OK) { + LOGE("prepare failed: %s", sqlite3_errmsg(db)); + return PMINFO_R_ERROR; + } + + ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_STATIC); + if (ret != SQLITE_OK) { + LOGE("bind failed: %s", sqlite3_errmsg(db)); + sqlite3_finalize(stmt); + return PMINFO_R_ERROR; + } + + while (sqlite3_step(stmt) == SQLITE_ROW) { + req = calloc(1, sizeof(struct required_by)); + if (req == NULL) { + LOGE("out of memory"); + sqlite3_finalize(stmt); + return PMINFO_R_ERROR; + } + _save_column_str(stmt, 0, &req->pkgid); + _save_column_str(stmt, 1, &req->type); + _save_column_str(stmt, 2, &req->version); + + *pkg_list = g_list_append(*pkg_list, req); + g_queue_push_tail(*queue, strdup(req->pkgid)); + } + + sqlite3_finalize(stmt); + + return PMINFO_R_OK; +} + +static int _pkginfo_foreach_required_by(uid_t uid, const char *pkgid, + GList **pkg_list) +{ + int ret; + char *dbpath; + sqlite3 *db; + GQueue *queue; + GHashTable *table; + char *item; + + dbpath = getUserPkgParserDBPathUID(uid); + if (dbpath == NULL) + 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); + + queue = g_queue_new(); + if (queue == NULL) { + LOGE("out of memory"); + sqlite3_close_v2(db); + return PMINFO_R_ERROR; + } + + table = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL); + + g_queue_push_tail(queue, strdup(pkgid)); + while (!g_queue_is_empty(queue)) { + item = g_queue_pop_head(queue); + ret = _get_required_by(db, item, &queue, &table, pkg_list); + free(item); + if (ret != PMINFO_R_OK) { + LOGE("failed to get required by pkgs"); + g_hash_table_destroy(table); + g_queue_free_full(queue, free); + sqlite3_close_v2(db); + return PMINFO_R_ERROR; + } + } + + g_hash_table_destroy(table); + g_queue_free_full(queue, free); + sqlite3_close_v2(db); + + return PMINFO_R_OK; +} + +static void __free_required_by(gpointer data) +{ + struct required_by *req = (struct required_by *)data; + + free(req->pkgid); + free(req->type); + free(req->version); + free(req); +} + +API int pkgmgrinfo_pkginfo_foreach_required_by(pkgmgrinfo_pkginfo_h handle, + pkgmgrinfo_pkg_dependency_list_cb dependency_cb, + void *user_data) +{ + int ret; + pkgmgr_pkginfo_x *info = (pkgmgr_pkginfo_x *)handle; + GList *pkg_list = NULL; + GList *l; + struct required_by *req; + + if (handle == NULL || dependency_cb == NULL || info->pkg_info == NULL) { + LOGE("invalid parameter"); + return PMINFO_R_EINVAL; + } + + ret = _pkginfo_foreach_required_by(info->uid, info->pkg_info->package, + &pkg_list); + if (ret == PMINFO_R_OK && info->uid != GLOBAL_USER) + ret = _pkginfo_foreach_required_by(GLOBAL_USER, + info->pkg_info->package, &pkg_list); + + if (ret != PMINFO_R_OK) { + g_list_free_full(pkg_list, __free_required_by); + return ret; + } + + for (l = pkg_list; l != NULL; l = l->next) { + req = (struct required_by *)l->data; + ret = dependency_cb(req->pkgid, req->type, req->version, + user_data); + if (ret < 0) + break; + } + + g_list_free_full(pkg_list, __free_required_by); + + return PMINFO_R_OK; +} + int __compare_package_version(const char *version, int *major, int *minor, int *macro, int *nano) {