From 2f051a45019188ecafafc06d440b81dcabb3055e Mon Sep 17 00:00:00 2001 From: Ilho Kim Date: Wed, 27 Mar 2024 19:58:28 +0900 Subject: [PATCH] Remove TIDL for signal transmission Change-Id: I0878a9560fc9ba954a6d3ad3ade6fa3b6bf8d962 Signed-off-by: Ilho Kim --- client/include/package-manager.h | 2 +- client/src/api_stub.cc | 751 +++++++++++++-- client/src/connector.cc | 16 +- client/src/connector.hh | 12 +- client/src/pkgmgr_client_connection.c | 466 +++++++++ client/src/pkgmgr_client_debug.h | 91 ++ client/src/pkgmgr_client_internal.c | 198 ++++ client/src/pkgmgr_client_internal.h | 98 ++ installer/CMakeLists.txt | 2 +- installer/pkgmgr_installer_config.h | 33 + installer/pkgmgr_installer_signal_agent.c | 337 +++++++ installer/pkgmgr_installer_signal_agent.cc | 384 -------- installer/src/api_stub.cc | 453 --------- installer/src/control.cc | 741 -------------- installer/src/control.hh | 70 -- installer/src/pkgmgr_installer.c | 1446 ++++++++++++++++++++++++++++ installer/src/pkgmgr_installer.h | 2 +- installer/src/pkgmgr_installer_debug.h | 12 +- installer/src/request.hh | 2 - 19 files changed, 3344 insertions(+), 1772 deletions(-) create mode 100644 client/src/pkgmgr_client_connection.c create mode 100644 client/src/pkgmgr_client_debug.h create mode 100644 client/src/pkgmgr_client_internal.c create mode 100644 client/src/pkgmgr_client_internal.h create mode 100644 installer/pkgmgr_installer_config.h create mode 100644 installer/pkgmgr_installer_signal_agent.c delete mode 100644 installer/pkgmgr_installer_signal_agent.cc delete mode 100644 installer/src/api_stub.cc delete mode 100644 installer/src/control.cc delete mode 100644 installer/src/control.hh create mode 100644 installer/src/pkgmgr_installer.c diff --git a/client/include/package-manager.h b/client/include/package-manager.h index 5f26051..9c0604a 100644 --- a/client/include/package-manager.h +++ b/client/include/package-manager.h @@ -193,7 +193,7 @@ typedef struct { typedef struct _pkgmgr_res_event_info_t { int error_code; - void *path_states; + GList *path_states; } pkgmgr_res_event_info_t; typedef struct _res_event_path_state_t { diff --git a/client/src/api_stub.cc b/client/src/api_stub.cc index a6760cf..04eb2c0 100644 --- a/client/src/api_stub.cc +++ b/client/src/api_stub.cc @@ -25,6 +25,7 @@ #include "client/src/connector.hh" #include "client/src/log.hh" #include "client/src/internal.hh" +#include "client/src/pkgmgr_client_internal.h" #ifdef API #undef API @@ -40,6 +41,9 @@ using pkgmgr::client::Connector; namespace { +static GList *jobs_to_free; +static pthread_mutex_t __mutex = PTHREAD_MUTEX_INITIALIZER; + static int GetDelayedResult(pkgmgr_client *pc, const std::string& req_key) { if (pc == nullptr) { _E("invalid parameter"); @@ -160,6 +164,194 @@ static inline uid_t GetUid() { return uid; } +static int __jobs_to_free_add(gpointer 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 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) +{ + if (__jobs_to_free_add(cb_info) < 0) + return; + + g_idle_add(__free_cb_info_at_idle, cb_info); +} + +static int _get_internal_request_id() +{ + static int internal_req_id = 1; + + return internal_req_id++; +} + +static struct cb_info *__create_event_cb_info(struct pkgmgr_client_t *client, + pkgmgr_handler event_cb, void *data, const char *req_key) { + struct cb_info *ci; + + ci = static_cast(calloc(1, sizeof(struct cb_info))); + if (ci == NULL) { + _E("out of memory"); + return NULL; + } + ci->client = client; + ci->event_cb = event_cb; + ci->data = data; + ci->req_id = _get_internal_request_id(); + if (req_key != NULL) { + ci->req_key = strdup(req_key); + if (ci->req_key == NULL) { + _E("out of memory"); + free(ci); + return NULL; + } + } + + return ci; +} + +static struct cb_info *__create_app_event_cb_info( + struct pkgmgr_client_t *client, pkgmgr_app_handler app_event_cb, + void *data, const char *req_key) { + cb_info *ci; + + ci = static_cast(calloc(1, sizeof(cb_info))); + if (ci == NULL) { + _E("out of memory"); + return NULL; + } + ci->client = client; + ci->app_event_cb = app_event_cb; + ci->data = data; + ci->req_id = _get_internal_request_id(); + if (req_key != NULL) { + ci->req_key = strdup(req_key); + if (ci->req_key == NULL) { + _E("out of memory"); + free(ci); + return NULL; + } + } + + return ci; +} + +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 *ci; + + ci = static_cast(calloc(1, sizeof(cb_info))); + if (ci == NULL) { + _E("out of memory"); + return NULL; + } + + ci->client = client; + ci->res_event_cb = res_event_cb; + ci->data = data; + ci->req_id = _get_internal_request_id(); + if (req_key == NULL) + return ci; + + ci->req_key = strdup(req_key); + if (ci->req_key == NULL) { + _E("out of memory"); + free(ci); + return NULL; + } + + return ci; +} + +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 *ci; + + ci = static_cast(calloc(1, sizeof(cb_info))); + if (ci == NULL) { + _E("out of memory"); + return NULL; + } + + ci->client = client; + ci->upgrade_event_cb = upgrade_event_cb; + ci->data = data; + ci->req_id = _get_internal_request_id(); + if (req_key == NULL) + return ci; + + ci->req_key = strdup(req_key); + if (ci->req_key == NULL) { + _E("out of memory"); + free(ci); + return NULL; + } + + return ci; +} + +static struct cb_info *__create_size_info_cb_info( + struct pkgmgr_client_t *client, + pkgmgr_pkg_size_info_receive_cb size_info_cb, + void *data, const char *req_key) { + struct cb_info *ci; + + ci = static_cast(calloc(1, sizeof(cb_info))); + if (ci == NULL) { + _E("out of memory"); + return NULL; + } + ci->client = client; + ci->size_info_cb = size_info_cb; + ci->data = data; + ci->req_id = _get_internal_request_id(); + if (req_key != NULL) { + ci->req_key = strdup(req_key); + if (ci->req_key == NULL) { + _E("out of memory"); + free(ci); + return NULL; + } + } + + return ci; +} + } API pkgmgr_client* pkgmgr_client_new(pkgmgr_client_type pc_type) { @@ -168,7 +360,23 @@ API pkgmgr_client* pkgmgr_client_new(pkgmgr_client_type pc_type) { return nullptr; } - return new Connector(pc_type); + pkgmgr_client_t* raw_pc = + static_cast(calloc(1, sizeof(pkgmgr_client_t))); + if (raw_pc == nullptr) { + _E("out of memory"); + return nullptr; + } + + raw_pc->pc_type = pc_type; + raw_pc->status_type = PKGMGR_CLIENT_STATUS_ALL; + + if (pkgmgr_client_connection_connect(raw_pc) != PKGMGR_R_OK) { + _E("pkgmgr_client_connection_connect fail"); + free(raw_pc); + return nullptr; + } + + return new Connector(pc_type, raw_pc); } API int pkgmgr_client_free(pkgmgr_client* pc) { @@ -178,6 +386,20 @@ API int pkgmgr_client_free(pkgmgr_client* pc) { } Connector* con = static_cast(pc); + pkgmgr_client_t* raw_pc = con->GetRawPc(); + if (raw_pc) { + pkgmgr_client_remove_listen_status(raw_pc); + pkgmgr_client_connection_disconnect(raw_pc); + if (raw_pc->tep_path) + free(raw_pc->tep_path); + if (raw_pc->res_copy_builder) + g_variant_builder_unref(raw_pc->res_copy_builder); + if (raw_pc->res_remove_builder) + g_variant_builder_unref(raw_pc->res_remove_builder); + if (raw_pc->res_create_dir_builder) + g_variant_builder_unref(raw_pc->res_create_dir_builder); + free(raw_pc); + } delete con; return PKGMGR_R_OK; @@ -218,13 +440,24 @@ API int pkgmgr_client_usr_install_packages(pkgmgr_client *pc, for (int i = 0; i < n_pkgs; i++) pkgs.push_back(pkg_paths[i]); - const auto& receiver = con->GetSignalReceiver(); int ret = proxy->InstallPkgs(uid, pkgs, con->GetArgv(), con->GenerateRequestId(), req_key); if (ret != PKGMGR_R_OK) return ret; - return receiver->AddEventHandler(req_key, event_cb, data); + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_event_cb_info(client, event_cb, data, req_key.c_str()); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_install_packages(pkgmgr_client *pc, @@ -275,14 +508,25 @@ API int pkgmgr_client_usr_install(pkgmgr_client *pc, const char *pkg_type, if (proxy == nullptr) return PKGMGR_R_EIO; - const auto& receiver = con->GetSignalReceiver(); std::string req_key; int ret = proxy->Install(uid, pkg_type ? pkg_type : "", pkg_path, con->GetArgv(), con->GenerateRequestId(), req_key); if (ret != PKGMGR_R_OK) return ret; - return receiver->AddEventHandler(req_key, event_cb, data); + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_event_cb_info(client, event_cb, data, req_key.c_str()); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_reinstall(pkgmgr_client *pc, const char *pkg_type, @@ -310,13 +554,24 @@ API int pkgmgr_client_usr_reinstall(pkgmgr_client *pc, const char *pkg_type, if (proxy == nullptr) return PKGMGR_R_EIO; - const auto& receiver = con->GetSignalReceiver(); std::string req_key; int ret = proxy->Reinstall(uid, pkgid, req_key); if (ret != PKGMGR_R_OK) return ret; - return receiver->AddEventHandler(req_key, event_cb, data); + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_event_cb_info(client, event_cb, data, req_key.c_str()); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_uninstall_packages(pkgmgr_client *pc, @@ -349,12 +604,23 @@ API int pkgmgr_client_usr_uninstall_packages(pkgmgr_client *pc, for (int i = 0; i < n_pkgs; i++) pkgs.push_back(pkgids[i]); - const auto& receiver = con->GetSignalReceiver(); int ret = proxy->UninstallPkgs(uid, pkgs, req_key); if (ret != PKGMGR_R_OK) return ret; - return receiver->AddEventHandler(req_key, event_cb, data); + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_event_cb_info(client, event_cb, data, req_key.c_str()); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_uninstall(pkgmgr_client *pc, const char *pkg_type, @@ -382,13 +648,24 @@ API int pkgmgr_client_usr_uninstall(pkgmgr_client *pc, const char *pkg_type, if (proxy == nullptr) return PKGMGR_R_EIO; - const auto& receiver = con->GetSignalReceiver(); std::string req_key; int ret = proxy->Uninstall(uid, pkgid, req_key); if (ret != PKGMGR_R_OK) return ret; - return receiver->AddEventHandler(req_key, event_cb, data); + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_event_cb_info(client, event_cb, data, req_key.c_str()); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_listen_res_status(pkgmgr_client *pc, @@ -399,19 +676,42 @@ API int pkgmgr_client_listen_res_status(pkgmgr_client *pc, return PKGMGR_R_EINVAL; } - try { - const auto& receiver = con->GetSignalReceiver(); - return receiver->AddEventHandler("", event_cb, data); - } catch (...) { - _E("exception occured"); - return PKGMGR_R_ERROR; + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_res_event_cb_info(client, event_cb, data, nullptr); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + int ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_listen_pkg_upgrade_status(pkgmgr_client *pc, pkgmgr_pkg_upgrade_handler event_cb, void *data) { - //TODO - return PKGMGR_R_OK; + Connector* con = static_cast(pc); + if (con->GetPcType() != PC_LISTENING) { + _E("client->pc_type is not PC_LISTENING"); + return PKGMGR_R_EINVAL; + } + + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_upgrade_event_cb_info(client, event_cb, data, nullptr); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + int ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_usr_mount_install_packages(pkgmgr_client *pc, @@ -443,13 +743,24 @@ API int pkgmgr_client_usr_mount_install_packages(pkgmgr_client *pc, pkgs.push_back(pkg_paths[i]); } - const auto& receiver = con->GetSignalReceiver(); int ret = proxy->MountInstallPkgs(uid, pkgs, con->GenerateRequestId(), req_key); if (ret != PKGMGR_R_OK) return ret; - return receiver->AddEventHandler(req_key, event_cb, data); + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_event_cb_info(client, event_cb, data, req_key.c_str()); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_mount_install_packages(pkgmgr_client *pc, @@ -501,14 +812,25 @@ API int pkgmgr_client_usr_mount_install(pkgmgr_client *pc, const char *pkg_type, if (proxy == nullptr) return PKGMGR_R_EIO; - const auto& receiver = con->GetSignalReceiver(); std::string req_key; int ret = proxy->MountInstall(uid, pkg_type ? pkg_type : "", pkg_path, con->GetArgv(), con->GenerateRequestId(), req_key); if (ret != PKGMGR_R_OK) return ret; - return receiver->AddEventHandler(req_key, event_cb, data); + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_event_cb_info(client, event_cb, data, req_key.c_str()); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_move(pkgmgr_client *pc, const char *pkg_type, @@ -540,13 +862,24 @@ API int pkgmgr_client_usr_move(pkgmgr_client *pc, const char *pkg_type, if (proxy == nullptr) return PKGMGR_R_EIO; - const auto& receiver = con->GetSignalReceiver(); std::string req_key; int ret = proxy->Move(uid, pkgid, move_type, req_key); if (ret != PKGMGR_R_OK) return ret; - return receiver->AddEventHandler(req_key, event_cb, data); + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_event_cb_info(client, event_cb, data, req_key.c_str()); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_register_pkg_update_info(pkgmgr_client *pc, @@ -686,12 +1019,23 @@ API int pkgmgr_client_usr_activate_packages(pkgmgr_client *pc, vec.push_back(pkgids[i]); } - const auto& receiver = con->GetSignalReceiver(); int ret = proxy->EnablePkgs(uid, std::move(vec), req_key); if (ret != PKGMGR_R_OK) return ret; - return receiver->AddEventHandler(req_key, event_cb, data); + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_event_cb_info(client, event_cb, data, req_key.c_str()); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_activate_packages(pkgmgr_client *pc, @@ -745,12 +1089,23 @@ API int pkgmgr_client_usr_deactivate_packages(pkgmgr_client *pc, for (int i = 0; i < n_pkgs; i++) { vec.push_back(pkgids[i]); } - const auto& receiver = con->GetSignalReceiver(); int ret = proxy->DisablePkgs(uid, std::move(vec), req_key); if (ret != PKGMGR_R_OK) return ret; - return receiver->AddEventHandler(req_key, event_cb, data); + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_event_cb_info(client, event_cb, data, req_key.c_str()); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_deactivate_packages(pkgmgr_client *pc, @@ -772,13 +1127,24 @@ API int pkgmgr_client_usr_activate_app(pkgmgr_client *pc, const char *appid, if (proxy == nullptr) return PKGMGR_R_EIO; - const auto& receiver = con->GetSignalReceiver(); std::string req_key; int ret = proxy->EnableApp(uid, appid, req_key); if (ret != PKGMGR_R_OK) return ret; - return receiver->AddEventHandler(req_key, app_event_cb, data); + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_app_event_cb_info(client, app_event_cb, data, req_key.c_str()); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_activate_app(pkgmgr_client *pc, const char *appid, @@ -810,12 +1176,23 @@ API int pkgmgr_client_usr_activate_apps(pkgmgr_client *pc, const char **appids, vec.push_back(appids[i]); } - const auto& receiver = con->GetSignalReceiver(); int ret = proxy->EnableApps(uid, std::move(vec), req_key); if (ret != PKGMGR_R_OK) return ret; - return receiver->AddEventHandler(req_key, app_event_cb, data); + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_app_event_cb_info(client, app_event_cb, data, req_key.c_str()); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_activate_apps(pkgmgr_client *pc, const char **appids, @@ -836,13 +1213,24 @@ API int pkgmgr_client_activate_global_app_for_uid(pkgmgr_client *pc, if (proxy == nullptr) return PKGMGR_R_EIO; - const auto& receiver = con->GetSignalReceiver(); std::string req_key; int ret = proxy->EnableGlobalAppForUid(uid, appid, req_key); if (ret != PKGMGR_R_OK) return ret; - return receiver->AddEventHandler(req_key, app_event_cb, data); + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_app_event_cb_info(client, app_event_cb, data, req_key.c_str()); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_usr_deactivate_app(pkgmgr_client *pc, const char *appid, @@ -857,13 +1245,24 @@ API int pkgmgr_client_usr_deactivate_app(pkgmgr_client *pc, const char *appid, if (proxy == nullptr) return PKGMGR_R_EIO; - const auto& receiver = con->GetSignalReceiver(); std::string req_key; int ret = proxy->DisableApp(uid, appid, req_key); if (ret != PKGMGR_R_OK) return ret; - return receiver->AddEventHandler(req_key, app_event_cb, data); + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_app_event_cb_info(client, app_event_cb, data, req_key.c_str()); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_deactivate_app(pkgmgr_client *pc, const char *appid, @@ -896,12 +1295,23 @@ API int pkgmgr_client_usr_deactivate_apps(pkgmgr_client *pc, vec.push_back(appids[i]); } - const auto& receiver = con->GetSignalReceiver(); int ret = proxy->DisableApps(uid, std::move(vec), req_key); if (ret != PKGMGR_R_OK) return ret; - return receiver->AddEventHandler(req_key, app_event_cb, data); + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_app_event_cb_info(client, app_event_cb, data, req_key.c_str()); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_deactivate_apps(pkgmgr_client *pc, const char **appids, @@ -922,13 +1332,24 @@ API int pkgmgr_client_deactivate_global_app_for_uid(pkgmgr_client *pc, if (proxy == nullptr) return PKGMGR_R_EIO; - const auto& receiver = con->GetSignalReceiver(); std::string req_key; int ret = proxy->DisableGlobalAppForUid(uid, appid, req_key); if (ret != PKGMGR_R_OK) return ret; - return receiver->AddEventHandler(req_key, app_event_cb, data); + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_app_event_cb_info(client, app_event_cb, data, req_key.c_str()); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_clear_user_data(pkgmgr_client *pc, const char *pkg_type, @@ -988,7 +1409,21 @@ API int pkgmgr_client_clear_user_data_with_path(pkgmgr_client *pc, const char *p } API int pkgmgr_client_set_status_type(pkgmgr_client *pc, int status_type) { - //TODO + if (pc == NULL) { + _E("invalid parameter"); + return PKGMGR_R_EINVAL; + } + + auto* con = static_cast(pc); + pkgmgr_client_t* client = static_cast(con->GetRawPc()); + + if (client == NULL) { + _E("invalid parameter"); + return PKGMGR_R_EINVAL; + } + + client->status_type = status_type; + return PKGMGR_R_OK; } @@ -1005,13 +1440,20 @@ API int pkgmgr_client_listen_status(pkgmgr_client *pc, pkgmgr_handler event_cb, return PKGMGR_R_EINVAL; } - try { - const auto& receiver = con->GetSignalReceiver(); - return receiver->AddEventHandler("", event_cb, data); - } catch (...) { - _E("exception occured"); - return PKGMGR_R_ERROR; + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_event_cb_info(client, event_cb, data, nullptr); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ci->status_type = client->status_type; + int ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_listen_app_status(pkgmgr_client *pc, @@ -1027,17 +1469,45 @@ API int pkgmgr_client_listen_app_status(pkgmgr_client *pc, return PKGMGR_R_EINVAL; } - try { - const auto& receiver = con->GetSignalReceiver(); - return receiver->AddEventHandler("", app_event_cb, data); - } catch (...) { - _E("exception occured"); - return PKGMGR_R_ERROR; + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_app_event_cb_info(client, app_event_cb, data, nullptr); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ci->status_type = client->status_type; + int ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_remove_listen_status(pkgmgr_client *pc) { - //TODO + struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc; + GList *tmp; + GList *next; + struct cb_info *ci; + + if (pc == NULL) { + _E("invalid parameter"); + return PKGMGR_R_EINVAL; + } + + /* unset all callback */ + tmp = client->cb_info_list; + while (tmp != NULL) { + next = tmp->next; + ci = (struct cb_info *)tmp->data; + pkgmgr_client_connection_unset_callback(client, ci); + client->cb_info_list = g_list_delete_link(client->cb_info_list, + tmp); + __free_cb_info(ci); + tmp = next; + } + return PKGMGR_R_OK; } @@ -1164,13 +1634,24 @@ API int pkgmgr_client_usr_get_size(pkgmgr_client *pc, const char *pkgid, if (proxy == nullptr) return PKGMGR_R_EIO; - const auto& receiver = con->GetSignalReceiver(); std::string req_key; int ret = proxy->GetSize(uid, pkgid, get_type, req_key); if (ret != PKGMGR_R_OK) return ret; - return receiver->AddEventHandler(req_key, event_cb, data); + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_event_cb_info(client, event_cb, data, req_key.c_str()); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return PKGMGR_R_OK; } API int pkgmgr_client_get_package_size_info(pkgmgr_client *pc, @@ -1219,13 +1700,22 @@ API int pkgmgr_client_usr_get_package_size_info(pkgmgr_client *pc, if (proxy == nullptr) return PKGMGR_R_EIO; - const auto& receiver = con->GetSignalReceiver(); std::string req_key; int ret = proxy->GetSize(uid, pkgid, get_type, req_key); if (ret != PKGMGR_R_OK) return ret; - receiver->AddEventHandler(req_key, event_cb, pc, user_data); + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_size_info_cb_info(client, event_cb, user_data, req_key.c_str()); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); return PKGMGR_R_OK; } @@ -1623,14 +2113,24 @@ API int pkgmgr_client_res_copy(pkgmgr_client *pc, if (proxy == nullptr) return PKGMGR_R_EIO; - const auto& receiver = con->GetSignalReceiver(); - std::string req_key; int ret = proxy->ResCopy(con->GetResCopyPath(), req_key); if (ret != PKGMGR_R_OK) return ret; - return receiver->AddEventHandler(req_key, event_cb, user_data); + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_res_event_cb_info(client, event_cb, user_data, req_key.c_str()); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_add_res_create_dir_path(pkgmgr_client *pc, @@ -1658,14 +2158,24 @@ API int pkgmgr_client_res_create_dir(pkgmgr_client *pc, if (proxy == nullptr) return PKGMGR_R_EIO; - const auto& receiver = con->GetSignalReceiver(); - std::string req_key; int ret = proxy->ResCreateDir(con->GetResCreateDir(), req_key); if (ret != PKGMGR_R_OK) return ret; - return receiver->AddEventHandler(req_key, event_cb, user_data); + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_res_event_cb_info(client, event_cb, user_data, req_key.c_str()); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_add_res_remove_path(pkgmgr_client *pc, @@ -1693,14 +2203,24 @@ API int pkgmgr_client_res_remove(pkgmgr_client *pc, if (proxy == nullptr) return PKGMGR_R_EIO; - const auto& receiver = con->GetSignalReceiver(); - std::string req_key; int ret = proxy->ResRemove(con->GetResRemovePath(), req_key); if (ret != PKGMGR_R_OK) return ret; - return receiver->AddEventHandler(req_key, event_cb, user_data); + pkgmgr_client_t* client = con->GetRawPc(); + + cb_info* ci = __create_res_event_cb_info(client, event_cb, user_data, req_key.c_str()); + if (ci == NULL) + return PKGMGR_R_ENOMEM; + ret = pkgmgr_client_connection_set_callback(client, ci); + if (ret != PKGMGR_R_OK) { + __free_cb_info(ci); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, ci); + + return ci->req_id; } API int pkgmgr_client_res_uninstall(pkgmgr_client *pc, const char *pkgid) { @@ -1724,84 +2244,109 @@ API int pkgmgr_client_res_usr_uninstall(pkgmgr_client *pc, const char *pkgid, } API pkgmgr_res_event_info *pkgmgr_res_event_info_new() { - pkgmgr_res_event_info* info = - reinterpret_cast( - new rpc_port::PkgSignal::ExtraData); - if (!info) { - _E("Out of memory"); - return nullptr; + pkgmgr_res_event_info_t *info; + + info = static_cast(calloc(1, sizeof(pkgmgr_res_event_info_t))); + if (info == NULL) { + _E("out of memory"); + return NULL; } - return info; + + 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) { - if (!info) { - _E("invalid parameter"); + pkgmgr_res_event_info_t *event_info = + (pkgmgr_res_event_info_t *)info; + + if (event_info == NULL) { + _E("invalid argument"); return PKGMGR_R_EINVAL; } - rpc_port::PkgSignal::ExtraData* event_info = - reinterpret_cast(info); - delete event_info; + + 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) { - if (!handle) { + pkgmgr_res_event_info_t *info = static_cast(handle); + if (info == NULL) { _E("invalid parameter"); return PKGMGR_R_EINVAL; } - rpc_port::PkgSignal::ExtraData* event_info = - reinterpret_cast(handle); - event_info->SetErrCode(error_code); - + 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) { - if (!handle) { + pkgmgr_res_event_info_t *info = static_cast(handle); + if (info == NULL || error_code == NULL) { _E("invalid parameter"); return PKGMGR_R_EINVAL; } - rpc_port::PkgSignal::ExtraData* event_info = - reinterpret_cast(handle); - *error_code = event_info->GetErrCode(); - + *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) { - if (!handle || !path) { + pkgmgr_res_event_info_t *info = static_cast(handle); + res_event_path_state_t *path_state; + + if (info == NULL || path == NULL) { _E("invalid parameter"); return PKGMGR_R_EINVAL; } - rpc_port::PkgSignal::ExtraData* event_info = - reinterpret_cast(handle); + path_state = static_cast(calloc(1, sizeof(res_event_path_state_t))); + if (path_state == NULL) { + _E("out of memory"); + return PKGMGR_R_ENOMEM; + } - auto paths = event_info->GetPaths(); - paths.emplace_back(path, state); - event_info->SetPaths(std::move(paths)); + path_state->path = strdup(path); + if (path_state->path == NULL) { + _E("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) { - if (!handle || !callback) { + pkgmgr_res_event_info_t *info = static_cast(handle); + GList *list; + res_event_path_state_t *path_state; + + if (info == NULL) { _E("invalid parameter"); return PKGMGR_R_EINVAL; } - rpc_port::PkgSignal::ExtraData* event_info = - reinterpret_cast(handle); - - for (const auto& p : event_info->GetPaths()) { - if (callback(p.GetPath().c_str(), - static_cast(p.GetState()), user_data) < 0) + 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; } diff --git a/client/src/connector.cc b/client/src/connector.cc index a7a950f..eb8ffae 100644 --- a/client/src/connector.cc +++ b/client/src/connector.cc @@ -199,12 +199,12 @@ bool Connector::ConnectForDelayedResult() { return true; } -const std::unique_ptr& Connector::GetSignalReceiver() { - if (!signal_receiver_) - signal_receiver_.reset(new SignalReceiver(__is_system_type(pc_type_))); - - return signal_receiver_; -} +//const std::unique_ptr& Connector::GetSignalReceiver() { +// if (!signal_receiver_) +// signal_receiver_.reset(new SignalReceiver(__is_system_type(pc_type_))); +// +// return signal_receiver_; +//} pkgmgr_client_type Connector::GetPcType() const { return pc_type_; @@ -230,6 +230,10 @@ bool Connector::GetTepMove() { return tep_move_; } +pkgmgr_client_t* Connector::GetRawPc() { + return raw_pc_; +} + bool Connector::Activator::Connect() { if (!Create()) return false; diff --git a/client/src/connector.hh b/client/src/connector.hh index aa359a4..29236b3 100644 --- a/client/src/connector.hh +++ b/client/src/connector.hh @@ -24,10 +24,12 @@ #include #include +#include "package-manager.h" #include "PkgMgrProxy.h" +#include "pkgmgr_client_internal.h" #include "connection_event_listener.hh" -#include "signal_receiver.hh" +//#include "signal_receiver.hh" namespace pkgmgr { namespace client { @@ -37,14 +39,14 @@ namespace pp = rpc_port::PkgMgrProxy; class Connector { public: - Connector(pkgmgr_client_type pc_type) : pc_type_(pc_type) {} + Connector(pkgmgr_client_type pc_type, pkgmgr_client_t* raw_pc = nullptr) : pc_type_(pc_type), raw_pc_(raw_pc) {} virtual ~Connector(); virtual pkg_proxy::PkgMgrAdmin* GetAdminProxy(); virtual pkg_proxy::PkgMgr* GetInfoProxy(); virtual pkg_proxy::PkgMgrForClearCache* GetCacheProxy(); virtual pkg_proxy::DelayedResult* GetDelayedResultProxy(); - virtual const std::unique_ptr& GetSignalReceiver(); +// virtual const std::unique_ptr& GetSignalReceiver(); std::string GenerateRequestId() const; void SetTep(std::string tep_path, bool tep_move); void SetTepArgs(); @@ -57,6 +59,7 @@ class Connector { std::vector& GetResCopyPath(); const std::string& GetTepPath(); bool GetTepMove(); + pkgmgr_client_t* GetRawPc(); private: bool ConnectForAdmin(); @@ -90,11 +93,12 @@ class Connector { ConnectionEventListener conn_info_listener_; ConnectionEventListener conn_cache_listener_; ConnectionEventListener conn_delayed_result_listener_; - std::unique_ptr signal_receiver_; +// std::unique_ptr signal_receiver_; std::vector res_remove_path_; std::vector res_create_dir_; std::vector res_copy_path_; std::string tep_path_; + pkgmgr_client_t *raw_pc_; bool tep_move_ = false; Activator activator_; }; diff --git a/client/src/pkgmgr_client_connection.c b/client/src/pkgmgr_client_connection.c new file mode 100644 index 0000000..5703d77 --- /dev/null +++ b/client/src/pkgmgr_client_connection.c @@ -0,0 +1,466 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include +#include + +#include "package-manager.h" +#include "pkgmgr_client_debug.h" +#include "pkgmgr_client_internal.h" +#include "../../installer/src/pkgmgr_installer.h" +#include "../../installer/pkgmgr_installer_config.h" + +#define CONNECTION_RETRY_MAX 5 +#define CONNECTION_WAIT_USEC (1000000 / 2) /* 0.5 sec */ +#define CONNECTION_TIMEOUT_MSEC 5000 /* 5 sec */ +#define REGULAR_USER 5000 + +static int _is_system_user(void) +{ + uid_t uid = getuid(); + + if (uid < REGULAR_USER) + return 1; + else + return 0; +} + +static GBusType __get_bus_type(pkgmgr_client_type type) +{ + if (type == PC_REQUEST || _is_system_user()) + return G_BUS_TYPE_SYSTEM; + else + return G_BUS_TYPE_SESSION; +} + +int pkgmgr_client_connection_connect(struct pkgmgr_client_t *pc) +{ + GError *error = NULL; + GBusType bus_type; + +#if !GLIB_CHECK_VERSION(2, 35, 0) + g_type_init(); +#endif + bus_type = __get_bus_type(pc->pc_type); + pc->conn = g_bus_get_sync(bus_type, NULL, &error); + if (error) { + ERR("gdbus connection error (%s)", error->message); + g_error_free(error); + return PKGMGR_R_ECOMM; + } + + return PKGMGR_R_OK; +} + +void pkgmgr_client_connection_disconnect(struct pkgmgr_client_t *pc) +{ + /* flush remaining buffer: blocking mode */ + g_dbus_connection_flush_sync(pc->conn, NULL, NULL); + g_object_unref(pc->conn); + pc->conn = NULL; +} + +struct signal_map { + const char *signal_str; + int signal_type; +}; + +struct signal_map map[] = { + {PKGMGR_INSTALLER_INSTALL_EVENT_STR, PKGMGR_CLIENT_STATUS_INSTALL}, + {PKGMGR_INSTALLER_UNINSTALL_EVENT_STR, PKGMGR_CLIENT_STATUS_UNINSTALL}, + {PKGMGR_INSTALLER_UPGRADE_EVENT_STR, PKGMGR_CLIENT_STATUS_UPGRADE}, + {PKGMGR_INSTALLER_CLEAR_EVENT_STR, PKGMGR_CLIENT_STATUS_CLEAR_DATA}, + {PKGMGR_INSTALLER_MOVE_EVENT_STR, PKGMGR_CLIENT_STATUS_MOVE}, + {PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR, + PKGMGR_CLIENT_STATUS_INSTALL_PROGRESS}, + {PKGMGR_INSTALLER_GET_SIZE_KEY_STR, PKGMGR_CLIENT_STATUS_GET_SIZE}, + {PKGMGR_INSTALLER_CLEAR_CACHE_KEY_STR, + PKGMGR_CLIENT_STATUS_CLEAR_CACHE}, + {PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR, + PKGMGR_CLIENT_STATUS_ENABLE_APP}, + {PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR, + PKGMGR_CLIENT_STATUS_DISABLE_APP}, + {PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR, + PKGMGR_CLIENT_STATUS_ENABLE_APP_SPLASH_SCREEN}, + {PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR, + PKGMGR_CLIENT_STATUS_DISABLE_APP_SPLASH_SCREEN}, + {PKGMGR_INSTALLER_RES_COPY_EVENT_STR, PKGMGR_CLIENT_STATUS_RES_COPY}, + {PKGMGR_INSTALLER_RES_CREATE_DIR_EVENT_STR, + PKGMGR_CLIENT_STATUS_RES_CREATE_DIR}, + {PKGMGR_INSTALLER_RES_REMOVE_EVENT_STR, + PKGMGR_CLIENT_STATUS_RES_REMOVE}, + {PKGMGR_INSTALLER_RES_UNINSTALL_EVENT_STR, + PKGMGR_CLIENT_STATUS_RES_UNINSTALL}, + {NULL, -1} +}; + +static int __get_signal_type(const char *name) +{ + int i; + + if (name == NULL) + return -1; + + for (i = 0; map[i].signal_str != NULL; i++) { + if (strcmp(map[i].signal_str, name) == 0) + return map[i].signal_type; + } + + return -1; +} + +static void __handle_size_info_callback(struct cb_info *cb_info, + const char *pkgid, const char *val) +{ + pkg_size_info_t size_info; + char buf[BUFMAX]; + char *saveptr; + char *token; + pkgmgr_total_pkg_size_info_receive_cb callback; + + snprintf(buf, sizeof(buf), "%s", val); + + DBG("%s, %s", pkgid, val); + + token = strtok_r(buf, ":", &saveptr); + if (token == NULL) { + ERR("failed to parse size info"); + return; + } + size_info.data_size = atoll(token); + token = strtok_r(NULL, ":", &saveptr); + if (token == NULL) { + ERR("failed to parse size info"); + return; + } + size_info.cache_size = atoll(token); + token = strtok_r(NULL, ":", &saveptr); + if (token == NULL) { + ERR("failed to parse size info"); + return; + } + size_info.app_size = atoll(token); + token = strtok_r(NULL, ":", &saveptr); + if (token == NULL) { + ERR("failed to parse size info"); + return; + } + size_info.ext_data_size = atoll(token); + token = strtok_r(NULL, ":", &saveptr); + if (token == NULL) { + ERR("failed to parse size info"); + return; + } + size_info.ext_cache_size = atoll(token); + token = strtok_r(NULL, ":", &saveptr); + if (token == NULL) { + ERR("failed to parse size info"); + return; + } + size_info.ext_app_size = atoll(token); + + DBG("data: %lld, cache: %lld, app: %lld, ext_data: %lld, " + "ext_cache: %lld, ext_app: %lld", + size_info.data_size, size_info.cache_size, + size_info.app_size, size_info.ext_data_size, + size_info.ext_cache_size, size_info.ext_app_size); + + if (strcmp(pkgid, PKG_SIZE_INFO_TOTAL) == 0) { + callback = (pkgmgr_total_pkg_size_info_receive_cb) + cb_info->size_info_cb; + callback(cb_info->client, &size_info, cb_info->data); + } else { + cb_info->size_info_cb(cb_info->client, pkgid, &size_info, + cb_info->data); + } +} + +static void __handle_pkg_signal(const gchar *signal_name, + GVariant *parameters, gpointer user_data) +{ + uid_t target_uid; + char *req_id; + char *pkg_type = NULL; + char *appid = NULL; + char *pkgid = NULL; + char *key = NULL; + char *val = NULL; + struct cb_info *cb_info = (struct cb_info *)user_data; + GVariantIter *iter = NULL; + int signal_type; + + g_variant_get(parameters, "(u&sa(sss)&s&s)", &target_uid, &req_id, &iter, + &key, &val); + while (g_variant_iter_loop(iter, "(&s&s&s)", &pkgid, &appid, &pkg_type)) { + if (cb_info->req_key) { + if (strcmp(cb_info->req_key, req_id) != 0) + continue; + } else { + signal_type = __get_signal_type(signal_name); + if (signal_type < 0 || !(cb_info->status_type & signal_type)) { + g_variant_iter_free(iter); + return; + } + } + + /* each cb_data can only has one callback */ + if (cb_info->event_cb) { + cb_info->event_cb(target_uid, cb_info->req_id, + pkg_type, pkgid, key, val, NULL, cb_info->data); + } else if (cb_info->app_event_cb && strcmp(appid, "") != 0) { + cb_info->app_event_cb(target_uid, cb_info->req_id, + pkg_type, pkgid, appid, key, val, NULL, + cb_info->data); + } else if (cb_info->size_info_cb) { + __handle_size_info_callback(cb_info, pkgid, val); + } + + /* TODO: unsubscribe request callback */ + } + g_variant_iter_free(iter); +} + +static void __handle_res_event_signal(const gchar *signal_name, + GVariant *parameters, gpointer user_data) +{ + uid_t target_uid; + char *req_id; + char *pkgid = NULL; + char *status = NULL; + char *path = NULL; + pkgmgr_res_event_path_state state; + struct cb_info *cb_info = (struct cb_info *)user_data; + int signal_type; + GVariant *extra_param = NULL; + pkgmgr_res_event_info_t *event_info; + GVariantIter *iter; + + if (!cb_info->res_event_cb) + return; + + g_variant_get(parameters, "(u&s&s&sv)", &target_uid, &req_id, &pkgid, &status, &extra_param); + if (!g_variant_type_equal(G_VARIANT_TYPE("(ia(si))"), + g_variant_get_type(extra_param))) { + ERR("invalid extra parameter"); + g_variant_unref(extra_param); + return; + } + if (cb_info->req_key) { + if (strcmp(cb_info->req_key, req_id) != 0) { + g_variant_unref(extra_param); + return; + } + } else { + signal_type = __get_signal_type(signal_name); + if (signal_type < 0 || !(cb_info->status_type & signal_type)) { + g_variant_unref(extra_param); + return; + } + } + + event_info = pkgmgr_res_event_info_new(); + if (event_info == NULL) { + ERR("out of memory"); + g_variant_unref(extra_param); + return; + } + + g_variant_get(extra_param, "(ia(si))", &event_info->error_code, &iter); + + while (g_variant_iter_loop(iter, "(&si)", &path, &state)) { + if (pkgmgr_res_event_info_add_path_state(event_info, + path, state) != PKGMGR_R_OK) { + ERR("Fail to add path state"); + g_variant_unref(extra_param); + g_variant_iter_free(iter); + pkgmgr_res_event_info_free(event_info); + return; + } + } + cb_info->res_event_cb(target_uid, cb_info->req_id, pkgid, signal_name, + status, event_info, cb_info->data); + g_variant_unref(extra_param); + g_variant_iter_free(iter); + pkgmgr_res_event_info_free(event_info); +} + +static void __handle_pkg_upgrade_event_signal(const gchar *signal_name, + GVariant *parameters, gpointer user_data) +{ + guint32 progress; + struct cb_info *cb_info = (struct cb_info *)user_data; + + if (!cb_info->upgrade_event_cb) + return; + + if (strcmp(signal_name, PKGMGR_INSTALLER_PKG_UPGRADE_EVENT_STR) != 0) { + return; + } + + g_variant_get(parameters, "(u)", &progress); + cb_info->upgrade_event_cb(progress, cb_info->data); +} + +static void __signal_handler(GDBusConnection *conn, const gchar *sender_name, + const gchar *object_path, const gchar *interface_name, + const gchar *signal_name, GVariant *parameters, + gpointer user_data) +{ + if (g_variant_type_equal(G_VARIANT_TYPE("(usa(sss)ss)"), + g_variant_get_type(parameters))) { + __handle_pkg_signal(signal_name, parameters, user_data); + } else if (!strcmp(signal_name, PKGMGR_INSTALLER_RES_COPY_EVENT_STR) || + !strcmp(signal_name, PKGMGR_INSTALLER_RES_REMOVE_EVENT_STR) || + !strcmp(signal_name, PKGMGR_INSTALLER_RES_UNINSTALL_EVENT_STR) || + !strcmp(signal_name, PKGMGR_INSTALLER_RES_CREATE_DIR_EVENT_STR)) { + __handle_res_event_signal(signal_name, parameters, user_data); + } else if (!strcmp(signal_name, PKGMGR_INSTALLER_PKG_UPGRADE_EVENT_STR)) { + __handle_pkg_upgrade_event_signal(signal_name, parameters, user_data); + } +} + +static void __set_signal_list(int event, GList **signal_list) +{ + int i; + if (event == PKGMGR_CLIENT_STATUS_ALL) + return; + + for (i = 0; map[i].signal_str != NULL; i++) { + if (event & map[i].signal_type) + *signal_list = g_list_append(*signal_list, + (char *)map[i].signal_str); + } +} + +static int __subscribe_signal(struct pkgmgr_client_t *pc, + struct cb_info *cb_info, const char *signal) +{ + guint sid = g_dbus_connection_signal_subscribe(pc->conn, NULL, + PKGMGR_INSTALLER_DBUS_INTERFACE, signal, + PKGMGR_INSTALLER_DBUS_OBJECT_PATH, NULL, + G_DBUS_SIGNAL_FLAGS_NONE, __signal_handler, + (gpointer)cb_info, NULL); + if (!sid) { + ERR("failed to subscribe singal"); + return PKGMGR_R_ERROR; + } + cb_info->sid_list = g_list_append(cb_info->sid_list, + GUINT_TO_POINTER(sid)); + + return PKGMGR_R_OK; +} + +int pkgmgr_client_connection_set_callback(struct pkgmgr_client_t *pc, + struct cb_info *cb_info) +{ + GList *signal_list = NULL; + GList *tmp_list = NULL; + int ret; + char *signal_type; + __set_signal_list(pc->status_type, &signal_list); + + if (g_list_length(signal_list) == 0) + return __subscribe_signal(pc, cb_info, NULL); + + for (tmp_list = signal_list; tmp_list != NULL; + tmp_list = g_list_next(tmp_list)) { + signal_type = (char *)tmp_list->data; + ret = __subscribe_signal(pc, cb_info, signal_type); + if (ret != 0) { + g_list_free(signal_list); + return PKGMGR_R_ERROR; + } + } + + g_list_free(signal_list); + return PKGMGR_R_OK; +} + +void pkgmgr_client_connection_unset_callback(struct pkgmgr_client_t *pc, + struct cb_info *cb_info) +{ + GList *tmp = NULL; + guint tmp_sid; + for (tmp = cb_info->sid_list; tmp != NULL; tmp = g_list_next(tmp)) { + tmp_sid = GPOINTER_TO_UINT(tmp->data); + g_dbus_connection_signal_unsubscribe(pc->conn, tmp_sid); + } +} + +int pkgmgr_client_connection_send_request(struct pkgmgr_client_t *pc, + const char *method, GVariant *params, GVariant **result) +{ + GError *error = NULL; + GDBusProxy *proxy; + GVariant *r = NULL; + int retry_cnt = 0; + int ret = PKGMGR_R_ECOMM; + + /* convert floating ref into normal ref */ + g_variant_ref_sink(params); + + do { + proxy = g_dbus_proxy_new_sync(pc->conn, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, PKGMGR_DBUS_SERVICE, + PKGMGR_DBUS_OBJECT_PATH, + PKGMGR_DBUS_INTERFACE, NULL, &error); + if (proxy == NULL) { + ERR("failed to get proxy object, sleep and retry[%s]", + error->message); + g_error_free(error); + error = NULL; + usleep(CONNECTION_WAIT_USEC); + retry_cnt++; + continue; + } + + r = g_dbus_proxy_call_sync(proxy, method, params, + G_DBUS_CALL_FLAGS_NONE, + CONNECTION_TIMEOUT_MSEC, NULL, &error); + g_object_unref(proxy); + if (error && error->code == G_DBUS_ERROR_ACCESS_DENIED) { + ERR("failed to send request, privilege denied[%s]", + error->message); + g_error_free(error); + ret = PKGMGR_R_EPRIV; + break; + } + if (r) { + *result = r; + ret = PKGMGR_R_OK; + break; + } + + ERR("failed to send request, sleep and retry[%s]", + error->message); + g_error_free(error); + error = NULL; + usleep(CONNECTION_WAIT_USEC); + retry_cnt++; + } while (retry_cnt <= CONNECTION_RETRY_MAX); + + /* decrease ref count to 0 to free resource */ + g_variant_unref(params); + + return ret; +} diff --git a/client/src/pkgmgr_client_debug.h b/client/src/pkgmgr_client_debug.h new file mode 100644 index 0000000..b81f948 --- /dev/null +++ b/client/src/pkgmgr_client_debug.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: junsuk. oh + * + * 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. + * + */ + +#ifndef __PKGMGR_CLIENT_DEBUG_H__ +#define __PKGMGR_CLIENT_DEBUG_H__ + +#include + +#ifdef LOG_TAG +#undef LOG_TAG +#endif /* LOG_TAG */ +#define LOG_TAG "PKGMGR" + +#ifndef ERR +#define ERR(fmt, args...) LOGE("[%s:%d] "fmt"\n", __func__, __LINE__, ##args) +#endif + +#ifndef DBG +#define DBG(fmt, args...) LOGD("[%s:%d] "fmt"\n", __func__, __LINE__, ##args) +#endif + +#ifndef INFO +#define INFO(fmt, args...) LOGI("[%s:%d] "fmt"\n", __func__, __LINE__, ##args) +#endif + +#define ret_if(expr) \ + do { \ + if (expr) { \ + ERR("(%s) ", #expr); \ + return; \ + } \ + } while (0) + +#define retm_if(expr, fmt, arg...) \ + do { \ + if (expr) { \ + ERR("(%s) "fmt, #expr, ##arg); \ + return; \ + } \ + } while (0) + +#define retv_if(expr, val) \ + do { \ + if (expr) { \ + ERR("(%s) ", #expr); \ + return (val); \ + } \ + } while (0) + +#define retvm_if(expr, val, fmt, arg...) \ + do { \ + if (expr) { \ + ERR("(%s) "fmt, #expr, ##arg); \ + return (val); \ + } \ + } while (0) + +#define trym_if(expr, fmt, arg...) \ + do { \ + if (expr) { \ + ERR("(%s) "fmt, #expr, ##arg); \ + goto catch; \ + } \ + } while (0) + +#define tryvm_if(expr, val, fmt, arg...) \ + do { \ + if (expr) { \ + ERR("(%s) "fmt, #expr, ##arg); \ + val; \ + goto catch; \ + } \ + } while (0) + +#endif /* __PKGMGR_CLIENT_DEBUG_H__ */ diff --git a/client/src/pkgmgr_client_internal.c b/client/src/pkgmgr_client_internal.c new file mode 100644 index 0000000..da4d5a7 --- /dev/null +++ b/client/src/pkgmgr_client_internal.c @@ -0,0 +1,198 @@ +/* + * slp-pkgmgr + * + * Copyright (c) 2000 - 2011 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 "package-manager.h" +#include "pkgmgr_client_debug.h" +#include "pkgmgr_client_internal.h" + +#define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER) + +#define IS_WHITESPACE(CHAR) \ + ((CHAR == ' ' || CHAR == '\t' || CHAR == '\r' || CHAR == '\n') ? \ + true : false) + +void _app_str_trim(char *input) +{ + char *trim_str = input; + + if (input == NULL) + return; + + while (*input != 0) { + if (!IS_WHITESPACE(*input)) { + *trim_str = *input; + trim_str++; + } + input++; + } + + *trim_str = 0; + return; +} + +static pkg_plugin_set *plugin_set_list[24] = { 0, }; + +pkg_plugin_set *_pkg_plugin_load_library(const char *pkg_type, + const char *library_path) +{ + void *library_handle; + int i; + bool (*on_load)(pkg_plugin_set *plugin); + + if (library_path == NULL || pkg_type == NULL) { + ERR("invalid parameter"); + return NULL; + } + + for (i = 0; plugin_set_list[i]; i++) { + if (strcmp(plugin_set_list[i]->pkg_type, pkg_type) == 0) { + DBG("already loaded [%s]", library_path); + return plugin_set_list[i]; + } + } + + if ((library_handle = dlopen(library_path, RTLD_LAZY)) == NULL) { + ERR("dlopen is failed library_path[%s]", library_path); + return NULL; + } + + if ((on_load = dlsym(library_handle, "pkg_plugin_on_load")) == NULL || + dlerror() != NULL) { + ERR("can not find symbol"); + dlclose(library_handle); + return NULL; + } + + plugin_set_list[i] = (pkg_plugin_set *)calloc(1, sizeof(pkg_plugin_set)); + if (plugin_set_list[i] == NULL) { + ERR("malloc of the plugin_set_list element is failed"); + dlclose(library_handle); + return NULL; + } + + if (on_load(plugin_set_list[i]) != 0) { + ERR("pkg_plugin_on_load failed"); + free(plugin_set_list[i]); + dlclose(library_handle); + plugin_set_list[i] = NULL; + return NULL; + } + + plugin_set_list[i]->plugin_handle = library_handle; + snprintf(plugin_set_list[i]->pkg_type, + sizeof(plugin_set_list[i]->pkg_type), "%s", pkg_type); + + DBG("library [%s] is loaded", library_path); + + return plugin_set_list[i]; +} + +int _pkg_plugin_get_library_path(const char *pkg_type, char *library_path) +{ + FILE *fp = NULL; + char buffer[1024] = { 0 }; + + if (pkg_type == NULL || library_path == NULL) { + ERR("invalid argument\n"); + return -1; + } + + fp = fopen(PKG_CONF_PATH, "r"); + if (fp == NULL) { + ERR("no matching backendlib\n"); + return PKGMGR_R_ERROR; + } + + char *path = NULL; + while (fgets(buffer, 1024, fp) != NULL) { + if (buffer[0] == '#') + continue; + + _app_str_trim(buffer); + + if ((path = strstr(buffer, PKG_BACKENDLIB)) != NULL) { + DBG("[%s]\n", buffer); + DBG("[%s]\n", path); + path = path + strlen(PKG_BACKENDLIB); + DBG("[%s]\n", path); + + break; + } + + memset(buffer, 0x00, 1024); + } + + if (fp != NULL) + fclose(fp); + + if (path == NULL) { + ERR("no matching backendlib\n"); + return PKGMGR_R_ERROR; + } + + snprintf(library_path, 1024, "%slib%s.so", path, pkg_type); + + return PKGMGR_R_OK; + +} + +pkg_plugin_set *_package_manager_load_library(const char *pkg_type) +{ + char package_path[1024] = { 0, }; + pkg_plugin_set *plugin_set; + + if (pkg_type == NULL) { + ERR("cannot load library - pkg_type is null"); + return NULL; + } + + if (_pkg_plugin_get_library_path(pkg_type, package_path) != + PKGMGR_R_OK) { + ERR("cannot find path"); + return NULL; + } + + plugin_set = _pkg_plugin_load_library(pkg_type, package_path); + if (plugin_set == NULL) { + ERR("cannot load library"); + return NULL; + } + + return plugin_set; +} diff --git a/client/src/pkgmgr_client_internal.h b/client/src/pkgmgr_client_internal.h new file mode 100644 index 0000000..90ec62f --- /dev/null +++ b/client/src/pkgmgr_client_internal.h @@ -0,0 +1,98 @@ +/* + * slp-pkgmgr + * + * Copyright (c) 2000 - 2011 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. + * + */ + +#ifndef __PKGMGR_CLIENT_INTERNAL_H__ +#define __PKGMGR_CLIENT_INTERNAL_H__ + +#include +#include + +#include +#include + +#include "package-manager-plugin.h" +#include "package-manager.h" + +#define BUFMAX 4096 + +#ifdef __cplusplus +extern "C" { +#endif + +struct cb_info { + int req_id; + char *req_key; + int status_type; + pkgmgr_handler event_cb; + pkgmgr_app_handler app_event_cb; + pkgmgr_pkg_size_info_receive_cb size_info_cb; + pkgmgr_res_handler res_event_cb; + pkgmgr_pkg_upgrade_handler upgrade_event_cb; + void *data; + struct pkgmgr_client_t *client; + GList *sid_list; +}; + +struct pkgmgr_client_t { + pkgmgr_client_type pc_type; + int status_type; + GDBusConnection *conn; + GList *cb_info_list; + GVariantBuilder *res_copy_builder; + GVariantBuilder *res_remove_builder; + GVariantBuilder *res_create_dir_builder; + char *tep_path; + bool tep_move; + bool debug_mode; + bool skip_optimization; +}; + +struct manifest_and_type { + const char *manifest; + const char *type; +}; + +int pkgmgr_client_connection_connect(struct pkgmgr_client_t *pc); +void pkgmgr_client_connection_disconnect(struct pkgmgr_client_t *pc); +int pkgmgr_client_connection_set_callback(struct pkgmgr_client_t *pc, + struct cb_info *cb_info); +void pkgmgr_client_connection_unset_callback(struct pkgmgr_client_t *pc, + struct cb_info *cb_info); +int pkgmgr_client_connection_send_request(struct pkgmgr_client_t *pc, + const char *method, GVariant *params, GVariant **result); + +pkg_plugin_set *_pkg_plugin_load_library(const char *pkg_type, + const char *library_path); + +int _pkg_plugin_get_library_path(const char *pkg_type, char *library_path); + +pkg_plugin_set *_package_manager_load_library(const char *pkg_type); + +#define PKG_BACKENDLIB "backendlib:" +#define PKG_CONF_PATH "/etc/package-manager/pkg_path.conf" + +void _app_str_trim(char *input); + +#ifdef __cplusplus +} +#endif +#endif /* __PKGMGR_CLIENT_INTERNAL_H__ */ diff --git a/installer/CMakeLists.txt b/installer/CMakeLists.txt index 8e3c230..b667763 100644 --- a/installer/CMakeLists.txt +++ b/installer/CMakeLists.txt @@ -50,7 +50,7 @@ INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/pkgmgr_installer_type.h DESTINATIO INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/pkgmgr-installer.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) ## pkgmgr_installer_signal_agent -ADD_EXECUTABLE(pkgmgr-installer-signal-agent pkgmgr_installer_signal_agent.cc) +ADD_EXECUTABLE(pkgmgr-installer-signal-agent pkgmgr_installer_signal_agent.c) SET_TARGET_PROPERTIES(pkgmgr-installer-signal-agent PROPERTIES COMPILE_FLAGS "${AGENT_CFLAGS} -fPIE") TARGET_LINK_LIBRARIES(pkgmgr-installer-signal-agent PRIVATE pkgmgr_installer) TARGET_LINK_LIBRARIES(pkgmgr-installer-signal-agent ${AGENT_DEPS_LDFLAGS} "-pie") diff --git a/installer/pkgmgr_installer_config.h b/installer/pkgmgr_installer_config.h new file mode 100644 index 0000000..320620b --- /dev/null +++ b/installer/pkgmgr_installer_config.h @@ -0,0 +1,33 @@ +/* + * slp-pkgmgr + * + * Copyright (c) 2000 - 2011 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. + * + */ + +#ifndef __PACKAGE_INSTALLER_CONFIG_H__ +#define __PACKAGE_INSTALLER_CONFIG_H__ + +#define PKGMGR_DBUS_SERVICE "org.tizen.pkgmgr" +#define PKGMGR_DBUS_INTERFACE "org.tizen.pkgmgr" +#define PKGMGR_DBUS_OBJECT_PATH "/org/tizen/pkgmgr" + +#define PKGMGR_INSTALLER_DBUS_INTERFACE "org.tizen.pkgmgr.signal" +#define PKGMGR_INSTALLER_DBUS_OBJECT_PATH "/org/tizen/pkgmgr/signal" + +#endif /* __PACKAGE_INSTALLER_CONFIG_H__ */ diff --git a/installer/pkgmgr_installer_signal_agent.c b/installer/pkgmgr_installer_signal_agent.c new file mode 100644 index 0000000..bb82be1 --- /dev/null +++ b/installer/pkgmgr_installer_signal_agent.c @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "pkgmgr_installer_config.h" +#include "src/pkgmgr_installer_type.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "PKGMGR_INSTALLER_SIGNAL_AGENT" + +#define BUFMAX 4096 +#define PWBUFSIZE sysconf(_SC_GETPW_R_SIZE_MAX) +#define APPFW_USERNAME "app_fw" + +static int server_fd = -1; +static GMainLoop *loop; +static guint sid; +static guint tid; +static GDBusConnection *conn; + +static int __create_server_socket(const char *path) +{ + int r; + int fd; + struct sockaddr_un sa; + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) { + LOGE("socket create failed: %d", errno); + return -1; + } + + memset(&sa, 0, sizeof(sa)); + sa.sun_family = AF_UNIX; + snprintf(sa.sun_path, sizeof(sa.sun_path), "%s", path); + + r = unlink(sa.sun_path); + if (r == -1 && errno != ENOENT) { + LOGE("unlink(%s) failed: %d", sa.sun_path, errno); + close(fd); + return -1; + } + + r = bind(fd, (struct sockaddr *)&sa, sizeof(sa)); + if (r == -1) { + LOGE("bind(%s) failed: %d", sa.sun_path, errno); + close(fd); + return -1; + } + + r = chmod(sa.sun_path, 0660); + if (r == -1) + LOGW("chmod(%s) failed: %d", sa.sun_path, errno); + + r = listen(fd, SOMAXCONN); + if (r == -1) { + LOGE("listen(%s) failed: %d", sa.sun_path, errno); + close(fd); + return -1; + } + + return fd; +} + +static int __get_server_socket(const char *path) +{ + int i; + int n; + int r; + int fd = -1; + + n = sd_listen_fds(0); + if (n < 0) { + LOGE("sd_listen_fds: %d", n); + return -1; + } else if (n == 0) { + return __create_server_socket(path); + } + + for (i = SD_LISTEN_FDS_START; i < SD_LISTEN_FDS_START + n; i++) { + r = sd_is_socket_unix(i, SOCK_STREAM, -1, path, 0); + if (r > 0) { + fd = i; + break; + } + } + + if (fd == -1) { + LOGE("socket is not passed, create server socket"); + return __create_server_socket(path); + } + + return fd; +} + +static void __emit_signal(const char *name, GVariant *gv) +{ + GError *err = NULL; + + if (g_dbus_connection_emit_signal(conn, NULL, + PKGMGR_INSTALLER_DBUS_OBJECT_PATH, + PKGMGR_INSTALLER_DBUS_INTERFACE, + name, gv, &err) != TRUE) { + LOGE("g_dbus_connection_emit_signal failed: %s", err->message); + g_error_free(err); + } +} + +static gboolean __quit(gpointer user_data) +{ + g_main_loop_quit(loop); + return FALSE; +} + +static int __check_authority(int fd) +{ + int r; + struct ucred cr; + socklen_t len; + struct passwd pwd; + struct passwd *pwd_r; + char buf[PWBUFSIZE]; + + len = sizeof(struct ucred); + r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &len); + if (r != 0) { + LOGE("getsockopt failed: %d", errno); + return -1; + } + + /* allow root user */ + if (cr.uid == 0) + return 0; + + r = getpwuid_r(cr.uid, &pwd, buf, sizeof(buf), &pwd_r); + if (r != 0 || pwd_r == NULL) { + LOGE("getpwuid failed: %d", r); + return -1; + } + + /* only app_fw user can send signal to agent */ + if (strcmp(pwd_r->pw_name, APPFW_USERNAME) != 0) { + LOGE("unauthorized client"); + return -1; + } + + return 0; +} + +/** + * packet format: + * +----------------+-------------+-----------+-------------------+ + * |signal name size|GVariant size|signal name|serialized GVariant| + * +----------------+-------------+-----------+-------------------+ + */ +static gboolean __handle_signal(gint fd, GIOCondition cond, gpointer user_data) +{ + int r; + unsigned char buf[BUFMAX]; + int clifd; + struct sockaddr_un sa; + socklen_t s = sizeof(sa); + size_t type_len; + char *type_name; + gsize data_len; + gpointer data; + GVariant *gv; + + clifd = accept(fd, (struct sockaddr *)&sa, &s); + if (clifd == -1) { + LOGE("accept failed: %d", errno); + return FALSE; + } + + if (__check_authority(clifd)) { + close(clifd); + return TRUE; + } + + r = recv(clifd, buf, sizeof(size_t) + sizeof(gsize), 0); + if (r < 0) { + LOGE("recv failed: %d", errno); + close(clifd); + return FALSE; + } else if (r == 0) { + LOGE("client fd already closed"); + close(clifd); + return FALSE; + } + + memcpy(&type_len, buf, sizeof(size_t)); + memcpy(&data_len, buf + sizeof(size_t), sizeof(gsize)); + + if (type_len > BUFMAX || data_len > BUFMAX || + (type_len + data_len) > BUFMAX) { + LOGE("received size is too large: %zu %zu", type_len, data_len); + close(clifd); + return FALSE; + } + + r = recv(clifd, buf, type_len + data_len, 0); + if (r < 0) { + LOGE("recv failed: %d", errno); + close(clifd); + return FALSE; + } else if (r == 0) { + LOGE("client fd already closed"); + close(clifd); + return FALSE; + } + + if (type_len == 0) { + LOGE("invalid type_len"); + close(clifd); + return FALSE; + } + + /* get signal name (including terminating null byte) */ + type_name = malloc(type_len); + memcpy(type_name, buf, type_len); + + /* get data */ + data = malloc(data_len); + memcpy(data, buf + type_len, data_len); + + /* floating type GVariant instance */ + if (!strcmp(type_name, PKGMGR_INSTALLER_RES_COPY_EVENT_STR) || + !strcmp(type_name, PKGMGR_INSTALLER_RES_CREATE_DIR_EVENT_STR) || + !strcmp(type_name, PKGMGR_INSTALLER_RES_REMOVE_EVENT_STR) || + !strcmp(type_name, PKGMGR_INSTALLER_RES_UNINSTALL_EVENT_STR)) { + gv = g_variant_new_from_data(G_VARIANT_TYPE("(usssv)"), + data, data_len, TRUE, NULL, NULL); + } else { + gv = g_variant_new_from_data(G_VARIANT_TYPE("(usa(sss)ss)"), + data, data_len, TRUE, NULL, NULL); + } + __emit_signal(type_name, gv); + + free(data); + free(type_name); + close(clifd); + + /* renew timeout */ + g_source_remove(tid); + tid = g_timeout_add_seconds(10, __quit, NULL); + + return TRUE; +} + +static int __init(void) +{ + char path[PATH_MAX]; + GError *err = NULL; + + snprintf(path, sizeof(path), "/run/pkgmgr/agent/%d", getuid()); + server_fd = __get_server_socket(path); + if (server_fd < 0) { + LOGE("server init failed"); + return -1; + } + + conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &err); + if (conn == NULL) { + LOGE("g_bus_get_sync failed: %s", err->message); + g_error_free(err); + close(server_fd); + return -1; + } + + loop = g_main_loop_new(NULL, FALSE); + sid = g_unix_fd_add(server_fd, G_IO_IN, __handle_signal, NULL); + tid = g_timeout_add_seconds(10, __quit, NULL); + + return 0; +} + +static void __fini(void) +{ + if (sid > 0) + g_source_remove(sid); + if (loop) + g_main_loop_unref(loop); + if (conn) + g_object_unref(conn); + if (server_fd > 0) + close(server_fd); +} + +int main(int argc, char *argv[]) +{ + int r; + + r = __init(); + if (r < 0) + return -1; + + g_main_loop_run(loop); + + __fini(); + + return 0; +} diff --git a/installer/pkgmgr_installer_signal_agent.cc b/installer/pkgmgr_installer_signal_agent.cc deleted file mode 100644 index be1d656..0000000 --- a/installer/pkgmgr_installer_signal_agent.cc +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include "src/pkgmgr_installer_type.h" -#include "src/PkgSignal.h" - -#ifdef LOG_TAG -#undef LOG_TAG -#endif -#define LOG_TAG "PKGMGR_INSTALLER_SIGNAL_AGENT" - -#define BUFMAX 4096 -#define PWBUFSIZE sysconf(_SC_GETPW_R_SIZE_MAX) -#define APPFW_USERNAME "app_fw" -#define AGENT_APPID "signal_agent" - -namespace pkg_group = rpc_port::PkgSignal::group; -namespace pkg_signal = rpc_port::PkgSignal; - -static int server_fd = -1; -static GMainLoop* loop; -static guint sid; -static guint tid; -static std::unique_ptr signal_sender; - -static int __create_server_socket(const char* path) { - int r; - int fd; - struct sockaddr_un sa; - - fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd == -1) { - LOGE("socket create failed: %d", errno); - return -1; - } - - memset(&sa, 0, sizeof(sa)); - sa.sun_family = AF_UNIX; - snprintf(sa.sun_path, sizeof(sa.sun_path), "%s", path); - - r = unlink(sa.sun_path); - if (r == -1 && errno != ENOENT) { - LOGE("unlink(%s) failed: %d", sa.sun_path, errno); - close(fd); - return -1; - } - - r = bind(fd, (struct sockaddr*)&sa, sizeof(sa)); - if (r == -1) { - LOGE("bind(%s) failed: %d", sa.sun_path, errno); - close(fd); - return -1; - } - - r = chmod(sa.sun_path, 0660); - if (r == -1) - LOGW("chmod(%s) failed: %d", sa.sun_path, errno); - - r = listen(fd, SOMAXCONN); - if (r == -1) { - LOGE("listen(%s) failed: %d", sa.sun_path, errno); - close(fd); - return -1; - } - - return fd; -} - -static int __get_server_socket(const char* path) { - int i; - int n; - int r; - int fd = -1; - - n = sd_listen_fds(0); - if (n < 0) { - LOGE("sd_listen_fds: %d", n); - return -1; - } else if (n == 0) { - return __create_server_socket(path); - } - - for (i = SD_LISTEN_FDS_START; i < SD_LISTEN_FDS_START + n; i++) { - r = sd_is_socket_unix(i, SOCK_STREAM, -1, path, 0); - if (r > 0) { - fd = i; - break; - } - } - - if (fd == -1) { - LOGE("socket is not passed, create server socket"); - return __create_server_socket(path); - } - - return fd; -} - -static void __emit_signal_for_res_event(const char* signal, GVariant* gv) { - uid_t target_uid; - char* req_id; - char* pkgid = NULL; - char* status = NULL; - char* path = NULL; - int state; - int signal_type; - int error_code; - GVariant* extra_param = NULL; - GVariantIter* iter; - - g_variant_get(gv, "(u&s&s&sv)", &target_uid, &req_id, &pkgid, &status, &extra_param); - if (!g_variant_type_equal(G_VARIANT_TYPE("(ia(si))"), - g_variant_get_type(extra_param))) { - LOGE("invalid extra parameter"); - g_variant_unref(extra_param); - return; - } - - std::vector path_info; - - g_variant_get(extra_param, "(ia(si))", &error_code, &iter); - while (g_variant_iter_loop(iter, "(&si)", &path, &state)) - path_info.emplace_back(path, state); - - signal_sender->AsyncResultForResource(signal, target_uid, req_id, pkgid, status, - pkg_signal::ExtraData(error_code, std::move(path_info))); - g_variant_unref(extra_param); - g_variant_iter_free(iter); -} - -static void __emit_signal_for_pkg_event(GVariant* gv) { - uid_t target_uid; - char* req_id; - char* pkg_type = NULL; - char* appid = NULL; - char* pkgid = NULL; - char* key = NULL; - char* val = NULL; - GVariantIter* iter = NULL; - int signal_type; - - g_variant_get(gv, "(u&sa(sss)&s&s)", &target_uid, &req_id, &iter, - &key, &val); - std::vector pkgs; - while (g_variant_iter_loop(iter, "(&s&s&s)", &pkgid, &appid, &pkg_type)) - pkgs.emplace_back(pkg_signal::PkgInfo(pkgid, appid, pkg_type)); - signal_sender->AsyncResult("", target_uid, req_id, std::move(pkgs), key, val); - g_variant_iter_free(iter); -} - -static gboolean __quit(gpointer user_data) { - g_main_loop_quit(loop); - return FALSE; -} - -static int __check_authority(int fd) { - int r; - struct ucred cr; - socklen_t len; - struct passwd pwd; - struct passwd* pwd_r; - char buf[PWBUFSIZE]; - - len = sizeof(struct ucred); - r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &len); - if (r != 0) { - LOGE("getsockopt failed: %d", errno); - return -1; - } - - /* allow root user */ - if (cr.uid == 0) - return 0; - - r = getpwuid_r(cr.uid, &pwd, buf, sizeof(buf), &pwd_r); - if (r != 0 || pwd_r == NULL) { - LOGE("getpwuid failed: %d", r); - return -1; - } - - /* only app_fw user can send signal to agent */ - if (strcmp(pwd_r->pw_name, APPFW_USERNAME) != 0) { - LOGE("unauthorized client"); - return -1; - } - - return 0; -} - -/** - * packet format: - * +----------------+-------------+-----------+-------------------+ - * |signal name size|GVariant size|signal name|serialized GVariant| - * +----------------+-------------+-----------+-------------------+ - */ -static gboolean __handle_signal(gint fd, - GIOCondition cond, gpointer user_data) { - int r; - unsigned char buf[BUFMAX]; - int clifd; - struct sockaddr_un sa; - socklen_t s = sizeof(sa); - size_t type_len; - char* type_name; - gsize data_len; - gpointer data; - GVariant* gv; - - clifd = accept(fd, (struct sockaddr*)&sa, &s); - if (clifd == -1) { - LOGE("accept failed: %d", errno); - return FALSE; - } - - if (__check_authority(clifd)) { - close(clifd); - return TRUE; - } - - r = recv(clifd, buf, sizeof(size_t) + sizeof(gsize), 0); - if (r < 0) { - LOGE("recv failed: %d", errno); - close(clifd); - return FALSE; - } else if (r == 0) { - LOGE("client fd already closed"); - close(clifd); - return FALSE; - } - - memcpy(&type_len, buf, sizeof(size_t)); - memcpy(&data_len, buf + sizeof(size_t), sizeof(gsize)); - - if (type_len > BUFMAX || data_len > BUFMAX || - (type_len + data_len) > BUFMAX) { - LOGE("received size is too large: %zu %zu", type_len, data_len); - close(clifd); - return FALSE; - } - - r = recv(clifd, buf, type_len + data_len, 0); - if (r < 0) { - LOGE("recv failed: %d", errno); - close(clifd); - return FALSE; - } else if (r == 0) { - LOGE("client fd already closed"); - close(clifd); - return FALSE; - } - - if (type_len == 0) { - LOGE("invalid type_len"); - close(clifd); - return FALSE; - } - - /* get signal name (including terminating null byte) */ - type_name = static_cast(malloc(type_len)); - memcpy(type_name, buf, type_len); - - /* get data */ - data = malloc(data_len); - memcpy(data, buf + type_len, data_len); - - /* floating type GVariant instance */ - if (!strcmp(type_name, PKGMGR_INSTALLER_RES_COPY_EVENT_STR) || - !strcmp(type_name, PKGMGR_INSTALLER_RES_CREATE_DIR_EVENT_STR) || - !strcmp(type_name, PKGMGR_INSTALLER_RES_REMOVE_EVENT_STR) || - !strcmp(type_name, PKGMGR_INSTALLER_RES_UNINSTALL_EVENT_STR)) { - gv = g_variant_new_from_data(G_VARIANT_TYPE("(usssv)"), - data, data_len, TRUE, NULL, NULL); - __emit_signal_for_res_event(type_name, gv); - } else { - gv = g_variant_new_from_data(G_VARIANT_TYPE("(usa(sss)ss)"), - data, data_len, TRUE, NULL, NULL); - __emit_signal_for_pkg_event(gv); - } - g_variant_unref(gv); - - free(data); - free(type_name); - close(clifd); - - /* renew timeout */ - g_source_remove(tid); - tid = g_timeout_add_seconds(10, __quit, NULL); - - return TRUE; -} - -static int __init(void) { - char path[PATH_MAX]; - GError* err = NULL; - - snprintf(path, sizeof(path), "/run/pkgmgr/agent/%d", getuid()); - server_fd = __get_server_socket(path); - if (server_fd < 0) { - LOGE("server init failed"); - return -1; - } - - if (aul_proc_register(AGENT_APPID, NULL) != AUL_R_OK) { - LOGE("aul_proc_register fail"); - return -1; - } - - try { - signal_sender = std::make_unique(AGENT_APPID, false); - } catch(...) { - LOGE("Exception occured"); - return -1; - } - - loop = g_main_loop_new(NULL, FALSE); - sid = g_unix_fd_add(server_fd, G_IO_IN, __handle_signal, NULL); - tid = g_timeout_add_seconds(10, __quit, NULL); - - return 0; -} - -static void __fini(void) { - if (sid > 0) - g_source_remove(sid); - if (loop) - g_main_loop_unref(loop); - if (server_fd > 0) - close(server_fd); - aul_proc_deregister(); -} - -int main(int argc, char* argv[]) { - int r; - - r = __init(); - if (r < 0) - return -1; - - g_main_loop_run(loop); - - __fini(); - - return 0; -} diff --git a/installer/src/api_stub.cc b/installer/src/api_stub.cc deleted file mode 100644 index 8925d28..0000000 --- a/installer/src/api_stub.cc +++ /dev/null @@ -1,453 +0,0 @@ -/* -* Copyright (c) 2022 Samsung Electronics Co., Ltd. -* -* 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 "pkgmgr_installer.h" -#include "pkgmgr_installer_debug.h" -#include "pkgmgr_installer_info.h" - -#include -#include - -#include "control.hh" - -#include - -#ifdef API -#undef API -#endif -#define API __attribute__ ((visibility("default"))) - -#define CHK_PI_RET(r) \ - do { if (nullptr == pi) return (r); } while (0) - -static uid_t g_target_uid; - -API pkgmgr_installer* pkgmgr_installer_new() { - try { - return new pkgmgr::installer::Control(); - } catch (...) { - _E("pkgmgr_installer_new fail"); - return nullptr; - } - - return nullptr; -} - -API pkgmgr_installer* pkgmgr_installer_offline_new() { - return new pkgmgr::installer::Control(true); -} - -API int pkgmgr_installer_free(pkgmgr_installer* pi) { - auto* cls = static_cast(pi); - delete cls; - return 0; -} - -API int pkgmgr_installer_receive_request(pkgmgr_installer *pi, - const int argc, char **argv) { - auto* cls = static_cast(pi); - - int ret = cls->SetRequestFromArgv(argc, argv); - if (ret < 0) - return ret; - - /* if target user is not set, set as tizenglobalapp user */ - if (cls->GetRequest()->GetUid() == 0) - cls->GetRequest()->SetUid(tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)); - - g_target_uid = cls->GetRequest()->GetUid(); - - return 0; -} - -API int pkgmgr_installer_get_request_type(pkgmgr_installer *pi) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return PKGMGR_REQ_INVALID; - return cls->GetRequest()->GetRequestType(); -} - -API uid_t pkgmgr_installer_get_uid(pkgmgr_installer *pi) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return PKGMGR_REQ_INVALID; - return cls->GetRequest()->GetUid(); -} - -API const char* pkgmgr_installer_get_request_info(pkgmgr_installer *pi) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return nullptr; - return cls->GetRequest()->GetRequestInfo().c_str(); -} - -API const char* pkgmgr_installer_get_request_info_at(pkgmgr_installer *pi, - int at) { - CHK_PI_RET(nullptr); - auto* cls = static_cast(pi); - auto& rq = cls->GetRequest(); - if (!rq) - return nullptr; - - const auto& requests = rq->GetRequests(); - if (requests.size() <= at) - return nullptr; - - return requests[at].c_str(); -} - -API int pkgmgr_installer_get_request_info_count(pkgmgr_installer *pi) { - CHK_PI_RET(PKGMGR_REQ_INVALID); - auto* cls = static_cast(pi); - auto& rq = cls->GetRequest(); - if (!rq) - return PKGMGR_REQ_INVALID; - - return rq->GetRequests().size(); -} - -API const char *pkgmgr_installer_get_tep_path(pkgmgr_installer *pi) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return nullptr; - return cls->GetRequest()->GetTepPath().c_str(); -} - -API int pkgmgr_installer_get_tep_move_type(pkgmgr_installer *pi) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return PKGMGR_REQ_INVALID; - return cls->GetRequest()->IsTepMove() ? 1 : 0; -} - -API const char* pkgmgr_installer_get_session_id(pkgmgr_installer *pi) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return nullptr; - return cls->GetRequest()->GetSessionId().c_str(); -} - -API const char* pkgmgr_installer_get_license_path(pkgmgr_installer *pi) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return nullptr; - return cls->GetRequest()->GetLicensePath().c_str(); -} - -API const char* pkgmgr_installer_get_optional_data(pkgmgr_installer *pi) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return nullptr; - return cls->GetRequest()->GetOptionalData().c_str(); -} - -API int pkgmgr_installer_is_quiet(pkgmgr_installer *pi) { - return 1; -} - -API int pkgmgr_installer_get_move_type(pkgmgr_installer *pi) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return PKGMGR_REQ_INVALID; - return cls->GetRequest()->GetMoveType(); -} - -API const char *pkgmgr_installer_get_caller_pkgid(pkgmgr_installer *pi) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return nullptr; - return cls->GetRequest()->GetCallerPkgid().c_str(); -} - -API int pkgmgr_installer_get_is_preload(pkgmgr_installer *pi) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return PKGMGR_REQ_INVALID; - return cls->GetRequest()->IsPreload() ? 1 : 0; -} - -API int pkgmgr_installer_get_force_removal(pkgmgr_installer *pi) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return PKGMGR_REQ_INVALID; - return cls->GetRequest()->IsForceRemoval() ? 1 : 0; -} - -API int pkgmgr_installer_get_is_preload_rw(pkgmgr_installer *pi) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return PKGMGR_REQ_INVALID; - return cls->GetRequest()->IsPreloadRw() ? 1 : 0; -} - -API int pkgmgr_installer_get_no_removal(pkgmgr_installer *pi) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return PKGMGR_REQ_INVALID; - return cls->GetRequest()->IsNoRemoval() ? 1 : 0; -} - -API int pkgmgr_installer_get_keep_rwdata(pkgmgr_installer *pi) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return PKGMGR_REQ_INVALID; - return cls->GetRequest()->IsKeepRwData() ? 1 : 0; -} - -API int pkgmgr_installer_get_partial_rw(pkgmgr_installer *pi) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return PKGMGR_REQ_INVALID; - return cls->GetRequest()->IsPartialRw() ? 1 : 0; -} - -API int pkgmgr_installer_get_debug_mode(pkgmgr_installer *pi) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return PKGMGR_REQ_INVALID; - return cls->GetRequest()->IsDebugMode() ? 1 : 0; -} - -API int pkgmgr_installer_get_skip_check_reference(pkgmgr_installer *pi) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return PKGMGR_REQ_INVALID; - return cls->GetRequest()->IsSkipCheckReference() ? 1 : 0; -} - -API int pkgmgr_installer_get_skip_optimization(pkgmgr_installer *pi) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return PKGMGR_REQ_INVALID; - return cls->GetRequest()->IsSkipOptimization() ? 1 : 0; -} - -API int pkgmgr_installer_get_recovery_cleanup(pkgmgr_installer *pi) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return PKGMGR_REQ_INVALID; - return cls->GetRequest()->IsRecoveryCleanup() ? 1 : 0; -} - -API int pkgmgr_installer_send_app_uninstall_signal(pkgmgr_installer *pi, - const char *pkg_type, const char *pkgid, const char *val) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return -1; - return cls->SendSignal(pkg_type, pkgid, "", PKGMGR_INSTALLER_APPID_KEY_STR, val); -} - -API int pkgmgr_installer_send_app_uninstall_signal_for_uid( - pkgmgr_installer *pi, uid_t uid, const char *pkg_type, - const char *pkgid, const char *val) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return -1; - return cls->SendSignalForUid(uid, pkg_type, pkgid, "", PKGMGR_INSTALLER_APPID_KEY_STR, val); -} - -API int pkgmgr_installer_set_uid(pkgmgr_installer *pi, uid_t uid) { - if (pi == NULL) - return -1; - - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return -1; - - cls->GetRequest()->SetUid(uid); - - g_target_uid = uid; - - return 0; -} - -API int pkgmgr_installer_send_app_signal(pkgmgr_installer *pi, - const char *pkg_type, const char *pkgid, const char *appid, - const char *key, const char *val) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return -1; - return cls->SendSignal(pkg_type, pkgid, appid, key, val); -} - -API int pkgmgr_installer_send_signal(pkgmgr_installer *pi, - const char *pkg_type, const char *pkgid, const char *key, - const char *val) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return -1; - return cls->SendSignal(pkg_type, pkgid, "", key, val); -} - -API int pkgmgr_installer_send_app_signal_for_uid(pkgmgr_installer *pi, - uid_t uid, const char *pkg_type, const char *pkgid, - const char *appid, const char *key, const char *val) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return -1; - return cls->SendSignalForUid(uid, pkg_type, pkgid, appid, key, val); -} - -API int pkgmgr_installer_send_signal_for_uid(pkgmgr_installer *pi, - uid_t uid, const char *pkg_type, const char *pkgid, - const char *key, const char *val) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return -1; - return cls->SendSignalForUid(uid, pkg_type, pkgid, "", key, val); -} - -API int pkgmgr_installer_set_request_type(pkgmgr_installer *pi, - int request_type) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return -1; - cls->GetRequest()->SetRequestType(request_type); - return 0; -} - -API int pkgmgr_installer_set_session_id(pkgmgr_installer *pi, - const char *session_id) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return -1; - cls->GetRequest()->SetSessionId(std::string(session_id)); - return 0; -} - -API int pkgmgr_installer_create_certinfo_set_handle( - pkgmgr_instcertinfo_h *handle) { - return pkgmgrinfo_create_certinfo_set_handle(handle); -} - -API int pkgmgr_installer_set_cert_value(pkgmgr_instcertinfo_h handle, - pkgmgr_instcert_type cert_type, char *cert_value) { - return pkgmgrinfo_set_cert_value(handle, static_cast(cert_type), cert_value); -} - -API int pkgmgr_installer_save_certinfo(const char *pkgid, - pkgmgr_instcertinfo_h handle, uid_t uid) { - return pkgmgrinfo_save_certinfo(pkgid, handle, uid); -} - -API int pkgmgr_installer_destroy_certinfo_set_handle( - pkgmgr_instcertinfo_h handle) { - return pkgmgrinfo_destroy_certinfo_set_handle(handle); -} - -API int pkgmgr_installer_delete_certinfo(const char *pkgid) { - return pkgmgrinfo_delete_certinfo(pkgid); -} - -API int pkgmgr_installer_set_privilege_level(pkgmgr_privilege_level level) { - //TODO - return 0; -} - -API int pkgmgr_installer_info_get_target_uid(uid_t *uid) { - *uid = g_target_uid; - - return 0; -} - -API int pkgmgr_installer_info_get_privilege_level( - pkgmgr_privilege_level *level) { - //TODO - return 0; -} - -API int pkgmgr_installer_info_get_debug_mode(int *debug_mode) { - //TODO - return 0; -} - -API int pkgmgr_installer_info_get_skip_optimization(int *skip_optimization) { - //TODO - return 0; -} - -API const char* pkgmgr_installer_error_to_string(int error_code) { - //TODO - return nullptr; -} - -API int pkgmgr_installer_add_pkg(pkgmgr_installer *pi, - const char *pkgid, const char *pkg_type) { - auto* cls = static_cast(pi); - cls->AddPkg(pkgid, pkg_type); - - return 0; -} - -API int pkgmgr_installer_send_signals(pkgmgr_installer *pi, - const char *key, const char *val) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return -1; - return cls->SendSignals(key, val); -} - -API int pkgmgr_installer_send_signals_for_uid(pkgmgr_installer *pi, uid_t uid, - const char *key, const char *val) { - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return -1; - return cls->SendSignalsForUid(uid, key, val); -} - -API int pkgmgr_installer_set_is_upgrade(pkgmgr_installer *pi, int is_upgrade) { - //TODO - return 0; -} - -API int pkgmgr_installer_send_res_signal(pkgmgr_installer *pi, - const char *pkgid, const char *status, - pkgmgr_res_event_info *event_info) { - if (!pi || !pkgid || !status || !event_info) { - _E("invalid argument"); - return -1; - } - - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return -1; - - return cls->SendSignalForResource(pkgid, status, - reinterpret_cast(event_info)); -} - -API int pkgmgr_installer_send_res_signal_for_uid(pkgmgr_installer *pi, - uid_t uid, const char *pkgid, const char *status, - pkgmgr_res_event_info *event_info) { - if (!pi || !pkgid || !status || !event_info) { - _E("invalid argument"); - return -1; - } - - auto* cls = static_cast(pi); - if (!cls->GetRequest()) - return -1; - - return cls->SendSignalForResourceForUid(uid, pkgid, status, - reinterpret_cast(event_info)); -} - -API int pkgmgr_installer_send_pkg_upgrade_signal(pkgmgr_installer *pi, - unsigned int progress) { - //TODO - return 0; -} diff --git a/installer/src/control.cc b/installer/src/control.cc deleted file mode 100644 index 8c0e8f0..0000000 --- a/installer/src/control.cc +++ /dev/null @@ -1,741 +0,0 @@ -/* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. - * - * 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 "control.hh" - -#include -#include -#include -#include -#include - -#include - -#include "pkgmgr_installer.h" -#include "pkgmgr_installer_debug.h" -#include "pkgmgr_installer_type.h" - -namespace { - -constexpr int OPTVAL_PRELOAD = 1000; -constexpr int OPTVAL_FORCE_REMOVAL = 1001; -constexpr int OPTVAL_PRELOAD_RW = 1002; -constexpr int OPTVAL_NO_REMOVAL = 1003; -constexpr int OPTVAL_KEEP_RWDATA = 1004; -constexpr int OPTVAL_PARTIAL_RW = 1005; -constexpr int OPTVAL_MIGRATE_EXTIMG = 1006; -constexpr int OPTVAL_SKIP_CHECK_REFERENCE = 1007; -constexpr int OPTVAL_RECOVER_DB = 1008; -constexpr int OPTVAL_RECOVERY_CLEANUP = 1009; - -constexpr const char short_opts[] = "k:l:i:d:c:m:t:o:r:p:s:b:e:M:y:u:w:D:A:qGS"; -constexpr const struct option long_opts[] = { - { "session-id", 1, nullptr, 'k' }, - { "license-path", 1, nullptr, 'l' }, - { "install", 1, nullptr, 'i' }, - { "uninstall", 1, nullptr, 'd' }, - { "clear", 1, nullptr, 'c' }, - { "move", 1, nullptr, 'm' }, - { "move-type", 1, nullptr, 't' }, - { "optional-data", 0, nullptr, 'o' }, - { "reinstall", 0, nullptr, 'r' }, - { "caller-pkgid", 1, nullptr, 'p' }, - { "tep-path", 1, nullptr, 'e' }, - { "tep-move", 1, nullptr, 'M' }, - { "smack", 1, nullptr, 's' }, - { "manifest-direct-install", 1, nullptr, 'y' }, - { "mount-install", 1, nullptr, 'w' }, - { "recovery", 1, nullptr, 'b' }, - { "debug-mode", 0, nullptr, 'G' }, - { "skip-optimization", 0, nullptr, 'S' }, - { "preload", 0, nullptr, OPTVAL_PRELOAD }, - { "force-remove", 0, nullptr, OPTVAL_FORCE_REMOVAL }, - { "preload-rw", 0, nullptr, OPTVAL_PRELOAD_RW }, - { "no-remove", 0, nullptr, OPTVAL_NO_REMOVAL }, - { "keep-rwdata", 0, nullptr, OPTVAL_KEEP_RWDATA }, - { "partial-rw", 0, nullptr, OPTVAL_PARTIAL_RW }, - { "migrate-extimg", 1, nullptr, OPTVAL_MIGRATE_EXTIMG }, - { "skip-check-reference", 0, nullptr, OPTVAL_SKIP_CHECK_REFERENCE }, - { "recover-db", 1, nullptr, OPTVAL_RECOVER_DB }, - { "recovery-cleanup", 0, nullptr, OPTVAL_RECOVERY_CLEANUP }, - { 0, 0, 0, 0 } -}; - -static const char* __get_signal_name( - const std::unique_ptr& req, - const char* key, const char* pkg_type) { - if (strcmp(key, PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR) == 0) - return key; - else if (strcmp(key, PKGMGR_INSTALLER_GET_SIZE_KEY_STR) == 0) - return key; - else if (strcmp(key, PKGMGR_INSTALLER_APPID_KEY_STR) == 0) - return PKGMGR_INSTALLER_UNINSTALL_EVENT_STR; - else if (strcmp(pkg_type, PKGMGR_INSTALLER_CLEAR_CACHE_KEY_STR) == 0) - return pkg_type; - else if (req->IsUpgrade()) - return PKGMGR_INSTALLER_UPGRADE_EVENT_STR; - - - switch (req->GetRequestType()) { - case PKGMGR_REQ_INSTALL: - case PKGMGR_REQ_MANIFEST_DIRECT_INSTALL: - case PKGMGR_REQ_MOUNT_INSTALL: - case PKGMGR_REQ_REINSTALL: - case PKGMGR_REQ_ENABLE_PKG: - case PKGMGR_REQ_RECOVER: - return PKGMGR_INSTALLER_INSTALL_EVENT_STR; - case PKGMGR_REQ_UNINSTALL: - case PKGMGR_REQ_DISABLE_PKG: - return PKGMGR_INSTALLER_UNINSTALL_EVENT_STR; - case PKGMGR_REQ_UPGRADE: - return PKGMGR_INSTALLER_UPGRADE_EVENT_STR; - case PKGMGR_REQ_MOVE: - return PKGMGR_INSTALLER_MOVE_EVENT_STR; - case PKGMGR_REQ_ENABLE_APP: - return PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR; - case PKGMGR_REQ_DISABLE_APP: - return PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR; - case PKGMGR_REQ_ENABLE_APP_SPLASH_SCREEN: - return PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR; - case PKGMGR_REQ_DISABLE_APP_SPLASH_SCREEN: - return PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR; - case PKGMGR_REQ_CLEAR: - return PKGMGR_INSTALLER_CLEAR_EVENT_STR; - case PKGMGR_REQ_GETSIZE: - return PKGMGR_INSTALLER_GET_SIZE_KEY_STR; - case PKGMGR_REQ_RES_COPY: - return PKGMGR_INSTALLER_RES_COPY_EVENT_STR; - case PKGMGR_REQ_RES_CREATE_DIR: - return PKGMGR_INSTALLER_RES_CREATE_DIR_EVENT_STR; - case PKGMGR_REQ_RES_REMOVE: - return PKGMGR_INSTALLER_RES_REMOVE_EVENT_STR; - case PKGMGR_REQ_RES_UNINSTALL: - return PKGMGR_INSTALLER_RES_UNINSTALL_EVENT_STR; - } - - _E("cannot find type"); - - return NULL; -} - -} - -namespace pkgmgr { -namespace installer { - -Control::Control(bool offline) { - if (!offline) { - signal_.reset(new pkg_group::PkgSignal("", true)); - } - - request_ = std::make_unique(); - - option_map_[OPTVAL_PRELOAD] = [](const std::unique_ptr& req) { - req->is_preload_ = true; - _D("preload request [%d]", req->is_preload_); - return 0; - }; - - option_map_[OPTVAL_FORCE_REMOVAL] = [](const std::unique_ptr& req) { - req->force_removal_ = true; - _D("force-remove request [%d]", req->force_removal_); - return 0; - }; - - option_map_[OPTVAL_PRELOAD_RW] = [](const std::unique_ptr& req) { - req->is_preload_rw_ = true; - _D("preload-rw request [%d]", req->is_preload_rw_); - return 0; - }; - - option_map_[OPTVAL_NO_REMOVAL] = [](const std::unique_ptr& req) { - req->no_removal_ = true; - _D("no-remove request [%d]", req->no_removal_); - return 0; - }; - - option_map_[OPTVAL_KEEP_RWDATA] = [](const std::unique_ptr& req) { - req->keep_rwdata_ = true; - _D("keep-rwdata request [%d]", req->keep_rwdata_); - return 0; - }; - - option_map_[OPTVAL_PARTIAL_RW] = [](const std::unique_ptr& req) { - req->partial_rw_ = true; - _D("partial-rw request [%d]", req->partial_rw_); - return 0; - }; - - option_map_[OPTVAL_MIGRATE_EXTIMG] = [this](const std::unique_ptr& req) { - if (mode_) - return -EINVAL; - mode_ = OPTVAL_MIGRATE_EXTIMG; - req->request_type_ = PKGMGR_REQ_MIGRATE_EXTIMG; - req->pkgmgr_info_ = optarg; - ParseMultiplePkgs(req); - _D("legacy extimg migration requested"); - return 0; - }; - - option_map_[OPTVAL_SKIP_CHECK_REFERENCE] = [](const std::unique_ptr& req) { - req->skip_check_reference_ = true; - return 0; - }; - - option_map_[OPTVAL_RECOVER_DB] = [this](const std::unique_ptr& req) { - req->request_type_ = PKGMGR_REQ_RECOVER_DB; - req->pkgmgr_info_ = optarg; - ParseMultiplePkgs(req); - return 0; - }; - - option_map_[OPTVAL_RECOVERY_CLEANUP] = [](const std::unique_ptr& req) { - req->recovery_cleanup_ = true; - return 0; - }; - - option_map_['k'] = [](const std::unique_ptr& req) { - req->session_id_ = optarg; - return 0; - }; - - option_map_['l'] = [](const std::unique_ptr& req) { - req->license_path_ = optarg; - return 0; - }; - - option_map_['i'] = [this](const std::unique_ptr& req) { - if (mode_) - return -EINVAL; - mode_ = 'i'; - req->request_type_ = PKGMGR_REQ_INSTALL; - req->pkgmgr_info_ = optarg; - ParseMultiplePkgs(req); - _D("option is [i] pkgid[%s]", req->pkgmgr_info_.c_str()); - return 0; - }; - - option_map_['e'] = [](const std::unique_ptr& req) { - req->tep_path_ = optarg; - _D("option is [e] tep_path[%s]", req->tep_path_.c_str()); - return 0; - }; - - option_map_['M'] = [](const std::unique_ptr& req) { - if (strcmp(optarg, "tep_move") == 0) - req->tep_move_ = true; - else - req->tep_move_ = false; - _D("option is [M] tep_move[%d]", req->tep_move_); - return 0; - }; - - option_map_['d'] = [this](const std::unique_ptr& req) { - if (mode_) - return -EINVAL; - mode_ = 'd'; - req->request_type_ = PKGMGR_REQ_UNINSTALL; - req->pkgmgr_info_ = optarg; - ParseMultiplePkgs(req); - return 0; - }; - - option_map_['c'] = [this](const std::unique_ptr& req) { - if (mode_) - return -EINVAL; - mode_ = 'c'; - req->request_type_ = PKGMGR_REQ_CLEAR; - req->pkgmgr_info_ = optarg; - ParseMultiplePkgs(req); - return 0; - }; - - option_map_['m'] = [this](const std::unique_ptr& req) { - if (mode_) - return -EINVAL; - mode_ = 'm'; - req->request_type_ = PKGMGR_REQ_MOVE; - req->pkgmgr_info_ = optarg; - ParseMultiplePkgs(req); - return 0; - }; - - option_map_['r'] = [this](const std::unique_ptr& req) { - if (mode_) - return -EINVAL; - mode_ = 'r'; - req->request_type_ = PKGMGR_REQ_REINSTALL; - req->pkgmgr_info_ = optarg; - ParseMultiplePkgs(req); - return 0; - }; - - option_map_['t'] = [](const std::unique_ptr& req) { - req->move_type_ = atoi(optarg); - return 0; - }; - - option_map_['p'] = [](const std::unique_ptr& req) { - req->caller_pkgid_ = optarg; - return 0; - }; - - option_map_['s'] = [this](const std::unique_ptr& req) { - if (mode_) - return -EINVAL; - mode_ = 's'; - req->request_type_ = PKGMGR_REQ_SMACK; - req->pkgmgr_info_ = optarg; - ParseMultiplePkgs(req); - return 0; - }; - - option_map_['o'] = [](const std::unique_ptr& req) { - req->optional_data_ = optarg; - return 0; - }; - - option_map_['y'] = [this](const std::unique_ptr& req) { - req->request_type_ = PKGMGR_REQ_MANIFEST_DIRECT_INSTALL; - req->pkgmgr_info_ = optarg; - ParseMultiplePkgs(req); - return 0; - }; - - option_map_['w'] = [this](const std::unique_ptr& req) { - req->request_type_ = PKGMGR_REQ_MOUNT_INSTALL; - req->pkgmgr_info_ = optarg; - ParseMultiplePkgs(req); - return 0; - }; - - option_map_['b'] = [this](const std::unique_ptr& req) { - if (mode_) - return -EINVAL; - mode_ = 'b'; - req->request_type_ = PKGMGR_REQ_RECOVER; - req->pkgmgr_info_ = optarg; - ParseMultiplePkgs(req); - return 0; - }; - - option_map_['D'] = [this](const std::unique_ptr& req) { - req->request_type_ = PKGMGR_REQ_DISABLE_PKG; - req->pkgmgr_info_ = optarg; - ParseMultiplePkgs(req); - return 0; - }; - - option_map_['A'] = [this](const std::unique_ptr& req) { - req->request_type_ = PKGMGR_REQ_ENABLE_PKG; - req->pkgmgr_info_ = optarg; - ParseMultiplePkgs(req); - return 0; - }; - - option_map_['u'] = [](const std::unique_ptr& req) { - req->target_uid_ = (uid_t)atoi(optarg); - return 0; - }; - - option_map_['G'] = [](const std::unique_ptr& req) { - req->debug_mode_ = true; - return 0; - }; - - option_map_['S'] = [](const std::unique_ptr& req) { - req->skip_optimization_ = true; - return 0; - }; -} - -Control::~Control() = default; - -void Control::ParseMultiplePkgs(const std::unique_ptr& req) { - while ((optind <= argc_) && (*argv_[optind - 1] != '-')) { - req->pkgs_.push_back(argv_[optind - 1]); - optind++; - } - optind--; -} - -const std::unique_ptr& Control::GetRequest() const { - return request_; -} - -int Control::SendSignal(std::string pkg_type, std::string pkgid, - std::string appid, std::string key, std::string val) { - if (!signal_) { - _E("offline mode"); - return -1; - } - auto& req = GetRequest(); - std::vector pkgs; - pkgs.emplace_back(std::move(pkgid), std::move(appid), std::move(pkg_type)); - signal_->AsyncResult("", req->GetUid(), req->GetSessionId(), std::move(pkgs), - key, val); - return 0; -} - -int Control::SendSignals(std::string key, std::string val) { - if (!signal_) { - _E("offline mode"); - return -1; - } - auto& req = GetRequest(); - signal_->AsyncResult("", req->GetUid(), req->GetSessionId(), pkgs_, key, val); - return 0; -} - -int Control::SendSignalForResource(std::string pkgid, std::string status, - rpc_port::PkgSignal::ExtraData* event_info) { - if (!signal_) { - _E("offline mode"); - return -1; - } - - auto& req = GetRequest(); - const char* signal_name = __get_signal_name(req, "", ""); - if (!signal_name) { - _E("unknown signal type"); - return -1; - } - - signal_->AsyncResultForResource(signal_name, req->GetUid(), - req->GetSessionId(), std::move(pkgid), std::move(status), *event_info); - return 0; -} - -static int __send_signal_to_agent(uid_t uid, void* data, size_t len) { - int fd; - struct sockaddr_un sa; - int r; - - fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0); - if (fd == -1) { - _E("failed to create socket: %d", errno); - return -1; - } - - sa.sun_family = AF_UNIX; - snprintf(sa.sun_path, sizeof(sa.sun_path), "/run/pkgmgr/agent/%d", uid); - - r = connect(fd, (struct sockaddr*)&sa, sizeof(sa)); - if (r == -1) { - _E("failed to connect socket(%s): %d", sa.sun_path, errno); - close(fd); - return -1; - } - - r = send(fd, data, len, MSG_NOSIGNAL); - if (r < 0) { - _E("failed to send data: %d", errno); - close(fd); - return -1; - } - - close(fd); - - return 0; -} - -int Control::SendSignalForUid(uid_t uid, std::string pkg_type, - std::string pkgid, std::string appid, std::string key, std::string val) { - if (!signal_) { - _E("offline mode"); - return -1; - } - - const auto& req = GetRequest(); - const char* sid = req->GetSessionId().c_str(); - - const char* signal_name; - size_t name_size; - GVariantBuilder* builder; - GVariant* gv; - gsize gv_len; - gpointer gv_data; - void* data; - void* ptr; - size_t data_len; - - data_len = sizeof(size_t) + sizeof(gsize); - - signal_name = __get_signal_name(req, key.c_str(), pkg_type.c_str()); - if (!signal_name) { - _E("unknown signal name"); - return -1; - } - - /* including null byte */ - name_size = strlen(signal_name) + 1; - data_len += name_size; - - builder = g_variant_builder_new(G_VARIANT_TYPE("a(sss)")); - g_variant_builder_add(builder, "(sss)", pkgid.c_str(), - appid.c_str(), pkg_type.c_str()); - gv = g_variant_new("(usa(sss)ss)", req->GetUid(), sid, - builder, key.c_str(), val.c_str()); - g_variant_builder_unref(builder); - if (gv == NULL) { - _E("failed to create GVariant instance"); - return -1; - } - gv_len = g_variant_get_size(gv); - gv_data = g_malloc(gv_len); - g_variant_store(gv, gv_data); - g_variant_unref(gv); - data_len += gv_len; - - data = malloc(data_len); - if (data == NULL) { - _E("out of memory"); - g_free(gv_data); - return -1; - } - ptr = data; - memcpy(ptr, &name_size, sizeof(size_t)); - ptr += sizeof(size_t); - memcpy(ptr, &gv_len, sizeof(gsize)); - ptr += sizeof(gsize); - memcpy(ptr, signal_name, name_size); - ptr += name_size; - memcpy(ptr, gv_data, gv_len); - g_free(gv_data); - - if (__send_signal_to_agent(uid, data, data_len)) { - _E("failed to send signal to agent"); - free(data); - return -1; - } - - free(data); - - return 0; -} - -int Control::SendSignalsForUid(uid_t uid, std::string key, std::string val) { - if (!signal_) { - _E("offline mode"); - return -1; - } - - const auto& req = GetRequest(); - const char* sid = req->GetSessionId().c_str(); - - const char* signal_name; - size_t name_size; - GVariantBuilder* builder; - GVariant* gv; - gsize gv_len; - gpointer gv_data; - void* data; - void* ptr; - size_t data_len; - - data_len = sizeof(size_t) + sizeof(gsize); - - signal_name = __get_signal_name(req, key.c_str(), ""); - if (!signal_name) { - _E("unknown signal name"); - return -1; - } - - /* including null byte */ - name_size = strlen(signal_name) + 1; - data_len += name_size; - - builder = g_variant_builder_new(G_VARIANT_TYPE("a(sss)")); - for (const auto& pkg : pkgs_) - g_variant_builder_add(builder, "(sss)", pkg.GetPkgid().c_str(), - pkg.GetAppid().c_str(), pkg.GetPkgType().c_str()); - gv = g_variant_new("(usa(sss)ss)", req->GetUid(), sid, - builder, key.c_str(), val.c_str()); - g_variant_builder_unref(builder); - if (gv == NULL) { - _E("failed to create GVariant instance"); - return -1; - } - gv_len = g_variant_get_size(gv); - gv_data = g_malloc(gv_len); - g_variant_store(gv, gv_data); - g_variant_unref(gv); - data_len += gv_len; - - data = malloc(data_len); - if (data == NULL) { - _E("out of memory"); - g_free(gv_data); - return -1; - } - ptr = data; - memcpy(ptr, &name_size, sizeof(size_t)); - ptr += sizeof(size_t); - memcpy(ptr, &gv_len, sizeof(gsize)); - ptr += sizeof(gsize); - memcpy(ptr, signal_name, name_size); - ptr += name_size; - memcpy(ptr, gv_data, gv_len); - g_free(gv_data); - - if (__send_signal_to_agent(uid, data, data_len)) { - _E("failed to send signal to agent"); - free(data); - return -1; - } - - free(data); - - return 0; -} - -static GVariant* __get_gvariant_from_event_info( - pkgmgr_res_event_info* event_info) { - rpc_port::PkgSignal::ExtraData* info = - reinterpret_cast(event_info); - GVariantBuilder* builder; - GVariant* result; - GList* path_states; - res_event_path_state_t* path_state; - - builder = g_variant_builder_new(G_VARIANT_TYPE("a(si)")); - if (builder == NULL) { - _E("out of memory"); - return NULL; - } - - for (const auto& p : info->GetPaths()) - g_variant_builder_add(builder, "(si)", p.GetPath(), p.GetState()); - - result = g_variant_new("(ia(si))", info->GetErrCode(), builder); - g_variant_builder_unref(builder); - - if (result == NULL) { - _E("Fail to create extra data"); - return NULL; - } - - return result; -} - -int Control::SendSignalForResourceForUid(uid_t uid, std::string pkgid, - std::string status, rpc_port::PkgSignal::ExtraData* event_info) { - if (!signal_) { - _E("offline mode"); - return -1; - } - - const auto& req = GetRequest(); - const char* sid = req->GetSessionId().c_str(); - - const char* signal_name; - size_t name_size; - GVariant* gv; - gsize gv_len; - gpointer gv_data; - void* data; - void* ptr; - size_t data_len; - GVariant* extra_param; - - data_len = sizeof(size_t) + sizeof(gsize); - - signal_name = __get_signal_name(req, "", ""); - if (!signal_name) { - _E("unknown signal name"); - return -1; - } - - /* including null byte */ - name_size = strlen(signal_name) + 1; - data_len += name_size; - - extra_param = __get_gvariant_from_event_info(event_info); - if (extra_param == NULL) { - _E("Fail to get extra parameter"); - return -1; - } - - gv = g_variant_new("(usssv)", req->GetUid(), sid, - pkgid.c_str(), status.c_str(), extra_param); - if (gv == NULL) { - _E("failed to create GVariant instance"); - return -1; - } - - gv_len = g_variant_get_size(gv); - gv_data = g_malloc(gv_len); - g_variant_store(gv, gv_data); - g_variant_unref(gv); - data_len += gv_len; - - data = malloc(data_len); - if (data == NULL) { - _E("out of memory"); - g_free(gv_data); - return -1; - } - ptr = data; - memcpy(ptr, &name_size, sizeof(size_t)); - ptr += sizeof(size_t); - memcpy(ptr, &gv_len, sizeof(gsize)); - ptr += sizeof(gsize); - memcpy(ptr, signal_name, name_size); - ptr += name_size; - memcpy(ptr, gv_data, gv_len); - g_free(gv_data); - - if (__send_signal_to_agent(uid, data, data_len)) { - _E("failed to send signal to agent"); - free(data); - return -1; - } - - free(data); - - return 0; -} - -void Control::AddPkg(std::string pkgid, std::string pkg_type) { - pkgs_.emplace_back(rpc_port::PkgSignal::PkgInfo(std::move(pkgid), - "", std::move(pkg_type))); -} - -int Control::SetRequestFromArgv(const int argc, char** argv) { - int opt_idx = 0; - optind = 1; - argc_ = argc; - argv_ = argv; - mode_ = 0; - - while (true) { - int c = getopt_long(argc, argv, short_opts, long_opts, &opt_idx); - if (c == -1) - break; - - if (option_map_.find(c) != option_map_.end()) { - int ret = option_map_[c](request_); - if (ret < 0) - return ret; - } - } - - return 0; -} - -} // namespace installer -} // namespace pkgmgr diff --git a/installer/src/control.hh b/installer/src/control.hh deleted file mode 100644 index 6258a4f..0000000 --- a/installer/src/control.hh +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. - * - * 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. - */ - - -#ifndef INSTALLER_SRC_CONTROL_H_ -#define INSTALLER_SRC_CONTROL_H_ - -#include -#include -#include -#include -#include - -#include "PkgSignal.h" -#include "request.hh" - -namespace pkgmgr { -namespace installer { - -namespace pkg_group = rpc_port::PkgSignal::group; - -class Control { - public: - Control(bool offline = false); - virtual ~Control(); - int SetRequestFromArgv(const int argc, char** argv); - const std::unique_ptr& GetRequest() const; - int SendSignal(std::string pkg_type, std::string pkgid, - std::string appid, std::string key, std::string val); - int SendSignals(std::string key, std::string val); - int SendSignalForResource(std::string pkgid, std::string status, - rpc_port::PkgSignal::ExtraData* event_info); - int SendSignalForUid(uid_t uid, std::string pkg_type, std::string pkgid, - std::string appid, std::string key, std::string val); - int SendSignalsForUid(uid_t uid, std::string key, std::string val); - int SendSignalForResourceForUid(uid_t uid, std::string pkgid, - std::string status, rpc_port::PkgSignal::ExtraData* event_info); - void AddPkg(std::string pkgid, std::string pkg_type); - - private: - void ParseMultiplePkgs(const std::unique_ptr& req); - - private: - std::unique_ptr request_; - std::unique_ptr signal_; - std::map&)>> - option_map_; - std::vector pkgs_; - int argc_ = 0; - char** argv_ = nullptr; - int mode_ = 0; -}; - -} // namespace installer -} // namespace pkgmgr - -#endif // INSTALLER_SRC_CONTROL_H_ \ No newline at end of file diff --git a/installer/src/pkgmgr_installer.c b/installer/src/pkgmgr_installer.c new file mode 100644 index 0000000..fd8a09f --- /dev/null +++ b/installer/src/pkgmgr_installer.c @@ -0,0 +1,1446 @@ +/* + * slp-pkgmgr + * + * Copyright (c) 2000 - 2011 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 "package-manager.h" +#include "pkgmgr_installer.h" +#include "pkgmgr_installer_config.h" +#include "pkgmgr_installer_debug.h" +#include "pkgmgr_installer_info.h" +#include "pkgmgr_installer_error.h" +#include "package-manager-types.h" + +#include + +/* API export macro */ +#ifndef API +#define API __attribute__ ((visibility("default"))) +#endif + +#define MAX_STRLEN 1024 +#define MAX_QUERY_LEN 4096 + +#define CHK_PI_RET(r) \ + do { if (NULL == pi) return (r); } while (0) + +#define OPTVAL_PRELOAD 1000 +#define OPTVAL_FORCE_REMOVAL 1001 +#define OPTVAL_PRELOAD_RW 1002 +#define OPTVAL_NO_REMOVAL 1003 +#define OPTVAL_KEEP_RWDATA 1004 +#define OPTVAL_PARTIAL_RW 1005 +#define OPTVAL_MIGRATE_EXTIMG 1006 +#define OPTVAL_SKIP_CHECK_REFERENCE 1007 +#define OPTVAL_RECOVER_DB 1008 +#define OPTVAL_RECOVERY_CLEANUP 1009 + +/* Supported options */ +const char *short_opts = "k:l:i:d:c:m:t:o:r:p:s:b:e:M:y:u:w:D:A:qGS"; +const struct option long_opts[] = { + { "session-id", 1, NULL, 'k' }, + { "license-path", 1, NULL, 'l' }, + { "install", 1, NULL, 'i' }, + { "uninstall", 1, NULL, 'd' }, + { "clear", 1, NULL, 'c' }, + { "move", 1, NULL, 'm' }, + { "move-type", 1, NULL, 't' }, + { "optional-data", 0, NULL, 'o' }, + { "reinstall", 0, NULL, 'r' }, + { "caller-pkgid", 1, NULL, 'p' }, + { "tep-path", 1, NULL, 'e' }, + { "tep-move", 1, NULL, 'M' }, + { "smack", 1, NULL, 's' }, + { "manifest-direct-install", 1, NULL, 'y' }, + { "mount-install", 1, NULL, 'w' }, + { "recovery", 1, NULL, 'b' }, + { "debug-mode", 0, NULL, 'G' }, + { "skip-optimization", 0, NULL, 'S' }, + { "preload", 0, NULL, OPTVAL_PRELOAD }, /* for preload RO */ + { "force-remove", 0, NULL, OPTVAL_FORCE_REMOVAL }, /* for preload RO/RW */ + { "preload-rw", 0, NULL, OPTVAL_PRELOAD_RW }, /* for preload RW */ + { "no-remove", 0, NULL, OPTVAL_NO_REMOVAL }, /* for preload RW */ + { "keep-rwdata", 0, NULL, OPTVAL_KEEP_RWDATA }, /* for preload RW */ + { "partial-rw", 0, NULL, OPTVAL_PARTIAL_RW }, /* for preload RO */ + { "migrate-extimg", 1, NULL, OPTVAL_MIGRATE_EXTIMG }, + { "skip-check-reference", 0, NULL, OPTVAL_SKIP_CHECK_REFERENCE }, + { "recover-db", 1, NULL, OPTVAL_RECOVER_DB }, + { "recovery-cleanup", 0, NULL, OPTVAL_RECOVERY_CLEANUP }, + { 0, 0, 0, 0 } /* sentinel */ +}; + +struct pkgmgr_installer { + int request_type; + int move_type; + int is_upgrade; + char *pkgmgr_info; + char *session_id; + char *license_path; + char *optional_data; + char *caller_pkgid; + uid_t target_uid; + char *tep_path; + int tep_move; + int is_tep_included; + int is_preload; + int force_removal; + int is_preload_rw; + int no_removal; + int keep_rwdata; + int partial_rw; + int debug_mode; + int skip_check_reference; + int skip_optimization; + int recovery_cleanup; + GDBusConnection *conn; + GHashTable *pkg_list; + GList *pkgs; +}; + +typedef struct pkg_signal_info { + char *pkgid; + char *pkg_type; +} pkg_signal_info; + +static uid_t g_target_uid; +static int g_debug_mode; +static int g_skip_optimization; +static pkgmgr_privilege_level g_privilege_level = PM_PRIVILEGE_UNKNOWN; + +static const char *__get_signal_name(pkgmgr_installer *pi, const char *key, + const char *pkg_type) +{ + if (strcmp(key, PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR) == 0) + return key; + else if (strcmp(key, PKGMGR_INSTALLER_GET_SIZE_KEY_STR) == 0) + return key; + else if (strcmp(key, PKGMGR_INSTALLER_APPID_KEY_STR) == 0) + return PKGMGR_INSTALLER_UNINSTALL_EVENT_STR; + else if (strcmp(pkg_type, PKGMGR_INSTALLER_CLEAR_CACHE_KEY_STR) == 0) + return pkg_type; + else if (pi->is_upgrade) + return PKGMGR_INSTALLER_UPGRADE_EVENT_STR; + + + switch (pi->request_type) { + case PKGMGR_REQ_INSTALL: + case PKGMGR_REQ_MANIFEST_DIRECT_INSTALL: + case PKGMGR_REQ_MOUNT_INSTALL: + case PKGMGR_REQ_REINSTALL: + case PKGMGR_REQ_ENABLE_PKG: + case PKGMGR_REQ_RECOVER: + return PKGMGR_INSTALLER_INSTALL_EVENT_STR; + case PKGMGR_REQ_UNINSTALL: + case PKGMGR_REQ_DISABLE_PKG: + return PKGMGR_INSTALLER_UNINSTALL_EVENT_STR; + case PKGMGR_REQ_UPGRADE: + return PKGMGR_INSTALLER_UPGRADE_EVENT_STR; + case PKGMGR_REQ_MOVE: + return PKGMGR_INSTALLER_MOVE_EVENT_STR; + case PKGMGR_REQ_ENABLE_APP: + return PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR; + case PKGMGR_REQ_DISABLE_APP: + return PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR; + case PKGMGR_REQ_ENABLE_APP_SPLASH_SCREEN: + return PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR; + case PKGMGR_REQ_DISABLE_APP_SPLASH_SCREEN: + return PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR; + case PKGMGR_REQ_CLEAR: + return PKGMGR_INSTALLER_CLEAR_EVENT_STR; + case PKGMGR_REQ_GETSIZE: + return PKGMGR_INSTALLER_GET_SIZE_KEY_STR; + case PKGMGR_REQ_RES_COPY: + return PKGMGR_INSTALLER_RES_COPY_EVENT_STR; + case PKGMGR_REQ_RES_CREATE_DIR: + return PKGMGR_INSTALLER_RES_CREATE_DIR_EVENT_STR; + case PKGMGR_REQ_RES_REMOVE: + return PKGMGR_INSTALLER_RES_REMOVE_EVENT_STR; + case PKGMGR_REQ_RES_UNINSTALL: + return PKGMGR_INSTALLER_RES_UNINSTALL_EVENT_STR; + } + + ERR("cannot find type"); + + return NULL; +} + +static int __send_signal_for_event(pkgmgr_installer *pi, const char *pkg_type, + const char *pkgid, const char *appid, const char *key, + const char *val) +{ + char *sid; + const char *tmp_appid = appid; + const char *signal_name; + GVariant *v; + GVariantBuilder *builder; + GError *err = NULL; + + if (!pi || pi->conn == NULL) + return -1; + + sid = pi->session_id; + if (!sid) + sid = ""; + + signal_name = __get_signal_name(pi, key, pkg_type); + if (!signal_name) { + ERR("unknown signal type"); + return -1; + } + + builder = g_variant_builder_new(G_VARIANT_TYPE("a(sss)")); + g_variant_builder_add(builder, "(sss)", pkgid, + (tmp_appid ? tmp_appid : ""), pkg_type); + v = g_variant_new("(usa(sss)ss)", + pi->target_uid, sid, builder, key, val); + g_variant_builder_unref(builder); + if (g_dbus_connection_emit_signal(pi->conn, NULL, + PKGMGR_INSTALLER_DBUS_OBJECT_PATH, + PKGMGR_INSTALLER_DBUS_INTERFACE, signal_name, + v, &err) != TRUE) { + ERR("failed to send dbus signal"); + if (err) { + ERR("err: %s", err->message); + g_error_free(err); + } + return -1; + } + + return 0; +} + +static int __send_signal_to_agent(uid_t uid, void *data, size_t len) +{ + int fd; + struct sockaddr_un sa; + int r; + + fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0); + if (fd == -1) { + ERR("failed to create socket: %d", errno); + return -1; + } + + sa.sun_family = AF_UNIX; + snprintf(sa.sun_path, sizeof(sa.sun_path), "/run/pkgmgr/agent/%d", uid); + + r = connect(fd, (struct sockaddr *)&sa, sizeof(sa)); + if (r == -1) { + ERR("failed to connect socket(%s): %d", sa.sun_path, errno); + close(fd); + return -1; + } + + r = send(fd, data, len, MSG_NOSIGNAL); + if (r < 0) { + ERR("failed to send data: %d", errno); + close(fd); + return -1; + } + + close(fd); + + return 0; +} + +static int __send_signal_for_event_for_uid(pkgmgr_installer *pi, uid_t uid, + const char *pkg_type, const char *pkgid, const char *appid, + const char *key, const char *val) +{ + char *sid; + const char *signal_name; + const char *tmp_appid = appid; + size_t name_size; + GVariantBuilder *builder; + GVariant *gv; + gsize gv_len; + gpointer gv_data; + void *data; + void *ptr; + size_t data_len; + + if (!pi || pi->conn == NULL) + return -1; + + sid = pi->session_id; + if (!sid) + sid = ""; + + data_len = sizeof(size_t) + sizeof(gsize); + + signal_name = __get_signal_name(pi, key, pkg_type); + if (!signal_name) { + ERR("unknown signal name"); + return -1; + } + + /* including null byte */ + name_size = strlen(signal_name) + 1; + data_len += name_size; + + builder = g_variant_builder_new(G_VARIANT_TYPE("a(sss)")); + g_variant_builder_add(builder, "(sss)", pkgid, + (tmp_appid ? tmp_appid : ""), pkg_type); + gv = g_variant_new("(usa(sss)ss)", pi->target_uid, sid, + builder, key, val); + g_variant_builder_unref(builder); + if (gv == NULL) { + ERR("failed to create GVariant instance"); + return -1; + } + gv_len = g_variant_get_size(gv); + gv_data = g_malloc(gv_len); + g_variant_store(gv, gv_data); + g_variant_unref(gv); + data_len += gv_len; + + data = malloc(data_len); + if (data == NULL) { + ERR("out of memory"); + g_free(gv_data); + return -1; + } + ptr = data; + memcpy(ptr, &name_size, sizeof(size_t)); + ptr += sizeof(size_t); + memcpy(ptr, &gv_len, sizeof(gsize)); + ptr += sizeof(gsize); + memcpy(ptr, signal_name, name_size); + ptr += name_size; + memcpy(ptr, gv_data, gv_len); + g_free(gv_data); + + if (__send_signal_to_agent(uid, data, data_len)) { + ERR("failed to send signal to agent"); + free(data); + return -1; + } + + free(data); + + return 0; +} + +static void __free_pkg_list(gpointer data) +{ + pkg_signal_info *info = (pkg_signal_info *)data; + free(info->pkgid); + free(info->pkg_type); + free(info); +} + +API pkgmgr_installer *pkgmgr_installer_new(void) +{ + pkgmgr_installer *pi; + GError *err = NULL; + + pi = calloc(1, sizeof(struct pkgmgr_installer)); + if (pi == NULL) + return NULL; + + pi->conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); + if (pi->conn == NULL) { + ERR("failed to get bus: %s", err->message); + g_error_free(err); + free(pi); + return NULL; + } + + pi->tep_path = NULL; + pi->tep_move = 0; + pi->request_type = PKGMGR_REQ_INVALID; + pi->pkg_list = g_hash_table_new_full( + g_str_hash, g_str_equal, NULL, __free_pkg_list); + return pi; +} + +API pkgmgr_installer *pkgmgr_installer_offline_new(void) +{ + pkgmgr_installer *pi; + + pi = calloc(1, sizeof(struct pkgmgr_installer)); + if (pi == NULL) + return NULL; + + pi->tep_path = NULL; + pi->tep_move = 0; + pi->request_type = PKGMGR_REQ_INVALID; + + return pi; +} + +API int pkgmgr_installer_free(pkgmgr_installer *pi) +{ + CHK_PI_RET(-EINVAL); + + /* free members */ + if (pi->pkgmgr_info) + free(pi->pkgmgr_info); + if (pi->session_id) + free(pi->session_id); + if (pi->optional_data) + free(pi->optional_data); + if (pi->caller_pkgid) + free(pi->caller_pkgid); + if (pi->tep_path) + free(pi->tep_path); + + if (pi->conn) { + g_dbus_connection_flush_sync(pi->conn, NULL, NULL); + g_object_unref(pi->conn); + } + + if (pi->pkgs) + g_list_free_full(pi->pkgs, free); + + if (pi->pkg_list) + g_hash_table_destroy(pi->pkg_list); + + free(pi); + + return 0; +} + +static void __parse_multiple_pkgs(pkgmgr_installer *pi, int argc, char **argv) +{ + while ((optind <= argc) && (*argv[optind - 1] != '-')) { + pi->pkgs = g_list_append(pi->pkgs, strdup(argv[optind - 1])); + optind++; + } + optind--; +} + +API int +pkgmgr_installer_receive_request(pkgmgr_installer *pi, + const int argc, char **argv) +{ + CHK_PI_RET(-EINVAL); + + int r = 0; + + /* Parse argv */ + optind = 1; /* Initialize optind to clear prev. index */ + int opt_idx = 0; + int c; + int mode = 0; + + pi->target_uid = getuid(); + g_target_uid = pi->target_uid; + g_debug_mode = 0; + g_skip_optimization = 0; + + if (pi->pkgs) { + g_list_free_full(pi->pkgs, free); + pi->pkgs = NULL; + } + + while (1) { + c = getopt_long(argc, argv, short_opts, long_opts, &opt_idx); + /* printf("c=%d %c\n", c, c); //debug */ + if (-1 == c) + break; /* Parse is end */ + switch (c) { + case OPTVAL_PRELOAD: /* request for preload app */ + pi->is_preload = 1; + DBG("preload request [%d]", pi->is_preload); + break; + case OPTVAL_FORCE_REMOVAL: /* request for force-remove */ + pi->force_removal = 1; + DBG("force-remove request [%d]", pi->force_removal); + break; + case OPTVAL_PRELOAD_RW: /* request for preload-rw app */ + pi->is_preload_rw = 1; + DBG("preload-rw request [%d]", pi->is_preload_rw); + break; + case OPTVAL_NO_REMOVAL: /* request for no-remove */ + pi->no_removal = 1; + DBG("no-remove request [%d]", pi->no_removal); + break; + case OPTVAL_KEEP_RWDATA: /* request for keep-rwdata */ + pi->keep_rwdata = 1; + DBG("keep-rwdata request [%d]", pi->keep_rwdata); + break; + case OPTVAL_PARTIAL_RW: /* request for partial-rw */ + pi->partial_rw = 1; + DBG("partial-rw request [%d]", pi->partial_rw); + break; + case OPTVAL_MIGRATE_EXTIMG: + /* request for legacy extimg migration */ + if (mode) { + r = -EINVAL; + goto RET; + } + mode = OPTVAL_MIGRATE_EXTIMG; + pi->request_type = PKGMGR_REQ_MIGRATE_EXTIMG; + if (pi->pkgmgr_info) + free(pi->pkgmgr_info); + pi->pkgmgr_info = strndup(optarg, MAX_STRLEN); + __parse_multiple_pkgs(pi, argc, argv); + DBG("legacy extimg migration requested"); + break; + case OPTVAL_SKIP_CHECK_REFERENCE: + pi->skip_check_reference = 1; + break; + case OPTVAL_RECOVER_DB: + pi->request_type = PKGMGR_REQ_RECOVER_DB; + pi->pkgmgr_info = strndup(optarg, MAX_STRLEN); + __parse_multiple_pkgs(pi, argc, argv); + break; + case OPTVAL_RECOVERY_CLEANUP: + pi->recovery_cleanup = 1; + break; + case 'k': /* session id */ + if (pi->session_id) + free(pi->session_id); + pi->session_id = strndup(optarg, MAX_STRLEN); + break; + + case 'l': /* license path */ + if (pi->license_path) + free(pi->license_path); + pi->license_path = strndup(optarg, MAX_STRLEN); + break; + + case 'i': /* install */ + if (mode) { + r = -EINVAL; + goto RET; + } + mode = 'i'; + pi->request_type = PKGMGR_REQ_INSTALL; + if (pi->pkgmgr_info) + free(pi->pkgmgr_info); + pi->pkgmgr_info = strndup(optarg, MAX_STRLEN); + __parse_multiple_pkgs(pi, argc, argv); + DBG("option is [i] pkgid[%s]", pi->pkgmgr_info); + if (pi->pkgmgr_info && strlen(pi->pkgmgr_info) == 0) { + free(pi->pkgmgr_info); + pi->pkgmgr_info = NULL; + } else { + mode = 'i'; + } + break; + + case 'e': /* install */ + if (pi->tep_path) + free(pi->tep_path); + pi->tep_path = strndup(optarg, MAX_STRLEN); + pi->is_tep_included = 1; + DBG("option is [e] tep_path[%s]", pi->tep_path); + break; + + case 'M': /* install */ + if (strcmp(optarg, "tep_move") == 0) + pi->tep_move = 1; + else + pi->tep_move = 0; + DBG("option is [M] tep_move[%d]", pi->tep_move); + break; + + case 'd': /* uninstall */ + if (mode) { + r = -EINVAL; + goto RET; + } + mode = 'd'; + pi->request_type = PKGMGR_REQ_UNINSTALL; + if (pi->pkgmgr_info) + free(pi->pkgmgr_info); + pi->pkgmgr_info = strndup(optarg, MAX_STRLEN); + __parse_multiple_pkgs(pi, argc, argv); + break; + + + case 'c': /* clear */ + if (mode) { + r = -EINVAL; + goto RET; + } + mode = 'c'; + pi->request_type = PKGMGR_REQ_CLEAR; + if (pi->pkgmgr_info) + free(pi->pkgmgr_info); + pi->pkgmgr_info = strndup(optarg, MAX_STRLEN); + __parse_multiple_pkgs(pi, argc, argv); + break; + + case 'm': /* move */ + if (mode) { + r = -EINVAL; + goto RET; + } + mode = 'm'; + pi->request_type = PKGMGR_REQ_MOVE; + if (pi->pkgmgr_info) + free(pi->pkgmgr_info); + pi->pkgmgr_info = strndup(optarg, MAX_STRLEN); + __parse_multiple_pkgs(pi, argc, argv); + break; + + case 'r': /* reinstall */ + if (mode) { + r = -EINVAL; + goto RET; + } + mode = 'r'; + pi->request_type = PKGMGR_REQ_REINSTALL; + if (pi->pkgmgr_info) + free(pi->pkgmgr_info); + pi->pkgmgr_info = strndup(optarg, MAX_STRLEN); + __parse_multiple_pkgs(pi, argc, argv); + break; + + case 't': /* move type*/ + pi->move_type = atoi(optarg); + break; + + case 'p': /* caller pkgid*/ + if (pi->caller_pkgid) + free(pi->caller_pkgid); + pi->caller_pkgid = strndup(optarg, MAX_STRLEN); + + break; + + case 's': /* smack */ + if (mode) { + r = -EINVAL; + goto RET; + } + mode = 's'; + pi->request_type = PKGMGR_REQ_SMACK; + if (pi->pkgmgr_info) + free(pi->pkgmgr_info); + pi->pkgmgr_info = strndup(optarg, MAX_STRLEN); + __parse_multiple_pkgs(pi, argc, argv); + break; + + case 'o': /* optional data*/ + pi->optional_data = strndup(optarg, MAX_STRLEN); + break; + + case 'y': /* pkgid for direct manifest installation */ + mode = 'y'; + pi->request_type = PKGMGR_REQ_MANIFEST_DIRECT_INSTALL; + pi->pkgmgr_info = strndup(optarg, MAX_STRLEN); + __parse_multiple_pkgs(pi, argc, argv); + break; + + case 'w': /* pkgid for mount installation */ + mode = 'w'; + pi->request_type = PKGMGR_REQ_MOUNT_INSTALL; + pi->pkgmgr_info = strndup(optarg, MAX_STRLEN); + __parse_multiple_pkgs(pi, argc, argv); + break; + + case 'b': /* recovery */ + if (mode) { + r = -EINVAL; + goto RET; + } + mode = 'b'; + pi->request_type = PKGMGR_REQ_RECOVER; + if (pi->pkgmgr_info) + free(pi->pkgmgr_info); + pi->pkgmgr_info = strndup(optarg, MAX_STRLEN); + __parse_multiple_pkgs(pi, argc, argv); + break; + + case 'D': /* disable pkg */ + pi->request_type = PKGMGR_REQ_DISABLE_PKG; + if (pi->pkgmgr_info) + free(pi->pkgmgr_info); + pi->pkgmgr_info = strndup(optarg, MAX_STRLEN); + __parse_multiple_pkgs(pi, argc, argv); + break; + + case 'A': /* enable pkg */ + pi->request_type = PKGMGR_REQ_ENABLE_PKG; + if (pi->pkgmgr_info) + free(pi->pkgmgr_info); + pi->pkgmgr_info = strndup(optarg, MAX_STRLEN); + __parse_multiple_pkgs(pi, argc, argv); + break; + + case 'u': /* uid */ + g_target_uid = (uid_t)atoi(optarg); + pi->target_uid = (uid_t)atoi(optarg); + break; + + case 'G': /* debug mode */ + pi->debug_mode = 1; + g_debug_mode = 1; + break; + + case 'S': /* skip optimization */ + pi->skip_optimization = 1; + g_skip_optimization = 1; + break; + + /* Otherwise */ + case '?': /* Not an option */ + break; + + case ':': /* */ + break; + + } + } + + /* if target user is not set, set as tizenglobalapp user */ + if (pi->target_uid == 0) { + pi->target_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER); + g_target_uid = pi->target_uid; + } + RET: + return r; +} + +API int pkgmgr_installer_get_request_type(pkgmgr_installer *pi) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return pi->request_type; +} + +API uid_t pkgmgr_installer_get_uid(pkgmgr_installer *pi) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return pi->target_uid; +} + +API const char *pkgmgr_installer_get_request_info(pkgmgr_installer *pi) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return pi->pkgmgr_info; +} + +API const char *pkgmgr_installer_get_request_info_at(pkgmgr_installer *pi, + int at) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return (const char *)g_list_nth_data(pi->pkgs, at); +} + +API int pkgmgr_installer_get_request_info_count(pkgmgr_installer *pi) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return g_list_length(pi->pkgs); +} + +API const char *pkgmgr_installer_get_tep_path(pkgmgr_installer *pi) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return pi->tep_path; +} + +API int pkgmgr_installer_get_tep_move_type(pkgmgr_installer *pi) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return pi->tep_move; +} + +API const char *pkgmgr_installer_get_session_id(pkgmgr_installer *pi) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return pi->session_id; +} + +API const char *pkgmgr_installer_get_license_path(pkgmgr_installer *pi) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return pi->license_path; +} + +API const char *pkgmgr_installer_get_optional_data(pkgmgr_installer *pi) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return pi->optional_data; +} + +API int pkgmgr_installer_is_quiet(pkgmgr_installer *pi) +{ + return 1; +} + +API int pkgmgr_installer_get_move_type(pkgmgr_installer *pi) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return pi->move_type; +} + +API const char *pkgmgr_installer_get_caller_pkgid(pkgmgr_installer *pi) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return pi->caller_pkgid; +} + +API int pkgmgr_installer_get_is_preload(pkgmgr_installer *pi) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return pi->is_preload; +} + +API int pkgmgr_installer_get_force_removal(pkgmgr_installer *pi) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return pi->force_removal; +} + +API int pkgmgr_installer_get_is_preload_rw(pkgmgr_installer *pi) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return pi->is_preload_rw; +} + +API int pkgmgr_installer_get_no_removal(pkgmgr_installer *pi) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return pi->no_removal; +} + +API int pkgmgr_installer_get_keep_rwdata(pkgmgr_installer *pi) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return pi->keep_rwdata; +} + +API int pkgmgr_installer_get_partial_rw(pkgmgr_installer *pi) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return pi->partial_rw; +} + +API int pkgmgr_installer_get_debug_mode(pkgmgr_installer *pi) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return pi->debug_mode; +} + +API int pkgmgr_installer_get_skip_check_reference(pkgmgr_installer *pi) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return pi->skip_check_reference; +} + +API int pkgmgr_installer_get_skip_optimization(pkgmgr_installer *pi) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return pi->skip_optimization; +} + +API int pkgmgr_installer_get_recovery_cleanup(pkgmgr_installer *pi) +{ + CHK_PI_RET(PKGMGR_REQ_INVALID); + return pi->recovery_cleanup; +} + +API int pkgmgr_installer_send_app_uninstall_signal(pkgmgr_installer *pi, + const char *pkg_type, + const char *pkgid, + const char *val) +{ + int ret = 0; + ret = __send_signal_for_event(pi, pkg_type, pkgid, NULL, + PKGMGR_INSTALLER_APPID_KEY_STR, val); + return ret; +} + +API int pkgmgr_installer_send_app_uninstall_signal_for_uid( + pkgmgr_installer *pi, uid_t uid, const char *pkg_type, + const char *pkgid, const char *val) +{ + int ret = 0; + ret = __send_signal_for_event_for_uid(pi, uid, pkg_type, pkgid, NULL, + PKGMGR_INSTALLER_APPID_KEY_STR, val); + return ret; +} + +API int pkgmgr_installer_set_uid(pkgmgr_installer *pi, uid_t uid) +{ + if (pi == NULL) + return -1; + + pi->target_uid = uid; + g_target_uid = pi->target_uid; + + return 0; +} + +API int +pkgmgr_installer_send_app_signal(pkgmgr_installer *pi, + const char *pkg_type, + const char *pkgid, + const char *appid, + const char *key, const char *val) +{ + int r = 0; + + if (!pi->conn) { + ERR("connection is NULL"); + return -1; + } + + r = __send_signal_for_event(pi, pkg_type, pkgid, appid, key, val); + + return r; +} + +API int +pkgmgr_installer_send_signal(pkgmgr_installer *pi, + const char *pkg_type, + const char *pkgid, + const char *key, const char *val) +{ + int r = 0; + + if (!pi->conn) { + ERR("connection is NULL"); + return -1; + } + + r = __send_signal_for_event(pi, pkg_type, pkgid, NULL, key, val); + + return r; +} + +API int pkgmgr_installer_send_app_signal_for_uid(pkgmgr_installer *pi, + uid_t uid, const char *pkg_type, const char *pkgid, + const char *appid, const char *key, const char *val) +{ + int r = 0; + + if (!pi->conn) { + ERR("connection is NULL"); + return -1; + } + + r = __send_signal_for_event_for_uid(pi, uid, pkg_type, pkgid, appid, + key, val); + + return r; +} + +API int pkgmgr_installer_send_signal_for_uid(pkgmgr_installer *pi, + uid_t uid, const char *pkg_type, const char *pkgid, + const char *key, const char *val) +{ + int r = 0; + + if (!pi->conn) { + ERR("connection is NULL"); + return -1; + } + + r = __send_signal_for_event_for_uid(pi, uid, pkg_type, pkgid, NULL, + key, val); + + return r; +} + +API int pkgmgr_installer_set_request_type(pkgmgr_installer *pi, int request_type) +{ + if (pi == NULL) + return -1; + + pi->request_type = request_type; + return 0; +} + +API int pkgmgr_installer_set_session_id(pkgmgr_installer *pi, const char *session_id) +{ + if (pi == NULL || session_id == NULL) + return -1; + + pi->session_id = strndup(session_id, MAX_STRLEN); + return 0; +} + +API int pkgmgr_installer_create_certinfo_set_handle(pkgmgr_instcertinfo_h *handle) +{ + int ret = 0; + ret = pkgmgrinfo_create_certinfo_set_handle(handle); + return ret; +} + +API int pkgmgr_installer_set_cert_value(pkgmgr_instcertinfo_h handle, pkgmgr_instcert_type cert_type, char *cert_value) +{ + int ret = 0; + ret = pkgmgrinfo_set_cert_value(handle, cert_type, cert_value); + return ret; +} + +API int pkgmgr_installer_save_certinfo(const char *pkgid, pkgmgr_instcertinfo_h handle, uid_t uid) +{ + int ret = 0; + ret = pkgmgrinfo_save_certinfo(pkgid, handle, uid); + return ret; +} + +API int pkgmgr_installer_destroy_certinfo_set_handle(pkgmgr_instcertinfo_h handle) +{ + int ret = 0; + ret = pkgmgrinfo_destroy_certinfo_set_handle(handle); + return ret; +} + +API int pkgmgr_installer_delete_certinfo(const char *pkgid) +{ + int ret = 0; + ret = pkgmgrinfo_delete_certinfo(pkgid); + return ret; +} + +API int pkgmgr_installer_set_privilege_level(pkgmgr_privilege_level level) +{ + g_privilege_level = level; + + return 0; +} + +API int pkgmgr_installer_info_get_target_uid(uid_t *uid) +{ + *uid = g_target_uid; + + return 0; +} + +API int pkgmgr_installer_info_get_privilege_level(pkgmgr_privilege_level *level) +{ + *level = g_privilege_level; + + return 0; +} + +API int pkgmgr_installer_info_get_debug_mode(int *debug_mode) +{ + *debug_mode = g_debug_mode; + return 0; +} + +API int pkgmgr_installer_info_get_skip_optimization(int *skip_optimization) +{ + *skip_optimization = g_skip_optimization; + return 0; +} + +#define CASE_TO_STR(ERRCODE) case ERRCODE: return ERRCODE##_STR +API const char *pkgmgr_installer_error_to_string(int error_code) +{ + switch (error_code) { + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_UNDEFINED_ERROR); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_GLOBALSYMLINK_ERROR); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_GRANT_PERMISSION_ERROR); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_IMAGE_ERROR); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_UNZIP_ERROR); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_SECURITY_ERROR); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_REGISTER_ERROR); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_PRIVILEGE_ERROR); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_PARSE_ERROR); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_RECOVERY_ERROR); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_DELTA_ERROR); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_APP_DIR_ERROR); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_CONFIG_ERROR); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_SIGNATURE_ERROR); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_SIGNATURE_INVALID); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_CERT_ERROR); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_AUTHOR_CERT_NOT_MATCH); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_AUTHOR_CERT_NOT_FOUND); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_ICON_ERROR); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_ICON_NOT_FOUND); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_MANIFEST_ERROR); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_MANIFEST_NOT_FOUND); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_PACKAGE_NOT_FOUND); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_OPERATION_NOT_ALLOWED); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_OUT_OF_SPACE); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_INVALID_VALUE); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_ERROR); + CASE_TO_STR(PKGMGR_INSTALLER_ERRCODE_OK); + default: + return PKGMGR_INSTALLER_ERRCODE_UNDEFINED_ERROR_STR; + } +} + +API int pkgmgr_installer_add_pkg(pkgmgr_installer *pi, + const char *pkgid, const char *pkg_type) +{ + pkg_signal_info *info; + if (!pi || !pkgid || !pkg_type) { + ERR("invalid argument"); + return -1; + } + + info = calloc(1, sizeof(pkg_signal_info)); + if (!info) { + ERR("out of memory"); + return -1; + } + + info->pkgid = strdup(pkgid); + info->pkg_type = strdup(pkg_type); + if (!info->pkgid || !info->pkg_type) { + ERR("out of memory"); + free(info->pkgid); + free(info->pkg_type); + free(info); + return -1; + } + g_hash_table_insert(pi->pkg_list, (gpointer)info->pkgid, (gpointer)info); + + return 0; +} + +static void __build_multi_signal(gpointer key, gpointer value, + gpointer user_data) +{ + GVariantBuilder *builder = (GVariantBuilder *)user_data; + pkg_signal_info *info = (pkg_signal_info *)value; + + g_variant_builder_add(builder, "(sss)", info->pkgid, "", info->pkg_type); +} + +API int pkgmgr_installer_send_signals(pkgmgr_installer *pi, + const char *key, const char *val) +{ + char *sid; + const char *signal_name; + GError *err = NULL; + GVariantBuilder *builder; + + if (!pi || !key || !val) { + ERR("invalid argument"); + return -1; + } + + sid = pi->session_id; + if (!sid) + sid = ""; + + signal_name = __get_signal_name(pi, key, ""); + if (!signal_name) { + ERR("unknown signal type"); + return -1; + } + + builder = g_variant_builder_new(G_VARIANT_TYPE("a(sss)")); + g_hash_table_foreach(pi->pkg_list, __build_multi_signal, builder); + if (g_dbus_connection_emit_signal(pi->conn, NULL, + PKGMGR_INSTALLER_DBUS_OBJECT_PATH, + PKGMGR_INSTALLER_DBUS_INTERFACE, signal_name, + g_variant_new("(usa(sss)ss)", + pi->target_uid, sid, builder, key, + val), &err) != TRUE) { + ERR("failed to send dbus signal"); + if (err) { + ERR("err: %s", err->message); + g_error_free(err); + } + g_variant_builder_unref(builder); + return -1; + } + g_variant_builder_unref(builder); + + return 0; +} + +API int pkgmgr_installer_send_signals_for_uid(pkgmgr_installer *pi, uid_t uid, + const char *key, const char *val) +{ + char *sid; + size_t data_len; + size_t name_size; + GVariant *gv; + GVariantBuilder *builder; + gsize gv_len; + gpointer gv_data; + void *data; + void *ptr; + const char *signal_name; + + if (!pi || !pi->conn) { + ERR("connection is NULL"); + return -1; + } + + sid = pi->session_id; + if (!sid) + sid = ""; + + data_len = sizeof(size_t) + sizeof(gsize); + + /* including null byte */ + signal_name = __get_signal_name(pi, key, ""); + if (!signal_name) { + ERR("unknown signal type"); + return -1; + } + name_size = strlen(signal_name) + 1; + data_len += name_size; + + builder = g_variant_builder_new(G_VARIANT_TYPE("a(sss)")); + g_hash_table_foreach(pi->pkg_list, __build_multi_signal, builder); + + gv = g_variant_new("(usa(sss)ss)", uid, sid, builder, key, val); + g_variant_builder_unref(builder); + if (gv == NULL) { + ERR("failed to create GVariant instance"); + return -1; + } + + gv_len = g_variant_get_size(gv); + gv_data = g_malloc(gv_len); + g_variant_store(gv, gv_data); + g_variant_unref(gv); + data_len += gv_len; + + data = malloc(data_len); + if (data == NULL) { + ERR("out of memory"); + g_free(gv_data); + return -1; + } + ptr = data; + memcpy(ptr, &name_size, sizeof(size_t)); + ptr += sizeof(size_t); + memcpy(ptr, &gv_len, sizeof(gsize)); + ptr += sizeof(gsize); + memcpy(ptr, signal_name, name_size); + ptr += name_size; + memcpy(ptr, gv_data, gv_len); + g_free(gv_data); + + if (__send_signal_to_agent(uid, data, data_len)) { + ERR("failed to send signal to agent"); + free(data); + return -1; + } + + free(data); + + return 0; +} + +API int pkgmgr_installer_set_is_upgrade(pkgmgr_installer *pi, int is_upgrade) { + if (pi == NULL) + return -1; + + pi->is_upgrade = is_upgrade; + return 0; +} + +static GVariant *__get_gvariant_from_event_info(pkgmgr_res_event_info *event_info) +{ + pkgmgr_res_event_info_t *info = event_info; + GVariantBuilder *builder; + GVariant *result; + GList *path_states; + res_event_path_state_t *path_state; + + builder = g_variant_builder_new(G_VARIANT_TYPE("a(si)")); + if (builder == NULL) { + ERR("out of memory"); + return NULL; + } + + for (path_states = info->path_states; path_states != NULL; + path_states = path_states->next) { + path_state = (res_event_path_state_t *)path_states->data; + g_variant_builder_add(builder, "(si)", + path_state->path, path_state->state); + } + + result = g_variant_new("(ia(si))", info->error_code, builder); + g_variant_builder_unref(builder); + + if (result == NULL) { + ERR("Fail to create extra data"); + return NULL; + } + + return result; +} + +API int pkgmgr_installer_send_res_signal(pkgmgr_installer *pi, + const char *pkgid, const char *status, + pkgmgr_res_event_info *event_info) +{ + char *sid; + const char *signal_name; + GError *err = NULL; + GVariant *extra_param; + + if (!pi || !pkgid || !status) { + ERR("invalid argument"); + return -1; + } + + sid = pi->session_id; + if (!sid) + sid = ""; + + signal_name = __get_signal_name(pi, "", ""); + if (!signal_name) { + ERR("unknown signal type"); + return -1; + } + + extra_param = __get_gvariant_from_event_info(event_info); + if (extra_param == NULL) { + ERR("Fail to get extra parameter"); + return -1; + } + + if (g_dbus_connection_emit_signal(pi->conn, NULL, + PKGMGR_INSTALLER_DBUS_OBJECT_PATH, + PKGMGR_INSTALLER_DBUS_INTERFACE, signal_name, + g_variant_new("(usssv)", pi->target_uid, sid, + pkgid, status, extra_param), + &err) != TRUE) { + ERR("failed to send dbus signal"); + if (err) { + ERR("err: %s", err->message); + g_error_free(err); + } + return -1; + } + + return 0; +} + +API int pkgmgr_installer_send_res_signal_for_uid(pkgmgr_installer *pi, + uid_t uid, const char *pkgid, const char *status, + pkgmgr_res_event_info *event_info) +{ + char *sid; + size_t data_len; + size_t name_size; + GVariant *gv; + gsize gv_len; + gpointer gv_data; + void *data; + void *ptr; + const char *signal_name; + GVariant *extra_param; + + if (!pi || !pi->conn) { + ERR("connection is NULL"); + return -1; + } + + sid = pi->session_id; + if (!sid) + sid = ""; + + data_len = sizeof(size_t) + sizeof(gsize); + + /* including null byte */ + signal_name = __get_signal_name(pi, "", ""); + if (!signal_name) { + ERR("unknown signal type"); + return -1; + } + name_size = strlen(signal_name) + 1; + data_len += name_size; + + extra_param = __get_gvariant_from_event_info(event_info); + if (extra_param == NULL) { + ERR("Fail to get extra parameter"); + return -1; + } + + gv = g_variant_new("(usssv)", pi->target_uid, sid, + pkgid, status, extra_param); + if (gv == NULL) { + ERR("failed to create GVariant instance"); + return -1; + } + + gv_len = g_variant_get_size(gv); + gv_data = g_malloc(gv_len); + g_variant_store(gv, gv_data); + g_variant_unref(gv); + data_len += gv_len; + + data = malloc(data_len); + if (data == NULL) { + ERR("out of memory"); + g_free(gv_data); + return -1; + } + ptr = data; + memcpy(ptr, &name_size, sizeof(size_t)); + ptr += sizeof(size_t); + memcpy(ptr, &gv_len, sizeof(gsize)); + ptr += sizeof(gsize); + memcpy(ptr, signal_name, name_size); + ptr += name_size; + memcpy(ptr, gv_data, gv_len); + g_free(gv_data); + + if (__send_signal_to_agent(uid, data, data_len)) { + ERR("failed to send signal to agent"); + free(data); + return -1; + } + + free(data); + + return 0; +} + +API int pkgmgr_installer_send_pkg_upgrade_signal(pkgmgr_installer *pi, + unsigned int progress) +{ + const char *signal_name; + GError *err = NULL; + + if (!pi) { + ERR("invalid argument"); + return -1; + } + + signal_name = PKGMGR_INSTALLER_PKG_UPGRADE_EVENT_STR; + if (g_dbus_connection_emit_signal(pi->conn, NULL, + PKGMGR_INSTALLER_DBUS_OBJECT_PATH, + PKGMGR_INSTALLER_DBUS_INTERFACE, signal_name, + g_variant_new("(u)", progress), + &err) != TRUE) { + ERR("failed to send dbus signal"); + if (err) { + ERR("err: %s", err->message); + g_error_free(err); + } + return -1; + } + + return 0; +} diff --git a/installer/src/pkgmgr_installer.h b/installer/src/pkgmgr_installer.h index af71836..07b2e5e 100644 --- a/installer/src/pkgmgr_installer.h +++ b/installer/src/pkgmgr_installer.h @@ -43,7 +43,7 @@ extern "C" { /** * pkgmgr_installer is an opaque type for an object */ -typedef void pkgmgr_installer; +typedef struct pkgmgr_installer pkgmgr_installer; typedef void *pkgmgr_instcertinfo_h; /** diff --git a/installer/src/pkgmgr_installer_debug.h b/installer/src/pkgmgr_installer_debug.h index a92a883..26df677 100644 --- a/installer/src/pkgmgr_installer_debug.h +++ b/installer/src/pkgmgr_installer_debug.h @@ -25,16 +25,16 @@ #endif /* LOG_TAG */ #define LOG_TAG "PKGMGR_INSTALLER" -#ifndef _E -#define _E LOGE +#ifndef ERR +#define ERR(fmt, args...) LOGE("[%s:%d] "fmt"\n", __func__, __LINE__, ##args) #endif -#ifndef _D -#define _D LOGD +#ifndef DBG +#define DBG(fmt, args...) LOGD("[%s:%d] "fmt"\n", __func__, __LINE__, ##args) #endif -#ifndef _I -#define _I LOGI +#ifndef INFO +#define INFO(fmt, args...) LOGI("[%s:%d] "fmt"\n", __func__, __LINE__, ##args) #endif #endif /* __PKGMGR_INSTALLER_DEBUG_H__ */ diff --git a/installer/src/request.hh b/installer/src/request.hh index d8e49ad..d9c48d0 100644 --- a/installer/src/request.hh +++ b/installer/src/request.hh @@ -24,8 +24,6 @@ #include #include -#include "PkgSignal.h" - namespace pkgmgr { namespace installer { -- 2.7.4