76a11492c3e779ece3f833a0664115444bf2e0ae
[apps/livebox/data-provider-master.git] / src / notification_service.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (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://floralicense.org/license/
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 #include <stdio.h>
17
18 #include <Eina.h>
19
20 #include <dlog.h>
21 #if defined(HAVE_LIVEBOX)
22 #include <livebox-errno.h>
23 #else
24 #include "lite-errno.h"
25 #endif
26 #include <packet.h>
27
28 #include <sys/smack.h>
29 #include <security-server.h>
30
31 #include <vconf.h>
32 #include <notification_ipc.h>
33 #include <notification_noti.h>
34 #include <notification_error.h>
35 #include <notification_setting_service.h>
36
37 #include "service_common.h"
38 #include "debug.h"
39 #include "util.h"
40 #include "conf.h"
41
42 #ifndef NOTIFICATION_DEL_PACKET_UNIT
43 #define NOTIFICATION_DEL_PACKET_UNIT 10
44 #endif
45
46 static struct info {
47         Eina_List *context_list;
48         struct service_context *svc_ctx;
49 } s_info = {
50         .context_list = NULL, /*!< \WARN: This is only used for SERVICE THREAD */
51         .svc_ctx = NULL, /*!< \WARN: This is only used for MAIN THREAD */
52 };
53
54 struct context {
55         struct tcb *tcb;
56         double seq;
57 };
58
59 struct noti_service {
60         const char *cmd;
61         void (*handler)(struct tcb *tcb, struct packet *packet, void *data);
62         const char *rule;
63         const char *access;
64         void (*handler_access_error)(struct tcb *tcb, struct packet *packet);
65 };
66
67 static inline char *_string_get(char *string)
68 {
69         if (string == NULL) {
70                 return NULL;
71         }
72         if (string[0] == '\0') {
73                 return NULL;
74         }
75
76         return string;
77 }
78
79 /*!
80  * FUNCTIONS to create packets
81  */
82 static inline int _priv_id_get_from_list(int num_data, int *list, int index) {
83         if (index < num_data) {
84                 return *(list + index);
85         } else {
86                 return -1;
87         }
88 }
89
90 static inline struct packet *_packet_create_with_list(int op_num, int *list, int start_index) {
91         return packet_create(
92                 "del_noti_multiple",
93                 "iiiiiiiiiii",
94                 ((op_num - start_index) > NOTIFICATION_DEL_PACKET_UNIT) ? NOTIFICATION_DEL_PACKET_UNIT : op_num - start_index,
95                 _priv_id_get_from_list(op_num, list, start_index),
96                 _priv_id_get_from_list(op_num, list, start_index + 1),
97                 _priv_id_get_from_list(op_num, list, start_index + 2),
98                 _priv_id_get_from_list(op_num, list, start_index + 3),
99                 _priv_id_get_from_list(op_num, list, start_index + 4),
100                 _priv_id_get_from_list(op_num, list, start_index + 5),
101                 _priv_id_get_from_list(op_num, list, start_index + 6),
102                 _priv_id_get_from_list(op_num, list, start_index + 7),
103                 _priv_id_get_from_list(op_num, list, start_index + 8),
104                 _priv_id_get_from_list(op_num, list, start_index + 9)
105                 );
106 }
107
108 /*!
109  * SERVICE HANDLER
110  */
111 static void _handler_insert(struct tcb *tcb, struct packet *packet, void *data)
112 {
113         int ret = 0, ret_p = 0;
114         int priv_id = 0;
115         struct packet *packet_reply = NULL;
116         struct packet *packet_service = NULL;
117         notification_h noti = NULL;
118
119         noti = notification_create(NOTIFICATION_TYPE_NOTI);
120         if (noti != NULL) {
121                 if (notification_ipc_make_noti_from_packet(noti, packet) == NOTIFICATION_ERROR_NONE) {
122                         ret = notification_noti_insert(noti);
123                         notification_get_id(noti, NULL, &priv_id);
124                         DbgPrint("priv_id: [%d]\n", priv_id);
125                         packet_reply = packet_create_reply(packet, "ii", ret, priv_id);
126                         if (packet_reply) {
127                                 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
128                                         ErrPrint("failed to send reply packet: %d\n", ret_p);
129                                 }
130                                 packet_destroy(packet_reply);
131                         } else {
132                                 ErrPrint("failed to create a reply packet\n");
133                         }
134
135                         if (ret != NOTIFICATION_ERROR_NONE) {
136                                 ErrPrint("failed to insert a notification: %d\n", ret);
137                                 notification_free(noti);
138                                 return ;
139                         }
140
141                         packet_service = notification_ipc_make_packet_from_noti(noti, "add_noti", 2);
142                         if (packet_service != NULL) {
143                                 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
144                                         ErrPrint("failed to send a multicast packet: %d\n", ret_p);
145                                 }
146                                 packet_destroy(packet_service);
147                         } else {
148                                 ErrPrint("failed to create a multicats packet\n");
149                         }
150                 } else {
151                         ErrPrint("Failed to create the packet");
152                 }
153                 notification_free(noti);
154         }
155 }
156
157 static void _handler_update(struct tcb *tcb, struct packet *packet, void *data)
158 {
159         int ret = 0, ret_p = 0;
160         int priv_id = 0;
161         struct packet *packet_reply = NULL;
162         struct packet *packet_service = NULL;
163         notification_h noti = NULL;
164
165         noti = notification_create(NOTIFICATION_TYPE_NOTI);
166         if (noti != NULL) {
167                 if (notification_ipc_make_noti_from_packet(noti, packet) == NOTIFICATION_ERROR_NONE) {
168                         ret = notification_noti_update(noti);
169
170                         notification_get_id(noti, NULL, &priv_id);
171                         DbgPrint("priv_id: [%d]\n", priv_id);
172                         packet_reply = packet_create_reply(packet, "ii", ret, priv_id);
173                         if (packet_reply) {
174                                 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
175                                         ErrPrint("failed to send reply packet:%d\n", ret_p);
176                                 }
177                                 packet_destroy(packet_reply);
178                         } else {
179                                 ErrPrint("failed to create a reply packet\n");
180                         }
181
182                         if (ret != NOTIFICATION_ERROR_NONE) {
183                                 ErrPrint("failed to update a notification:%d\n", ret);
184                                 notification_free(noti);
185                                 return ;
186                         }
187
188                         packet_service = notification_ipc_make_packet_from_noti(noti, "update_noti", 2);
189                         if (packet_service != NULL) {
190                                 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
191                                         ErrPrint("failed to send a multicast packet: %d\n", ret_p);
192                                 }
193                                 packet_destroy(packet_service);
194                         }
195                 } else {
196                         ErrPrint("Failed to create the packet");
197                 }
198                 notification_free(noti);
199         }
200 }
201
202 static void _handler_refresh(struct tcb *tcb, struct packet *packet, void *data)
203 {
204         int ret = 0;
205         struct packet *packet_reply = NULL;
206
207         packet_reply = packet_create_reply(packet, "i", ret);
208         if (packet_reply) {
209                 if ((ret = service_common_unicast_packet(tcb, packet_reply)) < 0) {
210                         ErrPrint("failed to send reply packet:%d\n", ret);
211                 }
212                 packet_destroy(packet_reply);
213         } else {
214                 ErrPrint("failed to create a reply packet\n");
215         }
216
217         if ((ret = service_common_multicast_packet(tcb, packet, TCB_CLIENT_TYPE_SERVICE)) < 0) {
218                 ErrPrint("failed to send a multicast packet:%d\n", ret);
219         }
220 }
221
222 static void _handler_delete_single(struct tcb *tcb, struct packet *packet, void *data)
223 {
224         int num_changes = 0;
225         int ret = 0, ret_p = 0;
226         int priv_id = 0;
227         struct packet *packet_reply = NULL;
228         struct packet *packet_service = NULL;
229         char *pkgname = NULL;
230
231         if (packet_get(packet, "si", &pkgname, &priv_id) == 2) {
232                 pkgname = _string_get(pkgname);
233
234                 ret = notification_noti_delete_by_priv_id_get_changes(pkgname, priv_id, &num_changes);
235
236                 DbgPrint("priv_id: [%d] num_delete:%d\n", priv_id, num_changes);
237                 packet_reply = packet_create_reply(packet, "ii", ret, priv_id);
238                 if (packet_reply) {
239                         if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
240                                 ErrPrint("failed to send reply packet:%d\n", ret_p);
241                         }
242                         packet_destroy(packet_reply);
243                 } else {
244                         ErrPrint("failed to create a reply packet\n");
245                 }
246
247                 if (ret != NOTIFICATION_ERROR_NONE || num_changes <= 0) {
248                         ErrPrint("failed to delete a notification:%d %d\n", ret, num_changes);
249                         return ;
250                 }
251
252                 packet_service = packet_create("del_noti_single", "ii", 1, priv_id);
253                 if (packet_service != NULL) {
254                         if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
255                                 ErrPrint("failed to send a multicast packet: %d\n", ret_p);
256                         }
257                         packet_destroy(packet_service);
258                 }
259         } else {
260                 ErrPrint("Failed to get data from the packet");
261         }
262 }
263
264 static void _handler_delete_multiple(struct tcb *tcb, struct packet *packet, void *data)
265 {
266         int ret = 0, ret_p = 0;
267         struct packet *packet_reply = NULL;
268         struct packet *packet_service = NULL;
269         char *pkgname = NULL;
270         notification_type_e type = 0;
271         int num_deleted = 0;
272         int *list_deleted = NULL;
273
274         if (packet_get(packet, "si", &pkgname, &type) == 2) {
275                 pkgname = _string_get(pkgname);
276                 DbgPrint("pkgname: [%s] type: [%d]\n", pkgname, type);
277
278                 ret = notification_noti_delete_all(type, pkgname, &num_deleted, &list_deleted);
279                 DbgPrint("ret: [%d] num_deleted: [%d]\n", ret, num_deleted);
280
281                 packet_reply = packet_create_reply(packet, "ii", ret, num_deleted);
282                 if (packet_reply) {
283                         if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
284                                 ErrPrint("failed to send reply packet:%d\n", ret_p);
285                         }
286                         packet_destroy(packet_reply);
287                 } else {
288                         ErrPrint("failed to create a reply packet\n");
289                 }
290
291                 if (ret != NOTIFICATION_ERROR_NONE) {
292                         ErrPrint("failed to delete notifications:%d\n", ret);
293                         if (list_deleted != NULL) {
294                                 DbgFree(list_deleted);
295                         }
296                         return ;
297                 }
298
299                 if (num_deleted > 0) {
300                         if (num_deleted <= NOTIFICATION_DEL_PACKET_UNIT) {
301                                 packet_service = _packet_create_with_list(num_deleted, list_deleted, 0);
302
303                                 if (packet_service) {
304                                         if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
305                                                 ErrPrint("failed to send a multicast packet: %d\n", ret_p);
306                                         }
307                                         packet_destroy(packet_service);
308                                 } else {
309                                         ErrPrint("failed to create a multicast packet\n");
310                                 }
311                         } else {
312                                 int set = 0;
313                                 int set_total = num_deleted / NOTIFICATION_DEL_PACKET_UNIT;
314
315                                 for (set = 0; set <= set_total; set++) {
316                                         packet_service = _packet_create_with_list(num_deleted,
317                                                         list_deleted, set * NOTIFICATION_DEL_PACKET_UNIT);
318
319                                         if (packet_service) {
320                                                 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
321                                                         ErrPrint("failed to send a multicast packet:%d\n", ret_p);
322                                                 }
323                                                 packet_destroy(packet_service);
324                                         } else {
325                                                 ErrPrint("failed to create a multicast packet\n");
326                                         }
327                                 }
328                         }
329                 }
330
331                 if (list_deleted != NULL) {
332                         DbgFree(list_deleted);
333                         list_deleted = NULL;
334                 }
335         } else {
336                 ErrPrint("Failed to get data from the packet");
337         }
338 }
339
340 static void _handler_noti_property_set(struct tcb *tcb, struct packet *packet, void *data)
341 {
342         int ret = 0, ret_p = 0;
343         struct packet *packet_reply = NULL;
344         char *pkgname = NULL;
345         char *property = NULL;
346         char *value = NULL;
347
348         if (packet_get(packet, "sss", &pkgname, &property, &value) == 3) {
349                 pkgname = _string_get(pkgname);
350                 property = _string_get(property);
351                 value = _string_get(value);
352
353                 ret = notification_setting_db_set(pkgname, property, value);
354
355                 packet_reply = packet_create_reply(packet, "ii", ret, ret);
356                 if (packet_reply) {
357                         if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
358                                 ErrPrint("failed to send reply packet:%d\n", ret_p);
359                         }
360                         packet_destroy(packet_reply);
361                 } else {
362                         ErrPrint("failed to create a reply packet\n");
363                 }
364
365                 if (ret != NOTIFICATION_ERROR_NONE) {
366                         ErrPrint("failed to set noti property:%d\n", ret);
367                 }
368         } else {
369                 ErrPrint("Failed to get data from the packet");
370         }
371 }
372
373 static void _handler_noti_property_get(struct tcb *tcb, struct packet *packet, void *data)
374 {
375         int ret = 0, ret_p = 0;
376         struct packet *packet_reply = NULL;
377         char *pkgname = NULL;
378         char *property = NULL;
379         char *value = NULL;
380
381         if (packet_get(packet, "sss", &pkgname, &property) == 2) {
382                 pkgname = _string_get(pkgname);
383                 property = _string_get(property);
384
385                 ret = notification_setting_db_get(pkgname, property, &value);
386
387                 packet_reply = packet_create_reply(packet, "is", ret, value);
388                 if (packet_reply) {
389                         if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
390                                 ErrPrint("failed to send reply packet:%d\n", ret_p);
391                         }
392                         packet_destroy(packet_reply);
393                 } else {
394                         ErrPrint("failed to create a reply packet\n");
395                 }
396
397                 if (value != NULL) {
398                         DbgFree(value);
399                 }
400         }
401 }
402
403 static void _handler_service_register(struct tcb *tcb, struct packet *packet, void *data)
404 {
405         int ret = 0;
406         struct packet *packet_reply;
407
408         ret = tcb_client_type_set(tcb, TCB_CLIENT_TYPE_SERVICE);
409
410         packet_reply = packet_create_reply(packet, "i", ret);
411         if (packet_reply) {
412                 if ((ret = service_common_unicast_packet(tcb, packet_reply)) < 0) {
413                         ErrPrint("failed to send reply packet:%d\n", ret);
414                 }
415                 packet_destroy(packet_reply);
416         } else {
417                 ErrPrint("failed to create a reply packet\n");
418         }
419 }
420
421 /*!
422  * SERVICE PERMISSION CHECK
423  */
424 static void _permission_check_common(struct tcb *tcb, struct packet *packet)
425 {
426         int ret_p = 0;
427         struct packet *packet_reply = NULL;
428
429         packet_reply = packet_create_reply(packet, "ii", NOTIFICATION_ERROR_PERMISSION_DENIED, 0);
430         if (packet_reply) {
431                 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
432                         ErrPrint("Failed to send a reply packet:%d", ret_p);
433                 }
434                 packet_destroy(packet_reply);
435         } else {
436                 ErrPrint("Failed to create a reply packet");
437         }
438 }
439
440 static void _permission_check_refresh(struct tcb *tcb, struct packet *packet)
441 {
442         int ret_p = 0;
443         struct packet *packet_reply = NULL;
444
445         packet_reply = packet_create_reply(packet, "i", NOTIFICATION_ERROR_PERMISSION_DENIED);
446         if (packet_reply) {
447                 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
448                         ErrPrint("Failed to send a reply packet:%d", ret_p);
449                 }
450                 packet_destroy(packet_reply);
451         } else {
452                 ErrPrint("Failed to create a reply packet");
453         }
454 }
455
456 static void _permission_check_property_get(struct tcb *tcb, struct packet *packet)
457 {
458         int ret_p = 0;
459         struct packet *packet_reply = NULL;
460
461         packet_reply = packet_create_reply(packet, "is", NOTIFICATION_ERROR_PERMISSION_DENIED, NULL);
462         if (packet_reply) {
463                 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
464                         ErrPrint("Failed to send a reply packet:%d", ret_p);
465                 }
466                 packet_destroy(packet_reply);
467         } else {
468                 ErrPrint("Failed to create a reply packet");
469         }
470 }
471
472 static int _persmission_check(int fd, struct noti_service *service)
473 {
474         int ret;
475
476         if (service->rule != NULL && service->access != NULL) {
477                 ret = security_server_check_privilege_by_sockfd(fd, service->rule, service->access);
478                 if (ret == SECURITY_SERVER_API_ERROR_ACCESS_DENIED) {
479                         ErrPrint("SMACK:Access denied\n");
480                         return 0;
481                 }
482         }
483
484         return 1;
485 }
486
487 /*!
488  * NOTIFICATION SERVICE INITIALIZATION
489  */
490 static void _notification_data_init(void)
491 {
492         int property = 0;
493         int priv_id = 0;
494         char *noti_pkgname = NULL;
495         notification_h noti = NULL;
496         notification_list_h noti_list = NULL;
497         notification_list_h noti_list_head = NULL;
498         notification_type_e noti_type = NOTIFICATION_TYPE_NONE;
499
500         notification_get_list(NOTIFICATION_TYPE_NONE, -1, &noti_list);
501         noti_list_head = noti_list;
502
503         while (noti_list != NULL) {
504                 noti = notification_list_get_data(noti_list);
505                 if (noti) {
506                         notification_get_id(noti, NULL, &priv_id);
507                         notification_get_pkgname(noti, &noti_pkgname);
508                         notification_get_property(noti, &property);
509                         notification_get_type(noti, &noti_type);
510
511                         if (noti_type == NOTIFICATION_TYPE_ONGOING
512                                         || property & NOTIFICATION_PROP_VOLATILE_DISPLAY) {
513                                 notification_noti_delete_by_priv_id(noti_pkgname, priv_id);
514                         }
515                 }
516                 noti_list = notification_list_get_next(noti_list);
517         }
518
519         if (noti_list_head != NULL) {
520                 notification_free_list(noti_list_head);
521         }
522 }
523
524 static void _notification_init(void) {
525         int ret = -1;
526         int restart_count = 0;
527
528         ret = vconf_get_int(VCONFKEY_MASTER_RESTART_COUNT, &restart_count);
529         if (ret == 0 && restart_count <= 1) {
530                 _notification_data_init();
531         }
532 }
533
534 /*!
535  * SERVICE THREAD
536  */
537 static int service_thread_main(struct tcb *tcb, struct packet *packet, void *data)
538 {
539         int i = 0;
540         const char *command;
541         static struct noti_service service_req_table[] = {
542                 {
543                         .cmd = "add_noti",
544                         .handler = _handler_insert,
545                         .rule = "data-provider-master::notification.client",
546                         .access = "w",
547                         .handler_access_error = _permission_check_common,
548                 },
549                 {
550                         .cmd = "update_noti",
551                         .handler = _handler_update,
552                         .rule = "data-provider-master::notification.client",
553                         .access = "w",
554                         .handler_access_error = _permission_check_common,
555                 },
556                 {
557                         .cmd = "refresh_noti",
558                         .handler = _handler_refresh,
559                         .rule = "data-provider-master::notification.client",
560                         .access = "w",
561                         .handler_access_error = _permission_check_refresh,
562                 },
563                 {
564                         .cmd = "del_noti_single",
565                         .handler = _handler_delete_single,
566                         .rule = "data-provider-master::notification.client",
567                         .access = "w",
568                         .handler_access_error = _permission_check_common,
569                 },
570                 {
571                         .cmd = "del_noti_multiple",
572                         .handler = _handler_delete_multiple,
573                         .rule = "data-provider-master::notification.client",
574                         .access = "w",
575                         .handler_access_error = _permission_check_common,
576                 },
577                 {
578                         .cmd = "set_noti_property",
579                         .handler = _handler_noti_property_set,
580                         .rule = "data-provider-master::notification.client",
581                         .access = "w",
582                         .handler_access_error = _permission_check_common,
583                 },
584                 {
585                         .cmd = "get_noti_property",
586                         .handler = _handler_noti_property_get,
587                         .rule = "data-provider-master::notification.client",
588                         .access = "r",
589                         .handler_access_error = _permission_check_property_get,
590                 },
591                 {
592                         .cmd = "service_register",
593                         .handler = _handler_service_register,
594                         .rule = NULL,
595                         .access = NULL,
596                         .handler_access_error = NULL,
597                 },
598                 {
599                         .cmd = NULL,
600                         .handler = NULL,
601                         .rule = NULL,
602                         .access = NULL,
603                         .handler_access_error = NULL,
604                 },
605         };
606
607         if (!packet) {
608                 DbgPrint("TCB: %p is terminated\n", tcb);
609                 return 0;
610         }
611
612         command = packet_command(packet);
613         if (!command) {
614                 ErrPrint("Invalid command\n");
615                 return -EINVAL;
616         }
617
618         switch (packet_type(packet)) {
619         case PACKET_REQ:
620                 /* Need to send reply packet */
621                 DbgPrint("%p REQ: Command: [%s]\n", tcb, command);
622
623                 for (i = 0; service_req_table[i].cmd; i++) {
624                         if (strcmp(service_req_table[i].cmd, command)) {
625                                 continue;
626                         }
627
628                         if (_persmission_check(tcb_fd(tcb), &(service_req_table[i])) == 1) {
629                                 service_req_table[i].handler(tcb, packet, data);
630                         } else {
631                                 if (service_req_table[i].handler_access_error != NULL) {
632                                         service_req_table[i].handler_access_error(tcb, packet);
633                                 }
634                         }
635                         break;
636                 }
637
638                 break;
639         case PACKET_REQ_NOACK:
640                 break;
641         case PACKET_ACK:
642                 break;
643         default:
644                 ErrPrint("Packet type is not valid[%s]\n", command);
645                 return -EINVAL;
646         }
647
648         /*!
649          * return value has no meanning,
650          * it will be printed by dlogutil.
651          */
652         return 0;
653 }
654
655
656 /*!
657  * MAIN THREAD
658  * Do not try to do anyother operation in these functions
659  */
660 HAPI int notification_service_init(void)
661 {
662         if (s_info.svc_ctx) {
663                 ErrPrint("Already initialized\n");
664                 return LB_STATUS_ERROR_ALREADY;
665         }
666
667         _notification_init();
668
669         s_info.svc_ctx = service_common_create(NOTIFICATION_SOCKET, service_thread_main, NULL);
670         if (!s_info.svc_ctx) {
671                 ErrPrint("Unable to activate service thread\n");
672                 return LB_STATUS_ERROR_FAULT;
673         }
674
675         if (smack_fsetlabel(service_common_fd(s_info.svc_ctx), NOTIFICATION_SMACK_LABEL, SMACK_LABEL_IPOUT) != 0) {
676                 if (errno != EOPNOTSUPP) {
677                         ErrPrint("Unable to set SMACK label(%d)\n", errno);
678                         service_common_destroy(s_info.svc_ctx);
679                         s_info.svc_ctx = NULL;
680                         return LB_STATUS_ERROR_FAULT;
681                 }
682         }
683
684         if (smack_fsetlabel(service_common_fd(s_info.svc_ctx), NOTIFICATION_SMACK_LABEL, SMACK_LABEL_IPIN) != 0) {
685                 if (errno != EOPNOTSUPP) {
686                         ErrPrint("Unable to set SMACK label(%d)\n", errno);
687                         service_common_destroy(s_info.svc_ctx);
688                         s_info.svc_ctx = NULL;
689                         return LB_STATUS_ERROR_FAULT;
690                 }
691         }
692
693         DbgPrint("Successfully initiated\n");
694         return LB_STATUS_SUCCESS;
695 }
696
697 HAPI int notification_service_fini(void)
698 {
699         if (!s_info.svc_ctx) {
700                 return LB_STATUS_ERROR_INVALID;
701         }
702
703         service_common_destroy(s_info.svc_ctx);
704         s_info.svc_ctx = NULL;
705         DbgPrint("Successfully Finalized\n");
706         return LB_STATUS_SUCCESS;
707 }
708
709 /* End of a file */