Merge branch 'upstream' into tizen 64/265664/3
authorMateusz Majewski <m.majewski2@samsung.com>
Mon, 8 Nov 2021 10:23:16 +0000 (11:23 +0100)
committerMateusz Majewski <m.majewski2@samsung.com>
Mon, 8 Nov 2021 10:23:16 +0000 (11:23 +0100)
Note: glib/gbytes.c contains a particularly nontrivial merge conflict
resolution inside the g_bytes_get_region function.

Change-Id: Ifea638440da0f0094c3c79e51559c9598d7f6a1d

97 files changed:
.gitignore
LICENSE.MIT [new file with mode: 0644]
NEWS
docs/reference/.gitignore [deleted file]
docs/reference/gio/.gitignore [deleted file]
docs/reference/glib/glib-sections.txt
docs/reference/glib/gvariant-text.xml
gio/completion/.gitignore [deleted file]
gio/gapplicationimpl-dbus.c
gio/gdbus-2.0/codegen/.gitignore [deleted file]
gio/gdbusactiongroup.h
gio/gdbusaddress.c
gio/gdbusaddress.h
gio/gdbusauthobserver.h
gio/gdbusconnection.c [changed mode: 0644->0755]
gio/gdbusconnection.h
gio/gdbuserror.h
gio/gdbusinterface.h
gio/gdbusinterfaceskeleton.h
gio/gdbusintrospection.h
gio/gdbusmenumodel.h
gio/gdbusmessage.c
gio/gdbusmessage.h
gio/gdbusmethodinvocation.c
gio/gdbusmethodinvocation.h
gio/gdbusnameowning.h
gio/gdbusnamewatching.c [changed mode: 0644->0755]
gio/gdbusnamewatching.h
gio/gdbusobject.h
gio/gdbusobjectmanager.h
gio/gdbusobjectmanagerclient.c
gio/gdbusobjectmanagerclient.h
gio/gdbusobjectmanagerserver.h
gio/gdbusprivate.c
gio/gdbusprivate.h
gio/gdbusproxy.c
gio/gdbusproxy.h
gio/gdbusserver.h
gio/gdbusutils.c
gio/gdbusutils.h
gio/gioenums.h
gio/gkdbus.c [new file with mode: 0755]
gio/gkdbus.h [new file with mode: 0644]
gio/gkdbusfakedaemon.c [new file with mode: 0644]
gio/gkdbusfakedaemon.h [new file with mode: 0644]
gio/gunixfdlist.h
gio/meson.build
gio/tests/.gitignore [deleted file]
gio/tizen_header_glib.h [new file with mode: 0644]
gio/xdgmime/.gitignore [deleted file]
glib/gbytes.c
glib/gbytes.h
glib/glib-autocleanups.h
glib/glib-linux.h [new file with mode: 0644]
glib/glib-private.c
glib/glib-private.h
glib/glib-unix.c
glib/glib-unix.h
glib/gmessages.h
glib/gtestutils.c
glib/gtestutils.h
glib/gutils.c
glib/gvariant-core.c
glib/gvariant-core.h
glib/gvariant-parser.c
glib/gvariant-serialiser.c
glib/gvariant-serialiser.h
glib/gvariant-vectors.c [new file with mode: 0644]
glib/gvariant-vectors.h [new file with mode: 0644]
glib/gvariant.c
glib/gvariant.h
glib/gvarianttype.c
glib/gvarianttype.h
glib/gvarianttypeinfo.c
glib/libcharset/.gitignore [deleted file]
glib/meson.build
glib/tests/.gitignore [deleted file]
glib/tests/bytes.c
glib/tests/gvariant.c
gobject/tests/.gitignore [deleted file]
m4macros/glibtests.m4
meson_options.txt
packaging/README.Gsettings-overrides [new file with mode: 0644]
packaging/baselibs.conf [new file with mode: 0644]
packaging/coverage.txt [new file with mode: 0644]
packaging/glib2-rpmlintrc [new file with mode: 0644]
packaging/glib2-upstream-gnome_defaults.conf [new file with mode: 0644]
packaging/glib2.changes [new file with mode: 0644]
packaging/glib2.csh [new file with mode: 0644]
packaging/glib2.manifest [new file with mode: 0644]
packaging/glib2.sh [new file with mode: 0644]
packaging/glib2.spec [new file with mode: 0644]
packaging/gtk-doc.m4 [new file with mode: 0644]
packaging/macros.glib2 [new file with mode: 0644]
packaging/q_quark_block_size.patch [new file with mode: 0644]
packaging/test-runner.c [new file with mode: 0644]
tests/gobject/.gitignore [deleted file]

index 6b1ad6a..9306ae6 100644 (file)
@@ -1,30 +1,3 @@
-# for all subdirectories
-TAGS
+cscope.files
+cscope.out
 tags
-.libs
-.deps
-*.o
-*.lo
-*.la
-*.pc
-.*.swp
-.sw?
-*.rc
-*.gcno
-*.gcda
-*.gcov
-*.sourcefiles
-*.stp
-*.exe
-*.def
-*.test
-*.log
-*.trs
-
-INSTALL
-/glib-lcov.info
-/glib-lcov/
-
-# Meson
-/meson-build/
-/subprojects/*/
diff --git a/LICENSE.MIT b/LICENSE.MIT
new file mode 100644 (file)
index 0000000..c9998ac
--- /dev/null
@@ -0,0 +1,16 @@
+ MIT License
+
+ Copyright (c) 2016 Samsung Electronics Co., Ltd
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+
diff --git a/NEWS b/NEWS
index 2a50c5a..c9e45a4 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4715,6 +4715,43 @@ Overview of changes in GLib 2.45.1
  Russian
  Turkish
 
+Overview of changes in GLib 2.44.1
+==================================
+
+* Don't redefine typedefs to avoid build problems on OpenBSD
+
+* Improve the default application algorithm
+
+* Bump the number of children a GType can have
+
+* Various testsuite improvements
+
+* Translation updates:
+ Czech
+ Icelandic
+ Russian
+
+
+Overview of changes in GLib 2.44.0
+===================================
+
+With the exception of translation and documentation, there have been no
+changes since the prerelease.
+
+Bugs fixed:
+ 730188 gsocket: Document FD ownership with g_socket_new_from_fd()
+
+Translations updated:
+ Basque language
+ Brazilian Portuguese
+ Chinese (Taiwan)
+ Danish
+ Galician s
+ Hebrew
+ Indonesian
+ Norwegian bokmål
+ Turkish
+
 
 Overview of changes in GLib 2.43.92
 ===================================
diff --git a/docs/reference/.gitignore b/docs/reference/.gitignore
deleted file mode 100644 (file)
index f9e370e..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-*-decl-list.txt
-*-decl.txt
-*-unused.txt
-*-undocumented.txt
-*-undeclared.txt
-*.args
-*.hierarchy
-*.interfaces
-*.prerequisites
-*.signals
-*.stamp
-html
-xml
-*.bak
-version.xml
-*.1
diff --git a/docs/reference/gio/.gitignore b/docs/reference/gio/.gitignore
deleted file mode 100644 (file)
index e9e522e..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-*.1
-gio-overrides.txt
-tmpl
index efb261b..74b5e87 100644 (file)
@@ -1403,6 +1403,8 @@ g_set_printerr_handler
 <SUBSECTION>
 g_return_if_fail
 g_return_val_if_fail
+g_return_if_fail_se
+g_return_val_if_fail_se
 g_return_if_reached
 g_return_val_if_reached
 g_warn_if_fail
@@ -2571,6 +2573,7 @@ GUnixFDSourceFunc
 g_unix_fd_add
 g_unix_fd_add_full
 g_unix_fd_source_new
+g_unix_fd_ensure_zero_copy_safe
 
 <SUBSECTION>
 g_unix_get_passwd_entry
@@ -3033,12 +3036,14 @@ g_byte_array_free_to_bytes
 GBytes
 g_bytes_new
 g_bytes_new_take
+g_bytes_new_take_zero_copy_fd
 g_bytes_new_static
 g_bytes_new_with_free_func
 g_bytes_new_from_bytes
 g_bytes_get_data
 g_bytes_get_region
 g_bytes_get_size
+g_bytes_get_zero_copy_fd
 g_bytes_hash
 g_bytes_equal
 g_bytes_compare
@@ -3614,6 +3619,7 @@ g_test_rand_double
 g_test_rand_double_range
 
 g_assert
+g_assert_se
 g_assert_not_reached
 
 g_assert_cmpstr
index 55d476e..51e9567 100644 (file)
         <literal>handle</literal>,
         <literal>int64</literal>,
         <literal>uint64</literal>,
+        <literal>float</literal>,
         <literal>double</literal>,
         <literal>string</literal>,
         <literal>objectpath</literal>,
     Type keywords can be seen as more verbose (and more legible) versions of a common subset of the type codes.
     The type keywords <literal>boolean</literal>, <literal>byte</literal>, <literal>int16</literal>,
     <literal>uint16</literal>, <literal>int32</literal>, <literal>uint32</literal>, <literal>handle</literal>,
-    <literal>int64</literal>, <literal>uint64</literal>, <literal>double</literal>, <literal>string</literal>,
-    <literal>objectpath</literal> and literal <literal>signature</literal> are each exactly equivalent to their
-    corresponding type code.
+    <literal>int64</literal>, <literal>uint64</literal>, <literal>float</literal>, <literal>double</literal>,
+    <literal>string</literal>, <literal>objectpath</literal> and literal <literal>signature</literal> are each
+    exactly equivalent to their corresponding type code.
    </para>
    <para>
     Type codes are an <literal>@</literal> ("at" sign) followed by a definite GVariant type string.  Some
diff --git a/gio/completion/.gitignore b/gio/completion/.gitignore
deleted file mode 100644 (file)
index 6930af9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-!gio
index 5604b92..9a1206a 100644 (file)
@@ -368,10 +368,9 @@ g_application_impl_attempt_primary (GApplicationImpl  *impl,
     { 0 }
   };
   GApplicationClass *app_class = G_APPLICATION_GET_CLASS (impl->app);
+  GBusRequestNameReplyFlags rval;
   GBusNameOwnerFlags name_owner_flags;
   GApplicationFlags app_flags;
-  GVariant *reply;
-  guint32 rval;
   GError *local_error = NULL;
 
   if (org_gtk_Application == NULL)
@@ -477,23 +476,13 @@ g_application_impl_attempt_primary (GApplicationImpl  *impl,
   if (app_flags & G_APPLICATION_REPLACE)
     name_owner_flags |= G_BUS_NAME_OWNER_FLAGS_REPLACE;
 
-  reply = g_dbus_connection_call_sync (impl->session_bus,
-                                       "org.freedesktop.DBus",
-                                       "/org/freedesktop/DBus",
-                                       "org.freedesktop.DBus",
-                                       "RequestName",
-                                       g_variant_new ("(su)", impl->bus_name, name_owner_flags),
-                                       G_VARIANT_TYPE ("(u)"),
-                                       0, -1, cancellable, error);
+  rval = g_dbus_request_name (impl->session_bus, impl->bus_name, name_owner_flags, error);
 
-  if (reply == NULL)
+  if (rval == G_BUS_REQUEST_NAME_FLAGS_ERROR)
     return FALSE;
 
-  g_variant_get (reply, "(u)", &rval);
-  g_variant_unref (reply);
-
   /* DBUS_REQUEST_NAME_REPLY_EXISTS: 3 */
-  impl->primary = (rval != 3);
+  impl->primary = (rval != G_BUS_REQUEST_NAME_FLAGS_EXISTS);
 
   if (!impl->primary && impl->name_lost_signal)
     {
@@ -551,10 +540,7 @@ g_application_impl_stop_primary (GApplicationImpl *impl)
 
   if (impl->primary && impl->bus_name)
     {
-      g_dbus_connection_call (impl->session_bus, "org.freedesktop.DBus",
-                              "/org/freedesktop/DBus", "org.freedesktop.DBus",
-                              "ReleaseName", g_variant_new ("(s)", impl->bus_name),
-                              NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
+      g_dbus_release_name (impl->session_bus, impl->bus_name, NULL);
       impl->primary = FALSE;
     }
 }
@@ -924,13 +910,13 @@ g_dbus_command_line_get_stdin (GApplicationCommandLine *cmdline)
 
   if (fd_list && g_unix_fd_list_get_length (fd_list))
     {
-      gint *fds, n_fds, i;
+      const gint *fds;
 
-      fds = g_unix_fd_list_steal_fds (fd_list, &n_fds);
-      result = g_unix_input_stream_new (fds[0], TRUE);
-      for (i = 1; i < n_fds; i++)
-        (void) g_close (fds[i], NULL);
-      g_free (fds);
+      fds = g_unix_fd_list_peek_fds (fd_list, NULL);
+      result = g_unix_input_stream_new (fds[0], FALSE);
+      g_object_weak_ref (G_OBJECT (result),
+                         (GWeakNotify) g_object_unref,
+                         g_object_ref (fd_list));
     }
 
   return result;
diff --git a/gio/gdbus-2.0/codegen/.gitignore b/gio/gdbus-2.0/codegen/.gitignore
deleted file mode 100644 (file)
index 0015c09..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-*.pyc
-config.py
-gdbus-codegen
index 93e6a2c..c1f886e 100644 (file)
@@ -26,6 +26,7 @@
 #endif
 
 #include "giotypes.h"
+#include <gio/tizen_header_glib.h>  /* for TIZEN_PUBLIC_DEPRECATED_API */
 
 G_BEGIN_DECLS
 
@@ -42,12 +43,12 @@ G_BEGIN_DECLS
                                                              G_TYPE_DBUS_ACTION_GROUP, GDBusActionGroupClass))
 
 GLIB_AVAILABLE_IN_ALL
-GType                   g_dbus_action_group_get_type                  (void) G_GNUC_CONST;
+GType                   g_dbus_action_group_get_type                  (void) G_GNUC_CONST TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_2_32
 GDBusActionGroup *      g_dbus_action_group_get                       (GDBusConnection        *connection,
                                                                        const gchar            *bus_name,
-                                                                       const gchar            *object_path);
+                                                                       const gchar            *object_path) TIZEN_PUBLIC_DEPRECATED_API;
 
 G_END_DECLS
 
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;
 
index 43915bb..4686a95 100644 (file)
 #endif
 
 #include <gio/giotypes.h>
+#include <gio/tizen_header_glib.h>  /* for TIZEN_PUBLIC_DEPRECATED_API */
 
 G_BEGIN_DECLS
 
 GLIB_AVAILABLE_IN_2_36
-gchar *g_dbus_address_escape_value (const gchar *string);
+gchar *g_dbus_address_escape_value (const gchar *string) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
-gboolean g_dbus_is_address (const gchar *string);
+gboolean g_dbus_is_address (const gchar *string) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 gboolean g_dbus_is_supported_address (const gchar  *string,
-                                      GError      **error);
+                                      GError      **error) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
 void                 g_dbus_address_get_stream        (const gchar          *address,
                                                        GCancellable         *cancellable,
                                                        GAsyncReadyCallback   callback,
-                                                       gpointer              user_data);
+                                                       gpointer              user_data) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
 GIOStream           *g_dbus_address_get_stream_finish (GAsyncResult         *res,
                                                        gchar               **out_guid,
-                                                       GError              **error);
+                                                       GError              **error) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
 GIOStream           *g_dbus_address_get_stream_sync   (const gchar          *address,
                                                        gchar               **out_guid,
                                                        GCancellable         *cancellable,
-                                                       GError              **error);
+                                                       GError              **error) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
 gchar               *g_dbus_address_get_for_bus_sync  (GBusType              bus_type,
                                                        GCancellable  *cancellable,
-                                                       GError              **error);
+                                                       GError              **error) TIZEN_PUBLIC_DEPRECATED_API;
 
 G_END_DECLS
 
index 8fe7b32..62f28d9 100644 (file)
@@ -26,6 +26,7 @@
 #endif
 
 #include <gio/giotypes.h>
+#include <gio/tizen_header_glib.h>  /* for TIZEN_PUBLIC_DEPRECATED_API */
 
 G_BEGIN_DECLS
 
@@ -34,17 +35,17 @@ G_BEGIN_DECLS
 #define G_IS_DBUS_AUTH_OBSERVER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DBUS_AUTH_OBSERVER))
 
 GLIB_AVAILABLE_IN_ALL
-GType              g_dbus_auth_observer_get_type                     (void) G_GNUC_CONST;
+GType              g_dbus_auth_observer_get_type                     (void) G_GNUC_CONST TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusAuthObserver *g_dbus_auth_observer_new                          (void);
+GDBusAuthObserver *g_dbus_auth_observer_new                          (void) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 gboolean           g_dbus_auth_observer_authorize_authenticated_peer (GDBusAuthObserver  *observer,
                                                                       GIOStream          *stream,
-                                                                      GCredentials       *credentials);
+                                                                      GCredentials       *credentials) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_2_34
 gboolean           g_dbus_auth_observer_allow_mechanism (GDBusAuthObserver  *observer,
-                                                         const gchar        *mechanism);
+                                                         const gchar        *mechanism) TIZEN_PUBLIC_DEPRECATED_API;
 
 G_END_DECLS
 
old mode 100644 (file)
new mode 100755 (executable)
index d730111..339a198
 #include "gmarshal-internal.h"
 
 #ifdef G_OS_UNIX
+#ifdef KDBUS
+#include "gkdbus.h"
+#endif
 #include "gunixconnection.h"
 #include "gunixfdmessage.h"
 #endif
@@ -379,6 +382,12 @@ struct _GDBusConnection
    */
   GDBusWorker *worker;
 
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  GKDBusWorker *kdbus_worker;
+#endif
+#endif
+
   /* If connected to a message bus, this contains the unique name assigned to
    * us by the bus (e.g. ":1.42").
    * Read-only after initable_init(), so it may be read if you either
@@ -616,6 +625,7 @@ g_dbus_connection_dispose (GObject *object)
 
   G_LOCK (message_bus_lock);
   CONNECTION_LOCK (connection);
+
   if (connection->worker != NULL)
     {
       _g_dbus_worker_stop (connection->worker);
@@ -623,6 +633,17 @@ g_dbus_connection_dispose (GObject *object)
       if (alive_connections != NULL)
         g_warn_if_fail (g_hash_table_remove (alive_connections, connection));
     }
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  else if (connection->kdbus_worker != NULL)
+    {
+      _g_kdbus_worker_stop (connection->kdbus_worker);
+      connection->kdbus_worker = NULL;
+      if (alive_connections != NULL)
+        g_warn_if_fail (g_hash_table_remove (alive_connections, connection));
+    }
+#endif
+#endif
   else
     {
       if (alive_connections != NULL)
@@ -1109,6 +1130,19 @@ g_dbus_connection_init (GDBusConnection *connection)
   connection->filters = g_ptr_array_new ();
 }
 
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+gboolean
+_g_dbus_connection_is_kdbus (GDBusConnection *connection)
+{
+  if (connection->kdbus_worker)
+    return TRUE;
+  else
+    return FALSE;
+}
+#endif
+#endif
+
 /**
  * g_dbus_connection_get_stream:
  * @connection: a #GDBusConnection
@@ -1155,8 +1189,16 @@ g_dbus_connection_start_message_processing (GDBusConnection *connection)
   if (!check_initialized (connection))
     return;
 
-  g_assert (connection->worker != NULL);
-  _g_dbus_worker_unfreeze (connection->worker);
+  if (connection->worker)
+    _g_dbus_worker_unfreeze (connection->worker);
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  else if (connection->kdbus_worker)
+    _g_kdbus_worker_unfreeze (connection->kdbus_worker);
+#endif
+#endif
+  else
+    g_assert_not_reached ();
 }
 
 /**
@@ -1347,11 +1389,22 @@ g_dbus_connection_flush_sync (GDBusConnection  *connection,
   if (!check_unclosed (connection, 0, error))
     goto out;
 
-  g_assert (connection->worker != NULL);
-
-  ret = _g_dbus_worker_flush_sync (connection->worker,
-                                   cancellable,
-                                   error);
+  if (connection->worker != NULL)
+    {
+      ret = _g_dbus_worker_flush_sync (connection->worker,
+                                       cancellable,
+                                       error);
+    }
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  else if (connection->kdbus_worker != NULL)
+    {
+      ret = _g_kdbus_worker_flush_sync (connection->kdbus_worker);
+    }
+#endif
+#endif
+  else
+    g_assert_not_reached();
 
  out:
   return ret;
@@ -1451,7 +1504,7 @@ schedule_closed_unlocked (GDBusConnection *connection,
  * of the thread that @connection was constructed in.
  *
  * This is an asynchronous method. When the operation is finished,
- * @callback will be invoked in the 
+ * @callback will be invoked in the
  * [thread-default main context][g-main-context-push-thread-default]
  * of the thread you are calling this method from. You can
  * then call g_dbus_connection_close_finish() to get the result of the
@@ -1470,108 +1523,763 @@ g_dbus_connection_close (GDBusConnection     *connection,
 
   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
 
-  /* do not use g_return_val_if_fail(), we want the memory barrier */
-  if (!check_initialized (connection))
-    return;
+  /* do not use g_return_val_if_fail(), we want the memory barrier */
+  if (!check_initialized (connection))
+    return;
+
+  task = g_task_new (connection, cancellable, callback, user_data);
+  g_task_set_source_tag (task, g_dbus_connection_close);
+  if (connection->worker)
+    {
+      _g_dbus_worker_close (connection->worker, task);
+    }
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  else if (connection->kdbus_worker)
+    {
+      _g_kdbus_worker_close (connection->kdbus_worker, task);
+    }
+#endif
+#endif
+  else
+    g_assert_not_reached();
+  g_object_unref (task);
+}
+
+/**
+ * g_dbus_connection_close_finish:
+ * @connection: a #GDBusConnection
+ * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed
+ *     to g_dbus_connection_close()
+ * @error: return location for error or %NULL
+ *
+ * Finishes an operation started with g_dbus_connection_close().
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE if @error is set
+ *
+ * Since: 2.26
+ */
+gboolean
+g_dbus_connection_close_finish (GDBusConnection  *connection,
+                                GAsyncResult     *res,
+                                GError          **error)
+{
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
+  g_return_val_if_fail (g_task_is_valid (res, connection), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+typedef struct {
+    GMainLoop *loop;
+    GAsyncResult *result;
+} SyncCloseData;
+
+/* Can be called by any thread, without the connection lock */
+static void
+sync_close_cb (GObject *source_object,
+               GAsyncResult *res,
+               gpointer user_data)
+{
+  SyncCloseData *data = user_data;
+
+  data->result = g_object_ref (res);
+  g_main_loop_quit (data->loop);
+}
+
+/**
+ * g_dbus_connection_close_sync:
+ * @connection: a #GDBusConnection
+ * @cancellable: (nullable): a #GCancellable or %NULL
+ * @error: return location for error or %NULL
+ *
+ * Synchronously closes @connection. The calling thread is blocked
+ * until this is done. See g_dbus_connection_close() for the
+ * asynchronous version of this method and more details about what it
+ * does.
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE if @error is set
+ *
+ * Since: 2.26
+ */
+gboolean
+g_dbus_connection_close_sync (GDBusConnection  *connection,
+                              GCancellable     *cancellable,
+                              GError          **error)
+{
+  gboolean ret;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  ret = FALSE;
+
+  if (check_unclosed (connection, 0, error))
+    {
+      GMainContext *context;
+      SyncCloseData data;
+
+      context = g_main_context_new ();
+      g_main_context_push_thread_default (context);
+      data.loop = g_main_loop_new (context, TRUE);
+      data.result = NULL;
+
+      g_dbus_connection_close (connection, cancellable, sync_close_cb, &data);
+      g_main_loop_run (data.loop);
+      ret = g_dbus_connection_close_finish (connection, data.result, error);
+
+      g_object_unref (data.result);
+      g_main_loop_unref (data.loop);
+      g_main_context_pop_thread_default (context);
+      g_main_context_unref (context);
+    }
+
+  return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
+ * g_dbus_request_name:
+ * @connection: a #GDBusConnection
+ * @name: well-known bus name (name to request)
+ * @flags: a set of flags from the GBusNameOwnerFlags enumeration
+ * @error: return location for error or %NULL
+ *
+ * Synchronously acquires name on the bus and returns status code
+ * from the #GBusRequestNameReplyFlags enumeration.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: status code or %G_BUS_REQUEST_NAME_FLAGS_ERROR
+ *     if @error is set.
+ *
+ * Since: 2.44
+ */
+GBusRequestNameReplyFlags
+g_dbus_request_name (GDBusConnection     *connection,
+                     const gchar         *name,
+                     GBusNameOwnerFlags   flags,
+                     GError             **error)
+{
+  GVariant *result;
+  guint32 request_name_reply;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), G_BUS_RELEASE_NAME_FLAGS_ERROR);
+  g_return_val_if_fail (g_dbus_is_name (name) && !g_dbus_is_unique_name (name), G_BUS_RELEASE_NAME_FLAGS_ERROR);
+  g_return_val_if_fail (error == NULL || *error == NULL, G_BUS_RELEASE_NAME_FLAGS_ERROR);
+
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  if (connection->kdbus_worker)
+    return _g_kdbus_RequestName (connection->kdbus_worker, name, flags, error);
+#endif
+#endif
+
+  result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/org/freedesktop/DBus",
+                                        "org.freedesktop.DBus", "RequestName",
+                                        g_variant_new ("(su)", name, flags), G_VARIANT_TYPE ("(u)"),
+                                        G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+  if (result != NULL)
+    {
+      g_variant_get (result, "(u)", &request_name_reply);
+      g_variant_unref (result);
+    }
+  else
+    request_name_reply = G_BUS_REQUEST_NAME_FLAGS_ERROR;
+
+  return (GBusRequestNameReplyFlags) request_name_reply;
+}
+
+/**
+ * g_dbus_release_name:
+ * @connection: a #GDBusConnection
+ * @name: well-known bus name (name to release)
+ * @error: return location for error or %NULL
+ *
+ * Synchronously releases name on the bus and returns status code
+ * from the #GBusReleaseNameReplyFlags enumeration.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: status code or %G_BUS_RELEASE_NAME_FLAGS_ERROR
+ *     if @error is set.
+ *
+ * Since: 2.44
+ */
+GBusReleaseNameReplyFlags
+g_dbus_release_name (GDBusConnection  *connection,
+                     const gchar      *name,
+                     GError          **error)
+{
+  GVariant *result;
+  guint32 release_name_reply;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), G_BUS_RELEASE_NAME_FLAGS_ERROR);
+  g_return_val_if_fail (g_dbus_is_name (name) && !g_dbus_is_unique_name (name), G_BUS_RELEASE_NAME_FLAGS_ERROR);
+  g_return_val_if_fail (error == NULL || *error == NULL, G_BUS_RELEASE_NAME_FLAGS_ERROR);
+
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  if (connection->kdbus_worker)
+    return _g_kdbus_ReleaseName (connection->kdbus_worker, name, error);
+#endif
+#endif
+
+  result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/org/freedesktop/DBus",
+                                        "org.freedesktop.DBus", "ReleaseName",
+                                        g_variant_new ("(s)", name), G_VARIANT_TYPE ("(u)"),
+                                        G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+  if (result != NULL)
+    {
+      g_variant_get (result, "(u)", &release_name_reply);
+      g_variant_unref (result);
+    }
+  else
+    release_name_reply = G_BUS_RELEASE_NAME_FLAGS_ERROR;
+
+  return (GBusReleaseNameReplyFlags) release_name_reply;
+}
+
+/**
+ * g_dbus_add_match:
+ * @connection: a #GDBusConnection
+ * @match_rule: match rule to add to the @connection
+ * @error: return location for error or %NULL
+ *
+ * Synchronously adds a match rule to match messages.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE
+ *     if @error is set.
+ *
+ * Since: 2.44
+ */
+gboolean
+g_dbus_add_match (GDBusConnection  *connection,
+                  const gchar      *match_rule,
+                  GError          **error)
+{
+  GVariant *result;
+  gboolean ret;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  result = NULL;
+  ret = FALSE;
+
+  if (match_rule[0] == '-')
+    return ret;
+
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  if (connection->kdbus_worker)
+    return _g_kdbus_AddMatch (connection->kdbus_worker, match_rule, error);
+#endif
+#endif
+
+  result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/org/freedesktop/DBus",
+                                        "org.freedesktop.DBus", "AddMatch",
+                                        g_variant_new ("(s)", match_rule), NULL,
+                                        G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+  if (result != NULL)
+    {
+      ret = TRUE;
+      g_variant_unref (result);
+    }
+
+  return ret;
+}
+
+/**
+ * g_dbus_remove_match:
+ * @connection: a #GDBusConnection
+ * @match_rule: match rule to remove from the @connection
+ * @error: return location for error or %NULL
+ *
+ * Synchronously removes the first rule that matches.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE
+ *     if @error is set.
+ *
+ * Since: 2.44
+ */
+gboolean
+g_dbus_remove_match (GDBusConnection  *connection,
+                     const gchar      *match_rule,
+                     GError          **error)
+{
+  GVariant *result;
+  gboolean ret;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  result = NULL;
+  ret = FALSE;
+
+  if (match_rule[0] == '-')
+    return ret;
+
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  if (connection->kdbus_worker)
+    return _g_kdbus_RemoveMatch (connection->kdbus_worker, match_rule, error);
+#endif
+#endif
+
+  result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/org/freedesktop/DBus",
+                                        "org.freedesktop.DBus", "RemoveMatch",
+                                        g_variant_new ("(s)", match_rule), NULL,
+                                        G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+  if (result != NULL)
+    {
+      ret = TRUE;
+      g_variant_unref (result);
+    }
+
+  return ret;
+}
+
+/**
+ * g_dbus_get_bus_id:
+ * @connection: a #GDBusConnection
+ * @error: return location for error or %NULL
+ *
+ * Synchronously returns the unique ID of the bus.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: the unique ID of the bus or %NULL if @error is set.
+ *     Free with g_free().
+ *
+ * Since: 2.44
+ */
+gchar *
+g_dbus_get_bus_id (GDBusConnection  *connection,
+                   GError          **error)
+{
+  GVariant *result;
+  gchar *bus_id;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
+  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+  result = NULL;
+  bus_id = NULL;
+
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  if (connection->kdbus_worker)
+    return _g_kdbus_GetBusId (connection->kdbus_worker, error);
+#endif
+#endif
+
+  result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/",
+                                        "org.freedesktop.DBus", "GetId",
+                                        NULL, G_VARIANT_TYPE ("(s)"),
+                                        G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+  if (result != NULL)
+    {
+      g_variant_get (result, "(s)", &bus_id);
+      g_variant_unref (result);
+    }
+
+  return bus_id;
+}
+
+typedef enum
+{
+  LIST_NAMES,
+  LIST_ACTIVATABLE_NAMES,
+  LIST_QUEUED_OWNERS
+} GDBusListNameType;
+
+static gchar **
+_g_dbus_get_list_internal (GDBusConnection    *connection,
+                           const gchar        *name,
+                           GDBusListNameType   list_name_type,
+                           GError            **error)
+{
+  gchar **strv;
+  GVariant *result;
+  GVariantIter *iter;
+  gchar *str;
+  gsize n, i;
+
+  result = NULL;
+  strv = NULL;
+
+  if (list_name_type == LIST_QUEUED_OWNERS)
+    {
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+      if (connection->kdbus_worker)
+        return _g_kdbus_GetListQueuedOwners (connection->kdbus_worker, name, error);
+#endif
+#endif
+
+      result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/",
+                                            "org.freedesktop.DBus", "ListQueuedOwners",
+                                            g_variant_new ("(s)", name), G_VARIANT_TYPE ("(as)"),
+                                            G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+    }
+  else
+    {
+      gchar *method_name;
+
+      if (list_name_type == LIST_NAMES)
+        method_name = "ListNames";
+      else
+        method_name = "ListActivatableNames";
+
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+      if (connection->kdbus_worker)
+        return _g_kdbus_GetListNames (connection->kdbus_worker, list_name_type, error);
+#endif
+#endif
+
+      result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/",
+                                            "org.freedesktop.DBus", method_name,
+                                            NULL, G_VARIANT_TYPE ("(as)"),
+                                            G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+    }
+
+  if (result != NULL)
+    {
+      g_variant_get (result, "(as)", &iter);
+      n = g_variant_iter_n_children (iter);
+      strv = g_new (gchar *, n + 1);
+
+      i = 0;
+      while (g_variant_iter_loop (iter, "s", &str))
+        {
+          strv[i] = g_strdup (str);
+          i++;
+        }
+      strv[i] = NULL;
+
+      g_variant_iter_free (iter);
+      g_variant_unref (result);
+    }
+
+  return strv;
+}
+
+/**
+ * g_dbus_get_list_names:
+ * @connection: a #GDBusConnection
+ * @error: return location for error or %NULL
+ *
+ * Synchronously returns a list of all currently-owned names on the bus.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: a list of all currently-owned names on the bus or %NULL if
+ *     @error is set. Free with g_strfreev().
+ *
+ * Since: 2.44
+ */
+gchar **
+g_dbus_get_list_names (GDBusConnection  *connection,
+                       GError          **error)
+{
+  gchar **strv;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
+  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+  strv = _g_dbus_get_list_internal (connection, NULL, LIST_NAMES, error);
+
+  return strv;
+}
+
+/**
+ * g_dbus_get_list_activatable_names:
+ * @connection: a #GDBusConnection
+ * @error: return location for error or %NULL
+ *
+ * Synchronously returns a list of all names that can be activated on the bus.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: a list of all names that can be activated on the bus or %NULL if
+ *     @error is set. Free with g_strfreev().
+ *
+ * Since: 2.44
+ */
+gchar **
+g_dbus_get_list_activatable_names (GDBusConnection  *connection,
+                                   GError          **error)
+{
+  gchar **strv;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
+  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+  strv = _g_dbus_get_list_internal (connection, NULL, LIST_ACTIVATABLE_NAMES, error);
+
+  return strv;
+}
+
+/**
+ * g_dbus_get_list_queued_names:
+ * @connection: a #GDBusConnection
+ * @name: a unique or well-known bus name
+ * @error: return location for error or %NULL
+ *
+ * Synchronously returns the unique bus names of connections currently queued
+ * for the @name.
+ *
+ * If @name contains a value not compatible with the D-Bus syntax and naming
+ * conventions for bus names, the operation returns %NULL and @error is set.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: the unique bus names of connections currently queued for the @name
+ *     or %NULL if @error is set. Free with g_strfreev().
+ *
+ * Since: 2.44
+ */
+gchar **
+g_dbus_get_list_queued_owners (GDBusConnection  *connection,
+                               const gchar      *name,
+                               GError          **error)
+{
+  gchar **strv;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
+  g_return_val_if_fail (name == NULL || g_dbus_is_name (name), NULL);
+  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+  strv = _g_dbus_get_list_internal (connection, name, LIST_QUEUED_OWNERS, error);
+
+  return strv;
+}
+
+/**
+ * g_dbus_get_name_owner:
+ * @connection: a #GDBusConnection
+ * @name: well-known bus name to get the owner of
+ * @error: return location for error or %NULL
+ *
+ * Synchronously returns the unique connection name of the primary owner of
+ * the name given. If the requested name doesn't have an owner, an @error is
+ * returned.
+ *
+ * If @name contains a value not compatible with the D-Bus syntax and naming
+ * conventions for bus names, the operation returns %NULL and @error is set.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: the unique connection name of the primary owner of the
+ *     name given. If the requested name doesn't have an owner, function
+ *     returns %NULL and @error is set. Free with g_free().
+ *
+ * Since: 2.44
+ */
+gchar *
+g_dbus_get_name_owner (GDBusConnection  *connection,
+                       const gchar      *name,
+                       GError          **error)
+{
+  GVariant *result;
+  gchar *name_owner;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
+  g_return_val_if_fail (name == NULL || g_dbus_is_name (name), NULL);
+  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+  name_owner = NULL;
+  result = NULL;
+
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  if (connection->kdbus_worker)
+    return _g_kdbus_GetNameOwner (connection->kdbus_worker, name, error);
+#endif
+#endif
+
+  result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/",
+                                        "org.freedesktop.DBus", "GetNameOwner",
+                                        g_variant_new ("(s)", name), G_VARIANT_TYPE ("(s)"),
+                                        G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+  if (result != NULL)
+    {
+      g_variant_get (result, "(s)", &name_owner);
+      g_variant_unref (result);
+    }
+  else
+    name_owner = NULL;
+
+  return name_owner;
+}
+
+/**
+ * g_dbus_get_connection_pid:
+ * @connection: a #GDBusConnection
+ * @name: a unique or well-known bus name of the connection to query
+ * @error: return location for error or %NULL
+ *
+ * Synchronously returns the Unix process ID of the process connected to the
+ * bus. If unable to determine it, an @error is returned.
+ *
+ * If @name contains a value not compatible with the D-Bus syntax and naming
+ * conventions for bus names, the operation returns -1 and @error is set.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: the Unix process ID of the process connected to the bus or -1
+ *     if @error is set.
+ *
+ * Since: 2.44
+ */
+pid_t
+g_dbus_get_connection_pid (GDBusConnection  *connection,
+                           const gchar      *name,
+                           GError          **error)
+{
+  GVariant *result;
+  pid_t pid;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), -1);
+  g_return_val_if_fail (name == NULL || g_dbus_is_name (name), -1);
+  g_return_val_if_fail (error == NULL || *error == NULL, -1);
+
+  result = NULL;
+  pid = -1;
+
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  if (connection->kdbus_worker)
+    return _g_kdbus_GetConnectionUnixProcessID (connection->kdbus_worker, name, error);
+#endif
+#endif
 
-  g_assert (connection->worker != NULL);
+  result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/",
+                                        "org.freedesktop.DBus", "GetConnectionUnixProcessID",
+                                        g_variant_new ("(s)", name), G_VARIANT_TYPE ("(u)"),
+                                        G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+  if (result != NULL)
+    {
+      g_variant_get (result, "(u)", &pid);
+      g_variant_unref (result);
+    }
 
-  task = g_task_new (connection, cancellable, callback, user_data);
-  g_task_set_source_tag (task, g_dbus_connection_close);
-  _g_dbus_worker_close (connection->worker, task);
-  g_object_unref (task);
+  return pid;
 }
 
 /**
- * g_dbus_connection_close_finish:
+ * g_dbus_get_connection_uid:
  * @connection: a #GDBusConnection
- * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed
- *     to g_dbus_connection_close()
+ * @name: a unique or well-known bus name of the connection to query
  * @error: return location for error or %NULL
  *
- * Finishes an operation started with g_dbus_connection_close().
+ * Synchronously returns the Unix user ID of the process connected to the
+ * bus. If unable to determine it, an @error is returned.
  *
- * Returns: %TRUE if the operation succeeded, %FALSE if @error is set
+ * If @name contains a value not compatible with the D-Bus syntax and naming
+ * conventions for bus names, the operation returns -1 and @error is set.
  *
- * Since: 2.26
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: the Unix user ID of the process connected to the bus or -1
+ *     if @error is set.
+ *
+ * Since: 2.44
  */
-gboolean
-g_dbus_connection_close_finish (GDBusConnection  *connection,
-                                GAsyncResult     *res,
-                                GError          **error)
+uid_t
+g_dbus_get_connection_uid (GDBusConnection  *connection,
+                           const gchar      *name,
+                           GError          **error)
 {
-  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
-  g_return_val_if_fail (g_task_is_valid (res, connection), FALSE);
-  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+  GVariant *result;
+  uid_t uid;
 
-  return g_task_propagate_boolean (G_TASK (res), error);
-}
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), -1);
+  g_return_val_if_fail (name == NULL || g_dbus_is_name (name), -1);
+  g_return_val_if_fail (error == NULL || *error == NULL, -1);
 
-typedef struct {
-    GMainLoop *loop;
-    GAsyncResult *result;
-} SyncCloseData;
+  result = NULL;
+  uid = -1;
 
-/* Can be called by any thread, without the connection lock */
-static void
-sync_close_cb (GObject *source_object,
-               GAsyncResult *res,
-               gpointer user_data)
-{
-  SyncCloseData *data = user_data;
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  if (connection->kdbus_worker)
+    return _g_kdbus_GetConnectionUnixUser (connection->kdbus_worker, name, error);
+#endif
+#endif
 
-  data->result = g_object_ref (res);
-  g_main_loop_quit (data->loop);
+  result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/",
+                                        "org.freedesktop.DBus", "GetConnectionUnixUser",
+                                        g_variant_new ("(s)", name), G_VARIANT_TYPE ("(u)"),
+                                        G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+  if (result != NULL)
+    {
+      g_variant_get (result, "(u)", &uid);
+      g_variant_unref (result);
+    }
+
+  return uid;
 }
 
 /**
- * g_dbus_connection_close_sync:
+ * g_dbus_start_service_by_name:
  * @connection: a #GDBusConnection
- * @cancellable: (nullable): a #GCancellable or %NULL
+ * @name: name of the service to start
+ * @flags: (currently not used)
  * @error: return location for error or %NULL
  *
- * Synchronously closes @connection. The calling thread is blocked
- * until this is done. See g_dbus_connection_close() for the
- * asynchronous version of this method and more details about what it
- * does.
+ * Synchronously tries to launch the executable associated
+ * with a @name.
  *
- * Returns: %TRUE if the operation succeeded, %FALSE if @error is set
+ * The calling thread is blocked until a reply is received.
  *
- * Since: 2.26
+ * Returns: status code or %G_BUS_START_SERVICE_REPLY_ERROR
+ *     if @error is set.
+ *
+ * Since: 2.44
  */
-gboolean
-g_dbus_connection_close_sync (GDBusConnection  *connection,
-                              GCancellable     *cancellable,
+GBusStartServiceReplyFlags
+g_dbus_start_service_by_name (GDBusConnection  *connection,
+                              const gchar      *name,
+                              guint32           flags,
                               GError          **error)
 {
-  gboolean ret;
-
-  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
-  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-  ret = FALSE;
+  GVariant *result;
+  guint32 ret;
 
-  if (check_unclosed (connection, 0, error))
-    {
-      GMainContext *context;
-      SyncCloseData data;
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), -1);
+  g_return_val_if_fail (name == NULL || g_dbus_is_name (name), -1);
+  g_return_val_if_fail (error == NULL || *error == NULL, -1);
 
-      context = g_main_context_new ();
-      g_main_context_push_thread_default (context);
-      data.loop = g_main_loop_new (context, TRUE);
-      data.result = NULL;
+  result = NULL;
+  ret = G_BUS_START_SERVICE_REPLY_ERROR;
 
-      g_dbus_connection_close (connection, cancellable, sync_close_cb, &data);
-      g_main_loop_run (data.loop);
-      ret = g_dbus_connection_close_finish (connection, data.result, error);
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  if (connection->kdbus_worker)
+    return _g_kdbus_StartServiceByName (connection->kdbus_worker, name, flags, NULL, error);
+#endif
+#endif
 
-      g_object_unref (data.result);
-      g_main_loop_unref (data.loop);
-      g_main_context_pop_thread_default (context);
-      g_main_context_unref (context);
+  result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/",
+                                        "org.freedesktop.DBus", "StartServiceByName",
+                                        g_variant_new ("(su)", name, flags), G_VARIANT_TYPE ("(u)"),
+                                        G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+  if (result != NULL)
+    {
+      g_variant_get (result, "(u)", &ret);
+      g_variant_unref (result);
     }
 
-  return ret;
+  return (GBusStartServiceReplyFlags) ret;
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
@@ -1614,11 +2322,13 @@ g_dbus_connection_send_message_unlocked (GDBusConnection   *connection,
                                          GDBusMessage      *message,
                                          GDBusSendMessageFlags flags,
                                          guint32           *out_serial,
-                                         GError           **error)
+                                         GError           **error,
+                                         gint timeout_msec)
 {
   guchar *blob;
   gsize blob_size;
   guint32 serial_to_use;
+  gboolean ret;
 
   CONNECTION_ENSURE_LOCK (connection);
 
@@ -1627,6 +2337,9 @@ g_dbus_connection_send_message_unlocked (GDBusConnection   *connection,
 
   /* TODO: check all necessary headers are present */
 
+  ret = FALSE;
+  blob = NULL;
+
   if (out_serial != NULL)
     *out_serial = 0;
 
@@ -1638,33 +2351,41 @@ g_dbus_connection_send_message_unlocked (GDBusConnection   *connection,
   if (!check_unclosed (connection,
                        (flags & SEND_MESSAGE_FLAGS_INITIALIZING) ? MAY_BE_UNINITIALIZED : 0,
                        error))
-    return FALSE;
+    goto out;
 
-  blob = g_dbus_message_to_blob (message,
-                                 &blob_size,
-                                 connection->capabilities,
-                                 error);
-  if (blob == NULL)
-    return FALSE;
+  if (!(flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL))
+    g_dbus_message_set_serial (message, ++connection->last_serial);
 
-  if (flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL)
-    serial_to_use = g_dbus_message_get_serial (message);
-  else
-    serial_to_use = ++connection->last_serial; /* TODO: handle overflow */
+  serial_to_use = g_dbus_message_get_serial (message);
 
-  switch (blob[0])
+  /*
+   * serializes message to a blob
+   */
+  if (connection->worker)
     {
-    case 'l':
-      ((guint32 *) blob)[2] = GUINT32_TO_LE (serial_to_use);
-      break;
-    case 'B':
-      ((guint32 *) blob)[2] = GUINT32_TO_BE (serial_to_use);
-      break;
-    default:
-      g_assert_not_reached ();
-      break;
+      blob = g_dbus_message_to_blob (message,
+                                     &blob_size,
+                                     connection->capabilities,
+                                     error);
+      if (blob == NULL)
+        goto out;
+
+      switch (blob[0])
+        {
+        case 'l':
+          ((guint32 *) blob)[2] = GUINT32_TO_LE (serial_to_use);
+          break;
+        case 'B':
+          ((guint32 *) blob)[2] = GUINT32_TO_BE (serial_to_use);
+          break;
+        default:
+          g_assert_not_reached ();
+          break;
+        }
     }
 
+  g_dbus_message_lock (message);
+
 #if 0
   g_printerr ("Writing message of %" G_GSIZE_FORMAT " bytes (serial %d) on %p:\n",
               blob_size, serial_to_use, connection);
@@ -1687,17 +2408,32 @@ g_dbus_connection_send_message_unlocked (GDBusConnection   *connection,
                         g_thread_self (),
                         GUINT_TO_POINTER (serial_to_use));
 
-  if (!(flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL))
-    g_dbus_message_set_serial (message, serial_to_use);
+  ret = TRUE;
 
-  g_dbus_message_lock (message);
+  if (connection->worker)
+    {
+      _g_dbus_worker_send_message (connection->worker,
+                                   message,
+                                   (gchar*) blob,
+                                   blob_size);
+    }
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  else if (connection->kdbus_worker)
+    {
+      ret = _g_kdbus_worker_send_message (connection->kdbus_worker, message, timeout_msec, error);
+    }
+#endif
+#endif
+  else
+    g_assert_not_reached ();
 
-  _g_dbus_worker_send_message (connection->worker,
-                               message,
-                               (gchar*) blob, /* transfer ownership */
-                               blob_size);
+  blob = NULL; /* since _g_dbus_worker_send_message() steals the blob */
 
-  return TRUE;
+ out:
+  g_free (blob);
+
+  return ret;
 }
 
 /**
@@ -1751,7 +2487,7 @@ g_dbus_connection_send_message (GDBusConnection        *connection,
   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
   CONNECTION_LOCK (connection);
-  ret = g_dbus_connection_send_message_unlocked (connection, message, flags, (guint32 *) out_serial, error);
+  ret = g_dbus_connection_send_message_unlocked (connection, message, flags, (guint32 *) out_serial, error, -1);
   CONNECTION_UNLOCK (connection);
   return ret;
 }
@@ -1924,9 +2660,6 @@ g_dbus_connection_send_message_with_reply_unlocked (GDBusConnection     *connect
   if (out_serial == NULL)
     out_serial = &serial;
 
-  if (timeout_msec == -1)
-    timeout_msec = 25 * 1000;
-
   data = g_slice_new0 (SendMessageData);
   task = g_task_new (connection, cancellable, callback, user_data);
   g_task_set_source_tag (task,
@@ -1939,7 +2672,7 @@ g_dbus_connection_send_message_with_reply_unlocked (GDBusConnection     *connect
       return;
     }
 
-  if (!g_dbus_connection_send_message_unlocked (connection, message, flags, out_serial, &error))
+  if (!g_dbus_connection_send_message_unlocked (connection, message, flags, out_serial, &error, timeout_msec))
     {
       g_task_return_error (task, error);
       g_object_unref (task);
@@ -1955,9 +2688,16 @@ g_dbus_connection_send_message_with_reply_unlocked (GDBusConnection     *connect
                                                             g_object_unref);
     }
 
-  if (timeout_msec != G_MAXINT)
+  if (timeout_msec != G_MAXINT
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+        /* Userspace timeouts unnecessary on unix/kdbus - kdbus handles timeouts. */
+        && !connection->kdbus_worker
+#endif
+#endif
+     )
     {
-      data->timeout_source = g_timeout_source_new (timeout_msec);
+      data->timeout_source = g_timeout_source_new (timeout_msec == -1 ? DBUS_DEFAULT_TIMEOUT_MSEC : timeout_msec);
       g_task_attach_source (task, data->timeout_source,
                             (GSourceFunc) send_message_with_reply_timeout_cb);
       g_source_unref (data->timeout_source);
@@ -1999,7 +2739,7 @@ g_dbus_connection_send_message_with_reply_unlocked (GDBusConnection     *connect
  * the operation fails with %G_IO_ERROR_INVALID_ARGUMENT.
  *
  * This is an asynchronous method. When the operation is finished, @callback
- * will be invoked in the 
+ * will be invoked in the
  * [thread-default main context][g-main-context-push-thread-default]
  * of the thread you are calling this method from. You can then call
  * g_dbus_connection_send_message_with_reply_finish() to get the result of the operation.
@@ -2161,32 +2901,102 @@ g_dbus_connection_send_message_with_reply_sync (GDBusConnection        *connecti
   g_return_val_if_fail (timeout_msec >= 0 || timeout_msec == -1, NULL);
   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
-  data.res = NULL;
-  data.context = g_main_context_new ();
-  data.loop = g_main_loop_new (data.context, FALSE);
+  if (connection->worker)
+    {
+      data.res = NULL;
+      data.context = g_main_context_new ();
+      data.loop = g_main_loop_new (data.context, FALSE);
 
-  g_main_context_push_thread_default (data.context);
+      g_main_context_push_thread_default (data.context);
 
-  g_dbus_connection_send_message_with_reply (connection,
-                                             message,
-                                             flags,
-                                             timeout_msec,
-                                             out_serial,
-                                             cancellable,
-                                             (GAsyncReadyCallback) send_message_with_reply_sync_cb,
-                                             &data);
-  g_main_loop_run (data.loop);
-  reply = g_dbus_connection_send_message_with_reply_finish (connection,
-                                                            data.res,
-                                                            error);
+      g_dbus_connection_send_message_with_reply (connection,
+                                                 message,
+                                                 flags,
+                                                 timeout_msec,
+                                                 out_serial,
+                                                 cancellable,
+                                                 (GAsyncReadyCallback) send_message_with_reply_sync_cb,
+                                                 &data);
+      g_main_loop_run (data.loop);
+      reply = g_dbus_connection_send_message_with_reply_finish (connection,
+                                                                data.res,
+                                                                error);
+
+      g_main_context_pop_thread_default (data.context);
+
+      g_main_context_unref (data.context);
+      g_main_loop_unref (data.loop);
+      if (data.res)
+        g_object_unref (data.res);
+    }
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  else if (connection->kdbus_worker)
+    {
+      /* kdbus supports blocking synchronous calls, so let's use them instead of mainloops */
+
+      volatile guint32 serial;
+      guint32 serial_to_use;
+
+      reply = NULL;
+
+      CONNECTION_LOCK (connection);
+
+      if (out_serial == NULL)
+        out_serial = &serial;
+      else
+        *out_serial = 0;
+
+      /*
+       * Check that we never actually send a message if the GCancellable
+       * is already cancelled
+       */
+      if (g_cancellable_is_cancelled (cancellable))
+        {
+          g_set_error_literal (error,
+                               G_IO_ERROR,
+                               G_IO_ERROR_CANCELLED,
+                               _("Operation was cancelled"));
+          CONNECTION_UNLOCK (connection);
+          goto out;
+        }
+
+      if (!check_unclosed (connection,
+                           (flags & SEND_MESSAGE_FLAGS_INITIALIZING) ? MAY_BE_UNINITIALIZED : 0,
+                           error))
+        {
+          CONNECTION_UNLOCK (connection);
+          goto out;
+        }
+
+      if (!(flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL))
+        g_dbus_message_set_serial (message, ++connection->last_serial);
+
+      serial_to_use = g_dbus_message_get_serial (message);
 
-  g_main_context_pop_thread_default (data.context);
+      g_dbus_message_lock (message);
+
+      if (out_serial != NULL)
+        *out_serial = serial_to_use;
+
+      CONNECTION_UNLOCK (connection);
 
-  g_main_context_unref (data.context);
-  g_main_loop_unref (data.loop);
-  if (data.res)
-    g_object_unref (data.res);
+      /* Reference is still kept for the connection, so there is no worry
+       * that it will be freed. Same for connection->kdbus_worker - by reference
+       * from the connection. Inside _g_kdbus_worker_send_message_sync only
+       * initialized-once, read-only fields from kdbus_worker are used, except
+       * 'matches', which now has got its own mutex.
+       */
+      _g_kdbus_worker_send_message_sync (connection->kdbus_worker, message,
+                                         &reply, timeout_msec, cancellable, error);
+
+    }
+#endif /* G_OS_UNIX */
+#endif /* G_OS_UNIX */
+  else
+    g_assert_not_reached ();
 
+out:
   return reply;
 }
 
@@ -2255,8 +3065,7 @@ free_filter_list (FilterData **filters)
 
 /* Called in GDBusWorker's thread - we must not block - with no lock held */
 static void
-on_worker_message_received (GDBusWorker  *worker,
-                            GDBusMessage *message,
+on_worker_message_received (GDBusMessage *message,
                             gpointer      user_data)
 {
   GDBusConnection *connection;
@@ -2275,7 +3084,25 @@ on_worker_message_received (GDBusWorker  *worker,
   g_object_ref (connection);
   G_UNLOCK (message_bus_lock);
 
-  //g_debug ("in on_worker_message_received");
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  if (_g_dbus_connection_is_kdbus (connection))
+    {
+      if (G_UNLIKELY (_g_dbus_debug_message ()))
+        {
+          gchar *s;
+          _g_dbus_debug_print_lock ();
+          g_print ("========================================================================\n"
+                   "GDBus-debug:Message:\n"
+                   "  <<<< RECEIVED D-Bus message\n");
+          s = g_dbus_message_print (message, 2);
+          g_print ("%s", s);
+          g_free (s);
+          _g_dbus_debug_print_unlock ();
+        }
+    }
+#endif
+#endif
 
   g_object_ref (message);
   g_dbus_message_lock (message);
@@ -2353,8 +3180,7 @@ on_worker_message_received (GDBusWorker  *worker,
 
 /* Called in GDBusWorker's thread, lock is not held */
 static GDBusMessage *
-on_worker_message_about_to_be_sent (GDBusWorker  *worker,
-                                    GDBusMessage *message,
+on_worker_message_about_to_be_sent (GDBusMessage *message,
                                     gpointer      user_data)
 {
   GDBusConnection *connection;
@@ -2426,10 +3252,9 @@ cancel_method_on_close (gpointer key, gpointer value, gpointer user_data)
 
 /* Called in GDBusWorker's thread - we must not block - without lock held */
 static void
-on_worker_closed (GDBusWorker *worker,
-                  gboolean     remote_peer_vanished,
-                  GError      *error,
-                  gpointer     user_data)
+on_worker_closed (gboolean  remote_peer_vanished,
+                  GError   *error,
+                  gpointer  user_data)
 {
   GDBusConnection *connection;
   gboolean alive;
@@ -2491,6 +3316,7 @@ initable_init (GInitable     *initable,
                GError       **error)
 {
   GDBusConnection *connection = G_DBUS_CONNECTION (initable);
+  gboolean initially_frozen;
   gboolean ret;
 
   /* This method needs to be idempotent to work with the singleton
@@ -2528,6 +3354,8 @@ initable_init (GInitable     *initable,
    */
   if (connection->address != NULL)
     {
+      GObject *ret;
+
       g_assert (connection->stream == NULL);
 
       if ((connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER) ||
@@ -2541,12 +3369,22 @@ initable_init (GInitable     *initable,
           goto out;
         }
 
-      connection->stream = g_dbus_address_get_stream_sync (connection->address,
-                                                           NULL, /* TODO: out_guid */
-                                                           cancellable,
-                                                           &connection->initialization_error);
-      if (connection->stream == NULL)
+      ret = g_dbus_address_get_stream_internal (connection->address, TRUE,
+                                                NULL, /* TODO: out_guid */
+                                                cancellable, &connection->initialization_error);
+      if (ret == NULL)
         goto out;
+
+      if (G_IS_IO_STREAM (ret))
+        connection->stream = G_IO_STREAM (ret);
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+      else if (G_IS_KDBUS_WORKER (ret))
+        connection->kdbus_worker = G_KDBUS_WORKER (ret);
+#endif
+#endif
+      else
+        g_assert_not_reached ();
     }
   else if (connection->stream != NULL)
     {
@@ -2557,6 +3395,22 @@ initable_init (GInitable     *initable,
       g_assert_not_reached ();
     }
 
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  /* Skip authentication process for kdbus transport */
+  if (connection->kdbus_worker)
+    {
+      if (!_g_kdbus_can_connect (connection->kdbus_worker,
+                                 &connection->initialization_error))
+        goto out;
+
+      /* kdbus connection always supports exchanging UNIX file descriptors with the remote peer */
+      connection->capabilities |= G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING;
+      goto authenticated;
+    }
+#endif
+#endif
+
   /* Authenticate the connection */
   if (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER)
     {
@@ -2596,6 +3450,8 @@ initable_init (GInitable     *initable,
       connection->authentication_observer = NULL;
     }
 
+authenticated:
+
   //g_output_stream_flush (G_SOCKET_CONNECTION (connection->stream)
 
   //g_debug ("haz unix fd passing powers: %d", connection->capabilities & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);
@@ -2616,13 +3472,34 @@ initable_init (GInitable     *initable,
   g_hash_table_add (alive_connections, connection);
   G_UNLOCK (message_bus_lock);
 
-  connection->worker = _g_dbus_worker_new (connection->stream,
-                                           connection->capabilities,
-                                           ((connection->flags & G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING) != 0),
-                                           on_worker_message_received,
-                                           on_worker_message_about_to_be_sent,
-                                           on_worker_closed,
-                                           connection);
+  initially_frozen = (connection->flags & G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING) != 0;
+
+  if (0)
+    {
+    }
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  else if (connection->kdbus_worker)
+    {
+      _g_kdbus_worker_associate (connection->kdbus_worker,
+                                 connection->capabilities,
+                                 on_worker_message_received,
+                                 on_worker_message_about_to_be_sent,
+                                 on_worker_closed,
+                                 connection);
+    }
+#endif
+#endif
+  else
+    {
+      connection->worker = _g_dbus_worker_new (connection->stream,
+                                               connection->capabilities,
+                                               initially_frozen,
+                                               on_worker_message_received,
+                                               on_worker_message_about_to_be_sent,
+                                               on_worker_closed,
+                                               connection);
+    }
 
   /* if a bus connection, call org.freedesktop.DBus.Hello - this is how we're getting a name */
   if (connection->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION)
@@ -2639,25 +3516,50 @@ initable_init (GInitable     *initable,
           goto out;
         }
 
-      hello_result = g_dbus_connection_call_sync (connection,
-                                                  "org.freedesktop.DBus", /* name */
-                                                  "/org/freedesktop/DBus", /* path */
-                                                  "org.freedesktop.DBus", /* interface */
-                                                  "Hello",
-                                                  NULL, /* parameters */
-                                                  G_VARIANT_TYPE ("(s)"),
-                                                  CALL_FLAGS_INITIALIZING,
-                                                  -1,
-                                                  NULL, /* TODO: cancellable */
-                                                  &connection->initialization_error);
-      if (hello_result == NULL)
-        goto out;
+      if (connection->worker)
+        {
+          hello_result = g_dbus_connection_call_sync (connection,
+                                                      "org.freedesktop.DBus", /* name */
+                                                      "/org/freedesktop/DBus", /* path */
+                                                      "org.freedesktop.DBus", /* interface */
+                                                      "Hello",
+                                                      NULL, /* parameters */
+                                                      G_VARIANT_TYPE ("(s)"),
+                                                      CALL_FLAGS_INITIALIZING,
+                                                      -1,
+                                                      NULL, /* TODO: cancellable */
+                                                      &connection->initialization_error);
+          if (hello_result == NULL)
+            goto out;
+
+          g_variant_get (hello_result, "(s)", &connection->bus_unique_name);
+          g_variant_unref (hello_result);
+        }
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+      else if (connection->kdbus_worker)
+        {
+          const gchar *unique_name;
+
+          unique_name = _g_kdbus_Hello (connection->kdbus_worker, &connection->initialization_error);
+          if (unique_name == NULL)
+            goto out;
 
-      g_variant_get (hello_result, "(s)", &connection->bus_unique_name);
-      g_variant_unref (hello_result);
-      //g_debug ("unique name is '%s'", connection->bus_unique_name);
+          connection->bus_unique_name = g_strdup (unique_name);
+        }
+#endif
+#endif
+      else
+        g_assert_not_reached ();
     }
 
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  if (connection->kdbus_worker && !initially_frozen)
+    _g_kdbus_worker_unfreeze (connection->kdbus_worker);
+#endif
+#endif
+
   ret = TRUE;
  out:
   if (!ret)
@@ -3377,7 +4279,8 @@ add_match_rule (GDBusConnection *connection,
                                                 message,
                                                 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
                                                 NULL,
-                                                &error))
+                                                &error,
+                                                -1))
     {
       g_critical ("Error while sending AddMatch() message: %s", error->message);
       g_error_free (error);
@@ -3409,7 +4312,8 @@ remove_match_rule (GDBusConnection *connection,
                                                 message,
                                                 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
                                                 NULL,
-                                                &error))
+                                                &error,
+                                                -1))
     {
       /* If we could get G_IO_ERROR_CLOSED here, it wouldn't be reasonable to
        * critical; but we're holding the lock, and our caller checked whether
@@ -3456,7 +4360,7 @@ is_signal_data_for_name_lost_or_acquired (SignalData *signal_data)
  *     subscription is removed or %NULL
  *
  * Subscribes to signals on @connection and invokes @callback with a whenever
- * the signal is received. Note that @callback will be invoked in the 
+ * the signal is received. Note that @callback will be invoked in the
  * [thread-default main context][g-main-context-push-thread-default]
  * of the thread you are calling this method from.
  *
@@ -3604,8 +4508,60 @@ g_dbus_connection_signal_subscribe (GDBusConnection     *connection,
    */
   if (connection->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION)
     {
-      if (!is_signal_data_for_name_lost_or_acquired (signal_data))
-        add_match_rule (connection, signal_data->rule);
+      if (connection->worker)
+        {
+          if (!is_signal_data_for_name_lost_or_acquired (signal_data))
+            add_match_rule (connection, signal_data->rule);
+        }
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+      else if (connection->kdbus_worker)
+        {
+          gboolean special_rule = FALSE;
+          /* rule for special message */
+          if (!signal_data->sender_unique_name[0] || g_strcmp0 (signal_data->sender_unique_name, "org.freedesktop.DBus") == 0)
+            {
+              if (signal_data->sender_unique_name[0])  /* So, this is org.freedesktop.DBus */
+                special_rule = TRUE;
+              if (!signal_data->object_path || g_strcmp0 (signal_data->object_path, "/org/freedesktop/DBus") == 0)
+                {
+                  if (!signal_data->interface_name || g_strcmp0 (signal_data->interface_name, "org.freedesktop.DBus") == 0)
+                    {
+                      /* By https://dbus.freedesktop.org/doc/dbus-specification.html, org.freedesktop.DBus
+                       * has three signal types: NameAcquired, NameLost, NameOwnerChanged (all covered below).
+                       *
+                       * 1. if sender is NULL and other parameters are matched with special rule, add BOTH special and standard,
+                       *   - (NULL, NULL or DBUS, NULL or DBUS, NULL or Special Name)
+                       *
+                       *    if other parameters are NOT matched with special rule, add standard rule
+                       *   - (NULL, X, X, "NotSpecial")
+                       *
+                       * 2. if sender is 'org.freedesktop.DBus' and other parameters are matched with special rule, add special rule
+                       *   - (org.freedesktop.DBus, NULL or DBUS, NULL or DBUS, NULL or Special Name)
+                       *
+                       *    if other parameters are NOT matched with special rule, then ignore
+                       *   - (org.freedesktop.DBus, X, X, "NotSpecial")
+                       *
+                       * for every other cases, add standard rule,
+                       */
+
+                      if (g_strcmp0 (signal_data->member, "NameAcquired") == 0)
+                        _g_kdbus_subscribe_name_acquired (connection->kdbus_worker, signal_data->rule, arg0, NULL);
+                      else if (g_strcmp0 (signal_data->member, "NameLost") == 0)
+                        _g_kdbus_subscribe_name_lost (connection->kdbus_worker, signal_data->rule, arg0, NULL);
+                      else if (!signal_data->member || g_strcmp0 (signal_data->member, "NameOwnerChanged") == 0)
+                        _g_kdbus_subscribe_name_owner_changed (connection->kdbus_worker, signal_data->rule, arg0, NULL);
+                    }
+                }
+            }
+            /* standard rule */
+            if (!special_rule)
+              _g_kdbus_AddMatch (connection->kdbus_worker, signal_data->rule, NULL);
+        }
+#endif
+#endif
+      else
+        g_assert_not_reached ();
     }
 
   signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array,
@@ -3684,7 +4640,6 @@ unsubscribe_id_internal (GDBusConnection *connection,
 
           /* remove the match rule from the bus unless NameLost or NameAcquired (see subscribe()) */
           if ((connection->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION) &&
-              !is_signal_data_for_name_lost_or_acquired (signal_data) &&
               !g_dbus_connection_is_closed (connection) &&
               !connection->finalizing)
             {
@@ -3694,7 +4649,21 @@ unsubscribe_id_internal (GDBusConnection *connection,
                * so on_worker_closed() can't happen between the check we just
                * did, and releasing the lock later.
                */
-              remove_match_rule (connection, signal_data->rule);
+              if (connection->worker)
+                {
+                  if (!is_signal_data_for_name_lost_or_acquired (signal_data))
+                    remove_match_rule (connection, signal_data->rule);
+                }
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+              else if (connection->kdbus_worker)
+                {
+                  _g_kdbus_RemoveMatch (connection->kdbus_worker, signal_data->rule, NULL);
+                }
+#endif
+#endif
+              else
+                g_assert_not_reached ();
             }
 
           signal_data_free (signal_data);
@@ -3778,7 +4747,7 @@ emit_signal_instance_in_idle_cb (gpointer data)
     }
   else
     {
-      g_variant_ref_sink (parameters);
+      g_variant_ref (parameters);
     }
 
 #if 0
@@ -4330,7 +5299,7 @@ validate_and_maybe_schedule_property_getset (GDBusConnection            *connect
                                                "org.freedesktop.DBus.Error.InvalidArgs",
                                                _("No such property “%s”"),
                                                property_name);
-      g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+      g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
       g_object_unref (reply);
       handled = TRUE;
       goto out;
@@ -4342,7 +5311,7 @@ validate_and_maybe_schedule_property_getset (GDBusConnection            *connect
                                                "org.freedesktop.DBus.Error.InvalidArgs",
                                                _("Property “%s” is not readable"),
                                                property_name);
-      g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+      g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
       g_object_unref (reply);
       handled = TRUE;
       goto out;
@@ -4353,7 +5322,7 @@ validate_and_maybe_schedule_property_getset (GDBusConnection            *connect
                                                "org.freedesktop.DBus.Error.InvalidArgs",
                                                _("Property “%s” is not writable"),
                                                property_name);
-      g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+      g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
       g_object_unref (reply);
       handled = TRUE;
       goto out;
@@ -4374,7 +5343,7 @@ validate_and_maybe_schedule_property_getset (GDBusConnection            *connect
                                                    _("Error setting property “%s”: Expected type “%s” but got “%s”"),
                                                    property_name, property_info->signature,
                                                    g_variant_get_type_string (value));
-          g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+          g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
           g_variant_unref (value);
           g_object_unref (reply);
           handled = TRUE;
@@ -4478,7 +5447,7 @@ handle_getset_property (GDBusConnection *connection,
                                                "org.freedesktop.DBus.Error.InvalidArgs",
                                                _("No such interface “%s”"),
                                                interface_name);
-      g_dbus_connection_send_message_unlocked (eo->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+      g_dbus_connection_send_message_unlocked (eo->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
       g_object_unref (reply);
       handled = TRUE;
       goto out;
@@ -4686,7 +5655,7 @@ handle_get_all_properties (GDBusConnection *connection,
                                                "org.freedesktop.DBus.Error.InvalidArgs",
                                                _("No such interface “%s”"),
                                                interface_name);
-      g_dbus_connection_send_message_unlocked (eo->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+      g_dbus_connection_send_message_unlocked (eo->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
       g_object_unref (reply);
       handled = TRUE;
       goto out;
@@ -4876,7 +5845,7 @@ handle_introspect (GDBusConnection *connection,
 
   reply = g_dbus_message_new_method_reply (message);
   g_dbus_message_set_body (reply, g_variant_new ("(s)", s->str));
-  g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+  g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
   g_object_unref (reply);
   g_string_free (s, TRUE);
 
@@ -5002,7 +5971,7 @@ validate_and_maybe_schedule_method_call (GDBusConnection            *connection,
                                                "org.freedesktop.DBus.Error.UnknownMethod",
                                                _("No such method “%s”"),
                                                g_dbus_message_get_member (message));
-      g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+      g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
       g_object_unref (reply);
       handled = TRUE;
       goto out;
@@ -5034,7 +6003,7 @@ validate_and_maybe_schedule_method_call (GDBusConnection            *connection,
                                                _("Type of message, “%s”, does not match expected type “%s”"),
                                                g_variant_get_type_string (parameters),
                                                type_string);
-      g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+      g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
       g_variant_type_free (in_type);
       g_variant_unref (parameters);
       g_object_unref (reply);
@@ -5151,7 +6120,7 @@ obj_message_func (GDBusConnection *connection,
  * D-Bus interface that is described in @interface_info.
  *
  * Calls to functions in @vtable (and @user_data_free_func) will happen
- * in the 
+ * in the
  * [thread-default main context][g-main-context-push-thread-default]
  * of the thread you are calling this method from.
  *
@@ -5718,6 +6687,16 @@ decode_method_reply (GDBusMessage        *reply,
 
     case G_DBUS_MESSAGE_TYPE_ERROR:
       g_dbus_message_to_gerror (reply, error);
+      if (error == NULL || *error == NULL)
+        break;
+      if ((*error)->code == G_DBUS_ERROR_NO_REPLY)
+        {
+          g_clear_error(error);
+          g_set_error (error,
+                       G_IO_ERROR,
+                       G_IO_ERROR_TIMED_OUT,
+                       _("Timeout was reached"));
+        }
       break;
 
     default:
@@ -7001,7 +7980,7 @@ handle_generic_ping_unlocked (GDBusConnection *connection,
 {
   GDBusMessage *reply;
   reply = g_dbus_message_new_method_reply (message);
-  g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+  g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
   g_object_unref (reply);
 }
 
@@ -7034,7 +8013,7 @@ handle_generic_get_machine_id_unlocked (GDBusConnection *connection,
       reply = g_dbus_message_new_method_reply (message);
       g_dbus_message_set_body (reply, g_variant_new ("(s)", connection->machine_id));
     }
-  g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+  g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
   g_object_unref (reply);
 }
 
@@ -7061,7 +8040,7 @@ handle_generic_introspect_unlocked (GDBusConnection *connection,
 
   reply = g_dbus_message_new_method_reply (message);
   g_dbus_message_set_body (reply, g_variant_new ("(s)", s->str));
-  g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+  g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
   g_object_unref (reply);
   g_string_free (s, TRUE);
 }
@@ -7210,7 +8189,7 @@ distribute_method_call (GDBusConnection *connection,
                                            object_path);
     }
 
-  g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+  g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
   g_object_unref (reply);
 
  out:
@@ -7517,3 +8496,10 @@ g_bus_get_finish (GAsyncResult  *res,
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
+#ifdef _TIZEN_DBUS_TOUCH
+static void __attribute__((constructor)) glib_type_dbus_connection_gc( void )
+{
+       GObject* temp = g_type_class_ref(G_TYPE_DBUS_CONNECTION);
+       g_type_class_unref(temp);
+}
+#endif
index 4bd3e9a..ea1184f 100644 (file)
 #endif
 
 #include <gio/giotypes.h>
+#include <gio/tizen_header_glib.h>  /* for TIZEN_PUBLIC_DEPRECATED_API */
 
 G_BEGIN_DECLS
 
+#define DBUS_DEFAULT_TIMEOUT_MSEC   25000U
+
 #define G_TYPE_DBUS_CONNECTION         (g_dbus_connection_get_type ())
 #define G_DBUS_CONNECTION(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DBUS_CONNECTION, GDBusConnection))
 #define G_IS_DBUS_CONNECTION(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DBUS_CONNECTION))
@@ -42,14 +45,14 @@ GLIB_AVAILABLE_IN_ALL
 void              g_bus_get                    (GBusType             bus_type,
                                                 GCancellable        *cancellable,
                                                 GAsyncReadyCallback  callback,
-                                                gpointer             user_data);
+                                                gpointer             user_data) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusConnection  *g_bus_get_finish             (GAsyncResult        *res,
-                                                GError             **error);
+                                                GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusConnection  *g_bus_get_sync               (GBusType            bus_type,
                                                 GCancellable       *cancellable,
-                                                GError            **error);
+                                                GError            **error) TIZEN_PUBLIC_DEPRECATED_API;
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -60,17 +63,17 @@ void             g_dbus_connection_new                        (GIOStream
                                                                GDBusAuthObserver      *observer,
                                                                GCancellable           *cancellable,
                                                                GAsyncReadyCallback     callback,
-                                                               gpointer                user_data);
+                                                               gpointer                user_data) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusConnection *g_dbus_connection_new_finish                 (GAsyncResult           *res,
-                                                               GError                **error);
+                                                               GError                **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusConnection *g_dbus_connection_new_sync                   (GIOStream              *stream,
                                                                const gchar            *guid,
                                                                GDBusConnectionFlags    flags,
                                                                GDBusAuthObserver      *observer,
                                                                GCancellable           *cancellable,
-                                                               GError                **error);
+                                                               GError                **error) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
 void             g_dbus_connection_new_for_address            (const gchar            *address,
@@ -78,44 +81,96 @@ void             g_dbus_connection_new_for_address            (const gchar
                                                                GDBusAuthObserver      *observer,
                                                                GCancellable           *cancellable,
                                                                GAsyncReadyCallback     callback,
-                                                               gpointer                user_data);
+                                                               gpointer                user_data) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusConnection *g_dbus_connection_new_for_address_finish     (GAsyncResult           *res,
-                                                               GError                **error);
+                                                               GError                **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusConnection *g_dbus_connection_new_for_address_sync       (const gchar            *address,
                                                                GDBusConnectionFlags    flags,
                                                                GDBusAuthObserver      *observer,
                                                                GCancellable           *cancellable,
-                                                               GError                **error);
+                                                               GError                **error) TIZEN_PUBLIC_DEPRECATED_API;
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+gboolean                     _g_dbus_connection_is_kdbus         (GDBusConnection     *connection) TIZEN_PUBLIC_DEPRECATED_API;
+
+/* GLIB_AVAILABLE_IN_2_44 */
+GBusRequestNameReplyFlags    g_dbus_request_name                 (GDBusConnection     *connection,
+                                                                  const gchar         *name,
+                                                                  GBusNameOwnerFlags   flags,
+                                                                  GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
+/* GLIB_AVAILABLE_IN_2_44 */
+GBusReleaseNameReplyFlags    g_dbus_release_name                 (GDBusConnection     *connection,
+                                                                  const gchar         *name,
+                                                                  GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
+/* GLIB_AVAILABLE_IN_2_44 */
+gboolean                     g_dbus_add_match                    (GDBusConnection     *connection,
+                                                                  const gchar         *match_rule,
+                                                                  GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
+/* GLIB_AVAILABLE_IN_2_44 */
+gboolean                     g_dbus_remove_match                 (GDBusConnection     *connection,
+                                                                  const gchar         *match_rule,
+                                                                  GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
+/* GLIB_AVAILABLE_IN_2_44 */
+gchar                       *g_dbus_get_bus_id                   (GDBusConnection     *connection,
+                                                                  GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
+/* GLIB_AVAILABLE_IN_2_44 */
+gchar                      **g_dbus_get_list_names               (GDBusConnection     *connection,
+                                                                  GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
+/* GLIB_AVAILABLE_IN_2_44 */
+gchar                      **g_dbus_get_list_activatable_names   (GDBusConnection     *connection,
+                                                                  GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
+/* GLIB_AVAILABLE_IN_2_44 */
+gchar                      **g_dbus_get_list_queued_owners       (GDBusConnection     *connection,
+                                                                  const gchar         *name,
+                                                                  GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
+/* GLIB_AVAILABLE_IN_2_44 */
+gchar                       *g_dbus_get_name_owner               (GDBusConnection     *connection,
+                                                                  const gchar         *name,
+                                                                  GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
+/* GLIB_AVAILABLE_IN_2_44 */
+pid_t                        g_dbus_get_connection_pid           (GDBusConnection     *connection,
+                                                                  const gchar         *name,
+                                                                  GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
+/* GLIB_AVAILABLE_IN_2_44 */
+uid_t                        g_dbus_get_connection_uid           (GDBusConnection     *connection,
+                                                                  const gchar         *name,
+                                                                  GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
+/* GLIB_AVAILABLE_IN_2_44 */
+GBusStartServiceReplyFlags   g_dbus_start_service_by_name        (GDBusConnection     *connection,
+                                                                  const gchar         *name,
+                                                                  guint32              flags,
+                                                                  GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
 
 /* ---------------------------------------------------------------------------------------------------- */
 
 GLIB_AVAILABLE_IN_ALL
-void             g_dbus_connection_start_message_processing   (GDBusConnection    *connection);
+void             g_dbus_connection_start_message_processing   (GDBusConnection    *connection) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-gboolean         g_dbus_connection_is_closed                  (GDBusConnection    *connection);
+gboolean         g_dbus_connection_is_closed                  (GDBusConnection    *connection) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GIOStream       *g_dbus_connection_get_stream                 (GDBusConnection    *connection);
+GIOStream       *g_dbus_connection_get_stream                 (GDBusConnection    *connection) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-const gchar     *g_dbus_connection_get_guid                   (GDBusConnection    *connection);
+const gchar     *g_dbus_connection_get_guid                   (GDBusConnection    *connection) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-const gchar     *g_dbus_connection_get_unique_name            (GDBusConnection    *connection);
+const gchar     *g_dbus_connection_get_unique_name            (GDBusConnection    *connection) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GCredentials    *g_dbus_connection_get_peer_credentials       (GDBusConnection    *connection);
+GCredentials    *g_dbus_connection_get_peer_credentials       (GDBusConnection    *connection) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_2_34
-guint32          g_dbus_connection_get_last_serial            (GDBusConnection    *connection);
+guint32          g_dbus_connection_get_last_serial            (GDBusConnection    *connection) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
-gboolean         g_dbus_connection_get_exit_on_close          (GDBusConnection    *connection);
+gboolean         g_dbus_connection_get_exit_on_close          (GDBusConnection    *connection) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void             g_dbus_connection_set_exit_on_close          (GDBusConnection    *connection,
-                                                               gboolean            exit_on_close);
+                                                               gboolean            exit_on_close) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusCapabilityFlags  g_dbus_connection_get_capabilities      (GDBusConnection    *connection);
+GDBusCapabilityFlags  g_dbus_connection_get_capabilities      (GDBusConnection    *connection) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_2_60
-GDBusConnectionFlags  g_dbus_connection_get_flags             (GDBusConnection    *connection);
+GDBusConnectionFlags  g_dbus_connection_get_flags             (GDBusConnection    *connection) TIZEN_PUBLIC_DEPRECATED_API;
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -123,15 +178,15 @@ GLIB_AVAILABLE_IN_ALL
 void             g_dbus_connection_close                          (GDBusConnection     *connection,
                                                                    GCancellable        *cancellable,
                                                                    GAsyncReadyCallback  callback,
-                                                                   gpointer             user_data);
+                                                                   gpointer             user_data) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 gboolean         g_dbus_connection_close_finish                   (GDBusConnection     *connection,
                                                                    GAsyncResult        *res,
-                                                                   GError             **error);
+                                                                   GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 gboolean         g_dbus_connection_close_sync                     (GDBusConnection     *connection,
                                                                    GCancellable        *cancellable,
-                                                                   GError             **error);
+                                                                   GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -139,15 +194,15 @@ GLIB_AVAILABLE_IN_ALL
 void             g_dbus_connection_flush                          (GDBusConnection     *connection,
                                                                    GCancellable        *cancellable,
                                                                    GAsyncReadyCallback  callback,
-                                                                   gpointer             user_data);
+                                                                   gpointer             user_data) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 gboolean         g_dbus_connection_flush_finish                   (GDBusConnection     *connection,
                                                                    GAsyncResult        *res,
-                                                                   GError             **error);
+                                                                   GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 gboolean         g_dbus_connection_flush_sync                     (GDBusConnection     *connection,
                                                                    GCancellable        *cancellable,
-                                                                   GError             **error);
+                                                                   GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -156,7 +211,7 @@ gboolean         g_dbus_connection_send_message                   (GDBusConnecti
                                                                    GDBusMessage        *message,
                                                                    GDBusSendMessageFlags flags,
                                                                    volatile guint32    *out_serial,
-                                                                   GError             **error);
+                                                                   GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void             g_dbus_connection_send_message_with_reply        (GDBusConnection     *connection,
                                                                    GDBusMessage        *message,
@@ -165,11 +220,11 @@ void             g_dbus_connection_send_message_with_reply        (GDBusConnecti
                                                                    volatile guint32    *out_serial,
                                                                    GCancellable        *cancellable,
                                                                    GAsyncReadyCallback  callback,
-                                                                   gpointer             user_data);
+                                                                   gpointer             user_data) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusMessage    *g_dbus_connection_send_message_with_reply_finish (GDBusConnection     *connection,
                                                                    GAsyncResult        *res,
-                                                                   GError             **error);
+                                                                   GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusMessage    *g_dbus_connection_send_message_with_reply_sync   (GDBusConnection     *connection,
                                                                    GDBusMessage        *message,
@@ -177,7 +232,7 @@ GDBusMessage    *g_dbus_connection_send_message_with_reply_sync   (GDBusConnecti
                                                                    gint                 timeout_msec,
                                                                    volatile guint32    *out_serial,
                                                                    GCancellable        *cancellable,
-                                                                   GError             **error);
+                                                                   GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -188,7 +243,7 @@ gboolean  g_dbus_connection_emit_signal                       (GDBusConnection
                                                                const gchar        *interface_name,
                                                                const gchar        *signal_name,
                                                                GVariant           *parameters,
-                                                               GError            **error);
+                                                               GError            **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void      g_dbus_connection_call                              (GDBusConnection    *connection,
                                                                const gchar        *bus_name,
@@ -201,11 +256,11 @@ void      g_dbus_connection_call                              (GDBusConnection
                                                                gint                timeout_msec,
                                                                GCancellable       *cancellable,
                                                                GAsyncReadyCallback callback,
-                                                               gpointer            user_data);
+                                                               gpointer            user_data) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GVariant *g_dbus_connection_call_finish                       (GDBusConnection    *connection,
                                                                GAsyncResult       *res,
-                                                               GError            **error);
+                                                               GError            **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GVariant *g_dbus_connection_call_sync                         (GDBusConnection    *connection,
                                                                const gchar        *bus_name,
@@ -217,7 +272,7 @@ GVariant *g_dbus_connection_call_sync                         (GDBusConnection
                                                                GDBusCallFlags      flags,
                                                                gint                timeout_msec,
                                                                GCancellable       *cancellable,
-                                                               GError            **error);
+                                                               GError            **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_2_30
 void      g_dbus_connection_call_with_unix_fd_list            (GDBusConnection    *connection,
                                                                const gchar        *bus_name,
@@ -231,12 +286,12 @@ void      g_dbus_connection_call_with_unix_fd_list            (GDBusConnection
                                                                GUnixFDList        *fd_list,
                                                                GCancellable       *cancellable,
                                                                GAsyncReadyCallback callback,
-                                                               gpointer            user_data);
+                                                               gpointer            user_data) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_2_30
 GVariant *g_dbus_connection_call_with_unix_fd_list_finish     (GDBusConnection    *connection,
                                                                GUnixFDList       **out_fd_list,
                                                                GAsyncResult       *res,
-                                                               GError            **error);
+                                                               GError            **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_2_30
 GVariant *g_dbus_connection_call_with_unix_fd_list_sync       (GDBusConnection    *connection,
                                                                const gchar        *bus_name,
@@ -250,7 +305,7 @@ GVariant *g_dbus_connection_call_with_unix_fd_list_sync       (GDBusConnection
                                                                GUnixFDList        *fd_list,
                                                                GUnixFDList       **out_fd_list,
                                                                GCancellable       *cancellable,
-                                                               GError            **error);
+                                                               GError            **error) TIZEN_PUBLIC_DEPRECATED_API;
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -402,7 +457,7 @@ guint            g_dbus_connection_register_object            (GDBusConnection
                                                                const GDBusInterfaceVTable *vtable,
                                                                gpointer                    user_data,
                                                                GDestroyNotify              user_data_free_func,
-                                                               GError                    **error);
+                                                               GError                    **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_2_46
 guint            g_dbus_connection_register_object_with_closures (GDBusConnection         *connection,
                                                                   const gchar             *object_path,
@@ -410,10 +465,10 @@ guint            g_dbus_connection_register_object_with_closures (GDBusConnectio
                                                                   GClosure                *method_call_closure,
                                                                   GClosure                *get_property_closure,
                                                                   GClosure                *set_property_closure,
-                                                                  GError                 **error);
+                                                                  GError                 **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 gboolean         g_dbus_connection_unregister_object          (GDBusConnection            *connection,
-                                                               guint                       registration_id);
+                                                               guint                       registration_id) TIZEN_PUBLIC_DEPRECATED_API;
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -540,10 +595,10 @@ guint            g_dbus_connection_register_subtree           (GDBusConnection
                                                                GDBusSubtreeFlags           flags,
                                                                gpointer                    user_data,
                                                                GDestroyNotify              user_data_free_func,
-                                                               GError                    **error);
+                                                               GError                    **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 gboolean         g_dbus_connection_unregister_subtree         (GDBusConnection            *connection,
-                                                               guint                       registration_id);
+                                                               guint                       registration_id) TIZEN_PUBLIC_DEPRECATED_API;
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -580,10 +635,10 @@ guint            g_dbus_connection_signal_subscribe           (GDBusConnection
                                                                GDBusSignalFlags     flags,
                                                                GDBusSignalCallback  callback,
                                                                gpointer             user_data,
-                                                               GDestroyNotify       user_data_free_func);
+                                                               GDestroyNotify       user_data_free_func) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void             g_dbus_connection_signal_unsubscribe         (GDBusConnection     *connection,
-                                                               guint                subscription_id);
+                                                               guint                subscription_id) TIZEN_PUBLIC_DEPRECATED_API;
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -670,11 +725,11 @@ GLIB_AVAILABLE_IN_ALL
 guint g_dbus_connection_add_filter (GDBusConnection            *connection,
                                     GDBusMessageFilterFunction  filter_function,
                                     gpointer                    user_data,
-                                    GDestroyNotify              user_data_free_func);
+                                    GDestroyNotify              user_data_free_func) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
 void  g_dbus_connection_remove_filter (GDBusConnection    *connection,
-                                       guint               filter_id);
+                                       guint               filter_id) TIZEN_PUBLIC_DEPRECATED_API;
 
 /* ---------------------------------------------------------------------------------------------------- */
 
index 35a156c..5bd8b5b 100644 (file)
@@ -26,6 +26,7 @@
 #endif
 
 #include <gio/giotypes.h>
+#include <gio/tizen_header_glib.h>  /* for TIZEN_PUBLIC_DEPRECATED_API */
 
 G_BEGIN_DECLS
 
@@ -46,15 +47,15 @@ G_BEGIN_DECLS
 #define G_DBUS_ERROR g_dbus_error_quark()
 
 GLIB_AVAILABLE_IN_ALL
-GQuark g_dbus_error_quark (void);
+GQuark g_dbus_error_quark (void) TIZEN_PUBLIC_DEPRECATED_API;
 
 /* Used by applications to check, get and strip the D-Bus error name */
 GLIB_AVAILABLE_IN_ALL
-gboolean g_dbus_error_is_remote_error       (const GError    *error);
+gboolean g_dbus_error_is_remote_error       (const GError    *error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-gchar   *g_dbus_error_get_remote_error      (const GError    *error);
+gchar   *g_dbus_error_get_remote_error      (const GError    *error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-gboolean g_dbus_error_strip_remote_error    (GError          *error);
+gboolean g_dbus_error_strip_remote_error    (GError          *error) TIZEN_PUBLIC_DEPRECATED_API;
 
 /**
  * GDBusErrorEntry:
@@ -74,35 +75,35 @@ struct _GDBusErrorEntry
 GLIB_AVAILABLE_IN_ALL
 gboolean g_dbus_error_register_error        (GQuark                 error_domain,
                                              gint                   error_code,
-                                             const gchar           *dbus_error_name);
+                                             const gchar           *dbus_error_name) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 gboolean g_dbus_error_unregister_error      (GQuark                 error_domain,
                                              gint                   error_code,
-                                             const gchar           *dbus_error_name);
+                                             const gchar           *dbus_error_name) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void     g_dbus_error_register_error_domain (const gchar           *error_domain_quark_name,
                                              volatile gsize        *quark_volatile,
                                              const GDBusErrorEntry *entries,
-                                             guint                  num_entries);
+                                             guint                  num_entries) TIZEN_PUBLIC_DEPRECATED_API;
 
 /* Only used by object mappings to map back and forth to GError */
 GLIB_AVAILABLE_IN_ALL
 GError  *g_dbus_error_new_for_dbus_error    (const gchar     *dbus_error_name,
-                                             const gchar     *dbus_error_message);
+                                             const gchar     *dbus_error_message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void     g_dbus_error_set_dbus_error        (GError         **error,
                                              const gchar     *dbus_error_name,
                                              const gchar     *dbus_error_message,
                                              const gchar     *format,
-                                             ...) G_GNUC_PRINTF(4, 5);
+                                             ...) G_GNUC_PRINTF(4, 5) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void     g_dbus_error_set_dbus_error_valist (GError         **error,
                                              const gchar     *dbus_error_name,
                                              const gchar     *dbus_error_message,
                                              const gchar     *format,
-                                             va_list          var_args) G_GNUC_PRINTF(4, 0);
+                                             va_list          var_args) G_GNUC_PRINTF(4, 0) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-gchar   *g_dbus_error_encode_gerror         (const GError    *error);
+gchar   *g_dbus_error_encode_gerror         (const GError    *error) TIZEN_PUBLIC_DEPRECATED_API;
 
 G_END_DECLS
 
index b2f3c44..e6cd535 100644 (file)
@@ -22,6 +22,7 @@
 #define __G_DBUS_INTERFACE_H__
 
 #include <gio/giotypes.h>
+#include <gio/tizen_header_glib.h>  /* for TIZEN_PUBLIC_DEPRECATED_API */
 
 G_BEGIN_DECLS
 
@@ -65,16 +66,16 @@ struct _GDBusInterfaceIface
 };
 
 GLIB_AVAILABLE_IN_ALL
-GType                 g_dbus_interface_get_type         (void) G_GNUC_CONST;
+GType                 g_dbus_interface_get_type         (void) G_GNUC_CONST TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusInterfaceInfo   *g_dbus_interface_get_info         (GDBusInterface      *interface_);
+GDBusInterfaceInfo   *g_dbus_interface_get_info         (GDBusInterface      *interface_) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusObject          *g_dbus_interface_get_object       (GDBusInterface      *interface_);
+GDBusObject          *g_dbus_interface_get_object       (GDBusInterface      *interface_) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                  g_dbus_interface_set_object       (GDBusInterface      *interface_,
-                                                         GDBusObject         *object);
+                                                         GDBusObject         *object) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_2_32
-GDBusObject          *g_dbus_interface_dup_object       (GDBusInterface      *interface_);
+GDBusObject          *g_dbus_interface_dup_object       (GDBusInterface      *interface_) TIZEN_PUBLIC_DEPRECATED_API;
 
 G_END_DECLS
 
index bf3b630..47f5ebe 100644 (file)
@@ -22,6 +22,7 @@
 #define __G_DBUS_INTERFACE_SKELETON_H__
 
 #include <gio/giotypes.h>
+#include <gio/tizen_header_glib.h>  /* for TIZEN_PUBLIC_DEPRECATED_API */
 
 G_BEGIN_DECLS
 
@@ -86,41 +87,41 @@ struct _GDBusInterfaceSkeletonClass
 };
 
 GLIB_AVAILABLE_IN_ALL
-GType                        g_dbus_interface_skeleton_get_type        (void) G_GNUC_CONST;
+GType                        g_dbus_interface_skeleton_get_type        (void) G_GNUC_CONST TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusInterfaceSkeletonFlags  g_dbus_interface_skeleton_get_flags       (GDBusInterfaceSkeleton      *interface_);
+GDBusInterfaceSkeletonFlags  g_dbus_interface_skeleton_get_flags       (GDBusInterfaceSkeleton      *interface_) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                         g_dbus_interface_skeleton_set_flags       (GDBusInterfaceSkeleton      *interface_,
-                                                                        GDBusInterfaceSkeletonFlags  flags);
+                                                                        GDBusInterfaceSkeletonFlags  flags) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusInterfaceInfo          *g_dbus_interface_skeleton_get_info        (GDBusInterfaceSkeleton      *interface_);
+GDBusInterfaceInfo          *g_dbus_interface_skeleton_get_info        (GDBusInterfaceSkeleton      *interface_) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusInterfaceVTable        *g_dbus_interface_skeleton_get_vtable      (GDBusInterfaceSkeleton      *interface_);
+GDBusInterfaceVTable        *g_dbus_interface_skeleton_get_vtable      (GDBusInterfaceSkeleton      *interface_) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GVariant                    *g_dbus_interface_skeleton_get_properties  (GDBusInterfaceSkeleton      *interface_);
+GVariant                    *g_dbus_interface_skeleton_get_properties  (GDBusInterfaceSkeleton      *interface_) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-void                         g_dbus_interface_skeleton_flush           (GDBusInterfaceSkeleton      *interface_);
+void                         g_dbus_interface_skeleton_flush           (GDBusInterfaceSkeleton      *interface_) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
 gboolean                     g_dbus_interface_skeleton_export          (GDBusInterfaceSkeleton      *interface_,
                                                                         GDBusConnection             *connection,
                                                                         const gchar                 *object_path,
-                                                                        GError                     **error);
+                                                                        GError                     **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-void                         g_dbus_interface_skeleton_unexport        (GDBusInterfaceSkeleton      *interface_);
+void                         g_dbus_interface_skeleton_unexport        (GDBusInterfaceSkeleton      *interface_) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                g_dbus_interface_skeleton_unexport_from_connection (GDBusInterfaceSkeleton      *interface_,
-                                                                        GDBusConnection             *connection);
+                                                                        GDBusConnection             *connection) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
-GDBusConnection             *g_dbus_interface_skeleton_get_connection  (GDBusInterfaceSkeleton      *interface_);
+GDBusConnection             *g_dbus_interface_skeleton_get_connection  (GDBusInterfaceSkeleton      *interface_) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GList                       *g_dbus_interface_skeleton_get_connections (GDBusInterfaceSkeleton      *interface_);
+GList                       *g_dbus_interface_skeleton_get_connections (GDBusInterfaceSkeleton      *interface_) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 gboolean                     g_dbus_interface_skeleton_has_connection  (GDBusInterfaceSkeleton      *interface_,
-                                                                        GDBusConnection             *connection);
+                                                                        GDBusConnection             *connection) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-const gchar                 *g_dbus_interface_skeleton_get_object_path (GDBusInterfaceSkeleton      *interface_);
+const gchar                 *g_dbus_interface_skeleton_get_object_path (GDBusInterfaceSkeleton      *interface_) TIZEN_PUBLIC_DEPRECATED_API;
 
 G_END_DECLS
 
index f2e2917..bd5c860 100644 (file)
@@ -26,6 +26,7 @@
 #endif
 
 #include <gio/giotypes.h>
+#include <gio/tizen_header_glib.h>  /* for TIZEN_PUBLIC_DEPRECATED_API */
 
 G_BEGIN_DECLS
 
@@ -181,66 +182,66 @@ struct _GDBusNodeInfo
 
 GLIB_AVAILABLE_IN_ALL
 const gchar        *g_dbus_annotation_info_lookup          (GDBusAnnotationInfo **annotations,
-                                                            const gchar          *name);
+                                                            const gchar          *name) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusMethodInfo    *g_dbus_interface_info_lookup_method    (GDBusInterfaceInfo   *info,
-                                                            const gchar          *name);
+                                                            const gchar          *name) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusSignalInfo    *g_dbus_interface_info_lookup_signal    (GDBusInterfaceInfo   *info,
-                                                            const gchar          *name);
+                                                            const gchar          *name) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusPropertyInfo  *g_dbus_interface_info_lookup_property  (GDBusInterfaceInfo   *info,
-                                                            const gchar          *name);
+                                                            const gchar          *name) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-void                g_dbus_interface_info_cache_build      (GDBusInterfaceInfo   *info);
+void                g_dbus_interface_info_cache_build      (GDBusInterfaceInfo   *info) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-void                g_dbus_interface_info_cache_release    (GDBusInterfaceInfo   *info);
+void                g_dbus_interface_info_cache_release    (GDBusInterfaceInfo   *info) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
 void                g_dbus_interface_info_generate_xml     (GDBusInterfaceInfo   *info,
                                                             guint                 indent,
-                                                            GString              *string_builder);
+                                                            GString              *string_builder) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
 GDBusNodeInfo      *g_dbus_node_info_new_for_xml           (const gchar          *xml_data,
-                                                            GError              **error);
+                                                            GError              **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusInterfaceInfo *g_dbus_node_info_lookup_interface      (GDBusNodeInfo        *info,
-                                                            const gchar          *name);
+                                                            const gchar          *name) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                g_dbus_node_info_generate_xml          (GDBusNodeInfo        *info,
                                                             guint                 indent,
-                                                            GString              *string_builder);
+                                                            GString              *string_builder) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
-GDBusNodeInfo       *g_dbus_node_info_ref                  (GDBusNodeInfo        *info);
+GDBusNodeInfo       *g_dbus_node_info_ref                  (GDBusNodeInfo        *info) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusInterfaceInfo  *g_dbus_interface_info_ref             (GDBusInterfaceInfo   *info);
+GDBusInterfaceInfo  *g_dbus_interface_info_ref             (GDBusInterfaceInfo   *info) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusMethodInfo     *g_dbus_method_info_ref                (GDBusMethodInfo      *info);
+GDBusMethodInfo     *g_dbus_method_info_ref                (GDBusMethodInfo      *info) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusSignalInfo     *g_dbus_signal_info_ref                (GDBusSignalInfo      *info);
+GDBusSignalInfo     *g_dbus_signal_info_ref                (GDBusSignalInfo      *info) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusPropertyInfo   *g_dbus_property_info_ref              (GDBusPropertyInfo    *info);
+GDBusPropertyInfo   *g_dbus_property_info_ref              (GDBusPropertyInfo    *info) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusArgInfo        *g_dbus_arg_info_ref                   (GDBusArgInfo         *info);
+GDBusArgInfo        *g_dbus_arg_info_ref                   (GDBusArgInfo         *info) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusAnnotationInfo *g_dbus_annotation_info_ref            (GDBusAnnotationInfo  *info);
+GDBusAnnotationInfo *g_dbus_annotation_info_ref            (GDBusAnnotationInfo  *info) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
-void                 g_dbus_node_info_unref                (GDBusNodeInfo        *info);
+void                 g_dbus_node_info_unref                (GDBusNodeInfo        *info) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-void                 g_dbus_interface_info_unref           (GDBusInterfaceInfo   *info);
+void                 g_dbus_interface_info_unref           (GDBusInterfaceInfo   *info) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-void                 g_dbus_method_info_unref              (GDBusMethodInfo      *info);
+void                 g_dbus_method_info_unref              (GDBusMethodInfo      *info) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-void                 g_dbus_signal_info_unref              (GDBusSignalInfo      *info);
+void                 g_dbus_signal_info_unref              (GDBusSignalInfo      *info) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-void                 g_dbus_property_info_unref            (GDBusPropertyInfo    *info);
+void                 g_dbus_property_info_unref            (GDBusPropertyInfo    *info) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-void                 g_dbus_arg_info_unref                 (GDBusArgInfo         *info);
+void                 g_dbus_arg_info_unref                 (GDBusArgInfo         *info) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-void                 g_dbus_annotation_info_unref          (GDBusAnnotationInfo  *info);
+void                 g_dbus_annotation_info_unref          (GDBusAnnotationInfo  *info) TIZEN_PUBLIC_DEPRECATED_API;
 
 /**
  * G_TYPE_DBUS_NODE_INFO:
@@ -306,19 +307,19 @@ void                 g_dbus_annotation_info_unref          (GDBusAnnotationInfo
 #define G_TYPE_DBUS_ANNOTATION_INFO (g_dbus_annotation_info_get_type ())
 
 GLIB_AVAILABLE_IN_ALL
-GType g_dbus_node_info_get_type       (void) G_GNUC_CONST;
+GType g_dbus_node_info_get_type       (void) G_GNUC_CONST TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GType g_dbus_interface_info_get_type  (void) G_GNUC_CONST;
+GType g_dbus_interface_info_get_type  (void) G_GNUC_CONST TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GType g_dbus_method_info_get_type     (void) G_GNUC_CONST;
+GType g_dbus_method_info_get_type     (void) G_GNUC_CONST TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GType g_dbus_signal_info_get_type     (void) G_GNUC_CONST;
+GType g_dbus_signal_info_get_type     (void) G_GNUC_CONST TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GType g_dbus_property_info_get_type   (void) G_GNUC_CONST;
+GType g_dbus_property_info_get_type   (void) G_GNUC_CONST TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GType g_dbus_arg_info_get_type        (void) G_GNUC_CONST;
+GType g_dbus_arg_info_get_type        (void) G_GNUC_CONST TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GType g_dbus_annotation_info_get_type (void) G_GNUC_CONST;
+GType g_dbus_annotation_info_get_type (void) G_GNUC_CONST TIZEN_PUBLIC_DEPRECATED_API;
 
 G_END_DECLS
 
index dd2882d..920cef0 100644 (file)
@@ -21,6 +21,7 @@
 #define __G_DBUS_MENU_MODEL_H__
 
 #include <gio/gdbusconnection.h>
+#include <gio/tizen_header_glib.h>  /* for TIZEN_PUBLIC_DEPRECATED_API */
 
 G_BEGIN_DECLS
 
@@ -33,12 +34,12 @@ G_BEGIN_DECLS
 typedef struct _GDBusMenuModel GDBusMenuModel;
 
 GLIB_AVAILABLE_IN_ALL
-GType                   g_dbus_menu_model_get_type     (void) G_GNUC_CONST;
+GType                   g_dbus_menu_model_get_type     (void) G_GNUC_CONST TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
 GDBusMenuModel *        g_dbus_menu_model_get          (GDBusConnection *connection,
                                                         const gchar     *bus_name,
-                                                        const gchar     *object_path);
+                                                        const gchar     *object_path) TIZEN_PUBLIC_DEPRECATED_API;
 
 G_END_DECLS
 
index cdc0b83..4059f7f 100644 (file)
@@ -3734,3 +3734,10 @@ g_dbus_message_copy (GDBusMessage  *message,
 #endif
   return ret;
 }
+
+void
+g_dbus_message_init_header_iter (GDBusMessage   *message,
+                                 GHashTableIter *iter)
+{
+  g_hash_table_iter_init (iter, message->headers);
+}
index 5f039dc..6e9cddd 100644 (file)
@@ -26,6 +26,7 @@
 #endif
 
 #include <gio/giotypes.h>
+#include <gio/tizen_header_glib.h>  /* for TIZEN_PUBLIC_DEPRECATED_API */
 
 G_BEGIN_DECLS
 
@@ -34,163 +35,163 @@ G_BEGIN_DECLS
 #define G_IS_DBUS_MESSAGE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DBUS_MESSAGE))
 
 GLIB_AVAILABLE_IN_ALL
-GType                     g_dbus_message_get_type           (void) G_GNUC_CONST;
+GType                     g_dbus_message_get_type           (void) G_GNUC_CONST TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusMessage             *g_dbus_message_new                (void);
+GDBusMessage             *g_dbus_message_new                (void) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusMessage             *g_dbus_message_new_signal         (const gchar              *path,
                                                              const gchar              *interface_,
-                                                             const gchar              *signal);
+                                                             const gchar              *signal) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusMessage             *g_dbus_message_new_method_call    (const gchar              *name,
                                                              const gchar              *path,
                                                              const gchar              *interface_,
-                                                             const gchar              *method);
+                                                             const gchar              *method) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusMessage             *g_dbus_message_new_method_reply   (GDBusMessage             *method_call_message);
+GDBusMessage             *g_dbus_message_new_method_reply   (GDBusMessage             *method_call_message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusMessage             *g_dbus_message_new_method_error   (GDBusMessage             *method_call_message,
                                                              const gchar              *error_name,
                                                              const gchar              *error_message_format,
-                                                             ...) G_GNUC_PRINTF(3, 4);
+                                                             ...) G_GNUC_PRINTF(3, 4) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusMessage             *g_dbus_message_new_method_error_valist (GDBusMessage             *method_call_message,
                                                                   const gchar              *error_name,
                                                                   const gchar              *error_message_format,
-                                                                  va_list                   var_args);
+                                                                  va_list                   var_args) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusMessage             *g_dbus_message_new_method_error_literal (GDBusMessage             *method_call_message,
                                                                    const gchar              *error_name,
-                                                                   const gchar              *error_message);
+                                                                   const gchar              *error_message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 gchar                    *g_dbus_message_print              (GDBusMessage             *message,
-                                                             guint                     indent);
+                                                             guint                     indent) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-gboolean                  g_dbus_message_get_locked         (GDBusMessage             *message);
+gboolean                  g_dbus_message_get_locked         (GDBusMessage             *message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-void                      g_dbus_message_lock               (GDBusMessage             *message);
+void                      g_dbus_message_lock               (GDBusMessage             *message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusMessage             *g_dbus_message_copy               (GDBusMessage             *message,
-                                                             GError                  **error);
+                                                             GError                  **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusMessageByteOrder     g_dbus_message_get_byte_order     (GDBusMessage             *message);
+GDBusMessageByteOrder     g_dbus_message_get_byte_order     (GDBusMessage             *message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                      g_dbus_message_set_byte_order     (GDBusMessage             *message,
-                                                             GDBusMessageByteOrder     byte_order);
+                                                             GDBusMessageByteOrder     byte_order) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
-GDBusMessageType          g_dbus_message_get_message_type   (GDBusMessage             *message);
+GDBusMessageType          g_dbus_message_get_message_type   (GDBusMessage             *message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                      g_dbus_message_set_message_type   (GDBusMessage             *message,
-                                                             GDBusMessageType          type);
+                                                             GDBusMessageType          type) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusMessageFlags         g_dbus_message_get_flags          (GDBusMessage             *message);
+GDBusMessageFlags         g_dbus_message_get_flags          (GDBusMessage             *message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                      g_dbus_message_set_flags          (GDBusMessage             *message,
-                                                             GDBusMessageFlags         flags);
+                                                             GDBusMessageFlags         flags) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-guint32                   g_dbus_message_get_serial         (GDBusMessage             *message);
+guint32                   g_dbus_message_get_serial         (GDBusMessage             *message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                      g_dbus_message_set_serial         (GDBusMessage             *message,
-                                                             guint32                   serial);
+                                                             guint32                   serial) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GVariant                 *g_dbus_message_get_header         (GDBusMessage             *message,
-                                                             GDBusMessageHeaderField   header_field);
+                                                             GDBusMessageHeaderField   header_field) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                      g_dbus_message_set_header         (GDBusMessage             *message,
                                                              GDBusMessageHeaderField   header_field,
-                                                             GVariant                 *value);
+                                                             GVariant                 *value) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-guchar                   *g_dbus_message_get_header_fields  (GDBusMessage             *message);
+guchar                   *g_dbus_message_get_header_fields  (GDBusMessage             *message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GVariant                 *g_dbus_message_get_body           (GDBusMessage             *message);
+GVariant                 *g_dbus_message_get_body           (GDBusMessage             *message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                      g_dbus_message_set_body           (GDBusMessage             *message,
-                                                             GVariant                 *body);
+                                                             GVariant                 *body) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GUnixFDList              *g_dbus_message_get_unix_fd_list   (GDBusMessage             *message);
+GUnixFDList              *g_dbus_message_get_unix_fd_list   (GDBusMessage             *message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                      g_dbus_message_set_unix_fd_list   (GDBusMessage             *message,
-                                                             GUnixFDList              *fd_list);
+                                                             GUnixFDList              *fd_list) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
-guint32                   g_dbus_message_get_reply_serial   (GDBusMessage             *message);
+guint32                   g_dbus_message_get_reply_serial   (GDBusMessage             *message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                      g_dbus_message_set_reply_serial   (GDBusMessage             *message,
-                                                             guint32                   value);
+                                                             guint32                   value) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
-const gchar              *g_dbus_message_get_interface      (GDBusMessage             *message);
+const gchar              *g_dbus_message_get_interface      (GDBusMessage             *message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                      g_dbus_message_set_interface      (GDBusMessage             *message,
-                                                             const gchar              *value);
+                                                             const gchar              *value) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
-const gchar              *g_dbus_message_get_member         (GDBusMessage             *message);
+const gchar              *g_dbus_message_get_member         (GDBusMessage             *message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                      g_dbus_message_set_member         (GDBusMessage             *message,
-                                                             const gchar              *value);
+                                                             const gchar              *value) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
-const gchar              *g_dbus_message_get_path           (GDBusMessage             *message);
+const gchar              *g_dbus_message_get_path           (GDBusMessage             *message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                      g_dbus_message_set_path           (GDBusMessage             *message,
-                                                             const gchar              *value);
+                                                             const gchar              *value) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
-const gchar              *g_dbus_message_get_sender         (GDBusMessage             *message);
+const gchar              *g_dbus_message_get_sender         (GDBusMessage             *message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                      g_dbus_message_set_sender         (GDBusMessage             *message,
-                                                             const gchar              *value);
+                                                             const gchar              *value) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
-const gchar              *g_dbus_message_get_destination    (GDBusMessage             *message);
+const gchar              *g_dbus_message_get_destination    (GDBusMessage             *message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                      g_dbus_message_set_destination    (GDBusMessage             *message,
-                                                             const gchar              *value);
+                                                             const gchar              *value) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
-const gchar              *g_dbus_message_get_error_name     (GDBusMessage             *message);
+const gchar              *g_dbus_message_get_error_name     (GDBusMessage             *message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                      g_dbus_message_set_error_name     (GDBusMessage             *message,
-                                                             const gchar              *value);
+                                                             const gchar              *value) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
-const gchar              *g_dbus_message_get_signature      (GDBusMessage             *message);
+const gchar              *g_dbus_message_get_signature      (GDBusMessage             *message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                      g_dbus_message_set_signature      (GDBusMessage             *message,
-                                                             const gchar              *value);
+                                                             const gchar              *value) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
-guint32                   g_dbus_message_get_num_unix_fds   (GDBusMessage             *message);
+guint32                   g_dbus_message_get_num_unix_fds   (GDBusMessage             *message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                      g_dbus_message_set_num_unix_fds   (GDBusMessage             *message,
-                                                             guint32                   value);
+                                                             guint32                   value) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
-const gchar              *g_dbus_message_get_arg0           (GDBusMessage             *message);
+const gchar              *g_dbus_message_get_arg0           (GDBusMessage             *message) TIZEN_PUBLIC_DEPRECATED_API;
 
 
 GLIB_AVAILABLE_IN_ALL
 GDBusMessage             *g_dbus_message_new_from_blob      (guchar                   *blob,
                                                              gsize                     blob_len,
                                                              GDBusCapabilityFlags      capabilities,
-                                                             GError                  **error);
+                                                             GError                  **error) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
 gssize                    g_dbus_message_bytes_needed       (guchar                   *blob,
                                                              gsize                     blob_len,
-                                                             GError                  **error);
+                                                             GError                  **error) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
 guchar                   *g_dbus_message_to_blob            (GDBusMessage             *message,
                                                              gsize                    *out_size,
                                                              GDBusCapabilityFlags      capabilities,
-                                                             GError                  **error);
+                                                             GError                  **error) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
 gboolean                  g_dbus_message_to_gerror          (GDBusMessage             *message,
-                                                             GError                  **error);
+                                                             GError                  **error) TIZEN_PUBLIC_DEPRECATED_API;
 
 G_END_DECLS
 
index c22e19e..09d3d7c 100644 (file)
@@ -309,6 +309,44 @@ g_dbus_method_invocation_get_parameters (GDBusMethodInvocation *invocation)
 }
 
 /**
+ * g_dbus_method_invocation_peek_unix_fd:
+ * @invocation: A #GDBusMethodInvocation.
+ * @index_: the index
+ *
+ * Gets the fd associated with @index in the method invocation.
+ *
+ * If there is no file descriptor at the given index, -1 is returned.
+ *
+ * The returned file descriptor is owned by the message and must not be
+ * closed by the caller.  Use dup() if you want your own copy.
+ *
+ * Returns: the file descriptor, or -1
+ */
+#ifdef G_OS_UNIX
+gint
+g_dbus_method_invocation_peek_unix_fd (GDBusMethodInvocation *invocation,
+                                       guint                  index_)
+{
+  GUnixFDList *fd_list;
+
+  fd_list = g_dbus_message_get_unix_fd_list (invocation->message);
+
+  if (fd_list)
+    {
+      const gint *fds;
+      gint n_fds;
+
+      fds = g_unix_fd_list_peek_fds (fd_list, &n_fds);
+
+      if (index_ < (guint) n_fds)
+        return fds[index_];
+    }
+
+  return -1;
+}
+#endif
+
+/**
  * g_dbus_method_invocation_get_user_data: (skip)
  * @invocation: A #GDBusMethodInvocation.
  *
index 775070a..2ec68e1 100644 (file)
@@ -26,6 +26,7 @@
 #endif
 
 #include <gio/giotypes.h>
+#include <gio/tizen_header_glib.h>  /* for TIZEN_PUBLIC_DEPRECATED_API */
 
 G_BEGIN_DECLS
 
@@ -69,63 +70,68 @@ G_BEGIN_DECLS
 #define G_DBUS_METHOD_INVOCATION_UNHANDLED FALSE GLIB_AVAILABLE_MACRO_IN_2_68
 
 GLIB_AVAILABLE_IN_ALL
-GType                  g_dbus_method_invocation_get_type             (void) G_GNUC_CONST;
+GType                  g_dbus_method_invocation_get_type             (void) G_GNUC_CONST TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-const gchar           *g_dbus_method_invocation_get_sender           (GDBusMethodInvocation *invocation);
+const gchar           *g_dbus_method_invocation_get_sender           (GDBusMethodInvocation *invocation) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-const gchar           *g_dbus_method_invocation_get_object_path      (GDBusMethodInvocation *invocation);
+const gchar           *g_dbus_method_invocation_get_object_path      (GDBusMethodInvocation *invocation) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-const gchar           *g_dbus_method_invocation_get_interface_name   (GDBusMethodInvocation *invocation);
+const gchar           *g_dbus_method_invocation_get_interface_name   (GDBusMethodInvocation *invocation) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-const gchar           *g_dbus_method_invocation_get_method_name      (GDBusMethodInvocation *invocation);
+const gchar           *g_dbus_method_invocation_get_method_name      (GDBusMethodInvocation *invocation) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-const GDBusMethodInfo *g_dbus_method_invocation_get_method_info      (GDBusMethodInvocation *invocation);
+const GDBusMethodInfo *g_dbus_method_invocation_get_method_info      (GDBusMethodInvocation *invocation) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_2_38
-const GDBusPropertyInfo *g_dbus_method_invocation_get_property_info  (GDBusMethodInvocation *invocation);
+const GDBusPropertyInfo *g_dbus_method_invocation_get_property_info  (GDBusMethodInvocation *invocation) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusConnection       *g_dbus_method_invocation_get_connection       (GDBusMethodInvocation *invocation);
+GDBusConnection       *g_dbus_method_invocation_get_connection       (GDBusMethodInvocation *invocation) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusMessage          *g_dbus_method_invocation_get_message          (GDBusMethodInvocation *invocation);
+GDBusMessage          *g_dbus_method_invocation_get_message          (GDBusMethodInvocation *invocation) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GVariant              *g_dbus_method_invocation_get_parameters       (GDBusMethodInvocation *invocation);
+GVariant              *g_dbus_method_invocation_get_parameters       (GDBusMethodInvocation *invocation) TIZEN_PUBLIC_DEPRECATED_API;
+#ifdef G_OS_UNIX
+GLIB_AVAILABLE_IN_2_44
+gint                   g_dbus_method_invocation_peek_unix_fd         (GDBusMethodInvocation *invocation,
+                                                                      guint                  index_) TIZEN_PUBLIC_DEPRECATED_API;
+#endif
 GLIB_AVAILABLE_IN_ALL
-gpointer               g_dbus_method_invocation_get_user_data        (GDBusMethodInvocation *invocation);
+gpointer               g_dbus_method_invocation_get_user_data        (GDBusMethodInvocation *invocation) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
 void                   g_dbus_method_invocation_return_value         (GDBusMethodInvocation *invocation,
-                                                                      GVariant              *parameters);
+                                                                      GVariant              *parameters) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                   g_dbus_method_invocation_return_value_with_unix_fd_list (GDBusMethodInvocation *invocation,
                                                                                 GVariant              *parameters,
-                                                                                GUnixFDList           *fd_list);
+                                                                                GUnixFDList           *fd_list) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                   g_dbus_method_invocation_return_error         (GDBusMethodInvocation *invocation,
                                                                       GQuark                 domain,
                                                                       gint                   code,
                                                                       const gchar           *format,
-                                                                      ...) G_GNUC_PRINTF(4, 5);
+                                                                      ...) G_GNUC_PRINTF(4, 5) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                   g_dbus_method_invocation_return_error_valist  (GDBusMethodInvocation *invocation,
                                                                       GQuark                 domain,
                                                                       gint                   code,
                                                                       const gchar           *format,
                                                                       va_list                var_args)
-                                                                      G_GNUC_PRINTF(4, 0);
+                                                                      G_GNUC_PRINTF(4, 0) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                   g_dbus_method_invocation_return_error_literal (GDBusMethodInvocation *invocation,
                                                                       GQuark                 domain,
                                                                       gint                   code,
-                                                                      const gchar           *message);
+                                                                      const gchar           *message) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                   g_dbus_method_invocation_return_gerror        (GDBusMethodInvocation *invocation,
-                                                                      const GError          *error);
+                                                                      const GError          *error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                   g_dbus_method_invocation_take_error           (GDBusMethodInvocation *invocation,
-                                                                      GError                *error);
+                                                                      GError                *error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                   g_dbus_method_invocation_return_dbus_error    (GDBusMethodInvocation *invocation,
                                                                       const gchar           *error_name,
-                                                                      const gchar           *error_message);
+                                                                      const gchar           *error_message) TIZEN_PUBLIC_DEPRECATED_API;
 
 G_END_DECLS
 
index 89c011a..2bfbe23 100644 (file)
@@ -26,6 +26,7 @@
 #endif
 
 #include <gio/giotypes.h>
+#include <gio/tizen_header_glib.h>  /* for TIZEN_PUBLIC_DEPRECATED_API */
 
 G_BEGIN_DECLS
 
@@ -80,7 +81,7 @@ guint g_bus_own_name                 (GBusType                  bus_type,
                                       GBusNameAcquiredCallback  name_acquired_handler,
                                       GBusNameLostCallback      name_lost_handler,
                                       gpointer                  user_data,
-                                      GDestroyNotify            user_data_free_func);
+                                      GDestroyNotify            user_data_free_func) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
 guint g_bus_own_name_on_connection   (GDBusConnection          *connection,
@@ -89,7 +90,7 @@ guint g_bus_own_name_on_connection   (GDBusConnection          *connection,
                                       GBusNameAcquiredCallback  name_acquired_handler,
                                       GBusNameLostCallback      name_lost_handler,
                                       gpointer                  user_data,
-                                      GDestroyNotify            user_data_free_func);
+                                      GDestroyNotify            user_data_free_func) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
 guint g_bus_own_name_with_closures   (GBusType                  bus_type,
@@ -97,7 +98,7 @@ guint g_bus_own_name_with_closures   (GBusType                  bus_type,
                                       GBusNameOwnerFlags        flags,
                                       GClosure                 *bus_acquired_closure,
                                       GClosure                 *name_acquired_closure,
-                                      GClosure                 *name_lost_closure);
+                                      GClosure                 *name_lost_closure) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
 guint g_bus_own_name_on_connection_with_closures (
@@ -105,10 +106,10 @@ guint g_bus_own_name_on_connection_with_closures (
                                       const gchar              *name,
                                       GBusNameOwnerFlags        flags,
                                       GClosure                 *name_acquired_closure,
-                                      GClosure                 *name_lost_closure);
+                                      GClosure                 *name_lost_closure) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
-void  g_bus_unown_name               (guint                     owner_id);
+void  g_bus_unown_name               (guint                     owner_id) TIZEN_PUBLIC_DEPRECATED_API;
 
 G_END_DECLS
 
old mode 100644 (file)
new mode 100755 (executable)
index d4272e4..ef6481f
@@ -351,9 +351,6 @@ on_name_owner_changed (GDBusConnection *connection,
   if (client == NULL)
     return;
 
-  if (!client->initialized)
-    goto out;
-
   if (g_strcmp0 (object_path, "/org/freedesktop/DBus") != 0 ||
       g_strcmp0 (interface_name, "org.freedesktop.DBus") != 0 ||
       g_strcmp0 (sender_name, "org.freedesktop.DBus") != 0)
@@ -369,7 +366,7 @@ on_name_owner_changed (GDBusConnection *connection,
   if (g_strcmp0 (name, client->name) != 0)
     goto out;
 
-  if ((old_owner != NULL && strlen (old_owner) > 0) && client->name_owner != NULL)
+  if (old_owner != NULL && strlen (old_owner) > 0)
     {
       g_free (client->name_owner);
       client->name_owner = NULL;
@@ -378,12 +375,18 @@ on_name_owner_changed (GDBusConnection *connection,
 
   if (new_owner != NULL && strlen (new_owner) > 0)
     {
-      g_warn_if_fail (client->name_owner == NULL);
       g_free (client->name_owner);
       client->name_owner = g_strdup (new_owner);
       call_appeared_handler (client);
     }
 
+  /* initialized set to TRUE means that signal was delivered and processed.
+   * Now, if we receive a reply to GetNameOwner call, we may just ignore it as it carries the same
+   * information as the current signal, or if something changed in the meantime we will
+   * get next signal very soon.
+   */
+  client->initialized = TRUE;
+
  out:
   client_unref (client);
 }
@@ -405,6 +408,13 @@ get_name_owner_cb (GObject      *source_object,
   result = g_dbus_connection_call_finish (client->connection,
                                           res,
                                           NULL);
+  /* In case we already received NameOwnerChanged signal, we don't need to
+   * process GetNameOwner answer, because all the information we needed was already
+   * delivered with the signal and processed by the signal handler.
+   */
+  if (client->initialized)
+    goto out;
+
   if (result != NULL)
     {
       g_variant_get (result, "(&s)", &name_owner);
@@ -421,10 +431,10 @@ get_name_owner_cb (GObject      *source_object,
       call_vanished_handler (client);
     }
 
-  client->initialized = TRUE;
-
+ out:
   if (result != NULL)
     g_variant_unref (result);
+
   client_unref (client);
 }
 
index 19d57f2..9d9d0ad 100644 (file)
@@ -26,6 +26,7 @@
 #endif
 
 #include <gio/giotypes.h>
+#include <gio/tizen_header_glib.h>  /* for TIZEN_PUBLIC_DEPRECATED_API */
 
 G_BEGIN_DECLS
 
@@ -72,7 +73,7 @@ guint g_bus_watch_name               (GBusType                  bus_type,
                                       GBusNameAppearedCallback  name_appeared_handler,
                                       GBusNameVanishedCallback  name_vanished_handler,
                                       gpointer                  user_data,
-                                      GDestroyNotify            user_data_free_func);
+                                      GDestroyNotify            user_data_free_func) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 guint g_bus_watch_name_on_connection (GDBusConnection          *connection,
                                       const gchar              *name,
@@ -80,22 +81,22 @@ guint g_bus_watch_name_on_connection (GDBusConnection          *connection,
                                       GBusNameAppearedCallback  name_appeared_handler,
                                       GBusNameVanishedCallback  name_vanished_handler,
                                       gpointer                  user_data,
-                                      GDestroyNotify            user_data_free_func);
+                                      GDestroyNotify            user_data_free_func) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 guint g_bus_watch_name_with_closures (GBusType                  bus_type,
                                       const gchar              *name,
                                       GBusNameWatcherFlags      flags,
                                       GClosure                 *name_appeared_closure,
-                                      GClosure                 *name_vanished_closure);
+                                      GClosure                 *name_vanished_closure) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 guint g_bus_watch_name_on_connection_with_closures (
                                       GDBusConnection          *connection,
                                       const gchar              *name,
                                       GBusNameWatcherFlags      flags,
                                       GClosure                 *name_appeared_closure,
-                                      GClosure                 *name_vanished_closure);
+                                      GClosure                 *name_vanished_closure) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-void  g_bus_unwatch_name             (guint                     watcher_id);
+void  g_bus_unwatch_name             (guint                     watcher_id) TIZEN_PUBLIC_DEPRECATED_API;
 
 G_END_DECLS
 
index 157c52b..1dfab29 100644 (file)
@@ -22,6 +22,7 @@
 #define __G_DBUS_OBJECT_H__
 
 #include <gio/giotypes.h>
+#include <gio/tizen_header_glib.h>  /* for TIZEN_PUBLIC_DEPRECATED_API */
 
 G_BEGIN_DECLS
 
@@ -64,14 +65,14 @@ struct _GDBusObjectIface
 };
 
 GLIB_AVAILABLE_IN_ALL
-GType            g_dbus_object_get_type        (void) G_GNUC_CONST;
+GType            g_dbus_object_get_type        (void) G_GNUC_CONST TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-const gchar     *g_dbus_object_get_object_path (GDBusObject  *object);
+const gchar     *g_dbus_object_get_object_path (GDBusObject  *object) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GList           *g_dbus_object_get_interfaces  (GDBusObject  *object);
+GList           *g_dbus_object_get_interfaces  (GDBusObject  *object) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusInterface  *g_dbus_object_get_interface   (GDBusObject  *object,
-                                                const gchar  *interface_name);
+                                                const gchar  *interface_name) TIZEN_PUBLIC_DEPRECATED_API;
 
 G_END_DECLS
 
index 260ae2e..f390f2c 100644 (file)
@@ -22,6 +22,7 @@
 #define __G_DBUS_OBJECT_MANAGER_H__
 
 #include <gio/giotypes.h>
+#include <gio/tizen_header_glib.h>  /* for TIZEN_PUBLIC_DEPRECATED_API */
 
 G_BEGIN_DECLS
 
@@ -76,18 +77,18 @@ struct _GDBusObjectManagerIface
 };
 
 GLIB_AVAILABLE_IN_ALL
-GType            g_dbus_object_manager_get_type        (void) G_GNUC_CONST;
+GType            g_dbus_object_manager_get_type        (void) G_GNUC_CONST TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-const gchar     *g_dbus_object_manager_get_object_path (GDBusObjectManager    *manager);
+const gchar     *g_dbus_object_manager_get_object_path (GDBusObjectManager    *manager) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GList           *g_dbus_object_manager_get_objects     (GDBusObjectManager    *manager);
+GList           *g_dbus_object_manager_get_objects     (GDBusObjectManager    *manager) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusObject     *g_dbus_object_manager_get_object      (GDBusObjectManager    *manager,
-                                                        const gchar           *object_path);
+                                                        const gchar           *object_path) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusInterface  *g_dbus_object_manager_get_interface   (GDBusObjectManager    *manager,
                                                         const gchar           *object_path,
-                                                        const gchar           *interface_name);
+                                                        const gchar           *interface_name) TIZEN_PUBLIC_DEPRECATED_API;
 
 G_END_DECLS
 
index 04c5599..cd9322c 100644 (file)
@@ -1131,7 +1131,6 @@ subscribe_signals (GDBusObjectManagerClient *manager,
                    const gchar *name_owner)
 {
   GError *error = NULL;
-  GVariant *ret;
 
   g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager));
   g_return_if_fail (manager->priv->signal_subscription_id == 0);
@@ -1157,22 +1156,7 @@ subscribe_signals (GDBusObjectManagerClient *manager,
 
       /* The bus daemon may not implement path_namespace so gracefully
        * handle this by using a fallback triggered if @error is set. */
-      ret = g_dbus_connection_call_sync (manager->priv->connection,
-                                         "org.freedesktop.DBus",
-                                         "/org/freedesktop/DBus",
-                                         "org.freedesktop.DBus",
-                                         "AddMatch",
-                                         g_variant_new ("(s)",
-                                                        manager->priv->match_rule),
-                                         NULL, /* reply_type */
-                                         G_DBUS_CALL_FLAGS_NONE,
-                                         -1, /* default timeout */
-                                         NULL, /* TODO: Cancellable */
-                                         &error);
-
-      /* yay, bus daemon supports path_namespace */
-      if (ret != NULL)
-        g_variant_unref (ret);
+      g_dbus_add_match (manager->priv->connection, manager->priv->match_rule, &error);
     }
 
   if (error == NULL)
@@ -1242,19 +1226,9 @@ maybe_unsubscribe_signals (GDBusObjectManagerClient *manager)
       /* Since the AddMatch call succeeded this is guaranteed to not
        * fail - therefore, don't bother checking the return value
        */
-      g_dbus_connection_call (manager->priv->connection,
-                              "org.freedesktop.DBus",
-                              "/org/freedesktop/DBus",
-                              "org.freedesktop.DBus",
-                              "RemoveMatch",
-                              g_variant_new ("(s)",
-                                             manager->priv->match_rule),
-                              NULL, /* reply_type */
-                              G_DBUS_CALL_FLAGS_NONE,
-                              -1, /* default timeout */
-                              NULL, /* GCancellable */
-                              NULL, /* GAsyncReadyCallback */
-                              NULL); /* user data */
+      g_dbus_remove_match (manager->priv->connection,
+                           manager->priv->match_rule,
+                           NULL);
       g_free (manager->priv->match_rule);
       manager->priv->match_rule = NULL;
     }
index eafabfb..57aa8e9 100644 (file)
@@ -22,6 +22,7 @@
 #define __G_DBUS_OBJECT_MANAGER_CLIENT_H__
 
 #include <gio/giotypes.h>
+#include <gio/tizen_header_glib.h>  /* for TIZEN_PUBLIC_DEPRECATED_API */
 
 G_BEGIN_DECLS
 
@@ -83,7 +84,7 @@ struct _GDBusObjectManagerClientClass
 };
 
 GLIB_AVAILABLE_IN_ALL
-GType                         g_dbus_object_manager_client_get_type           (void) G_GNUC_CONST;
+GType                         g_dbus_object_manager_client_get_type           (void) G_GNUC_CONST TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                          g_dbus_object_manager_client_new                (GDBusConnection               *connection,
                                                                                GDBusObjectManagerClientFlags  flags,
@@ -94,10 +95,10 @@ void                          g_dbus_object_manager_client_new                (G
                                                                                GDestroyNotify                 get_proxy_type_destroy_notify,
                                                                                GCancellable                  *cancellable,
                                                                                GAsyncReadyCallback            callback,
-                                                                               gpointer                       user_data);
+                                                                               gpointer                       user_data) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusObjectManager           *g_dbus_object_manager_client_new_finish         (GAsyncResult                  *res,
-                                                                               GError                       **error);
+                                                                               GError                       **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusObjectManager           *g_dbus_object_manager_client_new_sync           (GDBusConnection               *connection,
                                                                                GDBusObjectManagerClientFlags  flags,
@@ -107,7 +108,7 @@ GDBusObjectManager           *g_dbus_object_manager_client_new_sync           (G
                                                                                gpointer                       get_proxy_type_user_data,
                                                                                GDestroyNotify                 get_proxy_type_destroy_notify,
                                                                                GCancellable                  *cancellable,
-                                                                               GError                       **error);
+                                                                               GError                       **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                          g_dbus_object_manager_client_new_for_bus        (GBusType                       bus_type,
                                                                                GDBusObjectManagerClientFlags  flags,
@@ -118,10 +119,10 @@ void                          g_dbus_object_manager_client_new_for_bus        (G
                                                                                GDestroyNotify                 get_proxy_type_destroy_notify,
                                                                                GCancellable                  *cancellable,
                                                                                GAsyncReadyCallback            callback,
-                                                                               gpointer                       user_data);
+                                                                               gpointer                       user_data) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusObjectManager           *g_dbus_object_manager_client_new_for_bus_finish (GAsyncResult                  *res,
-                                                                               GError                       **error);
+                                                                               GError                       **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusObjectManager           *g_dbus_object_manager_client_new_for_bus_sync   (GBusType                       bus_type,
                                                                                GDBusObjectManagerClientFlags  flags,
@@ -131,15 +132,15 @@ GDBusObjectManager           *g_dbus_object_manager_client_new_for_bus_sync   (G
                                                                                gpointer                       get_proxy_type_user_data,
                                                                                GDestroyNotify                 get_proxy_type_destroy_notify,
                                                                                GCancellable                  *cancellable,
-                                                                               GError                       **error);
+                                                                               GError                       **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusConnection              *g_dbus_object_manager_client_get_connection     (GDBusObjectManagerClient      *manager);
+GDBusConnection              *g_dbus_object_manager_client_get_connection     (GDBusObjectManagerClient      *manager) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusObjectManagerClientFlags g_dbus_object_manager_client_get_flags          (GDBusObjectManagerClient      *manager);
+GDBusObjectManagerClientFlags g_dbus_object_manager_client_get_flags          (GDBusObjectManagerClient      *manager) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-const gchar                  *g_dbus_object_manager_client_get_name           (GDBusObjectManagerClient      *manager);
+const gchar                  *g_dbus_object_manager_client_get_name           (GDBusObjectManagerClient      *manager) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-gchar                        *g_dbus_object_manager_client_get_name_owner     (GDBusObjectManagerClient      *manager);
+gchar                        *g_dbus_object_manager_client_get_name_owner     (GDBusObjectManagerClient      *manager) TIZEN_PUBLIC_DEPRECATED_API;
 
 G_END_DECLS
 
index dd725b7..4fe085f 100644 (file)
@@ -22,6 +22,7 @@
 #define __G_DBUS_OBJECT_MANAGER_SERVER_H__
 
 #include <gio/giotypes.h>
+#include <gio/tizen_header_glib.h>  /* for TIZEN_PUBLIC_DEPRECATED_API */
 
 G_BEGIN_DECLS
 
@@ -67,26 +68,26 @@ struct _GDBusObjectManagerServerClass
 };
 
 GLIB_AVAILABLE_IN_ALL
-GType                     g_dbus_object_manager_server_get_type            (void) G_GNUC_CONST;
+GType                     g_dbus_object_manager_server_get_type            (void) G_GNUC_CONST TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusObjectManagerServer *g_dbus_object_manager_server_new                 (const gchar               *object_path);
+GDBusObjectManagerServer *g_dbus_object_manager_server_new                 (const gchar               *object_path) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusConnection          *g_dbus_object_manager_server_get_connection      (GDBusObjectManagerServer  *manager);
+GDBusConnection          *g_dbus_object_manager_server_get_connection      (GDBusObjectManagerServer  *manager) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                      g_dbus_object_manager_server_set_connection      (GDBusObjectManagerServer  *manager,
-                                                                            GDBusConnection           *connection);
+                                                                            GDBusConnection           *connection) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                      g_dbus_object_manager_server_export              (GDBusObjectManagerServer  *manager,
-                                                                            GDBusObjectSkeleton       *object);
+                                                                            GDBusObjectSkeleton       *object) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void                      g_dbus_object_manager_server_export_uniquely     (GDBusObjectManagerServer  *manager,
-                                                                            GDBusObjectSkeleton       *object);
+                                                                            GDBusObjectSkeleton       *object) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 gboolean                  g_dbus_object_manager_server_is_exported         (GDBusObjectManagerServer  *manager,
-                                                                            GDBusObjectSkeleton       *object);
+                                                                            GDBusObjectSkeleton       *object) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 gboolean                  g_dbus_object_manager_server_unexport            (GDBusObjectManagerServer  *manager,
-                                                                            const gchar               *object_path);
+                                                                            const gchar               *object_path) TIZEN_PUBLIC_DEPRECATED_API;
 
 G_END_DECLS
 
index fc58aea..2bf9a61 100644 (file)
@@ -477,7 +477,7 @@ _g_dbus_worker_emit_disconnected (GDBusWorker  *worker,
                                   GError       *error)
 {
   if (!g_atomic_int_get (&worker->stopped))
-    worker->disconnected_callback (worker, remote_peer_vanished, error, worker->user_data);
+    worker->disconnected_callback (remote_peer_vanished, error, worker->user_data);
 }
 
 static void
@@ -485,7 +485,7 @@ _g_dbus_worker_emit_message_received (GDBusWorker  *worker,
                                       GDBusMessage *message)
 {
   if (!g_atomic_int_get (&worker->stopped))
-    worker->message_received_callback (worker, message, worker->user_data);
+    worker->message_received_callback (message, worker->user_data);
 }
 
 static GDBusMessage *
@@ -494,7 +494,7 @@ _g_dbus_worker_emit_message_about_to_be_sent (GDBusWorker  *worker,
 {
   GDBusMessage *ret;
   if (!g_atomic_int_get (&worker->stopped))
-    ret = worker->message_about_to_be_sent_callback (worker, g_steal_pointer (&message), worker->user_data);
+    ret = worker->message_about_to_be_sent_callback (g_steal_pointer (&message), worker->user_data);
   else
     ret = g_steal_pointer (&message);
   return ret;
index 72d2c32..f65b3e5 100644 (file)
@@ -33,16 +33,13 @@ G_BEGIN_DECLS
 
 typedef struct GDBusWorker GDBusWorker;
 
-typedef void (*GDBusWorkerMessageReceivedCallback) (GDBusWorker   *worker,
-                                                    GDBusMessage  *message,
+typedef void (*GDBusWorkerMessageReceivedCallback) (GDBusMessage  *message,
                                                     gpointer       user_data);
 
-typedef GDBusMessage *(*GDBusWorkerMessageAboutToBeSentCallback) (GDBusWorker   *worker,
-                                                                  GDBusMessage  *message,
+typedef GDBusMessage *(*GDBusWorkerMessageAboutToBeSentCallback) (GDBusMessage  *message,
                                                                   gpointer       user_data);
 
-typedef void (*GDBusWorkerDisconnectedCallback)    (GDBusWorker   *worker,
-                                                    gboolean       remote_peer_vanished,
+typedef void (*GDBusWorkerDisconnectedCallback)    (gboolean       remote_peer_vanished,
                                                     GError        *error,
                                                     gpointer       user_data);
 
@@ -160,6 +157,17 @@ gchar *_g_dbus_hexencode (const gchar *str,
 GDBusConnection *_g_bus_get_singleton_if_exists (GBusType bus_type);
 void             _g_bus_forget_singleton        (GBusType bus_type);
 
+void g_dbus_message_init_header_iter (GDBusMessage   *message,
+                                      GHashTableIter *iter);
+
+GObject *
+g_dbus_address_get_stream_internal (const gchar   *address,
+                                    gboolean       kdbus_okay,
+                                    gchar        **out_uuid,
+                                    GCancellable  *cancellable,
+                                    GError       **error);
+
+
 G_END_DECLS
 
 #endif /* __G_DBUS_PRIVATE_H__ */
index 7a2289b..cc7e3ac 100644 (file)
@@ -2595,26 +2595,10 @@ out:
 static const gchar *
 get_destination_for_call (GDBusProxy *proxy)
 {
-  const gchar *ret;
-
-  ret = NULL;
-
-  /* If proxy->priv->name is a unique name, then proxy->priv->name_owner
-   * is never NULL and always the same as proxy->priv->name. We use this
-   * knowledge to avoid checking if proxy->priv->name is a unique or
-   * well-known name.
-   */
-  ret = proxy->priv->name_owner;
-  if (ret != NULL)
-    goto out;
-
   if (proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START)
-    goto out;
-
-  ret = proxy->priv->name;
+    return proxy->priv->name_owner;
 
- out:
-  return ret;
+  return proxy->priv->name;
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
index 6be9871..41e2dcd 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <gio/giotypes.h>
 #include <gio/gdbusintrospection.h>
+#include <gio/tizen_header_glib.h>  /* for TIZEN_PUBLIC_DEPRECATED_API */
 
 G_BEGIN_DECLS
 
@@ -85,7 +86,7 @@ struct _GDBusProxyClass
 };
 
 GLIB_AVAILABLE_IN_ALL
-GType            g_dbus_proxy_get_type                  (void) G_GNUC_CONST;
+GType            g_dbus_proxy_get_type                  (void) G_GNUC_CONST TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void             g_dbus_proxy_new                       (GDBusConnection     *connection,
                                                          GDBusProxyFlags      flags,
@@ -95,10 +96,10 @@ void             g_dbus_proxy_new                       (GDBusConnection     *co
                                                          const gchar         *interface_name,
                                                          GCancellable        *cancellable,
                                                          GAsyncReadyCallback  callback,
-                                                         gpointer             user_data);
+                                                         gpointer             user_data) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusProxy      *g_dbus_proxy_new_finish                (GAsyncResult        *res,
-                                                         GError             **error);
+                                                         GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusProxy      *g_dbus_proxy_new_sync                  (GDBusConnection     *connection,
                                                          GDBusProxyFlags      flags,
@@ -107,7 +108,7 @@ GDBusProxy      *g_dbus_proxy_new_sync                  (GDBusConnection     *co
                                                          const gchar         *object_path,
                                                          const gchar         *interface_name,
                                                          GCancellable        *cancellable,
-                                                         GError             **error);
+                                                         GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void             g_dbus_proxy_new_for_bus               (GBusType             bus_type,
                                                          GDBusProxyFlags      flags,
@@ -117,10 +118,10 @@ void             g_dbus_proxy_new_for_bus               (GBusType             bu
                                                          const gchar         *interface_name,
                                                          GCancellable        *cancellable,
                                                          GAsyncReadyCallback  callback,
-                                                         gpointer             user_data);
+                                                         gpointer             user_data) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusProxy      *g_dbus_proxy_new_for_bus_finish        (GAsyncResult        *res,
-                                                         GError             **error);
+                                                         GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusProxy      *g_dbus_proxy_new_for_bus_sync          (GBusType             bus_type,
                                                          GDBusProxyFlags      flags,
@@ -129,38 +130,38 @@ GDBusProxy      *g_dbus_proxy_new_for_bus_sync          (GBusType             bu
                                                          const gchar         *object_path,
                                                          const gchar         *interface_name,
                                                          GCancellable        *cancellable,
-                                                         GError             **error);
+                                                         GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusConnection *g_dbus_proxy_get_connection            (GDBusProxy          *proxy);
+GDBusConnection *g_dbus_proxy_get_connection            (GDBusProxy          *proxy) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusProxyFlags  g_dbus_proxy_get_flags                 (GDBusProxy          *proxy);
+GDBusProxyFlags  g_dbus_proxy_get_flags                 (GDBusProxy          *proxy) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-const gchar     *g_dbus_proxy_get_name                  (GDBusProxy          *proxy);
+const gchar     *g_dbus_proxy_get_name                  (GDBusProxy          *proxy) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-gchar           *g_dbus_proxy_get_name_owner            (GDBusProxy          *proxy);
+gchar           *g_dbus_proxy_get_name_owner            (GDBusProxy          *proxy) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-const gchar     *g_dbus_proxy_get_object_path           (GDBusProxy          *proxy);
+const gchar     *g_dbus_proxy_get_object_path           (GDBusProxy          *proxy) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-const gchar     *g_dbus_proxy_get_interface_name        (GDBusProxy          *proxy);
+const gchar     *g_dbus_proxy_get_interface_name        (GDBusProxy          *proxy) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-gint             g_dbus_proxy_get_default_timeout       (GDBusProxy          *proxy);
+gint             g_dbus_proxy_get_default_timeout       (GDBusProxy          *proxy) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void             g_dbus_proxy_set_default_timeout       (GDBusProxy          *proxy,
-                                                         gint                 timeout_msec);
+                                                         gint                 timeout_msec) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusInterfaceInfo *g_dbus_proxy_get_interface_info     (GDBusProxy          *proxy);
+GDBusInterfaceInfo *g_dbus_proxy_get_interface_info     (GDBusProxy          *proxy) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void             g_dbus_proxy_set_interface_info        (GDBusProxy           *proxy,
-                                                         GDBusInterfaceInfo   *info);
+                                                         GDBusInterfaceInfo   *info) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GVariant        *g_dbus_proxy_get_cached_property       (GDBusProxy          *proxy,
-                                                         const gchar         *property_name);
+                                                         const gchar         *property_name) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void             g_dbus_proxy_set_cached_property       (GDBusProxy          *proxy,
                                                          const gchar         *property_name,
-                                                         GVariant            *value);
+                                                         GVariant            *value) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-gchar          **g_dbus_proxy_get_cached_property_names (GDBusProxy          *proxy);
+gchar          **g_dbus_proxy_get_cached_property_names (GDBusProxy          *proxy) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 void             g_dbus_proxy_call                      (GDBusProxy          *proxy,
                                                          const gchar         *method_name,
@@ -169,11 +170,11 @@ void             g_dbus_proxy_call                      (GDBusProxy          *pr
                                                          gint                 timeout_msec,
                                                          GCancellable        *cancellable,
                                                          GAsyncReadyCallback  callback,
-                                                         gpointer             user_data);
+                                                         gpointer             user_data) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GVariant        *g_dbus_proxy_call_finish               (GDBusProxy          *proxy,
                                                          GAsyncResult        *res,
-                                                         GError             **error);
+                                                         GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GVariant        *g_dbus_proxy_call_sync                 (GDBusProxy          *proxy,
                                                          const gchar         *method_name,
@@ -181,7 +182,7 @@ GVariant        *g_dbus_proxy_call_sync                 (GDBusProxy          *pr
                                                          GDBusCallFlags       flags,
                                                          gint                 timeout_msec,
                                                          GCancellable        *cancellable,
-                                                         GError             **error);
+                                                         GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
 void             g_dbus_proxy_call_with_unix_fd_list        (GDBusProxy          *proxy,
@@ -192,12 +193,12 @@ void             g_dbus_proxy_call_with_unix_fd_list        (GDBusProxy
                                                              GUnixFDList         *fd_list,
                                                              GCancellable        *cancellable,
                                                              GAsyncReadyCallback  callback,
-                                                             gpointer             user_data);
+                                                             gpointer             user_data) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GVariant        *g_dbus_proxy_call_with_unix_fd_list_finish (GDBusProxy          *proxy,
                                                              GUnixFDList        **out_fd_list,
                                                              GAsyncResult        *res,
-                                                             GError             **error);
+                                                             GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GVariant        *g_dbus_proxy_call_with_unix_fd_list_sync   (GDBusProxy          *proxy,
                                                              const gchar         *method_name,
@@ -207,7 +208,7 @@ GVariant        *g_dbus_proxy_call_with_unix_fd_list_sync   (GDBusProxy
                                                              GUnixFDList         *fd_list,
                                                              GUnixFDList        **out_fd_list,
                                                              GCancellable        *cancellable,
-                                                             GError             **error);
+                                                             GError             **error) TIZEN_PUBLIC_DEPRECATED_API;
 
 G_END_DECLS
 
index 123eac4..a504cba 100644 (file)
@@ -26,6 +26,7 @@
 #endif
 
 #include <gio/giotypes.h>
+#include <gio/tizen_header_glib.h>  /* for TIZEN_PUBLIC_DEPRECATED_API */
 
 G_BEGIN_DECLS
 
@@ -34,26 +35,26 @@ G_BEGIN_DECLS
 #define G_IS_DBUS_SERVER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DBUS_SERVER))
 
 GLIB_AVAILABLE_IN_ALL
-GType             g_dbus_server_get_type           (void) G_GNUC_CONST;
+GType             g_dbus_server_get_type           (void) G_GNUC_CONST TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GDBusServer      *g_dbus_server_new_sync           (const gchar       *address,
                                                     GDBusServerFlags   flags,
                                                     const gchar       *guid,
                                                     GDBusAuthObserver *observer,
                                                     GCancellable      *cancellable,
-                                                    GError           **error);
+                                                    GError           **error) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-const gchar      *g_dbus_server_get_client_address (GDBusServer       *server);
+const gchar      *g_dbus_server_get_client_address (GDBusServer       *server) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-const gchar      *g_dbus_server_get_guid           (GDBusServer       *server);
+const gchar      *g_dbus_server_get_guid           (GDBusServer       *server) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-GDBusServerFlags  g_dbus_server_get_flags          (GDBusServer       *server);
+GDBusServerFlags  g_dbus_server_get_flags          (GDBusServer       *server) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-void              g_dbus_server_start              (GDBusServer       *server);
+void              g_dbus_server_start              (GDBusServer       *server) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-void              g_dbus_server_stop               (GDBusServer       *server);
+void              g_dbus_server_stop               (GDBusServer       *server) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-gboolean          g_dbus_server_is_active          (GDBusServer       *server);
+gboolean          g_dbus_server_is_active          (GDBusServer       *server) TIZEN_PUBLIC_DEPRECATED_API;
 
 G_END_DECLS
 
index f12e862..b96b55c 100644 (file)
@@ -451,6 +451,11 @@ g_dbus_gvariant_to_gvalue (GVariant  *value,
       g_value_set_uint64 (out_gvalue, g_variant_get_uint64 (value));
       break;
 
+    case G_VARIANT_CLASS_FLOAT:
+      g_value_init (out_gvalue, G_TYPE_FLOAT);
+      g_value_set_float (out_gvalue, g_variant_get_float (value));
+      break;
+
     case G_VARIANT_CLASS_DOUBLE:
       g_value_init (out_gvalue, G_TYPE_DOUBLE);
       g_value_set_double (out_gvalue, g_variant_get_double (value));
@@ -625,6 +630,10 @@ g_dbus_gvalue_to_gvariant (const GValue       *gvalue,
           ret = g_variant_ref_sink (g_variant_new_uint64 (g_value_get_uint64 (gvalue)));
           break;
 
+        case G_VARIANT_CLASS_FLOAT:
+          ret = g_variant_ref_sink (g_variant_new_float (g_value_get_float (gvalue)));
+          break;
+
         case G_VARIANT_CLASS_DOUBLE:
           ret = g_variant_ref_sink (g_variant_new_double (g_value_get_double (gvalue)));
           break;
index da8e422..c68b249 100644 (file)
 #endif
 
 #include <gio/giotypes.h>
+#include <gio/tizen_header_glib.h>  /* for TIZEN_PUBLIC_DEPRECATED_API */
 
 G_BEGIN_DECLS
 
 GLIB_AVAILABLE_IN_ALL
-gboolean g_dbus_is_guid (const gchar *string);
+gboolean g_dbus_is_guid (const gchar *string) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-gchar *g_dbus_generate_guid (void);
+gchar *g_dbus_generate_guid (void) TIZEN_PUBLIC_DEPRECATED_API;
 
 GLIB_AVAILABLE_IN_ALL
-gboolean g_dbus_is_name (const gchar *string);
+gboolean g_dbus_is_name (const gchar *string) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-gboolean g_dbus_is_unique_name (const gchar *string);
+gboolean g_dbus_is_unique_name (const gchar *string) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-gboolean g_dbus_is_member_name (const gchar *string);
+gboolean g_dbus_is_member_name (const gchar *string) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
-gboolean g_dbus_is_interface_name (const gchar *string);
+gboolean g_dbus_is_interface_name (const gchar *string) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_2_70
 gboolean g_dbus_is_error_name (const gchar *string);
 
 GLIB_AVAILABLE_IN_ALL
 void g_dbus_gvariant_to_gvalue (GVariant  *value,
-                                GValue    *out_gvalue);
+                                GValue    *out_gvalue) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_ALL
 GVariant *g_dbus_gvalue_to_gvariant (const GValue         *gvalue,
-                                     const GVariantType   *type);
+                                     const GVariantType   *type) TIZEN_PUBLIC_DEPRECATED_API;
 GLIB_AVAILABLE_IN_2_68
 gchar *g_dbus_escape_object_path_bytestring (const guint8 *bytes);
 GLIB_AVAILABLE_IN_2_68
index d81ada4..9a54d37 100644 (file)
@@ -992,6 +992,66 @@ typedef enum
  * used in the D-Bus Specification. */
 
 /**
+ * GBusRequestNameReplyFlags:
+ * @G_BUS_REQUEST_NAME_FLAGS_ERROR: Error flag.
+ * @G_BUS_REQUEST_NAME_FLAGS_PRIMARY_OWNER: Caller is now the primary owner of the name, replacing
+ * any previous owner.
+ * @G_BUS_REQUEST_NAME_FLAGS_IN_QUEUE: The name already had an owner, the application will be
+ * placed in a queue.
+ * @G_BUS_REQUEST_NAME_FLAGS_EXISTS: The name already has an owner.
+ * @G_BUS_REQUEST_NAME_FLAGS_ALREADY_OWNER: The application trying to request ownership of a name
+ * is already the owner of it.
+ *
+ * Flags used in g_dbus_request_name().
+ *
+ * Since: 2.44
+ */
+typedef enum
+{
+  G_BUS_REQUEST_NAME_FLAGS_ERROR = 0,
+  G_BUS_REQUEST_NAME_FLAGS_PRIMARY_OWNER = 1,
+  G_BUS_REQUEST_NAME_FLAGS_IN_QUEUE = 2,
+  G_BUS_REQUEST_NAME_FLAGS_EXISTS = 3,
+  G_BUS_REQUEST_NAME_FLAGS_ALREADY_OWNER = 4
+} GBusRequestNameReplyFlags;
+
+/**
+ * GBusReleaseNameReplyFlags:
+ * @G_BUS_RELEASE_NAME_FLAGS_ERROR: Error flag.
+ * @G_BUS_RELEASE_NAME_FLAGS_RELEASED: The caller has released his claim on the given name.
+ * @G_BUS_RELEASE_NAME_FLAGS_NON_EXISTENT: The given name does not exist on this bus.
+ * @G_BUS_RELEASE_NAME_FLAGS_NOT_OWNER: The caller not waiting in the queue to own this name.
+ *
+ * Flags used in g_dbus_release_name().
+ *
+ * Since: 2.44
+ */
+typedef enum
+{
+  G_BUS_RELEASE_NAME_FLAGS_ERROR = 0,
+  G_BUS_RELEASE_NAME_FLAGS_RELEASED = 1,
+  G_BUS_RELEASE_NAME_FLAGS_NON_EXISTENT = 2,
+  G_BUS_RELEASE_NAME_FLAGS_NOT_OWNER = 3
+} GBusReleaseNameReplyFlags;
+
+/**
+ * GBusStartServiceReplyFlags:
+ * @G_BUS_START_SERVICE_REPLY_ERROR: Error flag.
+ * @G_BUS_START_SERVICE_REPLY_SUCCESS: The service was successfully started.
+ * @G_BUS_START_SERVICE_REPLY_ALREADY_RUNNING: A connection already owns the given name.
+ *
+ * Flags used in g_dbus_start_service_by_name().
+ *
+ * Since: 2.44
+ */
+typedef enum
+{
+  G_BUS_START_SERVICE_REPLY_ERROR = 0,
+  G_BUS_START_SERVICE_REPLY_SUCCESS = 1,
+  G_BUS_START_SERVICE_REPLY_ALREADY_RUNNING = 2
+} GBusStartServiceReplyFlags;
+
+/**
  * GBusNameWatcherFlags:
  * @G_BUS_NAME_WATCHER_FLAGS_NONE: No flags set.
  * @G_BUS_NAME_WATCHER_FLAGS_AUTO_START: If no-one owns the name when
diff --git a/gio/gkdbus.c b/gio/gkdbus.c
new file mode 100755 (executable)
index 0000000..a764bce
--- /dev/null
@@ -0,0 +1,4354 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2015 Samsung Electronics
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Lukasz Skalski       <l.skalski@samsung.com>
+ * Author: Adrian Szyndela      <adrian.s@samsung.com>
+ * Author: Michal Eljasiewicz   <m.eljasiewic@samsung.com>
+ */
+
+#include "config.h"
+#include "gdbusconnection.h" /* DBUS_DEFAULT_TIMEOUT_MSEC */
+#include "gkdbus.h"
+#include "glib-unix.h"
+#include "glib-linux.h"
+#include "glibintl.h"
+#include "gvariant-serialiser.h"
+#include <linux/kdbus.h>
+
+#include <gio/gio.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+
+#ifdef LIBDBUSPOLICY
+#include <dbuspolicy/libdbuspolicy1.h>
+#endif
+
+#define DBUS_DAEMON_EMULATION
+#ifdef DBUS_DAEMON_EMULATION
+#include "gkdbusfakedaemon.h"
+#endif
+
+#include <glib/gstdio.h>
+#include <glib/glib-private.h>
+#include <gio/gio.h>
+#include <gio/gunixfdlist.h>
+
+#include "glibintl.h"
+#include "gunixfdmessage.h"
+
+#define KDBUS_MSG_MAX_SIZE          8192
+#define KDBUS_INFINITE_TIMEOUT_NS   0x3fffffffffffffffLLU
+
+#define RECEIVE_POOL_SIZE_DEFAULT_SIZE    (16 * 1024LU * 1024LU)
+#define RECEIVE_POOL_SIZE_ENV_VAR_NAME    "KDBUS_MEMORY_POOL_SIZE"
+#define RECEIVE_POOL_SIZE_MAX_MBYTES      64
+#define RECEIVE_POOL_SIZE_MIN_KBYTES      16
+
+#define KDBUS_MEMFD_THRESHOLD      (512 * 1024LU)
+#define KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE  0x00200000      /* maximum size of message header and items */
+
+#define KDBUS_ALIGN8(l)            (((l) + 7) & ~7)
+#define KDBUS_ALIGN8_PTR(p)        ((void*) (uintptr_t)(p))
+
+#define KDBUS_ITEM_HEADER_SIZE G_STRUCT_OFFSET(struct kdbus_item, data)
+#define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
+
+#define KDBUS_ITEM_NEXT(item) \
+        (typeof(item))(((guint8 *)item) + KDBUS_ALIGN8((item)->size))
+#define KDBUS_ITEM_FOREACH(item, head, first)                    \
+        for (item = (head)->first;                               \
+             (guint8 *)(item) < (guint8 *)(head) + (head)->size; \
+             item = KDBUS_ITEM_NEXT(item))
+#define KDBUS_FOREACH(iter, first, _size)                             \
+        for (iter = (first);                                          \
+             ((guint8 *)(iter) < (guint8 *)(first) + (_size)) &&      \
+               ((guint8 *)(iter) >= (guint8 *)(first));               \
+             iter = (void*)(((guint8 *)iter) + KDBUS_ALIGN8((iter)->size)))
+
+#define g_alloca0(x) memset(g_alloca(x), '\0', (x))
+
+struct dbus_fixed_header {
+  guint8  endian;
+  guint8  type;
+  guint8  flags;
+  guint8  version;
+  guint32 reserved;
+  guint64 serial;
+};
+
+#define DBUS_FIXED_HEADER_TYPE     ((const GVariantType *) "(yyyyut)")
+#define DBUS_EXTENDED_HEADER_TYPE  ((const GVariantType *) "a{tv}")
+#define DBUS_MESSAGE_TYPE          ((const GVariantType *) "((yyyyut)a{tv}v)")
+
+/*
+ * Macros for SipHash algorithm
+ */
+
+#define ROTL(x,b) (guint64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
+
+#define U32TO8_LE(p, v)         \
+    (p)[0] = (guint8)((v)      ); (p)[1] = (guint8)((v) >>  8); \
+    (p)[2] = (guint8)((v) >> 16); (p)[3] = (guint8)((v) >> 24);
+
+#define U64TO8_LE(p, v)         \
+  U32TO8_LE((p),     (guint32)((v)      ));   \
+  U32TO8_LE((p) + 4, (guint32)((v) >> 32));
+
+#define U8TO64_LE(p) \
+  (((guint64)((p)[0])      ) | \
+   ((guint64)((p)[1]) <<  8) | \
+   ((guint64)((p)[2]) << 16) | \
+   ((guint64)((p)[3]) << 24) | \
+   ((guint64)((p)[4]) << 32) | \
+   ((guint64)((p)[5]) << 40) | \
+   ((guint64)((p)[6]) << 48) | \
+   ((guint64)((p)[7]) << 56))
+
+#define SIPROUND            \
+  do {              \
+    v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
+    v2 += v3; v3=ROTL(v3,16); v3 ^= v2;     \
+    v0 += v3; v3=ROTL(v3,21); v3 ^= v0;     \
+    v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
+  } while(0)
+
+typedef GObjectClass GKDBusWorkerClass;
+
+struct _GKDBusWorker
+{
+  GObject            parent_instance;
+
+  const gchar       *address;
+  gint               fd;
+
+  GMainContext      *context;
+  GMainLoop         *loop;
+  GThread           *thread;
+  GSource           *source;
+
+  gchar             *kdbus_buffer;
+  guint64           receive_pool_size;
+  gchar             *unique_name;
+  guint64            unique_id;
+
+  guint64            flags;
+  guint64            attach_flags_send;
+  guint64            attach_flags_recv;
+
+  gsize              bloom_size;
+  guint              bloom_n_hash;
+
+  guint              closed : 1;
+  guint              inited : 1;
+  guint              timeout;
+  guint              timed_out : 1;
+
+  guchar             bus_id[16];
+
+  GMutex             matches_mutex;
+  GList             *matches;
+
+#ifdef LIBDBUSPOLICY
+  void              *dbuspolicy;
+#endif
+
+  GDBusCapabilityFlags                     capabilities;
+  GDBusWorkerMessageReceivedCallback       message_received_callback;
+  GDBusWorkerMessageAboutToBeSentCallback  message_about_to_be_sent_callback;
+  GDBusWorkerDisconnectedCallback          disconnected_callback;
+  gpointer                                 user_data;
+};
+
+static gboolean  _g_kdbus_send    (GKDBusWorker  *worker,
+                                   GDBusMessage  *message,
+                                   GDBusMessage **reply,
+                                   gint           timeout_msec,
+                                   GCancellable  *cancellable,
+                                   GError       **error);
+
+static void      _g_kdbus_receive (GKDBusWorker  *worker,
+                                   GError       **error);
+
+G_DEFINE_TYPE (GKDBusWorker, g_kdbus_worker, G_TYPE_OBJECT)
+
+/* Hash keys for bloom filters*/
+const guint8 hash_keys[8][16] =
+{
+  {0xb9,0x66,0x0b,0xf0,0x46,0x70,0x47,0xc1,0x88,0x75,0xc4,0x9c,0x54,0xb9,0xbd,0x15},
+  {0xaa,0xa1,0x54,0xa2,0xe0,0x71,0x4b,0x39,0xbf,0xe1,0xdd,0x2e,0x9f,0xc5,0x4a,0x3b},
+  {0x63,0xfd,0xae,0xbe,0xcd,0x82,0x48,0x12,0xa1,0x6e,0x41,0x26,0xcb,0xfa,0xa0,0xc8},
+  {0x23,0xbe,0x45,0x29,0x32,0xd2,0x46,0x2d,0x82,0x03,0x52,0x28,0xfe,0x37,0x17,0xf5},
+  {0x56,0x3b,0xbf,0xee,0x5a,0x4f,0x43,0x39,0xaf,0xaa,0x94,0x08,0xdf,0xf0,0xfc,0x10},
+  {0x31,0x80,0xc8,0x73,0xc7,0xea,0x46,0xd3,0xaa,0x25,0x75,0x0f,0x9e,0x4c,0x09,0x29},
+  {0x7d,0xf7,0x18,0x4b,0x7b,0xa4,0x44,0xd5,0x85,0x3c,0x06,0xe0,0x65,0x53,0x96,0x6d},
+  {0xf2,0x77,0xe9,0x6f,0x93,0xb5,0x4e,0x71,0x9a,0x0c,0x34,0x88,0x39,0x25,0xbf,0x35}
+};
+
+enum {
+  MATCH_ELEMENT_TYPE,
+  MATCH_ELEMENT_SENDER,
+  MATCH_ELEMENT_INTERFACE,
+  MATCH_ELEMENT_MEMBER,
+  MATCH_ELEMENT_PATH,
+  MATCH_ELEMENT_PATH_NAMESPACE,
+  MATCH_ELEMENT_DESTINATION,
+  MATCH_ELEMENT_ARG0NAMESPACE,
+  MATCH_ELEMENT_EAVESDROP,
+  MATCH_ELEMENT_ARGN,
+  MATCH_ELEMENT_ARGNPATH,
+};
+
+static guint64 _global_match_cookie = 1;
+
+/* MatchElement struct */
+typedef struct {
+  guint16 type;
+  guint16 arg;
+  char *value;
+} MatchElement;
+
+/* Match struct */
+typedef struct {
+  int n_elements;
+  MatchElement *elements;
+  guint64 cookie;
+} Match;
+
+
+/*
+ * SipHash algorithm
+ */
+static void
+_g_siphash24 (guint8         out[8],
+              const void    *_in,
+              gsize          inlen,
+              const guint8   k[16])
+{
+  /* "somepseudorandomlygeneratedbytes" */
+  guint64 v0 = 0x736f6d6570736575ULL;
+  guint64 v1 = 0x646f72616e646f6dULL;
+  guint64 v2 = 0x6c7967656e657261ULL;
+  guint64 v3 = 0x7465646279746573ULL;
+  guint64 b;
+  guint64 k0 = U8TO64_LE (k);
+  guint64 k1 = U8TO64_LE (k + 8);
+  guint64 m;
+  const guint8 *in = _in;
+  const guint8 *end = in + inlen - (inlen % sizeof(guint64));
+  const int left = inlen & 7;
+  b = ((guint64) inlen) << 56;
+  v3 ^= k1;
+  v2 ^= k0;
+  v1 ^= k1;
+  v0 ^= k0;
+
+  for (; in != end; in += 8)
+    {
+      m = U8TO64_LE (in);
+      v3 ^= m;
+      SIPROUND;
+      SIPROUND;
+      v0 ^= m;
+    }
+
+  switch (left)
+    {
+      case 7: b |= ((guint64) in[6]) << 48;
+      case 6: b |= ((guint64) in[5]) << 40;
+      case 5: b |= ((guint64) in[4]) << 32;
+      case 4: b |= ((guint64) in[3]) << 24;
+      case 3: b |= ((guint64) in[2]) << 16;
+      case 2: b |= ((guint64) in[1]) <<  8;
+      case 1: b |= ((guint64) in[0]); break;
+      case 0: break;
+    }
+
+  v3 ^= b;
+  SIPROUND;
+  SIPROUND;
+  v0 ^= b;
+
+  v2 ^= 0xff;
+  SIPROUND;
+  SIPROUND;
+  SIPROUND;
+  SIPROUND;
+  b = v0 ^ v1 ^ v2  ^ v3;
+  U64TO8_LE (out, b);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+is_key (const char *key_start, const char *key_end, char *value)
+{
+  gsize len = strlen (value);
+
+  if (len != key_end - key_start)
+    return FALSE;
+
+  return strncmp (key_start, value, len) == 0;
+}
+
+static gboolean
+parse_key (MatchElement *element, const char *key_start, const char *key_end)
+{
+  gboolean res = TRUE;
+
+  if (is_key (key_start, key_end, "type"))
+    {
+      element->type = MATCH_ELEMENT_TYPE;
+    }
+  else if (is_key (key_start, key_end, "sender"))
+    {
+      element->type = MATCH_ELEMENT_SENDER;
+    }
+  else if (is_key (key_start, key_end, "interface"))
+    {
+      element->type = MATCH_ELEMENT_INTERFACE;
+    }
+  else if (is_key (key_start, key_end, "member"))
+    {
+      element->type = MATCH_ELEMENT_MEMBER;
+    }
+  else if (is_key (key_start, key_end, "path"))
+    {
+      element->type = MATCH_ELEMENT_PATH;
+    }
+  else if (is_key (key_start, key_end, "path_namespace"))
+    {
+      element->type = MATCH_ELEMENT_PATH_NAMESPACE;
+    }
+  else if (is_key (key_start, key_end, "destination"))
+    {
+      element->type = MATCH_ELEMENT_DESTINATION;
+    }
+  else if (is_key (key_start, key_end, "arg0namespace"))
+    {
+      element->type = MATCH_ELEMENT_ARG0NAMESPACE;
+    }
+  else if (is_key (key_start, key_end, "eavesdrop"))
+    {
+      element->type = MATCH_ELEMENT_EAVESDROP;
+    }
+  else if (key_end - key_start > 3 && is_key (key_start, key_start + 3, "arg"))
+    {
+      const char *digits = key_start + 3;
+      const char *end_digits = digits;
+
+      while (end_digits < key_end && g_ascii_isdigit (*end_digits))
+        end_digits++;
+
+      if (end_digits == key_end) /* argN */
+        {
+          element->type = MATCH_ELEMENT_ARGN;
+          element->arg = atoi (digits);
+        }
+      else if (is_key (end_digits, key_end, "path")) /* argNpath */
+        {
+          element->type = MATCH_ELEMENT_ARGNPATH;
+          element->arg = atoi (digits);
+        }
+      else
+        res = FALSE;
+    }
+  else
+    res = FALSE;
+
+  return res;
+}
+
+static const char *
+parse_value (MatchElement *element, const char *s)
+{
+  char quote_char;
+  GString *value;
+
+  value = g_string_new ("");
+
+  quote_char = 0;
+
+  for (;*s; s++)
+    {
+      if (quote_char == 0)
+        {
+          switch (*s)
+            {
+            case '\'':
+              quote_char = '\'';
+              break;
+
+            case ',':
+              s++;
+              goto out;
+
+            case '\\':
+              quote_char = '\\';
+              break;
+
+            default:
+              g_string_append_c (value, *s);
+              break;
+            }
+        }
+      else if (quote_char == '\\')
+        {
+          /* \ only counts as an escape if escaping a quote mark */
+          if (*s != '\'')
+            g_string_append_c (value, '\\');
+
+          g_string_append_c (value, *s);
+          quote_char = 0;
+        }
+      else /* quote_char == ' */
+        {
+          if (*s == '\'')
+            quote_char = 0;
+          else
+            g_string_append_c (value, *s);
+        }
+    }
+
+ out:
+  if (quote_char == '\\')
+    g_string_append_c (value, '\\');
+  else if (quote_char == '\'')
+    {
+      g_string_free (value, TRUE);
+      return NULL;
+    }
+
+  element->value = g_string_free (value, FALSE);
+  return s;
+}
+
+static Match *
+match_new (const char *str)
+{
+  Match *match;
+  GArray *elements;
+  const char *p;
+  const char *key_start;
+  const char *key_end;
+  MatchElement element;
+  int i;
+
+  elements = g_array_new (TRUE, TRUE, sizeof (MatchElement));
+
+  p = str;
+
+  while (*p != 0)
+    {
+      memset (&element, 0, sizeof (element));
+
+      /* Skip initial whitespace */
+      while (*p && g_ascii_isspace (*p))
+        p++;
+
+      key_start = p;
+
+      /* Read non-whitespace non-equals chars */
+      while (*p && *p != '=' && !g_ascii_isspace (*p))
+        p++;
+
+      key_end = p;
+
+      /* Skip any whitespace after key */
+      while (*p && g_ascii_isspace (*p))
+        p++;
+
+      if (key_start == key_end)
+        continue; /* Allow trailing whitespace */
+      if (*p != '=')
+        goto error;
+
+      ++p;
+
+      if (!parse_key (&element, key_start, key_end))
+        goto error;
+
+      p = parse_value (&element, p);
+      if (p == NULL)
+        goto error;
+
+      g_array_append_val (elements, element);
+    }
+
+  match = g_new0 (Match, 1);
+  match->n_elements = elements->len;
+  match->elements = (MatchElement *)g_array_free (elements, FALSE);
+  match->cookie = _global_match_cookie++;
+
+  return match;
+
+ error:
+  for (i = 0; i < elements->len; i++)
+    g_free (g_array_index (elements, MatchElement, i).value);
+  g_array_free (elements, TRUE);
+  return NULL;
+}
+
+static gboolean
+match_equal (Match *a, Match *b)
+{
+  int i;
+
+  if (a->n_elements != b->n_elements)
+    return FALSE;
+
+  for (i = 0; i < a->n_elements; i++)
+    {
+      if (a->elements[i].type != b->elements[i].type ||
+          a->elements[i].arg != b->elements[i].arg ||
+          strcmp (a->elements[i].value, b->elements[i].value) != 0)
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
+static void
+match_free (Match *match)
+{
+  int i;
+
+  for (i = 0; i < match->n_elements; i++)
+    g_free (match->elements[i].value);
+
+  g_free (match->elements);
+  g_free (match);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/*
+ * _g_kdbus_open
+ */
+gboolean
+_g_kdbus_open (GKDBusWorker  *worker,
+               const gchar   *address,
+               GError       **error)
+{
+  g_return_val_if_fail (G_IS_KDBUS_WORKER (worker), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  worker->fd = g_open(address, O_RDWR|O_NOCTTY|O_CLOEXEC, 0);
+  if (worker->fd<0)
+    {
+      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Cannot open kdbus endpoint"));
+      return FALSE;
+    }
+
+  worker->address = g_strdup(address);
+  worker->closed = FALSE;
+  return TRUE;
+}
+
+static gboolean
+_g_kdbus_quit_loop (gpointer loop)
+{
+  g_main_loop_quit ((GMainLoop*)loop);
+  return FALSE;
+}
+
+gboolean
+_g_kdbus_can_connect (GKDBusWorker *worker,
+                      GError       **error)
+{
+#ifdef LIBDBUSPOLICY
+  worker->dbuspolicy = dbuspolicy1_init_shared (worker->address, worker->fd);
+  if (worker->dbuspolicy == NULL)
+    {
+      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Cannot load dbus policy for kdbus transport or access to bus denied by security policy"));
+      return FALSE;
+    }
+#endif
+  return TRUE;
+}
+
+/*
+ * _g_kdbus_close
+ */
+gboolean
+_g_kdbus_close (GKDBusWorker *worker)
+{
+  g_return_val_if_fail (G_IS_KDBUS_WORKER (worker), FALSE);
+
+  if (worker->closed)
+    return TRUE;
+
+  g_main_context_invoke (worker->context, _g_kdbus_quit_loop, worker->loop);
+
+  g_main_context_unref (worker->context);
+  worker->context = NULL;
+
+  g_main_loop_unref (worker->loop);
+
+  g_thread_unref(worker->thread);
+
+  worker->thread = NULL;
+
+  g_free ((char*)worker->address);
+
+  close (worker->fd);
+  worker->fd = -1;
+
+  worker->closed = TRUE;
+  return TRUE;
+}
+
+/*
+ * _g_kdbus_is_closed
+ */
+gboolean
+_g_kdbus_is_closed (GKDBusWorker *worker)
+{
+  g_return_val_if_fail (G_IS_KDBUS_WORKER (worker), FALSE);
+
+  return worker->closed;
+}
+
+static void
+g_kdbus_free_data (GKDBusWorker  *worker,
+                   guint64        offset)
+{
+  struct kdbus_cmd_free cmd = {
+    .size = sizeof(cmd),
+    .offset = offset,
+    .flags = 0
+  };
+
+  if (ioctl (worker->fd, KDBUS_CMD_FREE, &cmd) < 0)
+    {
+      g_error ("kdbus: invalid KDBUS_CMD_FREE ioctl : %" G_GUINT64_FORMAT " offset\n", offset);
+    }
+}
+
+static void
+g_kdbus_close_msg (GKDBusWorker      *worker,
+                   struct kdbus_msg  *msg)
+{
+  guint64 offset;
+
+  offset = (guint8 *)msg - (guint8 *)worker->kdbus_buffer;
+  g_kdbus_free_data (worker, offset);
+}
+
+
+/*
+ * g_kdbus_translate_nameowner_flags
+ */
+static void
+g_kdbus_translate_nameowner_flags (GBusNameOwnerFlags   flags,
+                                   guint64             *kdbus_flags)
+{
+  guint64 new_flags;
+
+  new_flags = 0;
+
+  if (flags & G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT)
+    new_flags |= KDBUS_NAME_ALLOW_REPLACEMENT;
+
+  if (flags & G_BUS_NAME_OWNER_FLAGS_REPLACE)
+    new_flags |= KDBUS_NAME_REPLACE_EXISTING;
+
+  if (!(flags & G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE))
+    new_flags |= KDBUS_NAME_QUEUE;
+
+  *kdbus_flags = new_flags;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/* < internal >
+ *
+ * _g_kdbus_Hello:
+ *
+ * Gets the unique name.
+ *
+ * Returns: the unique name or NULL. Do not free this string,
+ * it is owned by GKDBusWorker.
+ */
+const gchar *
+_g_kdbus_Hello (GKDBusWorker  *worker,
+                GError       **error)
+{
+  struct kdbus_cmd_hello *cmd;
+  struct kdbus_bloom_parameter *bloom;
+  struct kdbus_item *item, *items;
+
+  gchar *conn_name;
+  size_t size, conn_name_size;
+
+  const gchar *env_pool;
+  guint64 receive_pool_size = RECEIVE_POOL_SIZE_DEFAULT_SIZE;
+
+  conn_name = "gdbus-kdbus";
+  conn_name_size = strlen (conn_name);
+
+  size = KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_cmd_hello, items)) +
+         KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, str) + conn_name_size + 1);
+
+  cmd = g_alloca0 (size);
+  cmd->flags = worker->flags;
+  cmd->attach_flags_send = worker->attach_flags_send;
+  cmd->attach_flags_recv = worker->attach_flags_recv;
+  cmd->size = size;
+
+  env_pool = getenv (RECEIVE_POOL_SIZE_ENV_VAR_NAME);
+  if(env_pool)
+    {
+      guint64 size;
+      guint32 multiply = 1;
+      gint64 page_size;
+
+      page_size = sysconf(_SC_PAGESIZE);
+      if(page_size == -1)
+        {
+          size = 0;
+          goto finish;
+        }
+
+      errno = 0;
+      size = strtoul(env_pool, (char**)&env_pool, 10);
+      if(errno == EINVAL || size == 0)
+        {
+          size = 0;
+          goto finish;
+        }
+
+      if(*env_pool == 'k')
+        {
+          multiply = 1024;
+          env_pool++;
+        }
+      else if (*env_pool == 'M')
+        {
+          multiply = 1024 * 1024;
+          env_pool++;
+        }
+
+      if(*env_pool != '\0')
+        {
+          size = 0;
+          goto finish;
+        }
+
+      receive_pool_size = size * multiply;
+
+      if((receive_pool_size > RECEIVE_POOL_SIZE_MAX_MBYTES * 1024 * 1024) ||
+         (receive_pool_size < RECEIVE_POOL_SIZE_MIN_KBYTES * 1024) ||
+         ((receive_pool_size & (page_size - 1)) != 0))
+        size = 0;
+
+    finish:
+      if(size == 0)
+        {
+          g_warning ("%s value is invalid, default value %luB will be used.", RECEIVE_POOL_SIZE_ENV_VAR_NAME,
+                     RECEIVE_POOL_SIZE_DEFAULT_SIZE);
+          g_warning ("Correct value must be between %ukB and %uMB and must be aligned to page size: %" G_GINT64_FORMAT "B.",
+                     RECEIVE_POOL_SIZE_MIN_KBYTES, RECEIVE_POOL_SIZE_MAX_MBYTES, page_size);
+
+          receive_pool_size = RECEIVE_POOL_SIZE_DEFAULT_SIZE;
+        }
+    }
+
+  g_debug ("[KDBUS] receive pool size set to %" G_GUINT64_FORMAT "\n", receive_pool_size);
+  worker->receive_pool_size = receive_pool_size;
+  cmd->pool_size = worker->receive_pool_size;
+
+  item = cmd->items;
+  item->size = (guint64) G_STRUCT_OFFSET (struct kdbus_item, str) + conn_name_size + 1;
+  item->type = KDBUS_ITEM_CONN_DESCRIPTION;
+  memcpy (item->str, conn_name, conn_name_size+1);
+  item = KDBUS_ITEM_NEXT (item);
+
+  if (worker->unique_id != -1)
+    {
+      g_set_error (error, G_DBUS_ERROR,
+                   G_DBUS_ERROR_FAILED,
+                   "Already handled an Hello message");
+      return NULL;
+    }
+
+  if (ioctl(worker->fd, KDBUS_CMD_HELLO, cmd))
+    {
+      g_set_error (error, G_IO_ERROR,
+                   g_io_error_from_errno (errno),
+                   _("Failed to send HELLO: %s"),
+                   g_strerror (errno));
+      return NULL;
+    }
+
+  worker->kdbus_buffer = mmap(NULL, worker->receive_pool_size, PROT_READ, MAP_SHARED, worker->fd, 0);
+  if (worker->kdbus_buffer == MAP_FAILED)
+    {
+      g_set_error (error, G_IO_ERROR,
+                   g_io_error_from_errno (errno),
+                   _("mmap error: %s"),
+                   g_strerror (errno));
+      return NULL;
+    }
+
+  if (cmd->bus_flags > 0xFFFFFFFFULL)
+    {
+      g_set_error_literal (error,
+                           G_IO_ERROR,
+                           G_IO_ERROR_FAILED,
+                           _("Incompatible HELLO flags"));
+      return NULL;
+    }
+
+  memcpy (worker->bus_id, cmd->id128, 16);
+
+  worker->unique_id = cmd->id;
+  if (asprintf (&worker->unique_name, ":1.%llu", (unsigned long long) cmd->id) < 0)
+    {
+      g_set_error (error,
+                   G_IO_ERROR,
+                   G_IO_ERROR_UNKNOWN,
+                   "asprintf error: %s",
+                   g_strerror(errno));
+      return NULL;
+    }
+
+  /* read bloom filters parameters */
+  bloom = NULL;
+  items = (void*)(worker->kdbus_buffer + cmd->offset);
+  KDBUS_FOREACH(item, items, cmd->items_size)
+    {
+      switch (item->type)
+        {
+          case KDBUS_ITEM_BLOOM_PARAMETER:
+            bloom = &item->bloom_parameter;
+          break;
+        }
+    }
+
+  if (bloom != NULL)
+    {
+      worker->bloom_size = (gsize) bloom->size;
+      worker->bloom_n_hash = (guint) bloom->n_hash;
+    }
+  else
+    {
+      g_set_error_literal (error,
+                           G_IO_ERROR,
+                           G_IO_ERROR_FAILED,
+                           _("Can't read bloom filter parameters"));
+      return NULL;
+    }
+
+  g_kdbus_free_data (worker, cmd->offset);
+
+#ifdef LIBDBUSPOLICY
+  dbuspolicy1_init_set_pool (worker->dbuspolicy, worker->kdbus_buffer);
+#endif
+
+  return worker->unique_name;
+}
+
+
+/* < internal >
+ *
+ * _g_kdbus_RequestName:
+ *
+ * Synchronously acquires name on the bus and returns status code
+ * from the GBusRequestNameReplyFlags enumeration.
+ *
+ * Returns: status code or G_BUS_REQUEST_NAME_FLAGS_ERROR
+ * if error is set.
+ */
+GBusRequestNameReplyFlags
+_g_kdbus_RequestName (GKDBusWorker        *worker,
+                      const gchar         *name,
+                      GBusNameOwnerFlags   flags,
+                      GError             **error)
+{
+  GBusRequestNameReplyFlags status;
+  struct kdbus_cmd *cmd;
+  guint64 kdbus_flags;
+  gsize len, size;
+  gint ret;
+
+  status = G_BUS_REQUEST_NAME_FLAGS_PRIMARY_OWNER;
+
+  if (!g_dbus_is_name (name))
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_INVALID_ARGS,
+                   "Given bus name \"%s\" is not valid", name);
+      return G_BUS_REQUEST_NAME_FLAGS_ERROR;
+    }
+
+  if (g_strcmp0 (name, "org.freedesktop.DBus") == 0)
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_INVALID_ARGS,
+                   "Cannot acquire a service named '%s', because that is reserved", name);
+      return G_BUS_REQUEST_NAME_FLAGS_ERROR;
+    }
+
+  if (*name == ':')
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_INVALID_ARGS,
+                   "Cannot acquire a service starting with ':' such as \"%s\"", name);
+      return G_BUS_REQUEST_NAME_FLAGS_ERROR;
+    }
+
+#ifdef LIBDBUSPOLICY
+  if (worker->dbuspolicy != NULL)
+    {
+      if (dbuspolicy1_can_own (worker->dbuspolicy, name) != 1)
+        {
+          g_set_error (error,
+                       G_DBUS_ERROR,
+                       G_DBUS_ERROR_ACCESS_DENIED,
+                       "Connection \"%s\" is not allowed to own the "
+                       "service \"%s\" due to security policies", worker->unique_name, name);
+          return G_BUS_REQUEST_NAME_FLAGS_ERROR;
+        }
+    }
+#endif
+
+  g_kdbus_translate_nameowner_flags (flags, &kdbus_flags);
+
+  len = strlen(name) + 1;
+  size = (gulong) G_STRUCT_OFFSET (struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(len);
+  cmd = g_alloca0 (size);
+  cmd->size = size;
+  cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
+  cmd->items[0].type = KDBUS_ITEM_NAME;
+  cmd->flags = kdbus_flags;
+  memcpy (cmd->items[0].str, name, len);
+
+  ret = ioctl(worker->fd, KDBUS_CMD_NAME_ACQUIRE, cmd);
+  if (ret < 0)
+    {
+      if (errno == EEXIST)
+        status = G_BUS_REQUEST_NAME_FLAGS_EXISTS;
+      else if (errno == EALREADY)
+        status = G_BUS_REQUEST_NAME_FLAGS_ALREADY_OWNER;
+      else
+        {
+          g_set_error (error, G_IO_ERROR,
+                       g_io_error_from_errno (errno),
+                       _("Error while acquiring name: %s"),
+                       g_strerror (errno));
+          return G_BUS_REQUEST_NAME_FLAGS_ERROR;
+        }
+    }
+  else if ((cmd->return_flags & KDBUS_NAME_PRIMARY)
+      && !(cmd->return_flags & KDBUS_NAME_ACQUIRED))
+    status = G_BUS_REQUEST_NAME_FLAGS_ALREADY_OWNER;
+
+  if (cmd->return_flags & KDBUS_NAME_IN_QUEUE)
+    status = G_BUS_REQUEST_NAME_FLAGS_IN_QUEUE;
+
+  return status;
+}
+
+
+/* < internal >
+ *
+ * _g_kdbus_ReleaseName:
+ *
+ * Synchronously releases name on the bus and returns status code
+ * from the GBusReleaseNameReplyFlags enumeration.
+ *
+ * Returns: status code or G_BUS_RELEASE_NAME_FLAGS_ERROR
+ * if error is set.
+ */
+GBusReleaseNameReplyFlags
+_g_kdbus_ReleaseName (GKDBusWorker  *worker,
+                      const gchar   *name,
+                      GError       **error)
+{
+  GBusReleaseNameReplyFlags status;
+  struct kdbus_cmd *cmd;
+  gsize len, size;
+  gint ret;
+
+  status = G_BUS_RELEASE_NAME_FLAGS_RELEASED;
+
+  if (!g_dbus_is_name (name))
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_INVALID_ARGS,
+                   "Given bus name \"%s\" is not valid", name);
+      return G_BUS_RELEASE_NAME_FLAGS_ERROR;
+    }
+
+  if (g_strcmp0 (name, "org.freedesktop.DBus") == 0)
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_INVALID_ARGS,
+                   "Cannot release a service named '%s', because that is owned by the bus", name);
+      return G_BUS_RELEASE_NAME_FLAGS_ERROR;
+    }
+
+  if (*name == ':')
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_INVALID_ARGS,
+                   "Cannot release a service starting with ':' such as \"%s\"", name);
+      return G_BUS_RELEASE_NAME_FLAGS_ERROR;
+    }
+
+  len = strlen(name) + 1;
+  size = (gulong) G_STRUCT_OFFSET (struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(len);
+  cmd = g_alloca0 (size);
+  cmd->size = size;
+  cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
+  cmd->items[0].type = KDBUS_ITEM_NAME;
+  memcpy (cmd->items[0].str, name, len);
+
+  ret = ioctl(worker->fd, KDBUS_CMD_NAME_RELEASE, cmd);
+  if (ret < 0)
+    {
+      if (errno == ESRCH)
+        status = G_BUS_RELEASE_NAME_FLAGS_NON_EXISTENT;
+      else if (errno == EADDRINUSE)
+        status = G_BUS_RELEASE_NAME_FLAGS_NOT_OWNER;
+      else
+        {
+          g_set_error (error, G_IO_ERROR,
+                       g_io_error_from_errno (errno),
+                       _("Error while releasing name: %s"),
+                       g_strerror (errno));
+          return G_BUS_RELEASE_NAME_FLAGS_ERROR;
+        }
+    }
+
+  return status;
+}
+
+
+/* < internal >
+ *
+ * _g_kdbus_GetBusId:
+ *
+ * Synchronously returns the unique ID of the bus.
+ *
+ * Returns: the unique ID of the bus or NULL if error is set.
+ * Free with g_free().
+ */
+gchar *
+_g_kdbus_GetBusId (GKDBusWorker  *worker,
+                   GError       **error)
+{
+  GString  *result;
+  guint     cnt;
+
+  result = g_string_new (NULL);
+
+  for (cnt=0; cnt<16; cnt++)
+    g_string_append_printf (result, "%02x", worker->bus_id[cnt]);
+
+  return g_string_free (result, FALSE);
+}
+
+
+static void
+expand_strv (gchar  ***strv_ptr,
+             gchar    *value)
+{
+  gchar **strv;
+  guint strv_len;
+
+  if (!value)
+    return;
+
+  strv = *strv_ptr;
+  strv_len = g_strv_length (strv);
+
+  strv = g_renew (gchar *, strv, strv_len + 2);
+  strv[strv_len] = value;
+  strv[strv_len + 1] = NULL;
+
+  *strv_ptr = strv;
+}
+
+
+/* < internal >
+ *
+ * _g_kdbus_GetListNames:
+ *
+ * Synchronously returns a list of:
+ *   - all currently-owned names on the bus (activatable = FALSE),
+ *   - all names that can be activated on the bus (activatable = TRUE),
+ *
+ * or NULL if error is set. Free with g_strfreev().
+ */
+gchar **
+_g_kdbus_GetListNames (GKDBusWorker  *worker,
+                       gboolean       activatable,
+                       GError       **error)
+{
+  struct kdbus_info *name_list, *name;
+  struct kdbus_cmd_list cmd = {
+    .size = sizeof(cmd)
+  };
+
+  gchar **listnames;
+  guint64 prev_id;
+  gint ret;
+
+  prev_id = 0;
+
+  if (activatable)
+    cmd.flags = KDBUS_LIST_ACTIVATORS;                /* ListActivatableNames */
+  else
+    cmd.flags = KDBUS_LIST_UNIQUE | KDBUS_LIST_NAMES; /* ListNames */
+
+  ret = ioctl(worker->fd, KDBUS_CMD_LIST, &cmd);
+  if (ret < 0)
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_FAILED,
+                   _("Error listing names"));
+      return NULL;
+    }
+
+  listnames = g_new0 (gchar *, 1);
+  name_list = (struct kdbus_info *) ((guint8 *) worker->kdbus_buffer + cmd.offset);
+
+  KDBUS_FOREACH (name, name_list, cmd.list_size)
+    {
+      struct kdbus_item *item;
+
+      if ((cmd.flags & KDBUS_LIST_UNIQUE) && name->id != prev_id)
+        {
+          gchar *unique_name;
+
+          if (asprintf (&unique_name, ":1.%llu", name->id) < 0)
+            {
+              g_set_error (error,
+                           G_IO_ERROR,
+                           G_IO_ERROR_UNKNOWN,
+                           "asprintf error: %s",
+                           g_strerror(errno));
+              goto error;
+            }
+
+          expand_strv (&listnames, unique_name);
+          prev_id = name->id;
+        }
+
+       KDBUS_ITEM_FOREACH (item, name, items)
+         {
+           if (item->type == KDBUS_ITEM_OWNED_NAME)
+             {
+               if (g_dbus_is_name (item->name.name))
+                 expand_strv (&listnames, g_strdup (item->name.name));
+             }
+         }
+    }
+
+  /* org.freedesktop.DBus.ListNames */
+  if (!activatable)
+    expand_strv (&listnames, g_strdup ("org.freedesktop.DBus"));
+
+  g_kdbus_free_data (worker, cmd.offset);
+
+  return listnames;
+
+error:
+  g_strfreev(listnames);
+  return NULL;
+}
+
+
+static gboolean
+g_kdbus_NameHasOwner_internal (GKDBusWorker  *worker,
+                               const gchar   *name)
+{
+  struct kdbus_cmd_info *cmd;
+  struct kdbus_info *conn_info;
+  gsize size, len;
+  gint ret;
+
+  if (g_dbus_is_unique_name(name))
+    {
+       size = (gulong) G_STRUCT_OFFSET (struct kdbus_cmd_info, items);
+       cmd = g_alloca0 (size);
+       cmd->id = g_ascii_strtoull (name+3, NULL, 10);
+    }
+  else
+    {
+       len = strlen(name) + 1;
+       size = (gulong) G_STRUCT_OFFSET (struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(len);
+       cmd = g_alloca0 (size);
+       cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
+       cmd->items[0].type = KDBUS_ITEM_NAME;
+       memcpy (cmd->items[0].str, name, len);
+    }
+  cmd->size = size;
+
+  ret = ioctl(worker->fd, KDBUS_CMD_CONN_INFO, cmd);
+  if (ret < 0)
+    return FALSE;
+
+  conn_info = (struct kdbus_info *) ((guint8 *) worker->kdbus_buffer + cmd->offset);
+
+  if (conn_info->flags & KDBUS_HELLO_ACTIVATOR)
+    ret = -1;
+
+  g_kdbus_free_data (worker, cmd->offset);
+
+  if (ret < 0)
+    return FALSE;
+  else
+    return TRUE;
+}
+
+
+/* < internal >
+ *
+ * _g_kdbus_GetListQueuedOwners:
+ *
+ * Synchronously returns the unique bus names of connections currently
+ * queued for the name.
+ *
+ * Returns: the unique bus names of connections currently queued for the
+ * 'name' or NULL if error is set. Free with g_strfreev().
+ */
+gchar **
+_g_kdbus_GetListQueuedOwners (GKDBusWorker  *worker,
+                              const gchar   *name,
+                              GError       **error)
+{
+  struct kdbus_info *name_list, *kname;
+  struct kdbus_cmd_list cmd = {
+    .size = sizeof(cmd),
+    .flags = KDBUS_LIST_QUEUED
+  };
+
+  gchar **queued_owners;
+  gint ret;
+
+  if (!g_dbus_is_name (name))
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_INVALID_ARGS,
+                   "Given bus name \"%s\" is not valid", name);
+      return NULL;
+    }
+
+  if (!g_kdbus_NameHasOwner_internal (worker, name))
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_NAME_HAS_NO_OWNER,
+                   "Could not get owner of name '%s': no such name", name);
+      return NULL;
+    }
+
+  ret = ioctl(worker->fd, KDBUS_CMD_LIST, &cmd);
+  if (ret < 0)
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_FAILED,
+                   _("Error listing names"));
+      return NULL;
+    }
+
+  queued_owners = g_new0 (gchar *, 1);
+  name_list = (struct kdbus_info *) ((guint8 *) worker->kdbus_buffer + cmd.offset);
+
+  KDBUS_FOREACH(kname, name_list, cmd.list_size)
+    {
+      struct kdbus_item *item;
+
+      KDBUS_ITEM_FOREACH(item, kname, items)
+        {
+          if (item->type == KDBUS_ITEM_OWNED_NAME)
+            {
+              gchar *unique_name;
+
+              if (strcmp(item->name.name, name))
+                continue;
+
+              if (asprintf (&unique_name, ":1.%llu", kname->id) != -1)
+                expand_strv (&queued_owners, unique_name);
+            }
+        }
+    }
+
+  g_kdbus_free_data (worker, cmd.offset);
+
+  return queued_owners;
+}
+
+
+/* < internal >
+ *
+ * _g_kdbus_NameHasOwner:
+ *
+ * Checks if the specified name exists (currently has an owner).
+ *
+ * Returns: TRUE if the name exists and FALSE when name doesn't exists
+ * or error is set.
+ */
+gboolean
+_g_kdbus_NameHasOwner (GKDBusWorker  *worker,
+                       const gchar   *name,
+                       GError       **error)
+{
+  if (!g_dbus_is_name (name))
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_INVALID_ARGS,
+                   "Given bus name \"%s\" is not valid", name);
+      return FALSE;
+    }
+
+  if (g_strcmp0 (name, "org.freedesktop.DBus") == 0)
+    return  TRUE;
+
+  if (!g_kdbus_NameHasOwner_internal (worker, name))
+    return FALSE; /* Don't make g_set_error, otherwise NameHasOwner will fail. */
+  else
+    return TRUE;
+}
+
+
+GDBusCredentials *
+_g_kdbus_GetConnInfo (GKDBusWorker  *worker,
+                      const gchar   *name,
+                      guint          flags,
+                      GError       **error)
+{
+  GDBusCredentials *creds;
+  struct kdbus_cmd_info *cmd;
+  struct kdbus_info *conn_info;
+  struct kdbus_item *item;
+  gsize size, len;
+  gint ret;
+
+  creds = g_new0 (GDBusCredentials, 1);
+
+  if (!g_dbus_is_name (name))
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_INVALID_ARGS,
+                   "Given bus name \"%s\" is not valid", name);
+      goto error;
+    }
+
+  if (!g_kdbus_NameHasOwner_internal (worker, name))
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_NAME_HAS_NO_OWNER,
+                   "Could not get owner of name '%s': no such name", name);
+      goto error;
+    }
+
+  if (g_dbus_is_unique_name(name))
+    {
+       size = (gulong) G_STRUCT_OFFSET (struct kdbus_cmd_info, items);
+       cmd = g_alloca0 (size);
+       cmd->id = g_ascii_strtoull (name+3, NULL, 10);
+    }
+  else
+    {
+       len = strlen(name) + 1;
+       size = (gulong) G_STRUCT_OFFSET (struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(len);
+       cmd = g_alloca0 (size);
+       cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
+       cmd->items[0].type = KDBUS_ITEM_NAME;
+       memcpy (cmd->items[0].str, name, len);
+    }
+
+  cmd->attach_flags = _KDBUS_ATTACH_ALL;
+  cmd->size = size;
+
+  ret = ioctl(worker->fd, KDBUS_CMD_CONN_INFO, cmd);
+  if (ret < 0)
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_FAILED,
+                   _("Could not get connection info"));
+      goto error;
+    }
+
+  conn_info = (struct kdbus_info *) ((guint8 *) worker->kdbus_buffer + cmd->offset);
+
+  if (flags & G_DBUS_CREDS_UNIQUE_NAME)
+    {
+       if (asprintf (&creds->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0)
+         {
+           g_set_error (error,
+                        G_DBUS_ERROR,
+                        G_DBUS_ERROR_FAILED,
+                        "asprintf error: %s",
+                        g_strerror(errno));
+           goto error;
+         }
+    }
+
+  KDBUS_ITEM_FOREACH(item, conn_info, items)
+   {
+      switch (item->type)
+        {
+          case KDBUS_ITEM_PIDS:
+            if (flags & G_DBUS_CREDS_PID)
+              creds->pid = item->pids.pid;
+          break;
+
+          case KDBUS_ITEM_CREDS:
+            if (flags & G_DBUS_CREDS_UID)
+              creds->uid = item->creds.uid;
+          break;
+
+          case KDBUS_ITEM_SECLABEL:
+            if (flags & G_DBUS_CREDS_SEC_LABEL)
+              creds->sec_label = g_strdup (item->str);
+          break;
+
+          case KDBUS_ITEM_PID_COMM:
+          case KDBUS_ITEM_TID_COMM:
+          case KDBUS_ITEM_EXE:
+          case KDBUS_ITEM_CMDLINE:
+          case KDBUS_ITEM_CGROUP:
+          case KDBUS_ITEM_CAPS:
+          case KDBUS_ITEM_AUDIT:
+          case KDBUS_ITEM_CONN_DESCRIPTION:
+          case KDBUS_ITEM_AUXGROUPS:
+          case KDBUS_ITEM_OWNED_NAME:
+            break;
+        }
+   }
+
+  g_kdbus_free_data (worker, cmd->offset);
+  return creds;
+
+error:
+  g_free (creds->unique_name);
+  g_free (creds->sec_label);
+  g_free (creds);
+  return NULL;
+}
+
+
+/* < internal >
+ *
+ * _g_kdbus_GetNameOwner:
+ *
+ * Synchronously returns the unique connection name of the primary owner of
+ * the name given. If the requested name doesn't have an owner, an error is
+ * returned.
+ *
+ * Returns: the unique connection name of the primary owner of the
+ * name given. If the requested name doesn't have an owner, function
+ * returns NULL and error is set. Free with g_free().
+ */
+gchar *
+_g_kdbus_GetNameOwner (GKDBusWorker  *worker,
+                       const gchar   *name,
+                       GError       **error)
+{
+  GDBusCredentials *creds;
+  gchar *unique_name;
+  guint flags;
+
+  creds = NULL;
+  unique_name = NULL;
+
+  if (g_strcmp0 (name, "org.freedesktop.DBus") == 0)
+    return g_strdup (name);
+
+  flags = G_DBUS_CREDS_UNIQUE_NAME;
+  creds = _g_kdbus_GetConnInfo (worker,
+                                name,
+                                flags,
+                                error);
+  if (creds != NULL)
+    {
+      unique_name = creds->unique_name;
+      g_free (creds);
+    }
+
+  return unique_name;
+}
+
+
+/* < internal >
+ *
+ * _g_kdbus_GetConnectionUnixProcessID:
+ *
+ * Synchronously returns the Unix process ID of the process connected to the
+ * bus. If unable to determine it, an error is returned.
+ *
+ * If name contains a value not compatible with the D-Bus syntax and naming
+ * conventions for bus names, the operation returns -1 and error is set.
+ *
+ * Returns: the Unix process ID of the process connected to the bus or -1
+ * if error is set.
+ */
+pid_t
+_g_kdbus_GetConnectionUnixProcessID (GKDBusWorker  *worker,
+                                     const gchar   *name,
+                                     GError       **error)
+{
+  GDBusCredentials *creds;
+  guint flags;
+  pid_t pid;
+
+  creds = NULL;
+  pid = -1;
+
+  flags = G_DBUS_CREDS_PID;
+  creds = _g_kdbus_GetConnInfo (worker,
+                                name,
+                                flags,
+                                error);
+  if (creds != NULL)
+    {
+      pid = creds->pid;
+      g_free (creds);
+    }
+
+  return pid;
+}
+
+
+/* < internal >
+ *
+ * _g_kdbus_GetConnectionUnixUser:
+ *
+ * Synchronously returns the Unix user ID of the process connected to the
+ * bus. If unable to determine it, an error is returned.
+ *
+ * If name contains a value not compatible with the D-Bus syntax and naming
+ * conventions for bus names, the operation returns -1 and error is set.
+ *
+ * Returns: the Unix user ID of the process connected to the bus or -1
+ * if error is set.
+ */
+uid_t
+_g_kdbus_GetConnectionUnixUser (GKDBusWorker  *worker,
+                                const gchar   *name,
+                                GError       **error)
+{
+  GDBusCredentials *creds;
+  guint flags;
+  uid_t uid;
+
+  creds = NULL;
+  uid = -1;
+
+  flags = G_DBUS_CREDS_UID;
+  creds = _g_kdbus_GetConnInfo (worker,
+                                name,
+                                flags,
+                                error);
+  if (creds != NULL)
+    {
+      uid = creds->uid;
+      g_free (creds);
+    }
+
+  return uid;
+}
+
+
+/* < internal >
+ *
+ * _g_kdbus_GetConnectionSecurityLabel:
+ *
+ * Synchronously returns security label of the process connected to the bus.
+ *
+ * If name contains a value not compatible with the D-Bus syntax and naming
+ * conventions for bus names, the operation returns -1 and error is set.
+ *
+ * Returns: security label of the process connected to the bus or -1
+ */
+gchar *
+_g_kdbus_GetConnectionSecurityLabel (GKDBusWorker  *worker,
+                                     const gchar   *name,
+                                     GError       **error)
+{
+  GDBusCredentials *creds;
+  gchar *sec_label;
+  guint flags;
+
+  creds = NULL;
+  sec_label = NULL;
+
+  flags = G_DBUS_CREDS_SEC_LABEL;
+  creds = _g_kdbus_GetConnInfo (worker,
+                                name,
+                                flags,
+                                error);
+  if (creds != NULL)
+    {
+      sec_label = creds->sec_label;
+      g_free (creds);
+    }
+
+  return sec_label;
+}
+
+typedef struct
+{
+  GKDBusWorker  *worker;
+  GDBusMessage  *message;
+} SyntheticReplyData;
+
+static gboolean
+deliver_synthetic_reply (gpointer user_data)
+{
+  SyntheticReplyData *data;
+  GKDBusWorker *worker;
+  GDBusMessage *message;
+
+  data = user_data;
+  worker = data->worker;
+  message = data->message;
+
+  (* worker->message_received_callback) (message, worker->user_data);
+
+  g_object_unref (message);
+  g_free (data);
+
+  return FALSE;
+}
+
+static void
+send_synthetic_message (GKDBusWorker *worker,
+                    GDBusMessage *message)
+{
+  SyntheticReplyData *reply_data;
+  reply_data = g_new0 (SyntheticReplyData, 1);
+  reply_data->worker = worker;
+  reply_data->message = message;
+  g_main_context_invoke (worker->context, deliver_synthetic_reply, reply_data);
+}
+
+static GBusStartServiceReplyFlags
+_g_kdbus_send_Ping (GKDBusWorker *worker,
+                    const gchar  *name,
+                    GError      **error)
+{
+  GDBusMessage *ping_message;
+  GDBusMessage *reply = NULL;
+  gboolean ret;
+
+  ping_message = g_dbus_message_new_method_call (name, "/", "org.freedesktop.DBus.Peer", "Ping");
+  g_dbus_message_set_serial (ping_message, -1);
+
+  ret = _g_kdbus_send (worker, ping_message, &reply, 25000, NULL, NULL);
+  g_object_unref (ping_message);
+  if (reply)
+    g_object_unref (reply);
+
+  if (!ret)
+    {
+      g_set_error (error,
+                  G_DBUS_ERROR,
+                  G_DBUS_ERROR_SERVICE_UNKNOWN,
+                  "The name %s was not provided by any .service files", name);
+      return G_BUS_START_SERVICE_REPLY_ERROR;
+    }
+  return G_BUS_START_SERVICE_REPLY_SUCCESS;
+}
+
+static void
+_g_kdbus_send_Ping_thread (GTask        *task,
+                           gpointer      source_object,
+                           gpointer      task_data,
+                           GCancellable *cancellable)
+{
+  GKDBusWorker *worker = source_object;
+  GDBusMessage *message = task_data;
+  const gchar *name = NULL;
+  GError *error = NULL;
+
+  GBusStartServiceReplyFlags status;
+
+  g_variant_get (g_dbus_message_get_body (message), "(su)", &name, NULL);
+
+  status = _g_kdbus_send_Ping (worker, name, &error);
+  g_free ((gchar*) name);
+
+  if (status == G_BUS_START_SERVICE_REPLY_SUCCESS)
+    g_task_return_int (task, G_BUS_START_SERVICE_REPLY_SUCCESS);
+  else
+    g_task_return_error (task, error);
+
+}
+
+static void
+_g_kdbus_send_Ping_finish (GKDBusWorker *worker,
+                           GAsyncResult *result,
+                           gpointer user_data)
+{
+  GDBusMessage *message = user_data;
+  GDBusMessage *synthetic_reply = NULL;
+  GError *error = NULL;
+  gssize status = g_task_propagate_int (G_TASK (result), &error);
+  if (status != -1)
+    {
+      synthetic_reply = g_dbus_message_new_method_reply (message);
+      g_dbus_message_set_body (synthetic_reply, g_variant_new ("(u)", status));
+    }
+  else
+    {
+      gchar *dbus_error_name = g_dbus_error_encode_gerror (error);
+      synthetic_reply = g_dbus_message_new_method_error (message, dbus_error_name, "%s", error->message);
+      g_free (dbus_error_name);
+      g_error_free (error);
+    }
+  g_object_unref (message);
+  g_dbus_message_set_serial (synthetic_reply, -1);
+  send_synthetic_message (worker, synthetic_reply);
+}
+
+/* < internal >
+ *
+ * _g_kdbus_StartServiceByName:
+ *
+ * Synchronously tries to launch the executable associated
+ * with a name.
+ *
+ * Returns: status code or G_BUS_START_SERVICE_REPLY_ERROR
+   if error is set.
+ */
+GBusStartServiceReplyFlags
+_g_kdbus_StartServiceByName (GKDBusWorker  *worker,
+                             const gchar   *name,
+                             guint32        flags,
+                             GDBusMessage  *message,
+                             GError       **error)
+{
+  if (!g_dbus_is_name (name))
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_INVALID_ARGS,
+                   "Given bus name \"%s\" is not valid", name);
+      return G_BUS_START_SERVICE_REPLY_ERROR;
+    }
+
+  if (g_strcmp0 (name, "org.freedesktop.DBus") == 0)
+    return G_BUS_START_SERVICE_REPLY_ALREADY_RUNNING;
+
+  if (!g_kdbus_NameHasOwner_internal (worker, name))
+    {
+      if (!message)
+        {
+            return _g_kdbus_send_Ping(worker, name, error);
+        }
+      else
+        {
+          GTask *task;
+          task = g_task_new (worker,
+                             NULL,
+                             (GAsyncReadyCallback) _g_kdbus_send_Ping_finish,
+                             g_object_ref(message));
+          g_task_set_task_data (task, message, NULL);
+          g_task_run_in_thread (task, _g_kdbus_send_Ping_thread);
+          g_object_unref (task);
+          return G_BUS_START_SERVICE_REPLY_SUCCESS;
+        }
+    }
+  else
+    {
+      return G_BUS_START_SERVICE_REPLY_ALREADY_RUNNING;
+    }
+}
+
+
+/*
+ * g_kdbus_bloom_add_data:
+ * Based on bus-bloom.c from systemd
+ * http://cgit.freedesktop.org/systemd/systemd/tree/src/libsystemd/sd-bus/bus-bloom.c
+ */
+static void
+g_kdbus_bloom_add_data (GKDBusWorker  *worker,
+                        guint64        bloom_data[],
+                        const void    *data,
+                        gsize          n)
+{
+  guint8 hash[8];
+  guint64 bit_num;
+  guint bytes_num = 0;
+  guint cnt_1, cnt_2;
+  guint hash_index = 0;
+
+  guint c = 0;
+
+  bit_num = (guint64)worker->bloom_size * 8;
+
+  if (bit_num > 1)
+    bytes_num = ((__builtin_clzll(bit_num) ^ 63U) + 7) / 8;
+
+  for (cnt_1 = 0, hash_index = 0; cnt_1 < (worker->bloom_n_hash); cnt_1++)
+    {
+      guint64 p = 0;
+      for (cnt_2 = 0; cnt_2 < bytes_num; cnt_2++)
+        {
+          if (c <= 0)
+            {
+              _g_siphash24(hash, data, n, hash_keys[hash_index++]);
+              c += 8;
+            }
+
+          p = (p << 8ULL) | (guint64) hash[8 - c];
+          c--;
+        }
+
+      p &= bit_num - 1;
+      bloom_data[p >> 6] |= 1ULL << (p & 63);
+    }
+}
+
+static void
+g_kdbus_bloom_add_pair (GKDBusWorker  *worker,
+                        guint64        bloom_data[],
+                        const gchar   *parameter,
+                        const gchar   *value)
+{
+  gchar buf[1024];
+  gsize size;
+
+  size = strlen(parameter) + strlen(value) + 1;
+  if (size >= 1024)
+    return;
+
+  strcpy(stpcpy(stpcpy(buf, parameter), ":"), value);
+  g_kdbus_bloom_add_data(worker, bloom_data, buf, size);
+}
+
+static void
+g_kdbus_bloom_add_prefixes (GKDBusWorker  *worker,
+                            guint64        bloom_data[],
+                            const gchar   *parameter,
+                            const gchar   *value,
+                            gchar          separator)
+{
+  gchar buf[1024];
+  gsize size;
+
+  size = strlen(parameter) + strlen(value) + 1;
+  if (size >= 1024)
+    return;
+
+  strcpy(stpcpy(stpcpy(buf, parameter), ":"), value);
+
+  for (;;)
+    {
+      gchar *last_sep;
+      last_sep = strrchr(buf, separator);
+      if (!last_sep || last_sep == buf)
+        break;
+
+      *last_sep = 0;
+      g_kdbus_bloom_add_data(worker, bloom_data, buf, last_sep-buf);
+    }
+}
+
+
+/* < internal >
+ *
+ * _g_kdbus_AddMatch:
+ *
+ * Synchronously adds a match rule to match messages.
+ *
+ * Returns: TRUE if the operation succeeded, FALSE
+ * if error is set.
+ *
+ */
+gboolean
+_g_kdbus_AddMatch (GKDBusWorker  *worker,
+                   const gchar   *match_rule,
+                   GError       **error)
+{
+  Match *match;
+  MatchElement *element;
+  const gchar *sender_name;
+  gsize sender_len, size;
+  struct kdbus_cmd_match *cmd;
+  struct kdbus_item *item;
+  guint64 *bloom;
+  guint64 src_id;
+  gchar *type;
+  gint cnt, ret;
+
+  if (match_rule[0] == '-')
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_MATCH_RULE_INVALID,
+                   "Invalid rule: %s", match_rule);
+      return FALSE;
+    }
+
+  match = match_new (match_rule);
+  if (!match)
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_MATCH_RULE_INVALID,
+                   "Invalid rule: %s", match_rule);
+      return FALSE;
+    }
+
+  sender_name = NULL;
+  src_id = KDBUS_MATCH_ID_ANY;
+
+  bloom = g_alloca0 (worker->bloom_size);
+  size = KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_cmd_match, items));
+
+  for (cnt = 0; cnt < match->n_elements; cnt++)
+    {
+      element = &match->elements[cnt];
+      switch (element->type)
+        {
+          case MATCH_ELEMENT_SENDER:
+            if (g_dbus_is_unique_name(element->value))
+              {
+                src_id = g_ascii_strtoull ((element->value)+3, NULL, 10);
+                size += KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, id) + sizeof(src_id));
+              }
+            else if (g_dbus_is_name (element->value))
+              {
+                sender_name = element->value;
+                sender_len = strlen(element->value) + 1;
+                size += KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, str) + sender_len);
+              }
+            else
+              {
+                g_set_error (error,
+                             G_DBUS_ERROR,
+                             G_DBUS_ERROR_MATCH_RULE_INVALID,
+                             "Invalid rule: %s", match_rule);
+                match_free (match);
+                return FALSE;
+              }
+            break;
+
+          case MATCH_ELEMENT_TYPE:
+            g_kdbus_bloom_add_pair (worker, bloom, "message-type", element->value);
+            break;
+
+          case MATCH_ELEMENT_INTERFACE:
+            g_kdbus_bloom_add_pair (worker, bloom, "interface", element->value);
+            break;
+
+          case MATCH_ELEMENT_MEMBER:
+            g_kdbus_bloom_add_pair (worker, bloom, "member", element->value);
+            break;
+
+          case MATCH_ELEMENT_PATH:
+            g_kdbus_bloom_add_pair (worker, bloom, "path", element->value);
+            break;
+
+          case MATCH_ELEMENT_PATH_NAMESPACE:
+            if (g_strcmp0 (element->value, "/"))
+              g_kdbus_bloom_add_pair (worker, bloom, "path-slash-prefix", element->value);
+            break;
+
+          case MATCH_ELEMENT_ARGN:
+            if (asprintf (&type, "arg%u", element->arg) < 0)
+              {
+                 g_set_error (error,
+                              G_DBUS_ERROR,
+                              G_DBUS_ERROR_FAILED,
+                              "asprintf failed: %s", g_strerror(errno));
+                 match_free (match);
+                 return FALSE;
+              }
+            else
+              {
+                g_kdbus_bloom_add_pair (worker, bloom, type, element->value);
+                free (type);
+              }
+            break;
+
+          case MATCH_ELEMENT_ARGNPATH:
+            if (asprintf (&type, "arg%u-slash-prefix", element->arg) < 0)
+              {
+                 g_set_error (error,
+                              G_DBUS_ERROR,
+                              G_DBUS_ERROR_FAILED,
+                              "asprintf failed: %s", g_strerror(errno));
+                 match_free (match);
+                 return FALSE;
+              }
+            else
+              {
+                g_kdbus_bloom_add_pair (worker, bloom, type, element->value);
+                free (type);
+              }
+            break;
+
+          case MATCH_ELEMENT_ARG0NAMESPACE:
+            g_kdbus_bloom_add_pair (worker, bloom, "arg0-dot-prefix", element->value);
+            break;
+
+          case MATCH_ELEMENT_DESTINATION:
+          case MATCH_ELEMENT_EAVESDROP:
+            break;
+        }
+    }
+
+  size += KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, data64) + worker->bloom_size);
+  cmd = g_alloca0 (size);
+  cmd->size = size;
+  cmd->cookie = match->cookie;
+
+  item = cmd->items;
+  item->size = (guint64) G_STRUCT_OFFSET(struct kdbus_item, data64) + worker->bloom_size;
+  item->type = KDBUS_ITEM_BLOOM_MASK;
+  memcpy(item->data64, bloom, worker->bloom_size);
+  item = KDBUS_ITEM_NEXT(item);
+
+  if (src_id != KDBUS_MATCH_ID_ANY)
+    {
+      item->size = (guint64) G_STRUCT_OFFSET (struct kdbus_item, id) + sizeof(src_id);
+      item->type = KDBUS_ITEM_ID;
+      item->id = src_id;
+      item = KDBUS_ITEM_NEXT(item);
+    }
+
+  if (sender_name)
+    {
+      item->size = (guint64) G_STRUCT_OFFSET (struct kdbus_item, str) + sender_len;
+      item->type = KDBUS_ITEM_NAME;
+      memcpy (item->str, sender_name, sender_len);
+    }
+
+  ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
+  if (ret < 0)
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_FAILED,
+                   "Error while adding a match");
+      match_free (match);
+      return FALSE;
+    }
+
+  g_mutex_lock (&worker->matches_mutex);
+  worker->matches = g_list_prepend (worker->matches, match);
+  g_mutex_unlock (&worker->matches_mutex);
+  return TRUE;
+}
+
+
+/* < internal >
+ *
+ * _g_kdbus_RemoveMatch:
+ *
+ * Synchronously removes the first rule that matches.
+ *
+ * Returns: TRUE if the operation succeeded, FALSE
+ * if error is set.
+ */
+gboolean
+_g_kdbus_RemoveMatch (GKDBusWorker  *worker,
+                      const gchar   *match_rule,
+                      GError       **error)
+{
+  Match *match, *other_match;
+  GList *matches;
+  guint64 cookie;
+
+  if (match_rule[0] == '-')
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_MATCH_RULE_INVALID,
+                   "Invalid rule: %s", match_rule);
+      return FALSE;
+    }
+
+  match = match_new (match_rule);
+  if (!match)
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_MATCH_RULE_INVALID,
+                   "Invalid rule: %s", match_rule);
+      return FALSE;
+    }
+
+  g_mutex_lock (&worker->matches_mutex);
+  for (matches = worker->matches; matches != NULL; matches = matches->next)
+    {
+      other_match = matches->data;
+      if (match_equal (match, other_match))
+        {
+          cookie = other_match->cookie;
+          match_free (other_match);
+          worker->matches = g_list_delete_link (worker->matches, matches);
+          break;
+        }
+    }
+  g_mutex_unlock (&worker->matches_mutex);
+
+  if (matches == NULL)
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_MATCH_RULE_NOT_FOUND,
+                   "The given match rule wasn't found and can't be removed");
+      match_free (match);
+      return FALSE;
+    }
+  else
+    {
+      struct kdbus_cmd_match cmd = {
+        .size = sizeof(cmd),
+        .cookie = cookie
+      };
+      gint ret;
+
+      ret = ioctl(worker->fd, KDBUS_CMD_MATCH_REMOVE, &cmd);
+      if (ret < 0)
+        {
+          if (errno == EBADSLT)
+            {
+              g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_NOT_FOUND,
+                           "A match entry with the given cookie could not be found");
+            }
+          else
+            {
+              g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+                           "Error while removing a match");
+            }
+          match_free (match);
+          return FALSE;
+        }
+    }
+
+  match_free (match);
+  return TRUE;
+}
+
+
+/*
+ * _g_kdbus_subscribe_name_owner_changed_internal
+ */
+static gboolean
+_g_kdbus_subscribe_name_owner_changed_internal (GKDBusWorker  *worker,
+                                                const gchar   *name,
+                                                const gchar   *old_name,
+                                                const gchar   *new_name,
+                                                guint64        cookie,
+                                                GError       **error)
+{
+  struct kdbus_item *item;
+  struct kdbus_cmd_match *cmd;
+  gsize size, len;
+  gint ret;
+  guint64 old_id = 0;
+  guint64 new_id = KDBUS_MATCH_ID_ANY;
+
+  if (name)
+    len = strlen(name) + 1;
+  else
+    len = 0;
+
+  size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
+                      G_STRUCT_OFFSET (struct kdbus_item, name_change) +
+                      G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len);
+
+  cmd = g_alloca0 (size);
+  cmd->size = size;
+  cmd->cookie = cookie;
+  item = cmd->items;
+
+  if (old_name == NULL)
+    {
+      old_id = KDBUS_MATCH_ID_ANY;
+    }
+  else
+    {
+      if (g_dbus_is_unique_name(old_name))
+        old_id = strtoull (old_name + 3, NULL, 10);
+      else
+        return TRUE;
+    }
+
+  if (new_name == NULL)
+    {
+      new_id = KDBUS_MATCH_ID_ANY;
+    }
+  else
+    {
+      if (g_dbus_is_unique_name(new_name))
+        new_id = strtoull (new_name + 3, NULL, 10);
+      else
+        return TRUE;
+    }
+
+  cmd = g_alloca0 (size);
+  cmd->size = size;
+  cmd->cookie = cookie;
+  item = cmd->items;
+
+  item->type = KDBUS_ITEM_NAME_CHANGE;
+  item->name_change.old_id.id = old_id;
+  item->name_change.new_id.id = new_id;
+
+  if (name)
+    memcpy(item->name_change.name, name, len);
+
+  item->size = (guint64) G_STRUCT_OFFSET (struct kdbus_item, name_change) +
+               (guint64) G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len;
+  item = KDBUS_ITEM_NEXT(item);
+
+  ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
+  if (ret < 0)
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_FAILED,
+                   "Error while adding a match");
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+
+/*
+ * _g_kdbus_subscribe_name_acquired
+ */
+gboolean
+_g_kdbus_subscribe_name_acquired (GKDBusWorker  *worker,
+                                  const gchar   *match_rule,
+                                  const gchar   *name,
+                                  GError       **error)
+{
+  Match *match;
+  struct kdbus_item *item;
+  struct kdbus_cmd_match *cmd;
+  gsize size, len;
+  gint ret;
+
+  if (match_rule[0] == '-')
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_MATCH_RULE_INVALID,
+                   "Invalid rule: %s", match_rule);
+      return FALSE;
+    }
+
+  if (name != NULL)
+    {
+      if (!g_dbus_is_name (name))
+        {
+          g_set_error (error,
+                       G_DBUS_ERROR,
+                       G_DBUS_ERROR_MATCH_RULE_INVALID,
+                       "Invalid rule: %s", match_rule);
+          return FALSE;
+        }
+    }
+
+  match = match_new (match_rule);
+  if (!match)
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_MATCH_RULE_INVALID,
+                   "Invalid rule: %s", match_rule);
+      return FALSE;
+    }
+
+  if (name)
+    len = strlen(name) + 1;
+  else
+    len = 0;
+
+  size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
+                      G_STRUCT_OFFSET (struct kdbus_item, name_change) +
+                      G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len);
+
+  cmd = g_alloca0 (size);
+  cmd->size = size;
+  cmd->cookie = match->cookie;
+  item = cmd->items;
+
+  item->type = KDBUS_ITEM_NAME_ADD;
+  item->name_change.old_id.id = KDBUS_MATCH_ID_ANY;
+  item->name_change.new_id.id = worker->unique_id;
+
+  if (name)
+    memcpy(item->name_change.name, name, len);
+
+  item->size = (guint64) G_STRUCT_OFFSET (struct kdbus_item, name_change) +
+               (guint64) G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len;
+  item = KDBUS_ITEM_NEXT(item);
+
+  ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
+  if (ret < 0)
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_FAILED,
+                   "Error while adding a match");
+      match_free (match);
+      return FALSE;
+    }
+
+  if (!_g_kdbus_subscribe_name_owner_changed_internal (worker, name, NULL, worker->unique_name, match->cookie, error))
+    {
+      match_free (match);
+      return FALSE;
+    }
+
+  g_mutex_lock (&worker->matches_mutex);
+  worker->matches = g_list_prepend (worker->matches, match);
+  g_mutex_unlock (&worker->matches_mutex);
+  return TRUE;
+}
+
+
+/*
+ * _g_kdbus_subscribe_name_lost
+ */
+gboolean
+_g_kdbus_subscribe_name_lost (GKDBusWorker  *worker,
+                              const gchar   *match_rule,
+                              const gchar   *name,
+                              GError       **error)
+{
+  Match *match;
+  struct kdbus_item *item;
+  struct kdbus_cmd_match *cmd;
+  gsize size, len;
+  gint ret;
+
+  if (match_rule[0] == '-')
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_MATCH_RULE_INVALID,
+                   "Invalid rule: %s", match_rule);
+      return FALSE;
+    }
+
+  if (name != NULL)
+    {
+      if (!g_dbus_is_name (name))
+        {
+          g_set_error (error,
+                       G_DBUS_ERROR,
+                       G_DBUS_ERROR_MATCH_RULE_INVALID,
+                       "Invalid rule: %s", match_rule);
+          return FALSE;
+        }
+    }
+
+  match = match_new (match_rule);
+  if (!match)
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_MATCH_RULE_INVALID,
+                   "Invalid rule: %s", match_rule);
+      return FALSE;
+    }
+
+  if (name)
+    len = strlen(name) + 1;
+  else
+    len = 0;
+
+  size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
+                      G_STRUCT_OFFSET (struct kdbus_item, name_change) +
+                      G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len);
+
+  cmd = g_alloca0 (size);
+  cmd->size = size;
+  cmd->cookie = match->cookie;
+  item = cmd->items;
+
+  item->type = KDBUS_ITEM_NAME_REMOVE;
+  item->name_change.old_id.id = worker->unique_id;
+  item->name_change.new_id.id = KDBUS_MATCH_ID_ANY;
+
+  if (name)
+    memcpy(item->name_change.name, name, len);
+
+  item->size = (guint64) G_STRUCT_OFFSET (struct kdbus_item, name_change) +
+               (guint64) G_STRUCT_OFFSET(struct kdbus_notify_name_change, name) + len;
+  item = KDBUS_ITEM_NEXT(item);
+
+  ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
+  if (ret < 0)
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_FAILED,
+                   "Error while adding a match");
+      match_free (match);
+      return FALSE;
+    }
+
+  if (!_g_kdbus_subscribe_name_owner_changed_internal (worker, name, worker->unique_name, NULL, match->cookie, error))
+    {
+      match_free (match);
+      return FALSE;
+    }
+
+  g_mutex_lock (&worker->matches_mutex);
+  worker->matches = g_list_prepend (worker->matches, match);
+  g_mutex_unlock (&worker->matches_mutex);
+  return TRUE;
+}
+
+
+/*
+ * _g_kdbus_subscribe_name_owner_changed
+ */
+gboolean
+_g_kdbus_subscribe_name_owner_changed (GKDBusWorker  *worker,
+                                       const gchar   *match_rule,
+                                       const gchar   *name,
+                                       GError       **error)
+{
+  Match *match;
+  struct kdbus_item *item;
+  struct kdbus_cmd_match *cmd;
+  gsize size, len;
+  gint ret;
+
+  if (match_rule[0] == '-')
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_MATCH_RULE_INVALID,
+                   "Invalid rule: %s", match_rule);
+      return FALSE;
+    }
+
+  if (name != NULL)
+  {
+    if (!g_dbus_is_name (name))
+      {
+        g_set_error (error,
+                      G_DBUS_ERROR,
+                      G_DBUS_ERROR_INVALID_ARGS,
+                      "Invalid dbus name: %s", name);
+        return FALSE;
+      }
+  }
+
+  match = match_new (match_rule);
+  if (!match)
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_MATCH_RULE_INVALID,
+                   "Invalid rule: %s", match_rule);
+      return FALSE;
+    }
+
+  /* 'name' argument is missing or is a unique name */
+  if (name == NULL || g_dbus_is_unique_name (name))
+    {
+      size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
+                          G_STRUCT_OFFSET (struct kdbus_item, id_change) +
+                          sizeof (struct kdbus_notify_id_change));
+
+      cmd = g_alloca0 (size);
+      cmd->size = size;
+      cmd->cookie = match->cookie;
+      item = cmd->items;
+
+      if (name)
+        item->id_change.id = strtoull (name + 3, NULL, 10);
+      else
+        item->id_change.id = KDBUS_MATCH_ID_ANY;
+
+      item->size = (guint64) G_STRUCT_OFFSET (struct kdbus_item, id_change) +
+                   sizeof (struct kdbus_notify_id_change);
+
+      item->type = KDBUS_ITEM_ID_ADD;
+      ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
+      if (ret < 0)
+        {
+          g_set_error (error,
+                       G_DBUS_ERROR,
+                       G_DBUS_ERROR_FAILED,
+                       "Error while adding a match");
+          match_free (match);
+          return FALSE;
+        }
+
+      item->type = KDBUS_ITEM_ID_REMOVE;
+      ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
+      if (ret < 0)
+        {
+          g_set_error (error,
+                       G_DBUS_ERROR,
+                       G_DBUS_ERROR_FAILED,
+                       "Error while adding a match");
+          match_free (match);
+          return FALSE;
+        }
+    }
+
+  /* 'name' argument is missing or is a well-known name */
+  if (name == NULL || !g_dbus_is_unique_name (name))
+    {
+      if (name)
+        len = strlen(name) + 1;
+      else
+        len = 0;
+
+      size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
+                          G_STRUCT_OFFSET (struct kdbus_item, name_change) +
+                          G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len);
+
+      cmd = g_alloca0 (size);
+      cmd->size = size;
+      cmd->cookie = match->cookie;
+      item = cmd->items;
+
+      item->name_change.old_id.id = KDBUS_MATCH_ID_ANY;
+      item->name_change.new_id.id = KDBUS_MATCH_ID_ANY;
+      item->size = (guint64) G_STRUCT_OFFSET (struct kdbus_item, name_change) +
+                   (guint64) G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len;
+
+      if (name)
+        memcpy(item->name_change.name, name, len);
+
+      item->type = KDBUS_ITEM_NAME_ADD;
+      ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
+      if (ret < 0)
+        {
+          g_set_error (error,
+                       G_DBUS_ERROR,
+                       G_DBUS_ERROR_FAILED,
+                       "Error while adding a match");
+          match_free (match);
+          return FALSE;
+        }
+
+      item->type = KDBUS_ITEM_NAME_REMOVE;
+      ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
+      if (ret < 0)
+        {
+          g_set_error (error,
+                       G_DBUS_ERROR,
+                       G_DBUS_ERROR_FAILED,
+                       "Error while adding a match");
+          match_free (match);
+          return FALSE;
+        }
+
+      item->type = KDBUS_ITEM_NAME_CHANGE;
+      ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
+      if (ret < 0)
+        {
+          g_set_error (error,
+                       G_DBUS_ERROR,
+                       G_DBUS_ERROR_FAILED,
+                       "Error while adding a match");
+          match_free (match);
+          return FALSE;
+        }
+    }
+
+  g_mutex_lock (&worker->matches_mutex);
+  worker->matches = g_list_prepend (worker->matches, match);
+  g_mutex_unlock (&worker->matches_mutex);
+  return TRUE;
+}
+
+
+/*
+ * g_kdbus_setup_bloom:
+ * Based on bus-bloom.c from systemd
+ * http://cgit.freedesktop.org/systemd/systemd/tree/src/libsystemd/sd-bus/bus-bloom.c
+ */
+static void
+g_kdbus_setup_bloom (GKDBusWorker               *worker,
+                     GDBusMessage               *dbus_msg,
+                     struct kdbus_bloom_filter  *bloom_filter)
+{
+  GVariant *body;
+  gchar *message_type;
+  const gchar *interface;
+  const gchar *member;
+  const gchar *path;
+  void *bloom_data;
+
+  body = g_dbus_message_get_body (dbus_msg);
+  message_type = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_TYPE, g_dbus_message_get_message_type (dbus_msg));
+  interface = g_dbus_message_get_interface (dbus_msg);
+  member = g_dbus_message_get_member (dbus_msg);
+  path = g_dbus_message_get_path (dbus_msg);
+
+  bloom_data = bloom_filter->data;
+  memset (bloom_data, 0, worker->bloom_size);
+  bloom_filter->generation = 0;
+
+  g_kdbus_bloom_add_pair(worker, bloom_data, "message-type", message_type);
+
+  if (interface)
+    g_kdbus_bloom_add_pair(worker, bloom_data, "interface", interface);
+
+  if (member)
+    g_kdbus_bloom_add_pair(worker, bloom_data, "member", member);
+
+  if (path)
+    {
+      g_kdbus_bloom_add_pair(worker, bloom_data, "path", path);
+      g_kdbus_bloom_add_pair(worker, bloom_data, "path-slash-prefix", path);
+      g_kdbus_bloom_add_prefixes(worker, bloom_data, "path-slash-prefix", path, '/');
+    }
+
+  if (body != NULL)
+    {
+      const GVariantType *body_type;
+      const GVariantType *arg_type;
+      guint cnt;
+
+      body_type = g_variant_get_type (body);
+
+      for (arg_type = g_variant_type_first (body_type), cnt = 0;
+           arg_type;
+           arg_type = g_variant_type_next (arg_type), cnt++)
+        {
+          gchar type_char = g_variant_type_peek_string (arg_type)[0];
+          gchar buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
+          const gchar *str;
+          GVariant *child;
+          gchar *e;
+
+          if (type_char != 's' && type_char != 'o')
+            /* XXX: kdbus docs say "stop after first non-string" but I
+             * think they're wrong (vs. dbus-1 compat)...
+             */
+            continue;
+
+          child = g_variant_get_child_value (body, cnt);
+          str = g_variant_get_string (child, NULL);
+
+          e = stpcpy(buf, "arg");
+          if (cnt < 10)
+            *(e++) = '0' + (char) cnt;
+          else
+            {
+              *(e++) = '0' + (char) (cnt / 10);
+              *(e++) = '0' + (char) (cnt % 10);
+            }
+
+          /* We add this one for both strings and object paths */
+          strcpy(e, "-slash-prefix");
+          g_kdbus_bloom_add_prefixes(worker, bloom_data, buf, str, '/');
+
+          /* But the others are only for strings */
+          if (type_char == 's')
+            {
+              strcpy(e, "-dot-prefix");
+              g_kdbus_bloom_add_prefixes(worker, bloom_data, buf, str, '.');
+
+              *e = 0;
+              g_kdbus_bloom_add_pair(worker, bloom_data, buf, str);
+            }
+
+          g_variant_unref (child);
+        }
+    }
+  g_free (message_type);
+}
+
+
+/*
+ * g_kdbus_translate_id_change
+ */
+static void
+g_kdbus_translate_id_change (GKDBusWorker       *worker,
+                             struct kdbus_item  *item)
+{
+  GDBusMessage *signal_message;
+  gchar *name;
+
+  signal_message = g_dbus_message_new_signal ("/org/freedesktop/DBus",
+                                              "org.freedesktop.DBus",
+                                              "NameOwnerChanged");
+
+  name = g_strdup_printf (":1.%"G_GUINT64_FORMAT, (guint64) item->id_change.id);
+
+  g_dbus_message_set_sender (signal_message, "org.freedesktop.DBus");
+  g_dbus_message_set_body (signal_message,
+                           g_variant_new ("(sss)",
+                                          name,
+                                          item->type == KDBUS_ITEM_ID_ADD ? "" : name,
+                                          item->type == KDBUS_ITEM_ID_ADD ? name : ""));
+
+  (* worker->message_received_callback) (signal_message, worker->user_data);
+
+  g_free (name);
+  g_object_unref (signal_message);
+}
+
+
+/*
+ * g_kdbus_translate_name_change
+ */
+static void
+g_kdbus_translate_name_change (GKDBusWorker       *worker,
+                               struct kdbus_item  *item)
+{
+  GDBusMessage *signal_message;
+
+  signal_message = NULL;
+
+  /* NameAcquired */
+  if ((item->type == KDBUS_ITEM_NAME_ADD) ||
+      (item->type == KDBUS_ITEM_NAME_CHANGE && ((guint64)item->name_change.new_id.id == worker->unique_id)))
+    {
+      signal_message = g_dbus_message_new_signal ("/org/freedesktop/DBus",
+                                                  "org.freedesktop.DBus",
+                                                  "NameAcquired");
+
+      g_dbus_message_set_sender (signal_message, "org.freedesktop.DBus");
+      g_dbus_message_set_body (signal_message,
+                               g_variant_new ("(s)", item->name_change.name));
+
+      (* worker->message_received_callback) (signal_message, worker->user_data);
+      g_object_unref (signal_message);
+    }
+
+  /* NameLost */
+  if ((item->type == KDBUS_ITEM_NAME_REMOVE) ||
+      (item->type == KDBUS_ITEM_NAME_CHANGE && ((guint64)item->name_change.old_id.id == worker->unique_id)))
+    {
+      signal_message = g_dbus_message_new_signal ("/org/freedesktop/DBus",
+                                                  "org.freedesktop.DBus",
+                                                  "NameLost");
+
+      g_dbus_message_set_sender (signal_message, "org.freedesktop.DBus");
+      g_dbus_message_set_body (signal_message,
+                               g_variant_new ("(s)", item->name_change.name));
+
+      (* worker->message_received_callback) (signal_message, worker->user_data);
+      g_object_unref (signal_message);
+    }
+
+  /* NameOwnerChanged */
+  if (1)
+    {
+      gchar *old_name;
+      gchar *new_name;
+
+      old_name = NULL;
+      new_name = NULL;
+
+      /* old_name */
+      if (!(item->type == KDBUS_ITEM_NAME_ADD || (item->name_change.old_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR))))
+        old_name = g_strdup_printf (":1.%"G_GUINT64_FORMAT, (guint64) item->name_change.old_id.id);
+
+      /* new_name */
+      if (!(item->type == KDBUS_ITEM_NAME_REMOVE || (item->name_change.new_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR))))
+        new_name = g_strdup_printf (":1.%"G_GUINT64_FORMAT, (guint64) item->name_change.new_id.id);
+      else
+        if (old_name == NULL)
+          return;
+
+      /* send signal */
+      signal_message = g_dbus_message_new_signal ("/org/freedesktop/DBus",
+                                                  "org.freedesktop.DBus",
+                                                  "NameOwnerChanged");
+      g_dbus_message_set_sender (signal_message, "org.freedesktop.DBus");
+      g_dbus_message_set_body (signal_message,
+                               g_variant_new ("(sss)",
+                                              item->name_change.name,
+                                              old_name ? old_name : "",
+                                              new_name ? new_name : ""));
+
+      (* worker->message_received_callback) (signal_message, worker->user_data);
+
+      g_free (old_name);
+      g_free (new_name);
+      g_object_unref (signal_message);
+    }
+}
+
+
+/*
+ * g_kdbus_translate_kernel_reply
+ */
+static void
+g_kdbus_translate_kernel_reply (GKDBusWorker       *worker,
+                                struct kdbus_msg   *msg,
+                                struct kdbus_item  *item)
+{
+  GDBusMessage *message;
+
+  message = g_dbus_message_new ();
+
+  g_dbus_message_set_message_type (message, G_DBUS_MESSAGE_TYPE_ERROR);
+  g_dbus_message_set_flags (message, G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED);
+  g_dbus_message_set_reply_serial (message, (guint32) msg->cookie_reply);
+
+  g_dbus_message_set_sender (message, "org.freedesktop.DBus");
+  g_dbus_message_set_destination (message, worker->unique_name);
+
+  g_dbus_message_set_error_name (message, "org.freedesktop.DBus.Error.NoReply");
+
+  if (item->type == KDBUS_ITEM_REPLY_TIMEOUT)
+    g_dbus_message_set_body (message, g_variant_new ("(s)", "Method call timed out"));
+  else
+    g_dbus_message_set_body (message, g_variant_new ("(s)", "Method call peer died"));
+
+  (* worker->message_received_callback) (message, worker->user_data);
+
+  g_object_unref (message);
+}
+
+
+/*
+ * g_kdbus_decode_kernel_msg
+ */
+static void
+g_kdbus_decode_kernel_msg (GKDBusWorker      *worker,
+                           struct kdbus_msg  *msg)
+{
+  struct kdbus_item *item = NULL;
+
+  KDBUS_ITEM_FOREACH(item, msg, items)
+    {
+     switch (item->type)
+        {
+          case KDBUS_ITEM_ID_ADD:
+          case KDBUS_ITEM_ID_REMOVE:
+            g_kdbus_translate_id_change (worker, item);
+            break;
+
+          case KDBUS_ITEM_NAME_ADD:
+          case KDBUS_ITEM_NAME_REMOVE:
+          case KDBUS_ITEM_NAME_CHANGE:
+            g_kdbus_translate_name_change (worker, item);
+            break;
+
+          case KDBUS_ITEM_REPLY_TIMEOUT:
+          case KDBUS_ITEM_REPLY_DEAD:
+            g_kdbus_translate_kernel_reply (worker, msg, item);
+            break;
+
+          case KDBUS_ITEM_TIMESTAMP:
+            break;
+
+          default:
+            g_warning ("kdbus: unknown field in kernel message - %lld", item->type);
+       }
+    }
+}
+
+#define DEFINE_READ_FUNCTION(name, type) \
+  static inline type \
+  read_ ## name (GVariantSerialised data) \
+  { \
+    if (data.size < sizeof(type)) \
+      return 0; \
+    return *(type *)data.data; \
+  }
+
+DEFINE_READ_FUNCTION (byte, guchar)
+DEFINE_READ_FUNCTION (uint64, guint64)
+DEFINE_READ_FUNCTION (uint32, guint32)
+
+static const gchar *
+check_str (GVariantSerialised data)
+{
+  const gchar *str = data.data;
+  if (str[data.size] == '\0')
+    return str;
+  return "";
+}
+
+/*
+ * g_kdbus_decode_dbus_msg
+ */
+static GKDBusMessage *
+g_kdbus_decode_dbus_msg (GKDBusWorker      *worker,
+                         struct kdbus_msg  *msg)
+{
+  GKDBusMessage *kmsg;
+  struct kdbus_item *item;
+  gssize data_size = 0;
+  GArray *body_vectors;
+  gsize body_size;
+  GVariant *body;
+  gchar *sender;
+  guint i;
+  GVariant *parts[2];
+  GString *owned_name;
+  guint8 type = 0, flags = 0;
+  guint64 serial = 0;
+  GVariantSerialised gvs;
+
+  kmsg = g_new0 (GKDBusMessage, 1);
+  kmsg->message = g_dbus_message_new();
+  kmsg->sender_euid = (uid_t) -1;
+  kmsg->sender_egid = (gid_t) -1;
+  kmsg->sender_seclabel = NULL;
+  kmsg->sender_names = NULL;
+
+  body_vectors = g_array_new (FALSE, FALSE, sizeof (GVariantVector));
+
+  item = msg->items;
+  body_size = 0;
+  owned_name = NULL;
+
+  KDBUS_ITEM_FOREACH(item, msg, items)
+    {
+      if (item->size < KDBUS_ITEM_HEADER_SIZE)
+        g_error("kdbus: %llu bytes - invalid data record", item->size);
+
+      data_size = item->size - KDBUS_ITEM_HEADER_SIZE;
+
+      switch (item->type)
+        {
+         case KDBUS_ITEM_DST_NAME:
+           /* Classic D-Bus doesn't make this known to the receiver, so
+            * we don't do it here either (for compatibility with the
+            * fallback case).
+            */
+           break;
+
+        case KDBUS_ITEM_PAYLOAD_OFF:
+          {
+            GVariantVector vector;
+            gsize flavour;
+
+            /* We want to make sure the bytes are aligned the same as
+             * they would be if they appeared in a contiguously
+             * allocated chunk of aligned memory.
+             *
+             * We decide what the alignment 'should' be by consulting
+             * body_size, which has been tracking the total size of the
+             * message up to this point.
+             *
+             * We then play around with the pointer by removing as many
+             * bytes as required to get it to the proper alignment (and
+             * copy extra bytes accordingly).  This means that we will
+             * grab some extra data in the 'bytes', but it won't be
+             * shared with GVariant (which means there is no chance of
+             * it being accidentally retransmitted).
+             *
+             * The kernel does the same thing, so make sure we get the
+             * expected result.  Because of the kernel doing the same,
+             * the result is that we will always be rounding-down to a
+             * multiple of 8 for the pointer, which means that the
+             * pointer will always be valid, assuming the original
+             * address was.
+             *
+             * We could fix this with a new GBytes constructor that took
+             * 'flavour' as a parameter, but it's not worth it...
+             */
+            flavour = body_size & 7;
+            g_assert ((item->vec.offset & 7) == flavour);
+
+            vector.gbytes = g_bytes_new (((guchar *) msg) + item->vec.offset - flavour, item->vec.size + flavour);
+            vector.data.pointer = g_bytes_get_data (vector.gbytes, NULL);
+            vector.data.pointer += flavour;
+            vector.size = item->vec.size;
+
+            g_array_append_val (body_vectors, vector);
+            body_size += vector.size;
+          }
+          break;
+
+        case KDBUS_ITEM_PAYLOAD_MEMFD:
+          {
+            GVariantVector vector;
+            const guchar *data;
+            gsize size;
+
+            vector.gbytes = g_bytes_new_take_zero_copy_fd_size (item->memfd.fd, item->memfd.size);
+            data = g_bytes_get_data (vector.gbytes, &size);
+
+            g_assert (item->memfd.size == size);
+
+            vector.data.pointer = data + item->memfd.start;
+            vector.size = item->memfd.size;
+
+            g_array_append_val (body_vectors, vector);
+            body_size += vector.size;
+          }
+          break;
+
+        case KDBUS_ITEM_FDS:
+          {
+            GUnixFDList *fd_list;
+
+            fd_list = g_unix_fd_list_new_from_array (item->fds, data_size / sizeof (int));
+            g_dbus_message_set_unix_fd_list (kmsg->message, fd_list);
+            g_object_unref (fd_list);
+          }
+          break;
+
+        /* [libdbuspolicy] read euid and egid values */
+        case KDBUS_ITEM_CREDS:
+
+          if ((uid_t) item->creds.euid != (uid_t) -1)
+            kmsg->sender_euid = (uid_t) item->creds.euid;
+
+          if ((gid_t) item->creds.egid != (gid_t) -1)
+            kmsg->sender_egid = (gid_t) item->creds.egid;
+
+          break;
+
+        /* [libdbuspolicy] read security label value */
+        case KDBUS_ITEM_SECLABEL:
+
+          /*if (item->str != NULL)*/
+            kmsg->sender_seclabel = g_strdup (item->str);
+
+          break;
+
+        /* [libdbuspolicy] read all owned well-known names */
+        case KDBUS_ITEM_OWNED_NAME:
+
+          if (g_dbus_is_name (item->name.name))
+            {
+              if (owned_name == NULL)
+                owned_name = g_string_new (item->name.name);
+              else
+                g_string_append_printf (owned_name, " %s", item->name.name);
+            }
+
+          break;
+
+        case KDBUS_ITEM_TIMESTAMP:
+        case KDBUS_ITEM_PIDS:
+        case KDBUS_ITEM_PID_COMM:
+        case KDBUS_ITEM_TID_COMM:
+        case KDBUS_ITEM_EXE:
+        case KDBUS_ITEM_CMDLINE:
+        case KDBUS_ITEM_CGROUP:
+        case KDBUS_ITEM_AUDIT:
+        case KDBUS_ITEM_CAPS:
+        case KDBUS_ITEM_CONN_DESCRIPTION:
+        case KDBUS_ITEM_AUXGROUPS:
+        case KDBUS_ITEM_NAME:
+        case KDBUS_ITEM_DST_ID:
+        case KDBUS_ITEM_BLOOM_FILTER:
+          break;
+
+        default:
+          g_warning ("kdbus: unknown filed - %lld", item->type);
+          break;
+        }
+    }
+
+  body = GLIB_PRIVATE_CALL(g_variant_from_vectors) (G_VARIANT_TYPE ("((yyyyuta{tv})v)"),
+                                                    (GVariantVector *) body_vectors->data,
+                                                    body_vectors->len, body_size, FALSE);
+  g_assert (body);
+
+  parts[0] = g_variant_get_child_value (body, 0);
+  gvs.type_info = g_variant_type_info_get (G_VARIANT_TYPE ("(yyyyuta{tv})"));
+  gvs.data = (guchar *)g_variant_get_data (parts[0]);
+  gvs.size = g_variant_get_size (parts[0]);
+  gvs.depth = 0;
+
+  type = read_byte (g_variant_serialised_get_child(gvs, 1));
+  flags = read_byte (g_variant_serialised_get_child(gvs, 2));
+  serial = read_uint64 (g_variant_serialised_get_child(gvs, 5));
+
+  {
+    guint8 i = 0;
+    gsize n_children;
+    GVariantSerialised gvsc;
+
+    gvsc = g_variant_serialised_get_child(gvs, 6);
+    n_children = g_variant_serialised_n_children(gvsc);
+
+    for (i = 0; i < n_children; i++) {
+      GVariantSerialised item;
+      GVariantSerialised variant;
+      guint64 key;
+      GVariantSerialised variant_value;
+
+      item = g_variant_serialised_get_child (gvsc, i);
+      key = read_uint64 (g_variant_serialised_get_child (item, 0));
+      variant = g_variant_serialised_get_child (item, 1);
+      variant_value = g_variant_serialised_get_child (variant, 0);  /* strip variant */
+
+      switch (key) {
+        case G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL:
+          {
+            guint64 val = read_uint64 (variant_value);
+            g_dbus_message_set_reply_serial (kmsg->message, (guint32)val);
+          }
+          break;
+        case G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS:
+          g_dbus_message_set_header (kmsg->message, key, g_variant_new_uint32 (read_uint32 (variant_value)));
+          break;
+        case G_DBUS_MESSAGE_HEADER_FIELD_PATH:
+          g_dbus_message_set_header (kmsg->message, key, g_variant_new_object_path (check_str (variant_value)));
+          break;
+        case G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE:
+          g_dbus_message_set_header (kmsg->message, key, g_variant_new_signature (check_str (variant_value)));
+          break;
+        default:
+          g_dbus_message_set_header (kmsg->message, key, g_variant_new_string (check_str (variant_value)));
+          break;
+      }
+    }
+  }
+
+  parts[1] = g_variant_get_child_value (body, 1);
+  g_variant_unref (body);
+
+  g_variant_unref (parts[0]);
+
+  for (i = 0; i < body_vectors->len; i++)
+    g_bytes_unref (g_array_index (body_vectors, GVariantVector, i).gbytes);
+
+  g_array_free (body_vectors, TRUE);
+
+  g_dbus_message_set_flags (kmsg->message, flags);
+  g_dbus_message_set_serial (kmsg->message, serial);
+  g_dbus_message_set_message_type (kmsg->message, type);
+
+  body = g_variant_get_variant (parts[1]);
+  if (!g_variant_is_of_type (body, G_VARIANT_TYPE ("()")))
+    g_dbus_message_set_body (kmsg->message, body);
+  else
+    g_dbus_message_set_body (kmsg->message, NULL);
+
+  g_variant_unref (body);
+  g_variant_unref (parts[1]);
+
+  /* set 'sender' field */
+  sender = g_strdup_printf (":1.%"G_GUINT64_FORMAT, (guint64) msg->src_id);
+  g_dbus_message_set_sender (kmsg->message, sender);
+  g_free (sender);
+
+  /* owned name */
+  if (owned_name != NULL)
+    kmsg->sender_names = g_string_free (owned_name, FALSE);
+
+  return kmsg;
+}
+
+
+/*
+ * _g_kdbus_receive
+ */
+static void
+_g_kdbus_receive (GKDBusWorker  *worker,
+                  GError       **error)
+{
+  struct kdbus_cmd_recv recv;
+  struct kdbus_msg *msg;
+  gboolean can_receive;
+  gint ret = 0;
+
+  can_receive = TRUE;
+  memset (&recv, 0, sizeof recv);
+  recv.size = sizeof (recv);
+
+again:
+    ret = ioctl (worker->fd, KDBUS_CMD_RECV, &recv);
+    if (ret < 0)
+           ret = errno;
+
+    if (recv.return_flags & KDBUS_RECV_RETURN_DROPPED_MSGS)
+      g_warning ("kdbus: %lld dropped broadcast messages", recv.dropped_msgs);
+
+    if (ret != 0)
+      {
+        if (ret == EINTR)
+          goto again;
+
+        if (ret == EAGAIN)
+          return;
+
+        g_set_error (error, G_IO_ERROR,
+                     g_io_error_from_errno (ret),
+                     _("Error while receiving message: %s"),
+                     g_strerror (ret));
+        return;
+      }
+
+    msg = (struct kdbus_msg *)((guint8 *)worker->kdbus_buffer + recv.msg.offset);
+
+    if (msg->payload_type == KDBUS_PAYLOAD_DBUS)
+      {
+        GKDBusMessage *kmsg;
+
+        kmsg = g_kdbus_decode_dbus_msg (worker, msg);
+
+#ifdef LIBDBUSPOLICY
+    if (worker->dbuspolicy != NULL)
+      {
+        if (g_dbus_message_get_message_type (kmsg->message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL ||
+            g_dbus_message_get_message_type (kmsg->message) == G_DBUS_MESSAGE_TYPE_SIGNAL)
+          {
+            if ((kmsg->sender_euid != (uid_t) -1) && (kmsg->sender_egid != (gid_t) -1) &&
+                (kmsg->sender_seclabel != NULL))
+              {
+                gint check;
+                const gchar *destination = g_dbus_message_get_destination (kmsg->message);
+                if (!destination)
+                  destination = worker->unique_name;
+
+                check = dbuspolicy1_check_in (worker->dbuspolicy,
+                                              destination,
+                                              kmsg->sender_names,
+                                              kmsg->sender_seclabel,
+                                              kmsg->sender_euid,
+                                              kmsg->sender_egid,
+                                              g_dbus_message_get_path (kmsg->message),
+                                              g_dbus_message_get_interface (kmsg->message),
+                                              g_dbus_message_get_member (kmsg->message),
+                                              g_dbus_message_get_message_type (kmsg->message),
+                                              NULL, 0, 0);
+                if (check != 1)
+                  {
+                    can_receive = FALSE;
+                  }
+              }
+            else
+              {
+                can_receive = FALSE;
+              }
+          }
+      }
+#endif
+
+       if (can_receive)
+         (* worker->message_received_callback) (kmsg->message, worker->user_data);
+
+       if (kmsg->sender_seclabel != NULL)
+         g_free (kmsg->sender_seclabel);
+
+       if (kmsg->sender_names != NULL)
+         g_free (kmsg->sender_names);
+
+       g_object_unref (kmsg->message);
+       g_free (kmsg);
+     }
+   else if (msg->payload_type == KDBUS_PAYLOAD_KERNEL)
+     g_kdbus_decode_kernel_msg (worker, msg);
+   else
+     {
+       g_set_error (error,
+                    G_DBUS_ERROR,
+                    G_DBUS_ERROR_FAILED,
+                    _("Received unknown payload type"));
+     }
+
+  g_kdbus_close_msg (worker, msg);
+  return;
+}
+
+static gboolean
+g_kdbus_msg_append_item (struct kdbus_msg  *msg,
+                         gsize              type,
+                         gconstpointer      data,
+                         gsize              size)
+{
+  struct kdbus_item *item;
+  gsize item_size;
+
+  item_size = size + G_STRUCT_OFFSET(struct kdbus_item, data);
+
+  msg->size += (-msg->size) & 7;
+  item = (struct kdbus_item *) ((guchar *) msg + msg->size);
+  item->type = type;
+  item->size = item_size;
+  memcpy (item->data, data, size);
+
+  msg->size += item_size;
+
+  return TRUE;
+}
+
+static gboolean
+g_kdbus_msg_append_payload_vec (struct kdbus_msg  *msg,
+                                gconstpointer      data,
+                                gsize              size)
+{
+  gboolean ok = TRUE;
+  do {
+    struct kdbus_vec vec = {
+      .size = size <= KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE ? size : KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE,
+      .address = (gsize) data
+    };
+    ok = g_kdbus_msg_append_item (msg, KDBUS_ITEM_PAYLOAD_VEC, &vec, sizeof vec);
+    data = (char*)data + vec.size;
+    size -= vec.size;
+  } while (size > 0 && ok);
+  return ok;
+}
+
+static gboolean
+g_kdbus_msg_append_payload_memfd (struct kdbus_msg  *msg,
+                                  gint               fd,
+                                  gsize              offset,
+                                  gsize              size)
+{
+  struct kdbus_memfd mfd = {
+   .start = offset,
+   .size = size,
+   .fd = fd,
+  };
+
+  return g_kdbus_msg_append_item (msg, KDBUS_ITEM_PAYLOAD_MEMFD, &mfd, sizeof mfd);
+}
+
+static struct kdbus_bloom_filter *
+g_kdbus_msg_append_bloom (struct kdbus_msg  *msg,
+                          gsize              size)
+{
+  struct kdbus_item *bloom_item;
+  gsize bloom_item_size;
+
+  bloom_item_size = (gulong) G_STRUCT_OFFSET (struct kdbus_item, bloom_filter) +
+                    (gulong) G_STRUCT_OFFSET (struct kdbus_bloom_filter, data) +
+                    size;
+
+  msg->size += (-msg->size) & 7;
+  bloom_item = (struct kdbus_item *) ((guchar *) msg + msg->size);
+
+  bloom_item->size = bloom_item_size;
+  bloom_item->type = KDBUS_ITEM_BLOOM_FILTER;
+
+  msg->size += bloom_item->size;
+  return &bloom_item->bloom_filter;
+}
+
+/*
+ * Returns header size.
+ */
+static gsize
+prepare_body_vectors (GKDBusWorker    *worker,
+                      GDBusMessage    *message,
+                      GVariantVectors *body_vectors,
+                      gboolean        *lg_h_field_exist)
+{
+  struct dbus_fixed_header fh;
+  GHashTableIter header_iter;
+  GVariantBuilder builder;
+  gpointer key, value;
+  GVariant *parts[3];
+  GVariant *body;
+  gsize header_size;
+
+  *lg_h_field_exist = FALSE;
+
+  fh.endian = (G_BYTE_ORDER == G_LITTLE_ENDIAN) ? 'l': 'B';
+  fh.type = g_dbus_message_get_message_type (message);
+  fh.flags = g_dbus_message_get_flags (message);
+  fh.version = 2;
+  fh.reserved = 0;
+  fh.serial = g_dbus_message_get_serial (message);
+  parts[0] = g_variant_new_from_data (DBUS_FIXED_HEADER_TYPE, &fh, sizeof fh, TRUE, NULL, NULL);
+  g_assert_nonnull (parts[0]);
+
+  g_dbus_message_init_header_iter (message, &header_iter);
+  g_variant_builder_init (&builder, DBUS_EXTENDED_HEADER_TYPE);
+
+  /* We set the sender field to the correct value for ourselves */
+  g_variant_builder_add (&builder, "{tv}",
+                         (guint64) G_DBUS_MESSAGE_HEADER_FIELD_SENDER,
+                         g_variant_new_printf (":1.%"G_GUINT64_FORMAT, worker->unique_id));
+
+  while (g_hash_table_iter_next (&header_iter, &key, &value))
+    {
+      guint64 key_int = (gsize) key;
+
+      switch (key_int)
+        {
+          /* These are the normal header fields that get passed
+           * straight through.
+           */
+          case G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL:
+            g_variant_builder_add (&builder, "{tv}", key_int, g_variant_new_uint64 (g_dbus_message_get_reply_serial(message)));
+            continue;
+
+
+          case G_DBUS_MESSAGE_HEADER_FIELD_PATH:
+          case G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE:
+          case G_DBUS_MESSAGE_HEADER_FIELD_MEMBER:
+          case G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME:
+          case G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION:
+          case G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS:
+            g_variant_builder_add (&builder, "{tv}", key_int, value);
+            /* This is a little bit gross.
+             *
+             * We must send the header part of the message in a single
+             * vector as per kdbus rules, but the GVariant serialiser
+             * code will split any item >= 128 bytes into its own
+             * vector to save the copy.
+             *
+             * Anyway, kdbus does not check it, and libraries handle it...
+             */
+
+            if (g_variant_get_size (value) >= 128)
+              *lg_h_field_exist = TRUE;
+
+            continue;
+
+          /* We send this one unconditionally, but set it ourselves */
+          case G_DBUS_MESSAGE_HEADER_FIELD_SENDER:
+            continue;
+
+          /* We don't send these at all in GVariant format */
+          case G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE:
+            continue;
+
+          default:
+            g_assert_not_reached ();
+        }
+    }
+  parts[1] = g_variant_builder_end (&builder);
+  g_assert_nonnull (parts[1]);
+
+  body = g_dbus_message_get_body (message);
+  if (!body)
+    body = g_variant_new ("()");
+  parts[2] = g_variant_new_variant (body);
+  g_assert_nonnull (parts[2]);
+
+  header_size = g_variant_get_size (parts[0]) + g_variant_get_size (parts[1]);
+
+  body = g_variant_ref_sink (g_variant_new_tuple (parts, G_N_ELEMENTS (parts)));
+  GLIB_PRIVATE_CALL(g_variant_to_vectors) (body, body_vectors);
+
+  /* Sanity check to make sure the header is really contiguous:
+   *
+   *  - we must have at least one vector in the output
+   *  - the first vector must completely contain at least the header; this
+   *    condition must be assured later, during composing kdbus vectors.
+   */
+  g_assert_cmpint (body_vectors->vectors->len, >, 0);
+
+  g_variant_unref (body);
+
+  return header_size;
+}
+
+static void
+make_single_header_vector (GVariantVectors *body_vectors,
+                           gsize            header_size,
+                           gboolean         lg_h_field_exist)
+{
+  guint i = 0;
+  gsize added_vectors_size = 0;
+  GVariantVector *first_vector;
+
+  /* Merge all header vectors into single vector */
+  first_vector = &g_array_index (body_vectors->vectors, GVariantVector, 0);
+  if (first_vector->size < header_size)
+    {
+      /* There are multiple header vectors, we have to join them together into a single one */
+      GByteArray *header = g_byte_array_sized_new (header_size);
+      gsize dummy_size;
+
+      g_assert_nonnull (header);
+      g_assert_true (lg_h_field_exist);
+
+      while (added_vectors_size < header_size && i < body_vectors->vectors->len)
+        {
+          GVariantVector *vector = &g_array_index (body_vectors->vectors, GVariantVector, i);
+
+          if (vector->gbytes)
+            {
+              g_byte_array_append (header, vector->data.pointer, vector->size);
+              g_bytes_unref (vector->gbytes);
+            }
+          else
+            {
+              g_byte_array_append (header, body_vectors->extra_bytes->data + vector->data.offset, vector->size);
+            }
+
+          added_vectors_size += vector->size;
+          i++;
+        }
+
+      /* Sanity check if the first vector contains at least the complete header */
+      g_assert_cmpint (added_vectors_size, >=, header_size);
+
+      first_vector->gbytes = g_byte_array_free_to_bytes (header);
+      first_vector->data.pointer = g_bytes_get_data (first_vector->gbytes, &dummy_size);
+      first_vector->size = added_vectors_size;
+
+      g_array_remove_range (body_vectors->vectors, 1, i-1);
+    }
+  /* else: If there is only a single header vector, then just go */
+}
+
+static gboolean
+add_message_destination_item (struct kdbus_msg *msg,
+                              GDBusMessage     *message,
+                              GError          **error)
+{
+  const gchar *dst_name;
+
+  dst_name = g_dbus_message_get_destination (message);
+  if (dst_name != NULL)
+    {
+      if (g_dbus_is_unique_name (dst_name))
+        {
+          if (dst_name[1] != '1' || dst_name[2] != '.')
+            {
+              g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
+                           "Invalid unique D-Bus name '%s'", dst_name);
+              return FALSE;
+            }
+
+          /* We already know that it passes the checks for unique
+           * names, so no need to perform error checking on strtoull.
+           */
+          msg->dst_id = strtoull (dst_name + 3, NULL, 10);
+        }
+      else
+        {
+          g_kdbus_msg_append_item (msg, KDBUS_ITEM_DST_NAME, dst_name, strlen (dst_name) + 1);
+          msg->dst_id = KDBUS_DST_ID_NAME;
+        }
+    }
+  else
+    msg->dst_id = KDBUS_DST_ID_BROADCAST;
+
+  return TRUE;
+}
+
+static void
+add_file_descriptors_item (struct kdbus_msg *msg,
+                           GDBusMessage     *message)
+{
+  GUnixFDList *fd_list;
+
+  fd_list = g_dbus_message_get_unix_fd_list (message);
+  if (fd_list != NULL)
+    {
+      const gint *fds;
+      gint n_fds;
+
+      fds = g_unix_fd_list_peek_fds (fd_list, &n_fds);
+
+      if (n_fds)
+        g_kdbus_msg_append_item (msg, KDBUS_ITEM_FDS, fds, sizeof (gint) * n_fds);
+    }
+}
+
+static gboolean
+add_body_vectors (struct kdbus_msg *msg,
+                  GVariantVectors  *body_vectors,
+                  gint             *memfd_fd)
+{
+  guint i = 0;
+
+  /* Add all the vectors to the kdbus message */
+  for (; i < body_vectors->vectors->len; i++)
+    {
+      GVariantVector vector = g_array_index (body_vectors->vectors, GVariantVector, i);
+
+      if (vector.gbytes)
+        {
+          const guchar *bytes_data;
+          gboolean use_memfd;
+          gsize bytes_size;
+
+          use_memfd = FALSE;
+          bytes_data = g_bytes_get_data (vector.gbytes, &bytes_size);
+
+          /* check whether we can and should use memfd */
+          if ((msg->dst_id != KDBUS_DST_ID_BROADCAST) && (bytes_size > KDBUS_MEMFD_THRESHOLD))
+            use_memfd = TRUE;
+
+          if (use_memfd)
+            {
+              const guchar *bytes_data_wr;
+              gint64 wr;
+
+              /* create memfd object */
+              *memfd_fd = glib_linux_memfd_create ("glib-kdbus-memfd", MFD_CLOEXEC | MFD_ALLOW_SEALING);
+              if (*memfd_fd == -1)
+                {
+                  g_warning ("kdbus: missing kernel memfd support");
+                  use_memfd = FALSE; /* send as PAYLOAD_VEC item */
+                }
+              else
+                {
+                  /* write data to memfd */
+                  bytes_data_wr = bytes_data;
+                  while (bytes_size)
+                    {
+                      wr = write (*memfd_fd, bytes_data_wr, bytes_size);
+                      if (wr < 0)
+                        g_warning ("kdbus: writing to memfd failed: (%d) %m", errno);
+
+                      bytes_size -= wr;
+                      bytes_data_wr += wr;
+                    }
+
+                  /* seal memfd */
+                  if (!g_unix_fd_ensure_zero_copy_safe (*memfd_fd))
+                    {
+                      g_warning ("kdbus: memfd sealing failed");
+                      use_memfd = FALSE; /* send as PAYLOAD_VEC item */
+                    }
+                  else
+                    {
+                      /* attach memfd item */
+                      if (!g_kdbus_msg_append_payload_memfd (msg, *memfd_fd, vector.data.pointer - bytes_data, vector.size))
+                        return FALSE;
+                    }
+                } /* *memfd_fd == -1 */
+            } /* use_memfd */
+
+          if (!use_memfd)
+            if (!g_kdbus_msg_append_payload_vec (msg, vector.data.pointer, vector.size))
+              return FALSE;
+        }
+      else
+        if (!g_kdbus_msg_append_payload_vec (msg, body_vectors->extra_bytes->data + vector.data.offset, vector.size))
+          return FALSE;
+    }
+  return TRUE;
+}
+
+static gboolean
+add_bloom_item (struct kdbus_msg *msg,
+                GDBusMessage     *message,
+                GKDBusWorker     *worker)
+{
+  struct kdbus_bloom_filter *bloom_filter;
+
+  if (g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_SIGNAL)
+    {
+      msg->flags |= KDBUS_MSG_SIGNAL;
+      bloom_filter = g_kdbus_msg_append_bloom (msg, worker->bloom_size);
+      if (bloom_filter == NULL)
+        return FALSE;
+      g_kdbus_setup_bloom (worker, message, bloom_filter);
+    }
+  return TRUE;
+}
+
+static gsize
+compute_msg_size (GDBusMessage    *message,
+                  GKDBusWorker    *worker,
+                  GVariantVectors *body_vectors)
+{
+  gsize items_size = 0;
+  GUnixFDList *fd_list;
+  const gchar *dst_name;
+  guint i;
+  GDBusMessageType msg_type = g_dbus_message_get_message_type (message);
+
+  /* payload - check which vectors will become memfds */
+  for (i = 0; i < body_vectors->vectors->len; i++)
+    {
+      GVariantVector vector = g_array_index (body_vectors->vectors, GVariantVector, i);
+      gsize payload_size;
+      gsize kdbus_num_vectors;
+
+      if (vector.gbytes)
+        {
+          payload_size = g_bytes_get_size (vector.gbytes);
+          if (msg_type != G_DBUS_MESSAGE_TYPE_SIGNAL && payload_size > KDBUS_MEMFD_THRESHOLD)
+            {
+              /* We can do this because we know that struct kdbus_memfd is larger or equal than
+                 struct kdbus_vec. struct kdbus_vec is fallback option if memfd does not work */
+              items_size += KDBUS_ITEM_SIZE (sizeof (struct kdbus_memfd));
+              continue;
+            }
+        }
+      else
+        {
+          payload_size = vector.size;
+        }
+
+      kdbus_num_vectors = (payload_size + KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE - 1) / KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE;
+      items_size += KDBUS_ITEM_SIZE (sizeof (struct kdbus_vec)) * kdbus_num_vectors;
+    }
+
+  /* file descriptors */
+  fd_list = g_dbus_message_get_unix_fd_list (message);
+  if (fd_list != NULL)
+    items_size += KDBUS_ITEM_SIZE (g_unix_fd_list_get_length (fd_list) * sizeof(gint));
+
+  /* destination */
+  dst_name = g_dbus_message_get_destination (message);
+  if (dst_name != NULL)
+    items_size += KDBUS_ITEM_SIZE (strlen (dst_name) + 1);
+
+  /* bloom filters */
+  if (msg_type == G_DBUS_MESSAGE_TYPE_SIGNAL)
+    items_size += KDBUS_ITEM_SIZE (sizeof (struct kdbus_bloom_filter) + worker->bloom_size);
+
+  return sizeof (struct kdbus_msg) + items_size;
+}
+
+#ifdef LIBDBUSPOLICY
+static GDBusMessage*
+create_access_error_reply (GDBusMessage *message,
+                           const GQuark  domain,
+                           const gint    code,
+                           const gchar  *format,
+                           ...)
+{
+  gchar *error_text;
+  GError *access_error;
+  gchar *dbus_error_name;
+  GDBusMessage *error_reply;
+  va_list args;
+
+  va_start (args, format);
+  error_text = g_strdup_vprintf (format, args);
+  va_end (args);
+
+  access_error = NULL;
+  g_set_error (&access_error, domain, code, "%s", error_text);
+  dbus_error_name = g_dbus_error_encode_gerror (access_error);
+  g_error_free (access_error);
+
+  error_reply = g_dbus_message_new_method_error (message, dbus_error_name, "%s", error_text);
+  g_free (dbus_error_name);
+  g_free (error_text);
+  return error_reply;
+}
+#endif
+
+#ifdef LIBDBUSPOLICY
+static GDBusMessage*
+check_result_to_error_reply (GDBusMessage *message,
+                             const gint    check_result)
+{
+  switch (check_result)
+    {
+      case DBUSPOLICY_RESULT_DENY:
+        return create_access_error_reply (message, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED,
+                     "Cannot send message - message rejected due to XML security policies");
+
+      case DBUSPOLICY_RESULT_DEST_NOT_AVAILABLE:
+        if (g_dbus_message_get_flags (message) & G_DBUS_MESSAGE_FLAGS_NO_AUTO_START)
+          return create_access_error_reply (message, G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
+                       "Name \"%s\" does not exist", g_dbus_message_get_destination (message));
+        else
+          return create_access_error_reply (message, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN,
+                       "Cannot send message - destination '%s' not known", g_dbus_message_get_destination (message));
+
+      case DBUSPOLICY_RESULT_KDBUS_ERROR:
+        return create_access_error_reply (message, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED,
+                     "Cannot send message - message rejected due to internal libdbuspolicy error (kdbus)");
+
+      case DBUSPOLICY_RESULT_CYNARA_ERROR:
+        return create_access_error_reply (message, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED,
+                     "Cannot send message - message rejected due to internal libdbuspolicy error (Cynara)");
+
+      default:
+        return create_access_error_reply (message, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED,
+                     "Cannot send message - unknown libdbuspolicy error");
+    }
+}
+#endif
+
+/*
+ * _g_kdbus_send
+ */
+static gboolean
+_g_kdbus_send (GKDBusWorker  *worker,
+               GDBusMessage  *message,
+               GDBusMessage **out_reply,
+               gint           timeout_msec,
+               GCancellable  *cancellable,
+               GError       **error)
+{
+  struct kdbus_msg *msg;
+  GVariantVectors body_vectors;
+  struct kdbus_cmd_send *send;
+  gsize send_size;
+  gboolean result = FALSE;
+  gboolean lg_h_field_exist = FALSE;
+
+  gint memfd_fd;
+  gint cancel_fd;
+
+  gsize header_size;
+  gsize msg_size;
+
+  g_return_val_if_fail (G_IS_KDBUS_WORKER (worker), FALSE);
+
+  send = NULL;
+  send_size = sizeof(*send);
+
+  /* Prepare message body - it is needed for kdbus msg size computation */
+  header_size = prepare_body_vectors (worker, message, &body_vectors, &lg_h_field_exist);
+  make_single_header_vector (&body_vectors, header_size, lg_h_field_exist);
+
+  /* We precompute needed size for the message to allocate exact space instead
+     of some arbitrary amount */
+  msg_size = compute_msg_size (message, worker, &body_vectors);
+  if (msg_size <= KDBUS_MSG_MAX_SIZE)
+    {
+      msg = g_alloca (msg_size);
+      memset (msg, 0, msg_size);
+    }
+  else
+    {
+      msg = g_malloc0 (msg_size);
+    }
+  g_assert_nonnull (msg);
+
+  memfd_fd = -1;
+  cancel_fd = -1;
+
+  /* fill in as we go... */
+  msg->size = sizeof (struct kdbus_msg);
+  msg->payload_type = KDBUS_PAYLOAD_DBUS;
+  msg->cookie = g_dbus_message_get_serial(message);
+
+  /* Message destination */
+  if (!add_message_destination_item (msg, message, error))
+    goto out;
+
+  /* File descriptors */
+  add_file_descriptors_item (msg, message);
+
+  if (!add_body_vectors (msg, &body_vectors, &memfd_fd))
+    {
+      g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+                   "message serialisation error: body vectors");
+      g_warning ("kdbus: message serialisation error: body vectors");
+      goto out;
+    }
+
+  /*
+   * set message flags
+   */
+  msg->flags = ((g_dbus_message_get_flags (message) & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_EXPECT_REPLY) |
+                ((g_dbus_message_get_flags (message) & G_DBUS_MESSAGE_FLAGS_NO_AUTO_START) ? KDBUS_MSG_NO_AUTO_START : 0);
+
+  if ((msg->flags) & KDBUS_MSG_EXPECT_REPLY)
+    msg->timeout_ns = 1U | ( /* ensure nonzero */
+                        1000U * g_get_monotonic_time() + (
+                          timeout_msec == -1 ? DBUS_DEFAULT_TIMEOUT_MSEC * 1000000LLU :
+                          timeout_msec == G_MAXINT ? KDBUS_INFINITE_TIMEOUT_NS :
+                          (guint64)timeout_msec * 1000000U
+                        )
+                      );
+  else
+    msg->cookie_reply = g_dbus_message_get_reply_serial(message);
+
+  /*
+   * append bloom filter item for broadcast signals
+   */
+  if (!add_bloom_item (msg, message, worker))
+    {
+      g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+                   "message serialisation error: bloom filters");
+      g_warning ("kdbus: message serialisation error: bloom filters");
+      goto out;
+    }
+
+  if (out_reply != NULL && cancellable)
+    {
+      cancel_fd = g_cancellable_get_fd (cancellable);
+      if (cancel_fd != -1)
+        send_size += KDBUS_ITEM_SIZE (sizeof(cancel_fd));
+    }
+
+  g_assert_cmpuint (msg->size, <=, msg_size);
+
+  send = g_alloca0 (send_size);
+  send->size = send_size;
+  send->msg_address = (gsize) msg;
+
+  if (out_reply != NULL)
+    {
+      /* synchronous call */
+      send->flags = KDBUS_SEND_SYNC_REPLY;
+
+      if (cancel_fd != -1)
+        {
+          struct kdbus_item *item;
+
+          item = send->items;
+          item->type = KDBUS_ITEM_CANCEL_FD;
+          item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(cancel_fd);
+          item->fds[0] = cancel_fd;
+        }
+    }
+  else
+    {
+      /* asynchronous call */
+      send->flags = 0;
+    }
+
+  /*
+   * show debug
+   */
+  if (G_UNLIKELY (_g_dbus_debug_message ()))
+    {
+      gchar *s;
+      _g_dbus_debug_print_lock ();
+      g_print ("========================================================================\n"
+               "GDBus-debug:Message:\n"
+               "  >>>> SENT D-Bus/kdbus message\n");
+      s = g_dbus_message_print (message, 2);
+      g_print ("%s", s);
+      g_free (s);
+      _g_dbus_debug_print_unlock ();
+    }
+
+  /*
+   * check policy
+   */
+#ifdef LIBDBUSPOLICY
+  if (worker->dbuspolicy != NULL)
+    {
+      if (g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL ||
+         (g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_SIGNAL &&
+           g_dbus_message_get_destination (message) != NULL))
+        {
+          gint check;
+
+          check = dbuspolicy1_check_out (worker->dbuspolicy,
+                                         g_dbus_message_get_destination (message),
+                                         worker->unique_name,
+                                         g_dbus_message_get_path (message),
+                                         g_dbus_message_get_interface (message),
+                                         g_dbus_message_get_member (message),
+                                         g_dbus_message_get_message_type (message),
+                                         NULL, 0, 0);
+          if (check != DBUSPOLICY_RESULT_ALLOW)
+            {
+              GDBusMessage *access_error_message;
+              access_error_message = check_result_to_error_reply (message, check);
+              result = TRUE;
+              if (out_reply != NULL)
+                {
+                  *out_reply = access_error_message;
+                }
+              else
+                {
+                  send_synthetic_message (worker, access_error_message);
+                }
+
+              goto out;
+            }
+        }
+    }
+#endif
+
+  /*
+   * send message
+   */
+  if (ioctl(worker->fd, KDBUS_CMD_SEND, send))
+    {
+      int ret = errno;
+      gchar *info;
+      if (asprintf (&info, "sender=%s destination=%s path=%s interface=%s member=%s type=%d",
+                       g_dbus_message_get_sender (message),
+                       g_dbus_message_get_destination (message),
+                       g_dbus_message_get_path (message),
+                       g_dbus_message_get_interface (message),
+                       g_dbus_message_get_member (message),
+                       g_dbus_message_get_message_type (message)) < 0)
+        {
+        g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "%s", g_strerror(errno));
+        /* If asprintf fails, we lose the ioctl errno,
+         * but without info, we can't give a useful error message.
+         * In practice though, asprintf failure is exceedingly rare.
+         */
+        }
+      else
+        {
+          errno = ret;
+          if (errno == ENXIO || errno == ESRCH)
+            {
+              if (g_dbus_message_get_flags (message) & G_DBUS_MESSAGE_FLAGS_NO_AUTO_START)
+                g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
+                             "Name \"%s\" does not exist, %s", g_dbus_message_get_destination (message), info);
+              else
+                g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN,
+                             "Destination '%s' not known, %s", g_dbus_message_get_destination (message), info);
+            }
+          else if (errno == EADDRNOTAVAIL)
+            {
+              g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN,
+                           "No support for activation for name: %s, %s", g_dbus_message_get_destination (message), info);
+            }
+          else if (errno == EXFULL)
+            {
+              g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_LIMITS_EXCEEDED,
+                           "The memory pool of the receiver is full, %s", info);
+            }
+          else if (errno == ENOBUFS)
+            {
+              g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_LIMITS_EXCEEDED,
+                           "Too many pending messages on the receiver side, %s", info);
+            }
+            else if (errno == EMSGSIZE)
+            {
+              g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_LIMITS_EXCEEDED,
+                           "The size of the message is excessive, %s", info);
+            }
+          else if (errno == EMLINK)
+            {
+              g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_LIMITS_EXCEEDED,
+                           "The maximum number of pending replies per connection has been reached, %s", info);
+            }
+          else if (errno == ECANCELED)
+            {
+              g_set_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
+                           "Operation was cancelled, %s", info);
+            }
+          else if (errno == ETIMEDOUT)
+            {
+              g_set_error (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT,
+                           "Timeout was reached, %s", info);
+            }
+          else if (errno == EPERM)
+            {
+              g_set_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+                           "Permission denied, %s", info);
+            }
+          else
+            {
+              g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "%s, %s", g_strerror(errno), info);
+              g_warning ("kdbus: %s, %s", g_strerror(errno), info);
+            }
+          free(info);
+        }
+    }
+  else
+    {
+      result = TRUE;
+      if (out_reply != NULL)
+        {
+          GKDBusMessage *kmsg;
+          struct kdbus_msg *kdbus_msg;
+
+          kdbus_msg = (struct kdbus_msg *)((guint8 *)worker->kdbus_buffer + send->reply.offset);
+
+          kmsg = g_kdbus_decode_dbus_msg (worker, kdbus_msg);
+          g_kdbus_close_msg (worker, kdbus_msg);
+
+          *out_reply = kmsg->message;
+
+          if (kmsg->sender_seclabel != NULL)
+            g_free (kmsg->sender_seclabel);
+
+          if (kmsg->sender_names != NULL)
+            g_free (kmsg->sender_names);
+
+          g_free (kmsg);
+
+          if (G_UNLIKELY (_g_dbus_debug_message ()))
+            {
+              gchar *s;
+              _g_dbus_debug_print_lock ();
+              g_print ("========================================================================\n"
+                       "GDBus-debug:Message:\n"
+                       "  <<<< RECEIVED D-Bus message\n");
+              s = g_dbus_message_print (*out_reply, 2);
+              g_print ("%s", s);
+              g_free (s);
+              _g_dbus_debug_print_unlock ();
+            }
+        }
+    }
+
+out:
+  if (msg_size > KDBUS_MSG_MAX_SIZE)
+    g_free (msg);
+
+  if (cancel_fd != -1)
+    g_cancellable_release_fd (cancellable);
+
+  if (memfd_fd != -1)
+    close (memfd_fd);
+
+  GLIB_PRIVATE_CALL(g_variant_vectors_deinit) (&body_vectors);
+
+  return result;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+g_kdbus_worker_finalize (GObject *object)
+{
+  GKDBusWorker *worker;
+  GList *match;
+
+  worker = G_KDBUS_WORKER (object);
+
+  if (worker->kdbus_buffer != NULL)
+    {
+      munmap (worker->kdbus_buffer, worker->receive_pool_size);
+      worker->kdbus_buffer = NULL;
+      worker->receive_pool_size = 0;
+    }
+
+  if (worker->unique_name != NULL)
+    g_free (worker->unique_name);
+  worker->unique_name = NULL;
+
+  for (match = worker->matches; match != NULL; match = match->next)
+    match_free (match->data);
+  g_list_free (worker->matches);
+  g_mutex_clear (&worker->matches_mutex);
+
+#ifdef LIBDBUSPOLICY
+  if (worker->dbuspolicy != NULL)
+    dbuspolicy1_free (worker->dbuspolicy);
+#endif
+
+  if (worker->fd != -1 && !worker->closed)
+    _g_kdbus_close (worker);
+
+  G_OBJECT_CLASS (g_kdbus_worker_parent_class)->finalize (object);
+}
+
+static void
+g_kdbus_worker_class_init (GKDBusWorkerClass *class)
+{
+  class->finalize = g_kdbus_worker_finalize;
+}
+
+static void
+g_kdbus_worker_init (GKDBusWorker *worker)
+{
+  worker->fd = -1;
+
+  worker->context = NULL;
+  worker->loop = NULL;
+  worker->thread = NULL;
+  worker->source = 0;
+
+  worker->kdbus_buffer = NULL;
+  worker->receive_pool_size = 0;
+  worker->unique_name = NULL;
+  worker->unique_id = -1;
+
+  worker->flags = KDBUS_HELLO_ACCEPT_FD;
+  worker->attach_flags_send = _KDBUS_ATTACH_ALL;
+  /* Attach items we really use only. Each collected item brings unneccessary overhead.
+   *
+   * The flags are used by libdbuspolicy library which uses these to apply dbus policy
+   * to each received message.
+   */
+  worker->attach_flags_recv = KDBUS_ATTACH_PIDS | KDBUS_ATTACH_CREDS | KDBUS_ATTACH_SECLABEL;
+
+  worker->bloom_size = 0;
+  worker->bloom_n_hash = 0;
+  worker->matches = NULL;
+  g_mutex_init (&worker->matches_mutex);
+
+#ifdef LIBDBUSPOLICY
+  worker->dbuspolicy = NULL;
+#endif
+}
+
+static gpointer
+_g_kdbus_worker_thread (gpointer _data)
+{
+  GMainLoop *loop = (GMainLoop *) _data;
+
+  g_main_loop_run (loop);
+
+  g_main_loop_unref (loop);
+
+  return NULL;
+}
+
+GKDBusWorker *
+_g_kdbus_worker_new (const gchar  *address,
+                     GError      **error)
+{
+  GKDBusWorker *worker;
+
+  worker = g_object_new (G_TYPE_KDBUS_WORKER, NULL);
+  if (!_g_kdbus_open (worker, address, error))
+    {
+      g_object_unref (worker);
+      return NULL;
+    }
+
+  worker->context = g_main_context_new ();
+  worker->loop = g_main_loop_new (worker->context, FALSE);
+  worker->thread = g_thread_new ("gkdbus", _g_kdbus_worker_thread, g_main_loop_ref(worker->loop));
+
+  return worker;
+}
+
+void
+_g_kdbus_worker_associate (GKDBusWorker                            *worker,
+                           GDBusCapabilityFlags                     capabilities,
+                           GDBusWorkerMessageReceivedCallback       message_received_callback,
+                           GDBusWorkerMessageAboutToBeSentCallback  message_about_to_be_sent_callback,
+                           GDBusWorkerDisconnectedCallback          disconnected_callback,
+                           gpointer                                 user_data)
+{
+  worker->capabilities = capabilities;
+  worker->message_received_callback = message_received_callback;
+  worker->message_about_to_be_sent_callback = message_about_to_be_sent_callback;
+  worker->disconnected_callback = disconnected_callback;
+  worker->user_data = user_data;
+}
+
+static gboolean
+g_kdbus_ready (gint           fd,
+               GIOCondition   condition,
+               gpointer       user_data)
+{
+  GKDBusWorker *worker;
+  GError *error;
+
+  worker = user_data;
+  error = NULL;
+
+  _g_kdbus_receive (worker, &error);
+  g_assert_no_error (error);
+
+  return G_SOURCE_CONTINUE;
+}
+
+void
+_g_kdbus_worker_unfreeze (GKDBusWorker *worker)
+{
+  gchar *name;
+
+  if (worker->source != NULL)
+    return;
+
+  worker->source = g_unix_fd_source_new (worker->fd, G_IO_IN);
+
+  g_source_set_callback (worker->source, (GSourceFunc) g_kdbus_ready,
+                         g_object_ref (worker), g_object_unref);
+  name = g_strdup_printf ("kdbus worker");
+  g_source_set_name (worker->source, name);
+  g_free (name);
+
+  g_source_attach (worker->source, worker->context);
+}
+
+gboolean
+_g_kdbus_worker_send_message (GKDBusWorker  *worker,
+                              GDBusMessage  *message,
+                              gint           timeout_msec,
+                              GError       **error)
+{
+#ifdef DBUS_DAEMON_EMULATION
+  if (_is_message_to_dbus_daemon (message))
+    {
+      GDBusMessage *reply = NULL;
+      reply = _dbus_daemon_synthetic_reply (worker, message, FALSE);
+
+      if (reply)
+        {
+          SyntheticReplyData *data;
+
+          data = g_new0 (SyntheticReplyData, 1);
+
+          data->worker = worker;
+          data->message = reply;
+
+          g_main_context_invoke (worker->context, deliver_synthetic_reply, data);
+        }
+
+      return TRUE;
+    }
+#endif /* DBUS_DAEMON_EMULATION */
+
+  return _g_kdbus_send (worker, message, NULL, timeout_msec, NULL, error);
+}
+
+gboolean
+_g_kdbus_worker_send_message_sync (GKDBusWorker  *worker,
+                                   GDBusMessage  *message,
+                                   GDBusMessage **out_reply,
+                                   gint           timeout_msec,
+                                   GCancellable  *cancellable,
+                                   GError       **error)
+{
+#ifdef DBUS_DAEMON_EMULATION
+  if (_is_message_to_dbus_daemon (message))
+    {
+      *out_reply = _dbus_daemon_synthetic_reply (worker, message, TRUE);
+      return TRUE;
+    }
+#endif /* DBUS_DAEMON_EMULATION */
+
+  return _g_kdbus_send (worker, message, out_reply, timeout_msec, cancellable, error);
+}
+
+gboolean
+_g_kdbus_worker_flush_sync (GKDBusWorker *worker)
+{
+  return TRUE;
+}
+
+void
+_g_kdbus_worker_stop (GKDBusWorker *worker)
+{
+  g_source_destroy (worker->source);
+  g_source_unref (worker->source);
+  worker->source = 0;
+
+  g_object_unref (worker);
+}
+
+void
+_g_kdbus_worker_close (GKDBusWorker       *worker,
+                       GTask              *task)
+{
+  worker->disconnected_callback (FALSE, NULL, worker->user_data);
+  g_task_return_boolean (task, TRUE);
+}
diff --git a/gio/gkdbus.h b/gio/gkdbus.h
new file mode 100644 (file)
index 0000000..acbc0d5
--- /dev/null
@@ -0,0 +1,203 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2015 Samsung Electronics
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Lukasz Skalski       <l.skalski@samsung.com>
+ * Author: Michal Eljasiewicz   <m.eljasiewic@samsung.com>
+ */
+
+#ifndef __G_KDBUS_H__
+#define __G_KDBUS_H__
+
+#if !defined (GIO_COMPILATION)
+#error "gkdbus.h is a private header file."
+#endif
+
+#include <gio/giotypes.h>
+#include "gdbusprivate.h"
+
+#define G_TYPE_KDBUS_WORKER                                (g_kdbus_worker_get_type ())
+#define G_KDBUS_WORKER(inst)                               (G_TYPE_CHECK_INSTANCE_CAST ((inst),                     \
+                                                            G_TYPE_KDBUS_WORKER, GKDBusWorker))
+#define G_KDBUS_WORKER_CLASS(class)                        (G_TYPE_CHECK_CLASS_CAST ((class),                       \
+                                                            G_TYPE_KDBUS_WORKER, GKDBusWorkerClass))
+#define G_IS_KDBUS_WORKER(inst)                            (G_TYPE_CHECK_INSTANCE_TYPE ((inst),                     \
+                                                            G_TYPE_KDBUS_WORKER))
+#define G_IS_KDBUS_WORKER_CLASS(class)                     (G_TYPE_CHECK_CLASS_TYPE ((class),                       \
+                                                            G_TYPE_KDBUS_WORKER))
+#define G_KDBUS_WORKER_GET_CLASS(inst)                     (G_TYPE_INSTANCE_GET_CLASS ((inst),                      \
+                                                            G_TYPE_KDBUS_WORKER, GKDBusWorkerClass))
+typedef enum {
+  G_DBUS_CREDS_NONE = 0,
+  G_DBUS_CREDS_PID = (1<<0),
+  G_DBUS_CREDS_UID = (1<<1),
+  G_DBUS_CREDS_UNIQUE_NAME = (1<<2),
+  G_DBUS_CREDS_SEC_LABEL = (1<<3)
+} GDBusCredentialsFlags;
+
+typedef struct
+{
+  guint   pid;
+  guint   uid;
+  gchar  *unique_name;
+  gchar  *sec_label;
+} GDBusCredentials;
+
+typedef struct
+{
+  GDBusMessage  *message;
+  uid_t          sender_euid;
+  gid_t          sender_egid;
+  gchar         *sender_seclabel;
+  gchar         *sender_names;
+} GKDBusMessage;
+
+typedef struct _GKDBusWorker                                  GKDBusWorker;
+
+void                  _g_kdbus_worker_associate              (GKDBusWorker                             *worker,
+                                                              GDBusCapabilityFlags                      capabilities,
+                                                              GDBusWorkerMessageReceivedCallback        message_received_callback,
+                                                              GDBusWorkerMessageAboutToBeSentCallback   message_about_to_be_sent_callback,
+                                                              GDBusWorkerDisconnectedCallback           disconnected_callback,
+                                                              gpointer                                  user_data);
+
+GType                  g_kdbus_worker_get_type               (void);
+
+GKDBusWorker *        _g_kdbus_worker_new                    (const gchar         *address,
+                                                              GError             **error);
+
+void                  _g_kdbus_worker_unfreeze               (GKDBusWorker        *worker);
+
+gboolean              _g_kdbus_worker_send_message           (GKDBusWorker        *worker,
+                                                              GDBusMessage        *message,
+                                                              gint                 timeout_msec,
+                                                              GError             **error);
+
+gboolean              _g_kdbus_worker_send_message_sync      (GKDBusWorker        *worker,
+                                                              GDBusMessage        *message,
+                                                              GDBusMessage       **out_reply,
+                                                              gint                 timeout_msec,
+                                                              GCancellable        *cancellable,
+                                                              GError             **error);
+
+void                  _g_kdbus_worker_stop                   (GKDBusWorker        *worker);
+
+gboolean              _g_kdbus_worker_flush_sync             (GKDBusWorker        *worker);
+
+void                  _g_kdbus_worker_close                  (GKDBusWorker        *worker,
+                                                              GTask               *task);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+gboolean              _g_kdbus_open                          (GKDBusWorker        *worker,
+                                                              const gchar         *address,
+                                                              GError             **error);
+
+gboolean              _g_kdbus_can_connect                   (GKDBusWorker        *worker,
+                                                              GError             **error);
+
+gboolean              _g_kdbus_close                         (GKDBusWorker        *worker);
+
+gboolean              _g_kdbus_is_closed                     (GKDBusWorker        *worker);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+const gchar *               _g_kdbus_Hello                           (GKDBusWorker        *worker,
+                                                                      GError             **error);
+
+gchar *                     _g_kdbus_GetBusId                        (GKDBusWorker        *worker,
+                                                                      GError             **error);
+
+GBusRequestNameReplyFlags   _g_kdbus_RequestName                     (GKDBusWorker        *worker,
+                                                                      const gchar         *name,
+                                                                      GBusNameOwnerFlags   flags,
+                                                                      GError             **error);
+
+GBusReleaseNameReplyFlags   _g_kdbus_ReleaseName                     (GKDBusWorker     *worker,
+                                                                      const gchar      *name,
+                                                                      GError          **error);
+
+gchar **                    _g_kdbus_GetListNames                    (GKDBusWorker     *worker,
+                                                                      gboolean          activatable,
+                                                                      GError          **error);
+
+gchar **                    _g_kdbus_GetListQueuedOwners             (GKDBusWorker     *worker,
+                                                                      const gchar      *name,
+                                                                      GError          **error);
+
+gboolean                    _g_kdbus_NameHasOwner                    (GKDBusWorker     *connection,
+                                                                      const gchar      *name,
+                                                                      GError          **error);
+
+gchar *                     _g_kdbus_GetNameOwner                    (GKDBusWorker     *worker,
+                                                                      const gchar      *name,
+                                                                      GError          **error);
+
+pid_t                       _g_kdbus_GetConnectionUnixProcessID      (GKDBusWorker     *worker,
+                                                                      const gchar      *name,
+                                                                      GError          **error);
+
+uid_t                       _g_kdbus_GetConnectionUnixUser           (GKDBusWorker     *worker,
+                                                                      const gchar      *name,
+                                                                      GError          **error);
+
+gchar *                     _g_kdbus_GetConnectionSecurityLabel      (GKDBusWorker     *worker,
+                                                                      const gchar      *name,
+                                                                      GError          **error);
+
+GBusStartServiceReplyFlags  _g_kdbus_StartServiceByName              (GKDBusWorker     *worker,
+                                                                      const gchar      *name,
+                                                                      guint32           flags,
+                                                                      GDBusMessage     *message,
+                                                                      GError          **error);
+
+gboolean                    _g_kdbus_AddMatch                        (GKDBusWorker     *worker,
+                                                                      const gchar      *match_rule,
+                                                                      GError          **error);
+
+gboolean                    _g_kdbus_RemoveMatch                     (GKDBusWorker     *worker,
+                                                                      const gchar      *match_rule,
+                                                                      GError          **error);
+
+GDBusCredentials *          _g_kdbus_GetConnInfo                     (GKDBusWorker     *worker,
+                                                                      const gchar      *name,
+                                                                      guint             flags,
+                                                                      GError          **error);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+gboolean              _g_kdbus_subscribe_name_acquired               (GKDBusWorker     *worker,
+                                                                      const gchar      *match_rule,
+                                                                      const gchar      *name,
+                                                                      GError          **error);
+
+gboolean              _g_kdbus_subscribe_name_lost                   (GKDBusWorker     *worker,
+                                                                      const gchar      *match_rule,
+                                                                      const gchar      *name,
+                                                                      GError          **error);
+
+gboolean              _g_kdbus_subscribe_name_owner_changed          (GKDBusWorker     *worker,
+                                                                      const gchar      *match_rule,
+                                                                      const gchar      *name,
+                                                                      GError          **error);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+G_END_DECLS
+
+#endif /* __G_KDBUS_H__ */
diff --git a/gio/gkdbusfakedaemon.c b/gio/gkdbusfakedaemon.c
new file mode 100644 (file)
index 0000000..04272f3
--- /dev/null
@@ -0,0 +1,694 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2015 Samsung Electronics
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Lukasz Skalski <l.skalski@samsung.com>
+ */
+
+#include "config.h"
+#include "gkdbus.h"
+#include "gkdbusfakedaemon.h"
+
+#include <gio/gio.h>
+#include <string.h>
+
+static gchar *introspect =
+  "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
+  "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
+  "<node>\n"
+  " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
+  "  <method name=\"Introspect\">\n"
+  "   <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
+  "  </method>\n"
+  " </interface>\n"
+  " <interface name=\"org.freedesktop.DBus\">\n"
+  "  <method name=\"AddMatch\">\n"
+  "   <arg type=\"s\" direction=\"in\"/>\n"
+  "  </method>\n"
+  "  <method name=\"RemoveMatch\">\n"
+  "   <arg type=\"s\" direction=\"in\"/>\n"
+  "  </method>\n"
+  "  <method name=\"GetConnectionCredentials\">\n"
+  "   <arg type=\"s\" direction=\"in\"/>\n"
+  "   <arg type=\"a{sv}\" direction=\"out\"/>\n"
+  "  </method>\n"
+  "  <method name=\"GetConnectionSELinuxSecurityContext\">\n"
+  "   <arg type=\"s\" direction=\"in\"/>\n"
+  "   <arg type=\"ay\" direction=\"out\"/>\n"
+  "  </method>\n"
+  "  <method name=\"GetConnectionUnixProcessID\">\n"
+  "   <arg type=\"s\" direction=\"in\"/>\n"
+  "   <arg type=\"u\" direction=\"out\"/>\n"
+  "  </method>\n"
+  "  <method name=\"GetConnectionUnixUser\">\n"
+  "   <arg type=\"s\" direction=\"in\"/>\n"
+  "   <arg type=\"u\" direction=\"out\"/>\n"
+  "  </method>\n"
+  "  <method name=\"GetId\">\n"
+  "   <arg type=\"s\" direction=\"out\"/>\n"
+  "  </method>\n"
+  "  <method name=\"GetNameOwner\">\n"
+  "   <arg type=\"s\" direction=\"in\"/>\n"
+  "   <arg type=\"s\" direction=\"out\"/>\n"
+  "  </method>\n"
+  "  <method name=\"Hello\">\n"
+  "   <arg type=\"s\" direction=\"out\"/>\n"
+  "  </method>\n"
+  "  <method name=\"ListActivatableNames\">\n"
+  "   <arg type=\"as\" direction=\"out\"/>\n"
+  "  </method>\n"
+  "  <method name=\"ListNames\">\n"
+  "   <arg type=\"as\" direction=\"out\"/>\n"
+  "  </method>\n"
+  "  <method name=\"ListQueuedOwners\">\n"
+  "   <arg type=\"s\" direction=\"in\"/>\n"
+  "   <arg type=\"as\" direction=\"out\"/>\n"
+  "  </method>\n"
+  "  <method name=\"NameHasOwner\">\n"
+  "   <arg type=\"s\" direction=\"in\"/>\n"
+  "   <arg type=\"b\" direction=\"out\"/>\n"
+  "  </method>\n"
+  "  <method name=\"ReleaseName\">\n"
+  "   <arg type=\"s\" direction=\"in\"/>\n"
+  "   <arg type=\"u\" direction=\"out\"/>\n"
+  "  </method>\n"
+  "  <method name=\"ReloadConfig\">\n"
+  "  </method>\n"
+  "  <method name=\"RequestName\">\n"
+  "   <arg type=\"s\" direction=\"in\"/>\n"
+  "   <arg type=\"u\" direction=\"in\"/>\n"
+  "   <arg type=\"u\" direction=\"out\"/>\n"
+  "  </method>\n"
+  "  <method name=\"StartServiceByName\">\n"
+  "   <arg type=\"s\" direction=\"in\"/>\n"
+  "   <arg type=\"u\" direction=\"in\"/>\n"
+  "   <arg type=\"u\" direction=\"out\"/>\n"
+  "  </method>\n"
+  "  <method name=\"UpdateActivationEnvironment\">\n"
+  "   <arg type=\"a{ss}\" direction=\"in\"/>\n"
+  "  </method>\n"
+  "  <signal name=\"NameAcquired\">\n"
+  "   <arg type=\"s\"/>\n"
+  "  </signal>\n"
+  "  <signal name=\"NameLost\">\n"
+  "   <arg type=\"s\"/>\n"
+  "  </signal>\n"
+  "  <signal name=\"NameOwnerChanged\">\n"
+  "   <arg type=\"s\"/>\n"
+  "   <arg type=\"s\"/>\n"
+  "   <arg type=\"s\"/>\n"
+  "  </signal>\n"
+  " </interface>\n"
+  "</node>\n";
+
+static gboolean
+_mac_smack_use (void)
+{
+  static int cached_use = -1;
+
+  if (cached_use < 0)
+    cached_use = access("/sys/fs/smackfs/", F_OK) >= 0;
+
+  return cached_use;
+}
+
+/**
+ * _is_message_to_dbus_daemon()
+ */
+gboolean
+_is_message_to_dbus_daemon (GDBusMessage  *message)
+{
+  return g_strcmp0 (g_dbus_message_get_destination (message), "org.freedesktop.DBus") == 0 &&
+         (g_strcmp0 (g_dbus_message_get_interface (message), "org.freedesktop.DBus") == 0 ||
+          g_strcmp0 (g_dbus_message_get_interface (message), "org.freedesktop.DBus.Introspectable") == 0) &&
+         (g_strcmp0 (g_dbus_message_get_path (message), "/org/freedesktop/DBus") == 0 ||
+          g_strcmp0 (g_dbus_message_get_path (message), "/") == 0);
+}
+
+
+/**
+ * _dbus_daemon_synthetic_reply()
+ */
+GDBusMessage *
+_dbus_daemon_synthetic_reply (GKDBusWorker  *worker,
+                              GDBusMessage  *message,
+                              gboolean sync)
+{
+  GDBusMessage *reply;
+  GVariant     *reply_body;
+  GVariant     *body;
+  GError       *local_error;
+  const gchar  *member;
+
+  reply = NULL;
+  reply_body = NULL;
+  local_error = NULL;
+
+  member = g_dbus_message_get_member (message);
+  body = g_dbus_message_get_body (message);
+
+  /* show debug */
+  if (G_UNLIKELY (_g_dbus_debug_message ()))
+    {
+      gchar *s;
+      _g_dbus_debug_print_lock ();
+      g_print ("========================================================================\n"
+               "GDBus-debug:Message:\n"
+               "  >>>> SENT D-Bus/kdbus message\n");
+      s = g_dbus_message_print (message, 2);
+      g_print ("%s", s);
+      g_free (s);
+      _g_dbus_debug_print_unlock ();
+    }
+
+  /*
+   * Introspect
+   */
+  if (!g_strcmp0 (member, "Introspect"))
+    {
+      reply_body = g_variant_new ("(s)", introspect);
+    }
+
+  /*
+   * AddMatch
+   */
+  else if (!g_strcmp0 (member, "AddMatch"))
+    {
+      if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
+        {
+          gchar *rule;
+
+          g_variant_get (body, "(&s)", &rule);
+
+          _g_kdbus_AddMatch (worker, rule, &local_error);
+          if (local_error == NULL)
+            reply_body = g_variant_new ("()", NULL);
+        }
+      else
+        g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                     "Call to 'AddMatch' has wrong args (expected s)");
+    }
+
+  /*
+   * RemoveMatch
+   */
+  else if (!g_strcmp0 (member, "RemoveMatch"))
+    {
+      if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
+        {
+          gchar *rule;
+
+          g_variant_get (body, "(&s)", &rule);
+
+          _g_kdbus_RemoveMatch (worker, rule, &local_error);
+          if (local_error == NULL)
+            reply_body = g_variant_new ("()", NULL);
+        }
+      else
+        g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                     "Call to 'RemoveMatch' has wrong args (expected s)");
+    }
+
+  /*
+   * GetConnectionCredentials
+   */
+  else if (!g_strcmp0 (member, "GetConnectionCredentials"))
+    {
+      if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
+        {
+          GDBusCredentials *creds;
+          gchar *name;
+          guint flags;
+
+          creds = NULL;
+          flags = G_DBUS_CREDS_PID | G_DBUS_CREDS_UID | G_DBUS_CREDS_SEC_LABEL;
+
+          g_variant_get (body, "(&s)", &name);
+
+          creds = _g_kdbus_GetConnInfo (worker,
+                                        name,
+                                        flags,
+                                        &local_error);
+          if (local_error == NULL)
+            {
+              GVariantBuilder builder;
+
+              g_variant_builder_init (&builder, G_VARIANT_TYPE ("(a{sv})"));
+              g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{sv}"));
+
+              g_variant_builder_add (&builder, "{sv}", "UnixUserID", g_variant_new_uint32 (creds->uid));
+              g_variant_builder_add (&builder, "{sv}", "ProcessID", g_variant_new_uint32 (creds->pid));
+
+              if (creds->sec_label != NULL)
+                {
+                  GVariantBuilder *label_builder;
+                  gint counter;
+                  gint label_size;
+
+                  label_size = strlen (creds->sec_label);
+                  label_builder = g_variant_builder_new (G_VARIANT_TYPE ("ay"));
+                  for (counter = 0 ; counter < label_size + 1; counter++)   /* label_size + 1 : include the \0 in the payload, for zero-copy reading. From dbus/bus/driver.c */
+                    g_variant_builder_add (label_builder, "y", creds->sec_label[counter]);
+
+                  g_variant_builder_add (&builder, "{sv}", "LinuxSecurityLabel", g_variant_new ("ay", label_builder));
+
+                  g_variant_builder_unref (label_builder);
+                  g_free (creds->sec_label);
+                }
+
+              g_variant_builder_close (&builder);
+              reply_body = g_variant_builder_end (&builder);
+              g_free (creds);
+            }
+        }
+      else
+        g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                     "Call to 'GetConnectionCredentials' has wrong args (expected s)");
+    }
+
+  /*
+   * GetConnectionSELinuxSecurityContext
+   */
+  else if (!g_strcmp0 (member, "GetConnectionSELinuxSecurityContext"))
+    {
+      if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
+        {
+          gchar *name;
+          gchar *label;
+
+          g_variant_get (body, "(&s)", &name);
+
+          label = _g_kdbus_GetConnectionSecurityLabel (worker, name, &local_error);
+          if (label == NULL && local_error == NULL)
+            g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "Operation not supported");
+          else if (local_error == NULL)
+            {
+              /* 'label' (KDBUS_ITEM_SECLABEL item) contains valid LSM security label... */
+              if (_mac_smack_use())
+                {
+                  /* but if we are using SMACK - to keep compatibility with legacy dbus1 - return error */
+                  g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN,
+                               "Could not determine security context for '%s'", name);
+                }
+              else
+                {
+                  /* if it is not SMACK - let's assume that it's SELinux label */
+                  GVariantBuilder builder;
+                  gint counter;
+
+                  g_variant_builder_init (&builder, G_VARIANT_TYPE ("(ay)"));
+                  g_variant_builder_open (&builder, G_VARIANT_TYPE ("ay"));
+
+                  for (counter = 0 ; counter < strlen (label) ; counter++)
+                    g_variant_builder_add (&builder, "y", label[counter]);
+
+                  g_variant_builder_close (&builder);
+                  reply_body = g_variant_builder_end (&builder);
+                }
+              g_free (label);
+            }
+        }
+      else
+        g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                     "Call to 'GetConnectionSELinuxSecurityContext' has wrong args (expected s)");
+    }
+
+  /*
+   * GetConnectionUnixProcessID
+   */
+  else if (!g_strcmp0 (member, "GetConnectionUnixProcessID"))
+    {
+      if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
+        {
+          gchar *name;
+          pid_t pid;
+
+          g_variant_get (body, "(&s)", &name);
+          pid = _g_kdbus_GetConnectionUnixProcessID (worker, name, &local_error);
+          if (local_error == NULL)
+            reply_body = g_variant_new ("(u)", pid);
+        }
+      else
+        g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                     "Call to 'GetConnectionUnixProcessID' has wrong args (expected s)");
+    }
+
+  /*
+   * GetConnectionUnixUser
+   */
+  else if (!g_strcmp0 (member, "GetConnectionUnixUser"))
+    {
+      if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
+        {
+          gchar *name;
+          uid_t uid;
+
+          g_variant_get (body, "(&s)", &name);
+          uid = _g_kdbus_GetConnectionUnixUser (worker, name, &local_error);
+          if (local_error == NULL)
+            reply_body = g_variant_new ("(u)", uid);
+        }
+      else
+        g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                     "Call to 'GetConnectionUnixUser' has wrong args (expected s)");
+    }
+
+  /*
+   * GetId
+   */
+  else if (!g_strcmp0 (member, "GetId"))
+    {
+      if ((body == NULL) || g_variant_is_of_type (body, G_VARIANT_TYPE ("()")))
+        {
+          gchar *bus_id;
+
+          bus_id = _g_kdbus_GetBusId (worker, NULL);
+          reply_body = g_variant_new ("(s)", bus_id);
+
+          g_free (bus_id);
+        }
+      else
+        g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                     "Call to 'GetId' has wrong args");
+    }
+
+  /*
+   * GetNameOwner
+   */
+  else if (!g_strcmp0 (member, "GetNameOwner"))
+    {
+      if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
+        {
+          gchar *unique_name;
+          gchar *name;
+
+          g_variant_get (body, "(&s)", &name);
+
+          unique_name = _g_kdbus_GetNameOwner (worker, name, &local_error);
+          if (local_error == NULL)
+            reply_body = g_variant_new ("(s)", unique_name);
+          g_free (unique_name);
+        }
+      else
+        g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                     "Call to 'GetNameOwner' has wrong args (expected s)");
+    }
+
+  /*
+   * Hello
+   */
+  else if (!g_strcmp0 (member, "Hello"))
+    {
+      if ((body == NULL) || g_variant_is_of_type (body, G_VARIANT_TYPE ("()")))
+        {
+          const gchar *unique_name;
+
+          unique_name = _g_kdbus_Hello (worker, &local_error);
+          if (local_error == NULL)
+            reply_body = g_variant_new ("(s)", unique_name);
+        }
+      else
+        g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                     "Call to 'Hello' has wrong args");
+    }
+
+  /*
+   * ListActivatableNames
+   */
+  else if (!g_strcmp0 (member, "ListActivatableNames"))
+    {
+      if ((body == NULL) || g_variant_is_of_type (body, G_VARIANT_TYPE ("()")))
+        {
+          gchar **strv;
+          gint cnt;
+
+          cnt = 0;
+
+          strv = _g_kdbus_GetListNames (worker, TRUE, &local_error);
+          if (local_error == NULL)
+            {
+              GVariantBuilder *builder;
+
+              builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+
+              while (strv[cnt])
+                g_variant_builder_add (builder, "s", strv[cnt++]);
+
+              reply_body = g_variant_new ("(as)", builder);
+
+              g_variant_builder_unref (builder);
+            }
+          g_strfreev (strv);
+        }
+      else
+        g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                     "Call to 'ListActivatableNames' has wrong args");
+    }
+
+  /*
+   * ListNames
+   */
+  else if (!g_strcmp0 (member, "ListNames"))
+    {
+      if ((body == NULL) || g_variant_is_of_type (body, G_VARIANT_TYPE ("()")))
+        {
+          gchar **strv;
+          gint cnt;
+
+          cnt = 0;
+
+          strv = _g_kdbus_GetListNames (worker, FALSE, &local_error);
+          if (local_error == NULL)
+            {
+              GVariantBuilder *builder;
+
+              builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+
+              while (strv[cnt])
+                g_variant_builder_add (builder, "s", strv[cnt++]);
+
+              reply_body = g_variant_new ("(as)", builder);
+
+              g_variant_builder_unref (builder);
+            }
+          g_strfreev (strv);
+        }
+      else
+        g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                     "Call to 'ListNames' has wrong args");
+    }
+
+  /*
+   * ListQueuedOwners
+   */
+  else if (!g_strcmp0 (member, "ListQueuedOwners"))
+    {
+      if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
+        {
+          gchar **strv;
+          gchar *name;
+          gint cnt;
+
+          cnt = 0;
+
+          g_variant_get (body, "(&s)", &name);
+          strv = _g_kdbus_GetListQueuedOwners (worker, name, &local_error);
+          if (local_error == NULL)
+            {
+              GVariantBuilder *builder;
+
+              builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+
+              while (strv[cnt])
+                g_variant_builder_add (builder, "s", strv[cnt++]);
+
+              reply_body = g_variant_new ("(as)", builder);
+
+              g_variant_builder_unref (builder);
+            }
+          g_strfreev (strv);
+        }
+      else
+        g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                     "Call to 'ListQueuedOwners' has wrong args (expected s)");
+    }
+
+  /*
+   * NameHasOwner
+   */
+  else if (!g_strcmp0 (member, "NameHasOwner"))
+    {
+      if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
+        {
+          gboolean ret;
+          gchar *name;
+
+          g_variant_get (body, "(&s)", &name);
+
+          ret = _g_kdbus_NameHasOwner (worker, name, &local_error);
+          if (local_error == NULL)
+            {
+              if (ret)
+                reply_body = g_variant_new ("(b)", TRUE);
+              else
+                reply_body = g_variant_new ("(b)", FALSE);
+            }
+        }
+      else
+        g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                     "Call to 'NameHasOwner' has wrong args (expected s)");
+    }
+
+  /*
+   * ReleaseName
+   */
+  else if (!g_strcmp0 (member, "ReleaseName"))
+    {
+      if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
+        {
+          GBusReleaseNameReplyFlags status;
+          gchar *name;
+
+          g_variant_get (body, "(&s)", &name);
+
+          status = _g_kdbus_ReleaseName (worker, name, &local_error);
+          if (local_error == NULL)
+            reply_body = g_variant_new ("(u)", status);
+        }
+      else
+        g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                     "Call to 'ReleaseName' has wrong args (expected s)");
+    }
+
+  /*
+   * ReloadConfig
+   */
+  else if (!g_strcmp0 (member, "ReloadConfig"))
+    {
+      if ((body == NULL) || g_variant_is_of_type (body, G_VARIANT_TYPE ("()")))
+        reply_body = g_variant_new ("()", NULL);
+      else
+        g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                     "Call to 'ReloadConfig' has wrong args");
+    }
+
+  /*
+   * RequestName
+   */
+  else if (!g_strcmp0 (member, "RequestName"))
+    {
+      if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(su)")))
+        {
+          GBusRequestNameReplyFlags status;
+          guint32 flags;
+          gchar *name;
+
+          g_variant_get (body, "(&su)", &name, &flags);
+
+          status = _g_kdbus_RequestName (worker, name, flags, &local_error);
+          if (local_error == NULL)
+            reply_body = g_variant_new ("(u)", status);
+        }
+      else
+        g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                     "Call to 'RequestName' has wrong args (expected su)");
+    }
+
+  /*
+   * StartServiceByName
+   */
+  else if (!g_strcmp0 (member, "StartServiceByName"))
+    {
+      if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(su)")))
+        {
+          GBusStartServiceReplyFlags status;
+          gchar *name;
+          guint32 flags;
+
+          g_variant_get (body, "(&su)", &name, &flags);
+
+          if (sync)
+            status = _g_kdbus_StartServiceByName (worker, name, flags, NULL, &local_error);
+          else
+            status = _g_kdbus_StartServiceByName (worker, name, flags, message, &local_error);
+
+          if (local_error == NULL)
+            {
+              if (status == G_BUS_START_SERVICE_REPLY_ALREADY_RUNNING || sync)
+                reply_body = g_variant_new ("(u)", status);
+              else
+                return NULL;
+            }
+        }
+      else
+        g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                     "Call to 'StartServiceByName' has wrong args (expected su)");
+    }
+
+  /*
+   * UpdateActivationEnvironment
+   */
+  else if (!g_strcmp0 (member, "UpdateActivationEnvironment"))
+    {
+      g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED,
+                   "'%s' method not supported", member);
+    }
+
+  /*
+   * Method not supported
+   */
+  else
+    {
+      g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD,
+                   "org.freedesktop.DBus does not understand message %s", member);
+    }
+
+  if (reply_body == NULL && local_error)
+    {
+      gchar *dbus_error_name;
+
+      dbus_error_name = g_dbus_error_encode_gerror (local_error);
+      reply = g_dbus_message_new_method_error (message, dbus_error_name, "%s", local_error->message);
+      g_free (dbus_error_name);
+    }
+  else
+    {
+      reply = g_dbus_message_new_method_reply (message);
+      g_dbus_message_set_body (reply, reply_body);
+    }
+
+  g_dbus_message_set_serial (reply, -1);
+
+  if (local_error)
+    g_error_free (local_error);
+
+  if (G_UNLIKELY (_g_dbus_debug_message ()))
+    {
+      gchar *s;
+      _g_dbus_debug_print_lock ();
+      g_print ("========================================================================\n"
+               "GDBus-debug:Message:\n"
+               "  <<<< RECEIVED synthetic D-Bus message\n");
+      s = g_dbus_message_print (reply, 2);
+      g_print ("%s", s);
+      g_free (s);
+      _g_dbus_debug_print_unlock ();
+    }
+
+  return reply;
+}
diff --git a/gio/gkdbusfakedaemon.h b/gio/gkdbusfakedaemon.h
new file mode 100644 (file)
index 0000000..969b7b5
--- /dev/null
@@ -0,0 +1,39 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2015 Samsung Electronics
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Lukasz Skalski       <l.skalski@samsung.com>
+ */
+
+#ifndef __G_KDBUSFAKEDAEMON_H__
+#define __G_KDBUSFAKEDAEMON_H__
+
+#if !defined (GIO_COMPILATION)
+#error "gkdbusfakedaemon.h is a private header file."
+#endif
+
+#include <gio/giotypes.h>
+
+gboolean              _is_message_to_dbus_daemon             (GDBusMessage  *message);
+
+GDBusMessage *        _dbus_daemon_synthetic_reply           (GKDBusWorker  *worker,
+                                                              GDBusMessage  *message,
+                                                              gboolean sync);
+G_END_DECLS
+
+#endif /* __G_KDBUSFAKEDAEMON_H__ */
index 9d3204a..41d5b2a 100644 (file)
@@ -69,6 +69,9 @@ GLIB_AVAILABLE_IN_ALL
 GUnixFDList *           g_unix_fd_list_new_from_array                   (const gint   *fds,
                                                                          gint          n_fds);
 
+GLIB_AVAILABLE_IN_2_44
+void                    g_unix_fd_list_lock                             (GUnixFDList  *list);
+
 GLIB_AVAILABLE_IN_ALL
 gint                    g_unix_fd_list_append                           (GUnixFDList  *list,
                                                                          gint          fd,
index ac3373f..8ba4595 100644 (file)
@@ -228,6 +228,13 @@ gdbus_sources = files(
   'gtestdbus.c',
 )
 
+if get_option('kdbus')
+gdbus_sources += files(
+  'gkdbus.c',
+  'gkdbusfakedaemon.c',
+)
+endif
+
 # Generate gdbus-codegen
 subdir('gdbus-2.0/codegen')
 
@@ -724,6 +731,7 @@ gio_headers = files(
   'gzlibdecompressor.h',
   'glistmodel.h',
   'gliststore.h',
+  'tizen_header_glib.h',
 )
 
 gio_headers += application_headers
@@ -804,6 +812,16 @@ else
   gio_dtrace_hdr = []
 endif
 
+if get_option('kdbus')
+  gio_c_args += '-DKDBUS'
+endif
+
+libdbuspolicy_dep = dependency('', required : false)
+if get_option('libdbuspolicy')
+  libdbuspolicy_dep = dependency('libdbuspolicy1', version : '>=1', required : true)
+  gio_c_args += '-DLIBDBUSPOLICY'
+endif
+
 libgio = library('gio-2.0',
   gioenumtypes_h, gioenumtypes_c, gnetworking_h, gio_sources,
   gio_dtrace_hdr, gio_dtrace_obj,
@@ -816,7 +834,7 @@ libgio = library('gio-2.0',
   #  '$(gio_win32_res_ldflag)',
   dependencies : [libz_dep, libdl_dep, libmount_dep, libglib_dep,
                   libgobject_dep, libgmodule_dep, selinux_dep, xattr_dep,
-                  platform_deps, network_libs, libsysprof_capture_dep],
+                  platform_deps, network_libs, libdbuspolicy_dep, libsysprof_capture_dep],
   c_args : gio_c_args,
   objc_args : gio_c_args,
   # intl.lib is not compatible with SAFESEH
diff --git a/gio/tests/.gitignore b/gio/tests/.gitignore
deleted file mode 100644 (file)
index e6c9124..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-actions
-appinfo
-appinfo-test
-appmonitor
-apps
-async-close-output-stream
-async-splice-output-stream
-autoptr
-basic-application
-buffered-input-stream
-buffered-output-stream
-cancellable
-connectable
-contenttype
-contexts
-converter-stream
-credentials
-data-input-stream
-data-output-stream
-dbus-appinfo
-dbus-launch
-de/
-defaultvalue
-desktop-app-info
-echo-server
-file
-fileattributematcher
-filter-cat
-filter-streams
-gapplication
-gapplication-example-actions
-gapplication-example-cmdline
-gapplication-example-cmdline2
-gapplication-example-cmdline3
-gapplication-example-dbushooks
-gapplication-example-menu
-gapplication-example-open
-gdbus-addresses
-gdbus-auth
-gdbus-bz627724
-gdbus-close-pending
-gdbus-connection
-gdbus-connection-flush
-gdbus-connection-flush-helper
-gdbus-connection-loss
-gdbus-connection-slow
-gdbus-daemon
-gdbus-error
-gdbus-example-export
-gdbus-example-objectmanager-client
-gdbus-example-objectmanager-server
-gdbus-example-own-name
-gdbus-example-peer
-gdbus-example-proxy-subclass
-gdbus-example-server
-gdbus-example-subtree
-gdbus-example-unix-fd-client
-gdbus-example-watch-name
-gdbus-example-watch-proxy
-gdbus-exit-on-close
-gdbus-export
-gdbus-introspection
-gdbus-message
-gdbus-names
-gdbus-non-socket
-gdbus-overflow
-gdbus-peer
-gdbus-peer-object-manager
-gdbus-proxy
-gdbus-proxy-threads
-gdbus-proxy-well-known-name
-gdbus-serialization
-gdbus-test-codegen
-gdbus-test-codegen-generated*
-gdbus-test-codegen-old
-gdbus-test-fixture
-gdbus-testserver
-gdbus-threading
-gdbus-address-get-session
-glistmodel
-gio-du
-giomodule
-giotypefuncs.inc
-gnotification
-gsubprocess
-gsubprocess-testprog
-g-file
-g-file-info
-g-icon
-gmenumodel
-gschemas.compiled
-gsettings
-gsettings.store
-httpd
-icons
-inet-address
-io-stream
-live-g-file
-memory-input-stream
-memory-output-stream
-mimeapps
-monitor
-network-address
-network-monitor
-org.gtk.test.enums.xml
-org.gtk.test.gschema.xml
-permission
-pollable
-plugin_resources.c
-proxy
-proxy-test
-readwrite
-resolver
-resources
-send-data
-services/org.gtk.GDBus.Examples.ObjectManager.service
-simple-async-result
-simple-proxy
-sleepy-stream
-stream-rw_all
-socket
-socket-address
-socket-client
-socket-listener
-socket-service
-socket-server
-srvtarget
-task
-test-generated.txt
-test.gresource
-test.mo
-test_resources.c
-test_resources2.c
-test_resources2.h
-testfilemonitor
-thumbnail-verification
-tls-certificate
-tls-database
-tls-interaction
-unix-fd
-unix-streams
-vfs
-volumemonitor
-xgen-gio
-xgen-giosrc.c
-gresource-big-test.txt
diff --git a/gio/tizen_header_glib.h b/gio/tizen_header_glib.h
new file mode 100644 (file)
index 0000000..0501c63
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TIZEN_HEADER_GLIB_H__
+#define __TIZEN_HEADER_GLIB_H__
+
+#ifndef TIZEN_PUBLIC_DEPRECATED_API
+  #ifdef TIZEN_DEPRECATION
+    #define TIZEN_PUBLIC_DEPRECATED_API __attribute__((__visibility__("default"), deprecated))
+  #else
+    #define TIZEN_PUBLIC_DEPRECATED_API
+  #endif
+#endif
+
+#endif // __TIZEN_HEADER_GLIB_H__
diff --git a/gio/xdgmime/.gitignore b/gio/xdgmime/.gitignore
deleted file mode 100644 (file)
index 56e6945..0000000
+++ /dev/null
@@ -1 +0,0 @@
-test-mime
index a6ca0e3..c9424dc 100644 (file)
 #include <glib/grefcount.h>
 
 #include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#ifdef G_OS_UNIX
+#include "glib-unix.h"
+#include <sys/mman.h>
+#endif
 
 /**
  * GBytes:
 /* Keep in sync with glib/tests/bytes.c */
 struct _GBytes
 {
-  gconstpointer data;  /* may be NULL iff (size == 0) */
-  gsize size;  /* may be 0 */
+  gsize size;
   gatomicrefcount ref_count;
-  GDestroyNotify free_func;
-  gpointer user_data;
+  gint  type_or_fd;
 };
 
+typedef struct
+{
+  GBytes bytes;
+#if GLIB_SIZEOF_SIZE_T == 4
+  guint pad;
+#endif
+
+  guchar data[1];
+} GBytesInline;
+
+/* important: the ->data field of GBytesInline should always be 'nicely
+ * aligned'.
+ */
+G_STATIC_ASSERT (G_STRUCT_OFFSET (GBytesInline, data) % (2 * sizeof (gpointer)) == 0);
+G_STATIC_ASSERT (G_STRUCT_OFFSET (GBytesInline, data) % 8 == 0);
+
+
+typedef struct
+{
+  GBytes   bytes;
+
+  gpointer data;
+} GBytesData;
+
+typedef struct
+{
+  GBytesData     data_bytes;
+
+  GDestroyNotify notify;
+  gpointer       user_data;
+} GBytesNotify;
+
+#define G_BYTES_TYPE_INLINE        (-1)
+#define G_BYTES_TYPE_STATIC        (-2)
+#define G_BYTES_TYPE_FREE          (-3)
+#define G_BYTES_TYPE_NOTIFY        (-4)
+
+/* All bytes are either inline or subtypes of GBytesData */
+#define G_BYTES_IS_INLINE(bytes)   ((bytes)->type_or_fd == G_BYTES_TYPE_INLINE)
+#define G_BYTES_IS_DATA(bytes)     (!G_BYTES_IS_INLINE(bytes))
+
+/* More specific subtypes of GBytesData */
+#define G_BYTES_IS_STATIC(bytes)   ((bytes)->type_or_fd == G_BYTES_TYPE_STATIC)
+#define G_BYTES_IS_FREE(bytes)     ((bytes)->type_or_fd == G_BYTES_TYPE_FREE)
+#define G_BYTES_IS_NOTIFY(bytes)   ((bytes)->type_or_fd == G_BYTES_TYPE_NOTIFY)
+
+/* we have a memfd if type_or_fd >= 0 */
+#define G_BYTES_IS_MEMFD(bytes)    ((bytes)->type_or_fd >= 0)
+
+static gpointer
+g_bytes_allocate (guint struct_size,
+                  guint type_or_fd,
+                  gsize data_size)
+{
+  GBytes *bytes;
+
+  bytes = g_slice_alloc (struct_size);
+  bytes->size = data_size;
+  g_atomic_ref_count_init (&bytes->ref_count);
+  bytes->type_or_fd = type_or_fd;
+
+  return bytes;
+}
+
 /**
  * g_bytes_new:
  * @data: (transfer none) (array length=size) (element-type guint8) (nullable):
@@ -93,11 +163,75 @@ GBytes *
 g_bytes_new (gconstpointer data,
              gsize         size)
 {
+  GBytesInline *bytes;
+
   g_return_val_if_fail (data != NULL || size == 0, NULL);
 
-  return g_bytes_new_take (g_memdup2 (data, size), size);
+  bytes = g_bytes_allocate (G_STRUCT_OFFSET (GBytesInline, data[size]), G_BYTES_TYPE_INLINE, size);
+  memcpy (bytes->data, data, size);
+
+  return (GBytes *) bytes;
+}
+
+/**
+ * g_bytes_new_take_zero_copy_fd:
+ * @fd: a file descriptor capable of being zero-copy-safe
+ *
+ * Creates a new #GBytes from @fd.
+ *
+ * @fd must be capable of being made zero-copy-safe.  In concrete terms,
+ * this means that a call to g_unix_fd_ensure_zero_copy_safe() on @fd
+ * will succeed.  This call will be made before returning.
+ *
+ * This call consumes @fd, transferring ownership to the returned
+ * #GBytes.
+ *
+ * Returns: (transfer full): a new #GBytes
+ *
+ */
+#ifdef G_OS_UNIX
+GBytes *
+g_bytes_new_take_zero_copy_fd (gint fd)
+{
+  GBytes *bytes;
+  struct stat buf;
+
+  /* We already checked this is a memfd... */
+  g_assert_se (fstat (fd, &buf) == 0);
+
+  bytes = g_bytes_new_take_zero_copy_fd_size(fd, buf.st_size);
+
+  if (buf.st_size == 0)
+    {
+      g_assert_se (close (fd) == 0);
+    }
+
+  return bytes;
 }
 
+GBytes *
+g_bytes_new_take_zero_copy_fd_size (gint fd, gsize size)
+{
+  GBytesData *bytes;
+
+  g_return_val_if_fail_se (g_unix_fd_ensure_zero_copy_safe (fd), NULL);
+
+  /* We already checked this is a memfd... */
+  if (size == 0)
+    {
+      return g_bytes_new (NULL, 0);
+    }
+
+  bytes = g_bytes_allocate (sizeof (GBytesData), fd, size);
+  bytes->data = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
+  if (bytes->data == MAP_FAILED)
+    /* this is similar to malloc() failing, so do the same... */
+    g_error ("mmap() on memfd failed: %s\n", g_strerror (errno));
+
+  return (GBytes *) bytes;
+}
+#endif /* G_OS_UNIX */
+
 /**
  * g_bytes_new_take:
  * @data: (transfer full) (array length=size) (element-type guint8) (nullable):
@@ -125,9 +259,13 @@ GBytes *
 g_bytes_new_take (gpointer data,
                   gsize    size)
 {
-  return g_bytes_new_with_free_func (data, size, g_free, data);
-}
+  GBytesData *bytes;
+
+  bytes = g_bytes_allocate (sizeof (GBytesData), G_BYTES_TYPE_FREE, size);
+  bytes->data = data;
 
+  return (GBytes *) bytes;
+}
 
 /**
  * g_bytes_new_static: (skip)
@@ -148,7 +286,14 @@ GBytes *
 g_bytes_new_static (gconstpointer data,
                     gsize         size)
 {
-  return g_bytes_new_with_free_func (data, size, NULL, NULL);
+  GBytesData *bytes;
+
+  g_return_val_if_fail (data != NULL || size == 0, NULL);
+
+  bytes = g_bytes_allocate (sizeof (GBytesData), G_BYTES_TYPE_STATIC, size);
+  bytes->data = (gpointer) data;
+
+  return (GBytes *) bytes;
 }
 
 /**
@@ -179,18 +324,17 @@ g_bytes_new_with_free_func (gconstpointer  data,
                             GDestroyNotify free_func,
                             gpointer       user_data)
 {
-  GBytes *bytes;
+  GBytesNotify *bytes;
 
-  g_return_val_if_fail (data != NULL || size == 0, NULL);
+  if (!free_func)
+    return g_bytes_new_static (data, size);
 
-  bytes = g_slice_new (GBytes);
-  bytes->data = data;
-  bytes->size = size;
-  bytes->free_func = free_func;
+  bytes = g_bytes_allocate (sizeof (GBytesNotify), G_BYTES_TYPE_NOTIFY, size);
+  bytes->data_bytes.data = (gpointer) data;
+  bytes->notify = free_func;
   bytes->user_data = user_data;
-  g_atomic_ref_count_init (&bytes->ref_count);
 
-  return (GBytes *)bytes;
+  return (GBytes *) bytes;
 }
 
 /**
@@ -221,6 +365,7 @@ g_bytes_new_from_bytes (GBytes  *bytes,
                         gsize    length)
 {
   gchar *base;
+  gchar *data;
 
   /* Note that length may be 0. */
   g_return_val_if_fail (bytes != NULL, NULL);
@@ -231,18 +376,19 @@ g_bytes_new_from_bytes (GBytes  *bytes,
   if (offset == 0 && length == bytes->size)
     return g_bytes_ref (bytes);
 
-  base = (gchar *)bytes->data + offset;
+  base = (gchar *)g_bytes_get_data (bytes, NULL) + offset;
 
   /* Avoid referencing intermediate GBytes. In practice, this should
    * only loop once.
    */
-  while (bytes->free_func == (gpointer)g_bytes_unref)
-    bytes = bytes->user_data;
+  while (((GBytesNotify*)bytes)->notify == (gpointer)g_bytes_unref)
+    bytes = ((GBytesNotify*)bytes)->user_data;
 
+  data = (gchar *)g_bytes_get_data (bytes, NULL);
   g_return_val_if_fail (bytes != NULL, NULL);
-  g_return_val_if_fail (base >= (gchar *)bytes->data, NULL);
-  g_return_val_if_fail (base <= (gchar *)bytes->data + bytes->size, NULL);
-  g_return_val_if_fail (base + length <= (gchar *)bytes->data + bytes->size, NULL);
+  g_return_val_if_fail (base >= data, NULL);
+  g_return_val_if_fail (base <= data + bytes->size, NULL);
+  g_return_val_if_fail (base + length <= data + bytes->size, NULL);
 
   return g_bytes_new_with_free_func (base, length,
                                      (GDestroyNotify)g_bytes_unref, g_bytes_ref (bytes));
@@ -268,12 +414,27 @@ g_bytes_new_from_bytes (GBytes  *bytes,
  */
 gconstpointer
 g_bytes_get_data (GBytes *bytes,
-                  gsize *size)
+                  gsize  *size)
 {
   g_return_val_if_fail (bytes != NULL, NULL);
+
   if (size)
     *size = bytes->size;
-  return bytes->data;
+
+  if (G_BYTES_IS_DATA (bytes))
+    {
+      GBytesData *data_bytes = (GBytesData *) bytes;
+
+      return data_bytes->data;
+    }
+  else if (G_BYTES_IS_INLINE (bytes))
+    {
+      GBytesInline *inline_bytes = (GBytesInline *) bytes;
+
+      return inline_bytes->data;
+    }
+  else
+    g_assert_not_reached ();
 }
 
 /**
@@ -295,6 +456,35 @@ g_bytes_get_size (GBytes *bytes)
   return bytes->size;
 }
 
+/**
+ * g_bytes_get_zero_copy_fd:
+ * @bytes: a #GBytes
+ *
+ * Gets the zero-copy fd from a #GBytes, if it has one.
+ *
+ * Returns -1 if @bytes was not created from a zero-copy fd.
+ *
+ * A #GBytes created with a zero-copy fd may have been internally
+ * converted into another type of #GBytes for any reason at all.  This
+ * function may therefore return -1 at any time, even for a #GBytes that
+ * was created with g_bytes_new_take_zero_copy_fd().
+ *
+ * The returned file descriptor belongs to @bytes.  Do not close it.
+ *
+ * Returns: a file descriptor, or -1
+ *
+ * Since: 2.44
+ */
+gint
+g_bytes_get_zero_copy_fd (GBytes *bytes)
+{
+  g_return_val_if_fail (bytes != NULL, -1);
+
+  if (G_BYTES_IS_MEMFD (bytes))
+    return bytes->type_or_fd;
+  else
+    return -1;
+}
 
 /**
  * g_bytes_ref:
@@ -333,9 +523,52 @@ g_bytes_unref (GBytes *bytes)
 
   if (g_atomic_ref_count_dec (&bytes->ref_count))
     {
-      if (bytes->free_func != NULL)
-        bytes->free_func (bytes->user_data);
-      g_slice_free (GBytes, bytes);
+      switch (bytes->type_or_fd)
+        {
+        case G_BYTES_TYPE_STATIC:
+          /* data does not need to be freed */
+          g_slice_free (GBytesData, (GBytesData *) bytes);
+          break;
+
+        case G_BYTES_TYPE_INLINE:
+          /* data will be freed along with struct */
+          g_slice_free1 (G_STRUCT_OFFSET (GBytesInline, data[bytes->size]), bytes);
+          break;
+
+        case G_BYTES_TYPE_FREE:
+          {
+            GBytesData *data_bytes = (GBytesData *) bytes;
+
+            g_free (data_bytes->data);
+
+            g_slice_free (GBytesData, data_bytes);
+            break;
+          }
+
+        case G_BYTES_TYPE_NOTIFY:
+          {
+            GBytesNotify *notify_bytes = (GBytesNotify *) bytes;
+
+            /* We don't create GBytesNotify if callback was NULL */
+            (* notify_bytes->notify) (notify_bytes->user_data);
+
+            g_slice_free (GBytesNotify, notify_bytes);
+            break;
+          }
+
+        default:
+          {
+            GBytesData *data_bytes = (GBytesData *) bytes;
+
+            g_assert (bytes->type_or_fd >= 0);
+
+            g_assert_se (munmap (data_bytes->data, bytes->size) == 0);
+            g_assert_se (close (bytes->type_or_fd) == 0);
+
+            g_slice_free (GBytesData, data_bytes);
+            break;
+          }
+        }
     }
 }
 
@@ -358,14 +591,22 @@ gboolean
 g_bytes_equal (gconstpointer bytes1,
                gconstpointer bytes2)
 {
-  const GBytes *b1 = bytes1;
-  const GBytes *b2 = bytes2;
+  gconstpointer d1, d2;
+  gsize s1, s2;
 
   g_return_val_if_fail (bytes1 != NULL, FALSE);
   g_return_val_if_fail (bytes2 != NULL, FALSE);
 
-  return b1->size == b2->size &&
-         (b1->size == 0 || memcmp (b1->data, b2->data, b1->size) == 0);
+  d1 = g_bytes_get_data ((GBytes *) bytes1, &s1);
+  d2 = g_bytes_get_data ((GBytes *) bytes2, &s2);
+
+  if (s1 != s2)
+    return FALSE;
+
+  if (d1 == d2)
+    return TRUE;
+
+  return memcmp (d1, d2, s1) == 0;
 }
 
 /**
@@ -384,14 +625,18 @@ g_bytes_equal (gconstpointer bytes1,
 guint
 g_bytes_hash (gconstpointer bytes)
 {
-  const GBytes *a = bytes;
-  const signed char *p, *e;
+  const guchar *data;
+  const guchar *end;
+  gsize size;
   guint32 h = 5381;
 
   g_return_val_if_fail (bytes != NULL, 0);
 
-  for (p = (signed char *)a->data, e = (signed char *)a->data + a->size; p != e; p++)
-    h = (h << 5) + h + *p;
+  data = g_bytes_get_data ((GBytes *) bytes, &size);
+  end = data + size;
+
+  while (data != end)
+    h = (h << 5) + h + *(data++);
 
   return h;
 }
@@ -422,43 +667,23 @@ gint
 g_bytes_compare (gconstpointer bytes1,
                  gconstpointer bytes2)
 {
-  const GBytes *b1 = bytes1;
-  const GBytes *b2 = bytes2;
+  gconstpointer d1, d2;
+  gsize s1, s2;
   gint ret;
 
   g_return_val_if_fail (bytes1 != NULL, 0);
   g_return_val_if_fail (bytes2 != NULL, 0);
 
-  ret = memcmp (b1->data, b2->data, MIN (b1->size, b2->size));
-  if (ret == 0 && b1->size != b2->size)
-      ret = b1->size < b2->size ? -1 : 1;
-  return ret;
-}
-
-static gpointer
-try_steal_and_unref (GBytes         *bytes,
-                     GDestroyNotify  free_func,
-                     gsize          *size)
-{
-  gpointer result;
-
-  if (bytes->free_func != free_func || bytes->data == NULL ||
-      bytes->user_data != bytes->data)
-    return NULL;
+  d1 = g_bytes_get_data ((GBytes *) bytes1, &s1);
+  d2 = g_bytes_get_data ((GBytes *) bytes2, &s2);
 
-  /* Are we the only reference? */
-  if (g_atomic_ref_count_compare (&bytes->ref_count, 1))
-    {
-      *size = bytes->size;
-      result = (gpointer)bytes->data;
-      g_slice_free (GBytes, bytes);
-      return result;
-    }
+  ret = memcmp (d1, d2, MIN (s1, s2));
+  if (ret == 0 && s1 != s2)
+    ret = s1 < s2 ? -1 : 1;
 
-  return NULL;
+  return ret;
 }
 
-
 /**
  * g_bytes_unref_to_data:
  * @bytes: (transfer full): a #GBytes
@@ -487,20 +712,26 @@ g_bytes_unref_to_data (GBytes *bytes,
   g_return_val_if_fail (bytes != NULL, NULL);
   g_return_val_if_fail (size != NULL, NULL);
 
+
   /*
    * Optimal path: if this is was the last reference, then we can return
    * the data from this GBytes without copying.
    */
-
-  result = try_steal_and_unref (bytes, g_free, size);
-  if (result == NULL)
+  if (G_BYTES_IS_FREE(bytes) && g_atomic_int_get (&bytes->ref_count) == 1)
     {
-      /*
-       * Copy: Non g_malloc (or compatible) allocator, or static memory,
-       * so we have to copy, and then unref.
-       */
-      result = g_memdup2 (bytes->data, bytes->size);
+      GBytesData *data_bytes = (GBytesData *) bytes;
+
+      result = data_bytes->data;
       *size = bytes->size;
+
+      g_slice_free (GBytesData, data_bytes);
+    }
+  else
+    {
+      gconstpointer data;
+
+      data = g_bytes_get_data (bytes, size);
+      result = g_memdup (data, *size);
       g_bytes_unref (bytes);
     }
 
@@ -608,5 +839,8 @@ g_bytes_get_region (GBytes *bytes,
    *   0 <= offset <= end_offset <= bytes->size
    */
 
-  return ((guchar *) bytes->data) + offset;
-}
\ No newline at end of file
+  /* NB: The following line has been adapted to the kdbus rework by Mateusz
+   * and not by a competent programmer. Tread with caution!
+   */
+  return ((guchar *) g_bytes_get_data (bytes, NULL)) + offset;
+}
index 37cad86..2c10f04 100644 (file)
@@ -39,6 +39,15 @@ GLIB_AVAILABLE_IN_ALL
 GBytes *        g_bytes_new_take                (gpointer        data,
                                                  gsize           size);
 
+#ifdef G_OS_UNIX
+GLIB_AVAILABLE_IN_2_44
+GBytes *        g_bytes_new_take_zero_copy_fd   (gint            fd);
+
+GLIB_AVAILABLE_IN_2_44
+GBytes *        g_bytes_new_take_zero_copy_fd_size (gint fd,
+                                                    gsize           size);
+#endif
+
 GLIB_AVAILABLE_IN_ALL
 GBytes *        g_bytes_new_static              (gconstpointer   data,
                                                  gsize           size);
@@ -61,6 +70,9 @@ gconstpointer   g_bytes_get_data                (GBytes         *bytes,
 GLIB_AVAILABLE_IN_ALL
 gsize           g_bytes_get_size                (GBytes         *bytes);
 
+GLIB_AVAILABLE_IN_2_44
+gint            g_bytes_get_zero_copy_fd        (GBytes         *bytes);
+
 GLIB_AVAILABLE_IN_ALL
 GBytes *        g_bytes_ref                     (GBytes         *bytes);
 
index 6457eaf..9248c61 100644 (file)
@@ -29,10 +29,10 @@ g_autoptr_cleanup_generic_gfree (void *p)
 }
 
 static inline void
-g_autoptr_cleanup_gstring_free (GString *string)
+g_autoptr_cleanup_gstring_free (GString *__string__)
 {
-  if (string)
-    g_string_free (string, TRUE);
+  if (__string__)
+    g_string_free (__string__, TRUE);
 }
 
 /* Ignore deprecations in case we refer to a type which was added in a more
diff --git a/glib/glib-linux.h b/glib/glib-linux.h
new file mode 100644 (file)
index 0000000..8f8882c
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright © 2014 Canonical Limited
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the licence, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Ryan Lortie <desrt@desrt.ca>
+ */
+
+#ifndef __GLIB_LINUX_H__
+#define __GLIB_LINUX_H__
+
+#include <errno.h>
+
+/* If we know that we are on Linux, add some features, even if they are
+ * not (yet) advertised in the glibc or kernel headers.
+ *
+ * This allows us to use functionality regardless of if it was available
+ * when GLib was compiled or not.
+ *
+ * We take care not to define these things on non-Linux systems where
+ * certain numeric values could mean something different.
+ *
+ * This file is populated on an as-needed basis.
+ *
+ * As things in this file filter into glibc and the distributions we can
+ * remove them from this file and add unconditional dependencies.  Never
+ * add a configure.ac check in order to remove something from this file.
+ *
+ * import: include this header LAST
+ */
+
+#ifdef __linux__
+
+#define GLIB_LINUX
+
+#include <sys/syscall.h>
+
+static inline int
+glib_linux_enosys (void)
+{
+  errno = ENOSYS;
+  return -1;
+}
+
+/* futex */
+#include <linux/futex.h>
+
+static inline int
+glib_linux_futex (int                   *uaddr,
+                  int                    op,
+                  int                    val,
+                  const struct timespec *timeout,
+                  int                   *uaddr2,
+                  int                    val3)
+{
+  return syscall (__NR_futex, uaddr, op, val, timeout, uaddr2, val3);
+}
+
+/* memfd */
+#ifndef MFD_CLOEXEC
+#define MFD_CLOEXEC             0x0001U
+#endif
+
+#ifndef MFD_ALLOW_SEALING
+#define MFD_ALLOW_SEALING       0x0002U
+#endif
+
+#ifndef __NR_memfd_create
+#  if defined __x86_64__
+#    define __NR_memfd_create 319
+#  elif defined i386
+#    define __NR_memfd_create 356
+#  elif defined __arm__
+#    define __NR_memfd_create 385
+#  elif defined __aarch64__
+#    define __NR_memfd_create 279
+#  elif defined _MIPS_SIM
+#    if _MIPS_SIM == _MIPS_SIM_ABI32
+#      define __NR_memfd_create 4354
+#    endif
+#    if _MIPS_SIM == _MIPS_SIM_NABI32
+#      define __NR_memfd_create 6318
+#    endif
+#    if _MIPS_SIM == _MIPS_SIM_ABI64
+#      define __NR_memfd_create 5314
+#    endif
+#  endif
+#endif
+
+static inline int
+glib_linux_memfd_create (const char   *name,
+                         unsigned int  flags)
+{
+#ifdef __NR_memfd_create
+  return syscall (__NR_memfd_create, name, flags);
+#else
+  return glib_linux_enosys ();
+#endif
+}
+
+/* Linux-specific fcntl() operations */
+#ifndef F_LINUX_SPECIFIC_BASE
+#define F_LINUX_SPECIFIC_BASE 1024
+#endif
+
+#ifndef F_ADD_SEALS
+#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
+#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
+
+#define F_SEAL_SEAL     0x0001  /* prevent further seals from being set */
+#define F_SEAL_SHRINK   0x0002  /* prevent file from shrinking */
+#define F_SEAL_GROW     0x0004  /* prevent file from growing */
+#define F_SEAL_WRITE    0x0008  /* prevent writes */
+#endif
+
+#endif /* __linux __ */
+
+#endif /* __GLIB_LINUX_H__ */
index 1c0da19..ac0df0f 100644 (file)
@@ -47,6 +47,10 @@ glib__private__ (void)
     g_dir_open_with_errno,
     g_dir_new_from_dirp,
 
+    g_variant_to_vectors,
+    g_variant_from_vectors,
+    g_variant_vectors_deinit,
+
     glib_init,
 
 #ifdef G_OS_WIN32
index 8de380d..541f161 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <glib.h>
 #include "gwakeup.h"
+#include "gvariant-vectors.h"
 #include "gstdioprivate.h"
 
 /* gcc defines __SANITIZE_ADDRESS__, clang sets the address_sanitizer
@@ -81,6 +82,13 @@ g_ignore_strv_leak (GStrv strv)
 GMainContext *          g_get_worker_context            (void);
 gboolean                g_check_setuid                  (void);
 GMainContext *          g_main_context_new_with_next_id (guint next_id);
+void                    g_variant_to_vectors            (GVariant *value,
+                                                         GVariantVectors *vectors);
+GVariant *              g_variant_from_vectors          (const GVariantType *type,
+                                                         GVariantVector     *vectors,
+                                                         gsize               n_vectors,
+                                                         gsize               size,
+                                                         gboolean            trusted);
 
 #ifdef G_OS_WIN32
 gchar *_glib_get_dll_directory (void);
@@ -112,6 +120,15 @@ typedef struct {
                                                          guint        flags);
   GDir *                (* g_dir_new_from_dirp)         (gpointer dirp);
 
+  void                  (* g_variant_to_vectors)        (GVariant    *value,
+                                                         GVariantVectors *vectors);
+  GVariant *            (* g_variant_from_vectors)      (const GVariantType *type,
+                                                         GVariantVector  *vectors,
+                                                         gsize            n_vectors,
+                                                         gsize size,
+                                                         gboolean trusted);
+  void                  (* g_variant_vectors_deinit)    (GVariantVectors *vectors);
+
   /* See glib-init.c */
   void                  (* glib_init)                   (void);
 
index 9d2877c..b72491c 100644 (file)
@@ -39,6 +39,37 @@ G_STATIC_ASSERT (G_ALIGNOF (gssize) == G_ALIGNOF (ssize_t));
 G_STATIC_ASSERT (sizeof (GPid) == sizeof (pid_t));
 G_STATIC_ASSERT (G_ALIGNOF (GPid) == G_ALIGNOF (pid_t));
 
+#include <fcntl.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#ifdef __linux__
+
+/* We want to support these features of Linux even when building GLib
+ * against older versions of system headers.  This will allow us to
+ * 'automatically' start supporting a particular feature when GLib is
+ * used with a newer kernel, without recompile.
+ *
+ * This means that we're not changing functionality of GLib simply based
+ * on the set of headers we happen to compile against...
+ */
+
+#ifndef F_LINUX_SPECIFIC_BASE
+#define F_LINUX_SPECIFIC_BASE 1024
+#endif
+
+#ifndef F_ADD_SEALS
+#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
+#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
+
+#define F_SEAL_SEAL     0x0001  /* prevent further seals from being set */
+#define F_SEAL_SHRINK   0x0002  /* prevent file from shrinking */
+#define F_SEAL_GROW     0x0004  /* prevent file from growing */
+#define F_SEAL_WRITE    0x0008  /* prevent writes */
+#endif
+
+#endif
+
 /**
  * SECTION:gunix
  * @title: UNIX-specific utilities and integration
@@ -431,6 +462,65 @@ g_unix_fd_add (gint              fd,
 }
 
 /**
+ * g_unix_fd_ensure_zero_copy_safe:
+ * @fd: a file descriptor
+ *
+ * Checks whether @fd can be use in zero-copy mode. On Linux, this checks that
+ * the descriptor is a memfd, created with memfd_create(), and tries to apply
+ * seals to it so that it can be safely consumed by another process. On other
+ * Unix systems, this function will fail.
+ *
+ * Returns: whether the fd is safe to use in zero-copy mode. Sealing of memfds
+ *          is required for the @fd to be considered safe. If sealing fails, or
+ *          memfds are not available, or the @fd is not a memfd, returns %FALSE
+ *
+ * Since: 2.44
+ **/
+gboolean
+g_unix_fd_ensure_zero_copy_safe (gint fd)
+{
+#ifdef F_GET_SEALS
+  gint seals;
+  const gint IMMUTABLE_SEALS = F_SEAL_WRITE |
+                               F_SEAL_SHRINK |
+                               F_SEAL_GROW |
+                               F_SEAL_SEAL;
+
+  g_return_val_if_fail (fd >= 0, FALSE);
+
+  /* Seal the fd if possible (only on Linux 3.17+, and if the fd was created
+   * with memfd_create()). */
+  seals = fcntl (fd, F_GET_SEALS);
+  if (seals == -1)
+    {
+      g_debug ("Retrieving fd seals failed: %s", g_strerror (errno));
+      return FALSE;
+    }
+
+  /* Seal the fd, if it is not already. */
+  if ((seals & (IMMUTABLE_SEALS)) >= IMMUTABLE_SEALS)
+    {
+      g_debug ("%s", "fd already sealed");
+    }
+  else
+    {
+      gint error;
+
+      error = fcntl (fd, F_ADD_SEALS, IMMUTABLE_SEALS);
+      if (error == -1)
+        {
+          g_debug ("fd sealing failed: %s", g_strerror (errno));
+          return FALSE;
+        }
+    }
+
+  return TRUE;
+#else
+  return FALSE;
+#endif
+}
+
+/**
  * g_unix_get_passwd_entry:
  * @user_name: the username to get the passwd file entry for
  * @error: return location for a #GError, or %NULL
index a5ea9a1..9c14727 100644 (file)
@@ -114,6 +114,9 @@ guint    g_unix_fd_add             (gint              fd,
                                     GUnixFDSourceFunc function,
                                     gpointer          user_data);
 
+GLIB_AVAILABLE_IN_2_44
+gboolean g_unix_fd_ensure_zero_copy_safe (gint fd);
+
 GLIB_AVAILABLE_IN_2_64
 struct passwd *g_unix_get_passwd_entry (const gchar  *user_name,
                                         GError      **error);
index f0b3a86..1bc38f3 100644 (file)
@@ -598,14 +598,53 @@ GPrintFunc      g_set_printerr_handler  (GPrintFunc      func);
  * the result is usually that a critical message is logged and @val is
  * returned from the current function.
  *
- * If `G_DISABLE_CHECKS` is defined then the check is not performed.  You
- * should therefore not depend on any side effects of @expr.
+ * If G_DISABLE_CHECKS is defined then the check is not performed.  You
+ * should therefore not depend on any side effects of @expr.  See
+ * g_return_if_fail_se() for a version that guarantees side effects.
  *
  * See g_return_if_fail() for guidance on how to debug failure of this check.
  */
 #define g_return_val_if_fail(expr,val) G_STMT_START{ (void)0; }G_STMT_END
 
 /**
+ * g_return_if_fail_se:
+ * @expr: the expression to check
+ *
+ * Verifies that the expression @expr, usually representing a
+ * precondition, evaluates to %TRUE.
+ *
+ * This is the same as g_return_if_fail() except that @expr is
+ * guaranteed to be evaluated, so it may contain side effects.
+ *
+ * Note: it is still undefined if this function will actually return or
+ * not, or if any side effects of @val will be evaluated.  There is only
+ * a guarantee with respect to side effects of @expr.
+ *
+ * Since: 2.44
+ */
+#define g_return_if_fail_se(expr)         ((void) (expr))
+
+/**
+ * g_return_val_if_fail_se:
+ * @expr: the expression to check
+ * @val: the value to return from the current function
+ *       if the expression is not true
+ *
+ * Verifies that the expression @expr, usually representing a
+ * precondition, evaluates to %TRUE.
+ *
+ * This is the same as g_return_val_if_fail() except that @expr is
+ * guaranteed to be evaluated, so it may contain side effects.
+ *
+ * Note: it is still undefined if this function will actually return or
+ * not, or if any side effects of @val will be evaluated.  There is only
+ * a guarantee with respect to side effects of @expr.
+ *
+ * Since: 2.44
+ */
+#define g_return_val_if_fail_se(expr,val) ((void) (expr))
+
+/**
  * g_return_if_reached:
  *
  * Logs a critical message and returns from the current function.
@@ -653,27 +692,26 @@ GPrintFunc      g_set_printerr_handler  (GPrintFunc      func);
       } \
   } G_STMT_END
 
-#define g_return_if_reached() \
-  G_STMT_START { \
-    g_log (G_LOG_DOMAIN, \
-           G_LOG_LEVEL_CRITICAL, \
-           "file %s: line %d (%s): should not be reached", \
-           __FILE__, \
-           __LINE__, \
-           G_STRFUNC); \
-    return; \
-  } G_STMT_END
-
-#define g_return_val_if_reached(val) \
-  G_STMT_START { \
-    g_log (G_LOG_DOMAIN, \
-           G_LOG_LEVEL_CRITICAL, \
-           "file %s: line %d (%s): should not be reached", \
-           __FILE__, \
-           __LINE__, \
-           G_STRFUNC); \
-    return (val); \
-  } G_STMT_END
+#define g_return_if_fail_se(expr)         g_return_if_fail((expr))
+#define g_return_val_if_fail_se(expr,val) g_return_val_if_fail((expr), (val))
+
+#define g_return_if_reached()          G_STMT_START{                   \
+     g_log (G_LOG_DOMAIN,                                              \
+           G_LOG_LEVEL_CRITICAL,                                       \
+           "file %s: line %d (%s): should not be reached",             \
+           __FILE__,                                                   \
+           __LINE__,                                                   \
+           G_STRFUNC);                                                 \
+     return;                           }G_STMT_END
+
+#define g_return_val_if_reached(val)   G_STMT_START{                   \
+     g_log (G_LOG_DOMAIN,                                              \
+           G_LOG_LEVEL_CRITICAL,                                       \
+           "file %s: line %d (%s): should not be reached",             \
+           __FILE__,                                                   \
+           __LINE__,                                                   \
+           G_STRFUNC);                                                 \
+     return (val);                     }G_STMT_END
 
 #endif /* !G_DISABLE_CHECKS */
 
index 5782703..f502970 100644 (file)
  * in unit tests, otherwise the unit tests will be ineffective if compiled with
  * `G_DISABLE_ASSERT`. Use g_assert_true() and related macros in unit tests
  * instead.
+ *
+ * For a version which is guaranteed to evaluate side effects in @expr,
+ * see g_assert_se().
+ */
+
+/**
+ * g_assert_se:
+ * @expr: the expression to check
+ *
+ * Debugging macro to terminate the application if the assertion
+ * fails. If the assertion fails (i.e. the expression is not true),
+ * an error message is logged and the application is terminated.
+ *
+ * The check can be turned off in final releases of code by defining
+ * `G_DISABLE_ASSERT` when compiling the application.
+ *
+ * Unlike g_assert(), this macro is guaranteed to evaluate side effects
+ * of @expr, even if checks are disabled.  It is still undefined if the
+ * program will actually be aborted or not.
  */
 
 /**
index f5202ac..31f5ee5 100644 (file)
@@ -226,6 +226,7 @@ typedef void (*GTestFixtureFunc) (gpointer      fixture,
 #endif
 
 #define g_assert(expr)                  G_STMT_START { (void) 0; } G_STMT_END
+#define g_assert_se(expr)               ((void) (expr))
 #else /* !G_DISABLE_ASSERT */
 #define g_assert_not_reached()          G_STMT_START { g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, NULL); } G_STMT_END
 #define g_assert(expr)                  G_STMT_START { \
@@ -233,6 +234,7 @@ typedef void (*GTestFixtureFunc) (gpointer      fixture,
                                                g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
                                                                          #expr); \
                                         } G_STMT_END
+#define g_assert_se(expr)               g_assert((expr))
 #endif /* !G_DISABLE_ASSERT */
 
 GLIB_AVAILABLE_IN_ALL
index b7a2113..76241cd 100644 (file)
@@ -3008,7 +3008,24 @@ g_check_setuid (void)
   value = getauxval (AT_SECURE);
   errsv = errno;
   if (errsv)
-    g_error ("getauxval () failed: %s", g_strerror (errsv));
+    {
+/*
+    Apparently, Tizen is built with qemu version < 2.12.
+    
+    qemu 2.12 introduces providing AT_SECURE in auxiliary vector,
+    and the only purpose of using getauxval in glib is to get AT_SECURE.
+    
+    If g_check_setuid() bails out with error, some packages may not build,
+    as their building process requires executing tools that call g_check_setuid().
+
+    So, don't bail out with error if getauxval(AT_SECURE) fails.
+    Instead, set the result of checking suid to FALSE (no suid).
+
+       It may be reverted if all the builds are made within qemu >= 2.12.
+*/
+/*      g_error ("getauxval () failed: %s", g_strerror (errsv));*/
+      return FALSE;
+    }
   return value;
 #elif defined(HAVE_ISSETUGID) && !defined(__BIONIC__)
   /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
index a31d396..79fd0de 100644 (file)
@@ -19,6 +19,7 @@
 #include "config.h"
 
 #include <glib/gvariant-core.h>
+#include "glib-private.h"
 
 #include <glib/gvariant-internal.h>
 #include <glib/gvariant-serialiser.h>
@@ -109,21 +110,11 @@ struct _GVariant
  *            The type_info field never changes during the life of the
  *            instance, so it can be accessed without a lock.
  *
- * size: this is the size of the serialized form for the instance, if it
- *       is known.  If the instance is in serialized form then it is, by
- *       definition, known.  If the instance is in tree form then it may
- *       be unknown (in which case it is -1).  It is possible for the
- *       size to be known when in tree form if, for example, the user
- *       has called g_variant_get_size() without calling
- *       g_variant_get_data().  Additionally, even when the user calls
- *       g_variant_get_data() the size of the data must first be
- *       determined so that a large enough buffer can be allocated for
- *       the data.
- *
- *       Once the size is known, it can never become unknown again.
- *       g_variant_ensure_size() is used to ensure that the size is in
- *       the known state -- it calculates the size if needed.  After
- *       that, the size field can be accessed without a lock.
+ * size: this is the size of the serialised form for the instance.  It
+ *       is known for serialised instances and also tree-form instances
+ *       (for which it is calculated at construction time, from the
+ *       known sizes of the children used).  After construction, it
+ *       never changes and therefore can be accessed without a lock.
  *
  * contents: a union containing either the information associated with
  *           holding a value in serialized form or holding a value in
@@ -267,7 +258,32 @@ g_variant_release_children (GVariant *value)
   g_free (value->contents.tree.children);
 }
 
-/* This begins the main body of the recursive serializer.
+/* < private >
+ * g_variant_lock_in_tree_form:
+ * @value: a #GVariant
+ *
+ * Locks @value if it is in tree form.
+ *
+ * Returns: %TRUE if @value is now in tree form with the lock acquired
+ */
+static gboolean
+g_variant_lock_in_tree_form (GVariant *value)
+{
+  if (g_atomic_int_get (&value->state) & STATE_SERIALISED)
+    return FALSE;
+
+  g_variant_lock (value);
+
+  if (value->state & STATE_SERIALISED)
+    {
+      g_variant_unlock (value);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* This begins the main body of the recursive serialiser.
  *
  * There are 3 functions here that work as a team with the serializer to
  * get things done.  g_variant_store() has a trivial role, but as a
@@ -284,31 +300,19 @@ g_variant_release_children (GVariant *value)
  * instances are always in serialized form.  For these instances,
  * storing their serialized form merely involves a memcpy().
  *
- * Serialization is a two-step process.  First, the size of the
- * serialized data must be calculated so that an appropriately-sized
- * buffer can be allocated.  Second, the data is written into the
- * buffer.
+ * Converting to serialised form:
  *
- * Determining the size:
- *   The process of determining the size is triggered by a call to
- *   g_variant_ensure_size() on a container.  This invokes the
- *   serializer code to determine the size.  The serializer is passed
- *   g_variant_fill_gvs() as a callback.
- *
- *   g_variant_fill_gvs() is called by the serializer on each child of
- *   the container which, in turn, calls g_variant_ensure_size() on
- *   itself and fills in the result of its own size calculation.
+ *   The first step in the process of converting a GVariant to
+ *   serialised form is to allocate a buffer.  The size of the buffer is
+ *   always known because we computed at construction time of the
+ *   GVariant.
  *
- *   The serializer uses the size information from the children to
- *   calculate the size needed for the entire container.
- *
- * Writing the data:
  *   After the buffer has been allocated, g_variant_serialise() is
- *   called on the container.  This invokes the serializer code to write
- *   the bytes to the container.  The serializer is, again, passed
+ *   called on the container.  This invokes the serialiser code to write
+ *   the bytes to the container.  The serialiser is passed
  *   g_variant_fill_gvs() as a callback.
  *
- *   This time, when g_variant_fill_gvs() is called for each child, the
+ *   At the time that g_variant_fill_gvs() is called for each child, the
  *   child is given a pointer to a sub-region of the allocated buffer
  *   where it should write its data.  This is done by calling
  *   g_variant_store().  In the event that the instance is in serialized
@@ -322,34 +326,6 @@ g_variant_release_children (GVariant *value)
 static void g_variant_fill_gvs (GVariantSerialised *, gpointer);
 
 /* < private >
- * g_variant_ensure_size:
- * @value: a #GVariant
- *
- * Ensures that the ->size field of @value is filled in properly.  This
- * must be done as a precursor to any serialization of the value in
- * order to know how large of a buffer is needed to store the data.
- *
- * The current thread must hold the lock on @value.
- */
-static void
-g_variant_ensure_size (GVariant *value)
-{
-  g_assert (value->state & STATE_LOCKED);
-
-  if (value->size == (gsize) -1)
-    {
-      gpointer *children;
-      gsize n_children;
-
-      children = (gpointer *) value->contents.tree.children;
-      n_children = value->contents.tree.n_children;
-      value->size = g_variant_serialiser_needed_size (value->type_info,
-                                                      g_variant_fill_gvs,
-                                                      children, n_children);
-    }
-}
-
-/* < private >
  * g_variant_serialise:
  * @value: a #GVariant
  * @data: an appropriately-sized buffer
@@ -395,9 +371,12 @@ g_variant_serialise (GVariant *value,
  *
  *  - reporting its type
  *
- *  - reporting its serialized size (requires knowing the size first)
+ *  - reporting its serialised size
  *
- *  - possibly storing its serialized form into the provided buffer
+ *  - possibly storing its serialised form into the provided buffer
+ *
+ * This callback is also used during g_variant_new_from_children() in
+ * order to discover the size and type of each child.
  */
 static void
 g_variant_fill_gvs (GVariantSerialised *serialised,
@@ -405,10 +384,6 @@ g_variant_fill_gvs (GVariantSerialised *serialised,
 {
   GVariant *value = data;
 
-  g_variant_lock (value);
-  g_variant_ensure_size (value);
-  g_variant_unlock (value);
-
   if (serialised->type_info == NULL)
     serialised->type_info = value->type_info;
   g_assert (serialised->type_info == value->type_info);
@@ -433,25 +408,19 @@ g_variant_fill_gvs (GVariantSerialised *serialised,
  *
  * Ensures that @value is in serialized form.
  *
- * If @value is in tree form then this function ensures that the
- * serialized size is known and then allocates a buffer of that size and
- * serializes the instance into the buffer.  The 'children' array is
- * then released and the instance is set to serialized form based on the
- * contents of the buffer.
- *
- * The current thread must hold the lock on @value.
+ * If @value is in tree form then this function allocates a buffer of
+ * that size and serialises the instance into the buffer.  The
+ * 'children' array is then released and the instance is set to
+ * serialised form based on the contents of the buffer.
  */
 static void
 g_variant_ensure_serialised (GVariant *value)
 {
-  g_assert (value->state & STATE_LOCKED);
-
-  if (~value->state & STATE_SERIALISED)
+  if (g_variant_lock_in_tree_form (value))
     {
       GBytes *bytes;
       gpointer data;
 
-      g_variant_ensure_size (value);
       data = g_malloc (value->size);
       g_variant_serialise (value, data);
 
@@ -461,12 +430,69 @@ g_variant_ensure_serialised (GVariant *value)
       value->contents.serialised.data = g_bytes_get_data (bytes, NULL);
       value->contents.serialised.bytes = bytes;
       value->state |= STATE_SERIALISED;
+
+      g_variant_unlock (value);
+    }
+}
+
+/* Now we have the code to recursively serialise a GVariant into a
+ * GVariantVectors structure.
+ *
+ * We want to do this in cases where the GVariant contains large chunks
+ * of serialised data in order to avoid having to copy this data.
+ *
+ * This generally works the same as normal serialising (co-recursion
+ * with the serialiser) but instead of using a callback we just hard-code
+ * the callback with the name g_variant_callback_write_to_vectors().
+ *
+ * This is a private API that will be used by GDBus.
+ */
+gsize
+g_variant_callback_write_to_vectors (GVariantVectors   *vectors,
+                                     gpointer           data,
+                                     GVariantTypeInfo **type_info)
+{
+  GVariant *value = data;
+
+  if (g_variant_lock_in_tree_form (value))
+    {
+      g_variant_serialiser_write_to_vectors (vectors, value->type_info, value->size,
+                                             (gpointer *) value->contents.tree.children,
+                                             value->contents.tree.n_children);
+
+      g_variant_unlock (value);
     }
+  else
+    g_variant_vectors_append_gbytes (vectors, value->contents.serialised.bytes,
+                                     value->contents.serialised.data, value->size);
+
+  if (type_info)
+    *type_info = value->type_info;
+
+  return value->size;
+}
+
+/* < private >
+ * g_variant_serialise_to_vectors:
+ * @value: a #GVariant
+ * @vectors: (out): the result
+ *
+ * Serialises @value into @vectors.
+ *
+ * The caller must free @vectors.
+ */
+void
+g_variant_to_vectors (GVariant        *value,
+                      GVariantVectors *vectors)
+{
+  g_variant_vectors_init (vectors);
+
+  g_variant_callback_write_to_vectors (vectors, value, NULL);
 }
 
 /* < private >
  * g_variant_alloc:
- * @type: the type of the new instance
+ * @type_info: (transfer full) the type info of the new instance
  * @serialised: if the instance will be in serialised form
  * @trusted: if the instance will be trusted
  *
@@ -477,71 +503,104 @@ g_variant_ensure_serialised (GVariant *value)
  * Returns: a new #GVariant with a floating reference
  */
 static GVariant *
-g_variant_alloc (const GVariantType *type,
-                 gboolean            serialised,
-                 gboolean            trusted)
+g_variant_alloc (GVariantTypeInfo *type_info,
+                 gboolean          serialised,
+                 gboolean          trusted)
 {
   GVariant *value;
 
   value = g_slice_new (GVariant);
-  value->type_info = g_variant_type_info_get (type);
+  value->type_info = type_info;
   value->state = (serialised ? STATE_SERIALISED : 0) |
                  (trusted ? STATE_TRUSTED : 0) |
                  STATE_FLOATING;
-  value->size = (gssize) -1;
   g_atomic_ref_count_init (&value->ref_count);
   value->depth = 0;
 
   return value;
 }
 
-/**
- * g_variant_new_from_bytes:
- * @type: a #GVariantType
- * @bytes: a #GBytes
- * @trusted: if the contents of @bytes are trusted
+/* -- internal -- */
+
+/* < internal >
+ * g_variant_new_from_children:
+ * @type_info: (transfer full) a #GVariantTypeInfo
+ * @children: an array of #GVariant pointers.  Consumed.
+ * @n_children: the length of @children
+ * @trusted: %TRUE if every child in @children in trusted
+ *
+ * Constructs a new tree-mode #GVariant instance.  This is the inner
+ * interface for creation of new tree-mode values that gets called from
+ * various functions in gvariant.c.
+ *
+ * @children is consumed by this function.  g_free() will be called on
+ * it some time later.
  *
- * Constructs a new serialized-mode #GVariant instance.  This is the
- * inner interface for creation of new serialized values that gets
- * called from various functions in gvariant.c.
+ * Returns: a new #GVariant with a floating reference
+ */
+GVariant *
+g_variant_new_from_children (GVariantTypeInfo  *type_info,
+                             GVariant         **children,
+                             gsize              n_children,
+                             gboolean           trusted)
+{
+  GVariant *value;
+
+  value = g_variant_alloc (type_info, FALSE, trusted);
+  value->contents.tree.children = children;
+  value->contents.tree.n_children = n_children;
+  value->size = g_variant_serialiser_needed_size (value->type_info, g_variant_fill_gvs,
+                                                  (gpointer *) children, n_children);
+
+  return value;
+}
+
+/* < internal >
+ * g_variant_new_serialised:
+ * @type_info: (transfer full): a #GVariantTypeInfo
+ * @bytes: (transfer full): the #GBytes holding @data
+ * @data: a pointer to the serialised data
+ * @size: the size of @data, in bytes
+ * @trusted: %TRUE if @data is trusted
+ *
+ * Constructs a new serialised #GVariant instance.  This is the inner
+ * interface for creation of new serialised values that gets called from
+ * various functions in gvariant.c.
  *
- * A reference is taken on @bytes.
+ * @bytes is consumed by this function.  g_bytes_unref() will be called
+ * on it some time later.
  *
  * The data in @bytes must be aligned appropriately for the @type being loaded.
  * Otherwise this function will internally create a copy of the memory (since
  * GLib 2.60) or (in older versions) fail and exit the process.
  *
- * Returns: (transfer none): a new #GVariant with a floating reference
- *
- * Since: 2.36
+ * Returns: a new #GVariant with a floating reference
  */
 GVariant *
-g_variant_new_from_bytes (const GVariantType *type,
-                          GBytes             *bytes,
-                          gboolean            trusted)
+g_variant_new_serialised (GVariantTypeInfo *type_info,
+                          GBytes           *bytes,
+                          gconstpointer     data,
+                          gsize             size,
+                          gboolean          trusted)
 {
   GVariant *value;
   guint alignment;
-  gsize size;
+  gsize fixed_size;
   GBytes *owned_bytes = NULL;
-  GVariantSerialised serialised;
 
-  value = g_variant_alloc (type, TRUE, trusted);
+  value = g_variant_alloc (type_info, TRUE, trusted);
+  value->contents.serialised.data = data;
+  value->size = size;
 
   g_variant_type_info_query (value->type_info,
-                             &alignment, &size);
-
+                             &alignment, &fixed_size);
   /* Ensure the alignment is correct. This is a huge performance hit if it’s
    * not correct, but that’s better than aborting if a caller provides data
    * with the wrong alignment (which is likely to happen very occasionally, and
    * only cause an abort on some architectures — so is unlikely to be caught
    * in testing). Callers can always actively ensure they use the correct
    * alignment to avoid the performance hit. */
-  serialised.type_info = value->type_info;
-  serialised.data = (guchar *) g_bytes_get_data (bytes, &serialised.size);
-  serialised.depth = 0;
-
-  if (!g_variant_serialised_check (serialised))
+  if ((alignment & (gsize) g_bytes_get_data (bytes, NULL)) != 0)
     {
 #ifdef HAVE_POSIX_MEMALIGN
       gpointer aligned_data = NULL;
@@ -557,37 +616,43 @@ g_variant_new_from_bytes (const GVariantType *type,
       if (aligned_size != 0)
         memcpy (aligned_data, g_bytes_get_data (bytes, NULL), aligned_size);
 
-      bytes = owned_bytes = g_bytes_new_with_free_func (aligned_data,
-                                                        aligned_size,
-                                                        free, aligned_data);
+      owned_bytes = g_bytes_new_with_free_func (aligned_data,
+                                                aligned_size,
+                                                free, aligned_data);
       aligned_data = NULL;
 #else
       /* NOTE: there may be platforms that lack posix_memalign() and also
        * have malloc() that returns non-8-aligned.  if so, we need to try
        * harder here.
        */
-      bytes = owned_bytes = g_bytes_new (g_bytes_get_data (bytes, NULL),
-                                         g_bytes_get_size (bytes));
+      owned_bytes = g_bytes_new (g_bytes_get_data (bytes, NULL),
+                                 g_bytes_get_size (bytes));
 #endif
+      g_bytes_unref (bytes);
+      bytes = g_bytes_ref (owned_bytes);
     }
 
-  value->contents.serialised.bytes = g_bytes_ref (bytes);
+  value->contents.serialised.bytes = bytes;
 
-  if (size && g_bytes_get_size (bytes) != size)
+  if G_UNLIKELY (fixed_size && size != fixed_size)
     {
       /* Creating a fixed-sized GVariant with a bytes of the wrong
        * size.
        *
        * We should do the equivalent of pulling a fixed-sized child out
-       * of a brozen container (ie: data is NULL size is equal to the correct
+       * of a broken container (ie: data is NULL size is equal to the correct
        * fixed size).
+       *
+       * This really ought not to happen if the data is trusted...
+       */
+      if (trusted)
+        g_error ("Attempting to create a trusted GVariant instance out of invalid data");
+
+      /* We hang on to the GBytes (even though we don't use it anymore)
+       * because every GVariant must have a GBytes.
        */
       value->contents.serialised.data = NULL;
-      value->size = size;
-    }
-  else
-    {
-      value->contents.serialised.data = g_bytes_get_data (bytes, &value->size);
+      value->size = fixed_size;
     }
 
   g_clear_pointer (&owned_bytes, g_bytes_unref);
@@ -595,39 +660,6 @@ g_variant_new_from_bytes (const GVariantType *type,
   return value;
 }
 
-/* -- internal -- */
-
-/* < internal >
- * g_variant_new_from_children:
- * @type: a #GVariantType
- * @children: an array of #GVariant pointers.  Consumed.
- * @n_children: the length of @children
- * @trusted: %TRUE if every child in @children in trusted
- *
- * Constructs a new tree-mode #GVariant instance.  This is the inner
- * interface for creation of new serialized values that gets called from
- * various functions in gvariant.c.
- *
- * @children is consumed by this function.  g_free() will be called on
- * it some time later.
- *
- * Returns: a new #GVariant with a floating reference
- */
-GVariant *
-g_variant_new_from_children (const GVariantType  *type,
-                             GVariant           **children,
-                             gsize                n_children,
-                             gboolean             trusted)
-{
-  GVariant *value;
-
-  value = g_variant_alloc (type, FALSE, trusted);
-  value->contents.tree.children = children;
-  value->contents.tree.n_children = n_children;
-
-  return value;
-}
-
 /* < internal >
  * g_variant_get_type_info:
  * @value: a #GVariant
@@ -667,6 +699,191 @@ g_variant_is_trusted (GVariant *value)
 }
 
 /* < internal >
+ * g_variant_get_serialised:
+ * @value: a #GVariant
+ * @bytes: (out) (transfer none): a location to store the #GBytes
+ * @size: (out): a location to store the size of the returned data
+ *
+ * Ensures that @value is in serialised form and returns information
+ * about it.  This is called from various APIs in gvariant.c
+ *
+ * Returns: data, of length @size
+ */
+gconstpointer
+g_variant_get_serialised (GVariant  *value,
+                          GBytes   **bytes,
+                          gsize     *size)
+{
+  g_variant_ensure_serialised (value);
+
+  if (bytes)
+    *bytes = value->contents.serialised.bytes;
+
+  *size = value->size;
+
+  return value->contents.serialised.data;
+}
+
+static GVariant *
+g_variant_vector_deserialise (GVariantTypeInfo *type_info,
+                              GVariantVector   *first_vector,
+                              GVariantVector   *last_vector,
+                              gsize             size,
+                              gboolean          trusted,
+                              GArray           *unpacked_children)
+{
+  g_assert (size > 0);
+
+  if (first_vector < last_vector)
+    {
+      GVariantVector *vector = first_vector;
+      const guchar *end_pointer;
+      GVariant **children;
+      guint save_point;
+      guint n_children;
+      gboolean failed;
+      guint i;
+
+      end_pointer = last_vector->data.pointer + last_vector->size;
+      save_point = unpacked_children->len;
+
+      if (!g_variant_serialiser_unpack_all (type_info, end_pointer, last_vector->size, size, unpacked_children))
+        {
+          for (i = save_point; i < unpacked_children->len; i++)
+            g_variant_type_info_unref (g_array_index (unpacked_children, GVariantUnpacked, i).type_info);
+          g_array_set_size (unpacked_children, save_point);
+
+          g_variant_type_info_unref (type_info);
+
+          return NULL;
+        }
+
+      n_children = unpacked_children->len - save_point;
+      children = g_new (GVariant *, n_children);
+      failed = FALSE;
+
+      for (i = 0; i < n_children; i++)
+        {
+          GVariantUnpacked *unpacked = &g_array_index (unpacked_children, GVariantUnpacked, save_point + i);
+          const guchar *resume_at_data;
+          gsize resume_at_size;
+          GVariantVector *fv;
+
+          /* Skip the alignment.
+           *
+           * We can destroy vectors because we won't be going back.
+           *
+           * We do a >= compare because we want to go to the next vector
+           * if it is the start of our child.
+           */
+          while (unpacked->skip >= vector->size)
+            {
+              unpacked->skip -= vector->size;
+              vector++;
+            }
+          g_assert (vector <= last_vector);
+
+          fv = vector;
+          fv->data.pointer += unpacked->skip;
+          fv->size -= unpacked->skip;
+
+          if (unpacked->size == 0)
+            {
+              children[i] = g_variant_new_serialised (unpacked->type_info, g_bytes_new (NULL, 0), NULL, 0, trusted);
+              g_variant_ref_sink (children[i]);
+              continue;
+            }
+
+          /* Now skip to the end, according to 'size'.
+           *
+           * We cannot destroy everything here because we will probably
+           * end up reusing the last one.
+           *
+           * We do a > compare because we want to stay on this vector if
+           * it is the end of our child.
+           */
+          size = unpacked->size;
+          while (unpacked->size > vector->size)
+            {
+              unpacked->size -= vector->size;
+              vector++;
+            }
+          g_assert (vector <= last_vector);
+
+          /* We have to modify the vectors for the benefit of the
+           * recursive step.  We also have to remember where we left
+           * off, keeping in mind that the recursive step may itself
+           * modify the vectors.
+           */
+          resume_at_data = vector->data.pointer + unpacked->size;
+          resume_at_size = vector->size - unpacked->size;
+          vector->size = unpacked->size;
+
+          children[i] = g_variant_vector_deserialise (unpacked->type_info, fv, vector,
+                                                      size, trusted, unpacked_children);
+
+          vector->data.pointer = resume_at_data;
+          vector->size = resume_at_size;
+
+          if (children[i])
+            g_variant_ref_sink (children[i]);
+          else
+            failed = TRUE;
+        }
+
+      /* We consumed all the type infos */
+      g_array_set_size (unpacked_children, save_point);
+
+      if G_UNLIKELY (failed)
+        {
+          for (i = 0; i < n_children; i++)
+            if (children[i])
+              g_variant_unref (children[i]);
+
+          g_variant_type_info_unref (type_info);
+          g_free (children);
+
+          return NULL;
+        }
+
+      return g_variant_new_from_children (type_info, children, n_children, trusted);
+    }
+  else
+    {
+      g_assert (first_vector == last_vector);
+      g_assert (size == first_vector->size);
+
+      return g_variant_new_serialised (type_info, g_bytes_ref (first_vector->gbytes),
+                                       first_vector->data.pointer, size, trusted);
+    }
+}
+
+GVariant *
+g_variant_from_vectors (const GVariantType *type,
+                        GVariantVector     *vectors,
+                        gsize               n_vectors,
+                        gsize               size,
+                        gboolean            trusted)
+{
+  GVariant *result;
+  GArray *tmp;
+
+  g_return_val_if_fail (vectors != NULL || n_vectors == 0, NULL);
+
+  if (size == 0)
+    return g_variant_new_serialised (g_variant_type_info_get (type), g_bytes_new (NULL, 0), NULL, 0, trusted);
+
+  tmp = g_array_new (FALSE, FALSE, sizeof (GVariantUnpacked));
+  result = g_variant_vector_deserialise (g_variant_type_info_get (type),
+                                         vectors, vectors + n_vectors - 1, size, trusted, tmp);
+  if (result)
+    g_variant_ref_sink (result);
+  g_array_free (tmp, TRUE);
+
+  return result;
+}
+
+/* < internal >
  * g_variant_get_depth:
  * @value: a #GVariant
  *
@@ -885,10 +1102,6 @@ g_variant_is_floating (GVariant *value)
 gsize
 g_variant_get_size (GVariant *value)
 {
-  g_variant_lock (value);
-  g_variant_ensure_size (value);
-  g_variant_unlock (value);
-
   return value->size;
 }
 
@@ -929,57 +1142,12 @@ g_variant_get_size (GVariant *value)
 gconstpointer
 g_variant_get_data (GVariant *value)
 {
-  g_variant_lock (value);
   g_variant_ensure_serialised (value);
-  g_variant_unlock (value);
 
   return value->contents.serialised.data;
 }
 
 /**
- * g_variant_get_data_as_bytes:
- * @value: a #GVariant
- *
- * Returns a pointer to the serialized form of a #GVariant instance.
- * The semantics of this function are exactly the same as
- * g_variant_get_data(), except that the returned #GBytes holds
- * a reference to the variant data.
- *
- * Returns: (transfer full): A new #GBytes representing the variant data
- *
- * Since: 2.36
- */ 
-GBytes *
-g_variant_get_data_as_bytes (GVariant *value)
-{
-  const gchar *bytes_data;
-  const gchar *data;
-  gsize bytes_size;
-  gsize size;
-
-  g_variant_lock (value);
-  g_variant_ensure_serialised (value);
-  g_variant_unlock (value);
-
-  bytes_data = g_bytes_get_data (value->contents.serialised.bytes, &bytes_size);
-  data = value->contents.serialised.data;
-  size = value->size;
-
-  if (data == NULL)
-    {
-      g_assert (size == 0);
-      data = bytes_data;
-    }
-
-  if (data == bytes_data && size == bytes_size)
-    return g_bytes_ref (value->contents.serialised.bytes);
-  else
-    return g_bytes_new_from_bytes (value->contents.serialised.bytes,
-                                   data - bytes_data, size);
-}
-
-
-/**
  * g_variant_n_children:
  * @value: a container #GVariant
  *
@@ -1004,9 +1172,12 @@ g_variant_n_children (GVariant *value)
 {
   gsize n_children;
 
-  g_variant_lock (value);
-
-  if (value->state & STATE_SERIALISED)
+  if (g_variant_lock_in_tree_form (value))
+    {
+      n_children = value->contents.tree.n_children;
+      g_variant_unlock (value);
+    }
+  else
     {
       GVariantSerialised serialised = {
         value->type_info,
@@ -1017,10 +1188,6 @@ g_variant_n_children (GVariant *value)
 
       n_children = g_variant_serialised_n_children (serialised);
     }
-  else
-    n_children = value->contents.tree.n_children;
-
-  g_variant_unlock (value);
 
   return n_children;
 }
@@ -1062,69 +1229,56 @@ GVariant *
 g_variant_get_child_value (GVariant *value,
                            gsize     index_)
 {
+  GVariant *child;
+
   g_return_val_if_fail (index_ < g_variant_n_children (value), NULL);
   g_return_val_if_fail (value->depth < G_MAXSIZE, NULL);
 
-  if (~g_atomic_int_get (&value->state) & STATE_SERIALISED)
+  if (g_variant_lock_in_tree_form (value))
     {
-      g_variant_lock (value);
 
-      if (~value->state & STATE_SERIALISED)
-        {
-          GVariant *child;
-
-          child = g_variant_ref (value->contents.tree.children[index_]);
-          g_variant_unlock (value);
+      child = g_variant_ref (value->contents.tree.children[index_]);
+      g_variant_unlock (value);
+    }
+  else
+    {
+      GVariantSerialised serialised = {
+        value->type_info,
+        (gpointer) value->contents.serialised.data,
+        value->size,
+        value->depth,
+      };
+      GVariantSerialised s_child;
 
-          return child;
+      /* get the serialiser to extract the serialised data for the child
+       * from the serialised data for the container
+       */
+      s_child = g_variant_serialised_get_child (serialised, index_);
+
+      /* Check whether this would cause nesting too deep. If so, return a fake
+       * child. The only situation we expect this to happen in is with a variant,
+       * as all other deeply-nested types have a static type, and hence should
+       * have been rejected earlier. In the case of a variant whose nesting plus
+       * the depth of its child is too great, return a unit variant () instead of
+       * the real child. */
+      if (!(value->state & STATE_TRUSTED) &&
+          g_variant_type_info_query_depth (s_child.type_info) >=
+          G_VARIANT_MAX_RECURSION_DEPTH - value->depth)
+        {
+          g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE_VARIANT));
+          return g_variant_new_tuple (NULL, 0);
         }
 
-      g_variant_unlock (value);
+      /* create a new serialised instance out of it */
+      child = g_variant_new_serialised (s_child.type_info,
+                                        g_bytes_ref (value->contents.serialised.bytes),
+                                        s_child.data, s_child.size,
+                                        value->state & STATE_TRUSTED);
+      child->state &= ~STATE_FLOATING;
+      child->depth = value->depth + 1;
     }
 
-  {
-    GVariantSerialised serialised = {
-      value->type_info,
-      (gpointer) value->contents.serialised.data,
-      value->size,
-      value->depth,
-    };
-    GVariantSerialised s_child;
-    GVariant *child;
-
-    /* get the serializer to extract the serialized data for the child
-     * from the serialized data for the container
-     */
-    s_child = g_variant_serialised_get_child (serialised, index_);
-
-    /* Check whether this would cause nesting too deep. If so, return a fake
-     * child. The only situation we expect this to happen in is with a variant,
-     * as all other deeply-nested types have a static type, and hence should
-     * have been rejected earlier. In the case of a variant whose nesting plus
-     * the depth of its child is too great, return a unit variant () instead of
-     * the real child. */
-    if (!(value->state & STATE_TRUSTED) &&
-        g_variant_type_info_query_depth (s_child.type_info) >=
-        G_VARIANT_MAX_RECURSION_DEPTH - value->depth)
-      {
-        g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE_VARIANT));
-        return g_variant_new_tuple (NULL, 0);
-      }
-
-    /* create a new serialized instance out of it */
-    child = g_slice_new (GVariant);
-    child->type_info = s_child.type_info;
-    child->state = (value->state & STATE_TRUSTED) |
-                   STATE_SERIALISED;
-    child->size = s_child.size;
-    g_atomic_ref_count_init (&child->ref_count);
-    child->depth = value->depth + 1;
-    child->contents.serialised.bytes =
-      g_bytes_ref (value->contents.serialised.bytes);
-    child->contents.serialised.data = s_child.data;
-
-    return child;
-  }
+  return child;
 }
 
 /**
@@ -1151,19 +1305,18 @@ void
 g_variant_store (GVariant *value,
                  gpointer  data)
 {
-  g_variant_lock (value);
-
-  if (value->state & STATE_SERIALISED)
+  if (g_variant_lock_in_tree_form (value))
+    {
+      g_variant_serialise (value, data);
+      g_variant_unlock (value);
+    }
+  else
     {
       if (value->contents.serialised.data != NULL)
         memcpy (data, value->contents.serialised.data, value->size);
       else
         memset (data, 0, value->size);
     }
-  else
-    g_variant_serialise (value, data);
-
-  g_variant_unlock (value);
 }
 
 /**
@@ -1191,9 +1344,13 @@ g_variant_store (GVariant *value,
 gboolean
 g_variant_is_normal_form (GVariant *value)
 {
-  if (value->state & STATE_TRUSTED)
+  if (g_atomic_int_get (&value->state) & STATE_TRUSTED)
     return TRUE;
 
+  /* We always take the lock here because we expect to find that the
+   * value is in normal form and in that case, we need to update the
+   * state, which requires holding the lock.
+   */
   g_variant_lock (value);
 
   if (value->depth >= G_VARIANT_MAX_RECURSION_DEPTH)
index fc04711..dd020e9 100644 (file)
 
 /* gvariant-core.c */
 
-GVariant *              g_variant_new_from_children                     (const GVariantType  *type,
+GVariant *              g_variant_new_from_children                     (GVariantTypeInfo    *type_info,
                                                                          GVariant           **children,
                                                                          gsize                n_children,
                                                                          gboolean             trusted);
 
+GVariant *              g_variant_new_serialised                        (GVariantTypeInfo    *type_info,
+                                                                         GBytes              *bytes,
+                                                                         gconstpointer        data,
+                                                                         gsize                size,
+                                                                         gboolean             trusted);
+
 gboolean                g_variant_is_trusted                            (GVariant            *value);
 
 GVariantTypeInfo *      g_variant_get_type_info                         (GVariant            *value);
 
+gconstpointer           g_variant_get_serialised                        (GVariant            *value,
+                                                                         GBytes             **bytes,
+                                                                         gsize               *size);
+
 gsize                   g_variant_get_depth                             (GVariant            *value);
 
 #endif /* __G_VARIANT_CORE_H__ */
index bb5238b..85bd1ae 100644 (file)
@@ -467,7 +467,13 @@ pattern_coalesce (const gchar *left,
               (*one)++;
             }
 
-          else if (**one == 'N' && strchr ("ynqiuxthd", **the_other))
+          else if (**one == 'N' && strchr ("ynqiuxthfd", **the_other))
+            {
+              *out++ = *(*the_other)++;
+              (*one)++;
+            }
+
+          else if (**one == 'D' && (**the_other == 'f' || **the_other == 'd'))
             {
               *out++ = *(*the_other)++;
               (*one)++;
@@ -628,6 +634,10 @@ ast_resolve (AST     *ast,
         pattern[j++] = 'i';
         break;
 
+      case 'D':
+        pattern[j++] = 'd';
+        break;
+
       default:
         pattern[j++] = pattern[i];
         break;
@@ -1276,7 +1286,7 @@ dictionary_get_pattern (AST     *ast,
   /* the basic types,
    * plus undetermined number type and undetermined string type.
    */
-  if (!strchr ("bynqiuxthdsogNS", key_char))
+  if (!strchr ("bynqiuxthfdsogNDS", key_char))
     {
       ast_set_error (ast, error, NULL,
                      G_VARIANT_PARSE_ERROR_BASIC_TYPE_EXPECTED,
@@ -1843,7 +1853,7 @@ number_get_pattern (AST     *ast,
       (!g_str_has_prefix (number->token, "0x") && strchr (number->token, 'e')) ||
       strstr (number->token, "inf") ||
       strstr (number->token, "nan"))
-    return g_strdup ("Md");
+    return g_strdup ("MD");
 
   return g_strdup ("MN");
 }
@@ -1868,17 +1878,16 @@ number_get_value (AST                 *ast,
   Number *number = (Number *) ast;
   const gchar *token;
   gboolean negative;
-  gboolean floating;
   guint64 abs_val;
   gdouble dbl_val;
+  gchar typechar;
   gchar *end;
 
+  typechar = *g_variant_type_peek_string (type);
   token = number->token;
 
-  if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
+  if (typechar == 'f' || typechar == 'd')
     {
-      floating = TRUE;
-
       errno = 0;
       dbl_val = g_ascii_strtod (token, &end);
       if (dbl_val != 0.0 && errno == ERANGE)
@@ -1895,7 +1904,6 @@ number_get_value (AST                 *ast,
     }
   else
     {
-      floating = FALSE;
       negative = token[0] == '-';
       if (token[0] == '-')
         token++;
@@ -1931,10 +1939,7 @@ number_get_value (AST                 *ast,
       return NULL;
      }
 
-  if (floating)
-    return g_variant_new_double (dbl_val);
-
-  switch (*g_variant_type_peek_string (type))
+  switch (typechar)
     {
     case 'y':
       if (negative || abs_val > G_MAXUINT8)
@@ -1988,6 +1993,12 @@ number_get_value (AST                 *ast,
       return g_variant_new_handle (negative ?
                                    -((gint32) abs_val) : ((gint32) abs_val));
 
+    case 'f':
+      return g_variant_new_float (dbl_val);
+
+    case 'd':
+      return g_variant_new_double (dbl_val);
+
     default:
       return ast_type_error (ast, type, error);
     }
@@ -2274,6 +2285,9 @@ typedecl_parse (TokenStream  *stream,
       else if (token_stream_consume (stream, "uint64"))
         type = g_variant_type_copy (G_VARIANT_TYPE_UINT64);
 
+      else if (token_stream_consume (stream, "float"))
+        type = g_variant_type_copy (G_VARIANT_TYPE_FLOAT);
+
       else if (token_stream_consume (stream, "double"))
         type = g_variant_type_copy (G_VARIANT_TYPE_DOUBLE);
 
index 832a8fd..6806ad7 100644 (file)
@@ -268,6 +268,27 @@ gvs_fixed_sized_maybe_get_child (GVariantSerialised value,
   return value;
 }
 
+static gboolean
+gvs_fixed_sized_maybe_unpack_all (GVariantTypeInfo *type_info,
+                                  const guchar     *end_pointer,
+                                  gsize             end_size,
+                                  gsize             total_size,
+                                  GArray           *unpacked_children)
+{
+  if (total_size)
+    {
+      GVariantUnpacked unpacked;
+
+      unpacked.type_info = g_variant_type_info_ref (g_variant_type_info_element (type_info));
+      unpacked.skip = 0;
+      unpacked.size = total_size;
+
+      g_array_append_val (unpacked_children, unpacked);
+    }
+
+  return TRUE;
+}
+
 static gsize
 gvs_fixed_sized_maybe_needed_size (GVariantTypeInfo         *type_info,
                                    GVariantSerialisedFiller  gvs_filler,
@@ -301,6 +322,19 @@ gvs_fixed_sized_maybe_serialise (GVariantSerialised        value,
     }
 }
 
+static gsize
+gvs_fixed_sized_maybe_write_to_vectors (GVariantVectors  *vectors,
+                                        GVariantTypeInfo *type_info,
+                                        gsize             size,
+                                        const gpointer   *children,
+                                        gsize             n_children)
+{
+  if (!n_children)
+    return 0;
+
+  return g_variant_callback_write_to_vectors (vectors, children[0], NULL);
+}
+
 static gboolean
 gvs_fixed_sized_maybe_is_normal (GVariantSerialised value)
 {
@@ -362,6 +396,27 @@ gvs_variable_sized_maybe_get_child (GVariantSerialised value,
   return value;
 }
 
+static gboolean
+gvs_variable_sized_maybe_unpack_all (GVariantTypeInfo *type_info,
+                                     const guchar     *end_pointer,
+                                     gsize             end_size,
+                                     gsize             total_size,
+                                     GArray           *unpacked_children)
+{
+  if (total_size)
+    {
+      GVariantUnpacked unpacked;
+
+      unpacked.type_info = g_variant_type_info_ref (g_variant_type_info_element (type_info));
+      unpacked.skip = 0;
+      unpacked.size = total_size - 1;
+
+      g_array_append_val (unpacked_children, unpacked);
+    }
+
+  return TRUE;
+}
+
 static gsize
 gvs_variable_sized_maybe_needed_size (GVariantTypeInfo         *type_info,
                                       GVariantSerialisedFiller  gvs_filler,
@@ -396,6 +451,20 @@ gvs_variable_sized_maybe_serialise (GVariantSerialised        value,
     }
 }
 
+static void
+gvs_variable_sized_maybe_write_to_vectors (GVariantVectors  *vectors,
+                                           GVariantTypeInfo *type_info,
+                                           gsize             size,
+                                           const gpointer   *children,
+                                           gsize             n_children)
+{
+  if (n_children)
+    {
+      g_variant_callback_write_to_vectors (vectors, children[0], NULL);
+      g_variant_vectors_append_copy (vectors, "", 1);
+    }
+}
+
 static gboolean
 gvs_variable_sized_maybe_is_normal (GVariantSerialised value)
 {
@@ -463,6 +532,39 @@ gvs_fixed_sized_array_get_child (GVariantSerialised value,
   return child;
 }
 
+static gboolean
+gvs_fixed_sized_array_unpack_all (GVariantTypeInfo *type_info,
+                                  const guchar     *end_pointer,
+                                  gsize             end_size,
+                                  gsize             total_size,
+                                  GArray           *unpacked_children)
+{
+  GVariantTypeInfo *element;
+  gsize element_fixed_size;
+  gsize i, n;
+
+  element = g_variant_type_info_element (type_info);
+  g_variant_type_info_query (element, NULL, &element_fixed_size);
+
+  if (total_size % element_fixed_size)
+    return FALSE;
+
+  n = total_size / element_fixed_size;
+
+  for (i = 0; i < n; i++)
+    {
+      GVariantUnpacked unpacked;
+
+      unpacked.type_info = g_variant_type_info_ref (element);
+      unpacked.skip = 0;
+      unpacked.size = element_fixed_size;
+
+      g_array_append_val (unpacked_children, unpacked);
+    }
+
+  return TRUE;
+}
+
 static gsize
 gvs_fixed_sized_array_needed_size (GVariantTypeInfo         *type_info,
                                    GVariantSerialisedFiller  gvs_filler,
@@ -497,6 +599,19 @@ gvs_fixed_sized_array_serialise (GVariantSerialised        value,
     }
 }
 
+static void
+gvs_fixed_sized_array_write_to_vectors (GVariantVectors  *vectors,
+                                        GVariantTypeInfo *type_info,
+                                        gsize             size,
+                                        const gpointer   *children,
+                                        gsize             n_children)
+{
+  gsize i;
+
+  for (i = 0; i < n_children; i++)
+    g_variant_callback_write_to_vectors (vectors, children[i], NULL);
+}
+
 static gboolean
 gvs_fixed_sized_array_is_normal (GVariantSerialised value)
 {
@@ -568,8 +683,8 @@ gvs_fixed_sized_array_is_normal (GVariantSerialised value)
 
 /* bytes may be NULL if (size == 0). */
 static inline gsize
-gvs_read_unaligned_le (guchar *bytes,
-                       guint   size)
+gvs_read_unaligned_le (const guchar *bytes,
+                       guint         size)
 {
   union
   {
@@ -705,6 +820,80 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
   return child;
 }
 
+static gboolean
+gvs_variable_sized_array_unpack_all (GVariantTypeInfo *type_info,
+                                     const guchar     *end_pointer,
+                                     gsize             end_size,
+                                     gsize             total_size,
+                                     GArray           *unpacked_children)
+{
+  GVariantTypeInfo *element;
+  guint element_alignment;
+  const guchar *offsets;
+  gsize offset_size;
+  gsize offsets_array_size;
+  gsize prev_end;
+  gsize last_end;
+  gsize i, n;
+
+  if (total_size == 0)
+    return TRUE;
+
+  element = g_variant_type_info_element (type_info);
+  g_variant_type_info_query (element, &element_alignment, NULL);
+
+  offset_size = gvs_get_offset_size (total_size);
+
+  if (offset_size > end_size)
+    return FALSE;
+
+  last_end = gvs_read_unaligned_le (end_pointer - offset_size, offset_size);
+
+  if (last_end > total_size)
+    return 0;
+
+  offsets_array_size = total_size - last_end;
+
+  if (offsets_array_size > end_size)
+    return FALSE;
+
+  offsets = end_pointer - offsets_array_size;
+
+  if (offsets_array_size % offset_size)
+    return FALSE;
+
+  n = offsets_array_size / offset_size;
+
+  if (n == 0)
+    return FALSE;
+
+  prev_end = 0;
+
+  for (i = 0; i < n; i++)
+    {
+      GVariantUnpacked unpacked;
+      gsize start;
+      gsize end;
+
+      start = prev_end + ((-prev_end) & element_alignment);
+      end = gvs_read_unaligned_le (offsets, offset_size);
+      offsets += offset_size;
+
+      if (start < prev_end || end < start || end > last_end)
+       return FALSE;
+
+      unpacked.type_info = g_variant_type_info_ref (element);
+      unpacked.skip = start - prev_end;
+      unpacked.size = end - start;
+
+      g_array_append_val (unpacked_children, unpacked);
+
+      prev_end = end;
+    }
+
+  return TRUE;
+}
+
 static gsize
 gvs_variable_sized_array_needed_size (GVariantTypeInfo         *type_info,
                                       GVariantSerialisedFiller  gvs_filler,
@@ -764,6 +953,38 @@ gvs_variable_sized_array_serialise (GVariantSerialised        value,
     }
 }
 
+static void
+gvs_variable_sized_array_write_to_vectors (GVariantVectors  *vectors,
+                                           GVariantTypeInfo *type_info,
+                                           gsize             size,
+                                           const gpointer   *children,
+                                           gsize             n_children)
+{
+  guint offset_key;
+  guint alignment;
+  gsize offset;
+  gsize i;
+
+  if (n_children == 0)
+    return;
+
+  offset_key = g_variant_vectors_reserve_offsets (vectors, n_children, gvs_get_offset_size (size));
+  g_variant_type_info_query (type_info, &alignment, NULL);
+  offset = 0;
+
+  for (i = 0; i < n_children; i++)
+    {
+      if ((-offset) & alignment)
+        offset += g_variant_vectors_append_pad (vectors, (-offset) & alignment);
+
+      offset += g_variant_callback_write_to_vectors (vectors, children[i], NULL);
+
+      g_variant_vectors_write_to_offsets (vectors, i, offset, offset_key);
+    }
+
+  g_variant_vectors_commit_offsets (vectors, offset_key);
+}
+
 static gboolean
 gvs_variable_sized_array_is_normal (GVariantSerialised value)
 {
@@ -963,6 +1184,86 @@ gvs_tuple_get_child (GVariantSerialised value,
   return child;
 }
 
+static gboolean
+gvs_tuple_unpack_all (GVariantTypeInfo *type_info,
+                      const guchar     *end_pointer,
+                      gsize             end_size,
+                      gsize             total_size,
+                      GArray           *unpacked_children)
+{
+  gsize offset_size;
+  gsize prev_end;
+  gsize i, n;
+
+  n = g_variant_type_info_n_members (type_info);
+
+  /* An empty tuple (n = 0) is always encoded as a single byte, which
+   * means that we should not be attempting to unpack it from multiple
+   * vectors.
+   */
+  if (n == 0)
+    return FALSE;
+
+  offset_size = gvs_get_offset_size (total_size);
+
+  prev_end = 0;
+
+  for (i = 0; i < n; i++)
+    {
+      const GVariantMemberInfo *member_info;
+      GVariantUnpacked unpacked;
+      gsize fixed_size;
+      guint alignment;
+      gsize start;
+      gsize end;
+
+      member_info = g_variant_type_info_member_info (type_info, i);
+      g_variant_type_info_query (member_info->type_info, &alignment, &fixed_size);
+
+      start = prev_end + ((-prev_end) & alignment);
+
+      switch (member_info->ending_type)
+        {
+        case G_VARIANT_MEMBER_ENDING_FIXED:
+          end = start + fixed_size;
+          break;
+
+        case G_VARIANT_MEMBER_ENDING_LAST:
+          end = total_size;
+          break;
+
+        case G_VARIANT_MEMBER_ENDING_OFFSET:
+          if (end_size < offset_size)
+            return FALSE;
+
+          end_pointer -= offset_size;
+          total_size -= offset_size;
+          end_size -= offset_size;
+
+          end = gvs_read_unaligned_le (end_pointer, offset_size);
+          break;
+
+        default:
+          g_assert_not_reached ();
+        }
+
+      if (start < prev_end || end < start || end > total_size)
+        return FALSE;
+
+      unpacked.type_info = g_variant_type_info_ref (member_info->type_info);
+      unpacked.skip = start - prev_end;
+      unpacked.size = end - start;
+
+      g_array_append_val (unpacked_children, unpacked);
+
+      prev_end = end;
+    }
+
+  g_assert (prev_end == total_size);
+
+  return TRUE;
+}
+
 static gsize
 gvs_tuple_needed_size (GVariantTypeInfo         *type_info,
                        GVariantSerialisedFiller  gvs_filler,
@@ -1045,6 +1346,95 @@ gvs_tuple_serialise (GVariantSerialised        value,
     value.data[offset++] = '\0';
 }
 
+
+static void
+gvs_tuple_write_to_vectors (GVariantVectors  *vectors,
+                            GVariantTypeInfo *type_info,
+                            gsize             size,
+                            const gpointer   *children,
+                            gsize             n_children)
+{
+  const GVariantMemberInfo *member_info = NULL;
+  gsize fixed_size;
+  gsize offset;
+  gsize i;
+
+  if (n_children == 0)
+    {
+      g_variant_vectors_append_copy (vectors, "", 1);
+      return;
+    }
+
+  g_variant_type_info_query (type_info, NULL, &fixed_size);
+  offset = 0;
+
+  if (!fixed_size)
+    {
+      gsize n_offsets;
+
+      member_info = g_variant_type_info_member_info (type_info, n_children - 1);
+      n_offsets = member_info->i + 1;
+
+      if (n_offsets)
+        {
+          gsize offset_key = 0;
+
+          offset_key = g_variant_vectors_reserve_offsets (vectors, n_offsets, gvs_get_offset_size (size));
+
+          for (i = 0; i < n_children; i++)
+            {
+              guint alignment;
+
+              member_info = g_variant_type_info_member_info (type_info, i);
+              g_variant_type_info_query (member_info->type_info, &alignment, NULL);
+
+              if ((-offset) & alignment)
+                offset += g_variant_vectors_append_pad (vectors, (-offset) & alignment);
+
+              offset += g_variant_callback_write_to_vectors (vectors, children[i], NULL);
+
+              if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_OFFSET)
+                g_variant_vectors_write_to_offsets (vectors, --n_offsets, offset, offset_key);
+            }
+
+          g_variant_vectors_commit_offsets (vectors, offset_key);
+        }
+      else
+        {
+          for (i = 0; i < n_children; i++)
+            {
+              guint alignment;
+
+              member_info = g_variant_type_info_member_info (type_info, i);
+              g_variant_type_info_query (member_info->type_info, &alignment, NULL);
+
+              if ((-offset) & alignment)
+                offset += g_variant_vectors_append_pad (vectors, (-offset) & alignment);
+
+              offset += g_variant_callback_write_to_vectors (vectors, children[i], NULL);
+            }
+        }
+    }
+  else
+    {
+      for (i = 0; i < n_children; i++)
+        {
+          guint alignment;
+
+          member_info = g_variant_type_info_member_info (type_info, i);
+          g_variant_type_info_query (member_info->type_info, &alignment, NULL);
+
+          if ((-offset) & alignment)
+            offset += g_variant_vectors_append_pad (vectors, (-offset) & alignment);
+
+          offset += g_variant_callback_write_to_vectors (vectors, children[i], NULL);
+        }
+
+      g_assert (fixed_size - offset < 8);
+      g_variant_vectors_append_pad (vectors, fixed_size - offset);
+    }
+}
+
 static gboolean
 gvs_tuple_is_normal (GVariantSerialised value)
 {
@@ -1174,66 +1564,100 @@ gvs_variant_n_children (GVariantSerialised value)
   return 1;
 }
 
-static inline GVariantSerialised
-gvs_variant_get_child (GVariantSerialised value,
-                       gsize              index_)
+static GVariantTypeInfo *
+gvs_variant_find_type (const guchar *end_pointer,
+                       gsize         end_size,
+                       gsize         total_size,
+                       gsize        *child_size,
+                       gsize         depth)
 {
-  GVariantSerialised child = { 0, };
+  gsize i;
 
-  /* NOTE: not O(1) and impossible for it to be... */
-  if (value.size)
-    {
-      /* find '\0' character */
-      for (child.size = value.size - 1; child.size; child.size--)
-        if (value.data[child.size] == '\0')
-          break;
+  for (i = 1; i <= end_size; i++)
+    if (end_pointer[-i] == '\0')
+      {
+        const gchar *type_string = (gchar *) end_pointer - i + 1;
+        const gchar *limit = (gchar *) end_pointer;
+        const gchar *end;
 
-      /* ensure we didn't just hit the start of the string */
-      if (value.data[child.size] == '\0')
-        {
-          const gchar *type_string = (gchar *) &value.data[child.size + 1];
-          const gchar *limit = (gchar *) &value.data[value.size];
-          const gchar *end;
+        /* We may have a type string of length 'i'.  Check for validity. */
+        if (g_variant_type_string_scan (type_string, limit, &end) && end == limit)
+          {
+            const GVariantType *type = (GVariantType *) type_string;
 
-          if (g_variant_type_string_scan (type_string, limit, &end) &&
-              end == limit)
-            {
-              const GVariantType *type = (GVariantType *) type_string;
+            if (g_variant_type_is_definite (type))
+              {
+                GVariantTypeInfo *type_info;
+                gsize fixed_size;
+                gsize child_type_depth;
 
-              if (g_variant_type_is_definite (type))
-                {
-                  gsize fixed_size;
-                  gsize child_type_depth;
+                type_info = g_variant_type_info_get (type);
 
-                  child.type_info = g_variant_type_info_get (type);
-                  child.depth = value.depth + 1;
+                g_variant_type_info_query (type_info, NULL, &fixed_size);
+                child_type_depth = g_variant_type_info_query_depth (type_info);
 
-                  if (child.size != 0)
-                    /* only set to non-%NULL if size > 0 */
-                    child.data = value.data;
+                if ((!fixed_size || fixed_size == total_size - i) &&
+                      depth < G_VARIANT_MAX_RECURSION_DEPTH - child_type_depth)
+                  {
+                    *child_size = total_size - i;
 
-                  g_variant_type_info_query (child.type_info,
-                                             NULL, &fixed_size);
-                  child_type_depth = g_variant_type_info_query_depth (child.type_info);
+                    return type_info;
+                  }
 
-                  if ((!fixed_size || fixed_size == child.size) &&
-                      value.depth < G_VARIANT_MAX_RECURSION_DEPTH - child_type_depth)
-                    return child;
+                g_variant_type_info_unref (type_info);
+              }
+          }
 
-                  g_variant_type_info_unref (child.type_info);
-                }
-            }
-        }
+        /* No sense in trying other lengths if we already failed */
+        break;
+      }
+
+  return NULL;
+}
+
+static inline GVariantSerialised
+gvs_variant_get_child (GVariantSerialised value,
+                       gsize              index_)
+{
+  GVariantSerialised child = { 0, };
+
+  if ((child.type_info = gvs_variant_find_type (value.data + value.size, value.size, value.size, &child.size, value.depth)))
+    {
+      if (child.size != 0)
+        child.data = value.data;
+    }
+  else
+    {
+      child.type_info = g_variant_type_info_get (G_VARIANT_TYPE_UNIT);
+      child.size = 1;
     }
 
-  child.type_info = g_variant_type_info_get (G_VARIANT_TYPE_UNIT);
-  child.data = NULL;
-  child.size = 1;
   child.depth = value.depth + 1;
 
   return child;
 }
 
+static gboolean
+gvs_variant_unpack_all (GVariantTypeInfo *type_info,
+                        const guchar     *end_pointer,
+                        gsize             end_size,
+                        gsize             total_size,
+                        GArray           *unpacked_children)
+{
+  GVariantUnpacked unpacked;
+
+  if ((unpacked.type_info = gvs_variant_find_type (end_pointer, end_size, total_size, &unpacked.size, 0)))
+    {
+      unpacked.skip = 0;
+
+      g_array_append_val (unpacked_children, unpacked);
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
 static inline gsize
 gvs_variant_needed_size (GVariantTypeInfo         *type_info,
                          GVariantSerialisedFiller  gvs_filler,
@@ -1266,6 +1690,23 @@ gvs_variant_serialise (GVariantSerialised        value,
   memcpy (value.data + child.size + 1, type_string, strlen (type_string));
 }
 
+static void
+gvs_variant_write_to_vectors (GVariantVectors  *vectors,
+                              GVariantTypeInfo *type_info,
+                              gsize             size,
+                              const gpointer   *children,
+                              gsize             n_children)
+{
+  GVariantTypeInfo *child_type_info;
+  const gchar *type_string;
+
+  g_variant_callback_write_to_vectors (vectors, children[0], &child_type_info);
+  type_string = g_variant_type_info_get_type_string (child_type_info);
+
+  g_variant_vectors_append_copy (vectors, "", 1);
+  g_variant_vectors_append_copy (vectors, type_string, strlen (type_string));
+}
+
 static inline gboolean
 gvs_variant_is_normal (GVariantSerialised value)
 {
@@ -1478,7 +1919,35 @@ g_variant_serialiser_needed_size (GVariantTypeInfo         *type_info,
 
                   return gvs_/**/,/**/_needed_size (type_info, gvs_filler,
                                                     children, n_children);
+                 )
+  g_assert_not_reached ();
+}
+
+gboolean
+g_variant_serialiser_unpack_all (GVariantTypeInfo *type_info,
+                                 const guchar     *end_pointer,
+                                 gsize             end_size,
+                                 gsize             total_size,
+                                 GArray           *unpacked_children)
+{
+  DISPATCH_CASES (type_info,
+                  return gvs_/**/,/**/_unpack_all (type_info, end_pointer, end_size, total_size, unpacked_children);
+                 )
+
+  /* We are here because type_info is not a container type */
+  return FALSE;
+}
 
+void
+g_variant_serialiser_write_to_vectors (GVariantVectors  *vectors,
+                                       GVariantTypeInfo *type_info,
+                                       gsize             size,
+                                       const gpointer   *children,
+                                       gsize             n_children)
+{
+  DISPATCH_CASES (type_info,
+                  gvs_/**/,/**/_write_to_vectors (vectors, type_info, size, children, n_children);
+                  return;
                  )
   g_assert_not_reached ();
 }
index 859cb7b..e1ff51b 100644 (file)
@@ -22,6 +22,7 @@
 #define __G_VARIANT_SERIALISER_H__
 
 #include "gvarianttypeinfo.h"
+#include "gvariant-vectors.h"
 
 typedef struct
 {
@@ -31,14 +32,27 @@ typedef struct
   gsize             depth;  /* same semantics as GVariant.depth */
 } GVariantSerialised;
 
-/* deserialization */
+typedef struct
+{
+  GVariantTypeInfo *type_info;
+  gsize             skip;
+  gsize             size;
+} GVariantUnpacked;
+
+/* deserialisation */
 GLIB_AVAILABLE_IN_ALL
 gsize                           g_variant_serialised_n_children         (GVariantSerialised        container);
 GLIB_AVAILABLE_IN_ALL
 GVariantSerialised              g_variant_serialised_get_child          (GVariantSerialised        container,
                                                                          gsize                     index);
 
-/* serialization */
+gboolean                        g_variant_serialiser_unpack_all         (GVariantTypeInfo         *type_info,
+                                                                         const guchar             *end_pointer,
+                                                                         gsize                     end_size,
+                                                                         gsize                     total_size,
+                                                                         GArray                   *unpacked_children);
+
+/* serialisation */
 typedef void                  (*GVariantSerialisedFiller)               (GVariantSerialised       *serialised,
                                                                          gpointer                  data);
 
@@ -73,4 +87,14 @@ GLIB_AVAILABLE_IN_ALL
 gboolean                        g_variant_serialiser_is_signature       (gconstpointer             data,
                                                                          gsize                     size);
 
+
+gsize                           g_variant_callback_write_to_vectors     (GVariantVectors          *vectors,
+                                                                         gpointer                  data,
+                                                                         GVariantTypeInfo        **type_info);
+void                            g_variant_serialiser_write_to_vectors   (GVariantVectors          *items,
+                                                                         GVariantTypeInfo         *type_info,
+                                                                         gsize                     size,
+                                                                         const gpointer           *children,
+                                                                         gsize                     n_children);
+
 #endif /* __G_VARIANT_SERIALISER_H__ */
diff --git a/glib/gvariant-vectors.c b/glib/gvariant-vectors.c
new file mode 100644 (file)
index 0000000..5e07786
--- /dev/null
@@ -0,0 +1,248 @@
+#include "config.h"
+
+#include "gvariant-vectors.h"
+#include "gtestutils.h"
+
+static void
+append_zeros (GByteArray *array,
+              guint       n)
+{
+  guchar zeros[8] = "";
+
+  g_byte_array_append (array, zeros, n);
+}
+
+void
+g_variant_vectors_init (GVariantVectors *vectors)
+{
+
+  /* The first 8 bytes of 'extra_bytes' is always 0.  We use this for
+   * inserting padding in between two GBytes records.
+   */
+  vectors->extra_bytes = g_byte_array_new ();
+  append_zeros (vectors->extra_bytes, 8);
+
+  vectors->vectors = g_array_new (FALSE, FALSE, sizeof (GVariantVector));
+
+  vectors->offsets = g_byte_array_new ();
+}
+
+void
+g_variant_vectors_deinit (GVariantVectors *vectors)
+{
+  int i;
+  for (i = 0; i < vectors->vectors->len; i++)
+    {
+      GVariantVector *v = &g_array_index (vectors->vectors, GVariantVector, i);
+      g_bytes_unref (v->gbytes);
+    }
+  g_byte_array_unref (vectors->extra_bytes);
+  g_array_unref (vectors->vectors);
+  g_byte_array_unref (vectors->offsets);
+}
+
+gsize
+g_variant_vectors_append_pad (GVariantVectors *vectors,
+                              gsize            padding)
+{
+  /* If the last vector that we stored was 'pad' or 'copy' then we will
+   * expand it instead of adding a new one.
+   */
+  if (vectors->vectors->len)
+    {
+      GVariantVector *expand_vector = &g_array_index (vectors->vectors, GVariantVector, vectors->vectors->len - 1);
+
+      if (expand_vector->gbytes == NULL)
+        {
+          expand_vector->size += padding;
+
+          /* If the vector points to data, we need to add the padding to
+           * the end of that data.  If it points to the zero bytes at
+           * the start then we can just grow it (but we must ensure that
+           * it doesn't get too large).
+           */
+          if (expand_vector->data.offset)
+            append_zeros (vectors->extra_bytes, padding);
+          else
+            g_assert (expand_vector->size < 8);
+
+          return padding;
+        }
+
+      /* If the last vector was a GBytes then fall through */
+    }
+
+  /* Otherwise, record a new vector pointing to the padding bytes at the
+   * start.
+   */
+  {
+    GVariantVector v;
+
+    v.gbytes = NULL;
+    v.data.offset = 0;
+    v.size = padding;
+
+    g_array_append_val (vectors->vectors, v);
+  }
+
+  return padding;
+}
+
+void
+g_variant_vectors_append_copy (GVariantVectors *vectors,
+                               gconstpointer    data,
+                               gsize            size)
+{
+  /* If the last vector that we stored was 'pad' or 'copy' then we will
+   * expand it instead of adding a new one.
+   */
+  if (vectors->vectors->len)
+    {
+      GVariantVector *expand_vector = &g_array_index (vectors->vectors, GVariantVector, vectors->vectors->len - 1);
+
+      if (expand_vector->gbytes == NULL)
+        {
+          /* If this was a padding vector then we must convert it to
+           * data first.
+           */
+          if (expand_vector->data.offset == 0)
+            {
+              expand_vector->data.offset = vectors->extra_bytes->len;
+              append_zeros (vectors->extra_bytes, expand_vector->size);
+            }
+
+          /* We have a vector pointing to data at the end of the
+           * extra_bytes array, so just append there and grow the
+           * vector.
+           */
+          g_byte_array_append (vectors->extra_bytes, data, size);
+          expand_vector->size += size;
+          return;
+        }
+
+      /* If the last vector was a GBytes then fall through */
+    }
+
+  /* Otherwise, copy the data and record a new vector. */
+  {
+    GVariantVector v;
+
+    v.gbytes = NULL;
+    v.data.offset = vectors->extra_bytes->len;
+    v.size = size;
+
+    g_byte_array_append (vectors->extra_bytes, data, size);
+    g_array_append_val (vectors->vectors, v);
+  }
+}
+
+void
+g_variant_vectors_append_gbytes (GVariantVectors *vectors,
+                                 GBytes          *gbytes,
+                                 gconstpointer    data,
+                                 gsize            size)
+{
+  GVariantVector v;
+
+  /* Some very rough profiling has indicated that the trade-off for
+   * overhead on the atomic operations involved in the ref/unref on the
+   * GBytes is larger than the cost of the copy at ~128 bytes.
+   */
+  if (size < 128)
+    {
+      g_variant_vectors_append_copy (vectors, data, size);
+      return;
+    }
+
+  v.gbytes = g_bytes_ref (gbytes);
+  v.data.pointer = data;
+  v.size = size;
+
+  g_array_append_val (vectors->vectors, v);
+}
+
+typedef void (* WriteFunction) (gpointer base, gsize offset, gsize value);
+static void write_1 (gpointer base, gsize offset, gsize value) { ((guint8 *) base)[offset] = value; }
+static void write_2 (gpointer base, gsize offset, gsize value) { ((guint16 *) base)[offset] = GUINT16_TO_LE (value); }
+static void write_4 (gpointer base, gsize offset, gsize value) { ((guint32 *) base)[offset] = GUINT32_TO_LE (value); }
+static void write_8 (gpointer base, gsize offset, gsize value) { ((guint64 *) base)[offset] = GUINT64_TO_LE (value); }
+
+typedef struct
+{
+  gsize         size;
+  WriteFunction func;
+} OffsetsHeader;
+
+gsize
+g_variant_vectors_reserve_offsets (GVariantVectors *vectors,
+                                   guint            n_offsets,
+                                   guint            offset_size)
+{
+  OffsetsHeader *header;
+  gsize total_size;
+  gsize add_size;
+  guint key;
+
+  total_size = n_offsets * offset_size;
+
+  /* Add room for the metadata and round up to multiple of 8 */
+  add_size = (sizeof (OffsetsHeader) + total_size + 7) & ~7ull;
+  key = vectors->offsets->len;
+  g_byte_array_set_size (vectors->offsets, key + add_size);
+  header = (OffsetsHeader *) (vectors->offsets->data + key);
+  key += sizeof (OffsetsHeader);
+  header->size = total_size;
+
+  switch (offset_size)
+    {
+    case 1:
+      header->func = write_1;
+      break;
+
+    case 2:
+      header->func = write_2;
+      break;
+
+    case 4:
+      header->func = write_4;
+      break;
+
+    case 8:
+      header->func = write_8;
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+
+  return key;
+}
+
+void
+g_variant_vectors_write_to_offsets (GVariantVectors *vectors,
+                                    gsize            offset,
+                                    gsize            value,
+                                    gsize            key)
+{
+  OffsetsHeader *header;
+  guchar *offsets;
+
+  offsets = vectors->offsets->data + key;
+  header = (OffsetsHeader *) (offsets - sizeof (OffsetsHeader));
+
+  header->func (offsets, offset, value);
+}
+
+void
+g_variant_vectors_commit_offsets (GVariantVectors *vectors,
+                                  gsize            key)
+{
+  OffsetsHeader *header;
+  guchar *offsets;
+
+  offsets = vectors->offsets->data + key;
+  header = (OffsetsHeader *) (offsets - sizeof (OffsetsHeader));
+
+  g_variant_vectors_append_copy (vectors, offsets, header->size);
+  g_byte_array_set_size (vectors->offsets, key - sizeof (OffsetsHeader));
+}
diff --git a/glib/gvariant-vectors.h b/glib/gvariant-vectors.h
new file mode 100644 (file)
index 0000000..05e2258
--- /dev/null
@@ -0,0 +1,63 @@
+
+#ifndef __G_VARIANT_VECTORS_H__
+#define __G_VARIANT_VECTORS_H__
+
+#include <glib/garray.h>
+
+typedef struct
+{
+  GByteArray *extra_bytes;
+  GArray     *vectors;
+  GByteArray *offsets;
+} GVariantVectors;
+
+
+/* If ->bytes is NULL then offset/size point inside of extra_bytes,
+ * otherwise pointer/size point to memory owned by the GBytes.
+ */
+typedef struct
+{
+  GBytes *gbytes;
+  union {
+    const guchar *pointer;
+    gsize         offset;
+  } data;
+  gsize    size;
+} GVariantVector;
+
+void                    g_variant_vectors_init                          (GVariantVectors *vectors);
+
+
+void                    g_variant_vectors_deinit                        (GVariantVectors *vectors);
+
+
+gsize                   g_variant_vectors_append_pad                    (GVariantVectors *vectors,
+                                                                         gsize            padding);
+
+
+void                    g_variant_vectors_append_copy                   (GVariantVectors *vectors,
+                                                                         gconstpointer    data,
+                                                                         gsize            size);
+
+
+void                    g_variant_vectors_append_gbytes                 (GVariantVectors *vectors,
+                                                                         GBytes          *gbytes,
+                                                                         gconstpointer    data,
+                                                                         gsize            size);
+
+
+gsize                   g_variant_vectors_reserve_offsets               (GVariantVectors *vectors,
+                                                                         guint            n_offsets,
+                                                                         guint            offset_size);
+
+
+void                    g_variant_vectors_write_to_offsets              (GVariantVectors *vectors,
+                                                                         gsize            offset,
+                                                                         gsize            value,
+                                                                         gsize            offset_key);
+
+
+void                    g_variant_vectors_commit_offsets                (GVariantVectors *vectors,
+                                                                         gsize            offset_key);
+
+#endif /* __G_GVARIANT_VECTORS_H__ */
index a9bb99c..58457e1 100644 (file)
@@ -69,7 +69,7 @@
  *
  * The range of possible values is determined by the type.
  *
- * The type system used by #GVariant is #GVariantType. 
+ * The type system used by #GVariant is #GVariantType.
  *
  * #GVariant instances always have a type and a value (which are given
  * at construction time).  The type and value of a #GVariant instance
  * endianness, or of the length or type of the top-level variant.
  *
  * The amount of memory required to store a boolean is 1 byte. 16,
- * 32 and 64 bit integers and double precision floating point numbers
+ * 32 and 64 bit integers and floating point numbers
  * use their "natural" size.  Strings (including object path and
  * signature strings) are stored with a nul terminator, and as such
  * use the length of the string plus 1 byte.
  *
  * This means that in total, for our "a{sv}" example, 91 bytes of
  * type information would be allocated.
- * 
+ *
  * The type information cache, additionally, uses a #GHashTable to
  * store and look up the cached items and stores a pointer to this
  * hash table in static storage.  The hash table is freed when there
@@ -319,14 +319,10 @@ g_variant_new_from_trusted (const GVariantType *type,
                             gconstpointer       data,
                             gsize               size)
 {
-  GVariant *value;
-  GBytes *bytes;
-
-  bytes = g_bytes_new (data, size);
-  value = g_variant_new_from_bytes (type, bytes, TRUE);
-  g_bytes_unref (bytes);
+  gpointer mydata = g_memdup (data, size);
 
-  return value;
+  return g_variant_new_serialised (g_variant_type_info_get (type),
+                                   g_bytes_new_take (mydata, size), mydata, size, TRUE);
 }
 
 /**
@@ -373,7 +369,7 @@ g_variant_get_boolean (GVariant *value)
 }
 
 /* the constructors and accessors for byte, int{16,32,64}, handles and
- * doubles all look pretty much exactly the same, so we reduce
+ * floats all look pretty much exactly the same, so we reduce
  * copy/pasting here.
  */
 #define NUMERIC_TYPE(TYPE, type, ctype) \
@@ -598,6 +594,31 @@ NUMERIC_TYPE (UINT64, uint64, guint64)
 NUMERIC_TYPE (HANDLE, handle, gint32)
 
 /**
+ * g_variant_new_float:
+ * @value: a #gfloat floating point value
+ *
+ * Creates a new float #GVariant instance.
+ *
+ * Returns: (transfer none): a floating reference to a new float #GVariant instance
+ *
+ * Since: 2.44
+ **/
+/**
+ * g_variant_get_float:
+ * @value: a float #GVariant instance
+ *
+ * Returns the single precision floating point value of @value.
+ *
+ * It is an error to call this function with a @value of any type
+ * other than %G_VARIANT_TYPE_FLOAT.
+ *
+ * Returns: a #gfloat
+ *
+ * Since: 2.44
+ **/
+NUMERIC_TYPE (FLOAT, float, gfloat)
+
+/**
  * g_variant_new_double:
  * @value: a #gdouble floating point value
  *
@@ -647,8 +668,8 @@ GVariant *
 g_variant_new_maybe (const GVariantType *child_type,
                      GVariant           *child)
 {
+  GVariantTypeInfo *type_info;
   GVariantType *maybe_type;
-  GVariant *value;
 
   g_return_val_if_fail (child_type == NULL || g_variant_type_is_definite
                         (child_type), 0);
@@ -661,6 +682,8 @@ g_variant_new_maybe (const GVariantType *child_type,
     child_type = g_variant_get_type (child);
 
   maybe_type = g_variant_type_new_maybe (child_type);
+  type_info = g_variant_type_info_get (maybe_type);
+  g_variant_type_free (maybe_type);
 
   if (child != NULL)
     {
@@ -671,14 +694,10 @@ g_variant_new_maybe (const GVariantType *child_type,
       children[0] = g_variant_ref_sink (child);
       trusted = g_variant_is_trusted (children[0]);
 
-      value = g_variant_new_from_children (maybe_type, children, 1, trusted);
+      return g_variant_new_from_children (type_info, children, 1, trusted);
     }
   else
-    value = g_variant_new_from_children (maybe_type, NULL, 0, TRUE);
-
-  g_variant_type_free (maybe_type);
-
-  return value;
+    return g_variant_new_from_children (type_info, NULL, 0, TRUE);
 }
 
 /**
@@ -724,7 +743,7 @@ g_variant_new_variant (GVariant *value)
 
   g_variant_ref_sink (value);
 
-  return g_variant_new_from_children (G_VARIANT_TYPE_VARIANT,
+  return g_variant_new_from_children (g_variant_type_info_get (G_VARIANT_TYPE_VARIANT),
                                       g_memdup2 (&value, sizeof value),
                                       1, g_variant_is_trusted (value));
 }
@@ -780,10 +799,10 @@ g_variant_new_array (const GVariantType *child_type,
                      GVariant * const   *children,
                      gsize               n_children)
 {
+  GVariantTypeInfo *type_info;
   GVariantType *array_type;
   GVariant **my_children;
   gboolean trusted;
-  GVariant *value;
   gsize i;
 
   g_return_val_if_fail (n_children > 0 || child_type != NULL, NULL);
@@ -797,6 +816,8 @@ g_variant_new_array (const GVariantType *child_type,
   if (child_type == NULL)
     child_type = g_variant_get_type (children[0]);
   array_type = g_variant_type_new_array (child_type);
+  type_info = g_variant_type_info_get (array_type);
+  g_variant_type_free (array_type);
 
   for (i = 0; i < n_children; i++)
     {
@@ -805,11 +826,7 @@ g_variant_new_array (const GVariantType *child_type,
       trusted &= g_variant_is_trusted (children[i]);
     }
 
-  value = g_variant_new_from_children (array_type, my_children,
-                                       n_children, trusted);
-  g_variant_type_free (array_type);
-
-  return value;
+  return g_variant_new_from_children (type_info, my_children, n_children, trusted);
 }
 
 /*< private >
@@ -860,10 +877,10 @@ GVariant *
 g_variant_new_tuple (GVariant * const *children,
                      gsize             n_children)
 {
+  GVariantTypeInfo *type_info;
   GVariantType *tuple_type;
   GVariant **my_children;
   gboolean trusted;
-  GVariant *value;
   gsize i;
 
   g_return_val_if_fail (n_children == 0 || children != NULL, NULL);
@@ -878,11 +895,10 @@ g_variant_new_tuple (GVariant * const *children,
     }
 
   tuple_type = g_variant_make_tuple_type (children, n_children);
-  value = g_variant_new_from_children (tuple_type, my_children,
-                                       n_children, trusted);
+  type_info = g_variant_type_info_get (tuple_type);
   g_variant_type_free (tuple_type);
 
-  return value;
+  return g_variant_new_from_children (type_info, my_children, n_children, trusted);
 }
 
 /*< private >
@@ -920,6 +936,7 @@ GVariant *
 g_variant_new_dict_entry (GVariant *key,
                           GVariant *value)
 {
+  GVariantTypeInfo *type_info;
   GVariantType *dict_type;
   GVariant **children;
   gboolean trusted;
@@ -933,10 +950,10 @@ g_variant_new_dict_entry (GVariant *key,
   trusted = g_variant_is_trusted (key) && g_variant_is_trusted (value);
 
   dict_type = g_variant_make_dict_entry_type (key, value);
-  value = g_variant_new_from_children (dict_type, children, 2, trusted);
+  type_info = g_variant_type_info_get (dict_type);
   g_variant_type_free (dict_type);
 
-  return value;
+  return g_variant_new_from_children (type_info, children, 2, trusted);
 }
 
 /**
@@ -1112,6 +1129,7 @@ g_variant_lookup_value (GVariant           *dictionary,
  * - %G_VARIANT_TYPE_BOOLEAN: #guchar (not #gboolean!)
  * - %G_VARIANT_TYPE_BYTE: #guint8
  * - %G_VARIANT_TYPE_HANDLE: #guint32
+ * - %G_VARIANT_TYPE_FLOAT: #gfloat
  * - %G_VARIANT_TYPE_DOUBLE: #gdouble
  *
  * For example, if calling this function for an array of 32-bit integers,
@@ -1568,7 +1586,7 @@ g_variant_new_strv (const gchar * const *strv,
   for (i = 0; i < length_unsigned; i++)
     strings[i] = g_variant_ref_sink (g_variant_new_string (strv[i]));
 
-  return g_variant_new_from_children (G_VARIANT_TYPE_STRING_ARRAY,
+  return g_variant_new_from_children (g_variant_type_info_get (G_VARIANT_TYPE_STRING_ARRAY),
                                       strings, length_unsigned, TRUE);
 }
 
@@ -1705,7 +1723,7 @@ g_variant_new_objv (const gchar * const *strv,
   for (i = 0; i < length_unsigned; i++)
     strings[i] = g_variant_ref_sink (g_variant_new_object_path (strv[i]));
 
-  return g_variant_new_from_children (G_VARIANT_TYPE_OBJECT_PATH_ARRAY,
+  return g_variant_new_from_children (g_variant_type_info_get (G_VARIANT_TYPE_OBJECT_PATH_ARRAY),
                                       strings, length_unsigned, TRUE);
 }
 
@@ -1946,7 +1964,7 @@ g_variant_new_bytestring_array (const gchar * const *strv,
   for (i = 0; i < length_unsigned; i++)
     strings[i] = g_variant_ref_sink (g_variant_new_bytestring (strv[i]));
 
-  return g_variant_new_from_children (G_VARIANT_TYPE_BYTESTRING_ARRAY,
+  return g_variant_new_from_children (g_variant_type_info_get (G_VARIANT_TYPE_BYTESTRING_ARRAY),
                                       strings, length_unsigned, TRUE);
 }
 
@@ -2156,10 +2174,12 @@ g_variant_is_container (GVariant *value)
  * @G_VARIANT_CLASS_INT64: The #GVariant is a signed 64 bit integer.
  * @G_VARIANT_CLASS_UINT64: The #GVariant is an unsigned 64 bit integer.
  * @G_VARIANT_CLASS_HANDLE: The #GVariant is a file handle index.
- * @G_VARIANT_CLASS_DOUBLE: The #GVariant is a double precision floating 
+ * @G_VARIANT_CLASS_FLOAT: The #GVariant is a single precision floating
+ *                         point value.
+ * @G_VARIANT_CLASS_DOUBLE: The #GVariant is a double precision floating
  *                          point value.
  * @G_VARIANT_CLASS_STRING: The #GVariant is a normal string.
- * @G_VARIANT_CLASS_OBJECT_PATH: The #GVariant is a D-Bus object path 
+ * @G_VARIANT_CLASS_OBJECT_PATH: The #GVariant is a D-Bus object path
  *                               string.
  * @G_VARIANT_CLASS_SIGNATURE: The #GVariant is a D-Bus signature string.
  * @G_VARIANT_CLASS_VARIANT: The #GVariant is a variant.
@@ -2561,6 +2581,32 @@ g_variant_print_string (GVariant *value,
                               g_variant_get_uint64 (value));
       break;
 
+    case G_VARIANT_CLASS_FLOAT:
+      {
+        gchar buffer[100];
+        gint i;
+
+        g_ascii_dtostr (buffer, sizeof buffer, g_variant_get_float (value));
+
+        for (i = 0; buffer[i]; i++)
+          if (buffer[i] == '.' || buffer[i] == 'e' ||
+              buffer[i] == 'n' || buffer[i] == 'N')
+            break;
+
+        /* if there is no '.' or 'e' in the float then add one */
+        if (buffer[i] == '\0')
+          {
+            buffer[i++] = '.';
+            buffer[i++] = '0';
+            buffer[i++] = '\0';
+          }
+
+        if (type_annotate)
+          g_string_append (string, "float ");
+        g_string_append (string, buffer);
+      }
+      break;
+
     case G_VARIANT_CLASS_DOUBLE:
       {
         gchar buffer[100];
@@ -2685,6 +2731,7 @@ g_variant_hash (gconstpointer value_)
     case G_VARIANT_CLASS_INT32:
     case G_VARIANT_CLASS_UINT32:
     case G_VARIANT_CLASS_HANDLE:
+    case G_VARIANT_CLASS_FLOAT:
       {
         const guint *ptr;
 
@@ -2807,7 +2854,7 @@ g_variant_equal (gconstpointer one,
  * two values that have types that are not exactly equal.  For example,
  * you cannot compare a 32-bit signed integer with a 32-bit unsigned
  * integer.  Also note that this function is not particularly
- * well-behaved when it comes to comparison of doubles; in particular,
+ * well-behaved when it comes to comparison of floats; in particular,
  * the handling of incomparable values (ie: NaN) is undefined.
  *
  * If you only require an equality comparison, g_variant_equal() is more
@@ -2878,6 +2925,14 @@ g_variant_compare (gconstpointer one,
         return (a_val == b_val) ? 0 : (a_val > b_val) ? 1 : -1;
       }
 
+    case G_VARIANT_CLASS_FLOAT:
+      {
+        gfloat a_val = g_variant_get_float (a);
+        gfloat b_val = g_variant_get_float (b);
+
+        return (a_val == b_val) ? 0 : (a_val > b_val) ? 1 : -1;
+      }
+
     case G_VARIANT_CLASS_DOUBLE:
       {
         gdouble a_val = g_variant_get_double (a);
@@ -3081,7 +3136,7 @@ g_variant_iter_free (GVariantIter *iter)
  * you no longer need it.
  *
  * Here is an example for iterating with g_variant_iter_next_value():
- * |[<!-- language="C" --> 
+ * |[<!-- language="C" -->
  *   // recursively iterate a container
  *   void
  *   iterate_container_recursive (GVariant *container)
@@ -3715,7 +3770,7 @@ g_variant_builder_end (GVariantBuilder *builder)
   else
     g_assert_not_reached ();
 
-  value = g_variant_new_from_children (my_type,
+  value = g_variant_new_from_children (g_variant_type_info_get (my_type),
                                        g_renew (GVariant *,
                                                 GVSB(builder)->children,
                                                 GVSB(builder)->offset),
@@ -4296,8 +4351,8 @@ g_variant_format_string_scan (const gchar  *string,
   switch (next_char())
     {
     case 'b': case 'y': case 'n': case 'q': case 'i': case 'u':
-    case 'x': case 't': case 'h': case 'd': case 's': case 'o':
-    case 'g': case 'v': case '*': case '?': case 'r':
+    case 'x': case 't': case 'h': case 'f': case 'd': case 's':
+    case 'o': case 'g': case 'v': case '*': case '?': case 'r':
       break;
 
     case 'm':
@@ -4974,6 +5029,7 @@ g_variant_valist_skip_leaf (const gchar **str,
       va_arg (*app, guint64);
       return;
 
+    case 'f':
     case 'd':
       va_arg (*app, gdouble);
       return;
@@ -5019,6 +5075,9 @@ g_variant_valist_new_leaf (const gchar **str,
     case 'h':
       return g_variant_new_handle (va_arg (*app, gint));
 
+    case 'f':
+      return g_variant_new_float (va_arg (*app, gdouble));
+
     case 'd':
       return g_variant_new_double (va_arg (*app, gdouble));
 
@@ -5029,6 +5088,7 @@ g_variant_valist_new_leaf (const gchar **str,
 
 /* The code below assumes this */
 G_STATIC_ASSERT (sizeof (gboolean) == sizeof (guint32));
+G_STATIC_ASSERT (sizeof (gfloat) == sizeof (guint32));
 G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
 
 static void
@@ -5102,6 +5162,10 @@ g_variant_valist_get_leaf (const gchar **str,
           *(gint32 *) ptr = g_variant_get_handle (value);
           return;
 
+        case 'f':
+          *(gfloat *) ptr = g_variant_get_float (value);
+          return;
+
         case 'd':
           *(gdouble *) ptr = g_variant_get_double (value);
           return;
@@ -5124,6 +5188,7 @@ g_variant_valist_get_leaf (const gchar **str,
         case 'u':
         case 'h':
         case 'b':
+        case 'f':
           *(guint32 *) ptr = 0;
           return;
 
@@ -5524,7 +5589,7 @@ g_variant_get_va (GVariant     *value,
  *
  * This function might be used as follows:
  *
- * |[<!-- language="C" --> 
+ * |[<!-- language="C" -->
  * GVariant *
  * make_pointless_dictionary (void)
  * {
@@ -5620,7 +5685,7 @@ g_variant_get_child (GVariant    *value,
  * the unpacking process.
  *
  * Here is an example for memory management with g_variant_iter_next():
- * |[<!-- language="C" --> 
+ * |[<!-- language="C" -->
  *   // Iterates a dictionary of type 'a{sv}'
  *   void
  *   iterate_dictionary (GVariant *dictionary)
@@ -5712,7 +5777,7 @@ g_variant_iter_next (GVariantIter *iter,
  * g_variant_get(). Failure to do so will cause a memory leak.
  *
  * Here is an example for memory management with g_variant_iter_loop():
- * |[<!-- language="C" --> 
+ * |[<!-- language="C" -->
  *   // Iterates a dictionary of type 'a{sv}'
  *   void
  *   iterate_dictionary (GVariant *dictionary)
@@ -5848,6 +5913,9 @@ g_variant_deep_copy (GVariant *value)
     case G_VARIANT_CLASS_HANDLE:
       return g_variant_new_handle (g_variant_get_handle (value));
 
+    case G_VARIANT_CLASS_FLOAT:
+      return g_variant_new_float (g_variant_get_float (value));
+
     case G_VARIANT_CLASS_DOUBLE:
       return g_variant_new_double (g_variant_get_double (value));
 
@@ -5917,8 +5985,7 @@ g_variant_get_normal_form (GVariant *value)
  * Performs a byteswapping operation on the contents of @value.  The
  * result is that all multi-byte numeric data contained in @value is
  * byteswapped.  That includes 16, 32, and 64bit signed and unsigned
- * integers as well as file handles and double precision floating point
- * values.
+ * integers as well as file handles and floating point values.
  *
  * This function is an identity mapping on any value that does not
  * contain multi-byte numeric data.  That include strings, booleans,
@@ -6020,21 +6087,99 @@ g_variant_new_from_data (const GVariantType *type,
                          GDestroyNotify      notify,
                          gpointer            user_data)
 {
-  GVariant *value;
   GBytes *bytes;
 
   g_return_val_if_fail (g_variant_type_is_definite (type), NULL);
   g_return_val_if_fail (data != NULL || size == 0, NULL);
 
+  if (size == 0)
+    {
+      if (notify)
+        {
+          (* notify) (user_data);
+          notify = NULL;
+        }
+
+      data = NULL;
+    }
+
   if (notify)
     bytes = g_bytes_new_with_free_func (data, size, notify, user_data);
   else
     bytes = g_bytes_new_static (data, size);
 
-  value = g_variant_new_from_bytes (type, bytes, trusted);
-  g_bytes_unref (bytes);
+  return g_variant_new_serialised (g_variant_type_info_get (type), bytes, data, size, trusted);
+}
 
-  return value;
+/**
+ * g_variant_new_from_bytes:
+ * @type: a #GVariantType
+ * @bytes: a #GBytes
+ * @trusted: if the contents of @bytes are trusted
+ *
+ * Constructs a new serialised-mode #GVariant instance.  This is the
+ * inner interface for creation of new serialised values that gets
+ * called from various functions in gvariant.c.
+ *
+ * A reference is taken on @bytes.
+ *
+ * Returns: (transfer none): a new #GVariant with a floating reference
+ *
+ * Since: 2.36
+ */
+GVariant *
+g_variant_new_from_bytes (const GVariantType *type,
+                          GBytes             *bytes,
+                          gboolean            trusted)
+{
+  gconstpointer data;
+  gsize size;
+
+  g_return_val_if_fail (g_variant_type_is_definite (type), NULL);
+
+  data = g_bytes_get_data (bytes, &size);
+
+  return g_variant_new_serialised (g_variant_type_info_get (type), g_bytes_ref (bytes), data, size, trusted);
+}
+
+/**
+ * g_variant_get_data_as_bytes:
+ * @value: a #GVariant
+ *
+ * Returns a pointer to the serialised form of a #GVariant instance.
+ * The semantics of this function are exactly the same as
+ * g_variant_get_data(), except that the returned #GBytes holds
+ * a reference to the variant data.
+ *
+ * Returns: (transfer full): A new #GBytes representing the variant data
+ *
+ * Since: 2.36
+ */
+GBytes *
+g_variant_get_data_as_bytes (GVariant *value)
+{
+  gconstpointer data;
+  GBytes *bytes;
+  gsize size;
+  gconstpointer bytes_data;
+  gsize bytes_size;
+
+  data = g_variant_get_serialised (value, &bytes, &size);
+  bytes_data = g_bytes_get_data (bytes, &bytes_size);
+
+  /* Try to reuse the GBytes held internally by GVariant, if it exists
+   * and is covering exactly the correct range.
+   */
+  if (data == bytes_data && size == bytes_size)
+    return g_bytes_ref (bytes);
+
+  /* See g_variant_get_data() about why it can return NULL... */
+  else if (data == NULL)
+    return g_bytes_new_take (g_malloc0 (size), size);
+
+  /* Otherwise, make a new GBytes with reference to the old. */
+  else
+    return g_bytes_new_with_free_func (data, size, (GDestroyNotify) g_bytes_unref, g_bytes_ref (bytes));
 }
 
 /* Epilogue {{{1 */
index 11c74d5..000171a 100644 (file)
@@ -44,6 +44,7 @@ typedef enum
   G_VARIANT_CLASS_INT64         = 'x',
   G_VARIANT_CLASS_UINT64        = 't',
   G_VARIANT_CLASS_HANDLE        = 'h',
+  G_VARIANT_CLASS_FLOAT         = 'f',
   G_VARIANT_CLASS_DOUBLE        = 'd',
   G_VARIANT_CLASS_STRING        = 's',
   G_VARIANT_CLASS_OBJECT_PATH   = 'o',
@@ -95,6 +96,8 @@ GLIB_AVAILABLE_IN_ALL
 GVariant *                      g_variant_new_uint64                    (guint64               value);
 GLIB_AVAILABLE_IN_ALL
 GVariant *                      g_variant_new_handle                    (gint32                value);
+GLIB_AVAILABLE_IN_2_44
+GVariant *                      g_variant_new_float                     (gfloat                value);
 GLIB_AVAILABLE_IN_ALL
 GVariant *                      g_variant_new_double                    (gdouble               value);
 GLIB_AVAILABLE_IN_ALL
@@ -148,6 +151,8 @@ GLIB_AVAILABLE_IN_ALL
 guint64                         g_variant_get_uint64                    (GVariant             *value);
 GLIB_AVAILABLE_IN_ALL
 gint32                          g_variant_get_handle                    (GVariant             *value);
+GLIB_AVAILABLE_IN_2_44
+gfloat                          g_variant_get_float                     (GVariant             *value);
 GLIB_AVAILABLE_IN_ALL
 gdouble                         g_variant_get_double                    (GVariant             *value);
 GLIB_AVAILABLE_IN_ALL
index cc97235..6b8ca45 100644 (file)
  * A basic type string describes a basic type (as per
  * g_variant_type_is_basic()) and is always a single character in length.
  * The valid basic type strings are "b", "y", "n", "q", "i", "u", "x", "t",
- * "h", "d", "s", "o", "g" and "?".
+ * "h", "f", "d", "s", "o", "g" and "?".
  *
  * The above definition is recursive to arbitrary depth. "aaaaai" and
  * "(ui(nq((y)))s)" are both valid type strings, as is
  * - `h`: the type string of %G_VARIANT_TYPE_HANDLE; a signed 32 bit value
  *   that, by convention, is used as an index into an array of file
  *   descriptors that are sent alongside a D-Bus message.
+ * - `f`: the type string of %G_VARIANT_TYPE_FLOAT; a single precision
+ *   floating point value.
  * - `d`: the type string of %G_VARIANT_TYPE_DOUBLE; a double precision
  *   floating point value.
  * - `s`: the type string of %G_VARIANT_TYPE_STRING; a string.
@@ -232,7 +234,7 @@ variant_type_string_scan_internal (const gchar  *string,
     case '{':
       if (depth_limit == 0 ||
           string == limit || *string == '\0' ||                                  /* { */
-          !strchr ("bynqihuxtdsog?", *string++) ||                               /* key */
+          !strchr ("bynqihuxtfdsog?", *string++) ||                               /* key */
           !variant_type_string_scan_internal (string, limit, &string,
                                               &child_depth, depth_limit - 1) ||  /* value */
           string == limit || *string++ != '}')                                   /* } */
@@ -252,7 +254,7 @@ variant_type_string_scan_internal (const gchar  *string,
 
     case 'b': case 'y': case 'n': case 'q': case 'i': case 'u':
     case 'x': case 't': case 'd': case 's': case 'o': case 'g':
-    case 'v': case 'r': case '*': case '?': case 'h':
+    case 'v': case 'r': case '*': case '?': case 'h': case 'f':
       max_depth = MAX (max_depth, 1);
       break;
 
@@ -598,8 +600,8 @@ g_variant_type_is_container (const GVariantType *type)
  *
  * Determines if the given @type is a basic type.
  *
- * Basic types are booleans, bytes, integers, doubles, strings, object
- * paths and signatures.
+ * Basic types are booleans, bytes, integers, floats, doubles, strings,
+ * object paths and signatures.
  *
  * Only a basic type may be used as the key of a dictionary entry.
  *
@@ -629,6 +631,7 @@ g_variant_type_is_basic (const GVariantType *type)
     case 'u':
     case 't':
     case 'x':
+    case 'f':
     case 'd':
     case 's':
     case 'o':
index fdc3641..974d7f1 100644 (file)
@@ -104,6 +104,15 @@ typedef struct _GVariantType GVariantType;
 #define G_VARIANT_TYPE_UINT64               ((const GVariantType *) "t")
 
 /**
+ * G_VARIANT_TYPE_FLOAT:
+ *
+ * The type of a single precision IEEE754 floating point number.  You
+ * can store a number as large as 3.40e38 in these (plus and minus) but
+ * there are some gaps on the way.
+ **/
+#define G_VARIANT_TYPE_FLOAT                ((const GVariantType *) "f")
+
+/**
  * G_VARIANT_TYPE_DOUBLE:
  *
  * The type of a double precision IEEE754 floating point number.
index 6fdde8f..0a73a53 100644 (file)
@@ -116,7 +116,7 @@ static const GVariantTypeInfo g_variant_type_info_basic_table[24] = {
   /* 'c' */ { not_a_type },
   /* 'd' */ { fixed_aligned(8) },   /* double */
   /* 'e' */ { not_a_type },
-  /* 'f' */ { not_a_type },
+  /* 'f' */ { fixed_aligned(4) },   /* float */
   /* 'g' */ { unaligned        },   /* signature string */
   /* 'h' */ { fixed_aligned(4) },   /* file handle (int32) */
   /* 'i' */ { fixed_aligned(4) },   /* int32 */
@@ -148,7 +148,7 @@ static const GVariantTypeInfo g_variant_type_info_basic_table[24] = {
  * GVariantTypeInfo itself, we save a bunch of relocations.
  */
 static const char g_variant_type_info_basic_chars[24][2] = {
-  "b", " ", "d", " ", " ", "g", "h", "i", " ", " ", " ", " ",
+  "b", " ", "d", " ", "f", "g", "h", "i", " ", " ", " ", " ",
   "n", "o", " ", "q", " ", "s", "t", "u", "v", " ", "x", "y"
 };
 
diff --git a/glib/libcharset/.gitignore b/glib/libcharset/.gitignore
deleted file mode 100644 (file)
index 0cef440..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-charset.alias
-ref-add.sed
-ref-del.sed
index 93600b2..da9d007 100644 (file)
@@ -310,6 +310,7 @@ glib_sources = files(
   'gvariant-core.c',
   'gvariant-parser.c',
   'gvariant-serialiser.c',
+  'gvariant-vectors.c',
   'gvarianttypeinfo.c',
   'gvarianttype.c',
   'gversion.c',
diff --git a/glib/tests/.gitignore b/glib/tests/.gitignore
deleted file mode 100644 (file)
index 9e4c147..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-1bit-emufutex
-1bit-mutex
-642026
-642026-ec
-array-test
-asyncqueue
-atomic
-autoptr
-base64
-bitlock
-bookmarkfile
-bytes
-cache
-checksum
-collate
-cond
-convert
-dataset
-date
-dir
-environment
-error
-fileutils
-gdatetime
-guuid
-gvariant
-gwakeup
-gwakeup-fallback
-hash
-hmac
-hook
-hostutils
-include
-keyfile
-list
-logging
-mainloop
-malloc
-mappedfile
-markup
-markup-collect
-markup-escape
-markup-parse
-markup-subparser
-mem-overflow
-mutex
-node
-once
-option-argv0
-option-context
-overflow
-overflow-fallback
-pattern
-private
-protocol
-queue
-rand
-rec-mutex
-regex
-rwlock
-scannerapi
-search-utils
-sequence
-shell
-slice
-slist
-sort
-spawn-multithreaded
-spawn-singlethread
-strfuncs
-string
-testing
-test-printf
-test-spawn-echo
-thread
-timeout
-timer
-tmpsample.xml
-tree
-unicode
-unix
-unix-multithreaded
-unix-nothreads
-uri
-utf8-misc
-utf8-performance
-utf8-pointer
-utf8-validate
-utils
index 8178bc2..561cc23 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
+#include <unistd.h>
 #include "glib.h"
+#include "glib-unix.h"
+
+#include "glib-linux.h"
 
 /* Keep in sync with glib/gbytes.c */
 struct _GBytes
@@ -269,7 +274,7 @@ test_to_data_transferred (void)
   GBytes *bytes;
 
   /* Memory transferred: one reference, and allocated with g_malloc */
-  bytes = g_bytes_new (NYAN, N_NYAN);
+  bytes = g_bytes_new_take (g_memdup (NYAN, N_NYAN), N_NYAN);
   memory = g_bytes_get_data (bytes, NULL);
   data = g_bytes_unref_to_data (bytes, &size);
   g_assert_true (data == memory);
@@ -347,7 +352,7 @@ test_to_array_transferred (void)
   GBytes *bytes;
 
   /* Memory transferred: one reference, and allocated with g_malloc */
-  bytes = g_bytes_new (NYAN, N_NYAN);
+  bytes = g_bytes_new_take (g_memdup (NYAN, N_NYAN), N_NYAN);
   memory = g_bytes_get_data (bytes, NULL);
   array = g_bytes_unref_to_array (bytes);
   g_assert_nonnull (array);
@@ -481,6 +486,46 @@ test_unref_null (void)
   g_bytes_unref (NULL);
 }
 
+#ifdef GLIB_LINUX
+static void
+test_memfd (void)
+{
+  GBytes *bytes;
+  gint fd;
+
+  fd = glib_linux_memfd_create ("", MFD_CLOEXEC);
+  if (fd == -1 && errno == EINVAL)
+    {
+      g_test_skip ("missing kernel memfd support");
+      return;
+    }
+
+  /* We should not be able to seal this one */
+  g_assert (!g_unix_fd_ensure_zero_copy_safe (fd));
+  close (fd);
+
+  /* but this one will work */
+  fd = glib_linux_memfd_create ("", MFD_CLOEXEC | MFD_ALLOW_SEALING);
+  bytes = g_bytes_new_take_zero_copy_fd (fd);
+  g_assert_cmpint (g_bytes_get_size (bytes), ==, 0);
+  g_bytes_unref (bytes);
+
+  /* try with real data */
+  fd = glib_linux_memfd_create ("", MFD_CLOEXEC | MFD_ALLOW_SEALING);
+  g_assert_se (write (fd, NYAN, N_NYAN) == N_NYAN);
+  bytes = g_bytes_new_take_zero_copy_fd (fd);
+  g_assert_cmpint (g_bytes_get_size (bytes), ==, N_NYAN);
+  g_assert (memcmp (g_bytes_get_data (bytes, NULL), NYAN, N_NYAN) == 0);
+  g_assert (g_bytes_get_zero_copy_fd (bytes) == fd);
+
+  /* ensure that we cannot modify the fd further */
+  g_assert_se (write (fd, NYAN, N_NYAN) == -1);
+
+  /* that's enough for now */
+  g_bytes_unref (bytes);
+}
+#endif
+
 int
 main (int argc, char *argv[])
 {
@@ -505,6 +550,9 @@ main (int argc, char *argv[])
   g_test_add_func ("/bytes/to-array/two-refs", test_to_array_two_refs);
   g_test_add_func ("/bytes/to-array/non-malloc", test_to_array_non_malloc);
   g_test_add_func ("/bytes/null", test_null);
+#ifdef GLIB_LINUX
+  g_test_add_func ("/bytes/memfd", test_memfd);
+#endif
   g_test_add_func ("/bytes/get-region", test_get_region);
   g_test_add_func ("/bytes/unref-null", test_unref_null);
 
index 0110f26..9674bd8 100644 (file)
 #include "config.h"
 
 #include <glib/gvariant-internal.h>
+#include <glib/glib-private.h>
 #include <string.h>
 #include <stdlib.h>
 #include <glib.h>
 
-#define BASIC "bynqiuxthdsog?"
+#define BASIC "bynqiuxthfdsog?"
 #define N_BASIC (G_N_ELEMENTS (BASIC) - 1)
 
-#define INVALIDS "cefjklpwz&@^$"
+#define INVALIDS "cejklpwz&@^$"
 #define N_INVALIDS (G_N_ELEMENTS (INVALIDS) - 1)
 
 /* see comment in gvariant-serialiser.c about this madness.
@@ -81,6 +82,8 @@ append_type_string (GString  *string,
           return g_variant_type_copy (G_VARIANT_TYPE_UINT64);
         case 'h':
           return g_variant_type_copy (G_VARIANT_TYPE_HANDLE);
+        case 'f':
+          return g_variant_type_copy (G_VARIANT_TYPE_FLOAT);
         case 'd':
           return g_variant_type_copy (G_VARIANT_TYPE_DOUBLE);
         case 's':
@@ -448,6 +451,8 @@ describe_type (const GVariantType *type)
             result = g_strdup ("t");
           else if (g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
             result = g_strdup ("h");
+          else if (g_variant_type_equal (type, G_VARIANT_TYPE_FLOAT))
+            result = g_strdup ("f");
           else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
             result = g_strdup ("d");
           else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
@@ -803,6 +808,7 @@ calculate_type_info (const GVariantType *type,
 
       else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32) ||
                g_variant_type_equal (type, G_VARIANT_TYPE_UINT32) ||
+               g_variant_type_equal (type, G_VARIANT_TYPE_FLOAT) ||
                g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
         {
           al = fs = 4;
@@ -1938,6 +1944,7 @@ struct _TreeInstance
 
   union {
     guint64 integer;
+    gfloat single;
     gdouble floating;
     gchar string[200];
   } data;
@@ -2052,6 +2059,11 @@ tree_instance_new (const GVariantType *type,
       instance->data_size = 8;
       break;
 
+    case 'f':
+      instance->data.single = g_test_rand_double ();
+      instance->data_size = 4;
+      break;
+
     case 'd':
       instance->data.floating = g_test_rand_double ();
       instance->data_size = 8;
@@ -2532,6 +2544,10 @@ tree_instance_get_gvariant (TreeInstance *tree)
       result = g_variant_new_handle (tree->data.integer);
       break;
 
+    case 'f':
+      result = g_variant_new_float (tree->data.single);
+      break;
+
     case 'd':
       result = g_variant_new_double (tree->data.floating);
       break;
@@ -2555,6 +2571,19 @@ tree_instance_get_gvariant (TreeInstance *tree)
   return result;
 }
 
+static GVariant *
+create_random_gvariant (guint depth)
+{
+  TreeInstance *tree;
+  GVariant *value;
+
+  tree = tree_instance_new (NULL, depth);
+  value = g_variant_take_ref (tree_instance_get_gvariant (tree));
+  tree_instance_free (tree);
+
+  return value;
+}
+
 static gboolean
 tree_instance_check_gvariant (TreeInstance *tree,
                               GVariant     *value)
@@ -2659,6 +2688,13 @@ tree_instance_check_gvariant (TreeInstance *tree,
     case 'h':
       return g_variant_get_handle (value) == (gint32) tree->data.integer;
 
+    case 'f':
+      {
+        gfloat floating = g_variant_get_float (value);
+
+        return memcmp (&floating, &tree->data.single, sizeof floating) == 0;
+      }
+
     case 'd':
       {
         gdouble floating = g_variant_get_double (value);
@@ -3809,6 +3845,7 @@ test_gv_byteswap (void)
 static void
 test_parser (void)
 {
+  GError *error = NULL;
   TreeInstance *tree;
   GVariant *parsed;
   GVariant *value;
@@ -3822,16 +3859,19 @@ test_parser (void)
   pt = g_variant_print (value, TRUE);
   p = g_variant_print (value, FALSE);
 
-  parsed = g_variant_parse (NULL, pt, NULL, NULL, NULL);
+  parsed = g_variant_parse (NULL, pt, NULL, NULL, &error);
+  g_assert_no_error (error);
   res = g_variant_print (parsed, FALSE);
-  g_assert_cmpstr (p, ==, res);
+  if (!strstr (pt, "float")) /* FIXME: need reliable round-trip for floats */
+    g_assert_cmpstr (p, ==, res);
   g_variant_unref (parsed);
   g_free (res);
 
-  parsed = g_variant_parse (g_variant_get_type (value), p,
-                            NULL, NULL, NULL);
+  parsed = g_variant_parse (g_variant_get_type (value), p, NULL, NULL, &error);
+  g_assert_no_error (error);
   res = g_variant_print (parsed, TRUE);
-  g_assert_cmpstr (pt, ==, res);
+  if (!strstr (pt, "float")) /* FIXME: need reliable round-trip for floats */
+    g_assert_cmpstr (pt, ==, res);
   g_variant_unref (parsed);
   g_free (res);
 
@@ -4730,10 +4770,13 @@ test_gbytes (void)
 {
   GVariant *a;
   GVariant *tuple;
+  GVariant *b;
+  GVariant *c;
   GBytes *bytes;
   GBytes *bytes2;
   const guint8 values[5] = { 1, 2, 3, 4, 5 };
   const guint8 *elts;
+  gchar *tmp;
   gsize n_elts;
   gsize i;
 
@@ -4764,6 +4807,41 @@ test_gbytes (void)
   g_bytes_unref (bytes2);
   g_variant_unref (a);
   g_variant_unref (tuple);
+
+  /* Feed in some non-normal data... make sure it's aligned.
+   *
+   * Here we have an array of three elements.  The first and last are
+   * normal ints ('iiii') and array-of-bytes data ('ayay').  The middle
+   * element is zero-bytes wide, which will present a problem when
+   * fetching the fixed-size integer out of it.
+   * */
+  tmp = g_strdup ("iiiiayayiiiisayay\x08\x08\x10");
+  bytes = g_bytes_new_take (tmp, strlen (tmp));
+  a = g_variant_new_from_bytes (G_VARIANT_TYPE ("a(iay)"), bytes, FALSE);
+  g_bytes_unref (bytes);
+
+  /* The middle tuple is zero bytes */
+  b = g_variant_get_child_value (a, 1);
+  g_assert_cmpint (g_variant_get_size (b), ==, 0);
+
+  /* But we're going to pull a 4-byte child out of it... */
+  c = g_variant_get_child_value (b, 0);
+  g_assert_cmpint (g_variant_get_size (c), ==, 4);
+
+  /* g_variant_get_data() is allowed to fail in this case.
+   * NB: if someone finds a way to avoid this then that's fine too...
+   */
+  g_assert (g_variant_get_data (c) == NULL);
+
+  /* but since it's four bytes, it ought to have data... */
+  bytes = g_variant_get_data_as_bytes (c);
+  g_assert_cmpint (g_bytes_get_size (bytes), ==, 4);
+  g_assert (memcmp (g_bytes_get_data (bytes, NULL), "\0\0\0\0", 4) == 0);
+  g_bytes_unref (bytes);
+
+  g_variant_unref (c);
+  g_variant_unref (b);
+  g_variant_unref (a);
 }
 
 typedef struct {
@@ -4807,6 +4885,81 @@ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
 G_GNUC_END_IGNORE_DEPRECATIONS
 }
 
+static GByteArray *
+flatten_vectors (GVariantVectors *v)
+{
+  GByteArray *result;
+  guint i;
+
+  result = g_byte_array_new ();
+
+  for (i = 0; i < v->vectors->len; i++)
+    {
+      GVariantVector vec = g_array_index (v->vectors, GVariantVector, i);
+
+      if (vec.gbytes)
+        g_byte_array_append (result, vec.data.pointer, vec.size);
+      else
+        g_byte_array_append (result, v->extra_bytes->data + vec.data.offset, vec.size);
+    }
+
+  return result;
+}
+
+static void
+test_vector_serialiser (void)
+{
+  GVariantVectors vectors;
+  GByteArray *flattened;
+  GVariant *value;
+  guint i;
+
+  for (i = 0; i < 100; i++)
+    {
+      guint j;
+
+      value = create_random_gvariant (2);
+      //g_print (">>> %s\n", g_variant_print (value, TRUE));
+
+      GLIB_PRIVATE_CALL(g_variant_to_vectors) (value, &vectors);
+      for (j = 0; j < vectors.vectors->len; j++)
+        {
+          GVariantVector *v = &g_array_index (vectors.vectors, GVariantVector, j);
+
+          if (!v->gbytes)
+            {
+              v->gbytes = g_bytes_new (NULL, 0);
+              v->data.pointer = v->data.offset + vectors.extra_bytes->data;
+            }
+
+          //g_print ("  V %p %p %d\n", v, v->data.pointer, (guint) v->size);
+        }
+      GLIB_PRIVATE_CALL(g_variant_from_vectors) (g_variant_get_type (value), (GVariantVector *) vectors.vectors->data, vectors.vectors->len, g_variant_get_size (value), TRUE);
+      continue;
+      flattened = flatten_vectors (&vectors);
+      g_byte_array_free (vectors.extra_bytes, TRUE);
+      g_byte_array_free (vectors.offsets, TRUE);
+      g_array_free (vectors.vectors, TRUE);
+
+#if 0
+      if (flattened->len != g_variant_get_size (value) ||
+          memcmp (flattened->data, g_variant_get_data (value), flattened->len) != 0)
+        {
+          g_file_set_contents ("flattened", flattened->data, flattened->len, NULL);
+          g_file_set_contents ("serialised", g_variant_get_data (value), g_variant_get_size (value), NULL);
+          g_print ("type is %s\n", g_variant_get_type_string (value));
+          g_assert_not_reached ();
+        }
+#endif
+
+      g_assert_cmpint (flattened->len, ==, g_variant_get_size (value));
+      g_assert (memcmp (flattened->data, g_variant_get_data (value), flattened->len) == 0);
+
+      g_byte_array_free (flattened, TRUE);
+      g_variant_unref (value);
+    }
+}
+
 static void
 test_stack_builder_init (void)
 {
@@ -5181,6 +5334,7 @@ main (int argc, char **argv)
   g_test_add_func ("/gvariant/gbytes", test_gbytes);
   g_test_add_func ("/gvariant/print-context", test_print_context);
   g_test_add_func ("/gvariant/error-quark", test_error_quark);
+  g_test_add_func ("/gvariant/vector-serialiser", test_vector_serialiser);
 
   g_test_add_func ("/gvariant/stack-builder-init", test_stack_builder_init);
   g_test_add_func ("/gvariant/stack-dict-init", test_stack_dict_init);
diff --git a/gobject/tests/.gitignore b/gobject/tests/.gitignore
deleted file mode 100644 (file)
index 06f3991..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-binding
-boxed
-closure
-dynamictests
-enums
-ifaceproperties
-object
-param
-properties
-qdata
-reference
-signal-handler
-signals
-threadtests
-type
-value
-private
-marshalers.[ch]
index 581726a..a9267e9 100644 (file)
@@ -28,4 +28,12 @@ AC_DEFUN([GLIB_TESTS],
     AC_SUBST(installed_test_metadir, [${datadir}/installed-tests/]AC_PACKAGE_NAME)
     AC_SUBST(installed_testdir, [${libexecdir}/installed-tests/]AC_PACKAGE_NAME)
   fi
+  AC_ARG_ENABLE(force-dbus-tests,
+                AS_HELP_STRING([--enable-force-dbus-tests],
+                               [Force including dbus tests even if dbus-daemon is not detected]),
+                [case ${enableval} in
+                  yes) FORCE_DBUS_TESTS="1"  ;;
+                  no)  FORCE_DBUS_TESTS="" ;;
+                  *) AC_MSG_ERROR([bad value ${enableval} for --enable-force-dbus-tests]) ;;
+                 esac])
 ])
index 6cd7bc9..f976ec5 100644 (file)
@@ -95,6 +95,16 @@ option('nls',
        yield: true,
        description : 'Enable native language support (translations)')
 
+option('kdbus',
+       type : 'boolean',
+       value : false,
+       description : 'enable kdbus transport')
+
+option('libdbuspolicy',
+       type : 'boolean',
+       value : false,
+       description : 'enable libdbuspolicy for kdbus transport')
+
 option('oss_fuzz',
        type : 'feature',
        value : 'disabled',
diff --git a/packaging/README.Gsettings-overrides b/packaging/README.Gsettings-overrides
new file mode 100644 (file)
index 0000000..1244df3
--- /dev/null
@@ -0,0 +1,19 @@
+Quoting the "Vendor overrides" section from [1]:
+
+Default values are defined in the schemas that get installed by an application.
+Sometimes, it is necessary for a vendor or distributor to adjust these
+defaults. Since patching the XML source for the schema is inconvenient and
+error-prone, glib-compile-schemas reads so-called 'vendor override' files.
+These are keyfiles in the same directory as the XML schema sources which can
+override default values. The schema id serves as the group name in the key
+file, and the values are expected in serialized GVariant form, as in the
+following example:
+
+       [org.gtk.Example]
+       key1='string'
+       key2=1.5
+
+glib-compile-schemas expects schema files to have the extension
+.gschema.override
+
+[1] http://developer.gnome.org/gio/stable/GSettings.html
diff --git a/packaging/baselibs.conf b/packaging/baselibs.conf
new file mode 100644 (file)
index 0000000..f2977fd
--- /dev/null
@@ -0,0 +1,22 @@
+glib2-tools
+  +/usr/bin/gio-querymodules(-64)?
+libglib
+  obsoletes "glib2-<targettype> <= <version>"
+  provides "glib2-<targettype> = <version>"
+libgmodule
+libgio
+libgthread
+libgobject
+libgio-fam
+  requires "glib2-tools-<targettype>"
+  post "%if "%_lib" == "lib64""
+  post "<prefix>%{_bindir}/gio-querymodules-64 <prefix>%{_libdir}/gio/modules"
+  post "%else"
+  post "<prefix>%{_bindir}/gio-querymodules <prefix>%{_libdir}/gio/modules"
+  post "%endif"
+  postun "%if "%_lib" == "lib64""
+  postun "<prefix>%{_bindir}/gio-querymodules-64 <prefix>%{_libdir}/gio/modules"
+  postun "%else"
+  postun "<prefix>%{_bindir}/gio-querymodules <prefix>%{_libdir}/gio/modules"
+  postun "%endif"
+
diff --git a/packaging/coverage.txt b/packaging/coverage.txt
new file mode 100644 (file)
index 0000000..ef5e4d4
--- /dev/null
@@ -0,0 +1,19 @@
+How to analyze coverage:
+1. gbs build adding --define '_with_coverage 1'
+2. take *.o and *.gcno files from compilation (
+               <gbs-build-root>/home/abuild/rpmbuild/BUILD/glib2-2.44.1/gio/.libs
+               <gbs-build-root>/home/abuild/rpmbuild/BUILD/glib2-2.44.1/glib/.libs
+               <gbs-build-root>/home/abuild/rpmbuild/BUILD/glib2-2.44.1/gmodule/.libs
+               <gbs-build-root>/home/abuild/rpmbuild/BUILD/glib2-2.44.1/gobject/.libs
+               <gbs-build-root>/home/abuild/rpmbuild/BUILD/glib2-2.44.1/gthread/.libs
+               ) into a /safe/place
+       you may also use generated rpm package glib2-coverage-objects.
+3. install coverage package (glib2-coverage) on the target
+4. run test programs adding LD_LIBRARY_PATH=/usr/lib/dbus-tests/coverage-libs
+       Data gathering is cumulative, so you can run multiple programs one after another.
+       Use GCOV_PREFIX and GCOV_PREFIX_STRIP environment variables to set output directory.
+       If not set, data files (*.gcda) will be generated in /home/abuild/rpmbuild/BUILD/glib2-2.44.1/.
+5. download generated gcda files from the target to /safe/place
+6. put source code *.c files together with object files into a /safe/place
+7. run gcov /safe/place/*.o
+       or gcov -r /safe/place/*.o for only local source code output
diff --git a/packaging/glib2-rpmlintrc b/packaging/glib2-rpmlintrc
new file mode 100644 (file)
index 0000000..5a39ef6
--- /dev/null
@@ -0,0 +1,2 @@
+addFilter(".*shlib-fixed-dependency.*glib2")
+
diff --git a/packaging/glib2-upstream-gnome_defaults.conf b/packaging/glib2-upstream-gnome_defaults.conf
new file mode 100644 (file)
index 0000000..599ee82
--- /dev/null
@@ -0,0 +1,46 @@
+# GNOME Default Applications Source
+# /etc/gnome-defaults.conf
+#
+# WARNING: This is a dumb file, which provides only upstream GNOME
+# packages as preferred defaults. You most probably don't want this
+# package!
+# You probably want to install distribution glib2-branding and prefer
+# distribution wise GNOME defaults.
+#
+# After any change of this file run
+# SuSEconfig --module glib2
+#
+# This list is a source for defaults.list.
+#
+# If application in this list is installed, it is used as default in GNOME.
+# It works in following way:
+# 1. Read this file.
+# 2. Collect all available desktop files.
+# 3. Go through all declared MIME types and search for default application
+#    for defaults.list in following order:
+# 3.1 Installed application listed here for certain MIME type.
+# 3.2 Installed application listed here as preferred default.
+# 3.3 Installed application listed here as default.
+# 3.4 Installed application with GNOME in Categories.
+# 3.5 Installed application with GTK in Categories.
+# 3.6 Installed application.
+# If there are more applications in the same order, it uses pseudo-randomly
+# one of them (last in aplhabetical order).
+#
+# Syntax:
+# Use xxx as default for all MIME types it declares (see 3.3):
+# xxx.desktop
+# Use xxx as preferred default for all MIME types it declares (see 3.2):
+# !xxx.desktop
+# Use xxx as default for mime/type (see 3.1):
+# mime/type=xxx.desktop
+
+# Upstream GNOME default applications
+eog.desktop
+evince.desktop
+gedit.desktop
+file-roller.desktop
+epiphany.desktop
+nautilus-folder-handler.desktop
+# evince supports multi-page tiff, but most people will prefer eog:
+image/tiff=eog.desktop
diff --git a/packaging/glib2.changes b/packaging/glib2.changes
new file mode 100644 (file)
index 0000000..806157b
--- /dev/null
@@ -0,0 +1,47 @@
+* Tue Aug 13 2013 Anas Nashif <anas.nashif@intel.com> 2.36.3@0540f90
+- add .gbs.conf and update to 2.36.4
+
+* Tue Aug 13 2013 Anas Nashif <anas.nashif@intel.com> accepted/tizen/20130520.095512@84a55be
+- Remove empty docs package
+
+* Fri Jul 19 2013 Philippe Coval <philippe.coval@eurogiciel.fr> accepted/tizen/20130710.220535@5c863cc
+- gdesktopappinfo: Allow getting the desktop ID from the filename
+  Bug-Tizen: TZPC-3317 (... remove the fav apps icon ...)
+  Origin: upstream, https://git.gnome.org/browse/glib/commit/?id=c0af442909e1304b799a4b6c145f8444c752e3da
+- resetting manifest requested domain to floor
+- GSocks5Proxy: don't crash if parsing negotiation reply fails
+  Applied-upstream: 2.36.2, commit:0ba982e05
+  Bug: https://bugzilla.gnome.org/show_bug.cgi?id=699493
+  Bug-Tizen: TZPC-34 (Empathy / Telepathy - Proxy support)
+
+* Sat Apr 27 2013 Anas Nashif <anas.nashif@intel.com> 2.36.1@1b0d9ca
+- Update to 2.36.1
+
+* Wed Mar 27 2013 Anas Nashif <anas.nashif@intel.com> 2.36.0@3e8939c
+- Update to 2.36.0
+
+* Fri Mar 22 2013 Anas Nashif <anas.nashif@intel.com> 2.35.9@14fe501
+- Update to 2.35.9
+
+* Tue Mar 05 2013 Anas Nashif <anas.nashif@intel.com> 2.35.8@89b88e0
+- Remove previous crash fix (TZPC-453)
+
+* Tue Feb 26 2013 Anas Nashif <anas.nashif@intel.com> 2.35.8@8aed25e
+- Update to 2.35.8
+
+* Thu Feb 07 2013 Anas Nashif <anas.nashif@intel.com> 2.35.7@c7a2158
+- Update to 2.35.7
+
+* Thu Jan 31 2013 Anas Nashif <anas.nashif@intel.com> submit/trunk/20130131.165010@88f28c3
+- Update to 2.35.4
+
+* Thu Jan 03 2013 jbollo <jose.bollo@eurogiciel.fr> accepted/trunk/20121220.211950@7fcf93d
+- Avoiding SIGSEGV when running gio-querymodules
+
+* Tue Dec 18 2012 Anas Nashif <anas.nashif@intel.com> 2.35.3@28d76f3
+- update to 2.35.3
+
+* Sun Dec 09 2012 Anas Nashif <anas.nashif@intel.com> submit/devel/20121210.025910@9a11327
+- package license file
+- update to 2.35.2
+
diff --git a/packaging/glib2.csh b/packaging/glib2.csh
new file mode 100644 (file)
index 0000000..aac46f3
--- /dev/null
@@ -0,0 +1,468 @@
+# GLib filename encoding guesser.
+# Author: Stanislav Brabec <sbrabec@suse.cz>
+# Additions are welcome.
+# This script must be executed after setting LANG variable.
+
+# Try filenames which are invalid in UTF-8 as locale specific.
+# For selected locales, G_FILENAME_ENCODING takes precedence.
+setenv G_BROKEN_FILENAMES 1
+
+# In West Europe there was used both ISO-8859-15 and ISO-8859-1.
+# There is no chance to recognize it, so we must guess.
+#set west_europe_legacy_encoding=ISO-8859-1
+set west_europe_legacy_encoding=ISO-8859-15
+
+# In Russia, "official" encoding is ISO-8859-5, but most GNOME users
+# preferred KOI8-R. We must guess.
+#set russian_legacy_encoding=ISO-8859-5
+set russian_legacy_encoding=KOI8-R
+
+# In former Yugoslavia sr_YU have covered two different alphabets -
+# one Latin and on Cyrillic. No chance to guess.
+set sr_YU_legacy_encoding=ISO-8859-2,CP1250
+#set sr_YU_legacy_encoding=ISO-8859-5
+
+# Japanese uses two legacy encodings. Guess sometimes fails, sometimes not.
+# Defining preferred encoding increases chance for success.
+set japanese_legacy_encoding=EUC-JP
+#set japanese_legacy_encoding=SHIFT_JIS
+
+if (! ${?LANG} ) goto skip
+
+switch ( $LANG )
+    case aa_DJ*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case af_ZA*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case an_ES*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-15,CP1252
+       breaksw
+    case ar_AE*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-6
+       breaksw
+    case ar_BH*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-6
+       breaksw
+    case ar_DZ*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-6
+       breaksw
+    case ar_EG*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-6
+       breaksw
+    case ar_IQ*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-6
+       breaksw
+    case ar_JO*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-6
+       breaksw
+    case ar_KW*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-6
+       breaksw
+    case ar_LB*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-6
+       breaksw
+    case ar_LY*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-6
+       breaksw
+    case ar_MA*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-6
+       breaksw
+    case ar_OM*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-6
+       breaksw
+    case ar_QA*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-6
+       breaksw
+    case ar_SA*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-6
+       breaksw
+    case ar_SD*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-6
+       breaksw
+    case ar_SY*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-6
+       breaksw
+    case ar_TN*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-6
+       breaksw
+    case ar_YE*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-6
+       breaksw
+    case be_BY*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,CP1251
+       breaksw
+    case bg_BG*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,CP1251
+       breaksw
+    case br_FR*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case bs_BA*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-2,CP1250
+       breaksw
+    case ca_ES*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case cs_CZ*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-2,CP1250
+       breaksw
+    case cy_GB*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-14,CP1252
+       breaksw
+    case da_DK*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case de_AT*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case de_BE*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case de_DE*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case de_CH*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case de_LU*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case el_GR*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-7
+       breaksw
+    case en_AU*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case en_BE*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case en_BW*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case en_CA*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case en_DK*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case en_GB*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case en_HK*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case en_IE*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case en_NZ*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case en_PH*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case en_SG*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case en_US*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case en_ZA*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case en_ZW*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case es_AR*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case es_BO*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case es_CL*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case es_CO*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case es_CR*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case es_DO*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case es_EC*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case es_ES*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case es_GT*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case es_HN*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case es_MX*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case es_NI*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case es_PA*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case es_PE*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case es_PR*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case es_PY*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case es_SV*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case es_US*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case es_UY*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case es_VE*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case et_EE*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case eu_ES*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case fa_IR*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,CP1256
+       breaksw
+    case fi_FI*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case fo_FO*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case fr_BE*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case fr_CA*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case fr_FR*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case fr_CH*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case fr_LU*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case ga_IE*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case gd_GB*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-15,CP1252
+       breaksw
+    case gl_ES*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case gv_GB*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case he_IL*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-8
+       breaksw
+    case hr_HR*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-2,CP1250
+       breaksw
+    case hu_HU*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-2,CP1250
+       breaksw
+    case hy_AM*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ARMSCII-8
+       breaksw
+    case id_ID*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case is_IS*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case it_CH*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case it_IT*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case iw_IL*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-8
+       breaksw
+    case ja_JP*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$japanese_legacy_encoding,EUC-JP,SHIFT_JIS,ISO-8859-1
+       breaksw
+    case ka_GE*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,GEORGIAN-PS
+       breaksw
+    case kl_GL*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case km_KH*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,GB18030
+       breaksw
+    case ko_KR*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,EUC-KR,ISO-8859-1
+       breaksw
+    case kw_GB*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case lg_UG*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-10,CP1252
+       breaksw
+    case lt_LT*:                                           
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-13,CP1252
+       breaksw
+    case lv_LV*:                                           
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-13,CP1252
+       breaksw
+    case mi_NZ*:                                           
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-13,CP1252
+       breaksw
+    case mk_MK*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-5,CP1251
+       breaksw
+    case ms_MY*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case mt_MT*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-3
+       breaksw
+    case nb_NO*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case nl_BE*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case nl_NL*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case nn_NO*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case no_NO*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case oc_FR*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case om_KE*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case pl_PL*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-2,CP1250
+       breaksw
+    case pt_BR*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case pt_PT*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case ro_RO*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-2,CP1250
+       breaksw
+    case ru_RU*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$russian_legacy_encoding,CP1251
+       breaksw
+    case ru_UA*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,KOI8-U
+       breaksw
+    case sh_YU*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-2,CP1250
+       breaksw
+    case sk_SK*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-2,CP1250
+       breaksw
+    case sl_SI*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-2,CP1250
+       breaksw
+    case so_DJ*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case so_KE*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case so_SO*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case sq_AL*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case sr_YU*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$sr_YU_legacy_encoding
+       breaksw
+    case st_ZA*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case sv_FI*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case sv_SE*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case tg_TJ*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,KOI8-T
+       breaksw
+    case th_TH*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,TIS-620,ISO-8859-1
+       breaksw
+    case tl_PH*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case tr_TR*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-9
+       breaksw
+    case uk_UA*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,KOI8-U
+       breaksw
+    case uz_UZ*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case vi_VN*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,TCVN5712-1,ISO-8859-1
+       breaksw
+    case wa_BE*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       breaksw
+    case xh_ZA*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+    case yi_US*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,CP1255
+       breaksw
+    case zh_CN*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,GB2312,GB18030,GBK,ISO-8859-1
+       breaksw
+    case zh_HK*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,BIG5-HKSCS,ISO-8859-1
+       breaksw
+    case zh_SG*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,GB2312,GB18030,GBK,ISO-8859-1
+       breaksw
+    case zh_TW*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,BIG5,EUC-TW,ISO-8859-1
+       breaksw
+    case zu_ZA*:
+       setenv G_FILENAME_ENCODING @locale,UTF-8,ISO-8859-1,CP1252
+       breaksw
+endsw
+
+skip:
+
+unset west_europe_legacy_encoding
+unset russian_legacy_encoding
+unset sr_YU_legacy_encoding
diff --git a/packaging/glib2.manifest b/packaging/glib2.manifest
new file mode 100644 (file)
index 0000000..017d22d
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+ <request>
+    <domain name="_"/>
+ </request>
+</manifest>
diff --git a/packaging/glib2.sh b/packaging/glib2.sh
new file mode 100644 (file)
index 0000000..b8f63c8
--- /dev/null
@@ -0,0 +1,465 @@
+# GLib filename encoding guesser.
+# Author: Stanislav Brabec <sbrabec@suse.cz>
+# Additions are welcome.
+# This script must be executed after setting LANG variable.
+
+# Try filenames which are invalid in UTF-8 as locale specific.
+# For selected locales, G_FILENAME_ENCODING takes precedence.
+export G_BROKEN_FILENAMES=1
+
+# In West Europe there was used both ISO-8859-15 and ISO-8859-1.
+# There is no chance to recognize it, so we must guess.
+#west_europe_legacy_encoding=ISO-8859-1
+west_europe_legacy_encoding=ISO-8859-15
+
+# In Russia, "official" encoding is ISO-8859-5, but most GNOME users
+# preferred KOI8-R. We must guess.
+#russian_legacy_encoding=ISO-8859-5
+russian_legacy_encoding=KOI8-R
+
+# In former Yugoslavia sr_YU have covered two different alphabets -
+# one Latin and on Cyrillic. No chance to guess.
+sr_YU_legacy_encoding=ISO-8859-2,CP1250
+#sr_YU_legacy_encoding=ISO-8859-5
+
+# Japanese uses two legacy encodings. Guess sometimes fails, sometimes not.
+# Defining preferred encoding increases chance for success.
+japanese_legacy_encoding=EUC-JP
+#japanese_legacy_encoding=SHIFT_JIS
+
+case $LANG in
+    aa_DJ* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    af_ZA* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    an_ES* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-15,CP1252
+       ;;
+    ar_AE* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-6
+       ;;
+    ar_BH* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-6
+       ;;
+    ar_DZ* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-6
+       ;;
+    ar_EG* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-6
+       ;;
+    ar_IQ* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-6
+       ;;
+    ar_JO* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-6
+       ;;
+    ar_KW* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-6
+       ;;
+    ar_LB* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-6
+       ;;
+    ar_LY* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-6
+       ;;
+    ar_MA* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-6
+       ;;
+    ar_OM* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-6
+       ;;
+    ar_QA* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-6
+       ;;
+    ar_SA* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-6
+       ;;
+    ar_SD* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-6
+       ;;
+    ar_SY* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-6
+       ;;
+    ar_TN* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-6
+       ;;
+    ar_YE* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-6
+       ;;
+    be_BY* )
+       G_FILENAME_ENCODING=@locale,UTF-8,CP1251
+       ;;
+    bg_BG* )
+       G_FILENAME_ENCODING=@locale,UTF-8,CP1251
+       ;;
+    br_FR* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    bs_BA* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-2,CP1250
+       ;;
+    ca_ES* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    cs_CZ* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-2,CP1250
+       ;;
+    cy_GB* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-14,CP1252
+       ;;
+    da_DK* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    de_AT* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    de_BE* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    de_DE* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    de_CH* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    de_LU* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    el_GR* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-7
+       ;;
+    en_AU* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    en_BE* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    en_BW* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    en_CA* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    en_DK* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    en_GB* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    en_HK* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    en_IE* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    en_NZ* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    en_PH* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    en_SG* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    en_US* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    en_ZA* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    en_ZW* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    es_AR* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    es_BO* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    es_CL* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    es_CO* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    es_CR* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    es_DO* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    es_EC* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    es_ES* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    es_GT* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    es_HN* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    es_MX* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    es_NI* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    es_PA* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    es_PE* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    es_PR* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    es_PY* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    es_SV* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    es_US* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    es_UY* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    es_VE* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    et_EE* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    eu_ES* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    fa_IR* )
+       G_FILENAME_ENCODING=@locale,UTF-8,CP1256
+       ;;
+    fi_FI* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    fo_FO* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    fr_BE* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    fr_CA* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    fr_FR* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    fr_CH* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    fr_LU* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    ga_IE* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    gd_GB* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-15,CP1252
+       ;;
+    gl_ES* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    gv_GB* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    he_IL* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-8
+       ;;
+    hr_HR* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-2,CP1250
+       ;;
+    hu_HU* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-2,CP1250
+       ;;
+    hy_AM* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ARMSCII-8
+       ;;
+    id_ID* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    is_IS* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    it_CH* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    it_IT* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    iw_IL* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-8
+       ;;
+    ja_JP* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$japanese_legacy_encoding,EUC-JP,SHIFT_JIS,ISO-8859-1
+       ;;
+    ka_GE* )
+       G_FILENAME_ENCODING=@locale,UTF-8,GEORGIAN-PS
+       ;;
+    kl_GL* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    km_KH* )
+       G_FILENAME_ENCODING=@locale,UTF-8,GB18030
+       ;;
+    ko_KR* )
+       G_FILENAME_ENCODING=@locale,UTF-8,EUC-KR,ISO-8859-1
+       ;;
+    kw_GB* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    lg_UG* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-10,CP1252
+       ;;                                          
+    lt_LT* )                                        
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-13,CP1252
+       ;;                                          
+    lv_LV* )                                        
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-13,CP1252
+       ;;                                          
+    mi_NZ* )                                        
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-13,CP1252
+       ;;
+    mk_MK* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-5,CP1251
+       ;;
+    ms_MY* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    mt_MT* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-3
+       ;;
+    nb_NO* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    nl_BE* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    nl_NL* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    nn_NO* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    no_NO* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    oc_FR* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    om_KE* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    pl_PL* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-2,CP1250
+       ;;
+    pt_BR* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    pt_PT* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    ro_RO* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-2,CP1250
+       ;;
+    ru_RU* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$russian_legacy_encoding,CP1251
+       ;;
+    ru_UA* )
+       G_FILENAME_ENCODING=@locale,UTF-8,KOI8-U
+       ;;
+    sh_YU* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-2,CP1250
+       ;;
+    sk_SK* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-2,CP1250
+       ;;
+    sl_SI* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-2,CP1250
+       ;;
+    so_DJ* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    so_KE* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    so_SO* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    sq_AL* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    sr_YU* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$sr_YU_legacy_encoding
+       ;;
+    st_ZA* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    sv_FI* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    sv_SE* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    tg_TJ* )
+       G_FILENAME_ENCODING=@locale,UTF-8,KOI8-T
+       ;;
+    th_TH* )
+       G_FILENAME_ENCODING=@locale,UTF-8,TIS-620,ISO-8859-1
+       ;;
+    tl_PH* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    tr_TR* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-9
+       ;;
+    uk_UA* )
+       G_FILENAME_ENCODING=@locale,UTF-8,KOI8-U
+       ;;
+    uz_UZ* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    vi_VN* )
+       G_FILENAME_ENCODING=@locale,UTF-8,TCVN5712-1,ISO-8859-1
+       ;;
+    wa_BE* )
+       G_FILENAME_ENCODING=@locale,UTF-8,$west_europe_legacy_encoding,CP1252
+       ;;
+    xh_ZA* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+    yi_US* )
+       G_FILENAME_ENCODING=@locale,UTF-8,CP1255
+       ;;
+    zh_CN* )
+       G_FILENAME_ENCODING=@locale,UTF-8,GB2312,GB18030,GBK,ISO-8859-1
+       ;;
+    zh_HK* )
+       G_FILENAME_ENCODING=@locale,UTF-8,BIG5-HKSCS,ISO-8859-1
+       ;;
+    zh_SG* )
+       G_FILENAME_ENCODING=@locale,UTF-8,GB2312,GB18030,GBK,ISO-8859-1
+       ;;
+    zh_TW* )
+       G_FILENAME_ENCODING=@locale,UTF-8,BIG5,EUC-TW,ISO-8859-1
+       ;;
+    zu_ZA* )
+       G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-1,CP1252
+       ;;
+esac
+export G_FILENAME_ENCODING
+
+unset west_europe_legacy_encoding
+unset russian_legacy_encoding
+unset sr_YU_legacy_encoding
diff --git a/packaging/glib2.spec b/packaging/glib2.spec
new file mode 100644 (file)
index 0000000..8342951
--- /dev/null
@@ -0,0 +1,456 @@
+# Do not create provides from extension .so files because the main package
+# should anchor any reverse-dependencies
+%global __provides_exclude_from ^(.*\\.extension-kdbus)$
+
+%define baseline 2.62
+%define with_systemtap 0
+%define keepstatic 1
+%define build_dir _build
+%define build_dir_kdbus _build_kdbus
+
+# The 'meson' macro is defined in rpm macros, but it uses features from rpm 4.15 ({shrink, set_build_flags)
+# Below is a version suitable for our purposes
+%define meson \
+  CFLAGS="${CFLAGS:-%optflags}" \
+  export CFLAGS \
+  %{__meson} \\\
+        --buildtype=plain \\\
+        --prefix=%{_prefix} \\\
+        --libdir=%{_libdir} \\\
+        --libexecdir=%{_libexecdir} \\\
+        --bindir=%{_bindir} \\\
+        --sbindir=%{_sbindir} \\\
+        --includedir=%{_includedir} \\\
+        --datadir=%{_datadir} \\\
+        --mandir=%{_mandir} \\\
+        --infodir=%{_infodir} \\\
+        --localedir=%{_datadir}/locale \\\
+        --sysconfdir=%{_sysconfdir} \\\
+        --localstatedir=%{_localstatedir} \\\
+        --sharedstatedir=%{_sharedstatedir} \\\
+        --wrap-mode=%{__meson_wrap_mode} \\\
+               %{_vpath_builddir}
+# Ninja macros below are defined for ninja in e.g. fedora distro, but
+# so far they are not provided by Tizen's ninja package.
+%define __ninja %{_bindir}/ninja
+%define __ninja_common_opts -v %{?_smp_flags}
+%define ninja_build \
+               %{__ninja} %{__ninja_common_opts}
+%define ninja_install \
+               DESTDIR=%{buildroot} %{__ninja} install %{__ninja_common_opts}
+
+Name:           glib2
+Version:        2.62.3
+Release:        0
+# FIXME: find out if tapsets should really be in devel package or in main package
+Summary:        General-Purpose Utility Library
+License:        LGPL-2.1+
+Group:          Base/Libraries
+Url:            http://www.gtk.org/
+Source:         http://download.gnome.org/sources/glib/%{baseline}/%{name}-%{version}.tar.xz
+Source1:        glib2.sh
+Source2:        glib2.csh
+Source3:        test-runner.c
+# Not upstream file. Only proposes upstream packages:
+Source4:        glib2-upstream-gnome_defaults.conf
+Source6:        macros.glib2
+# Not depending on gtk-doc shortens bootstrap compilation path.
+# Please update this file from the latest gtk-doc package:
+Source7:        gtk-doc.m4
+Source98:       q_quark_block_size.patch
+Source99:       baselibs.conf
+Source1001:    glib2.manifest
+BuildRequires:  automake
+BuildRequires:  fdupes
+BuildRequires:  gcc-c++
+BuildRequires:  m4
+BuildRequires:  meson >= 0.49.2
+BuildRequires:  pkg-config
+BuildRequires:  python3
+BuildRequires:  gettext-tools
+# gdbus-codegen is run during the build, so we need python-xml
+BuildRequires:  python3-xml
+%if 0%{?with_systemtap}
+BuildRequires:  systemtap-sdt-devel
+%endif
+# Needed for gresource
+BuildRequires:  pkgconfig(libelf) >= 0.8.12
+BuildRequires:  pkgconfig(libffi)
+BuildRequires:  pkgconfig(libpcre) >= 8.31
+BuildRequires:  pkgconfig(mount) >= 2.28
+BuildRequires:  pkgconfig(zlib)
+# Enable support for libdbuspolicy (only for kdbus transport)
+BuildRequires:  pkgconfig(libdbuspolicy1)
+
+%description
+GLib is a general-purpose utility library, which provides many useful
+data types, macros, type conversions, string utilities, file utilities,
+a main loop abstraction, and so on.
+
+%package tools
+Summary:        General-Purpose Utility Library -- Tools
+
+%description tools
+GLib is a general-purpose utility library, which provides many useful
+data types, macros, type conversions, string utilities, file utilities,
+a main loop abstraction, and so on.
+
+%package -n gio-branding-upstream
+Summary:        Upstream definitions of default settings and applications
+Requires:       libgio = %{version}
+Provides:       %{name}-branding-upstream = %{version}
+Obsoletes:      %{name}-branding-upstream < %{version}
+Provides:       gio-branding = %{version}
+Conflicts:      otherproviders(gio-branding)
+Supplements:    packageand(libgio:branding-upstream)
+BuildArch:      noarch
+#BRAND: The /etc/gnome_defaults.conf allows to define arbitrary
+#BRAND: applications as preferred defaults.
+#BRAND: A /usr/share/glib-2.0/schemas/$NAME.gschema.override file can
+#BRAND: be used to override the default value for GSettings keys. See
+#BRAND: README.Gsettings-overrides for more details. The branding
+#BRAND: package should then have proper Requires for features changed
+#BRAND: with such an override file.
+# NOTE: gnome_defaults is not an upstream feature, but a SuSE
+# enhancement, but to conform branding conventions, the package is named
+# as gio-branding-upstream.
+
+%description -n gio-branding-upstream
+This package provides upstream defaults for settings stored with
+GSettings and applications used by the MIME system.
+
+%package devel
+#'
+Requires:       %{name} = %{version}
+Requires:       glibc-devel
+Requires:       pkg-config
+# Now require the subpackages too
+Requires:       glib2-tools = %{version}
+Requires:       libgio = %{version}
+Requires:       libglib = %{version}
+Requires:       libgmodule = %{version}
+Requires:       libgobject = %{version}
+Requires:       libgthread = %{version}
+# Required by gdbus-codegen
+Requires:       python3-xml
+Requires:       python3
+Provides:       glib2-doc = 2.19.6
+Obsoletes:      glib2-doc < 2.19.6
+Summary:        General-Purpose Utility Library -- Development Files
+
+%description devel
+GLib is a general-purpose utility library, which provides many useful
+data types, macros, type conversions, string utilities, file utilities,
+a main loop abstraction, and so on.
+
+This package contains the development files for GLib.
+
+%package devel-static
+Summary:        Static libraries for glib, a general-purpose utility library
+Group:          Development/Libraries/C and C++
+Requires:       %{name}-devel = %{version}
+
+%description devel-static
+GLib is a general-purpose utility library, which provides many useful
+data types, macros, type conversions, string utilities, file utilities,
+a main loop abstraction, and so on.
+
+This package contains static versions of the GLib libraries.
+
+%package -n libglib
+Summary:        General-Purpose Utility Library
+Provides:       %{name} = %{version}
+Obsoletes:      %{name} < %{version}
+
+%description -n libglib
+GLib is a general-purpose utility library, which provides many useful
+data types, macros, type conversions, string utilities, file utilities,
+a main loop abstraction, and so on.
+
+%package -n libgmodule
+Summary:        General-Purpose Utility Library -- Library for Modules
+
+%description -n libgmodule
+GLib is a general-purpose utility library, which provides many useful
+data types, macros, type conversions, string utilities, file utilities,
+a main loop abstraction, and so on.
+
+The libgmodule library provides a portable way to dynamically load
+object files (commonly known as 'plug-ins').
+
+%package -n libgio
+Summary:        General-Purpose Utility Library -- Library for VFS
+Requires:       gio-branding = %{version}
+# bnc#555605: shared-mime-info is required by libgio to properly detect mime types.
+Requires:       shared-mime-info
+# bnc#678518: libgio interacts with others by means of dbus-launch
+#Requires:       dbus-1-x11
+Provides:       gio = %{version}
+
+%description -n libgio
+GLib is a general-purpose utility library, which provides many useful
+data types, macros, type conversions, string utilities, file utilities,
+a main loop abstraction, and so on.
+
+GIO provides a modern, easy-to-use VFS API.
+
+%package -n libgio-extension-kdbus
+Summary:       Extension for libgio to support KDBUS in Tizen
+Requires:      libgio = %{version}-%{release}
+
+%description -n libgio-extension-kdbus
+This modifies libgio to support KDBUS in Tizen.
+
+
+%package -n libgthread
+Summary:        General-Purpose Utility Library -- Library for Threads
+
+%description -n libgthread
+GLib is a general-purpose utility library, which provides many useful
+data types, macros, type conversions, string utilities, file utilities,
+a main loop abstraction, and so on.
+
+The libgthread library provides a portable way to write multi-threaded
+software.
+
+%package -n libgobject
+Summary:        General-Purpose Utility Library -- Object-Oriented Framework for C
+
+%description -n libgobject
+GLib is a general-purpose utility library, which provides many useful
+data types, macros, type conversions, string utilities, file utilities,
+a main loop abstraction, and so on.
+
+The GObject library provides an object-oriented framework for C.
+
+%package tests
+License:        LGPL-2.0+ and MIT
+Summary:        Set of tests for gdbus component
+Requires:       %{name} = %{version}
+
+%description tests
+This package is part of 'dbus-integration-tests' framework and contains set of tests
+for gdbus component.
+
+%prep
+%setup -q -n %{name}-%{version}
+%{__patch} -p1 < %{SOURCE98}
+
+%build
+cp %{SOURCE3} .
+cp %{SOURCE1001} .
+cp -a %{S:1} %{S:2} .
+cp -a %{S:4} gnome_defaults.conf
+if ! test -f %{_datadir}/aclocal/gtk-doc.m4 ; then
+    cp -a %{S:7} m4macros/
+fi
+
+%define _vpath_srcdir .
+
+# Normal build
+%define _vpath_builddir %{build_dir}
+%meson \
+       --default-library=both \
+       -Dinstalled_tests=true \
+       -Db_pie=true
+%meson_build
+
+# Configure kdbus extension build
+%define _vpath_builddir %{build_dir_kdbus}
+%meson \
+       --default-library=both \
+       -Dkdbus=true \
+       -Dlibdbuspolicy=true \
+       -Db_pie=true
+%meson_build
+
+# compile test-runner for 'dbus-integration-test' framework
+%__cc %{_builddir}/%{name}-%{version}/test-runner.c -fPIC -pie -o %{_builddir}/%{name}-%{version}/glib-tests
+
+%install
+# kdbus extension install and gather required files
+%define _vpath_builddir %{build_dir_kdbus}
+%meson_install
+for FILE in %{buildroot}%{_libdir}/libgio*; do mv "$FILE" "$FILE.extension-kdbus"; done
+
+# normal install overwriting kdbus extension install
+%define _vpath_builddir %{build_dir}
+%meson_install
+%find_lang glib20 %{?no_lang_C}
+
+mkdir -p %{buildroot}%{_sysconfdir}/profile.d
+install -D -m0644 glib2.sh %{buildroot}%{_sysconfdir}/profile.d/zzz-glib2.sh
+install -D -m0644 glib2.csh %{buildroot}%{_sysconfdir}/profile.d/zzz-glib2.csh
+install -D -m0644 gnome_defaults.conf %{buildroot}%{_sysconfdir}/gnome_defaults.conf
+
+# gio-querymodules magic
+%if "%{_lib}" == "lib64"
+mv %{buildroot}%{_bindir}/gio-querymodules %{buildroot}%{_bindir}/gio-querymodules-64
+%endif
+
+# prepare tests for 'dbus-integration-test' framework
+%define relative_dbus_tests_base_dir %{_prefix}/lib/dbus-tests
+%define dbus_tests_base_dir %{buildroot}%{relative_dbus_tests_base_dir}
+
+install -D -m 755 %{_builddir}/%{name}-%{version}/glib-tests %{dbus_tests_base_dir}/runner/glib-tests
+mkdir -p %{dbus_tests_base_dir}/test-suites/glib-tests/
+mv %{buildroot}%{_prefix}/libexec/installed-tests/glib/*gdbus-* %{dbus_tests_base_dir}/test-suites/glib-tests/
+# workaround for UNIX fd passing test (gdbus-peer)
+echo "Testfile - check for UNIX fd passing" > %{dbus_tests_base_dir}/test-suites/glib-tests/file.c
+rm %{dbus_tests_base_dir}/test-suites/glib-tests/gdbus-testserver
+rm -Rf %{buildroot}%{_prefix}/libexec/installed-tests/glib/
+rm -Rf %{buildroot}%{_prefix}/share/installed-tests/glib/
+
+# Install rpm macros
+mkdir -p %{buildroot}%{_sysconfdir}/rpm
+cp %{SOURCE6} %{buildroot}%{_sysconfdir}/rpm
+
+mkdir -p %{buildroot}%{_libdir}/gio/modules
+mkdir -p %{buildroot}%{_datadir}/glib-2.0/schemas/
+
+chmod 755 %{buildroot}%{_bindir}/*
+
+%post -n libglib -p /sbin/ldconfig
+%post -n libgobject -p /sbin/ldconfig
+%post -n libgthread -p /sbin/ldconfig
+%post -n libgio -p /sbin/ldconfig
+%post -n libgmodule -p /sbin/ldconfig
+
+%postun -n libglib -p /sbin/ldconfig
+%postun -n libgobject -p /sbin/ldconfig
+%postun -n libgthread -p /sbin/ldconfig
+%postun -n libgio -p /sbin/ldconfig
+%postun -n libgmodule -p /sbin/ldconfig
+
+%files tools
+%manifest %{name}.manifest
+%defattr(-,root,root)
+%license COPYING
+%dir %{_datadir}/bash-completion
+%dir %{_datadir}/bash-completion/completions
+%{_datadir}/bash-completion/completions/gresource
+%{_datadir}/bash-completion/completions/gsettings
+%{_bindir}/gdbus
+%{_bindir}/gio
+%{_bindir}/gio-querymodules*
+%{_bindir}/glib-compile-schemas
+%{_bindir}/gresource
+%{_bindir}/gsettings
+%{_bindir}/gapplication
+
+# We put those files here, but they don't really belong here. They just don't
+# have a better home... The zzz-glib2 scripts could arguably be in
+# libglib but that would break the shared library policy.
+%{_sysconfdir}/profile.d/zzz-glib2.*
+
+%files -n gio-branding-upstream
+%manifest %{name}.manifest
+%defattr(-,root,root)
+%license COPYING
+%config (noreplace) %{_sysconfdir}/gnome_defaults.conf
+
+%files -n libglib
+%manifest %{name}.manifest
+%defattr(-, root, root)
+%license COPYING
+%{_libdir}/libglib*.so.*
+
+%files -n libgmodule
+%manifest %{name}.manifest
+%defattr(-, root, root)
+%license COPYING
+%{_libdir}/libgmodule*.so.*
+
+%files -n libgobject
+%manifest %{name}.manifest
+%defattr(-, root, root)
+%license COPYING
+%{_libdir}/libgobject*.so.*
+
+%files -n libgthread
+%manifest %{name}.manifest
+%defattr(-, root, root)
+%license COPYING
+%{_libdir}/libgthread*.so.*
+
+%files -n libgio
+%manifest %{name}.manifest
+%defattr(-, root, root)
+%license COPYING
+%exclude %{_libdir}/libgio*.so.*.extension-kdbus
+%{_libdir}/libgio*.so.*
+%dir %{_libdir}/gio
+%dir %{_libdir}/gio/modules
+%ghost %{_libdir}/gio/modules/giomodule.cache
+%dir %{_datadir}/glib-2.0/
+%dir %{_datadir}/glib-2.0/schemas/
+
+%lang_package -f glib20
+
+%post -n libgio-extension-kdbus
+pushd %{_libdir}
+for FILE in libgio*.so.*.extension-kdbus; do mv "$FILE" "${FILE%.extension-kdbus}"; done
+popd
+
+%files -n libgio-extension-kdbus
+%manifest %{name}.manifest
+%license COPYING
+%{_libdir}/libgio*.so.*.extension-kdbus
+
+%files devel
+%manifest %{name}.manifest
+%defattr(-,root,root)
+%license COPYING
+
+%{_bindir}/gdbus-codegen
+%{_datadir}/bash-completion/completions/*
+%_datadir/glib-2.0/codegen
+
+%{_bindir}/glib-compile-resources
+%{_bindir}/glib-genmarshal
+%{_bindir}/glib-gettextize
+%{_bindir}/glib-mkenums
+%{_bindir}/gobject-query
+%{_bindir}/gtester
+%{_bindir}/gtester-report
+%dir %{_datadir}/aclocal
+%{_datadir}/aclocal/glib-2.0.m4
+%{_datadir}/aclocal/glib-gettext.m4
+%{_datadir}/aclocal/gsettings.m4
+%dir %{_datadir}/glib-2.0/
+%{_datadir}/glib-2.0/gdb/
+%{_datadir}/glib-2.0/gettext/
+%{_datadir}/glib-2.0/schemas/gschema.dtd
+%{_datadir}/glib-2.0/valgrind/glib.supp
+%{_includedir}/glib-2.0
+%{_includedir}/gio-unix-2.0
+%{_libdir}/lib*.so
+%dir %{_libdir}/glib-2.0/
+%{_libdir}/glib-2.0/include/
+%{_libdir}/pkgconfig/*.pc
+%{_datadir}/gdb/auto-load/%{_libdir}/*-gdb.py
+%{_datadir}/gettext/its/gschema.*
+%if 0%{?with_systemtap}
+%{_datadir}/systemtap/tapset/*.stp
+%endif
+%{_sysconfdir}/rpm/macros.glib2
+# Own these directories to not depend on gdb
+%dir %{_datadir}/gdb
+%dir %{_datadir}/gdb/auto-load
+%dir %{_datadir}/gdb/auto-load%{_prefix}
+%dir %{_datadir}/gdb/auto-load%{_libdir}
+
+%files devel-static
+%manifest %{name}.manifest
+%defattr(-,root,root)
+%license COPYING
+%{_libdir}/lib*.a
+%{_libdir}/lib*.a.extension-kdbus
+
+%files tests
+%manifest %{name}.manifest
+%license COPYING LICENSE.MIT
+%{relative_dbus_tests_base_dir}/test-suites/glib-tests/
+%{relative_dbus_tests_base_dir}/runner/glib-tests
+
+%changelog
diff --git a/packaging/gtk-doc.m4 b/packaging/gtk-doc.m4
new file mode 100644 (file)
index 0000000..0ada151
--- /dev/null
@@ -0,0 +1,67 @@
+dnl -*- mode: autoconf -*-
+
+# serial 1
+
+dnl Usage:
+dnl   GTK_DOC_CHECK([minimum-gtk-doc-version])
+AC_DEFUN([GTK_DOC_CHECK],
+[
+  AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+  AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first
+  AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first
+
+  dnl check for tools we added during development
+  AC_PATH_PROG([GTKDOC_CHECK],[gtkdoc-check])
+  AC_PATH_PROGS([GTKDOC_REBASE],[gtkdoc-rebase],[true])
+  AC_PATH_PROG([GTKDOC_MKPDF],[gtkdoc-mkpdf])
+
+  dnl for overriding the documentation installation directory
+  AC_ARG_WITH([html-dir],
+    AS_HELP_STRING([--with-html-dir=PATH], [path to installed docs]),,
+    [with_html_dir='${datadir}/gtk-doc/html'])
+  HTML_DIR="$with_html_dir"
+  AC_SUBST([HTML_DIR])
+
+  dnl enable/disable documentation building
+  AC_ARG_ENABLE([gtk-doc],
+    AS_HELP_STRING([--enable-gtk-doc],
+                   [use gtk-doc to build documentation [[default=no]]]),,
+    [enable_gtk_doc=no])
+
+  if test x$enable_gtk_doc = xyes; then
+    ifelse([$1],[],
+      [PKG_CHECK_EXISTS([gtk-doc],,
+                        AC_MSG_ERROR([gtk-doc not installed and --enable-gtk-doc requested]))],
+      [PKG_CHECK_EXISTS([gtk-doc >= $1],,
+                        AC_MSG_ERROR([You need to have gtk-doc >= $1 installed to build $PACKAGE_NAME]))])
+    dnl don't check for glib if we build glib
+    if test "x$PACKAGE_NAME" != "xglib"; then
+      dnl don't fail if someone does not have glib
+      PKG_CHECK_MODULES(GTKDOC_DEPS, glib-2.0 >= 2.10.0 gobject-2.0  >= 2.10.0,,)
+    fi
+  fi
+
+  AC_MSG_CHECKING([whether to build gtk-doc documentation])
+  AC_MSG_RESULT($enable_gtk_doc)
+
+  dnl enable/disable output formats
+  AC_ARG_ENABLE([gtk-doc-html],
+    AS_HELP_STRING([--enable-gtk-doc-html],
+                   [build documentation in html format [[default=yes]]]),,
+    [enable_gtk_doc_html=yes])
+    AC_ARG_ENABLE([gtk-doc-pdf],
+      AS_HELP_STRING([--enable-gtk-doc-pdf],
+                     [build documentation in pdf format [[default=no]]]),,
+      [enable_gtk_doc_pdf=no])
+
+  if test -z "$GTKDOC_MKPDF"; then
+    enable_gtk_doc_pdf=no
+  fi
+
+
+  AM_CONDITIONAL([ENABLE_GTK_DOC], [test x$enable_gtk_doc = xyes])
+  AM_CONDITIONAL([GTK_DOC_BUILD_HTML], [test x$enable_gtk_doc_html = xyes])
+  AM_CONDITIONAL([GTK_DOC_BUILD_PDF], [test x$enable_gtk_doc_pdf = xyes])
+  AM_CONDITIONAL([GTK_DOC_USE_LIBTOOL], [test -n "$LIBTOOL"])
+  AM_CONDITIONAL([GTK_DOC_USE_REBASE], [test -n "$GTKDOC_REBASE"])
+])
diff --git a/packaging/macros.glib2 b/packaging/macros.glib2
new file mode 100644 (file)
index 0000000..f682995
--- /dev/null
@@ -0,0 +1,73 @@
+# RPM macros for packages installing a GSettings schema or GIO module
+#
+###
+#
+# When a package installs a GSettings schemas, it should use all
+# three macros:
+#
+#  - %glib2_gsettings_schema_requires in the preamble
+#  - %glib2_gsettings_schema_post in %post
+#  - %glib2_gsettings_schema_postun in %postun
+#
+###
+#
+# When a package installs a GIO module, it should use all
+# three macros:
+#
+#  - %glib2_gio_module_requires in the preamble
+#  - %glib2_gio_module_post in %post
+#  - %glib2_gio_module_postun in %postun
+#
+# Note that %glib2_gio_module_post and %glib2_gio_module_postun can
+# optionally take the path to the directory where modules live. This
+# is useful for applications using the GIO module system on their own,
+# since they will install modules in their own directory. If no
+# argument is passed, the path for the modules for GIO itself is used.
+#
+###
+
+%glib2_gsettings_schema_requires                                \
+Requires(post): glib2-tools                                     \
+Requires(postun): glib2-tools
+
+%glib2_gsettings_schema_post                                    \
+%{_bindir}/glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || :
+
+# Note: we ignore upgrades (already handled in %post of the new package).
+%glib2_gsettings_schema_postun                                  \
+if [ $1 -eq 0 ]; then                                           \
+  %{_bindir}/glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : \
+fi
+
+%glib2_gio_module_requires                                      \
+Requires(post): glib2-tools                                     \
+Requires(postun): glib2-tools
+
+# On install, update the cache
+%glib2_gio_module_post()                                        \
+%if "x%1" != "x%%1"                                             \
+  GIO_MODULES_DIR="%1"                                          \
+%else                                                           \
+  GIO_MODULES_DIR="%{_libdir}/gio/modules"                      \
+%endif                                                          \
+%if "%{_lib}" == "lib64"                                        \
+  %{_bindir}/gio-querymodules-64 "${GIO_MODULES_DIR}"           \
+%else                                                           \
+  %{_bindir}/gio-querymodules "${GIO_MODULES_DIR}"              \
+%endif
+
+# On uninstall, update the cache. Note: we ignore upgrades (already
+# handled in %post of the new package).
+%glib2_gio_module_postun()                                      \
+if [ $1 -eq 0 ]; then                                           \
+  %if "x%1" != "x%%1"                                           \
+    GIO_MODULES_DIR="%1"                                        \
+  %else                                                         \
+    GIO_MODULES_DIR="%{_libdir}/gio/modules"                    \
+  %endif                                                        \
+  %if "%_lib" == "lib64"                                        \
+    %{_bindir}/gio-querymodules-64 "${GIO_MODULES_DIR}"         \
+  %else                                                         \
+    %{_bindir}/gio-querymodules "${GIO_MODULES_DIR}"            \
+  %endif                                                        \
+fi
diff --git a/packaging/q_quark_block_size.patch b/packaging/q_quark_block_size.patch
new file mode 100644 (file)
index 0000000..88542f1
--- /dev/null
@@ -0,0 +1,13 @@
+diff --git a/glib/gquark.c b/glib/gquark.c
+index 2a0861094..d18ac89c5 100644
+--- a/glib/gquark.c
++++ b/glib/gquark.c
+@@ -42,7 +42,7 @@
+ #include "glib_trace.h"
+ #include "glib-init.h"
+
+-#define QUARK_BLOCK_SIZE         2048
++#define QUARK_BLOCK_SIZE         32
+ #define QUARK_STRING_BLOCK_SIZE (4096 - sizeof (gsize))
+
+ static inline GQuark  quark_new (gchar *string);
diff --git a/packaging/test-runner.c b/packaging/test-runner.c
new file mode 100644 (file)
index 0000000..4312726
--- /dev/null
@@ -0,0 +1,532 @@
+/*
+ * This file contains standalone test-runner.
+ * This file is NOT part of GLib project.
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ * Author: Kazimierz Krosman <k.krosman@samsung.com>
+ *
+ * MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <ctype.h>
+#include <time.h>
+#include <sys/select.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <assert.h>
+#include <stdbool.h>
+
+#define MAX_TC_NUM 1024
+#define MAX_BUFFER (64*1024)
+#define MAX_COMMENT 1024
+
+enum {
+        INIT_TEST,
+        NEW_STDOUT,
+        NEW_STDERR,
+        RESULT_CODE,
+        RESULT_SIGNAL,
+        RESULT_ERROR,
+        RESULT_TIMEOUT
+};
+
+struct test_result {
+        bool is_positive;
+        char comment[MAX_COMMENT];
+        char result[MAX_COMMENT];
+        char name[MAX_COMMENT];
+};
+
+struct test_case {
+        const char* name;
+        const char* description;
+};
+
+struct binary {
+        const char* path;
+        const char* name;
+        struct test_case* test_cases;
+        int timeout;
+
+        char** (*prepare_args) (const struct binary* b, const char* test_name);
+        void (*parse) (const struct binary* b, const char* test_name, char* buffer, int state_change, int state_option);
+        int (*init)(void);
+        int (*clean)(void);
+};
+
+char* get_test_id(char* dest, const struct binary* b, const char* test_name);
+void add_test_result(const char* test_id, const char* result, const char* comment, int res);
+
+enum {
+        PIPE_READ,
+        PIPE_WRITE,
+};
+
+void parse_test_state(const struct binary* b, const char* test_name, char* buffer, int state_change, int state_option);
+void parse_one_test_one_binary(const struct binary* b, const char* test_name, char* buffer, int state_change, int state_option);
+char** prepare_args_for_binary(const struct binary* b, const char* test_name);
+
+static struct test_case test_case_desc_01[] = {
+        {"", "Checks if the library supports format of addresses described in the D-Bus specification (key/value pairs for each transport are valid)"},
+        {NULL, NULL}
+};
+
+static struct test_case test_case_desc_02[] = {
+        {"", "Test case for GNOME #662395"},
+        {NULL, NULL}
+};
+
+static struct test_case test_case_desc_03[] = {
+        {"", "Test flushing connection with g_dbus_connection_flush_sync() function"},
+        {NULL, NULL}
+};
+
+static struct test_case test_case_desc_04[] = {
+        {"", "Test 'lock' and 'copy' operations on GDBusMessage object"},
+        {NULL, NULL}
+};
+
+static struct test_case test_case_desc_05[] = {
+        {"", "Test 'non-socket' connections (connection via pipes and GIOStreams objects)"},
+        {NULL, NULL}
+};
+
+static struct test_case test_case_desc_06[] = {
+        {"", "Test overflowing socket buffer in producer/consumer scenario (UNIX sockets as a transport mechanism)"},
+        {NULL, NULL}
+};
+
+static struct test_case test_case_desc_07[] = {
+        {"", "Test that peer-to-peer connections work"},
+        {NULL, NULL}
+};
+
+static struct test_case test_case_desc_08[] = {
+        {"", "Test that peer-to-peer connections work (using GDBusObjectManagerServer and GDBusObjectManager objects)"},
+        {NULL, NULL}
+};
+
+/* This table is used to start binaries */
+struct binary tests[] = {
+        /*path, name, TC_table, timeout in us, prepare_args_handler, parse_function_handler, init_handler, clean_handler*/
+        {"/usr/lib/dbus-tests/test-suites/glib-tests/gdbus-addresses",               "gdbus-addresses",               test_case_desc_01, 5000*1000, prepare_args_for_binary, parse_one_test_one_binary, NULL, NULL},
+        {"/usr/lib/dbus-tests/test-suites/glib-tests/gdbus-connection-flush",        "gdbus-connection-flush",        test_case_desc_02, 5000*1000, prepare_args_for_binary, parse_one_test_one_binary, NULL, NULL},
+        {"/usr/lib/dbus-tests/test-suites/glib-tests/gdbus-connection-flush-helper", "gdbus-connection-flush-helper", test_case_desc_03, 5000*1000, prepare_args_for_binary, parse_one_test_one_binary, NULL, NULL},
+        {"/usr/lib/dbus-tests/test-suites/glib-tests/gdbus-message",                 "gdbus-message",                 test_case_desc_04, 5000*1000, prepare_args_for_binary, parse_one_test_one_binary, NULL, NULL},
+        {"/usr/lib/dbus-tests/test-suites/glib-tests/gdbus-non-socket",              "gdbus-non-socket",              test_case_desc_05, 5000*1000, prepare_args_for_binary, parse_one_test_one_binary, NULL, NULL},
+        {"/usr/lib/dbus-tests/test-suites/glib-tests/gdbus-overflow",                "gdbus-overflow",                test_case_desc_06, 5000*1000, prepare_args_for_binary, parse_one_test_one_binary, NULL, NULL},
+        {"/usr/lib/dbus-tests/test-suites/glib-tests/gdbus-peer",                    "gdbus-peer",                    test_case_desc_07, 5000*1000, prepare_args_for_binary, parse_one_test_one_binary, NULL, NULL},
+        {"/usr/lib/dbus-tests/test-suites/glib-tests/gdbus-peer-object-manager",     "gdbus-peer-object-manager",     test_case_desc_08, 5000*1000, prepare_args_for_binary, parse_one_test_one_binary, NULL, NULL},
+};
+
+static char* args[3];
+char** prepare_args_for_binary(const struct binary* b, const char* test_name)
+{
+        args[0] = (char*)b->name;
+        args[1] = NULL;
+        return args;
+}
+
+void parse_one_test_one_binary(const struct binary* b, const char* test_name, char* buffer, int state_change, int state_option)
+{
+        char test_id[MAX_COMMENT];
+
+        switch(state_change) {
+        case INIT_TEST:
+                break;
+        case NEW_STDOUT:
+                buffer[state_option] = 0;
+                get_test_id(test_id, b, test_name);
+                fprintf(stderr, "[stdout][%s]%s\n",test_id, buffer);
+                break;
+        case NEW_STDERR:
+                buffer[state_option] = 0;
+                get_test_id(test_id, b, test_name);
+                fprintf(stderr, "[stderr][%s]%s\n",test_id, buffer);
+                break;
+        case RESULT_CODE:
+                get_test_id(test_id, b, test_name);
+                if (state_option == 0)
+                        add_test_result(test_id, "PASS", "", 1);
+                else if (state_option == 77)
+                        add_test_result(test_id, "SKIP", "", 0);
+                else
+                        add_test_result(test_id, "FAIL", "", 0);
+                break;
+        case RESULT_SIGNAL:
+                get_test_id(test_id, b, test_name);
+                add_test_result(test_id, "FAIL", "Finished by SIGNAL", 0);
+                break;
+        case RESULT_TIMEOUT:
+                get_test_id(test_id, b, test_name);
+                add_test_result(test_id, "FAIL", "Test TIMEOUT", 0);
+                break;
+        }
+}
+
+static struct option long_options[] = {
+        {"list",        no_argument,       0, 'l'},
+        {"run",         required_argument, 0, 'r'},
+        {"description", required_argument, 0, 'd'},
+        {0,             0,                 0,  0 }
+};
+
+static int stdin_pipe[2];
+static int stdout_pipe[2];
+static int stderr_pipe[2];
+static int gravedigger_pipe[2];
+static char buffer[MAX_BUFFER];
+static const char* requested_tc[MAX_TC_NUM];
+
+char* get_test_id(char* dest, const struct binary* b, const char* test_name)
+{
+        int len = strlen(b->name);
+        memcpy(dest, b->name, len);
+        memcpy(dest + len, test_name, strlen(test_name)+1);
+        return dest;
+}
+
+static void print_description(const char* name, const char* description)
+{
+        printf("%s;%s\n",name, description);
+}
+
+static void print_list(const char* test_name)
+{
+        unsigned int i;
+        char full_name[MAX_COMMENT];
+        for (i = 0;i < sizeof(tests)/sizeof(struct binary); i++) {
+                int j = 0;
+                int l = strlen(tests[i].name);
+                memcpy(full_name, tests[i].name, l+1);
+                if (test_name && strncmp(test_name, full_name, l) != 0)
+                        continue;
+
+                while (tests[i].test_cases[j].name) {
+                        memcpy(full_name + l, tests[i].test_cases[j].name, strlen(tests[i].test_cases[j].name) + 1);
+                        if (!test_name || strncmp(full_name, test_name, sizeof(full_name)) == 0)
+                                print_description(full_name,tests[i].test_cases[j].description);
+                        j++;
+                }
+        }
+}
+
+
+static void stop_binary(const struct binary* b, pid_t pid, const char* test_name, int w_res)
+{
+        int status = 0;
+        int res = 0;
+        if (w_res == 0)
+                res = waitpid(pid, &status, WNOHANG);
+        else
+                res = waitpid(pid, &status, 0);
+
+        if (res == 0) {
+                //timeouted
+                kill(pid, SIGKILL);
+                res = waitpid(pid, &status, WNOHANG);
+                b->parse(b, test_name, buffer, RESULT_TIMEOUT, res);
+        } else if (res < 0) {
+                //errno check
+                kill(pid, SIGKILL);
+                res = waitpid(pid, &status, WNOHANG);
+                b->parse(b, test_name, buffer, RESULT_ERROR, res);
+        } else if (res > 0) {
+                if (WIFEXITED(status)) {
+                        b->parse(b, test_name, buffer, RESULT_CODE, WEXITSTATUS(status));
+                } else if (WIFSIGNALED(status)) {
+                        b->parse(b, test_name, buffer, RESULT_SIGNAL, WTERMSIG(status));
+                } else if (WIFSTOPPED(status)) {
+                        b->parse(b, test_name, buffer, RESULT_SIGNAL, WSTOPSIG(status));
+        } else if (WIFCONTINUED(status)) {
+                        kill(pid, SIGKILL);
+                        b->parse(b, test_name, buffer, RESULT_SIGNAL, -1);
+                }
+        }
+}
+
+static void parse_output_with_timeout(const struct binary* b, pid_t pid, const char* test_name)
+{
+        struct timeval tv;
+        fd_set rfds;
+        int nfds;
+        int res;
+        int w_res = 0;
+        tv.tv_sec = b->timeout/(1000*1000);
+        tv.tv_usec = (b->timeout-tv.tv_sec*1000*1000);
+        while (1) {
+                FD_ZERO(&rfds);
+                if (stdout_pipe[PIPE_READ] > -1) {
+                        assert(stdout_pipe[PIPE_READ] > -1);
+                        assert(stdout_pipe[PIPE_READ] < 1024);
+                        FD_SET(stdout_pipe[PIPE_READ], &rfds);
+                }
+                if (stderr_pipe[PIPE_READ] > -1) {
+                        assert(stderr_pipe[PIPE_READ] > -1);
+                        assert(stderr_pipe[PIPE_READ] < 1024);
+                        FD_SET(stderr_pipe[PIPE_READ], &rfds);
+                }
+                FD_SET(gravedigger_pipe[PIPE_READ], &rfds);
+
+                nfds = select(FD_SETSIZE, &rfds, NULL, NULL, &tv);
+                if (nfds == -1) {
+                        if (errno != EINTR) {
+                                w_res = 0;
+                                break;
+                        }
+                } else if (nfds > 0) {
+                        if (stdout_pipe[PIPE_READ] > -1 && FD_ISSET(stdout_pipe[PIPE_READ], &rfds)) {
+                                res = read(stdout_pipe[PIPE_READ], buffer, MAX_BUFFER-1);
+                                if (res == 0 || (res < 0 && errno != EINTR)) {
+                                        close (stdout_pipe[PIPE_READ]);
+                                        stdout_pipe[PIPE_READ] = -1;
+                                        continue;
+                                } else if (res >=0) {
+                                        b->parse(b, test_name, buffer, NEW_STDOUT, res);
+                                }
+                        }
+
+                        if (stderr_pipe[PIPE_READ] > -1 && FD_ISSET(stderr_pipe[PIPE_READ], &rfds)) {
+                                res = read(stderr_pipe[PIPE_READ], buffer, MAX_BUFFER-1);
+                                if (res == 0 || (res < 0 && errno != EINTR)) {
+                                        close (stderr_pipe[PIPE_READ]);
+                                        stderr_pipe[PIPE_READ] = -1;
+                                        continue;
+                                }
+                                b->parse(b, test_name, buffer, NEW_STDERR, res);
+                        }
+
+                        if (FD_ISSET(gravedigger_pipe[PIPE_READ], &rfds)) {
+                                w_res = 1;
+                                break; //it has ended
+                        }
+                } else {
+                        //timeout
+                        w_res = 0;
+                        break;
+                }
+        }
+        stop_binary(b, pid, test_name, w_res);
+}
+
+static int create_child(const char* path, char* const arguments[])
+{
+        int child;
+        int nResult;
+        if (pipe(gravedigger_pipe) < 0) {
+                perror("allocating pipe for gravedigger failed");
+                goto error1;
+        }
+
+        if (pipe(stdin_pipe) < 0) {
+                perror("allocating pipe for child input redirect failed");
+                goto error1;
+        }
+
+        if (pipe(stdout_pipe) < 0) {
+                perror("allocating pipe for child output redirect failed");
+                goto error2;
+        }
+
+        if (pipe(stderr_pipe) < 0) {
+                perror("allocating pipe for child output redirect failed");
+                goto error3;
+        }
+
+        child = fork();
+        if (!child) {
+                char ld_path[512];
+                sprintf(ld_path, "/usr/lib/dbus-tests/test-suites/glib-tests/:");
+                // redirect stdin
+                if (dup2(stdin_pipe[PIPE_READ], STDIN_FILENO) == -1) {
+                        perror("redirecting stdin failed");
+                        return -1;
+                }
+
+                if (dup2(stdout_pipe[PIPE_WRITE], STDOUT_FILENO) == -1) {
+                        perror("redirecting stdout failed");
+                        return -1;
+                }
+
+                if (dup2(stderr_pipe[PIPE_WRITE], STDERR_FILENO) == -1) {
+                        perror("redirecting stderr failed");
+                        return -1;
+                }
+
+                close(stdin_pipe[PIPE_READ]);
+                close(stdin_pipe[PIPE_WRITE]);
+                close(stdout_pipe[PIPE_READ]);
+                close(stdout_pipe[PIPE_WRITE]);
+                close(stderr_pipe[PIPE_READ]);
+                close(stderr_pipe[PIPE_WRITE]);
+                close(gravedigger_pipe[PIPE_READ]);
+
+                char* ld_path_b = getenv("LD_LIBRARY_PATH");
+                if (ld_path_b != NULL)
+                        memcpy(ld_path + strlen(ld_path), ld_path_b, strlen(ld_path_b)+1);
+                setenv("LD_LIBRARY_PATH", ld_path, 1);
+                setenv("G_TEST_SRCDIR", "/usr/lib/dbus-tests/test-suites/glib-tests", 1);
+
+                // run child process image
+                nResult = execv(path, arguments);
+
+                // if we get here at all, an error occurred, but we are in the child
+                // process, so just exit
+                perror("exec of the child process  failed");
+                exit(nResult);
+        } else if (child > 0) {
+                // close unused file descriptors, these are for child only
+                close(stdin_pipe[PIPE_READ]);
+                close(stdout_pipe[PIPE_WRITE]);
+                close(stderr_pipe[PIPE_WRITE]);
+                close(gravedigger_pipe[PIPE_WRITE]);
+        } else {
+                // failed to create child
+                goto error4;
+        }
+
+        return child;
+
+error4:
+        close(stderr_pipe[PIPE_READ]);
+        close(stderr_pipe[PIPE_WRITE]);
+error3:
+        close(stdout_pipe[PIPE_READ]);
+        close(stdout_pipe[PIPE_WRITE]);
+error2:
+        close(stdin_pipe[PIPE_READ]);
+        close(stdin_pipe[PIPE_WRITE]);
+error1:
+        return -1;
+}
+
+static void run_test(const struct binary* b, const char* test_name)
+{
+        int res = -1;
+        char** arg;
+        char test_id[MAX_COMMENT];
+
+        assert(b);
+        assert(b->name);
+        assert(b->path);
+        assert(test_name);
+
+        arg = b->prepare_args(b, test_name);
+
+        if (b->init)
+                if (!b->init()) {
+                        add_test_result(get_test_id(test_id, b, test_name), "ERROR", "Cannot init test", 0);
+                        return;
+                }
+
+        res = create_child(b->path, arg);
+        if (res > 0)
+                parse_output_with_timeout(b, res, test_name);
+        else
+                add_test_result(get_test_id(test_id, b, test_name), "ERROR", "Cannot start test", 0);
+
+        if (b->clean)
+                b->clean();
+}
+
+static void parse_run_test(const char* tc) {
+        unsigned int i = 0;
+        for (i = 0;i < sizeof(tests)/sizeof(struct binary); i++) {
+                int len = strlen(tests[i].name);
+                if (strncmp(tc, tests[i].name, len) == 0) {
+                        if (tc[len] == '*' || tc[len] == '\0')
+                                run_test(&tests[i], "");
+            else
+                                run_test(&tests[i], tc + len);
+                }
+        }
+}
+
+static int parse_option(int argc, char* argv[])
+{
+        int ch = 0;
+        int c = 0;
+        while ((ch = getopt_long(argc, argv, "lr:d:", long_options, NULL)) != -1) {
+                switch (ch) {
+                case 'l':
+                        print_list(NULL);
+                        return 1;
+                case 'r':
+                        if (c >= MAX_TC_NUM - 1) //NULL at the end
+                                return 0;
+
+                        if (optarg)
+                                requested_tc[c++] = optarg;
+
+                        break;
+                case 'd':
+                        print_list(optarg);
+            return 1;
+                }
+        }
+        return 0;
+}
+
+void add_test_result(const char* test_id, const char* result, const char* comment, int res)
+{
+       printf("%s;%s;%s\n", test_id, result, comment);
+       fflush(stdout);
+}
+
+static void prepare_results(void)
+{
+}
+
+int main(int argc, char* argv[])
+{
+        unsigned int i;
+        signal(SIGPIPE, SIG_IGN);
+        if (parse_option(argc, argv))
+                return 0;
+
+        prepare_results();
+
+        if (!requested_tc[0]) {
+                for (i = 0;i < sizeof(tests)/sizeof(struct binary); i++)
+                    run_test(&tests[i], "");
+        } else {
+                i = 0;
+                while(requested_tc[i]) {
+                    parse_run_test(requested_tc[i]);
+                        i++;
+                }
+        }
+
+        return 0;
+}
diff --git a/tests/gobject/.gitignore b/tests/gobject/.gitignore
deleted file mode 100644 (file)
index 120092d..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-accumulator
-defaultiface
-dynamictype
-gvalue-test
-ifacecheck
-ifaceinherit
-ifaceinit
-ifaceproperties
-override
-paramspec-test
-performance
-performance-threaded
-references
-signals
-singleton