From fac50248a3f8d3a93f0a96d64c820712151d06fa Mon Sep 17 00:00:00 2001 From: Ilho Kim Date: Tue, 27 Jul 2021 17:19:29 +0900 Subject: Add api for resource copy -pkgmgr_client_add_res_copy_path -pkgmgr_client_res_copy -pkgmgr_client_add_res-remove_path -pkgmgr_client_res_remove -pkgmgr_client_res_uninstall -pkgmgr_client_res_usr_uninstall Change-Id: I50f1c5eeec8e1593b0909a21bd18afee34d2ef39 Signed-off-by: Ilho Kim --- client/include/package-manager.h | 87 +++++++++++++ client/src/pkgmgr.c | 236 ++++++++++++++++++++++++++++++++++ client/src/pkgmgr_client_connection.c | 6 +- client/src/pkgmgr_client_internal.h | 3 + 4 files changed, 331 insertions(+), 1 deletion(-) diff --git a/client/include/package-manager.h b/client/include/package-manager.h index e710850..662f784 100644 --- a/client/include/package-manager.h +++ b/client/include/package-manager.h @@ -156,6 +156,7 @@ typedef enum _pkgmgr_return_val { typedef void pkgmgr_client; typedef void pkgmgr_info; +typedef void *pkgmgr_res_cb_info_h; typedef struct { long long data_size; @@ -195,6 +196,10 @@ typedef void (*pkgmgr_pkg_size_info_receive_cb)(pkgmgr_client *pc, const char *p typedef void (*pkgmgr_total_pkg_size_info_receive_cb)(pkgmgr_client *pc, const pkg_size_info_t *size_info, void *user_data); +typedef void (*pkgmgr_res_request_cb)(uid_t target_uid, int req_id, + const char *pkgid, const char *request_type, const char *status, + pkgmgr_res_cb_info_h handle, void *user_data); + typedef enum { PC_REQUEST = 0, PC_LISTENING, @@ -1195,6 +1200,88 @@ int pkgmgr_client_set_skip_optimization(pkgmgr_client *pc, bool skip_optimizatio */ int pkgmgr_client_usr_migrate_external_image(pkgmgr_client *pc, const char *pkgid, uid_t uid); +/** + * @brief Add resource path to copy + * + * This API adds path for resource copy request.\n + * + * @param[in] pc The pointer to pkgmgr_client instance + * @param[in] src_path Path of a resource that client want to copy + * @param[in] dest_path Destination path to copy source path, if dest_path is null it will be set to root path of the package's sharing resource directory + * @return 0 if success, error code(<0) if fail\n + * @retval PKGMGR_R_OK success + * @retval PKGMGR_R_EINVAL invalid argument + * @retval PKGMGR_R_ENOMEM out of memory + */ +int pkgmgr_client_add_res_copy_path(pkgmgr_client *pc, const char *src_path, const char *dest_path); + +/** + * @brief This API copy resources. + * + * This API is for package-manager client application.\n + * + * @param[in] pc pkgmgr_client + * @param[in] event_cb user callback + * @param[in] data user data + * @return request_id (>0) if success, error code(<0) if fail\n + * @retval PKGMGR_R_OK success + * @retval PKGMGR_R_ECOMM communication error + * @retval PKGMGR_R_EINVAL invalid argument + * @retval PKGMGR_R_ENOMEM out of memory + * @retval PKGMGR_R_EPRIV privilege denied +*/ +int pkgmgr_client_res_copy(pkgmgr_client *pc, pkgmgr_res_request_cb event_cb, void *user_data); + +/** + * @brief Add resource path to remove + * + * This API adds path for resource remove request.\n + * + * @param[in] pc The pointer to pkgmgr_client instance + * @param[in] res_path Path of a copied resource that client want to remove + * @return 0 if success, error code(<0) if fail\n + * @retval PKGMGR_R_OK success + * @retval PKGMGR_R_EINVAL invalid argument + * @retval PKGMGR_R_ENOMEM out of memory + */ +int pkgmgr_client_add_res_remove_path(pkgmgr_client *pc, const char *res_path); + +/** + * @brief This API removes resources. + * + * This API is for package-manager client application.\n + * + * @param[in] pc pkgmgr_client + * @param[in] event_cb user callback + * @param[in] data user data + * @return request_id (>0) if success, error code(<0) if fail\n + * @retval PKGMGR_R_OK success + * @retval PKGMGR_R_ECOMM communication error + * @retval PKGMGR_R_EINVAL invalid argument + * @retval PKGMGR_R_ENOMEM out of memory + * @retval PKGMGR_R_EPRIV privilege denied +*/ +int pkgmgr_client_res_remove(pkgmgr_client *pc, pkgmgr_res_request_cb event_cb, void *user_data); + +/** + * @brief This API uninstall copied resources of the package. + * + * This API is for package-manager client application.\n + * + * @param[in] pc pkgmgr_client + * @param[in] pkgid package id + * @param[in] event_cb user callback + * @param[in] user_data user data + * @return request_id (>0) if success, error code(<0) if fail\n + * @retval PKGMGR_R_OK success + * @retval PKGMGR_R_ECOMM communication error + * @retval PKGMGR_R_EINVAL invalid argument + * @retval PKGMGR_R_ENOMEM out of memory + * @retval PKGMGR_R_EPRIV privilege denied + */ +int pkgmgr_client_res_uninstall(pkgmgr_client *pc, const char *pkgid, pkgmgr_res_request_cb event_cb, void *user_data); +int pkgmgr_client_res_usr_uninstall(pkgmgr_client *pc, const char *pkgid, pkgmgr_res_request_cb event_cb, void *user_data, uid_t uid); + /** @} */ diff --git a/client/src/pkgmgr.c b/client/src/pkgmgr.c index 16d61ed..2e7d350 100644 --- a/client/src/pkgmgr.c +++ b/client/src/pkgmgr.c @@ -141,6 +141,36 @@ static struct cb_info *__create_app_event_cb_info( return cb_info; } +static struct cb_info *__create_res_request_cb_info( + struct pkgmgr_client_t *client, + pkgmgr_res_request_cb res_request_cb, + void *data, const char *req_key) +{ + struct cb_info *cb_info; + + cb_info = calloc(1, sizeof(struct cb_info)); + if (cb_info == NULL) { + ERR("out of memory"); + return NULL; + } + + cb_info->client = client; + cb_info->res_request_cb = res_request_cb; + cb_info->data = data; + cb_info->req_id = _get_internal_request_id(); + if (req_key == NULL) + return cb_info; + + cb_info->req_key = strdup(req_key); + if (cb_info->req_key == NULL) { + ERR("out of memory"); + free(cb_info); + return NULL; + } + + return cb_info; +} + static struct cb_info *__create_size_info_cb_info( struct pkgmgr_client_t *client, pkgmgr_pkg_size_info_receive_cb size_info_cb, @@ -383,6 +413,10 @@ API int pkgmgr_client_free(pkgmgr_client *pc) pkgmgr_client_connection_disconnect(client); if (client->tep_path) free(client->tep_path); + if (client->res_copy_builder) + g_variant_builder_unref(client->res_copy_builder); + if (client->res_remove_builder) + g_variant_builder_unref(client->res_remove_builder); free(client); return PKGMGR_R_OK; @@ -2726,3 +2760,205 @@ API int pkgmgr_client_usr_migrate_external_image(pkgmgr_client *pc, return ret; } + +API int pkgmgr_client_add_res_copy_path(pkgmgr_client *pc, + const char *src_path, const char *dest_path) +{ + struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc; + + if (pc == NULL || src_path == NULL) { + ERR("invalid parameter"); + return PKGMGR_R_EINVAL; + } + + if (client->res_copy_builder == NULL) { + client->res_copy_builder = + g_variant_builder_new(G_VARIANT_TYPE("a(ss)")); + if (client->res_copy_builder == NULL) { + ERR("out of memory"); + return PKGMGR_R_ENOMEM; + } + } + + g_variant_builder_add(client->res_copy_builder, "(ss)", + src_path, dest_path ? dest_path : ""); + + return PKGMGR_R_OK; +} + +API int pkgmgr_client_res_copy(pkgmgr_client *pc, + pkgmgr_res_request_cb event_cb, void *user_data) +{ + GVariant *result; + int ret; + char *req_key = NULL; + struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc; + struct cb_info *cb_info; + + if (pc == NULL || event_cb == NULL) { + ERR("invalid parameter"); + return PKGMGR_R_EINVAL; + } + + ret = pkgmgr_client_connection_send_request(client, + "res_copy", + g_variant_new("(a(ss))", + client->res_copy_builder), &result); + if (ret != PKGMGR_R_OK) { + ERR("request failed: %d", ret); + return ret; + } + + g_variant_get(result, "(i&s)", &ret, &req_key); + if (req_key == NULL) { + g_variant_unref(result); + return PKGMGR_R_ECOMM; + } + if (ret != PKGMGR_R_OK) { + g_variant_unref(result); + return ret; + } + + cb_info = __create_res_request_cb_info(client, + event_cb, user_data, req_key); + g_variant_unref(result); + if (cb_info == NULL) + return PKGMGR_R_ENOMEM; + + ret = pkgmgr_client_connection_set_callback(client, cb_info); + if (ret != PKGMGR_R_OK) { + __free_cb_info(cb_info); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, cb_info); + + return cb_info->req_id; +} + +API int pkgmgr_client_add_res_remove_path(pkgmgr_client *pc, + const char *res_path) +{ + struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc; + + if (pc == NULL || res_path == NULL) { + ERR("invalid parameter"); + return PKGMGR_R_EINVAL; + } + + if (client->res_remove_builder == NULL) { + client->res_remove_builder = + g_variant_builder_new(G_VARIANT_TYPE("as")); + if (client->res_remove_builder == NULL) { + ERR("out of memory"); + return PKGMGR_R_ENOMEM; + } + } + + g_variant_builder_add(client->res_remove_builder, "s", res_path); + + return PKGMGR_R_OK; +} + +API int pkgmgr_client_res_remove(pkgmgr_client *pc, + pkgmgr_res_request_cb event_cb, void *user_data) +{ + GVariant *result; + int ret; + char *req_key = NULL; + struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc; + struct cb_info *cb_info; + + if (pc == NULL || event_cb == NULL) { + ERR("invalid parameter"); + return PKGMGR_R_EINVAL; + } + + ret = pkgmgr_client_connection_send_request(client, + "res_remove", + g_variant_new("(as)", + client->res_remove_builder), &result); + if (ret != PKGMGR_R_OK) { + ERR("request failed: %d", ret); + return ret; + } + + g_variant_get(result, "(i&s)", &ret, &req_key); + if (req_key == NULL) { + g_variant_unref(result); + return PKGMGR_R_ECOMM; + } + if (ret != PKGMGR_R_OK) { + g_variant_unref(result); + return ret; + } + + cb_info = __create_res_request_cb_info(client, + event_cb, user_data, req_key); + g_variant_unref(result); + if (cb_info == NULL) + return PKGMGR_R_ENOMEM; + + ret = pkgmgr_client_connection_set_callback(client, cb_info); + if (ret != PKGMGR_R_OK) { + __free_cb_info(cb_info); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, cb_info); + + return cb_info->req_id; +} + +API int pkgmgr_client_res_uninstall(pkgmgr_client *pc, const char *pkgid, + pkgmgr_res_request_cb event_cb, void *user_data) +{ + return pkgmgr_client_res_usr_uninstall(pc, pkgid, event_cb, + user_data, _getuid()); +} + +API int pkgmgr_client_res_usr_uninstall(pkgmgr_client *pc, const char *pkgid, + pkgmgr_res_request_cb event_cb, void *user_data, uid_t uid) +{ + GVariant *result; + int ret = PKGMGR_R_ECOMM; + char *req_key = NULL; + struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc; + struct cb_info *cb_info; + + if (pc == NULL || pkgid == NULL || event_cb == NULL) { + ERR("invalid parameter"); + return PKGMGR_R_EINVAL; + } + + ret = pkgmgr_client_connection_send_request(client, + "res_uninstall", + g_variant_new("(us)", uid, pkgid), &result); + if (ret != PKGMGR_R_OK) { + ERR("request failed: %d", ret); + return ret; + } + + g_variant_get(result, "(i&s)", &ret, &req_key); + if (req_key == NULL) { + g_variant_unref(result); + return PKGMGR_R_ECOMM; + } + if (ret != PKGMGR_R_OK) { + g_variant_unref(result); + return ret; + } + + cb_info = __create_res_request_cb_info(client, + event_cb, user_data, req_key); + g_variant_unref(result); + if (cb_info == NULL) + return PKGMGR_R_ENOMEM; + + ret = pkgmgr_client_connection_set_callback(client, cb_info); + if (ret != PKGMGR_R_OK) { + __free_cb_info(cb_info); + return ret; + } + client->cb_info_list = g_list_append(client->cb_info_list, cb_info); + + return cb_info->req_id; +} diff --git a/client/src/pkgmgr_client_connection.c b/client/src/pkgmgr_client_connection.c index e5c909d..e83fda1 100644 --- a/client/src/pkgmgr_client_connection.c +++ b/client/src/pkgmgr_client_connection.c @@ -225,8 +225,12 @@ static void __signal_handler(GDBusConnection *conn, const gchar *sender_name, 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) + } else if (cb_info->size_info_cb) { __handle_size_info_callback(cb_info, pkgid, val); + } else if (cb_info->res_request_cb) { + // TODO(ilho159.kim): + //Need to handle resource copy request's event callback + } /* TODO: unsubscribe request callback */ } diff --git a/client/src/pkgmgr_client_internal.h b/client/src/pkgmgr_client_internal.h index 7f434c1..d356b58 100644 --- a/client/src/pkgmgr_client_internal.h +++ b/client/src/pkgmgr_client_internal.h @@ -41,6 +41,7 @@ struct cb_info { pkgmgr_handler event_cb; pkgmgr_app_handler app_event_cb; pkgmgr_pkg_size_info_receive_cb size_info_cb; + pkgmgr_res_request_cb res_request_cb; void *data; struct pkgmgr_client_t *client; GList *sid_list; @@ -51,6 +52,8 @@ struct pkgmgr_client_t { int status_type; GDBusConnection *conn; GList *cb_info_list; + GVariantBuilder *res_copy_builder; + GVariantBuilder *res_remove_builder; char *tep_path; bool tep_move; bool debug_mode; -- cgit v1.2.3