From ee31c9d447801e2640cd642b0883a6767633e2c9 Mon Sep 17 00:00:00 2001 From: Ilho Kim Date: Thu, 26 Aug 2021 15:14:24 +0900 Subject: [PATCH] Add api for resource copy Change-Id: Iaab6a96888b3ea8f894e5f4acefe7b5be46a3b7d Signed-off-by: Ilho Kim --- include/package_manager.h | 257 ++++++++++++++++++++ src/package_manager.c | 585 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 835 insertions(+), 7 deletions(-) diff --git a/include/package_manager.h b/include/package_manager.h index bcb0b21..21cefce 100644 --- a/include/package_manager.h +++ b/include/package_manager.h @@ -103,6 +103,10 @@ typedef enum { PACKAGE_MANAGER_EVENT_TYPE_UPDATE, /**< Update event type */ PACKAGE_MANAGER_EVENT_TYPE_MOVE, /**< Move event type (Since 3.0) */ PACKAGE_MANAGER_EVENT_TYPE_CLEAR, /**< Clear event type (Since 3.0) */ + PACKAGE_MANAGER_EVENT_TYPE_RES_COPY, /**< Resource copy event type (Since 6.5) */ + PACKAGE_MANAGER_EVENT_TYPE_RES_CREATE_DIR, /**< Create directory for resource event type (Since 6.5) */ + PACKAGE_MANAGER_EVENT_TYPE_RES_REMOVE, /**< Remove resource event type (Since 6.5) */ + PACKAGE_MANAGER_EVENT_TYPE_RES_UNINSTALL, /**< Uninstall resource event type (Since 6.5) */ } package_manager_event_type_e; @@ -166,8 +170,23 @@ typedef enum { PACKAGE_MANAGER_STATUS_TYPE_CLEAR_DATA = 0x10, /**< Clear data status */ PACKAGE_MANAGER_STATUS_TYPE_INSTALL_PROGRESS = 0x20, /**< Install progress status */ PACKAGE_MANAGER_STATUS_TYPE_GET_SIZE = 0x40, /**< Get size status */ + PACKAGE_MANAGER_STATUS_TYPE_RES_COPY = 0x80, /**< Resource copy status (Since 6.5) */ + PACKAGE_MANAGER_STATUS_TYPE_RES_CREATE_DIR = 0x100, /**< Resource create directory status (Since 6.5) */ + PACKAGE_MANAGER_STATUS_TYPE_RES_REMOVE = 0x200, /**< Resource remove status (Since 6.5) */ + PACKAGE_MANAGER_STATUS_TYPE_RES_UNINSTALL = 0x400, /**< Resource uninstall status (Since 6.5) */ } package_manager_status_type_e; + +/** + * @brief Enumeration for resource event path state. + * @since_tizen 6.5 + */ +typedef enum { + PACKAGE_MANAGER_RES_EVENT_PATH_STATE_NONE = 0, /**< State that operation do nothing about the path */ + PACKAGE_MANAGER_RES_EVENT_PATH_STATE_OK, /**< State that operation success about the path */ + PACKAGE_MANAGER_RES_EVENT_PATH_STATE_FAILED, /**< State that operation fail about the path */ +} package_manager_res_event_path_state_e; + /** * @brief The Package manager update info request handle. * @since_tizen 4.0 @@ -187,6 +206,11 @@ typedef struct package_manager_s *package_manager_h; */ typedef struct package_manager_filter_s *package_manager_filter_h; +/** + * @brief Resource share event handle. + * @since_tizen 6.5 + */ +typedef struct package_manager_res_event_info_s *package_manager_res_event_info_h; /** * @brief Called when the package is installed, uninstalled, or updated, and the progress of the request to the package manager changes. @@ -204,6 +228,24 @@ typedef struct package_manager_filter_s *package_manager_filter_h; */ typedef void (*package_manager_event_cb) (const char *type, const char *package, package_manager_event_type_e event_type, package_manager_event_state_e event_state, int progress, package_manager_error_e error, void *user_data); +/** + * @brief Called when the progress of the request to the package resource share changes. + * @since_tizen 6.5 + * @remarks The @a pkgid should not be released. The @a pkgid can be used only in the callback. + * @remarks The @a handle should not be released. The @a handle can be used only in the callback. + * @param[in] pkgid The package ID of resource owner + * @param[in] event_type The type of resource event + * @param[in] event_state The state of resource event + * @param[in] handle The handle which contains additional information of event + * @param[in] user_data The user data passed from package_manager_set_res_event_cb() + * @see package_manager_set_res_event_cb() + * @see package_manager_unset_event_cb() + */ +typedef void (*package_manager_res_event_cb) (const char *pkgid, + package_manager_event_type_e event_type, + package_manager_event_state_e event_state, + package_manager_res_event_info_h handle, void *user_data); + /** * @brief Creates a package manager handle. @@ -276,6 +318,28 @@ int package_manager_set_event_cb(package_manager_h manager, package_manager_even /** + * @platform + * @brief Registers a callback function to be invoked when the progress of the request to the package resource share changes. + * @since_tizen 6.5 + * @privlevel platform + * @privilege %http://tizen.org/privilege/packagemanager.admin + * @param[in] manager The package manager handle + * @param[in] callback The callback function to be registered + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PACKAGE_MANAGER_ERROR_NONE Successful + * @retval #PACKAGE_MANAGER_ERROR_PERMISSION_DENIED Permission denied + * @retval #PACKAGE_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter + * @post package_manager_res_event_cb() will be invoked. + * @see package_manager_set_event_status() + * @see package_manager_res_event_cb() + * @see package_manager_unset_event_cb() + */ +int package_manager_set_res_event_cb(package_manager_h manager, package_manager_res_event_cb callback, void *user_data); + + +/** * @brief Unregisters the callback function. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * @param[in] manager The package manager handle @@ -854,6 +918,27 @@ typedef void (*package_manager_request_event_cb) (int id, const char *type, cons /** * @platform + * @brief Called when the progress of the request to the package resource share changes. + * @since_tizen 6.5 + * @remarks The @a pkgid should not be released. The @a pkgid can be used only in the callback. + * @remarks The @a handle should not be released. The @a handle can be used only in the callback. + * @param[in] req_id The ID of the request to the package manager + * @param[in] pkgid The package ID of resource owner + * @param[in] event_type The type of resource event + * @param[in] event_state The state of resource event + * @param[in] handle The handle which contains additional information of event + * @param[in] user_data The user data passed from package_manager_request_res_copy_with_cb(), package_manager_request_res_create_dir_with_cb(), package_manager_request_res_remove_with_cb() + * @see package_manager_request_res_copy_with_cb() + * @see package_manager_request_res_create_dir_with_cb() + * @see package_manager_request_res_remove_with_cb() + */ +typedef void (*package_manager_request_res_event_cb) (int req_id, + const char *pkgid, package_manager_event_type_e event_type, package_manager_event_state_e event_state, + package_manager_res_event_info_h handle, void *user_data); + + +/** + * @platform * @brief Creates a request handle to the package manager. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * @remarks You must release @a request using package_manager_request_destroy(). @@ -1275,6 +1360,178 @@ int package_manager_updateinfo_request_unregister(package_updateinfo_request_h p */ int package_manager_updateinfo_request_unregister_all(package_updateinfo_request_h pkg_updateinfo_req); +/** + * @platform + * @brief Adds resource source and destination path into handle. + * @details Adds resource source path and destination path to be copied into handle + * @since_tizen 6.5 + * @privlevel platform + * @privilege %http://tizen.org/privilege/packagemanager.admin + * @param[in] request The package manager request handle + * @param[in] src_path The relative path of resource file or directory to be copied + * @param[in] dest_path The relative path of destination + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PACKAGE_MANAGER_ERROR_NONE Successful + * @retval #PACKAGE_MANAGER_ERROR_PERMISSION_DENIED Permission denied + * @retval #PACKAGE_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PACKAGE_MANAGER_ERROR_SYSTEM_ERROR Severe system error + * @see package_manager_request_res_copy_with_cb() + */ +int package_manager_request_add_res_copy_path(package_manager_request_h request, const char *src_path, const char *dest_path); + +/** + * @platform + * @brief Copies resources into target directory, asynchronously. + * @details Copies resources into directory, which could be access via privileged applications only. + * @since_tizen 6.5 + * @privlevel platform + * @privilege %http://tizen.org/privilege/packagemanager.admin + * @param[in] request The package manager request handle + * @param[in] callback The callback function to be invoked + * @param[in] user_data The user data to be passed to the callback function + * @param[out] id The ID of the request to the package manager + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PACKAGE_MANAGER_ERROR_NONE Successful + * @retval #PACKAGE_MANAGER_ERROR_PERMISSION_DENIED Permission denied + * @retval #PACKAGE_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PACKAGE_MANAGER_ERROR_OUT_OF_MEMORY Out of memory + * @retval #PACKAGE_MANAGER_ERROR_IO_ERROR I/O error + * @retval #PACKAGE_MANAGER_ERROR_SYSTEM_ERROR Severe system error + * @see package_manager_request_add_res_copy_path() + */ +int package_manager_request_res_copy_with_cb(package_manager_request_h request, package_manager_request_res_event_cb callback, void *user_data, int *id); + +/** + * @platform + * @brief Add directory path to be created at privileged shared directory into handle. + * @details Added directory path will be created into directory existed for sharing resources via privileged applications + * @since_tizen 6.5 + * @privlevel platform + * @privilege %http://tizen.org/privilege/packagemanager.admin + * @param[in] request The package manager request handle + * @param[in] dir_path The relative path of directories to be created under shared resource path + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PACKAGE_MANAGER_ERROR_NONE Successful + * @retval #PACKAGE_MANAGER_ERROR_PERMISSION_DENIED Permission denied + * @retval #PACKAGE_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PACKAGE_MANAGER_ERROR_SYSTEM_ERROR Severe system error + * @see package_manager_request_res_create_dir_with_cb() + */ +int package_manager_request_add_res_create_dir_path(package_manager_request_h request, const char *dir_path); + +/** + * @platform + * @brief Create directories into directory for sharing resources via privileged application, asynchronously. + * @details Create directories into certain directory which could be access via privileged applications only. + * @since_tizen 6.5 + * @privlevel platform + * @privilege %http://tizen.org/privilege/packagemanager.admin + * @param[in] request The package manager request handle + * @param[in] callback The callback function to be invoked + * @param[in] user_data The user data to be passed to the callback function + * @param[out] id The ID of the request to the package manager + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PACKAGE_MANAGER_ERROR_NONE Successful + * @retval #PACKAGE_MANAGER_ERROR_PERMISSION_DENIED Permission denied + * @retval #PACKAGE_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PACKAGE_MANAGER_ERROR_OUT_OF_MEMORY Out of memory + * @see package_manager_request_add_res_create_dir_path() + */ +int package_manager_request_res_create_dir_with_cb(package_manager_request_h request, package_manager_request_res_event_cb callback, void *user_data, int *id); + +/** + * @platform + * @brief Adds file or directory path to be removed located at privileged shared directory into handle. + * @details Added path will be removed from directory existed for sharing resources via privileged applications + * @since_tizen 6.5 + * @privlevel platform + * @privilege %http://tizen.org/privilege/packagemanager.admin + * @param[in] request The package manager request handle + * @param[in] res_path The relative path of resources to be removed from privileged shared resource directory + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PACKAGE_MANAGER_ERROR_NONE Successful + * @retval #PACKAGE_MANAGER_ERROR_PERMISSION_DENIED Permission denied + * @retval #PACKAGE_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PACKAGE_MANAGER_ERROR_SYSTEM_ERROR Severe system error + * @see package_manager_request_res_remove_with_cb() + */ +int package_manager_request_add_res_remove_path(package_manager_request_h request, const char *res_path); + +/** + * @platform + * @brief Removes resources from for sharing resources via privileged application, asynchronously. + * @details Removes resources added at handle from certain directory which could be access via privileged applications only. + * @since_tizen 6.5 + * @privlevel platform + * @privilege %http://tizen.org/privilege/packagemanager.admin + * @param[in] request The package manager request handle + * @param[in] callback The callback function to be invoked + * @param[in] user_data The user data to be passed to the callback function + * @param[out] id The ID of the request to the package manager + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PACKAGE_MANAGER_ERROR_NONE Successful + * @retval #PACKAGE_MANAGER_ERROR_PERMISSION_DENIED Permission denied + * @retval #PACKAGE_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PACKAGE_MANAGER_ERROR_OUT_OF_MEMORY Out of memory + * @see package_manager_request_add_res_remove_path() + */ +int package_manager_request_res_remove_with_cb(package_manager_request_h request, package_manager_request_res_event_cb callback, void *user_data, int *id); + +/** + * @platform + * @brief Gets the error code from given resource event handle. + * @since_tizen 6.5 + * @privlevel platform + * @privilege %http://tizen.org/privilege/packagemanager.admin + * @param[in] handle Resource event info handle + * @param[out] error Error will be returned + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PACKAGE_MANAGER_ERROR_NONE Successful + * @retval #PACKAGE_MANAGER_ERROR_PERMISSION_DENIED Permission denied + * @retval #PACKAGE_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter + */ +int package_manager_res_event_info_get_error_code(package_manager_res_event_info_h handle, package_manager_error_e *error); + + +/** + * @brief Called to retrieve all path state about resource event. + * @since_tizen 6.5 + * @remarks The @a path should not be released. The @a path can be used only in the callback. + * @param[in] path The path handled by a resource event + * @param[in] state The state of the path + * @param[in] user_data The user data passed from the foreach function + * @return @c true to continue with the next iteration of the loop, + * otherwise @c false to break out of the loop + * @see package_manager_res_event_info_foreach_path() + */ +typedef bool (*package_manager_res_event_path_cb) (const char *path, package_manager_res_event_path_state_e state, void *user_data); + +/** + * @platform + * @brief Retrieves all package information of installed packages. + * @since_tizen 6.5 + * @privlevel platform + * @privilege %http://tizen.org/privilege/packagemanager.admin + * @param[in] handle Resource event info handle + * @param[in] callback The callback function to be invoked + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PACKAGE_MANAGER_ERROR_NONE Successful + * @retval #PACKAGE_MANAGER_ERROR_PERMISSION_DENIED Permission denied + * @retval #PACKAGE_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter + * @post This function invokes package_manager_res_event_path_cb() repeatedly for each path state handled by resource event. + * @see package_manager_res_event_path_cb() + */ +int package_manager_res_event_info_foreach_path(package_manager_res_event_info_h handle, package_manager_res_event_path_cb callback, void *user_data); + /** * @} diff --git a/src/package_manager.c b/src/package_manager.c index 2485c5f..2dbee7f 100644 --- a/src/package_manager.c +++ b/src/package_manager.c @@ -49,6 +49,7 @@ struct package_manager_s { pkgmgr_mode mode; GHashTable *event_info_table; package_manager_event_cb event_cb; + package_manager_res_event_cb res_event_cb; void *user_data; GMutex mutex; }; @@ -69,6 +70,7 @@ struct package_manager_request_s { struct package_manager_request_cb_info { int req_id; package_manager_request_event_cb callback; + package_manager_request_res_event_cb res_callback; void *user_data; }; @@ -91,6 +93,10 @@ struct package_updateinfo_request_s { pkg_update_info_t *updateinfo_handle; }; +struct package_manager_res_event_info_s { + pkgmgr_res_event_info *res_event_info_handle; +}; + static int package_manager_request_new_id() { static int request_handle_id = 0; @@ -189,6 +195,27 @@ static int __insert_request_cb_info(package_manager_request_h request, int req_i return 0; } +static int __insert_res_request_cb_info(package_manager_request_h request, + int req_id, package_manager_request_res_event_cb callback, + void *user_data) +{ + struct package_manager_request_cb_info *cb_info; + + if (request->request_cb_table == NULL) + return -1; + + cb_info = calloc(1, sizeof(struct package_manager_request_cb_info)); + if (cb_info == NULL) + return -1; + cb_info->req_id = req_id; + cb_info->res_callback = callback; + cb_info->user_data = user_data; + _LOGD("insert req_id(%d)", req_id); + g_hash_table_insert(request->request_cb_table, GINT_TO_POINTER(cb_info->req_id), cb_info); + + return 0; +} + API int package_manager_request_create(package_manager_request_h *request) { struct package_manager_request_s *package_manager_request; @@ -368,16 +395,22 @@ static int package_manager_get_event_type(const char *key, *event_type = PACKAGE_MANAGER_EVENT_TYPE_MOVE; else if (strcasecmp(key, PKGMGR_INSTALLER_CLEAR_EVENT_STR) == 0) *event_type = PACKAGE_MANAGER_EVENT_TYPE_CLEAR; + else if (strcasecmp(key, PKGMGR_INSTALLER_RES_COPY_EVENT_STR) == 0) + *event_type = PACKAGE_MANAGER_EVENT_TYPE_RES_COPY; + else if (strcasecmp(key, PKGMGR_INSTALLER_RES_CREATE_DIR_EVENT_STR) == 0) + *event_type = PACKAGE_MANAGER_EVENT_TYPE_RES_CREATE_DIR; + else if (strcasecmp(key, PKGMGR_INSTALLER_RES_REMOVE_EVENT_STR) == 0) + *event_type = PACKAGE_MANAGER_EVENT_TYPE_RES_REMOVE; + else if (strcasecmp(key, PKGMGR_INSTALLER_RES_UNINSTALL_EVENT_STR) == 0) + *event_type = PACKAGE_MANAGER_EVENT_TYPE_RES_UNINSTALL; else return PACKAGE_MANAGER_ERROR_INVALID_PARAMETER; return PACKAGE_MANAGER_ERROR_NONE; } -static package_manager_error_e __convert_to_error(const char *val) +static package_manager_error_e __convert_to_error(int errcode) { - int errcode = atoi(val); - switch (errcode) { case PKGMGR_INSTALLER_ERRCODE_UNDEFINED_ERROR: case PKGMGR_INSTALLER_ERRCODE_GLOBALSYMLINK_ERROR: @@ -418,6 +451,13 @@ static package_manager_error_e __convert_to_error(const char *val) } } +static package_manager_error_e __convert_str_to_error(const char *val) +{ + int errcode = atoi(val); + + return __convert_to_error(errcode); +} + static int __add_event_info(request_event_info **head, int req_id, package_manager_event_type_e event_type, package_manager_event_state_e event_state) @@ -561,7 +601,7 @@ static int request_event_handler(uid_t target_uid, int req_id, const char *pkg_t pkg_name, event_type, PACKAGE_MANAGER_EVENT_STATE_FAILED, 0, - __convert_to_error(val), + __convert_str_to_error(val), request->user_data); } else if (strcasecmp(key, "end") == 0) { @@ -661,7 +701,7 @@ static int internal_request_callback(uid_t target_uid, int req_id, const char *p pkg_name, event_type, PACKAGE_MANAGER_EVENT_STATE_FAILED, 0, - __convert_to_error(val), + __convert_str_to_error(val), user_data); } } else if (strcasecmp(key, "end") == 0) { @@ -701,6 +741,68 @@ static int internal_request_callback(uid_t target_uid, int req_id, const char *p return 0; } +static void internal_res_request_callback(uid_t target_uid, int req_id, + const char *pkgid, const char *request_type, const char *status, + pkgmgr_res_event_info *handle, void *data) +{ + int ret; + package_manager_event_type_e event_type = -1; + package_manager_event_state_e event_state = -1; + struct package_manager_request_cb_info *cb_info; + package_manager_request_res_event_cb event_cb; + struct package_manager_res_event_info_s event_info; + void *user_data = NULL; + + _LOGD("request callback called, req_id[%d]", req_id); + + package_manager_request_h request = data; + event_info.res_event_info_handle = handle; + + if (request->request_cb_table) + cb_info = g_hash_table_lookup(request->request_cb_table, + GINT_TO_POINTER(req_id)); + else + cb_info = NULL; + + if (!cb_info || (cb_info && !cb_info->res_callback)) { + _LOGE("no callback info"); + return; + } + + if (cb_info->req_id != req_id) { + _LOGE("not matched request id"); + return; + } + + event_cb = cb_info->res_callback; + user_data = cb_info->user_data; + + ret = package_manager_get_event_type(request_type, &event_type); + if (ret != PACKAGE_MANAGER_ERROR_NONE) + return; + if (strcasecmp(status, "start") == 0) { + event_state = PACKAGE_MANAGER_EVENT_STATE_STARTED; + } else if (strcasecmp(status, "fail") == 0) { + event_state = PACKAGE_MANAGER_EVENT_STATE_FAILED; + _LOGD("remove item, req_id(%d)", req_id); + g_hash_table_remove(request->request_cb_table, + GINT_TO_POINTER(req_id)); + } else if (strcasecmp(status, "ok") == 0) { + event_state = PACKAGE_MANAGER_EVENT_STATE_COMPLETED; + _LOGD("remove item, req_id(%d)", req_id); + g_hash_table_remove(request->request_cb_table, + GINT_TO_POINTER(req_id)); + } else { + _LOGE("unexpected event"); + return; + } + + event_cb(req_id, pkgid, event_type, event_state, + &event_info, user_data); + + return; +} + static int __request_install(package_manager_request_h request, const char *path, pkgmgr_handler event_cb, int *id) { @@ -965,6 +1067,99 @@ static int __request_mount_install_packages(package_manager_request_h request, return PACKAGE_MANAGER_ERROR_NONE; } +static int __request_res_copy(package_manager_request_h request, + pkgmgr_res_handler event_cb, int *id) +{ + int retval; + retval = check_privilege(PRIVILEGE_PACKAGE_MANAGER_ADMIN); + if (retval != PACKAGE_MANAGER_ERROR_NONE) + return retval; + + if (package_manager_client_validate_handle(request)) + return package_manager_error(PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + int request_id = 0; + request_id = pkgmgr_client_res_copy(request->pc, event_cb, request); + + if (request_id == PKGMGR_R_EINVAL) + return package_manager_error(PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + else if (request_id == PKGMGR_R_ENOMEM) + return package_manager_error(PACKAGE_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); + else if (request_id == PKGMGR_R_EIO) + return package_manager_error(PACKAGE_MANAGER_ERROR_IO_ERROR, __FUNCTION__, NULL); + else if (request_id == PKGMGR_R_EPRIV) + return package_manager_error(PACKAGE_MANAGER_ERROR_PERMISSION_DENIED, __FUNCTION__, NULL); + else if (request_id == PKGMGR_R_ESYSTEM || request_id == PKGMGR_R_ECOMM || request_id == PKGMGR_R_ERROR) + return package_manager_error(PACKAGE_MANAGER_ERROR_SYSTEM_ERROR, __FUNCTION__, NULL); + + if (id) + *id = request_id; + + return PACKAGE_MANAGER_ERROR_NONE; +} + +static int __request_res_create_dir(package_manager_request_h request, + pkgmgr_res_handler event_cb, int *id) +{ + int retval; + retval = check_privilege(PRIVILEGE_PACKAGE_MANAGER_ADMIN); + if (retval != PACKAGE_MANAGER_ERROR_NONE) + return retval; + + if (package_manager_client_validate_handle(request)) + return package_manager_error(PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + int request_id = 0; + request_id = pkgmgr_client_res_create_dir(request->pc, event_cb, request); + + if (request_id == PKGMGR_R_EINVAL) + return package_manager_error(PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + else if (request_id == PKGMGR_R_ENOMEM) + return package_manager_error(PACKAGE_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); + else if (request_id == PKGMGR_R_EIO) + return package_manager_error(PACKAGE_MANAGER_ERROR_IO_ERROR, __FUNCTION__, NULL); + else if (request_id == PKGMGR_R_EPRIV) + return package_manager_error(PACKAGE_MANAGER_ERROR_PERMISSION_DENIED, __FUNCTION__, NULL); + else if (request_id == PKGMGR_R_ESYSTEM || request_id == PKGMGR_R_ECOMM || request_id == PKGMGR_R_ERROR) + return package_manager_error(PACKAGE_MANAGER_ERROR_SYSTEM_ERROR, __FUNCTION__, NULL); + + if (id) + *id = request_id; + + return PACKAGE_MANAGER_ERROR_NONE; +} + +static int __request_res_remove(package_manager_request_h request, + pkgmgr_res_handler event_cb, int *id) +{ + int retval; + retval = check_privilege(PRIVILEGE_PACKAGE_MANAGER_ADMIN); + if (retval != PACKAGE_MANAGER_ERROR_NONE) + return retval; + + if (package_manager_client_validate_handle(request)) + return package_manager_error(PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + int request_id = 0; + request_id = pkgmgr_client_res_remove(request->pc, event_cb, request); + + if (request_id == PKGMGR_R_EINVAL) + return package_manager_error(PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + else if (request_id == PKGMGR_R_ENOMEM) + return package_manager_error(PACKAGE_MANAGER_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); + else if (request_id == PKGMGR_R_EIO) + return package_manager_error(PACKAGE_MANAGER_ERROR_IO_ERROR, __FUNCTION__, NULL); + else if (request_id == PKGMGR_R_EPRIV) + return package_manager_error(PACKAGE_MANAGER_ERROR_PERMISSION_DENIED, __FUNCTION__, NULL); + else if (request_id == PKGMGR_R_ESYSTEM || request_id == PKGMGR_R_ECOMM || request_id == PKGMGR_R_ERROR) + return package_manager_error(PACKAGE_MANAGER_ERROR_SYSTEM_ERROR, __FUNCTION__, NULL); + + if (id) + *id = request_id; + + return PACKAGE_MANAGER_ERROR_NONE; +} + API int package_manager_request_install(package_manager_request_h request, const char *path, int *id) { @@ -1320,7 +1515,7 @@ static int internal_callback(uid_t target_uid, int req_id, const char *pkg_type, event_type = info->event_type; event_state = info->event_state; progress = 0; - error = __convert_to_error(val); + error = __convert_str_to_error(val); invoke_callback = true; } else if (strcasecmp(key, "end") == 0) { if (info->event_state != PACKAGE_MANAGER_EVENT_STATE_FAILED) { @@ -1352,6 +1547,67 @@ static int internal_callback(uid_t target_uid, int req_id, const char *pkg_type, return PACKAGE_MANAGER_ERROR_NONE; } +static void internal_res_callback(uid_t target_uid, int req_id, + const char *pkgid, const char *request_type, const char *status, + pkgmgr_res_event_info *handle, void *data) +{ + int ret = -1; + package_manager_h manager = data; + uid_t uid = target_uid; + package_manager_event_type_e event_type = -1; + package_manager_event_state_e event_state; + struct package_manager_res_event_info_s event_info; + + event_info.res_event_info_handle = handle; + + _LOGD("req_id(%d), pkg_name(%s), request_type(%s), status(%s)", + req_id, pkgid, request_type, status); + + if (target_uid == GLOBAL_USER) + uid = getuid(); + + if (__validate_event_signal(uid)) + return; + + if (manager) { + g_mutex_lock(&manager->mutex); + } else { + _LOGE("invalid handle"); + return; + } + ret = package_manager_get_event_type(request_type, &event_type); + if (ret != PACKAGE_MANAGER_ERROR_NONE) { + g_mutex_unlock(&manager->mutex); + return; + } + + if (strcasecmp(status, "start") == 0) { + event_state = PACKAGE_MANAGER_EVENT_STATE_STARTED; + } else if (strcasecmp(status, "fail") == 0) { + event_state = PACKAGE_MANAGER_EVENT_STATE_FAILED; + } else if (strcasecmp(status, "ok") == 0) { + event_state = PACKAGE_MANAGER_EVENT_STATE_COMPLETED; + } else { + _LOGE("unexpected event"); + g_mutex_unlock(&manager->mutex); + return; + } + g_mutex_unlock(&manager->mutex); + + if (manager->res_event_cb && getuid() == uid) { + _LOGE("call callback"); + manager->res_event_cb(pkgid, event_type, event_state, + &event_info, manager->user_data); + } else { + if (!manager->res_event_cb) + _LOGE("res_event_cb is null"); + if (getuid() != uid) + _LOGE("getuid : %d, uid : %d", getuid(), uid); + } + + return; +} + static int __convert_status_type(package_manager_status_type_e status_type) { int type = 0; @@ -1373,6 +1629,14 @@ static int __convert_status_type(package_manager_status_type_e status_type) type |= PKGMGR_CLIENT_STATUS_INSTALL_PROGRESS; if (status_type & PACKAGE_MANAGER_STATUS_TYPE_GET_SIZE) type |= PKGMGR_CLIENT_STATUS_GET_SIZE; + if (status_type & PACKAGE_MANAGER_STATUS_TYPE_RES_COPY) + type |= PKGMGR_CLIENT_STATUS_RES_COPY; + if (status_type & PACKAGE_MANAGER_STATUS_TYPE_RES_CREATE_DIR) + type |= PKGMGR_CLIENT_STATUS_RES_CREATE_DIR; + if (status_type & PACKAGE_MANAGER_STATUS_TYPE_RES_REMOVE) + type |= PKGMGR_CLIENT_STATUS_RES_REMOVE; + if (status_type & PACKAGE_MANAGER_STATUS_TYPE_RES_UNINSTALL) + type |= PKGMGR_CLIENT_STATUS_RES_UNINSTALL; return type; } @@ -1387,7 +1651,11 @@ API int package_manager_set_event_status(package_manager_h manager, int status_t PACKAGE_MANAGER_STATUS_TYPE_MOVE | PACKAGE_MANAGER_STATUS_TYPE_CLEAR_DATA | PACKAGE_MANAGER_STATUS_TYPE_INSTALL_PROGRESS | - PACKAGE_MANAGER_STATUS_TYPE_GET_SIZE; + PACKAGE_MANAGER_STATUS_TYPE_GET_SIZE | + PACKAGE_MANAGER_STATUS_TYPE_RES_COPY | + PACKAGE_MANAGER_STATUS_TYPE_RES_CREATE_DIR | + PACKAGE_MANAGER_STATUS_TYPE_RES_REMOVE | + PACKAGE_MANAGER_STATUS_TYPE_RES_UNINSTALL; if (manager == NULL) return package_manager_error(PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); @@ -1445,6 +1713,40 @@ API int package_manager_set_event_cb(package_manager_h manager, return PACKAGE_MANAGER_ERROR_NONE; } +API int package_manager_set_res_event_cb(package_manager_h manager, + package_manager_res_event_cb callback, void *user_data) +{ + int retval; + retval = check_privilege(PRIVILEGE_PACKAGE_MANAGER_ADMIN); + if (retval != PACKAGE_MANAGER_ERROR_NONE) + return retval; + + if (package_manager_validate_handle(manager)) { + return + package_manager_error + (PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, + NULL); + } + + manager->res_event_cb = callback; + manager->user_data = user_data; + + retval = pkgmgr_client_remove_listen_status(manager->pc); + if (retval < 0) { + return package_manager_error(PACKAGE_MANAGER_ERROR_IO_ERROR, + __FUNCTION__, NULL); + } + + retval = pkgmgr_client_listen_res_status(manager->pc, + internal_res_callback, manager); + if (retval < 0) { + return package_manager_error(PACKAGE_MANAGER_ERROR_IO_ERROR, + __FUNCTION__, NULL); + } + + return PACKAGE_MANAGER_ERROR_NONE; +} + API int package_manager_unset_event_cb(package_manager_h manager) { if (manager == NULL) { @@ -1456,6 +1758,7 @@ API int package_manager_unset_event_cb(package_manager_h manager) int retval; manager->event_cb = NULL; + manager->res_event_cb = NULL; manager->user_data = NULL; g_mutex_lock(&manager->mutex); @@ -2209,3 +2512,271 @@ API int package_manager_updateinfo_request_unregister_all(package_updateinfo_req return PACKAGE_MANAGER_ERROR_NONE; } + +API int package_manager_request_add_res_copy_path( + package_manager_request_h request, + const char *src_path, const char *dest_path) +{ + int retval = 0; + + if (package_manager_client_validate_handle(request) + || src_path == NULL || dest_path == NULL) { + return + package_manager_error + (PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, + NULL); + } + + retval = check_privilege(PRIVILEGE_PACKAGE_MANAGER_ADMIN); + if (retval != PACKAGE_MANAGER_ERROR_NONE) + return retval; + + if (pkgmgr_client_add_res_copy_path(request->pc, src_path, dest_path)) + return PACKAGE_MANAGER_ERROR_SYSTEM_ERROR; + + return PACKAGE_MANAGER_ERROR_NONE; +} + +API int package_manager_request_res_copy_with_cb(package_manager_request_h request, + package_manager_request_res_event_cb callback, + void *user_data, int *id) +{ + int ret; + int req_id = 0; + + ret = check_privilege(PRIVILEGE_PACKAGE_MANAGER_ADMIN); + if (ret != PACKAGE_MANAGER_ERROR_NONE) + return ret; + + if (request->request_cb_table == NULL) + __initialize_request_cb_table(request); + + ret = __request_res_copy(request, internal_res_request_callback, &req_id); + + if (req_id > 0) { + ret = __insert_res_request_cb_info(request, req_id, + callback, user_data); + if (ret < 0) + return package_manager_error(PACKAGE_MANAGER_ERROR_OUT_OF_MEMORY, + __FUNCTION__, "failed to create request cb info"); + if (id) + *id = req_id; + } + + return ret; +} + +API int package_manager_request_add_res_create_dir_path( + package_manager_request_h request, const char *dir_path) +{ + int retval = 0; + + if (package_manager_client_validate_handle(request) + || dir_path == NULL) { + return + package_manager_error + (PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, + NULL); + } + + retval = check_privilege(PRIVILEGE_PACKAGE_MANAGER_ADMIN); + if (retval != PACKAGE_MANAGER_ERROR_NONE) + return retval; + + if (pkgmgr_client_add_res_create_dir_path(request->pc, dir_path)) + return PACKAGE_MANAGER_ERROR_SYSTEM_ERROR; + + return PACKAGE_MANAGER_ERROR_NONE; +} + +API int package_manager_request_res_create_dir_with_cb( + package_manager_request_h request, + package_manager_request_res_event_cb callback, + void *user_data, int *id) +{ + int ret; + int req_id = 0; + + if (request->request_cb_table == NULL) + __initialize_request_cb_table(request); + + ret = check_privilege(PRIVILEGE_PACKAGE_MANAGER_ADMIN); + if (ret != PACKAGE_MANAGER_ERROR_NONE) + return ret; + + ret = __request_res_create_dir(request, internal_res_request_callback, &req_id); + + if (req_id > 0) { + ret = __insert_res_request_cb_info(request, req_id, + callback, user_data); + if (ret < 0) + return package_manager_error(PACKAGE_MANAGER_ERROR_OUT_OF_MEMORY, + __FUNCTION__, "failed to create request cb info"); + if (id) + *id = req_id; + } + + return ret; +} + +API int package_manager_request_add_res_remove_path( + package_manager_request_h request, const char *res_path) +{ + int retval = 0; + + if (package_manager_client_validate_handle(request) + || res_path == NULL) { + return + package_manager_error + (PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, + NULL); + } + + retval = check_privilege(PRIVILEGE_PACKAGE_MANAGER_ADMIN); + if (retval != PACKAGE_MANAGER_ERROR_NONE) + return retval; + + if (pkgmgr_client_add_res_remove_path(request->pc, res_path)) + return PACKAGE_MANAGER_ERROR_SYSTEM_ERROR; + + return PACKAGE_MANAGER_ERROR_NONE; +} + +API int package_manager_request_res_remove_with_cb( + package_manager_request_h request, + package_manager_request_res_event_cb callback, + void *user_data, int *id) +{ + int ret; + int req_id = 0; + + ret = check_privilege(PRIVILEGE_PACKAGE_MANAGER_ADMIN); + if (ret != PACKAGE_MANAGER_ERROR_NONE) + return ret; + + if (request->request_cb_table == NULL) + __initialize_request_cb_table(request); + + ret = __request_res_remove(request, internal_res_request_callback, &req_id); + + if (req_id > 0) { + ret = __insert_res_request_cb_info(request, req_id, + callback, user_data); + if (ret < 0) + return package_manager_error(PACKAGE_MANAGER_ERROR_OUT_OF_MEMORY, + __FUNCTION__, "failed to create request cb info"); + if (id) + *id = req_id; + } + + return ret; +} + +API int package_manager_res_event_info_get_error_code( + package_manager_res_event_info_h handle, + package_manager_error_e *error) +{ + int ret; + int error_code = 0; + + ret = check_privilege(PRIVILEGE_PACKAGE_MANAGER_ADMIN); + if (ret != PACKAGE_MANAGER_ERROR_NONE) + return ret; + + if (handle == NULL || error == NULL) + return package_manager_error(PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + struct package_manager_res_event_info_s *event_info = + (struct package_manager_res_event_info_s *)handle; + + if (event_info->res_event_info_handle == NULL) + return package_manager_error( + PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, + __FUNCTION__, NULL); + + if (pkgmgr_res_event_info_get_error_code( + event_info->res_event_info_handle, &error_code)) + return package_manager_error( + PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, + __FUNCTION__, NULL); + + *error = __convert_to_error(error_code); + + return PACKAGE_MANAGER_ERROR_NONE; +} + +typedef struct _foreach_res_event_path_context_ { + package_manager_res_event_path_cb callback; + void *user_data; +} foreach_res_event_path_context_s; + +static int package_res_event_info_foreach_path_cb(const char *path, + pkgmgr_res_event_path_state state, void *user_data) +{ + foreach_res_event_path_context_s *foreach_context = user_data; + package_manager_res_event_path_state_e path_state = + PACKAGE_MANAGER_RES_EVENT_PATH_STATE_NONE; + bool r = false; + + if (foreach_context == NULL) { + package_manager_error(PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, + __FUNCTION__, NULL); + return -1; + } + + if (state == PM_RES_EVENT_PATH_STATE_NONE) { + path_state = PACKAGE_MANAGER_RES_EVENT_PATH_STATE_NONE; + } else if (state == PM_RES_EVENT_PATH_STATE_OK) { + path_state = PACKAGE_MANAGER_RES_EVENT_PATH_STATE_OK; + } else if (state == PM_RES_EVENT_PATH_STATE_FAILED) { + path_state = PACKAGE_MANAGER_RES_EVENT_PATH_STATE_FAILED; + } else { + package_manager_error(PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, + __FUNCTION__, NULL); + return -1; + } + + r = foreach_context->callback(path, path_state, + foreach_context->user_data); + if (r == false) + return -1; + + return 0; +} + +API int package_manager_res_event_info_foreach_path( + package_manager_res_event_info_h handle, + package_manager_res_event_path_cb callback, void *user_data) +{ + int ret; + foreach_res_event_path_context_s foreach_res_event_path_context = { + .callback = callback, + .user_data = user_data, + }; + + ret = check_privilege(PRIVILEGE_PACKAGE_MANAGER_ADMIN); + if (ret != PACKAGE_MANAGER_ERROR_NONE) + return ret; + + if (handle == NULL || callback == NULL) + return package_manager_error(PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + struct package_manager_res_event_info_s *event_info = + (struct package_manager_res_event_info_s *)handle; + + if (event_info->res_event_info_handle == NULL) + return package_manager_error( + PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, + __FUNCTION__, NULL); + + ret = pkgmgr_res_event_info_foreach_path( + event_info->res_event_info_handle, + package_res_event_info_foreach_path_cb, + &foreach_res_event_path_context); + if (ret != PKGMGR_R_OK) { + return package_manager_error(PACKAGE_MANAGER_ERROR_SYSTEM_ERROR, + __FUNCTION__, NULL); + } + + return PACKAGE_MANAGER_ERROR_NONE; +} -- 2.7.4