Merge 2.53.2 into tizen
authorAdrian Szyndela <adrian.s@samsung.com>
Fri, 17 Jan 2020 11:14:16 +0000 (12:14 +0100)
committerAdrian Szyndela <adrian.s@samsung.com>
Fri, 17 Jan 2020 11:14:16 +0000 (12:14 +0100)
Change-Id: If32a06713d2d82d60b99b1480cdffc48aeb4a4de

94 files changed:
NEWS
autogen.sh
configure.ac
docs/reference/glib/glib-sections.txt
docs/reference/glib/gvariant-text.xml
gio/Makefile.am
gio/gapplicationimpl-dbus.c
gio/gdbus-2.0/codegen/codegen.py
gio/gdbusactiongroup.h
gio/gdbusaddress.c
gio/gdbusaddress.h
gio/gdbusauth.c
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/gfile.c
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/tests/Makefile.am
gio/tizen_header_glib.h [new file with mode: 0644]
glib/Makefile.am
glib/gbytes.c
glib/gbytes.h
glib/gfileutils.c
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/gmarkup.c
glib/gmessages.c
glib/gmessages.h
glib/grand.c
glib/gslice.c
glib/gtestutils.c
glib/gtestutils.h
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/tests/bytes.c
glib/tests/gvariant.c
gobject/Makefile.am
m4macros/glibtests.m4
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/test-runner.c [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 59b5910..b47d723 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1191,6 +1191,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
 ===================================
index 4bbc00d..77e1f4b 100755 (executable)
@@ -30,7 +30,7 @@ fi
 # regenerated from their corresponding *.in files by ./configure anyway.
 touch README INSTALL
 
-autoreconf --force --install --verbose || exit $?
+test -n "$NOAUTORECONF" || autoreconf --force --install --verbose || exit $?
 
 cd "$olddir"
 test -n "$NOCONFIGURE" || "$srcdir/configure" "$@"
index bd48088..9e0e0e3 100644 (file)
@@ -256,6 +256,10 @@ AC_ARG_ENABLE(rebuilds,
               [AS_HELP_STRING([--disable-rebuilds],
                               [disable all source autogeneration rules])],,
               [enable_rebuilds=yes])
+AC_ARG_ENABLE(libdbuspolicy,
+              [AS_HELP_STRING([--enable-libdbuspolicy],
+                              [enable libdbuspolicy for kdbus transport [default=no]])],,
+              [enable_libdbuspolicy=no])
 
 GLIB_TESTS
 
@@ -273,6 +277,16 @@ AS_IF([test "x$disable_mem_pools" = "xno"], [
   AC_MSG_RESULT([yes])
 ])
 
+AC_MSG_CHECKING([whether to enable libdbuspolicy for kdbus transport])
+AM_CONDITIONAL(LIBDBUSPOLICY, [test "x$enable_libdbuspolicy" = "xyes"])
+AS_IF([test "x$enable_libdbuspolicy" = "xyes"], [
+  PKG_CHECK_MODULES(LIBDBUSPOLICY1, libdbuspolicy1 >= 1)
+  AC_SUBST(LIBDBUSPOLICY1_CFLAGS)
+  AC_SUBST(LIBDBUSPOLICY1_LIBS)
+  AC_DEFINE(LIBDBUSPOLICY, 1, [Whether to enable libdbuspolicy for kdbus transport])
+  AC_MSG_RESULT([yes])
+], [ AC_MSG_RESULT([no]) ])
+
 dnl location to install runtime libraries, e.g. ../../lib to install
 dnl to /lib if libdir is /usr/lib
 AC_ARG_WITH(runtime-libdir,
@@ -708,7 +722,7 @@ AC_CHECK_HEADERS([sys/param.h sys/resource.h mach/mach_time.h])
 AC_CHECK_HEADERS([sys/select.h stdint.h inttypes.h sched.h malloc.h])
 AC_CHECK_HEADERS([sys/vfs.h sys/vmount.h sys/statfs.h sys/statvfs.h sys/filio.h])
 AC_CHECK_HEADERS([mntent.h sys/mnttab.h sys/vfstab.h sys/mntctl.h fstab.h])
-AC_CHECK_HEADERS([linux/magic.h])
+AC_CHECK_HEADERS([linux/magic.h linux/memfd.h sys/prctl.h])
 AC_CHECK_HEADERS([termios.h])
 
 # Some versions of MSC lack these
@@ -2634,6 +2648,43 @@ AS_IF([ test "x$use_gcov" = "xyes"], [
   LDFLAGS="$LDFLAGS -lgcov"
 ])
 
+dnl ************************************
+dnl *** Enable gcov (without lcov) coverage reports ***
+dnl ************************************
+
+AC_ARG_ENABLE(gcov-coverage,
+  AS_HELP_STRING([--enable-gcov-coverage],
+                [enable coverage testing with gcov, without lcov]),
+  [use_only_gcov=$enableval], [use_only_gcov=no])
+
+AS_IF([ test "x$use_only_gcov" = "xyes"], [
+  dnl we need gcc:
+  if test "$GCC" != "yes"; then
+    AC_MSG_ERROR([GCC is required for --enable-gcov-coverage])
+  fi
+
+  dnl Check if ccache is being used
+  AC_CHECK_PROG(SHTOOL, shtool, shtool)
+  case `$SHTOOL path $CC` in
+    *ccache*[)] gcc_ccache=yes;;
+    *[)] gcc_ccache=no;;
+  esac
+
+  if test "$gcc_ccache" = "yes" && (test -z "$CCACHE_DISABLE" || test "$CCACHE_DISABLE" != "1"); then
+    AC_MSG_ERROR([ccache must be disabled when --enable-coverage option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.])
+  fi
+
+  dnl Remove all optimization flags from CFLAGS
+  changequote({,})
+  CFLAGS=`echo "$CFLAGS" | $SED -e 's/-Wl,-O[0-9]*//g'`
+  CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'`
+  changequote([,])
+
+  dnl Add the special gcc flags
+  CFLAGS="$CFLAGS -O0 -fprofile-arcs -ftest-coverage"
+  LDFLAGS="$LDFLAGS -lgcov"
+])
+
 dnl ******************************
 dnl *** output the whole stuff ***
 dnl ******************************
@@ -3286,7 +3337,7 @@ AC_SUBST(DBUS1_LIBS)
 AM_CONDITIONAL(HAVE_DBUS1, [test "x$have_dbus1" = "xyes"])
 
 AC_CHECK_PROGS([DBUS_DAEMON], [dbus-daemon])
-AM_CONDITIONAL([HAVE_DBUS_DAEMON], [test x$DBUS_DAEMON = xdbus-daemon ])
+AM_CONDITIONAL([HAVE_DBUS_DAEMON], [test x$DBUS_DAEMON = xdbus-daemon || test x$FORCE_DBUS_TESTS = x1 ])
 
 # Check whether MSVC toolset is explicitly set
 AM_CONDITIONAL(MSVC_BASE_NO_TOOLSET_SET, [test x$MSVC_BASE_TOOLSET = x])
index e09d4d3..3f445c2 100644 (file)
@@ -1063,6 +1063,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
@@ -2164,6 +2166,7 @@ GUnixFDSourceFunc
 g_unix_fd_add
 g_unix_fd_add_full
 g_unix_fd_source_new
+g_unix_fd_ensure_zero_copy_safe
 
 <SUBSECTION Private>
 g_unix_error_quark
@@ -2605,11 +2608,13 @@ 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_size
+g_bytes_get_zero_copy_fd
 g_bytes_hash
 g_bytes_equal
 g_bytes_compare
@@ -3113,6 +3118,7 @@ g_test_rand_double
 g_test_rand_double_range
 
 g_assert
+g_assert_se
 g_assert_not_reached
 
 g_assert_cmpstr
index da80d17..8522334 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
index 67db1b7..324a774 100644 (file)
@@ -28,7 +28,7 @@ AM_CPPFLAGS = \
        $(gmodule_INCLUDES)                             \
        $(GLIB_DEBUG_FLAGS)                             \
        -DGIO_COMPILATION                               \
-       -DGIO_MODULE_DIR=\"$(GIO_MODULE_DIR)\"  
+       -DGIO_MODULE_DIR=\"$(GIO_MODULE_DIR)\"
 
 AM_CFLAGS = $(GLIB_WARN_CFLAGS)
 
@@ -226,6 +226,10 @@ appinfo_sources =
 appinfo_headers =
 contenttype_sources =
 
+if LIBDBUSPOLICY
+platform_libadd += $(LIBDBUSPOLICY1_LIBS)
+endif
+
 if HAVE_INOTIFY
 SUBDIRS += inotify
 platform_libadd += inotify/libinotify.la
@@ -261,6 +265,10 @@ endif
 
 unix_sources = \
        gfiledescriptorbased.c  \
+       gkdbus.c                \
+       gkdbus.h                \
+       gkdbusfakedaemon.c      \
+       gkdbusfakedaemon.h      \
        gunixconnection.c       \
        gunixcredentialsmessage.c       \
        gunixfdlist.c           \
@@ -613,6 +621,10 @@ libgio_2_0_la_CFLAGS += $(LIBMOUNT_CFLAGS)
 libgio_2_0_la_LIBADD += $(LIBMOUNT_LIBS)
 endif
 
+if LIBDBUSPOLICY
+libgio_2_0_la_CPPFLAGS += $(LIBDBUSPOLICY1_CFLAGS)
+endif
+
 libgio_2_0_la_DEPENDENCIES = $(gio_win32_res) $(gio_def) $(platform_deps)
 
 gio-win32-res.o: gio.rc
@@ -724,6 +736,7 @@ gio_headers =                       \
        gzlibdecompressor.h     \
        glistmodel.h            \
        gliststore.h            \
+       tizen_header_glib.h     \
        $(application_headers)  \
        $(settings_headers)     \
        $(gdbus_headers)        \
@@ -796,6 +809,7 @@ glib_compile_resources_LDADD = libgio-2.0.la                \
        $(top_builddir)/gmodule/libgmodule-2.0.la       \
        $(top_builddir)/glib/libglib-2.0.la             \
        $(NULL)
+glib_compile_resources_LDFLAGS = -pie
 
 glib_compile_resources_SOURCES = \
        gvdb/gvdb-format.h              \
@@ -809,11 +823,13 @@ gio_querymodules_LDADD     = libgio-2.0.la                \
        $(top_builddir)/gmodule/libgmodule-2.0.la       \
        $(top_builddir)/glib/libglib-2.0.la             \
        $(NULL)
+gio_querymodules_LDFLAGS        = -pie
 
 gconstructor_as_data.h: $(top_srcdir)/glib/gconstructor.h data-to-c.pl
        $(AM_V_GEN) $(srcdir)/data-to-c.pl $(top_srcdir)/glib/gconstructor.h gconstructor_code > $@.tmp && mv $@.tmp $@
 
 glib_compile_schemas_LDADD = $(top_builddir)/glib/libglib-2.0.la
+glib_compile_schemas_LDFLAGS = -pie
 glib_compile_schemas_SOURCES = \
        gconstructor_as_data.h \
        gvdb/gvdb-format.h              \
@@ -826,6 +842,7 @@ gsettings_LDADD = libgio-2.0.la                     \
        $(top_builddir)/gmodule/libgmodule-2.0.la       \
        $(top_builddir)/glib/libglib-2.0.la             \
        $(NULL)
+gsettings_LDFLAGS = -pie
 gsettings_SOURCES = gsettings-tool.c
 
 schemadir = $(datadir)/glib-2.0/schemas
@@ -878,6 +895,7 @@ gdbus_LDADD = libgio-2.0.la                                 \
        $(top_builddir)/gmodule/libgmodule-2.0.la       \
        $(top_builddir)/glib/libglib-2.0.la             \
        $(NULL)
+gdbus_LDFLAGS = -pie
 
 if OS_UNIX
 if !OS_COCOA
@@ -890,6 +908,7 @@ gapplication_LDADD = libgio-2.0.la                  \
        $(top_builddir)/gmodule/libgmodule-2.0.la       \
        $(top_builddir)/glib/libglib-2.0.la             \
        $(NULL)
+gapplication_LDFLAGS = -pie
 endif
 endif
 
@@ -912,6 +931,7 @@ gresource_LDADD = libgio-2.0.la                             \
        $(top_builddir)/gmodule/libgmodule-2.0.la       \
        $(top_builddir)/glib/libglib-2.0.la             \
        $(LIBELF_LIBS)
+gresource_LDFLAGS = -pie
 
 # ------------------------------------------------------------------------
 # gio tool
@@ -941,6 +961,7 @@ gio_LDADD = libgio-2.0.la                           \
        $(top_builddir)/gobject/libgobject-2.0.la       \
        $(top_builddir)/glib/libglib-2.0.la             \
        $(NULL)
+gio_LDFLAGS = -pie
 
 # ------------------------------------------------------------------------
 # ------ MSVC Project File Generation ------
index 94cf6ea..bbe6a51 100644 (file)
@@ -346,8 +346,7 @@ g_application_impl_attempt_primary (GApplicationImpl  *impl,
     NULL /* set_property */
   };
   GApplicationClass *app_class = G_APPLICATION_GET_CLASS (impl->app);
-  GVariant *reply;
-  guint32 rval;
+  GBusRequestNameReplyFlags rval;
 
   if (org_gtk_Application == NULL)
     {
@@ -425,19 +424,13 @@ g_application_impl_attempt_primary (GApplicationImpl  *impl,
    * in the case that we can't do that.
    */
   /* DBUS_NAME_FLAG_DO_NOT_QUEUE: 0x4 */
-  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, 0x4), G_VARIANT_TYPE ("(u)"),
-                                       0, -1, cancellable, error);
+  rval = g_dbus_request_name (impl->session_bus, impl->bus_name, G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE, 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);
 
   return TRUE;
 }
@@ -479,10 +472,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;
     }
 }
@@ -852,13 +842,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;
index f9f404c..ab9ced4 100644 (file)
@@ -1003,7 +1003,7 @@ class CodeGenerator:
                     %(i.name_lower, i.camel_name), False))
             self.write_gtkdoc_deprecated_and_since_and_close(i, self.c, 0)
             self.c.write('guint\n'
-                         '%s_override_properties (GObjectClass *klass, guint property_id_begin)\n'
+                         '%s_override_properties (GObjectClass *klass G_GNUC_UNUSED, guint property_id_begin)\n'
                          '{\n'%(i.name_lower))
             for p in i.properties:
                 self.c.write ('  g_object_class_override_property (klass, property_id_begin++, "%s");\n'%(p.name_hyphen))
@@ -1540,7 +1540,7 @@ class CodeGenerator:
             self.write_gtkdoc_deprecated_and_since_and_close(m, self.c, 0)
             self.c.write('void\n'
                          '%s_complete_%s (\n'
-                         '    %s *object,\n'
+                         '    %s *object G_GNUC_UNUSED,\n'
                          '    GDBusMethodInvocation *invocation'%(i.name_lower, m.name_lower, i.camel_name))
             if unix_fd:
                 self.c.write(',\n    GUnixFDList *fd_list')
@@ -1626,9 +1626,9 @@ class CodeGenerator:
         # laid out in the same order as introspection data pointers
         #
         self.c.write('static void\n'
-                     '%s_proxy_get_property (GObject      *object,\n'
-                     '  guint         prop_id,\n'
-                     '  GValue       *value,\n'
+                     '%s_proxy_get_property (GObject      *object G_GNUC_UNUSED,\n'
+                     '  guint         prop_id G_GNUC_UNUSED,\n'
+                     '  GValue       *value G_GNUC_UNUSED,\n'
                      '  GParamSpec   *pspec G_GNUC_UNUSED)\n'
                      '{\n'%(i.name_lower))
         if len(i.properties) > 0:
@@ -1679,9 +1679,9 @@ class CodeGenerator:
             self.c.write('}\n'
                          '\n')
         self.c.write('static void\n'
-                     '%s_proxy_set_property (GObject      *object,\n'
-                     '  guint         prop_id,\n'
-                     '  const GValue *value,\n'
+                     '%s_proxy_set_property (GObject      *object G_GNUC_UNUSED,\n'
+                     '  guint         prop_id G_GNUC_UNUSED,\n'
+                     '  const GValue *value G_GNUC_UNUSED,\n'
                      '  GParamSpec   *pspec G_GNUC_UNUSED)\n'
                      '{\n'%(i.name_lower))
         if len(i.properties) > 0:
@@ -1875,7 +1875,7 @@ class CodeGenerator:
                      '\n')
 
         self.c.write('static void\n'
-                     '%s_proxy_iface_init (%sIface *iface)\n'
+                     '%s_proxy_iface_init (%sIface *iface G_GNUC_UNUSED)\n'
                      '{\n'%(i.name_lower, i.camel_name))
         for p in i.properties:
             self.c.write('  iface->get_%s = %s_proxy_get_%s;\n'%(p.name_lower, i.name_lower, p.name_lower))
@@ -2328,7 +2328,7 @@ class CodeGenerator:
                          %(i.name_lower))
 
         self.c.write('static void\n'
-                     '%s_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton)\n'
+                     '%s_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton G_GNUC_UNUSED)\n'
                      '{\n'
                      %(i.name_lower))
         if len(i.properties) > 0:
@@ -2658,7 +2658,7 @@ class CodeGenerator:
                      '\n')
 
         self.c.write('static void\n'
-                     '%s_skeleton_iface_init (%sIface *iface)\n'
+                     '%s_skeleton_iface_init (%sIface *iface G_GNUC_UNUSED)\n'
                      '{\n'
                      %(i.name_lower, i.camel_name))
         for s in i.signals:
index 9407d82..1b5eda3 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 9b3619c..0854788 100644 (file)
@@ -42,6 +42,7 @@
 #include "gstdio.h"
 
 #ifdef G_OS_UNIX
+#include "gkdbus.h"
 #include <unistd.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -529,8 +530,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);
@@ -540,14 +542,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;
 
@@ -559,6 +562,29 @@ g_dbus_address_connect (const gchar   *address_entry,
     {
     }
 #ifdef G_OS_UNIX
+  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);
+        }
+    }
   else if (g_strcmp0 (transport_name, "unix") == 0)
     {
       const gchar *path;
@@ -649,7 +675,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;
         }
@@ -684,7 +710,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)
         {
@@ -737,7 +763,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,
@@ -757,13 +783,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;
@@ -780,6 +807,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);
@@ -937,7 +965,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;
@@ -964,6 +1010,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);
@@ -1039,6 +1086,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
@@ -1579,6 +1650,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",
@@ -1611,7 +1683,7 @@ g_dbus_address_get_for_bus_sync (GBusType       bus_type,
       ret = g_strdup (g_getenv ("DBUS_SYSTEM_BUS_ADDRESS"));
       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;
 
@@ -1619,7 +1691,11 @@ g_dbus_address_get_for_bus_sync (GBusType       bus_type,
       ret = g_strdup (g_getenv ("DBUS_SESSION_BUS_ADDRESS"));
       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 fb62836..8e6aa82 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 a4458b2..2b8c83c 100644 (file)
@@ -1302,9 +1302,9 @@ _g_dbus_auth_run_server (GDBusAuth              *auth,
                                                     &line_length,
                                                     cancellable,
                                                     error);
-          debug_print ("SERVER: WaitingForBegin, read '%s'", line);
           if (line == NULL)
             goto out;
+          debug_print ("SERVER: WaitingForBegin, read '%s'", line);
           if (g_strcmp0 (line, "BEGIN") == 0)
             {
               /* YAY, done! */
index 5e78976..e76da12 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 8263419..9dd59a9
 #include "gtask.h"
 
 #ifdef G_OS_UNIX
+#include "gkdbus.h"
 #include "gunixconnection.h"
 #include "gunixfdmessage.h"
 #endif
@@ -388,6 +389,10 @@ struct _GDBusConnection
    */
   GDBusWorker *worker;
 
+#ifdef G_OS_UNIX
+  GKDBusWorker *kdbus_worker;
+#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
@@ -625,6 +630,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);
@@ -632,6 +638,15 @@ 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
+  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
   else
     {
       if (alive_connections != NULL)
@@ -1101,6 +1116,17 @@ g_dbus_connection_init (GDBusConnection *connection)
   connection->filters = g_ptr_array_new ();
 }
 
+#ifdef G_OS_UNIX
+gboolean
+_g_dbus_connection_is_kdbus (GDBusConnection *connection)
+{
+  if (connection->kdbus_worker)
+    return TRUE;
+  else
+    return FALSE;
+}
+#endif
+
 /**
  * g_dbus_connection_get_stream:
  * @connection: a #GDBusConnection
@@ -1147,8 +1173,14 @@ 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
+  else if (connection->kdbus_worker)
+    _g_kdbus_worker_unfreeze (connection->kdbus_worker);
+#endif
+  else
+    g_assert_not_reached ();
 }
 
 /**
@@ -1317,11 +1349,20 @@ 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
+  else if (connection->kdbus_worker != NULL)
+    {
+      ret = _g_kdbus_worker_flush_sync (connection->kdbus_worker);
+    }
+#endif
+  else
+    g_assert_not_reached();
 
  out:
   return ret;
@@ -1421,7 +1462,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
@@ -1444,11 +1485,20 @@ g_dbus_connection_close (GDBusConnection     *connection,
   if (!check_initialized (connection))
     return;
 
-  g_assert (connection->worker != NULL);
-
   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);
+  if (connection->worker)
+    {
+      _g_dbus_worker_close (connection->worker, task);
+    }
+#ifdef G_OS_UNIX
+  else if (connection->kdbus_worker)
+    {
+      _g_kdbus_worker_close (connection->kdbus_worker, task);
+    }
+#endif
+  else
+    g_assert_not_reached();
   g_object_unref (task);
 }
 
@@ -1547,6 +1597,628 @@ g_dbus_connection_close_sync (GDBusConnection  *connection,
 /* ---------------------------------------------------------------------------------------------------- */
 
 /**
+ * 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
+  if (connection->kdbus_worker)
+    return _g_kdbus_RequestName (connection->kdbus_worker, name, flags, error);
+#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
+  if (connection->kdbus_worker)
+    return _g_kdbus_ReleaseName (connection->kdbus_worker, name, error);
+#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
+  if (connection->kdbus_worker)
+    return _g_kdbus_AddMatch (connection->kdbus_worker, match_rule, error);
+#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
+  if (connection->kdbus_worker)
+    return _g_kdbus_RemoveMatch (connection->kdbus_worker, match_rule, error);
+#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
+  if (connection->kdbus_worker)
+    return _g_kdbus_GetBusId (connection->kdbus_worker, error);
+#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
+      if (connection->kdbus_worker)
+        return _g_kdbus_GetListQueuedOwners (connection->kdbus_worker, name, error);
+#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
+      if (connection->kdbus_worker)
+        return _g_kdbus_GetListNames (connection->kdbus_worker, list_name_type, error);
+#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
+  if (connection->kdbus_worker)
+    return _g_kdbus_GetNameOwner (connection->kdbus_worker, name, error);
+#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
+  if (connection->kdbus_worker)
+    return _g_kdbus_GetConnectionUnixProcessID (connection->kdbus_worker, name, error);
+#endif
+
+  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);
+    }
+
+  return pid;
+}
+
+/**
+ * g_dbus_get_connection_uid:
+ * @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 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.
+ *
+ * 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
+ */
+uid_t
+g_dbus_get_connection_uid (GDBusConnection  *connection,
+                           const gchar      *name,
+                           GError          **error)
+{
+  GVariant *result;
+  uid_t uid;
+
+  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;
+  uid = -1;
+
+#ifdef G_OS_UNIX
+  if (connection->kdbus_worker)
+    return _g_kdbus_GetConnectionUnixUser (connection->kdbus_worker, name, error);
+#endif
+
+  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_start_service_by_name:
+ * @connection: a #GDBusConnection
+ * @name: name of the service to start
+ * @flags: (currently not used)
+ * @error: return location for error or %NULL
+ *
+ * Synchronously tries to launch the executable associated
+ * with a @name.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: status code or %G_BUS_START_SERVICE_REPLY_ERROR
+ *     if @error is set.
+ *
+ * Since: 2.44
+ */
+GBusStartServiceReplyFlags
+g_dbus_start_service_by_name (GDBusConnection  *connection,
+                              const gchar      *name,
+                              guint32           flags,
+                              GError          **error)
+{
+  GVariant *result;
+  guint32 ret;
+
+  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;
+  ret = G_BUS_START_SERVICE_REPLY_ERROR;
+
+#ifdef G_OS_UNIX
+  if (connection->kdbus_worker)
+    return _g_kdbus_StartServiceByName (connection->kdbus_worker, name, flags, NULL, error);
+#endif
+
+  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 (GBusStartServiceReplyFlags) ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
  * g_dbus_connection_get_last_serial:
  * @connection: a #GDBusConnection
  *
@@ -1584,7 +2256,8 @@ g_dbus_connection_send_message_unlocked (GDBusConnection   *connection,
                                          GDBusMessage      *message,
                                          GDBusSendMessageFlags flags,
                                          volatile guint32  *out_serial,
-                                         GError           **error)
+                                         GError           **error,
+                                         gint timeout_msec)
 {
   guchar *blob;
   gsize blob_size;
@@ -1614,31 +2287,39 @@ g_dbus_connection_send_message_unlocked (GDBusConnection   *connection,
                        error))
     goto out;
 
-  blob = g_dbus_message_to_blob (message,
-                                 &blob_size,
-                                 connection->capabilities,
-                                 error);
-  if (blob == NULL)
-    goto out;
+  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);
@@ -1661,17 +2342,25 @@ 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);
-  _g_dbus_worker_send_message (connection->worker,
-                               message,
-                               (gchar*) blob,
-                               blob_size);
-  blob = NULL; /* since _g_dbus_worker_send_message() steals the blob */
+  if (connection->worker)
+    {
+      _g_dbus_worker_send_message (connection->worker,
+                                   message,
+                                   (gchar*) blob,
+                                   blob_size);
+    }
+#ifdef G_OS_UNIX
+  else if (connection->kdbus_worker)
+    {
+      ret = _g_kdbus_worker_send_message (connection->kdbus_worker, message, timeout_msec, error);
+    }
+#endif
+  else
+    g_assert_not_reached ();
 
-  ret = TRUE;
+  blob = NULL; /* since _g_dbus_worker_send_message() steals the blob */
 
  out:
   g_free (blob);
@@ -1728,7 +2417,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, out_serial, error);
+  ret = g_dbus_connection_send_message_unlocked (connection, message, flags, out_serial, error, -1);
   CONNECTION_UNLOCK (connection);
   return ret;
 }
@@ -1901,9 +2590,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,
@@ -1916,7 +2602,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);
@@ -1932,9 +2618,14 @@ 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
+        /* Userspace timeouts unnecessary on unix/kdbus - kdbus handles timeouts. */
+        && !connection->kdbus_worker
+#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);
@@ -1974,7 +2665,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.
@@ -2134,32 +2825,100 @@ 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
+  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_dbus_message_lock (message);
 
-  g_main_context_pop_thread_default (data.context);
+      if (out_serial != NULL)
+        *out_serial = serial_to_use;
 
-  g_main_context_unref (data.context);
-  g_main_loop_unref (data.loop);
-  if (data.res)
-    g_object_unref (data.res);
+      CONNECTION_UNLOCK (connection);
+
+      /* 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 */
+  else
+    g_assert_not_reached ();
 
+out:
   return reply;
 }
 
@@ -2216,8 +2975,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;
@@ -2236,7 +2994,23 @@ 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
+  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
 
   g_object_ref (message);
   g_dbus_message_lock (message);
@@ -2314,8 +3088,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;
@@ -2387,10 +3160,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;
@@ -2452,6 +3224,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
@@ -2489,6 +3262,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) ||
@@ -2501,12 +3276,20 @@ 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
+      else if (G_IS_KDBUS_WORKER (ret))
+        connection->kdbus_worker = G_KDBUS_WORKER (ret);
+#endif
+      else
+        g_assert_not_reached ();
     }
   else if (connection->stream != NULL)
     {
@@ -2517,6 +3300,20 @@ initable_init (GInitable     *initable,
       g_assert_not_reached ();
     }
 
+#ifdef G_OS_UNIX
+  /* 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
+
   /* Authenticate the connection */
   if (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER)
     {
@@ -2555,6 +3352,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);
@@ -2575,13 +3374,32 @@ initable_init (GInitable     *initable,
   g_hash_table_insert (alive_connections, connection, 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
+  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
+  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)
@@ -2598,25 +3416,46 @@ 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
+      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
+      else
+        g_assert_not_reached ();
     }
 
+#ifdef G_OS_UNIX
+  if (connection->kdbus_worker && !initially_frozen)
+    _g_kdbus_worker_unfreeze (connection->kdbus_worker);
+#endif
+
   ret = TRUE;
  out:
   if (!ret)
@@ -3233,6 +4072,8 @@ typedef struct
 {
   GDBusSignalCallback callback;
   gpointer user_data;
+  GFunc user_data_ref_func;
+  GFunc user_data_unref_func;
   GDestroyNotify user_data_free_func;
   guint id;
   GMainContext *context;
@@ -3314,7 +4155,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);
@@ -3346,7 +4188,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
@@ -3393,7 +4236,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.
  *
@@ -3435,6 +4278,34 @@ g_dbus_connection_signal_subscribe (GDBusConnection     *connection,
                                     gpointer             user_data,
                                     GDestroyNotify       user_data_free_func)
 {
+  return g_dbus_connection_signal_subscribe_with_ref (connection,
+                                                      sender,
+                                                      interface_name,
+                                                      member,
+                                                      object_path,
+                                                      arg0,
+                                                      flags,
+                                                      callback,
+                                                      user_data,
+                                                      NULL,
+                                                      NULL,
+                                                      user_data_free_func);
+}
+
+guint
+g_dbus_connection_signal_subscribe_with_ref (GDBusConnection             *connection,
+                                             const gchar                 *sender,
+                                             const gchar                 *interface_name,
+                                             const gchar                 *member,
+                                             const gchar                 *object_path,
+                                             const gchar                 *arg0,
+                                             GDBusSignalFlags            flags,
+                                             GDBusSignalCallback         callback,
+                                             gpointer                    user_data,
+                                             GFunc                       user_data_ref_func,
+                                             GFunc                       user_data_unref_func,
+                                             GDestroyNotify              user_data_free_func)
+{
   gchar *rule;
   SignalData *signal_data;
   SignalSubscriber subscriber;
@@ -3483,6 +4354,8 @@ g_dbus_connection_signal_subscribe (GDBusConnection     *connection,
   subscriber.user_data_free_func = user_data_free_func;
   subscriber.id = g_atomic_int_add (&_global_subscriber_id, 1); /* TODO: overflow etc. */
   subscriber.context = g_main_context_ref_thread_default ();
+  subscriber.user_data_ref_func = user_data_ref_func;
+  subscriber.user_data_unref_func = user_data_unref_func;
 
   /* see if we've already have this rule */
   signal_data = g_hash_table_lookup (connection->map_rule_to_signal_data, rule);
@@ -3516,8 +4389,58 @@ 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
+      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
+      else
+        g_assert_not_reached ();
     }
 
   signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array,
@@ -3592,7 +4515,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)
             {
@@ -3602,7 +4524,19 @@ 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
+              else if (connection->kdbus_worker)
+                {
+                  _g_kdbus_RemoveMatch (connection->kdbus_worker, signal_data->rule, NULL);
+                }
+#endif
+              else
+                g_assert_not_reached ();
             }
 
           signal_data_free (signal_data);
@@ -3669,6 +4603,8 @@ typedef struct
   guint                subscription_id;
   GDBusSignalCallback  callback;
   gpointer             user_data;
+  GFunc                user_data_ref_func;
+  GFunc                user_data_unref_func;
   GDBusMessage        *message;
   GDBusConnection     *connection;
   const gchar         *sender;
@@ -3695,7 +4631,7 @@ emit_signal_instance_in_idle_cb (gpointer data)
     }
   else
     {
-      g_variant_ref_sink (parameters);
+      g_variant_ref (parameters);
     }
 
 #if 0
@@ -3713,17 +4649,25 @@ emit_signal_instance_in_idle_cb (gpointer data)
   has_subscription = FALSE;
   if (g_hash_table_lookup (signal_instance->connection->map_id_to_signal_data,
                            GUINT_TO_POINTER (signal_instance->subscription_id)) != NULL)
-    has_subscription = TRUE;
+    {
+      if (signal_instance->user_data_ref_func)
+        signal_instance->user_data_ref_func (signal_instance->user_data, 0);
+      has_subscription = TRUE;
+    }
   CONNECTION_UNLOCK (signal_instance->connection);
 
   if (has_subscription)
-    signal_instance->callback (signal_instance->connection,
-                               signal_instance->sender,
-                               signal_instance->path,
-                               signal_instance->interface,
-                               signal_instance->member,
-                               parameters,
-                               signal_instance->user_data);
+    {
+      signal_instance->callback (signal_instance->connection,
+                                 signal_instance->sender,
+                                 signal_instance->path,
+                                 signal_instance->interface,
+                                 signal_instance->member,
+                                 parameters,
+                                 signal_instance->user_data);
+      if (signal_instance->user_data_unref_func)
+        signal_instance->user_data_unref_func (signal_instance->user_data, 0);
+    }
 
   g_variant_unref (parameters);
 
@@ -3859,6 +4803,8 @@ schedule_callbacks (GDBusConnection *connection,
           signal_instance->subscription_id = subscriber->id;
           signal_instance->callback = subscriber->callback;
           signal_instance->user_data = subscriber->user_data;
+          signal_instance->user_data_ref_func = subscriber->user_data_ref_func;
+          signal_instance->user_data_unref_func = subscriber->user_data_unref_func;
           signal_instance->message = g_object_ref (message);
           signal_instance->connection = g_object_ref (connection);
           signal_instance->sender = sender;
@@ -4265,7 +5211,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;
@@ -4277,7 +5223,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;
@@ -4288,7 +5234,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;
@@ -4309,7 +5255,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;
@@ -4413,7 +5359,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;
@@ -4621,7 +5567,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;
@@ -4811,7 +5757,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);
 
@@ -4937,7 +5883,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;
@@ -4969,7 +5915,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);
@@ -5081,7 +6027,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.
  *
@@ -5645,6 +6591,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:
@@ -6898,7 +7854,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);
 }
 
@@ -6931,7 +7887,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);
 }
 
@@ -6958,7 +7914,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);
 }
@@ -7095,7 +8051,7 @@ distribute_method_call (GDBusConnection *connection,
                                            _("No such interface '%s' on object at path %s"),
                                            interface_name,
                                            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:
@@ -7386,3 +8342,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 7aa1256..4a80c17 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,42 +81,94 @@ 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;
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -121,15 +176,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;
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -137,15 +192,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;
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -154,7 +209,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,
@@ -163,11 +218,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,
@@ -175,7 +230,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;
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -186,7 +241,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,
@@ -199,11 +254,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,
@@ -215,7 +270,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,
@@ -229,12 +284,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,
@@ -248,7 +303,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;
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -400,7 +455,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,
@@ -408,10 +463,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;
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -538,10 +593,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;
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -577,10 +632,23 @@ 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
+guint            g_dbus_connection_signal_subscribe_with_ref  (GDBusConnection     *connection,
+                                                               const gchar         *sender,
+                                                               const gchar         *interface_name,
+                                                               const gchar         *member,
+                                                               const gchar         *object_path,
+                                                               const gchar         *arg0,
+                                                               GDBusSignalFlags     flags,
+                                                               GDBusSignalCallback  callback,
+                                                               gpointer             user_data,
+                                                               GFunc                user_data_ref_func,
+                                                               GFunc                user_data_unref_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;
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -667,11 +735,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 c6bc754..da724a1 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 d6316b3..dd05b0b 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 45307fe..fb2d149 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 edaf63e..0191ab5 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 05ae93b..fe7e469 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 6f62afb..2548325 100644 (file)
@@ -2697,7 +2697,6 @@ g_dbus_message_to_blob (GDBusMessage          *message,
   if (message->body != NULL)
     {
       gchar *tupled_signature_str;
-      tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
       if (signature == NULL)
         {
           g_set_error (error,
@@ -2705,10 +2704,10 @@ g_dbus_message_to_blob (GDBusMessage          *message,
                        G_IO_ERROR_INVALID_ARGUMENT,
                        _("Message body has signature “%s” but there is no signature header"),
                        signature_str);
-          g_free (tupled_signature_str);
           goto out;
         }
-      else if (g_strcmp0 (tupled_signature_str, g_variant_get_type_string (message->body)) != 0)
+      tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
+      if (g_strcmp0 (tupled_signature_str, g_variant_get_type_string (message->body)) != 0)
         {
           g_set_error (error,
                        G_IO_ERROR,
@@ -3638,3 +3637,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 bd3e8e9..e079afa 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 69dc435..79c4796 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 6354e41..c01a64e 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,63 +35,68 @@ G_BEGIN_DECLS
 #define G_IS_DBUS_METHOD_INVOCATION(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DBUS_METHOD_INVOCATION))
 
 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 a9cedcb..7e2f99a 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 14603c5..6ac4aa8
@@ -112,6 +112,20 @@ client_unref (Client *client)
     }
 }
 
+static void
+client_ref_func (gpointer user_data, gpointer unused)
+{
+  if (user_data)
+    client_ref ((Client*)user_data);
+}
+
+static void
+client_unref_func (gpointer user_data, gpointer unused)
+{
+  if (user_data)
+    client_unref ((Client*)user_data);
+}
+
 /* ---------------------------------------------------------------------------------------------------- */
 
 typedef enum
@@ -285,9 +299,6 @@ on_name_owner_changed (GDBusConnection *connection,
   const gchar *old_owner;
   const gchar *new_owner;
 
-  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)
@@ -303,7 +314,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;
@@ -312,12 +323,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:
   ;
 }
@@ -339,6 +356,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);
@@ -355,10 +379,10 @@ get_name_owner_cb (GObject      *source_object,
       call_vanished_handler (client, FALSE);
     }
 
-  client->initialized = TRUE;
-
+ out:
   if (result != NULL)
     g_variant_unref (result);
+
   client_unref (client);
 }
 
@@ -413,7 +437,6 @@ start_service_by_name_cb (GObject      *source_object,
         {
           g_warning ("Unexpected reply %d from StartServiceByName() method", start_service_result);
           call_vanished_handler (client, FALSE);
-          client->initialized = TRUE;
         }
     }
   else
@@ -447,16 +470,19 @@ has_connection (Client *client)
                                                              client);
 
   /* start listening to NameOwnerChanged messages immediately */
-  client->name_owner_changed_subscription_id = g_dbus_connection_signal_subscribe (client->connection,
-                                                                                   "org.freedesktop.DBus",  /* name */
-                                                                                   "org.freedesktop.DBus",  /* if */
-                                                                                   "NameOwnerChanged",      /* signal */
-                                                                                   "/org/freedesktop/DBus", /* path */
-                                                                                   client->name,
-                                                                                   G_DBUS_SIGNAL_FLAGS_NONE,
-                                                                                   on_name_owner_changed,
-                                                                                   client,
-                                                                                   NULL);
+  client->name_owner_changed_subscription_id
+    = g_dbus_connection_signal_subscribe_with_ref (client->connection,
+                                                   "org.freedesktop.DBus",  /* name */
+                                                   "org.freedesktop.DBus",  /* if */
+                                                   "NameOwnerChanged",      /* signal */
+                                                   "/org/freedesktop/DBus", /* path */
+                                                   client->name,
+                                                   G_DBUS_SIGNAL_FLAGS_NONE,
+                                                   on_name_owner_changed,
+                                                   client,
+                                                   client_ref_func,
+                                                   client_unref_func,
+                                                   NULL);
 
   if (client->flags & G_BUS_NAME_WATCHER_FLAGS_AUTO_START)
     {
index bdc7d32..6757a83 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 b408e2e..e173fa8 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 0ba8671..c1395f3 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 24327bf..9298d9f 100644 (file)
@@ -1096,7 +1096,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);
@@ -1122,22 +1121,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)
@@ -1207,19 +1191,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;
     }
@@ -1541,6 +1515,13 @@ add_interfaces (GDBusObjectManagerClient *manager,
       g_variant_unref (properties);
     }
 
+  if (added)
+    {
+      g_hash_table_insert (manager->priv->map_object_path_to_object_proxy,
+                           g_strdup (object_path),
+                           op);
+    }
+
   g_mutex_unlock (&manager->priv->lock);
 
   /* now that we don't hold the lock any more, emit signals */
@@ -1554,12 +1535,8 @@ add_interfaces (GDBusObjectManagerClient *manager,
   g_list_free (interface_added_signals);
 
   if (added)
-    {
-      g_hash_table_insert (manager->priv->map_object_path_to_object_proxy,
-                           g_strdup (object_path),
-                           op);
-      g_signal_emit_by_name (manager, "object-added", op);
-    }
+    g_signal_emit_by_name (manager, "object-added", op);
+
   g_object_unref (manager);
   g_object_unref (op);
 }
index e7986b6..eef3f31 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 6debf59..b1a5cc9 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 d0bc233..f3fec5a 100644 (file)
@@ -468,7 +468,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
@@ -476,7 +476,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 *
@@ -485,7 +485,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, message, worker->user_data);
+    ret = worker->message_about_to_be_sent_callback (message, worker->user_data);
   else
     ret = message;
   return ret;
index b1f4890..6c9319f 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);
 
@@ -144,6 +141,17 @@ void _g_dbus_object_proxy_remove_interface (GDBusObjectProxy *proxy,
 /* Implemented in gdbusconnection.c */
 GDBusConnection *_g_bus_get_singleton_if_exists (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 96c761b..41acde3 100644 (file)
@@ -2616,26 +2616,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 3dbe9cf..cf40f4e 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 f0beb85..7f3393c 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 4e17749..1ecc57b 100644 (file)
@@ -419,6 +419,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));
@@ -593,6 +598,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 fa64426..5d6320c 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_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;
 
 G_END_DECLS
 
index af0587b..73aa022 100644 (file)
@@ -3159,12 +3159,12 @@ file_copy_fallback (GFile                  *source,
         out = (GOutputStream*)_g_local_file_output_stream_replace (_g_local_file_get_filename (G_LOCAL_FILE (destination)),
                                                                    FALSE, NULL,
                                                                    flags & G_FILE_COPY_BACKUP,
-                                                                   G_FILE_CREATE_REPLACE_DESTINATION,
-                                                                   info,
+                                                                   G_FILE_CREATE_REPLACE_DESTINATION |
+                                                                   G_FILE_CREATE_PRIVATE, info,
                                                                    cancellable, error);
       else
         out = (GOutputStream*)_g_local_file_output_stream_create (_g_local_file_get_filename (G_LOCAL_FILE (destination)),
-                                                                  FALSE, 0, info,
+                                                                  FALSE, G_FILE_CREATE_PRIVATE, info,
                                                                   cancellable, error);
     }
   else if (flags & G_FILE_COPY_OVERWRITE)
@@ -3177,7 +3177,7 @@ file_copy_fallback (GFile                  *source,
     }
   else
     {
-      out = (GOutputStream *)g_file_create (destination, 0, cancellable, error);
+      out = (GOutputStream *)g_file_create (destination, G_FILE_CREATE_PRIVATE, cancellable, error);
     }
 
   if (!out)
index ee17370..d7b862e 100644 (file)
@@ -952,6 +952,7 @@ typedef enum
  * @G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT: Allow another message bus connection to claim the name.
  * @G_BUS_NAME_OWNER_FLAGS_REPLACE: If another message bus connection owns the name and have
  * specified #G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT, then take the name from the other connection.
+ * @G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE: Do not place message bus connection in a queue to own the name.
  *
  * Flags used in g_bus_own_name().
  *
@@ -961,10 +962,71 @@ typedef enum
 {
   G_BUS_NAME_OWNER_FLAGS_NONE = 0,                    /*< nick=none >*/
   G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT = (1<<0),  /*< nick=allow-replacement >*/
-  G_BUS_NAME_OWNER_FLAGS_REPLACE = (1<<1)            /*< nick=replace >*/
+  G_BUS_NAME_OWNER_FLAGS_REPLACE = (1<<1),            /*< nick=replace >*/
+  G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE = (1<<2)        /*< nick=do-not-queue >*/
 } GBusNameOwnerFlags;
 
 /**
+ * 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..9160f84
--- /dev/null
@@ -0,0 +1,4293 @@
+/* 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 <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;
+    }
+
+  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 != 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;
+        }
+    }
+
+  /* '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);
+       }
+    }
+}
+
+
+/*
+ * 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, *value;
+  gchar *sender;
+  guint i;
+  GVariant *parts[2];
+  GVariantIter *fields_iter;
+  GString *owned_name;
+  guint8 endianness, type, flags, version;
+  guint64 key, serial;
+
+  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);
+
+  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);
+
+  parts[0] = g_variant_get_child_value (body, 0);
+  parts[1] = g_variant_get_child_value (body, 1);
+  g_variant_unref (body);
+
+  g_variant_get (parts[0], "(yyyyuta{tv})", &endianness, &type, &flags, &version, NULL, &serial, &fields_iter);
+  g_variant_unref (parts[0]);
+
+  while (g_variant_iter_loop (fields_iter, "{tv}", &key, &value))
+    {
+      switch (key)
+        {
+          case G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL:
+            g_dbus_message_set_reply_serial (kmsg->message, (guint32) g_variant_get_uint64 (value));
+            continue;
+
+          default:
+            g_dbus_message_set_header (kmsg->message, key, value);
+            continue;
+        }
+    }
+
+  g_variant_iter_free (fields_iter);
+
+  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;
+  worker->attach_flags_recv = _KDBUS_ATTACH_ALL;
+
+  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 d159dbb..04ab94e 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 8ba7626..db43f23 100644 (file)
@@ -586,3 +586,30 @@ install-data-hook:
        $(AM_V_at) chmod a+x $(DESTDIR)$(installed_testdir)/x-content/win32-software/autorun.exe
 endif
 endif
+
+gdbus_addresses_LDFLAGS = -pie
+gdbus_auth_LDFLAGS = -pie
+gdbus_bz627724_LDFLAGS = -pie
+gdbus_close_pending_LDFLAGS = -pie
+gdbus_connection_LDFLAGS = -pie
+gdbus_connection_flush_LDFLAGS = -pie
+gdbus_connection_flush_helper_LDFLAGS = -pie
+gdbus_connection_loss_LDFLAGS = -pie
+gdbus_connection_slow_LDFLAGS = -pie
+gdbus_error_LDFLAGS = -pie
+gdbus_exit_on_close_LDFLAGS = -pie
+gdbus_export_LDFLAGS = -pie
+gdbus_introspection_LDFLAGS = -pie
+gdbus_message_LDFLAGS = -pie
+gdbus_names_LDFLAGS = -pie
+gdbus_non_socket_LDFLAGS = -pie
+gdbus_overflow_LDFLAGS = -pie
+gdbus_peer_LDFLAGS = -pie
+gdbus_peer_object_manager_LDFLAGS = -pie
+gdbus_proxy_LDFLAGS = -pie
+gdbus_proxy_threads_LDFLAGS = -pie
+gdbus_proxy_well_known_name_LDFLAGS = -pie
+gdbus_test_codegen_LDFLAGS = -pie
+gdbus_test_codegen_old_LDFLAGS = -pie
+gdbus_threading_LDFLAGS = -pie
+gdbus_unix_addresses_LDFLAGS = -pie
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__
index d755853..5b09685 100644 (file)
@@ -26,11 +26,11 @@ if HAVE_GOOD_PRINTF
 else
 PRINTF_SUBDIR = gnulib
 printf_la = gnulib/libgnulib.la
-endif 
+endif
 
 if USE_SYSTEM_PCRE
 else
-MAYBE_PCRE = pcre 
+MAYBE_PCRE = pcre
 endif
 
 SUBDIRS = libcharset $(PRINTF_SUBDIR) $(MAYBE_PCRE) update-pcre . tests
@@ -136,6 +136,7 @@ libglib_2_0_la_SOURCES =    \
        glib_trace.h            \
        glib-init.h             \
        glib-init.c             \
+       glib-linux.h            \
        glib-private.h          \
        glib-private.c          \
        glist.c                 \
@@ -197,6 +198,8 @@ libglib_2_0_la_SOURCES =    \
        gvariant-parser.c       \
        gvariant-serialiser.h   \
        gvariant-serialiser.c   \
+       gvariant-vectors.h      \
+       gvariant-vectors.c      \
        gvarianttypeinfo.h      \
        gvarianttypeinfo.c      \
        gvarianttype.c          \
@@ -410,12 +413,12 @@ if OS_WIN32
 if OS_WIN32_X64
 INSTALL_PROGS += gspawn-win64-helper gspawn-win64-helper-console
 gspawn_win64_helper_LDADD = libglib-2.0.la
-gspawn_win64_helper_LDFLAGS = -mwindows
+gspawn_win64_helper_LDFLAGS = -pie -mwindows
 gspawn_win64_helper_console_LDADD = libglib-2.0.la
 else
 INSTALL_PROGS += gspawn-win32-helper gspawn-win32-helper-console
 gspawn_win32_helper_LDADD = libglib-2.0.la
-gspawn_win32_helper_LDFLAGS = -mwindows
+gspawn_win32_helper_LDFLAGS = -pie -mwindows
 gspawn_win32_helper_console_LDADD = libglib-2.0.la
 endif
 endif
@@ -429,7 +432,8 @@ if OS_UNIX
 
 INSTALL_PROGS  += gtester
 gtester_SOURCES         = gtester.c
-gtester_LDADD   = libglib-2.0.la 
+gtester_LDADD   = libglib-2.0.la
+gtester_LDFLAGS         = -pie
 
 auto_config_binscripts = gtester-report
 bin_SCRIPTS = ${auto_config_binscripts}
index b9ca4eb..2cdf0e5 100644 (file)
 #include <glib/gmessages.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:
 
 struct _GBytes
 {
-  gconstpointer data;  /* may be NULL iff (size == 0) */
-  gsize size;  /* may be 0 */
-  gint ref_count;
-  GDestroyNotify free_func;
-  gpointer user_data;
+  gsize size;
+  gint  ref_count;
+  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;
+  bytes->ref_count = 1;
+  bytes->type_or_fd = type_or_fd;
+
+  return bytes;
+}
+
 /**
  * g_bytes_new:
  * @data: (transfer none) (array length=size) (element-type guint8) (nullable):
@@ -91,10 +161,74 @@ 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_memdup (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:
@@ -123,9 +257,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)
@@ -146,7 +284,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;
 }
 
 /**
@@ -177,18 +322,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;
-  bytes->ref_count = 1;
 
-  return (GBytes *)bytes;
+  return (GBytes *) bytes;
 }
 
 /**
@@ -217,7 +361,7 @@ g_bytes_new_from_bytes (GBytes  *bytes,
   g_return_val_if_fail (offset <= bytes->size, NULL);
   g_return_val_if_fail (offset + length <= bytes->size, NULL);
 
-  return g_bytes_new_with_free_func ((gchar *)bytes->data + offset, length,
+  return g_bytes_new_with_free_func ((gchar *) g_bytes_get_data (bytes, NULL) + offset, length,
                                      (GDestroyNotify)g_bytes_unref, g_bytes_ref (bytes));
 }
 
@@ -241,12 +385,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 ();
 }
 
 /**
@@ -268,6 +427,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:
@@ -306,9 +494,52 @@ g_bytes_unref (GBytes *bytes)
 
   if (g_atomic_int_dec_and_test (&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;
+          }
+        }
     }
 }
 
@@ -331,14 +562,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 &&
-         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;
 }
 
 /**
@@ -357,14 +596,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;
 }
@@ -387,42 +630,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)
-    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_int_get (&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
@@ -451,20 +675,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_memdup (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);
     }
 
index 24f1856..a53f581 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 ca330fa..705844b 100644 (file)
@@ -1280,7 +1280,7 @@ get_tmp_file (gchar            *tmpl,
     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
   static const int NLETTERS = sizeof (letters) - 1;
   glong value;
-  GTimeVal tv;
+  gint64 now_us;
   static int counter = 0;
 
   g_return_val_if_fail (tmpl != NULL, -1);
@@ -1295,8 +1295,8 @@ get_tmp_file (gchar            *tmpl,
     }
 
   /* Get some more or less random data.  */
-  g_get_current_time (&tv);
-  value = (tv.tv_usec ^ tv.tv_sec) + counter++;
+  now_us = g_get_real_time ();
+  value = ((now_us % G_USEC_PER_SEC) ^ (now_us / G_USEC_PER_SEC)) + counter++;
 
   for (count = 0; count < 100; value += 7777, ++count)
     {
index 6355f75..c96e1bc 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);
 }
 
 /* If adding a cleanup here, please also add a test case to
diff --git a/glib/glib-linux.h b/glib/glib-linux.h
new file mode 100644 (file)
index 0000000..e417584
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * 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__
+     /* arm and arm64 have the same value */
+#    define __NR_memfd_create 385
+#  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 3dbf744..ba1b0ac 100644 (file)
@@ -47,7 +47,11 @@ glib__private__ (void)
     g_dir_open_with_errno,
     g_dir_new_from_dirp,
 
-    glib_init,
+    g_variant_to_vectors,
+    g_variant_from_vectors,
+    g_variant_vectors_deinit,
+
+    glib_init
   };
 
   return &table;
index 198e07f..0f6a472 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <glib.h>
 #include "gwakeup.h"
+#include "gvariant-vectors.h"
 
 #if defined(__GNUC__)
 # define _g_alignof(type) (__alignof__ (type))
 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);
@@ -61,6 +69,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 d666a06..835e09c 100644 (file)
 
 #include <string.h>
 
+#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
@@ -421,3 +452,62 @@ g_unix_fd_add (gint              fd,
 {
   return g_unix_fd_add_full (G_PRIORITY_DEFAULT, fd, condition, function, user_data, NULL);
 }
+
+/**
+ * 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
+}
index 5546943..ab1cd1c 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);
+
 G_END_DECLS
 
 #endif  /* __G_UNIX_H__ */
index 46923b8..3bdb220 100644 (file)
@@ -557,11 +557,23 @@ char_str (gunichar c,
   return buf;
 }
 
+/* Format the next UTF-8 character as a gchar* for printing in error output
+ * when we encounter a syntax error. This correctly handles invalid UTF-8,
+ * emitting it as hex escapes. */
 static gchar*
 utf8_str (const gchar *utf8,
           gchar       *buf)
 {
-  char_str (g_utf8_get_char (utf8), buf);
+  gunichar c = g_utf8_get_char_validated (utf8, -1);
+  if (c == (gunichar) -1 || c == (gunichar) -2)
+    {
+      gchar *temp = g_strdup_printf ("\\x%02x", (guint)(guchar)*utf8);
+      memset (buf, 0, 8);
+      memcpy (buf, temp, strlen (temp));
+      g_free (temp);
+    }
+  else
+    char_str (c, buf);
   return buf;
 }
 
@@ -1832,9 +1844,14 @@ g_markup_parse_context_end_parse (GMarkupParseContext  *context,
     case STATE_AFTER_CLOSE_TAG_SLASH:
     case STATE_INSIDE_CLOSE_TAG_NAME:
     case STATE_AFTER_CLOSE_TAG_NAME:
-      set_error (context, error, G_MARKUP_ERROR_PARSE,
-                 _("Document ended unexpectedly inside the close tag for "
-                   "element '%s'"), current_element (context));
+      if (context->tag_stack != NULL)
+        set_error (context, error, G_MARKUP_ERROR_PARSE,
+                   _("Document ended unexpectedly inside the close tag for "
+                     "element “%s”"), current_element (context));
+      else
+        set_error (context, error, G_MARKUP_ERROR_PARSE,
+                   _("Document ended unexpectedly inside the close tag for an "
+                     "unopened element"));
       break;
 
     case STATE_INSIDE_PASSTHROUGH:
index eba1255..decaebd 100644 (file)
@@ -2119,7 +2119,8 @@ g_log_writer_is_journald (gint output_fd)
   static gsize initialized;
   static gboolean fd_is_journal = FALSE;
 
-  g_return_val_if_fail (output_fd >= 0, FALSE);
+  if (output_fd < 0)
+    return FALSE;
 
   if (g_once_init_enter (&initialized))
     {
index c923aea..754a072 100644 (file)
@@ -551,11 +551,50 @@ GPrintFunc      g_set_printerr_handler  (GPrintFunc      func);
  * 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.
+ * should therefore not depend on any side effects of @expr.  See
+ * g_return_if_fail_se() for a version that guarantees side effects.
  */
 #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.
@@ -591,6 +630,9 @@ GPrintFunc      g_set_printerr_handler  (GPrintFunc      func);
         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,                                       \
index 0cb833e..cb31b06 100644 (file)
@@ -49,6 +49,7 @@
 #include "gmem.h"
 #include "gtestutils.h"
 #include "gthread.h"
+#include "gtimer.h"
 
 #ifdef G_OS_UNIX
 #include <unistd.h>
@@ -220,7 +221,6 @@ g_rand_new (void)
   guint32 seed[4];
 #ifdef G_OS_UNIX
   static gboolean dev_urandom_exists = TRUE;
-  GTimeVal now;
 
   if (dev_urandom_exists)
     {
@@ -254,10 +254,10 @@ g_rand_new (void)
     }
 
   if (!dev_urandom_exists)
-    {  
-      g_get_current_time (&now);
-      seed[0] = now.tv_sec;
-      seed[1] = now.tv_usec;
+    {
+      gint64 now_us = g_get_real_time ();
+      seed[0] = now_us / G_USEC_PER_SEC;
+      seed[1] = now_us % G_USEC_PER_SEC;
       seed[2] = getpid ();
       seed[3] = getppid ();
     }
index 9022062..f201e6f 100644 (file)
@@ -596,9 +596,8 @@ magazine_cache_update_stamp (void)
 {
   if (allocator->stamp_counter >= MAX_STAMP_COUNTER)
     {
-      GTimeVal tv;
-      g_get_current_time (&tv);
-      allocator->last_stamp = tv.tv_sec * 1000 + tv.tv_usec / 1000; /* milli seconds */
+      gint64 now_us = g_get_real_time ();
+      allocator->last_stamp = now_us / 1000; /* milli seconds */
       allocator->stamp_counter = 0;
     }
   else
index e06256d..080528b 100644 (file)
  * The macro can be turned off in final releases of code by defining
  * `G_DISABLE_ASSERT` when compiling the application, so code must
  * not depend on any side effects from @expr.
+ *
+ * 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 99e237d..e8ce42a 100644 (file)
@@ -110,6 +110,7 @@ typedef void (*GTestFixtureFunc) (gpointer      fixture,
 #ifdef G_DISABLE_ASSERT
 #define g_assert_not_reached()          G_STMT_START { (void) 0; } G_STMT_END
 #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 { \
@@ -117,6 +118,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 8301250..bfaa671 100644 (file)
@@ -19,6 +19,7 @@
 #include "config.h"
 
 #include <glib/gvariant-core.h>
+#include "glib-private.h"
 
 #include <glib/gvariant-serialiser.h>
 #include <glib/gtestutils.h>
@@ -106,21 +107,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 serialised form for the instance, if it
- *       is known.  If the instance is in serialised 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 serialised form or holding a value in
@@ -259,6 +250,31 @@ g_variant_release_children (GVariant *value)
   g_free (value->contents.tree.children);
 }
 
+/* < 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 serialiser to
@@ -276,31 +292,19 @@ g_variant_release_children (GVariant *value)
  * instances are always in serialised form.  For these instances,
  * storing their serialised form merely involves a memcpy().
  *
- * Serialisation is a two-step process.  First, the size of the
- * serialised 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
- *   serialiser code to determine the size.  The serialiser is passed
- *   g_variant_fill_gvs() as a callback.
- *
- *   g_variant_fill_gvs() is called by the serialiser 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 serialiser 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 serialiser code to write
- *   the bytes to the container.  The serialiser is, again, passed
+ *   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 serialised
@@ -314,34 +318,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 serialisation 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 == (gssize) -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
@@ -386,9 +362,12 @@ g_variant_serialise (GVariant *value,
  *
  *  - reporting its type
  *
- *  - reporting its serialised size (requires knowing the size first)
+ *  - reporting its serialised size
  *
  *  - 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,
@@ -396,10 +375,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);
@@ -423,25 +398,19 @@ g_variant_fill_gvs (GVariantSerialised *serialised,
  *
  * Ensures that @value is in serialised form.
  *
- * If @value is in tree form then this function ensures that the
- * serialised size is known and then 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.
- *
- * 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);
 
@@ -451,12 +420,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
  *
@@ -467,104 +493,110 @@ 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;
   value->ref_count = 1;
 
   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.
+/* -- 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
  *
- * A reference is taken on @bytes.
+ * 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.
  *
- * Returns: (transfer none): a new #GVariant with a floating reference
+ * @children is consumed by this function.  g_free() will be called on
+ * it some time later.
  *
- * 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_from_children (GVariantTypeInfo  *type_info,
+                             GVariant         **children,
+                             gsize              n_children,
+                             gboolean           trusted)
 {
   GVariant *value;
-  guint alignment;
-  gsize size;
-
-  value = g_variant_alloc (type, TRUE, trusted);
-
-  value->contents.serialised.bytes = g_bytes_ref (bytes);
-
-  g_variant_type_info_query (value->type_info,
-                             &alignment, &size);
 
-  if (size && g_bytes_get_size (bytes) != 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
-       * fixed size).
-       */
-      value->contents.serialised.data = NULL;
-      value->size = size;
-    }
-  else
-    {
-      value->contents.serialised.data = g_bytes_get_data (bytes, &value->size);
-    }
+  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 -- */
-
 /* < 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
+ * 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.
  *
- * @children is consumed by this function.  g_free() will be called on
- * it some time later.
+ * @bytes is consumed by this function.  g_bytes_unref() 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)
+g_variant_new_serialised (GVariantTypeInfo *type_info,
+                          GBytes           *bytes,
+                          gconstpointer     data,
+                          gsize             size,
+                          gboolean          trusted)
 {
   GVariant *value;
+  gsize fixed_size;
 
-  value = g_variant_alloc (type, FALSE, trusted);
-  value->contents.tree.children = children;
-  value->contents.tree.n_children = n_children;
+  value = g_variant_alloc (type_info, TRUE, trusted);
+  value->contents.serialised.bytes = bytes;
+  value->contents.serialised.data = data;
+  value->size = size;
+
+  g_variant_type_info_query (value->type_info, NULL, &fixed_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 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 = fixed_size;
+    }
 
   return value;
 }
@@ -607,6 +639,191 @@ g_variant_is_trusted (GVariant *value)
   return (value->state & STATE_TRUSTED) != 0;
 }
 
+/* < 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;
+}
+
 /* -- public -- */
 
 /**
@@ -813,10 +1030,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;
 }
 
@@ -857,49 +1070,11 @@ 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 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)
-{
-  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 == 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:
@@ -926,9 +1101,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,
@@ -938,10 +1116,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;
 }
@@ -972,52 +1146,39 @@ GVariant *
 g_variant_get_child_value (GVariant *value,
                            gsize     index_)
 {
+  GVariant *child;
+
   g_return_val_if_fail (index_ < g_variant_n_children (value), 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);
-
-          return child;
-        }
 
+      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
+      };
+      GVariantSerialised s_child;
 
-  {
-    GVariantSerialised serialised = {
-      value->type_info,
-      (gpointer) value->contents.serialised.data,
-      value->size
-    };
-    GVariantSerialised s_child;
-    GVariant *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_);
-
-    /* create a new serialised 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;
-    child->ref_count = 1;
-    child->contents.serialised.bytes =
-      g_bytes_ref (value->contents.serialised.bytes);
-    child->contents.serialised.data = s_child.data;
-
-    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_);
+
+      /* 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;
+    }
+
+  return child;
 }
 
 /**
@@ -1044,19 +1205,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);
 }
 
 /**
@@ -1081,9 +1241,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->state & STATE_SERIALISED)
index 034dd43..f658ced 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);
+
 #endif /* __G_VARIANT_CORE_H__ */
index 3741acb..f786a5c 100644 (file)
@@ -458,7 +458,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)++;
@@ -619,6 +625,10 @@ ast_resolve (AST     *ast,
         pattern[j++] = 'i';
         break;
 
+      case 'D':
+        pattern[j++] = 'd';
+        break;
+
       default:
         pattern[j++] = pattern[i];
         break;
@@ -1249,7 +1259,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,
@@ -1795,7 +1805,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");
 }
@@ -1820,17 +1830,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)
@@ -1847,7 +1856,6 @@ number_get_value (AST                 *ast,
     }
   else
     {
-      floating = FALSE;
       negative = token[0] == '-';
       if (token[0] == '-')
         token++;
@@ -1883,10 +1891,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)
@@ -1928,6 +1933,12 @@ number_get_value (AST                 *ast,
         return number_overflow (ast, type, error);
       return g_variant_new_handle (negative ? -abs_val : 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);
     }
@@ -2213,6 +2224,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 5643cc1..1a196ae 100644 (file)
@@ -259,6 +259,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,
@@ -292,6 +313,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)
 {
@@ -350,6 +384,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,
@@ -384,6 +439,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)
 {
@@ -449,6 +518,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,
@@ -482,6 +584,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)
 {
@@ -552,8 +667,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
   {
@@ -688,6 +803,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,
@@ -747,6 +936,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)
 {
@@ -932,6 +1153,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,
@@ -1014,6 +1315,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)
 {
@@ -1139,59 +1529,92 @@ gvs_variant_n_children (GVariantSerialised value)
   return 1;
 }
 
+static GVariantTypeInfo *
+gvs_variant_find_type (const guchar *end_pointer,
+                       gsize         end_size,
+                       gsize         total_size,
+                       gsize        *child_size)
+{
+  gsize i;
+
+  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;
+
+        /* 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_is_definite (type))
+              {
+                GVariantTypeInfo *type_info;
+                gsize fixed_size;
+
+                type_info = g_variant_type_info_get (type);
+
+                g_variant_type_info_query (type_info, NULL, &fixed_size);
+
+                if (!fixed_size || fixed_size == total_size - i)
+                  {
+                    *child_size = total_size - i;
+
+                    return type_info;
+                  }
+
+                g_variant_type_info_unref (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, };
 
-  /* NOTE: not O(1) and impossible for it to be... */
-  if (value.size)
+  if ((child.type_info = gvs_variant_find_type (value.data + value.size, value.size, value.size, &child.size)))
     {
-      /* find '\0' character */
-      for (child.size = value.size - 1; child.size; child.size--)
-        if (value.data[child.size] == '\0')
-          break;
-
-      /* 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;
-
-          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))
-                {
-                  gsize fixed_size;
+      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 (type);
+  return child;
+}
 
-                  if (child.size != 0)
-                    /* only set to non-%NULL if size > 0 */
-                    child.data = value.data;
+static gboolean
+gvs_variant_unpack_all (GVariantTypeInfo *type_info,
+                        const guchar     *end_pointer,
+                        gsize             end_size,
+                        gsize             total_size,
+                        GArray           *unpacked_children)
+{
+  GVariantUnpacked unpacked;
 
-                  g_variant_type_info_query (child.type_info,
-                                             NULL, &fixed_size);
+  if ((unpacked.type_info = gvs_variant_find_type (end_pointer, end_size, total_size, &unpacked.size)))
+    {
+      unpacked.skip = 0;
 
-                  if (!fixed_size || fixed_size == child.size)
-                    return child;
+      g_array_append_val (unpacked_children, unpacked);
 
-                  g_variant_type_info_unref (child.type_info);
-                }
-            }
-        }
+      return TRUE;
     }
 
-  child.type_info = g_variant_type_info_get (G_VARIANT_TYPE_UNIT);
-  child.data = NULL;
-  child.size = 1;
-
-  return child;
+  return FALSE;
 }
 
 static inline gsize
@@ -1226,6 +1649,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)
 {
@@ -1435,7 +1875,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 2be3299..b248245 100644 (file)
@@ -22,6 +22,7 @@
 #define __G_VARIANT_SERIALISER_H__
 
 #include "gvarianttypeinfo.h"
+#include "gvariant-vectors.h"
 
 typedef struct
 {
@@ -30,6 +31,13 @@ typedef struct
   gsize             size;
 } GVariantSerialised;
 
+typedef struct
+{
+  GVariantTypeInfo *type_info;
+  gsize             skip;
+  gsize             size;
+} GVariantUnpacked;
+
 /* deserialisation */
 GLIB_AVAILABLE_IN_ALL
 gsize                           g_variant_serialised_n_children         (GVariantSerialised        container);
@@ -37,6 +45,12 @@ GLIB_AVAILABLE_IN_ALL
 GVariantSerialised              g_variant_serialised_get_child          (GVariantSerialised        container,
                                                                          gsize                     index);
 
+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);
@@ -70,4 +84,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 579f569..75cda00 100644 (file)
  * 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.
@@ -314,14 +314,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);
 }
 
 /**
@@ -368,7 +364,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) \
@@ -593,6 +589,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
  *
@@ -642,8 +663,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);
@@ -656,6 +677,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)
     {
@@ -666,14 +689,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);
 }
 
 /**
@@ -719,7 +738,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_memdup (&value, sizeof value),
                                       1, g_variant_is_trusted (value));
 }
@@ -775,10 +794,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);
@@ -792,6 +811,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++)
     {
@@ -800,11 +821,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 >
@@ -855,10 +872,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);
@@ -873,11 +890,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 >
@@ -915,6 +931,7 @@ GVariant *
 g_variant_new_dict_entry (GVariant *key,
                           GVariant *value)
 {
+  GVariantTypeInfo *type_info;
   GVariantType *dict_type;
   GVariant **children;
   gboolean trusted;
@@ -928,10 +945,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);
 }
 
 /**
@@ -1107,6 +1124,7 @@ g_variant_lookup_value (GVariant           *dictionary,
  * - %G_VARIANT_TYPE_BOOLEAN: #guchar (not #gboolean!)
  * - %G_VARIANT_TYPE_BYTE: #guchar
  * - %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,
@@ -1558,7 +1576,7 @@ g_variant_new_strv (const gchar * const *strv,
   for (i = 0; i < length; 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, TRUE);
 }
 
@@ -1694,7 +1712,7 @@ g_variant_new_objv (const gchar * const *strv,
   for (i = 0; i < length; 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, TRUE);
 }
 
@@ -1934,7 +1952,7 @@ g_variant_new_bytestring_array (const gchar * const *strv,
   for (i = 0; i < length; 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, TRUE);
 }
 
@@ -2144,6 +2162,8 @@ 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_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.
@@ -2549,6 +2569,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];
@@ -2673,6 +2719,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;
 
@@ -2792,7 +2839,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
@@ -2863,6 +2910,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);
@@ -3700,7 +3755,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),
@@ -4281,8 +4336,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':
@@ -4945,6 +5000,7 @@ g_variant_valist_skip_leaf (const gchar **str,
       va_arg (*app, guint64);
       return;
 
+    case 'f':
     case 'd':
       va_arg (*app, gdouble);
       return;
@@ -4990,6 +5046,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));
 
@@ -5000,6 +5059,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
@@ -5073,6 +5133,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;
@@ -5095,6 +5159,7 @@ g_variant_valist_get_leaf (const gchar **str,
         case 'u':
         case 'h':
         case 'b':
+        case 'f':
           *(guint32 *) ptr = 0;
           return;
 
@@ -5818,6 +5883,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));
 
@@ -5880,8 +5948,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,
@@ -5977,21 +6044,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 5ffd8fc..de22a6c 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 e36c1c1..e2bec05 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.
@@ -240,7 +242,7 @@ g_variant_type_string_scan (const gchar  *string,
 
     case '{':
       if (string == limit || *string == '\0' ||                    /* { */
-          !strchr ("bynqihuxtdsog?", *string++) ||                 /* key */
+          !strchr ("bynqihuxtfdsog?", *string++) ||                /* key */
           !g_variant_type_string_scan (string, limit, &string) ||  /* value */
           string == limit || *string++ != '}')                     /* } */
         return FALSE;
@@ -252,7 +254,7 @@ g_variant_type_string_scan (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':
       break;
 
     default:
@@ -533,8 +535,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.
  *
@@ -564,6 +566,7 @@ g_variant_type_is_basic (const GVariantType *type)
     case 'u':
     case 't':
     case 'x':
+    case 'f':
     case 'd':
     case 's':
     case 'o':
index 1f1532c..7a51df5 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 e10a304..e689794 100644 (file)
@@ -115,7 +115,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 */
@@ -147,7 +147,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"
 };
 
index 58f3bed..14d1c2a 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"
 
 static const gchar *NYAN = "nyannyan";
 static const gsize N_NYAN = 8;
@@ -207,7 +212,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 (data == memory);
@@ -261,7 +266,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 (array != NULL);
@@ -324,6 +329,46 @@ test_null (void)
   g_assert (size == 0);
 }
 
+#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[])
 {
@@ -346,6 +391,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
 
   return g_test_run ();
 }
index dc738e0..cdbd916 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':
@@ -450,6 +453,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))
@@ -753,6 +758,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;
@@ -1884,6 +1890,7 @@ struct _TreeInstance
 
   union {
     guint64 integer;
+    gfloat single;
     gdouble floating;
     gchar string[200];
   } data;
@@ -1998,6 +2005,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;
@@ -2435,6 +2447,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;
@@ -2458,6 +2474,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)
@@ -2562,6 +2591,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);
@@ -3649,6 +3685,7 @@ test_gv_byteswap (void)
 static void
 test_parser (void)
 {
+  GError *error = NULL;
   TreeInstance *tree;
   GVariant *parsed;
   GVariant *value;
@@ -3662,16 +3699,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);
 
@@ -4456,10 +4496,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;
   gint i;
 
@@ -4490,6 +4533,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 {
@@ -4533,6 +4611,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)
 {
@@ -4657,6 +4810,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);
index a4fb370..d1d3493 100644 (file)
@@ -206,7 +206,9 @@ glib_genmarshal_SOURCES = glib-genmarshal.c
 # link programs against libgobject
 progs_LDADD = ./libgobject-2.0.la $(libglib)
 glib_genmarshal_LDADD = $(libglib)
+glib_genmarshal_LDFLAGS = -pie
 gobject_query_LDADD = $(progs_LDADD)
+gobject_query_LDFLAGS = -pie
 
 #
 # auxillary files
index 7d5920a..6779dcf 100644 (file)
@@ -25,4 +25,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])
 ])
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..25092eb
--- /dev/null
@@ -0,0 +1,529 @@
+# Do not create provides from extension .so files because the main package
+# should anchor any reverse-dependencies
+%global __provides_exclude_from ^(.*\\.extension-kdbus)$
+
+%bcond_with coverage
+%define baseline 2.52
+%define with_systemtap 0
+%define keepstatic 1
+
+Name:           glib2
+Version:        2.52.2
+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.0+
+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
+Source99:       baselibs.conf
+Source1001:    glib2.manifest
+BuildRequires:  automake
+BuildRequires:  fdupes
+BuildRequires:  gcc-c++
+BuildRequires:  pkg-config
+BuildRequires:  python
+BuildRequires:  gettext-tools
+# gdbus-codegen is run during the build, so we need python-xml
+BuildRequires:  python-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.13
+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:       python-xml
+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
+Requires:       %{name}-devel = %{version}
+Summary:        General-Purpose Utility Library -- Static Libraries
+
+%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 Apache-2.0
+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.
+
+%if %{with coverage}
+%package coverage
+Summary:    Special version of glib libraries for getting coverage analysis
+
+%description coverage
+Special version of glib libraries for getting coverage analysis. *.gcda coverage files
+are generated on each use of library in directory set by GCOV_PREFIX and GCOV_PREFIX_STRIP.
+Use the library by modifying LD_LIBRARY_PATH.
+This package is intended for debug/test use only.
+
+%package coverage-objects
+Summary:    Generated object files and gcov notes for coverage analysis
+
+%description coverage-objects
+Objects and gcno files to analyze coverage.
+This package is intended for debug/test use only.
+%endif
+
+%prep
+%setup -q -n %{name}-%{version}
+
+%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
+NOAUTORECONF=1 NOCONFIGURE=1 ./autogen.sh
+export CFLAGS+=" -D_TIZEN_DBUS_TOUCH"
+%ifarch %{arm}
+export CFLAGS=${CFLAGS/-Wa,-mimplicit-it=thumb/}" -marm"
+%endif
+
+export CFLAGS="${CFLAGS} -fPIC"
+export LDFLAGS="${LDFLAGS}"
+
+# Create kdbus extension first (libgio)
+%reconfigure \
+    --enable-static \
+%if 0%{?with_systemtap}
+    --enable-systemtap \
+%endif
+    --enable-libdbuspolicy \
+    --enable-always-build-tests \
+    --enable-installed-tests \
+    --enable-force-dbus-tests \
+%if %{with coverage}
+    --disable-gcov-coverage \
+%endif
+    --with-pcre=system \
+    --enable-libmount=no
+
+%{__make} %{?_smp_mflags} V=1
+
+mkdir -p extension-kdbus
+pushd gio/.libs/
+# rm if symlink. mv if regular file.
+for FILE in libgio-*.so*; do test -h "$FILE" && rm "$FILE" || mv "$FILE" ../../extension-kdbus/ ; done
+popd
+
+%{__make} clean
+
+
+
+# Support for generating separate packages with libraries generating coverage files
+# WARNING: if coverage build is enabled, incremental builds will not work correctly.
+#          Use the option only to generate glib2-coverage packages.
+%if %{with coverage}
+%reconfigure \
+    --disable-static \
+    --enable-libdbuspolicy \
+    --with-pcre=system \
+    --enable-libmount=no \
+    --enable-gcov-coverage
+
+%{__make} %{?_smp_mflags} V=1
+
+mkdir -p coverage
+mv gio/.libs/libgio-2.0.so* glib/.libs/libglib-2.0.so* gthread/.libs/libgthread-2.0.so* gobject/.libs/libgobject-2.0.so* gmodule/.libs/libgmodule-2.0.so* coverage
+mkdir -p coverage-objects
+find g* -name '*.o' -exec mv '{}' coverage-objects ';'
+find g* -name '*.gcno' -exec mv '{}' coverage-objects ';'
+
+%{__make} clean
+%endif
+
+%reconfigure \
+    --enable-static \
+%if 0%{?with_systemtap}
+    --enable-systemtap \
+%endif
+    --enable-always-build-tests \
+    --enable-installed-tests \
+    --enable-force-dbus-tests \
+%if %{with coverage}
+    --disable-gcov-coverage \
+%endif
+    --with-pcre=system \
+    --enable-libmount=no
+
+%{__make} %{?_smp_mflags} V=1
+
+# compile test-runner for 'dbus-integration-test' framework
+%__cc %{_builddir}/%{name}-%{version}/test-runner.c -fPIC -pie -o %{_builddir}/%{name}-%{version}/glib-tests
+
+%install
+%make_install
+%find_lang glib20 %{?no_lang_C}
+
+# kdbus extension
+pushd extension-kdbus
+for FILE in *; do mv "$FILE" "%{buildroot}%{_libdir}/$FILE.extension-kdbus"; done
+popd
+
+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
+# default apps magic
+mkdir -p %{buildroot}%{_localstatedir}/cache/gio-2.0 %{buildroot}%{_datadir}/applications
+touch %{buildroot}%{_localstatedir}/cache/gio-2.0/gnome-defaults.list
+touch %{buildroot}%{_localstatedir}/cache/gio-2.0/xfce-defaults.list
+touch %{buildroot}%{_localstatedir}/cache/gio-2.0/lxde-defaults.list
+ln -s %{_localstatedir}/cache/gio-2.0/gnome-defaults.list %{buildroot}%{_datadir}/applications/defaults.list
+# gio-querymodules magic
+%if "%{_lib}" == "lib64"
+mv %{buildroot}%{_bindir}/gio-querymodules %{buildroot}%{_bindir}/gio-querymodules-64
+%endif
+touch %{buildroot}%{_libdir}/gio/modules/giomodule.cache
+# gsettings magic
+touch %{buildroot}%{_datadir}/glib-2.0/schemas/gschemas.compiled
+# remove files we don't care about
+find %{buildroot}%{_libdir} -name '*.la' -type f -delete -print
+
+# 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 %{S:6} %{buildroot}%{_sysconfdir}/rpm
+%fdupes %{buildroot}
+
+# install libraries with coverage analysis enabled
+%if %{with coverage}
+%define relative_cov_lib_dir %{relative_dbus_tests_base_dir}/coverage-libs
+%define cov_lib_dir %{buildroot}%{relative_cov_lib_dir}
+
+mkdir -p %{cov_lib_dir}
+mkdir -p %{cov_lib_dir}/objects
+install -m 0755 coverage/*.so* %{cov_lib_dir}
+install -m 0644 coverage-objects/* %{cov_lib_dir}/objects
+%endif
+
+%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-querymodules*
+%{_bindir}/glib-compile-schemas
+%{_bindir}/gresource
+%{_bindir}/gsettings
+%{_bindir}/gapplication
+%{_bindir}/gio
+# 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/
+%ghost %{_datadir}/glib-2.0/schemas/gschemas.compiled
+%{_datadir}/applications/defaults.list
+%dir %{_localstatedir}/cache/gio-2.0
+%ghost %{_localstatedir}/cache/gio-2.0/gnome-defaults.list
+%ghost %{_localstatedir}/cache/gio-2.0/xfce-defaults.list
+%ghost %{_localstatedir}/cache/gio-2.0/lxde-defaults.list
+
+
+%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
+
+%files tests
+%manifest %{name}.manifest
+%license COPYING
+%{relative_dbus_tests_base_dir}/test-suites/glib-tests/
+%{relative_dbus_tests_base_dir}/runner/glib-tests
+
+%if %{with coverage}
+%files coverage
+%license COPYING
+%{relative_cov_lib_dir}/*.so*
+
+%files coverage-objects
+%license COPYING
+%{relative_cov_lib_dir}/objects/*
+%endif
+
+%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/test-runner.c b/packaging/test-runner.c
new file mode 100644 (file)
index 0000000..bf395e4
--- /dev/null
@@ -0,0 +1,524 @@
+/*
+ * 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>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#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;
+}