From: Inkyun Kil Date: Thu, 15 Jun 2017 02:41:24 +0000 (+0900) Subject: Refactor codes X-Git-Tag: submit/tizen/20170707.024819~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6634e17d1cc63fcbb23181e575fbfcbad0c10ad8;p=platform%2Fcore%2Fappfw%2Fdata-control.git Refactor codes - The goal of this patch is to remove duplicated codes Change-Id: I7e075196935b1a909ccca50e6dc27fea2d499cd9 Signed-off-by: Inkyun Kil Signed-off-by: jusung son --- diff --git a/include/data-control-bulk.h b/include/data-control-bulk.h deleted file mode 100644 index da8dfec..0000000 --- a/include/data-control-bulk.h +++ /dev/null @@ -1,42 +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 _APPFW_DATA_CONTROL_BULK_H_ -#define _APPFW_DATA_CONTROL_BULK_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -int datacontrol_bulk_data_get_data(data_control_bulk_data_h bulk_data_h, int idx, bundle **data); -int datacontrol_bulk_data_get_count(data_control_bulk_data_h bulk_data_h, int *count); -int datacontrol_bulk_data_add(data_control_bulk_data_h bulk_data_h, bundle *data); -int datacontrol_bulk_data_create(data_control_bulk_data_h *bulk_data_h); -int datacontrol_bulk_data_destroy(data_control_bulk_data_h bulk_data_h); - -int datacontrol_bulk_result_data_get_result_data(data_control_bulk_result_data_h result_data_h, int idx, bundle **data, int *result); -int datacontrol_bulk_result_data_get_count(data_control_bulk_result_data_h result_data_h, int *count); -int datacontrol_bulk_result_data_add(data_control_bulk_result_data_h result_data_h, bundle *result_data, int result); -int datacontrol_bulk_result_data_create(data_control_bulk_result_data_h *result_data_h); -int datacontrol_bulk_result_data_destroy(data_control_bulk_result_data_h result_data_h); - -#ifdef __cplusplus -} -#endif - -#endif /* _APPFW_DATA_CONTROL_BULK_H__ */ diff --git a/include/data-control-map.h b/include/data-control-map.h deleted file mode 100644 index e04f433..0000000 --- a/include/data-control-map.h +++ /dev/null @@ -1,513 +0,0 @@ -/* - * Copyright (c) 2013 - 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. - */ - -/** - * @file data-control-map.h - * @brief This is the header file for the key-value structured data control. - */ - -#ifndef _APPFW_DATA_CONTROL_MAP_H_ -#define _APPFW_DATA_CONTROL_MAP_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Called when the response is received from the key-value structured data control provider. - * - * @param [in] request_id The request ID that identifies the data control - * @param [in] provider The provider handle - * @param [in] provider_result Set to true if the data control provider successfully processed @n - * false otherwise. - * @param [in] error The error message from the data control provider - * @param [in] user_data The user data passed from the register function - */ -typedef void (*datacontrol_map_add_bulk_data_response_cb)(int request_id, datacontrol_h provider, - data_control_bulk_result_data_h bulk_results, - bool provider_result, const char *error, void *user_data); - - - -/** - * @brief Called when the result value list is received from the key-value structured data control provider. - * - * @param [in] request_id The request ID - * @param [in] provider The provider handle - * @param [in] result_value_list The result value list of the data control request that gets the matching values - * @param [in] result_value_count The number of the values - * @param [in] provider_result Set to true if the data control provider successfully processed. @n - * false otherwise. - * @param [in] error The error message from the data control provider - * @param [in] user_data The user data passed from the register function - */ -typedef void (*datacontrol_map_get_response_cb)(int request_id, datacontrol_h provider, - char **result_value_list, int result_value_count, bool provider_result, const char *error, void *user_data); - -/** - * @brief Called when the response is received from the key-value structured data control provider. - * - * @param [in] request_id The request ID that identifies the data control - * @param [in] provider The provider handle - * @param [in] provider_result Set to true if the data control provider successfully processed. @n - * false otherwise. - * @param [in] error The error message from the data control provider - * @param [in] user_data The user data passed from the register function - */ -typedef void (*datacontrol_map_set_response_cb)(int request_id, datacontrol_h provider, - bool provider_result, const char *error, void *user_data); - -/** - * @brief Called when the response is received from the key-value structured data control provider. - * - * @param [in] request_id The request ID that identifies the data control - * @param [in] provider The provider handle - * @param [in] provider_result Set to true if the data control provider successfully processed. @n - * false otherwise. - * @param [in] error The error message from the data control provider - * @param [in] user_data The user data passed from the register function - */ -typedef void (*datacontrol_map_add_response_cb)(int request_id, datacontrol_h provider, - bool provider_result, const char *error, void *user_data); - -/** - * @brief Called when the response is received from the key-value structured data control provider. - * - * @param [in] request_id The request ID that identifies the data control - * @param [in] provider The provider handle - * @param [in] provider_result Set to true if the data control provider successfully processed. @n - * false otherwise. - * @param [in] error The error message from the data control provider - * @param [in] user_data The user data passed from the register function - */ -typedef void (*datacontrol_map_remove_response_cb)(int request_id, datacontrol_h provider, - bool provider_result, const char *error, void *user_data); - -/** - * @brief The structure type to contain the set of callback functions for handling the response events - * of the key-value structured data control. - * @see datacontrol_map_get_response_cb() - * @see datacontrol_map_set_response_cb() - * @see datacontrol_map_add_response_cb() - * @see datacontrol_map_remove_response_cb() - * @see datacontrol_map_add_bulk_data_response_cb() - */ -typedef struct { - datacontrol_map_get_response_cb get; - datacontrol_map_set_response_cb set; - datacontrol_map_add_response_cb add; - datacontrol_map_remove_response_cb remove; - datacontrol_map_add_bulk_data_response_cb bulk_add; -} datacontrol_map_response_cb; - -/** - * @brief Creates a provider handle. - * @param [out] provider The provider handle - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * @see datacontrol_map_destroy() - * - * The following example demonstrates how to use the %datacontrol_map_create() method. - * - * @code - * - * int main() - * { - * const char *provider_id = "http://tizen.org/datacontrol/provider/example"; - * const char *data_id = "table"; - * datacontrol_h provider; - * int result = 0; - * - * result = datacontrol_map_create(&provider); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Creating data control provider is failed with error: %d", result); - * return result; - * } - * - * result = datacontrol_map_set_provider_id(provider, provider_id); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Setting providerID is failed with error: %d", result); - * return result; - * } - * - * result = datacontrol_map_set_data_id(provider, data_id); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Setting dataID is failed with error: %d", result); - * return result; - * } - * - * // Executes some operations - * - * result = datacontrol_map_destroy(provider); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Destroying data control provider is failed with error: %d", result); - * } - * - * return result; - * } - * - * @endcode - */ -EXPORT_API int datacontrol_map_create(datacontrol_h *provider); - -/** - * @brief Destroys the provider handle and releases all its resources. - * @param [in] provider The provider handle - * @return 0 on success, otherwise a negative error value. - * @remark When operations of data control are finished, this function must be called to prevent memory leak. - * @see datacontrol_map_create() - */ -EXPORT_API int datacontrol_map_destroy(datacontrol_h provider); - -/** - * @brief Sets the Provider ID. - * @param [in] provider The provider handle - * @param [in] provider_id The data control provider ID - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * @see datacontrol_map_get_provider_id() - */ -EXPORT_API int datacontrol_map_set_provider_id(datacontrol_h provider, const char *provider_id); - -/** - * @brief Gets the Provider ID. - * @param [in] provider The provider handle - * @param [out] provider_id The data control provider ID - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * @see datacontrol_map_set_provider_id() - */ -EXPORT_API int datacontrol_map_get_provider_id(datacontrol_h provider, char **provider_id); - -/** - * @brief Sets the Data ID. - * @param [in] provider The provider handle - * @param [in] data_id A string for identifying a specific table to operate. @n - * The string consists of one or more components separated by a slash('/'). - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * @see datacontrol_map_get_data_id() - */ -EXPORT_API int datacontrol_map_set_data_id(datacontrol_h provider, const char *data_id); - -/** - * @brief Gets the Data ID. - * @param [in] provider The provider handle - * @param [out] data_id A string for identifying a specific table to operate. @n - * The string consists of one or more components separated by a slash('/'). - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * @see datacontrol_map_set_data_id() - */ -EXPORT_API int datacontrol_map_get_data_id(datacontrol_h provider, char **data_id); - -/** - * @brief Registers a callback function for the key-value structured data control response. @n - * The application is notified when a data control response is received from the @c provider. - * @param [in] provider The provider handle - * @param [in] callback The callback function to be called when a response is received. - * @param [in] user_data The user data to be passed to the callback function - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * @see datacontrol_map_unregister_response_cb() - */ -EXPORT_API int datacontrol_map_register_response_cb(datacontrol_h provider, datacontrol_map_response_cb *callback, void *user_data); - -/** - * @brief Unregisters the callback function in @c provider. - * @param [in] provider The provider handle - * @return 0 on success, otherwise a negative error value. - */ -EXPORT_API int datacontrol_map_unregister_response_cb(datacontrol_h provider); - -/** - * @brief Gets the value list associated with the specified @c key from the key-values map owned by the key-value structured data control provider. - * - * @param [in] provider The provider handle - * @param [in] key The key of the value list to obtain - * @param [out] request_id The request ID - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * @retval #DATACONTROL_ERROR_MAX_EXCEEDED Too long argument - * - * The following example demonstrates how to use the %datacontrol_map_get() method. - * - * @code - * - * void map_get_response_cb(int request_id, datacontrol_h provider, - * char **result_value_list, int result_value_count, bool provider_result, const char *error) - * { - * if (provider_result) { - * LOGI("The get operation is successful"); - * } - * else { - * LOGI("The get operation for the request %d is failed. error message: %s", request_id, error); - * } - * } - * - * datacontrol_map_response_cb map_callback; - * - * int main() - * { - * int result = 0; - * int req_id = 0; - * char *key = "key"; - * - * map_callback.get = map_get_response_cb; - * result = datacontrol_map_register_response_cb(provider, &map_callback); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Registering the callback function is failed with error: %d", result); - * return result; - * } - * - * result = datacontrol_map_get(provider, key, &req_id); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Getting the value list of the key(%s) is failed with error: %d", key, result); - * } - * else { - * LOGI("req_id is %d", req_id); - * } - * - * return result; - * } - * - * @endcode - */ -EXPORT_API int datacontrol_map_get(datacontrol_h provider, const char *key, int *request_id); - -/** - * @brief Gets the value list associated with the specified @c key from the key-values map owned by the key-value structured data control provider. - * - * @param [in] provider The provider handle - * @param [in] key The key of the value list to obtain - * @param [out] request_id The request ID - * @param [in] page_number The page number of the value set @n - * It starts from 1. - * @param [in] count_per_page The desired maximum count of the data items per page - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * @retval #DATACONTROL_ERROR_MAX_EXCEEDED Too long argument - */ -EXPORT_API int datacontrol_map_get_with_page(datacontrol_h provider, const char *key, int *request_id, int page_number, int count_per_page); - -/** - * @brief Sets the value associated with the specified @c key to a new value. - * - * @param [in] provider The provider handle - * @param [in] key The key of the value to replace - * @param [in] old_value The value to replace - * @param [in] new_value The new value that replaces the existing value - * @param [out] request_id The request ID - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * @retval #DATACONTROL_ERROR_MAX_EXCEEDED Too long argument - * - * The following example demonstrates how to use the %datacontrol_map_set() method. - * - * @code - * - * void map_set_response_cb(int request_id, datacontrol_h provider, bool provider_result, const char *error) - * { - * if (provider_result) { - * LOGI("The set operation is successful"); - * } - * else { - * LOGI("The set operation for the request %d is failed. error message: %s", request_id, error); - * } - * } - * - * datacontrol_map_response_cb map_callback; - * - * int main() - * { - * int result = 0; - * int req_id = 0; - * char *key = "key"; - * char *old_value = "old value"; - * char *new_value = "new value"; - * - * map_callback.set = map_set_response_cb; - * result = datacontrol_map_register_response_cb(provider, &map_callback); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Registering the callback function is failed with error: %d", result); - * return result; - * } - * - * result = datacontrol_map_set(provider, key, old_value, new_value, &req_id); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Replacing old_value(%s) with new_value(%s) is failed with error: %d", old_value, new_value, result); - * } - * else { - * LOGI("req_id is %d", req_id); - * } - * - * return result; - * } - * - * @endcode - */ -EXPORT_API int datacontrol_map_set(datacontrol_h provider, const char *key, const char *old_value, const char *new_value, int *request_id); - -/** - * @brief Adds the @c value associated with the specified @c key to the key-values map owned by the key-value structured data control provider. - * - * @param [in] provider The provider handle - * @param [in] key The key of the value to add - * @param [in] value The value to add - * @param [out] request_id The request ID - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * @retval #DATACONTROL_ERROR_MAX_EXCEEDED Too long argument - * - * The following example demonstrates how to use the %datacontrol_map_add() method. - * - * @code - * - * void map_add_response_cb(int request_id, datacontrol_h provider, bool provider_result, const char *error) { - * if (provider_result) { - * LOGI("The add operation is successful"); - * } - * else { - * LOGI("The add operation for the request %d is failed. error message: %s", request_id, error); - * } - * } - * - * datacontrol_map_response_cb map_callback; - * - * int main() - * { - * int result = 0; - * int req_id = 0; - * const char *key = "key"; - * const char *value = "value"; - * - * map_callback.add = map_add_response_cb; - * result = datacontrol_map_register_response_cb(provider, &map_callback); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Registering the callback function is failed with error: %d", result); - * return result; - * } - * - * result = datacontrol_map_add(provider, key, value, &req_id); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Adding %s-%s pair is failed with error: %d", key, value, result); - * } - * else { - * LOGI("req_id is %d", req_id); - * } - * - * return result; - * } - * - * @endcode - */ -EXPORT_API int datacontrol_map_add(datacontrol_h provider, const char *key, const char *value, int *request_id); - -/** - * @brief Removes the @c value associated with the specified @c key from the key-values map owned by the key-value structured data control provider. - * - * @param [in] provider The provider handle - * @param [in] key The key of the value to remove - * @param [in] value The value to remove - * @param [out] request_id The request ID - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * @retval #DATACONTROL_ERROR_MAX_EXCEEDED Too long argument - * - * The following example demonstrates how to use the %datacontrol_map_remove() method. - * - * @code - * - * void map_remove_response_cb(int request_id, datacontrol_h provider, bool provider_result, const char *error) { - * if (provider_result) { - * LOGI("The remove operation is successful"); - * } - * else { - * LOGI("The remove operation for the request %d is failed. error message: %s", request_id, error); - * } - * } - * - * datacontrol_map_response_cb map_callback; - * - * int main() - * { - * int result = 0; - * int req_id = 0; - * const char *key = "key"; - * const char *value = "value"; - * - * ... - * - * map_callback.remove = map_remove_response_cb; - * result = datacontrol_map_register_response_cb(provider, &map_callback); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Registering the callback function is failed with error: %d", result); - * return result; - * } - * - * result = datacontrol_map_remove(provider, key, value, &req_id); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Removing %s-%s pair is failed with error: %d", key, value, result); - * } - * else { - * LOGI("req_id is %d", req_id); - * } - * - * return result; - * } - * - * @endcode - */ -EXPORT_API int datacontrol_map_remove(datacontrol_h provider, const char *key, const char *value, int *request_id); -EXPORT_API int datacontrol_map_add_bulk_data(datacontrol_h provider, data_control_bulk_data_h bulk_data_h, int *request_id); -EXPORT_API bool datacontrol_map_cb_is_registered(char *provider_id); - -#ifdef __cplusplus -} -#endif - -#endif /* _APPFW_DATA_CONTROL_MAP_H_ */ - diff --git a/include/data-control-noti.h b/include/data-control-noti.h deleted file mode 100644 index 93009a9..0000000 --- a/include/data-control-noti.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2013 - 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 _APPFW_DATA_CONTROL_DATA_CHANGE_H_ -#define _APPFW_DATA_CONTROL_DATA_CHANGE_H_ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Adds data changed callback which called when provider's data is changed. - * @param [in] provider Target provider handle - * @param [in] callback The callback function to be called when consumer receive data changed notification - * @param [in] user_data The user data to be passed to the callback function - * @param [in] result_callback The callback function to be called when consumer receive add data changed callback process result - * @param [in] result_cb_user_data The user data to be passed to the result_callback function - * @param [out] callback_id Added callback ID - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - */ -EXPORT_API int datacontrol_add_data_change_cb(datacontrol_h provider, - data_control_data_change_cb callback, - void *user_data, - data_control_add_callback_result_cb result_callback, - void *result_cb_user_data, - int *callback_id); - -/** - * @brief Removes the data changed callback function. - * @param [in] provider Target provider handle - * @param [in] callback_id Target callback ID - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - */ -EXPORT_API int datacontrol_remove_data_change_cb(datacontrol_h provider, int callback_id); - -#ifdef __cplusplus -} -#endif - -#endif /* _APPFW_DATA_CONTROL_DATA_CHANGE_H__ */ diff --git a/include/data-control-provider.h b/include/data-control-provider.h deleted file mode 100755 index 2e69e00..0000000 --- a/include/data-control-provider.h +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Copyright (c) 2013 - 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. - */ - -/** - * @file data-control-provider.h - * @brief This is the header file for the data control provider. - */ - -#ifndef _APPFW_DATA_CONTROL_PROVIDER_H_ -#define _APPFW_DATA_CONTROL_PROVIDER_H_ - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Called when the insert request is received from an application using SQL-friendly interface based data control. - * - * @param [in] request_id The request ID - * @param [in] provider The provider handle - * @param [in] bulk_results The column-value pairs to insert @n - * If the value is a string, the value must be wrapped in single quotes, else it does not need to be wrapped in single quotes. - * @param [in] user_data The user data passed from the register function - */ -typedef void (*datacontrol_provider_sql_bulk_insert_request_cb)(int request_id, datacontrol_h provider, - data_control_bulk_data_h bulk_data, void *user_data); - -/** - * @brief Called when the insert request is received from an application using SQL-friendly interface based data control. - * - * @param [in] request_id The request ID - * @param [in] provider The provider handle - * @param [in] insert_data The column-value pairs to insert @n - * If the value is a string, the value must be wrapped in single quotes, else it does not need to be wrapped in single quotes. - * @param [in] user_data The user data passed from the register function - */ -typedef void (*datacontrol_provider_sql_insert_request_cb)(int request_id, datacontrol_h provider, - bundle *insert_data, void *user_data); - -/** - * @brief Called when the update request is received from an application using SQL-friendly interface based data control. - * - * @param [in] request_id The request ID - * @param [in] provider The provider handle - * @param [in] update_data The column-value pairs to update @n - * If the value is a string, the value must be wrapped in single quotes, else it does not need to be wrapped in single quotes. - * @param [in] where A filter to select the desired rows to update. @n - * It is an SQL 'WHERE' clause excluding the 'WHERE' itself such as column1 = 'stringValue' and column2 = numericValue. - * @param [in] user_data The user data passed from the register function - */ -typedef void (*datacontrol_provider_sql_update_request_cb)(int request_id, datacontrol_h provider, - bundle *update_data, const char *where, void *user_data); - -/** - * @brief Called when the delete request is received from an application using SQL-friendly interface based data control. - * - * @param [in] request_id The request ID - * @param [in] provider The provider handle - * @param [in] where A filter to select the desired rows to delete. @n - * It is an SQL 'WHERE' clause excluding the 'WHERE' itself such as column1 = 'stringValue' and column2 = numericValue. - * @param [in] user_data The user data passed from the register function - */ -typedef void (*datacontrol_provider_sql_delete_request_cb)(int request_id, datacontrol_h provider, - const char *where, void *user_data); - -/** - * @brief Called when the select request is received from an application using SQL-friendly interface based data control. - * - * @param [in] request_id The request ID - * @param [in] provider The provider handle - * @param [in] column_list The column list to query - * @param [in] column_count The total number of columns to be queried - * @param [in] where A filter to select the desired rows. @n - * It is an SQL 'WHERE' clause excluding the 'WHERE' itself such as column1 = 'stringValue' and column2 = numericValue. - * @param [in] order The sorting order of the rows to query. @n - * It is an SQL 'ORDER BY' clause excluding the 'ORDER BY' itself. - * @param [in] user_data The user data passed from the register function - */ -typedef void (*datacontrol_provider_sql_select_request_cb)(int request_id, datacontrol_h provider, - const char **column_list, int column_count, const char *where, const char *order, void *user_data); - -/** - * @brief Called when the request for obtaining the value list is received from the key-value structured data control consumer. - * - * @param [in] request_id The request ID - * @param [in] provider The provider handle - * @param [in] key The key of the value list to obtain - * @param [in] user_data The user data passed from the register function - */ -typedef void (*datacontrol_provider_map_get_value_request_cb)(int request_id, datacontrol_h provider, const char *key, void *user_data); - -/** - * @brief Called when the request for replacing the value is received from the key-value structured data control consumer. - * - * @param [in] request_id The request ID - * @param [in] provider The provider handle - * @param [in] key The key of the value to replace - * @param [in] old_value The value to replace - * @param [in] new_value The new value that replaces the existing value - * @param [in] user_data The user data passed from the register function - */ -typedef void (*datacontrol_provider_map_set_value_request_cb)(int request_id, datacontrol_h provider, const char *key, - const char *old_value, const char *new_value, void *user_data); - -/** - * @brief Called when the request for adding the value is received from the key-value structured data control consumer. - * - * @param [in] request_id The request ID - * @param [in] provider The provider handle - * @param [in] key The key of the value to add - * @param [in] value The value to add - * @param [in] user_data The user data passed from the register function - */ -typedef void (*datacontrol_provider_map_add_value_request_cb)(int request_id, datacontrol_h provider, const char *key, - const char *value, void *user_data); - -/** - * @brief Called when the request for removing the value is received from the key-value structured data control consumer. - * - * @param [in] request_id The request ID - * @param [in] provider The provider handle - * @param [in] key The key of the value to remove - * @param [in] value The value to remove - * @param [in] user_data The user data passed from the register function - */ -typedef void (*datacontrol_provider_map_remove_value_request_cb)(int request_id, datacontrol_h provider, const char *key, - const char *value, void *user_data); - -/** - * @brief Called when the request for removing the value is received from the key-value structured data control consumer. - * - * @param [in] request_id The request ID - * @param [in] provider The provider handle - * @param [in] key The key of the value to remove - * @param [in] value The value to remove - * @param [in] user_data The user data passed from the register function - */ -typedef void (*datacontrol_provider_map_bulk_add_value_request_cb)(int request_id, datacontrol_h provider, - data_control_bulk_data_h bulk_data, void *user_data); - -/** - * @brief The structure type to contain the set of callback functions for handling the request events - * of SQL-friendly interface based data control. - * @see datacontrol_provider_sql_select_request_cb() - * @see datacontrol_provider_sql_insert_request_cb() - * @see datacontrol_provider_sql_update_request_cb() - * @see datacontrol_provider_sql_delete_request_cb() - */ -typedef struct { - datacontrol_provider_sql_insert_request_cb insert; - datacontrol_provider_sql_select_request_cb select; - datacontrol_provider_sql_update_request_cb update; - datacontrol_provider_sql_delete_request_cb delete; - datacontrol_provider_sql_bulk_insert_request_cb bulk_insert; -} datacontrol_provider_sql_cb; - -/** - * @brief The structure type to contain the set of callback functions for handling the request events - * from the key-value structured data control consumer. - * @see datacontrol_provider_map_get_value_request_cb() - * @see datacontrol_provider_map_set_value_request_cb() - * @see datacontrol_provider_map_add_value_request_cb() - * @see datacontrol_provider_map_remove_value_request_cb() - */ -typedef struct { - datacontrol_provider_map_get_value_request_cb get; - datacontrol_provider_map_set_value_request_cb set; - datacontrol_provider_map_add_value_request_cb add; - datacontrol_provider_map_remove_value_request_cb remove; - datacontrol_provider_map_bulk_add_value_request_cb bulk_add; -} datacontrol_provider_map_cb; - -/** - * @brief Registers a callback function for the sql data control request. - * The provider is notified when a data control request is received from the client applications. - * @param [in] callback The callback function to be called when a data control request is received - * @param [in] user_data The user data to be passed to the callback function - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - */ -EXPORT_API int datacontrol_provider_sql_register_cb(datacontrol_provider_sql_cb *callback, void *user_data); - -/** - * @brief Unregisters the callback functions. - * @return 0 on success, otherwise a negative error value. - */ -EXPORT_API int datacontrol_provider_sql_unregister_cb(void); - -/** - * @brief Registers a callback function for the map data control request. - * The provider is notified when a data control request is received from the client applications. - * @param [in] callback The callback function to be called when a data control request is received - * @param [in] user_data The user data to be passed to the callback function - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - */ -EXPORT_API int datacontrol_provider_map_register_cb(datacontrol_provider_map_cb *callback, void *user_data); - -/** - * @brief Unregisters the callback functions. - * @return 0 on success, otherwise a negative error value. - */ -EXPORT_API int datacontrol_provider_map_unregister_cb(void); - -/** - * @brief Gets the application ID which sends the data control request. - * @param [in] request_id The request ID - * @param [out] appid The application ID - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - */ -EXPORT_API int datacontrol_provider_get_client_appid(int request_id, char **appid); - -/** - * @brief Sends the success result and the result set of the select request to the client application. - * @param [in] request_id The request ID - * @param [in] db_handle The result db handle for the result set - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - */ -EXPORT_API int datacontrol_provider_send_select_result(int request_id, void *db_handle); - -/** - * @brief Sends the success result of the insert request and the last inserted row ID to the client application. - * @param [in] request_id The request ID - * @param [in] row_id The row ID of the database changed by the insert request - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - */ -EXPORT_API int datacontrol_provider_send_insert_result(int request_id, long long row_id); - -/** - * @brief Sends the success result of the update request the client application. - * @param [in] request_id The request ID - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - */ -EXPORT_API int datacontrol_provider_send_update_result(int request_id); - -/** - * @brief Sends the success result of the delete request the client application. - * @param [in] request_id The request ID - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - */ -EXPORT_API int datacontrol_provider_send_delete_result(int request_id); - -/** - * @brief Sends the provider error message to the client application. - * @param [in] request_id The request ID - * @param [in] error The provider-defined error message - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - */ -EXPORT_API int datacontrol_provider_send_error(int request_id, const char *error); - -/** - * @brief Sends the success result of the request for setting, adding and removing the key-value structured data the client application. - * @param [in] request_id The request ID - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - */ -EXPORT_API int datacontrol_provider_send_map_result(int request_id); - -/** - * @brief Sends the success result of the request for getting the value list the client application. - * @param [in] request_id The request ID - * @param [in] value_list The result value list - * @param [in] value_count The number of the values - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - */ -EXPORT_API int datacontrol_provider_send_map_get_value_result(int request_id, char **value_list, int value_count); - -/** - * @brief Send data changed notification to consumer apps which are successfully add data changed callback. - * @param[in] provider Target provider handle - * @param[in] type Changed data type - * @param[in] data Customized data, intend to contains information about changed data - * - * @return @c 0 on success, - * otherwise a negative error value - * - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - */ -EXPORT_API int datacontrol_provider_send_data_change_noti( - datacontrol_h provider, - datacontrol_data_change_type_e type, - bundle *data); - -/** - * @brief Add consumer filter for add data changed callback process. - * @param[in] callback Consumer filter callback filtering consumers which try to add data changed callback - * @param[in] user_data The user data to be passed to the list_cb function - * @param[out] callback_id Added callback ID - * - * @return @c 0 on success, - * otherwise a negative error value - * - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - */ -EXPORT_API int datacontrol_provider_add_data_change_consumer_filter_cb( - data_control_provider_data_change_consumer_filter_cb callback, - void *user_data, - int *callback_id); - -/** - * @brief Remove consumer filter for add data changed callback process. - * @param[in] callback_id Target callback ID - * - * @return @c 0 on success, - * otherwise a negative error value - * - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - */ -EXPORT_API int datacontrol_provider_remove_data_change_consumer_filter_cb(int callback_id); - -/** - * @brief Get consumer list which successfully add data changed callback. - * @param[in] provider The provider handle - * @param[in] list_cb Callback for each consumer info - * @param[in] user_data The user data to be passed to the list_cb function - * - * @return @c 0 on success, - * otherwise a negative error value - * - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - */ -EXPORT_API int datacontrol_provider_foreach_data_change_consumer( - datacontrol_h provider, - data_control_provider_data_change_consumer_cb list_cb, - void *user_data); - -EXPORT_API int datacontrol_provider_send_bulk_insert_result( - int request_id, - data_control_bulk_result_data_h bulk_results); - -EXPORT_API int datacontrol_provider_send_map_bulk_add_result( - int request_id, - data_control_bulk_result_data_h bulk_results); - -EXPORT_API bool datacontrol_provider_map_is_registered(); -EXPORT_API bool datacontrol_provider_sql_is_registered(); - -/** - * @brief Sends select result without selected data. - * @details This API is made for C# API. C# API has a different select flow. \n - * It will send select result after provider's select callback and \n - * do not get db handle for sending result to remove db dependancy. \n - * So, this API just send provider's select callback result and pass \n - * connected socket fd for sending selected data to consumer. - * - * @param[in] request_id The request ID - * @param[out] fd The socket fd - * - * @return @c 0 on success, - * otherwise a negative error value - * - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - */ -EXPORT_API int datacontrol_provider_send_select_result_without_data(int request_id, int *fd); - -/** - * @brief Writes data to socket. - * @details This API is made for C# API. C# API has a different select flow. \n - * It will send select result after provider's select callback and \n - * do not get db handle for sending result to remove db dependancy. \n - * So, C# API need native API which get buffer and send it to the consumer. - * - * @param[in] fd The socket fd - * @param[in] buffer The data for sending to the consumer application - * @param[in] nbytes The data size - * @param[out] bytes_write The data size of sent successfully to the consumer - * - * @return @c 0 on success, - * otherwise a negative error value - * - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - */ -EXPORT_API int datacontrol_provider_write_socket(int fd, void *buffer, unsigned int nbytes, - unsigned int *bytes_write); - -/** - * @brief Gets select request page info. - * @details This API is made for C# API. C# API can control selected page in proivder's callback. \n - * This API provide request page info to the provider application so that provider application \n - * can manage which page should be sent to the consumer. - * - * @param[in] request_id The request ID - * @param[out] page_num The requested page number - * @param[out] count_per_page The requested count per page - * - * @return @c 0 on success, - * otherwise a negative error value - * - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - */ -EXPORT_API int datacontrol_provider_get_select_page_info(int request_id, int *page_num, int *count_per_page); - -#ifdef __cplusplus -} -#endif - -#endif /* _APPFW_DATA_CONTROL_PROVIDER_H_ */ - diff --git a/include/data-control-sql-cursor.h b/include/data-control-sql-cursor.h deleted file mode 100644 index 42bf058..0000000 --- a/include/data-control-sql-cursor.h +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright (c) 2013 - 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. - */ - -/** - * @file data-control-sql-cursor.h - * @brief This is the header file for the cursor of the SQL-friendly interface based data control. - */ - -#ifndef _APPFW_DATA_CONTROL_SQL_ENUMERATOR_H_ -#define _APPFW_DATA_CONTROL_SQL_ENUMERATOR_H_ - -#include -#include -#include "data-control-types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief The structure type to represent a sql result set. This type can be used to enumerate through the result set of an SQL query. - */ -typedef struct { - int resultset_fd; - sqlite3_int64 resultset_row_count; - int resultset_col_count; - off_t resultset_col_type_offset; - off_t resultset_col_name_offset; - off_t resultset_content_offset; - off_t resultset_current_offset; - sqlite3_int64 resultset_current_row_count; - char *resultset_path; - off_t *row_offset_list; -} resultset_cursor; - -/** - * @brief Creates a cursor to enumerate through an SQL result set - * - * @param [in] path The path of the file containing the SQL result set - * @return A pointer to struct @c resultset_cursor - */ -resultset_cursor *datacontrol_sql_get_cursor(); - -/** - * @brief Moves the cursor to the first position - * - * @param [in] cursor Navigates the result of the request for the select operation - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * - * The following example demonstrates how to use the %datacontrol_sql_step_first() method. - * - * @code - * - * void sql_select_response_cb(int request_id, datacontrol_h provider, resultset_cursor *cursor, bool provider_result, const char *error) - * { - * char person_name[32] = {0,}; - * long long person_number = -1; - * - * datacontrol_sql_step_first(cursor); - * datacontrol_sql_get_text_data(cursor, 0, person_name); - * datacontrol_sql_get_int64_data(cursor, 1, &person_number); - * printf("The person %s has the number %l", person_name, person_number); - * } - * - * @endcode - */ -EXPORT_API int datacontrol_sql_step_first(resultset_cursor *cursor); - -/** - * @brief Moves the cursor to the last position - * - * @param [in] cursor Navigates the result of data control select request - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * - * The following example demonstrates how to use the %datacontrol_sql_step_last() method. - * - * @code - * - * void sql_select_response_cb(int request_id, datacontrol_h provider, resultset_cursor *cursor, bool provider_result, const char *error) - * { - * char person_name[32] = {0,}; - * long long person_number = -1; - * - * datacontrol_sql_step_last(cursor); - * datacontrol_sql_get_text_data(cursor, 0, person_name); - * datacontrol_sql_get_int64_data(cursor, 1, &person_number); - * printf("The person %s has the number %l", person_name, person_number); - * } - * - * @endcode - */ -EXPORT_API int datacontrol_sql_step_last(resultset_cursor *cursor); - -/** - * @brief Moves the cursor to the next position - * - * @param [in] cursor Navigates the result of the request for the select operation - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * - * The following example demonstrates how to use the %datacontrol_sql_step_next() method. - * - * @code - * - * void sql_select_response_cb(int request_id, datacontrol_h provider, resultset_cursor *cursor, bool provider_result, const char *error) - * { - * char person_name[32] = {0,}; - * long long person_number = -1; - * while (datacontrol_sql_step_next(cursor) == DATACONTROL_ERROR_NONE) { - * datacontrol_sql_get_text_data(cursor, 0, person_name); - * datacontrol_sql_get_int64_data(cursor, 1, &person_number); - * printf("The person %s has the number %l", person_name, person_number); - * } - * } - * - * @endcode - */ -EXPORT_API int datacontrol_sql_step_next(resultset_cursor *cursor); - -/** - * @brief Moves the cursor to the previous position - * - * @param [in] cursor Navigates the result of the request for the select operation - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - */ -EXPORT_API int datacontrol_sql_step_previous(resultset_cursor *cursor); - -/** - * @brief Gets the number of columns for this cursor - * - * @param [in] cursor Navigates the result of the request for the select operation - * @return The number of columns in the calling cursor - */ -EXPORT_API int datacontrol_sql_get_column_count(resultset_cursor *cursor); - -/** - * @brief Gets the name of the column indicated by the specified index - * - * @param [in] cursor Navigates the result of the request for the select operation - * @param [in] column_index The index of the destination column - * @param [out] name The name of the destination column - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - */ -EXPORT_API int datacontrol_sql_get_column_name(resultset_cursor *cursor, int column_index, char *name); - -/** - * @brief Gets the size of data in the column indicated by the specified index - * - * @param [in] cursor Navigates the result of the request for the select operation - * @param [in] column_index The index of the destination column - * @return The size of data in the column indicated by the specified index. @n - * If an error is occurred, a negative value is returned. - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - */ -EXPORT_API int datacontrol_sql_get_column_item_size(resultset_cursor *cursor, int column_index); - -/** - * @brief Gets the type of the column indicated by the specified index - * - * @param [in] cursor Navigates the result of the request for the select operation - * @param [in] column_index The index of the destination column - * @param [out] type The type of the destination column - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - */ -EXPORT_API int datacontrol_sql_get_column_item_type(resultset_cursor *cursor, int column_index, datacontrol_sql_column_type* type); - -/** - * @brief Gets a blob data from the column indicated by the specified index - * - * @param [in] cursor Navigates the result of the request for the select operation - * @param [in] column_index The index of the destination column - * @param [out] data The blob value obtained from the column - * @param [out] size The size of the data - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_MAX_EXCEEDED Too long argument - */ -EXPORT_API int datacontrol_sql_get_blob_data(resultset_cursor *cursor, int column_index, void *data, int size); - -/** - * @brief Gets an int value from the column indicated by the specified index - * - * @param [in] cursor Navigates the result of the request for the select operation - * @param [in] column_index The index of the destination column - * @param [out] data The integer value obtained from the column - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - */ -EXPORT_API int datacontrol_sql_get_int_data(resultset_cursor *cursor, int column_index, int *data); - -/** - * @brief Gets a long long value from the column indicated by the specified index - * - * @param [in] cursor Navigates the result of the request for the select operation - * @param [in] column_index The index of the destination column - * @param [out] data The 64-bit integer value obtained from the column - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - */ -EXPORT_API int datacontrol_sql_get_int64_data(resultset_cursor *cursor, int column_index, long long *data); - -/** - * @brief Gets a double value from the column indicated by the specified index - * - * @param [in] cursor Navigates the result of the request for the select operation - * @param [in] column_index The index of the destination column - * @param [out] data The value obtained from the column as double - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - */ -EXPORT_API int datacontrol_sql_get_double_data(resultset_cursor *cursor, int column_index, double *data); - -/** - * @brief Gets a text value from the column indicated by the specified index - * - * @param [in] cursor Navigates the result of the request for the select operation - * @param [in] column_index The index of the destination column - * @param [out] data The value obtained from the column as text - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - */ -EXPORT_API int datacontrol_sql_get_text_data(resultset_cursor *cursor, int column_index, char *data); - -/** - * @brief Removes the @c cursor containing SQL result set - * - * @param [in] cursor A pointer to the result set cursor to be removed - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - */ -EXPORT_API int datacontrol_sql_remove_cursor(resultset_cursor *cursor); - -#ifdef __cplusplus -} -#endif - -#endif /* _APPFW_DATA_CONTROL_SQL_ENUMERATOR_H_ */ - diff --git a/include/data-control-sql.h b/include/data-control-sql.h deleted file mode 100644 index aa76a11..0000000 --- a/include/data-control-sql.h +++ /dev/null @@ -1,529 +0,0 @@ -/* - * Copyright (c) 2013 - 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. - */ - -/** - * @file data-control-sql.h - * @brief This is the header file for the SQL-friendly interface based data control. - */ - -#ifndef _APPFW_DATA_CONTROL_SQL_H_ -#define _APPFW_DATA_CONTROL_SQL_H_ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @brief Called when response is received for insert operation from an application using the SQL-friendly interface based data control. - * - * @param [in] request_id The request ID - * @param [in] provider The provider handle - * @param [in] bulk_results The inserted row ID set by the data control - * @param [in] provider_result Set to true if the data control provider successfully processed @n - * false otherwise. - * @param [in] error The error message from the data control provider - * @param [in] user_data The user data passed from the register function - */ -typedef void (*datacontrol_sql_insert_bulk_data_response_cb)(int request_id, datacontrol_h provider, - data_control_bulk_result_data_h bulk_results, bool provider_result, const char *error, void *user_data); - -/** - * @brief Called when response is received for insert operation from an application using the SQL-friendly interface based data control. - * - * @param [in] request_id The request ID - * @param [in] provider The provider handle - * @param [in] inserted_row_id The inserted row ID set by the data control - * @param [in] provider_result Set to true if the data control provider successfully processed. @n - * false otherwise. - * @param [in] error The error message from the data control provider - * @param [in] user_data The user data passed from the register function - */ -typedef void (*datacontrol_sql_insert_response_cb)(int request_id, datacontrol_h provider, - long long inserted_row_id, bool provider_result, const char *error, void *user_data); - -/** - * @brief Called when response is received for delete operation from an application using the SQL-friendly interface based data control. - * - * @param [in] request_id The request ID that identifies the data control - * @param [in] provider_result Set to true if the data control provider successfully processed. @n - * false otherwise. - * @param [in] error The error message from the data control provider - * @param [in] user_data The user data passed from the register function - */ -typedef void (*datacontrol_sql_delete_response_cb)(int request_id, datacontrol_h provider, - bool provider_result, const char *error, void *user_data); - -/** - * @brief Called when response is received for select operation from an application using the SQL-friendly interface based data control. - * - * @param [in] request_id The request ID - * @param [in] provider The provider handle - * @param [in] enumerator Navigates the result of data control select request - * @param [in] provider_result Set to true if the data control provider successfully processed. @n - * false otherwise. - * @param [in] error The error message from the data control provider - * @param [in] user_data The user data passed from the register function - */ -typedef void (*datacontrol_sql_select_response_cb)(int request_id, datacontrol_h provider, - resultset_cursor *enumerator, bool provider_result, const char *error, void *user_data); - -/** - * @brief Called when response is received for update operation from an application using the SQL-friendly interface based data control. - * - * @param [in] request_id The request ID - * @param [in] provider The provider handle - * @param [in] provider_result Set to true if the data control provider successfully processed. @n - * false otherwise. - * @param [in] error The error message from the data control provider - * @param [in] user_data The user data passed from the register function - */ -typedef void (*datacontrol_sql_update_response_cb)(int request_id, datacontrol_h provider, - bool provider_result, const char *error, void *user_data); - -/** - * @brief The structure type to contain the set of callback functions for handling the response events - * of SQL-friendly interface based data control. - * @see datacontrol_sql_select_response_cb() - * @see datacontrol_sql_insert_response_cb() - * @see datacontrol_sql_update_response_cb() - * @see datacontrol_sql_delete_response_cb() - * @see datacontrol_sql_insert_bulk_data_response_cb() - */ -typedef struct { - datacontrol_sql_select_response_cb select; - datacontrol_sql_insert_response_cb insert; - datacontrol_sql_update_response_cb update; - datacontrol_sql_delete_response_cb delete; - datacontrol_sql_insert_bulk_data_response_cb bulk_insert; -} datacontrol_sql_response_cb; - -/** - * @brief Creates a provider handle. - * @param [out] provider The provider handle - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * @see datacontrol_sql_destroy() - * - * The following example demonstrates how to use the %datacontrol_sql_create() method. - * - * @code - * - * int main() - * { - * const char *provider_id = "http://tizen.org/datacontrol/provider/example"; - * const char *data_id = "table"; - * datacontrol_h provider; - * int result = 0; - * - * result = datacontrol_sql_create(&provider); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Creating data control provider is failed with error: %d", result); - * return result; - * } - * - * result = datacontrol_sql_set_provider_id(provider, provider_id); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Setting providerID is failed with error: %d", result); - * return result; - * } - * - * result = datacontrol_sql_set_data_id(provider, data_id); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Setting dataID is failed with error: %d", result); - * return result; - * } - * - * // Executes some operations - * - * result = datacontrol_sql_destroy(provider); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Destroying data control provider is failed with error: %d", result); - * } - * - * return result; - * } - * - * @endcode - */ -EXPORT_API int datacontrol_sql_create(datacontrol_h *provider); - -/** - * @brief Destroys the provider handle and releases all its resources. - * @param [in] provider The provider handle - * @return 0 on success, otherwise a negative error value. - * @remark When operations of data control are finished, this function must be called to prevent memory leak. - * @see datacontrol_sql_create() - */ -EXPORT_API int datacontrol_sql_destroy(datacontrol_h provider); - -/** - * @brief Sets the Provider ID. - * @param [in] provider The provider handle - * @param [in] provider_id The data control provider ID - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * @see datacontrol_sql_get_provider_id() - */ -EXPORT_API int datacontrol_sql_set_provider_id(datacontrol_h provider, const char *provider_id); - -/** - * @brief Gets the Provider ID. - * @param [in] provider The provider handle - * @param [out] provider_id The data control provider ID - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * @see datacontrol_sql_set_provider_id() - */ -EXPORT_API int datacontrol_sql_get_provider_id(datacontrol_h provider, char **provider_id); - -/** - * @brief Sets the Data ID. - * @param [in] provider The provider handle - * @param [in] data_id A string for identifying a specific table to operate. @n - * The string consists of one or more components separated by a slash('/'). - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * @see datacontrol_sql_get_data_id() - */ -EXPORT_API int datacontrol_sql_set_data_id(datacontrol_h provider, const char *data_id); - -/** - * @brief Gets the Data ID. - * @param [in] provider The provider handle - * @param [out] data_id A string for identifying a specific table to operate. @n - * The string consists of one or more components separated by a slash('/'). - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * @see datacontrol_sql_set_data_id() - */ -EXPORT_API int datacontrol_sql_get_data_id(datacontrol_h provider, char **data_id); - -/** - * @brief Registers a callback function for the sql data control response. @n - * The application is notified when a data control response is received from the @c provider. - * @param [in] provider The provider handle - * @param [in] callback The callback function to be called when a response is received. - * @param [in] user_data The user data to be passed to the callback function - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * @see datacontrol_sql_unregister_response_cb() - */ -EXPORT_API int datacontrol_sql_register_response_cb(datacontrol_h provider, datacontrol_sql_response_cb *callback, void *user_data); - -/** - * @brief Unregisters the callback function in @c provider. - * @param [in] provider The provider handle - * @return 0 on success, otherwise a negative error value. - */ -EXPORT_API int datacontrol_sql_unregister_response_cb(datacontrol_h provider); - -/** - * @brief Deletes rows of a table owned by the SQL-type data control provider - * - * @remarks If the value is a string, the value must be wrapped in single quotes, else it does not need to be wrapped in single quotes. - * @param [in] provider The provider handle - * @param [in] where A filter to select the desired rows to delete. @n - * It is an SQL 'WHERE' clause excluding the 'WHERE' itself such as column1 = 'stringValue' and column2 = numericValue. - * @param [out] request_id The request ID - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * - * The following example demonstrates how to use the %datacontrol_sql_delete() method. - * - * @code - * - * void sql_delete_response_cb(int request_id, datacontrol_h provider, bool provider_result, const char *error) { - * if (provider_result) { - * LOGI("The delete operation is successful"); - * } - * else { - * LOGI("The delete operation for the request %d is failed. error message: %s", request_id, error); - * } - * } - * - * datacontrol_sql_response_cb sql_callback; - * - * int main() - * { - * const char *where = "group = 'friend'"; - * int result = 0; - * int req_id = 0; - * - * sql_callback.delete = sql_delete_response_cb; - * result = datacontrol_sql_register_response_cb(provider, &sql_callback); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Registering the callback function is failed with error: %d", result); - * return result; - * } - * - * result = datacontrol_sql_delete(provider, where, &req_id); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Deleting is failed with error: %d", result); - * } - * else { - * LOGI("req_id is %d", req_id); - * } - * - * return result; - * } - * - * @endcode - */ -EXPORT_API int datacontrol_sql_delete(datacontrol_h provider, const char *where, int *request_id); - -/** - * @brief Inserts new rows in a table owned by the SQL-type data control provider - * - * @param [in] provider The provider handle - * @param [in] insert_data The column-value pairs to insert. @n - * If the value is a string, the value must be wrapped in single quotes, - * else it does not need to be wrapped in single quotes. - * @param [out] request_id The request ID - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * @retval #DATACONTROL_ERROR_MAX_EXCEEDED Too long argument - * - * The following example demonstrates how to use the %datacontrol_sql_insert() method. - * - * @code - * - * void sql_insert_response_cb(int request_id, datacontrol_h provider, long long inserted_row_id, bool provider_result, const char *error) { - * if (provider_result) { - * LOGI("The insert operation is successful"); - * } - * else { - * LOGI("The insert operation for the request %d is failed. error message: %s", request_id, error); - * } - * } - * - * datacontrol_sql_response_cb sql_callback; - * - * int main() - * { - * int result = 0; - * int req_id = 0; - * bundle *b = NULL; - * - * sql_callback.insert = sql_insert_response_cb; - * result = datacontrol_sql_register_response_cb(provider, &sql_callback); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Registering the callback function is failed with error: %d", result); - * return result; - * } - * - * b = bundle_create(); - * bundle_add_str(b, "WORD", "test"); - * bundle_add_str(b, "WORD_DESC", "test description"); - * - * result = datacontrol_sql_insert(provider, b, &req_id); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Inserting is failed with error: %d", result); - * } - * else { - * LOGI("req_id is %d", req_id); - * } - * - * bundle_free(b); - * return result; - * } - * - * @endcode - */ -EXPORT_API int datacontrol_sql_insert(datacontrol_h provider, const bundle *insert_data, int *request_id); - -/** - * @brief Selects the specified columns to be queried - * - * @param [in] provider The provider handle - * @param [in] column_list The column list to query - * @param [in] column_count The total number of columns to be queried - * @param [in] where A filter to select the desired rows. @n - * It is an SQL 'WHERE' clause excluding the 'WHERE' itself such as column1 = 'stringValue' and column2 = numericValue. - * @param [in] order The sorting order of the rows to query. @n - * It is an SQL 'ORDER BY' clause excluding the 'ORDER BY' itself. - * @param [out] request_id The request ID - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * - * The following example demonstrates how to use the %datacontrol_sql_select() method. - * - * @code - * - * void sql_select_response_cb(int request_id, datacontrol_h provider, resultset_cursor *enumerator, bool provider_result, const char *error) { - * if (provider_result) { - * LOGI("The select operation is successful"); - * } - * else { - * LOGI("The select operation for the request %d is failed. error message: %s", request_id, error); - * } - * } - * - * datacontrol_sql_response_cb sql_callback; - * - * int main() - * { - * int result = 0; - * int req_id = 0; - * char *column_list[2]; - * column_list[0] = "WORD"; - * column_list[1] = "WORD_DESC"; - * const char *where = "WORD = 'test'"; - * const char *order = "WORD ASC"; - * - * sql_callback.select = sql_select_response_cb; - * result = datacontrol_sql_register_response_cb(provider, &sql_callback); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Registering the callback function is failed with error: %d", result); - * return result; - * } - * - * result = datacontrol_sql_select(provider, column_list, 2, where, order, &req_id); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Selecting is failed with error: %d", result); - * } - * else { - * LOGI("req_id is %d", req_id); - * } - * - * return result; - * } - * - * @endcode - */ -EXPORT_API int datacontrol_sql_select(datacontrol_h provider, char **column_list, int column_count, const char *where, const char *order, int *request_id); - -/** - * @brief Selects the specified columns to be queried - * - * @param [in] provider The provider handle - * @param [in] column_list The column list to query - * @param [in] column_count The total number of columns to be queried - * @param [in] where A filter to select the desired rows. @n - * It is an SQL 'WHERE' clause excluding the 'WHERE' itself such as column1 = 'stringValue' and column2 = numericValue. - * @param [in] order The sorting order of the rows to query. @n - * It is an SQL 'ORDER BY' clause excluding the 'ORDER BY' itself. - * @param [in] page_number The page number of the result set @n - * It starts from 1. - * @param [in] count_per_page The desired maximum count of rows on a page - * @param [out] request_id The request ID - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * @see datacontrol_sql_select() - */ -EXPORT_API int datacontrol_sql_select_with_page(datacontrol_h provider, char **column_list, int column_count, const char *where, const char *order, int page_number, int count_per_page, int *request_id); - -/** - * @brief Updates values of a table owned by the SQL-type data control provider. - * - * @param [in] provider The provider handle - * @param [in] update_data The column-value pairs to update. @n - * If the value is a string, the value must be wrapped in single quotes, - * else it does not need to be wrapped in single quotes. - * @param [in] where A filter to select the desired rows to update. @n - * It is an SQL 'WHERE' clause excluding the 'WHERE' itself such as column1 = 'stringValue' and column2 = numericValue. - * @param [out] request_id The request ID - * @return 0 on success, otherwise a negative error value. - * @retval #DATACONTROL_ERROR_NONE Successful - * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DATACONTROL_ERROR_IO_ERROR I/O error - * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory - * @retval #DATACONTROL_ERROR_MAX_EXCEEDED Too long argument - * - * The following example demonstrates how to use the %datacontrol_sql_update() method. - * - * @code - * - * void sql_update_response_cb(int request_id, datacontrol_h provider, bool provider_result, const char *error) { - * if (provider_result) { - * LOGI("The update operation is successful"); - * } - * else { - * LOGI("The update operation for the request %d is failed. error message: %s", request_id, error); - * } - * } - * - * datacontrol_sql_response_cb sql_callback; - * - * int main() - * { - * int result = 0; - * int req_id = 0; - * const char *where = "WORD = 'test'"; - * bundle *b = NULL; - * - * sql_callback.update = sql_update_response_cb; - * result = datacontrol_sql_register_response_cb(provider, &sql_callback); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Registering the callback function is failed with error: %d", result); - * return result; - * } - * - * b = bundle_create(); - * bundle_add_str(b, "WORD", "test_new"); - * - * result = datacontrol_sql_update(provider, b, where, &req_id); - * if (result != DATACONTROL_ERROR_NONE) { - * LOGE("Updating is failed with error: %d", result); - * } - * else { - * LOGI("req_id is %d", req_id); - * } - * - * bundle_free(b); - * return result; - * } - * - * @endcode - */ -EXPORT_API int datacontrol_sql_update(datacontrol_h provider, const bundle *update_data, const char *where, int *request_id); -EXPORT_API int datacontrol_sql_insert_bulk_data(datacontrol_h provider, data_control_bulk_data_h bulk_data_h, int *request_id); -EXPORT_API bool datacontrol_sql_cb_is_registered(char *provider_id); - -#ifdef __cplusplus -} -#endif - -#endif /* _APPFW_DATA_CONTROL_SQL_H_ */ - diff --git a/include/data-control-types.h b/include/data-control-types.h deleted file mode 100644 index 83bdeb0..0000000 --- a/include/data-control-types.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2013 - 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. - */ - -/** - * @file data-control-types.h - * @brief This is the header file for data types of the data-control. - */ - -#ifndef _APPFW_DATA_CONTROL_TYPES_H_ -#define _APPFW_DATA_CONTROL_TYPES_H_ -#include - -#include -#include - - -#ifdef __GNUC__ -# ifndef EXPORT_API -# define EXPORT_API __attribute__((visibility("default"))) -# endif -#else -# define EXPORT_API -#endif - -typedef struct { - bundle *result_data; - int result; -} data_control_bulk_result_data_item_s; - -struct data_control_bulk_result_data_s { - GList *data_list; -}; - -struct data_control_bulk_data_s { - GList *data_list; -}; - -/** - * @brief Provider handle - */ -typedef struct datacontrol_s *datacontrol_h; - -/** - * @brief Enumerations of different types of columns in an SQL table. - */ -typedef enum { - DATACONTROL_SQL_COLUMN_TYPE_UNDEFINED = 0, - DATACONTROL_SQL_COLUMN_TYPE_INT64, - DATACONTROL_SQL_COLUMN_TYPE_DOUBLE, - DATACONTROL_SQL_COLUMN_TYPE_TEXT, - DATACONTROL_SQL_COLUMN_TYPE_BLOB, - DATACONTROL_SQL_COLUMN_TYPE_NULL -} datacontrol_sql_column_type; - -/** - * @brief Enumerations of the various error-codes an API can return. - */ -typedef enum { - DATACONTROL_ERROR_NONE = 0, /**< Successful */ - DATACONTROL_ERROR_OUT_OF_MEMORY = -ENOMEM, /**< Out of memory */ - DATACONTROL_ERROR_IO_ERROR = -EIO, /**< I/O error */ - DATACONTROL_ERROR_INVALID_PARAMETER = -EINVAL, /**< Invalid parameter */ - DATACONTROL_ERROR_PERMISSION_DENIED = -EACCES, /**< Permission denied */ - DATACONTROL_ERROR_MAX_EXCEEDED = -EMSGSIZE /**< Too long argument */ -} datacontrol_error_e; - -/** - * @brief Enumerations of different type of data control requests. - */ -typedef enum -{ - DATACONTROL_TYPE_ERROR = -1, - DATACONTROL_TYPE_UNDEFINED, - DATACONTROL_TYPE_SQL_SELECT, - DATACONTROL_TYPE_SQL_INSERT, - DATACONTROL_TYPE_SQL_UPDATE, - DATACONTROL_TYPE_SQL_DELETE, - DATACONTROL_TYPE_SQL_BULK_INSERT, - DATACONTROL_TYPE_MAP_GET, - DATACONTROL_TYPE_MAP_SET, - DATACONTROL_TYPE_MAP_ADD, - DATACONTROL_TYPE_MAP_REMOVE, - DATACONTROL_TYPE_MAP_BULK_ADD, - DATACONTROL_TYPE_ADD_DATA_CHANGED_CB, - DATACONTROL_TYPE_REMOVE_DATA_CHANGED_CB, - DATACONTROL_TYPE_MAX = 255 -} datacontrol_request_type; - - -/** - * @brief Enumerations of the various datacontrol noti type. - */ -typedef enum { - DATACONTROL_DATA_CHANGE_SQL_UPDATE, - DATACONTROL_DATA_CHANGE_SQL_INSERT, - DATACONTROL_DATA_CHANGE_SQL_DELETE, - DATACONTROL_DATA_CHANGE_MAP_SET, - DATACONTROL_DATA_CHANGE_MAP_ADD, - DATACONTROL_DATA_CHANGE_MAP_REMOVE, - DATACONTROL_DATA_CHANGE_CALLBACK_ADD_RESULT, - DATACONTROL_DATA_CHANGE_CALLBACK_REMOVE_RESULT -} datacontrol_data_change_type_e; - - -#endif /* _APPFW_DATA_CONTROL_TYPES_H_ */ - diff --git a/include/data-control.h b/include/data-control.h deleted file mode 100644 index 5b71856..0000000 --- a/include/data-control.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2013 - 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. - */ - -/** - * @file data-control.h - * @brief This is the header file for the data control. - */ - -#ifndef _APPFW_DATA_CONTROL_H_ -#define _APPFW_DATA_CONTROL_H_ - -#include -#include -#include -#include -#include - -#endif /* _APPFW_DATA_CONTROL_H_ */ - diff --git a/include/data_control_internal.h b/include/data_control_internal.h deleted file mode 100644 index a6be427..0000000 --- a/include/data_control_internal.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2011 - 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 __TIZEN_APPFW_DATA_CONTROL_INTERNAL_H__ -#define __TIZEN_APPFW_DATA_CONTROL_INTERNAL_H__ - -#include -#include "data_control_types.h" -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - PRIVILEGE_PROVIDER, - PRIVILEGE_CONSUMER -} privilege_type; - -typedef enum { - CERT_UNCHECKED, - CERT_MATCH, - CERT_MISMATCH -} cert_status_type; - -int convert_to_tizen_error(datacontrol_error_e error); -int datacontrol_check_privilege(privilege_type check_type); -int datacontrol_check_cert(const char *provider_id, bool is_map, - const char *consumer_appid); - -#ifdef __cplusplus -} -#endif - -#endif /* __TIZEN_APPFW_DATA_CONTROL_INTERNAL_H__ */ - diff --git a/include/data_control_provider_internal.h b/include/data_control_provider_internal.h new file mode 100755 index 0000000..e1b294c --- /dev/null +++ b/include/data_control_provider_internal.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2013 - 2017 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. + */ + +/** + * @file data-control-provider.h + * @brief This is the header file for the data control provider. + */ + +#ifndef _APPFW_DATA_CONTROL_PROVIDER_H_ +#define _APPFW_DATA_CONTROL_PROVIDER_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Sends select result without selected data. + * @details This API is made for C# API. C# API has a different select flow. \n + * It will send select result after provider's select callback and \n + * do not get db handle for sending result to remove db dependancy. \n + * So, this API just send provider's select callback result and pass \n + * connected socket fd for sending selected data to consumer. + * + * @param[in] request_id The request ID + * @param[out] fd The socket fd + * + * @return @c 0 on success, + * otherwise a negative error value + * + * @retval #DATACONTROL_ERROR_NONE Successful + * @retval #DATACONTROL_ERROR_IO_ERROR I/O error + * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter + */ +EXPORT_API int datacontrol_provider_send_select_result_without_data(int request_id, int *fd); + +/** + * @brief Writes data to socket. + * @details This API is made for C# API. C# API has a different select flow. \n + * It will send select result after provider's select callback and \n + * do not get db handle for sending result to remove db dependancy. \n + * So, C# API need native API which get buffer and send it to the consumer. + * + * @param[in] fd The socket fd + * @param[in] buffer The data for sending to the consumer application + * @param[in] nbytes The data size + * @param[out] bytes_write The data size of sent successfully to the consumer + * + * @return @c 0 on success, + * otherwise a negative error value + * + * @retval #DATACONTROL_ERROR_NONE Successful + * @retval #DATACONTROL_ERROR_IO_ERROR I/O error + */ +EXPORT_API int datacontrol_provider_write_socket(int fd, void *buffer, unsigned int nbytes, + unsigned int *bytes_write); + +/** + * @brief Gets select request page info. + * @details This API is made for C# API. C# API can control selected page in proivder's callback. \n + * This API provide request page info to the provider application so that provider application \n + * can manage which page should be sent to the consumer. + * + * @param[in] request_id The request ID + * @param[out] page_num The requested page number + * @param[out] count_per_page The requested count per page + * + * @return @c 0 on success, + * otherwise a negative error value + * + * @retval #DATACONTROL_ERROR_NONE Successful + * @retval #DATACONTROL_ERROR_IO_ERROR I/O error + * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter + */ +EXPORT_API int datacontrol_provider_get_select_page_info(int request_id, int *page_num, int *count_per_page); + +#ifdef __cplusplus +} +#endif + +#endif /* _APPFW_DATA_CONTROL_PROVIDER_H_ */ + diff --git a/src/data-control-bulk.c b/src/data-control-bulk.c deleted file mode 100755 index 2554492..0000000 --- a/src/data-control-bulk.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2013 - 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 - -#include "data_control_log.h" -#include "data-control-bulk.h" -#include "data-control-types.h" - -static void __free_bulk_result_data(gpointer data) -{ - data_control_bulk_result_data_item_s *result_data_item = (data_control_bulk_result_data_item_s *)data; - bundle_free(result_data_item->result_data); - free(result_data_item); -} - -static void __free_bulk_data(gpointer data) -{ - bundle *bulk_data = (bundle *)data; - bundle_free(bulk_data); -} - -int datacontrol_bulk_data_get_data(data_control_bulk_data_h bulk_data_h, int idx, bundle **data) -{ - bundle *ret_data; - - if (bulk_data_h->data_list == NULL) { - LOGE("NULL data_list"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - ret_data = (bundle *)g_list_nth_data(bulk_data_h->data_list, idx); - if (ret_data == NULL) { - LOGE("no data at index %d", idx); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - *data = ret_data; - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_bulk_data_get_count(data_control_bulk_data_h bulk_data_h, int *count) -{ - *count = g_list_length(bulk_data_h->data_list); - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_bulk_data_add(data_control_bulk_data_h bulk_data_h, bundle *data) -{ - bulk_data_h->data_list = g_list_append(bulk_data_h->data_list, bundle_dup(data)); - LOGI("append bulk data : %d", g_list_length(bulk_data_h->data_list)); - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_bulk_data_create(data_control_bulk_data_h *bulk_data_h) -{ - *bulk_data_h = (struct data_control_bulk_data_s *)calloc(1, sizeof(struct data_control_bulk_data_s)); - if (*bulk_data_h == NULL) { - LOGE("Fail to create bulk data. Out of memory."); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_bulk_data_destroy(data_control_bulk_data_h bulk_data_h) -{ - g_list_free_full(bulk_data_h->data_list, __free_bulk_data); - free(bulk_data_h); - LOGI("bulk data destroy done"); - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_bulk_result_data_get_result_data(data_control_bulk_result_data_h result_data_h, - int idx, bundle **result_data, int *result) -{ - data_control_bulk_result_data_item_s *result_data_item; - - if (result_data_h->data_list == NULL) { - LOGE("NULL result data_list"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - result_data_item = (data_control_bulk_result_data_item_s *)g_list_nth_data(result_data_h->data_list, idx); - if (result_data) - *result_data = result_data_item->result_data; - *result = result_data_item->result; - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_bulk_result_data_get_count(data_control_bulk_result_data_h result_data_h, int *count) -{ - *count = g_list_length(result_data_h->data_list); - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_bulk_result_data_add(data_control_bulk_result_data_h result_data_h, bundle *result_data, int result) -{ - data_control_bulk_result_data_item_s *result_data_item = - (data_control_bulk_result_data_item_s *)calloc(1, sizeof(data_control_bulk_result_data_item_s)); - if (result_data_item == NULL) { - LOGE("fail to alloc bulk_result_data"); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - if (result_data != NULL) { - result_data_item->result_data = bundle_dup(result_data); - if (result_data_item->result_data == NULL) { - free(result_data_item); - LOGE("fail to alloc result_data"); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - } - result_data_item->result = result; - - result_data_h->data_list = g_list_append(result_data_h->data_list, result_data_item); - LOGI("append bulk result data : %d", g_list_length(result_data_h->data_list)); - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_bulk_result_data_create(data_control_bulk_result_data_h *result_data_h) -{ - *result_data_h = (struct data_control_bulk_result_data_s *)calloc(1, sizeof(struct data_control_bulk_result_data_s)); - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_bulk_result_data_destroy(data_control_bulk_result_data_h result_data_h) -{ - g_list_free_full(result_data_h->data_list, __free_bulk_result_data); - free(result_data_h); - LOGI("bulk result data destroy done"); - return DATACONTROL_ERROR_NONE; -} diff --git a/src/data-control-internal.c b/src/data-control-internal.c deleted file mode 100755 index e657ada..0000000 --- a/src/data-control-internal.c +++ /dev/null @@ -1,706 +0,0 @@ -/* - * Copyright (c) 2013 - 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 - -#include - -#include - -#include "data-control-sql-cursor.h" -#include "data-control-internal.h" -#include "data-control-types.h" -#include "data-control-bulk.h" - -#define MAX_STATEMENT_SIZE 1024 -#define RESULT_VALUE_COUNT "RESULT_VALUE_COUNT" -#define MAX_COUNT_PER_PAGE "MAX_COUNT_PER_PAGE" -#define RESULT_PAGE_NUMBER "RESULT_PAGE_NUMBER" -#define MAX_RETRY 10 - -#define ERR_BUFFER_SIZE 1024 -#define BUFSIZE 512 -#define DATA_CONTROL_DBUS_PATH_PREFIX "/org/tizen/data_control_service_" -#define DATA_CONTROL_OBJECT_PATH "/org/tizen/data_control_service" -#define DATA_CONTROL_INTERFACE_NAME "org.tizen.data_control_service" -#define DATA_CONTROL_DB_NAME_PREFIX "._data_control_list_" -#define DATA_CONTROL_DB_NAME "DATA_CONTROL_DATA_CHANGE_TABLE" - -static GDBusConnection *_gdbus_conn = NULL; - -void _bundle_foreach_check_arg_size_cb(const char *key, const int type, - const bundle_keyval_t *kv, void *arg_size) -{ - char *value = NULL; - size_t value_len = 0; - bundle_keyval_get_basic_val((bundle_keyval_t *)kv, (void **)&value, &value_len); - - arg_size += (strlen(key) + value_len) * sizeof(wchar_t); - return; -} - -int _datacontrol_send_async(int sockfd, bundle *kb, void *extra_data, datacontrol_request_type type, void *data) -{ - bundle_raw *kb_data = NULL; - bundle_raw *extra_kb_data = NULL; - int ret = DATACONTROL_ERROR_NONE; - int datalen = 0; - int extra_kb_datalen = 0; - char *buf = NULL; - int total_len = 0; - unsigned int nb = 0; - int i; - int count; - bundle *bulk_data; - data_control_bulk_data_h bulk_data_h = NULL; - bundle_raw *encode_data = NULL; - int encode_datalen = 0; - - LOGD("send async ~~~"); - - bundle_encode_raw(kb, &kb_data, &datalen); - if (kb_data == NULL) { - LOGE("bundle encode error"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - if (DATACONTROL_TYPE_SQL_INSERT == type || - DATACONTROL_TYPE_SQL_UPDATE == type) { - bundle_encode_raw((bundle *)extra_data, &extra_kb_data, &extra_kb_datalen); - if (extra_kb_data == NULL) { - LOGE("bundle encode error"); - goto out; - } - } - - total_len = sizeof(datalen) + datalen; - if (extra_kb_datalen > 0) - total_len += sizeof(extra_kb_datalen) + extra_kb_datalen; - - /* encoded bundle + encoded bundle size */ - buf = (char *)calloc(total_len, sizeof(char)); - if (buf == NULL) { - bundle_free_encoded_rawdata(&kb_data); - LOGE("Out of memory."); - goto out; - } - - memcpy(buf, &datalen, sizeof(datalen)); - memcpy(buf + sizeof(datalen), kb_data, datalen); - if (extra_kb_datalen > 0) { - memcpy(buf + sizeof(datalen) + datalen, &extra_kb_datalen, sizeof(extra_kb_datalen)); - memcpy(buf + sizeof(datalen) + datalen + sizeof(extra_kb_datalen), extra_kb_data, extra_kb_datalen); - } - - LOGI("write : %d", total_len); - if (_write_socket(sockfd, buf, total_len, &nb) != DATACONTROL_ERROR_NONE) { - LOGE("write data fail"); - ret = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - if (DATACONTROL_TYPE_SQL_BULK_INSERT == type || - DATACONTROL_TYPE_MAP_BULK_ADD == type) { - bulk_data_h = (data_control_bulk_data_h)extra_data; - datacontrol_bulk_data_get_count(bulk_data_h, &count); - - if (_write_socket(sockfd, &count, sizeof(count), &nb) != DATACONTROL_ERROR_NONE) { - LOGE("write bulk count fail"); - ret = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - LOGI("write bulk count %d ", count); - for (i = 0; i < count; i++) { - datacontrol_bulk_data_get_data(bulk_data_h, i, &bulk_data); - bundle_encode_raw(bulk_data, &encode_data, &encode_datalen); - if (_write_socket(sockfd, &encode_datalen, sizeof(encode_datalen), &nb) != DATACONTROL_ERROR_NONE) { - LOGE("write bulk encode_datalen fail"); - ret = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - LOGI("write encode_datalen %d ", encode_datalen); - - if (_write_socket(sockfd, encode_data, encode_datalen, &nb) != DATACONTROL_ERROR_NONE) { - LOGE("write bulk encode_data fail"); - ret = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - encode_datalen = 0; - bundle_free_encoded_rawdata(&encode_data); - } - } - -out: - if (buf) - free(buf); - bundle_free_encoded_rawdata(&kb_data); - bundle_free_encoded_rawdata(&extra_kb_data); - bundle_free_encoded_rawdata(&encode_data); - - return ret; -} - -int _recv_bulk_process(int fd, data_control_bulk_result_data_h *result_data_h) -{ - int bulk_results_size; - guint nb; - int retval = DATACONTROL_ERROR_NONE; - int i; - int bulk_result = 0; - char *encode_data = NULL; - int encode_datalen = 0; - bundle *result_data = NULL; - - datacontrol_bulk_result_data_create(result_data_h); - if (_read_socket(fd, (char *)&bulk_results_size, sizeof(bulk_results_size), &nb) != DATACONTROL_ERROR_NONE) { - retval = DATACONTROL_ERROR_IO_ERROR; - LOGE("read socket fail: bulk_results_size"); - goto out; - } - - LOGI("##### bulk result size : %d", bulk_results_size); - for (i = 0; i < bulk_results_size; i++) { - if (_read_socket(fd, (char *)&bulk_result, sizeof(bulk_result), &nb) != DATACONTROL_ERROR_NONE) { - retval = DATACONTROL_ERROR_IO_ERROR; - LOGE("read socket fail: bulk_result"); - goto out; - } - LOGI("##### bulk result : %d", bulk_result); - if (_read_socket(fd, (char *)&encode_datalen, sizeof(encode_datalen), &nb) != DATACONTROL_ERROR_NONE) { - retval = DATACONTROL_ERROR_IO_ERROR; - LOGE("read socket fail: encode_datalen"); - goto out; - } - LOGI("##### encode_datalen : %d", encode_datalen); - if (encode_datalen <= 0 || encode_datalen >= MAX_REQUEST_ARGUMENT_SIZE) { - retval = DATACONTROL_ERROR_IO_ERROR; - LOGE("Invalid encode_datalen %d", encode_datalen); - goto out; - } - encode_data = (char *)calloc(encode_datalen, sizeof(char)); - if (encode_data == NULL) { - retval = DATACONTROL_ERROR_IO_ERROR; - LOGE("FAIL to alloc encode data"); - goto out; - } - if (_read_socket(fd, encode_data, encode_datalen, &nb) != DATACONTROL_ERROR_NONE) { - retval = DATACONTROL_ERROR_IO_ERROR; - LOGE("read socket fail: encode_data"); - free(encode_data); - goto out; - } - result_data = bundle_decode_raw((bundle_raw *)encode_data, encode_datalen); - datacontrol_bulk_result_data_add(*result_data_h, result_data, bulk_result); - if (encode_data) { - free(encode_data); - encode_data = NULL; - } - bundle_free(result_data); - } - -out: - return retval; -} - -datacontrol_data_change_type_e _get_internal_noti_type(data_control_data_change_type_e type) -{ - datacontrol_data_change_type_e ret_type = DATACONTROL_DATA_CHANGE_SQL_UPDATE; - switch (type) { - case DATA_CONTROL_DATA_CHANGE_SQL_UPDATE: - ret_type = DATACONTROL_DATA_CHANGE_SQL_UPDATE; - break; - case DATA_CONTROL_DATA_CHANGE_SQL_INSERT: - ret_type = DATACONTROL_DATA_CHANGE_SQL_INSERT; - break; - case DATA_CONTROL_DATA_CHANGE_SQL_DELETE: - ret_type = DATACONTROL_DATA_CHANGE_SQL_DELETE; - break; - case DATA_CONTROL_DATA_CHANGE_MAP_SET: - ret_type = DATACONTROL_DATA_CHANGE_MAP_SET; - break; - case DATA_CONTROL_DATA_CHANGE_MAP_ADD: - ret_type = DATACONTROL_DATA_CHANGE_MAP_ADD; - break; - case DATA_CONTROL_DATA_CHANGE_MAP_REMOVE: - ret_type = DATACONTROL_DATA_CHANGE_MAP_REMOVE; - break; - default: - LOGE("Invalid noti type"); - break; - } - return ret_type; -} - -data_control_data_change_type_e _get_public_noti_type(datacontrol_data_change_type_e type) -{ - data_control_data_change_type_e ret_type = DATA_CONTROL_DATA_CHANGE_SQL_UPDATE; - switch (type) { - case DATACONTROL_DATA_CHANGE_SQL_UPDATE: - ret_type = DATA_CONTROL_DATA_CHANGE_SQL_UPDATE; - break; - case DATACONTROL_DATA_CHANGE_SQL_INSERT: - ret_type = DATA_CONTROL_DATA_CHANGE_SQL_INSERT; - break; - case DATACONTROL_DATA_CHANGE_SQL_DELETE: - ret_type = DATA_CONTROL_DATA_CHANGE_SQL_DELETE; - break; - case DATACONTROL_DATA_CHANGE_MAP_SET: - ret_type = DATA_CONTROL_DATA_CHANGE_MAP_SET; - break; - case DATACONTROL_DATA_CHANGE_MAP_ADD: - ret_type = DATA_CONTROL_DATA_CHANGE_MAP_ADD; - break; - case DATACONTROL_DATA_CHANGE_MAP_REMOVE: - ret_type = DATA_CONTROL_DATA_CHANGE_MAP_REMOVE; - break; - default: - LOGE("Invalid noti type"); - break; - } - return ret_type; -} - -int _consumer_request_compare_cb(gconstpointer a, gconstpointer b) -{ - datacontrol_consumer_request_info *key1 = (datacontrol_consumer_request_info *)a; - datacontrol_consumer_request_info *key2 = (datacontrol_consumer_request_info *)b; - if (key1->request_id == key2->request_id) - return 0; - - return 1; -} - -int _create_datacontrol_h(datacontrol_h *provider) -{ - struct datacontrol_s *request; - - if (provider == NULL) - return DATACONTROL_ERROR_INVALID_PARAMETER; - - request = malloc(sizeof(struct datacontrol_s)); - if (request == NULL) - return DATACONTROL_ERROR_OUT_OF_MEMORY; - - request->provider_id = NULL; - request->data_id = NULL; - - *provider = request; - - return 0; -} - -int _destroy_datacontrol_h(datacontrol_h provider) -{ - if (provider == NULL) - return DATACONTROL_ERROR_INVALID_PARAMETER; - - if (provider->provider_id != NULL) - free(provider->provider_id); - - if (provider->data_id != NULL) - free(provider->data_id); - - free(provider); - return 0; -} - -int _set_provider_id(datacontrol_h provider, const char *provider_id) -{ - if (provider == NULL || provider_id == NULL) - return DATACONTROL_ERROR_INVALID_PARAMETER; - - if (provider->provider_id != NULL) - free(provider->provider_id); - - provider->provider_id = strdup(provider_id); - if (provider->provider_id == NULL) - return DATACONTROL_ERROR_OUT_OF_MEMORY; - - return 0; -} - -int _set_data_id(datacontrol_h provider, const char *data_id) -{ - if (provider == NULL || data_id == NULL) - return DATACONTROL_ERROR_INVALID_PARAMETER; - - if (provider->data_id != NULL) - free(provider->data_id); - - provider->data_id = strdup(data_id); - if (provider->data_id == NULL) - return DATACONTROL_ERROR_OUT_OF_MEMORY; - - return 0; -} - -int _write_socket(int fd, void *buffer, unsigned int nbytes, - unsigned int *bytes_write) -{ - unsigned int left = nbytes; - gsize nb; - int retry_cnt = 0; - - *bytes_write = 0; - while (left && (retry_cnt < MAX_RETRY)) { - nb = write(fd, buffer, left); - LOGI("_write_socket: ...from %d: nb %d left %d\n", fd, nb, left - nb); - - if (nb == -1) { - if (errno == EINTR) { - LOGE("_write_socket: EINTR error continue ..."); - retry_cnt++; - continue; - } - LOGE("_write_socket: ...error fd %d: errno %d\n", fd, errno); - return DATACONTROL_ERROR_IO_ERROR; - } - - left -= nb; - buffer += nb; - *bytes_write += nb; - retry_cnt = 0; - } - - return DATACONTROL_ERROR_NONE; -} - -int _read_socket(int fd, char *buffer, unsigned int nbytes, - unsigned int *bytes_read) -{ - unsigned int left = nbytes; - gsize nb; - int retry_cnt = 0; - const struct timespec TRY_SLEEP_TIME = { 0, 500 * 1000 * 1000 }; - - *bytes_read = 0; - while (left && (retry_cnt < MAX_RETRY)) { - nb = read(fd, buffer, left); - LOGI("_read_socket: ...from %d: nb %d left %d\n", fd, nb, left - nb); - if (nb == 0) { - LOGE("_read_socket: ...read EOF, socket closed %d: nb %d\n", fd, nb); - return DATACONTROL_ERROR_IO_ERROR; - } else if (nb == -1) { - /* wrt(nodejs) could change socket to none-blocking socket :-( */ - if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { - LOGE("_read_socket: %d errno, sleep and retry ...", errno); - retry_cnt++; - nanosleep(&TRY_SLEEP_TIME, 0); - continue; - } - LOGE("_read_socket: ...error fd %d: errno %d\n", fd, errno); - return DATACONTROL_ERROR_IO_ERROR; - } - - left -= nb; - buffer += nb; - *bytes_read += nb; - retry_cnt = 0; - } - return DATACONTROL_ERROR_NONE; -} - -int _datacontrol_create_request_id(void) -{ - static int id = 0; - g_atomic_int_inc(&id); - - return id; -} - -int _datacontrol_get_data_changed_callback_id(void) -{ - static int id = 0; - g_atomic_int_inc(&id); - - return id; -} - -int _datacontrol_get_data_changed_filter_callback_id(void) -{ - static int id = 0; - g_atomic_int_inc(&id); - - return id; -} - -void _socket_info_free(gpointer socket) -{ - GError *error = NULL; - datacontrol_socket_info *socket_info = (datacontrol_socket_info *)socket; - - if (socket_info != NULL) { - if (socket_info->gio_read != NULL) { - LOGE("shutdown socketpair !!!! %d ", socket_info->socket_fd); - g_io_channel_shutdown(socket_info->gio_read, TRUE, &error); - if (error) { - LOGE("g_io_channel_shutdown error : %s", error->message); - g_error_free(error); - } - g_io_channel_unref(socket_info->gio_read); - socket_info->gio_read = NULL; - } - if (socket_info->g_src_id != 0) { - g_source_remove(socket_info->g_src_id); - socket_info->g_src_id = 0; - } - free(socket_info); - socket_info = NULL; - } - -} - -int _add_watch_on_socket_info(const char *caller_id, - const char *callee_id, const char *type, const char *provider_id, - const char *data_type, GIOFunc cb, void *data, - datacontrol_socket_info **socket_info) -{ - char err_buf[ERR_BUFFER_SIZE]; - int socketpair = 0; - int g_src_id; - int ret; - - datacontrol_socket_info *_socket_info = NULL; - bundle *sock_bundle = bundle_create(); - bundle_add_str(sock_bundle, AUL_K_CALLER_APPID, caller_id); - bundle_add_str(sock_bundle, AUL_K_CALLEE_APPID, callee_id); - bundle_add_str(sock_bundle, "DATA_CONTROL_TYPE", type); - if (provider_id) - bundle_add_str(sock_bundle, OSP_K_DATACONTROL_PROVIDER, provider_id); - if (data_type) - bundle_add_str(sock_bundle, "DATA_CONTROL_DATA_TYPE", data_type); - - ret = aul_request_data_control_socket_pair(sock_bundle, &socketpair); - bundle_free(sock_bundle); - if (ret != AUL_R_OK) { - if (ret == AUL_R_EILLACC) { - LOGE("Permission denied. Consumer need privilege."); - return DATACONTROL_ERROR_PERMISSION_DENIED; - } - - return DATACONTROL_ERROR_IO_ERROR; - } - - LOGI("consumer socket pair : %d", socketpair); - - if (socketpair > 0) { - GIOChannel *gio_read = NULL; - gio_read = g_io_channel_unix_new(socketpair); - if (!gio_read) { - LOGE("Error is %s\n", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - g_src_id = g_io_add_watch(gio_read, G_IO_IN | G_IO_HUP, - cb, data); - if (g_src_id == 0) { - g_io_channel_unref(gio_read); - LOGE("fail to add watch on socket"); - return DATACONTROL_ERROR_IO_ERROR; - } - - _socket_info = (datacontrol_socket_info *)calloc(1, sizeof(datacontrol_socket_info)); - if (_socket_info == NULL) { - g_io_channel_unref(gio_read); - g_source_remove(g_src_id); - LOGE("fail to calloc socket_info"); - return DATACONTROL_ERROR_IO_ERROR; - } - _socket_info->socket_fd = socketpair; - _socket_info->gio_read = gio_read; - _socket_info->g_src_id = g_src_id; - LOGI("Watch on socketpair done."); - } else { - LOGE("fail to get socket pair"); - return DATACONTROL_ERROR_IO_ERROR; - } - - *socket_info = _socket_info; - return DATACONTROL_ERROR_NONE; -} - -int _request_appsvc_run(const char *caller_id, const char *callee_id) -{ - int pid = -1; - int count = 0; - const int TRY_COUNT = 4; - const struct timespec TRY_SLEEP_TIME = { 0, 1000 * 1000 * 1000 }; - bundle *arg_list = bundle_create(); - - if (!arg_list) { - LOGE("unable to create bundle: %d", errno); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - appsvc_set_operation(arg_list, APPSVC_OPERATION_DEFAULT); - appsvc_set_appid(arg_list, callee_id); - bundle_add_str(arg_list, OSP_K_CALLER_TYPE, OSP_V_CALLER_TYPE_OSP); - bundle_add_str(arg_list, OSP_K_LAUNCH_TYPE, OSP_V_LAUNCH_TYPE_DATACONTROL); - bundle_add_str(arg_list, AUL_K_CALLER_APPID, caller_id); - bundle_add_str(arg_list, AUL_K_CALLEE_APPID, callee_id); - bundle_add_str(arg_list, AUL_K_NO_CANCEL, "1"); - LOGI("caller_id %s, callee_id %s", caller_id, callee_id); - - /* For DataControl CAPI */ - bundle_add_str(arg_list, AUL_K_DATA_CONTROL_TYPE, "CORE"); - - do { - pid = appsvc_run_service(arg_list, 0, NULL, NULL); - if (pid >= 0) { - LOGI("Launch the provider app successfully: %d", pid); - bundle_free(arg_list); - break; - } else if (pid == APPSVC_RET_EINVAL) { - LOGE("not able to launch service: %d", pid); - bundle_free(arg_list); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - count++; - - nanosleep(&TRY_SLEEP_TIME, 0); - } while (count < TRY_COUNT); - - if (count >= TRY_COUNT) { - bundle_free(arg_list); - LOGE("unable to launch service: %d", pid); - return DATACONTROL_ERROR_IO_ERROR; - } - - return DATACONTROL_ERROR_NONE; -} - -char *_get_encoded_db_path() -{ - char db_path[PATH_MAX]; - char *dup_db_path = NULL; - char *encoded_appid = NULL; - char provider_appid[255]; - if (aul_app_get_appid_bypid(getpid(), provider_appid, sizeof(provider_appid)) != 0) { - LOGE("Failed to get appid by pid"); - return NULL; - } - - encoded_appid = g_compute_checksum_for_string(G_CHECKSUM_MD5, provider_appid, -1); - snprintf(db_path, sizeof(db_path), "/run/user/%d/%s%s.db", - getuid(), DATA_CONTROL_DB_NAME_PREFIX, encoded_appid); - dup_db_path = strdup(db_path); - if (dup_db_path == NULL) - LOGE("fail to dup db path. out of memory."); - - free(encoded_appid); - LOGI("dup db path : %s ", dup_db_path); - return dup_db_path; -} - -char *_get_encoded_path(datacontrol_h provider, char *consumer_appid) -{ - int prefix_len = strlen(DATA_CONTROL_DBUS_PATH_PREFIX); - char *encoded_path; - char *full_path; - int path_len = strlen(provider->provider_id) + strlen(provider->data_id) + strlen(consumer_appid) + 3; - int full_path_len = path_len + prefix_len; - char *path = (char *)calloc(path_len, sizeof(char)); - if (path == NULL) { - LOGE("path calloc failed"); - return 0; - } - - snprintf(path, path_len, "%s_%s_%s", provider->provider_id, provider->data_id, consumer_appid); - encoded_path = g_compute_checksum_for_string(G_CHECKSUM_MD5, path, -1); - - full_path = (char *)calloc(full_path_len, sizeof(char)); - snprintf(full_path, full_path_len, "%s%s", DATA_CONTROL_DBUS_PATH_PREFIX, encoded_path); - - free(path); - free(encoded_path); - LOGI("full path : %s ", full_path); - return full_path; -} - -int _dbus_init() -{ - int ret = DATACONTROL_ERROR_NONE; - GError *error = NULL; - - if (_gdbus_conn == NULL) { - _gdbus_conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error); - - if (_gdbus_conn == NULL) { - if (error != NULL) { - LOGE("Failed to get dbus [%s]", error->message); - g_error_free(error); - } - return DATACONTROL_ERROR_IO_ERROR; - } - ret = DATACONTROL_ERROR_NONE; - } - return ret; -} - -GDBusConnection *_get_dbus_connection() -{ - int result = _dbus_init(); - if (result != DATACONTROL_ERROR_NONE) { - LOGE("Can't init dbus %d", result); - return NULL; - } - return _gdbus_conn; -} - -int _dbus_signal_init(int *monitor_id, char *path, GDBusSignalCallback callback) -{ - int id; - id = g_dbus_connection_signal_subscribe( - _get_dbus_connection(), - NULL, - DATA_CONTROL_INTERFACE_NAME, /* interface */ - NULL, /* member */ - path, /* path */ - NULL, /* arg0 */ - G_DBUS_SIGNAL_FLAGS_NONE, - callback, - NULL, - NULL); - - LOGI("subscribe id : %d", id); - if (id == 0) { - return DATACONTROL_ERROR_IO_ERROR; - LOGE("Failed to _register_noti_dbus_interface"); - } else { - *monitor_id = id; - } - - return DATACONTROL_ERROR_NONE; -} diff --git a/src/data-control-internal.h b/src/data-control-internal.h deleted file mode 100755 index a8cf535..0000000 --- a/src/data-control-internal.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2013 - 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. - */ - -/** - * @file data-control-internal.h - * @brief This is the header file for private keys of the data-control. - */ -#include -#include -#include "data_control_types.h" -#include "data_control_internal.h" - -#ifndef _APPFW_DATA_CONTROL_INTERNAL_H_ -#define _APPFW_DATA_CONTROL_INTERNAL_H_ - -#undef LOG_TAG -#ifndef LOG_TAG -#define LOG_TAG "DATA_CONTROL" -#endif - -#define MAX_LEN_DATACONTROL_REQ_TYPE 8 -#define MAX_LEN_DATACONTROL_COLUMN_COUNT 8 - -#define OSP_K_LAUNCH_TYPE "__OSP_LAUNCH_TYPE__" -#define OSP_K_ARG "__OSP_ARGS__" -#define OSP_K_REQUEST_ID "__OSP_REQUEST_ID__" -#define OSP_K_DATACONTROL_PROVIDER "__OSP_DATACONTROL_PROVIDER__" -#define OSP_K_DATACONTROL_DATA "__OSP_DATACONTROL_DATA__" -#define OSP_K_DATACONTROL_REQUEST_TYPE "__OSP_DATACONTROL_REQUEST_TYPE__" -#define OSP_K_DATACONTROL_PROTOCOL_VERSION "__OSP_DATACONTROL_PROTOCOL_VERSION__" -#define OSP_K_CALLER_TYPE "__OSP_CALLER_TYPE__" -#define OSP_K_DATACONTROL_UNIQUE_NAME "__OSP_DATACONTROL_UNIQUE_NAME__" -#define OSP_K_DATA_CHANGED_CALLBACK_ID "__OSP_DATA_CHANGED_CALLBACK_ID__" - -#define DATACONTROL_SELECT_STATEMENT "DATACONTROL_SELECT_STATEMENT" - -#define DATACONTROL_EMPTY "NULL" -#define DATACONTROL_SELECT_EXTRA_COUNT 6 /* data id, column count, where, order, page, per_page */ -#define DATACONTROL_RESULT_NO_DATA -1 - -#define OSP_V_LAUNCH_TYPE_DATACONTROL "datacontrol" -#define OSP_V_VERSION_2_1_0_3 "ver_2.1.0.3" -#define OSP_V_CALLER_TYPE_OSP "osp" -#define DATACONTROL_REQUEST_FILE_PREFIX "datacontrol.request." - -#define MAX_REQUEST_ARGUMENT_SIZE 1048576 /* 1MB */ -#define MAX_ROW_COUNT 1024 -#define MAX_COLUMN_SIZE 512 -#define MAX_COLUMN_COUNT 32767 /* Base on sqlite3 maximum column count */ -#define MAX_VALUE_COUNT 1024 - -/** - * @brief Enumerations of different type of data control requests. - */ - -typedef struct datacontrol_pkt { - int len; - unsigned char data[1]; -} datacontrol_pkt_s; - -typedef struct datacontrol_socket { - GIOChannel *gio_read; - int g_src_id; - int socket_fd; -} datacontrol_socket_info; - -typedef struct datacontrol_consumer_request { - int request_id; - datacontrol_request_type type; -} datacontrol_consumer_request_info; - -typedef struct datacontrol_consumer { - int monitor_id; - char *appid; - char *object_path; - char *unique_id; -} datacontrol_consumer_info; - -struct datacontrol_s { - char *provider_id; - char *data_id; -}; - -void _bundle_foreach_check_arg_size_cb(const char *key, const int type, - const bundle_keyval_t *kv, void *arg_size); -int _datacontrol_send_async(int sockfd, bundle *kb, void *extra_data, datacontrol_request_type type, void *data); -int _recv_bulk_process(int fd, data_control_bulk_result_data_h *result_data_h); -int _consumer_request_compare_cb(gconstpointer a, gconstpointer b); -int _datacontrol_sql_set_cursor(const char *path); -int _datacontrol_create_request_id(void); -int _datacontrol_get_data_changed_callback_id(void); -int _datacontrol_get_data_changed_filter_callback_id(void); - -int _read_socket(int fd, char *buffer, unsigned int nbytes, unsigned int *bytes_read); -int _write_socket(int fd, void *buffer, unsigned int nbytes, unsigned int *bytes_write); - -gboolean _datacontrol_recv_message(GIOChannel *channel, GIOCondition cond, gpointer data); -int _get_gdbus_shared_connection(GDBusConnection **connection, char *provider_id); -void _socket_info_free(gpointer socket); -int _add_watch_on_socket_info(const char *caller_id, - const char *callee_id, const char *type, const char *provider_id, - const char *data_type, GIOFunc cb, void *data, - datacontrol_socket_info **socket_info); -int _request_appsvc_run(const char *caller_id, const char *callee_id); - -GDBusConnection *_get_dbus_connection(); -int _dbus_signal_init(int *monitor_id, char *path, GDBusSignalCallback callback); -char *_get_encoded_path(datacontrol_h provider, char *consumer_appid); -char *_get_encoded_db_path(); - -int _create_datacontrol_h(datacontrol_h *provider); -int _destroy_datacontrol_h(datacontrol_h provider); -int _set_provider_id(datacontrol_h provider, const char *provider_id); -int _set_data_id(datacontrol_h provider, const char *data_id); -datacontrol_data_change_type_e _get_internal_noti_type(data_control_data_change_type_e type); -data_control_data_change_type_e _get_public_noti_type(datacontrol_data_change_type_e type); -bool _check_int(int num); - -#endif /* _APPFW_DATA_CONTROL_INTERNAL_H_ */ - diff --git a/src/data-control-map.c b/src/data-control-map.c deleted file mode 100755 index f3313e1..0000000 --- a/src/data-control-map.c +++ /dev/null @@ -1,1089 +0,0 @@ -/* - * Copyright (c) 2013 - 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 -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "data-control-map.h" -#include "data-control-internal.h" -#include "data-control-bulk.h" - -typedef struct { - char *provider_id; - char *app_id; - char *data_id; - char *access_info; - void *user_data; - GList *request_info_list; - datacontrol_map_response_cb *map_response_cb; -} map_response_cb_s; - -static void *datacontrol_map_tree_root = NULL; -static GHashTable *__socket_pair_hash = NULL; - -static void __map_call_cb(const char *provider_id, int request_id, datacontrol_request_type type, - const char *data_id, bool provider_result, const char *error, char **result_value_list, int result_value_count, - data_control_bulk_result_data_h bulk_results, void *data) -{ - LOGI("__map_call_cb, dataID: %s", data_id); - - datacontrol_map_response_cb *callback = NULL; - - map_response_cb_s *map_dc = NULL; - map_dc = (map_response_cb_s *)data; - callback = map_dc->map_response_cb; - if (!callback) { - LOGE("no listener set"); - return; - } - - datacontrol_h provider; - datacontrol_map_create(&provider); - - datacontrol_map_set_provider_id(provider, provider_id); - datacontrol_map_set_data_id(provider, data_id); - - switch (type) { - case DATACONTROL_TYPE_MAP_BULK_ADD: - LOGI("ADD VALUE"); - if (callback != NULL && callback->bulk_add != NULL) - callback->bulk_add(request_id, provider, bulk_results, provider_result, error, map_dc->user_data); - else - LOGI("No registered callback function"); - - break; - case DATACONTROL_TYPE_MAP_GET: - LOGI("GET VALUE"); - if (callback != NULL && callback->get != NULL) - callback->get(request_id, provider, result_value_list, result_value_count, provider_result, error, map_dc->user_data); - else - LOGI("No registered callback function"); - - break; - case DATACONTROL_TYPE_MAP_SET: - LOGI("SET VALUE"); - if (callback != NULL && callback->set != NULL) - callback->set(request_id, provider, provider_result, error, map_dc->user_data); - else - LOGI("No registered callback function"); - - break; - case DATACONTROL_TYPE_MAP_ADD: - LOGI("ADD VALUE"); - if (callback != NULL && callback->add != NULL) - callback->add(request_id, provider, provider_result, error, map_dc->user_data); - else - LOGI("No registered callback function"); - - break; - case DATACONTROL_TYPE_MAP_REMOVE: - LOGI("REMOVE VALUE"); - if (callback != NULL && callback->remove != NULL) - callback->remove(request_id, provider, provider_result, error, map_dc->user_data); - else - LOGI("No registered callback function"); - - break; - default: - break; - } - - datacontrol_map_destroy(provider); -} - -static void __map_instance_free(void *datacontrol_map_instance) -{ - map_response_cb_s *dc = (map_response_cb_s *)datacontrol_map_instance; - if (dc) { - free(dc->provider_id); - free(dc->data_id); - free(dc->app_id); - free(dc->access_info); - free(datacontrol_map_instance); - } - - return; -} - -static int __map_instance_compare(const void *l_datacontrol_map_instance, const void *r_datacontrol_map_instance) -{ - map_response_cb_s *dc_left = (map_response_cb_s *)l_datacontrol_map_instance; - map_response_cb_s *dc_right = (map_response_cb_s *)r_datacontrol_map_instance; - return strcmp(dc_left->provider_id, dc_right->provider_id); -} - -static char **__map_get_value_list(int fd, int *value_count) -{ - char **value_list = NULL; - int i = 0; - int count = 0; - int nbytes = 0; - unsigned int nb = 0; - int j; - - if (_read_socket(fd, (char *)&count, sizeof(count), &nb)) { - LOGE("datacontrol_recv_map_get_value_list : ...from %d: fail to read\n", fd); - return NULL; - } - - if (count < 0 || count > MAX_VALUE_COUNT) { - LOGE("invalid count %d", count); - return NULL; - } - - value_list = (char **)calloc(count, sizeof(char *)); - if (value_list == NULL) { - LOGE("Failed to create value list"); - return NULL; - } - - for (i = 0; i < count; i++) { - if (_read_socket(fd, (char *)&nbytes, sizeof(nbytes), &nb)) { - LOGE("datacontrol_recv_map_get_value_list : ...from %d: fail to read\n", fd); - goto ERROR; - } - if (nbytes < 0 || nbytes > MAX_REQUEST_ARGUMENT_SIZE) { - LOGE("invalid nbytes %d", nbytes); - goto ERROR; - } - - LOGI("nbytes : %d %d" , nbytes , nb); - value_list[i] = (char *)calloc(nbytes + 1, sizeof(char)); - - if (_read_socket(fd, value_list[i], nbytes, &nb)) { - LOGE("datacontrol_recv_map_get_value_list : ...from %d: fail to read\n", fd); - goto ERROR; - } - LOGI("value_list[i] : %s %d" , value_list[i] , nb); - } - *value_count = count; - - return value_list; - - /* LCOV_EXCL_START */ -ERROR: - if (value_list) { - for (j = 0; j < i; j++) { - if (value_list[j] != NULL) - free(value_list[j]); - } - free(value_list); - } - - return NULL; - /* LCOV_EXCL_STOP */ -} - -static void __remove_map_request_info(int request_id, map_response_cb_s *map_dc) -{ - - datacontrol_consumer_request_info temp_request_info; - datacontrol_consumer_request_info *data; - - temp_request_info.request_id = request_id; - GList *list = g_list_find_custom(map_dc->request_info_list, &temp_request_info, - (GCompareFunc)_consumer_request_compare_cb); - if (list != NULL) { - data = (datacontrol_consumer_request_info *)list->data; - map_dc->request_info_list = g_list_remove(map_dc->request_info_list, list->data); - free(data); - } -} - -static int __map_handle_cb(int fd, bundle *b, int request_type, int request_id, appsvc_result_val res, void *data) -{ - int ret = 0; - const char **result_list = NULL; - const char *provider_id = NULL; - const char *data_id = NULL; - const char *error_message = NULL; - int result_list_len = 0; - int provider_result = 0; - int value_count = 0; - int i; - char **value_list = NULL; - const char *p = NULL; - data_control_bulk_result_data_h bulk_results = NULL; - - LOGI("__map_handle_cb, request_type: %d", request_type); - - if (!b) { - LOGE("the bundle returned from datacontrol-provider-service is null"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - /* result list */ - result_list = bundle_get_str_array(b, OSP_K_ARG, &result_list_len); - if (!result_list) { - LOGE("Invalid Bundle: arguement list is null"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - p = result_list[0]; /* result list[0] = provider_result */ - if (!p) { - LOGE("Invalid Bundle: provider_result is null"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - LOGI("Provider result: %s", p); - - provider_result = atoi(p); - - error_message = result_list[1]; /* result list[1] = error */ - if (!error_message) { - LOGE("Invalid Bundle: error_message is null"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - LOGI("Error message: %s", error_message); - - provider_id = bundle_get_val(b, OSP_K_DATACONTROL_PROVIDER); - if (!provider_id) { - LOGE("Invalid Bundle: provider_id is null"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - data_id = bundle_get_val(b, OSP_K_DATACONTROL_DATA); - if (!data_id) { - LOGE("Invalid Bundle: data_id is null"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - LOGI("Provider ID: %s, Data ID: %s, Operation type: %d", provider_id, data_id, request_type); - - switch (request_type) { - case DATACONTROL_TYPE_MAP_BULK_ADD: - LOGI("BULK ADD RESPONSE"); - if (provider_result) { - if (_recv_bulk_process(fd, &bulk_results) - != DATACONTROL_ERROR_NONE) { - if (bulk_results) - datacontrol_bulk_result_data_destroy(bulk_results); - - return DATACONTROL_ERROR_IO_ERROR; - } - } - break; - case DATACONTROL_TYPE_MAP_GET: - LOGI("GET RESPONSE"); - if (provider_result) { - value_list = __map_get_value_list(fd, &value_count); - - if (value_list == NULL && value_count != 0) { - LOGE("Invalid data: value_list is null"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - } - break; - case DATACONTROL_TYPE_MAP_SET: - case DATACONTROL_TYPE_MAP_ADD: - case DATACONTROL_TYPE_MAP_REMOVE: - LOGI("SET or ADD or REMOVE RESPONSE"); - break; - default: - break; - } - - if (request_type >= DATACONTROL_TYPE_MAP_GET && request_type <= DATACONTROL_TYPE_MAP_BULK_ADD) { - __map_call_cb(provider_id, request_id, request_type, data_id, provider_result, - error_message, value_list, value_count, bulk_results, data); - ret = DATACONTROL_ERROR_NONE; - } else { - ret = DATACONTROL_ERROR_INVALID_PARAMETER; - } - - if (bulk_results) - datacontrol_bulk_result_data_destroy(bulk_results); - - if (value_list) { - for (i = 0; i < value_count; i++) { - if (value_list[i] != NULL) - free(value_list[i]); - } - free(value_list); - } - - return ret; -} - -static gboolean __recv_map_message(GIOChannel *channel, - GIOCondition cond, - gpointer data) -{ - char *buf = NULL; - int nbytes; - guint nb; - int request_type = 0; - const char *request_code = NULL; - const char *p = NULL; - int request_id = -1; - bundle *kb = NULL; - gint fd = g_io_channel_unix_get_fd(channel); - map_response_cb_s *map_dc; - GList *itr; - datacontrol_consumer_request_info *request_info; - - LOGI("__recv_map_message: ...from %d:%s%s%s%s\n", fd, - (cond & G_IO_ERR) ? " ERR" : "", - (cond & G_IO_HUP) ? " HUP" : "", - (cond & G_IO_IN) ? " IN" : "", - (cond & G_IO_PRI) ? " PRI" : ""); - - if (cond & (G_IO_ERR | G_IO_HUP)) - goto error; - - if (cond & G_IO_IN) { - if (_read_socket(fd, (char *)&nbytes, sizeof(nbytes), &nb)) { - LOGE("Fail to read nbytes from socket"); - goto error; - } - LOGI("nbytes : %d", nbytes); - - if (nb == 0) { - LOGE("__recv_map_message: ...from %d: socket closed\n", fd); - goto error; - } - - LOGI("__recv_map_message: ...from %d: %d bytes\n", fd, nbytes); - if (nbytes > 0 && nbytes < MAX_REQUEST_ARGUMENT_SIZE) { - buf = (char *) calloc(nbytes + 1, sizeof(char)); - if (buf == NULL) { - LOGE("Malloc failed!!"); - goto error; - } - if (_read_socket(fd, buf, nbytes, &nb)) { - LOGE("Fail to read buf from socket"); - goto error; - } - - if (nb == 0) { - LOGE("__recv_map_message: ...from %d: socket closed\n", fd); - goto error; - } - - kb = bundle_decode_raw((bundle_raw *)buf, nbytes); - if (kb == NULL) { - LOGE("__recv_map_message: Unable to decode the bundle\n"); - goto error; - } - - LOGI("__recv_map_message: ...from %d: OK\n", fd); - LOGI("__recv_map_message: ...caller appid %s: OK\n", bundle_get_val(kb, AUL_K_CALLER_APPID)); - - p = bundle_get_val(kb, OSP_K_REQUEST_ID); - if (!p) { - LOGE("Invalid Bundle: request_id is null"); - goto error; - } else { - request_id = atoi(p); - } - LOGI("Request ID: %d", request_id); - - if (data) { - request_code = bundle_get_val(kb, OSP_K_DATACONTROL_REQUEST_TYPE); - if (!request_code) { - LOGE("Invalid Bundle: data-control request type is null"); - goto error; - } - request_type = atoi(request_code); - - if (__map_handle_cb(fd, kb, request_type, request_id, 0, data) != DATACONTROL_ERROR_NONE) - goto error; - } else { - LOGE("error: listener information is null"); - goto error; - } - __remove_map_request_info(request_id, data); - - if (kb) - bundle_free(kb); - if (buf) - free(buf); - } - } - return TRUE; -error: - /* LCOV_EXCL_START */ - if (kb) - bundle_free(kb); - if (buf) - free(buf); - - if (((map_response_cb_s *)data) != NULL) { - map_dc = (map_response_cb_s *)data; - g_hash_table_remove(__socket_pair_hash, map_dc->provider_id); - - itr = g_list_first(map_dc->request_info_list); - while (itr != NULL) { - request_info = (datacontrol_consumer_request_info *)itr->data; - __map_call_cb(map_dc->provider_id, request_info->request_id, request_info->type, map_dc->data_id, false, - "provider IO Error", NULL, 0, NULL, data); - itr = g_list_next(itr); - } - if (map_dc->request_info_list) { - LOGI("free map request_info_list"); - g_list_free_full(map_dc->request_info_list, free); - map_dc->request_info_list = NULL; - } - } - return FALSE; - /* LCOV_EXCL_STOP */ -} - -static int __map_request_provider(datacontrol_h provider, datacontrol_request_type type, bundle *request_data, void *extra_data, int request_id) -{ - char *app_id = NULL; - void *data = NULL; - int ret = DATACONTROL_ERROR_NONE; - void *map_dc_returned = NULL; - char caller_app_id[255]; - char datacontrol_request_operation[MAX_LEN_DATACONTROL_REQ_TYPE] = {0, }; - char req_id[32] = {0,}; - int count = 0; - const int TRY_COUNT = 2; - const struct timespec TRY_SLEEP_TIME = { 0, 1000 * 1000 * 1000 }; - bundle *send_data; - - LOGI("Map Data control request, type: %d, request id: %d", type, request_id); - - if (type < DATACONTROL_TYPE_MAP_GET || type > DATACONTROL_TYPE_MAP_BULK_ADD) { - LOGE("Invalid request type: %d", (int)type); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - if (__socket_pair_hash == NULL) - __socket_pair_hash = g_hash_table_new_full(g_str_hash, g_str_equal, free, _socket_info_free); - - if (!datacontrol_map_tree_root) { - LOGE("The listener tree is empty"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - map_response_cb_s *map_dc_temp = (map_response_cb_s *)calloc(1, sizeof(map_response_cb_s)); - if (!map_dc_temp) { - LOGE("Failed to create map datacontrol"); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - map_dc_temp->provider_id = strdup(provider->provider_id); - if (!map_dc_temp->provider_id) { - LOGE("Failed to assign provider id to map data control: %d", errno); - free(map_dc_temp); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - map_dc_temp->data_id = strdup(provider->data_id); - if (!map_dc_temp->data_id) { - LOGE("Failed to assign data id to map data control: %d", errno); - free(map_dc_temp->provider_id); - free(map_dc_temp); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - map_dc_temp->app_id = NULL; - map_dc_temp->access_info = NULL; - map_dc_temp->user_data = NULL; - map_dc_temp->map_response_cb = NULL; - - map_dc_returned = tfind(map_dc_temp, &datacontrol_map_tree_root, __map_instance_compare); - - __map_instance_free(map_dc_temp); - - if (!map_dc_returned) { - LOGE("Finding the map datacontrol in the listener tree is failed."); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - map_response_cb_s *map_dc = *(map_response_cb_s **)map_dc_returned; - app_id = map_dc->app_id; - datacontrol_consumer_request_info *request_info = (datacontrol_consumer_request_info *)calloc(sizeof(datacontrol_consumer_request_info), 1); - request_info->request_id = request_id; - request_info->type = type; - map_dc->request_info_list = g_list_append(map_dc->request_info_list, request_info); - data = map_dc; - - LOGI("Map datacontrol appid: %s", map_dc->app_id); - - pid_t pid = getpid(); - if (aul_app_get_appid_bypid(pid, caller_app_id, sizeof(caller_app_id)) != 0) { - LOGE("Failed to get appid by pid(%d).", pid); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - send_data = bundle_dup(request_data); - if (send_data == NULL) { - LOGE("fail to alloc result_data"); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - bundle_add_str(send_data, OSP_K_DATACONTROL_PROTOCOL_VERSION, OSP_V_VERSION_2_1_0_3); - bundle_add_str(send_data, AUL_K_CALLER_APPID, caller_app_id); - - snprintf(datacontrol_request_operation, MAX_LEN_DATACONTROL_REQ_TYPE, "%d", (int)(type)); - bundle_add_str(send_data, OSP_K_DATACONTROL_REQUEST_TYPE, datacontrol_request_operation); - - snprintf(req_id, 32, "%d", request_id); - bundle_add_str(send_data, OSP_K_REQUEST_ID, req_id); - - LOGI("caller_id %s, app_id %s", caller_app_id, app_id); - - do { - datacontrol_socket_info *socket_info = g_hash_table_lookup(__socket_pair_hash, provider->provider_id); - if (socket_info == NULL) { - ret = _add_watch_on_socket_info(caller_app_id, app_id, - "consumer", provider->provider_id, "Map", - __recv_map_message, data, - &socket_info); - if (ret != DATACONTROL_ERROR_NONE) { - bundle_free(send_data); - return ret; - } - - ret = _request_appsvc_run(caller_app_id, app_id); - if (ret != DATACONTROL_ERROR_NONE) { - _socket_info_free(socket_info); - bundle_free(send_data); - return ret; - } - - g_hash_table_insert(__socket_pair_hash, strdup(provider->provider_id), socket_info); - } - - LOGI("send data from consumer !!!"); - ret = _datacontrol_send_async(socket_info->socket_fd, send_data, extra_data, type, NULL); - if (ret != DATACONTROL_ERROR_NONE) - g_hash_table_remove(__socket_pair_hash, provider->provider_id); - else - break; - count++; - nanosleep(&TRY_SLEEP_TIME, 0); - } while (ret != DATACONTROL_ERROR_NONE && count < TRY_COUNT); - - bundle_free(send_data); - return ret; -} - -int datacontrol_map_create(datacontrol_h *provider) -{ - struct datacontrol_s *request; - - if (provider == NULL) - return DATACONTROL_ERROR_INVALID_PARAMETER; - - request = malloc(sizeof(struct datacontrol_s)); - if (request == NULL) - return DATACONTROL_ERROR_OUT_OF_MEMORY; - - request->provider_id = NULL; - request->data_id = NULL; - - *provider = request; - - return 0; -} - -int datacontrol_map_destroy(datacontrol_h provider) -{ - if (provider == NULL) - return DATACONTROL_ERROR_INVALID_PARAMETER; - - if (provider->provider_id != NULL) - free(provider->provider_id); - - if (provider->data_id != NULL) - free(provider->data_id); - - free(provider); - - return 0; -} - -int datacontrol_map_set_provider_id(datacontrol_h provider, const char *provider_id) -{ - if (provider == NULL || provider_id == NULL) - return DATACONTROL_ERROR_INVALID_PARAMETER; - - if (provider->provider_id != NULL) - free(provider->provider_id); - - provider->provider_id = strdup(provider_id); - if (provider->provider_id == NULL) - return DATACONTROL_ERROR_OUT_OF_MEMORY; - - return 0; -} - -int datacontrol_map_get_provider_id(datacontrol_h provider, char **provider_id) -{ - if (provider == NULL || provider_id == NULL) - return DATACONTROL_ERROR_INVALID_PARAMETER; - - if (provider->provider_id != NULL) { - *provider_id = strdup(provider->provider_id); - if (*provider_id == NULL) - return DATACONTROL_ERROR_OUT_OF_MEMORY; - - } else { - *provider_id = NULL; - } - - return 0; -} - -int datacontrol_map_set_data_id(datacontrol_h provider, const char *data_id) -{ - if (provider == NULL || data_id == NULL) - return DATACONTROL_ERROR_INVALID_PARAMETER; - - if (provider->data_id != NULL) - free(provider->data_id); - - provider->data_id = strdup(data_id); - if (provider->data_id == NULL) - return DATACONTROL_ERROR_OUT_OF_MEMORY; - - return 0; -} - -int datacontrol_map_get_data_id(datacontrol_h provider, char **data_id) -{ - if (provider == NULL || data_id == NULL) - return DATACONTROL_ERROR_INVALID_PARAMETER; - - if (provider->data_id != NULL) { - *data_id = strdup(provider->data_id); - if (*data_id == NULL) - return DATACONTROL_ERROR_OUT_OF_MEMORY; - - } else { - *data_id = NULL; - } - - return 0; -} - -bool datacontrol_map_cb_is_registered(char *provider_id) -{ - map_response_cb_s map_dc_temp; - map_dc_temp.provider_id = provider_id; - - if (tfind(&map_dc_temp, &datacontrol_map_tree_root, __map_instance_compare) != NULL) - return true; - return false; -} - -int datacontrol_map_register_response_cb(datacontrol_h provider, datacontrol_map_response_cb *callback, void *user_data) -{ - int ret = 0; - char *app_id = NULL; - char *access = NULL; - void *map_dc_returned = NULL; - - ret = pkgmgrinfo_appinfo_usr_get_datacontrol_info(provider->provider_id, "Map", getuid(), &app_id, &access); - if (ret != PMINFO_R_OK) { - LOGE("unable to get map data control information: %d", ret); - return DATACONTROL_ERROR_IO_ERROR; - } - - LOGI("data control provider appid = %s", app_id); - - map_response_cb_s *map_dc_temp = (map_response_cb_s *)calloc(1, sizeof(map_response_cb_s)); - if (!map_dc_temp) { - LOGE("unable to create a temporary map data control"); - ret = DATACONTROL_ERROR_OUT_OF_MEMORY; - goto EXCEPTION; - } - - map_dc_temp->provider_id = strdup(provider->provider_id); - if (!map_dc_temp->provider_id) { - LOGE("unable to assign provider_id to map data control: %d", errno); - ret = DATACONTROL_ERROR_OUT_OF_MEMORY; - goto EXCEPTION; - } - - map_dc_temp->data_id = strdup(provider->data_id); - if (!map_dc_temp->data_id) { - LOGE("unable to assign data_id to map data control: %d", errno); - ret = DATACONTROL_ERROR_OUT_OF_MEMORY; - goto EXCEPTION; - } - - map_dc_temp->app_id = app_id; - map_dc_temp->access_info = access; - map_dc_temp->user_data = user_data; - map_dc_temp->map_response_cb = callback; - - map_dc_returned = tsearch(map_dc_temp, &datacontrol_map_tree_root, __map_instance_compare); - - map_response_cb_s *map_dc = *(map_response_cb_s **)map_dc_returned; - if (map_dc != map_dc_temp) { - map_dc->map_response_cb = callback; - map_dc->user_data = user_data; - LOGI("the data control is already set"); - __map_instance_free(map_dc_temp); - } - - return DATACONTROL_ERROR_NONE; - - /* LCOV_EXCL_START */ -EXCEPTION: - if (access) - free(access); - if (app_id) - free(app_id); - if (map_dc_temp) { - if (map_dc_temp->provider_id) - free(map_dc_temp->provider_id); - if (map_dc_temp->data_id) - free(map_dc_temp->data_id); - free(map_dc_temp); - } - - return ret; - /* LCOV_EXCL_STOP */ -} - -int datacontrol_map_unregister_response_cb(datacontrol_h provider) -{ - int ret = DATACONTROL_ERROR_NONE; - map_response_cb_s *map_dc_temp = (map_response_cb_s *)calloc(1, sizeof(map_response_cb_s)); - map_response_cb_s *map_dc_returned = NULL; - char *tmp_provider_id; - - g_hash_table_remove(__socket_pair_hash, provider->provider_id); - - if (!map_dc_temp) { - LOGE("unable to create a temporary map data control"); - ret = DATACONTROL_ERROR_OUT_OF_MEMORY; - goto EXCEPTION; - } - - map_dc_temp->provider_id = strdup(provider->provider_id); - if (!map_dc_temp->provider_id) { - LOGE("unable to assign provider_id to map data control: %d", errno); - ret = DATACONTROL_ERROR_OUT_OF_MEMORY; - goto EXCEPTION; - } - - if (datacontrol_map_tree_root == NULL) { - LOGE("The listener tree is empty"); - ret = DATACONTROL_ERROR_INVALID_PARAMETER; - goto EXCEPTION; - } - - map_dc_returned = *(map_response_cb_s **)tfind(map_dc_temp, &datacontrol_map_tree_root, __map_instance_compare); - if (map_dc_returned == NULL) { - LOGE("invalid parameter"); - ret = DATACONTROL_ERROR_INVALID_PARAMETER; - goto EXCEPTION; - } - - if (map_dc_returned->app_id) - free(map_dc_returned->app_id); - if (map_dc_returned->data_id) - free(map_dc_returned->data_id); - if (map_dc_returned->access_info) - free(map_dc_returned->access_info); - if (map_dc_returned->request_info_list) - g_list_free_full(map_dc_returned->request_info_list, free); - - tmp_provider_id = map_dc_returned->provider_id; - tdelete(map_dc_temp, &datacontrol_map_tree_root, __map_instance_compare); - free(tmp_provider_id); - - /* LCOV_EXCL_START */ -EXCEPTION: - if (map_dc_temp) { - if (map_dc_temp->provider_id) - free(map_dc_temp->provider_id); - free(map_dc_temp); - } - - return ret; - /* LCOV_EXCL_STOP */ -} - -int datacontrol_map_get(datacontrol_h provider, const char *key, int *request_id) -{ - return datacontrol_map_get_with_page(provider, key, request_id, 1, 20); -} - -int datacontrol_map_get_with_page(datacontrol_h provider, const char *key, int *request_id, int page_number, int count_per_page) -{ - unsigned int arg_size; - int ret = 0; - const char *arg_list[4]; - char page_no_str[32]; - char count_per_page_str[32]; - int reqId; - - if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || key == NULL) { - LOGE("Invalid parameter"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - LOGI("Gets the value list from provider_id: %s, data_id: %s", provider->provider_id, provider->data_id); - - arg_size = (strlen(provider->data_id) + strlen(key)) * sizeof(wchar_t); - if (arg_size > MAX_REQUEST_ARGUMENT_SIZE) { - LOGE("The size of sending argument (%u) exceeds the maximum limit.", arg_size); - return DATACONTROL_ERROR_MAX_EXCEEDED; - } - - bundle *b = bundle_create(); - if (!b) { - LOGE("unable to create bundle: %d", errno); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id); - bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id); - - arg_list[0] = provider->data_id; - arg_list[1] = key; - - ret = snprintf(page_no_str, sizeof(page_no_str), "%d", page_number); - if (ret < 0) { - LOGE("unable to convert page no to string: %d", errno); - bundle_free(b); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - ret = snprintf(count_per_page_str, sizeof(count_per_page_str), "%d", count_per_page); - if (ret < 0) { - LOGE("unable to convert count per page no to string: %d", errno); - bundle_free(b); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - arg_list[2] = page_no_str; - arg_list[3] = count_per_page_str; - - bundle_add_str_array(b, OSP_K_ARG, arg_list, 4); - - /* Set the request id */ - reqId = _datacontrol_create_request_id(); - *request_id = reqId; - - ret = __map_request_provider(provider, DATACONTROL_TYPE_MAP_GET, b, NULL, reqId); - bundle_free(b); - - return ret; -} - -int datacontrol_map_set(datacontrol_h provider, const char *key, const char *old_value, const char *new_value, int *request_id) -{ - unsigned int arg_size; - bundle *b; - const char *arg_list[4]; - int reqId; - int ret; - - if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || key == NULL || old_value == NULL || new_value == NULL) { - LOGE("Invalid parameter"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - LOGI("Sets the old value to new value in provider_id: %s, data_id: %s", provider->provider_id, provider->data_id); - - arg_size = (strlen(provider->data_id) + strlen(key) + strlen(old_value) + strlen(new_value)) * sizeof(wchar_t); - if (arg_size > MAX_REQUEST_ARGUMENT_SIZE) { - LOGE("The size of sending argument (%u) exceeds the maximum limit.", arg_size); - return DATACONTROL_ERROR_MAX_EXCEEDED; - } - - b = bundle_create(); - if (!b) { - LOGE("unable to create bundle: %d", errno); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id); - bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id); - - arg_list[0] = provider->data_id; - arg_list[1] = key; - arg_list[2] = old_value; - arg_list[3] = new_value; - - bundle_add_str_array(b, OSP_K_ARG, arg_list, 4); - - /* Set the request id */ - reqId = _datacontrol_create_request_id(); - *request_id = reqId; - - ret = __map_request_provider(provider, DATACONTROL_TYPE_MAP_SET, b, NULL, reqId); - bundle_free(b); - - return ret; -} - -int datacontrol_map_add_bulk_data(datacontrol_h provider, data_control_bulk_data_h bulk_data_h, int *request_id) -{ - unsigned int arg_size = 0; - bundle *b; - bundle *data; - const char *arg_list[3]; - int ret; - int count; - int i; - - if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL) { - LOGE("Invalid parameter"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - LOGI("Adds the value in provider_id: %s, data_id: %s", provider->provider_id, provider->data_id); - datacontrol_bulk_data_get_count(bulk_data_h, &count); - for (i = 0; i < count; i++) { - datacontrol_bulk_data_get_data(bulk_data_h, i, &data); - bundle_foreach(data, _bundle_foreach_check_arg_size_cb, &arg_size); - } - - arg_size += (strlen(provider->data_id) + strlen(provider->provider_id)) * sizeof(char); - if (arg_size > MAX_REQUEST_ARGUMENT_SIZE) { - LOGE("The size of sending argument (%u) exceeds the maximum limit.", arg_size); - return DATACONTROL_ERROR_MAX_EXCEEDED; - } - - b = bundle_create(); - if (!b) { - LOGE("unable to create bundle: %d", errno); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id); - bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id); - - arg_list[0] = provider->data_id; - - bundle_add_str_array(b, OSP_K_ARG, arg_list, 1); - *request_id = _datacontrol_create_request_id(); - - ret = __map_request_provider(provider, DATACONTROL_TYPE_MAP_BULK_ADD, b, bulk_data_h, *request_id); - bundle_free(b); - - return ret; -} - - -int datacontrol_map_add(datacontrol_h provider, const char *key, const char *value, int *request_id) -{ - unsigned int arg_size; - bundle *b; - const char *arg_list[3]; - int reqId; - int ret; - - if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || key == NULL || value == NULL) { - LOGE("Invalid parameter"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - LOGI("Adds the value in provider_id: %s, data_id: %s", provider->provider_id, provider->data_id); - - arg_size = (strlen(provider->data_id) + strlen(key) + strlen(value)) * sizeof(wchar_t); - if (arg_size > MAX_REQUEST_ARGUMENT_SIZE) { - LOGE("The size of sending argument (%u) exceeds the maximum limit.", arg_size); - return DATACONTROL_ERROR_MAX_EXCEEDED; - } - - b = bundle_create(); - if (!b) { - LOGE("unable to create bundle: %d", errno); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id); - bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id); - - arg_list[0] = provider->data_id; - arg_list[1] = key; - arg_list[2] = value; - - bundle_add_str_array(b, OSP_K_ARG, arg_list, 3); - - /* Set the request id */ - reqId = _datacontrol_create_request_id(); - *request_id = reqId; - - ret = __map_request_provider(provider, DATACONTROL_TYPE_MAP_ADD, b, NULL, reqId); - bundle_free(b); - - return ret; -} - -int datacontrol_map_remove(datacontrol_h provider, const char *key, const char *value, int *request_id) -{ - unsigned int arg_size; - bundle *b; - const char *arg_list[3]; - int reqId; - int ret; - - if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || key == NULL || value == NULL) { - LOGE("Invalid parameter"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - LOGI("Removes the value in provider_id: %s, data_id: %s", provider->provider_id, provider->data_id); - - arg_size = (strlen(provider->data_id) + strlen(key) + strlen(value)) * sizeof(wchar_t); - if (arg_size > MAX_REQUEST_ARGUMENT_SIZE) { - LOGE("The size of sending argument (%u) exceeds the maximum limit.", arg_size); - return DATACONTROL_ERROR_MAX_EXCEEDED; - } - - b = bundle_create(); - if (!b) { - LOGE("unable to create bundle: %d", errno); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id); - bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id); - - arg_list[0] = provider->data_id; - arg_list[1] = key; - arg_list[2] = value; - - bundle_add_str_array(b, OSP_K_ARG, arg_list, 3); - - /* Set the request id */ - reqId = _datacontrol_create_request_id(); - *request_id = reqId; - - ret = __map_request_provider(provider, DATACONTROL_TYPE_MAP_REMOVE, b, NULL, reqId); - bundle_free(b); - - return ret; -} - diff --git a/src/data-control-noti.c b/src/data-control-noti.c deleted file mode 100755 index 53541d9..0000000 --- a/src/data-control-noti.c +++ /dev/null @@ -1,502 +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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "data_control_log.h" -#include "data-control-noti.h" -#include "data-control-internal.h" - - -typedef struct { - GList *cb_list; - char *provider_appid; - char *provider_id; - char *data_id; - int monitor_id; -} provider_info_s; - -typedef struct { - void *user_data; - int callback_id; - data_control_data_change_cb changed_cb; -} changed_cb_info_s; - -typedef struct { - void *user_data; - int callback_id; - char *provider_id; - char *data_id; - int timeout_id; - data_control_add_callback_result_cb callback; -} add_callback_result_cb_info_s; - -static GList *__add_callback_result_cb_list = NULL; -static GList *__changed_provider_list = NULL; - -static int __callback_result_info_compare_cb(gconstpointer a, gconstpointer b) -{ - add_callback_result_cb_info_s *key1 = - (add_callback_result_cb_info_s *)a; - add_callback_result_cb_info_s *key2 = - (add_callback_result_cb_info_s *)b; - - return !(key1->callback_id == key2->callback_id); -} - -static int __provider_info_compare_cb(gconstpointer a, gconstpointer b) -{ - provider_info_s *key1 = (provider_info_s *)a; - provider_info_s *key2 = (provider_info_s *)b; - return (strcmp(key1->provider_id, key2->provider_id) || strcmp(key1->data_id, key2->data_id)); -} - -static int __changed_cb_info_compare_cb(gconstpointer a, gconstpointer b) -{ - changed_cb_info_s *key1 = (changed_cb_info_s *)a; - changed_cb_info_s *key2 = (changed_cb_info_s *)b; - - return !(key1->callback_id == key2->callback_id); -} - -static void __free_result_cb_info( - add_callback_result_cb_info_s *result_cb_info) -{ - if (result_cb_info) { - if (result_cb_info->provider_id) - free(result_cb_info->provider_id); - if (result_cb_info->data_id) - free(result_cb_info->data_id); - if (result_cb_info->timeout_id > 0) - g_source_remove(result_cb_info->timeout_id); - free(result_cb_info); - } -} - -static void __free_provider_info( - provider_info_s *provider_info) -{ - if (provider_info) { - if (provider_info->provider_appid) - free(provider_info->provider_appid); - if (provider_info->provider_id) - free(provider_info->provider_id); - if (provider_info->data_id) - free(provider_info->data_id); - if (provider_info->monitor_id > 0) - g_dbus_connection_signal_unsubscribe(_get_dbus_connection(), provider_info->monitor_id); - g_list_free_full(provider_info->cb_list, free); - free(provider_info); - } -} - -static void __noti_process(GVariant *parameters) -{ - char *provider_id = NULL; - char *data_id = NULL; - bundle_raw *raw = NULL; - bundle *noti_data = NULL; - int len = 0; - datacontrol_h provider = NULL; - GList *find_list; - changed_cb_info_s *cb_info = NULL; - provider_info_s find_info; - provider_info_s *provider_info; - GList *callback_list = NULL; - datacontrol_data_change_type_e type; - - g_variant_get(parameters, "(i&s&s&si)", &type, &provider_id, &data_id, &raw, &len); - LOGI("__noti_process : %d %s %s %d", type, provider_id, data_id, len); - - if (provider_id == NULL || data_id == NULL) - return; - - find_info.provider_id = provider_id; - find_info.data_id = data_id; - - find_list = g_list_find_custom(__changed_provider_list, &find_info, - (GCompareFunc)__provider_info_compare_cb); - if (find_list != NULL) { - _create_datacontrol_h(&provider); - _set_provider_id(provider, provider_id); - _set_data_id(provider, data_id); - noti_data = bundle_decode(raw, len); - provider_info = (provider_info_s *)find_list->data; - callback_list = g_list_first(provider_info->cb_list); - for (; callback_list != NULL; callback_list = callback_list->next) { - cb_info = callback_list->data; - cb_info->changed_cb((data_control_h)provider, _get_public_noti_type(type), noti_data, cb_info->user_data); - LOGI("callback called: %s, %s", provider_info->provider_id, provider_info->data_id); - } - bundle_free(noti_data); - _destroy_datacontrol_h(provider); - - } else { - LOGE("data_control_data_change_cb is null"); - } - LOGI("__noti_process done"); -} - -static void __call_result_callback(int callback_id, int callback_result) -{ - add_callback_result_cb_info_s *result_cb_info; - add_callback_result_cb_info_s find_info; - datacontrol_h provider; - GList *find_list; - - find_info.callback_id = callback_id; - find_list = g_list_find_custom(__add_callback_result_cb_list, &find_info, - (GCompareFunc)__callback_result_info_compare_cb); - - if (find_list != NULL) { - result_cb_info = (add_callback_result_cb_info_s *)find_list->data; - if (result_cb_info->callback) { - _create_datacontrol_h(&provider); - _set_provider_id(provider, result_cb_info->provider_id); - _set_data_id(provider, result_cb_info->data_id); - - result_cb_info->callback( - (data_control_h)provider, - callback_result, - callback_id, - result_cb_info->user_data); - - _destroy_datacontrol_h(provider); - } else { - LOGE("data_control_add_callback_result_cb is null"); - } - - __add_callback_result_cb_list = g_list_remove(__add_callback_result_cb_list, find_list->data); - __free_result_cb_info(result_cb_info); - } else { - LOGE("add_callback_result_cb_info_s is null"); - } -} - -/* LCOV_EXCL_START */ -static gboolean __add_callback_result_timeout_handler(gpointer user_data) -{ - LOGE("add data changed callback time out !!!"); - add_callback_result_cb_info_s *result_cb_info = - (add_callback_result_cb_info_s *)user_data; - __call_result_callback(result_cb_info->callback_id, DATA_CONTROL_ERROR_IO_ERROR); - return FALSE; -} -/* LCOV_EXCL_STOP */ - -static void __noti_add_remove_data_changed_cb_result_process( - GVariant *parameters) -{ - int callback_id; - data_control_error_e callback_result; - datacontrol_data_change_type_e type; - - g_variant_get(parameters, "(iii)", &type, &callback_id, &callback_result); - LOGI("__noti_add_remove_data_changed_cb_result_process: %d %d %d", type, callback_id, callback_result); - - if (type == DATACONTROL_DATA_CHANGE_CALLBACK_ADD_RESULT) - __call_result_callback(callback_id, callback_result); -} - -static void __handle_noti(GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer user_data) -{ - LOGI("signal_name: %s", signal_name); - - if (g_strcmp0(signal_name, "noti_data_changed") == 0) - __noti_process(parameters); - else if (g_strcmp0(signal_name, "noti_add_remove_result") == 0) - __noti_add_remove_data_changed_cb_result_process(parameters); -} - -static int __noti_request_appsvc_run(const char *callee_id, - char *provider_id, char *data_id, const char *unique_id, int callback_id, int request_type) -{ - int pid = -1; - char callback_id_str[32] = {0,}; - char request_type_str[MAX_LEN_DATACONTROL_REQ_TYPE] = {0,}; - bundle *arg_list = bundle_create(); - if (!arg_list) { - LOGE("unable to create bundle: %d", errno); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - snprintf(callback_id_str, 32, "%d", callback_id); - snprintf(request_type_str, MAX_LEN_DATACONTROL_REQ_TYPE, "%d", (int)(request_type)); - - appsvc_set_operation(arg_list, APPSVC_OPERATION_DEFAULT); - appsvc_set_appid(arg_list, callee_id); - - bundle_add_str(arg_list, OSP_K_DATACONTROL_REQUEST_TYPE, request_type_str); - bundle_add_str(arg_list, OSP_K_DATACONTROL_UNIQUE_NAME, unique_id); - bundle_add_str(arg_list, OSP_K_DATACONTROL_PROVIDER, provider_id); - bundle_add_str(arg_list, OSP_K_DATACONTROL_DATA, data_id); - bundle_add_str(arg_list, OSP_K_DATA_CHANGED_CALLBACK_ID, callback_id_str); - - bundle_add_str(arg_list, OSP_K_CALLER_TYPE, OSP_V_CALLER_TYPE_OSP); - bundle_add_str(arg_list, OSP_K_LAUNCH_TYPE, OSP_V_LAUNCH_TYPE_DATACONTROL); - bundle_add_str(arg_list, AUL_K_CALLEE_APPID, callee_id); - bundle_add_str(arg_list, AUL_K_NO_CANCEL, "1"); - LOGI("callee_id %s", callee_id); - LOGI("provider_id %s, data_id %s", provider_id, data_id); - - /* For DataControl CAPI */ - bundle_add_str(arg_list, AUL_K_DATA_CONTROL_TYPE, "CORE"); - - pid = appsvc_run_service(arg_list, 0, NULL, NULL); - if (pid >= 0) { - LOGI("Launch the provider app successfully: %d", pid); - bundle_free(arg_list); - } else if (pid == APPSVC_RET_EINVAL) { - LOGE("not able to launch service: %d", pid); - bundle_free(arg_list); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } else { - LOGE("unable to launch service: %d", pid); - return DATACONTROL_ERROR_IO_ERROR; - } - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_add_data_change_cb(datacontrol_h provider, - data_control_data_change_cb callback, - void *user_data, - data_control_add_callback_result_cb result_callback, - void *result_cb_user_data, - int *callback_id) -{ - int ret = DATACONTROL_ERROR_NONE; - changed_cb_info_s *cb_info = NULL; - provider_info_s *provider_info = NULL; - provider_info_s find_provider_info; - int monitor_id = 0; - GList *find_list; - char *path = NULL; - const char *unique_id = NULL; - char caller_app_id[255]; - pid_t pid; - add_callback_result_cb_info_s *result_cb_info = NULL; - char *provider_app_id = NULL; - char *access = NULL; - - LOGI("provider_id : %s, data_id : %s", provider->provider_id, provider->data_id); - ret = pkgmgrinfo_appinfo_usr_get_datacontrol_info(provider->provider_id, "Sql", getuid(), &provider_app_id, &access); - if (ret != PMINFO_R_OK) { - LOGE("unable to get sql data control information, retry with map: %d", ret); - ret = pkgmgrinfo_appinfo_usr_get_datacontrol_info(provider->provider_id, "Map", getuid(), &provider_app_id, &access); - if (ret != PMINFO_R_OK) { - LOGE("unable to get map data control information: %d", ret); - return DATACONTROL_ERROR_IO_ERROR; - } - } - - *callback_id = _datacontrol_get_data_changed_callback_id(); - unique_id = g_dbus_connection_get_unique_name(_get_dbus_connection()); - LOGI("unique_id : %s, callback_id %d", unique_id, *callback_id); - - find_provider_info.provider_id = provider->provider_id; - find_provider_info.data_id = provider->data_id; - find_list = g_list_find_custom(__changed_provider_list, &find_provider_info, - (GCompareFunc)__provider_info_compare_cb); - if (find_list == NULL) { - - pid = getpid(); - if (aul_app_get_appid_bypid(pid, caller_app_id, sizeof(caller_app_id)) != 0) { - LOGE("Failed to get appid by pid(%d).", pid); - ret = DATACONTROL_ERROR_INVALID_PARAMETER; - goto err; - } - path = _get_encoded_path(provider, caller_app_id); - if (path == NULL) { - LOGE("cannot get encoded path. out of memory."); - ret = DATACONTROL_ERROR_OUT_OF_MEMORY; - goto err; - } - - ret = _dbus_signal_init(&monitor_id, path, __handle_noti); - if (ret != DATACONTROL_ERROR_NONE) { - LOGE("fail to init dbus signal."); - ret = DATACONTROL_ERROR_IO_ERROR; - goto err; - } - - provider_info = (provider_info_s *)calloc(1, sizeof(provider_info_s)); - if (provider_info == NULL) { - LOGE("provider_info_s alloc fail out of memory."); - ret = DATACONTROL_ERROR_OUT_OF_MEMORY; - goto err; - } - provider_info->provider_appid = strdup(provider_app_id); - provider_info->provider_id = strdup(provider->provider_id); - provider_info->data_id = strdup(provider->data_id); - provider_info->monitor_id = monitor_id; - if (provider_info->provider_id == NULL || provider_info->data_id == NULL) { - LOGE("data_id alloc fail out of memory."); - ret = DATACONTROL_ERROR_OUT_OF_MEMORY; - __free_provider_info(provider_info); - goto err; - } - __changed_provider_list = g_list_append(__changed_provider_list, provider_info); - } else { - provider_info = (provider_info_s *)find_list->data; - } - - ret = __noti_request_appsvc_run( - provider_app_id, - provider_info->provider_id, - provider_info->data_id, - unique_id, - *callback_id, - DATACONTROL_TYPE_ADD_DATA_CHANGED_CB); - if (ret != DATACONTROL_ERROR_NONE) { - LOGE("__noti_request_appsvc_run error !!!"); - goto err; - } - - cb_info = (changed_cb_info_s *)calloc(1, - sizeof(changed_cb_info_s)); - if (cb_info == NULL) { - LOGE("changed_cb_info_s alloc fail out of memory."); - ret = DATACONTROL_ERROR_OUT_OF_MEMORY; - goto err; - } - - cb_info->changed_cb = callback; - cb_info->user_data = user_data; - cb_info->callback_id = *callback_id; - provider_info->cb_list = g_list_append( - provider_info->cb_list, cb_info); - - result_cb_info = - (add_callback_result_cb_info_s *)calloc(1, sizeof(add_callback_result_cb_info_s)); - result_cb_info->callback_id = *callback_id; - result_cb_info->callback = result_callback; - result_cb_info->user_data = result_cb_user_data; - result_cb_info->provider_id = strdup(provider_info->provider_id); - result_cb_info->data_id = strdup(provider_info->data_id); - result_cb_info->timeout_id = g_timeout_add(5000, __add_callback_result_timeout_handler, result_cb_info); - __add_callback_result_cb_list = g_list_append(__add_callback_result_cb_list, result_cb_info); - LOGI("datacontrol_add_data_change_cb done"); - - /* LCOV_EXCL_START */ -err: - if (access) - free(access); - if (provider_app_id) - free(provider_app_id); - if (path) - free(path); - if (ret != DATACONTROL_ERROR_NONE) { - if (monitor_id > 0) - g_dbus_connection_signal_unsubscribe(_get_dbus_connection(), monitor_id); - } - - return ret; - /* LCOV_EXCL_STOP */ -} - -int datacontrol_remove_data_change_cb(datacontrol_h provider, int callback_id) -{ - changed_cb_info_s *removed_cb_info = NULL; - changed_cb_info_s cb_info; - provider_info_s info; - provider_info_s *target_provider_info; - add_callback_result_cb_info_s result_cb_info; - add_callback_result_cb_info_s *tmp; - GList *provider_list = NULL; - GList *callback_list = NULL; - GList *result_cb_list = NULL; - const char *unique_id = NULL; - int ret = DATACONTROL_ERROR_NONE; - - info.provider_id = provider->provider_id; - info.data_id = provider->data_id; - - provider_list = g_list_find_custom(__changed_provider_list, &info, - (GCompareFunc)__provider_info_compare_cb); - if (provider_list == NULL) { - LOGE("Cannot find provider info"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - cb_info.callback_id = callback_id; - target_provider_info = (provider_info_s *)provider_list->data; - callback_list = g_list_find_custom( - target_provider_info->cb_list, - &cb_info, - (GCompareFunc)__changed_cb_info_compare_cb); - if (callback_list == NULL) { - LOGE("Cannot find changed callback info"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - removed_cb_info = (changed_cb_info_s *)callback_list->data; - target_provider_info->cb_list - = g_list_remove(target_provider_info->cb_list, removed_cb_info); - free(removed_cb_info); - - if (g_list_length(target_provider_info->cb_list) == 0) { - unique_id = g_dbus_connection_get_unique_name(_get_dbus_connection()); - LOGI("unique_id : %s", unique_id); - ret = __noti_request_appsvc_run( - target_provider_info->provider_appid, - target_provider_info->provider_id, - target_provider_info->data_id, - unique_id, - callback_id, - DATACONTROL_TYPE_REMOVE_DATA_CHANGED_CB); - if (ret != DATACONTROL_ERROR_NONE) { - LOGE("__sql_request_provider fail %d", ret); - return ret; - } - - __changed_provider_list = g_list_remove(__changed_provider_list, target_provider_info); - __free_provider_info(target_provider_info); - } - - result_cb_info.callback_id = callback_id; - result_cb_list = g_list_find_custom(__add_callback_result_cb_list, &result_cb_info, - (GCompareFunc)__callback_result_info_compare_cb); - if (result_cb_list) { - tmp = (add_callback_result_cb_info_s *)result_cb_list->data; - __add_callback_result_cb_list = g_list_remove(__add_callback_result_cb_list, result_cb_list->data); - __free_result_cb_info(tmp); - } - return DATACONTROL_ERROR_NONE; -} diff --git a/src/data-control-provider.c b/src/data-control-provider.c deleted file mode 100755 index a1e5cfd..0000000 --- a/src/data-control-provider.c +++ /dev/null @@ -1,2342 +0,0 @@ -/* - * Copyright (c) 2013 - 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 -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "data-control-sql.h" -#include "data-control-provider.h" -#include "data-control-internal.h" -#include "data-control-bulk.h" - -#define QUERY_MAXLEN 4096 -#define ROW_ID_SIZE 32 -#define RESULT_PATH_MAX 512 - -#define RESULT_PAGE_NUMBER "RESULT_PAGE_NUMBER" -#define MAX_COUNT_PER_PAGE "MAX_COUNT_PER_PAGE" -#define RESULT_VALUE_COUNT "RESULT_VALUE_COUNT" - -#define PACKET_INDEX_REQUEST_RESULT 0 -#define PACKET_INDEX_ERROR_MSG 1 -#define PACKET_INDEX_SELECT_RESULT_FILE 2 -#define PACKET_INDEX_ROW_ID 2 -#define PACKET_INDEX_VALUE_COUNT 2 -#define PACKET_INDEX_GET_RESULT_FILE 3 - -#define PACKET_INDEX_DATAID 0 -#define PACKET_INDEX_MAP 2 - -#define PACKET_INDEX_UPDATEWHERE 1 -#define PACKET_INDEX_DELETEWHERE 1 - -#define PACKET_INDEX_MAP_KEY 1 -#define PACKET_INDEX_MAP_VALUE_1ST 2 -#define PACKET_INDEX_MAP_VALUE_2ND 3 -#define PACKET_INDEX_MAP_PAGE_NO 2 -#define PACKET_INDEX_MAP_COUNT_PER_PAGE 3 - -#define DATA_CONTROL_BUS_NAME "org.tizen.data_control_service" -#define DATA_CONTROL_OBJECT_PATH "/org/tizen/data_control_service" -#define DATA_CONTROL_INTERFACE_NAME "org.tizen.data_control_service" -#define DATA_CONTROL_DATA_CHANGE_DATA_CHANGED "noti_data_changed" -#define DATA_CONTROL_DATA_CHANGE_ADD_REMOVE_RESULT "noti_add_remove_result" - -static GHashTable *__request_table = NULL; -static GHashTable *__socket_pair_hash = NULL; -static sqlite3 *__provider_db = NULL; - -void *provider_sql_user_data; -void *provider_map_user_data; - -/* static pthread_mutex_t provider_lock = PTHREAD_MUTEX_INITIALIZER; */ -typedef int (*provider_handler_cb) (bundle *b, int request_id, void *data); - -typedef struct { - void *user_data; - int callback_id; - data_control_provider_data_change_consumer_filter_cb callback; -} changed_noti_consumer_filter_info_s; - -static datacontrol_provider_sql_cb *provider_sql_cb = NULL; -static datacontrol_provider_map_cb *provider_map_cb = NULL; - -static GList *__noti_consumer_app_list = NULL; -static GList *__noti_consumer_filter_info_list = NULL; -static int __create_consumer_list_db(); -static int __delete_consumer_list_db_info(char *unique_id); - -static int __data_changed_filter_cb_info_compare_cb(gconstpointer a, gconstpointer b) -{ - changed_noti_consumer_filter_info_s *key1 = (changed_noti_consumer_filter_info_s *)a; - changed_noti_consumer_filter_info_s *key2 = (changed_noti_consumer_filter_info_s *)b; - - return !(key1->callback_id == key2->callback_id); -} - -static int __noti_consumer_app_list_compare_cb(gconstpointer a, gconstpointer b) -{ - datacontrol_consumer_info *info_a = (datacontrol_consumer_info *)a; - datacontrol_consumer_info *info_b = (datacontrol_consumer_info *)b; - - return strcmp(info_a->unique_id, info_b->unique_id); -} - -static void __free_consumer_info(const gchar *name) -{ - datacontrol_consumer_info find_key; - datacontrol_consumer_info *info; - GList *find_list = NULL; - int result; - - find_key.unique_id = (char *)name; - find_list = g_list_find_custom(__noti_consumer_app_list, &find_key, - (GCompareFunc)__noti_consumer_app_list_compare_cb); - if (find_list == NULL) { - LOGI("__free_consumer_info %s not exist", name); - return; - } - - info = (datacontrol_consumer_info *)find_list->data; - result = __delete_consumer_list_db_info(info->unique_id); - if (result != DATACONTROL_ERROR_NONE) - LOGE("__delete_consumer_list_db_info fail %d", result); - - if (info->appid) - free(info->appid); - if (info->object_path) - free(info->object_path); - if (info->unique_id) - free(info->unique_id); - g_bus_unwatch_name(info->monitor_id); - - __noti_consumer_app_list = g_list_remove(__noti_consumer_app_list, find_list->data); - - free(info); - LOGI("__free_consumer_info done"); -} - -static void __free_bundle_data(gpointer data) -{ - if (data) { - bundle_free(data); - data = NULL; - } -} - -static void __free_data(gpointer data) -{ - if (data) { - free(data); - data = NULL; - } -} - -static void __initialize_provider(void) -{ - int result; - __request_table = g_hash_table_new_full(g_int_hash, g_int_equal, __free_data, __free_bundle_data); - __socket_pair_hash = g_hash_table_new_full(g_str_hash, g_str_equal, free, _socket_info_free); - result = __create_consumer_list_db(); - if (result != DATACONTROL_ERROR_NONE) - LOGE("fail to create consumer list db"); -} - -static int __provider_new_request_id(void) -{ - static int id = 0; - g_atomic_int_inc(&id); - return id; -} - -static int __send_select_result(int fd, bundle *b, void *data) -{ - /* - In this function, the result set is written in socket as specific form. - [sizeof(int)] column count - [sizeof(int)] column type x N - [ variant ] (column name leng, column name) x N - [sieeof(int)] total size of column names - [sizeof(int)] row count - [ variant ] (type, size, content) x N - */ - - sqlite3_stmt *state = (sqlite3_stmt *)data; - int column_count = DATACONTROL_RESULT_NO_DATA; - int i = 0; - char *column_name = NULL; - int total_len_of_column_names = 0; - int count_per_page = 0; - int page_number = 1; - int offset = 0; - sqlite3_int64 offset_idx = 0; - sqlite3_int64 row_count = 0; - unsigned int nb = 0; - int type = 0; - int column_name_len; - const char *page_number_str; - int size = 0; - void *value = NULL; - int column_type; - long long tmp_long = 0; - double tmp_double = 0.0; - void *buf = NULL; - int buf_len = 0; - const char *count_per_page_str; - - LOGI("__send_select_result"); - if (b == NULL || data == NULL) { - LOGE("The input param is invalid."); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - if (sqlite3_reset(state) != SQLITE_OK) { - LOGE("sqlite3_reset() is failed."); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - if (sqlite3_step(state) != SQLITE_ROW) { - LOGE("The DB does not have another row."); - if (_write_socket(fd, &column_count, sizeof(int), &nb) != DATACONTROL_ERROR_NONE) { - LOGE("Writing a column_count to a file descriptor is failed."); - return DATACONTROL_ERROR_IO_ERROR; - } - return DATACONTROL_ERROR_NONE; - } - - /* 1. column count */ - column_count = sqlite3_column_count(state); - if (_write_socket(fd, &column_count, sizeof(int), &nb) != DATACONTROL_ERROR_NONE) { - LOGE("Writing a column_count to a file descriptor is failed. errno = %d", errno); - return DATACONTROL_ERROR_IO_ERROR; - } - - LOGI("Writing a column_count %d", column_count); - - /* - 2. column type x column_count - #define SQLITE_INTEGER 1 - #define SQLITE_FLOAT 2 - #define SQLITE_TEXT 3 - #define SQLITE_BLOB 4 - #define SQLITE_NULL 5 - */ - for (i = 0; i < column_count; i++) { - type = sqlite3_column_type(state, i); - if (_write_socket(fd, &type, sizeof(int), &nb) != DATACONTROL_ERROR_NONE) { - LOGI("Writing a type to a file descriptor is failed."); - return DATACONTROL_ERROR_IO_ERROR; - } - LOGI("Writing a column_type %d", type); - } - - /* 3. column name x column_count */ - for (i = 0; i < column_count; i++) { - column_name = (char *)sqlite3_column_name(state, i); - if (column_name == NULL) { - LOGI("sqlite3_column_name is failed. errno = %d", errno); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } else { - column_name_len = strlen(column_name) + 1; - if (_write_socket(fd, &column_name_len, sizeof(int), &nb) != DATACONTROL_ERROR_NONE) { - LOGI("Writing a column_name_len to a file descriptor is failed. errno = %d", errno); - return DATACONTROL_ERROR_IO_ERROR; - } - - LOGI("Writing a column_name_len %d", column_name_len); - - if (_write_socket(fd, column_name, column_name_len, &nb) != DATACONTROL_ERROR_NONE) { - LOGI("Writing a column_name to a file descriptor is failed. errno = %d", errno); - return DATACONTROL_ERROR_IO_ERROR; - } - total_len_of_column_names += strlen(column_name); - LOGI("Writing a column_name %s", column_name); - } - } - - /* 4. total length of column names */ - if (_write_socket(fd, &total_len_of_column_names, sizeof(int), &nb) != DATACONTROL_ERROR_NONE) { - LOGI("Writing a total_len_of_column_names to a file descriptor is failed. errno = %d", errno); - return DATACONTROL_ERROR_IO_ERROR; - } - - LOGI("Writing a total_len_of_column_names %d", total_len_of_column_names); - - page_number_str = bundle_get_val(b, RESULT_PAGE_NUMBER); - count_per_page_str = bundle_get_val(b, MAX_COUNT_PER_PAGE); - - LOGI("page_number: %s, per_page: %s", page_number_str, count_per_page_str); - - /* 5. type, size and value of each element */ - if (page_number_str != NULL) - page_number = atoi(page_number_str); - else - page_number = 1; - - if (count_per_page_str != NULL) - count_per_page = atoi(count_per_page_str); - else - count_per_page = 20; - - offset = (page_number - 1) * count_per_page; - - LOGI("page_number: %d, count_per_page: %d, offset: %d", page_number, count_per_page, offset); - - if (sqlite3_reset(state) != SQLITE_OK) { - LOGE("sqlite3_reset() is failed."); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - if (sqlite3_step(state) != SQLITE_ROW) { - LOGE("The DB does not have another row."); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - do { - offset_idx++; - if (offset_idx > offset) - ++row_count; - } while (sqlite3_step(state) == SQLITE_ROW && row_count < count_per_page); - - /* 6. row count */ - if (_write_socket(fd, &row_count, sizeof(row_count), &nb) != DATACONTROL_ERROR_NONE) { - LOGI("Writing a row_count to a file descriptor is failed. errno = %d", errno); - return DATACONTROL_ERROR_IO_ERROR; - } - LOGI("Writing a row_count %lld", row_count); - - row_count = 0; - offset_idx = 0; - if (sqlite3_reset(state) != SQLITE_OK) { - LOGI("sqlite3_reset() is failed."); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - if (sqlite3_step(state) != SQLITE_ROW) { - LOGE("The DB does not have another row."); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - do { - offset_idx++; - if (offset_idx > offset) { - ++row_count; - for (i = 0; i < column_count; ++i) { - column_type = sqlite3_column_type(state, i); - - switch (column_type) { - case SQLITE_INTEGER: - type = 1; - size = sizeof(long long); - tmp_long = sqlite3_column_int64(state, i); - value = &tmp_long; - break; - case SQLITE_FLOAT: - type = 2; - size = sizeof(double); - tmp_double = sqlite3_column_double(state, i); - value = &tmp_double; - break; - case SQLITE_TEXT: - type = 3; - value = (char *)sqlite3_column_text(state, i); - if (value) - size = strlen(value) + 1; - else - size = 0; - break; - case SQLITE_BLOB: - type = 4; - size = sqlite3_column_bytes(state, i); - value = (char *)sqlite3_column_blob(state, i); - break; - case SQLITE_NULL: - type = 5; - size = 0; - break; - default: - LOGI("The column type is invalid."); - break; - } - - if (value == NULL && type != 5) - return DATACONTROL_ERROR_IO_ERROR; - - buf_len = sizeof(int) * 2 + size; - buf = calloc(buf_len, sizeof(void)); - if (buf == NULL) { - LOGE("calloc failed"); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - memcpy(buf, &type, sizeof(int)); - memcpy(buf + sizeof(int), &size, sizeof(int)); - if (size > 0) - memcpy(buf + sizeof(int) + sizeof(int), value, size); - - if (_write_socket(fd, buf, buf_len, &nb) != DATACONTROL_ERROR_NONE) { - LOGE("Writing a size to a file descriptor is failed. errno = %d", errno); - free(buf); - return DATACONTROL_ERROR_IO_ERROR; - } - - free(buf); - - } - LOGI("row_count ~~~~ %lld", row_count); - - } - - } while (sqlite3_step(state) == SQLITE_ROW && row_count < count_per_page); - - return DATACONTROL_ERROR_NONE; -} - -static int _get_int_from_str(const char *str) -{ - int result = 0; - char *pend; - errno = 0; - result = strtol(str, &pend, 10); - if ((result == LONG_MIN || result == LONG_MAX) - && errno != 0) { - result = 0; - } - - if (*pend != '\0') - result = 0; - - return result; -} - -static int __send_get_value_result(int fd, bundle *b, void *data) -{ - int i = 0; - char **value_list = (char **)data; - const char *page_num_str = bundle_get_val(b, RESULT_PAGE_NUMBER); - const char *count_per_page_str = bundle_get_val(b, MAX_COUNT_PER_PAGE); - const char *value_count_str = bundle_get_val(b, RESULT_VALUE_COUNT); - int page_number = 0; - int count_per_page = 0; - int value_count = 0; - int current_offset = 0; - int remain_count = 0; - unsigned int nb; - int add_value_count; - int length; - - LOGI("page num: %s, count_per_page: %s, value_count %s", page_num_str, count_per_page_str, value_count_str); - - page_number = _get_int_from_str(page_num_str); - count_per_page = _get_int_from_str(count_per_page_str); - value_count = _get_int_from_str(value_count_str); - - current_offset = (page_number - 1) * count_per_page; - remain_count = value_count - current_offset; - remain_count = (remain_count > 0) ? remain_count : 0; /* round off to zero if the negative num is found */ - - add_value_count = (count_per_page > remain_count) ? remain_count : count_per_page; - - LOGI("add_value_count: %d, current_offset: %d, remain_count %d", add_value_count, current_offset, remain_count); - - if (_write_socket(fd, &add_value_count, sizeof(int), &nb) != DATACONTROL_ERROR_NONE) { - LOGE("Writing a length to a file descriptor is failed. errno = %d", errno); - return DATACONTROL_ERROR_IO_ERROR; - } - - add_value_count += current_offset; - - for (i = current_offset; i < add_value_count; i++) { - length = strlen(value_list[i]); - LOGI("length = %d", length); - if (_write_socket(fd, &length, sizeof(int), &nb) != DATACONTROL_ERROR_NONE) { - LOGE("Writing a length to a file descriptor is failed. errno = %d", errno); - return DATACONTROL_ERROR_IO_ERROR; - } - - LOGI("value_list = %s", value_list[i]); - if (_write_socket(fd, value_list[i], length, &nb) != DATACONTROL_ERROR_NONE) { - LOGE("Writing a value_list to a file descriptor is failed. errno = %d", errno); - return DATACONTROL_ERROR_IO_ERROR; - } - } - return DATACONTROL_ERROR_NONE; -} - - -static int __send_bulk_result(int fd, void *data) -{ - data_control_bulk_result_data_h bulk_results = (data_control_bulk_result_data_h)data; - int count; - int i; - int result; - bundle_raw *encode_data = NULL; - int encode_datalen = 0; - bundle *result_data; - unsigned int nb = 0; - - datacontrol_bulk_result_data_get_count(bulk_results, &count); - if (_write_socket(fd, &count, sizeof(int), &nb) != DATACONTROL_ERROR_NONE) { - LOGE("Writing a result count to a file descriptor is failed. errno = %d", errno); - return DATACONTROL_ERROR_IO_ERROR; - } - LOGD("__send_bulk_result %d", count); - - for (i = 0; i < count; i++) { - datacontrol_bulk_result_data_get_result_data(bulk_results, i, &result_data, &result); - if (_write_socket(fd, &result, sizeof(int), &nb) != DATACONTROL_ERROR_NONE) { - LOGE("Writing a result to a file descriptor is failed. errno = %d", errno); - return DATACONTROL_ERROR_IO_ERROR; - } - - if (result_data != NULL) { - bundle_encode_raw(result_data, &encode_data, &encode_datalen); - if (encode_data == NULL) { - LOGE("bundle encode error"); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - } - - if (_write_socket(fd, &encode_datalen, sizeof(int), &nb) != DATACONTROL_ERROR_NONE) { - LOGE("Writing a encode_datalen to a file descriptor is failed. errno = %d", errno); - free(encode_data); - return DATACONTROL_ERROR_IO_ERROR; - } - - if (_write_socket(fd, encode_data, encode_datalen, &nb) != DATACONTROL_ERROR_NONE) { - LOGE("Writing a encode_data to a file descriptor is failed. errno = %d", errno); - free(encode_data); - return DATACONTROL_ERROR_IO_ERROR; - } - - LOGE("result %d, encode_datalen %d", result, encode_datalen); - free(encode_data); - encode_data = NULL; - encode_datalen = 0; - } - return DATACONTROL_ERROR_NONE; -} - -int __datacontrol_send_async(int sockfd, bundle *kb, datacontrol_request_type type, void *data) -{ - bundle_raw *kb_data = NULL; - int ret = DATACONTROL_ERROR_NONE; - int datalen = 0; - char *buf; - int total_len = 0; - unsigned int nb = 0; - - LOGI("send async ~~~"); - bundle_encode_raw(kb, &kb_data, &datalen); - if (kb_data == NULL) { - LOGE("bundle encode error"); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - /* encoded bundle + encoded bundle len */ - buf = (char *)calloc(datalen + 4, sizeof(char)); - if (buf == NULL) { - LOGE("buf calloc error"); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - memcpy(buf, &datalen, sizeof(datalen)); - memcpy(buf + sizeof(datalen), kb_data, datalen); - - total_len = sizeof(datalen) + datalen; - - LOGI("write : %d", datalen); - if (_write_socket(sockfd, buf, total_len, &nb) != DATACONTROL_ERROR_NONE) { - LOGI("write data fail "); - ret = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - if (DATACONTROL_TYPE_SQL_SELECT == type) - ret = __send_select_result(sockfd, kb, data); - else if (DATACONTROL_TYPE_MAP_GET == type) - ret = __send_get_value_result(sockfd, kb, data); - else if (DATACONTROL_TYPE_SQL_BULK_INSERT == type || - DATACONTROL_TYPE_MAP_BULK_ADD == type) - ret = __send_bulk_result(sockfd, data); - -out: - free(buf); - bundle_free_encoded_rawdata(&kb_data); - - return ret; -} - -static bundle *__get_bundle_data_from_fd(int fd) -{ - bundle *b = NULL; - int len = 0; - int ret; - char *buf; - - ret = read(fd, &len, sizeof(int)); - if (ret < sizeof(int)) { - LOGE("read error :%d", ret); - return NULL; - } - LOGD("read len : %d", len); - - if (len > 0 && len < MAX_REQUEST_ARGUMENT_SIZE) { - buf = (char *)calloc(len, sizeof(char)); - if (buf == NULL) { - LOGE("calloc fail"); - return NULL; - } - ret = read(fd, buf, len); - if (ret < len) { - LOGE("read error :%d", ret); - if (buf) - free(buf); - return NULL; - } - b = bundle_decode_raw((bundle_raw *)buf, len); - - if (buf) - free(buf); - } else { - LOGE("__get_bundle_data_from_fd read count : %d", len); - } - - return b; -} - -static data_control_bulk_data_h __get_bulk_data_from_fd(int fd) -{ - data_control_bulk_data_h ret_bulk_data_h = NULL; - int size = 0; - int ret; - int i; - bundle *data = NULL; - - datacontrol_bulk_data_create(&ret_bulk_data_h); - ret = read(fd, &size, sizeof(int)); - if (ret < sizeof(int)) { - LOGE("read error :%d", ret); - datacontrol_bulk_data_destroy(ret_bulk_data_h); - return NULL; - } - - LOGI("bulk data size : %d", size); - if (size < 0 || size >= MAX_REQUEST_ARGUMENT_SIZE) { - LOGE("Invalid data size"); - datacontrol_bulk_data_destroy(ret_bulk_data_h); - return NULL; - } - - for (i = 0; i < size; i++) { - LOGI("bulk data : %d", i); - data = __get_bundle_data_from_fd(fd); - if (data == NULL) { - LOGE("get bundle data from fd fail"); - datacontrol_bulk_data_destroy(ret_bulk_data_h); - return NULL; - } - datacontrol_bulk_data_add(ret_bulk_data_h, data); - bundle_free(data); - } - return ret_bulk_data_h; -} - -static bundle *__set_result(bundle *b, datacontrol_request_type type, void *data) -{ - bundle *res = bundle_create(); - - /* Set the type */ - char type_str[MAX_LEN_DATACONTROL_REQ_TYPE] = {0,}; - const char *request_type; - const char *provider_id; - const char *data_id; - const char *request_id; - const char *caller_appid; - const char *list[3]; - const char *page_num = bundle_get_val(b, RESULT_PAGE_NUMBER); - const char *count_per_page = bundle_get_val(b, MAX_COUNT_PER_PAGE); - - if (type == DATACONTROL_TYPE_UNDEFINED || type == DATACONTROL_TYPE_ERROR) { - request_type = bundle_get_val(b, OSP_K_DATACONTROL_REQUEST_TYPE); - strncpy(type_str, request_type, MAX_LEN_DATACONTROL_REQ_TYPE); - LOGI("type is %s", type_str); - - } else { - snprintf(type_str, MAX_LEN_DATACONTROL_REQ_TYPE, "%d", (int)type); - } - - bundle_add_str(res, OSP_K_DATACONTROL_REQUEST_TYPE, type_str); - - /* Set the provider id */ - provider_id = bundle_get_val(b, OSP_K_DATACONTROL_PROVIDER); - bundle_add_str(res, OSP_K_DATACONTROL_PROVIDER, provider_id); - - /* Set the data id */ - data_id = bundle_get_val(b, OSP_K_DATACONTROL_DATA); - bundle_add_str(res, OSP_K_DATACONTROL_DATA, data_id); - - /* Set the caller request id */ - request_id = bundle_get_val(b, OSP_K_REQUEST_ID); - bundle_add_str(res, OSP_K_REQUEST_ID, request_id); - - caller_appid = bundle_get_val(b, AUL_K_CALLER_APPID); - bundle_add_str(res, AUL_K_CALLER_APPID, caller_appid); - - switch (type) { - case DATACONTROL_TYPE_SQL_SELECT: - { - list[PACKET_INDEX_REQUEST_RESULT] = "1"; /* request result */ - list[PACKET_INDEX_ERROR_MSG] = DATACONTROL_EMPTY; - list[PACKET_INDEX_SELECT_RESULT_FILE] = DATACONTROL_EMPTY; - - page_num = bundle_get_val(b, RESULT_PAGE_NUMBER); - count_per_page = bundle_get_val(b, MAX_COUNT_PER_PAGE); - - LOGI("page num: %s, count_per_page: %s", page_num, count_per_page); - - bundle_add_str(res, RESULT_PAGE_NUMBER, page_num); - bundle_add_str(res, MAX_COUNT_PER_PAGE, count_per_page); - - bundle_add_str_array(res, OSP_K_ARG, list, 3); - - break; - } - case DATACONTROL_TYPE_SQL_BULK_INSERT: - { - list[PACKET_INDEX_REQUEST_RESULT] = "1"; /* request result */ - list[PACKET_INDEX_ERROR_MSG] = DATACONTROL_EMPTY; - bundle_add_str_array(res, OSP_K_ARG, list, 2); - break; - } - case DATACONTROL_TYPE_SQL_INSERT: - { - long long row_id = *(long long *)data; - - const char *list[3]; - list[PACKET_INDEX_REQUEST_RESULT] = "1"; /* request result */ - list[PACKET_INDEX_ERROR_MSG] = DATACONTROL_EMPTY; - - /* Set the row value */ - char row_str[ROW_ID_SIZE] = {0,}; - snprintf(row_str, ROW_ID_SIZE, "%lld", row_id); - - list[PACKET_INDEX_ROW_ID] = row_str; - bundle_add_str_array(res, OSP_K_ARG, list, 3); - break; - } - case DATACONTROL_TYPE_SQL_UPDATE: - case DATACONTROL_TYPE_SQL_DELETE: - { - const char *list[2]; - list[PACKET_INDEX_REQUEST_RESULT] = "1"; /* request result */ - list[PACKET_INDEX_ERROR_MSG] = DATACONTROL_EMPTY; - - bundle_add_str_array(res, OSP_K_ARG, list, 2); - break; - } - case DATACONTROL_TYPE_MAP_BULK_ADD: - { - list[PACKET_INDEX_REQUEST_RESULT] = "1"; /* request result */ - list[PACKET_INDEX_ERROR_MSG] = DATACONTROL_EMPTY; - bundle_add_str_array(res, OSP_K_ARG, list, 2); - break; - } - case DATACONTROL_TYPE_MAP_GET: - { - const char *list[4]; - list[PACKET_INDEX_REQUEST_RESULT] = "1"; /* request result */ - list[PACKET_INDEX_ERROR_MSG] = DATACONTROL_EMPTY; - - bundle_add_str_array(res, OSP_K_ARG, list, 2); - const char *page_num = bundle_get_val(b, RESULT_PAGE_NUMBER); - const char *count_per_page = bundle_get_val(b, MAX_COUNT_PER_PAGE); - const char *value_count = bundle_get_val(b, RESULT_VALUE_COUNT); - - bundle_add_str(res, RESULT_PAGE_NUMBER, page_num); - bundle_add_str(res, MAX_COUNT_PER_PAGE, count_per_page); - bundle_add_str(res, RESULT_VALUE_COUNT, value_count); - - break; - } - case DATACONTROL_TYPE_ADD_DATA_CHANGED_CB: - { - const char *list[2]; - char result_str[2] = {0,}; - bool result = *(bool *)data; - snprintf(result_str, 2, "%d", result); - - list[PACKET_INDEX_REQUEST_RESULT] = result_str; /* request result */ - list[PACKET_INDEX_ERROR_MSG] = DATACONTROL_EMPTY; - - bundle_add_str_array(res, OSP_K_ARG, list, 2); - break; - } - case DATACONTROL_TYPE_UNDEFINED: /* DATACONTROL_TYPE_MAP_SET || ADD || REMOVE */ - { - const char *list[2]; - list[PACKET_INDEX_REQUEST_RESULT] = "1"; /* request result */ - list[PACKET_INDEX_ERROR_MSG] = DATACONTROL_EMPTY; - - bundle_add_str_array(res, OSP_K_ARG, list, 2); - break; - } - default: /* Error */ - { - const char *list[2]; - list[PACKET_INDEX_REQUEST_RESULT] = "0"; /* request result */ - list[PACKET_INDEX_ERROR_MSG] = (char *)data; /* error string */ - - bundle_add_str_array(res, OSP_K_ARG, list, 2); - break; - } - } - - return res; -} - -static int __send_result(bundle *b, datacontrol_request_type type, void *data) -{ - datacontrol_socket_info *socket_info; - char *caller_app_id = (char *)bundle_get_val(b, AUL_K_CALLER_APPID); - int ret = DATACONTROL_ERROR_NONE; - - LOGI("__datacontrol_send_async caller_app_id : %s ", caller_app_id); - - socket_info = g_hash_table_lookup(__socket_pair_hash, caller_app_id); - if (socket_info == NULL) { - LOGE("__socket_pair_hash lookup fail"); - return DATACONTROL_ERROR_IO_ERROR; - } - ret = __datacontrol_send_async(socket_info->socket_fd, b, type, data); - LOGI("__datacontrol_send_async result : %d ", ret); - if (ret != DATACONTROL_ERROR_NONE) - g_hash_table_remove(__socket_pair_hash, caller_app_id); - - return ret; -} - -static int __insert_consumer_list_db_info(char *app_id, char *provider_id, char *data_id, char *unique_id, char *object_path) -{ - int r; - int result = DATACONTROL_ERROR_NONE; - char query[QUERY_MAXLEN]; - sqlite3_stmt *stmt = NULL; - sqlite3_snprintf(QUERY_MAXLEN, query, - "INSERT OR REPLACE INTO data_control_consumer_path_list(app_id, provider_id, data_id, unique_id, object_path)" \ - "VALUES (?,?,?,?,?)"); - LOGI("consumer list db insert sql : %s", query); - r = sqlite3_prepare(__provider_db, query, sizeof(query), &stmt, NULL); - if (r != SQLITE_OK) { - LOGE("sqlite3_prepare error(%d , %d, %s)", r, sqlite3_extended_errcode(__provider_db), sqlite3_errmsg(__provider_db)); - result = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - r = sqlite3_bind_text(stmt, 1, app_id, strlen(app_id), SQLITE_STATIC); - if (r != SQLITE_OK) { - LOGE("app_id bind error(%d) \n", r); - result = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - r = sqlite3_bind_text(stmt, 2, provider_id, strlen(provider_id), SQLITE_STATIC); - if (r != SQLITE_OK) { - LOGE("provider_id bind error(%d) \n", r); - result = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - r = sqlite3_bind_text(stmt, 3, data_id, strlen(data_id), SQLITE_STATIC); - if (r != SQLITE_OK) { - LOGE("data_id bind error(%d) \n", r); - result = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - r = sqlite3_bind_text(stmt, 4, unique_id, strlen(unique_id), SQLITE_STATIC); - if (r != SQLITE_OK) { - LOGE("unique_id bind error(%d) \n", r); - result = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - r = sqlite3_bind_text(stmt, 5, object_path, strlen(object_path), SQLITE_STATIC); - if (r != SQLITE_OK) { - LOGE("object_path bind error(%d) \n", r); - result = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - r = sqlite3_step(stmt); - if (r != SQLITE_DONE) { - LOGE("step error(%d) \n", r); - LOGE("sqlite3_step error(%d, %s)", - sqlite3_extended_errcode(__provider_db), - sqlite3_errmsg(__provider_db)); - result = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - -out: - if (stmt) - sqlite3_finalize(stmt); - - return result; -} - -static int __delete_consumer_list_db_info(char *unique_id) -{ - int r; - char query[QUERY_MAXLEN]; - int result = DATACONTROL_ERROR_NONE; - sqlite3_stmt *stmt = NULL; - sqlite3_snprintf(QUERY_MAXLEN, query, - "DELETE FROM data_control_consumer_path_list WHERE unique_id = ?"); - LOGI("consumer list db DELETE : %s, unique_id : %s", query, unique_id); - r = sqlite3_prepare(__provider_db, query, sizeof(query), &stmt, NULL); - if (r != SQLITE_OK) { - LOGE("sqlite3_prepare error(%d , %d, %s)", r, - sqlite3_extended_errcode(__provider_db), sqlite3_errmsg(__provider_db)); - result = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - r = sqlite3_bind_text(stmt, 1, unique_id, strlen(unique_id), SQLITE_STATIC); - if (r != SQLITE_OK) { - LOGE("caller bind error(%d) \n", r); - result = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - r = sqlite3_step(stmt); - if (r != SQLITE_DONE) { - LOGE("step error(%d) \n", r); - result = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - -out: - if (stmt) - sqlite3_finalize(stmt); - - LOGI("__delete_consumer_list_db_info done"); - return result; -} - -static void __on_name_appeared(GDBusConnection *connection, - const gchar *name, - const gchar *name_owner, - gpointer user_data) -{ - LOGI("name appeared : %s", name); -} - -static void __on_name_vanished(GDBusConnection *connection, - const gchar *name, - gpointer user_data) -{ - LOGI("name vanished : %s", name); - __free_consumer_info(name); -} - -static int __init_changed_noti_consumer_list() -{ - char *app_id = NULL; - char *unique_id = NULL; - char *object_path = NULL; - int ret = DATACONTROL_ERROR_NONE; - sqlite3_stmt *stmt = NULL; - char query[QUERY_MAXLEN]; - datacontrol_consumer_info *consumer_info = NULL; - - sqlite3_snprintf(QUERY_MAXLEN, query, - "SELECT app_id, object_path, unique_id " \ - "FROM data_control_consumer_path_list"); - - LOGI("__init_changed_noti_consumer_list query : %s", query); - ret = sqlite3_prepare_v2(__provider_db, query, -1, &stmt, NULL); - if (ret != SQLITE_OK) { - LOGE("prepare stmt fail"); - return DATACONTROL_ERROR_IO_ERROR; - } - - while (SQLITE_ROW == sqlite3_step(stmt)) { - app_id = (char *)sqlite3_column_text(stmt, 0); - if (!app_id) { - LOGE("Failed to get package name\n"); - continue; - } - - object_path = (char *)sqlite3_column_text(stmt, 1); - if (!object_path) { - LOGE("Failed to get object_path\n"); - continue; - } - - unique_id = (char *)sqlite3_column_text(stmt, 2); - if (!unique_id) { - LOGE("Failed to get unique_id\n"); - continue; - } - LOGI("sql : app_id : %s, object_path : %s, unique_id : %s", - app_id, object_path, unique_id); - - consumer_info = (datacontrol_consumer_info *) - calloc(1, sizeof(datacontrol_consumer_info)); - consumer_info->appid = strdup(app_id); - consumer_info->object_path = strdup(object_path); - consumer_info->unique_id = strdup(unique_id); - - consumer_info->monitor_id = g_bus_watch_name_on_connection( - _get_dbus_connection(), - consumer_info->unique_id, - G_BUS_NAME_WATCHER_FLAGS_NONE, - __on_name_appeared, - __on_name_vanished, - consumer_info, - NULL); - - if (consumer_info->monitor_id == 0) { - LOGE("g_bus_watch_name_on_connection fail"); - - free(consumer_info->appid); - free(consumer_info->object_path); - free(consumer_info->unique_id); - free(consumer_info); - continue; - } - - LOGI("noti consumer_app_list append %s", consumer_info->object_path); - __noti_consumer_app_list = - g_list_append(__noti_consumer_app_list, consumer_info); - } - sqlite3_reset(stmt); - sqlite3_finalize(stmt); - - return ret; -} - -static int __create_consumer_list_db() -{ - char *db_path = NULL; - int ret = SQLITE_OK; - int open_flags = (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); - char *table_command = - "CREATE TABLE IF NOT EXISTS data_control_consumer_path_list" \ - "(app_id TEXT NOT NULL, provider_id TEXT NOT NULL, data_id TEXT NOT NULL, " \ - "unique_id TEXT NOT NULL, object_path TEXT NOT NULL, " \ - "PRIMARY KEY(object_path))"; - - if (__provider_db == NULL) { - db_path = _get_encoded_db_path(); - if (db_path == NULL) - return DATACONTROL_ERROR_IO_ERROR; - LOGI("data-control provider db path : %s", db_path); - - ret = sqlite3_open_v2(db_path, &__provider_db, open_flags, NULL); - free(db_path); - if (ret != SQLITE_OK) { - LOGE("database creation failed with error: %d", ret); - return DATACONTROL_ERROR_IO_ERROR; - } - ret = sqlite3_exec(__provider_db, table_command, NULL, NULL, NULL); - if (ret != SQLITE_OK) { - LOGE("database table creation failed with error: %d", ret); - return DATACONTROL_ERROR_IO_ERROR; - } - ret = __init_changed_noti_consumer_list(); - if (ret != DATACONTROL_ERROR_NONE) { - LOGE("__init_changed_noti_consumer_list fail %d", ret); - return ret; - } - } - return DATACONTROL_ERROR_NONE; -} - -static int __set_consumer_app_list( - char *caller, - char *object_path, - char *unique_id) -{ - datacontrol_consumer_info find_key; - datacontrol_consumer_info *consumer_info; - GList *find_list = NULL; - int ret = DATACONTROL_ERROR_NONE; - LOGI("set consumer_app_list caller : %s, path : %s, unique_id : %s", - caller, object_path, unique_id); - - find_key.unique_id = unique_id; - find_list = g_list_find_custom(__noti_consumer_app_list, - &find_key, - (GCompareFunc)__noti_consumer_app_list_compare_cb); - - if (!find_list) { - consumer_info = (datacontrol_consumer_info *) - calloc(1, sizeof(datacontrol_consumer_info)); - consumer_info->appid = strdup(caller); - consumer_info->object_path = strdup(object_path); - consumer_info->unique_id = strdup(unique_id); - - consumer_info->monitor_id = g_bus_watch_name_on_connection( - _get_dbus_connection(), - consumer_info->unique_id, - G_BUS_NAME_WATCHER_FLAGS_NONE, - __on_name_appeared, - __on_name_vanished, - consumer_info, - NULL); - if (consumer_info->monitor_id == 0) { - LOGE("g_bus_watch_name_on_connection fail"); - - free(consumer_info->appid); - free(consumer_info->object_path); - free(consumer_info->unique_id); - free(consumer_info); - - return DATACONTROL_ERROR_IO_ERROR; - } - LOGI("new noti consumer_app_list append %s", consumer_info->object_path); - __noti_consumer_app_list = g_list_append(__noti_consumer_app_list, consumer_info); - } - return ret; -} - -int __provider_process(bundle *b, int fd, const char *consumer_appid) -{ - int ret; - int len = 0; - const char **arg_list = NULL; - const char **column_list = NULL; - datacontrol_h provider = NULL; - int provider_req_id = 0; - int *key = NULL; - bool is_map; - char *provider_id; - char *caller_appid; - bundle *value = NULL; - - const char *request_type = bundle_get_val(b, OSP_K_DATACONTROL_REQUEST_TYPE); - if (request_type == NULL) { - LOGE("Invalid data control request"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - /* Get the request type */ - datacontrol_request_type type = atoi(request_type); - if (type >= DATACONTROL_TYPE_SQL_SELECT && type <= DATACONTROL_TYPE_SQL_BULK_INSERT) { - is_map = false; - if (provider_sql_cb == NULL) { - LOGE("SQL callback is not registered."); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - } else if (type >= DATACONTROL_TYPE_MAP_GET && type <= DATACONTROL_TYPE_MAP_BULK_ADD) { - is_map = true; - if (provider_map_cb == NULL) { - LOGE("Map callback is not registered."); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - } else { - LOGE("Invalid request type"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - caller_appid = (char *)bundle_get_val(b, AUL_K_CALLER_APPID); - if (caller_appid && strncmp(caller_appid, - consumer_appid, strlen(consumer_appid)) != 0) { - LOGE("The passed appid(%s) is different from the registered appid(%s).", - caller_appid, consumer_appid); - return DATACONTROL_ERROR_NONE; - } - - provider_id = (char *)bundle_get_val(b, OSP_K_DATACONTROL_PROVIDER); - ret = datacontrol_check_cert(provider_id, is_map, consumer_appid); - if (ret != DATA_CONTROL_ERROR_NONE) { - if (ret == DATA_CONTROL_ERROR_PERMISSION_DENIED) { - LOGE("The consumer (%s) is not signed with the same certificate", - consumer_appid); - return DATACONTROL_ERROR_NONE; - } else { - return DATACONTROL_ERROR_IO_ERROR; - } - } - - arg_list = bundle_get_str_array(b, OSP_K_ARG, &len); - - provider = malloc(sizeof(struct datacontrol_s)); - if (provider == NULL) { - LOGE("Out of memory. fail to alloc provider."); - return DATACONTROL_ERROR_IO_ERROR; - } - - /* Set the provider ID */ - provider->provider_id = provider_id; - - /* Set the data ID */ - provider->data_id = (char *)arg_list[PACKET_INDEX_DATAID]; - - /* Set the request ID */ - provider_req_id = __provider_new_request_id(); - - LOGI("Provider ID: %s, data ID: %s, request type: %s", provider->provider_id, provider->data_id, request_type); - - /* Add the data to the table */ - key = malloc(sizeof(int)); - if (key == NULL) { - LOGE("Out of memory. fail to malloc key"); - goto err; - } - *key = provider_req_id; - - value = bundle_dup(b); - if (value == NULL) { - LOGE("Fail to dup value"); - goto err; - } - g_hash_table_insert(__request_table, key, value); - - switch (type) { - case DATACONTROL_TYPE_SQL_SELECT: - { - int i = 1; - int current = 0; - int column_count = _get_int_from_str(arg_list[i++]); /* Column count */ - - if (column_count <= 0 || column_count > MAX_COLUMN_COUNT) { - LOGE("Invalid column count %d", column_count); - goto err; - } - - LOGI("SELECT column count: %d", column_count); - column_list = (const char **)malloc(column_count * (sizeof(char *))); - if (column_list == NULL) { - LOGE("Out of memory. Fail to malloc column_list."); - goto err; - } - - while (current < column_count) { - column_list[current++] = arg_list[i++]; /* Column data */ - LOGI("Column %d: %s", current, column_list[current-1]); - } - - const char *where = arg_list[i++]; /* where */ - const char *order = arg_list[i++]; /* order */ - LOGI("where: %s, order: %s", where, order); - - if (strncmp(where, DATACONTROL_EMPTY, strlen(DATACONTROL_EMPTY)) == 0) - where = NULL; - - if (strncmp(order, DATACONTROL_EMPTY, strlen(DATACONTROL_EMPTY)) == 0) - order = NULL; - - const char *page_number = arg_list[i++]; - const char *per_page = arg_list[i]; - - LOGI("page_number: %s, per_page: %s", page_number, per_page); - bundle_add_str(value, RESULT_PAGE_NUMBER, page_number); - bundle_add_str(value, MAX_COUNT_PER_PAGE, per_page); - provider_sql_cb->select(provider_req_id, provider, column_list, column_count, where, order, provider_sql_user_data); - free(column_list); - break; - } - case DATACONTROL_TYPE_SQL_INSERT: - case DATACONTROL_TYPE_SQL_UPDATE: - { - LOGI("INSERT / UPDATE handler"); - bundle *sql = __get_bundle_data_from_fd(fd); - if (sql == NULL) { - LOGE("__get_bundle_data_from_fd fail"); - goto err; - } - if (type == DATACONTROL_TYPE_SQL_INSERT) { - provider_sql_cb->insert(provider_req_id, provider, sql, provider_sql_user_data); - } else { - const char *where = arg_list[PACKET_INDEX_UPDATEWHERE]; - LOGI("UPDATE from where: %s", where); - if (strncmp(where, DATACONTROL_EMPTY, strlen(DATACONTROL_EMPTY)) == 0) - where = NULL; - provider_sql_cb->update(provider_req_id, provider, sql, where, provider_sql_user_data); - } - bundle_free(sql); - break; - } - case DATACONTROL_TYPE_SQL_BULK_INSERT: - { - LOGI("BULK INSERT handler"); - data_control_bulk_data_h data = __get_bulk_data_from_fd(fd); - if (data == NULL) { - LOGE("__get_bulk_data_from_fd fail"); - goto err; - } - - provider_sql_cb->bulk_insert(provider_req_id, provider, data, provider_sql_user_data); - - LOGI("bulk_insert callback call done"); - datacontrol_bulk_data_destroy(data); - break; - } - case DATACONTROL_TYPE_SQL_DELETE: - { - const char *where = arg_list[PACKET_INDEX_DELETEWHERE]; - LOGI("DELETE from where: %s", where); - if (strncmp(where, DATACONTROL_EMPTY, strlen(DATACONTROL_EMPTY)) == 0) - where = NULL; - provider_sql_cb->delete(provider_req_id, provider, where, provider_sql_user_data); - break; - } - case DATACONTROL_TYPE_MAP_GET: - { - const char *map_key = arg_list[PACKET_INDEX_MAP_KEY]; - const char *page_number = arg_list[PACKET_INDEX_MAP_PAGE_NO]; - const char *count_per_page = arg_list[PACKET_INDEX_MAP_COUNT_PER_PAGE]; - bundle_add_str(value, RESULT_PAGE_NUMBER, page_number); - bundle_add_str(value, MAX_COUNT_PER_PAGE, count_per_page); - LOGI("Gets the value list related with the key(%s) from Map datacontrol. ", map_key); - provider_map_cb->get(provider_req_id, provider, map_key, provider_map_user_data); - break; - } - case DATACONTROL_TYPE_MAP_SET: - { - const char *map_key = arg_list[PACKET_INDEX_MAP_KEY]; - const char *old_value = arg_list[PACKET_INDEX_MAP_VALUE_1ST]; - const char *new_value = arg_list[PACKET_INDEX_MAP_VALUE_2ND]; - LOGI("Sets the old value(%s) of the key(%s) to the new value(%s) in Map datacontrol.", old_value, map_key, new_value); - provider_map_cb->set(provider_req_id, provider, map_key, old_value, new_value, provider_map_user_data); - break; - } - case DATACONTROL_TYPE_MAP_ADD: - { - const char *map_key = arg_list[PACKET_INDEX_MAP_KEY]; - const char *map_value = arg_list[PACKET_INDEX_MAP_VALUE_1ST]; - LOGI("Adds the %s-%s in Map datacontrol.", map_key, map_value); - provider_map_cb->add(provider_req_id, provider, map_key, map_value, provider_map_user_data); - break; - } - case DATACONTROL_TYPE_MAP_BULK_ADD: - { - LOGI("BULK ADD handler"); - data_control_bulk_data_h data = __get_bulk_data_from_fd(fd); - if (data == NULL) { - LOGE("__get_bulk_data_from_fd fail"); - goto err; - } - - provider_map_cb->bulk_add(provider_req_id, provider, data, provider_map_user_data); - LOGI("bulk_add callback call done"); - datacontrol_bulk_data_destroy(data); - break; - } - case DATACONTROL_TYPE_MAP_REMOVE: - { - const char *map_key = arg_list[PACKET_INDEX_MAP_KEY]; - const char *map_value = arg_list[PACKET_INDEX_MAP_VALUE_1ST]; - LOGI("Removes the %s-%s in Map datacontrol.", map_key, map_value); - provider_map_cb->remove(provider_req_id, provider, map_key, map_value, provider_map_user_data); - break; - } - default: - break; - } - - free(provider); - - return DATACONTROL_ERROR_NONE; -err: - - if (provider) - free(provider); - if (key) - free(key); - if (value) - bundle_free(value); - - return DATACONTROL_ERROR_IO_ERROR; -} - -gboolean __provider_recv_message(GIOChannel *channel, - GIOCondition cond, - gpointer data) -{ - char *buf = NULL; - int data_len; - char *consumer_appid = (char *)data; - guint nb; - - gint fd = g_io_channel_unix_get_fd(channel); - gboolean retval = TRUE; - - LOGI("__provider_recv_message : ...from %d:%s%s%s%s\n", fd, - (cond & G_IO_ERR) ? " ERR" : "", - (cond & G_IO_HUP) ? " HUP" : "", - (cond & G_IO_IN) ? " IN" : "", - (cond & G_IO_PRI) ? " PRI" : ""); - - if (cond & (G_IO_ERR | G_IO_HUP)) - goto error; - - if (cond & G_IO_IN) { - if (_read_socket(fd, (char *)&data_len, sizeof(data_len), &nb) != DATACONTROL_ERROR_NONE) { - LOGE("read socket fail : data_len"); - goto error; - } - - LOGI("data_len : %d", data_len); - - if (nb == 0) { - LOGI("__provider_recv_message : ...from %d: EOF\n", fd); - goto error; - } - - LOGI("__provider_recv_message: ...from %d: %d bytes\n", fd, data_len); - if (data_len > 0 && data_len < MAX_REQUEST_ARGUMENT_SIZE) { - bundle *kb = NULL; - - buf = (char *)calloc(data_len + 1, sizeof(char)); - if (buf == NULL) { - LOGE("calloc failed"); - goto error; - } - - if (_read_socket(fd, buf, data_len, &nb) != DATACONTROL_ERROR_NONE) { - LOGI("read socket fail : data_len\n"); - goto error; - } - - if (nb == 0) { - LOGI("__provider_recv_message: nb 0 : EOF\n"); - goto error; - } - - kb = bundle_decode_raw((bundle_raw *)buf, data_len); - if (__provider_process(kb, fd, consumer_appid) != DATACONTROL_ERROR_NONE) { - bundle_free(kb); - goto error; - } - bundle_free(kb); - } - } - if (buf) - free(buf); - - return retval; -error: - if (consumer_appid != NULL) - g_hash_table_remove(__socket_pair_hash, consumer_appid); - if (buf) - free(buf); - - return FALSE; -} - -static int __send_add_callback_result( - datacontrol_data_change_type_e result_type, - char *unique_id, - char *path, - int callback_id, - int callback_result) -{ - GError *err = NULL; - int result = DATACONTROL_ERROR_NONE; - gboolean signal_result = TRUE; - LOGI("add callback_result type : %d, callback_id : %d, result : %d", - result_type, callback_id, callback_result); - - signal_result = g_dbus_connection_emit_signal( - _get_dbus_connection(), - unique_id, - path, - DATA_CONTROL_INTERFACE_NAME, - DATA_CONTROL_DATA_CHANGE_ADD_REMOVE_RESULT, - g_variant_new("(iii)", - result_type, - callback_id, - callback_result), &err); - if (signal_result == FALSE) { - LOGE("g_dbus_connection_emit_signal() is failed"); - if (err != NULL) { - LOGE("g_dbus_connection_emit_signal() err : %s", - err->message); - g_error_free(err); - } - return DATACONTROL_ERROR_IO_ERROR; - } - - LOGI("Send __send_add_callback_result done %d", result); - return result; -} - - -static int __get_sender_pid(const char *sender_name) -{ - GDBusMessage *msg = NULL; - GDBusMessage *reply = NULL; - GError *err = NULL; - GVariant *body; - int pid = 0; - - msg = g_dbus_message_new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus", - "org.freedesktop.DBus", "GetConnectionUnixProcessID"); - if (!msg) { - LOGE("Can't allocate new method call"); - goto out; - } - - g_dbus_message_set_body(msg, g_variant_new("(s)", sender_name)); - reply = g_dbus_connection_send_message_with_reply_sync(_get_dbus_connection(), msg, - G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &err); - - if (!reply) { - if (err != NULL) { - LOGE("Failed to get pid [%s]", err->message); - g_error_free(err); - } - goto out; - } - - body = g_dbus_message_get_body(reply); - g_variant_get(body, "(u)", &pid); - -out: - if (msg) - g_object_unref(msg); - if (reply) - g_object_unref(reply); - - return pid; -} - -static int __provider_noti_process(bundle *b, datacontrol_request_type type) -{ - datacontrol_h provider = NULL; - bool noti_allow = true; - char *path = NULL; - int result = DATACONTROL_ERROR_NONE; - char *unique_id = NULL; - datacontrol_data_change_type_e result_type = DATACONTROL_DATA_CHANGE_CALLBACK_ADD_RESULT; - char *callback_id_str = NULL; - int callback_id = -1; - GList *filter_iter; - changed_noti_consumer_filter_info_s *filter_info; - char caller_app_id[255]; - const char *pid_str; - int pid; - int sender_pid; - - pid_str = bundle_get_val(b, AUL_K_CALLER_PID); - if (pid_str == NULL) { - LOGE("fail to get caller pid"); - result = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - pid = atoi(pid_str); - if (pid <= 1) { - LOGE("invalid caller pid %s", pid_str); - result = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - if (aul_app_get_appid_bypid(pid, caller_app_id, sizeof(caller_app_id)) != 0) { - LOGE("Failed to get appid by pid"); - return DATACONTROL_ERROR_IO_ERROR; - } - - unique_id = (char *)bundle_get_val(b, OSP_K_DATACONTROL_UNIQUE_NAME); - LOGI("unique_id : %s", unique_id); - sender_pid = __get_sender_pid(unique_id); - if (sender_pid != pid) { - LOGE("invalid unique id. sender does not have unique_id %s", unique_id); - return DATACONTROL_ERROR_PERMISSION_DENIED; - } - - result = __create_consumer_list_db(); - if (result != DATACONTROL_ERROR_NONE) { - LOGE("fail to create consumer list db"); - return result; - } - - provider = malloc(sizeof(struct datacontrol_s)); - if (provider == NULL) { - LOGE("Out of memory. fail to alloc provider."); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - provider->provider_id = (char *)bundle_get_val(b, OSP_K_DATACONTROL_PROVIDER); - provider->data_id = (char *)bundle_get_val(b, OSP_K_DATACONTROL_DATA); - if (provider->provider_id == NULL || provider->data_id == NULL) { - LOGE("invalid provider value %s, %s", provider->provider_id, provider->data_id); - free(provider); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - LOGI("Noti Provider ID: %s, data ID: %s, request type: %d", provider->provider_id, provider->data_id, type); - path = _get_encoded_path(provider, caller_app_id); - if (path == NULL) { - LOGE("can not get encoded path out of memory"); - free(provider); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - callback_id_str = (char *)bundle_get_val(b, OSP_K_DATA_CHANGED_CALLBACK_ID); - if (callback_id_str == NULL) { - LOGE("callback_id is NULL"); - result = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - callback_id = atoi(callback_id_str); - - switch (type) { - case DATACONTROL_TYPE_ADD_DATA_CHANGED_CB: - { - LOGI("DATACONTROL_TYPE_ADD_DATA_CHANGED_CB called"); - result_type = DATACONTROL_DATA_CHANGE_CALLBACK_ADD_RESULT; - filter_iter = g_list_first(__noti_consumer_filter_info_list); - for (; filter_iter != NULL; filter_iter = filter_iter->next) { - filter_info = (changed_noti_consumer_filter_info_s *)filter_iter->data; - noti_allow = filter_info->callback((data_control_h)provider, caller_app_id, filter_info->user_data); - if (!noti_allow) - break; - } - LOGI("provider_sql_consumer_filter_cb result %d", noti_allow); - - if (noti_allow) { - result = __insert_consumer_list_db_info( - caller_app_id, - provider->provider_id, - provider->data_id, - unique_id, - path); - if (result != DATACONTROL_ERROR_NONE) { - LOGE("fail to set consumer list db info %d", result); - result = DATACONTROL_ERROR_PERMISSION_DENIED; - break; - } - - result = __set_consumer_app_list( - caller_app_id, - path, - unique_id); - if (result != DATACONTROL_ERROR_NONE) - LOGE("fail to __set_consumer_app_list"); - - } else { - result = DATACONTROL_ERROR_PERMISSION_DENIED; - break; - } - break; - } - case DATACONTROL_TYPE_REMOVE_DATA_CHANGED_CB: - { - LOGI("DATACONTROL_NOTI_REMOVE_DATA_CHANGED_CB called"); - result_type = DATACONTROL_DATA_CHANGE_CALLBACK_REMOVE_RESULT; - if (__noti_consumer_app_list) { - __free_consumer_info(unique_id); - LOGI("unregister %s from __noti_consumer_app_list", unique_id); - } else { - LOGI("empty __consumer_app_list"); - } - result = __delete_consumer_list_db_info(unique_id); - if (result != DATACONTROL_ERROR_NONE) { - LOGE("__delete_consumer_list_db_info fail %d", result); - result = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - break; - } - default: - break; - } - -out: - __send_add_callback_result( - result_type, unique_id, path, callback_id, result); - - if (provider) - free(provider); - if (path) - free(path); - - return result; -} - -int __datacontrol_handler_cb(bundle *b, int request_id, void *data) -{ - datacontrol_socket_info *socket_info; - int ret = DATACONTROL_ERROR_NONE; - const char *caller; - const char *callee; - char *dup_caller; - - const char *request_type = bundle_get_val(b, OSP_K_DATACONTROL_REQUEST_TYPE); - if (request_type == NULL) { - caller = bundle_get_val(b, AUL_K_CALLER_APPID); - callee = bundle_get_val(b, AUL_K_CALLEE_APPID); - - if (caller == NULL) { - LOGE("Invalid data control request caller is NULL"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - dup_caller = strdup(caller); - socket_info = g_hash_table_lookup(__socket_pair_hash, dup_caller); - - if (socket_info != NULL) - g_hash_table_remove(__socket_pair_hash, dup_caller); - - ret = _add_watch_on_socket_info(dup_caller, callee, "provider", - NULL, NULL, __provider_recv_message, - dup_caller, &socket_info); - if (ret != DATACONTROL_ERROR_NONE) - return ret; - - g_hash_table_insert(__socket_pair_hash, dup_caller, socket_info); - } else { - /* Get the request type */ - datacontrol_request_type type = atoi(request_type); - if (type == DATACONTROL_TYPE_ADD_DATA_CHANGED_CB || - type == DATACONTROL_TYPE_REMOVE_DATA_CHANGED_CB) { - __provider_noti_process(b, type); - } else { - LOGE("Invalid data control request"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - } - - return ret; -} - -bool datacontrol_provider_sql_is_registered() -{ - return provider_sql_cb == NULL ? false : true; -} - -int datacontrol_provider_sql_register_cb(datacontrol_provider_sql_cb *callback, void *user_data) -{ - int ret = DATACONTROL_ERROR_NONE; - - if (callback == NULL) - return DATACONTROL_ERROR_INVALID_PARAMETER; - - if (__request_table == NULL) - __initialize_provider(); - - LOGI("datacontrol_provider_sql_register_cb"); - - provider_sql_cb = callback; - provider_sql_user_data = user_data; - - /* If the provider_map_cb was registered(not NULL), __datacontrol_handler_cb is set already. */ - if (provider_map_cb == NULL) - ret = aul_set_data_control_provider_cb(__datacontrol_handler_cb); - - return ret; -} - -int datacontrol_provider_sql_unregister_cb(void) -{ - /* When both SQL_cb and Map_cb are unregisted, unsetting the provider cb is possible. */ - if (provider_map_cb == NULL) - aul_unset_data_control_provider_cb(); - - provider_sql_cb = NULL; - provider_sql_user_data = NULL; - - return DATACONTROL_ERROR_NONE; -} - -bool datacontrol_provider_map_is_registered() -{ - return provider_map_cb == NULL ? false : true; -} - -int datacontrol_provider_map_register_cb(datacontrol_provider_map_cb *callback, void *user_data) -{ - int ret = DATACONTROL_ERROR_NONE; - - if (callback == NULL) - return DATACONTROL_ERROR_INVALID_PARAMETER; - - if (__request_table == NULL) - __initialize_provider(); - - LOGI("datacontrol_provider_map_register_cb"); - - provider_map_cb = callback; - provider_map_user_data = user_data; - - /* If the provider_sql_cb was registered(not NULL), __datacontrol_handler_cb is set already. */ - if (provider_sql_cb == NULL) - ret = aul_set_data_control_provider_cb(__datacontrol_handler_cb); - - return ret; -} - -int datacontrol_provider_map_unregister_cb(void) -{ - /* When both SQL_cb and Map_cb are unregisted, unsetting the provider cb is possible. */ - if (provider_sql_cb == NULL) - aul_unset_data_control_provider_cb(); - - provider_map_cb = NULL; - provider_map_user_data = NULL; - - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_provider_get_client_appid(int request_id, char **appid) -{ - const char *caller; - bundle *b; - - if (__request_table == NULL) - __initialize_provider(); - - b = g_hash_table_lookup(__request_table, &request_id); - if (!b) { - LOGE("No data for the request id: %d", request_id); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - caller = bundle_get_val(b, AUL_K_CALLER_APPID); - if (!caller) { - LOGE("No appid for the request id: %d", request_id); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - LOGI("Request ID: %d, caller appid: %s", request_id, caller); - - *appid = strdup(caller); - - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_provider_write_socket(int fd, void *buffer, unsigned int nbytes, - unsigned int *bytes_write) -{ - int ret = _write_socket(fd, buffer, nbytes, bytes_write); - return ret; -} - -int datacontrol_provider_send_select_result_without_data(int request_id, int *fd) -{ - int ret; - bundle *res; - bundle *b; - datacontrol_socket_info *socket_info; - char *caller_app_id; - - LOGI("Send select result by byte array for request id: %d", request_id); - - if (__request_table == NULL) - __initialize_provider(); - - b = g_hash_table_lookup(__request_table, &request_id); - if (!b) { - LOGE("No data for the request id: %d", request_id); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - res = __set_result(b, DATACONTROL_TYPE_SQL_SELECT, NULL); - ret = __send_result(res, DATACONTROL_TYPE_UNDEFINED, NULL); - bundle_free(res); - - caller_app_id = (char *)bundle_get_val(b, AUL_K_CALLER_APPID); - socket_info = g_hash_table_lookup(__socket_pair_hash, caller_app_id); - if (socket_info == NULL) { - LOGE("__socket_pair_hash lookup fail"); - return DATACONTROL_ERROR_IO_ERROR; - } - *fd = socket_info->socket_fd; - g_hash_table_remove(__request_table, &request_id); - - return ret; -} - -int datacontrol_provider_get_select_page_info(int request_id, int *page_num, int *count_per_page) -{ - bundle *b; - const char *page_num_str; - const char *count_per_page_str; - - if (__request_table == NULL) { - LOGE("__request_table is NULL"); - return DATACONTROL_ERROR_IO_ERROR; - } - - b = g_hash_table_lookup(__request_table, &request_id); - if (!b) { - LOGE("No data for the request id: %d", request_id); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - page_num_str = bundle_get_val(b, RESULT_PAGE_NUMBER); - count_per_page_str = bundle_get_val(b, MAX_COUNT_PER_PAGE); - if (page_num_str == NULL || count_per_page_str == NULL) { - LOGE("No page data for the request id: %d, ", request_id); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - *page_num = _get_int_from_str(page_num_str); - *count_per_page = _get_int_from_str(count_per_page_str); - - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_provider_send_bulk_insert_result(int request_id, data_control_bulk_result_data_h bulk_result_data) -{ - int ret; - bundle *res; - bundle *b; - - LOGI("Send an insert result for request id: %d", request_id); - - if (__request_table == NULL) - __initialize_provider(); - - b = g_hash_table_lookup(__request_table, &request_id); - if (!b) { - LOGE("No data for the request id: %d", request_id); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - res = __set_result(b, DATACONTROL_TYPE_SQL_BULK_INSERT, NULL); - ret = __send_result(res, DATACONTROL_TYPE_SQL_BULK_INSERT, (void *)bulk_result_data); - bundle_free(res); - g_hash_table_remove(__request_table, &request_id); - - return ret; -} - -int datacontrol_provider_send_select_result(int request_id, void *db_handle) -{ - int ret; - bundle *res; - bundle *b; - - LOGI("Send a select result for request id: %d", request_id); - - if (__request_table == NULL) - __initialize_provider(); - - b = g_hash_table_lookup(__request_table, &request_id); - if (!b) { - LOGE("No data for the request id: %d", request_id); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - res = __set_result(b, DATACONTROL_TYPE_SQL_SELECT, db_handle); - ret = __send_result(res, DATACONTROL_TYPE_SQL_SELECT, db_handle); - bundle_free(res); - g_hash_table_remove(__request_table, &request_id); - - return ret; -} - -int datacontrol_provider_send_insert_result(int request_id, long long row_id) -{ - int ret; - bundle *res; - bundle *b; - - LOGI("Send an insert result for request id: %d", request_id); - - if (__request_table == NULL) - __initialize_provider(); - - b = g_hash_table_lookup(__request_table, &request_id); - if (!b) { - LOGE("No data for the request id: %d", request_id); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - res = __set_result(b, DATACONTROL_TYPE_SQL_INSERT, (void *)&row_id); - - ret = __send_result(res, DATACONTROL_TYPE_SQL_INSERT, NULL); - bundle_free(res); - g_hash_table_remove(__request_table, &request_id); - - return ret; - -} - -int datacontrol_provider_send_update_result(int request_id) -{ - int ret; - bundle *res; - bundle *b; - - LOGI("Send an update result for request id: %d", request_id); - - if (__request_table == NULL) - __initialize_provider(); - - b = g_hash_table_lookup(__request_table, &request_id); - if (!b) { - LOGE("No data for the request id: %d", request_id); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - res = __set_result(b, DATACONTROL_TYPE_SQL_UPDATE, NULL); - - ret = __send_result(res, DATACONTROL_TYPE_SQL_UPDATE, NULL); - bundle_free(res); - g_hash_table_remove(__request_table, &request_id); - - return ret; -} - -int datacontrol_provider_send_delete_result(int request_id) -{ - int ret; - bundle *res; - bundle *b; - - LOGI("Send a delete result for request id: %d", request_id); - - if (__request_table == NULL) - __initialize_provider(); - - b = g_hash_table_lookup(__request_table, &request_id); - if (!b) { - LOGE("No data for the request id: %d", request_id); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - res = __set_result(b, DATACONTROL_TYPE_SQL_DELETE, NULL); - - ret = __send_result(res, DATACONTROL_TYPE_SQL_DELETE, NULL); - bundle_free(res); - g_hash_table_remove(__request_table, &request_id); - - return ret; -} - -int datacontrol_provider_send_error(int request_id, const char *error) -{ - bundle *res; - bundle *b; - int ret; - - LOGI("Send an error for request id: %d", request_id); - - if (__request_table == NULL) - __initialize_provider(); - - b = g_hash_table_lookup(__request_table, &request_id); - if (!b) { - LOGE("No data for the request id: %d", request_id); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - res = __set_result(b, DATACONTROL_TYPE_ERROR, (void *)error); - ret = __send_result(res, DATACONTROL_TYPE_ERROR, NULL); - bundle_free(res); - - return ret; -} - - -int datacontrol_provider_send_map_bulk_add_result(int request_id, data_control_bulk_result_data_h bulk_result_data) -{ - int ret; - bundle *res; - bundle *b; - - LOGI("Send bulk add result for request id: %d", request_id); - - if (__request_table == NULL) - __initialize_provider(); - - b = g_hash_table_lookup(__request_table, &request_id); - if (!b) { - LOGE("No data for the request id: %d", request_id); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - res = __set_result(b, DATACONTROL_TYPE_MAP_BULK_ADD, NULL); - ret = __send_result(res, DATACONTROL_TYPE_MAP_BULK_ADD, (void *)bulk_result_data); - bundle_free(res); - g_hash_table_remove(__request_table, &request_id); - - return ret; -} - -int datacontrol_provider_send_map_result(int request_id) -{ - int ret; - bundle *res; - bundle *b; - - LOGI("Send a set/add/remove result for request id: %d", request_id); - - if (__request_table == NULL) - __initialize_provider(); - - b = g_hash_table_lookup(__request_table, &request_id); - if (!b) { - LOGE("No data for the request id: %d", request_id); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - res = __set_result(b, DATACONTROL_TYPE_UNDEFINED, NULL); - - ret = __send_result(res, DATACONTROL_TYPE_UNDEFINED, NULL); - bundle_free(res); - g_hash_table_remove(__request_table, &request_id); - - return ret; -} - -int datacontrol_provider_send_map_get_value_result(int request_id, char **value_list, int value_count) -{ - int ret; - char value_count_str[32]; - bundle *b; - bundle *res; - - LOGI("Send a get result for request id: %d", request_id); - - if (__request_table == NULL) - __initialize_provider(); - - b = g_hash_table_lookup(__request_table, &request_id); - if (!b) { - LOGE("No data for the request id: %d", request_id); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - snprintf(value_count_str, 32, "%d", value_count); - bundle_add_str(b, RESULT_VALUE_COUNT, value_count_str); - - res = __set_result(b, DATACONTROL_TYPE_MAP_GET, value_list); - - ret = __send_result(res, DATACONTROL_TYPE_MAP_GET, value_list); - bundle_free(res); - g_hash_table_remove(__request_table, &request_id); - - return ret; -} - -static int __send_signal_to_consumer(datacontrol_h provider, - char *unique_id, - char *path, - datacontrol_data_change_type_e type, - bundle *data) -{ - int result = DATACONTROL_ERROR_NONE; - int len = 0; - bundle_raw *raw = NULL; - GError *err = NULL; - gboolean signal_result = TRUE; - - if (data) { - if (bundle_encode(data, &raw, &len) != BUNDLE_ERROR_NONE) { - LOGE("bundle_encode fail"); - result = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - } - - LOGI("emit signal to object path %s", path); - signal_result = g_dbus_connection_emit_signal( - _get_dbus_connection(), - unique_id, - path, - DATA_CONTROL_INTERFACE_NAME, - DATA_CONTROL_DATA_CHANGE_DATA_CHANGED, - g_variant_new("(isssi)", - type, - provider->provider_id, - provider->data_id, - ((raw) ? (char *)raw : ""), - len), &err); - - if (signal_result == FALSE) { - LOGE("g_dbus_connection_emit_signal() is failed"); - if (err != NULL) { - LOGE("g_dbus_connection_emit_signal() err : %s", - err->message); - g_error_free(err); - } - result = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - -out: - if (raw) - free(raw); - - return result; -} - -static int __check_consumer_cert(const char *provider_id, - const char *consumer_appid, - datacontrol_data_change_type_e type) -{ - bool is_map; - - if (consumer_appid == NULL) - return DATACONTROL_ERROR_IO_ERROR; - - if (type >= DATACONTROL_DATA_CHANGE_SQL_UPDATE && - type <= DATACONTROL_DATA_CHANGE_SQL_DELETE) - is_map = false; - else - is_map = true; - - return datacontrol_check_cert(provider_id, is_map, consumer_appid); -} - -int datacontrol_provider_send_data_change_noti( - datacontrol_h provider, - datacontrol_data_change_type_e type, - bundle *data) -{ - int result = DATACONTROL_ERROR_NONE; - GList *consumer_iter = NULL; - datacontrol_consumer_info *consumer_info = NULL; - - LOGE("datacontrol_provider_send_data_change_noti %d, %d", g_list_length(__noti_consumer_app_list), type); - consumer_iter = g_list_first(__noti_consumer_app_list); - for (; consumer_iter != NULL; consumer_iter = consumer_iter->next) { - consumer_info = (datacontrol_consumer_info *)consumer_iter->data; - if (__check_consumer_cert(provider->provider_id, - consumer_info->appid, - type) != DATACONTROL_ERROR_NONE) - continue; - result = __send_signal_to_consumer( - provider, - consumer_info->unique_id, - consumer_info->object_path, - type, - data); - if (result != DATACONTROL_ERROR_NONE) { - LOGE("__send_signal_to_consumer fail : %d", result); - break; - } - } - return result; -} - -int datacontrol_provider_add_data_change_consumer_filter_cb( - data_control_provider_data_change_consumer_filter_cb callback, - void *user_data, - int *callback_id) -{ - changed_noti_consumer_filter_info_s *filter_info = (changed_noti_consumer_filter_info_s *)calloc(1, - sizeof(changed_noti_consumer_filter_info_s)); - - *callback_id = _datacontrol_get_data_changed_filter_callback_id(); - - filter_info->callback_id = *callback_id; - filter_info->callback = callback; - filter_info->user_data = user_data; - __noti_consumer_filter_info_list = g_list_append(__noti_consumer_filter_info_list, filter_info); - - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_provider_remove_data_change_consumer_filter_cb(int callback_id) -{ - GList *find_list; - changed_noti_consumer_filter_info_s filter_info; - changed_noti_consumer_filter_info_s *temp; - - filter_info.callback_id = callback_id; - find_list = g_list_find_custom(__noti_consumer_filter_info_list, &filter_info, - (GCompareFunc)__data_changed_filter_cb_info_compare_cb); - if (find_list != NULL) { - temp = (changed_noti_consumer_filter_info_s *)find_list->data; - __noti_consumer_filter_info_list = g_list_remove(__noti_consumer_filter_info_list, find_list->data); - free(temp); - } else { - LOGE("invalid callback_id : %d", callback_id); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_provider_foreach_data_change_consumer( - datacontrol_h provider, - data_control_provider_data_change_consumer_cb list_cb, - void *user_data) -{ - char *app_id = NULL; - char *unique_id = NULL; - int ret = DATACONTROL_ERROR_NONE; - sqlite3_stmt *stmt = NULL; - char query[QUERY_MAXLEN]; - bool callback_result; - data_control_provider_data_change_consumer_cb consumer_list_cb; - consumer_list_cb = list_cb; - - sqlite3_snprintf(QUERY_MAXLEN, query, - "SELECT app_id, unique_id " \ - "FROM data_control_consumer_path_list WHERE provider_id = ? AND data_id = ?"); - LOGI("get_changed_noti_consumer_list query : %s", query); - - ret = sqlite3_prepare_v2(__provider_db, query, -1, &stmt, NULL); - if (ret != SQLITE_OK) { - LOGE("prepare stmt fail"); - ret = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - ret = sqlite3_bind_text(stmt, 1, provider->provider_id, -1, SQLITE_TRANSIENT); - if (ret != SQLITE_OK) { - LOGE("bind provider id fail: %s", sqlite3_errmsg(__provider_db)); - ret = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - ret = sqlite3_bind_text(stmt, 2, provider->data_id, -1, SQLITE_TRANSIENT); - if (ret != SQLITE_OK) { - LOGE("bind data id fail: %s", sqlite3_errmsg(__provider_db)); - ret = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - while (SQLITE_ROW == sqlite3_step(stmt)) { - - app_id = (char *)sqlite3_column_text(stmt, 0); - if (!app_id) { - LOGE("Failed to get package name\n"); - continue; - } - unique_id = (char *)sqlite3_column_text(stmt, 1); - callback_result = consumer_list_cb((data_control_h)provider, app_id, user_data); - LOGI("app_id : %s, unique_id : %s, result : %d ", app_id, unique_id, callback_result); - if (!callback_result) - break; - } -out: - if (stmt) { - sqlite3_reset(stmt); - sqlite3_clear_bindings(stmt); - sqlite3_finalize(stmt); - } - - return ret; -} - diff --git a/src/data-control-sql-cursor.c b/src/data-control-sql-cursor.c deleted file mode 100755 index b56c3fb..0000000 --- a/src/data-control-sql-cursor.c +++ /dev/null @@ -1,618 +0,0 @@ -/* - * Copyright (c) 2013 - 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 "data-control-sql-cursor.h" -#include "data-control-internal.h" - -#undef LOG_TAG -#ifndef LOG_TAG -#define LOG_TAG "DATA_CONTROL" -#endif - -#define ERR_BUFFER_SIZE 1024 - -resultset_cursor *datacontrol_sql_get_cursor() -{ - resultset_cursor *cursor = (resultset_cursor *)calloc(1, sizeof(resultset_cursor)); - if (!cursor) { - LOGE("unable to create cursor"); - return NULL; - } - return cursor; - -} - -int datacontrol_sql_step_next(resultset_cursor *cursor) -{ - if (cursor == NULL || cursor->resultset_row_count == 0) { - LOGE("Reached to the end of the result set"); - return DATACONTROL_ERROR_IO_ERROR; - } - - if (cursor->resultset_current_offset == 0) { - cursor->resultset_current_offset = cursor->resultset_content_offset; - } else { - if (!(cursor->resultset_current_row_count < (cursor->resultset_row_count - 1))) { - LOGE("Reached to the end of the result set"); - return DATACONTROL_ERROR_IO_ERROR; - } - - cursor->resultset_current_offset = - cursor->row_offset_list[cursor->resultset_current_row_count + 1]; - cursor->resultset_current_row_count++; - } - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_sql_step_last(resultset_cursor *cursor) -{ - int ret = 0; - int i = 0; - - if (cursor->resultset_current_row_count == (cursor->resultset_row_count - 1)) - return DATACONTROL_ERROR_NONE; /* Already @ last row */ - - if (!cursor->row_offset_list) { - ret = datacontrol_sql_step_next(cursor); /* make a first move */ - if (ret != DATACONTROL_ERROR_NONE) - return ret; - } - - /* check if the rowOffsetList contains last row offset */ - if (cursor->row_offset_list && cursor->row_offset_list[cursor->resultset_row_count - 1] != 0) { - cursor->resultset_current_offset = cursor->row_offset_list[cursor->resultset_row_count - 1]; - cursor->resultset_current_row_count = cursor->resultset_row_count - 1; - } else { - /* Move till last row offset. */ - for (i = (cursor->resultset_current_row_count + 1); i < cursor->resultset_row_count; i++) { - ret = datacontrol_sql_step_next(cursor); /* move till last row data offset */ - if (ret != DATACONTROL_ERROR_NONE) - return ret; - } - } - - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_sql_step_first(resultset_cursor *cursor) -{ - if (cursor->resultset_current_offset > 0) { - cursor->resultset_current_offset = cursor->resultset_content_offset; - cursor->resultset_current_row_count = 0; - return DATACONTROL_ERROR_NONE; - } - - /* MoveFirst is called for the first time before MoveNext() or MoveLast() */ - cursor->resultset_current_offset = 0; - return datacontrol_sql_step_next(cursor); -} - -int datacontrol_sql_step_previous(resultset_cursor *cursor) -{ - if ((cursor->resultset_current_row_count - 1) < 0) { - LOGE("invalid request"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - cursor->resultset_current_offset = cursor->row_offset_list[cursor->resultset_current_row_count - 1]; - cursor->resultset_current_row_count--; - - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_sql_get_column_count(resultset_cursor *cursor) -{ - return cursor->resultset_col_count; -} - -int datacontrol_sql_get_column_name(resultset_cursor *cursor, int column_index, char *name) -{ - char *col_name = NULL; - int i = 0; - int ret = 0; - int column_len = 0; - int fd = cursor->resultset_fd; - char err_buf[ERR_BUFFER_SIZE]; - - ret = lseek(fd, cursor->resultset_col_name_offset, SEEK_SET); - if (ret < 0) { - LOGE("unable to seek in the resultset file: %d %s", cursor->resultset_current_offset, - strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - for (i = 0; i < column_index + 1; i++) { - ret = read(fd, &column_len, sizeof(int)); - if (ret == 0) { - LOGE("unable to read column_len: %d", column_len); - return DATACONTROL_ERROR_IO_ERROR; - } - - if (column_len < 0 || column_len > MAX_COLUMN_SIZE) { - LOGE("Invalid column_len: %d", column_len); - return DATACONTROL_ERROR_IO_ERROR; - } - - if (i == column_index) { - col_name = (char *)calloc(column_len, sizeof(char)); - ret = read(fd, col_name, column_len); - if (ret == 0) { - LOGE("unable to read col_name : %s", strerror_r(errno, err_buf, sizeof(err_buf))); - free(col_name); - return DATACONTROL_ERROR_IO_ERROR; - } - } else { - ret = lseek(fd, column_len, SEEK_CUR); - if (ret < 0) { - LOGE("unable to seek in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - } - } - memset(name, 0, column_len); - memcpy(name, col_name, column_len); - free(col_name); - LOGI("The column name is %s", name); - - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_sql_get_column_item_size(resultset_cursor *cursor, int column_index) -{ - int type = -1; - int size = 0; - int i = 0; - int ret = 0; - char err_buf[ERR_BUFFER_SIZE]; - int fd = cursor->resultset_fd; - - ret = lseek(fd, cursor->resultset_current_offset, SEEK_SET); - if (ret < 0) { - LOGE("unable to seek in the resultset file: %d %s", cursor->resultset_current_offset, - strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - /* move to column index */ - for (i = 0; i < column_index; i++) { - ret = read(fd, &type, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - ret = read(fd, &size, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - ret = lseek(fd, size, SEEK_CUR); - if (ret < 0) { - LOGE("unable to seek in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - } - - ret = read(fd, &type, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - ret = read(fd, &size, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - return size; -} - -int datacontrol_sql_get_column_item_type(resultset_cursor *cursor, int column_index, - datacontrol_sql_column_type *col_type) -{ - int type = -1; - int i = 0; - int size = 0; - int ret = 0; - char err_buf[ERR_BUFFER_SIZE]; - int fd = cursor->resultset_fd; - - ret = lseek(fd, cursor->resultset_current_offset, SEEK_SET); - if (ret < 0) { - LOGE("unable to seek in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - /* move to column index */ - for (i = 0; i < column_index; i++) { - ret = read(fd, &type, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - ret = read(fd, &size, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - ret = lseek(fd, size, SEEK_CUR); - if (ret < 0) { - LOGE("unable to seek in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - } - - ret = read(fd, &type, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - switch (type) { - case DATACONTROL_SQL_COLUMN_TYPE_INT64: - *col_type = DATACONTROL_SQL_COLUMN_TYPE_INT64; - break; - case DATACONTROL_SQL_COLUMN_TYPE_DOUBLE: - *col_type = DATACONTROL_SQL_COLUMN_TYPE_DOUBLE; - break; - case DATACONTROL_SQL_COLUMN_TYPE_TEXT: - *col_type = DATACONTROL_SQL_COLUMN_TYPE_TEXT; - break; - case DATACONTROL_SQL_COLUMN_TYPE_BLOB: - *col_type = DATACONTROL_SQL_COLUMN_TYPE_BLOB; - break; - case DATACONTROL_SQL_COLUMN_TYPE_NULL: - *col_type = DATACONTROL_SQL_COLUMN_TYPE_NULL; - break; - default: - *col_type = DATACONTROL_SQL_COLUMN_TYPE_UNDEFINED; - break; - } - - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_sql_get_blob_data(resultset_cursor *cursor, int column_index, void *buffer, int data_size) -{ - int type = -1; - int size = 0; - int i = 0; - int ret = 0; - char err_buf[ERR_BUFFER_SIZE]; - int fd = cursor->resultset_fd; - char *data; - - ret = lseek(fd, cursor->resultset_current_offset, SEEK_SET); - if (ret < 0) { - LOGE("unable to seek in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - /* move to column index */ - for (i = 0; i < column_index; i++) { - ret = read(fd, &type, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - ret = read(fd, &size, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - ret = lseek(fd, size, SEEK_CUR); - if (ret < 0) { - LOGE("unable to seek in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - } - - ret = read(fd, &type, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - if (type != (int)DATACONTROL_SQL_COLUMN_TYPE_BLOB) { - LOGE("type mismatch: requested for BLOB type but %d present:", type); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - ret = read(fd, &size, sizeof(int)); - if (ret == 0) { - LOGE("unable to read size in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - if (size > data_size) { - LOGE("size is more than the size requested"); - return DATACONTROL_ERROR_MAX_EXCEEDED; /* overflow */ - } - - if (size > 0 && size < MAX_REQUEST_ARGUMENT_SIZE) { - data = (char *)malloc((size + 1) * (sizeof(char))); - memset(data, 0, size + 1); - - ret = read(fd, data, size); - if (ret < size) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - free(data); - return DATACONTROL_ERROR_IO_ERROR; - } - - memcpy(buffer, data, size + 1); - free(data); - } else { - LOGE("Invalid size %d", size); - return DATACONTROL_ERROR_IO_ERROR; - } - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_sql_get_int_data(resultset_cursor *cursor, int column_index, int *data) -{ - long long long_value = 0; - int ret = -1; - - ret = datacontrol_sql_get_int64_data(cursor, column_index, &long_value); - if (ret == 0) - *data = (int) long_value; - - return ret; -} - -int datacontrol_sql_get_int64_data(resultset_cursor *cursor, int column_index, long long *data) -{ - int type = -1; - int size = 0; - int i = 0; - int ret = 0; - char err_buf[ERR_BUFFER_SIZE]; - int fd = cursor->resultset_fd; - - ret = lseek(fd, cursor->resultset_current_offset, SEEK_SET); - if (ret < 0) { - LOGE("unable to seek in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - /* move to column index */ - for (i = 0; i < column_index; i++) { - ret = read(fd, &type, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - ret = read(fd, &size, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - ret = lseek(fd, size, SEEK_CUR); - if (ret < 0) { - LOGE("unable to seek in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - } - - ret = read(fd, &type, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - if (type != (int)DATACONTROL_SQL_COLUMN_TYPE_INT64) { - LOGE("type mismatch: requested for int type but %d present:", type); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - ret = read(fd, &size, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - ret = read(fd, data, size); - if (ret < size) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_sql_get_double_data(resultset_cursor *cursor, int column_index, double *data) -{ - int type = -1; - int size = 0; - int i = 0; - int ret = 0; - char err_buf[ERR_BUFFER_SIZE]; - int fd = cursor->resultset_fd; - - ret = lseek(fd, cursor->resultset_current_offset, SEEK_SET); - if (ret < 0) { - LOGE("unable to seek in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - /* move to column index */ - for (i = 0; i < column_index; i++) { - ret = read(fd, &type, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - ret = read(fd, &size, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - ret = lseek(fd, size, SEEK_CUR); - if (ret < 0) { - LOGE("unable to seek in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - } - - ret = read(fd, &type, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - if (type != (int)DATACONTROL_SQL_COLUMN_TYPE_DOUBLE) { - LOGE("type mismatch: requested for double type but %d present:", type); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - ret = read(fd, &size, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - ret = read(fd, data, size); - if (ret < size) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - return DATACONTROL_ERROR_NONE; -} - - -int datacontrol_sql_get_text_data(resultset_cursor *cursor, int column_index, char *buffer) -{ - int type = -1; - int size = 0; - int i = 0; - int ret = 0; - char err_buf[ERR_BUFFER_SIZE]; - int fd = cursor->resultset_fd; - char *data; - - ret = lseek(fd, cursor->resultset_current_offset, SEEK_SET); - if (ret < 0) { - LOGE("unable to seek in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - /* move to column index */ - for (i = 0; i < column_index; i++) { - ret = read(fd, &type, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - ret = read(fd, &size, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - ret = lseek(fd, size, SEEK_CUR); - if (ret < 0) { - LOGE("unable to seek in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - } - - ret = read(fd, &type, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - if (type != (int)DATACONTROL_SQL_COLUMN_TYPE_TEXT) { - LOGE("type mismatch: requested for text type but %d present %d", type, - cursor->resultset_current_offset); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - ret = read(fd, &size, sizeof(int)); - if (ret == 0) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - return DATACONTROL_ERROR_IO_ERROR; - } - - if (size > 0 && size < MAX_REQUEST_ARGUMENT_SIZE) { - data = (char *)malloc((size + 1) * (sizeof(char))); - if (!data) { - LOGE("unable to create buffer to read"); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - memset(data, 0, size + 1); - ret = read(fd, data, size); - if (ret < size) { - LOGE("unable to read in the resultset file: %s", strerror_r(errno, err_buf, sizeof(err_buf))); - free(data); - return DATACONTROL_ERROR_IO_ERROR; - } - - memcpy(buffer, data, size + 1); - free(data); - } else { - LOGE("Invalid size %d", size); - return DATACONTROL_ERROR_IO_ERROR; - } - - return DATACONTROL_ERROR_NONE; -} - -int datacontrol_sql_remove_cursor(resultset_cursor *cursor) -{ - int ret; - - if (cursor == NULL) - return DATACONTROL_ERROR_INVALID_PARAMETER; - - close(cursor->resultset_fd); - if (cursor->resultset_path) { - ret = remove(cursor->resultset_path); - if (ret == -1) - LOGE("unable to remove map query result file: %d", ret); - free(cursor->resultset_path); - } - if (cursor->row_offset_list) - free(cursor->row_offset_list); - free(cursor); - - return DATACONTROL_ERROR_NONE; -} - diff --git a/src/data-control-sql.c b/src/data-control-sql.c deleted file mode 100755 index b400068..0000000 --- a/src/data-control-sql.c +++ /dev/null @@ -1,1508 +0,0 @@ -/* - * Copyright (c) 2014 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 -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include -#include - -#include "data-control-sql.h" -#include "data-control-internal.h" -#include "data-control-bulk.h" - -#define REQUEST_PATH_MAX 512 - -typedef struct { - char *provider_id; - char *app_id; - char *data_id; - char *access_info; - void *user_data; - GList *request_info_list; - datacontrol_sql_response_cb *sql_response_cb; -} sql_response_cb_s; - -static void *datacontrol_sql_tree_root = NULL; -static GHashTable *__socket_pair_hash = NULL; -static int __recv_sql_select_process(bundle *kb, int fd, - resultset_cursor *cursor); -static int __recv_sql_bulk_insert_process(int fd, data_control_bulk_result_data_h *result_data_h); - -static void __sql_call_cb(const char *provider_id, int request_id, - datacontrol_request_type type, const char *data_id, - bool provider_result, const char *error, long long insert_rowid, - resultset_cursor *cursor, data_control_bulk_result_data_h bulk_results, void *data) -{ - datacontrol_sql_response_cb *callback = NULL; - sql_response_cb_s *sql_dc; - datacontrol_h provider; - - LOGI("__sql_call_cb, dataID !!!: %s", data_id); - - sql_dc = (sql_response_cb_s *)data; - callback = sql_dc->sql_response_cb; - if (!callback) { - LOGE("no listener set"); - return; - } - - datacontrol_sql_create(&provider); - datacontrol_sql_set_provider_id(provider, provider_id); - datacontrol_sql_set_data_id(provider, data_id); - - switch (type) { - case DATACONTROL_TYPE_SQL_BULK_INSERT: - LOGI("BULK INSERT"); - if (callback != NULL && callback->bulk_insert != NULL) - callback->bulk_insert(request_id, provider, bulk_results, provider_result, error, sql_dc->user_data); - else - LOGI("No registered callback function"); - - break; - case DATACONTROL_TYPE_SQL_SELECT: - LOGI("SELECT"); - if (callback != NULL && callback->select != NULL) - callback->select(request_id, provider, cursor, provider_result, error, sql_dc->user_data); - else - LOGI("No registered callback function"); - - break; - case DATACONTROL_TYPE_SQL_INSERT: - LOGI("INSERT row_id: %lld", insert_rowid); - if (callback != NULL && callback->insert != NULL) - callback->insert(request_id, provider, insert_rowid, provider_result, error, sql_dc->user_data); - else - LOGI("No registered callback function"); - - break; - case DATACONTROL_TYPE_SQL_UPDATE: - LOGI("UPDATE"); - if (callback != NULL && callback->update != NULL) - callback->update(request_id, provider, provider_result, error, sql_dc->user_data); - else - LOGI("No registered callback function"); - break; - case DATACONTROL_TYPE_SQL_DELETE: - LOGI("DELETE"); - if (callback != NULL && callback->delete != NULL) - callback->delete(request_id, provider, provider_result, error, sql_dc->user_data); - else - LOGI("No registered callback function"); - break; - default: - break; - } - - datacontrol_sql_destroy(provider); -} - -static void __sql_instance_free(void *datacontrol_sql_instance) -{ - sql_response_cb_s *dc = (sql_response_cb_s *)datacontrol_sql_instance; - if (dc) { - free(dc->provider_id); - free(dc->data_id); - free(dc->app_id); - free(dc->access_info); - free(datacontrol_sql_instance); - } - - return; -} - -static int __sql_instance_compare(const void *l_datacontrol_sql_instance, const void *r_datacontrol_sql_instance) -{ - sql_response_cb_s *dc_left = (sql_response_cb_s *)l_datacontrol_sql_instance; - sql_response_cb_s *dc_right = (sql_response_cb_s *)r_datacontrol_sql_instance; - return strcmp(dc_left->provider_id, dc_right->provider_id); -} - -static void __remove_sql_request_info(int request_id, sql_response_cb_s *sql_dc) -{ - - datacontrol_consumer_request_info temp_request_info; - datacontrol_consumer_request_info *temp_data; - - temp_request_info.request_id = request_id; - GList *list = g_list_find_custom(sql_dc->request_info_list, &temp_request_info, - (GCompareFunc)_consumer_request_compare_cb); - if (list != NULL) { - temp_data = (datacontrol_consumer_request_info *)list->data; - sql_dc->request_info_list = g_list_remove(sql_dc->request_info_list, list->data); - free(temp_data); - } - -} - -static int __sql_handle_cb(bundle *b, void *data, int fd, int request_id) -{ - resultset_cursor *cursor = NULL; - int ret = 0; - const char **result_list = NULL; - const char *provider_id = NULL; - const char *data_id = NULL; - const char *error_message = NULL; - long long insert_rowid = -1; - datacontrol_request_type request_type = 0; - int result_list_len = 0; - int provider_result = 0; - const char *p = NULL; - data_control_bulk_result_data_h bulk_results = NULL; - - if (b) { - /* result list */ - result_list = appsvc_get_data_array(b, OSP_K_ARG, &result_list_len); - if (!result_list) { - LOGE("Invalid Bundle: arguement list is null"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - p = result_list[0]; /* result list[0] = provider_result */ - if (!p) { - LOGE("Invalid Bundle: provider_result is null"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - LOGI("Provider result: %s", p); - - provider_result = atoi(p); - - error_message = result_list[1]; /* result list[1] = error */ - if (!error_message) { - LOGE("Invalid Bundle: error_message is null"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - LOGI("Error message: %s", error_message); - - p = appsvc_get_data(b, OSP_K_DATACONTROL_REQUEST_TYPE); - if (!p) { - LOGE("Invalid Bundle: data-control request type is null"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - request_type = (datacontrol_request_type)atoi(p); - - provider_id = appsvc_get_data(b, OSP_K_DATACONTROL_PROVIDER); - if (!provider_id) { - LOGE("Invalid Bundle: provider_id is null"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - data_id = appsvc_get_data(b, OSP_K_DATACONTROL_DATA); - if (!data_id) { - LOGE("Invalid Bundle: data_id is null"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - LOGI("Provider ID: %s, Data ID: %s, Operation type: %d", provider_id, data_id, request_type); - switch (request_type) { - case DATACONTROL_TYPE_SQL_BULK_INSERT: - LOGI("BULK INSERT RESPONSE"); - if (provider_result) { - if (__recv_sql_bulk_insert_process(fd, &bulk_results) - != DATACONTROL_ERROR_NONE) { - if (bulk_results) - datacontrol_bulk_result_data_destroy(bulk_results); - - return DATACONTROL_ERROR_IO_ERROR; - } - } - break; - case DATACONTROL_TYPE_SQL_SELECT: - if (provider_result) { - cursor = datacontrol_sql_get_cursor(); - if (!cursor) { - LOGE("failed to get cursor on sql query resultset"); - return DATACONTROL_ERROR_IO_ERROR; - } - if (__recv_sql_select_process(b, fd, cursor) - != DATACONTROL_ERROR_NONE) - return DATACONTROL_ERROR_IO_ERROR; - } - break; - case DATACONTROL_TYPE_SQL_INSERT: - LOGI("INSERT RESPONSE"); - if (provider_result) { - p = result_list[2]; /* result list[2] */ - if (!p) { - LOGE("Invalid Bundle: insert row_id is null"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - insert_rowid = atoll(p); - } - break; - case DATACONTROL_TYPE_SQL_UPDATE: - case DATACONTROL_TYPE_SQL_DELETE: - LOGI("UPDATE or DELETE RESPONSE"); - break; - default: - break; - } - - } else { - LOGE("the bundle returned from datacontrol-provider-service is null"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - if (request_type >= DATACONTROL_TYPE_SQL_SELECT && - request_type <= DATACONTROL_TYPE_SQL_BULK_INSERT) { - __sql_call_cb( - provider_id, - request_id, - request_type, - data_id, - provider_result, - error_message, - insert_rowid, - cursor, - bulk_results, - data); - if ((request_type == DATACONTROL_TYPE_SQL_SELECT) && (cursor)) - datacontrol_sql_remove_cursor(cursor); - ret = DATACONTROL_ERROR_NONE; - } else { - ret = DATACONTROL_ERROR_INVALID_PARAMETER; - } - - if (bulk_results) - datacontrol_bulk_result_data_destroy(bulk_results); - - return ret; -} - -static int __recv_sql_bulk_insert_process(int fd, data_control_bulk_result_data_h *result_data_h) -{ - int bulk_results_size; - guint nb; - int retval = DATACONTROL_ERROR_NONE; - int i; - int bulk_result = 0; - char *encode_data = NULL; - int encode_datalen = 0; - bundle *result_data = NULL; - - datacontrol_bulk_result_data_create(result_data_h); - if (_read_socket(fd, (char *)&bulk_results_size, sizeof(bulk_results_size), &nb) != DATACONTROL_ERROR_NONE) { - retval = DATACONTROL_ERROR_IO_ERROR; - LOGE("read socket fail: bulk_results_size"); - goto out; - } - - LOGI("##### bulk result size : %d", bulk_results_size); - for (i = 0; i < bulk_results_size; i++) { - if (_read_socket(fd, (char *)&bulk_result, sizeof(bulk_result), &nb) != DATACONTROL_ERROR_NONE) { - retval = DATACONTROL_ERROR_IO_ERROR; - LOGE("read socket fail: bulk_result"); - goto out; - } - LOGI("##### bulk result : %d", bulk_result); - if (_read_socket(fd, (char *)&encode_datalen, sizeof(encode_datalen), &nb) != DATACONTROL_ERROR_NONE) { - retval = DATACONTROL_ERROR_IO_ERROR; - LOGE("read socket fail: encode_datalen"); - goto out; - } - LOGI("##### encode_datalen : %d", encode_datalen); - if (encode_datalen <= 0 || encode_datalen >= MAX_REQUEST_ARGUMENT_SIZE) { - retval = DATACONTROL_ERROR_IO_ERROR; - LOGE("Invalid encode_datalen %d", encode_datalen); - goto out; - } - encode_data = (char *)calloc(encode_datalen, sizeof(char)); - if (encode_data == NULL) { - retval = DATACONTROL_ERROR_IO_ERROR; - LOGE("FAIL to alloc encode data"); - goto out; - } - if (_read_socket(fd, encode_data, encode_datalen, &nb) != DATACONTROL_ERROR_NONE) { - retval = DATACONTROL_ERROR_IO_ERROR; - LOGE("read socket fail: encode_data"); - free(encode_data); - goto out; - } - result_data = bundle_decode_raw((bundle_raw *)encode_data, encode_datalen); - datacontrol_bulk_result_data_add(*result_data_h, result_data, bulk_result); - if (encode_data) { - free(encode_data); - encode_data = NULL; - } - bundle_free(result_data); - } - -out: - return retval; -} - -static int __recv_sql_select_process(bundle *kb, int fd, resultset_cursor *cursor) -{ - int column_count = 0; - int column_type = 0; - int column_name_len = 0; - char *column_name = NULL; - int total_len_of_column_names = 0; - sqlite3_int64 row_count = 0; - int type; - int size; - void *value = NULL; - sqlite3_int64 i = 0; - int j = 0; - char select_map_file[REQUEST_PATH_MAX] = {0,}; - char *req_id = (char *)bundle_get_val(kb, OSP_K_REQUEST_ID); - int result_fd = 0; - guint nb; - int retval = DATACONTROL_ERROR_NONE; - - LOGI("req_id : %s", req_id); - LOGI("SELECT RESPONSE"); - - size = snprintf(select_map_file, REQUEST_PATH_MAX, "/run/user/%d/%s%s%s", getuid(), DATACONTROL_REQUEST_FILE_PREFIX, - (char *)bundle_get_val(kb, AUL_K_CALLER_APPID), req_id); - if (size < 0) { - LOGE("unable to write formatted output to select_map_file. errno = %d", errno); - retval = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - LOGI("select_map_file : %s", select_map_file); - - /* TODO - shoud be changed to solve security concerns */ - result_fd = open(select_map_file, O_RDWR | O_CREAT, 0644); - if (result_fd == -1) { - LOGE("unable to open insert_map file: %d", errno); - retval = DATACONTROL_ERROR_IO_ERROR; - goto out; - - } - cursor->resultset_path = strdup(select_map_file); - if (cursor->resultset_path == NULL) { - LOGE("Out of memory. can not dup select map file."); - retval = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - cursor->resultset_fd = result_fd; - if (_read_socket(fd, (char *)&column_count, sizeof(column_count), &nb) != DATACONTROL_ERROR_NONE) { - retval = DATACONTROL_ERROR_IO_ERROR; - LOGE("read socket fail: column_count"); - goto out; - } - - /* no data check. */ - if (column_count == DATACONTROL_RESULT_NO_DATA) { - LOGE("No result"); - close(result_fd); - return DATACONTROL_ERROR_NONE; - } - - if (column_count < 0 || column_name_len > MAX_COLUMN_COUNT) { - retval = DATACONTROL_ERROR_IO_ERROR; - LOGE("Invalid column_count %d", column_count); - goto out; - } - - cursor->resultset_col_count = column_count; - LOGI("column_count : %d", column_count); - - if (write(result_fd, &column_count, sizeof(int)) == -1) { - LOGE("Writing a column_count to a file descriptor is failed. errno = %d", errno); - retval = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - cursor->resultset_col_type_offset = sizeof(int); - for (i = 0; i < column_count; i++) { - if (_read_socket(fd, (char *)&column_type, sizeof(column_type), &nb) != DATACONTROL_ERROR_NONE) { - retval = DATACONTROL_ERROR_IO_ERROR; - LOGE("read socket fail: column_type"); - goto out; - } - - LOGE("column_type : %d", column_type); - if (write(result_fd, &column_type, sizeof(int)) == -1) { - LOGE("Writing a column_type to a file descriptor is failed. errno = %d", errno); - retval = DATACONTROL_ERROR_IO_ERROR; - goto out; - - } - } - - cursor->resultset_col_name_offset = cursor->resultset_col_type_offset + - (cursor->resultset_col_count) * sizeof(int); - for (i = 0; i < column_count; i++) { - - if (_read_socket(fd, (char *)&column_name_len, sizeof(column_name_len), &nb) - != DATACONTROL_ERROR_NONE) { - retval = DATACONTROL_ERROR_IO_ERROR; - LOGE("read socket fail: column_name_len"); - goto out; - } - - if (column_name_len < 0 || column_name_len > MAX_COLUMN_SIZE) { - retval = DATACONTROL_ERROR_IO_ERROR; - LOGE("Invalid column_name_len %d", column_name_len); - goto out; - } - - LOGE("column_name_len : %d", column_name_len); - if (write(result_fd, &column_name_len, sizeof(int)) == -1) { - LOGE("Writing a column_type to a file descriptor is failed. errno = %d", errno); - retval = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - column_name = (char *)calloc(column_name_len, sizeof(char)); - if (column_name == NULL) { - LOGE("Out of memory."); - retval = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - if (_read_socket(fd, (char *)column_name, column_name_len, &nb) != DATACONTROL_ERROR_NONE) { - LOGE("read socket fail: column_name"); - retval = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - LOGE("column_name read : %d", nb); - LOGE("column_name : %s", column_name); - if (write(result_fd, column_name, column_name_len) == -1) { - LOGE("Writing a column_type to a file descriptor is failed. errno = %d", errno); - retval = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - free(column_name); - column_name = NULL; - - } - - if (_read_socket(fd, (char *)&total_len_of_column_names, sizeof(total_len_of_column_names), &nb) - != DATACONTROL_ERROR_NONE) { - LOGE("read socket fail: total_len_of_column_names"); - retval = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - LOGE("total_len_of_column_names : %d", total_len_of_column_names); - if (write(result_fd, &total_len_of_column_names, sizeof(int)) == -1) { - LOGE("Writing a total_len_of_column_names to a file descriptor is failed. errno = %d", errno); - retval = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - if (_read_socket(fd, (char *)&row_count, sizeof(row_count), &nb) != DATACONTROL_ERROR_NONE) { - LOGE("read socket fail: row_count"); - retval = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - if (row_count < 0 || row_count > MAX_ROW_COUNT) { - LOGE("invalid row_count %lld", row_count); - retval = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - LOGE("row_count : %lld", row_count); - if (write(result_fd, &row_count, sizeof(row_count)) == -1) { - LOGE("Writing a row_count to a file descriptor is failed. errno = %d", errno); - retval = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - cursor->resultset_row_count = row_count; - cursor->row_offset_list = (off_t *)calloc(row_count, sizeof(off_t)); - if (cursor->row_offset_list == NULL) { - LOGE("Out of memory. can not alloc row_offset_list."); - goto out; - } - - cursor->row_offset_list[0] = lseek(result_fd, 0, SEEK_CUR); - cursor->resultset_content_offset = cursor->row_offset_list[0]; - - LOGE("resultset_content_offset : %lld", - (unsigned long long)cursor->resultset_content_offset); - - off_t row_offset = 0; - for (i = 0; i < row_count; i++) { - row_offset = 0; - for (j = 0; j < column_count; j++) { - if (_read_socket(fd, (char *)&type, sizeof(type), &nb) != DATACONTROL_ERROR_NONE) { - LOGE("read socket fail: type"); - retval = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - LOGE("type : %d", type); - if (write(result_fd, &type, sizeof(int)) == -1) { - LOGE("Writing a type to a file descriptor is failed. errno = %d", errno); - retval = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - if (_read_socket(fd, (char *)&size, sizeof(size), &nb) != DATACONTROL_ERROR_NONE) { - LOGE("read socket fail: size"); - retval = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - LOGE("size : %d", size); - if (write(result_fd, &size, sizeof(int)) == -1) { - LOGE("Writing a size to a file descriptor is failed. errno = %d", errno); - retval = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - if (size > 0 && size < MAX_REQUEST_ARGUMENT_SIZE) { - value = (void *)malloc(sizeof(void) * size); - if (value == NULL) { - LOGE("Out of mememory"); - retval = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - if (_read_socket(fd, (char *)value, size, &nb) != DATACONTROL_ERROR_NONE) { - LOGE("read socket fail: value"); - retval = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - LOGE("value : %s", value); - if (write(result_fd, value, sizeof(void) * size) == -1) { - LOGE("Writing a value to a file descriptor is failed. errno = %d", errno); - retval = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - free(value); - value = NULL; - - } - row_offset += sizeof(int) * 2 + size; - - } - if (i + 1 < row_count) - cursor->row_offset_list[i + 1] = cursor->row_offset_list[i] + row_offset; - } - - return retval; - -out: - if (result_fd != -1) - close(result_fd); - if (column_name) - free(column_name); - if (value) - free(value); - - datacontrol_sql_remove_cursor(cursor); - return retval; -} - -static gboolean __consumer_recv_sql_message(GIOChannel *channel, - GIOCondition cond, gpointer data) -{ - gint fd = g_io_channel_unix_get_fd(channel); - char *buf = NULL; - int data_len; - guint nb; - const char *p = NULL; - int request_id; - bundle *kb = NULL; - sql_response_cb_s *sql_dc; - GList *itr; - datacontrol_consumer_request_info *request_info; - - LOGI("__consumer_recv_sql_message: ...from %d:%s%s%s%s\n", fd, - (cond & G_IO_ERR) ? " ERR" : "", - (cond & G_IO_HUP) ? " HUP" : "", - (cond & G_IO_IN) ? " IN" : "", - (cond & G_IO_PRI) ? " PRI" : ""); - - if (cond & (G_IO_ERR | G_IO_HUP)) - goto error; - - if (cond & G_IO_IN) { - if (_read_socket(fd, (char *)&data_len, sizeof(data_len), &nb) != DATACONTROL_ERROR_NONE) - goto error; - LOGI("data_len : %d", data_len); - - if (nb == 0) { - LOGE("__consumer_recv_sql_message: ...from %d: EOF\n", fd); - goto error; - } - if (data_len > 0 && data_len < MAX_REQUEST_ARGUMENT_SIZE) { - buf = (char *)calloc(data_len + 1, sizeof(char)); - if (buf == NULL) { - LOGE("Out of memory."); - goto error; - } - - if (_read_socket(fd, buf, data_len, &nb) != DATACONTROL_ERROR_NONE) { - LOGE("Out of memory."); - goto error; - } - - if (nb == 0) { - LOGE("__consumer_recv_sql_message: ...from %d: EOF\n", fd); - goto error; - } - - kb = bundle_decode_raw((bundle_raw *)buf, data_len); - - free(buf); - buf = NULL; - - if (kb == NULL) { - LOGE("bundle_decode_raw fail"); - goto error; - } - - p = appsvc_get_data(kb, OSP_K_REQUEST_ID); - if (!p) { - LOGE("Invalid Bundle: request_id is null"); - goto error; - } else { - request_id = atoi(p); - } - LOGI("Request ID: %d", request_id); - if (__sql_handle_cb(kb, data, fd, request_id) - != DATACONTROL_ERROR_NONE) - goto error; - __remove_sql_request_info(request_id, data); - bundle_free(kb); - } - } - return TRUE; -error: - if (buf) - free(buf); - if (kb) - bundle_free(kb); - - if (((sql_response_cb_s *)data) != NULL) { - LOGE("g_hash_table_remove"); - - sql_dc = (sql_response_cb_s *)data; - g_hash_table_remove(__socket_pair_hash, sql_dc->provider_id); - - itr = g_list_first(sql_dc->request_info_list); - while (itr != NULL) { - request_info = (datacontrol_consumer_request_info *)itr->data; - __sql_call_cb(sql_dc->provider_id, request_info->request_id, request_info->type, sql_dc->data_id, false, - "provider IO Error", -1, NULL, NULL, data); - itr = g_list_next(itr); - } - if (sql_dc->request_info_list) { - LOGE("free sql request_info_list"); - g_list_free_full(sql_dc->request_info_list, free); - sql_dc->request_info_list = NULL; - } - } - - return FALSE; -} - -int __datacontrol_send_sql_async(int sockfd, bundle *kb, void *extra_data, datacontrol_request_type type, void *data) -{ - bundle_raw *kb_data = NULL; - bundle_raw *extra_kb_data = NULL; - int ret = DATACONTROL_ERROR_NONE; - int datalen = 0; - int extra_kb_datalen = 0; - char *buf = NULL; - int total_len = 0; - unsigned int nb = 0; - int i; - int count; - bundle *bulk_data; - data_control_bulk_data_h bulk_data_h = NULL; - bundle_raw *encode_data = NULL; - int encode_datalen = 0; - - LOGD("send async ~~~"); - - bundle_encode_raw(kb, &kb_data, &datalen); - if (kb_data == NULL) { - LOGE("bundle encode error"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - if (DATACONTROL_TYPE_SQL_INSERT == type || - DATACONTROL_TYPE_SQL_UPDATE == type) { - bundle_encode_raw((bundle *)extra_data, &extra_kb_data, &extra_kb_datalen); - if (extra_kb_data == NULL) { - LOGE("bundle encode error"); - goto out; - } - } - - total_len = sizeof(datalen) + datalen; - if (extra_kb_datalen > 0) - total_len += sizeof(extra_kb_datalen) + extra_kb_datalen; - - /* encoded bundle + encoded bundle size */ - buf = (char *)calloc(total_len, sizeof(char)); - if (buf == NULL) { - bundle_free_encoded_rawdata(&kb_data); - LOGE("Out of memory."); - goto out; - } - - memcpy(buf, &datalen, sizeof(datalen)); - memcpy(buf + sizeof(datalen), kb_data, datalen); - if (extra_kb_datalen > 0) { - memcpy(buf + sizeof(datalen) + datalen, &extra_kb_datalen, sizeof(extra_kb_datalen)); - memcpy(buf + sizeof(datalen) + datalen + sizeof(extra_kb_datalen), extra_kb_data, extra_kb_datalen); - } - - LOGI("write : %d", total_len); - if (_write_socket(sockfd, buf, total_len, &nb) != DATACONTROL_ERROR_NONE) { - LOGI("write data fail"); - ret = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - - if (DATACONTROL_TYPE_SQL_BULK_INSERT == type) { - bulk_data_h = (data_control_bulk_data_h)extra_data; - datacontrol_bulk_data_get_count(bulk_data_h, &count); - - if (_write_socket(sockfd, &count, sizeof(count), &nb) != DATACONTROL_ERROR_NONE) { - LOGI("write bulk count fail"); - ret = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - LOGI("write bulk count %d ", count); - for (i = 0; i < count; i++) { - datacontrol_bulk_data_get_data(bulk_data_h, i, &bulk_data); - bundle_encode_raw(bulk_data, &encode_data, &encode_datalen); - if (_write_socket(sockfd, &encode_datalen, sizeof(encode_datalen), &nb) != DATACONTROL_ERROR_NONE) { - LOGE("write bulk encode_datalen fail"); - ret = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - LOGI("write encode_datalen %d ", encode_datalen); - - if (_write_socket(sockfd, encode_data, encode_datalen, &nb) != DATACONTROL_ERROR_NONE) { - LOGE("write bulk encode_data fail"); - ret = DATACONTROL_ERROR_IO_ERROR; - goto out; - } - encode_datalen = 0; - bundle_free_encoded_rawdata(&encode_data); - } - } - -out: - if (buf) - free(buf); - bundle_free_encoded_rawdata(&kb_data); - bundle_free_encoded_rawdata(&extra_kb_data); - bundle_free_encoded_rawdata(&encode_data); - - return ret; -} - -static int __sql_request_provider(datacontrol_h provider, datacontrol_request_type type, bundle *request_data, void *extra_data, int request_id) -{ - char *app_id = NULL; - void *response_cb_data = NULL; - int ret = DATACONTROL_ERROR_NONE; - sql_response_cb_s *sql_dc_temp; - void *sql_dc_returned = NULL; - char caller_app_id[255]; - char datacontrol_request_operation[MAX_LEN_DATACONTROL_REQ_TYPE] = {0, }; - char req_id[32] = {0, }; - int count = 0; - const int TRY_COUNT = 2; - const struct timespec TRY_SLEEP_TIME = { 0, 1000 * 1000 * 1000 }; - char *socket_info_key; - bundle *send_data; - - LOGI("SQL Data control request, type: %d, request id: %d", type, request_id); - - if (__socket_pair_hash == NULL) - __socket_pair_hash = g_hash_table_new_full(g_str_hash, g_str_equal, free, _socket_info_free); - - if ((int)type <= (int)DATACONTROL_TYPE_SQL_BULK_INSERT) { - if ((int)type < (int)DATACONTROL_TYPE_SQL_SELECT) { - LOGE("invalid request type: %d", (int)type); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - if (!datacontrol_sql_tree_root) { - LOGE("the listener tree is empty"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - sql_dc_temp = (sql_response_cb_s *)calloc(1, sizeof(sql_response_cb_s)); - if (!sql_dc_temp) { - LOGE("failed to create sql datacontrol"); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - sql_dc_temp->provider_id = strdup(provider->provider_id); - if (!sql_dc_temp->provider_id) { - LOGE("failed to assign provider id to sql data control: %d", errno); - free(sql_dc_temp); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - sql_dc_temp->data_id = strdup(provider->data_id); - if (!sql_dc_temp->data_id) { - LOGE("failed to assign data id to sql data control: %d", errno); - free(sql_dc_temp->provider_id); - free(sql_dc_temp); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - sql_dc_temp->app_id = NULL; - sql_dc_temp->access_info = NULL; - sql_dc_temp->user_data = NULL; - sql_dc_temp->sql_response_cb = NULL; - - sql_dc_returned = tfind(sql_dc_temp, &datacontrol_sql_tree_root, __sql_instance_compare); - - __sql_instance_free(sql_dc_temp); - - if (!sql_dc_returned) { - LOGE("sql datacontrol returned after tfind is null"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - sql_response_cb_s *sql_dc = *(sql_response_cb_s **)sql_dc_returned; - app_id = sql_dc->app_id; - - datacontrol_consumer_request_info *request_info = (datacontrol_consumer_request_info *)calloc(sizeof(datacontrol_consumer_request_info), 1); - request_info->request_id = request_id; - request_info->type = type; - sql_dc->request_info_list = g_list_append(sql_dc->request_info_list, request_info); - - response_cb_data = sql_dc; - - LOGI("SQL datacontrol appid: %s", sql_dc->app_id); - } - - pid_t pid = getpid(); - if (aul_app_get_appid_bypid(pid, caller_app_id, sizeof(caller_app_id)) != 0) { - LOGE("Failed to get appid by pid(%d).", pid); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - send_data = bundle_dup(request_data); - if (send_data == NULL) { - LOGE("fail to alloc result_data"); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - bundle_add_str(send_data, OSP_K_DATACONTROL_PROTOCOL_VERSION, OSP_V_VERSION_2_1_0_3); - bundle_add_str(send_data, AUL_K_CALLER_APPID, caller_app_id); - - snprintf(datacontrol_request_operation, MAX_LEN_DATACONTROL_REQ_TYPE, "%d", (int)(type)); - bundle_add_str(send_data, OSP_K_DATACONTROL_REQUEST_TYPE, datacontrol_request_operation); - - snprintf(req_id, 32, "%d", request_id); - bundle_add_str(send_data, OSP_K_REQUEST_ID, req_id); - - do { - datacontrol_socket_info *socket_info = g_hash_table_lookup(__socket_pair_hash, provider->provider_id); - - if (socket_info == NULL) { - ret = _add_watch_on_socket_info(caller_app_id, app_id, - "consumer", provider->provider_id, "Sql", - __consumer_recv_sql_message, response_cb_data, - &socket_info); - if (ret != DATACONTROL_ERROR_NONE) { - LOGE("_get_socket_info error !!!"); - bundle_free(send_data); - return ret; - } - - ret = _request_appsvc_run(caller_app_id, app_id); - if (ret != DATACONTROL_ERROR_NONE) { - LOGE("_request_appsvc_run error !!!"); - bundle_free(send_data); - _socket_info_free(socket_info); - return ret; - } - - socket_info_key = strdup(provider->provider_id); - if (socket_info_key == NULL) { - LOGE("Out of memory. can not dup select map file."); - bundle_free(send_data); - return DATACONTROL_ERROR_IO_ERROR; - } - g_hash_table_insert(__socket_pair_hash, socket_info_key, socket_info); - } - - LOGE("send data from consumer"); - ret = __datacontrol_send_sql_async(socket_info->socket_fd, send_data, extra_data, type, NULL); - if (ret != DATACONTROL_ERROR_NONE) - g_hash_table_remove(__socket_pair_hash, provider->provider_id); - else - break; - - count++; - nanosleep(&TRY_SLEEP_TIME, 0); - } while (ret != DATACONTROL_ERROR_NONE && count < TRY_COUNT); - - bundle_free(send_data); - return ret; -} - -int datacontrol_sql_create(datacontrol_h *provider) -{ - struct datacontrol_s *request; - - if (provider == NULL) - return DATACONTROL_ERROR_INVALID_PARAMETER; - - request = malloc(sizeof(struct datacontrol_s)); - if (request == NULL) - return DATACONTROL_ERROR_OUT_OF_MEMORY; - - request->provider_id = NULL; - request->data_id = NULL; - - *provider = request; - - return 0; -} - -int datacontrol_sql_destroy(datacontrol_h provider) -{ - if (provider == NULL) - return DATACONTROL_ERROR_INVALID_PARAMETER; - - if (provider->provider_id != NULL) - free(provider->provider_id); - - if (provider->data_id != NULL) - free(provider->data_id); - - free(provider); - return 0; -} - -int datacontrol_sql_set_provider_id(datacontrol_h provider, const char *provider_id) -{ - if (provider == NULL || provider_id == NULL) - return DATACONTROL_ERROR_INVALID_PARAMETER; - - if (provider->provider_id != NULL) - free(provider->provider_id); - - provider->provider_id = strdup(provider_id); - if (provider->provider_id == NULL) - return DATACONTROL_ERROR_OUT_OF_MEMORY; - - return 0; -} - -int datacontrol_sql_get_provider_id(datacontrol_h provider, char **provider_id) -{ - if (provider == NULL || provider_id == NULL) - return DATACONTROL_ERROR_INVALID_PARAMETER; - - if (provider->provider_id != NULL) { - - *provider_id = strdup(provider->provider_id); - if (*provider_id == NULL) - return DATACONTROL_ERROR_OUT_OF_MEMORY; - - } else { - *provider_id = NULL; - } - - return 0; -} - -int datacontrol_sql_set_data_id(datacontrol_h provider, const char *data_id) -{ - if (provider == NULL || data_id == NULL) - return DATACONTROL_ERROR_INVALID_PARAMETER; - - if (provider->data_id != NULL) - free(provider->data_id); - - provider->data_id = strdup(data_id); - if (provider->data_id == NULL) - return DATACONTROL_ERROR_OUT_OF_MEMORY; - - return 0; -} - -int datacontrol_sql_get_data_id(datacontrol_h provider, char **data_id) -{ - if (provider == NULL || data_id == NULL) - return DATACONTROL_ERROR_INVALID_PARAMETER; - - if (provider->data_id != NULL) { - - *data_id = strdup(provider->data_id); - if (*data_id == NULL) - return DATACONTROL_ERROR_OUT_OF_MEMORY; - - } else - *data_id = NULL; - - return 0; -} - -bool datacontrol_sql_cb_is_registered(char *provider_id) -{ - sql_response_cb_s sql_dc_temp; - sql_dc_temp.provider_id = provider_id; - - if (tfind(&sql_dc_temp, &datacontrol_sql_tree_root, __sql_instance_compare) != NULL) - return true; - return false; -} - -int datacontrol_sql_register_response_cb(datacontrol_h provider, datacontrol_sql_response_cb *callback, void *user_data) -{ - int ret = 0; - char *app_id = NULL; - char *access = NULL; - void *sql_dc_returned = NULL; - sql_response_cb_s *sql_dc; - - ret = pkgmgrinfo_appinfo_usr_get_datacontrol_info(provider->provider_id, "Sql", getuid(), &app_id, &access); - if (ret != PMINFO_R_OK) { - LOGE("unable to get sql data control information: %d", ret); - return DATACONTROL_ERROR_IO_ERROR; - } - - LOGI("data control provider appid = %s", app_id); - - sql_response_cb_s *sql_dc_temp = (sql_response_cb_s *)calloc(1, sizeof(sql_response_cb_s)); - if (!sql_dc_temp) { - LOGE("unable to create a temporary sql data control"); - ret = DATACONTROL_ERROR_OUT_OF_MEMORY; - goto EXCEPTION; - } - - sql_dc_temp->provider_id = strdup(provider->provider_id); - if (!sql_dc_temp->provider_id) { - LOGE("unable to assign provider_id to sql data control: %d", errno); - ret = DATACONTROL_ERROR_OUT_OF_MEMORY; - goto EXCEPTION; - } - - sql_dc_temp->data_id = strdup(provider->data_id); - if (!sql_dc_temp->data_id) { - LOGE("unable to assign data_id to sql data control: %d", errno); - ret = DATACONTROL_ERROR_OUT_OF_MEMORY; - goto EXCEPTION; - } - - sql_dc_temp->app_id = app_id; - sql_dc_temp->access_info = access; - sql_dc_temp->user_data = user_data; - sql_dc_temp->sql_response_cb = callback; - - sql_dc_returned = tsearch(sql_dc_temp, &datacontrol_sql_tree_root, __sql_instance_compare); - - sql_dc = *(sql_response_cb_s **)sql_dc_returned; - if (sql_dc != sql_dc_temp) { - sql_dc->sql_response_cb = callback; - sql_dc->user_data = user_data; - LOGI("the data control is already set"); - __sql_instance_free(sql_dc_temp); - } - - return DATACONTROL_ERROR_NONE; - -EXCEPTION: - if (access) - free(access); - if (app_id) - free(app_id); - - if (sql_dc_temp) { - if (sql_dc_temp->provider_id) - free(sql_dc_temp->provider_id); - if (sql_dc_temp->data_id) - free(sql_dc_temp->data_id); - free(sql_dc_temp); - } - - return ret; -} - -int datacontrol_sql_unregister_response_cb(datacontrol_h provider) -{ - int ret = DATACONTROL_ERROR_NONE; - sql_response_cb_s *sql_dc_returned = NULL; - char *tmp_provider_id; - - LOGE("g_hash_table_remove"); - - g_hash_table_remove(__socket_pair_hash, provider->provider_id); - - sql_response_cb_s *sql_dc_temp = (sql_response_cb_s *)calloc(1, sizeof(sql_response_cb_s)); - - if (!sql_dc_temp) { - LOGE("unable to create a temporary sql data control"); - ret = DATACONTROL_ERROR_OUT_OF_MEMORY; - goto EXCEPTION; - } - - sql_dc_temp->provider_id = strdup(provider->provider_id); - if (!sql_dc_temp->provider_id) { - LOGE("unable to assign provider_id to sql data control: %d", errno); - ret = DATACONTROL_ERROR_OUT_OF_MEMORY; - goto EXCEPTION; - } - - if (datacontrol_sql_tree_root == NULL) { - LOGE("The listener tree is empty"); - ret = DATACONTROL_ERROR_INVALID_PARAMETER; - goto EXCEPTION; - } - - sql_dc_returned = *(sql_response_cb_s **)tfind(sql_dc_temp, &datacontrol_sql_tree_root, __sql_instance_compare); - if (sql_dc_returned == NULL) { - LOGE("invalid parameter"); - ret = DATACONTROL_ERROR_INVALID_PARAMETER; - goto EXCEPTION; - } - - if (sql_dc_returned->app_id) - free(sql_dc_returned->app_id); - if (sql_dc_returned->data_id) - free(sql_dc_returned->data_id); - if (sql_dc_returned->access_info) - free(sql_dc_returned->access_info); - if (sql_dc_returned->request_info_list) - g_list_free_full(sql_dc_returned->request_info_list, free); - - tmp_provider_id = sql_dc_returned->provider_id; - tdelete(sql_dc_temp, &datacontrol_sql_tree_root, __sql_instance_compare); - free(tmp_provider_id); - -EXCEPTION: - if (sql_dc_temp) { - if (sql_dc_temp->provider_id) - free(sql_dc_temp->provider_id); - free(sql_dc_temp); - } - - return ret; -} - -int datacontrol_sql_insert(datacontrol_h provider, const bundle *insert_data, int *request_id) -{ - int ret = 0; - long long arg_size = 0; - const char *arg_list[2]; - bundle *b; - char insert_column_count[MAX_LEN_DATACONTROL_COLUMN_COUNT] = {0, }; - int count; - - if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || insert_data == NULL) { - LOGE("Invalid parameter"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - LOGI("SQL data control, insert to provider_id: %s, data_id: %s", provider->provider_id, provider->data_id); - - /* Check size of arguments */ - bundle_foreach((bundle *)insert_data, _bundle_foreach_check_arg_size_cb, &arg_size); - arg_size += strlen(provider->data_id) * sizeof(wchar_t); - if (arg_size > MAX_REQUEST_ARGUMENT_SIZE) { - LOGE("The size of the request argument exceeds the limit, 1M."); - return DATACONTROL_ERROR_MAX_EXCEEDED; - } - - b = bundle_create(); - if (!b) { - LOGE("unable to create bundle: %d", errno); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id); - bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id); - - count = bundle_get_count((bundle *)insert_data); - ret = snprintf(insert_column_count, MAX_LEN_DATACONTROL_COLUMN_COUNT, "%d", count); - if (ret < 0) { - LOGE("unable to convert insert column count to string: %d", errno); - bundle_free(b); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - arg_list[0] = provider->data_id; - arg_list[1] = insert_column_count; - - bundle_add_str_array(b, OSP_K_ARG, arg_list, 2); - - /* Set the request id */ - *request_id = _datacontrol_create_request_id(); - LOGI("request id : %d", *request_id); - - ret = __sql_request_provider(provider, DATACONTROL_TYPE_SQL_INSERT, b, (bundle *)insert_data, *request_id); - bundle_free(b); - return ret; -} - -int datacontrol_sql_delete(datacontrol_h provider, const char *where, int *request_id) -{ - const char *arg_list[2]; - int reqId; - int ret; - bundle *b; - - if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL) { - LOGE("Invalid parameter"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - b = bundle_create(); - if (!b) { - LOGE("unable to create bundle: %d", errno); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id); - bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id); - - arg_list[0] = provider->data_id; - - if (where) - arg_list[1] = where; - else - arg_list[1] = DATACONTROL_EMPTY; - - bundle_add_str_array(b, OSP_K_ARG, arg_list, 2); - - /* Set the request id */ - reqId = _datacontrol_create_request_id(); - *request_id = reqId; - - ret = __sql_request_provider(provider, DATACONTROL_TYPE_SQL_DELETE, b, NULL, reqId); - bundle_free(b); - return ret; -} - -int datacontrol_sql_select(datacontrol_h provider, char **column_list, int column_count, - const char *where, const char *order, int *request_id) -{ - return datacontrol_sql_select_with_page(provider, column_list, column_count, where, order, 1, 20, request_id); -} - -int datacontrol_sql_select_with_page(datacontrol_h provider, char **column_list, int column_count, - const char *where, const char *order, int page_number, int count_per_page, int *request_id) -{ - int total_arg_count = -1; - int ret = 0; - bundle *b; - char page[32] = {0, }; - char count_per_page_no[32] = {0, }; - const char **arg_list; - int i; - char select_column_count[MAX_LEN_DATACONTROL_COLUMN_COUNT] = {0, }; - int select_col; - int reqId; - - if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL) { - LOGE("Invalid parameter"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - LOGI("SQL data control, select to provider_id: %s, data_id: %s, col_count: %d, where: %s, order: %s, page_number: %d, per_page: %d", provider->provider_id, provider->data_id, column_count, where, order, page_number, count_per_page); - - if (column_list == NULL) { - LOGE("Invalid parameter"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - b = bundle_create(); - if (!b) { - LOGE("unable to create bundle: %d", errno); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id); - bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id); - - ret = snprintf(page, 32, "%d", page_number); - if (ret < 0) { - LOGE("unable to convert page no to string: %d", errno); - bundle_free(b); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - ret = snprintf(count_per_page_no, 32, "%d", count_per_page); - if (ret < 0) { - LOGE("unable to convert count per page no to string: %d", errno); - bundle_free(b); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - total_arg_count = column_count + DATACONTROL_SELECT_EXTRA_COUNT; - arg_list = (const char **)malloc(total_arg_count * (sizeof(char *))); - - LOGI("total arg count %d", total_arg_count); - - arg_list[0] = provider->data_id; /* arg[0]: data ID */ - i = 1; - if (column_list) { - ret = snprintf(select_column_count, MAX_LEN_DATACONTROL_COLUMN_COUNT, "%d", column_count); - if (ret < 0) { - LOGE("unable to convert select col count to string: %d", errno); - free(arg_list); - bundle_free(b); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - - arg_list[i] = select_column_count; /* arg[1]: selected column count */ - - ++i; - select_col = 0; - while (select_col < column_count) - arg_list[i++] = column_list[select_col++]; - } - - if (where) /* arg: where clause */ - arg_list[i++] = where; - else - arg_list[i++] = DATACONTROL_EMPTY; - - if (order) /* arg: order clause */ - arg_list[i++] = order; - else - arg_list[i++] = DATACONTROL_EMPTY; - - arg_list[i++] = page; /* arg: page number */ - - arg_list[i] = count_per_page_no; /* arg: count per page */ - - bundle_add_str_array(b, OSP_K_ARG, arg_list, total_arg_count); - free(arg_list); - - reqId = _datacontrol_create_request_id(); - *request_id = reqId; - - ret = __sql_request_provider(provider, DATACONTROL_TYPE_SQL_SELECT, b, NULL, reqId); - bundle_free(b); - return ret; -} - -int datacontrol_sql_update(datacontrol_h provider, const bundle *update_data, const char *where, int *request_id) -{ - int ret = 0; - long long arg_size = 0; - bundle *b; - const char *arg_list[4]; - - if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || update_data == NULL || where == NULL) { - LOGE("Invalid parameter"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - /* Check size of arguments */ - bundle_foreach((bundle *)update_data, _bundle_foreach_check_arg_size_cb, &arg_size); - arg_size += strlen(provider->data_id) * sizeof(wchar_t); - if (arg_size > MAX_REQUEST_ARGUMENT_SIZE) { - LOGE("The size of the request argument exceeds the limit, 1M."); - return DATACONTROL_ERROR_MAX_EXCEEDED; - } - - b = bundle_create(); - if (!b) { - LOGE("unable to create bundle: %d", errno); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id); - bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id); - - arg_list[0] = provider->data_id; /* list(0): data ID */ - arg_list[1] = where; - bundle_add_str_array(b, OSP_K_ARG, arg_list, 2); - - *request_id = _datacontrol_create_request_id(); - ret = __sql_request_provider(provider, DATACONTROL_TYPE_SQL_UPDATE, b, (bundle *)update_data, *request_id); - - bundle_free(b); - return ret; -} - -int datacontrol_sql_insert_bulk_data(datacontrol_h provider, data_control_bulk_data_h bulk_data_h, int *request_id) -{ - int ret = 0; - long long arg_size = 0; - const char *arg_list[2]; - bundle *b; - bundle *data; - int count; - int i; - - if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL) { - LOGE("Invalid parameter"); - return DATACONTROL_ERROR_INVALID_PARAMETER; - } - - LOGI("SQL data control, insert to provider_id: %s, data_id: %s", provider->provider_id, provider->data_id); - - /* Check size of arguments */ - count = datacontrol_bulk_data_get_count(bulk_data_h, &count); - for (i = 0; i < count; i++) { - datacontrol_bulk_data_get_data(bulk_data_h, i, &data); - bundle_foreach(data, _bundle_foreach_check_arg_size_cb, &arg_size); - } - arg_size += (strlen(provider->data_id) + strlen(provider->provider_id)) * sizeof(wchar_t); - if (arg_size > MAX_REQUEST_ARGUMENT_SIZE) { - LOGE("The size of the request argument exceeds the limit, 1M."); - return DATACONTROL_ERROR_MAX_EXCEEDED; - } - - b = bundle_create(); - if (!b) { - LOGE("unable to create bundle: %d", errno); - return DATACONTROL_ERROR_OUT_OF_MEMORY; - } - - bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id); - bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id); - - arg_list[0] = provider->data_id; - bundle_add_str_array(b, OSP_K_ARG, arg_list, 1); - - /* Set the request id */ - *request_id = _datacontrol_create_request_id(); - LOGI("request id : %d", *request_id); - - ret = __sql_request_provider(provider, DATACONTROL_TYPE_SQL_BULK_INSERT, b, bulk_data_h, *request_id); - bundle_free(b); - return ret; -} diff --git a/src/data_control_bulk.c b/src/data_control_bulk.c index 2630dab..83b36d3 100644 --- a/src/data_control_bulk.c +++ b/src/data_control_bulk.c @@ -14,7 +14,6 @@ * limitations under the License. */ -#include #include #include #include @@ -22,114 +21,202 @@ #include "data_control_log.h" #include "data_control_bulk.h" -#include "data-control-bulk.h" +#include "data_control_internal.h" -EXPORT_API int data_control_bulk_data_get_data(data_control_bulk_data_h bulk_data_h, int idx, bundle **data) +typedef struct { + bundle *result_data; + int result; +} data_control_bulk_result_data_item_s; + +struct data_control_bulk_result_data_s { + GList *data_list; +}; + +struct data_control_bulk_data_s { + GList *data_list; +}; + +static void __free_bulk_result_data(gpointer data) { - int ret; + data_control_bulk_result_data_item_s *result_data_item = + (data_control_bulk_result_data_item_s *)data; + bundle_free(result_data_item->result_data); + free(result_data_item); +} - if (bulk_data_h == NULL || data == NULL) { - LOGE("Invalid bulk data handle"); +static void __free_bulk_data(gpointer data) +{ + bundle *bulk_data = (bundle *)data; + bundle_free(bulk_data); +} + +EXPORT_API int data_control_bulk_data_get_data(data_control_bulk_data_h bulk_data_h, + int idx, bundle **data) +{ + bundle *ret_data; + + if (bulk_data_h == NULL || data == NULL || + bulk_data_h->data_list == NULL) { + _LOGE("Invalid bulk data handle"); return DATA_CONTROL_ERROR_INVALID_PARAMETER; } if (idx < 0) { - LOGE("Invalid index"); + _LOGE("Invalid index"); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + ret_data = (bundle *)g_list_nth_data(bulk_data_h->data_list, idx); + if (ret_data == NULL) { + _LOGE("no data at index %d", idx); return DATA_CONTROL_ERROR_INVALID_PARAMETER; } - ret = datacontrol_bulk_data_get_data(bulk_data_h, idx, data); - return ret; + + *data = ret_data; + return DATA_CONTROL_ERROR_NONE; } -EXPORT_API int data_control_bulk_data_get_count(data_control_bulk_data_h bulk_data_h, int *count) +EXPORT_API int data_control_bulk_data_get_count(data_control_bulk_data_h bulk_data_h, + int *count) { - int ret; if (bulk_data_h == NULL || count == NULL) { - LOGE("Invalid bulk data handle"); + _LOGE("Invalid bulk data handle"); return DATA_CONTROL_ERROR_INVALID_PARAMETER; } - ret = datacontrol_bulk_data_get_count(bulk_data_h, count); - return ret; + + *count = g_list_length(bulk_data_h->data_list); + return DATA_CONTROL_ERROR_NONE; } -EXPORT_API int data_control_bulk_data_add(data_control_bulk_data_h bulk_data_h, bundle *data) +EXPORT_API int data_control_bulk_data_add(data_control_bulk_data_h bulk_data_h, + bundle *data) { if (bulk_data_h == NULL || data == NULL) { - LOGE("Invalid data"); + _LOGE("Invalid data"); return DATA_CONTROL_ERROR_INVALID_PARAMETER; } - return datacontrol_bulk_data_add(bulk_data_h, data); + + bulk_data_h->data_list = g_list_append(bulk_data_h->data_list, + bundle_dup(data)); + _LOGI("append bulk data : %d", g_list_length(bulk_data_h->data_list)); + return DATA_CONTROL_ERROR_NONE; } EXPORT_API int data_control_bulk_data_create(data_control_bulk_data_h *bulk_data_h) { if (bulk_data_h == NULL) { - LOGE("Invalid bulk data handle"); + _LOGE("Invalid bulk data handle"); return DATA_CONTROL_ERROR_INVALID_PARAMETER; } - return datacontrol_bulk_data_create(bulk_data_h); + *bulk_data_h = (struct data_control_bulk_data_s *)calloc(1, + sizeof(struct data_control_bulk_data_s)); + if (*bulk_data_h == NULL) { + _LOGE("Fail to create bulk data. Out of memory."); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } + return DATA_CONTROL_ERROR_NONE; } EXPORT_API int data_control_bulk_data_destroy(data_control_bulk_data_h bulk_data_h) { if (bulk_data_h == NULL) { - LOGE("Invalid bulk data handle"); + _LOGE("Invalid bulk data handle"); return DATA_CONTROL_ERROR_INVALID_PARAMETER; } - return datacontrol_bulk_data_destroy(bulk_data_h); + + g_list_free_full(bulk_data_h->data_list, __free_bulk_data); + free(bulk_data_h); + _LOGI("bulk data destroy done"); + return DATA_CONTROL_ERROR_NONE; } -EXPORT_API int data_control_bulk_result_data_get_result_data(data_control_bulk_result_data_h result_data_h, int idx, bundle **result_data, int *result) +EXPORT_API int data_control_bulk_result_data_get_result_data(data_control_bulk_result_data_h result_data_h, + int idx, bundle **result_data, int *result) { - int ret; + data_control_bulk_result_data_item_s *result_data_item; - if (result_data_h == NULL || result == NULL) { - LOGE("Invalid bulk data handle"); + if (result_data_h == NULL || result == NULL || + result_data_h->data_list == NULL) { + _LOGE("Invalid bulk data handle"); return DATA_CONTROL_ERROR_INVALID_PARAMETER; } if (idx < 0) { - LOGE("Invalid index"); + _LOGE("Invalid index"); return DATA_CONTROL_ERROR_INVALID_PARAMETER; } - ret = datacontrol_bulk_result_data_get_result_data(result_data_h, idx, result_data, result); - return ret; + + result_data_item = + (data_control_bulk_result_data_item_s *)g_list_nth_data(result_data_h->data_list, idx); + if (result_data) + *result_data = result_data_item->result_data; + *result = result_data_item->result; + return DATA_CONTROL_ERROR_NONE; } -EXPORT_API int data_control_bulk_result_data_get_count(data_control_bulk_result_data_h result_data_h, int *count) +EXPORT_API int data_control_bulk_result_data_get_count(data_control_bulk_result_data_h result_data_h, + int *count) { - int ret; if (result_data_h == NULL || count == NULL) { - LOGE("Invalid bulk data handle"); + _LOGE("Invalid bulk data handle"); return DATA_CONTROL_ERROR_INVALID_PARAMETER; } - ret = datacontrol_bulk_result_data_get_count(result_data_h, count); - return ret; + + *count = g_list_length(result_data_h->data_list); + return DATA_CONTROL_ERROR_NONE; } -EXPORT_API int data_control_bulk_result_data_add(data_control_bulk_result_data_h result_data_h, bundle *result_data, int result) +EXPORT_API int data_control_bulk_result_data_add(data_control_bulk_result_data_h result_data_h, + bundle *result_data, int result) { if (result_data_h == NULL) { - LOGE("Invalid bulk data handle"); + _LOGE("Invalid bulk data handle"); return DATA_CONTROL_ERROR_INVALID_PARAMETER; } - return datacontrol_bulk_result_data_add(result_data_h, result_data, result); + + data_control_bulk_result_data_item_s *result_data_item = + (data_control_bulk_result_data_item_s *)calloc(1, sizeof(data_control_bulk_result_data_item_s)); + if (result_data_item == NULL) { + _LOGE("fail to alloc bulk_result_data"); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } + + if (result_data != NULL) { + result_data_item->result_data = bundle_dup(result_data); + if (result_data_item->result_data == NULL) { + free(result_data_item); + _LOGE("fail to alloc result_data"); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } + } + result_data_item->result = result; + + result_data_h->data_list = g_list_append(result_data_h->data_list, + result_data_item); + _LOGI("append bulk result data : %d", g_list_length(result_data_h->data_list)); + return DATA_CONTROL_ERROR_NONE; } EXPORT_API int data_control_bulk_result_data_create(data_control_bulk_result_data_h *result_data_h) { if (result_data_h == NULL) { - LOGE("Invalid bulk data handle"); + _LOGE("Invalid bulk data handle"); return DATA_CONTROL_ERROR_INVALID_PARAMETER; } - return datacontrol_bulk_result_data_create(result_data_h); + *result_data_h = + (struct data_control_bulk_result_data_s *)calloc(1, sizeof(struct data_control_bulk_result_data_s)); + return DATA_CONTROL_ERROR_NONE; } EXPORT_API int data_control_bulk_result_data_destroy(data_control_bulk_result_data_h result_data_h) { if (result_data_h == NULL) { - LOGE("Invalid bulk data handle"); + _LOGE("Invalid bulk data handle"); return DATA_CONTROL_ERROR_INVALID_PARAMETER; } - return datacontrol_bulk_result_data_destroy(result_data_h); + + g_list_free_full(result_data_h->data_list, __free_bulk_result_data); + free(result_data_h); + _LOGI("bulk result data destroy done"); + return DATA_CONTROL_ERROR_NONE; } diff --git a/src/data_control_internal.c b/src/data_control_internal.c index 2ab1b32..4b9343f 100755 --- a/src/data_control_internal.c +++ b/src/data_control_internal.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2013 - 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. @@ -13,44 +13,1862 @@ * 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 + +#include +#include + +#include +#include #include -#include +#include + +#include "data_control_map.h" +#include "data_control_sql.h" +#include "data_control_provider.h" +#include "data_control_internal.h" +#include "data_control_types.h" +#include "data_control_bulk.h" +#include "data_control_log.h" + +#define MAX_STATEMENT_SIZE 1024 +#define RESULT_VALUE_COUNT "RESULT_VALUE_COUNT" +#define MAX_COUNT_PER_PAGE "MAX_COUNT_PER_PAGE" +#define RESULT_PAGE_NUMBER "RESULT_PAGE_NUMBER" +#define MAX_RETRY 10 + +#define ERR_BUFFER_SIZE 1024 +#define BUFSIZE 512 +#define DATA_CONTROL_DBUS_PATH_PREFIX "/org/tizen/data_control_service_" +#define DATA_CONTROL_OBJECT_PATH "/org/tizen/data_control_service" +#define DATA_CONTROL_INTERFACE_NAME "org.tizen.data_control_service" +#define DATA_CONTROL_DB_NAME_PREFIX "._data_control_list_" +#define DATA_CONTROL_DB_NAME "DATA_CONTROL_DATA_CHANGE_TABLE" + +#define SMACK_LABEL_LEN 255 +#define CHECKED_CACHE_SIZE 10 +#define REQUEST_PATH_MAX 512 + +struct datacontrol_cert_info { + cert_status_type sql; + cert_status_type map; + time_t time; +}; + +typedef struct { + char *provider_id; + char *app_id; + char *data_id; + int map_access_info; + int sql_access_info; + GList *request_info_list; + data_control_map_response_cb *map_response_cb; + data_control_sql_response_cb *sql_response_cb; + data_control_bulk_cb map_bulk_add_cb; + data_control_bulk_cb sql_bulk_insert_cb; + void *map_user_data; + void *map_bulk_user_data; + void *sql_user_data; + void *sql_bulk_user_data; +} __response_cb_s; + +static GHashTable *__response_table = NULL; +static GHashTable *__socket_pair_hash = NULL; + + +static GHashTable *__checked_provider_hash; +static GHashTable *__checked_consumer_hash; + +static GDBusConnection *_gdbus_conn = NULL; + +int __datacontrol_get_provider_id(void) +{ + static int id = 0; + g_atomic_int_inc(&id); + + return id; +} + +static char *__get_victim(GHashTable *hash) +{ + GHashTableIter iter; + gpointer key; + gpointer value; + time_t time = 0; + char *victim_key = NULL; + + g_hash_table_iter_init(&iter, hash); + + while (g_hash_table_iter_next(&iter, &key, &value)) { + struct datacontrol_cert_info *info = (struct datacontrol_cert_info *)value; + if (time == 0 || time > info->time) { + time = info->time; + victim_key = key; + } + } + + return victim_key; +} + +static void __insert_hash(GHashTable *hash, const char *key, + bool is_map, cert_status_type status) +{ + struct datacontrol_cert_info *cert_info; + char *victim_key; + + if (g_hash_table_size(hash) > CHECKED_CACHE_SIZE) { + victim_key = __get_victim(hash); + if (victim_key) + g_hash_table_remove(hash, victim_key); + } + + cert_info = (struct datacontrol_cert_info *)calloc(1, + sizeof(struct datacontrol_cert_info)); + + if (is_map) + cert_info->map = status; + else + cert_info->sql = status; + + time(&cert_info->time); + + g_hash_table_insert(hash, strdup(key), cert_info); +} + +static void __free_data(gpointer data) +{ + if (data) { + g_free(data); + data = NULL; + } +} + +static void __free_response_cb(gpointer data) +{ + __response_cb_s *dc = (__response_cb_s *)data; + if (dc) { + if (dc->provider_id) + free(dc->provider_id); + if (dc->data_id) + free(dc->data_id); + if (dc->app_id) + free(dc->app_id); + if (dc->map_response_cb) + free(dc->map_response_cb); + if (dc->sql_response_cb) + free(dc->sql_response_cb); + if (dc->request_info_list) + g_list_free_full(dc->request_info_list, free); + + free(dc); + } +} + +static void __initialize(void) +{ + __response_table = g_hash_table_new_full(g_str_hash, g_str_equal, + __free_data, __free_response_cb); +} + +int __consumer_request_compare_cb(gconstpointer a, gconstpointer b) +{ + datacontrol_consumer_request_info *key1 = + (datacontrol_consumer_request_info *)a; + datacontrol_consumer_request_info *key2 = + (datacontrol_consumer_request_info *)b; + if (key1->request_id == key2->request_id) + return 0; + + return 1; +} + +static void __remove_request_info(int request_id, __response_cb_s *dc) +{ + + datacontrol_consumer_request_info temp_request_info; + datacontrol_consumer_request_info *data; + + temp_request_info.request_id = request_id; + GList *list = g_list_find_custom(dc->request_info_list, &temp_request_info, + (GCompareFunc)__consumer_request_compare_cb); + if (list != NULL) { + data = (datacontrol_consumer_request_info *)list->data; + dc->request_info_list = + g_list_remove(dc->request_info_list, list->data); + free(data); + } +} + +static char **__map_get_value_list(int fd, int *value_count) +{ + char **value_list = NULL; + int i = 0; + int count = 0; + int nbytes = 0; + unsigned int nb = 0; + int j; + + if (_read_socket(fd, (char *)&count, sizeof(count), &nb)) { + _LOGE("datacontrol_recv_map_get_value_list : ...from %d: fail to read\n", fd); + return NULL; + } + + if (count < 0 || count > MAX_VALUE_COUNT) { + _LOGE("invalid count %d", count); + return NULL; + } + + value_list = (char **)calloc(count, sizeof(char *)); + if (value_list == NULL) { + _LOGE("Failed to create value list"); + return NULL; + } + + for (i = 0; i < count; i++) { + if (_read_socket(fd, (char *)&nbytes, sizeof(nbytes), &nb)) { + _LOGE("datacontrol_recv_map_get_value_list : ..from %d: fail to read\n", fd); + goto ERROR; + } + if (nbytes < 0 || nbytes > MAX_REQUEST_ARGUMENT_SIZE) { + _LOGE("invalid nbytes %d", nbytes); + goto ERROR; + } + + _LOGI("nbytes : %d %d" , nbytes , nb); + value_list[i] = (char *)calloc(nbytes + 1, sizeof(char)); + + if (_read_socket(fd, value_list[i], nbytes, &nb)) { + _LOGE("datacontrol_recv_map_get_value_list : ...from %d: fail to read\n", fd); + goto ERROR; + } + _LOGI("value_list[i] : %s %d" , value_list[i] , nb); + } + *value_count = count; + + return value_list; + + /* LCOV_EXCL_START */ +ERROR: + if (value_list) { + for (j = 0; j < i; j++) { + if (value_list[j] != NULL) + free(value_list[j]); + } + free(value_list); + } + + return NULL; + /* LCOV_EXCL_STOP */ +} + +void __sql_remove_cursor(resultset_cursor *cursor) +{ + int ret; + + close(cursor->resultset_fd); + if (cursor->resultset_path) { + ret = remove(cursor->resultset_path); + if (ret == -1) + _LOGE("unable to remove map query result file: %d", ret); + free(cursor->resultset_path); + } + if (cursor->row_offset_list) + free(cursor->row_offset_list); + free(cursor); +} + +int __recv_bulk_process(int fd, data_control_bulk_result_data_h *result_data_h) +{ + int bulk_results_size; + guint nb; + int retval = DATA_CONTROL_ERROR_NONE; + int i; + int bulk_result = 0; + char *encode_data = NULL; + int encode_datalen = 0; + bundle *result_data = NULL; + + data_control_bulk_result_data_create(result_data_h); + if (_read_socket(fd, (char *)&bulk_results_size, + sizeof(bulk_results_size), &nb) != DATA_CONTROL_ERROR_NONE) { + retval = DATA_CONTROL_ERROR_IO_ERROR; + _LOGE("read socket fail: bulk_results_size"); + goto out; + } + + _LOGI("##### bulk result size : %d", bulk_results_size); + for (i = 0; i < bulk_results_size; i++) { + if (_read_socket(fd, (char *)&bulk_result, + sizeof(bulk_result), &nb) != DATA_CONTROL_ERROR_NONE) { + retval = DATA_CONTROL_ERROR_IO_ERROR; + _LOGE("read socket fail: bulk_result"); + goto out; + } + _LOGI("##### bulk result : %d", bulk_result); + if (_read_socket(fd, (char *)&encode_datalen, + sizeof(encode_datalen), &nb) != DATA_CONTROL_ERROR_NONE) { + retval = DATA_CONTROL_ERROR_IO_ERROR; + _LOGE("read socket fail: encode_datalen"); + goto out; + } + _LOGI("##### encode_datalen : %d", encode_datalen); + if (encode_datalen <= 0 || + encode_datalen >= MAX_REQUEST_ARGUMENT_SIZE) { + retval = DATA_CONTROL_ERROR_IO_ERROR; + _LOGE("Invalid encode_datalen %d", encode_datalen); + goto out; + } + encode_data = (char *)calloc(encode_datalen, sizeof(char)); + if (encode_data == NULL) { + retval = DATA_CONTROL_ERROR_IO_ERROR; + _LOGE("FAIL to alloc encode data"); + goto out; + } + if (_read_socket(fd, encode_data, encode_datalen, &nb) != + DATA_CONTROL_ERROR_NONE) { + retval = DATA_CONTROL_ERROR_IO_ERROR; + _LOGE("read socket fail: encode_data"); + free(encode_data); + goto out; + } + result_data = + bundle_decode_raw((bundle_raw *)encode_data, encode_datalen); + data_control_bulk_result_data_add(*result_data_h, result_data, + bulk_result); + if (encode_data) { + free(encode_data); + encode_data = NULL; + } + bundle_free(result_data); + } + +out: + return retval; +} + +static int __recv_sql_select_process(bundle *kb, int fd, + resultset_cursor *cursor) +{ + int column_count = 0; + int column_type = 0; + int column_name_len = 0; + char *column_name = NULL; + int total_len_of_column_names = 0; + sqlite3_int64 row_count = 0; + int type; + int size; + void *value = NULL; + sqlite3_int64 i = 0; + int j = 0; + char select_map_file[REQUEST_PATH_MAX] = {0,}; + char *req_id = (char *)bundle_get_val(kb, OSP_K_REQUEST_ID); + int result_fd = 0; + guint nb; + int retval = DATA_CONTROL_ERROR_NONE; + + _LOGI("req_id : %s", req_id); + _LOGI("SELECT RESPONSE"); + + size = snprintf(select_map_file, REQUEST_PATH_MAX, "/run/user/%d/%s%s%s", + getuid(), DATACONTROL_REQUEST_FILE_PREFIX, + (char *)bundle_get_val(kb, AUL_K_CALLER_APPID), req_id); + if (size < 0) { + _LOGE("unable to write formatted output to select_map_file. errno = %d", errno); + retval = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + + _LOGI("select_map_file : %s", select_map_file); + + /* TODO - shoud be changed to solve security concerns */ + result_fd = open(select_map_file, O_RDWR | O_CREAT, 0644); + if (result_fd == -1) { + _LOGE("unable to open insert_map file: %d", errno); + retval = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + + } + cursor->resultset_path = strdup(select_map_file); + if (cursor->resultset_path == NULL) { + _LOGE("Out of memory. can not dup select map file."); + retval = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + cursor->resultset_fd = result_fd; + if (_read_socket(fd, (char *)&column_count, + sizeof(column_count), &nb) != DATA_CONTROL_ERROR_NONE) { + retval = DATA_CONTROL_ERROR_IO_ERROR; + _LOGE("read socket fail: column_count"); + goto out; + } + + /* no data check. */ + if (column_count == DATACONTROL_RESULT_NO_DATA) { + _LOGE("No result"); + close(result_fd); + return DATA_CONTROL_ERROR_NONE; + } + + if (column_count < 0 || column_count > MAX_COLUMN_COUNT) { + retval = DATA_CONTROL_ERROR_IO_ERROR; + LOGE("Invalid column_count %d", column_count); + goto out; + } + + cursor->resultset_col_count = column_count; + _LOGI("column_count : %d", column_count); + + if (write(result_fd, &column_count, sizeof(int)) == -1) { + _LOGE("Writing a column_count to a file descriptor is failed. errno = %d", errno); + retval = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + + cursor->resultset_col_type_offset = sizeof(int); + for (i = 0; i < column_count; i++) { + if (_read_socket(fd, (char *)&column_type, + sizeof(column_type), &nb) != DATA_CONTROL_ERROR_NONE) { + retval = DATA_CONTROL_ERROR_IO_ERROR; + _LOGE("read socket fail: column_type"); + goto out; + } + + _LOGE("column_type : %d", column_type); + if (write(result_fd, &column_type, sizeof(int)) == -1) { + _LOGE("Writing a column_type to a file descriptor is failed. errno = %d", errno); + retval = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + + } + } + + cursor->resultset_col_name_offset = cursor->resultset_col_type_offset + + (cursor->resultset_col_count) * sizeof(int); + for (i = 0; i < column_count; i++) { + + if (_read_socket(fd, (char *)&column_name_len, + sizeof(column_name_len), &nb) != DATA_CONTROL_ERROR_NONE) { + retval = DATA_CONTROL_ERROR_IO_ERROR; + _LOGE("read socket fail: column_name_len"); + goto out; + } + + if (column_name_len < 0 || column_name_len > MAX_COLUMN_SIZE) { + retval = DATA_CONTROL_ERROR_IO_ERROR; + _LOGE("Invalid column_name_len %d", column_name_len); + goto out; + } + + _LOGE("column_name_len : %d", column_name_len); + if (write(result_fd, &column_name_len, sizeof(int)) == -1) { + _LOGE("Writing a column_type to a file descriptor is failed. errno = %d", errno); + retval = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + + column_name = (char *)calloc(column_name_len, sizeof(char)); + if (column_name == NULL) { + _LOGE("Out of memory."); + retval = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + if (_read_socket(fd, (char *)column_name, column_name_len, &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGE("read socket fail: column_name"); + retval = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + + _LOGE("column_name read : %d", nb); + _LOGE("column_name : %s", column_name); + if (write(result_fd, column_name, column_name_len) == -1) { + _LOGE("Writing a column_type to a file descriptor is failed. errno = %d", errno); + retval = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + + free(column_name); + column_name = NULL; + + } + + if (_read_socket(fd, (char *)&total_len_of_column_names, + sizeof(total_len_of_column_names), &nb) + != DATA_CONTROL_ERROR_NONE) { + _LOGE("read socket fail: total_len_of_column_names"); + retval = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + + _LOGE("total_len_of_column_names : %d", total_len_of_column_names); + if (write(result_fd, &total_len_of_column_names, sizeof(int)) == -1) { + _LOGE("Writing a total_len_of_column_names to a file descriptor is failed. errno = %d", errno); + retval = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + + if (_read_socket(fd, (char *)&row_count, + sizeof(row_count), &nb) != DATA_CONTROL_ERROR_NONE) { + _LOGE("read socket fail: row_count"); + retval = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + + if (row_count < 0 || row_count > MAX_ROW_COUNT) { + _LOGE("invalid row_count %lld", row_count); + retval = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + + _LOGE("row_count : %lld", row_count); + if (write(result_fd, &row_count, sizeof(row_count)) == -1) { + _LOGE("Writing a row_count to a file descriptor is failed. errno = %d", errno); + retval = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + + cursor->resultset_row_count = row_count; + cursor->row_offset_list = (off_t *)calloc(row_count, sizeof(off_t)); + if (cursor->row_offset_list == NULL) { + _LOGE("Out of memory. can not alloc row_offset_list."); + goto out; + } + + cursor->row_offset_list[0] = lseek(result_fd, 0, SEEK_CUR); + cursor->resultset_content_offset = cursor->row_offset_list[0]; + + _LOGE("resultset_content_offset : %lld", + (unsigned long long)cursor->resultset_content_offset); + + off_t row_offset = 0; + for (i = 0; i < row_count; i++) { + row_offset = 0; + for (j = 0; j < column_count; j++) { + if (_read_socket(fd, (char *)&type, sizeof(type), &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGE("read socket fail: type"); + retval = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + _LOGE("type : %d", type); + if (write(result_fd, &type, sizeof(int)) == -1) { + _LOGE("Writing a type to a file descriptor is failed. errno = %d", errno); + retval = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + + if (_read_socket(fd, (char *)&size, sizeof(size), &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGE("read socket fail: size"); + retval = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + + _LOGE("size : %d", size); + if (write(result_fd, &size, sizeof(int)) == -1) { + _LOGE("Writing a size to a file descriptor is failed. errno = %d", errno); + retval = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + + if (size > 0 && size < MAX_REQUEST_ARGUMENT_SIZE) { + value = (void *)malloc(sizeof(void) * size); + if (value == NULL) { + _LOGE("Out of mememory"); + retval = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + + if (_read_socket(fd, (char *)value, size, &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGE("read socket fail: value"); + retval = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + _LOGE("value : %s", value); + if (write(result_fd, value, sizeof(void) * size) == -1) { + _LOGE("Writing a value to a file descriptor is failed. errno = %d", errno); + retval = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + + free(value); + value = NULL; + + } + row_offset += sizeof(int) * 2 + size; + + } + if (i + 1 < row_count) + cursor->row_offset_list[i + 1] = + cursor->row_offset_list[i] + row_offset; + } + + return retval; + +out: + if (result_fd != -1) + close(result_fd); + if (column_name) + free(column_name); + if (value) + free(value); + + __sql_remove_cursor(cursor); + return retval; +} + +static void __sql_call_cb(const char *provider_id, int request_id, + datacontrol_request_type type, const char *data_id, + bool provider_result, const char *error, long long insert_rowid, + resultset_cursor *cursor, data_control_bulk_result_data_h bulk_results, + void *data) +{ + _LOGI("__sql_call_cb, dataID !!!: %s", data_id); + + __response_cb_s *_dc = NULL; + data_control_sql_response_cb *sql_callback = NULL; + data_control_bulk_cb bulk_callback = NULL; + + _dc = (__response_cb_s *)data; + sql_callback = (data_control_sql_response_cb *)_dc->sql_response_cb; + bulk_callback = (data_control_bulk_cb)_dc->sql_bulk_insert_cb; + + data_control_h provider = NULL; + _create_data_control_h(&provider); + + _set_provider_id(provider, provider_id); + _set_data_id(provider, data_id); + + switch (type) { + case DATACONTROL_TYPE_SQL_BULK_INSERT: + _LOGI("BULK INSERT"); + if (bulk_callback != NULL) + bulk_callback(request_id, provider, bulk_results, provider_result, + error, _dc->sql_bulk_user_data); + else + _LOGI("No registered sql_callback function"); + + break; + case DATACONTROL_TYPE_SQL_SELECT: + _LOGI("SELECT"); + if (sql_callback != NULL && sql_callback->select_cb != NULL) + sql_callback->select_cb(request_id, provider, + (result_set_cursor) cursor, provider_result, + error, _dc->sql_user_data); + else + _LOGI("No registered sql_callback function"); + + break; + case DATACONTROL_TYPE_SQL_INSERT: + _LOGI("INSERT row_id: %lld", insert_rowid); + if (sql_callback != NULL && sql_callback->insert_cb != NULL) + sql_callback->insert_cb(request_id, provider, insert_rowid, + provider_result, error, _dc->sql_user_data); + else + _LOGI("No registered sql_callback function"); + + break; + case DATACONTROL_TYPE_SQL_UPDATE: + _LOGI("UPDATE"); + if (sql_callback != NULL && sql_callback->update_cb != NULL) + sql_callback->update_cb(request_id, provider, provider_result, + error, _dc->sql_user_data); + else + _LOGI("No registered sql_callback function"); + break; + case DATACONTROL_TYPE_SQL_DELETE: + _LOGI("DELETE"); + if (sql_callback != NULL && sql_callback->delete_cb != NULL) + sql_callback->delete_cb(request_id, provider, provider_result, + error, _dc->sql_user_data); + else + _LOGI("No registered sql_callback function"); + break; + default: + break; + } + + _destroy_data_control_h(provider); +} + +static void __map_call_cb(const char *provider_id, int request_id, + datacontrol_request_type type, const char *data_id, bool provider_result, + const char *error, char **result_value_list, int result_value_count, + data_control_bulk_result_data_h bulk_results, + void *data) +{ + _LOGI("__map_call_cb, dataID: %s", data_id); + + __response_cb_s *_dc = NULL; + data_control_map_response_cb *map_callback = NULL; + data_control_bulk_cb bulk_callback = NULL; + + _dc = (__response_cb_s *)data; + map_callback = (data_control_map_response_cb *)_dc->map_response_cb; + bulk_callback = (data_control_bulk_cb)_dc->map_bulk_add_cb; + + data_control_h provider = NULL; + _create_data_control_h(&provider); + + _set_provider_id(provider, provider_id); + _set_data_id(provider, data_id); + + switch (type) { + case DATACONTROL_TYPE_MAP_BULK_ADD: + _LOGI("ADD VALUE"); + if (bulk_callback != NULL) + bulk_callback(request_id, provider, bulk_results, provider_result, + error, _dc->map_bulk_user_data); + else + _LOGI("No registered map_callback function"); + + break; + case DATACONTROL_TYPE_MAP_GET: + _LOGI("GET VALUE"); + if (map_callback != NULL && map_callback->get_cb != NULL) + map_callback->get_cb(request_id, provider, result_value_list, + result_value_count, provider_result, error, + _dc->map_user_data); + else + _LOGI("No registered map_callback function"); + + break; + case DATACONTROL_TYPE_MAP_SET: + _LOGI("SET VALUE"); + if (map_callback != NULL && map_callback->set_cb != NULL) + map_callback->set_cb(request_id, provider, provider_result, + error, _dc->map_user_data); + else + _LOGI("No registered map_callback function"); + + break; + case DATACONTROL_TYPE_MAP_ADD: + _LOGI("ADD VALUE"); + if (map_callback != NULL && map_callback->add_cb != NULL) + map_callback->add_cb(request_id, provider, provider_result, error, + _dc->map_user_data); + else + _LOGI("No registered map_callback function"); + + break; + case DATACONTROL_TYPE_MAP_REMOVE: + _LOGI("REMOVE VALUE"); + if (map_callback != NULL && map_callback->remove_cb != NULL) + map_callback->remove_cb(request_id, provider, provider_result, + error, _dc->map_user_data); + else + _LOGI("No registered map_callback function"); + + break; + default: + break; + } + + _destroy_data_control_h(provider); +} + +static int __handle_cb(int fd, bundle *b, __response_cb_s *data) +{ + int ret = 0; + int i = 0; + const char **result_list = NULL; + const char *provider_id = NULL; + const char *data_id = NULL; + const char *error_message = NULL; + int result_list_len = 0; + int provider_result = 0; + int value_count = 0; + char **value_list = NULL; + const char *p = NULL; + const char *request_code = NULL; + int request_type = 0; + int request_id = -1; + long long insert_rowid = -1; + data_control_bulk_result_data_h bulk_results = NULL; + resultset_cursor *cursor = NULL; + + _LOGI("__handle_cb, request_type: %d", request_type); + + if (!b) { + _LOGE("the bundle returned from datacontrol-provider-service is null"); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + /* result list */ + result_list = bundle_get_str_array(b, OSP_K_ARG, &result_list_len); + if (!result_list) { + _LOGE("Invalid Bundle: arguement list is null"); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + p = result_list[0]; /* result list[0] = provider_result */ + if (!p) { + _LOGE("Invalid Bundle: provider_result is null"); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + _LOGI("Provider result: %s", p); + + provider_result = atoi(p); + + error_message = result_list[1]; /* result list[1] = error */ + if (!error_message) { + _LOGE("Invalid Bundle: error_message is null"); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + _LOGI("Error message: %s", error_message); + + p = bundle_get_val(b, OSP_K_REQUEST_ID); + if (!p) { + _LOGE("Invalid Bundle: request_id is null"); + } else { + request_id = atoi(p); + } + + _LOGI("Request ID: %d", request_id); + + provider_id = bundle_get_val(b, OSP_K_DATACONTROL_PROVIDER); + if (!provider_id) { + _LOGE("Invalid Bundle: provider_id is null"); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + data_id = bundle_get_val(b, OSP_K_DATACONTROL_DATA); + if (!data_id) { + _LOGE("Invalid Bundle: data_id is null"); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + request_code = bundle_get_val(b, OSP_K_DATACONTROL_REQUEST_TYPE); + if (!request_code) { + _LOGE("Invalid Bundle: data-control request type is null"); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + request_type = atoi(request_code); + _LOGI("Provider ID: %s, Data ID: %s, Operation type: %d", + provider_id, data_id, request_type); + + switch (request_type) { + case DATACONTROL_TYPE_MAP_BULK_ADD: + _LOGI("BULK ADD RESPONSE"); + if (provider_result) { + if (__recv_bulk_process(fd, &bulk_results) + != DATA_CONTROL_ERROR_NONE) { + if (bulk_results) + data_control_bulk_result_data_destroy(bulk_results); + + return DATA_CONTROL_ERROR_IO_ERROR; + } + } + break; + case DATACONTROL_TYPE_MAP_GET: + _LOGI("GET RESPONSE"); + if (provider_result) { + value_list = __map_get_value_list(fd, &value_count); + + if (value_list == NULL && value_count != 0) { + _LOGE("Invalid data: value_list is null"); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + } + break; + case DATACONTROL_TYPE_SQL_BULK_INSERT: + _LOGI("BULK INSERT RESPONSE"); + if (provider_result) { + if (__recv_bulk_process(fd, &bulk_results) + != DATA_CONTROL_ERROR_NONE) { + if (bulk_results) + data_control_bulk_result_data_destroy(bulk_results); + + return DATA_CONTROL_ERROR_IO_ERROR; + } + } + break; + case DATACONTROL_TYPE_SQL_SELECT: + if (provider_result) { + cursor = (resultset_cursor *)calloc(1, sizeof(resultset_cursor)); + if (!cursor) { + _LOGE("failed to get cursor on sql query resultset"); + return DATA_CONTROL_ERROR_IO_ERROR; + } + if (__recv_sql_select_process(b, fd, cursor) + != DATA_CONTROL_ERROR_NONE) + return DATA_CONTROL_ERROR_IO_ERROR; + } + break; + case DATACONTROL_TYPE_SQL_INSERT: + _LOGI("INSERT RESPONSE"); + if (provider_result) { + p = result_list[2]; /* result list[2] */ + if (!p) { + _LOGE("Invalid Bundle: insert row_id is null"); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + insert_rowid = atoll(p); + } + break; + case DATACONTROL_TYPE_SQL_UPDATE: + case DATACONTROL_TYPE_SQL_DELETE: + case DATACONTROL_TYPE_MAP_SET: + case DATACONTROL_TYPE_MAP_ADD: + case DATACONTROL_TYPE_MAP_REMOVE: + _LOGI("MAP_SET or MAP_ADD or MAP_REMOVE or SQL_UPDATE or SQL_DELETE RESPONSE"); + break; + default: + break; + } + + if (request_type >= DATACONTROL_TYPE_MAP_GET && + request_type <= DATACONTROL_TYPE_MAP_BULK_ADD) { + __map_call_cb(provider_id, + request_id, + request_type, + data_id, + provider_result, + error_message, + value_list, + value_count, + bulk_results, + data); + if (value_list) { + for (i = 0; i < value_count; i++) { + if (value_list[i] != NULL) + free(value_list[i]); + } + free(value_list); + } + } else if (request_type >= DATACONTROL_TYPE_SQL_SELECT && + request_type <= DATACONTROL_TYPE_SQL_BULK_INSERT) { + __sql_call_cb( + provider_id, + request_id, + request_type, + data_id, + provider_result, + error_message, + insert_rowid, + cursor, + bulk_results, + data); + if ((request_type == DATACONTROL_TYPE_SQL_SELECT) && (cursor)) + __sql_remove_cursor(cursor); + } + + ret = DATA_CONTROL_ERROR_NONE; + + if (bulk_results) + data_control_bulk_result_data_destroy(bulk_results); + + return ret; +} + +static gboolean __recv_message(GIOChannel *channel, + GIOCondition cond, + gpointer data) +{ + int request_id = -1; + const char *p = NULL; + char *buf = NULL; + int nbytes; + guint nb; + bundle *kb = NULL; + gint fd = g_io_channel_unix_get_fd(channel); + __response_cb_s *_dc; + GList *itr; + datacontrol_consumer_request_info *request_info; + + _LOGI("__recv_message: ...from %d:%s%s%s%s\n", fd, + (cond & G_IO_ERR) ? " ERR" : "", + (cond & G_IO_HUP) ? " HUP" : "", + (cond & G_IO_IN) ? " IN" : "", + (cond & G_IO_PRI) ? " PRI" : ""); + + if (cond & (G_IO_ERR | G_IO_HUP)) + goto error; + + if (cond & G_IO_IN) { + if (_read_socket(fd, (char *)&nbytes, sizeof(nbytes), &nb)) { + _LOGE("Fail to read nbytes from socket"); + goto error; + } + _LOGI("nbytes : %d", nbytes); + + if (nb == 0) { + _LOGE("__recv_message: ...from %d: socket closed\n", fd); + goto error; + } + + _LOGI("__recv_message: ...from %d: %d bytes\n", fd, nbytes); + if (nbytes > 0 && nbytes < MAX_REQUEST_ARGUMENT_SIZE) { + buf = (char *) calloc(nbytes + 1, sizeof(char)); + if (buf == NULL) { + _LOGE("Malloc failed!!"); + goto error; + } + if (_read_socket(fd, buf, nbytes, &nb)) { + _LOGE("Fail to read buf from socket"); + goto error; + } + + if (nb == 0) { + _LOGE("__recv_message: ...from %d: socket closed\n", fd); + goto error; + } + + kb = bundle_decode_raw((bundle_raw *)buf, nbytes); + if (kb == NULL) { + _LOGE("__recv_message: Unable to decode the bundle\n"); + goto error; + } + + p = bundle_get_val(kb, OSP_K_REQUEST_ID); + if (!p) { + _LOGE("Invalid Bundle: request_id is null"); + goto error; + } else { + request_id = atoi(p); + } + + _LOGI("Request ID: %d", request_id); + + + _LOGI("__recv_message: ...from %d: OK\n", fd); + _LOGI("__recv_message: ...caller appid %s: OK\n", + bundle_get_val(kb, AUL_K_CALLER_APPID)); + + if (data) { + if (__handle_cb(fd, kb, data) != DATA_CONTROL_ERROR_NONE) + goto error; + } else { + _LOGE("error: listener information is null"); + goto error; + } + + __remove_request_info(request_id, data); + + if (kb) + bundle_free(kb); + if (buf) + free(buf); + } + } + return TRUE; +error: + /* LCOV_EXCL_START */ + if (kb) + bundle_free(kb); + if (buf) + free(buf); + + if (((__response_cb_s *)data) != NULL) { + _dc = (__response_cb_s *)data; + g_hash_table_remove(__socket_pair_hash, _dc->provider_id); + + itr = g_list_first(_dc->request_info_list); + while (itr != NULL) { + request_info = (datacontrol_consumer_request_info *)itr->data; + + if (request_info->type >= DATACONTROL_TYPE_MAP_GET && + request_info->type <= DATACONTROL_TYPE_MAP_BULK_ADD) { + __map_call_cb(_dc->provider_id, request_info->request_id, + request_info->type, _dc->data_id, false, + "provider IO Error", NULL, 0, NULL, data); + + } + + if (request_info->type >= DATACONTROL_TYPE_SQL_SELECT && + request_info->type <= DATACONTROL_TYPE_SQL_BULK_INSERT) { + __sql_call_cb(_dc->provider_id, request_info->request_id, + request_info->type, _dc->data_id, false, + "provider IO Error", -1, NULL, NULL, data); + } + + itr = g_list_next(itr); + } + if (_dc->request_info_list) { + _LOGI("free request_info_list"); + g_list_free_full(_dc->request_info_list, free); + _dc->request_info_list = NULL; + } + } + return FALSE; + /* LCOV_EXCL_STOP */ +} + +static int __datacontrol_send_async(int sockfd, bundle *kb, void *extra_data, + datacontrol_request_type type, void *data) +{ + bundle_raw *kb_data = NULL; + bundle_raw *extra_kb_data = NULL; + int ret = DATA_CONTROL_ERROR_NONE; + int datalen = 0; + int extra_kb_datalen = 0; + char *buf = NULL; + int total_len = 0; + unsigned int nb = 0; + int i; + int count; + bundle *bulk_data; + data_control_bulk_data_h bulk_data_h = NULL; + bundle_raw *encode_data = NULL; + int encode_datalen = 0; + + LOGD("send async ~~~"); + + bundle_encode_raw(kb, &kb_data, &datalen); + if (kb_data == NULL) { + _LOGE("bundle encode error"); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + if (DATACONTROL_TYPE_SQL_INSERT == type || + DATACONTROL_TYPE_SQL_UPDATE == type) { + bundle_encode_raw((bundle *)extra_data, + &extra_kb_data, &extra_kb_datalen); + if (extra_kb_data == NULL) { + _LOGE("bundle encode error"); + goto out; + } + } + + total_len = sizeof(datalen) + datalen; + if (extra_kb_datalen > 0) + total_len += sizeof(extra_kb_datalen) + extra_kb_datalen; + + /* encoded bundle + encoded bundle size */ + buf = (char *)calloc(total_len, sizeof(char)); + if (buf == NULL) { + bundle_free_encoded_rawdata(&kb_data); + _LOGE("Out of memory."); + goto out; + } + + memcpy(buf, &datalen, sizeof(datalen)); + memcpy(buf + sizeof(datalen), kb_data, datalen); + if (extra_kb_datalen > 0) { + memcpy(buf + sizeof(datalen) + datalen, + &extra_kb_datalen, sizeof(extra_kb_datalen)); + memcpy(buf + sizeof(datalen) + datalen + sizeof(extra_kb_datalen), + extra_kb_data, extra_kb_datalen); + } + + _LOGI("write : %d", total_len); + if (_write_socket(sockfd, buf, total_len, &nb) != DATA_CONTROL_ERROR_NONE) { + _LOGE("write data fail"); + ret = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + + if (DATACONTROL_TYPE_SQL_BULK_INSERT == type || + DATACONTROL_TYPE_MAP_BULK_ADD == type) { + bulk_data_h = (data_control_bulk_data_h)extra_data; + data_control_bulk_data_get_count(bulk_data_h, &count); + + if (_write_socket(sockfd, &count, sizeof(count), &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGE("write bulk count fail"); + ret = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + _LOGI("write bulk count %d ", count); + for (i = 0; i < count; i++) { + data_control_bulk_data_get_data(bulk_data_h, i, &bulk_data); + bundle_encode_raw(bulk_data, &encode_data, &encode_datalen); + if (_write_socket(sockfd, &encode_datalen, sizeof(encode_datalen), + &nb) != DATA_CONTROL_ERROR_NONE) { + _LOGE("write bulk encode_datalen fail"); + ret = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + _LOGI("write encode_datalen %d ", encode_datalen); + + if (_write_socket(sockfd, encode_data, encode_datalen, &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGE("write bulk encode_data fail"); + ret = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + encode_datalen = 0; + bundle_free_encoded_rawdata(&encode_data); + } + } + +out: + if (buf) + free(buf); + bundle_free_encoded_rawdata(&kb_data); + bundle_free_encoded_rawdata(&extra_kb_data); + bundle_free_encoded_rawdata(&encode_data); + + return ret; +} + +int __request_appsvc_run(const char *caller_id, const char *callee_id) +{ + int pid = -1; + int count = 0; + const int TRY_COUNT = 4; + const struct timespec TRY_SLEEP_TIME = { 0, 1000 * 1000 * 1000 }; + bundle *arg_list = bundle_create(); + + if (!arg_list) { + _LOGE("unable to create bundle: %d", errno); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } + + appsvc_set_operation(arg_list, APPSVC_OPERATION_DEFAULT); + appsvc_set_appid(arg_list, callee_id); + bundle_add_str(arg_list, OSP_K_CALLER_TYPE, OSP_V_CALLER_TYPE_OSP); + bundle_add_str(arg_list, OSP_K_LAUNCH_TYPE, OSP_V_LAUNCH_TYPE_DATACONTROL); + bundle_add_str(arg_list, AUL_K_CALLER_APPID, caller_id); + bundle_add_str(arg_list, AUL_K_CALLEE_APPID, callee_id); + bundle_add_str(arg_list, AUL_K_NO_CANCEL, "1"); + _LOGI("caller_id %s, callee_id %s", caller_id, callee_id); + + /* For DataControl CAPI */ + bundle_add_str(arg_list, AUL_K_DATA_CONTROL_TYPE, "CORE"); + + do { + pid = appsvc_run_service(arg_list, 0, NULL, NULL); + if (pid >= 0) { + _LOGI("Launch the provider app successfully: %d", pid); + bundle_free(arg_list); + break; + } else if (pid == APPSVC_RET_EINVAL) { + _LOGE("not able to launch service: %d", pid); + bundle_free(arg_list); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + count++; + + nanosleep(&TRY_SLEEP_TIME, 0); + } while (count < TRY_COUNT); + + if (count >= TRY_COUNT) { + bundle_free(arg_list); + _LOGE("unable to launch service: %d", pid); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + return DATA_CONTROL_ERROR_NONE; +} + +void _bundle_foreach_check_arg_size_cb(const char *key, const int type, + const bundle_keyval_t *kv, void *arg_size) +{ + char *value = NULL; + size_t value_len = 0; + bundle_keyval_get_basic_val((bundle_keyval_t *)kv, (void **)&value, &value_len); + + arg_size += (strlen(key) + value_len) * sizeof(wchar_t); + return; +} + +int _write_socket(int fd, void *buffer, unsigned int nbytes, + unsigned int *bytes_write) +{ + unsigned int left = nbytes; + gsize nb; + int retry_cnt = 0; + + *bytes_write = 0; + while (left && (retry_cnt < MAX_RETRY)) { + nb = write(fd, buffer, left); + _LOGI("_write_socket: ...from %d: nb %d left %d\n", fd, nb, left - nb); + + if (nb == -1) { + if (errno == EINTR) { + _LOGE("_write_socket: EINTR error continue ..."); + retry_cnt++; + continue; + } + _LOGE("_write_socket: ...error fd %d: errno %d\n", fd, errno); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + left -= nb; + buffer += nb; + *bytes_write += nb; + retry_cnt = 0; + } + + return DATA_CONTROL_ERROR_NONE; +} + +int _read_socket(int fd, char *buffer, unsigned int nbytes, + unsigned int *bytes_read) +{ + unsigned int left = nbytes; + gsize nb; + int retry_cnt = 0; + const struct timespec TRY_SLEEP_TIME = { 0, 500 * 1000 * 1000 }; + + *bytes_read = 0; + while (left && (retry_cnt < MAX_RETRY)) { + nb = read(fd, buffer, left); + _LOGI("_read_socket: ...from %d: nb %d left %d\n", fd, nb, left - nb); + if (nb == 0) { + _LOGE("_read_socket: ...read EOF, socket closed %d: nb %d\n", fd, nb); + return DATA_CONTROL_ERROR_IO_ERROR; + } else if (nb == -1) { + /* wrt(nodejs) could change socket to none-blocking socket :-( */ + if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { + _LOGE("_read_socket: %d errno, sleep and retry ...", errno); + retry_cnt++; + nanosleep(&TRY_SLEEP_TIME, 0); + continue; + } + _LOGE("_read_socket: ...error fd %d: errno %d\n", fd, errno); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + left -= nb; + buffer += nb; + *bytes_read += nb; + retry_cnt = 0; + } + return DATA_CONTROL_ERROR_NONE; +} + +void _socket_info_free(gpointer socket) +{ + GError *error = NULL; + datacontrol_socket_info *socket_info = (datacontrol_socket_info *)socket; + + if (socket_info != NULL) { + if (socket_info->gio_read != NULL) { + _LOGE("shutdown socketpair !!!! %d ", socket_info->socket_fd); + g_io_channel_shutdown(socket_info->gio_read, TRUE, &error); + if (error) { + _LOGE("g_io_channel_shutdown error : %s", error->message); + g_error_free(error); + } + g_io_channel_unref(socket_info->gio_read); + socket_info->gio_read = NULL; + } + if (socket_info->g_src_id != 0) { + g_source_remove(socket_info->g_src_id); + socket_info->g_src_id = 0; + } + free(socket_info); + socket_info = NULL; + } + +} + +int _add_watch_on_socket_info(const char *caller_id, + const char *callee_id, const char *type, const char *provider_id, + const char *data_type, GIOFunc cb, void *data, + datacontrol_socket_info **socket_info) +{ + char err_buf[ERR_BUFFER_SIZE]; + int socketpair = 0; + int g_src_id; + int ret; + + datacontrol_socket_info *_socket_info = NULL; + bundle *sock_bundle = bundle_create(); + bundle_add_str(sock_bundle, AUL_K_CALLER_APPID, caller_id); + bundle_add_str(sock_bundle, AUL_K_CALLEE_APPID, callee_id); + bundle_add_str(sock_bundle, "DATA_CONTROL_TYPE", type); + _LOGI("type : %s", type); + if (provider_id) + bundle_add_str(sock_bundle, OSP_K_DATACONTROL_PROVIDER, provider_id); + if (data_type) + bundle_add_str(sock_bundle, "DATA_CONTROL_DATA_TYPE", data_type); -#include "data_control_internal.h" + ret = aul_request_data_control_socket_pair(sock_bundle, &socketpair); + bundle_free(sock_bundle); + if (ret != AUL_R_OK) { + if (ret != AUL_R_EILLACC) { + _LOGE("Permission denied. Consumer need privilege."); + return DATA_CONTROL_ERROR_PERMISSION_DENIED; + } -#define SMACK_LABEL_LEN 255 + return DATA_CONTROL_ERROR_IO_ERROR; + } -#ifdef LOG_TAG -#undef LOG_TAG -#endif + _LOGI("consumer socket pair : %d", socketpair); -#define LOG_TAG "CAPI_APPFW_DATA_CONTROL" + if (socketpair > 0) { + GIOChannel *gio_read = NULL; + gio_read = g_io_channel_unix_new(socketpair); + if (!gio_read) { + _LOGE("Error is %s\n", strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } -#define _LOGE(fmt, arg...) LOGE(fmt, ##arg) -#define _LOGD(fmt, arg...) LOGD(fmt, ##arg) + g_src_id = g_io_add_watch(gio_read, G_IO_IN | G_IO_HUP, + cb, data); + if (g_src_id == 0) { + g_io_channel_unref(gio_read); + _LOGE("fail to add watch on socket"); + return DATA_CONTROL_ERROR_IO_ERROR; + } -#define CHECKED_CACHE_SIZE 10 + _socket_info = + (datacontrol_socket_info *)calloc(1, sizeof(datacontrol_socket_info)); + if (_socket_info == NULL) { + g_io_channel_unref(gio_read); + g_source_remove(g_src_id); + _LOGE("fail to calloc socket_info"); + return DATA_CONTROL_ERROR_IO_ERROR; + } + _socket_info->socket_fd = socketpair; + _socket_info->gio_read = gio_read; + _socket_info->g_src_id = g_src_id; + _LOGI("Watch on socketpair done."); + } else { + _LOGE("fail to get socket pair"); + return DATA_CONTROL_ERROR_IO_ERROR; + } -struct datacontrol_cert_info { - cert_status_type sql; - cert_status_type map; - time_t time; -}; + *socket_info = _socket_info; + return DATA_CONTROL_ERROR_NONE; +} -static GHashTable *__checked_provider_hash; -static GHashTable *__checked_consumer_hash; +int _datacontrol_create_request_id(void) +{ + static int id = 0; + g_atomic_int_inc(&id); + + return id; +} + +int _request_provider(data_control_h provider, datacontrol_request_type type, + bundle *request_data, void *extra_data, int request_id) +{ + char *app_id = NULL; + void *data = NULL; + char *data_type = NULL; + int ret = DATA_CONTROL_ERROR_NONE; + char caller_app_id[255]; + char datacontrol_request_operation[MAX_LEN_DATACONTROL_REQ_TYPE] = {0, }; + char req_id[32] = {0,}; + int count = 0; + const int TRY_COUNT = 2; + const struct timespec TRY_SLEEP_TIME = { 0, 1000 * 1000 * 1000 }; + bundle *send_data; + + _LOGI("Data control request, type: %d, request id: %d", type, request_id); + + if (__socket_pair_hash == NULL) + __socket_pair_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + free, _socket_info_free); + + if (!__response_table) { + _LOGE("The listener tree is empty"); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + if (type >= DATACONTROL_TYPE_MAP_GET && + type <= DATACONTROL_TYPE_MAP_BULK_ADD) { + data_type = "Map"; + } else if (type >= DATACONTROL_TYPE_SQL_SELECT && + type <= DATACONTROL_TYPE_SQL_BULK_INSERT) { + data_type = "Sql"; + } else { + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + __response_cb_s *_dc_returned = g_hash_table_lookup(__response_table, + provider->provider_id); + if (!_dc_returned) { + _LOGE("Finding the datacontrol in the listener table is failed."); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + app_id = _dc_returned->app_id; + datacontrol_consumer_request_info *request_info = + (datacontrol_consumer_request_info *)calloc( + sizeof(datacontrol_consumer_request_info), 1); + request_info->request_id = request_id; + request_info->type = type; + _dc_returned->request_info_list = + g_list_append(_dc_returned->request_info_list, request_info); + data = _dc_returned; + + _LOGI("datacontrol appid: %s", _dc_returned->app_id); + + pid_t pid = getpid(); + if (aul_app_get_appid_bypid(pid, caller_app_id, sizeof(caller_app_id)) != 0) { + _LOGE("Failed to get appid by pid(%d).", pid); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + send_data = bundle_dup(request_data); + if (send_data == NULL) { + _LOGE("fail to alloc result_data"); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } + + bundle_add_str(send_data, OSP_K_DATACONTROL_PROTOCOL_VERSION, OSP_V_VERSION_2_1_0_3); + bundle_add_str(send_data, AUL_K_CALLER_APPID, caller_app_id); + + snprintf(datacontrol_request_operation, MAX_LEN_DATACONTROL_REQ_TYPE, "%d", (int)(type)); + bundle_add_str(send_data, OSP_K_DATACONTROL_REQUEST_TYPE, datacontrol_request_operation); + + snprintf(req_id, 32, "%d", request_id); + bundle_add_str(send_data, OSP_K_REQUEST_ID, req_id); + + _LOGI("caller_id %s, app_id %s", caller_app_id, app_id); + + do { + datacontrol_socket_info *socket_info = + g_hash_table_lookup(__socket_pair_hash, provider->provider_id); + if (socket_info == NULL) { + ret = _add_watch_on_socket_info(caller_app_id, app_id, + "consumer", provider->provider_id, data_type, + __recv_message, data, + &socket_info); + if (ret != DATA_CONTROL_ERROR_NONE) { + bundle_free(send_data); + return ret; + } + + ret = __request_appsvc_run(caller_app_id, app_id); + if (ret != DATA_CONTROL_ERROR_NONE) { + bundle_free(send_data); + return ret; + } + + g_hash_table_insert(__socket_pair_hash, + strdup(provider->provider_id), socket_info); + } + + _LOGI("send data from consumer !!!"); + ret = __datacontrol_send_async(socket_info->socket_fd, send_data, + extra_data, type, NULL); + if (ret != DATA_CONTROL_ERROR_NONE) + g_hash_table_remove(__socket_pair_hash, provider->provider_id); + else + break; + count++; + nanosleep(&TRY_SLEEP_TIME, 0); + } while (ret != DATA_CONTROL_ERROR_NONE && count < TRY_COUNT); + + bundle_free(send_data); + return ret; +} + +int _register_response_cb(data_control_h provider, void *response_cb, + datacontrol_request_type type, void *user_data) +{ + int ret; + char *app_id = NULL; + char *access = NULL; + int access_info = ACCESS_INFO_NONE; + char *data_type; + __response_cb_s *_dc_temp; + + if (!response_cb || !provider || !provider->provider_id || !provider->data_id) + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + + if (__response_table == NULL) + __initialize(); + + if (type >= DATACONTROL_TYPE_MAP_GET && + type <= DATACONTROL_TYPE_MAP_BULK_ADD) { + data_type = "Map"; + } else if (type >= DATACONTROL_TYPE_SQL_SELECT && + type <= DATACONTROL_TYPE_SQL_BULK_INSERT) { + data_type = "Sql"; + } else { + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + ret = pkgmgrinfo_appinfo_usr_get_datacontrol_info(provider->provider_id, + data_type, getuid(), &app_id, &access); + if (ret != PMINFO_R_OK) { + _LOGE("unable to get %s data control information: %d", data_type, ret); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + if (strcasecmp(access, "readonly") == 0) + access_info = ACCESS_INFO_READONLY; + else if (strcasecmp(access, "writeonly") == 0) + access_info = ACCESS_INFO_WRITEONLY; + else if (strcasecmp(access, "readwrite") == 0) + access_info = ACCESS_INFO_READ_WRITE; + + _LOGI("data control provider appid = %s", app_id); + + _dc_temp = g_hash_table_lookup(__response_table, provider->provider_id); + + if (_dc_temp == NULL) { + _dc_temp = (__response_cb_s *)calloc(1, sizeof(__response_cb_s)); + if (!_dc_temp) { + _LOGE("unable to create a temporary data control"); + ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY; + goto EXCEPTION; + } + + _dc_temp->provider_id = strdup(provider->provider_id); + if (!_dc_temp->provider_id) { + _LOGE("unable to assign provider_id to data control: %d", errno); + ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY; + goto EXCEPTION; + } + + _dc_temp->data_id = strdup(provider->data_id); + if (!_dc_temp->data_id) { + _LOGE("unable to assign data_id to data control: %d", errno); + ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY; + goto EXCEPTION; + } + + _dc_temp->app_id = strdup(app_id); + if (!_dc_temp->app_id) { + _LOGE("unable to assign app_id to data control: %d", errno); + ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY; + goto EXCEPTION; + } + + g_hash_table_insert(__response_table, + strdup(provider->provider_id), _dc_temp); + } + + if (type >= DATACONTROL_TYPE_MAP_GET && + type < DATACONTROL_TYPE_MAP_BULK_ADD) { + if (_dc_temp->map_response_cb == NULL) { + _dc_temp->map_response_cb = + (data_control_map_response_cb *)calloc( + 1, sizeof(data_control_map_response_cb)); + if (!_dc_temp->map_response_cb) { + _LOGE("unable to create a response_cb of temporary"); + ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY; + goto EXCEPTION; + } + } + + memcpy(_dc_temp->map_response_cb, response_cb, + sizeof(data_control_map_response_cb)); + _dc_temp->map_access_info = access_info; + _dc_temp->map_user_data = user_data; + } else if (type == DATACONTROL_TYPE_MAP_BULK_ADD) { + _dc_temp->map_bulk_add_cb = (data_control_bulk_cb)response_cb; + _dc_temp->map_access_info = access_info; + _dc_temp->map_bulk_user_data = user_data; + } else if (type >= DATACONTROL_TYPE_SQL_SELECT && + type < DATACONTROL_TYPE_SQL_BULK_INSERT) { + if (_dc_temp->sql_response_cb == NULL) { + _dc_temp->sql_response_cb = + (data_control_sql_response_cb *)calloc( + 1, sizeof(data_control_sql_response_cb)); + if (!_dc_temp->sql_response_cb) { + _LOGE("unable to create a response_cb of temporary"); + ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY; + goto EXCEPTION; + } + } + + memcpy(_dc_temp->sql_response_cb, response_cb, + sizeof(data_control_sql_response_cb)); + + _dc_temp->sql_access_info = access_info; + _dc_temp->sql_user_data = user_data; + } else if (type == DATACONTROL_TYPE_SQL_BULK_INSERT) { + _dc_temp->sql_bulk_insert_cb = (data_control_bulk_cb)response_cb; + _dc_temp->sql_access_info = access_info; + _dc_temp->sql_bulk_user_data = user_data; + } + + ret = DATA_CONTROL_ERROR_NONE; + + /* LCOV_EXCL_START */ +EXCEPTION: + if (access) + free(access); + if (app_id) + free(app_id); + if (ret != DATA_CONTROL_ERROR_NONE && _dc_temp) { + __free_response_cb((gpointer)_dc_temp); + } + + return ret; + /* LCOV_EXCL_STOP */ +} + +int _unregister_response_cb(data_control_h provider, + datacontrol_request_type type) +{ + if (provider == NULL) + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + + __response_cb_s *_dc_temp = g_hash_table_lookup(__response_table, + provider->provider_id); + if (_dc_temp == NULL) + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + + switch (type) { + case DATACONTROL_TYPE_MAP_GET: + case DATACONTROL_TYPE_MAP_ADD: + case DATACONTROL_TYPE_MAP_SET: + case DATACONTROL_TYPE_MAP_REMOVE: + if (_dc_temp->map_response_cb) { + free(_dc_temp->map_response_cb); + _dc_temp->map_response_cb = NULL; + } + break; + case DATACONTROL_TYPE_MAP_BULK_ADD: + _dc_temp->map_bulk_add_cb = NULL; + break; + case DATACONTROL_TYPE_SQL_SELECT: + case DATACONTROL_TYPE_SQL_INSERT: + case DATACONTROL_TYPE_SQL_UPDATE: + case DATACONTROL_TYPE_SQL_DELETE: + if (_dc_temp->sql_response_cb) { + free(_dc_temp->sql_response_cb); + _dc_temp->sql_response_cb = NULL; + } + break; + case DATACONTROL_TYPE_SQL_BULK_INSERT: + _dc_temp->sql_bulk_insert_cb = NULL;; + break; + default: + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + if (!_dc_temp->map_response_cb && + !_dc_temp->sql_response_cb && + !_dc_temp->map_bulk_add_cb && + !_dc_temp->sql_bulk_insert_cb) { + + g_hash_table_remove(__response_table, provider->provider_id); + g_hash_table_remove(__socket_pair_hash, provider->provider_id); + } + + return DATA_CONTROL_ERROR_NONE; +} + + +char *_get_encoded_db_path() +{ + char db_path[PATH_MAX]; + char *dup_db_path = NULL; + char *encoded_appid = NULL; + char provider_appid[255]; + if (aul_app_get_appid_bypid(getpid(), provider_appid, sizeof(provider_appid)) != 0) { + _LOGE("Failed to get appid by pid"); + return NULL; + } + + encoded_appid = + g_compute_checksum_for_string(G_CHECKSUM_MD5, provider_appid, -1); + snprintf(db_path, sizeof(db_path), "/run/user/%d/%s%s.db", + getuid(), DATA_CONTROL_DB_NAME_PREFIX, encoded_appid); + dup_db_path = strdup(db_path); + if (dup_db_path == NULL) + _LOGE("fail to dup db path. out of memory."); + + free(encoded_appid); + _LOGI("dup db path : %s ", dup_db_path); + return dup_db_path; +} -int datacontrol_check_privilege(privilege_type check_type) +char *_get_encoded_path(data_control_h provider, char *consumer_appid) +{ + int prefix_len = strlen(DATA_CONTROL_DBUS_PATH_PREFIX); + char *encoded_path; + char *full_path; + int path_len = strlen(provider->provider_id) + + strlen(provider->data_id) + strlen(consumer_appid) + 3; + int full_path_len = path_len + prefix_len; + char *path = (char *)calloc(path_len, sizeof(char)); + if (path == NULL) { + _LOGE("path calloc failed"); + return 0; + } + + snprintf(path, path_len, "%s_%s_%s", provider->provider_id, + provider->data_id, consumer_appid); + encoded_path = g_compute_checksum_for_string(G_CHECKSUM_MD5, path, -1); + + full_path = (char *)calloc(full_path_len, sizeof(char)); + snprintf(full_path, full_path_len, "%s%s", + DATA_CONTROL_DBUS_PATH_PREFIX, encoded_path); + + free(path); + free(encoded_path); + _LOGI("full path : %s ", full_path); + return full_path; +} + +int _dbus_init() +{ + int ret = DATA_CONTROL_ERROR_NONE; + GError *error = NULL; + + if (_gdbus_conn == NULL) { + _gdbus_conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error); + + if (_gdbus_conn == NULL) { + if (error != NULL) { + _LOGE("Failed to get dbus [%s]", error->message); + g_error_free(error); + } + return DATA_CONTROL_ERROR_IO_ERROR; + } + ret = DATA_CONTROL_ERROR_NONE; + } + return ret; +} + +GDBusConnection *_get_dbus_connection() +{ + int result = _dbus_init(); + if (result != DATA_CONTROL_ERROR_NONE) { + _LOGE("Can't init dbus %d", result); + return NULL; + } + return _gdbus_conn; +} + +int _dbus_signal_init(int *monitor_id, char *path, GDBusSignalCallback callback) +{ + int id; + id = g_dbus_connection_signal_subscribe( + _get_dbus_connection(), + NULL, + DATA_CONTROL_INTERFACE_NAME, + NULL, + path, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + callback, + NULL, + NULL); + + _LOGI("subscribe id : %d", id); + if (id == 0) { + _LOGE("Failed to _register_noti_dbus_interface"); + return DATA_CONTROL_ERROR_IO_ERROR; + } else { + *monitor_id = id; + } + + return DATA_CONTROL_ERROR_NONE; +} + +int _check_privilege(privilege_type check_type) { cynara *p_cynara = NULL; @@ -67,21 +1885,21 @@ int datacontrol_check_privilege(privilege_type check_type) ret = cynara_initialize(&p_cynara, NULL); if (ret != CYNARA_API_SUCCESS) { - LOGE("cannot init cynara [%d] failed!", ret); + _LOGE("cannot init cynara [%d] failed!", ret); ret = DATA_CONTROL_ERROR_IO_ERROR; goto out; } fd = open("/proc/self/attr/current", O_RDONLY); if (fd < 0) { - LOGE("open [%d] failed!", errno); + _LOGE("open [%d] failed!", errno); ret = DATA_CONTROL_ERROR_IO_ERROR; goto out; } ret = read(fd, subject_label, SMACK_LABEL_LEN); if (ret < 0) { - LOGE("read [%d] failed!", errno); + _LOGE("read [%d] failed!", errno); close(fd); ret = DATA_CONTROL_ERROR_IO_ERROR; goto out; @@ -92,7 +1910,7 @@ int datacontrol_check_privilege(privilege_type check_type) ret = cynara_check(p_cynara, subject_label, client_session, uid, "http://tizen.org/privilege/datasharing"); if (ret != CYNARA_API_ACCESS_ALLOWED) { - LOGE("cynara access check [%d] failed!", ret); + _LOGE("cynara access check [%d] failed!", ret); ret = DATA_CONTROL_ERROR_PERMISSION_DENIED; goto out; } @@ -101,7 +1919,7 @@ int datacontrol_check_privilege(privilege_type check_type) ret = cynara_check(p_cynara, subject_label, client_session, uid, "http://tizen.org/privilege/appmanager.launch"); if (ret != CYNARA_API_ACCESS_ALLOWED) { - LOGE("cynara access check [%d] failed!", ret); + _LOGE("cynara access check [%d] failed!", ret); ret = DATA_CONTROL_ERROR_PERMISSION_DENIED; goto out; } @@ -117,53 +1935,7 @@ out: return ret; } -static char *__get_victim(GHashTable *hash) -{ - GHashTableIter iter; - gpointer key; - gpointer value; - time_t time = 0; - char *victim_key = NULL; - - g_hash_table_iter_init(&iter, hash); - - while (g_hash_table_iter_next(&iter, &key, &value)) { - struct datacontrol_cert_info *info = (struct datacontrol_cert_info *)value; - if (time == 0 || time > info->time) { - time = info->time; - victim_key = key; - } - } - - return victim_key; -} - -static void _insert_hash(GHashTable *hash, const char *key, - bool is_map, cert_status_type status) -{ - struct datacontrol_cert_info *cert_info; - char *victim_key; - - if (g_hash_table_size(hash) > CHECKED_CACHE_SIZE) { - victim_key = __get_victim(hash); - if (victim_key) - g_hash_table_remove(hash, victim_key); - } - - cert_info = (struct datacontrol_cert_info *)calloc(1, - sizeof(struct datacontrol_cert_info)); - - if (is_map) - cert_info->map = status; - else - cert_info->sql = status; - - time(&cert_info->time); - - g_hash_table_insert(hash, strdup(key), cert_info); -} - -int datacontrol_check_cert(const char *provider_id, bool is_map, +int _check_cert(const char *provider_id, bool is_map, const char *consumer_appid) { int ret; @@ -178,11 +1950,13 @@ int datacontrol_check_cert(const char *provider_id, bool is_map, if (consumer_appid == NULL) { if (__checked_provider_hash == NULL) - __checked_provider_hash = g_hash_table_new_full(g_str_hash, g_str_equal, free, free); + __checked_provider_hash = g_hash_table_new_full(g_str_hash, + g_str_equal, free, free); hash_table = __checked_provider_hash; } else { if (__checked_consumer_hash == NULL) - __checked_consumer_hash = g_hash_table_new_full(g_str_hash, g_str_equal, free, free); + __checked_consumer_hash = g_hash_table_new_full(g_str_hash, + g_str_equal, free, free); hash_table = __checked_consumer_hash; } @@ -202,7 +1976,7 @@ int datacontrol_check_cert(const char *provider_id, bool is_map, ret = pkgmgrinfo_appinfo_usr_get_datacontrol_trusted_info(provider_id, is_map ? "Map" : "Sql", getuid(), &provider_appid, &is_trusted); if (ret != PMINFO_R_OK) { - LOGE("unable to get data control information: %d", ret); + _LOGE("unable to get data control information: %d", ret); return DATA_CONTROL_ERROR_IO_ERROR; } @@ -210,7 +1984,7 @@ int datacontrol_check_cert(const char *provider_id, bool is_map, if (is_update) *status = CERT_MATCH; else - _insert_hash(hash_table, provider_id, is_map, CERT_MATCH); + __insert_hash(hash_table, provider_id, is_map, CERT_MATCH); free(provider_appid); return DATA_CONTROL_ERROR_NONE; } @@ -218,7 +1992,7 @@ int datacontrol_check_cert(const char *provider_id, bool is_map, if (!consumer_appid) { ret = aul_app_get_appid_bypid(getpid(), appid, sizeof(appid)); if (ret != AUL_R_OK) { - LOGE("Failed to get appid: %d", ret); + _LOGE("Failed to get appid: %d", ret); free(provider_appid); return DATA_CONTROL_ERROR_IO_ERROR; } @@ -228,17 +2002,17 @@ int datacontrol_check_cert(const char *provider_id, bool is_map, ret = pkgmgrinfo_pkginfo_compare_usr_app_cert_info(provider_appid, consumer_appid, getuid(), &res); if (ret < 0) { - LOGE("certificate check [%d] failed!", ret); + _LOGE("certificate check [%d] failed!", ret); free(provider_appid); return DATA_CONTROL_ERROR_IO_ERROR; } if (res != PMINFO_CERT_COMPARE_MATCH) { - LOGE("certificate mismatch. provider : %s consumer %s", + _LOGE("certificate mismatch. provider : %s consumer %s", provider_appid, consumer_appid); if (is_update) *status = CERT_MISMATCH; else - _insert_hash(hash_table, provider_id, is_map, CERT_MISMATCH); + __insert_hash(hash_table, provider_id, is_map, CERT_MISMATCH); free(provider_appid); return DATA_CONTROL_ERROR_PERMISSION_DENIED; } @@ -246,29 +2020,104 @@ int datacontrol_check_cert(const char *provider_id, bool is_map, if (is_update) *status = CERT_MATCH; else - _insert_hash(hash_table, provider_id, is_map, CERT_MATCH); + __insert_hash(hash_table, provider_id, is_map, CERT_MATCH); free(provider_appid); return DATA_CONTROL_ERROR_NONE; } -int convert_to_tizen_error(datacontrol_error_e error) +int _create_data_control_h(data_control_h *provider) { - switch (error) { - case DATACONTROL_ERROR_NONE: - return DATA_CONTROL_ERROR_NONE; - case DATACONTROL_ERROR_INVALID_PARAMETER: + struct data_control_s *request; + + if (provider == NULL) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - case DATACONTROL_ERROR_OUT_OF_MEMORY: + + request = (struct data_control_s *)calloc(1, sizeof(struct data_control_s)); + if (request == NULL) return DATA_CONTROL_ERROR_OUT_OF_MEMORY; - case DATACONTROL_ERROR_IO_ERROR: - return DATA_CONTROL_ERROR_IO_ERROR; - case DATACONTROL_ERROR_PERMISSION_DENIED: - return DATA_CONTROL_ERROR_PERMISSION_DENIED; - case DATACONTROL_ERROR_MAX_EXCEEDED: - return DATA_CONTROL_ERROR_MAX_EXCEEDED; - default: - return error; + + *provider = request; + + return DATA_CONTROL_ERROR_NONE; +} + +int _destroy_data_control_h(data_control_h provider) +{ + if (provider == NULL) + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + + if (provider->provider_id != NULL) + free(provider->provider_id); + + if (provider->data_id != NULL) + free(provider->data_id); + + free(provider); + return DATA_CONTROL_ERROR_NONE; +} + +int _set_provider_id(data_control_h provider, const char *provider_id) +{ + if (provider == NULL || provider_id == NULL) + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + + if (provider->provider_id != NULL) + free(provider->provider_id); + + provider->provider_id = strdup(provider_id); + if (provider->provider_id == NULL) + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + + return DATA_CONTROL_ERROR_NONE; +} + +int _get_provider_id(data_control_h provider, char **provider_id) +{ + if (provider == NULL || provider_id == NULL) + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + + if (provider->provider_id != NULL) { + *provider_id = strdup(provider->provider_id); + if (*provider_id == NULL) + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + + } else { + *provider_id = NULL; + } + + return DATA_CONTROL_ERROR_NONE; +} + +int _set_data_id(data_control_h provider, const char *data_id) +{ + if (provider == NULL || data_id == NULL) + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + + if (provider->data_id != NULL) + free(provider->data_id); + + provider->data_id = strdup(data_id); + if (provider->data_id == NULL) + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + + return DATA_CONTROL_ERROR_NONE; +} + +int _get_data_id(data_control_h provider, char **data_id) +{ + if (provider == NULL || data_id == NULL) + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + + if (provider->data_id != NULL) { + *data_id = strdup(provider->data_id); + if (*data_id == NULL) + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + + } else { + *data_id = NULL; } + + return DATA_CONTROL_ERROR_NONE; } diff --git a/src/data_control_internal.h b/src/data_control_internal.h new file mode 100755 index 0000000..c77540e --- /dev/null +++ b/src/data_control_internal.h @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2013 - 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. + */ + +/** + * @file data-control-internal.h + * @brief This is the header file for private keys of the data-control. + */ +#include +#include +#include +#include "data_control_types.h" + +#ifndef _APPFW_DATA_CONTROL_INTERNAL_H_ +#define _APPFW_DATA_CONTROL_INTERNAL_H_ + +#ifdef __GNUC__ +# ifndef EXPORT_API +# define EXPORT_API __attribute__((visibility("default"))) +# endif +#else +# define EXPORT_API +#endif + +#undef LOG_TAG +#ifndef LOG_TAG +#define LOG_TAG "DATA_CONTROL" +#endif + +#define MAX_LEN_DATACONTROL_REQ_TYPE 8 +#define MAX_LEN_DATACONTROL_COLUMN_COUNT 8 + +#define OSP_K_LAUNCH_TYPE "__OSP_LAUNCH_TYPE__" +#define OSP_K_ARG "__OSP_ARGS__" +#define OSP_K_REQUEST_ID "__OSP_REQUEST_ID__" +#define OSP_K_DATACONTROL_PROVIDER "__OSP_DATACONTROL_PROVIDER__" +#define OSP_K_DATACONTROL_DATA "__OSP_DATACONTROL_DATA__" +#define OSP_K_DATACONTROL_REQUEST_TYPE "__OSP_DATACONTROL_REQUEST_TYPE__" +#define OSP_K_DATACONTROL_PROTOCOL_VERSION "__OSP_DATACONTROL_PROTOCOL_VERSION__" +#define OSP_K_CALLER_TYPE "__OSP_CALLER_TYPE__" +#define OSP_K_DATACONTROL_UNIQUE_NAME "__OSP_DATACONTROL_UNIQUE_NAME__" +#define OSP_K_DATA_CHANGED_CALLBACK_ID "__OSP_DATA_CHANGED_CALLBACK_ID__" + +#define DATACONTROL_SELECT_STATEMENT "DATACONTROL_SELECT_STATEMENT" + +#define DATACONTROL_EMPTY "NULL" +#define DATACONTROL_SELECT_EXTRA_COUNT 6 /* data id, column count, where, order, page, per_page */ +#define DATACONTROL_RESULT_NO_DATA -1 + +#define OSP_V_LAUNCH_TYPE_DATACONTROL "datacontrol" +#define OSP_V_VERSION_2_1_0_3 "ver_2.1.0.3" +#define OSP_V_CALLER_TYPE_OSP "osp" +#define DATACONTROL_REQUEST_FILE_PREFIX "datacontrol.request." + +#define MAX_REQUEST_ARGUMENT_SIZE 1048576 /* 1MB */ +#define MAX_ROW_COUNT 1024 +#define MAX_COLUMN_SIZE 512 +#define MAX_COLUMN_COUNT 32767 /* Base on sqlite3 maximum column count */ +#define MAX_VALUE_COUNT 1024 + +/** + * @brief Enumerations of different type of data control requests. + */ +typedef enum +{ + DATACONTROL_TYPE_ERROR = -1, + DATACONTROL_TYPE_UNDEFINED, + DATACONTROL_TYPE_SQL_SELECT, + DATACONTROL_TYPE_SQL_INSERT, + DATACONTROL_TYPE_SQL_UPDATE, + DATACONTROL_TYPE_SQL_DELETE, + DATACONTROL_TYPE_SQL_BULK_INSERT, + DATACONTROL_TYPE_MAP_GET, + DATACONTROL_TYPE_MAP_SET, + DATACONTROL_TYPE_MAP_ADD, + DATACONTROL_TYPE_MAP_REMOVE, + DATACONTROL_TYPE_MAP_BULK_ADD, + DATACONTROL_TYPE_ADD_DATA_CHANGED_CB, + DATACONTROL_TYPE_REMOVE_DATA_CHANGED_CB, + DATACONTROL_TYPE_MAX = 255 +} datacontrol_request_type; + +/** + * @brief Enumerations of different type of data control requests. + */ +typedef enum { + DATACONTROL_DATA_CHANGE_SQL_UPDATE, /**< Update notification */ + DATACONTROL_DATA_CHANGE_SQL_INSERT, /**< Insert notification */ + DATACONTROL_DATA_CHANGE_SQL_DELETE, /**< Delete notification */ + DATACONTROL_DATA_CHANGE_MAP_SET, /**< Set notification */ + DATACONTROL_DATA_CHANGE_MAP_ADD, /**< Add notification */ + DATACONTROL_DATA_CHANGE_MAP_REMOVE, /**< Remove notification */ + DATACONTROL_DATA_CHANGE_CALLBACK_ADD_RESULT, + DATACONTROL_DATA_CHANGE_CALLBACK_REMOVE_RESULT +} datacontrol_data_change_type_e; + +/** + * @brief The structure type to represent a sql result set. This type can be used to enumerate through the result set of an SQL query. + */ +typedef struct { + int resultset_fd; + sqlite3_int64 resultset_row_count; + int resultset_col_count; + off_t resultset_col_type_offset; + off_t resultset_col_name_offset; + off_t resultset_content_offset; + off_t resultset_current_offset; + sqlite3_int64 resultset_current_row_count; + char *resultset_path; + off_t *row_offset_list; +} resultset_cursor; + +typedef enum { + PRIVILEGE_PROVIDER, + PRIVILEGE_CONSUMER +} privilege_type; + +typedef enum { + CERT_UNCHECKED, + CERT_MATCH, + CERT_MISMATCH +} cert_status_type; + +typedef enum { + ACCESS_INFO_NONE, + ACCESS_INFO_READONLY, + ACCESS_INFO_WRITEONLY, + ACCESS_INFO_READ_WRITE, +} access_info_type; + +typedef struct datacontrol_consumer_request { + int request_id; + datacontrol_request_type type; +} datacontrol_consumer_request_info; + +typedef struct datacontrol_socket { + GIOChannel *gio_read; + int g_src_id; + int socket_fd; +} datacontrol_socket_info; + +struct data_control_s { + char *provider_id; + char *data_id; +}; + +void _bundle_foreach_check_arg_size_cb(const char *key, const int type, + const bundle_keyval_t *kv, void *arg_size); + +int _read_socket(int fd, char *buffer, + unsigned int nbytes, unsigned int *bytes_read); +int _write_socket(int fd, void *buffer, + unsigned int nbytes, unsigned int *bytes_write); + +void _socket_info_free(gpointer socket); +int _add_watch_on_socket_info(const char *caller_id, + const char *callee_id, const char *type, const char *provider_id, + const char *data_type, GIOFunc cb, void *data, + datacontrol_socket_info **socket_info); + +GDBusConnection *_get_dbus_connection(); +int _dbus_signal_init(int *monitor_id, char *path, GDBusSignalCallback callback); +char *_get_encoded_path(data_control_h provider, char *consumer_appid); +char *_get_encoded_db_path(); + +int _check_privilege(privilege_type check_type); +int _check_cert(const char *provider_id, bool is_map, + const char *consumer_appid); + +int _create_data_control_h(data_control_h *provider); +int _destroy_data_control_h(data_control_h provider); +int _set_provider_id(data_control_h provider, const char *provider_id); +int _get_provider_id(data_control_h provider, char **provider_id); +int _set_data_id(data_control_h provider, const char *data_id); +int _get_data_id(data_control_h provider, char **data_id); + +int _datacontrol_create_request_id(void); +int _register_response_cb(data_control_h provider, void *response_cb, + datacontrol_request_type type, void *user_data); +int _unregister_response_cb(data_control_h provider, + datacontrol_request_type); +int _request_provider(data_control_h provider, datacontrol_request_type type, + bundle *request_data, void *extra_data, int request_id); + +#endif /* _APPFW_DATA_CONTROL_INTERNAL_H_ */ + diff --git a/src/data_control_log.h b/src/data_control_log.h index fcdc272..8da5358 100644 --- a/src/data_control_log.h +++ b/src/data_control_log.h @@ -27,7 +27,9 @@ # define EXPORT_API #endif +#ifdef LOG_TAG #undef LOG_TAG +#endif #define LOG_TAG "DATA_CONTROL" #define _LOGE(fmt, arg...) LOGE(fmt, ##arg) diff --git a/src/data_control_map.c b/src/data_control_map.c index 033701e..9b07959 100755 --- a/src/data_control_map.c +++ b/src/data_control_map.c @@ -14,318 +14,308 @@ * limitations under the License. */ -#include -#include #include #include #include #include +#include -#include +#include #include "data_control_internal.h" +#include "data_control_bulk.h" #include "data_control_map.h" #include "data_control_log.h" -struct data_control_s { - char *provider_id; - char *data_id; -}; - -struct datacontrol_s { - char *provider_id; - char *data_id; -}; - -typedef struct bulk_cb_info_s { - data_control_bulk_cb bulk_cb; - void *user_data; -} bulk_cb_info; - -static GHashTable *__response_table = NULL; -static GHashTable *__bulk_response_table = NULL; -static datacontrol_map_response_cb __datacontrol_map_cb; - -static void __map_get_response(int request_id, datacontrol_h provider, - char **result_value_list, int result_value_count, bool provider_result, const char *error, void *user_data) +EXPORT_API int data_control_map_create(data_control_h *provider) { - _LOGI("map_get_response"); - - data_control_map_response_cb *callback = (data_control_map_response_cb *)g_hash_table_lookup(__response_table, provider->provider_id); - if (callback) - callback->get_cb(request_id, (data_control_h)provider, result_value_list, result_value_count, provider_result, error, user_data); + return _create_data_control_h(provider); } -static void __map_set_response(int request_id, datacontrol_h provider, bool provider_result, const char *error, void *user_data) +EXPORT_API int data_control_map_destroy(data_control_h provider) { - _LOGI("map_set_response"); - - data_control_map_response_cb *callback = (data_control_map_response_cb *)g_hash_table_lookup(__response_table, provider->provider_id); - if (callback) - callback->set_cb(request_id, (data_control_h)provider, provider_result, error, user_data); + return _destroy_data_control_h(provider); } -static void __map_add_response(int request_id, datacontrol_h provider, bool provider_result, const char *error, void *user_data) +EXPORT_API int data_control_map_set_provider_id(data_control_h provider, + const char *provider_id) { - _LOGI("map_add_response"); - - data_control_map_response_cb *callback = (data_control_map_response_cb *)g_hash_table_lookup(__response_table, provider->provider_id); - if (callback) - callback->add_cb(request_id, (data_control_h)provider, provider_result, error, user_data); + return _set_provider_id(provider, provider_id); } -static void __map_remove_response(int request_id, datacontrol_h provider, bool provider_result, const char *error, void *user_data) +EXPORT_API int data_control_map_get_provider_id(data_control_h provider, + char **provider_id) { - _LOGI("map_remove_response"); - - data_control_map_response_cb *callback = (data_control_map_response_cb *)g_hash_table_lookup(__response_table, provider->provider_id); - if (callback) - callback->remove_cb(request_id, (data_control_h)provider, provider_result, error, user_data); + return _get_provider_id(provider, provider_id); } -static void __map_bulk_add_response(int request_id, datacontrol_h provider, data_control_bulk_result_data_h bulk_results, - bool provider_result, const char *error, void *user_data) +EXPORT_API int data_control_map_set_data_id(data_control_h provider, + const char *data_id) { - _LOGI("map_bulk_add_response"); - - bulk_cb_info *info = (bulk_cb_info *)g_hash_table_lookup(__bulk_response_table, provider->provider_id); - if (info) - info->bulk_cb(request_id, (data_control_h)provider, bulk_results, provider_result, error, user_data); + return _set_data_id(provider, data_id); } -static void __free_data(gpointer data) +EXPORT_API int data_control_map_get_data_id(data_control_h provider, + char **data_id) { - if (data) { - g_free(data); - data = NULL; - } + return _get_data_id(provider, data_id); } -static void __initialize(void) +EXPORT_API int data_control_map_register_response_cb(data_control_h provider, + data_control_map_response_cb *callback, void *user_data) { - __response_table = g_hash_table_new_full(g_str_hash, g_str_equal, __free_data, __free_data); - __bulk_response_table = g_hash_table_new_full(g_str_hash, g_str_equal, __free_data, __free_data); - - __datacontrol_map_cb.get = __map_get_response; - __datacontrol_map_cb.set = __map_set_response; - __datacontrol_map_cb.add = __map_add_response; - __datacontrol_map_cb.remove = __map_remove_response; - __datacontrol_map_cb.bulk_add = __map_bulk_add_response; + return _register_response_cb(provider, (void *)callback, + DATACONTROL_TYPE_MAP_GET, user_data); } -EXPORT_API int data_control_map_create(data_control_h *provider) +EXPORT_API int data_control_map_unregister_response_cb(data_control_h provider) { - return convert_to_tizen_error(datacontrol_map_create((datacontrol_h *)provider)); + return _unregister_response_cb(provider, DATACONTROL_TYPE_MAP_GET); } -EXPORT_API int data_control_map_destroy(data_control_h provider) +EXPORT_API int data_control_map_register_add_bulk_data_response_cb( + data_control_h provider, + data_control_bulk_cb callback, + void *user_data) { - return convert_to_tizen_error(datacontrol_map_destroy((datacontrol_h)provider)); + return _register_response_cb(provider, (void *)callback, + DATACONTROL_TYPE_MAP_BULK_ADD, user_data); } -EXPORT_API int data_control_map_set_provider_id(data_control_h provider, const char *provider_id) +EXPORT_API int data_control_map_unregister_add_bulk_data_response_cb( + data_control_h provider) { - return convert_to_tizen_error(datacontrol_map_set_provider_id((datacontrol_h)provider, provider_id)); + return _unregister_response_cb(provider, DATACONTROL_TYPE_MAP_BULK_ADD); } -EXPORT_API int data_control_map_get_provider_id(data_control_h provider, char **provider_id) +EXPORT_API int data_control_map_get(data_control_h provider, + const char *key, int *request_id) { - return convert_to_tizen_error(datacontrol_map_get_provider_id((datacontrol_h)provider, provider_id)); -} + int retval; -EXPORT_API int data_control_map_set_data_id(data_control_h provider, const char *data_id) -{ - return convert_to_tizen_error(datacontrol_map_set_data_id((datacontrol_h)provider, data_id)); -} + if (provider == NULL || provider->provider_id == NULL || + provider->data_id == NULL || key == NULL) { + _LOGE("Invalid parameter"); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } -EXPORT_API int data_control_map_get_data_id(data_control_h provider, char **data_id) -{ - return convert_to_tizen_error(datacontrol_map_get_data_id((datacontrol_h)provider, data_id)); + retval = _check_privilege(PRIVILEGE_CONSUMER); + if (retval != DATA_CONTROL_ERROR_NONE) + return retval; + + retval = _check_cert(provider->provider_id, true, NULL); + if (retval != DATA_CONTROL_ERROR_NONE) + return retval; + + return data_control_map_get_with_page(provider, key, request_id, 1, 20); } -EXPORT_API int data_control_map_register_response_cb(data_control_h provider, data_control_map_response_cb *callback, void *user_data) +EXPORT_API int data_control_map_get_with_page(data_control_h provider, + const char *key, int *request_id, int page_number, int count_per_page) { - data_control_map_response_cb *cb; - char *id; + unsigned int arg_size; + int ret = 0; + const char *arg_list[4]; + char page_no_str[32]; + char count_per_page_str[32]; + int reqId; - if (__response_table == NULL) - __initialize(); - - if (callback == NULL) + if (provider == NULL || provider->provider_id == NULL || + provider->data_id == NULL || key == NULL) { + _LOGE("Invalid parameter"); return DATA_CONTROL_ERROR_INVALID_PARAMETER; - - id = strdup(provider->provider_id); - if (id == NULL) - return DATA_CONTROL_ERROR_OUT_OF_MEMORY; - - cb = (data_control_map_response_cb *)malloc(sizeof(data_control_map_response_cb)); - if (cb == NULL) { - free(id); - return DATA_CONTROL_ERROR_OUT_OF_MEMORY; } - memcpy(cb, callback, sizeof(data_control_map_response_cb)); - g_hash_table_insert(__response_table, id, cb); - - return convert_to_tizen_error(datacontrol_map_register_response_cb((datacontrol_h)provider, &__datacontrol_map_cb, user_data)); -} - -EXPORT_API int data_control_map_unregister_response_cb(data_control_h provider) -{ - if (provider->provider_id) - g_hash_table_remove(__response_table, provider->provider_id); + ret = _check_privilege(PRIVILEGE_CONSUMER); + if (ret != DATA_CONTROL_ERROR_NONE) + return ret; - return convert_to_tizen_error(datacontrol_map_unregister_response_cb((datacontrol_h)provider)); -} + ret = _check_cert(provider->provider_id, true, NULL); + if (ret != DATA_CONTROL_ERROR_NONE) + return ret; -EXPORT_API int data_control_map_register_add_bulk_data_response_cb(data_control_h provider, - data_control_bulk_cb callback, void *user_data) -{ - char *id = NULL; - bulk_cb_info *info = NULL; - int ret; + _LOGI("Gets the value list from provider_id: %s, data_id: %s", + provider->provider_id, provider->data_id); - if (__bulk_response_table == NULL) - __initialize(); + arg_size = (strlen(provider->data_id) + strlen(key)) * sizeof(wchar_t); + if (arg_size > MAX_REQUEST_ARGUMENT_SIZE) { + _LOGE("The size of sending argument (%u) exceeds the maximum limit.", + arg_size); + return DATA_CONTROL_ERROR_MAX_EXCEEDED; + } - if (callback == NULL) + bundle *b = bundle_create(); + if (!b) { + _LOGE("unable to create bundle: %d", errno); return DATA_CONTROL_ERROR_INVALID_PARAMETER; - - info = (bulk_cb_info *)calloc(1, sizeof(bulk_cb_info)); - if (info == NULL) { - _LOGE("fail to alloc info"); - ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY; - goto out; } - info->bulk_cb = callback; - info->user_data = user_data; + bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id); + bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id); - id = strdup(provider->provider_id); - if (id == NULL) { - ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY; - goto out; + arg_list[0] = provider->data_id; + arg_list[1] = key; + + ret = snprintf(page_no_str, sizeof(page_no_str), "%d", page_number); + if (ret < 0) { + _LOGE("unable to convert page no to string: %d", errno); + bundle_free(b); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; } - g_hash_table_insert(__bulk_response_table, id, info); - if (datacontrol_map_cb_is_registered(id)) - return DATA_CONTROL_ERROR_NONE; - ret = datacontrol_map_register_response_cb((datacontrol_h)provider, &__datacontrol_map_cb, NULL); - -out: - if (ret != DATA_CONTROL_ERROR_NONE) { - if (id != NULL) - free(id); - if (info != NULL) - free(info); + ret = snprintf(count_per_page_str, sizeof(count_per_page_str), + "%d", count_per_page); + if (ret < 0) { + _LOGE("unable to convert count per page no to string: %d", errno); + bundle_free(b); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; } + arg_list[2] = page_no_str; + arg_list[3] = count_per_page_str; + + bundle_add_str_array(b, OSP_K_ARG, arg_list, 4); + + /* Set the request id */ + reqId = _datacontrol_create_request_id(); + *request_id = reqId; + + ret = _request_provider(provider, DATACONTROL_TYPE_MAP_GET, b, NULL, reqId); + bundle_free(b); + return ret; -} -EXPORT_API int data_control_map_unregister_add_bulk_data_response_cb(data_control_h provider) -{ - if (provider != NULL && provider->provider_id && __bulk_response_table) { - if (g_hash_table_lookup(__bulk_response_table, provider->provider_id) != NULL) { - g_hash_table_remove(__bulk_response_table, provider->provider_id); - } else { - _LOGE("Invalid param"); - return DATA_CONTROL_ERROR_INVALID_PARAMETER; - } - } else { - _LOGE("Invalid param"); - return DATA_CONTROL_ERROR_INVALID_PARAMETER; - } - return DATA_CONTROL_ERROR_NONE; } -EXPORT_API int data_control_map_get(data_control_h provider, const char *key, int *request_id) +EXPORT_API int data_control_map_set(data_control_h provider, const char *key, + const char *old_value, const char *new_value, int *request_id) { int retval; + unsigned int arg_size; + bundle *b; + const char *arg_list[4]; + int reqId; if (provider == NULL || provider->provider_id == NULL || - provider->data_id == NULL || key == NULL) { + provider->data_id == NULL || key == NULL || + old_value == NULL || new_value == NULL) { _LOGE("Invalid parameter"); return DATA_CONTROL_ERROR_INVALID_PARAMETER; } - retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER); + retval = _check_privilege(PRIVILEGE_CONSUMER); if (retval != DATA_CONTROL_ERROR_NONE) return retval; - retval = datacontrol_check_cert(provider->provider_id, true, NULL); + retval = _check_cert(provider->provider_id, true, NULL); if (retval != DATA_CONTROL_ERROR_NONE) return retval; - return convert_to_tizen_error(datacontrol_map_get((datacontrol_h)provider, key, request_id)); -} + _LOGI("Sets the old value to new value in provider_id: %s, data_id: %s", + provider->provider_id, provider->data_id); -EXPORT_API int data_control_map_get_with_page(data_control_h provider, const char *key, int *request_id, int page_number, int count_per_page) -{ - int retval; + arg_size = (strlen(provider->data_id) + strlen(key) + + strlen(old_value) + strlen(new_value)) * sizeof(wchar_t); + if (arg_size > MAX_REQUEST_ARGUMENT_SIZE) { + _LOGE("The size of sending argument (%u) exceeds the maximum limit.", + arg_size); + return DATA_CONTROL_ERROR_MAX_EXCEEDED; + } - if (provider == NULL || provider->provider_id == NULL || - provider->data_id == NULL || key == NULL) { - _LOGE("Invalid parameter"); - return DATA_CONTROL_ERROR_INVALID_PARAMETER; + b = bundle_create(); + if (!b) { + _LOGE("unable to create bundle: %d", errno); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; } - retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER); - if (retval != DATA_CONTROL_ERROR_NONE) - return retval; + bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id); + bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id); - retval = datacontrol_check_cert(provider->provider_id, true, NULL); - if (retval != DATA_CONTROL_ERROR_NONE) - return retval; + arg_list[0] = provider->data_id; + arg_list[1] = key; + arg_list[2] = old_value; + arg_list[3] = new_value; + + bundle_add_str_array(b, OSP_K_ARG, arg_list, 4); + + /* Set the request id */ + reqId = _datacontrol_create_request_id(); + *request_id = reqId; + + retval = + _request_provider(provider, DATACONTROL_TYPE_MAP_SET, b, NULL, reqId); + bundle_free(b); - return convert_to_tizen_error(datacontrol_map_get_with_page((datacontrol_h)provider, key, request_id, page_number, count_per_page)); + return retval; } -EXPORT_API int data_control_map_set(data_control_h provider, const char *key, const char *old_value, const char *new_value, int *request_id) +EXPORT_API int data_control_map_add(data_control_h provider, + const char *key, const char *value, int *request_id) { int retval; + unsigned int arg_size; + bundle *b; + const char *arg_list[3]; + int reqId; if (provider == NULL || provider->provider_id == NULL || - provider->data_id == NULL || key == NULL || - old_value == NULL || new_value == NULL) { + provider->data_id == NULL || key == NULL || value == NULL) { _LOGE("Invalid parameter"); return DATA_CONTROL_ERROR_INVALID_PARAMETER; } - retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER); + retval = _check_privilege(PRIVILEGE_CONSUMER); if (retval != DATA_CONTROL_ERROR_NONE) return retval; - retval = datacontrol_check_cert(provider->provider_id, true, NULL); + retval = _check_cert(provider->provider_id, true, NULL); if (retval != DATA_CONTROL_ERROR_NONE) return retval; - return convert_to_tizen_error(datacontrol_map_set((datacontrol_h)provider, key, old_value, new_value, request_id)); -} + _LOGI("Adds the value in provider_id: %s, data_id: %s", + provider->provider_id, provider->data_id); -EXPORT_API int data_control_map_add(data_control_h provider, const char *key, const char *value, int *request_id) -{ - int retval; + arg_size = (strlen(provider->data_id) + strlen(key) + + strlen(value)) * sizeof(wchar_t); + if (arg_size > MAX_REQUEST_ARGUMENT_SIZE) { + _LOGE("The size of sending argument (%u) exceeds the maximum limit.", + arg_size); + return DATA_CONTROL_ERROR_MAX_EXCEEDED; + } - if (provider == NULL || provider->provider_id == NULL || - provider->data_id == NULL || key == NULL || value == NULL) { - _LOGE("Invalid parameter"); - return DATA_CONTROL_ERROR_INVALID_PARAMETER; + b = bundle_create(); + if (!b) { + _LOGE("unable to create bundle: %d", errno); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; } - retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER); - if (retval != DATA_CONTROL_ERROR_NONE) - return retval; + bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id); + bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id); - retval = datacontrol_check_cert(provider->provider_id, true, NULL); - if (retval != DATA_CONTROL_ERROR_NONE) - return retval; + arg_list[0] = provider->data_id; + arg_list[1] = key; + arg_list[2] = value; + + bundle_add_str_array(b, OSP_K_ARG, arg_list, 3); + + /* Set the request id */ + reqId = _datacontrol_create_request_id(); + *request_id = reqId; + + retval = + _request_provider(provider, DATACONTROL_TYPE_MAP_ADD, b, NULL, reqId); + bundle_free(b); - return convert_to_tizen_error(datacontrol_map_add((datacontrol_h)provider, key, value, request_id)); + return retval; } -EXPORT_API int data_control_map_remove(data_control_h provider, const char *key, const char *value, int *request_id) +EXPORT_API int data_control_map_remove(data_control_h provider, + const char *key, const char *value, int *request_id) { int retval; + unsigned int arg_size; + bundle *b; + const char *arg_list[3]; + int reqId; if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || key == NULL || value == NULL) { @@ -333,20 +323,61 @@ EXPORT_API int data_control_map_remove(data_control_h provider, const char *key, return DATA_CONTROL_ERROR_INVALID_PARAMETER; } - retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER); + retval = _check_privilege(PRIVILEGE_CONSUMER); if (retval != DATA_CONTROL_ERROR_NONE) return retval; - retval = datacontrol_check_cert(provider->provider_id, true, NULL); + retval = _check_cert(provider->provider_id, true, NULL); if (retval != DATA_CONTROL_ERROR_NONE) return retval; - return convert_to_tizen_error(datacontrol_map_remove((datacontrol_h)provider, key, value, request_id)); + _LOGI("Removes the value in provider_id: %s, data_id: %s", + provider->provider_id, provider->data_id); + + arg_size = (strlen(provider->data_id) + strlen(key) + + strlen(value)) * sizeof(wchar_t); + if (arg_size > MAX_REQUEST_ARGUMENT_SIZE) { + _LOGE("The size of sending argument (%u) exceeds the maximum limit.", + arg_size); + return DATA_CONTROL_ERROR_MAX_EXCEEDED; + } + + b = bundle_create(); + if (!b) { + _LOGE("unable to create bundle: %d", errno); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } + + bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id); + bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id); + + arg_list[0] = provider->data_id; + arg_list[1] = key; + arg_list[2] = value; + + bundle_add_str_array(b, OSP_K_ARG, arg_list, 3); + + /* Set the request id */ + reqId = _datacontrol_create_request_id(); + *request_id = reqId; + + retval = + _request_provider(provider, DATACONTROL_TYPE_MAP_REMOVE, b, NULL, reqId); + bundle_free(b); + + return retval; } -EXPORT_API int data_control_map_add_bulk_data(data_control_h provider, data_control_bulk_data_h bulk_data_h, int *request_id) +EXPORT_API int data_control_map_add_bulk_data(data_control_h provider, + data_control_bulk_data_h bulk_data_h, int *request_id) { int retval; + unsigned int arg_size = 0; + bundle *b; + bundle *data; + const char *arg_list[3]; + int count; + int i; if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL) { @@ -354,14 +385,48 @@ EXPORT_API int data_control_map_add_bulk_data(data_control_h provider, data_cont return DATA_CONTROL_ERROR_INVALID_PARAMETER; } - retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER); + retval = _check_privilege(PRIVILEGE_CONSUMER); if (retval != DATA_CONTROL_ERROR_NONE) return retval; - retval = datacontrol_check_cert(provider->provider_id, true, NULL); + retval = _check_cert(provider->provider_id, true, NULL); if (retval != DATA_CONTROL_ERROR_NONE) return retval; - return convert_to_tizen_error(datacontrol_map_add_bulk_data((datacontrol_h)provider, bulk_data_h, request_id)); + _LOGI("Adds the value in provider_id: %s, data_id: %s", + provider->provider_id, provider->data_id); + data_control_bulk_data_get_count(bulk_data_h, &count); + for (i = 0; i < count; i++) { + data_control_bulk_data_get_data(bulk_data_h, i, &data); + bundle_foreach(data, _bundle_foreach_check_arg_size_cb, &arg_size); + } + + arg_size += + (strlen(provider->data_id) + strlen(provider->provider_id)) * sizeof(char); + if (arg_size > MAX_REQUEST_ARGUMENT_SIZE) { + _LOGE("The size of sending argument (%u) exceeds the maximum limit.", + arg_size); + return DATA_CONTROL_ERROR_MAX_EXCEEDED; + } + + b = bundle_create(); + if (!b) { + _LOGE("unable to create bundle: %d", errno); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } + + bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id); + bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id); + + arg_list[0] = provider->data_id; + + bundle_add_str_array(b, OSP_K_ARG, arg_list, 1); + *request_id = _datacontrol_create_request_id(); + + retval = _request_provider(provider, DATACONTROL_TYPE_MAP_BULK_ADD, b, + bulk_data_h, *request_id); + bundle_free(b); + + return retval; } diff --git a/src/data_control_noti.c b/src/data_control_noti.c index 860e9d9..f13ed3a 100644 --- a/src/data_control_noti.c +++ b/src/data_control_noti.c @@ -1,18 +1,290 @@ -#include #include #include #include #include +#include + +#include +#include +#include #include "data_control_internal.h" #include "data_control_log.h" #include "data_control_noti.h" -#include "data-control-noti.h" -struct data_control_s { +typedef struct { + GList *cb_list; + char *provider_appid; char *provider_id; char *data_id; -}; + int monitor_id; +} provider_info_s; + +typedef struct { + void *user_data; + int callback_id; + data_control_data_change_cb changed_cb; +} changed_cb_info_s; + +typedef struct { + void *user_data; + int callback_id; + char *provider_id; + char *data_id; + int timeout_id; + data_control_add_callback_result_cb callback; +} add_callback_result_cb_info_s; + +static GList *__add_callback_result_cb_list = NULL; +static GList *__changed_provider_list = NULL; + +static int __callback_result_info_compare_cb(gconstpointer a, gconstpointer b) +{ + add_callback_result_cb_info_s *key1 = + (add_callback_result_cb_info_s *)a; + add_callback_result_cb_info_s *key2 = + (add_callback_result_cb_info_s *)b; + + return !(key1->callback_id == key2->callback_id); +} + +static int __provider_info_compare_cb(gconstpointer a, gconstpointer b) +{ + provider_info_s *key1 = (provider_info_s *)a; + provider_info_s *key2 = (provider_info_s *)b; + return (strcmp(key1->provider_id, key2->provider_id) || + strcmp(key1->data_id, key2->data_id)); +} + +static int __changed_cb_info_compare_cb(gconstpointer a, gconstpointer b) +{ + changed_cb_info_s *key1 = (changed_cb_info_s *)a; + changed_cb_info_s *key2 = (changed_cb_info_s *)b; + + return !(key1->callback_id == key2->callback_id); +} + +static void __free_result_cb_info( + add_callback_result_cb_info_s *result_cb_info) +{ + if (result_cb_info) { + if (result_cb_info->provider_id) + free(result_cb_info->provider_id); + if (result_cb_info->data_id) + free(result_cb_info->data_id); + if (result_cb_info->timeout_id > 0) + g_source_remove(result_cb_info->timeout_id); + free(result_cb_info); + result_cb_info = NULL; + } +} + +static void __free_provider_info( + provider_info_s *provider_info) +{ + if (provider_info) { + if (provider_info->provider_appid) + free(provider_info->provider_appid); + if (provider_info->provider_id) + free(provider_info->provider_id); + if (provider_info->data_id) + free(provider_info->data_id); + if (provider_info->monitor_id > 0) + g_dbus_connection_signal_unsubscribe(_get_dbus_connection(), + provider_info->monitor_id); + g_list_free_full(provider_info->cb_list, free); + free(provider_info); + provider_info = NULL; + } +} + +static void __noti_process(GVariant *parameters) +{ + char *provider_id = NULL; + char *data_id = NULL; + bundle_raw *raw = NULL; + bundle *noti_data = NULL; + int len = 0; + data_control_h provider = NULL; + GList *find_list; + changed_cb_info_s *cb_info = NULL; + provider_info_s find_info; + provider_info_s *provider_info; + GList *callback_list = NULL; + data_control_data_change_type_e type; + + g_variant_get(parameters, "(i&s&s&si)", + &type, &provider_id, &data_id, &raw, &len); + _LOGI("__noti_process : %d %s %s %d", type, provider_id, data_id, len); + + if (provider_id == NULL || data_id == NULL) + return; + + find_info.provider_id = provider_id; + find_info.data_id = data_id; + + find_list = g_list_find_custom(__changed_provider_list, &find_info, + (GCompareFunc)__provider_info_compare_cb); + if (find_list != NULL) { + _create_data_control_h(&provider); + _set_provider_id(provider, provider_id); + _set_data_id(provider, data_id); + noti_data = bundle_decode(raw, len); + provider_info = (provider_info_s *)find_list->data; + callback_list = g_list_first(provider_info->cb_list); + for (; callback_list != NULL; callback_list = callback_list->next) { + cb_info = callback_list->data; + cb_info->changed_cb((data_control_h)provider, + type, noti_data, cb_info->user_data); + _LOGI("callback called: %s, %s", + provider_info->provider_id, provider_info->data_id); + } + bundle_free(noti_data); + _destroy_data_control_h(provider); + + } else { + _LOGE("data_control_data_change_cb is null"); + } + _LOGI("__noti_process done"); +} + +static void __call_result_callback(int callback_id, int callback_result) +{ + add_callback_result_cb_info_s *result_cb_info; + add_callback_result_cb_info_s find_info; + data_control_h provider; + GList *find_list; + + find_info.callback_id = callback_id; + find_list = g_list_find_custom(__add_callback_result_cb_list, &find_info, + (GCompareFunc)__callback_result_info_compare_cb); + + if (find_list != NULL) { + result_cb_info = (add_callback_result_cb_info_s *)find_list->data; + if (result_cb_info->callback) { + _create_data_control_h(&provider); + _set_provider_id(provider, result_cb_info->provider_id); + _set_data_id(provider, result_cb_info->data_id); + + result_cb_info->callback( + (data_control_h)provider, + callback_result, + callback_id, + result_cb_info->user_data); + + _destroy_data_control_h(provider); + } else { + _LOGE("data_control_add_callback_result_cb is null"); + } + + __add_callback_result_cb_list = + g_list_remove(__add_callback_result_cb_list, find_list->data); + __free_result_cb_info(result_cb_info); + } else { + _LOGE("add_callback_result_cb_info_s is null"); + } +} + +/* LCOV_EXCL_START */ +static gboolean __add_callback_result_timeout_handler(gpointer user_data) +{ + _LOGE("add data changed callback time out !!!"); + add_callback_result_cb_info_s *result_cb_info = + (add_callback_result_cb_info_s *)user_data; + __call_result_callback(result_cb_info->callback_id, + DATA_CONTROL_ERROR_IO_ERROR); + return FALSE; +} +/* LCOV_EXCL_STOP */ + +static void __noti_add_remove_data_changed_cb_result_process( + GVariant *parameters) +{ + int callback_id; + data_control_error_e callback_result; + datacontrol_data_change_type_e type; + + g_variant_get(parameters, "(iii)", &type, &callback_id, &callback_result); + _LOGI("__noti_add_remove_data_changed_cb_result_process: %d %d %d", + type, callback_id, callback_result); + + if (type == DATACONTROL_DATA_CHANGE_CALLBACK_ADD_RESULT) + __call_result_callback(callback_id, callback_result); +} + +static void __handle_noti(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + _LOGI("signal_name: %s", signal_name); + + if (g_strcmp0(signal_name, "noti_data_changed") == 0) + __noti_process(parameters); + else if (g_strcmp0(signal_name, "noti_add_remove_result") == 0) + __noti_add_remove_data_changed_cb_result_process(parameters); +} + +static int __noti_request_appsvc_run(const char *callee_id, + char *provider_id, char *data_id, const char *unique_id, + int callback_id, int request_type) +{ + int pid = -1; + char callback_id_str[32] = {0,}; + char request_type_str[MAX_LEN_DATACONTROL_REQ_TYPE] = {0,}; + bundle *arg_list = bundle_create(); + if (!arg_list) { + _LOGE("unable to create bundle: %d", errno); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } + + snprintf(callback_id_str, 32, "%d", callback_id); + snprintf(request_type_str, MAX_LEN_DATACONTROL_REQ_TYPE, "%d", (int)(request_type)); + + appsvc_set_operation(arg_list, APPSVC_OPERATION_DEFAULT); + appsvc_set_appid(arg_list, callee_id); + + bundle_add_str(arg_list, OSP_K_DATACONTROL_REQUEST_TYPE, request_type_str); + bundle_add_str(arg_list, OSP_K_DATACONTROL_UNIQUE_NAME, unique_id); + bundle_add_str(arg_list, OSP_K_DATACONTROL_PROVIDER, provider_id); + bundle_add_str(arg_list, OSP_K_DATACONTROL_DATA, data_id); + bundle_add_str(arg_list, OSP_K_DATA_CHANGED_CALLBACK_ID, callback_id_str); + + bundle_add_str(arg_list, OSP_K_CALLER_TYPE, OSP_V_CALLER_TYPE_OSP); + bundle_add_str(arg_list, OSP_K_LAUNCH_TYPE, OSP_V_LAUNCH_TYPE_DATACONTROL); + bundle_add_str(arg_list, AUL_K_CALLEE_APPID, callee_id); + bundle_add_str(arg_list, AUL_K_NO_CANCEL, "1"); + _LOGI("callee_id %s", callee_id); + _LOGI("provider_id %s, data_id %s", provider_id, data_id); + + /* For DataControl CAPI */ + bundle_add_str(arg_list, AUL_K_DATA_CONTROL_TYPE, "CORE"); + + pid = appsvc_run_service(arg_list, 0, NULL, NULL); + if (pid >= 0) { + _LOGI("Launch the provider app successfully: %d", pid); + bundle_free(arg_list); + } else if (pid == APPSVC_RET_EINVAL) { + _LOGE("not able to launch service: %d", pid); + bundle_free(arg_list); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } else { + _LOGE("unable to launch service: %d", pid); + return DATA_CONTROL_ERROR_IO_ERROR; + } + return DATA_CONTROL_ERROR_NONE; +} + +int _datacontrol_get_data_changed_callback_id(void) +{ + static int id = 0; + g_atomic_int_inc(&id); + + return id; +} EXPORT_API int data_control_add_data_change_cb( data_control_h provider, @@ -22,48 +294,241 @@ EXPORT_API int data_control_add_data_change_cb( void *result_cb_user_data, int *callback_id) { - int retval; + int ret = DATA_CONTROL_ERROR_NONE; + changed_cb_info_s *cb_info = NULL; + provider_info_s *provider_info = NULL; + provider_info_s find_provider_info; + int monitor_id = 0; + GList *find_list; + char *path = NULL; + const char *unique_id = NULL; + char caller_app_id[255]; + pid_t pid; + add_callback_result_cb_info_s *result_cb_info = NULL; + char *provider_app_id = NULL; + char *access = NULL; - retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER); - if (retval != DATA_CONTROL_ERROR_NONE) - return retval; + ret = _check_privilege(PRIVILEGE_CONSUMER); + if (ret != DATA_CONTROL_ERROR_NONE) + return ret; if (callback == NULL || provider == NULL || callback_id == NULL) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - retval = datacontrol_check_cert(provider->provider_id, true, NULL); - if (retval == DATA_CONTROL_ERROR_PERMISSION_DENIED) { - retval = datacontrol_check_cert(provider->provider_id, false, NULL); - if (retval == DATA_CONTROL_ERROR_PERMISSION_DENIED) + ret = _check_cert(provider->provider_id, true, NULL); + if (ret == DATA_CONTROL_ERROR_PERMISSION_DENIED) { + ret = _check_cert(provider->provider_id, false, NULL); + if (ret == DATA_CONTROL_ERROR_PERMISSION_DENIED) return DATA_CONTROL_ERROR_PERMISSION_DENIED; } - return datacontrol_add_data_change_cb( - (datacontrol_h)provider, - callback, - user_data, - result_callback, - result_cb_user_data, - callback_id); + _LOGI("provider_id : %s, data_id : %s", + provider->provider_id, provider->data_id); + ret = pkgmgrinfo_appinfo_usr_get_datacontrol_info(provider->provider_id, + "Sql", getuid(), &provider_app_id, &access); + if (ret != PMINFO_R_OK) { + _LOGE("unable to get sql data control information, retry with map: %d", ret); + ret = pkgmgrinfo_appinfo_usr_get_datacontrol_info(provider->provider_id, + "Map", getuid(), &provider_app_id, &access); + if (ret != PMINFO_R_OK) { + _LOGE("unable to get map data control information: %d", ret); + return DATA_CONTROL_ERROR_IO_ERROR; + } + } + + *callback_id = _datacontrol_get_data_changed_callback_id(); + unique_id = g_dbus_connection_get_unique_name(_get_dbus_connection()); + _LOGI("unique_id : %s, callback_id %d", unique_id, *callback_id); + + find_provider_info.provider_id = provider->provider_id; + find_provider_info.data_id = provider->data_id; + find_list = g_list_find_custom(__changed_provider_list, &find_provider_info, + (GCompareFunc)__provider_info_compare_cb); + if (find_list == NULL) { + + pid = getpid(); + if (aul_app_get_appid_bypid(pid, caller_app_id, sizeof(caller_app_id)) != 0) { + _LOGE("Failed to get appid by pid(%d).", pid); + ret = DATA_CONTROL_ERROR_INVALID_PARAMETER; + goto err; + } + path = _get_encoded_path(provider, caller_app_id); + if (path == NULL) { + _LOGE("cannot get encoded path. out of memory."); + ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY; + goto err; + } + + ret = _dbus_signal_init(&monitor_id, path, __handle_noti); + if (ret != DATA_CONTROL_ERROR_NONE) { + _LOGE("fail to init dbus signal."); + ret = DATA_CONTROL_ERROR_IO_ERROR; + goto err; + } + + provider_info = (provider_info_s *)calloc(1, sizeof(provider_info_s)); + if (provider_info == NULL) { + _LOGE("provider_info_s alloc fail out of memory."); + ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY; + goto err; + } + provider_info->provider_appid = strdup(provider_app_id); + provider_info->provider_id = strdup(provider->provider_id); + provider_info->data_id = strdup(provider->data_id); + provider_info->monitor_id = monitor_id; + if (provider_info->provider_id == NULL || + provider_info->data_id == NULL) { + _LOGE("data_id alloc fail out of memory."); + ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY; + __free_provider_info(provider_info); + goto err; + } + __changed_provider_list = + g_list_append(__changed_provider_list, provider_info); + } else { + provider_info = (provider_info_s *)find_list->data; + } + + ret = __noti_request_appsvc_run( + provider_app_id, + provider_info->provider_id, + provider_info->data_id, + unique_id, + *callback_id, + DATACONTROL_TYPE_ADD_DATA_CHANGED_CB); + if (ret != DATA_CONTROL_ERROR_NONE) { + _LOGE("__noti_request_appsvc_run error !!!"); + goto err; + } + + cb_info = (changed_cb_info_s *)calloc(1, + sizeof(changed_cb_info_s)); + if (cb_info == NULL) { + _LOGE("changed_cb_info_s alloc fail out of memory."); + ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY; + goto err; + } + + cb_info->changed_cb = callback; + cb_info->user_data = user_data; + cb_info->callback_id = *callback_id; + provider_info->cb_list = g_list_append( + provider_info->cb_list, cb_info); + + result_cb_info = + (add_callback_result_cb_info_s *)calloc(1, sizeof(add_callback_result_cb_info_s)); + result_cb_info->callback_id = *callback_id; + result_cb_info->callback = result_callback; + result_cb_info->user_data = result_cb_user_data; + result_cb_info->provider_id = strdup(provider_info->provider_id); + result_cb_info->data_id = strdup(provider_info->data_id); + result_cb_info->timeout_id = + g_timeout_add(5000, __add_callback_result_timeout_handler, result_cb_info); + __add_callback_result_cb_list = + g_list_append(__add_callback_result_cb_list, result_cb_info); + _LOGI("datacontrol_add_data_change_cb done"); + + /* LCOV_EXCL_START */ +err: + if (access) + free(access); + if (provider_app_id) + free(provider_app_id); + if (path) + free(path); + if (ret != DATA_CONTROL_ERROR_NONE) { + if (monitor_id > 0) + g_dbus_connection_signal_unsubscribe(_get_dbus_connection(), monitor_id); + } + + return ret; + /* LCOV_EXCL_STOP */ } -EXPORT_API int data_control_remove_data_change_cb(data_control_h provider, int callback_id) +EXPORT_API int data_control_remove_data_change_cb(data_control_h provider, + int callback_id) { - int retval; + changed_cb_info_s *removed_cb_info = NULL; + changed_cb_info_s cb_info; + provider_info_s info; + provider_info_s *target_provider_info; + add_callback_result_cb_info_s result_cb_info; + add_callback_result_cb_info_s *tmp; + GList *provider_list = NULL; + GList *callback_list = NULL; + GList *result_cb_list = NULL; + const char *unique_id = NULL; + int ret = DATA_CONTROL_ERROR_NONE; if (callback_id < 1 || provider == NULL) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER); - if (retval != DATA_CONTROL_ERROR_NONE) - return retval; + ret = _check_privilege(PRIVILEGE_CONSUMER); + if (ret != DATA_CONTROL_ERROR_NONE) + return ret; - retval = datacontrol_check_cert(provider->provider_id, true, NULL); - if (retval == DATA_CONTROL_ERROR_PERMISSION_DENIED) { - retval = datacontrol_check_cert(provider->provider_id, false, NULL); - if (retval == DATA_CONTROL_ERROR_PERMISSION_DENIED) + ret = _check_cert(provider->provider_id, true, NULL); + if (ret == DATA_CONTROL_ERROR_PERMISSION_DENIED) { + ret = _check_cert(provider->provider_id, false, NULL); + if (ret == DATA_CONTROL_ERROR_PERMISSION_DENIED) return DATA_CONTROL_ERROR_PERMISSION_DENIED; } - return datacontrol_remove_data_change_cb((datacontrol_h)provider, callback_id); + info.provider_id = provider->provider_id; + info.data_id = provider->data_id; + + provider_list = g_list_find_custom(__changed_provider_list, &info, + (GCompareFunc)__provider_info_compare_cb); + if (provider_list == NULL) { + _LOGE("Cannot find provider info"); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + cb_info.callback_id = callback_id; + target_provider_info = (provider_info_s *)provider_list->data; + callback_list = g_list_find_custom( + target_provider_info->cb_list, + &cb_info, + (GCompareFunc)__changed_cb_info_compare_cb); + if (callback_list == NULL) { + _LOGE("Cannot find changed callback info"); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + removed_cb_info = (changed_cb_info_s *)callback_list->data; + target_provider_info->cb_list + = g_list_remove(target_provider_info->cb_list, removed_cb_info); + free(removed_cb_info); + + if (g_list_length(target_provider_info->cb_list) == 0) { + unique_id = g_dbus_connection_get_unique_name(_get_dbus_connection()); + _LOGI("unique_id : %s", unique_id); + ret = __noti_request_appsvc_run( + target_provider_info->provider_appid, + target_provider_info->provider_id, + target_provider_info->data_id, + unique_id, + callback_id, + DATACONTROL_TYPE_REMOVE_DATA_CHANGED_CB); + if (ret != DATA_CONTROL_ERROR_NONE) { + _LOGE("__sql_request_provider fail %d", ret); + return ret; + } + + __changed_provider_list = + g_list_remove(__changed_provider_list, target_provider_info); + __free_provider_info(target_provider_info); + } + + result_cb_info.callback_id = callback_id; + result_cb_list = + g_list_find_custom(__add_callback_result_cb_list, &result_cb_info, + (GCompareFunc)__callback_result_info_compare_cb); + if (result_cb_list) { + tmp = (add_callback_result_cb_info_s *)result_cb_list->data; + __add_callback_result_cb_list = + g_list_remove(__add_callback_result_cb_list, result_cb_list->data); + __free_result_cb_info(tmp); + } + return DATA_CONTROL_ERROR_NONE; } diff --git a/src/data_control_provider.c b/src/data_control_provider.c index 36cc854..fe21968 100755 --- a/src/data_control_provider.c +++ b/src/data_control_provider.c @@ -16,253 +16,2007 @@ #include -#include +#include + +#include #include -#include -#include +#include + +#include "data_control_provider_internal.h" +#include "data_control_types.h" +#include "data_control_provider.h" +#include "data_control_sql.h" +#include "data_control_log.h" +#include "data_control_internal.h" + +#define INSERT_STMT_CONST_LEN 25 +#define DELETE_STMT_CONST_LEN 12 +#define UPDATE_STMT_CONST_LEN 15 +#define SELECT_STMT_CONST_LEN 13 +#define WHERE_COND_CONST_LEN 7 +#define ORDER_CLS_CONST_LEN 10 + +#define QUERY_MAXLEN 4096 +#define ROW_ID_SIZE 32 +#define RESULT_PATH_MAX 512 +#define MAX_COLUMN_COUNT 32767 /* Base on sqlite3 maximum column count */ + +#define RESULT_PAGE_NUMBER "RESULT_PAGE_NUMBER" +#define MAX_COUNT_PER_PAGE "MAX_COUNT_PER_PAGE" +#define RESULT_VALUE_COUNT "RESULT_VALUE_COUNT" + +#define PACKET_INDEX_REQUEST_RESULT 0 +#define PACKET_INDEX_ERROR_MSG 1 +#define PACKET_INDEX_SELECT_RESULT_FILE 2 +#define PACKET_INDEX_ROW_ID 2 +#define PACKET_INDEX_VALUE_COUNT 2 +#define PACKET_INDEX_GET_RESULT_FILE 3 + +#define PACKET_INDEX_DATAID 0 +#define PACKET_INDEX_MAP 2 + +#define PACKET_INDEX_UPDATEWHERE 1 +#define PACKET_INDEX_DELETEWHERE 1 + +#define PACKET_INDEX_MAP_KEY 1 +#define PACKET_INDEX_MAP_VALUE_1ST 2 +#define PACKET_INDEX_MAP_VALUE_2ND 3 +#define PACKET_INDEX_MAP_PAGE_NO 2 +#define PACKET_INDEX_MAP_COUNT_PER_PAGE 3 + +#define DATA_CONTROL_BUS_NAME "org.tizen.data_control_service" +#define DATA_CONTROL_OBJECT_PATH "/org/tizen/data_control_service" +#define DATA_CONTROL_INTERFACE_NAME "org.tizen.data_control_service" +#define DATA_CONTROL_DATA_CHANGE_DATA_CHANGED "noti_data_changed" +#define DATA_CONTROL_DATA_CHANGE_ADD_REMOVE_RESULT "noti_add_remove_result" + +typedef struct { + int no_of_elements; + int length; + char **keys; + char **vals; +} key_val_pair; + +typedef struct datacontrol_consumer { + int monitor_id; + char *appid; + char *object_path; + char *unique_id; +} datacontrol_consumer_info; + +typedef struct { + void *user_data; + int callback_id; + data_control_provider_data_change_consumer_filter_cb callback; +} changed_noti_consumer_filter_info_s; + +static GHashTable *__request_table = NULL; +static GHashTable *__socket_pair_hash = NULL; +static sqlite3 *__provider_db = NULL; + +static data_control_provider_sql_cb sql_callback; +static data_control_provider_map_cb map_callback; +static data_control_provider_bulk_cb sql_bulk_callback; +static data_control_provider_bulk_cb map_bulk_callback; + +static void *sql_user_data; +static void *map_user_data; +static void *sql_bulk_callback_user_data = NULL; +static void *map_bulk_callback_user_data = NULL; + +static GList *__noti_consumer_app_list = NULL; +static GList *__noti_consumer_filter_info_list = NULL; + +static int __create_consumer_list_db(); +static int __delete_consumer_list_db_info(char *unique_id); + +static int __is_null_sql_callback(data_control_provider_sql_cb callback) +{ + if (callback.select_cb == NULL && + callback.insert_cb == NULL && + callback.delete_cb == NULL && + callback.update_cb == NULL) + return 1; + + return 0; +} + +static int __is_null_map_callback(data_control_provider_map_cb callback) +{ + if (callback.get_cb == NULL && + callback.set_cb == NULL && + callback.add_cb == NULL && + callback.remove_cb == NULL) + return 1; + + return 0; +} + +static void __free_bundle_data(gpointer data) +{ + if (data) { + bundle_free(data); + data = NULL; + } +} + +static void __free_data(gpointer data) +{ + if (data) { + free(data); + data = NULL; + } +} + +static void __initialize_provider(void) +{ + int result; + __request_table = g_hash_table_new_full(g_int_hash, g_int_equal, + __free_data, __free_bundle_data); + __socket_pair_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + free, _socket_info_free); + result = __create_consumer_list_db(); + if (result != DATA_CONTROL_ERROR_NONE) + _LOGE("fail to create consumer list db"); +} + +static int __provider_new_request_id(void) +{ + static int id = 0; + g_atomic_int_inc(&id); + return id; +} + +static int __data_changed_filter_cb_info_compare_cb(gconstpointer a, gconstpointer b) +{ + changed_noti_consumer_filter_info_s *key1 = + (changed_noti_consumer_filter_info_s *)a; + changed_noti_consumer_filter_info_s *key2 = + (changed_noti_consumer_filter_info_s *)b; + + return !(key1->callback_id == key2->callback_id); +} + +static int __noti_consumer_app_list_compare_cb(gconstpointer a, gconstpointer b) +{ + datacontrol_consumer_info *info_a = (datacontrol_consumer_info *)a; + datacontrol_consumer_info *info_b = (datacontrol_consumer_info *)b; + + return strcmp(info_a->unique_id, info_b->unique_id); +} + +static void __free_consumer_info(const gchar *name) +{ + datacontrol_consumer_info find_key; + datacontrol_consumer_info *info; + GList *find_list = NULL; + int result; + + find_key.unique_id = (char *)name; + find_list = g_list_find_custom(__noti_consumer_app_list, &find_key, + (GCompareFunc)__noti_consumer_app_list_compare_cb); + if (find_list == NULL) { + _LOGI("__free_consumer_info %s not exist", name); + return; + } + + info = (datacontrol_consumer_info *)find_list->data; + result = __delete_consumer_list_db_info(info->unique_id); + if (result != DATA_CONTROL_ERROR_NONE) + _LOGE("__delete_consumer_list_db_info fail %d", result); + + if (info->appid) + free(info->appid); + if (info->object_path) + free(info->object_path); + if (info->unique_id) + free(info->unique_id); + g_bus_unwatch_name(info->monitor_id); + + __noti_consumer_app_list = + g_list_remove(__noti_consumer_app_list, find_list->data); + + free(info); + _LOGI("__free_consumer_info done"); +} +static int __check_consumer_cert(const char *provider_id, + const char *consumer_appid, + data_control_data_change_type_e type) +{ + bool is_map; + + if (consumer_appid == NULL) + return DATA_CONTROL_ERROR_IO_ERROR; + + if (type >= DATA_CONTROL_DATA_CHANGE_SQL_UPDATE && + type <= DATA_CONTROL_DATA_CHANGE_SQL_DELETE) + is_map = false; + else + is_map = true; + + return _check_cert(provider_id, is_map, consumer_appid); +} + +int __datacontrol_get_data_changed_filter_callback_id(void) +{ + static int id = 0; + g_atomic_int_inc(&id); + + return id; +} + +static int __get_int_from_str(const char *str) +{ + int result = 0; + char *pend; + errno = 0; + result = strtol(str, &pend, 10); + if ((result == LONG_MIN || result == LONG_MAX) + && errno != 0) { + result = 0; + } + + if (*pend != '\0') + result = 0; + + return result; +} + +static bundle *__get_bundle_data_from_fd(int fd) +{ + bundle *b = NULL; + int len = 0; + int ret; + char *buf; + + ret = read(fd, &len, sizeof(int)); + if (ret < sizeof(int)) { + _LOGE("read error :%d", ret); + return NULL; + } + LOGD("read len : %d", len); + + if (len > 0 && len < MAX_REQUEST_ARGUMENT_SIZE) { + buf = (char *)calloc(len, sizeof(char)); + if (buf == NULL) { + _LOGE("calloc fail"); + return NULL; + } + ret = read(fd, buf, len); + if (ret < len) { + _LOGE("read error :%d", ret); + if (buf) + free(buf); + return NULL; + } + b = bundle_decode_raw((bundle_raw *)buf, len); + + if (buf) + free(buf); + } else { + _LOGE("__get_bundle_data_from_fd read count : %d", len); + } + + return b; +} + +static data_control_bulk_data_h __get_bulk_data_from_fd(int fd) +{ + data_control_bulk_data_h ret_bulk_data_h = NULL; + int size = 0; + int ret; + int i; + bundle *data = NULL; + + data_control_bulk_data_create(&ret_bulk_data_h); + ret = read(fd, &size, sizeof(int)); + if (ret < sizeof(int)) { + _LOGE("read error :%d", ret); + data_control_bulk_data_destroy(ret_bulk_data_h); + return NULL; + } + + _LOGI("bulk data size : %d", size); + if (size < 0 || size >= MAX_REQUEST_ARGUMENT_SIZE) { + _LOGE("Invalid data size"); + data_control_bulk_data_destroy(ret_bulk_data_h); + return NULL; + } + + for (i = 0; i < size; i++) { + _LOGI("bulk data : %d", i); + data = __get_bundle_data_from_fd(fd); + if (data == NULL) { + _LOGE("get bundle data from fd fail"); + data_control_bulk_data_destroy(ret_bulk_data_h); + return NULL; + } + data_control_bulk_data_add(ret_bulk_data_h, data); + bundle_free(data); + } + return ret_bulk_data_h; +} + +static void __on_name_appeared(GDBusConnection *connection, + const gchar *name, + const gchar *name_owner, + gpointer user_data) +{ + _LOGI("name appeared : %s", name); +} + +static void __on_name_vanished(GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + _LOGI("name vanished : %s", name); + __free_consumer_info(name); +} + +static int __init_changed_noti_consumer_list() +{ + char *app_id = NULL; + char *unique_id = NULL; + char *object_path = NULL; + int ret = DATA_CONTROL_ERROR_NONE; + sqlite3_stmt *stmt = NULL; + char query[QUERY_MAXLEN]; + datacontrol_consumer_info *consumer_info = NULL; + + sqlite3_snprintf(QUERY_MAXLEN, query, + "SELECT app_id, object_path, unique_id " \ + "FROM data_control_consumer_path_list"); + + _LOGI("__init_changed_noti_consumer_list query : %s", query); + ret = sqlite3_prepare_v2(__provider_db, query, -1, &stmt, NULL); + if (ret != SQLITE_OK) { + _LOGE("prepare stmt fail"); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + while (SQLITE_ROW == sqlite3_step(stmt)) { + app_id = (char *)sqlite3_column_text(stmt, 0); + if (!app_id) { + _LOGE("Failed to get package name\n"); + continue; + } + + object_path = (char *)sqlite3_column_text(stmt, 1); + if (!object_path) { + _LOGE("Failed to get object_path\n"); + continue; + } + + unique_id = (char *)sqlite3_column_text(stmt, 2); + if (!unique_id) { + _LOGE("Failed to get unique_id\n"); + continue; + } + _LOGI("sql : app_id : %s, object_path : %s, unique_id : %s", + app_id, object_path, unique_id); + + consumer_info = (datacontrol_consumer_info *) + calloc(1, sizeof(datacontrol_consumer_info)); + consumer_info->appid = strdup(app_id); + consumer_info->object_path = strdup(object_path); + consumer_info->unique_id = strdup(unique_id); + + consumer_info->monitor_id = g_bus_watch_name_on_connection( + _get_dbus_connection(), + consumer_info->unique_id, + G_BUS_NAME_WATCHER_FLAGS_NONE, + __on_name_appeared, + __on_name_vanished, + consumer_info, + NULL); + + if (consumer_info->monitor_id == 0) { + _LOGE("g_bus_watch_name_on_connection fail"); + + free(consumer_info->appid); + free(consumer_info->object_path); + free(consumer_info->unique_id); + free(consumer_info); + continue; + } + + _LOGI("noti consumer_app_list append %s", consumer_info->object_path); + __noti_consumer_app_list = + g_list_append(__noti_consumer_app_list, consumer_info); + } + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + + return ret; +} + +static int __delete_consumer_list_db_info(char *unique_id) +{ + int r; + char *error = NULL; + char query[QUERY_MAXLEN]; + sqlite3_snprintf(QUERY_MAXLEN, query, + "DELETE FROM data_control_consumer_path_list WHERE unique_id = %Q", + unique_id); + _LOGI("consumer list db DELETE : %s, unique_id : %s", query, unique_id); + r = sqlite3_exec(__provider_db, query, NULL, NULL, &error); + if (r != SQLITE_OK) { + _LOGE("sqlite3_exec error(query = %s, error = %s)", query, error); + sqlite3_free(error); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + _LOGI("__delete_consumer_list_db_info done"); + return DATA_CONTROL_ERROR_NONE; +} + + +static int __create_consumer_list_db() +{ + char *db_path = NULL; + int ret = SQLITE_OK; + int open_flags = (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); + char *table_command = + "CREATE TABLE IF NOT EXISTS data_control_consumer_path_list" \ + "(app_id TEXT NOT NULL, provider_id TEXT NOT NULL, "\ + "data_id TEXT NOT NULL, " \ + "unique_id TEXT NOT NULL, object_path TEXT NOT NULL, " \ + "PRIMARY KEY(object_path))"; + + if (__provider_db == NULL) { + db_path = _get_encoded_db_path(); + if (db_path == NULL) + return DATA_CONTROL_ERROR_IO_ERROR; + _LOGI("data-control provider db path : %s", db_path); + + ret = sqlite3_open_v2(db_path, &__provider_db, open_flags, NULL); + free(db_path); + if (ret != SQLITE_OK) { + _LOGE("database creation failed with error: %d", ret); + return DATA_CONTROL_ERROR_IO_ERROR; + } + ret = sqlite3_exec(__provider_db, table_command, NULL, NULL, NULL); + if (ret != SQLITE_OK) { + _LOGE("database table creation failed with error: %d", ret); + return DATA_CONTROL_ERROR_IO_ERROR; + } + ret = __init_changed_noti_consumer_list(); + if (ret != DATA_CONTROL_ERROR_NONE) { + _LOGE("__init_changed_noti_consumer_list fail %d", ret); + return ret; + } + } + return DATA_CONTROL_ERROR_NONE; +} + +static int __get_sender_pid(const char *sender_name) +{ + GDBusMessage *msg = NULL; + GDBusMessage *reply = NULL; + GError *err = NULL; + GVariant *body; + int pid = 0; + + msg = g_dbus_message_new_method_call("org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "GetConnectionUnixProcessID"); + if (!msg) { + _LOGE("Can't allocate new method call"); + goto out; + } + + g_dbus_message_set_body(msg, g_variant_new("(s)", sender_name)); + reply = + g_dbus_connection_send_message_with_reply_sync(_get_dbus_connection(), + msg, + G_DBUS_SEND_MESSAGE_FLAGS_NONE, + -1, + NULL, + NULL, + &err); + + if (!reply) { + if (err != NULL) { + _LOGE("Failed to get pid [%s]", err->message); + g_error_free(err); + } + goto out; + } + + body = g_dbus_message_get_body(reply); + g_variant_get(body, "(u)", &pid); + +out: + if (msg) + g_object_unref(msg); + if (reply) + g_object_unref(reply); + + return pid; +} + +static int __insert_consumer_list_db_info(char *app_id, char *provider_id, + char *data_id, char *unique_id, char *object_path) +{ + int r; + char *error = NULL; + char query[QUERY_MAXLEN]; + sqlite3_snprintf(QUERY_MAXLEN, query, + "INSERT OR REPLACE INTO data_control_consumer_path_list(app_id, " \ + "provider_id, data_id, unique_id, object_path)" \ + "VALUES (%Q, %Q, %Q, %Q, %Q)", + app_id, provider_id, data_id, unique_id, object_path); + _LOGI("consumer list db insert sql : %s", query); + + r = sqlite3_exec(__provider_db, query, NULL, NULL, &error); + if (r != SQLITE_OK) { + _LOGE("sqlite3_exec error(query = %s, error = %s)", query, error); + sqlite3_free(error); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + return DATA_CONTROL_ERROR_NONE; +} + +static int __set_consumer_app_list( + char *caller, + char *object_path, + char *unique_id) +{ + datacontrol_consumer_info find_key; + datacontrol_consumer_info *consumer_info; + GList *find_list = NULL; + int ret = DATA_CONTROL_ERROR_NONE; + _LOGI("set consumer_app_list caller : %s, path : %s, unique_id : %s", + caller, object_path, unique_id); + + find_key.unique_id = unique_id; + find_list = g_list_find_custom(__noti_consumer_app_list, + &find_key, + (GCompareFunc)__noti_consumer_app_list_compare_cb); + + if (!find_list) { + consumer_info = (datacontrol_consumer_info *) + calloc(1, sizeof(datacontrol_consumer_info)); + consumer_info->appid = strdup(caller); + consumer_info->object_path = strdup(object_path); + consumer_info->unique_id = strdup(unique_id); + + consumer_info->monitor_id = g_bus_watch_name_on_connection( + _get_dbus_connection(), + consumer_info->unique_id, + G_BUS_NAME_WATCHER_FLAGS_NONE, + __on_name_appeared, + __on_name_vanished, + consumer_info, + NULL); + if (consumer_info->monitor_id == 0) { + _LOGE("g_bus_watch_name_on_connection fail"); + + free(consumer_info->appid); + free(consumer_info->object_path); + free(consumer_info->unique_id); + free(consumer_info); + + return DATA_CONTROL_ERROR_IO_ERROR; + } + _LOGI("new noti consumer_app_list append %s", + consumer_info->object_path); + __noti_consumer_app_list = + g_list_append(__noti_consumer_app_list, consumer_info); + } + return ret; +} + +static bundle *__set_result(bundle *b, datacontrol_request_type type, void *data) +{ + bundle *res = bundle_create(); + + /* Set the type */ + char type_str[MAX_LEN_DATACONTROL_REQ_TYPE] = {0,}; + const char *request_type; + const char *provider_id; + const char *data_id; + const char *request_id; + const char *caller_appid; + const char *list[3]; + const char *page_num = bundle_get_val(b, RESULT_PAGE_NUMBER); + const char *count_per_page = bundle_get_val(b, MAX_COUNT_PER_PAGE); + + if (type == DATACONTROL_TYPE_UNDEFINED || type == DATACONTROL_TYPE_ERROR) { + request_type = bundle_get_val(b, OSP_K_DATACONTROL_REQUEST_TYPE); + if (request_type) + strncpy(type_str, request_type, MAX_LEN_DATACONTROL_REQ_TYPE); + _LOGI("type is %s", type_str); + + } else { + snprintf(type_str, MAX_LEN_DATACONTROL_REQ_TYPE, "%d", (int)type); + } + + bundle_add_str(res, OSP_K_DATACONTROL_REQUEST_TYPE, type_str); + + /* Set the provider id */ + provider_id = bundle_get_val(b, OSP_K_DATACONTROL_PROVIDER); + bundle_add_str(res, OSP_K_DATACONTROL_PROVIDER, provider_id); + + /* Set the data id */ + data_id = bundle_get_val(b, OSP_K_DATACONTROL_DATA); + bundle_add_str(res, OSP_K_DATACONTROL_DATA, data_id); + + /* Set the caller request id */ + request_id = bundle_get_val(b, OSP_K_REQUEST_ID); + bundle_add_str(res, OSP_K_REQUEST_ID, request_id); + + caller_appid = bundle_get_val(b, AUL_K_CALLER_APPID); + bundle_add_str(res, AUL_K_CALLER_APPID, caller_appid); + + switch (type) { + case DATACONTROL_TYPE_SQL_SELECT: + { + list[PACKET_INDEX_REQUEST_RESULT] = "1"; /* request result */ + list[PACKET_INDEX_ERROR_MSG] = DATACONTROL_EMPTY; + list[PACKET_INDEX_SELECT_RESULT_FILE] = DATACONTROL_EMPTY; + + page_num = bundle_get_val(b, RESULT_PAGE_NUMBER); + count_per_page = bundle_get_val(b, MAX_COUNT_PER_PAGE); + + _LOGI("page num: %s, count_per_page: %s", page_num, count_per_page); + + bundle_add_str(res, RESULT_PAGE_NUMBER, page_num); + bundle_add_str(res, MAX_COUNT_PER_PAGE, count_per_page); + + bundle_add_str_array(res, OSP_K_ARG, list, 3); + + break; + } + case DATACONTROL_TYPE_SQL_BULK_INSERT: + { + list[PACKET_INDEX_REQUEST_RESULT] = "1"; /* request result */ + list[PACKET_INDEX_ERROR_MSG] = DATACONTROL_EMPTY; + bundle_add_str_array(res, OSP_K_ARG, list, 2); + break; + } + case DATACONTROL_TYPE_SQL_INSERT: + { + long long row_id = *(long long *)data; + + const char *list[3]; + list[PACKET_INDEX_REQUEST_RESULT] = "1"; /* request result */ + list[PACKET_INDEX_ERROR_MSG] = DATACONTROL_EMPTY; + + /* Set the row value */ + char row_str[ROW_ID_SIZE] = {0,}; + snprintf(row_str, ROW_ID_SIZE, "%lld", row_id); + + list[PACKET_INDEX_ROW_ID] = row_str; + bundle_add_str_array(res, OSP_K_ARG, list, 3); + break; + } + case DATACONTROL_TYPE_SQL_UPDATE: + case DATACONTROL_TYPE_SQL_DELETE: + { + const char *list[2]; + list[PACKET_INDEX_REQUEST_RESULT] = "1"; /* request result */ + list[PACKET_INDEX_ERROR_MSG] = DATACONTROL_EMPTY; + + bundle_add_str_array(res, OSP_K_ARG, list, 2); + break; + } + case DATACONTROL_TYPE_MAP_BULK_ADD: + { + list[PACKET_INDEX_REQUEST_RESULT] = "1"; /* request result */ + list[PACKET_INDEX_ERROR_MSG] = DATACONTROL_EMPTY; + bundle_add_str_array(res, OSP_K_ARG, list, 2); + break; + } + case DATACONTROL_TYPE_MAP_GET: + { + const char *list[4]; + list[PACKET_INDEX_REQUEST_RESULT] = "1"; /* request result */ + list[PACKET_INDEX_ERROR_MSG] = DATACONTROL_EMPTY; + + bundle_add_str_array(res, OSP_K_ARG, list, 2); + const char *page_num = bundle_get_val(b, RESULT_PAGE_NUMBER); + const char *count_per_page = bundle_get_val(b, MAX_COUNT_PER_PAGE); + const char *value_count = bundle_get_val(b, RESULT_VALUE_COUNT); + + bundle_add_str(res, RESULT_PAGE_NUMBER, page_num); + bundle_add_str(res, MAX_COUNT_PER_PAGE, count_per_page); + bundle_add_str(res, RESULT_VALUE_COUNT, value_count); + + break; + } + case DATACONTROL_TYPE_ADD_DATA_CHANGED_CB: + { + const char *list[2]; + char result_str[2] = {0,}; + bool result = *(bool *)data; + snprintf(result_str, 2, "%d", result); + + list[PACKET_INDEX_REQUEST_RESULT] = result_str; /* request result */ + list[PACKET_INDEX_ERROR_MSG] = DATACONTROL_EMPTY; + + bundle_add_str_array(res, OSP_K_ARG, list, 2); + break; + } + case DATACONTROL_TYPE_UNDEFINED: /* DATACONTROL_TYPE_MAP_SET || ADD || REMOVE */ + { + const char *list[2]; + list[PACKET_INDEX_REQUEST_RESULT] = "1"; /* request result */ + list[PACKET_INDEX_ERROR_MSG] = DATACONTROL_EMPTY; + + bundle_add_str_array(res, OSP_K_ARG, list, 2); + break; + } + default: /* Error */ + { + const char *list[2]; + list[PACKET_INDEX_REQUEST_RESULT] = "0"; /* request result */ + list[PACKET_INDEX_ERROR_MSG] = (char *)data; /* error string */ + + bundle_add_str_array(res, OSP_K_ARG, list, 2); + break; + } + } + + return res; +} + +static int __send_select_result(int fd, bundle *b, void *data) +{ + /* + In this function, the result set is written in socket as specific form. + [sizeof(int)] column count + [sizeof(int)] column type x N + [ variant ] (column name leng, column name) x N + [sieeof(int)] total size of column names + [sizeof(int)] row count + [ variant ] (type, size, content) x N + */ + + sqlite3_stmt *state = (sqlite3_stmt *)data; + int column_count = DATACONTROL_RESULT_NO_DATA; + int i = 0; + char *column_name = NULL; + int total_len_of_column_names = 0; + int count_per_page = 0; + int page_number = 1; + int offset = 0; + sqlite3_int64 offset_idx = 0; + sqlite3_int64 row_count = 0; + unsigned int nb = 0; + int type = 0; + int column_name_len; + const char *page_number_str; + int size = 0; + void *value = NULL; + int column_type; + long long tmp_long = 0; + double tmp_double = 0.0; + void *buf = NULL; + int buf_len = 0; + const char *count_per_page_str; + + _LOGI("__send_select_result"); + if (b == NULL || data == NULL) { + _LOGE("The input param is invalid."); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + if (sqlite3_reset(state) != SQLITE_OK) { + _LOGE("sqlite3_reset() is failed."); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + if (sqlite3_step(state) != SQLITE_ROW) { + _LOGE("The DB does not have another row."); + if (_write_socket(fd, &column_count, sizeof(int), &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGE("Writing a column_count to a file descriptor is failed."); + return DATA_CONTROL_ERROR_IO_ERROR; + } + return DATA_CONTROL_ERROR_NONE; + } + + /* 1. column count */ + column_count = sqlite3_column_count(state); + if (_write_socket(fd, &column_count, sizeof(int), &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGE("Writing a column_count to a file descriptor is failed. errno = %d", errno); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + _LOGI("Writing a column_count %d", column_count); + + /* + 2. column type x column_count + #define SQLITE_INTEGER 1 + #define SQLITE_FLOAT 2 + #define SQLITE_TEXT 3 + #define SQLITE_BLOB 4 + #define SQLITE_NULL 5 + */ + for (i = 0; i < column_count; i++) { + type = sqlite3_column_type(state, i); + if (_write_socket(fd, &type, sizeof(int), &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGI("Writing a type to a file descriptor is failed."); + return DATA_CONTROL_ERROR_IO_ERROR; + } + _LOGI("Writing a column_type %d", type); + } + + /* 3. column name x column_count */ + for (i = 0; i < column_count; i++) { + column_name = (char *)sqlite3_column_name(state, i); + if (column_name == NULL) { + _LOGI("sqlite3_column_name is failed. errno = %d", errno); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } else { + column_name_len = strlen(column_name) + 1; + if (_write_socket(fd, &column_name_len, sizeof(int), &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGI("Writing a column_name_len to a file descriptor is failed. errno = %d", errno); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + _LOGI("Writing a column_name_len %d", column_name_len); + + if (_write_socket(fd, column_name, column_name_len, &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGI("Writing a column_name to a file descriptor is failed. errno = %d", errno); + return DATA_CONTROL_ERROR_IO_ERROR; + } + total_len_of_column_names += strlen(column_name); + _LOGI("Writing a column_name %s", column_name); + } + } + + /* 4. total length of column names */ + if (_write_socket(fd, &total_len_of_column_names, sizeof(int), &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGI("Writing a total_len_of_column_names to a file descriptor is failed. errno = %d", errno); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + _LOGI("Writing a total_len_of_column_names %d", total_len_of_column_names); + + page_number_str = bundle_get_val(b, RESULT_PAGE_NUMBER); + count_per_page_str = bundle_get_val(b, MAX_COUNT_PER_PAGE); + + _LOGI("page_number: %s, per_page: %s", page_number_str, count_per_page_str); + + /* 5. type, size and value of each element */ + if (page_number_str != NULL) + page_number = atoi(page_number_str); + else + page_number = 1; + + if (count_per_page_str != NULL) + count_per_page = atoi(count_per_page_str); + else + count_per_page = 20; + + offset = (page_number - 1) * count_per_page; + + _LOGI("page_number: %d, count_per_page: %d, offset: %d", + page_number, count_per_page, offset); + + if (sqlite3_reset(state) != SQLITE_OK) { + _LOGE("sqlite3_reset() is failed."); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + if (sqlite3_step(state) != SQLITE_ROW) { + _LOGE("The DB does not have another row."); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + do { + offset_idx++; + if (offset_idx > offset) + ++row_count; + } while (sqlite3_step(state) == SQLITE_ROW && row_count < count_per_page); + + /* 6. row count */ + if (_write_socket(fd, &row_count, sizeof(row_count), &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGI("Writing a row_count to a file descriptor is failed. errno = %d", errno); + return DATA_CONTROL_ERROR_IO_ERROR; + } + _LOGI("Writing a row_count %lld", row_count); + + row_count = 0; + offset_idx = 0; + if (sqlite3_reset(state) != SQLITE_OK) { + _LOGI("sqlite3_reset() is failed."); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + if (sqlite3_step(state) != SQLITE_ROW) { + _LOGE("The DB does not have another row."); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + do { + offset_idx++; + if (offset_idx > offset) { + ++row_count; + for (i = 0; i < column_count; ++i) { + column_type = sqlite3_column_type(state, i); + + switch (column_type) { + case SQLITE_INTEGER: + type = 1; + size = sizeof(long long); + tmp_long = sqlite3_column_int64(state, i); + value = &tmp_long; + break; + case SQLITE_FLOAT: + type = 2; + size = sizeof(double); + tmp_double = sqlite3_column_double(state, i); + value = &tmp_double; + break; + case SQLITE_TEXT: + type = 3; + value = (char *)sqlite3_column_text(state, i); + if (value) + size = strlen(value) + 1; + else + size = 0; + break; + case SQLITE_BLOB: + type = 4; + size = sqlite3_column_bytes(state, i); + value = (char *)sqlite3_column_blob(state, i); + break; + case SQLITE_NULL: + type = 5; + size = 0; + break; + default: + _LOGI("The column type is invalid."); + break; + } + + if (value == NULL && type != 5) + return DATA_CONTROL_ERROR_IO_ERROR; + + buf_len = sizeof(int) * 2 + size; + buf = calloc(buf_len, sizeof(void)); + if (buf == NULL) { + _LOGE("calloc failed"); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } + memcpy(buf, &type, sizeof(int)); + memcpy(buf + sizeof(int), &size, sizeof(int)); + if (size > 0) + memcpy(buf + sizeof(int) + sizeof(int), value, size); + + if (_write_socket(fd, buf, buf_len, &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGE("Writing a size to a file descriptor is failed. errno = %d", errno); + free(buf); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + free(buf); + + } + _LOGI("row_count ~~~~ %lld", row_count); + + } + + } while (sqlite3_step(state) == SQLITE_ROW && row_count < count_per_page); + + return DATA_CONTROL_ERROR_NONE; +} + +static int __send_get_value_result(int fd, bundle *b, void *data) +{ + int i = 0; + char **value_list = (char **)data; + const char *page_num_str = bundle_get_val(b, RESULT_PAGE_NUMBER); + const char *count_per_page_str = bundle_get_val(b, MAX_COUNT_PER_PAGE); + const char *value_count_str = bundle_get_val(b, RESULT_VALUE_COUNT); + int page_number = 0; + int count_per_page = 0; + int value_count = 0; + int current_offset = 0; + int remain_count = 0; + unsigned int nb; + int add_value_count; + int length; + + _LOGI("page num: %s, count_per_page: %s, value_count %s", + page_num_str, count_per_page_str, value_count_str); + + if (page_num_str) + page_number = __get_int_from_str(page_num_str); + if (count_per_page_str) + count_per_page = __get_int_from_str(count_per_page_str); + if (value_count_str) + value_count = __get_int_from_str(value_count_str); + + current_offset = (page_number - 1) * count_per_page; + remain_count = value_count - current_offset; + remain_count = (remain_count > 0) ? remain_count : 0; /* round off to zero if the negative num is found */ + + add_value_count = + (count_per_page > remain_count) ? remain_count : count_per_page; + + _LOGI("add_value_count: %d, current_offset: %d, remain_count %d", + add_value_count, current_offset, remain_count); + + if (_write_socket(fd, &add_value_count, sizeof(int), &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGE("Writing a length to a file descriptor is failed. errno = %d", errno); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + add_value_count += current_offset; + + for (i = current_offset; i < add_value_count; i++) { + length = strlen(value_list[i]); + _LOGI("length = %d", length); + if (_write_socket(fd, &length, sizeof(int), &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGE("Writing a length to a file descriptor is failed. errno = %d", errno); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + _LOGI("value_list = %s", value_list[i]); + if (_write_socket(fd, value_list[i], length, &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGE("Writing a value_list to a file descriptor is failed. errno = %d", errno); + return DATA_CONTROL_ERROR_IO_ERROR; + } + } + return DATA_CONTROL_ERROR_NONE; +} + +static int __send_bulk_result(int fd, void *data) +{ + data_control_bulk_result_data_h bulk_results = + (data_control_bulk_result_data_h)data; + int count; + int i; + int result; + bundle_raw *encode_data = NULL; + int encode_datalen = 0; + bundle *result_data; + unsigned int nb = 0; + + data_control_bulk_result_data_get_count(bulk_results, &count); + if (_write_socket(fd, &count, sizeof(int), &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGE("Writing a result count to a file descriptor is failed. errno = %d", errno); + return DATA_CONTROL_ERROR_IO_ERROR; + } + LOGD("__send_bulk_result %d", count); + + for (i = 0; i < count; i++) { + data_control_bulk_result_data_get_result_data(bulk_results, i, + &result_data, &result); + if (_write_socket(fd, &result, sizeof(int), &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGE("Writing a result to a file descriptor is failed. errno = %d", errno); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + if (result_data != NULL) { + bundle_encode_raw(result_data, &encode_data, &encode_datalen); + if (encode_data == NULL) { + _LOGE("bundle encode error"); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } + } + + if (_write_socket(fd, &encode_datalen, sizeof(int), &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGE("Writing a encode_datalen to a file descriptor is failed. errno = %d", errno); + free(encode_data); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + if (_write_socket(fd, encode_data, encode_datalen, &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGE("Writing a encode_data to a file descriptor is failed. errno = %d", errno); + free(encode_data); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + _LOGE("result %d, encode_datalen %d", result, encode_datalen); + free(encode_data); + encode_data = NULL; + encode_datalen = 0; + } + return DATA_CONTROL_ERROR_NONE; +} + +int __datacontrol_send_async(int sockfd, bundle *kb, + datacontrol_request_type type, void *data) +{ + bundle_raw *kb_data = NULL; + int ret = DATA_CONTROL_ERROR_NONE; + int datalen = 0; + char *buf; + int total_len = 0; + unsigned int nb = 0; + + _LOGI("send async ~~~"); + bundle_encode_raw(kb, &kb_data, &datalen); + if (kb_data == NULL) { + _LOGE("bundle encode error"); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } + + /* encoded bundle + encoded bundle len */ + buf = (char *)calloc(datalen + 4, sizeof(char)); + if (buf == NULL) { + _LOGE("buf calloc error"); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } + memcpy(buf, &datalen, sizeof(datalen)); + memcpy(buf + sizeof(datalen), kb_data, datalen); + + total_len = sizeof(datalen) + datalen; + + _LOGI("write : %d", datalen); + if (_write_socket(sockfd, buf, total_len, &nb) != DATA_CONTROL_ERROR_NONE) { + _LOGI("write data fail "); + ret = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + + if (DATACONTROL_TYPE_SQL_SELECT == type) + ret = __send_select_result(sockfd, kb, data); + else if (DATACONTROL_TYPE_MAP_GET == type) + ret = __send_get_value_result(sockfd, kb, data); + else if (DATACONTROL_TYPE_SQL_BULK_INSERT == type || + DATACONTROL_TYPE_MAP_BULK_ADD == type) + ret = __send_bulk_result(sockfd, data); + +out: + free(buf); + bundle_free_encoded_rawdata(&kb_data); + + return ret; +} + +static int __send_result(bundle *b, datacontrol_request_type type, void *data) +{ + datacontrol_socket_info *socket_info; + char *caller_app_id = (char *)bundle_get_val(b, AUL_K_CALLER_APPID); + int ret = DATA_CONTROL_ERROR_NONE; + + _LOGI("__datacontrol_send_async caller_app_id : %s ", caller_app_id); + + socket_info = g_hash_table_lookup(__socket_pair_hash, caller_app_id); + if (socket_info == NULL) { + _LOGE("__socket_pair_hash lookup fail"); + return DATA_CONTROL_ERROR_IO_ERROR; + } + ret = __datacontrol_send_async(socket_info->socket_fd, b, type, data); + _LOGI("__datacontrol_send_async result : %d ", ret); + if (ret != DATA_CONTROL_ERROR_NONE) + g_hash_table_remove(__socket_pair_hash, caller_app_id); + + return ret; +} + +static int __send_add_callback_result( + data_control_data_change_type_e result_type, + char *unique_id, + char *path, + int callback_id, + int callback_result) +{ + GError *err = NULL; + int result = DATA_CONTROL_ERROR_NONE; + gboolean signal_result = TRUE; + _LOGI("add callback_result type : %d, callback_id : %d, result : %d", + result_type, callback_id, callback_result); + + signal_result = g_dbus_connection_emit_signal( + _get_dbus_connection(), + unique_id, + path, + DATA_CONTROL_INTERFACE_NAME, + DATA_CONTROL_DATA_CHANGE_ADD_REMOVE_RESULT, + g_variant_new("(iii)", + result_type, + callback_id, + callback_result), &err); + if (signal_result == FALSE) { + _LOGE("g_dbus_connection_emit_signal() is failed"); + if (err != NULL) { + _LOGE("g_dbus_connection_emit_signal() err : %s", + err->message); + g_error_free(err); + } + return DATA_CONTROL_ERROR_IO_ERROR; + } + + _LOGI("Send __send_add_callback_result done %d", result); + return result; +} + +static int __provider_noti_process(bundle *b, datacontrol_request_type type) +{ + data_control_h provider = NULL; + bool noti_allow = true; + char *path = NULL; + int result = DATA_CONTROL_ERROR_NONE; + char *unique_id = NULL; + datacontrol_data_change_type_e result_type = + DATACONTROL_DATA_CHANGE_CALLBACK_ADD_RESULT; + char *callback_id_str = NULL; + int callback_id = -1; + GList *filter_iter; + changed_noti_consumer_filter_info_s *filter_info; + char caller_app_id[255]; + const char *pid_str; + int pid; + int sender_pid; + + pid_str = bundle_get_val(b, AUL_K_CALLER_PID); + if (pid_str == NULL) { + _LOGE("fail to get caller pid"); + result = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + pid = atoi(pid_str); + if (pid <= 1) { + _LOGE("invalid caller pid %s", pid_str); + result = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + if (aul_app_get_appid_bypid(pid, caller_app_id, sizeof(caller_app_id)) != 0) { + _LOGE("Failed to get appid by pid"); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + unique_id = (char *)bundle_get_val(b, OSP_K_DATACONTROL_UNIQUE_NAME); + _LOGI("unique_id : %s", unique_id); + sender_pid = __get_sender_pid(unique_id); + if (sender_pid != pid) { + _LOGE("invalid unique id. sender does not have unique_id %s", unique_id); + return DATA_CONTROL_ERROR_PERMISSION_DENIED; + } + + result = __create_consumer_list_db(); + if (result != DATA_CONTROL_ERROR_NONE) { + _LOGE("fail to create consumer list db"); + return result; + } + + provider = malloc(sizeof(struct data_control_s)); + if (provider == NULL) { + _LOGE("Out of memory. fail to alloc provider."); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } + provider->provider_id = + (char *)bundle_get_val(b, OSP_K_DATACONTROL_PROVIDER); + provider->data_id = (char *)bundle_get_val(b, OSP_K_DATACONTROL_DATA); + if (provider->provider_id == NULL || provider->data_id == NULL) { + _LOGE("invalid provider value %s, %s", + provider->provider_id, provider->data_id); + free(provider); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + _LOGI("Noti Provider ID: %s, data ID: %s, request type: %d", + provider->provider_id, provider->data_id, type); + path = _get_encoded_path(provider, caller_app_id); + if (path == NULL) { + _LOGE("can not get encoded path out of memory"); + free(provider); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } + + callback_id_str = (char *)bundle_get_val(b, OSP_K_DATA_CHANGED_CALLBACK_ID); + if (callback_id_str == NULL) { + _LOGE("callback_id is NULL"); + result = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + callback_id = atoi(callback_id_str); + + switch (type) { + case DATACONTROL_TYPE_ADD_DATA_CHANGED_CB: + { + _LOGI("DATACONTROL_TYPE_ADD_DATA_CHANGED_CB called"); + result_type = DATACONTROL_DATA_CHANGE_CALLBACK_ADD_RESULT; + filter_iter = g_list_first(__noti_consumer_filter_info_list); + for (; filter_iter != NULL; filter_iter = filter_iter->next) { + filter_info = + (changed_noti_consumer_filter_info_s *)filter_iter->data; + noti_allow = filter_info->callback( + (data_control_h)provider, + caller_app_id, + filter_info->user_data); + if (!noti_allow) + break; + } + _LOGI("provider_sql_consumer_filter_cb result %d", noti_allow); + + if (noti_allow) { + result = __insert_consumer_list_db_info( + caller_app_id, + provider->provider_id, + provider->data_id, + unique_id, + path); + if (result != DATA_CONTROL_ERROR_NONE) { + _LOGE("fail to set consumer list db info %d", result); + result = DATA_CONTROL_ERROR_PERMISSION_DENIED; + break; + } + + result = __set_consumer_app_list( + caller_app_id, + path, + unique_id); + if (result != DATA_CONTROL_ERROR_NONE) + _LOGE("fail to __set_consumer_app_list"); + + } else { + result = DATA_CONTROL_ERROR_PERMISSION_DENIED; + break; + } + break; + } + case DATACONTROL_TYPE_REMOVE_DATA_CHANGED_CB: + { + _LOGI("DATACONTROL_NOTI_REMOVE_DATA_CHANGED_CB called"); + result_type = DATACONTROL_DATA_CHANGE_CALLBACK_REMOVE_RESULT; + if (__noti_consumer_app_list) { + __free_consumer_info(unique_id); + _LOGI("unregister %s from __noti_consumer_app_list", unique_id); + } else { + _LOGI("empty __consumer_app_list"); + } + result = __delete_consumer_list_db_info(unique_id); + if (result != DATA_CONTROL_ERROR_NONE) { + _LOGE("__delete_consumer_list_db_info fail %d", result); + result = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + break; + } + default: + break; + } -#include "data_control_provider.h" -#include "data_control_sql.h" -#include "data_control_log.h" -#include "data_control_internal.h" -#include "data-control-internal.h" +out: + __send_add_callback_result( + result_type, unique_id, path, callback_id, result); -#define INSERT_STMT_CONST_LEN 25 -#define DELETE_STMT_CONST_LEN 12 -#define UPDATE_STMT_CONST_LEN 15 -#define SELECT_STMT_CONST_LEN 13 -#define WHERE_COND_CONST_LEN 7 -#define ORDER_CLS_CONST_LEN 10 + if (provider) + free(provider); + if (path) + free(path); + + return result; +} -struct data_control_s { +int __provider_process(bundle *b, int fd, const char *consumer_appid) +{ + int ret; + int len = 0; + const char **arg_list = NULL; + const char **column_list = NULL; + data_control_h provider = NULL; + int provider_req_id = 0; + int *key = NULL; + bool is_map; char *provider_id; - char *data_id; -}; + char *caller_appid; + bundle *value = NULL; -typedef struct { - int no_of_elements; - int length; - char **keys; - char **vals; -} key_val_pair; + const char *request_type = + bundle_get_val(b, OSP_K_DATACONTROL_REQUEST_TYPE); + if (request_type == NULL) { + _LOGE("Invalid data control request"); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } -static data_control_provider_sql_cb sql_provider_callback; -static data_control_provider_map_cb map_provider_callback; -static data_control_provider_bulk_cb sql_provider_bulk_callback; -static data_control_provider_bulk_cb map_provider_bulk_callback; -static void *sql_bulk_callback_user_data = NULL; -static void *map_bulk_callback_user_data = NULL; + /* Get the request type */ + datacontrol_request_type type = atoi(request_type); + if (type >= DATACONTROL_TYPE_SQL_SELECT && + type <= DATACONTROL_TYPE_SQL_BULK_INSERT) { + is_map = false; + } else if (type >= DATACONTROL_TYPE_MAP_GET && + type <= DATACONTROL_TYPE_MAP_BULK_ADD) { + is_map = true; + } else { + _LOGE("Invalid request type"); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } -datacontrol_provider_sql_cb sql_internal_callback; -datacontrol_provider_map_cb map_internal_callback; + caller_appid = (char *)bundle_get_val(b, AUL_K_CALLER_APPID); + if (caller_appid && strncmp(caller_appid, + consumer_appid, strlen(consumer_appid)) != 0) { + _LOGE("The passed appid(%s) is different from the registered appid(%s).", + caller_appid, consumer_appid); + return DATA_CONTROL_ERROR_NONE; + } -static void __sql_insert_request_cb(int request_id, datacontrol_h provider, bundle *insert_data, void *user_data) -{ - _LOGI("sql_insert_request"); + provider_id = (char *)bundle_get_val(b, OSP_K_DATACONTROL_PROVIDER); + ret = _check_cert(provider_id, is_map, consumer_appid); + if (ret != DATA_CONTROL_ERROR_NONE) { + if (ret == DATA_CONTROL_ERROR_PERMISSION_DENIED) { + _LOGE("The consumer (%s) is not signed with the same certificate", + consumer_appid); + return DATA_CONTROL_ERROR_NONE; + } else { + return DATA_CONTROL_ERROR_IO_ERROR; + } + } - if (sql_provider_callback.insert_cb) - sql_provider_callback.insert_cb(request_id, (data_control_h)provider, insert_data, user_data); -} + arg_list = bundle_get_str_array(b, OSP_K_ARG, &len); -static void __sql_bulk_insert_request_cb(int request_id, datacontrol_h provider, data_control_bulk_data_h bulk_data, void *user_data) -{ - _LOGI("sql_bulk_insert_request"); + provider = malloc(sizeof(struct data_control_s)); + if (provider == NULL) { + _LOGE("Out of memory. fail to alloc provider."); + return DATA_CONTROL_ERROR_IO_ERROR; + } - if (sql_provider_bulk_callback) - sql_provider_bulk_callback(request_id, (data_control_h)provider, bulk_data, user_data); -} + /* Set the provider ID */ + provider->provider_id = provider_id; + /* Set the data ID */ + provider->data_id = (char *)arg_list[PACKET_INDEX_DATAID]; -static void __sql_update_request_cb(int request_id, datacontrol_h provider, bundle *update_data, const char *where, void *user_data) -{ - _LOGI("sql_update_request"); + /* Set the request ID */ + provider_req_id = __provider_new_request_id(); - if (sql_provider_callback.update_cb) - sql_provider_callback.update_cb(request_id, (data_control_h)provider, update_data, where, user_data); -} + _LOGI("Provider ID: %s, data ID: %s, request type: %s", + provider->provider_id, provider->data_id, request_type); -static void __sql_delete_request_cb(int request_id, datacontrol_h provider, const char *where, void *user_data) -{ - _LOGI("sql_delete_request"); + /* Add the data to the table */ + key = malloc(sizeof(int)); + if (key == NULL) { + _LOGE("Out of memory. fail to malloc key"); + goto err; + } + *key = provider_req_id; - if (sql_provider_callback.delete_cb) - sql_provider_callback.delete_cb(request_id, (data_control_h)provider, where, user_data); -} + value = bundle_dup(b); + if (value == NULL) { + _LOGE("Fail to dup value"); + goto err; + } + g_hash_table_insert(__request_table, key, value); + + switch (type) { + case DATACONTROL_TYPE_SQL_SELECT: + { + int i = 1; + int current = 0; + int column_count = __get_int_from_str(arg_list[i++]); /* Column count */ + + if (column_count <= 0 || column_count > MAX_COLUMN_COUNT) { + _LOGE("Invalid column count %d", column_count); + goto err; + } -static void __sql_select_request_cb(int request_id, datacontrol_h provider, const char **column_list, int column_count, const char *where, const char *order, void *user_data) -{ - _LOGI("sql_select_request"); + _LOGI("SELECT column count: %d", column_count); + column_list = (const char **)malloc(column_count * (sizeof(char *))); + if (column_list == NULL) { + _LOGE("Out of memory. Fail to malloc column_list."); + goto err; + } - if (sql_provider_callback.select_cb) - sql_provider_callback.select_cb(request_id, (data_control_h)provider, column_list, column_count, where, order, user_data); -} + while (current < column_count) { + column_list[current++] = arg_list[i++]; /* Column data */ + _LOGI("Column %d: %s", current, column_list[current-1]); + } -static void __map_get_request_cb(int request_id, datacontrol_h provider, const char *key, void *user_data) -{ - _LOGI("map_get_request"); + const char *where = arg_list[i++]; /* where */ + const char *order = arg_list[i++]; /* order */ + _LOGI("where: %s, order: %s", where, order); + + if (strncmp(where, DATACONTROL_EMPTY, strlen(DATACONTROL_EMPTY)) == 0) + where = NULL; + + if (strncmp(order, DATACONTROL_EMPTY, strlen(DATACONTROL_EMPTY)) == 0) + order = NULL; + + const char *page_number = arg_list[i++]; + const char *per_page = arg_list[i]; + + _LOGI("page_number: %s, per_page: %s", page_number, per_page); + bundle_add_str(value, RESULT_PAGE_NUMBER, page_number); + bundle_add_str(value, MAX_COUNT_PER_PAGE, per_page); + if (sql_callback.select_cb) { + sql_callback.select_cb( + provider_req_id, + provider, + column_list, + column_count, + where, + order, + sql_user_data); + } else { + _LOGE("sql_callback.select_cb is NULL"); + } + free(column_list); + break; + } + case DATACONTROL_TYPE_SQL_INSERT: + case DATACONTROL_TYPE_SQL_UPDATE: + { + _LOGI("INSERT / UPDATE handler"); + bundle *sql = __get_bundle_data_from_fd(fd); + if (sql == NULL) { + _LOGE("__get_bundle_data_from_fd fail"); + goto err; + } + if (type == DATACONTROL_TYPE_SQL_INSERT) { + if (sql_callback.insert_cb) { + sql_callback.insert_cb( + provider_req_id, + provider, + sql, + sql_user_data); + } else { + _LOGE("sql_callback.insert_cb is NULL"); + } + } else { + const char *where = arg_list[PACKET_INDEX_UPDATEWHERE]; + _LOGI("UPDATE from where: %s", where); + if (strncmp(where, DATACONTROL_EMPTY, strlen(DATACONTROL_EMPTY)) == 0) + where = NULL; + if (sql_callback.update_cb) { + sql_callback.update_cb( + provider_req_id, + provider, + sql, + where, + sql_user_data); + } else { + _LOGE("sql_callback.update_cb is NULL"); + } + } + bundle_free(sql); + break; + } + case DATACONTROL_TYPE_SQL_BULK_INSERT: + { + _LOGI("BULK INSERT handler"); + data_control_bulk_data_h data = __get_bulk_data_from_fd(fd); + if (data == NULL) { + _LOGE("__get_bulk_data_from_fd fail"); + goto err; + } - if (map_provider_callback.get_cb) - map_provider_callback.get_cb(request_id, (data_control_h)provider, key, user_data); -} + if (sql_bulk_callback) { + sql_bulk_callback( + provider_req_id, + provider, + data, + sql_bulk_callback_user_data); + } else { + _LOGE("sql_bulk_callback is NULL"); + } -static void __map_set_request_cb(int request_id, datacontrol_h provider, const char *key, const char *old_value, const char *new_value, void *user_data) -{ - _LOGI("map_set_request"); + data_control_bulk_data_destroy(data); + break; + } + case DATACONTROL_TYPE_SQL_DELETE: + { + const char *where = arg_list[PACKET_INDEX_DELETEWHERE]; + _LOGI("DELETE from where: %s", where); + if (strncmp(where, DATACONTROL_EMPTY, strlen(DATACONTROL_EMPTY)) == 0) + where = NULL; + if (sql_callback.delete_cb) { + sql_callback.delete_cb( + provider_req_id, + provider, + where, + sql_user_data); + } else { + _LOGE("sql_callback.delete_cb is NULL"); + } + break; + } + case DATACONTROL_TYPE_MAP_GET: + { + const char *map_key = arg_list[PACKET_INDEX_MAP_KEY]; + const char *page_number = arg_list[PACKET_INDEX_MAP_PAGE_NO]; + const char *count_per_page = arg_list[PACKET_INDEX_MAP_COUNT_PER_PAGE]; + bundle_add_str(value, RESULT_PAGE_NUMBER, page_number); + bundle_add_str(value, MAX_COUNT_PER_PAGE, count_per_page); + _LOGI("Gets the value list related with the key(%s) from Map datacontrol. ", map_key); + if (map_callback.get_cb) { + map_callback.get_cb( + provider_req_id, + provider, + map_key, + map_user_data); + } else { + _LOGE("map_callback.get_cb is NULL"); + } + break; + } + case DATACONTROL_TYPE_MAP_SET: + { + const char *map_key = arg_list[PACKET_INDEX_MAP_KEY]; + const char *old_value = arg_list[PACKET_INDEX_MAP_VALUE_1ST]; + const char *new_value = arg_list[PACKET_INDEX_MAP_VALUE_2ND]; + _LOGI("Sets the old value(%s) of the key(%s) to the new value(%s) in Map datacontrol.", old_value, map_key, new_value); + if (map_callback.set_cb) { + map_callback.set_cb( + provider_req_id, + provider, + map_key, + old_value, + new_value, + map_user_data); + } else { + _LOGE("map_callback.set_cb is NULL"); + } + break; + } + case DATACONTROL_TYPE_MAP_ADD: + { + const char *map_key = arg_list[PACKET_INDEX_MAP_KEY]; + const char *map_value = arg_list[PACKET_INDEX_MAP_VALUE_1ST]; + _LOGI("Adds the %s-%s in Map datacontrol.", map_key, map_value); + if (map_callback.add_cb) { + map_callback.add_cb( + provider_req_id, + provider, + map_key, + map_value, + map_user_data); + } else { + _LOGE("map_callback.add_cb is NULL"); + } + break; + } + case DATACONTROL_TYPE_MAP_BULK_ADD: + { + _LOGI("BULK ADD handler"); + data_control_bulk_data_h data = __get_bulk_data_from_fd(fd); + if (data == NULL) { + _LOGE("__get_bulk_data_from_fd fail"); + goto err; + } - if (map_provider_callback.set_cb) - map_provider_callback.set_cb(request_id, (data_control_h)provider, key, old_value, new_value, user_data); -} + if (map_bulk_callback) { + map_bulk_callback(provider_req_id, + provider, + data, + map_bulk_callback_user_data); + _LOGI("bulk_add callback call done"); + } else { + _LOGE("map_bulk_callback is NULL"); + } -static void __map_add_request_cb(int request_id, datacontrol_h provider, const char *key, const char *value, void *user_data) -{ - _LOGI("map_add_request"); + data_control_bulk_data_destroy(data); + break; + } + case DATACONTROL_TYPE_MAP_REMOVE: + { + const char *map_key = arg_list[PACKET_INDEX_MAP_KEY]; + const char *map_value = arg_list[PACKET_INDEX_MAP_VALUE_1ST]; + _LOGI("Removes the %s-%s in Map datacontrol.", map_key, map_value); + if (map_callback.remove_cb) { + map_callback.remove_cb( + provider_req_id, + provider, + map_key, + map_value, + map_user_data); + } else { + _LOGE("map_callback.remove_cb is NULL"); + } + break; + } + default: + break; + } - if (map_provider_callback.add_cb) - map_provider_callback.add_cb(request_id, (data_control_h)provider, key, value, user_data); + free(provider); + + return DATA_CONTROL_ERROR_NONE; +err: + + if (provider) + free(provider); + if (key) + free(key); + if (value) + bundle_free(value); + + return DATA_CONTROL_ERROR_IO_ERROR; } -static void __map_remove_request_cb(int request_id, datacontrol_h provider, const char *key, const char *value, void *user_data) +gboolean __provider_recv_message(GIOChannel *channel, + GIOCondition cond, + gpointer data) { - _LOGI("map_remove_request"); + char *buf = NULL; + int data_len; + char *consumer_appid = (char *)data; + guint nb; + + gint fd = g_io_channel_unix_get_fd(channel); + gboolean retval = TRUE; + + _LOGI("__provider_recv_message : ...from %d:%s%s%s%s\n", fd, + (cond & G_IO_ERR) ? " ERR" : "", + (cond & G_IO_HUP) ? " HUP" : "", + (cond & G_IO_IN) ? " IN" : "", + (cond & G_IO_PRI) ? " PRI" : ""); + + if (cond & (G_IO_ERR | G_IO_HUP)) + goto error; + + if (cond & G_IO_IN) { + if (_read_socket(fd, (char *)&data_len, sizeof(data_len), &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGE("read socket fail : data_len"); + goto error; + } + + _LOGI("data_len : %d", data_len); + + if (nb == 0) { + _LOGI("__provider_recv_message : ...from %d: EOF\n", fd); + goto error; + } - if (map_provider_callback.remove_cb) - map_provider_callback.remove_cb(request_id, (data_control_h)provider, key, value, user_data); + _LOGI("__provider_recv_message: ...from %d: %d bytes\n", fd, data_len); + if (data_len > 0 && data_len < MAX_REQUEST_ARGUMENT_SIZE) { + bundle *kb = NULL; + + buf = (char *)calloc(data_len + 1, sizeof(char)); + if (buf == NULL) { + _LOGE("calloc failed"); + goto error; + } + + if (_read_socket(fd, buf, data_len, &nb) != + DATA_CONTROL_ERROR_NONE) { + _LOGI("read socket fail : data_len\n"); + goto error; + } + + if (nb == 0) { + _LOGI("__provider_recv_message: nb 0 : EOF\n"); + goto error; + } + + kb = bundle_decode_raw((bundle_raw *)buf, data_len); + if (__provider_process(kb, fd, consumer_appid) != + DATA_CONTROL_ERROR_NONE) { + bundle_free(kb); + goto error; + } + bundle_free(kb); + } + } + if (buf) + free(buf); + + return retval; +error: + if (consumer_appid != NULL) + g_hash_table_remove(__socket_pair_hash, consumer_appid); + if (buf) + free(buf); + + return FALSE; } -static void __map_bulk_add_request_cb(int request_id, datacontrol_h provider, data_control_bulk_data_h bulk_data, void *user_data) +int __datacontrol_handler_cb(bundle *b, int request_id, void *data) { - _LOGI("map_bulk_add_request"); + datacontrol_socket_info *socket_info; + int ret = DATA_CONTROL_ERROR_NONE; + const char *caller; + const char *callee; + char *dup_caller; + + const char *request_type = + bundle_get_val(b, OSP_K_DATACONTROL_REQUEST_TYPE); + if (request_type == NULL) { + caller = bundle_get_val(b, AUL_K_CALLER_APPID); + callee = bundle_get_val(b, AUL_K_CALLEE_APPID); + + if (caller == NULL) { + _LOGE("Invalid data control request caller is NULL"); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + dup_caller = strdup(caller); + socket_info = g_hash_table_lookup(__socket_pair_hash, dup_caller); + + if (socket_info != NULL) + g_hash_table_remove(__socket_pair_hash, dup_caller); - if (map_provider_bulk_callback) - map_provider_bulk_callback(request_id, (data_control_h)provider, bulk_data, user_data); + ret = _add_watch_on_socket_info(dup_caller, callee, "provider", + NULL, NULL, __provider_recv_message, + dup_caller, &socket_info); + if (ret != DATA_CONTROL_ERROR_NONE) + return ret; + + g_hash_table_insert(__socket_pair_hash, dup_caller, socket_info); + } else { + /* Get the request type */ + datacontrol_request_type type = atoi(request_type); + if (type == DATACONTROL_TYPE_ADD_DATA_CHANGED_CB || + type == DATACONTROL_TYPE_REMOVE_DATA_CHANGED_CB) { + __provider_noti_process(b, type); + } else { + _LOGE("Invalid data control request"); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + } + + return ret; } -EXPORT_API int data_control_provider_sql_register_cb(data_control_provider_sql_cb *callback, void *user_data) +EXPORT_API int data_control_provider_sql_register_cb( + data_control_provider_sql_cb *callback, void *user_data) { - int retval = datacontrol_check_privilege(PRIVILEGE_PROVIDER); + int retval = _check_privilege(PRIVILEGE_PROVIDER); if (retval != DATA_CONTROL_ERROR_NONE) return retval; if (!callback) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - sql_provider_callback = *callback; + if (__request_table == NULL) + __initialize_provider(); + + memcpy(&sql_callback, callback, sizeof(data_control_provider_sql_cb)); + sql_user_data = user_data; - sql_internal_callback.insert = __sql_insert_request_cb; - sql_internal_callback.update = __sql_update_request_cb; - sql_internal_callback.delete = __sql_delete_request_cb; - sql_internal_callback.select = __sql_select_request_cb; - sql_internal_callback.bulk_insert = __sql_bulk_insert_request_cb; + /* If the provider_map_cb was registered(not NULL), + * __datacontrol_handler_cb is set already. */ + if (__is_null_map_callback(map_callback)) + retval = aul_set_data_control_provider_cb(__datacontrol_handler_cb); - return datacontrol_provider_sql_register_cb(&sql_internal_callback, user_data); + return retval; } EXPORT_API int data_control_provider_sql_unregister_cb(void) { - memset(&sql_provider_callback, 0, sizeof(data_control_provider_sql_cb)); - return datacontrol_provider_sql_unregister_cb(); + /* When both SQL_cb and Map_cb are unregisted, + * unsetting the provider cb is possible. */ + if (__is_null_map_callback(map_callback)) + aul_unset_data_control_provider_cb(); + + memset(&sql_callback, 0, sizeof(data_control_provider_sql_cb)); + sql_user_data = NULL; + + return DATA_CONTROL_ERROR_NONE; } EXPORT_API int data_control_provider_sql_register_insert_bulk_data_request_cb( data_control_provider_bulk_cb callback, void *user_data) { - int retval = datacontrol_check_privilege(PRIVILEGE_PROVIDER); + int retval = _check_privilege(PRIVILEGE_PROVIDER); if (retval != DATA_CONTROL_ERROR_NONE) return retval; if (callback == NULL) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - sql_provider_bulk_callback = callback; + sql_bulk_callback = callback; sql_bulk_callback_user_data = user_data; - /* sql callback already registered */ - if (datacontrol_provider_sql_is_registered()) - return DATA_CONTROL_ERROR_NONE; - - sql_internal_callback.insert = __sql_insert_request_cb; - sql_internal_callback.update = __sql_update_request_cb; - sql_internal_callback.delete = __sql_delete_request_cb; - sql_internal_callback.select = __sql_select_request_cb; - sql_internal_callback.bulk_insert = __sql_bulk_insert_request_cb; - - return datacontrol_provider_sql_register_cb(&sql_internal_callback, NULL); + return retval; } EXPORT_API int data_control_provider_sql_unregister_insert_bulk_data_request_cb(void) { - memset(&sql_provider_bulk_callback, 0, sizeof(data_control_provider_bulk_cb)); + sql_bulk_callback = NULL; + sql_bulk_callback_user_data = NULL; + return DATA_CONTROL_ERROR_NONE; } -EXPORT_API int data_control_provider_map_register_cb(data_control_provider_map_cb *callback, void *user_data) +EXPORT_API int data_control_provider_map_register_cb( + data_control_provider_map_cb *callback, void *user_data) { - int retval = datacontrol_check_privilege(PRIVILEGE_PROVIDER); + int retval = _check_privilege(PRIVILEGE_PROVIDER); if (retval != DATA_CONTROL_ERROR_NONE) return retval; if (!callback) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - map_provider_callback = *callback; + if (__request_table == NULL) + __initialize_provider(); + + memcpy(&map_callback, callback, sizeof(data_control_provider_map_cb)); + map_user_data = user_data; - map_internal_callback.get = __map_get_request_cb; - map_internal_callback.set = __map_set_request_cb; - map_internal_callback.add = __map_add_request_cb; - map_internal_callback.remove = __map_remove_request_cb; - map_internal_callback.bulk_add = __map_bulk_add_request_cb; + /* If the provider_sql_cb was registered(not NULL), + * __datacontrol_handler_cb is set already. */ + if (__is_null_sql_callback(sql_callback)) + retval = aul_set_data_control_provider_cb(__datacontrol_handler_cb); - return datacontrol_provider_map_register_cb(&map_internal_callback, user_data); + return retval; } EXPORT_API int data_control_provider_map_unregister_cb(void) { - memset(&map_provider_callback, 0, sizeof(data_control_provider_map_cb)); + /* When both SQL_cb and Map_cb are unregisted, + * unsetting the provider cb is possible. */ + if (__is_null_sql_callback(sql_callback)) + aul_unset_data_control_provider_cb(); - return datacontrol_provider_map_unregister_cb(); + memset(&map_callback, 0, sizeof(data_control_provider_map_cb)); + map_user_data = NULL; + + return DATA_CONTROL_ERROR_NONE; } EXPORT_API int data_control_provider_map_register_add_bulk_data_request_cb( data_control_provider_bulk_cb callback, void *user_data) { - int retval = datacontrol_check_privilege(PRIVILEGE_PROVIDER); + int retval = _check_privilege(PRIVILEGE_PROVIDER); if (retval != DATA_CONTROL_ERROR_NONE) return retval; if (callback == NULL) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - map_provider_bulk_callback = callback; + map_bulk_callback = callback; map_bulk_callback_user_data = user_data; - /* map callback already registered */ - if (datacontrol_provider_map_is_registered()) - return DATA_CONTROL_ERROR_NONE; - - map_internal_callback.get = __map_get_request_cb; - map_internal_callback.set = __map_set_request_cb; - map_internal_callback.add = __map_add_request_cb; - map_internal_callback.remove = __map_remove_request_cb; - map_internal_callback.bulk_add = __map_bulk_add_request_cb; - - return datacontrol_provider_map_register_cb(&map_internal_callback, NULL); + return retval; } EXPORT_API int data_control_provider_map_unregister_add_bulk_data_request_cb(void) { - memset(&map_provider_bulk_callback, 0, sizeof(data_control_provider_bulk_cb)); + map_bulk_callback = NULL; + map_bulk_callback_user_data = NULL; + return DATA_CONTROL_ERROR_NONE; } -EXPORT_API int data_control_provider_get_client_appid(int request_id, char **appid) +EXPORT_API int data_control_provider_get_client_appid( + int request_id, char **appid) { - return datacontrol_provider_get_client_appid(request_id, appid); + const char *caller; + bundle *b; + + if (__request_table == NULL) + __initialize_provider(); + + b = g_hash_table_lookup(__request_table, &request_id); + if (!b) { + _LOGE("No data for the request id: %d", request_id); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + caller = bundle_get_val(b, AUL_K_CALLER_APPID); + if (!caller) { + _LOGE("No appid for the request id: %d", request_id); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + _LOGI("Request ID: %d, caller appid: %s", request_id, caller); + + *appid = strdup(caller); + + return DATA_CONTROL_ERROR_NONE; } -EXPORT_API int data_control_provider_send_bulk_insert_result(int request_id, data_control_bulk_result_data_h bulk_results) +EXPORT_API int data_control_provider_send_bulk_insert_result( + int request_id, data_control_bulk_result_data_h bulk_results) { int count; int ret = DATA_CONTROL_ERROR_NONE; + bundle *res; + bundle *b; if (bulk_results == NULL) { _LOGE("Null bulk result data"); @@ -280,35 +2034,157 @@ EXPORT_API int data_control_provider_send_bulk_insert_result(int request_id, dat return DATA_CONTROL_ERROR_INVALID_PARAMETER; } - return datacontrol_provider_send_bulk_insert_result(request_id, bulk_results); + _LOGI("Send an insert result for request id: %d", request_id); + + if (__request_table == NULL) + __initialize_provider(); + + b = g_hash_table_lookup(__request_table, &request_id); + if (!b) { + _LOGE("No data for the request id: %d", request_id); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + res = __set_result(b, DATACONTROL_TYPE_SQL_BULK_INSERT, NULL); + ret = __send_result( + res, DATACONTROL_TYPE_SQL_BULK_INSERT, (void *)bulk_results); + bundle_free(res); + g_hash_table_remove(__request_table, &request_id); + + return ret; } -EXPORT_API int data_control_provider_send_select_result(int request_id, void *db_handle) +EXPORT_API int data_control_provider_send_select_result( + int request_id, void *db_handle) { - return datacontrol_provider_send_select_result(request_id, db_handle); + int ret; + bundle *res; + bundle *b; + + _LOGI("Send a select result for request id: %d", request_id); + + if (__request_table == NULL) + __initialize_provider(); + + b = g_hash_table_lookup(__request_table, &request_id); + if (!b) { + _LOGE("No data for the request id: %d", request_id); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + res = __set_result(b, DATACONTROL_TYPE_SQL_SELECT, db_handle); + ret = __send_result(res, DATACONTROL_TYPE_SQL_SELECT, db_handle); + bundle_free(res); + g_hash_table_remove(__request_table, &request_id); + + return ret; } -EXPORT_API int data_control_provider_send_insert_result(int request_id, long long row_id) +EXPORT_API int data_control_provider_send_insert_result( + int request_id, long long row_id) { - return datacontrol_provider_send_insert_result(request_id, row_id); +int ret; + bundle *res; + bundle *b; + + _LOGI("Send an insert result for request id: %d", request_id); + + if (__request_table == NULL) + __initialize_provider(); + + b = g_hash_table_lookup(__request_table, &request_id); + if (!b) { + _LOGE("No data for the request id: %d", request_id); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + res = __set_result(b, DATACONTROL_TYPE_SQL_INSERT, (void *)&row_id); + + ret = __send_result(res, DATACONTROL_TYPE_SQL_INSERT, NULL); + bundle_free(res); + g_hash_table_remove(__request_table, &request_id); + + return ret; } EXPORT_API int data_control_provider_send_update_result(int request_id) { - return datacontrol_provider_send_update_result(request_id); + int ret; + bundle *res; + bundle *b; + + _LOGI("Send an update result for request id: %d", request_id); + + if (__request_table == NULL) + __initialize_provider(); + + b = g_hash_table_lookup(__request_table, &request_id); + if (!b) { + _LOGE("No data for the request id: %d", request_id); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + res = __set_result(b, DATACONTROL_TYPE_SQL_UPDATE, NULL); + + ret = __send_result(res, DATACONTROL_TYPE_SQL_UPDATE, NULL); + bundle_free(res); + g_hash_table_remove(__request_table, &request_id); + + return ret; } EXPORT_API int data_control_provider_send_delete_result(int request_id) { - return datacontrol_provider_send_delete_result(request_id); + int ret; + bundle *res; + bundle *b; + + _LOGI("Send a delete result for request id: %d", request_id); + + if (__request_table == NULL) + __initialize_provider(); + + b = g_hash_table_lookup(__request_table, &request_id); + if (!b) { + _LOGE("No data for the request id: %d", request_id); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + res = __set_result(b, DATACONTROL_TYPE_SQL_DELETE, NULL); + + ret = __send_result(res, DATACONTROL_TYPE_SQL_DELETE, NULL); + bundle_free(res); + g_hash_table_remove(__request_table, &request_id); + + return ret; } -EXPORT_API int data_control_provider_send_error(int request_id, const char *error) +EXPORT_API int data_control_provider_send_error( + int request_id, const char *error) { - return datacontrol_provider_send_error(request_id, error); + bundle *res; + bundle *b; + int ret; + + _LOGI("Send an error for request id: %d", request_id); + + if (__request_table == NULL) + __initialize_provider(); + + b = g_hash_table_lookup(__request_table, &request_id); + if (!b) { + _LOGE("No data for the request id: %d", request_id); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + res = __set_result(b, DATACONTROL_TYPE_ERROR, (void *)error); + ret = __send_result(res, DATACONTROL_TYPE_ERROR, NULL); + bundle_free(res); + + return ret; } -static void bundle_foreach_cb(const char *key, const int type, const bundle_keyval_t *kv, void *user_data) +static void bundle_foreach_cb(const char *key, const int type, + const bundle_keyval_t *kv, void *user_data) { int index; char *value = NULL; @@ -331,7 +2207,8 @@ static void bundle_foreach_cb(const char *key, const int type, const bundle_keyv return; } -EXPORT_API char *data_control_provider_create_insert_statement(data_control_h provider, bundle *insert_map) +EXPORT_API char *data_control_provider_create_insert_statement( + data_control_h provider, bundle *insert_map) { int index; char *data_id = NULL; @@ -370,9 +2247,10 @@ EXPORT_API char *data_control_provider_create_insert_statement(data_control_h pr index = 0; bundle_foreach(insert_map, bundle_foreach_cb, (void *)(cols)); - data_control_sql_get_data_id(provider, &data_id); + _get_data_id(provider, &data_id); - sql_len = INSERT_STMT_CONST_LEN + strlen(data_id) + (row_count - 1) * 4 + (cols->length) + 1; + sql_len = INSERT_STMT_CONST_LEN + strlen(data_id) + + (row_count - 1) * 4 + (cols->length) + 1; _LOGI("SQL statement length: %d", sql_len); @@ -419,7 +2297,8 @@ EXPORT_API char *data_control_provider_create_insert_statement(data_control_h pr return sql; } -EXPORT_API char *data_control_provider_create_delete_statement(data_control_h provider, const char *where) +EXPORT_API char *data_control_provider_create_delete_statement( + data_control_h provider, const char *where) { char *data_id = NULL; int cond_len; @@ -431,7 +2310,7 @@ EXPORT_API char *data_control_provider_create_delete_statement(data_control_h pr return NULL; } - data_control_sql_get_data_id(provider, &data_id); + _get_data_id(provider, &data_id); cond_len = (where != NULL) ? (WHERE_COND_CONST_LEN + strlen(where)) : 0; sql_len = DELETE_STMT_CONST_LEN + strlen(data_id) + cond_len + 1; @@ -458,7 +2337,8 @@ EXPORT_API char *data_control_provider_create_delete_statement(data_control_h pr return sql; } -EXPORT_API char *data_control_provider_create_update_statement(data_control_h provider, bundle *update_map, const char *where) +EXPORT_API char *data_control_provider_create_update_statement( + data_control_h provider, bundle *update_map, const char *where) { int index; char *data_id = NULL; @@ -497,10 +2377,11 @@ EXPORT_API char *data_control_provider_create_update_statement(data_control_h pr index = 0; bundle_foreach(update_map, bundle_foreach_cb, (void *)(cols)); - data_control_sql_get_data_id(provider, &data_id); + _get_data_id(provider, &data_id); cond_len = (where != NULL) ? (WHERE_COND_CONST_LEN + strlen(where)) : 0; - sql_len = UPDATE_STMT_CONST_LEN + strlen(data_id) + (cols->length) + (row_count - 1) * 5 + cond_len + 1; + sql_len = UPDATE_STMT_CONST_LEN + strlen(data_id) + (cols->length) + + (row_count - 1) * 5 + cond_len + 1; _LOGI("SQL statement length: %d", sql_len); @@ -547,7 +2428,8 @@ EXPORT_API char *data_control_provider_create_update_statement(data_control_h pr return sql; } -EXPORT_API char *data_control_provider_create_select_statement(data_control_h provider, const char **column_list, +EXPORT_API char *data_control_provider_create_select_statement( + data_control_h provider, const char **column_list, int column_count, const char *where, const char *order) { int index = 0; @@ -573,11 +2455,12 @@ EXPORT_API char *data_control_provider_create_select_statement(data_control_h pr col_name_length = 1; } - data_control_sql_get_data_id(provider, &data_id); + _get_data_id(provider, &data_id); cond_len = (where != NULL) ? (WHERE_COND_CONST_LEN + strlen(where)) : 0; order_len = (order != NULL) ? (ORDER_CLS_CONST_LEN + strlen(order)) : 0; - sql_len = SELECT_STMT_CONST_LEN + col_name_length + strlen(data_id) + cond_len + order_len + 1; + sql_len = SELECT_STMT_CONST_LEN + col_name_length + strlen(data_id) + + cond_len + order_len + 1; _LOGI("SQL statement length: %d", sql_len); @@ -618,7 +2501,8 @@ EXPORT_API char *data_control_provider_create_select_statement(data_control_h pr return sql; } -EXPORT_API bool data_control_provider_match_provider_id(data_control_h provider, const char *provider_id) +EXPORT_API bool data_control_provider_match_provider_id( + data_control_h provider, const char *provider_id) { int ret = DATA_CONTROL_ERROR_NONE; char *prov_id = NULL; @@ -628,7 +2512,7 @@ EXPORT_API bool data_control_provider_match_provider_id(data_control_h provider, return false; } - ret = data_control_sql_get_provider_id(provider, &prov_id); + ret = _get_provider_id(provider, &prov_id); set_last_result(ret); if (ret != DATA_CONTROL_ERROR_NONE) return false; @@ -642,7 +2526,8 @@ EXPORT_API bool data_control_provider_match_provider_id(data_control_h provider, } } -EXPORT_API bool data_control_provider_match_data_id(data_control_h provider, const char *data_id) +EXPORT_API bool data_control_provider_match_data_id( + data_control_h provider, const char *data_id) { int ret = DATA_CONTROL_ERROR_NONE; char *data = NULL; @@ -652,7 +2537,7 @@ EXPORT_API bool data_control_provider_match_data_id(data_control_h provider, con return false; } - ret = data_control_sql_get_data_id(provider, &data); + ret = _get_data_id(provider, &data); set_last_result(ret); if (ret != DATA_CONTROL_ERROR_NONE) return false; @@ -666,10 +2551,13 @@ EXPORT_API bool data_control_provider_match_data_id(data_control_h provider, con } } -EXPORT_API int data_control_provider_send_map_bulk_add_result(int request_id, data_control_bulk_result_data_h bulk_results) +EXPORT_API int data_control_provider_send_map_bulk_add_result( + int request_id, data_control_bulk_result_data_h bulk_results) { int count; int ret = DATA_CONTROL_ERROR_NONE; + bundle *res; + bundle *b; if (bulk_results == NULL) { _LOGE("Null bulk result data"); @@ -687,17 +2575,132 @@ EXPORT_API int data_control_provider_send_map_bulk_add_result(int request_id, da return DATA_CONTROL_ERROR_INVALID_PARAMETER; } - return datacontrol_provider_send_map_bulk_add_result(request_id, bulk_results); + _LOGI("Send bulk add result for request id: %d", request_id); + + if (__request_table == NULL) + __initialize_provider(); + + b = g_hash_table_lookup(__request_table, &request_id); + if (!b) { + _LOGE("No data for the request id: %d", request_id); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + res = __set_result(b, DATACONTROL_TYPE_MAP_BULK_ADD, NULL); + ret = __send_result(res, DATACONTROL_TYPE_MAP_BULK_ADD, + (void *)bulk_results); + bundle_free(res); + g_hash_table_remove(__request_table, &request_id); + + return ret; } EXPORT_API int data_control_provider_send_map_result(int request_id) { - return datacontrol_provider_send_map_result(request_id); +int ret; + bundle *res; + bundle *b; + + _LOGI("Send a set/add/remove result for request id: %d", request_id); + + if (__request_table == NULL) + __initialize_provider(); + + b = g_hash_table_lookup(__request_table, &request_id); + if (!b) { + _LOGE("No data for the request id: %d", request_id); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + res = __set_result(b, DATACONTROL_TYPE_UNDEFINED, NULL); + + ret = __send_result(res, DATACONTROL_TYPE_UNDEFINED, NULL); + bundle_free(res); + g_hash_table_remove(__request_table, &request_id); + + return ret; +} + +EXPORT_API int data_control_provider_send_map_get_value_result( + int request_id, char **value_list, int value_count) +{ + int ret; + char value_count_str[32]; + bundle *b; + bundle *res; + + _LOGI("Send a get result for request id: %d", request_id); + + if (__request_table == NULL) + __initialize_provider(); + + b = g_hash_table_lookup(__request_table, &request_id); + if (!b) { + _LOGE("No data for the request id: %d", request_id); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + snprintf(value_count_str, 32, "%d", value_count); + bundle_add_str(b, RESULT_VALUE_COUNT, value_count_str); + + res = __set_result(b, DATACONTROL_TYPE_MAP_GET, value_list); + + ret = __send_result(res, DATACONTROL_TYPE_MAP_GET, value_list); + bundle_free(res); + g_hash_table_remove(__request_table, &request_id); + + return ret; } -EXPORT_API int data_control_provider_send_map_get_value_result(int request_id, char **value_list, int value_count) +static int __send_signal_to_consumer(data_control_h provider, + char *unique_id, + char *path, + data_control_data_change_type_e type, + bundle *data) { - return datacontrol_provider_send_map_get_value_result(request_id, value_list, value_count); + int result = DATA_CONTROL_ERROR_NONE; + int len = 0; + bundle_raw *raw = NULL; + GError *err = NULL; + gboolean signal_result = TRUE; + + if (data) { + if (bundle_encode(data, &raw, &len) != BUNDLE_ERROR_NONE) { + _LOGE("bundle_encode fail"); + result = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + } + + _LOGI("emit signal to object path %s", path); + signal_result = g_dbus_connection_emit_signal( + _get_dbus_connection(), + unique_id, + path, + DATA_CONTROL_INTERFACE_NAME, + DATA_CONTROL_DATA_CHANGE_DATA_CHANGED, + g_variant_new("(isssi)", + type, + provider->provider_id, + provider->data_id, + ((raw) ? (char *)raw : ""), + len), &err); + + if (signal_result == FALSE) { + _LOGE("g_dbus_connection_emit_signal() is failed"); + if (err != NULL) { + _LOGE("g_dbus_connection_emit_signal() err : %s", + err->message); + g_error_free(err); + } + result = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + +out: + if (raw) + free(raw); + + return result; } EXPORT_API int data_control_provider_add_data_change_consumer_filter_cb( @@ -710,15 +2713,43 @@ EXPORT_API int data_control_provider_add_data_change_consumer_filter_cb( if (callback_id == NULL) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - return datacontrol_provider_add_data_change_consumer_filter_cb(callback, user_data, callback_id); + changed_noti_consumer_filter_info_s *filter_info = + (changed_noti_consumer_filter_info_s *)calloc(1, sizeof(changed_noti_consumer_filter_info_s)); + + *callback_id = __datacontrol_get_data_changed_filter_callback_id(); + + filter_info->callback_id = *callback_id; + filter_info->callback = callback; + filter_info->user_data = user_data; + __noti_consumer_filter_info_list = + g_list_append(__noti_consumer_filter_info_list, filter_info); + + return DATA_CONTROL_ERROR_NONE; } EXPORT_API int data_control_provider_remove_data_change_consumer_filter_cb(int callback_id) { + GList *find_list; + changed_noti_consumer_filter_info_s filter_info; + changed_noti_consumer_filter_info_s *temp; + if (callback_id < 1) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - return datacontrol_provider_remove_data_change_consumer_filter_cb(callback_id); + filter_info.callback_id = callback_id; + find_list = g_list_find_custom(__noti_consumer_filter_info_list, &filter_info, + (GCompareFunc)__data_changed_filter_cb_info_compare_cb); + if (find_list != NULL) { + temp = (changed_noti_consumer_filter_info_s *)find_list->data; + __noti_consumer_filter_info_list = + g_list_remove(__noti_consumer_filter_info_list, find_list->data); + free(temp); + } else { + _LOGE("invalid callback_id : %d", callback_id); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + return DATA_CONTROL_ERROR_NONE; } EXPORT_API int data_control_provider_send_data_change_noti( @@ -726,7 +2757,10 @@ EXPORT_API int data_control_provider_send_data_change_noti( data_control_data_change_type_e type, bundle *data) { - int retval = datacontrol_check_privilege(PRIVILEGE_PROVIDER); + int retval = _check_privilege(PRIVILEGE_PROVIDER); + GList *consumer_iter = NULL; + datacontrol_consumer_info *consumer_info = NULL; + if (retval != DATA_CONTROL_ERROR_NONE) return retval; if (!provider) @@ -734,13 +2768,31 @@ EXPORT_API int data_control_provider_send_data_change_noti( if (provider->provider_id == NULL || provider->data_id == NULL) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - if (type < DATA_CONTROL_DATA_CHANGE_SQL_UPDATE || type > DATA_CONTROL_DATA_CHANGE_MAP_REMOVE) + if (type < DATA_CONTROL_DATA_CHANGE_SQL_UPDATE || + type > DATA_CONTROL_DATA_CHANGE_MAP_REMOVE) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - return datacontrol_provider_send_data_change_noti( - (datacontrol_h)provider, - _get_internal_noti_type(type), - data); + _LOGE("datacontrol_provider_send_data_change_noti %d, %d", + g_list_length(__noti_consumer_app_list), type); + consumer_iter = g_list_first(__noti_consumer_app_list); + for (; consumer_iter != NULL; consumer_iter = consumer_iter->next) { + consumer_info = (datacontrol_consumer_info *)consumer_iter->data; + if (__check_consumer_cert(provider->provider_id, + consumer_info->appid, + type) != DATA_CONTROL_ERROR_NONE) + continue; + retval = __send_signal_to_consumer( + provider, + consumer_info->unique_id, + consumer_info->object_path, + type, + data); + if (retval != DATA_CONTROL_ERROR_NONE) { + _LOGE("__send_signal_to_consumer fail : %d", retval); + break; + } + } + return retval; } EXPORT_API int data_control_provider_foreach_data_change_consumer( @@ -748,11 +2800,141 @@ EXPORT_API int data_control_provider_foreach_data_change_consumer( data_control_provider_data_change_consumer_cb list_cb, void *user_data) { + char *app_id = NULL; + char *unique_id = NULL; + int ret = DATA_CONTROL_ERROR_NONE; + sqlite3_stmt *stmt = NULL; + char query[QUERY_MAXLEN]; + bool callback_result; + data_control_provider_data_change_consumer_cb consumer_list_cb; + consumer_list_cb = list_cb; + if (!provider || !list_cb) return DATA_CONTROL_ERROR_INVALID_PARAMETER; if (provider->provider_id == NULL || provider->data_id == NULL) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - return datacontrol_provider_foreach_data_change_consumer( - (datacontrol_h)provider, list_cb, user_data); + sqlite3_snprintf(QUERY_MAXLEN, query, + "SELECT app_id, unique_id " \ + "FROM data_control_consumer_path_list " \ + "WHERE provider_id = ? AND data_id = ?"); + _LOGI("get_changed_noti_consumer_list query : %s", query); + + ret = sqlite3_prepare_v2(__provider_db, query, -1, &stmt, NULL); + if (ret != SQLITE_OK) { + _LOGE("prepare stmt fail"); + ret = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + + ret = sqlite3_bind_text(stmt, 1, provider->provider_id, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + _LOGE("bind provider id fail: %s", sqlite3_errmsg(__provider_db)); + ret = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + + ret = sqlite3_bind_text(stmt, 2, provider->data_id, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + _LOGE("bind data id fail: %s", sqlite3_errmsg(__provider_db)); + ret = DATA_CONTROL_ERROR_IO_ERROR; + goto out; + } + + while (SQLITE_ROW == sqlite3_step(stmt)) { + + app_id = (char *)sqlite3_column_text(stmt, 0); + if (!app_id) { + _LOGE("Failed to get package name\n"); + continue; + } + unique_id = (char *)sqlite3_column_text(stmt, 1); + callback_result = + consumer_list_cb((data_control_h)provider, app_id, user_data); + _LOGI("app_id : %s, unique_id : %s, result : %d ", + app_id, unique_id, callback_result); + if (!callback_result) + break; + } +out: + if (stmt) { + sqlite3_reset(stmt); + sqlite3_clear_bindings(stmt); + sqlite3_finalize(stmt); + } + + return ret; +} + +int datacontrol_provider_write_socket( + int fd, void *buffer, unsigned int nbytes, + unsigned int *bytes_write) +{ + int ret = _write_socket(fd, buffer, nbytes, bytes_write); + return ret; +} + +int datacontrol_provider_send_select_result_without_data( + int request_id, int *fd) +{ + int ret; + bundle *res; + bundle *b; + datacontrol_socket_info *socket_info; + char *caller_app_id; + + _LOGI("Send select result by byte array for request id: %d", request_id); + + if (__request_table == NULL) + __initialize_provider(); + + b = g_hash_table_lookup(__request_table, &request_id); + if (!b) { + _LOGE("No data for the request id: %d", request_id); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + res = __set_result(b, DATACONTROL_TYPE_SQL_SELECT, NULL); + ret = __send_result(res, DATACONTROL_TYPE_UNDEFINED, NULL); + bundle_free(res); + + caller_app_id = (char *)bundle_get_val(b, AUL_K_CALLER_APPID); + socket_info = g_hash_table_lookup(__socket_pair_hash, caller_app_id); + if (socket_info == NULL) { + _LOGE("__socket_pair_hash lookup fail"); + return DATA_CONTROL_ERROR_IO_ERROR; + } + *fd = socket_info->socket_fd; + g_hash_table_remove(__request_table, &request_id); + + return ret; +} + +int datacontrol_provider_get_select_page_info( + int request_id, int *page_num, int *count_per_page) +{ + bundle *b; + const char *page_num_str; + const char *count_per_page_str; + + if (__request_table == NULL) { + _LOGE("__request_table is NULL"); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + b = g_hash_table_lookup(__request_table, &request_id); + if (!b) { + _LOGE("No data for the request id: %d", request_id); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + page_num_str = bundle_get_val(b, RESULT_PAGE_NUMBER); + count_per_page_str = bundle_get_val(b, MAX_COUNT_PER_PAGE); + if (page_num_str == NULL || count_per_page_str == NULL) { + _LOGE("No page data for the request id: %d, ", request_id); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + *page_num = __get_int_from_str(page_num_str); + *count_per_page = __get_int_from_str(count_per_page_str); + + return DATA_CONTROL_ERROR_NONE; } diff --git a/src/data_control_sql.c b/src/data_control_sql.c index 624b0db..e753db3 100755 --- a/src/data_control_sql.c +++ b/src/data_control_sql.c @@ -15,232 +15,86 @@ */ -#include #include #include #include #include #include -#include #include "data_control_bulk.h" #include "data_control_internal.h" #include "data_control_sql.h" #include "data_control_log.h" -struct data_control_s { - char *provider_id; - char *data_id; -}; - -struct datacontrol_s { - char *provider_id; - char *data_id; -}; - -typedef struct bulk_cb_info_s { - data_control_bulk_cb bulk_cb; - void *user_data; -} bulk_cb_info; - -static GHashTable *__response_table = NULL; -static GHashTable *__bulk_response_table = NULL; - -static datacontrol_sql_response_cb __datacontrol_sql_cb; - -static void __sql_bulk_insert_response(int req_id, datacontrol_h provider, data_control_bulk_result_data_h bulk_results, bool provider_result, const char *error, void *user_data) -{ - _LOGI("sql_bulk_insert_response"); - - bulk_cb_info *info = (bulk_cb_info *)g_hash_table_lookup(__bulk_response_table, provider->provider_id); - if (info) - info->bulk_cb(req_id, (data_control_h)provider, bulk_results, provider_result, error, user_data); -} - -static void __sql_insert_response(int req_id, datacontrol_h provider, long long insert_rowid, bool provider_result, const char *error, void *user_data) -{ - _LOGI("sql_insert_response"); - - data_control_sql_response_cb *callback = (data_control_sql_response_cb *)g_hash_table_lookup(__response_table, provider->provider_id); - if (callback) - callback->insert_cb(req_id, (data_control_h)provider, insert_rowid, provider_result, error, user_data); -} - -static void __sql_update_response(int req_id, datacontrol_h provider, bool provider_result, const char *error, void *user_data) -{ - _LOGI("sql_update_response"); - - data_control_sql_response_cb *callback = (data_control_sql_response_cb *)g_hash_table_lookup(__response_table, provider->provider_id); - if (callback) - callback->update_cb(req_id, (data_control_h)provider, provider_result, error, user_data); -} - -static void __sql_delete_response(int req_id, datacontrol_h provider, bool provider_result, const char *error, void *user_data) -{ - _LOGI("sql_delete_response"); - - data_control_sql_response_cb *callback = (data_control_sql_response_cb *)g_hash_table_lookup(__response_table, provider->provider_id); - if (callback) - callback->delete_cb(req_id, (data_control_h)provider, provider_result, error, user_data); -} - -static void __sql_select_response(int req_id, datacontrol_h provider, resultset_cursor *enumerator, bool provider_result, const char *error, void *user_data) -{ - _LOGI("sql_select_response"); - - data_control_sql_response_cb *callback = (data_control_sql_response_cb *)g_hash_table_lookup(__response_table, provider->provider_id); - if (callback) - callback->select_cb(req_id, (data_control_h)provider, (result_set_cursor)enumerator, provider_result, error, user_data); -} - -static void __free_data(gpointer data) -{ - if (data) { - g_free(data); - data = NULL; - } -} - -static void __initialize(void) -{ - __response_table = g_hash_table_new_full(g_str_hash, g_str_equal, __free_data, __free_data); - __bulk_response_table = g_hash_table_new_full(g_str_hash, g_str_equal, __free_data, __free_data); - - __datacontrol_sql_cb.bulk_insert = __sql_bulk_insert_response; - __datacontrol_sql_cb.insert = __sql_insert_response; - __datacontrol_sql_cb.delete = __sql_delete_response; - __datacontrol_sql_cb.select = __sql_select_response; - __datacontrol_sql_cb.update = __sql_update_response; -} - EXPORT_API int data_control_sql_create(data_control_h *provider) { - return datacontrol_sql_create((datacontrol_h *)provider); + return _create_data_control_h(provider); } EXPORT_API int data_control_sql_destroy(data_control_h provider) { - return datacontrol_sql_destroy((datacontrol_h)provider); + return _destroy_data_control_h(provider); } -EXPORT_API int data_control_sql_set_provider_id(data_control_h provider, const char *provider_id) +EXPORT_API int data_control_sql_set_provider_id(data_control_h provider, + const char *provider_id) { - return datacontrol_sql_set_provider_id((datacontrol_h)provider, provider_id); + return _set_provider_id(provider, provider_id); } -EXPORT_API int data_control_sql_get_provider_id(data_control_h provider, char **provider_id) +EXPORT_API int data_control_sql_get_provider_id(data_control_h provider, + char **provider_id) { - return datacontrol_sql_get_provider_id((datacontrol_h)provider, provider_id); + return _get_provider_id(provider, provider_id); } -EXPORT_API int data_control_sql_set_data_id(data_control_h provider, const char *data_id) +EXPORT_API int data_control_sql_set_data_id(data_control_h provider, + const char *data_id) { - return datacontrol_sql_set_data_id((datacontrol_h)provider, data_id); + return _set_data_id(provider, data_id); } -EXPORT_API int data_control_sql_get_data_id(data_control_h provider, char **data_id) +EXPORT_API int data_control_sql_get_data_id(data_control_h provider, + char **data_id) { - return datacontrol_sql_get_data_id((datacontrol_h)provider, data_id); + return _get_data_id(provider, data_id); } -EXPORT_API int data_control_sql_register_response_cb(data_control_h provider, data_control_sql_response_cb *callback, void *user_data) +EXPORT_API int data_control_sql_register_response_cb(data_control_h provider, + data_control_sql_response_cb *callback, void *user_data) { - char *id; - data_control_sql_response_cb *cb; - - if (__response_table == NULL) - __initialize(); - - if (callback == NULL) - return DATA_CONTROL_ERROR_INVALID_PARAMETER; - - id = strdup(provider->provider_id); - if (id == NULL) - return DATA_CONTROL_ERROR_OUT_OF_MEMORY; - - cb = (data_control_sql_response_cb *)malloc(sizeof(data_control_sql_response_cb)); - if (cb == NULL) { - free(id); - return DATA_CONTROL_ERROR_OUT_OF_MEMORY; - } - - memcpy(cb, callback, sizeof(data_control_sql_response_cb)); - g_hash_table_insert(__response_table, id, cb); - - return datacontrol_sql_register_response_cb((datacontrol_h)provider, &__datacontrol_sql_cb, user_data); + return _register_response_cb(provider, (void *)callback, + DATACONTROL_TYPE_SQL_SELECT, user_data); } EXPORT_API int data_control_sql_unregister_response_cb(data_control_h provider) { - if (provider->provider_id) - g_hash_table_remove(__response_table, provider->provider_id); - - return datacontrol_sql_unregister_response_cb((datacontrol_h)provider); + return _unregister_response_cb(provider, DATACONTROL_TYPE_SQL_SELECT); } -EXPORT_API int data_control_sql_register_insert_bulk_data_response_cb(data_control_h provider, +EXPORT_API int data_control_sql_register_insert_bulk_data_response_cb( + data_control_h provider, data_control_bulk_cb callback, void *user_data) { - char *id = NULL; - bulk_cb_info *info = NULL; - int ret; - - if (__bulk_response_table == NULL) - __initialize(); - - if (callback == NULL) - return DATA_CONTROL_ERROR_INVALID_PARAMETER; - - info = (bulk_cb_info *)calloc(1, sizeof(bulk_cb_info)); - if (info == NULL) { - _LOGE("fail to alloc info"); - ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY; - goto out; - } - info->bulk_cb = callback; - info->user_data = user_data; - - id = strdup(provider->provider_id); - if (id == NULL) { - ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY; - goto out; - } - - g_hash_table_insert(__bulk_response_table, id, info); - if (datacontrol_sql_cb_is_registered(id)) - return DATA_CONTROL_ERROR_NONE; - ret = datacontrol_sql_register_response_cb((datacontrol_h)provider, &__datacontrol_sql_cb, NULL); - -out: - if (ret != DATA_CONTROL_ERROR_NONE) { - if (id != NULL) - free(id); - if (info != NULL) - free(info); - } - - return ret; + return _register_response_cb(provider, (void *)callback, + DATACONTROL_TYPE_SQL_BULK_INSERT, user_data); } EXPORT_API int data_control_sql_unregister_insert_bulk_data_response_cb(data_control_h provider) { - if (provider != NULL && provider->provider_id && __bulk_response_table) { - if (g_hash_table_lookup(__bulk_response_table, provider->provider_id) != NULL) { - g_hash_table_remove(__bulk_response_table, provider->provider_id); - } else { - _LOGE("Invalid param"); - return DATA_CONTROL_ERROR_INVALID_PARAMETER; - } - } else { - _LOGE("Invalid param"); - return DATA_CONTROL_ERROR_INVALID_PARAMETER; - } - return DATA_CONTROL_ERROR_NONE; + return _unregister_response_cb(provider, DATACONTROL_TYPE_SQL_BULK_INSERT); } -EXPORT_API int data_control_sql_insert_bulk_data(data_control_h provider, data_control_bulk_data_h bulk_data_h, int *request_id) +EXPORT_API int data_control_sql_insert_bulk_data(data_control_h provider, + data_control_bulk_data_h bulk_data_h, int *request_id) { int retval; + long long arg_size = 0; + const char *arg_list[2]; + bundle *b; + bundle *data; + int count; + int i; if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL) { @@ -248,20 +102,63 @@ EXPORT_API int data_control_sql_insert_bulk_data(data_control_h provider, data_c return DATA_CONTROL_ERROR_INVALID_PARAMETER; } - retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER); + retval = _check_privilege(PRIVILEGE_CONSUMER); + if (retval != DATA_CONTROL_ERROR_NONE) + return retval; + + retval = _check_cert(provider->provider_id, false, NULL); if (retval != DATA_CONTROL_ERROR_NONE) return retval; - retval = datacontrol_check_cert(provider->provider_id, false, NULL); + _LOGI("SQL data control, insert to provider_id: %s, data_id: %s", + provider->provider_id, provider->data_id); + + /* Check size of arguments */ + retval = data_control_bulk_data_get_count(bulk_data_h, &count); if (retval != DATA_CONTROL_ERROR_NONE) return retval; - return datacontrol_sql_insert_bulk_data((datacontrol_h)provider, bulk_data_h, request_id); + for (i = 0; i < count; i++) { + data_control_bulk_data_get_data(bulk_data_h, i, &data); + bundle_foreach(data, _bundle_foreach_check_arg_size_cb, &arg_size); + } + arg_size += (strlen(provider->data_id) + strlen(provider->provider_id)) * sizeof(wchar_t); + if (arg_size > MAX_REQUEST_ARGUMENT_SIZE) { + _LOGE("The size of the request argument exceeds the limit, 1M."); + return DATA_CONTROL_ERROR_MAX_EXCEEDED; + } + + b = bundle_create(); + if (!b) { + _LOGE("unable to create bundle: %d", errno); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } + + bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id); + bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id); + + arg_list[0] = provider->data_id; + bundle_add_str_array(b, OSP_K_ARG, arg_list, 1); + + /* Set the request id */ + *request_id = _datacontrol_create_request_id(); + _LOGI("request id : %d", *request_id); + + retval = _request_provider(provider, DATACONTROL_TYPE_SQL_BULK_INSERT, + b, bulk_data_h, *request_id); + bundle_free(b); + return retval; } -EXPORT_API int data_control_sql_insert(data_control_h provider, const bundle *insert_data, int *request_id) +EXPORT_API int data_control_sql_insert(data_control_h provider, + const bundle *insert_data, int *request_id) { int retval; + long long arg_size = 0; + const char *arg_list[2]; + bundle *b; + char insert_column_count[MAX_LEN_DATACONTROL_COLUMN_COUNT] = {0, }; + int count; if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || insert_data == NULL) { @@ -269,20 +166,62 @@ EXPORT_API int data_control_sql_insert(data_control_h provider, const bundle *in return DATA_CONTROL_ERROR_INVALID_PARAMETER; } - retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER); + retval = _check_privilege(PRIVILEGE_CONSUMER); if (retval != DATA_CONTROL_ERROR_NONE) return retval; - retval = datacontrol_check_cert(provider->provider_id, false, NULL); + retval = _check_cert(provider->provider_id, false, NULL); if (retval != DATA_CONTROL_ERROR_NONE) return retval; - return datacontrol_sql_insert((datacontrol_h)provider, insert_data, request_id); + /* Check size of arguments */ + bundle_foreach((bundle *)insert_data, _bundle_foreach_check_arg_size_cb, &arg_size); + arg_size += strlen(provider->data_id) * sizeof(wchar_t); + if (arg_size > MAX_REQUEST_ARGUMENT_SIZE) { + _LOGE("The size of the request argument exceeds the limit, 1M."); + return DATA_CONTROL_ERROR_MAX_EXCEEDED; + } + + b = bundle_create(); + if (!b) { + _LOGE("unable to create bundle: %d", errno); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } + + bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id); + bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id); + + count = bundle_get_count((bundle *)insert_data); + retval = snprintf(insert_column_count, MAX_LEN_DATACONTROL_COLUMN_COUNT, "%d", count); + if (retval < 0) { + _LOGE("unable to convert insert column count to string: %d", errno); + bundle_free(b); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } + + arg_list[0] = provider->data_id; + arg_list[1] = insert_column_count; + + bundle_add_str_array(b, OSP_K_ARG, arg_list, 2); + + /* Set the request id */ + *request_id = _datacontrol_create_request_id(); + _LOGI("request id : %d", *request_id); + + retval = _request_provider(provider, DATACONTROL_TYPE_SQL_INSERT, + b, (bundle *)insert_data, *request_id); + bundle_free(b); + + return retval; } -EXPORT_API int data_control_sql_delete(data_control_h provider, const char *where, int *request_id) +EXPORT_API int data_control_sql_delete(data_control_h provider, + const char *where, int *request_id) { int retval; + const char *arg_list[2]; + int reqId; + bundle *b; if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL) { @@ -290,20 +229,65 @@ EXPORT_API int data_control_sql_delete(data_control_h provider, const char *wher return DATA_CONTROL_ERROR_INVALID_PARAMETER; } - retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER); + retval = _check_privilege(PRIVILEGE_CONSUMER); if (retval != DATA_CONTROL_ERROR_NONE) return retval; - retval = datacontrol_check_cert(provider->provider_id, false, NULL); + retval = _check_cert(provider->provider_id, false, NULL); if (retval != DATA_CONTROL_ERROR_NONE) return retval; - return datacontrol_sql_delete((datacontrol_h)provider, where, request_id); + b = bundle_create(); + if (!b) { + _LOGE("unable to create bundle: %d", errno); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } + + bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id); + bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id); + + arg_list[0] = provider->data_id; + + if (where) + arg_list[1] = where; + else + arg_list[1] = DATACONTROL_EMPTY; + + bundle_add_str_array(b, OSP_K_ARG, arg_list, 2); + + /* Set the request id */ + reqId = _datacontrol_create_request_id(); + *request_id = reqId; + + retval = _request_provider(provider, DATACONTROL_TYPE_SQL_DELETE, b, NULL, reqId); + bundle_free(b); + return retval; + } -EXPORT_API int data_control_sql_select(data_control_h provider, char **column_list, int column_count, const char *where, const char *order, int *request_id) +EXPORT_API int data_control_sql_select(data_control_h provider, + char **column_list, int column_count, const char *where, + const char *order, int *request_id) { + return data_control_sql_select_with_page(provider, column_list, + column_count, where, order, 1, 20, request_id); +} + +EXPORT_API int data_control_sql_select_with_page(data_control_h provider, + char **column_list, int column_count, const char *where, + const char *order, int page_number, int count_per_page, + int *request_id) +{ + int total_arg_count = -1; int retval; + bundle *b; + char page[32] = {0, }; + char count_per_page_no[32] = {0, }; + const char **arg_list; + int i; + char select_column_count[MAX_LEN_DATACONTROL_COLUMN_COUNT] = {0, }; + int select_col; + int reqId; if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || column_list == NULL) { @@ -311,42 +295,104 @@ EXPORT_API int data_control_sql_select(data_control_h provider, char **column_li return DATA_CONTROL_ERROR_INVALID_PARAMETER; } - retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER); + retval = _check_privilege(PRIVILEGE_CONSUMER); if (retval != DATA_CONTROL_ERROR_NONE) return retval; - retval = datacontrol_check_cert(provider->provider_id, false, NULL); + retval = _check_cert(provider->provider_id, false, NULL); if (retval != DATA_CONTROL_ERROR_NONE) return retval; - return datacontrol_sql_select((datacontrol_h)provider, column_list, column_count, where, order, request_id); -} + _LOGI("SQL data control, select to provider_id: %s, data_id: %s, \ + col_count: %d, where: %s, order: %s, page_number: %d, \ + per_page: %d", + provider->provider_id, provider->data_id, + column_count, where, order, page_number, + count_per_page); -EXPORT_API int data_control_sql_select_with_page(data_control_h provider, char **column_list, int column_count, const char *where, const char *order, int page_number, int count_per_page, int *request_id) -{ - int retval; + b = bundle_create(); + if (!b) { + _LOGE("unable to create bundle: %d", errno); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } - if (provider == NULL || provider->provider_id == NULL || - provider->data_id == NULL || column_list == NULL) { - _LOGE("Invalid parameter"); - return DATA_CONTROL_ERROR_INVALID_PARAMETER; + bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id); + bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id); + + retval = snprintf(page, 32, "%d", page_number); + if (retval < 0) { + _LOGE("unable to convert page no to string: %d", errno); + bundle_free(b); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; } - retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER); - if (retval != DATA_CONTROL_ERROR_NONE) - return retval; + retval = snprintf(count_per_page_no, 32, "%d", count_per_page); + if (retval < 0) { + _LOGE("unable to convert count per page no to string: %d", errno); + bundle_free(b); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } - retval = datacontrol_check_cert(provider->provider_id, false, NULL); - if (retval != DATA_CONTROL_ERROR_NONE) - return retval; + total_arg_count = column_count + DATACONTROL_SELECT_EXTRA_COUNT; + arg_list = (const char **)malloc(total_arg_count * (sizeof(char *))); + + _LOGI("total arg count %d", total_arg_count); + + arg_list[0] = provider->data_id; /* arg[0]: data ID */ + i = 1; + if (column_list) { + retval = snprintf(select_column_count, + MAX_LEN_DATACONTROL_COLUMN_COUNT, "%d", column_count); + if (retval < 0) { + _LOGE("unable to convert select col count to string: %d", errno); + free(arg_list); + bundle_free(b); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } + + + arg_list[i] = select_column_count; /* arg[1]: selected column count */ + + ++i; + select_col = 0; + while (select_col < column_count) + arg_list[i++] = column_list[select_col++]; + } - return datacontrol_sql_select_with_page((datacontrol_h)provider, column_list, column_count, where, order, page_number, count_per_page, request_id); + if (where) /* arg: where clause */ + arg_list[i++] = where; + else + arg_list[i++] = DATACONTROL_EMPTY; + + if (order) /* arg: order clause */ + arg_list[i++] = order; + else + arg_list[i++] = DATACONTROL_EMPTY; + + arg_list[i++] = page; /* arg: page number */ + + arg_list[i] = count_per_page_no; /* arg: count per page */ + + bundle_add_str_array(b, OSP_K_ARG, arg_list, total_arg_count); + free(arg_list); + + reqId = _datacontrol_create_request_id(); + *request_id = reqId; + + retval = _request_provider(provider, DATACONTROL_TYPE_SQL_SELECT, + b, NULL, reqId); + bundle_free(b); + return retval; } -EXPORT_API int data_control_sql_update(data_control_h provider, const bundle *update_data, const char *where, int *request_id) +EXPORT_API int data_control_sql_update(data_control_h provider, + const bundle *update_data, const char *where, int *request_id) { int retval; + long long arg_size = 0; + bundle *b; + const char *arg_list[4]; if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || @@ -355,14 +401,40 @@ EXPORT_API int data_control_sql_update(data_control_h provider, const bundle *up return DATA_CONTROL_ERROR_INVALID_PARAMETER; } - retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER); + retval = _check_privilege(PRIVILEGE_CONSUMER); if (retval != DATA_CONTROL_ERROR_NONE) return retval; - retval = datacontrol_check_cert(provider->provider_id, false, NULL); + retval = _check_cert(provider->provider_id, false, NULL); if (retval != DATA_CONTROL_ERROR_NONE) return retval; - return datacontrol_sql_update((datacontrol_h)provider, update_data, where, request_id); -} + /* Check size of arguments */ + bundle_foreach((bundle *)update_data, _bundle_foreach_check_arg_size_cb, &arg_size); + arg_size += strlen(provider->data_id) * sizeof(wchar_t); + if (arg_size > MAX_REQUEST_ARGUMENT_SIZE) { + _LOGE("The size of the request argument exceeds the limit, 1M."); + return DATA_CONTROL_ERROR_MAX_EXCEEDED; + } + b = bundle_create(); + if (!b) { + _LOGE("unable to create bundle: %d", errno); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } + + bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id); + bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id); + + arg_list[0] = provider->data_id; /* list(0): data ID */ + arg_list[1] = where; + bundle_add_str_array(b, OSP_K_ARG, arg_list, 2); + + *request_id = _datacontrol_create_request_id(); + retval = _request_provider(provider, DATACONTROL_TYPE_SQL_UPDATE, + b, (bundle *)update_data, *request_id); + + bundle_free(b); + return retval; + +} diff --git a/src/data_control_sql_cursor.c b/src/data_control_sql_cursor.c old mode 100644 new mode 100755 index d8b8c95..25b080f --- a/src/data_control_sql_cursor.c +++ b/src/data_control_sql_cursor.c @@ -14,10 +14,15 @@ * limitations under the License. */ -#include -#include +#include +#include #include "data_control_sql_cursor.h" +#include "data_control_types.h" +#include "data_control_log.h" +#include "data_control_internal.h" + +#define ERR_BUFFER_SIZE 1024 struct result_set_s { int result_set_fd; @@ -33,92 +38,703 @@ struct result_set_s { EXPORT_API int data_control_sql_step_next(result_set_cursor cursor) { + resultset_cursor *__cursor = NULL; + if (cursor == NULL) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - return datacontrol_sql_step_next((resultset_cursor *)cursor); + + __cursor = (resultset_cursor *)cursor; + + if (__cursor->resultset_row_count == 0) { + _LOGE("Reached to the end of the result set"); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + if (__cursor->resultset_current_offset == 0) { + __cursor->resultset_current_offset = __cursor->resultset_content_offset; + } else { + if (!(__cursor->resultset_current_row_count < (__cursor->resultset_row_count - 1))) { + _LOGE("Reached to the end of the result set"); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + __cursor->resultset_current_offset = + __cursor->row_offset_list[__cursor->resultset_current_row_count + 1]; + __cursor->resultset_current_row_count++; + } + return DATA_CONTROL_ERROR_NONE; } EXPORT_API int data_control_sql_step_last(result_set_cursor cursor) { + int ret = 0; + int i = 0; + resultset_cursor *__cursor = NULL; + if (cursor == NULL) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - return datacontrol_sql_step_last((resultset_cursor *)cursor); + + __cursor = (resultset_cursor *)cursor; + + if (__cursor->resultset_current_row_count == + (__cursor->resultset_row_count - 1)) + return DATA_CONTROL_ERROR_NONE; /* Already @ last row */ + + if (!__cursor->row_offset_list) { + /* make a first move */ + ret = data_control_sql_step_next((result_set_cursor)__cursor); + if (ret != DATA_CONTROL_ERROR_NONE) + return ret; + } + + /* check if the rowOffsetList contains last row offset */ + if (__cursor->row_offset_list && + __cursor->row_offset_list[__cursor->resultset_row_count - 1] != 0) { + __cursor->resultset_current_offset = + __cursor->row_offset_list[__cursor->resultset_row_count - 1]; + __cursor->resultset_current_row_count = + __cursor->resultset_row_count - 1; + } else { + /* Move till last row offset. */ + for (i = (__cursor->resultset_current_row_count + 1); + i < __cursor->resultset_row_count; + i++) { + /* move till last row data offset */ + ret = data_control_sql_step_next((result_set_cursor)__cursor); + if (ret != DATA_CONTROL_ERROR_NONE) + return ret; + } + } + + return DATA_CONTROL_ERROR_NONE; } EXPORT_API int data_control_sql_step_first(result_set_cursor cursor) { + resultset_cursor *__cursor = NULL; + if (cursor == NULL) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - return datacontrol_sql_step_first((resultset_cursor *)cursor); + + __cursor = (resultset_cursor *)cursor; + + if (__cursor->resultset_current_offset > 0) { + __cursor->resultset_current_offset = __cursor->resultset_content_offset; + __cursor->resultset_current_row_count = 0; + return DATA_CONTROL_ERROR_NONE; + } + + /* MoveFirst is called for the first time before MoveNext() or MoveLast() */ + __cursor->resultset_current_offset = 0; + return data_control_sql_step_next((result_set_cursor)__cursor); } EXPORT_API int data_control_sql_step_previous(result_set_cursor cursor) { + resultset_cursor *__cursor = NULL; + if (cursor == NULL) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - return datacontrol_sql_step_previous((resultset_cursor *)cursor); + + __cursor = (resultset_cursor *)cursor; + + if ((__cursor->resultset_current_row_count - 1) < 0) { + _LOGE("invalid request"); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + __cursor->resultset_current_offset = + __cursor->row_offset_list[__cursor->resultset_current_row_count - 1]; + __cursor->resultset_current_row_count--; + + return DATA_CONTROL_ERROR_NONE; } EXPORT_API int data_control_sql_get_column_count(result_set_cursor cursor) { + resultset_cursor *__cursor = NULL; + if (cursor == NULL) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - return datacontrol_sql_get_column_count((resultset_cursor *)cursor); + + __cursor = (resultset_cursor *)cursor; + + return __cursor->resultset_col_count; } -EXPORT_API int data_control_sql_get_column_name(result_set_cursor cursor, int column_index, char *name) +EXPORT_API int data_control_sql_get_column_name(result_set_cursor cursor, + int column_index, char *name) { + char *col_name = NULL; + int i = 0; + int ret = 0; + int column_len = 0; + int fd; + char err_buf[ERR_BUFFER_SIZE]; + resultset_cursor *__cursor = NULL; + if (cursor == NULL) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - return datacontrol_sql_get_column_name((resultset_cursor *)cursor, column_index, name); + + __cursor = (resultset_cursor *)cursor; + + fd = __cursor->resultset_fd; + ret = lseek(fd, __cursor->resultset_col_name_offset, SEEK_SET); + if (ret < 0) { + _LOGE("unable to seek in the resultset file: %d %s", + __cursor->resultset_current_offset, + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + for (i = 0; i < column_index + 1; i++) { + ret = read(fd, &column_len, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read column_len: %d", column_len); + goto error; + } + + if (column_len < 0 || column_len > MAX_COLUMN_SIZE) { + _LOGE("Invalid column_len: %d", column_len); + goto error; + } + + if (i == column_index) { + col_name = (char *)calloc(column_len, sizeof(char)); + ret = read(fd, col_name, column_len); + if (ret == 0) { + _LOGE("unable to read col_name : %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + goto error; + } + } else { + ret = lseek(fd, column_len, SEEK_CUR); + if (ret < 0) { + _LOGE("unable to seek in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + goto error; + } + } + } + memset(name, 0, column_len); + memcpy(name, col_name, column_len); + free(col_name); + _LOGI("The column name is %s", name); + + return DATA_CONTROL_ERROR_NONE; + +error: + if (col_name) + free(col_name); + return DATA_CONTROL_ERROR_IO_ERROR; } -EXPORT_API int data_control_sql_get_column_item_size(result_set_cursor cursor, int column_index) +EXPORT_API int data_control_sql_get_column_item_size(result_set_cursor cursor, + int column_index) { + int type = -1; + int size = 0; + int i = 0; + int ret = 0; + char err_buf[ERR_BUFFER_SIZE]; + int fd = 0; + resultset_cursor *__cursor = NULL; + if (cursor == NULL) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - return datacontrol_sql_get_column_item_size((resultset_cursor *)cursor, column_index); + + __cursor = (resultset_cursor *)cursor; + + fd = __cursor->resultset_fd; + ret = lseek(fd, __cursor->resultset_current_offset, SEEK_SET); + if (ret < 0) { + _LOGE("unable to seek in the resultset file: %d %s", + __cursor->resultset_current_offset, + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + /* move to column index */ + for (i = 0; i < column_index; i++) { + ret = read(fd, &type, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + ret = read(fd, &size, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + ret = lseek(fd, size, SEEK_CUR); + if (ret < 0) { + _LOGE("unable to seek in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + } + + ret = read(fd, &type, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + ret = read(fd, &size, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + return size; + } -EXPORT_API int data_control_sql_get_column_item_type(result_set_cursor cursor, int column_index, data_control_sql_column_type_e *col_type) +EXPORT_API int data_control_sql_get_column_item_type(result_set_cursor cursor, + int column_index, data_control_sql_column_type_e *col_type) { + int type = -1; + int i = 0; + int size = 0; + int ret = 0; + char err_buf[ERR_BUFFER_SIZE]; + int fd = 0; + resultset_cursor *__cursor = NULL; + if (cursor == NULL) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - return datacontrol_sql_get_column_item_type((resultset_cursor *)cursor, column_index, (datacontrol_sql_column_type *)col_type); + + __cursor = (resultset_cursor *)cursor; + + fd = __cursor->resultset_fd; + + ret = lseek(fd, __cursor->resultset_current_offset, SEEK_SET); + if (ret < 0) { + _LOGE("unable to seek in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + /* move to column index */ + for (i = 0; i < column_index; i++) { + ret = read(fd, &type, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + ret = read(fd, &size, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + ret = lseek(fd, size, SEEK_CUR); + if (ret < 0) { + _LOGE("unable to seek in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + } + + ret = read(fd, &type, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + switch (type) { + case DATA_CONTROL_SQL_COLUMN_TYPE_INT64: + *col_type = DATA_CONTROL_SQL_COLUMN_TYPE_INT64; + break; + case DATA_CONTROL_SQL_COLUMN_TYPE_DOUBLE: + *col_type = DATA_CONTROL_SQL_COLUMN_TYPE_DOUBLE; + break; + case DATA_CONTROL_SQL_COLUMN_TYPE_TEXT: + *col_type = DATA_CONTROL_SQL_COLUMN_TYPE_TEXT; + break; + case DATA_CONTROL_SQL_COLUMN_TYPE_BLOB: + *col_type = DATA_CONTROL_SQL_COLUMN_TYPE_BLOB; + break; + case DATA_CONTROL_SQL_COLUMN_TYPE_NULL: + *col_type = DATA_CONTROL_SQL_COLUMN_TYPE_NULL; + break; + default: + *col_type = DATA_CONTROL_SQL_COLUMN_TYPE_UNDEFINED; + break; + } + + return DATA_CONTROL_ERROR_NONE; + } -EXPORT_API int data_control_sql_get_blob_data(result_set_cursor cursor, int column_index, void *buffer, int data_size) +EXPORT_API int data_control_sql_get_blob_data(result_set_cursor cursor, + int column_index, void *buffer, int data_size) { + int type = -1; + int size = 0; + int i = 0; + int ret = 0; + char err_buf[ERR_BUFFER_SIZE]; + int fd = 0; + char *data; + resultset_cursor *__cursor = NULL; + if (cursor == NULL) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - return datacontrol_sql_get_blob_data((resultset_cursor *)cursor, column_index, buffer, data_size); + + __cursor = (resultset_cursor *)cursor; + + fd = __cursor->resultset_fd; + + + ret = lseek(fd, __cursor->resultset_current_offset, SEEK_SET); + if (ret < 0) { + _LOGE("unable to seek in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + /* move to column index */ + for (i = 0; i < column_index; i++) { + ret = read(fd, &type, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + ret = read(fd, &size, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + ret = lseek(fd, size, SEEK_CUR); + if (ret < 0) { + _LOGE("unable to seek in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + } + + ret = read(fd, &type, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + if (type != (int)DATA_CONTROL_SQL_COLUMN_TYPE_BLOB) { + _LOGE("type mismatch: requested for BLOB type but %d present:", type); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + ret = read(fd, &size, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read size in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + if (size > data_size) { + _LOGE("size is more than the size requested"); + return DATA_CONTROL_ERROR_MAX_EXCEEDED; /* overflow */ + } + + if (size > 0 && size < MAX_REQUEST_ARGUMENT_SIZE) { + data = (char *)malloc((size + 1) * (sizeof(char))); + memset(data, 0, size + 1); + + ret = read(fd, data, size); + if (ret < size) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + free(data); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + memcpy(buffer, data, size + 1); + free(data); + } else { + _LOGE("Invalid size %d", size); + return DATA_CONTROL_ERROR_IO_ERROR; + } + return DATA_CONTROL_ERROR_NONE; } -EXPORT_API int data_control_sql_get_int_data(result_set_cursor cursor, int column_index, int *data) +EXPORT_API int data_control_sql_get_int_data(result_set_cursor cursor, + int column_index, int *data) { + long long long_value = 0; + int ret = -1; + if (cursor == NULL) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - return datacontrol_sql_get_int_data((resultset_cursor *)cursor, column_index, data); + + ret = data_control_sql_get_int64_data(cursor, column_index, &long_value); + if (ret == 0) + *data = (int) long_value; + + return ret; } -EXPORT_API int data_control_sql_get_int64_data(result_set_cursor cursor, int column_index, long long *data) +EXPORT_API int data_control_sql_get_int64_data(result_set_cursor cursor, + int column_index, long long *data) { + int type = -1; + int size = 0; + int i = 0; + int ret = 0; + char err_buf[ERR_BUFFER_SIZE]; + int fd = 0; + resultset_cursor *__cursor = NULL; + if (cursor == NULL) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - return datacontrol_sql_get_int64_data((resultset_cursor *)cursor, column_index, data); + + __cursor = (resultset_cursor *)cursor; + + fd = __cursor->resultset_fd; + ret = lseek(fd, __cursor->resultset_current_offset, SEEK_SET); + if (ret < 0) { + _LOGE("unable to seek in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + /* move to column index */ + for (i = 0; i < column_index; i++) { + ret = read(fd, &type, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + ret = read(fd, &size, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + ret = lseek(fd, size, SEEK_CUR); + if (ret < 0) { + _LOGE("unable to seek in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + } + + ret = read(fd, &type, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + if (type != (int)DATA_CONTROL_SQL_COLUMN_TYPE_INT64) { + _LOGE("type mismatch: requested for int type but %d present:", type); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + ret = read(fd, &size, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + ret = read(fd, data, size); + if (ret < size) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + return DATA_CONTROL_ERROR_NONE; + } -EXPORT_API int data_control_sql_get_double_data(result_set_cursor cursor, int column_index, double *data) +EXPORT_API int data_control_sql_get_double_data(result_set_cursor cursor, + int column_index, double *data) { + int type = -1; + int size = 0; + int i = 0; + int ret = 0; + char err_buf[ERR_BUFFER_SIZE]; + int fd = 0; + resultset_cursor *__cursor = NULL; + if (cursor == NULL) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - return datacontrol_sql_get_double_data((resultset_cursor *)cursor, column_index, data); + + __cursor = (resultset_cursor *)cursor; + + fd = __cursor->resultset_fd; + ret = lseek(fd, __cursor->resultset_current_offset, SEEK_SET); + if (ret < 0) { + _LOGE("unable to seek in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + /* move to column index */ + for (i = 0; i < column_index; i++) { + ret = read(fd, &type, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + ret = read(fd, &size, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + ret = lseek(fd, size, SEEK_CUR); + if (ret < 0) { + _LOGE("unable to seek in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + } + + ret = read(fd, &type, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + if (type != (int)DATA_CONTROL_SQL_COLUMN_TYPE_DOUBLE) { + _LOGE("type mismatch: requested for double type but %d present:", type); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + ret = read(fd, &size, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + ret = read(fd, data, size); + if (ret < size) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + return DATA_CONTROL_ERROR_NONE; + } -EXPORT_API int data_control_sql_get_text_data(result_set_cursor cursor, int column_index, char *buffer) +EXPORT_API int data_control_sql_get_text_data(result_set_cursor cursor, + int column_index, char *buffer) { + int type = -1; + int size = 0; + int i = 0; + int ret = 0; + char err_buf[ERR_BUFFER_SIZE]; + char *data; + int fd = 0; + resultset_cursor *__cursor = NULL; + if (cursor == NULL) return DATA_CONTROL_ERROR_INVALID_PARAMETER; - return datacontrol_sql_get_text_data((resultset_cursor *)cursor, column_index, buffer); -} + __cursor = (resultset_cursor *)cursor; + + fd = __cursor->resultset_fd; + ret = lseek(fd, __cursor->resultset_current_offset, SEEK_SET); + if (ret < 0) { + _LOGE("unable to seek in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + /* move to column index */ + for (i = 0; i < column_index; i++) { + ret = read(fd, &type, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + ret = read(fd, &size, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + ret = lseek(fd, size, SEEK_CUR); + if (ret < 0) { + _LOGE("unable to seek in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + } + + ret = read(fd, &type, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + if (type != (int)DATA_CONTROL_SQL_COLUMN_TYPE_TEXT) { + _LOGE("type mismatch: requested for text type but %d present %d", type, + __cursor->resultset_current_offset); + return DATA_CONTROL_ERROR_INVALID_PARAMETER; + } + + ret = read(fd, &size, sizeof(int)); + if (ret == 0) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + if (size > 0 && size < MAX_REQUEST_ARGUMENT_SIZE) { + data = (char *)malloc((size + 1) * (sizeof(char))); + if (!data) { + _LOGE("unable to create buffer to read"); + return DATA_CONTROL_ERROR_OUT_OF_MEMORY; + } + + memset(data, 0, size + 1); + ret = read(fd, data, size); + if (ret < size) { + _LOGE("unable to read in the resultset file: %s", + strerror_r(errno, err_buf, sizeof(err_buf))); + free(data); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + memcpy(buffer, data, size + 1); + free(data); + } else { + _LOGE("Invalid size %d", size); + return DATA_CONTROL_ERROR_IO_ERROR; + } + + return DATA_CONTROL_ERROR_NONE; +}