[kdbus] Integrate acquiring and releasing names on kdbus with GLib core
[platform/upstream/glib.git] / gio / gkdbus.c
1 /*  GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright (C) 2013 Samsung Electronics
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: Michal Eljasiewicz   <m.eljasiewic@samsung.com>
21  * Author: Lukasz Skalski       <l.skalski@samsung.com>
22  */
23
24 #include "config.h"
25 #include "gkdbus.h"
26 #include "glib-unix.h"
27 #include "glibintl.h"
28 #include "kdbus.h"
29 #include "gkdbusconnection.h"
30
31 #include <gio/gio.h>
32 #include <errno.h>
33 #include <string.h>
34 #include <sys/mman.h>
35 #include <sys/ioctl.h>
36 #include <stdio.h>
37
38 #ifdef HAVE_SYS_FILIO_H
39 # include <sys/filio.h>
40 #endif
41
42 #ifdef HAVE_SYS_UIO_H
43 #include <sys/uio.h>
44 #endif
45
46 #define KDBUS_POOL_SIZE (16 * 1024LU * 1024LU)
47 #define KDBUS_ALIGN8(l) (((l) + 7) & ~7)
48 #define KDBUS_ALIGN8_PTR(p) ((void*) (uintptr_t)(p))
49
50 #define KDBUS_ITEM_HEADER_SIZE G_STRUCT_OFFSET(struct kdbus_item, data)
51 #define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
52
53 #define KDBUS_ITEM_NEXT(item) \
54         (typeof(item))(((guint8 *)item) + KDBUS_ALIGN8((item)->size))
55 #define KDBUS_ITEM_FOREACH(item, head, first)                    \
56         for (item = (head)->first;                               \
57              (guint8 *)(item) < (guint8 *)(head) + (head)->size; \
58              item = KDBUS_ITEM_NEXT(item))
59
60 #define g_alloca0(x) memset(g_alloca(x), '\0', (x))
61
62 static void     g_kdbus_initable_iface_init (GInitableIface  *iface);
63 static gboolean g_kdbus_initable_init       (GInitable       *initable,
64                                              GCancellable    *cancellable,
65                                              GError         **error);
66
67 #define g_kdbus_get_type _g_kdbus_get_type
68 G_DEFINE_TYPE_WITH_CODE (GKdbus, g_kdbus, G_TYPE_OBJECT,
69                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
70                                                 g_kdbus_initable_iface_init));
71
72 /* GBusCredentialsFlags */
73 typedef enum
74 {
75   G_BUS_CREDS_PID              = 1,
76   G_BUS_CREDS_UID              = 2,
77   G_BUS_CREDS_UNIQUE_NAME      = 3,
78   G_BUS_CREDS_SELINUX_CONTEXT  = 4
79 } GBusCredentialsFlags;
80
81 /* GBusNameOwnerReturnFlags */
82 typedef enum
83 {
84   G_BUS_REQUEST_NAME_REPLY_PRIMARY_OWNER = 1, /* Caller is now the primary owner of the name, replacing any previous owner */
85   G_BUS_REQUEST_NAME_REPLY_IN_QUEUE = 2,      /* The name already had an owner, the application will be placed in a queue */
86   G_BUS_REQUEST_NAME_REPLY_EXISTS = 3,        /* The name already has an owner */
87   G_BUS_REQUEST_NAME_REPLY_ALREADY_OWNER = 4  /* The application trying to request ownership of a name is already the owner of it */
88 } GBusNameOwnerReturnFlags;
89
90 /* GBusReleaseNameReturnFlags */
91 typedef enum
92 {
93   G_BUS_RELEASE_NAME_REPLY_RELEASED = 1,     /* The caller has released his claim on the given name */
94   G_BUS_RELEASE_NAME_REPLY_NON_EXISTENT = 2, /* The given name does not exist on this bus*/
95   G_BUS_RELEASE_NAME_REPLY_NOT_OWNER = 3     /* The caller not waiting in the queue to own this name*/
96 } GBusReleaseNameReturnFlags;
97
98 /* GKdbusPrivate struct */
99 struct _GKdbusPrivate
100 {
101   gint               fd;
102
103   gchar             *kdbus_buffer;
104   gchar             *unique_name;
105   guint64            unique_id;
106
107   guint64            hello_flags;
108   guint64            attach_flags;
109
110   guint              closed : 1;
111   guint              inited : 1;
112   guint              timeout;
113   guint              timed_out : 1;
114
115   guchar             bus_id[16];
116 };
117
118 /* GKdbusSource struct */
119 typedef struct {
120   GSource        source;
121   GPollFD        pollfd;
122   GKdbus        *kdbus;
123   GIOCondition   condition;
124   GCancellable  *cancellable;
125   GPollFD        cancel_pollfd;
126   gint64         timeout_time;
127 } GKdbusSource;
128
129
130 typedef gboolean (*GKdbusSourceFunc) (GKdbus *kdbus,
131                                       GIOCondition condition,
132                                       gpointer user_data);
133
134 /**
135  * g_kdbus_finalize:
136  *
137  */
138 static void
139 g_kdbus_finalize (GObject  *object)
140 {
141   GKdbus *kdbus = G_KDBUS (object);
142
143   if (kdbus->priv->kdbus_buffer != NULL)
144     munmap (kdbus->priv->kdbus_buffer, KDBUS_POOL_SIZE);
145
146   kdbus->priv->kdbus_buffer = NULL;
147
148   if (kdbus->priv->fd != -1 && !kdbus->priv->closed)
149     _g_kdbus_close (kdbus, NULL);
150
151   if (G_OBJECT_CLASS (g_kdbus_parent_class)->finalize)
152     (*G_OBJECT_CLASS (g_kdbus_parent_class)->finalize) (object);
153 }
154
155
156 /**
157  * g_kdbus_class_init:
158  *
159  */
160 static void
161 g_kdbus_class_init (GKdbusClass  *klass)
162 {
163   GObjectClass *gobject_class G_GNUC_UNUSED = G_OBJECT_CLASS (klass);
164
165   g_type_class_add_private (klass, sizeof (GKdbusPrivate));
166   gobject_class->finalize = g_kdbus_finalize;
167 }
168
169
170 /**
171  * g_kdbus_initable_iface_init:
172  *
173  */
174 static void
175 g_kdbus_initable_iface_init (GInitableIface  *iface)
176 {
177   iface->init = g_kdbus_initable_init;
178 }
179
180
181 /**
182  * g_kdbus_init:
183  *
184  */
185 static void
186 g_kdbus_init (GKdbus  *kdbus)
187 {
188   kdbus->priv = G_TYPE_INSTANCE_GET_PRIVATE (kdbus, G_TYPE_KDBUS, GKdbusPrivate);
189
190   kdbus->priv->fd = -1;
191
192   kdbus->priv->unique_id = -1;
193   kdbus->priv->unique_name = NULL;
194
195   kdbus->priv->kdbus_buffer = NULL;
196
197   kdbus->priv->hello_flags = 0; /* KDBUS_HELLO_ACCEPT_FD */
198   kdbus->priv->attach_flags = KDBUS_ATTACH_NAMES;
199 }
200
201
202 /**
203  * g_kdbus_initable_init:
204  *
205  */
206 static gboolean
207 g_kdbus_initable_init (GInitable     *initable,
208                        GCancellable  *cancellable,
209                        GError       **error)
210 {
211   GKdbus *kdbus;
212
213   g_return_val_if_fail (G_IS_KDBUS (initable), FALSE);
214
215   kdbus = G_KDBUS (initable);
216
217   if (cancellable != NULL)
218     {
219       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
220                            _("Cancellable initialization not supported"));
221       return FALSE;
222     }
223
224   kdbus->priv->inited = TRUE;
225
226   return TRUE;
227 }
228
229
230 /**
231  * kdbus_source_prepare:
232  *
233  */
234 static gboolean
235 kdbus_source_prepare (GSource  *source,
236                       gint     *timeout)
237 {
238   GKdbusSource *kdbus_source = (GKdbusSource *)source;
239
240   if (g_cancellable_is_cancelled (kdbus_source->cancellable))
241     return TRUE;
242
243   if (kdbus_source->timeout_time)
244     {
245       gint64 now;
246
247       now = g_source_get_time (source);
248
249       *timeout = (kdbus_source->timeout_time - now + 999) / 1000;
250       if (*timeout < 0)
251         {
252           kdbus_source->kdbus->priv->timed_out = TRUE;
253           *timeout = 0;
254           return TRUE;
255         }
256     }
257   else
258     *timeout = -1;
259
260   if ((kdbus_source->condition & kdbus_source->pollfd.revents) != 0)
261     return TRUE;
262
263   return FALSE;
264 }
265
266
267 /**
268  * kdbus_source_check:
269  *
270  */
271 static gboolean
272 kdbus_source_check (GSource  *source)
273 {
274   gint timeout;
275
276   return kdbus_source_prepare (source, &timeout);
277 }
278
279
280 /**
281  * kdbus_source_dispatch
282  *
283  */
284 static gboolean
285 kdbus_source_dispatch  (GSource      *source,
286                         GSourceFunc   callback,
287                         gpointer      user_data)
288 {
289   GKdbusSourceFunc func = (GKdbusSourceFunc)callback;
290   GKdbusSource *kdbus_source = (GKdbusSource *)source;
291   GKdbus *kdbus = kdbus_source->kdbus;
292   gboolean ret;
293
294   if (kdbus_source->kdbus->priv->timed_out)
295     kdbus_source->pollfd.revents |= kdbus_source->condition & (G_IO_IN | G_IO_OUT);
296
297   ret = (*func) (kdbus,
298                  kdbus_source->pollfd.revents & kdbus_source->condition,
299                  user_data);
300
301   if (kdbus->priv->timeout)
302     kdbus_source->timeout_time = g_get_monotonic_time ()
303                                + kdbus->priv->timeout * 1000000;
304
305   else
306     kdbus_source->timeout_time = 0;
307
308   return ret;
309 }
310
311
312 /**
313  * kdbus_source_finalize
314  *
315  */
316 static void
317 kdbus_source_finalize (GSource  *source)
318 {
319   GKdbusSource *kdbus_source = (GKdbusSource *)source;
320   GKdbus *kdbus;
321
322   kdbus = kdbus_source->kdbus;
323
324   g_object_unref (kdbus);
325
326   if (kdbus_source->cancellable)
327     {
328       g_cancellable_release_fd (kdbus_source->cancellable);
329       g_object_unref (kdbus_source->cancellable);
330     }
331 }
332
333
334 /**
335  * kdbus_source_closure_callback:
336  *
337  */
338 static gboolean
339 kdbus_source_closure_callback (GKdbus        *kdbus,
340                                GIOCondition   condition,
341                                gpointer       data)
342 {
343   GClosure *closure = data;
344   GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT };
345   GValue result_value = G_VALUE_INIT;
346   gboolean result;
347
348   g_value_init (&result_value, G_TYPE_BOOLEAN);
349
350   g_value_init (&params[0], G_TYPE_KDBUS);
351   g_value_set_object (&params[0], kdbus);
352   g_value_init (&params[1], G_TYPE_IO_CONDITION);
353   g_value_set_flags (&params[1], condition);
354
355   g_closure_invoke (closure, &result_value, 2, params, NULL);
356
357   result = g_value_get_boolean (&result_value);
358   g_value_unset (&result_value);
359   g_value_unset (&params[0]);
360   g_value_unset (&params[1]);
361
362   return result;
363 }
364
365
366 static GSourceFuncs kdbus_source_funcs =
367 {
368   kdbus_source_prepare,
369   kdbus_source_check,
370   kdbus_source_dispatch,
371   kdbus_source_finalize,
372   (GSourceFunc)kdbus_source_closure_callback,
373 };
374
375
376 /**
377  * kdbus_source_new:
378  *
379  */
380 static GSource *
381 kdbus_source_new (GKdbus        *kdbus,
382                   GIOCondition   condition,
383                   GCancellable  *cancellable)
384 {
385   GSource *source;
386   GKdbusSource *kdbus_source;
387
388   source = g_source_new (&kdbus_source_funcs, sizeof (GKdbusSource));
389   g_source_set_name (source, "GKdbus");
390   kdbus_source = (GKdbusSource *)source;
391
392   kdbus_source->kdbus = g_object_ref (kdbus);
393   kdbus_source->condition = condition;
394
395   if (g_cancellable_make_pollfd (cancellable,
396                                  &kdbus_source->cancel_pollfd))
397     {
398       kdbus_source->cancellable = g_object_ref (cancellable);
399       g_source_add_poll (source, &kdbus_source->cancel_pollfd);
400     }
401
402   kdbus_source->pollfd.fd = kdbus->priv->fd;
403   kdbus_source->pollfd.events = condition;
404   kdbus_source->pollfd.revents = 0;
405   g_source_add_poll (source, &kdbus_source->pollfd);
406
407   if (kdbus->priv->timeout)
408     kdbus_source->timeout_time = g_get_monotonic_time ()
409                                + kdbus->priv->timeout * 1000000;
410   else
411     kdbus_source->timeout_time = 0;
412
413   return source;
414 }
415
416
417 /**
418  * _g_kdbus_create_source:
419  *
420  */
421 GSource *
422 _g_kdbus_create_source (GKdbus        *kdbus,
423                         GIOCondition   condition,
424                         GCancellable  *cancellable)
425 {
426   g_return_val_if_fail (G_IS_KDBUS (kdbus) && (cancellable == NULL || G_IS_CANCELLABLE (cancellable)), NULL);
427
428   return kdbus_source_new (kdbus, condition, cancellable);
429 }
430
431
432 /**
433  * _g_kdbus_open:
434  *
435  */
436 gboolean
437 _g_kdbus_open (GKdbus       *kdbus,
438                const gchar  *address,
439                GError      **error)
440 {
441   g_return_val_if_fail (G_IS_KDBUS (kdbus), FALSE);
442
443   kdbus->priv->fd = open(address, O_RDWR|O_NOCTTY|O_CLOEXEC);
444   if (kdbus->priv->fd<0)
445     {
446       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Can't open kdbus endpoint"));
447       return FALSE;
448     }
449
450   kdbus->priv->closed = FALSE;
451
452   return TRUE;
453 }
454
455
456 /**
457  * g_kdbus_free_data:
458  *
459  */
460 static gboolean
461 g_kdbus_free_data (GKdbus      *kdbus,
462                    guint64      offset)
463 {
464   struct kdbus_cmd_free cmd;
465   int ret;
466
467   cmd.offset = offset;
468   cmd.flags = 0;
469
470   ret = ioctl (kdbus->priv->fd, KDBUS_CMD_FREE, &cmd);
471   if (ret < 0)
472       return FALSE;
473
474   return TRUE;
475 }
476
477
478 /**
479  * g_kdbus_translate_nameowner_flags:
480  *
481  */
482 static void
483 g_kdbus_translate_nameowner_flags (GBusNameOwnerFlags   flags,
484                                    guint64             *kdbus_flags)
485 {
486   guint64 new_flags;
487
488   new_flags = 0;
489
490   if (flags & G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT)
491     new_flags |= KDBUS_NAME_ALLOW_REPLACEMENT;
492
493   if (flags & G_BUS_NAME_OWNER_FLAGS_REPLACE)
494     new_flags |= KDBUS_NAME_REPLACE_EXISTING;
495
496   if (!(flags & G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE))
497     new_flags |= KDBUS_NAME_QUEUE;
498
499   *kdbus_flags = new_flags;
500 }
501
502
503 /**
504  * _g_kdbus_close:
505  *
506  */
507 gboolean
508 _g_kdbus_close (GKdbus  *kdbus,
509                 GError **error)
510 {
511   gint res;
512
513   g_return_val_if_fail (G_IS_KDBUS (kdbus), FALSE);
514
515   if (kdbus->priv->closed)
516     return TRUE;
517
518   while (1)
519     {
520       res = close (kdbus->priv->fd);
521
522       if (res == -1)
523         {
524           if (errno == EINTR)
525             continue;
526
527           g_set_error (error, G_IO_ERROR,
528                        g_io_error_from_errno (errno),
529                        _("Error closing kdbus fd: %s"),
530                        g_strerror (errno));
531           return FALSE;
532         }
533       break;
534     }
535
536   kdbus->priv->closed = TRUE;
537   kdbus->priv->fd = -1;
538
539   return TRUE;
540 }
541
542
543 /**
544  * _g_kdbus_is_closed:
545  *
546  */
547 gboolean
548 _g_kdbus_is_closed (GKdbus  *kdbus)
549 {
550   g_return_val_if_fail (G_IS_KDBUS (kdbus), FALSE);
551
552   return kdbus->priv->closed;
553 }
554
555
556 /**
557  * _g_kdbus_Hello:
558  *
559  */
560 GVariant *
561 _g_kdbus_Hello (GIOStream  *stream,
562                 GError    **error)
563 {
564   GKdbus *kdbus;
565   struct kdbus_cmd_hello *hello;
566   struct kdbus_item *item;
567
568   gchar *conn_name;
569   size_t size, conn_name_size;
570
571   kdbus = _g_kdbus_connection_get_kdbus (G_KDBUS_CONNECTION (stream));
572
573   conn_name = "gdbus-kdbus";
574   conn_name_size = strlen (conn_name);
575
576   size = KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_cmd_hello, items)) +
577          KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, str) + conn_name_size + 1);
578
579   hello = g_alloca0 (size);
580   hello->conn_flags = kdbus->priv->hello_flags;
581   hello->attach_flags =  kdbus->priv->attach_flags;
582   hello->size = size;
583   hello->pool_size = KDBUS_POOL_SIZE;
584
585   item = hello->items;
586   item->size = G_STRUCT_OFFSET (struct kdbus_item, str) + conn_name_size + 1;
587   item->type = KDBUS_ITEM_CONN_NAME;
588   memcpy (item->str, conn_name, conn_name_size+1);
589   item = KDBUS_ITEM_NEXT (item);
590
591   if (ioctl(kdbus->priv->fd, KDBUS_CMD_HELLO, hello))
592     {
593       g_set_error (error, G_IO_ERROR,
594                    g_io_error_from_errno (errno),
595                    _("Failed to send HELLO: %s"),
596                    g_strerror (errno));
597       return NULL;
598     }
599
600   kdbus->priv->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, kdbus->priv->fd, 0);
601   if (kdbus->priv->kdbus_buffer == MAP_FAILED)
602     {
603       g_set_error (error, G_IO_ERROR,
604                    g_io_error_from_errno (errno),
605                    _("mmap error: %s"),
606                    g_strerror (errno));
607       return NULL;
608     }
609
610   if (hello->bus_flags > 0xFFFFFFFFULL)
611     {
612       g_set_error_literal (error,
613                            G_IO_ERROR,
614                            G_IO_ERROR_FAILED,
615                            _("Incompatible HELLO flags"));
616       return NULL;
617     }
618
619   memcpy (kdbus->priv->bus_id, hello->id128, 16);
620
621   kdbus->priv->unique_id = hello->id;
622   asprintf(&kdbus->priv->unique_name, ":1.%llu", (unsigned long long) hello->id);
623
624   return g_variant_new ("(s)", kdbus->priv->unique_name);
625 }
626
627
628 /*
629  * _g_kdbus_RequestName:
630  *
631  */
632 GVariant *
633 _g_kdbus_RequestName (GDBusConnection     *connection,
634                       const gchar         *name,
635                       GBusNameOwnerFlags   flags,
636                       GError             **error)
637 {
638   GKdbus *kdbus;
639   GVariant *result;
640   struct kdbus_cmd_name *kdbus_name;
641   guint64 kdbus_flags;
642   gssize len, size;
643   gint status, ret;
644
645   status = G_BUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
646
647   kdbus = _g_kdbus_connection_get_kdbus (G_KDBUS_CONNECTION (g_dbus_connection_get_stream (connection)));
648   if (kdbus == NULL)
649     {
650       g_set_error_literal (error,
651                            G_DBUS_ERROR,
652                            G_DBUS_ERROR_IO_ERROR,
653                            _("The connection is closed"));
654       return NULL;
655     }
656
657   if (!g_dbus_is_name (name))
658     {
659       g_set_error (error,
660                    G_DBUS_ERROR,
661                    G_DBUS_ERROR_INVALID_ARGS,
662                    "Given bus name \"%s\" is not valid", name);
663       return NULL;
664     }
665
666   if (*name == ':')
667     {
668       g_set_error (error,
669                    G_DBUS_ERROR,
670                    G_DBUS_ERROR_INVALID_ARGS,
671                    "Cannot acquire a service starting with ':' such as \"%s\"", name);
672       return NULL;
673     }
674
675   g_kdbus_translate_nameowner_flags (flags, &kdbus_flags);
676
677   len = strlen(name) + 1;
678   size = G_STRUCT_OFFSET (struct kdbus_cmd_name, items) + KDBUS_ITEM_SIZE(len);
679   kdbus_name = g_alloca0 (size);
680   kdbus_name->size = size;
681   kdbus_name->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
682   kdbus_name->items[0].type = KDBUS_ITEM_NAME;
683   kdbus_name->flags = kdbus_flags;
684   memcpy (kdbus_name->items[0].str, name, len);
685
686   ret = ioctl(kdbus->priv->fd, KDBUS_CMD_NAME_ACQUIRE, kdbus_name);
687   if (ret < 0)
688     {
689       if (errno == EEXIST)
690         status = G_BUS_REQUEST_NAME_REPLY_EXISTS;
691       else if (errno == EALREADY)
692         status = G_BUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
693       else
694         {
695           g_set_error (error, G_IO_ERROR,
696                        g_io_error_from_errno (errno),
697                        _("Error while acquiring name: %s"),
698                        g_strerror (errno));
699           return NULL;
700         }
701     }
702
703   if (kdbus_name->flags & KDBUS_NAME_IN_QUEUE)
704     status = G_BUS_REQUEST_NAME_REPLY_IN_QUEUE;
705
706   result = g_variant_new ("(u)", status);
707
708   return result;
709 }
710
711
712 /*
713  * _g_kdbus_ReleaseName:
714  *
715  */
716 GVariant *
717 _g_kdbus_ReleaseName (GDBusConnection     *connection,
718                       const gchar         *name,
719                       GError             **error)
720 {
721   GKdbus *kdbus;
722   GVariant *result;
723   struct kdbus_cmd_name *kdbus_name;
724   gssize len, size;
725   gint status, ret;
726
727   status = G_BUS_RELEASE_NAME_REPLY_RELEASED;
728
729   kdbus = _g_kdbus_connection_get_kdbus (G_KDBUS_CONNECTION (g_dbus_connection_get_stream (connection)));
730   if (kdbus == NULL)
731     {
732       g_set_error_literal (error,
733                            G_DBUS_ERROR,
734                            G_DBUS_ERROR_IO_ERROR,
735                            _("The connection is closed"));
736       return NULL;
737     }
738
739   if (!g_dbus_is_name (name))
740     {
741       g_set_error (error,
742                    G_DBUS_ERROR,
743                    G_DBUS_ERROR_INVALID_ARGS,
744                    "Given bus name \"%s\" is not valid", name);
745       return NULL;
746     }
747
748   if (*name == ':')
749     {
750       g_set_error (error,
751                    G_DBUS_ERROR,
752                    G_DBUS_ERROR_INVALID_ARGS,
753                    "Cannot release a service starting with ':' such as \"%s\"", name);
754       return NULL;
755     }
756
757   len = strlen(name) + 1;
758   size = G_STRUCT_OFFSET (struct kdbus_cmd_name, items) + KDBUS_ITEM_SIZE(len);
759   kdbus_name = g_alloca0 (size);
760   kdbus_name->size = size;
761   kdbus_name->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
762   kdbus_name->items[0].type = KDBUS_ITEM_NAME;
763   memcpy (kdbus_name->items[0].str, name, len);
764
765   ret = ioctl(kdbus->priv->fd, KDBUS_CMD_NAME_RELEASE, kdbus_name);
766   if (ret < 0)
767     {
768       if (errno == ESRCH)
769         status = G_BUS_RELEASE_NAME_REPLY_NON_EXISTENT;
770       else if (errno == EADDRINUSE)
771         status = G_BUS_RELEASE_NAME_REPLY_NOT_OWNER;
772       else
773         {
774           g_set_error (error, G_IO_ERROR,
775                        g_io_error_from_errno (errno),
776                        _("Error while releasing name: %s"),
777                        g_strerror (errno));
778           return NULL;
779         }
780     }
781
782   result = g_variant_new ("(u)", status);
783
784   return result;
785 }
786
787
788 /**
789  * _g_kdbus_GetBusId:
790  *
791  */
792 GVariant *
793 _g_kdbus_GetBusId (GDBusConnection  *connection,
794                    GError          **error)
795 {
796   GKdbus   *kdbus;
797   GVariant *result;
798   GString  *result_str;
799   guint     cnt;
800
801   result_str = g_string_new (NULL);
802   kdbus = _g_kdbus_connection_get_kdbus (G_KDBUS_CONNECTION (g_dbus_connection_get_stream (connection)));
803   if (kdbus == NULL)
804     {
805       g_set_error_literal (error,
806                            G_DBUS_ERROR,
807                            G_DBUS_ERROR_IO_ERROR,
808                            _("The connection is closed"));
809       g_string_free (result_str, TRUE);
810       return NULL;
811     }
812
813   for (cnt=0; cnt<16; cnt++)
814     g_string_append_printf (result_str, "%02x", kdbus->priv->bus_id[cnt]);
815
816   result = g_variant_new ("(s)", result_str->str);
817   g_string_free (result_str, TRUE);
818
819   return result;
820 }
821
822
823 /**
824  * _g_kdbus_GetListNames:
825  *
826  */
827 GVariant *
828 _g_kdbus_GetListNames (GDBusConnection  *connection,
829                        guint             list_name_type,
830                        GError          **error)
831 {
832   GKdbus *kdbus;
833   GVariant *result;
834   GVariantBuilder *builder;
835
836   struct kdbus_cmd_name_list cmd = {};
837   struct kdbus_name_list *name_list;
838   struct kdbus_cmd_name *name;
839
840   guint64 prev_id;
841   gint ret;
842
843   prev_id = 0;
844   kdbus = _g_kdbus_connection_get_kdbus (G_KDBUS_CONNECTION (g_dbus_connection_get_stream (connection)));
845   if (kdbus == NULL)
846     {
847       g_set_error_literal (error,
848                            G_DBUS_ERROR,
849                            G_DBUS_ERROR_IO_ERROR,
850                            _("The connection is closed"));
851       return NULL;
852     }
853
854   if (list_name_type)
855     cmd.flags = KDBUS_NAME_LIST_ACTIVATORS;                     /* ListActivatableNames */
856   else
857     cmd.flags = KDBUS_NAME_LIST_UNIQUE | KDBUS_NAME_LIST_NAMES; /* ListNames */
858
859   ret = ioctl(kdbus->priv->fd, KDBUS_CMD_NAME_LIST, &cmd);
860   if (ret < 0)
861     {
862       g_set_error (error,
863                    G_DBUS_ERROR,
864                    G_DBUS_ERROR_FAILED,
865                    _("Error listing names"));
866       return NULL;
867     }
868
869   name_list = (struct kdbus_name_list *) ((guint8 *) kdbus->priv->kdbus_buffer + cmd.offset);
870   builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
871
872   KDBUS_ITEM_FOREACH(name, name_list, names)
873     {
874       struct kdbus_item *item;
875       const gchar *item_name = "";
876
877       if ((cmd.flags & KDBUS_NAME_LIST_UNIQUE) && name->owner_id != prev_id)
878         {
879           GString *unique_name;
880
881           unique_name = g_string_new (NULL);
882           g_string_printf (unique_name, ":1.%llu", name->owner_id);
883           g_variant_builder_add (builder, "s", unique_name->str);
884           g_string_free (unique_name,TRUE);
885           prev_id = name->owner_id;
886         }
887
888        KDBUS_ITEM_FOREACH(item, name, items)
889          if (item->type == KDBUS_ITEM_NAME)
890            item_name = item->str;
891
892         if (g_dbus_is_name (item_name))
893           g_variant_builder_add (builder, "s", item_name);
894     }
895
896   result = g_variant_new ("(as)", builder);
897   g_variant_builder_unref (builder);
898
899   g_kdbus_free_data (kdbus, cmd.offset);
900   return result;
901 }
902
903
904 /**
905  * _g_kdbus_NameHasOwner_internal:
906  *
907  */
908 static gboolean
909 g_kdbus_NameHasOwner_internal (GKdbus       *kdbus,
910                                const gchar  *name,
911                                GError      **error)
912 {
913   struct kdbus_cmd_conn_info *cmd;
914   gssize size, len;
915   gint ret;
916
917   if (g_dbus_is_unique_name(name))
918     {
919        size = G_STRUCT_OFFSET (struct kdbus_cmd_conn_info, items);
920        cmd = g_alloca0 (size);
921        cmd->id = g_ascii_strtoull (name+3, NULL, 10);
922     }
923   else
924     {
925        len = strlen(name) + 1;
926        size = G_STRUCT_OFFSET (struct kdbus_cmd_conn_info, items) + KDBUS_ITEM_SIZE(len);
927        cmd = g_alloca0 (size);
928        cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
929        cmd->items[0].type = KDBUS_ITEM_NAME;
930        memcpy (cmd->items[0].str, name, len);
931     }
932   cmd->size = size;
933
934   ret = ioctl(kdbus->priv->fd, KDBUS_CMD_CONN_INFO, cmd);
935   g_kdbus_free_data (kdbus, cmd->offset);
936
937   if (ret < 0)
938     return FALSE;
939   else
940     return TRUE;
941 }
942
943
944 /**
945  * _g_kdbus_GetListQueuedOwners:
946  *
947  */
948 GVariant *
949 _g_kdbus_GetListQueuedOwners (GDBusConnection  *connection,
950                               const gchar      *name,
951                               GError          **error)
952 {
953   GKdbus *kdbus;
954   GVariant *result;
955   GVariantBuilder *builder;
956   GString *unique_name;
957   gint ret;
958
959   struct kdbus_cmd_name_list cmd = {};
960   struct kdbus_name_list *name_list;
961   struct kdbus_cmd_name *kname;
962
963   kdbus = _g_kdbus_connection_get_kdbus (G_KDBUS_CONNECTION (g_dbus_connection_get_stream (connection)));
964   if (kdbus == NULL)
965     {
966       g_set_error_literal (error,
967                            G_DBUS_ERROR,
968                            G_DBUS_ERROR_IO_ERROR,
969                            _("The connection is closed"));
970       return NULL;
971     }
972
973   if (!g_dbus_is_name (name))
974     {
975       g_set_error (error,
976                    G_DBUS_ERROR,
977                    G_DBUS_ERROR_INVALID_ARGS,
978                    "Given bus name \"%s\" is not valid", name);
979       return NULL;
980     }
981
982   if (!g_kdbus_NameHasOwner_internal (kdbus, name, error))
983     {
984       g_set_error (error,
985                    G_DBUS_ERROR,
986                    G_DBUS_ERROR_NAME_HAS_NO_OWNER,
987                    "Could not get owner of name '%s': no such name", name);
988       return NULL;
989     }
990
991   cmd.flags = KDBUS_NAME_LIST_QUEUED;
992   ret = ioctl(kdbus->priv->fd, KDBUS_CMD_NAME_LIST, &cmd);
993   if (ret < 0)
994     {
995       g_set_error (error,
996                    G_DBUS_ERROR,
997                    G_DBUS_ERROR_FAILED,
998                    _("Error listing names"));
999       return NULL;
1000     }
1001
1002   name_list = (struct kdbus_name_list *) ((guint8 *) kdbus->priv->kdbus_buffer + cmd.offset);
1003
1004   unique_name = g_string_new (NULL);
1005   builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
1006   KDBUS_ITEM_FOREACH(kname, name_list, names)
1007     {
1008       struct kdbus_item *item;
1009       const char *item_name = "";
1010
1011       KDBUS_ITEM_FOREACH(item, kname, items)
1012         if (item->type == KDBUS_ITEM_NAME)
1013           item_name = item->str;
1014
1015       if (strcmp(item_name, name))
1016         continue;
1017
1018       g_string_printf (unique_name, ":1.%llu", kname->owner_id);
1019       g_variant_builder_add (builder, "s", item_name);
1020     }
1021
1022   result = g_variant_new ("(as)", builder);
1023   g_variant_builder_unref (builder);
1024   g_string_free (unique_name,TRUE);
1025
1026   g_kdbus_free_data (kdbus, cmd.offset);
1027   return result;
1028 }
1029
1030
1031 /**
1032  * _g_kdbus_NameHasOwner:
1033  *
1034  */
1035 GVariant *
1036 _g_kdbus_NameHasOwner (GDBusConnection  *connection,
1037                        const gchar      *name,
1038                        GError          **error)
1039 {
1040   GKdbus *kdbus;
1041   GVariant *result;
1042
1043   kdbus = _g_kdbus_connection_get_kdbus (G_KDBUS_CONNECTION (g_dbus_connection_get_stream (connection)));
1044   if (kdbus == NULL)
1045     {
1046       g_set_error_literal (error,
1047                            G_DBUS_ERROR,
1048                            G_DBUS_ERROR_IO_ERROR,
1049                            _("The connection is closed"));
1050       return NULL;
1051     }
1052
1053   if (!g_dbus_is_name (name))
1054     {
1055       g_set_error (error,
1056                    G_DBUS_ERROR,
1057                    G_DBUS_ERROR_INVALID_ARGS,
1058                    "Given bus name \"%s\" is not valid", name);
1059       return NULL;
1060     }
1061
1062   if (!g_kdbus_NameHasOwner_internal (kdbus, name, error))
1063     result = g_variant_new ("(b)", FALSE);
1064   else
1065     result = g_variant_new ("(b)", TRUE);
1066
1067   return result;
1068 }
1069
1070
1071 /**
1072  * g_kdbus_GetConnInfo_internal:
1073  *
1074  */
1075 static GVariant *
1076 g_kdbus_GetConnInfo_internal (GDBusConnection  *connection,
1077                               const gchar      *name,
1078                               guint64           flag,
1079                               GError          **error)
1080 {
1081   GKdbus *kdbus;
1082   GVariant *result;
1083
1084   struct kdbus_cmd_conn_info *cmd;
1085   struct kdbus_conn_info *conn_info;
1086   struct kdbus_item *item;
1087   gssize size, len;
1088   gint ret;
1089
1090   result = NULL;
1091   kdbus = _g_kdbus_connection_get_kdbus (G_KDBUS_CONNECTION (g_dbus_connection_get_stream (connection)));
1092   if (kdbus == NULL)
1093     {
1094       g_set_error_literal (error,
1095                            G_DBUS_ERROR,
1096                            G_DBUS_ERROR_IO_ERROR,
1097                            _("The connection is closed"));
1098       return NULL;
1099     }
1100
1101   if (!g_dbus_is_name (name))
1102     {
1103       g_set_error (error,
1104                    G_DBUS_ERROR,
1105                    G_DBUS_ERROR_INVALID_ARGS,
1106                    "Given bus name \"%s\" is not valid", name);
1107       return NULL;
1108     }
1109
1110   if (!g_kdbus_NameHasOwner_internal (kdbus, name, error))
1111     {
1112       g_set_error (error,
1113                    G_DBUS_ERROR,
1114                    G_DBUS_ERROR_NAME_HAS_NO_OWNER,
1115                    "Could not get owner of name '%s': no such name", name);
1116       return NULL;
1117     }
1118
1119   if (g_dbus_is_unique_name(name))
1120     {
1121        size = G_STRUCT_OFFSET (struct kdbus_cmd_conn_info, items);
1122        cmd = g_alloca0 (size);
1123        cmd->id = g_ascii_strtoull (name+3, NULL, 10);
1124     }
1125   else
1126     {
1127        len = strlen(name) + 1;
1128        size = G_STRUCT_OFFSET (struct kdbus_cmd_conn_info, items) + KDBUS_ITEM_SIZE(len);
1129        cmd = g_alloca0 (size);
1130        cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
1131        cmd->items[0].type = KDBUS_ITEM_NAME;
1132        memcpy (cmd->items[0].str, name, len);
1133     }
1134
1135   cmd->flags = KDBUS_ATTACH_NAMES;
1136   cmd->size = size;
1137
1138   ret = ioctl(kdbus->priv->fd, KDBUS_CMD_CONN_INFO, cmd);
1139   if (ret < 0)
1140     {
1141       g_set_error (error,
1142                    G_DBUS_ERROR,
1143                    G_DBUS_ERROR_FAILED,
1144                    _("Could not get connection info"));
1145       return NULL;
1146     }
1147
1148   conn_info = (struct kdbus_conn_info *) ((guint8 *) kdbus->priv->kdbus_buffer + cmd->offset);
1149
1150   /*
1151   if (conn_info->flags & KDBUS_HELLO_ACTIVATOR)
1152     {}
1153   */
1154
1155   if (flag == G_BUS_CREDS_UNIQUE_NAME)
1156     {
1157        GString *unique_name;
1158
1159        unique_name = g_string_new (NULL);
1160        g_string_printf (unique_name, ":1.%llu", (unsigned long long) conn_info->id);
1161        result = g_variant_new ("(s)", unique_name->str);
1162        g_string_free (unique_name,TRUE);
1163        goto exit;
1164     }
1165
1166   KDBUS_ITEM_FOREACH(item, conn_info, items)
1167    {
1168       switch (item->type)
1169         {
1170           case KDBUS_ITEM_CREDS:
1171
1172             if (flag == G_BUS_CREDS_PID)
1173               {
1174                 guint pid = item->creds.pid;
1175                 result = g_variant_new ("(u)", pid);
1176                 goto exit;
1177                }
1178
1179             if (flag == G_BUS_CREDS_UID)
1180               {
1181                 guint uid = item->creds.uid;
1182                 result = g_variant_new ("(u)", uid);
1183                 goto exit;
1184               }
1185
1186           case KDBUS_ITEM_SECLABEL:
1187           case KDBUS_ITEM_PID_COMM:
1188           case KDBUS_ITEM_TID_COMM:
1189           case KDBUS_ITEM_EXE:
1190           case KDBUS_ITEM_CMDLINE:
1191           case KDBUS_ITEM_CGROUP:
1192           case KDBUS_ITEM_CAPS:
1193           case KDBUS_ITEM_NAME:
1194           case KDBUS_ITEM_AUDIT:
1195             break;
1196         }
1197    }
1198
1199 exit:
1200   g_kdbus_free_data (kdbus, cmd->offset);
1201   return result;
1202 }
1203
1204
1205 /**
1206  * _g_kdbus_GetNameOwner:
1207  *
1208  */
1209 GVariant *
1210 _g_kdbus_GetNameOwner (GDBusConnection  *connection,
1211                        const gchar      *name,
1212                        GError          **error)
1213 {
1214   return g_kdbus_GetConnInfo_internal (connection,
1215                                        name,
1216                                        G_BUS_CREDS_UNIQUE_NAME,
1217                                        error);
1218 }
1219
1220
1221 /**
1222  * _g_kdbus_GetConnectionUnixProcessID:
1223  *
1224  */
1225 GVariant *
1226 _g_kdbus_GetConnectionUnixProcessID (GDBusConnection  *connection,
1227                                      const gchar      *name,
1228                                      GError          **error)
1229 {
1230   return g_kdbus_GetConnInfo_internal (connection,
1231                                        name,
1232                                        G_BUS_CREDS_PID,
1233                                        error);
1234 }
1235
1236
1237 /**
1238  * _g_kdbus_GetConnectionUnixUser:
1239  *
1240  */
1241 GVariant *
1242 _g_kdbus_GetConnectionUnixUser (GDBusConnection  *connection,
1243                                 const gchar      *name,
1244                                 GError          **error)
1245 {
1246   return g_kdbus_GetConnInfo_internal (connection,
1247                                        name,
1248                                        G_BUS_CREDS_UID,
1249                                        error);
1250 }