Merge branch 'upstream' into tizen
[platform/upstream/glib.git] / gio / gdbusaddress.c
index 48c7666..8344b8e 100644 (file)
@@ -41,6 +41,7 @@
 #include "gstdio.h"
 
 #ifdef G_OS_UNIX
+#include "gkdbus.h"
 #include <unistd.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -545,8 +546,9 @@ out:
 
 /* ---------------------------------------------------------------------------------------------------- */
 
-static GIOStream *
+static GObject *
 g_dbus_address_try_connect_one (const gchar   *address_entry,
+                                gboolean       kdbus_okay,
                                 gchar        **out_guid,
                                 GCancellable  *cancellable,
                                 GError       **error);
@@ -556,14 +558,15 @@ g_dbus_address_try_connect_one (const gchar   *address_entry,
  * point. That way we can implement a D-Bus transport over X11 without
  * making libgio link to libX11...
  */
-static GIOStream *
+static GObject *
 g_dbus_address_connect (const gchar   *address_entry,
                         const gchar   *transport_name,
+                        gboolean       kdbus_okay,
                         GHashTable    *key_value_pairs,
                         GCancellable  *cancellable,
                         GError       **error)
 {
-  GIOStream *ret;
+  GObject *ret;
   GSocketConnectable *connectable;
   const gchar *nonce_file;
 
@@ -575,6 +578,31 @@ g_dbus_address_connect (const gchar   *address_entry,
     {
     }
 #ifdef G_OS_UNIX
+#ifdef KDBUS
+  else if (kdbus_okay && g_str_equal (transport_name, "kernel"))
+    {
+      GKDBusWorker *worker;
+      const gchar *path;
+
+      path = g_hash_table_lookup (key_value_pairs, "path");
+
+      if (path == NULL)
+        {
+          g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+                       _("Error in address '%s' - the kernel transport requires a path"),
+                       address_entry);
+        }
+      else
+        {
+          worker = _g_kdbus_worker_new (path, error);
+
+          if (worker == NULL)
+            return NULL;
+
+          return G_OBJECT (worker);
+        }
+    }
+#endif
   else if (g_strcmp0 (transport_name, "unix") == 0)
     {
       const gchar *path;
@@ -665,7 +693,7 @@ g_dbus_address_connect (const gchar   *address_entry,
       autolaunch_address = get_session_address_dbus_launch (error);
       if (autolaunch_address != NULL)
         {
-          ret = g_dbus_address_try_connect_one (autolaunch_address, NULL, cancellable, error);
+          ret = g_dbus_address_try_connect_one (autolaunch_address, kdbus_okay, NULL, cancellable, error);
           g_free (autolaunch_address);
           goto out;
         }
@@ -707,7 +735,7 @@ g_dbus_address_connect (const gchar   *address_entry,
       if (connection == NULL)
         goto out;
 
-      ret = G_IO_STREAM (connection);
+      ret = G_OBJECT (connection);
 
       if (nonce_file != NULL)
         {
@@ -763,7 +791,7 @@ g_dbus_address_connect (const gchar   *address_entry,
             }
           fclose (f);
 
-          if (!g_output_stream_write_all (g_io_stream_get_output_stream (ret),
+          if (!g_output_stream_write_all (g_io_stream_get_output_stream (G_IO_STREAM (connection)),
                                           nonce_contents,
                                           16,
                                           NULL,
@@ -783,13 +811,14 @@ g_dbus_address_connect (const gchar   *address_entry,
   return ret;
 }
 
-static GIOStream *
+static GObject *
 g_dbus_address_try_connect_one (const gchar   *address_entry,
+                                gboolean       kdbus_okay,
                                 gchar        **out_guid,
                                 GCancellable  *cancellable,
                                 GError       **error)
 {
-  GIOStream *ret;
+  GObject *ret;
   GHashTable *key_value_pairs;
   gchar *transport_name;
   const gchar *guid;
@@ -806,6 +835,7 @@ g_dbus_address_try_connect_one (const gchar   *address_entry,
 
   ret = g_dbus_address_connect (address_entry,
                                 transport_name,
+                                kdbus_okay,
                                 key_value_pairs,
                                 cancellable,
                                 error);
@@ -969,7 +999,25 @@ g_dbus_address_get_stream_sync (const gchar   *address,
                                 GCancellable  *cancellable,
                                 GError       **error)
 {
-  GIOStream *ret;
+  GObject *result;
+
+  result = g_dbus_address_get_stream_internal (address, FALSE, out_guid, cancellable, error);
+  g_assert (result == NULL || G_IS_IO_STREAM (result));
+
+  if (result)
+    return G_IO_STREAM (result);
+
+  return NULL;
+}
+
+GObject *
+g_dbus_address_get_stream_internal (const gchar   *address,
+                                    gboolean       kdbus_okay,
+                                    gchar        **out_guid,
+                                    GCancellable  *cancellable,
+                                    GError       **error)
+{
+  GObject *ret;
   gchar **addr_array;
   guint n;
   GError *last_error;
@@ -996,6 +1044,7 @@ g_dbus_address_get_stream_sync (const gchar   *address,
 
       this_error = NULL;
       ret = g_dbus_address_try_connect_one (addr,
+                                            kdbus_okay,
                                             out_guid,
                                             cancellable,
                                             &this_error);
@@ -1071,6 +1120,30 @@ out:
 #endif
 }
 
+static gchar *
+get_session_address_kdbus (void)
+{
+#ifdef G_OS_UNIX
+  gchar *ret = NULL;
+  gchar *bus;
+  GStatBuf buf;
+
+  bus = g_strdup_printf ("/sys/fs/kdbus/%d-user/bus", getuid());
+
+  /* if ENOENT, EPERM, etc., quietly don't use it */
+  if (g_stat (bus, &buf) < 0)
+    goto out;
+
+  ret = g_strconcat ("kernel:path=", bus, NULL);
+
+out:
+  g_free (bus);
+  return ret;
+#else
+  return NULL;
+#endif
+}
+
 /* ---------------------------------------------------------------------------------------------------- */
 
 #ifdef G_OS_UNIX
@@ -1299,6 +1372,7 @@ g_dbus_address_get_for_bus_sync (GBusType       bus_type,
   if (G_UNLIKELY (_g_dbus_debug_address ()))
     {
       guint n;
+      gchar *s;
       _g_dbus_debug_print_lock ();
       s = _g_dbus_enum_to_string (G_TYPE_BUS_TYPE, bus_type);
       g_print ("GDBus-debug:Address: In g_dbus_address_get_for_bus_sync() for bus type '%s'\n",
@@ -1337,7 +1411,7 @@ g_dbus_address_get_for_bus_sync (GBusType       bus_type,
 
       if (ret == NULL)
         {
-          ret = g_strdup ("unix:path=/var/run/dbus/system_bus_socket");
+          ret = g_strdup ("kernel:path=/sys/fs/kdbus/0-system/bus;unix:path=/var/run/dbus/system_bus_socket");
         }
       break;
 
@@ -1349,7 +1423,11 @@ g_dbus_address_get_for_bus_sync (GBusType       bus_type,
 
       if (ret == NULL)
         {
-          ret = get_session_address_platform_specific (&local_error);
+          ret = get_session_address_kdbus ();
+          if (ret == NULL)
+            ret = get_session_address_platform_specific (&local_error);
+          if (ret == NULL)
+            goto out;
         }
       break;