Remove unused gdbus APIs based on char string
[platform/core/system/libsyscommon.git] / src / libgdbus / dbus-system.c
1 /*
2  * libsyscommon
3  *
4  * Copyright (c) 2019 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *       http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stdbool.h>
22 #include <stdint.h>
23 #include <errno.h>
24 #include <string.h>
25
26 #include "shared/log.h"
27 #include "dbus-system.h"
28
29 /* 10 seconds */
30 #define DBUS_REPLY_TIMEOUT      (10000)
31
32 static GBusType g_default_bus_type = G_BUS_TYPE_SYSTEM;
33 pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
34
35 void dbus_handle_set_default_bus_type(GBusType bus_type)
36 {
37         if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION)
38                 return ;
39
40         pthread_mutex_lock(&g_mutex);
41         g_default_bus_type = bus_type;
42         pthread_mutex_unlock(&g_mutex);
43 }
44
45 GBusType dbus_handle_get_default_bus_type(void)
46 {
47         GBusType type;
48
49         pthread_mutex_lock(&g_mutex);
50         type = g_default_bus_type;
51         pthread_mutex_unlock(&g_mutex);
52
53         return type;
54 }
55
56 typedef struct {
57         const char *bus_name;
58         guint id;
59 } dbus_name;
60
61 /* basic information */
62 typedef struct {
63         GDBusConnection *conn;
64         GBusType bus_type;
65         gboolean priv;
66         GList *list_names;      /* dbus_name */
67         GList *list_object;     /* dbus_object_handle_s */
68         pthread_mutex_t mutex;
69 } dbus_handle_s;
70
71 /* path + interfaces */
72 typedef struct {
73         dbus_handle_s *dh;      /* dbus handle */
74         const char *path;       /* object path */
75         GList *list_ifaces;     /* dbus_interface_s */
76 } dbus_object_handle_s;
77
78 typedef struct {
79         dbus_object_handle_s *oh;       /* object handle */
80         const char *name;       /* interface name */
81         GList *list_methods;    /* const dbus_method_s */
82         guint reg_id;
83         int modified;
84 } dbus_interface_s;
85
86 #define get_dh_from_oh(oh) ((dbus_object_handle_s*)oh)->dh
87
88 /* global shared bus : system, session */
89 static dbus_handle_s g_dh[2];
90
91 static dbus_handle_s *_dbus_handle_get_connection(GBusType bus_type);
92
93 dbus_handle_s * _dbus_handle_get_default_connection(void)
94 {
95         return _dbus_handle_get_connection(dbus_handle_get_default_bus_type());
96 }
97
98 #define dbus_handle_lock(handle) do {\
99         assert(handle);\
100         pthread_mutex_lock(&((handle)->mutex));\
101 } while (0);
102
103 #define dbus_handle_unlock(handle) do {\
104         assert(handle);\
105         pthread_mutex_unlock(&(handle)->mutex);\
106 } while (0);
107
108 #define dcl_dbus_handle() dbus_handle_s *dh = (dbus_handle_s *)handle;
109 #define dcl_dbus_handle_null_check() dbus_handle_s *dh = (dbus_handle_s *)handle;\
110         if (!dh) {\
111         _E("dbus handle is null\n");\
112         return 0;\
113         }
114
115 dbus_object_handle_s * _dbus_handle_lookup_object(GList *list_obj, const char *obj_path);
116 dbus_interface_s * _dbus_handle_lookup_interface(GList *list_iface, const char *iface_name);
117 dbus_method_s * _dbus_handle_lookup_method(GList *list_methods, const char *method_name);
118
119 dbus_interface_s *_iface_u_to_s(const dbus_interface_u *iface_u)
120 {
121         dbus_interface_s *iface = NULL;
122
123         if (!iface_u || !iface_u->methods) {
124                 _E("param is null");
125                 return NULL;
126         }
127
128         iface = (dbus_interface_s *)calloc(1, sizeof(dbus_interface_s));
129         if (!iface) {
130                 _E("failed to calloc");
131                 return NULL;
132         }
133
134         iface->name = iface_u->name;
135         iface->modified = TRUE;
136
137         for (int i = 0 ; i < iface_u->nr_methods; ++i) {
138                 //_D("attached %s:%p", iface_u->methods[i].member, iface_u->methods[i].func);
139                 iface->list_methods = g_list_prepend(iface->list_methods, (void*)(iface_u->methods + i));
140         }
141
142         return iface;
143 }
144
145 static GDBusConnection * _get_bus(GBusType bus_type)
146 {
147         GDBusConnection *conn = NULL;
148         GError *err = NULL;
149
150         if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) {
151                 _E("Wrong bus_type %d", bus_type);
152                 return NULL;
153         }
154
155         conn = g_bus_get_sync(bus_type, NULL, &err);
156         if (!conn || err) {
157                 _E("failed to get bus:type:%d, %s\n", bus_type, err->message);
158                 g_error_free(err);
159                 return NULL;
160         }
161
162         return conn;
163 }
164
165 static GDBusConnection * _get_bus_private(GBusType bus_type)
166 {
167         GError *err = NULL;
168         GDBusConnection *conn = NULL;
169         const char * address;
170
171         if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) {
172                 _E("Wrong bus_type %d", bus_type);
173                 return NULL;
174         }
175
176         address = g_dbus_address_get_for_bus_sync(bus_type, NULL, &err);
177         if (!address || err) {
178                 _E("failed to get bus address\n");
179                 g_error_free(err);
180                 return NULL;
181         }
182
183         conn = g_dbus_connection_new_for_address_sync(address,
184                         (GDBusConnectionFlags) (G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
185                         G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION),
186                         NULL, /* GDBusAuthObserver */
187                         NULL,
188                         &err);
189         if (!conn || err) {
190                 _E("failed to get private bus\n");
191                 g_error_free(err);
192                 return NULL;
193         }
194
195         return conn;
196 }
197
198 /* ref cout is 1 */
199 static dbus_handle_s *_dbus_handle_get_connection(GBusType bus_type)
200 {
201         int ibus = bus_type - 1;
202         dbus_handle_s *dh = NULL;
203
204         if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) {
205                 _E("Unknown bus type %d", bus_type);
206                 return NULL;
207         }
208         dh = &g_dh[ibus];
209
210         dbus_handle_lock(dh);
211
212         if (!dh->conn) {
213                 dh->conn = _get_bus(bus_type);
214                 if (!dh->conn) {
215                         dbus_handle_unlock(dh);
216                         return NULL;
217                 }
218                 dh->priv = FALSE;
219                 dh->bus_type = bus_type;
220         }
221
222         dbus_handle_unlock(dh);
223
224         return dh;
225 }
226
227 /* ref cout is 1 */
228 static dbus_handle_s *_dbus_handle_get_connection_private(GBusType bus_type)
229 {
230         dbus_handle_s * dh;
231
232         if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) {
233                 _E("Unknown bus type %d", bus_type);
234                 return NULL;
235         }
236
237         dh = (dbus_handle_s *)calloc(1, sizeof(dbus_handle_s));
238         if (!dh) {
239                 _E("failed to allocate memory for dbus handle");
240                 return NULL;
241         }
242
243         dbus_handle_lock(dh);
244
245         if (!dh->conn) {
246                 dh->conn = _get_bus_private(bus_type);
247                 dh->bus_type = bus_type;
248                 if (!dh->conn)
249                         goto err;
250         }
251
252         dbus_handle_unlock(dh);
253
254         return dh;
255 err:
256         if (dh) {
257                 dbus_handle_unlock(dh);
258                 free(dh);
259         }
260         return NULL;
261 }
262
263 dbus_handle_h dbus_handle_get_connection(GBusType bus_type, gboolean priv)
264 {
265         dbus_handle_s *dh = NULL;
266         int i;
267
268         if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) {
269                 _E("Wrong bus_type %d\n", bus_type);
270                 return dh;
271         }
272
273         for (i = 0 ; i < 3; ++i) {
274                 /* private */
275                 if (priv)
276                         dh = _dbus_handle_get_connection_private(bus_type);
277                 /* shared */
278                 else
279                         dh = _dbus_handle_get_connection(bus_type);
280
281                 if (dh)
282                         break;
283                 usleep(5000);
284         }
285
286         return dh;
287 }
288
289 static void _dbus_handle_add_bus_name(dbus_handle_s *handle, const char *name, guint id)
290 {
291         dbus_name *dn = NULL;
292         int locked = 0;
293
294         if (!handle || !name || !id)
295                 return ;
296
297         dn = (dbus_name*)calloc(1, sizeof(dbus_name));
298         if (!dn) {
299                 _E("failed to calloc");
300                 assert(0);
301         }
302         dn->bus_name = name;
303         dn->id = id;
304
305         // todo : delete lock ?
306         locked = pthread_mutex_trylock(&handle->mutex);
307         if (locked != 0 && locked != EBUSY) {
308                 _E("failed to lock %d\n", locked);
309                 assert(0);
310         }
311
312         handle->list_names = g_list_prepend(handle->list_names, dn);
313
314         // todo : delete lock ?
315         if (locked != EBUSY)
316                 dbus_handle_unlock(handle);
317 }
318
319 static gint _compare_dbus_name(gconstpointer a, gconstpointer b)
320 {
321         const char *bus_name = ((dbus_name *)a)->bus_name;
322         if (!bus_name || !b)
323                 return -1;
324         return strcmp(bus_name, (const char *)b);
325 }
326
327 dbus_name * _dbus_handle_lookup_dbus_name(GList *list_name, const char *bus_name)
328 {
329         if (!list_name || !bus_name)
330                 return NULL;
331
332         GList *item = g_list_find_custom(list_name, bus_name, _compare_dbus_name);
333         if (!item)
334                 return NULL;
335
336         return (dbus_name *)item->data;
337 }
338
339 #define dh_to_ds(x) ((dbus_handle_s*)x)
340
341 /* remove dbus_name from dbus handle */
342 static void _dbus_handle_remove_bus_name(dbus_handle_s *handle, const char *bus_name)
343 {
344         dcl_dbus_handle();
345         dbus_name *dn = NULL;
346
347         if (!bus_name) {
348                 _E("wrong bus_name is null");
349                 return ;
350         }
351         if (!dh) {
352                 dh = _dbus_handle_get_default_connection();
353                 if (!dh) {
354                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
355                         return ;
356                 }
357         }
358
359         dbus_handle_lock(dh);
360         dn = _dbus_handle_lookup_dbus_name(dh->list_names, bus_name);
361         if (!dn) {
362                 _E("failed to find dbus name %s", bus_name);
363                 goto out;
364         }
365         dh->list_names = g_list_remove(dh->list_names, dn);
366         free(dn);
367 out:
368         dbus_handle_unlock(dh);
369 }
370
371 //extern void booting_done(void);
372
373 /* default handler */
374 static void _name_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
375 {
376         dbus_handle_s *dh = (dbus_handle_s *)user_data;
377
378         _D("name %s", name);
379
380         if (!dh) {
381                 _E("%s:%d:dbus handle is null\n", __func__, __LINE__);
382                 return ;
383         }
384
385         // todo: add bus name?
386         //dh->bus_name = name;
387 }
388
389 /* default handler */
390 static void _name_lost(GDBusConnection *connection, const gchar *name, gpointer user_data)
391 {
392         _E("%s:%d:%s\n", __func__, __LINE__, name);
393         dbus_handle_s *dh = (dbus_handle_s *)user_data;
394         if (!dh) {
395                 _E("%s:%d:dbus handle is null\n", __func__, __LINE__);
396                 return ;
397         }
398         _dbus_handle_remove_bus_name(dh, name);
399 }
400
401 int dbus_handle_request_bus_name(dbus_handle_h handle,
402                                 const char *bus_name,
403                                 GBusNameAcquiredCallback acquired_handler,
404                                 GBusNameLostCallback lost_handler)
405 {
406         dcl_dbus_handle();
407         int id = -1;
408         GList *item = NULL;
409
410         if (!bus_name) {
411                 _E("bus_name is NULL");
412                 return -1;
413         }
414
415         /* get shared connection */
416         if (!dh) {
417                 dh = _dbus_handle_get_default_connection();
418                 if (!dh) {
419                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
420                         return -1;
421                 }
422         }
423
424         dbus_handle_lock(dh);
425         if (!dh->conn) {
426                 _E("failed to register name: connection is null\n");
427                 goto out;
428         }
429
430         /* todo : search name on connection */
431         item = g_list_find_custom(dh->list_names, bus_name, _compare_dbus_name);
432         if (item) {
433                 id = ((dbus_name*)(item->data))->id;
434                 _E("name already exist:%u", id);
435                 goto out;
436         }
437
438         id = g_bus_own_name_on_connection(dh->conn,
439                                         bus_name,
440                                         G_BUS_NAME_OWNER_FLAGS_NONE,
441                                         acquired_handler ? acquired_handler : _name_acquired,
442                                         lost_handler ? lost_handler : _name_lost,
443                                         dh,
444                                         NULL);
445         if (!id) {
446                 _E("failed to own name:%s\n", bus_name);
447                 goto out;
448         }
449
450         _dbus_handle_add_bus_name(dh, bus_name, id);
451
452 out:
453         dbus_handle_unlock(dh);
454         return id;
455 }
456
457 /* !! _name_lost handler callback is disabled by g_bus_unown_name : ubuntu */
458 int dbus_handle_release_bus_name(dbus_handle_h handle, const char *bus_name)
459 {
460         dcl_dbus_handle();
461         dbus_name *dn = NULL;
462
463         if (!bus_name) {
464                 _E("Wrong bus name");
465                 return -1;
466         }
467
468         if (!dh) {
469                 dh = _dbus_handle_get_default_connection();
470                 if (!dh) {
471                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
472                         return -1;
473                 }
474         }
475
476         dn = _dbus_handle_lookup_dbus_name(dh->list_names, bus_name);
477         if (!dn) {
478                 _E("failed to find bus_name %s on dbus handle", bus_name);
479                 return -1;
480         }
481
482         _E("unown name %d", dn->id);
483         /* _name_lost handler is disabled by g_bus_unown_name : ubuntu */
484         g_bus_unown_name(dn->id);
485
486         dbus_handle_lock(dh);
487         dh->list_names = g_list_remove(dh->list_names, dn);
488         free(dn);
489         dbus_handle_unlock(dh);
490
491         return 0;
492 }
493
494 int dbus_handle_free_connection(dbus_handle_h handle)
495 {
496         dcl_dbus_handle();
497         dbus_handle_s *pdh = NULL;
498         GError *err = NULL;
499         GList *item = NULL;
500
501         if (!dh) {
502                 dh = _dbus_handle_get_default_connection();
503                 if (!dh) {
504                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
505                         return -1;
506                 }
507         }
508
509         if (!dh->conn) {
510                 _E("connection is NULL");
511                 return 0;
512         }
513
514         pdh = dh;
515
516         /* disable dbus handler */
517         dbus_handle_lock(dh);
518         if (!pdh->conn) {
519                 _E("conn is null");
520                 free(pdh);
521                 return 0;
522         }
523
524         /* flush everything */
525         if (!g_dbus_connection_flush_sync(pdh->conn, NULL, &err)) {
526                 _E("failed to flush %s\n", err->message);
527                 g_error_free(err);
528                 err = NULL;
529         }
530
531         _D("list_names %u", g_list_length(pdh->list_names));
532
533         /* unown every well-knwon name */
534         if (pdh->list_names) {
535                 dbus_name *dn = NULL;
536                 for (item = g_list_first(pdh->list_names); item != NULL; item = g_list_next(item)) {
537                         dn = (dbus_name *)item->data;
538                         if (!dn)
539                                 continue;
540
541                         /* _name_lost handler is disabled by g_bus_unown_name : ubuntu */
542                         _D("unown name id : %u", dn->id);
543                         g_bus_unown_name(dn->id);
544                         free(dn);
545                 }
546                 g_list_free(pdh->list_names);
547                 pdh->list_names = NULL;
548         }
549
550         _D("list_object %u", g_list_length(pdh->list_object));
551
552         /* unregister every object */
553         if (pdh->list_object) {
554                 dbus_object_handle_s * oh = NULL;
555                 //g_list_foreach(pdh->list_object, [] (gpointer data, gpointer user_data) {}, NULL);
556                 for (item = g_list_first(pdh->list_object); item != NULL; item = g_list_next(item)) {
557                         oh = (dbus_object_handle_s *)item->data;
558                         if (!oh || !oh->list_ifaces)
559                                 continue;
560
561                         _D("delete object path %s", oh->path);
562
563                         /* unregister every interface, method handles */
564                         for (GList *iface = g_list_first(oh->list_ifaces); iface != NULL; iface = g_list_next(iface)) {
565                                 dbus_interface_s *ih = (dbus_interface_s *)iface->data;
566                                 if (!ih)
567                                         continue;
568
569                                 _D("delete object iface %s", ih->name);
570
571                                 if (ih->reg_id)
572                                         g_dbus_connection_unregister_object(pdh->conn, ih->reg_id);
573                         }
574                 }
575         }
576
577         /* close connection */
578         if (pdh->priv) {
579                 _E("close private connection\n");
580
581                 if (!g_dbus_connection_close_sync(pdh->conn, NULL, &err)) {
582                         _E("Error closing connection %s\n", err->message);
583                         g_error_free(err);
584                         err = NULL;
585                 }
586         }
587
588         /* _free_func_object callback free the data */
589         //assert(g_list_length(pdh->list_names) == 0);
590         //assert(g_list_length(pdh->list_object) == 0);
591
592         g_object_unref(pdh->conn);
593
594         dbus_handle_unlock(dh);
595
596         if (dh->priv)
597                 free(dh);
598
599         return 0;
600
601         // todo: signal ?
602 }
603
604 #define buf_cal_free_space(size, nwrite) ((size - nwrite - 1) > 0 ? (size - nwrite - 1) : 0)
605 #define buf_block_size 8192
606
607 #define buf_check_space_realloc(buf, nwrite, buf_len) do {\
608         if ((nwrite >= buf_len - 1024)) {\
609                 if (buf_len >= buf_block_size * 10) {\
610                         _E("buf is too big to allocate. %d", buf_len);\
611                 } else {\
612                         _E("buf_check_space_realloc");\
613                         char *tmp = NULL;\
614                         buf_len += buf_block_size;\
615                         tmp = (char *)realloc(buf, buf_len);\
616                         if (!tmp) {\
617                                 _E("failed to realloc");\
618                         } else\
619                                 buf = tmp;\
620                 } \
621         } \
622 } while (0);
623
624 /* cal index of end of brace */
625 static int _check_brace(const char * expr)
626 {
627         int len = 0;
628         char qu[128];
629         int qucnt = 0;
630
631         if (!expr)
632                 return -1;
633
634         len = strlen(expr);
635
636         if (expr[0] != '(' && expr[0] != '{')
637                 return -1;
638
639         for (int i = 0 ; i < len; ++i) {
640
641                 if (expr[i] == '(' || expr[i] == '{') {
642                         qu[qucnt++] = expr[i];
643                         if (qucnt >= sizeof(qu)) {
644                                 _E("queue is too large. %s", expr);
645                                 return -1;
646                         }
647                         continue;
648                 }
649
650                 if (expr[i] == ')' || expr[i] == '}') {
651                         char ch;
652
653                         if (qucnt > 0)
654                                 ch = qu[qucnt-1];
655                         else
656                                 return -1;
657
658                         if (expr[i] == ')') {
659                                 if (ch == '(')
660                                         --qucnt;
661                                 else
662                                         return -1;
663                         } else if (expr[i] == '}') {
664                                 if (ch == '{')
665                                         --qucnt;
666                                 else
667                                         return -1;
668                         } else
669                                 return -1;
670
671                         if (qucnt == 0)
672                                 return i + 1;
673                 }
674         }
675
676         return -1;
677 }
678
679 /*
680 in : interface_s
681 out : xml format
682 */
683 static int _get_xml_from_interfaces(char **xml, const dbus_interface_s *interfaces)
684 {
685         int nwrite = 0;
686         int len_args;
687         char *buf = NULL;
688         const dbus_method_s *pmethod;
689         int buf_len = buf_block_size;
690
691         if (!interfaces) {
692                 _E("interfaces is null");
693                 return -1;
694         }
695
696         // todo : check dbus naming rule for interface name. ?
697         if (!interfaces->name) {
698                 _E("wrong interface name");
699                 return -1;
700         }
701         if (!interfaces->list_methods) {
702                 _E("no methods");
703                 return -1;
704         }
705
706         buf = (char *)malloc(buf_len);
707         if (!buf) {
708                 _E("buf is null. not enough memory\n");
709                 return -1;
710         }
711
712         nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "<node>""\n""\t""<interface name='%s'>""\n", interfaces->name);
713
714         /* members */
715         for (GList *item = g_list_first(interfaces->list_methods); item != NULL; item = g_list_next(item)) {
716                 pmethod = (const dbus_method_s *)item->data;
717                 if (!pmethod)
718                         continue;
719
720                 /* check free space of buf */
721                 buf_check_space_realloc(buf, nwrite, buf_len);
722
723                 if (pmethod->signature_in == NULL && pmethod->signature_out == NULL) {
724                         nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t""<method name='%s'/>""\n", pmethod->member);
725                         continue;
726                 }
727
728                 /* <method name='###'> */
729                 nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t""<method name='%s'>""\n", pmethod->member);
730
731                 /* in args */
732                 len_args = pmethod->signature_in ? strlen(pmethod->signature_in) : 0;
733                 for (int m = 0; m < len_args; ++m) {
734                         // todo
735                         // array a(), as, ay ?
736                         if (pmethod->signature_in[m] == 'a') {
737                                 int ei; //end index
738                                 ei = _check_brace(pmethod->signature_in + m + 1);
739                                 if (ei > 0) {
740                                         char tmp[128] = {0,};
741                                         strncpy(tmp, pmethod->signature_in + m, ei + 1);
742                                         nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%s' name='arg%d' direction='in'/>""\n", tmp, m);
743                                         m += ei;
744                                         continue;
745                                 } else {
746                                         nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%c%c' name='arg%d' direction='in'/>""\n", pmethod->signature_in[m], pmethod->signature_in[m+1], m);
747                                         m += 1;
748                                         continue;
749                                 }
750                         }
751                         nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%c' name='arg%d' direction='in'/>""\n", pmethod->signature_in[m], m);
752                 }
753
754                 /* out args */
755                 len_args = pmethod->signature_out ? strlen(pmethod->signature_out) : 0;
756                 for (int m = 0; m < len_args; ++m) {
757                         // array
758                         // todo: container type
759                         if (pmethod->signature_out[m] == 'a') {
760                                 int ei; //end index
761                                 ei = _check_brace(pmethod->signature_out + m + 1);
762                                 if (ei > 0) {
763                                         char tmp[128] = {0,};
764                                         strncpy(tmp, pmethod->signature_out + m, ei + 1);
765                                         nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%s' name='arg%d' direction='out'/>""\n", tmp, m);
766                                         m += ei;
767                                         continue;
768                                 } else {
769                                         nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%c%c' name='arg%d' direction='out'/>""\n", pmethod->signature_out[m], pmethod->signature_out[m+1], m);
770                                         m += 1;
771                                         continue;
772                                 }
773                         }
774                         nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%c' name='arg%d' direction='out'/>""\n", pmethod->signature_out[m], m);
775                 }
776
777                 /* </method> */
778                 nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t""</method>""\n");
779         }
780
781         nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t""</interface>""\n""</node>""");
782
783         *xml = buf;
784
785         /* todo: delete log */
786 #if 0
787         if (nwrite <= 512)
788                 _E("%s", buf);
789         else
790                 _E("%s", buf + nwrite - 512);
791 #endif
792         return 0;
793 }
794
795 static gint _compare_dbus_object(gconstpointer a, gconstpointer b)
796 {
797         dbus_object_handle_s * pa = (dbus_object_handle_s *)a;
798         if (!pa->path || !((const char*)b))
799                 return -1;
800         return strcmp(pa->path, (const char*)b);
801 }
802
803 static gint _compare_dbus_interface(gconstpointer a, gconstpointer b)
804 {
805         dbus_interface_s * pa = (dbus_interface_s *)a;
806         if (!pa->name || !((const char*)b))
807                 return -1;
808         return strcmp(pa->name, (const char*)b);
809 }
810
811 static gint _compare_dbus_interface_by_id(gconstpointer a, gconstpointer b)
812 {
813         dbus_interface_s * pa = (dbus_interface_s *)a;
814         if (!pa->reg_id || !((guint*)b))
815                 return -1;
816         return !(pa->reg_id == *((guint*)b));
817 }
818
819 static gint _compare_dbus_method(gconstpointer a, gconstpointer b)
820 {
821         dbus_method_s *pa = (dbus_method_s*)a;
822         if (!pa->member || !((const char*)b))
823                 return -1;
824         return strcmp(pa->member, (const char*)b);
825 }
826
827 dbus_object_handle_s * _dbus_handle_lookup_object(GList *list_obj, const char *obj_path)
828 {
829         if (!list_obj || !obj_path)
830                 return NULL;
831
832         GList *item = g_list_find_custom(list_obj, obj_path, _compare_dbus_object);
833         if (!item)
834                 return NULL;
835
836         return (dbus_object_handle_s *)item->data;
837 }
838
839 dbus_interface_s * _dbus_handle_lookup_interface(GList *list_iface, const char *iface_name)
840 {
841         if (!list_iface || !iface_name)
842                 return NULL;
843
844         GList *item = g_list_find_custom(list_iface, iface_name, _compare_dbus_interface);
845         if (!item)
846                 return NULL;
847
848         return (dbus_interface_s *)item->data;
849 }
850
851 dbus_interface_s * _dbus_handle_lookup_interface_by_id(GList *list_iface, guint id)
852 {
853         if (!list_iface || !id)
854                 return NULL;
855
856         GList *item = g_list_find_custom(list_iface, &id, _compare_dbus_interface_by_id);
857         if (!item)
858                 return NULL;
859
860         return (dbus_interface_s *)item->data;
861 }
862
863 dbus_method_s * _dbus_handle_lookup_method(GList *list_methods, const char *method_name)
864 {
865         if (!list_methods || !method_name)
866                 return NULL;
867
868         GList *item = g_list_find_custom(list_methods, method_name, _compare_dbus_method);
869         if (!item)
870                 return NULL;
871
872         return (dbus_method_s *)item->data;
873 }
874
875 static void _free_func_object(gpointer data)
876 {
877         dbus_interface_s *ih = (dbus_interface_s *)data;
878         dbus_object_handle_s *oh = NULL;
879
880         if (!ih) {
881                 _E("interface handle is null");
882                 assert(0); // something wrong
883                 return ;
884         }
885
886         _E("unregister interface %s", ih->name);
887
888         /* just free list, not data(static dbus_method_s) */
889         g_list_free(ih->list_methods);
890
891         oh = ih->oh;
892         if (!oh) {
893                 _E("object handle is null");
894                 assert(0); // something wrong
895                 return ;
896         }
897
898         /* remove ih from list_ifaces */
899         oh->list_ifaces = g_list_remove(oh->list_ifaces, ih);
900
901         /* interface_s is copy of interface_u */
902         free(ih);
903
904         /* remove oh from list_object */
905         if (!oh->list_ifaces) {
906                 oh->dh->list_object = g_list_remove(oh->dh->list_object, oh);
907                 free(oh);
908         }
909 }
910
911 static int _dbus_handle_attach_object(dbus_handle_s *dh, const char *obj_path, dbus_interface_s *iface)
912 {
913         dbus_object_handle_s *oh = NULL;
914
915         if (!dh || !obj_path || !iface) {
916                 _E("failed to attache object. wrong parameter");
917                 return -1;
918         }
919
920         /* find object handle */
921         if (dh->list_object)
922                 oh = _dbus_handle_lookup_object(dh->list_object, obj_path);
923
924         if (!oh) {
925                 oh = (dbus_object_handle_s*)calloc(1, sizeof(dbus_object_handle_s));
926                 if (!oh) {
927                         _E("failed to calloc");
928                         return -1;
929                 }
930                 oh->dh = dh;
931                 oh->path = obj_path;
932
933                 /* attach object */
934                 dh->list_object = g_list_prepend(dh->list_object, oh);
935         }
936
937         iface->oh = oh;
938         /* attach interface */
939         oh->list_ifaces = g_list_prepend(oh->list_ifaces, iface);
940
941         return 0;
942 }
943
944 /*
945 _method_call_handler
946
947 libgio verify path and interface of incoming message.
948 --> just check method name.
949
950 # parameters - member of invocation struct
951 every parameters of this function are member of GDBusMethodInvocation *invocation.
952 There are no reason to using g_dbus_method_invocation_get_* apis to get inforamtion from message.
953 just use params - sender, path, iface, name and param.
954
955
956 # user defined handler #
957
958 1. synchronous handling
959         1) with return value
960                 handler() {
961                         return g_variant_new("(i)", ret);
962                 }
963
964         2) without return value
965                 handler() {
966                         return dbus_handle_new_g_variant_tuple(); // g_variant_new_tuple(NULL, 0)
967                 }
968
969 2. asynchronous handling
970    handler MUST call 'g_dbus_method_invocation_return_value' itself. otherwise, LEAK !!
971
972         handler() {
973                 return NULL;
974         }
975
976         # if handler return NULL, assume asynchronous handling. do nothing.
977
978         thread() {
979                 do something;
980
981         1) with return value
982                 g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret));
983
984         2) without return value
985                 g_dbus_method_invocation_return_value(invocation, NULL);
986         }
987
988
989 */
990 static void _method_call_handler(GDBusConnection *conn,
991                                 const gchar *sender,
992                                 const gchar *path,
993                                 const gchar *iface,
994                                 const gchar *name,
995                                 GVariant *param,
996                                 GDBusMethodInvocation *invocation,
997                                 gpointer user_data)
998 {
999         dbus_interface_s *iface_s = (dbus_interface_s *)user_data;
1000         const dbus_method_s *methods;
1001         GVariant *result = NULL;
1002
1003         /* todo: ghash ? */
1004         methods = _dbus_handle_lookup_method(iface_s->list_methods, name);
1005         if (methods) {
1006                 result = methods->func(conn, sender, path, iface, name, param, invocation, get_dh_from_oh(iface_s->oh));
1007
1008                 /* async, maybe they will reply...maybe.. */
1009                 if (!result)
1010                         return;
1011         } else {
1012                 _E("no methods");
1013         }
1014
1015         g_dbus_method_invocation_return_value(invocation, result);
1016 }
1017
1018 static GDBusInterfaceVTable path_vtable = {_method_call_handler};
1019
1020
1021 /*
1022 before register object, attach object into dbus handle
1023 _dbus_handle_attach_object()
1024 */
1025 static int _dbus_handle_register_dbus_object(dbus_handle_h handle, const char *obj_path, dbus_interface_s *iface)
1026 {
1027         dcl_dbus_handle();
1028         int ret = 0;
1029         char *buf = NULL;
1030         GError *err = NULL;
1031         GDBusNodeInfo * nodeinfo = NULL;
1032         GDBusInterfaceInfo *ifaceinfo = NULL;
1033
1034         if (!obj_path || !iface) {
1035                 _E("wrong parameter\n");
1036                 return -1;
1037         }
1038         if (!dh) {
1039                 dh = _dbus_handle_get_default_connection();
1040                 if (!dh) {
1041                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1042                         return -1;
1043                 }
1044         }
1045         if (!dh->conn) {
1046                 _E("connection is null\n");
1047                 return -1;
1048         }
1049
1050         ret = _get_xml_from_interfaces(&buf, iface);
1051         if (ret < 0) {
1052                 _E("failed to make xml format");
1053                 goto err;
1054         }
1055
1056         /* todo: delete this */
1057 #if 0
1058         if (strlen(buf) <= 512) {
1059                 _E("%s", buf);
1060         } else {
1061                 _E("%s", buf + strlen(buf) - 512);
1062         }
1063 #endif
1064
1065         nodeinfo = g_dbus_node_info_new_for_xml(buf, &err);
1066         if (!nodeinfo || err) {
1067                 _E("failed to make introspection data:err:%s:xml:%s\n", err->message, buf);
1068                 ret = -1;
1069                 goto err;
1070         }
1071
1072         ifaceinfo = g_dbus_node_info_lookup_interface(nodeinfo, iface->name);
1073         if (!ifaceinfo) {
1074                 _E("failed to g_dbus_node_info_lookup_interface");
1075                 ret = -1;
1076                 goto err;
1077         }
1078
1079         /*
1080                 path own single interface
1081                 if interface is already registered, then failed.
1082                 g_dbus_connection_register_object ref(ifaceinfo) now, unref if object is unregistered
1083         */
1084         ret = g_dbus_connection_register_object(dh->conn,
1085                                                 obj_path,
1086                                                 ifaceinfo/*ref 2*/,
1087                                                 &path_vtable,
1088                                                 (void*)iface,
1089                                                 _free_func_object,
1090                                                 &err);
1091         if (err) {
1092                 _E("failed to register object:err:%s:\n", err->message);
1093                 ret = -1;
1094                 goto err;
1095         }
1096
1097         iface->reg_id = ret;
1098         iface->modified = FALSE;
1099
1100 err:
1101         /* todo: detach object */
1102         //_dbus_handle_detach_object(dh, obj_path, iface);
1103         /* attach interface before register object */
1104         /*ret = _dbus_handle_detach_object(dh, obj_path, iface);
1105         if (ret < 0) {
1106                 _E("failed to attach object");
1107                 goto err;
1108         }*/
1109
1110         if (nodeinfo)
1111                 g_dbus_node_info_unref(nodeinfo);
1112         if (buf)
1113                 free(buf);
1114         if (err)
1115                 g_error_free(err);
1116
1117         return ret;
1118 }
1119
1120 /*
1121 register same interface at once
1122
1123 if interface is constructed by multiple methods,
1124 also it is not possible to make methods struct at once,
1125
1126 use dbus_handle_add_dbus_object(), dbus_handle_register_dbus_object_all().
1127
1128 return reg_id
1129 */
1130 int dbus_handle_register_dbus_object(dbus_handle_h handle, const char *obj_path, const dbus_interface_u *iface_u)
1131 {
1132         dcl_dbus_handle();
1133         int ret = 0;
1134         dbus_interface_s *iface = NULL;
1135
1136         if (!obj_path || !iface_u) {
1137                 _E("wrong parameter\n");
1138                 return -1;
1139         }
1140         if (!dh) {
1141                 dh = _dbus_handle_get_default_connection();
1142                 if (!dh) {
1143                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1144                         return -1;
1145                 }
1146         }
1147         if (!dh->conn) {
1148                 _E("connection is null\n");
1149                 return -1;
1150         }
1151
1152         /* check registered interface */
1153         if (dh->list_object) {
1154                 dbus_object_handle_s *oh = _dbus_handle_lookup_object(dh->list_object, obj_path);
1155                 if (oh) {
1156                         dbus_interface_s *ih = _dbus_handle_lookup_interface(oh->list_ifaces, iface_u->name);
1157                         if (ih) {
1158                                 _E("path %s, interface %s already registered", obj_path, iface_u->name);
1159                                 return -1;
1160                         }
1161                 }
1162         }
1163
1164         iface = _iface_u_to_s(iface_u);
1165         if (!iface) {
1166                 _E("failed to _iface_u_to_s");
1167                 return -1;
1168         }
1169
1170         /* attach interface before register object */
1171         ret = _dbus_handle_attach_object(dh, obj_path, iface);
1172         if (ret < 0) {
1173                 _E("failed to attach object");
1174                 goto err;
1175         }
1176
1177         ret = _dbus_handle_register_dbus_object(dh, obj_path, iface);
1178         if (ret <= 0) {
1179                 _E("failed to register dbus object%d", ret);
1180                 goto err;
1181         }
1182 err:
1183         return ret;
1184 }
1185
1186 int dbus_handle_unregister_dbus_object(dbus_handle_h handle, const char *obj_path)
1187 {
1188         dcl_dbus_handle();
1189         dbus_object_handle_s *oh = NULL;
1190         int ret = 0;
1191
1192         if (!obj_path)
1193                 return -1;
1194
1195         if (!dh) {
1196                 dh = _dbus_handle_get_default_connection();
1197                 if (!dh) {
1198                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1199                         return -1;
1200                 }
1201         }
1202         if (!dh->list_object) {
1203                 _E("list_object is empty");
1204                 return 0;
1205         }
1206
1207         oh = _dbus_handle_lookup_object(dh->list_object, obj_path);
1208         if (!oh) {
1209                 _E("no object with name %s", obj_path);
1210                 return -1;
1211         }
1212
1213         /* unregister every interface of object*/
1214         for (GList *item = g_list_first(oh->list_ifaces); item != NULL; item = g_list_next(item)) {
1215                 dbus_interface_s *ih = item->data;
1216                 if (!ih) {
1217                         _E("this is error");
1218                         assert(0);
1219                 }
1220
1221                 /* remove ih from list_ifaces */
1222                 if (!ih->reg_id) {
1223                         item = g_list_previous(item);
1224
1225                         /* remove and free link */
1226                         oh->list_ifaces = g_list_remove(oh->list_ifaces, ih);
1227
1228                         /* free list_methods */
1229                         g_list_free(ih->list_methods);
1230
1231                         /* free data */
1232                         free(ih);
1233                         continue;
1234                 }
1235
1236                 /* unregister object by id */
1237                 ret = g_dbus_connection_unregister_object(dh->conn, ih->reg_id);
1238                 if (!ret)
1239                         _E("failed to unregister object %s, interface %s, regid %d", oh->path, ih->name, ih->reg_id);
1240         }
1241
1242         return 0;
1243 }
1244
1245 /*
1246 add object temporarily.
1247 dbus_handle_register_dbus_object_all register every objects on connection.
1248
1249 return registered method count
1250 */
1251 int dbus_handle_add_dbus_object(dbus_handle_h handle, const char *obj_path, const dbus_interface_u *iface_u)
1252 {
1253         dcl_dbus_handle();
1254         dbus_object_handle_s *oh = NULL;
1255         dbus_interface_s *ih = NULL;
1256         int cnt;
1257
1258         if (!obj_path || !iface_u) {
1259                 _E("wrong parameter path %s, iface_u %p\n", obj_path, iface_u);
1260                 return -1;
1261         }
1262         if (iface_u && (!iface_u->name || !iface_u->methods)) {
1263                 _E("wrong parameter path %s, iface_u %p\n", obj_path, iface_u);
1264                 return -1;
1265         }
1266
1267         cnt = iface_u->nr_methods;
1268
1269         if (!dh) {
1270                 dh = _dbus_handle_get_default_connection();
1271                 if (!dh) {
1272                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1273                         return -1;
1274                 }
1275         }
1276
1277         if (!dh->conn) {
1278                 _E("failed to register method. connection is null\n");
1279                 return -1;
1280         }
1281
1282         /* if there are no object list, just add */
1283         if (!dh->list_object) {
1284                 if (_dbus_handle_attach_object(dh, obj_path, _iface_u_to_s(iface_u))) {
1285                         _E("failed to attach object");
1286                         return -1;
1287                 }
1288                 goto out;
1289         }
1290
1291         oh = _dbus_handle_lookup_object(dh->list_object, obj_path);
1292         /* if there are no matched object, just add */
1293         if (!oh) {
1294                 if (_dbus_handle_attach_object(dh, obj_path, _iface_u_to_s(iface_u))) {
1295                         _E("failed to attach object");
1296                         return -1;
1297                 }
1298                 goto out;
1299         }
1300
1301         /* this is an error, interface must have one or more item ? */
1302         if (!oh->list_ifaces) {
1303                 _E("error. list_ifaces is null\n");
1304                 assert(0);
1305                 goto out;
1306         }
1307
1308         ih = _dbus_handle_lookup_interface(oh->list_ifaces, iface_u->name);
1309         /* if there are no matched interface, just add */
1310         if (!ih) {
1311                 if (_dbus_handle_attach_object(dh, obj_path, _iface_u_to_s(iface_u))) {
1312                         _E("failed to attach object");
1313                         return -1;
1314                 }
1315                 goto out;
1316         }
1317
1318         /*  todo:
1319                 1. unregister interface
1320                 2. update interface and methods
1321                 3. register interface
1322         */
1323         if (ih->reg_id) {
1324                 _E("interface already registered, ignore new interface");
1325                 return -1;
1326         }
1327
1328         /* attach new methods */
1329         cnt = 0;
1330         for (int i = 0; i < iface_u->nr_methods; ++i) {
1331                 GList *item = g_list_find_custom(g_list_first(ih->list_methods), iface_u->methods[i].member, _compare_dbus_method);
1332                 if (!item) {
1333                         //_D("attached %s", iface_u->methods[i].member);
1334                         ih->list_methods = g_list_prepend(ih->list_methods, (void*)(iface_u->methods + i));
1335                         ++cnt;
1336                 }
1337         }
1338
1339         if (cnt)
1340                 ih->modified = TRUE;
1341
1342 out:
1343         /*todo: delete debugging log */
1344         //if (dh && dh->list_object)
1345         //      _D("obj list len %d", g_list_length(dh->list_object));
1346         //if (oh && oh->list_ifaces)
1347         //      _D("iface list len %d", g_list_length(oh->list_ifaces));
1348         //if (ih && ih->list_methods)
1349         //      _D("method list len %d", g_list_length(ih->list_methods));
1350
1351         return cnt;
1352 }
1353
1354 int dbus_handle_register_dbus_object_all(dbus_handle_h handle)
1355 {
1356         dcl_dbus_handle();
1357         dbus_object_handle_s *oh = NULL;
1358         dbus_interface_s *ih = NULL;
1359         int ret = 0;
1360
1361         if (!dh) {
1362                 dh = _dbus_handle_get_default_connection();
1363                 if (!dh) {
1364                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1365                         return -1;
1366                 }
1367         }
1368         if (!dh->conn) {
1369                 _E("connection is null\n");
1370                 return -1;
1371         }
1372
1373         if (!dh->list_object) {
1374                 _E("obj list is empty");
1375                 return -1;
1376         }
1377
1378         /*if (dh && dh->list_object)
1379                 _D("obj list len %d", g_list_length(dh->list_object));*/
1380
1381         for (GList *item = g_list_first(dh->list_object); item != NULL; item = g_list_next(item)) {
1382                 oh = (dbus_object_handle_s *)item->data;
1383
1384                 if (!oh) {
1385                         _E("something wrong");
1386                         assert(0);
1387                 }
1388                 if (!oh->list_ifaces) {
1389                         _E("path %s: list_ifaces are null", oh->path);
1390                         goto err;
1391                 }
1392
1393                 //_D("iface list len %d", g_list_length(oh->list_ifaces));
1394
1395                 for (GList *li = g_list_first(oh->list_ifaces); li != NULL; li = g_list_next(li)) {
1396                         ih = (dbus_interface_s *)li->data;
1397
1398                         /* if there are no modification, goto next */
1399                         if (!ih->modified)
1400                                 continue;
1401
1402                         /* todo: if already registered interface, unregister first */
1403
1404                         /*_E("interface %s:", ih->name);
1405                         if (ih && ih->list_methods)
1406                                 _D("method list len %d", g_list_length(ih->list_methods));*/
1407
1408                         ret = _dbus_handle_register_dbus_object(dh, oh->path, ih);
1409                         if (ret <= 0)
1410                                 _E("failed to register dbus object%d", ret);
1411
1412                 }
1413         }
1414         return 0;
1415 err:
1416
1417         // todo: delete all updates
1418
1419         return -1;
1420 }
1421
1422 guint subscribe_dbus_signal(dbus_handle_h handle, const char *path,
1423                         const char *iface, const char *name,
1424                         GDBusSignalCallback cb, void *data,
1425                         destroy_notified free_func)
1426 {
1427         dcl_dbus_handle();
1428
1429         if (!dh) {
1430                 dh = _dbus_handle_get_default_connection();
1431                 if (!dh) {
1432                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1433                         return 0;
1434                 }
1435         }
1436
1437         if (!dh->conn) {
1438                 _E("connection is null. check bus status");
1439                 return 0;
1440         }
1441         return g_dbus_connection_signal_subscribe(dh->conn, NULL, iface, name, path, NULL, G_DBUS_SIGNAL_FLAGS_NONE, cb, data, free_func);
1442 }
1443
1444 void unsubscribe_dbus_signal(dbus_handle_h handle, guint id)
1445 {
1446         dcl_dbus_handle();
1447         if (!dh) {
1448                 dh = _dbus_handle_get_default_connection();
1449                 if (!dh) {
1450                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1451                         return;
1452                 }
1453         }
1454
1455         if (!dh->conn) {
1456                 _E("connection is null. check bus status");
1457                 return;
1458         }
1459
1460         g_dbus_connection_signal_unsubscribe(dh->conn, id);
1461 }
1462
1463 static void _signal_reply_sync_cb(GDBusConnection  *conn,
1464         const gchar *sender,
1465         const gchar *path,
1466         const gchar *iface,
1467         const gchar *name,
1468         GVariant *param,
1469         gpointer data)
1470 {
1471         sig_ctx *ctx = data;
1472         if (!ctx) {
1473                 _E("user data is null");
1474                 assert(0);
1475         }
1476
1477         ctx->param = g_variant_ref(param);
1478         ctx->quit_reason = CTX_QUIT_NORMAL;
1479
1480         if (ctx->timeout_src) {
1481                 g_source_destroy(ctx->timeout_src);
1482                 ctx->timeout_src = NULL;
1483         }
1484         g_main_loop_quit(ctx->loop);
1485 }
1486
1487 sig_ctx *dbus_handle_new_signal_ctx(void)
1488 {
1489         sig_ctx *ctx;
1490
1491         ctx = (sig_ctx *)malloc(sizeof(sig_ctx));
1492         if (!ctx) {
1493                 _E("failed to alloc mem");
1494                 return NULL;
1495         }
1496
1497         ctx->sig_id = 0;
1498
1499         ctx->context = g_main_context_new();
1500         if (!ctx->context) {
1501                 _E("failed to alloc context");
1502                 free(ctx);
1503                 return NULL;
1504         }
1505         ctx->loop = g_main_loop_new(ctx->context, FALSE);
1506         if (!ctx->loop) {
1507                 _E("failed to alloc main loop");
1508                 g_main_context_unref(ctx->context);
1509                 free(ctx);
1510                 return NULL;
1511         }
1512         ctx->timeout_src = NULL;
1513         ctx->param = NULL;
1514         ctx->quit_reason = CTX_QUIT_UNKNOWN;
1515         ctx->user_data = NULL;
1516
1517         return ctx;
1518 }
1519
1520 void dbus_handle_free_signal_ctx(sig_ctx *ctx)
1521 {
1522         if (!ctx)
1523                 return ;
1524
1525         if (ctx->param) {
1526                 g_variant_unref(ctx->param);
1527                 ctx->param = NULL;
1528         }
1529         if (ctx->sig_id) {
1530                 unsubscribe_dbus_signal(NULL, ctx->sig_id);
1531                 ctx->sig_id = 0;
1532         }
1533         if (ctx->timeout_src) {
1534                 g_source_destroy(ctx->timeout_src);
1535                 ctx->timeout_src = NULL;
1536         }
1537         if (ctx->context) {
1538                 g_main_context_pop_thread_default(ctx->context);
1539                 g_main_context_unref(ctx->context);
1540                 ctx->context = NULL;
1541         }
1542         if (ctx->loop) {
1543                 g_main_loop_unref(ctx->loop);
1544                 ctx->loop = NULL;
1545         }
1546         free(ctx);
1547 }
1548
1549 static gboolean _cb_ctx_timeout(gpointer user_data)
1550 {
1551         sig_ctx *ctx = user_data;
1552
1553         if (!ctx) {
1554                 _E("user_data is null");
1555                 return FALSE;
1556         }
1557
1558         ctx->quit_reason = CTX_QUIT_TIMEOUT;
1559         /* if cb return FALSE, source will be destroyed */
1560         ctx->timeout_src = NULL;
1561
1562         unsubscribe_dbus_signal(NULL, ctx->sig_id);
1563         ctx->sig_id = 0;
1564
1565         g_main_loop_quit(ctx->loop);
1566
1567         return FALSE;
1568 }
1569
1570 #define CTX_MAX_TIMEOUT 25000
1571
1572 int dbus_handle_signal_ctx_add_timeout(sig_ctx *ctx, int timeout_msec)
1573 {
1574         GSource *src = NULL;
1575
1576         if (!ctx)
1577                 return -EINVAL;
1578         if (timeout_msec < -1)
1579                 return -EINVAL;
1580
1581         if (timeout_msec == -1 || timeout_msec >= CTX_MAX_TIMEOUT)
1582                 timeout_msec = CTX_MAX_TIMEOUT;
1583
1584         src = g_timeout_source_new(timeout_msec);
1585         if (!src)
1586                 return -ENOMEM;
1587
1588         g_source_set_callback(src, _cb_ctx_timeout, ctx, NULL);
1589         g_source_attach(src, ctx->context);
1590         g_source_unref(src);
1591
1592         ctx->timeout_src = src;
1593
1594         return 0;
1595 }
1596
1597 guint subscribe_dbus_signal_ctx(dbus_handle_h handle, sig_ctx *ctx,
1598                 const char *sender,     const char *path,
1599                 const char *iface, const char *name,
1600                 GDBusSignalCallback _cb)
1601 {
1602         dcl_dbus_handle();
1603
1604         if (!ctx) {
1605                 _E("wrong param ctx is null");
1606                 return 0;
1607         }
1608
1609         if (!dh) {
1610                 dh = _dbus_handle_get_default_connection();
1611                 if (!dh) {
1612                         _E("failed to get default connection, bustype:%d",
1613                                         (int)dbus_handle_get_default_bus_type());
1614                         return 0;
1615                 }
1616         }
1617
1618         if (!dh->conn) {
1619                 _E("connection is null. check bus status");
1620                 return 0;
1621         }
1622
1623         if (!_cb)
1624                 _cb = _signal_reply_sync_cb;
1625
1626         /* change context before subscribe */
1627         g_main_context_push_thread_default(ctx->context);
1628
1629         ctx->sig_id = g_dbus_connection_signal_subscribe(dh->conn,
1630                         sender, iface, name, path, NULL,
1631                         G_DBUS_SIGNAL_FLAGS_NONE, _cb,
1632                         (void*)ctx, NULL);
1633
1634         if (!ctx->sig_id)
1635                 _E("failed to subscribe signal");
1636
1637         return ctx->sig_id;
1638 }
1639
1640 int dbus_handle_signal_ctx_wait(sig_ctx *ctx)
1641 {
1642         if (!ctx || !ctx->loop)
1643                 return -EINVAL;
1644
1645         g_main_loop_run(ctx->loop);
1646
1647         _D("quit g_main_loop");
1648
1649         return ctx->quit_reason;
1650 }
1651
1652 int _check_type_string_is_container(const char *signature)
1653 {
1654         if (!signature)
1655                 return FALSE;
1656
1657         switch (signature[0]) {
1658         case 'a':
1659         case 'm':
1660         case 'r':
1661         case '(':
1662         case '{':
1663         case 'v':
1664                 return TRUE;
1665         default:
1666                 return FALSE;
1667         }
1668
1669         return TRUE;
1670 }
1671
1672 int dbus_handle_emit_dbus_signal(const char *dest,
1673                                         const char *path,
1674                                         const char *iface,
1675                                         const char *name,
1676                                         GVariant *param)
1677 {
1678         dbus_handle_s *dh = NULL;
1679         GError *err = NULL;
1680         gboolean ret = 0;
1681
1682         dh = _dbus_handle_get_default_connection();
1683         if (!dh) {
1684                 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1685                 return -1;
1686         }
1687
1688         ret = g_dbus_connection_emit_signal(dh->conn, dest, path, iface, name, param, &err);
1689         if (err) {
1690                 _E("%d %s\n", ret, err ? err->message : "NULL");
1691                 g_error_free(err);
1692         }
1693
1694         return ret;
1695 }
1696
1697 int dbus_handle_emit_dbus_signal_sync(const char *dest,
1698                                         const char *path,
1699                                         const char *iface,
1700                                         const char *name,
1701                                         GVariant *param)
1702 {
1703         dbus_handle_s *dh = NULL;
1704         GError *err = NULL;
1705         gboolean ret = 0;
1706
1707         dh = _dbus_handle_get_default_connection();
1708         if (!dh) {
1709                 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1710                 return -1;
1711         }
1712
1713         ret = g_dbus_connection_emit_signal(dh->conn, dest, path, iface, name, param, &err);
1714         if (!ret) {
1715                 _E("%d %s\n", ret, err ? err->message : "NULL");
1716                 g_error_free(err);
1717         }
1718
1719         ret = g_dbus_connection_flush_sync(dh->conn, NULL, &err);
1720         if (!ret) {
1721                 _E("%d %s\n", ret, err ? err->message : "NULL");
1722                 g_error_free(err);
1723         }
1724
1725         return ret;
1726 }
1727
1728 int dbus_handle_flush_sync(dbus_handle_h handle)
1729 {
1730         dcl_dbus_handle();
1731         GError *err = NULL;
1732         gboolean ret = 0;
1733
1734         if (!dh) {
1735                 dh = _dbus_handle_get_default_connection();
1736                 if (!dh) {
1737                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1738                         return 0;
1739                 }
1740         }
1741
1742         ret = g_dbus_connection_flush_sync(dh->conn, NULL, &err);
1743         if (!ret) {
1744                 _E("%d %s\n", ret, err ? err->message : "NULL");
1745                 g_error_free(err);
1746         }
1747
1748         return ret;
1749 }
1750
1751 GVariant *dbus_handle_method_sync_with_reply_var(const char *dest,
1752                                                 const char *path,
1753                                                 const char *iface,
1754                                                 const char *method,
1755                                                 GVariant *var)
1756 {
1757         GError *err = NULL;
1758         GVariant * ret = NULL;
1759         dbus_handle_s *dh = NULL;
1760
1761         if (!dest || !path || !iface || !method) {
1762                 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
1763                 if (var)
1764                         g_variant_unref(var);
1765                 return NULL;
1766         }
1767
1768         dh = _dbus_handle_get_default_connection();
1769         if (!dh) {
1770                 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1771                 if (var)
1772                         g_variant_unref(var);
1773                 return NULL;
1774         }
1775
1776         ret = g_dbus_connection_call_sync(dh->conn,
1777                         dest, path, iface, method,
1778                         var, NULL,
1779                         G_DBUS_CALL_FLAGS_NONE,
1780                         DBUS_REPLY_TIMEOUT,
1781                         NULL,
1782                         &err);
1783         if (!ret || err) {
1784                 if (err) {
1785                         _E("failed to g_dbus_connection_call_sync:%s", err->message);
1786                         if (g_error_matches(err, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED))
1787                                 ret = g_variant_new("(i)", -EPERM);
1788                         else
1789                                 ret = NULL;
1790                         g_error_free(err);
1791                         return ret;
1792                 } else {
1793                         _E("failed to g_dbus_connection_call_sync");
1794                 }
1795                 return NULL;
1796         }
1797
1798         return ret;
1799 }
1800
1801 GVariant *dbus_handle_method_sync_with_reply_var_timeout(const char *dest, const char *path,
1802         const char *iface, const char *method, GVariant *var, int timeout)
1803 {
1804         GError *err = NULL;
1805         GVariant * ret = NULL;
1806         dbus_handle_s *dh = NULL;
1807
1808         if (!dest || !path || !iface || !method) {
1809                 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
1810                 if (var)
1811                         g_variant_unref(var);
1812                 return NULL;
1813         }
1814
1815         dh = _dbus_handle_get_default_connection();
1816         if (!dh) {
1817                 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1818                 if (var)
1819                         g_variant_unref(var);
1820                 return NULL;
1821         }
1822
1823         ret = g_dbus_connection_call_sync(dh->conn,
1824                                         dest, path, iface, method,
1825                                         var, NULL,
1826                                         G_DBUS_CALL_FLAGS_NONE,
1827                                         timeout,
1828                                         NULL,
1829                                         &err);
1830         if (!ret || err) {
1831                 if (err) {
1832                         _E("failed to g_dbus_connection_call_sync:%s", err->message);
1833                         g_error_free(err);
1834                 } else {
1835                         _E("failed to g_dbus_connection_call_sync");
1836                 }
1837                 return NULL;
1838         }
1839
1840         return ret;
1841 }
1842
1843 gint* dbus_handle_get_unix_fd_list(GDBusMethodInvocation *invocation, int *size)
1844 {
1845         GUnixFDList *fd_list = NULL;
1846         int length = 0;
1847
1848         fd_list = g_dbus_message_get_unix_fd_list(g_dbus_method_invocation_get_message(invocation));
1849
1850         if (!fd_list) {
1851                 _E("failed to g_unix_fd_list_get_length: fd_list is null");
1852                 return NULL;
1853         }
1854
1855         length = g_unix_fd_list_get_length(fd_list);
1856         if (length == 0) {
1857                 _E("failed to g_unix_fd_list_get_length: list size is 0");
1858                 return NULL;
1859         }
1860         if (size)
1861                 *size = length;
1862
1863         return g_unix_fd_list_steal_fds(fd_list, NULL);
1864 }
1865
1866 GVariant *dbus_handle_method_with_unix_fd_list_sync_with_reply_var(const char *dest,
1867                                                                 const char *path,
1868                                                                 const char *iface,
1869                                                                 const char *method,
1870                                                                 GVariant *param,
1871                                                                 int *in_fdlist,
1872                                                                 int in_size,
1873                                                                 int **out_fdlist,
1874                                                                 int *out_size)
1875 {
1876         GError *err = NULL;
1877         GVariant * ret = NULL;
1878         dbus_handle_s *dh = NULL;
1879         GUnixFDList *g_infdlist = NULL;
1880         GUnixFDList *g_outfdlist = NULL;
1881
1882         if (!dest || !path || !iface || !method) {
1883                 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
1884                 return NULL;
1885         }
1886         if (in_fdlist && in_size == 0) {
1887                 _E("wrong in_fdlist is not null but in_size is 0");
1888                 return NULL;
1889         }
1890
1891         dh = _dbus_handle_get_default_connection();
1892         if (!dh) {
1893                 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1894                 return NULL;
1895         }
1896
1897         /* append fd */
1898         if (in_fdlist) {
1899                 g_infdlist = g_unix_fd_list_new_from_array(in_fdlist, in_size);
1900                 if (!g_infdlist) {
1901                         _E("failed to g_unix_fd_list_new_from_array\n");
1902                         goto out;
1903                 }
1904                 //g_infdlist = g_unix_fd_list_new();
1905                 //if (g_unix_fd_list_append(g_infdlist, in_fdlist[0], &err) < 0) {
1906         }
1907
1908         /* send message */
1909         ret = g_dbus_connection_call_with_unix_fd_list_sync(dh->conn,
1910                 dest, path, iface, method,
1911                 param, NULL,
1912                 G_DBUS_CALL_FLAGS_NONE,
1913                 -1,
1914                 g_infdlist, &g_outfdlist,
1915                 NULL, &err);
1916         if (!ret || err) {
1917                 if (err) {
1918                         _E("failed to g_dbus_connection_call_with_unix_fd_list_sync:%s", err->message);
1919                         g_error_free(err);
1920                 } else {
1921                         _E("failed to g_dbus_connection_call_with_unix_fd_list_sync:");
1922                         if (param)
1923                                 g_variant_unref(param);
1924                         if (g_infdlist)
1925                                 g_object_unref(g_infdlist);
1926                 }
1927                 goto out;
1928         }
1929
1930         /* copy fds to out array */
1931         if (g_outfdlist) {
1932                 *out_size = g_unix_fd_list_get_length(g_outfdlist);
1933                 if (*out_size == 0)
1934                         goto out;
1935                 *out_fdlist = g_unix_fd_list_steal_fds(g_outfdlist, NULL);
1936         }
1937 out:
1938         if (g_outfdlist)
1939                 g_object_unref(g_outfdlist);
1940         return ret;
1941 }
1942
1943 int dbus_handle_method_sync_var(const char *dest,
1944                                 const char *path,
1945                                 const char *iface,
1946                                 const char *method,
1947                                 GVariant *param)
1948 {
1949         int result;
1950         gboolean result_bool;
1951         GVariant *reply = NULL;
1952
1953         if (!dest || !path || !iface || !method) {
1954                 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
1955                 return -1;
1956         }
1957
1958         reply = dbus_handle_method_sync_with_reply_var(dest, path, iface, method, param);
1959         if (!reply)
1960                 return -ECOMM;
1961
1962         if (g_strcmp0("(i)", g_variant_get_type_string(reply)) == 0) {
1963                 g_variant_get(reply, "(i)", &result);
1964         } else if (g_strcmp0("(b)", g_variant_get_type_string(reply)) == 0) {
1965                 g_variant_get(reply, "(b)", &result_bool);
1966                 result = (int)result_bool;
1967         } else {
1968                 result = -ENOMSG;
1969         }
1970
1971         g_variant_unref(reply);
1972
1973         return result;
1974 }
1975
1976 int dbus_handle_method_async_var(const char *dest,
1977                                         const char *path,
1978                                         const char *iface,
1979                                         const char *method,
1980                                         GVariant *param)
1981 {
1982         dbus_handle_s *dh = NULL;
1983
1984         if (!dest || !path || !iface || !method) {
1985                 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
1986                 return -1;
1987         }
1988
1989         dh = _dbus_handle_get_default_connection();
1990         if (!dh) {
1991                 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1992                 return -1;
1993         }
1994
1995         g_dbus_connection_call(dh->conn,
1996                                 dest, path, iface, method,
1997                                 param, NULL,
1998                                 G_DBUS_CALL_FLAGS_NONE,
1999                                 -1,
2000                                 NULL,
2001                                 NULL,
2002                                 NULL);
2003
2004         return 0;
2005 }
2006
2007 /* callback should free gvariant */
2008 static void _cb_pending(GDBusConnection *conn,
2009                         GAsyncResult *res,
2010                         gpointer user_data)
2011 {
2012         GVariant *reply = NULL;
2013         GError *err = NULL;
2014         pending_call_data *data = (pending_call_data *)user_data;
2015
2016         reply = g_dbus_connection_call_finish(conn, res, &err);
2017         if (!reply || err) {
2018                 if (!err)
2019                         g_set_error(&err, G_IO_ERROR, G_IO_ERROR_FAILED,
2020                                 "Error during g_dbus_connection_call");
2021
2022                 if (data && data->func)
2023                         data->func(NULL, data->data, err);
2024                 goto out;
2025         }
2026
2027         if (data && data->func)
2028                 data->func(reply, data->data, err);
2029 out:
2030         if (err)
2031                 g_error_free(err);
2032         if (data)
2033                 free(data);
2034 }
2035
2036 int dbus_handle_method_async_with_reply_var(const char *dest,
2037                                         const char *path,
2038                                         const char *iface,
2039                                         const char *method,
2040                                         GVariant *param,
2041                                         dbus_pending_cb cb,
2042                                         int timeout_msec,
2043                                         void *data)
2044 {
2045         dbus_handle_s *dh = NULL;
2046         pending_call_data *pdata = NULL;
2047         int ret = 0;
2048
2049         if (!dest || !path || !iface || !method) {
2050                 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
2051                 return -1;
2052         }
2053
2054         if (timeout_msec < -1) {
2055                 _E("wrong timeout %d", timeout_msec);
2056                 return -1;
2057         }
2058
2059         dh = _dbus_handle_get_default_connection();
2060         if (!dh) {
2061                 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2062                 return -EPERM;
2063         }
2064
2065         if (cb) {
2066                 pdata = (pending_call_data*)malloc(sizeof(pending_call_data));
2067                 if (!pdata) {
2068                         ret = -ENOMEM;
2069                         goto err;
2070                 }
2071
2072                 pdata->func = cb;
2073                 pdata->data = data;
2074         }
2075         g_dbus_connection_call(dh->conn,
2076                                 dest, path, iface, method,
2077                                 param, NULL,
2078                                 G_DBUS_CALL_FLAGS_NONE,
2079                                 timeout_msec,
2080                                 NULL,
2081                                 (GAsyncReadyCallback)_cb_pending,
2082                                 pdata);
2083
2084         return ret;
2085 err:
2086         if (param)
2087                 g_variant_unref(param);
2088         return ret;
2089 }
2090
2091 int dbus_connection_get_sender_pid(GDBusConnection *conn, const char * sender)
2092 {
2093         GError *err = NULL;
2094         GVariant *vret = NULL;
2095         pid_t pid = 0;
2096
2097         if (!conn) {
2098                 _E("connection is null");
2099                 return -1;
2100         }
2101         if (!sender) {
2102                 _E("sender is null");
2103                 return -1;
2104         }
2105
2106         vret = g_dbus_connection_call_sync(conn,
2107                         "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetConnectionUnixProcessID",
2108                         g_variant_new("(s)", sender), NULL,
2109                         G_DBUS_CALL_FLAGS_NONE,
2110                         DBUS_REPLY_TIMEOUT,
2111                         NULL,
2112                         &err);
2113         if (!vret || err) {
2114                 _E("failed to g_dbus_connection_call_sync:%s", err->message);
2115                 g_error_free(err);
2116                 return -1;
2117         }
2118
2119         g_variant_get(vret, "(u)", &pid);
2120         g_variant_unref(vret);
2121
2122         return pid;
2123 }
2124
2125 int dbus_handle_get_sender_pid(dbus_handle_h handle, const char * sender)
2126 {
2127         dcl_dbus_handle();
2128
2129         if (!dh) {
2130                 dh = _dbus_handle_get_default_connection();
2131                 if (!dh) {
2132                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2133                         return -1;
2134                 }
2135         }
2136         if (!dh->conn) {
2137                 _E("wrong dbus handle. connection is null");
2138                 assert(0);
2139                 return -1;
2140         }
2141
2142         return dbus_connection_get_sender_pid(dh->conn, sender);
2143 }
2144
2145 int dbus_handle_get_sender_credentials(dbus_handle_h handle, const char *name, GDBusCredentials *creds)
2146 {
2147         dcl_dbus_handle();
2148         GVariant *vret = NULL;
2149         GError *err = NULL;
2150         GVariantIter *iter = NULL;
2151         char * item;
2152         GVariant *sub;
2153
2154         if (!dh) {
2155                 dh = _dbus_handle_get_default_connection();
2156                 if (!dh) {
2157                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2158                         return -1;
2159                 }
2160         }
2161         vret = g_dbus_connection_call_sync(dh->conn,
2162                                         DBUS_BUS_NAME,
2163                                         DBUS_OBJECT_PATH,
2164                                         DBUS_INTERFACE_NAME,
2165                                         "GetConnectionCredentials",
2166                                         g_variant_new("(s)", name),
2167                                         NULL,
2168                                         G_DBUS_CALL_FLAGS_NONE,
2169                                         DBUS_REPLY_TIMEOUT,
2170                                         NULL,
2171                                         &err);
2172         if (!vret || err) {
2173                 _E("failed to g_dbus_connection_call_sync:%s", err->message);
2174                 return -1;
2175         }
2176
2177         g_variant_get(vret, "(a{sv})", &iter);
2178
2179         while (g_variant_iter_loop(iter, "{sv}", &item, &sub)) {
2180                 if (!g_strcmp0(item, "UnixUserID")) {
2181                         g_variant_get(sub, "u", &creds->uid);
2182                         //_D("UnixUserID %u", creds->uid);
2183                 } else if (!g_strcmp0(item, "ProcessID")) {
2184                         g_variant_get(sub, "u", &creds->pid);
2185                         //_D("ProcessID %u", creds->pid);
2186                 } else if (!g_strcmp0(item, "LinuxSecurityLabel")) {
2187                         g_variant_get(sub, "^ay", &creds->sec_label);
2188                         //_D("%s", creds->sec_label);
2189                 }
2190         }
2191
2192         if (iter)
2193                 g_variant_iter_free(iter);
2194         if (vret)
2195                 g_variant_unref(vret);
2196
2197         return 0;
2198 }
2199
2200 void _destroy_notify_watch_name(gpointer data)
2201 {
2202 //      if (data)
2203 //              free(data);
2204 }
2205
2206 int dbus_handle_watch_name(const char *name,
2207                         GBusNameAppearedCallback  name_appeared_handler,
2208                         GBusNameVanishedCallback  name_vanished_handler,
2209                         void *user_data,
2210                         GDestroyNotify user_data_free_func)
2211 {
2212         guint id = 0;
2213
2214         if (!name) {
2215                 _E("wrong name name is null");
2216                 return -1;
2217         }
2218         if (!name_appeared_handler && !name_vanished_handler) {
2219                 _E("both function pointers are null");
2220                 return -1;
2221         }
2222
2223         id = g_bus_watch_name(dbus_handle_get_default_bus_type(),
2224                                 name,
2225                                 G_BUS_NAME_WATCHER_FLAGS_NONE,
2226                                 name_appeared_handler,
2227                                 name_vanished_handler,
2228                                 user_data,
2229                                 user_data_free_func ? user_data_free_func : _destroy_notify_watch_name);
2230         if (!id) {
2231                 _E("failed to g_bus_watch_name");
2232                 return -1;
2233         }
2234
2235         return id;
2236 }
2237
2238 void dbus_handle_unwatch_name(guint id)
2239 {
2240         if (id == 0) {
2241                 _E("wrong id %d", id);
2242                 return;
2243         }
2244         g_bus_unwatch_name(id);
2245 }
2246
2247 int _get_cmdline_name(pid_t pid, char *cmdline, size_t cmdline_size)
2248 {
2249         int fd, ret;
2250         char buf[PATH_MAX + 1];
2251         char *filename;
2252
2253         snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
2254         fd = open(buf, O_RDONLY);
2255         if (fd < 0) {
2256                 errno = ESRCH;
2257                 return -1;
2258         }
2259
2260         ret = read(fd, buf, PATH_MAX);
2261         close(fd);
2262         if (ret < 0)
2263                 return -1;
2264
2265         buf[PATH_MAX] = '\0';
2266
2267         filename = strrchr(buf, '/');
2268         if (filename == NULL)
2269                 filename = buf;
2270         else
2271                 filename = filename + 1;
2272
2273         if (cmdline_size < strlen(filename) + 1) {
2274                 errno = EOVERFLOW;
2275                 return -1;
2276         }
2277
2278         strncpy(cmdline, filename, cmdline_size - 1);
2279         cmdline[cmdline_size - 1] = '\0';
2280         return 0;
2281 }
2282
2283 // g_strfreev(strv)
2284 char **dbus_handle_get_owner_list(dbus_handle_h handle, const char *bus_name)
2285 {
2286         dcl_dbus_handle();
2287         GError *err = NULL;
2288         GVariant *vret = NULL;
2289         GVariantIter *iter = NULL;
2290         gchar **strv = NULL;
2291         gchar *str = NULL;
2292         int i = 0;
2293
2294         if (!bus_name) {
2295                 _E("wrong parameter bus_name is null");
2296                 return NULL;
2297         }
2298
2299         if (!dh) {
2300                 dh = _dbus_handle_get_default_connection();
2301                 if (!dh) {
2302                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2303                         return NULL;
2304                 }
2305         }
2306
2307         vret = g_dbus_connection_call_sync(dh->conn,
2308                                         "org.freedesktop.DBus",
2309                                         "/",
2310                                         "org.freedesktop.DBus",
2311                                         "ListQueuedOwners",
2312                                         g_variant_new("(s)", bus_name),
2313                                         NULL,
2314                                         G_DBUS_CALL_FLAGS_NONE,
2315                                         DBUS_REPLY_TIMEOUT,
2316                                         NULL,
2317                                         &err);
2318         if (!vret || err) {
2319                 _E("failed to g_dbus_connection_call_sync:%s", err->message);
2320                 g_error_free(err);
2321                 return NULL;
2322         }
2323
2324         g_variant_get(vret, "(as)", &iter);
2325         strv = g_new(gchar *, g_variant_iter_n_children(iter) + 1);
2326
2327         i = 0;
2328         while (g_variant_iter_loop(iter, "s", &str))
2329                 strv[i++] = g_strdup(str);
2330         strv[i] = NULL;
2331
2332         g_variant_iter_free(iter);
2333         g_variant_unref(vret);
2334
2335         return strv;
2336 }
2337
2338 void dbus_handle_check_owner_name(dbus_handle_h handle, const char *owner_name)
2339 {
2340         dcl_dbus_handle();
2341         char exe_name[PATH_MAX];
2342         int pid;
2343         char **strv = NULL;
2344         int i;
2345
2346         if (!dh) {
2347                 dh = _dbus_handle_get_default_connection();
2348                 if (!dh) {
2349                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2350                         return ;
2351                 }
2352         }
2353
2354         strv = dbus_handle_get_owner_list(dh, owner_name);
2355         if (!strv) {
2356                 _E("failed to get owner list of %s", owner_name);
2357                 return ;
2358         }
2359
2360         for (i = 0; strv[i] != NULL; ++i) {
2361                 pid = dbus_handle_get_sender_pid(dh, strv[i]);
2362                 if (_get_cmdline_name(pid, exe_name, PATH_MAX) != 0)
2363                         break;
2364                 _I("%s(%d)", exe_name, pid);
2365         }
2366
2367         g_strfreev(strv);
2368 }
2369
2370 int check_systemd_active(void)
2371 {
2372         int ret = FALSE;
2373         GVariant *msg = NULL;
2374         GVariant *var = NULL;
2375         char *state;
2376
2377         _I("%s %s", "org.freedesktop.systemd1.Unit", "ActiveState");
2378
2379         msg = dbus_handle_method_sync_with_reply_var("org.freedesktop.systemd1",
2380                         "/org/freedesktop/systemd1/unit/default_2etarget",
2381                         "org.freedesktop.DBus.Properties",
2382                         "Get",
2383                         g_variant_new("(ss)", "org.freedesktop.systemd1.Unit", "ActiveState"));
2384         if (!msg)
2385                 return -EBADMSG;
2386
2387         if (!g_variant_get_safe(msg, "(v)", &var)) {
2388                 _E("reply is not variant type");
2389                 ret = -EBADMSG;
2390                 goto out;
2391         }
2392         if (!g_variant_get_safe(var, "(s)", &state)) {
2393                 _E("variant doesn't have string (%s)", g_variant_get_type_string(var));
2394                 ret = -EBADMSG;
2395                 goto out;
2396         }
2397
2398         if (strncmp(state, "active", 6) == 0)
2399                 ret = TRUE;
2400
2401         g_free(state);
2402 out:
2403         if (var)
2404                 g_variant_unref(var);
2405         if (msg)
2406                 g_variant_unref(msg);
2407
2408         return ret;
2409 }
2410
2411 GVariant *dbus_handle_make_simple_array(const char *sig, int *param)
2412 {
2413         GVariantBuilder *builder = NULL;
2414         GVariant *var = NULL;
2415         char format[256];
2416         int i = 0;
2417
2418         builder = g_variant_builder_new(G_VARIANT_TYPE(sig));
2419         if (!builder) {
2420                 _E("failed to g_variant_builder_new");
2421                 return NULL;
2422         }
2423
2424         while (param[i])
2425                 g_variant_builder_add(builder, "i", param[i++]);
2426
2427         snprintf(format, sizeof(format) - 1, "(%s)", sig);
2428         var = g_variant_new(format, builder);
2429         g_variant_builder_unref(builder);
2430         return var;
2431 }