Revert "Fix memory leaks"
[platform/core/appfw/data-control.git] / src / data-control-map.c
1 /*
2  * Copyright (c) 2013 - 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <dlog.h>
18 #include <errno.h>
19 #include <search.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <glib.h>
25 #include <pthread.h>
26 #include <fcntl.h>
27 #include <sys/socket.h>
28
29 #include <appsvc/appsvc.h>
30 #include <aul/aul.h>
31 #include <bundle.h>
32 #include <bundle_internal.h>
33 #include <pkgmgr-info.h>
34
35 #include "data-control-map.h"
36 #include "data-control-internal.h"
37 #include "data-control-bulk.h"
38
39 typedef struct {
40         char *provider_id;
41         char *app_id;
42         char *data_id;
43         char *access_info;
44         void *user_data;
45         GList *request_info_list;
46         datacontrol_map_response_cb *map_response_cb;
47 } map_response_cb_s;
48
49 static void *datacontrol_map_tree_root = NULL;
50 static GHashTable *__socket_pair_hash = NULL;
51
52 static void __map_call_cb(const char *provider_id, int request_id, datacontrol_request_type type,
53         const char *data_id, bool provider_result, const char *error, char **result_value_list, int result_value_count,
54         data_control_bulk_result_data_h bulk_results, void *data)
55 {
56         LOGI("__map_call_cb, dataID: %s", data_id);
57
58         datacontrol_map_response_cb *callback = NULL;
59
60         map_response_cb_s *map_dc = NULL;
61         map_dc = (map_response_cb_s *)data;
62         callback = map_dc->map_response_cb;
63         if (!callback) {
64                 LOGE("no listener set");
65                 return;
66         }
67
68         datacontrol_h provider;
69         datacontrol_map_create(&provider);
70
71         datacontrol_map_set_provider_id(provider, provider_id);
72         datacontrol_map_set_data_id(provider, data_id);
73
74         switch (type) {
75         case DATACONTROL_TYPE_MAP_BULK_ADD:
76                 LOGI("ADD VALUE");
77                 if (callback != NULL && callback->bulk_add != NULL)
78                         callback->bulk_add(request_id, provider, bulk_results, provider_result, error, map_dc->user_data);
79                 else
80                         LOGI("No registered callback function");
81
82                 break;
83         case DATACONTROL_TYPE_MAP_GET:
84                 LOGI("GET VALUE");
85                 if (callback != NULL && callback->get != NULL)
86                         callback->get(request_id, provider, result_value_list, result_value_count, provider_result, error, map_dc->user_data);
87                 else
88                         LOGI("No registered callback function");
89
90                 break;
91         case DATACONTROL_TYPE_MAP_SET:
92                 LOGI("SET VALUE");
93                 if (callback != NULL && callback->set != NULL)
94                         callback->set(request_id, provider, provider_result, error, map_dc->user_data);
95                 else
96                         LOGI("No registered callback function");
97
98                 break;
99         case DATACONTROL_TYPE_MAP_ADD:
100                 LOGI("ADD VALUE");
101                 if (callback != NULL && callback->add != NULL)
102                         callback->add(request_id, provider, provider_result, error, map_dc->user_data);
103                 else
104                         LOGI("No registered callback function");
105
106                 break;
107         case DATACONTROL_TYPE_MAP_REMOVE:
108                 LOGI("REMOVE VALUE");
109                 if (callback != NULL && callback->remove != NULL)
110                         callback->remove(request_id, provider, provider_result, error, map_dc->user_data);
111                 else
112                         LOGI("No registered callback function");
113
114                 break;
115         default:
116                 break;
117         }
118
119         datacontrol_map_destroy(provider);
120 }
121
122 static void __map_instance_free(void *datacontrol_map_instance)
123 {
124         map_response_cb_s *dc = (map_response_cb_s *)datacontrol_map_instance;
125         if (dc) {
126                 free(dc->provider_id);
127                 free(dc->data_id);
128                 free(dc->app_id);
129                 free(dc->access_info);
130                 free(datacontrol_map_instance);
131         }
132
133         return;
134 }
135
136 static int __map_instance_compare(const void *l_datacontrol_map_instance, const void *r_datacontrol_map_instance)
137 {
138         map_response_cb_s *dc_left = (map_response_cb_s *)l_datacontrol_map_instance;
139         map_response_cb_s *dc_right = (map_response_cb_s *)r_datacontrol_map_instance;
140         return strcmp(dc_left->provider_id, dc_right->provider_id);
141 }
142
143 static char **__map_get_value_list(int fd, int *value_count)
144 {
145         char **value_list = NULL;
146         int i = 0;
147         int count = 0;
148         int nbytes = 0;
149         unsigned int nb = 0;
150         int j;
151
152         if (_read_socket(fd, (char *)&count, sizeof(count), &nb)) {
153                 LOGE("datacontrol_recv_map_get_value_list : ...from %d: fail to read\n", fd);
154                 return NULL;
155         }
156
157         if (count < 0 || count > MAX_VALUE_COUNT) {
158                 LOGE("invalid count %d", count);
159                 return NULL;
160         }
161
162         value_list = (char **)calloc(count, sizeof(char *));
163         if (value_list == NULL) {
164                 LOGE("Failed to create value list");
165                 return NULL;
166         }
167
168         for (i = 0; i < count; i++) {
169                 if (_read_socket(fd, (char *)&nbytes, sizeof(nbytes), &nb)) {
170                         LOGE("datacontrol_recv_map_get_value_list : ...from %d: fail to read\n", fd);
171                         goto ERROR;
172                 }
173                 if (nbytes < 0 || nbytes > MAX_REQUEST_ARGUMENT_SIZE) {
174                         LOGE("invalid nbytes %d", nbytes);
175                         goto ERROR;
176                 }
177
178                 LOGI("nbytes : %d  %d" , nbytes , nb);
179                 value_list[i] = (char *)calloc(nbytes + 1, sizeof(char));
180
181                 if (_read_socket(fd, value_list[i], nbytes, &nb)) {
182                         LOGE("datacontrol_recv_map_get_value_list : ...from %d: fail to read\n", fd);
183                         goto ERROR;
184                 }
185                 LOGI("value_list[i] : %s  %d" , value_list[i] , nb);
186         }
187         *value_count = count;
188
189         return value_list;
190
191         /* LCOV_EXCL_START */
192 ERROR:
193         if (value_list) {
194                 for (j = 0; j < i; j++) {
195                         if (value_list[j] != NULL)
196                                 free(value_list[j]);
197                 }
198                 free(value_list);
199         }
200
201         return NULL;
202         /* LCOV_EXCL_STOP */
203 }
204
205 static void __remove_map_request_info(int request_id, map_response_cb_s *map_dc)
206 {
207
208         datacontrol_consumer_request_info temp_request_info;
209         datacontrol_consumer_request_info *data;
210
211         temp_request_info.request_id = request_id;
212         GList *list = g_list_find_custom(map_dc->request_info_list, &temp_request_info,
213                         (GCompareFunc)_consumer_request_compare_cb);
214         if (list != NULL) {
215                 data = (datacontrol_consumer_request_info *)list->data;
216                 map_dc->request_info_list = g_list_remove(map_dc->request_info_list, list->data);
217                 free(data);
218         }
219 }
220
221 static int __map_handle_cb(int fd, bundle *b, int request_type, int request_id, appsvc_result_val res, void *data)
222 {
223         int ret = 0;
224         const char **result_list = NULL;
225         const char *provider_id = NULL;
226         const char *data_id = NULL;
227         const char *error_message = NULL;
228         int result_list_len = 0;
229         int provider_result = 0;
230         int value_count = 0;
231         int i;
232         char **value_list = NULL;
233         const char *p = NULL;
234         data_control_bulk_result_data_h bulk_results = NULL;
235
236         LOGI("__map_handle_cb, request_type: %d", request_type);
237
238         if (!b) {
239                 LOGE("the bundle returned from datacontrol-provider-service is null");
240                 return DATACONTROL_ERROR_INVALID_PARAMETER;
241         }
242
243         /* result list */
244         result_list = bundle_get_str_array(b, OSP_K_ARG, &result_list_len);
245         if (!result_list) {
246                 LOGE("Invalid Bundle: arguement list is null");
247                 return DATACONTROL_ERROR_INVALID_PARAMETER;
248         }
249
250         p = result_list[0]; /* result list[0] = provider_result */
251         if (!p) {
252                 LOGE("Invalid Bundle: provider_result is null");
253                 return DATACONTROL_ERROR_INVALID_PARAMETER;
254         }
255
256         LOGI("Provider result: %s", p);
257
258         provider_result = atoi(p);
259
260         error_message = result_list[1]; /* result list[1] = error */
261         if (!error_message) {
262                 LOGE("Invalid Bundle: error_message is null");
263                 return DATACONTROL_ERROR_INVALID_PARAMETER;
264         }
265
266         LOGI("Error message: %s", error_message);
267
268         provider_id = bundle_get_val(b, OSP_K_DATACONTROL_PROVIDER);
269         if (!provider_id) {
270                 LOGE("Invalid Bundle: provider_id is null");
271                 return DATACONTROL_ERROR_INVALID_PARAMETER;
272         }
273
274         data_id = bundle_get_val(b, OSP_K_DATACONTROL_DATA);
275         if (!data_id) {
276                 LOGE("Invalid Bundle: data_id is null");
277                 return DATACONTROL_ERROR_INVALID_PARAMETER;
278         }
279
280         LOGI("Provider ID: %s, Data ID: %s, Operation type: %d", provider_id, data_id, request_type);
281
282         switch (request_type) {
283         case DATACONTROL_TYPE_MAP_BULK_ADD:
284                 LOGI("BULK ADD RESPONSE");
285                 if (provider_result) {
286                         if (_recv_bulk_process(fd, &bulk_results)
287                                                 != DATACONTROL_ERROR_NONE)
288                                         return DATACONTROL_ERROR_IO_ERROR;
289                 }
290                 break;
291         case DATACONTROL_TYPE_MAP_GET:
292                 LOGI("GET RESPONSE");
293                 if (provider_result) {
294                         value_list = __map_get_value_list(fd, &value_count);
295
296                         if (value_list == NULL && value_count != 0) {
297                                 LOGE("Invalid data: value_list is null");
298                                 return DATACONTROL_ERROR_INVALID_PARAMETER;
299                         }
300                 }
301                 break;
302         case DATACONTROL_TYPE_MAP_SET:
303         case DATACONTROL_TYPE_MAP_ADD:
304         case DATACONTROL_TYPE_MAP_REMOVE:
305                 LOGI("SET or ADD or REMOVE RESPONSE");
306                 break;
307         default:
308                 break;
309         }
310
311         if (request_type >= DATACONTROL_TYPE_MAP_GET && request_type <= DATACONTROL_TYPE_MAP_BULK_ADD) {
312                 __map_call_cb(provider_id, request_id, request_type, data_id, provider_result,
313                                 error_message, value_list, value_count, bulk_results, data);
314                 ret = DATACONTROL_ERROR_NONE;
315         } else {
316                 ret = DATACONTROL_ERROR_INVALID_PARAMETER;
317         }
318
319         if (bulk_results)
320                 datacontrol_bulk_result_data_destroy(bulk_results);
321
322         if (value_list) {
323                 for (i = 0; i < value_count; i++) {
324                         if (value_list[i] != NULL)
325                                 free(value_list[i]);
326                 }
327                 free(value_list);
328         }
329
330         return ret;
331 }
332
333 static gboolean __recv_map_message(GIOChannel *channel,
334                 GIOCondition cond,
335                 gpointer data)
336 {
337         char *buf = NULL;
338         int nbytes;
339         guint nb;
340         int request_type = 0;
341         const char *request_code = NULL;
342         const char *p = NULL;
343         int request_id = -1;
344         bundle *kb = NULL;
345         gint fd = g_io_channel_unix_get_fd(channel);
346         map_response_cb_s *map_dc;
347         GList *itr;
348         datacontrol_consumer_request_info *request_info;
349
350         LOGI("__recv_map_message: ...from %d:%s%s%s%s\n", fd,
351                         (cond & G_IO_ERR) ? " ERR" : "",
352                         (cond & G_IO_HUP) ? " HUP" : "",
353                         (cond & G_IO_IN)  ? " IN"  : "",
354                         (cond & G_IO_PRI) ? " PRI" : "");
355
356         if (cond & (G_IO_ERR | G_IO_HUP))
357                 goto error;
358
359         if (cond & G_IO_IN) {
360                 if (_read_socket(fd, (char *)&nbytes, sizeof(nbytes), &nb)) {
361                         LOGE("Fail to read nbytes from socket");
362                         goto error;
363                 }
364                 LOGI("nbytes : %d", nbytes);
365
366                 if (nb == 0) {
367                         LOGE("__recv_map_message: ...from %d: socket closed\n", fd);
368                         goto error;
369                 }
370
371                 LOGI("__recv_map_message: ...from %d: %d bytes\n", fd, nbytes);
372                 if (nbytes > 0 && nbytes < MAX_REQUEST_ARGUMENT_SIZE) {
373                         buf = (char *) calloc(nbytes + 1, sizeof(char));
374                         if (buf == NULL) {
375                                 LOGE("Malloc failed!!");
376                                 goto error;
377                         }
378                         if (_read_socket(fd, buf, nbytes, &nb)) {
379                                 LOGE("Fail to read buf from socket");
380                                 goto error;
381                         }
382
383                         if (nb == 0) {
384                                 LOGE("__recv_map_message: ...from %d: socket closed\n", fd);
385                                 goto error;
386                         }
387
388                         kb = bundle_decode_raw((bundle_raw *)buf, nbytes);
389                         if (kb == NULL) {
390                                 LOGE("__recv_map_message: Unable to decode the bundle\n");
391                                 goto error;
392                         }
393
394                         LOGI("__recv_map_message: ...from %d: OK\n", fd);
395                         LOGI("__recv_map_message: ...caller appid %s: OK\n", bundle_get_val(kb, AUL_K_CALLER_APPID));
396
397                         p = bundle_get_val(kb, OSP_K_REQUEST_ID);
398                         if (!p) {
399                                 LOGE("Invalid Bundle: request_id is null");
400                                 goto error;
401                         } else {
402                                 request_id = atoi(p);
403                         }
404                         LOGI("Request ID: %d", request_id);
405
406                         if (data) {
407                                 request_code = bundle_get_val(kb, OSP_K_DATACONTROL_REQUEST_TYPE);
408                                 if (!request_code) {
409                                         LOGE("Invalid Bundle: data-control request type is null");
410                                         goto error;
411                                 }
412                                 request_type = atoi(request_code);
413
414                                 if (__map_handle_cb(fd, kb, request_type, request_id, 0, data) != DATACONTROL_ERROR_NONE)
415                                         goto error;
416                         } else {
417                                 LOGE("error: listener information is null");
418                                 goto error;
419                         }
420                         __remove_map_request_info(request_id, data);
421
422                         if (kb)
423                                 bundle_free(kb);
424                         if (buf)
425                                 free(buf);
426                 }
427         }
428         return TRUE;
429 error:
430         /* LCOV_EXCL_START */
431         if (kb)
432                 bundle_free(kb);
433         if (buf)
434                 free(buf);
435
436         if (((map_response_cb_s *)data) != NULL) {
437                 map_dc = (map_response_cb_s *)data;
438                 g_hash_table_remove(__socket_pair_hash, map_dc->provider_id);
439
440                 itr = g_list_first(map_dc->request_info_list);
441                 while (itr != NULL) {
442                         request_info = (datacontrol_consumer_request_info *)itr->data;
443                         __map_call_cb(map_dc->provider_id, request_info->request_id, request_info->type, map_dc->data_id, false,
444                                         "provider IO Error", NULL, 0, NULL, data);
445                         itr = g_list_next(itr);
446                 }
447                 if (map_dc->request_info_list) {
448                         LOGI("free map request_info_list");
449                         g_list_free_full(map_dc->request_info_list, free);
450                         map_dc->request_info_list = NULL;
451                 }
452         }
453         return FALSE;
454         /* LCOV_EXCL_STOP */
455 }
456
457 static int __map_request_provider(datacontrol_h provider, datacontrol_request_type type, bundle *request_data, void *extra_data, int request_id)
458 {
459         char *app_id = NULL;
460         void *data = NULL;
461         int ret = DATACONTROL_ERROR_NONE;
462         void *map_dc_returned = NULL;
463         char caller_app_id[255];
464         char datacontrol_request_operation[MAX_LEN_DATACONTROL_REQ_TYPE] = {0, };
465         char req_id[32] = {0,};
466         int count = 0;
467         const int TRY_COUNT = 2;
468         const struct timespec TRY_SLEEP_TIME = { 0, 1000 * 1000 * 1000 };
469         bundle *send_data;
470
471         LOGI("Map Data control request, type: %d, request id: %d", type, request_id);
472
473         if (type < DATACONTROL_TYPE_MAP_GET || type > DATACONTROL_TYPE_MAP_BULK_ADD) {
474                 LOGE("Invalid request type: %d", (int)type);
475                 return DATACONTROL_ERROR_INVALID_PARAMETER;
476         }
477
478         if (__socket_pair_hash == NULL)
479                 __socket_pair_hash = g_hash_table_new_full(g_str_hash, g_str_equal, free, _socket_info_free);
480
481         if (!datacontrol_map_tree_root) {
482                 LOGE("The listener tree is empty");
483                 return DATACONTROL_ERROR_INVALID_PARAMETER;
484         }
485
486         map_response_cb_s *map_dc_temp = (map_response_cb_s *)calloc(1, sizeof(map_response_cb_s));
487         if (!map_dc_temp) {
488                 LOGE("Failed to create map datacontrol");
489                 return DATACONTROL_ERROR_OUT_OF_MEMORY;
490         }
491
492         map_dc_temp->provider_id = strdup(provider->provider_id);
493         if (!map_dc_temp->provider_id) {
494                 LOGE("Failed to assign provider id to map data control: %d", errno);
495                 free(map_dc_temp);
496                 return DATACONTROL_ERROR_OUT_OF_MEMORY;
497         }
498
499         map_dc_temp->data_id = strdup(provider->data_id);
500         if (!map_dc_temp->data_id) {
501                 LOGE("Failed to assign data id to map data control: %d", errno);
502                 free(map_dc_temp->provider_id);
503                 free(map_dc_temp);
504                 return DATACONTROL_ERROR_OUT_OF_MEMORY;
505         }
506
507         map_dc_temp->app_id = NULL;
508         map_dc_temp->access_info = NULL;
509         map_dc_temp->user_data = NULL;
510         map_dc_temp->map_response_cb = NULL;
511
512         map_dc_returned = tfind(map_dc_temp, &datacontrol_map_tree_root, __map_instance_compare);
513
514         __map_instance_free(map_dc_temp);
515
516         if (!map_dc_returned) {
517                 LOGE("Finding the map datacontrol in the listener tree is failed.");
518                 return DATACONTROL_ERROR_INVALID_PARAMETER;
519         }
520
521         map_response_cb_s *map_dc = *(map_response_cb_s **)map_dc_returned;
522         app_id = map_dc->app_id;
523         datacontrol_consumer_request_info *request_info = (datacontrol_consumer_request_info *)calloc(sizeof(datacontrol_consumer_request_info), 1);
524         request_info->request_id = request_id;
525         request_info->type = type;
526         map_dc->request_info_list = g_list_append(map_dc->request_info_list, request_info);
527         data = map_dc;
528
529         LOGI("Map datacontrol appid: %s", map_dc->app_id);
530
531         pid_t pid = getpid();
532         if (aul_app_get_appid_bypid(pid, caller_app_id, sizeof(caller_app_id)) != 0) {
533                 LOGE("Failed to get appid by pid(%d).", pid);
534                 return DATACONTROL_ERROR_INVALID_PARAMETER;
535         }
536
537         send_data = bundle_dup(request_data);
538         if (send_data == NULL) {
539                 LOGE("fail to alloc result_data");
540                 return DATACONTROL_ERROR_OUT_OF_MEMORY;
541         }
542
543         bundle_add_str(send_data, OSP_K_DATACONTROL_PROTOCOL_VERSION, OSP_V_VERSION_2_1_0_3);
544         bundle_add_str(send_data, AUL_K_CALLER_APPID, caller_app_id);
545
546         snprintf(datacontrol_request_operation, MAX_LEN_DATACONTROL_REQ_TYPE, "%d", (int)(type));
547         bundle_add_str(send_data, OSP_K_DATACONTROL_REQUEST_TYPE, datacontrol_request_operation);
548
549         snprintf(req_id, 32, "%d", request_id);
550         bundle_add_str(send_data, OSP_K_REQUEST_ID, req_id);
551
552         LOGI("caller_id %s, app_id %s", caller_app_id, app_id);
553
554         do {
555                 datacontrol_socket_info *socket_info = g_hash_table_lookup(__socket_pair_hash, provider->provider_id);
556                 if (socket_info == NULL) {
557                         ret = _request_appsvc_run(caller_app_id, app_id);
558                         if (ret != DATACONTROL_ERROR_NONE) {
559                                 bundle_free(send_data);
560                                 return ret;
561                         }
562
563                         socket_info = _add_watch_on_socket_info(caller_app_id, app_id, "consumer", __recv_map_message, data);
564                         if (socket_info == NULL) {
565                                 bundle_free(send_data);
566                                 return DATACONTROL_ERROR_IO_ERROR;
567                         }
568
569                         g_hash_table_insert(__socket_pair_hash, strdup(provider->provider_id), socket_info);
570                 }
571
572                 LOGI("send data from consumer !!!");
573                 ret = _datacontrol_send_async(socket_info->socket_fd, send_data, extra_data, type, NULL);
574                 if (ret != DATACONTROL_ERROR_NONE)
575                         g_hash_table_remove(__socket_pair_hash, provider->provider_id);
576                 else
577                         break;
578                 count++;
579                 nanosleep(&TRY_SLEEP_TIME, 0);
580         } while (ret != DATACONTROL_ERROR_NONE && count < TRY_COUNT);
581
582         bundle_free(send_data);
583         return ret;
584 }
585
586 int datacontrol_map_create(datacontrol_h *provider)
587 {
588         struct datacontrol_s *request;
589
590         if (provider == NULL)
591                 return DATACONTROL_ERROR_INVALID_PARAMETER;
592
593         request = malloc(sizeof(struct datacontrol_s));
594         if (request == NULL)
595                 return DATACONTROL_ERROR_OUT_OF_MEMORY;
596
597         request->provider_id = NULL;
598         request->data_id = NULL;
599
600         *provider = request;
601
602         return 0;
603 }
604
605 int datacontrol_map_destroy(datacontrol_h provider)
606 {
607         if (provider == NULL)
608                 return DATACONTROL_ERROR_INVALID_PARAMETER;
609
610         if (provider->provider_id != NULL)
611                 free(provider->provider_id);
612
613         if (provider->data_id != NULL)
614                 free(provider->data_id);
615
616         free(provider);
617
618         return 0;
619 }
620
621 int datacontrol_map_set_provider_id(datacontrol_h provider, const char *provider_id)
622 {
623         if (provider == NULL || provider_id == NULL)
624                 return DATACONTROL_ERROR_INVALID_PARAMETER;
625
626         if (provider->provider_id != NULL)
627                 free(provider->provider_id);
628
629         provider->provider_id = strdup(provider_id);
630         if (provider->provider_id == NULL)
631                 return DATACONTROL_ERROR_OUT_OF_MEMORY;
632
633         return 0;
634 }
635
636 int datacontrol_map_get_provider_id(datacontrol_h provider, char **provider_id)
637 {
638         if (provider == NULL || provider_id == NULL)
639                 return DATACONTROL_ERROR_INVALID_PARAMETER;
640
641         if (provider->provider_id != NULL) {
642                 *provider_id = strdup(provider->provider_id);
643                 if (*provider_id == NULL)
644                         return DATACONTROL_ERROR_OUT_OF_MEMORY;
645
646         } else {
647                 *provider_id = NULL;
648         }
649
650         return 0;
651 }
652
653 int datacontrol_map_set_data_id(datacontrol_h provider, const char *data_id)
654 {
655         if (provider == NULL || data_id == NULL)
656                 return DATACONTROL_ERROR_INVALID_PARAMETER;
657
658         if (provider->data_id != NULL)
659                 free(provider->data_id);
660
661         provider->data_id = strdup(data_id);
662         if (provider->data_id == NULL)
663                 return DATACONTROL_ERROR_OUT_OF_MEMORY;
664
665         return 0;
666 }
667
668 int datacontrol_map_get_data_id(datacontrol_h provider, char **data_id)
669 {
670         if (provider == NULL || data_id == NULL)
671                 return DATACONTROL_ERROR_INVALID_PARAMETER;
672
673         if (provider->data_id != NULL) {
674                 *data_id = strdup(provider->data_id);
675                 if (*data_id == NULL)
676                         return DATACONTROL_ERROR_OUT_OF_MEMORY;
677
678         } else {
679                 *data_id = NULL;
680         }
681
682         return 0;
683 }
684
685 bool datacontrol_map_cb_is_registered(char *provider_id)
686 {
687         map_response_cb_s map_dc_temp;
688         map_dc_temp.provider_id = provider_id;
689
690         if (tfind(&map_dc_temp, &datacontrol_map_tree_root, __map_instance_compare) != NULL)
691                 return true;
692         return false;
693 }
694
695 int datacontrol_map_register_response_cb(datacontrol_h provider, datacontrol_map_response_cb *callback, void *user_data)
696 {
697         int ret = 0;
698         char *app_id = NULL;
699         char *access = NULL;
700         void *map_dc_returned = NULL;
701
702         ret = pkgmgrinfo_appinfo_usr_get_datacontrol_info(provider->provider_id, "Map", getuid(), &app_id, &access);
703         if (ret != PMINFO_R_OK) {
704                 LOGE("unable to get map data control information: %d", ret);
705                 return DATACONTROL_ERROR_IO_ERROR;
706         }
707
708         LOGI("data control provider appid = %s", app_id);
709
710         map_response_cb_s *map_dc_temp = (map_response_cb_s *)calloc(1, sizeof(map_response_cb_s));
711         if (!map_dc_temp) {
712                 LOGE("unable to create a temporary map data control");
713                 ret = DATACONTROL_ERROR_OUT_OF_MEMORY;
714                 goto EXCEPTION;
715         }
716
717         map_dc_temp->provider_id = strdup(provider->provider_id);
718         if (!map_dc_temp->provider_id) {
719                 LOGE("unable to assign provider_id to map data control: %d", errno);
720                 ret = DATACONTROL_ERROR_OUT_OF_MEMORY;
721                 goto EXCEPTION;
722         }
723
724         map_dc_temp->data_id = strdup(provider->data_id);
725         if (!map_dc_temp->data_id) {
726                 LOGE("unable to assign data_id to map data control: %d", errno);
727                 ret = DATACONTROL_ERROR_OUT_OF_MEMORY;
728                 goto EXCEPTION;
729         }
730
731         map_dc_temp->app_id = app_id;
732         map_dc_temp->access_info = access;
733         map_dc_temp->user_data = user_data;
734         map_dc_temp->map_response_cb = callback;
735
736         map_dc_returned = tsearch(map_dc_temp, &datacontrol_map_tree_root, __map_instance_compare);
737
738         map_response_cb_s *map_dc = *(map_response_cb_s **)map_dc_returned;
739         if (map_dc != map_dc_temp) {
740                 map_dc->map_response_cb = callback;
741                 map_dc->user_data = user_data;
742                 LOGI("the data control is already set");
743                 __map_instance_free(map_dc_temp);
744         }
745
746         return DATACONTROL_ERROR_NONE;
747
748         /* LCOV_EXCL_START */
749 EXCEPTION:
750         if (access)
751                 free(access);
752         if (app_id)
753                 free(app_id);
754         if (map_dc_temp) {
755                 if (map_dc_temp->provider_id)
756                         free(map_dc_temp->provider_id);
757                 if (map_dc_temp->data_id)
758                         free(map_dc_temp->data_id);
759                 free(map_dc_temp);
760         }
761
762         return ret;
763         /* LCOV_EXCL_STOP */
764 }
765
766 int datacontrol_map_unregister_response_cb(datacontrol_h provider)
767 {
768         int ret = DATACONTROL_ERROR_NONE;
769         map_response_cb_s *map_dc_temp = (map_response_cb_s *)calloc(1, sizeof(map_response_cb_s));
770         void *map_dc_returned = NULL;
771
772         g_hash_table_remove(__socket_pair_hash, provider->provider_id);
773
774         if (!map_dc_temp) {
775                 LOGE("unable to create a temporary map data control");
776                 ret = DATACONTROL_ERROR_OUT_OF_MEMORY;
777                 goto EXCEPTION;
778         }
779
780         map_dc_temp->provider_id = strdup(provider->provider_id);
781         if (!map_dc_temp->provider_id) {
782                 LOGE("unable to assign provider_id to map data control: %d", errno);
783                 ret = DATACONTROL_ERROR_OUT_OF_MEMORY;
784                 goto EXCEPTION;
785         }
786
787         map_dc_returned = tdelete(map_dc_temp, &datacontrol_map_tree_root, __map_instance_compare);
788         if (map_dc_returned == NULL) {
789                 LOGE("invalid parameter");
790                 ret = DATACONTROL_ERROR_INVALID_PARAMETER;
791                 goto EXCEPTION;
792         }
793
794         /* LCOV_EXCL_START */
795 EXCEPTION:
796          if (map_dc_temp) {
797                 if (map_dc_temp->provider_id)
798                         free(map_dc_temp->provider_id);
799                 free(map_dc_temp);
800          }
801
802          return ret;
803         /* LCOV_EXCL_STOP */
804 }
805
806 int datacontrol_map_get(datacontrol_h provider, const char *key, int *request_id)
807 {
808         return datacontrol_map_get_with_page(provider, key, request_id, 1, 20);
809 }
810
811 int datacontrol_map_get_with_page(datacontrol_h provider, const char *key, int *request_id, int page_number, int count_per_page)
812 {
813         unsigned int arg_size;
814         int ret = 0;
815         const char *arg_list[4];
816         char page_no_str[32];
817         char count_per_page_str[32];
818         int reqId;
819
820         if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || key == NULL) {
821                 LOGE("Invalid parameter");
822                 return DATACONTROL_ERROR_INVALID_PARAMETER;
823         }
824
825         LOGI("Gets the value list from provider_id: %s, data_id: %s", provider->provider_id, provider->data_id);
826
827         arg_size = (strlen(provider->data_id) + strlen(key)) * sizeof(wchar_t);
828         if (arg_size > MAX_REQUEST_ARGUMENT_SIZE) {
829                 LOGE("The size of sending argument (%u) exceeds the maximum limit.", arg_size);
830                 return DATACONTROL_ERROR_MAX_EXCEEDED;
831         }
832
833         bundle *b = bundle_create();
834         if (!b) {
835                 LOGE("unable to create bundle: %d", errno);
836                 return DATACONTROL_ERROR_INVALID_PARAMETER;
837         }
838
839         bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
840         bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
841
842         arg_list[0] = provider->data_id;
843         arg_list[1] = key;
844
845         ret = snprintf(page_no_str, sizeof(page_no_str), "%d", page_number);
846         if (ret < 0) {
847                 LOGE("unable to convert page no to string: %d", errno);
848                 bundle_free(b);
849                 return DATACONTROL_ERROR_OUT_OF_MEMORY;
850         }
851
852         ret = snprintf(count_per_page_str, sizeof(count_per_page_str), "%d", count_per_page);
853         if (ret < 0) {
854                 LOGE("unable to convert count per page no to string: %d", errno);
855                 bundle_free(b);
856                 return DATACONTROL_ERROR_OUT_OF_MEMORY;
857         }
858
859         arg_list[2] = page_no_str;
860         arg_list[3] = count_per_page_str;
861
862         bundle_add_str_array(b, OSP_K_ARG, arg_list, 4);
863
864         /* Set the request id */
865         reqId = _datacontrol_create_request_id();
866         *request_id = reqId;
867
868         ret = __map_request_provider(provider, DATACONTROL_TYPE_MAP_GET, b, NULL, reqId);
869         bundle_free(b);
870
871         return ret;
872 }
873
874 int datacontrol_map_set(datacontrol_h provider, const char *key, const char *old_value, const char *new_value, int *request_id)
875 {
876         unsigned int arg_size;
877         bundle *b;
878         const char *arg_list[4];
879         int reqId;
880         int ret;
881
882         if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || key == NULL || old_value == NULL || new_value == NULL) {
883                 LOGE("Invalid parameter");
884                 return DATACONTROL_ERROR_INVALID_PARAMETER;
885         }
886
887         LOGI("Sets the old value to new value in provider_id: %s, data_id: %s", provider->provider_id, provider->data_id);
888
889         arg_size = (strlen(provider->data_id) + strlen(key) + strlen(old_value) + strlen(new_value)) * sizeof(wchar_t);
890         if (arg_size > MAX_REQUEST_ARGUMENT_SIZE) {
891                 LOGE("The size of sending argument (%u) exceeds the maximum limit.", arg_size);
892                 return DATACONTROL_ERROR_MAX_EXCEEDED;
893         }
894
895         b = bundle_create();
896         if (!b) {
897                 LOGE("unable to create bundle: %d", errno);
898                 return DATACONTROL_ERROR_OUT_OF_MEMORY;
899         }
900
901         bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
902         bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
903
904         arg_list[0] = provider->data_id;
905         arg_list[1] = key;
906         arg_list[2] = old_value;
907         arg_list[3] = new_value;
908
909         bundle_add_str_array(b, OSP_K_ARG, arg_list, 4);
910
911         /* Set the request id */
912         reqId = _datacontrol_create_request_id();
913         *request_id = reqId;
914
915         ret = __map_request_provider(provider, DATACONTROL_TYPE_MAP_SET, b, NULL, reqId);
916         bundle_free(b);
917
918         return ret;
919 }
920
921 int datacontrol_map_add_bulk_data(datacontrol_h provider, data_control_bulk_data_h bulk_data_h, int *request_id)
922 {
923         long long arg_size = 0;
924         bundle *b;
925         bundle *data;
926         const char *arg_list[3];
927         int ret;
928         int count;
929         int i;
930
931         if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL) {
932                 LOGE("Invalid parameter");
933                 return DATACONTROL_ERROR_INVALID_PARAMETER;
934         }
935
936         LOGI("Adds the value in provider_id: %s, data_id: %s", provider->provider_id, provider->data_id);
937         datacontrol_bulk_data_get_count(bulk_data_h, &count);
938         for (i = 0; i < count; i++) {
939                 datacontrol_bulk_data_get_data(bulk_data_h, i, &data);
940                 bundle_foreach(data, _bundle_foreach_check_arg_size_cb, &arg_size);
941         }
942
943         arg_size += (strlen(provider->data_id) + strlen(provider->provider_id)) * sizeof(char);
944         if (arg_size > MAX_REQUEST_ARGUMENT_SIZE) {
945                 LOGE("The size of sending argument (%u) exceeds the maximum limit.", arg_size);
946                 return DATACONTROL_ERROR_MAX_EXCEEDED;
947         }
948
949         b = bundle_create();
950         if (!b) {
951                 LOGE("unable to create bundle: %d", errno);
952                 return DATACONTROL_ERROR_OUT_OF_MEMORY;
953         }
954
955         bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
956         bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
957
958         arg_list[0] = provider->data_id;
959
960         bundle_add_str_array(b, OSP_K_ARG, arg_list, 1);
961         *request_id = _datacontrol_create_request_id();
962
963         ret = __map_request_provider(provider, DATACONTROL_TYPE_MAP_BULK_ADD, b, bulk_data_h, *request_id);
964         bundle_free(b);
965
966         return ret;
967 }
968
969
970 int datacontrol_map_add(datacontrol_h provider, const char *key, const char *value, int *request_id)
971 {
972         unsigned int arg_size;
973         bundle *b;
974         const char *arg_list[3];
975         int reqId;
976         int ret;
977
978         if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || key == NULL || value == NULL) {
979                 LOGE("Invalid parameter");
980                 return DATACONTROL_ERROR_INVALID_PARAMETER;
981         }
982
983         LOGI("Adds the value in provider_id: %s, data_id: %s", provider->provider_id, provider->data_id);
984
985         arg_size = (strlen(provider->data_id) + strlen(key) + strlen(value)) * sizeof(wchar_t);
986         if (arg_size > MAX_REQUEST_ARGUMENT_SIZE) {
987                 LOGE("The size of sending argument (%u) exceeds the maximum limit.", arg_size);
988                 return DATACONTROL_ERROR_MAX_EXCEEDED;
989         }
990
991         b = bundle_create();
992         if (!b) {
993                 LOGE("unable to create bundle: %d", errno);
994                 return DATACONTROL_ERROR_OUT_OF_MEMORY;
995         }
996
997         bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
998         bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
999
1000         arg_list[0] = provider->data_id;
1001         arg_list[1] = key;
1002         arg_list[2] = value;
1003
1004         bundle_add_str_array(b, OSP_K_ARG, arg_list, 3);
1005
1006         /* Set the request id */
1007         reqId = _datacontrol_create_request_id();
1008         *request_id = reqId;
1009
1010         ret = __map_request_provider(provider, DATACONTROL_TYPE_MAP_ADD, b, NULL, reqId);
1011         bundle_free(b);
1012
1013         return ret;
1014 }
1015
1016 int datacontrol_map_remove(datacontrol_h provider, const char *key, const char *value, int *request_id)
1017 {
1018         unsigned int arg_size;
1019         bundle *b;
1020         const char *arg_list[3];
1021         int reqId;
1022         int ret;
1023
1024         if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || key == NULL || value == NULL) {
1025                 LOGE("Invalid parameter");
1026                 return DATACONTROL_ERROR_INVALID_PARAMETER;
1027         }
1028
1029         LOGI("Removes the value in provider_id: %s, data_id: %s", provider->provider_id, provider->data_id);
1030
1031         arg_size = (strlen(provider->data_id) + strlen(key) + strlen(value)) * sizeof(wchar_t);
1032         if (arg_size > MAX_REQUEST_ARGUMENT_SIZE) {
1033                 LOGE("The size of sending argument (%u) exceeds the maximum limit.", arg_size);
1034                 return DATACONTROL_ERROR_MAX_EXCEEDED;
1035         }
1036
1037         b = bundle_create();
1038         if (!b) {
1039                 LOGE("unable to create bundle: %d", errno);
1040                 return DATACONTROL_ERROR_OUT_OF_MEMORY;
1041         }
1042
1043         bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
1044         bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
1045
1046         arg_list[0] = provider->data_id;
1047         arg_list[1] = key;
1048         arg_list[2] = value;
1049
1050         bundle_add_str_array(b, OSP_K_ARG, arg_list, 3);
1051
1052         /* Set the request id */
1053         reqId = _datacontrol_create_request_id();
1054         *request_id = reqId;
1055
1056         ret = __map_request_provider(provider, DATACONTROL_TYPE_MAP_REMOVE, b, NULL, reqId);
1057         bundle_free(b);
1058
1059         return ret;
1060 }
1061