#include <sys/wait.h>
#include <sys/time.h>
#include <unzip.h>
+#include <pthread.h>
#include <glib.h>
#include <tzplatform_config.h>
#include "package-manager.h"
+#include "package-manager-types.h"
#include "pkgmgr_client_debug.h"
#include "pkgmgr_client_internal.h"
#define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
#define REGULAR_USER 5000
+static GList *jobs_to_free;
+static pthread_mutex_t __mutex = PTHREAD_MUTEX_INITIALIZER;
+
static inline uid_t _getuid(void)
{
uid_t uid = getuid();
return uid;
}
-static int _get_request_id()
+static int _get_internal_request_id()
{
static int internal_req_id = 1;
return internal_req_id++;
}
+static char *_generate_request_id(void)
+{
+ struct timeval tv;
+ long curtime;
+ char buf[BUFMAX];
+
+ gettimeofday(&tv, NULL);
+ curtime = tv.tv_sec * 1000000 + tv.tv_usec;
+
+ snprintf(buf, sizeof(buf), "%d_%ld", getpid(), curtime);
+
+ return strdup(buf);
+}
+
static struct cb_info *__create_event_cb_info(struct pkgmgr_client_t *client,
pkgmgr_handler event_cb, void *data, const char *req_key)
{
cb_info->client = client;
cb_info->event_cb = event_cb;
cb_info->data = data;
- cb_info->req_id = _get_request_id();
+ cb_info->req_id = _get_internal_request_id();
if (req_key != NULL) {
cb_info->req_key = strdup(req_key);
if (cb_info->req_key == NULL) {
cb_info->client = client;
cb_info->app_event_cb = app_event_cb;
cb_info->data = data;
- cb_info->req_id = _get_request_id();
+ cb_info->req_id = _get_internal_request_id();
if (req_key != NULL) {
cb_info->req_key = strdup(req_key);
if (cb_info->req_key == NULL) {
return cb_info;
}
+static struct cb_info *__create_res_event_cb_info(
+ struct pkgmgr_client_t *client,
+ pkgmgr_res_handler res_event_cb,
+ void *data, const char *req_key)
+{
+ struct cb_info *cb_info;
+
+ cb_info = calloc(1, sizeof(struct cb_info));
+ if (cb_info == NULL) {
+ ERR("out of memory");
+ return NULL;
+ }
+
+ cb_info->client = client;
+ cb_info->res_event_cb = res_event_cb;
+ cb_info->data = data;
+ cb_info->req_id = _get_internal_request_id();
+ if (req_key == NULL)
+ return cb_info;
+
+ cb_info->req_key = strdup(req_key);
+ if (cb_info->req_key == NULL) {
+ ERR("out of memory");
+ free(cb_info);
+ return NULL;
+ }
+
+ return cb_info;
+}
+
+static struct cb_info *__create_upgrade_event_cb_info(
+ struct pkgmgr_client_t *client,
+ pkgmgr_pkg_upgrade_handler upgrade_event_cb,
+ void *data, const char *req_key)
+{
+ struct cb_info *cb_info;
+
+ cb_info = calloc(1, sizeof(struct cb_info));
+ if (cb_info == NULL) {
+ ERR("out of memory");
+ return NULL;
+ }
+
+ cb_info->client = client;
+ cb_info->upgrade_event_cb = upgrade_event_cb;
+ cb_info->data = data;
+ cb_info->req_id = _get_internal_request_id();
+ if (req_key == NULL)
+ return cb_info;
+
+ cb_info->req_key = strdup(req_key);
+ if (cb_info->req_key == NULL) {
+ ERR("out of memory");
+ free(cb_info);
+ return NULL;
+ }
+
+ return cb_info;
+}
+
static struct cb_info *__create_size_info_cb_info(
struct pkgmgr_client_t *client,
pkgmgr_pkg_size_info_receive_cb size_info_cb,
cb_info->client = client;
cb_info->size_info_cb = size_info_cb;
cb_info->data = data;
- cb_info->req_id = _get_request_id();
+ cb_info->req_id = _get_internal_request_id();
if (req_key != NULL) {
cb_info->req_key = strdup(req_key);
if (cb_info->req_key == NULL) {
return cb_info;
}
-static gboolean __free_cb_info_at_main_thread(gpointer user_data)
+static int __jobs_to_free_add(gpointer data)
{
- struct cb_info *cb_info = (struct cb_info *)user_data;
+ pthread_mutex_lock(&__mutex);
+ if (g_list_find(jobs_to_free, data)) {
+ pthread_mutex_unlock(&__mutex);
+ return -1;
+ }
+
+ jobs_to_free = g_list_append(jobs_to_free, data);
+ pthread_mutex_unlock(&__mutex);
+ return 0;
+}
+
+static void __jobs_to_free_remove(gpointer data)
+{
+ pthread_mutex_lock(&__mutex);
+ jobs_to_free = g_list_remove(jobs_to_free, data);
+ pthread_mutex_unlock(&__mutex);
+}
+
+static void __do_free_cb_info(gpointer data)
+{
+ struct cb_info *cb_info = (struct cb_info *)data;
+
g_list_free(cb_info->sid_list);
free(cb_info->req_key);
free(cb_info);
+}
+
+static void __free_cb_info_cb(gpointer data)
+{
+ g_idle_remove_by_data(data);
+ __do_free_cb_info(data);
+}
+
+__attribute__((destructor)) static void __free_cb_info_at_destructor(void)
+{
+ pthread_mutex_lock(&__mutex);
+ g_list_free_full(jobs_to_free, __free_cb_info_cb);
+ pthread_mutex_unlock(&__mutex);
+}
+
+static gboolean __free_cb_info_at_idle(gpointer data)
+{
+ __jobs_to_free_remove(data);
+ __do_free_cb_info(data);
return G_SOURCE_REMOVE;
}
static void __free_cb_info(struct cb_info *cb_info)
{
- g_idle_add(__free_cb_info_at_main_thread, cb_info);
+ if (__jobs_to_free_add(cb_info) < 0)
+ return;
+
+ g_idle_add(__free_cb_info_at_idle, cb_info);
}
static int __get_size_process(pkgmgr_client *pc, const char *pkgid, uid_t uid,
if (ret != PKGMGR_R_OK) {
ERR("request failed: %d", ret);
+ pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
return ret;
}
g_variant_unref(result);
if (ret != PKGMGR_R_OK) {
ERR("request failed, ret=%d", ret);
+ pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
return ret;
}
pkgmgr_client_connection_disconnect(client);
if (client->tep_path)
free(client->tep_path);
+ if (client->res_copy_builder)
+ g_variant_builder_unref(client->res_copy_builder);
+ if (client->res_remove_builder)
+ g_variant_builder_unref(client->res_remove_builder);
+ if (client->res_create_dir_builder)
+ g_variant_builder_unref(client->res_create_dir_builder);
free(client);
return PKGMGR_R_OK;
struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
struct cb_info *cb_info;
int i;
+ char *request_id = NULL;
if (pc == NULL || pkg_paths == NULL || n_pkgs < 1) {
ERR("invalid parameter");
return PKGMGR_R_EINVAL;
}
+ for (i = 0; i < n_pkgs; i++) {
+ if (access(pkg_paths[i], F_OK) != 0) {
+ ERR("failed to access: %s", pkg_paths[i]);
+ return PKGMGR_R_EINVAL;
+ }
+ }
+
pkgs_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
for (i = 0; i < n_pkgs; i++)
g_variant_builder_add(pkgs_builder, "s", pkg_paths[i]);
args = g_variant_new("as", args_builder);
g_variant_builder_unref(args_builder);
+ request_id = _generate_request_id();
ret = pkgmgr_client_connection_send_request(client, "install_pkgs",
- g_variant_new("(u@as@as)", uid, pkgs, args), &result);
+ g_variant_new("(u@as@ass)", uid, pkgs, args,
+ request_id),
+ &result);
+ free(request_id);
if (ret != PKGMGR_R_OK) {
ERR("request failed: %d", ret);
return ret;
GVariant *args = NULL;
struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
struct cb_info *cb_info;
+ char *request_id = NULL;
if (pc == NULL || pkg_path == NULL) {
ERR("invalid parameter");
args = g_variant_new("as", builder);
g_variant_builder_unref(builder);
+ request_id = _generate_request_id();
ret = pkgmgr_client_connection_send_request(client, "install",
- g_variant_new("(uss@as)", uid, pkg_type ? pkg_type : "",
- pkg_path, args),
+ g_variant_new("(uss@ass)", uid, pkg_type ? pkg_type : "",
+ pkg_path, args, request_id),
&result);
+ free(request_id);
if (ret != PKGMGR_R_OK) {
ERR("request failed: %d", ret);
return ret;
return ret;
}
client->cb_info_list = g_list_append(client->cb_info_list, cb_info);
-
return cb_info->req_id;
}
struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
struct cb_info *cb_info;
int i;
+ char *request_id = NULL;
if (pc == NULL || pkg_paths == NULL || n_pkgs < 1) {
ERR("invalid parameter");
return PKGMGR_R_EINVAL;
}
+ for (i = 0; i < n_pkgs; i++) {
+ if (access(pkg_paths[i], F_OK) != 0) {
+ ERR("failed to access: %s", pkg_paths[i]);
+ return PKGMGR_R_EINVAL;
+ }
+ }
+
pkgs_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
for (i = 0; i < n_pkgs; i++)
g_variant_builder_add(pkgs_builder, "s", pkg_paths[i]);
pkgs = g_variant_new("as", pkgs_builder);
g_variant_builder_unref(pkgs_builder);
+ request_id = _generate_request_id();
ret = pkgmgr_client_connection_send_request(client,
"mount_install_pkgs",
- g_variant_new("(u@as)", uid, pkgs), &result);
+ g_variant_new("(u@ass)", uid, pkgs, request_id),
+ &result);
+ free(request_id);
if (ret != PKGMGR_R_OK) {
ERR("request failed: %d", ret);
return ret;
return cb_info->req_id;
}
-API int pkgmgr_cient_mount_install_packages(pkgmgr_client *pc,
+API int pkgmgr_client_mount_install_packages(pkgmgr_client *pc,
const char **pkg_paths, int n_pkgs, pkgmgr_handler event_cb,
void *data)
{
GVariant *args = NULL;
struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
struct cb_info *cb_info;
+ char *request_id = NULL;
if (pc == NULL || pkg_path == NULL) {
ERR("invalid parameter");
args = g_variant_new("as", builder);
g_variant_builder_unref(builder);
+ request_id = _generate_request_id();
ret = pkgmgr_client_connection_send_request(client, "mount_install",
- g_variant_new("(uss@as)", uid, pkg_type ? pkg_type : "",
- pkg_path, args),
+ g_variant_new("(uss@ass)", uid,
+ pkg_type ? pkg_type : "", pkg_path,
+ args, request_id),
&result);
+ free(request_id);
if (ret != PKGMGR_R_OK) {
ERR("request failed: %d", ret);
return ret;
}
API int pkgmgr_client_usr_clear_user_data(pkgmgr_client *pc,
- const char *pkg_type, const char *appid, pkgmgr_mode mode,
+ const char *pkg_type, const char *pkgid, pkgmgr_mode mode,
uid_t uid)
{
GVariant *result;
int ret;
struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
- if (pc == NULL || appid == NULL || uid == GLOBAL_USER) {
+ if (pc == NULL || pkgid == NULL || uid == GLOBAL_USER) {
ERR("invalid parameter");
return PKGMGR_R_EINVAL;
}
}
ret = pkgmgr_client_connection_send_request(client, "cleardata",
- g_variant_new("(us)", uid, appid), &result);
+ g_variant_new("(us)", uid, pkgid), &result);
if (ret != PKGMGR_R_OK) {
ERR("request failed: %d", ret);
return ret;
}
API int pkgmgr_client_clear_user_data(pkgmgr_client *pc, const char *pkg_type,
- const char *appid, pkgmgr_mode mode)
+ const char *pkgid, pkgmgr_mode mode)
{
- return pkgmgr_client_usr_clear_user_data(pc, pkg_type, appid, mode,
+ return pkgmgr_client_usr_clear_user_data(pc, pkg_type, pkgid, mode,
_getuid());
}
+API int pkgmgr_client_usr_clear_user_data_with_path(pkgmgr_client *pc,
+ const char *pkg_type, const char *pkgid, const char *file_path,
+ pkgmgr_mode mode, uid_t uid)
+{
+ GVariant *result;
+ int ret;
+ struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+
+ if (!pc || !pkgid || !file_path || uid == GLOBAL_USER) {
+ ERR("invalid parameter");
+ return PKGMGR_R_EINVAL;
+ }
+
+ if (client->pc_type != PC_REQUEST) {
+ ERR("client->pc_type is not PC_REQUEST");
+ return PKGMGR_R_EINVAL;
+ }
+
+ ret = pkgmgr_client_connection_send_request(client, "cleardata_with_path",
+ g_variant_new("(uss)", uid, pkgid, file_path), &result);
+ if (ret != PKGMGR_R_OK) {
+ ERR("request failed: %d", ret);
+ return ret;
+ }
+
+ g_variant_get(result, "(i)", &ret);
+ g_variant_unref(result);
+
+ return ret;
+}
+
+API int pkgmgr_client_clear_user_data_with_path(pkgmgr_client *pc, const char *pkg_type,
+ const char *pkgid, const char *file_path, pkgmgr_mode mode)
+{
+ return pkgmgr_client_usr_clear_user_data_with_path(pc, pkg_type, pkgid,
+ file_path, mode, _getuid());
+}
+
API int pkgmgr_client_set_status_type(pkgmgr_client *pc, int status_type)
{
struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
return cb_info->req_id;
}
+API int pkgmgr_client_listen_res_status(pkgmgr_client *pc,
+ pkgmgr_res_handler event_cb, void *data)
+{
+ int ret;
+ struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+ struct cb_info *cb_info;
+
+ if (pc == NULL || event_cb == NULL) {
+ ERR("invalid parameter");
+ return PKGMGR_R_EINVAL;
+ }
+
+ if (client->pc_type != PC_LISTENING) {
+ ERR("client->pc_type is not PC_LISTENING");
+ return PKGMGR_R_EINVAL;
+ }
+
+ cb_info = __create_res_event_cb_info(client, event_cb, data, NULL);
+ if (cb_info == NULL)
+ return PKGMGR_R_ENOMEM;
+ cb_info->status_type = client->status_type;
+ ret = pkgmgr_client_connection_set_callback(client, cb_info);
+ if (ret != PKGMGR_R_OK) {
+ __free_cb_info(cb_info);
+ return ret;
+ }
+ client->cb_info_list = g_list_append(client->cb_info_list, cb_info);
+
+ return cb_info->req_id;
+}
+
+API int pkgmgr_client_listen_pkg_upgrade_status(pkgmgr_client *pc,
+ pkgmgr_pkg_upgrade_handler event_cb, void *data)
+{
+ int ret;
+ struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+ struct cb_info *cb_info;
+
+ if (pc == NULL || event_cb == NULL) {
+ ERR("invalid parameter");
+ return PKGMGR_R_EINVAL;
+ }
+
+ if (client->pc_type != PC_LISTENING) {
+ ERR("client->pc_type is not PC_LISTENING");
+ return PKGMGR_R_EINVAL;
+ }
+
+ cb_info = __create_upgrade_event_cb_info(client, event_cb, data, NULL);
+ if (cb_info == NULL)
+ return PKGMGR_R_ENOMEM;
+ cb_info->status_type = client->status_type;
+ ret = pkgmgr_client_connection_set_callback(client, cb_info);
+ if (ret != PKGMGR_R_OK) {
+ __free_cb_info(cb_info);
+ return ret;
+ }
+ client->cb_info_list = g_list_append(client->cb_info_list, cb_info);
+
+ return cb_info->req_id;
+}
+
API int pkgmgr_client_remove_listen_status(pkgmgr_client *pc)
{
struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
return ret;
}
+
+API int pkgmgr_client_add_res_copy_path(pkgmgr_client *pc,
+ const char *src_path, const char *dest_path)
+{
+ struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+
+ if (pc == NULL || src_path == NULL) {
+ ERR("invalid parameter");
+ return PKGMGR_R_EINVAL;
+ }
+
+ if (client->res_copy_builder == NULL) {
+ client->res_copy_builder =
+ g_variant_builder_new(G_VARIANT_TYPE("a(ss)"));
+ if (client->res_copy_builder == NULL) {
+ ERR("out of memory");
+ return PKGMGR_R_ENOMEM;
+ }
+ }
+
+ g_variant_builder_add(client->res_copy_builder, "(ss)",
+ src_path, dest_path ? dest_path : "");
+
+ return PKGMGR_R_OK;
+}
+
+API int pkgmgr_client_res_copy(pkgmgr_client *pc,
+ pkgmgr_res_handler event_cb, void *user_data)
+{
+ GVariant *result;
+ int ret;
+ char *req_key = NULL;
+ struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+ struct cb_info *cb_info;
+
+ if (pc == NULL || event_cb == NULL) {
+ ERR("invalid parameter");
+ return PKGMGR_R_EINVAL;
+ }
+
+ ret = pkgmgr_client_connection_send_request(client,
+ "res_copy",
+ g_variant_new("(a(ss))",
+ client->res_copy_builder), &result);
+ if (ret != PKGMGR_R_OK) {
+ ERR("request failed: %d", ret);
+ return ret;
+ }
+
+ g_variant_get(result, "(i&s)", &ret, &req_key);
+ if (req_key == NULL) {
+ g_variant_unref(result);
+ return PKGMGR_R_ECOMM;
+ }
+ if (ret != PKGMGR_R_OK) {
+ g_variant_unref(result);
+ return ret;
+ }
+
+ cb_info = __create_res_event_cb_info(client,
+ event_cb, user_data, req_key);
+ g_variant_unref(result);
+ if (cb_info == NULL)
+ return PKGMGR_R_ENOMEM;
+
+ ret = pkgmgr_client_connection_set_callback(client, cb_info);
+ if (ret != PKGMGR_R_OK) {
+ __free_cb_info(cb_info);
+ return ret;
+ }
+ client->cb_info_list = g_list_append(client->cb_info_list, cb_info);
+
+ return cb_info->req_id;
+}
+
+API int pkgmgr_client_add_res_create_dir_path(pkgmgr_client *pc,
+ const char *dir_path)
+{
+ struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+
+ if (pc == NULL || dir_path == NULL) {
+ ERR("invalid parameter");
+ return PKGMGR_R_EINVAL;
+ }
+
+ if (client->res_create_dir_builder == NULL) {
+ client->res_create_dir_builder =
+ g_variant_builder_new(G_VARIANT_TYPE("as"));
+ if (client->res_create_dir_builder == NULL) {
+ ERR("out of memory");
+ return PKGMGR_R_ENOMEM;
+ }
+ }
+
+ g_variant_builder_add(client->res_create_dir_builder, "s", dir_path);
+
+ return PKGMGR_R_OK;
+}
+
+API int pkgmgr_client_res_create_dir(pkgmgr_client *pc,
+ pkgmgr_res_handler event_cb, void *user_data)
+{
+ GVariant *result;
+ int ret;
+ char *req_key = NULL;
+ struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+ struct cb_info *cb_info;
+
+ if (pc == NULL || event_cb == NULL) {
+ ERR("invalid parameter");
+ return PKGMGR_R_EINVAL;
+ }
+
+ ret = pkgmgr_client_connection_send_request(client,
+ "res_create_dir",
+ g_variant_new("(as)",
+ client->res_create_dir_builder), &result);
+ if (ret != PKGMGR_R_OK) {
+ ERR("request failed: %d", ret);
+ return ret;
+ }
+
+ g_variant_get(result, "(i&s)", &ret, &req_key);
+ if (req_key == NULL) {
+ g_variant_unref(result);
+ return PKGMGR_R_ECOMM;
+ }
+ if (ret != PKGMGR_R_OK) {
+ g_variant_unref(result);
+ return ret;
+ }
+
+ cb_info = __create_res_event_cb_info(client,
+ event_cb, user_data, req_key);
+ g_variant_unref(result);
+ if (cb_info == NULL)
+ return PKGMGR_R_ENOMEM;
+
+ ret = pkgmgr_client_connection_set_callback(client, cb_info);
+ if (ret != PKGMGR_R_OK) {
+ __free_cb_info(cb_info);
+ return ret;
+ }
+ client->cb_info_list = g_list_append(client->cb_info_list, cb_info);
+
+ return cb_info->req_id;
+}
+
+API int pkgmgr_client_add_res_remove_path(pkgmgr_client *pc,
+ const char *res_path)
+{
+ struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+
+ if (pc == NULL || res_path == NULL) {
+ ERR("invalid parameter");
+ return PKGMGR_R_EINVAL;
+ }
+
+ if (client->res_remove_builder == NULL) {
+ client->res_remove_builder =
+ g_variant_builder_new(G_VARIANT_TYPE("as"));
+ if (client->res_remove_builder == NULL) {
+ ERR("out of memory");
+ return PKGMGR_R_ENOMEM;
+ }
+ }
+
+ g_variant_builder_add(client->res_remove_builder, "s", res_path);
+
+ return PKGMGR_R_OK;
+}
+
+API int pkgmgr_client_res_remove(pkgmgr_client *pc,
+ pkgmgr_res_handler event_cb, void *user_data)
+{
+ GVariant *result;
+ int ret;
+ char *req_key = NULL;
+ struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+ struct cb_info *cb_info;
+
+ if (pc == NULL || event_cb == NULL) {
+ ERR("invalid parameter");
+ return PKGMGR_R_EINVAL;
+ }
+
+ ret = pkgmgr_client_connection_send_request(client,
+ "res_remove",
+ g_variant_new("(as)",
+ client->res_remove_builder), &result);
+ if (ret != PKGMGR_R_OK) {
+ ERR("request failed: %d", ret);
+ return ret;
+ }
+
+ g_variant_get(result, "(i&s)", &ret, &req_key);
+ if (req_key == NULL) {
+ g_variant_unref(result);
+ return PKGMGR_R_ECOMM;
+ }
+ if (ret != PKGMGR_R_OK) {
+ g_variant_unref(result);
+ return ret;
+ }
+
+ cb_info = __create_res_event_cb_info(client,
+ event_cb, user_data, req_key);
+ g_variant_unref(result);
+ if (cb_info == NULL)
+ return PKGMGR_R_ENOMEM;
+
+ ret = pkgmgr_client_connection_set_callback(client, cb_info);
+ if (ret != PKGMGR_R_OK) {
+ __free_cb_info(cb_info);
+ return ret;
+ }
+ client->cb_info_list = g_list_append(client->cb_info_list, cb_info);
+
+ return cb_info->req_id;
+}
+
+API int pkgmgr_client_res_uninstall(pkgmgr_client *pc, const char *pkgid)
+{
+ return pkgmgr_client_res_usr_uninstall(pc, pkgid, _getuid());
+}
+
+API int pkgmgr_client_res_usr_uninstall(pkgmgr_client *pc, const char *pkgid,
+ uid_t uid)
+{
+ GVariant *result;
+ int ret = PKGMGR_R_ECOMM;
+ struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+
+ if (pc == NULL || pkgid == NULL) {
+ ERR("invalid parameter");
+ return PKGMGR_R_EINVAL;
+ }
+
+ ret = pkgmgr_client_connection_send_request(client,
+ "res_uninstall",
+ g_variant_new("(us)", uid, pkgid), &result);
+ if (ret != PKGMGR_R_OK) {
+ ERR("request failed: %d", ret);
+ return ret;
+ }
+
+ g_variant_get(result, "(i)", &ret);
+ g_variant_unref(result);
+
+ return ret;
+}
+
+API pkgmgr_res_event_info *pkgmgr_res_event_info_new()
+{
+ pkgmgr_res_event_info_t *info;
+
+ info = calloc(1, sizeof(pkgmgr_res_event_info_t));
+ if (info == NULL) {
+ ERR("out of memory");
+ return NULL;
+ }
+
+ return (pkgmgr_res_event_info *)info;
+}
+
+static void __free_path_states(gpointer data)
+{
+ res_event_path_state_t *path_state = (res_event_path_state_t *)data;
+
+ if (path_state == NULL)
+ return;
+ if (path_state->path)
+ free(path_state->path);
+ free(path_state);
+}
+
+API int pkgmgr_res_event_info_free(pkgmgr_res_event_info *info)
+{
+ pkgmgr_res_event_info_t *event_info =
+ (pkgmgr_res_event_info_t *)info;
+
+ if (event_info == NULL) {
+ ERR("invalid argument");
+ return PKGMGR_R_EINVAL;
+ }
+
+ if (event_info->path_states)
+ g_list_free_full(event_info->path_states, __free_path_states);
+ free(event_info);
+
+ return PKGMGR_R_OK;
+}
+
+API int pkgmgr_res_event_info_set_error_code(pkgmgr_res_event_info *handle, int error_code)
+{
+ pkgmgr_res_event_info_t *info = handle;
+ if (info == NULL) {
+ ERR("invalid parameter");
+ return PKGMGR_R_EINVAL;
+ }
+
+ info->error_code = error_code;
+ return PKGMGR_R_OK;
+}
+
+API int pkgmgr_res_event_info_get_error_code(pkgmgr_res_event_info *handle, int *error_code)
+{
+ pkgmgr_res_event_info_t *info = handle;
+ if (info == NULL || error_code == NULL) {
+ ERR("invalid parameter");
+ return PKGMGR_R_EINVAL;
+ }
+
+ *error_code = info->error_code;
+ return PKGMGR_R_OK;
+}
+
+API int pkgmgr_res_event_info_add_path_state(pkgmgr_res_event_info *handle,
+ const char *path, pkgmgr_res_event_path_state state)
+{
+ pkgmgr_res_event_info_t *info = handle;
+ res_event_path_state_t *path_state;
+
+ if (info == NULL || path == NULL) {
+ ERR("invalid parameter");
+ return PKGMGR_R_EINVAL;
+ }
+
+ path_state = calloc(1, sizeof(res_event_path_state_t));
+ if (path_state == NULL) {
+ ERR("out of memory");
+ return PKGMGR_R_ENOMEM;
+ }
+
+ path_state->path = strdup(path);
+ if (path_state->path == NULL) {
+ ERR("out of memory");
+ free(path_state);
+ return PKGMGR_R_ENOMEM;
+ }
+ path_state->state = state;
+
+ info->path_states = g_list_prepend(info->path_states , path_state);
+ return PKGMGR_R_OK;
+}
+
+API int pkgmgr_res_event_info_foreach_path(pkgmgr_res_event_info *handle,
+ pkgmgr_res_event_path_cb callback, void *user_data)
+{
+ pkgmgr_res_event_info_t *info = handle;
+ GList *list;
+ res_event_path_state_t *path_state;
+
+ if (info == NULL) {
+ ERR("invalid parameter");
+ return PKGMGR_R_EINVAL;
+ }
+
+ for (list = info->path_states; list != NULL; list = list->next) {
+ path_state = (res_event_path_state_t *)list->data;
+ if (callback(path_state->path, path_state->state,
+ user_data) < 0)
+ return PKGMGR_R_OK;
+ }
+
+ return PKGMGR_R_OK;
+}