summaryrefslogtreecommitdiffstats
path: root/devel/gvfs/files/patch-common_gvfsdbusutils.c
diff options
context:
space:
mode:
Diffstat (limited to 'devel/gvfs/files/patch-common_gvfsdbusutils.c')
-rw-r--r--devel/gvfs/files/patch-common_gvfsdbusutils.c543
1 files changed, 543 insertions, 0 deletions
diff --git a/devel/gvfs/files/patch-common_gvfsdbusutils.c b/devel/gvfs/files/patch-common_gvfsdbusutils.c
new file mode 100644
index 000000000..a79308b0d
--- /dev/null
+++ b/devel/gvfs/files/patch-common_gvfsdbusutils.c
@@ -0,0 +1,543 @@
+https://bugzilla.gnome.org/show_bug.cgi?id=722411
+
+--- common/gvfsdbusutils.c.orig 2014-05-25 17:43:08.000000000 +0200
++++ common/gvfsdbusutils.c 2014-05-25 17:43:08.000000000 +0200
+@@ -0,0 +1,538 @@
++/* GIO - GLib Input, Output and Streaming Library
++ *
++ * Copyright (C) 2006-2007 Red Hat, Inc.
++ *
++ * 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., 51 Franklin Street, Fifth Floor,
++ * Boston, MA 02110-1301, USA.
++ *
++ * Author: Alexander Larsson <alexl@redhat.com>
++ */
++
++#include <config.h>
++
++#include <stdlib.h>
++#include <string.h>
++
++#include <glib/gi18n-lib.h>
++#include <gvfsdbusutils.h>
++#include <gio/gio.h>
++
++static void
++_g_dbus_oom (void)
++{
++ g_error ("DBus failed with out of memory error");
++}
++
++/*************************************************************************
++ * Helper fd source *
++ ************************************************************************/
++
++typedef struct
++{
++ GSource source;
++ GPollFD pollfd;
++ GCancellable *cancellable;
++ gulong cancelled_tag;
++} FDSource;
++
++static gboolean
++fd_source_prepare (GSource *source,
++ gint *timeout)
++{
++ FDSource *fd_source = (FDSource *)source;
++ *timeout = -1;
++
++ return g_cancellable_is_cancelled (fd_source->cancellable);
++}
++
++static gboolean
++fd_source_check (GSource *source)
++{
++ FDSource *fd_source = (FDSource *)source;
++
++ return
++ g_cancellable_is_cancelled (fd_source->cancellable) ||
++ fd_source->pollfd.revents != 0;
++}
++
++static gboolean
++fd_source_dispatch (GSource *source,
++ GSourceFunc callback,
++ gpointer user_data)
++
++{
++ GFDSourceFunc func = (GFDSourceFunc)callback;
++ FDSource *fd_source = (FDSource *)source;
++
++ g_assert (func != NULL);
++
++ return (*func) (user_data, fd_source->pollfd.revents, fd_source->pollfd.fd);
++}
++
++static void
++fd_source_finalize (GSource *source)
++{
++ FDSource *fd_source = (FDSource *)source;
++
++ if (fd_source->cancelled_tag)
++ g_cancellable_disconnect (fd_source->cancellable,
++ fd_source->cancelled_tag);
++
++ if (fd_source->cancellable)
++ g_object_unref (fd_source->cancellable);
++}
++
++static GSourceFuncs fd_source_funcs = {
++ fd_source_prepare,
++ fd_source_check,
++ fd_source_dispatch,
++ fd_source_finalize
++};
++
++/* Might be called on another thread */
++static void
++fd_source_cancelled_cb (GCancellable *cancellable,
++ gpointer data)
++{
++ /* Wake up the mainloop in case we're waiting on async calls with FDSource */
++ g_main_context_wakeup (NULL);
++}
++
++/* Two __ to avoid conflict with gio version */
++GSource *
++__g_fd_source_new (int fd,
++ gushort events,
++ GCancellable *cancellable)
++{
++ GSource *source;
++ FDSource *fd_source;
++
++ source = g_source_new (&fd_source_funcs, sizeof (FDSource));
++ fd_source = (FDSource *)source;
++
++ if (cancellable)
++ fd_source->cancellable = g_object_ref (cancellable);
++
++ fd_source->pollfd.fd = fd;
++ fd_source->pollfd.events = events;
++ g_source_add_poll (source, &fd_source->pollfd);
++
++ if (cancellable)
++ fd_source->cancelled_tag =
++ g_cancellable_connect (cancellable,
++ (GCallback)fd_source_cancelled_cb,
++ NULL, NULL);
++
++ return source;
++}
++
++/*************************************************************************
++ * *
++ * dbus mainloop integration for async ops *
++ * *
++ *************************************************************************/
++
++static gint32 main_integration_data_slot = -1;
++static GOnce once_init_main_integration = G_ONCE_INIT;
++
++/**
++ * A GSource subclass for dispatching DBusConnection messages.
++ * We need this on top of the IO handlers, because sometimes
++ * there are messages to dispatch queued up but no IO pending.
++ *
++ * The source is owned by the connection (and the main context
++ * while that is alive)
++ */
++typedef struct
++{
++ GSource source;
++
++ DBusConnection *connection;
++ GSList *ios;
++ GSList *timeouts;
++} DBusSource;
++
++typedef struct
++{
++ DBusSource *dbus_source;
++ GSource *source;
++ DBusWatch *watch;
++} IOHandler;
++
++typedef struct
++{
++ DBusSource *dbus_source;
++ GSource *source;
++ DBusTimeout *timeout;
++} TimeoutHandler;
++
++static gpointer
++main_integration_init (gpointer arg)
++{
++ if (!dbus_connection_allocate_data_slot (&main_integration_data_slot))
++ g_error ("Unable to allocate data slot");
++
++ return NULL;
++}
++
++static gboolean
++dbus_source_prepare (GSource *source,
++ gint *timeout)
++{
++ DBusConnection *connection = ((DBusSource *)source)->connection;
++
++ *timeout = -1;
++
++ return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS);
++}
++
++static gboolean
++dbus_source_check (GSource *source)
++{
++ return FALSE;
++}
++
++static gboolean
++dbus_source_dispatch (GSource *source,
++ GSourceFunc callback,
++ gpointer user_data)
++{
++ DBusConnection *connection = ((DBusSource *)source)->connection;
++
++ dbus_connection_ref (connection);
++
++ /* Only dispatch once - we don't want to starve other GSource */
++ dbus_connection_dispatch (connection);
++
++ dbus_connection_unref (connection);
++
++ return TRUE;
++}
++
++static gboolean
++io_handler_dispatch (gpointer data,
++ GIOCondition condition,
++ int fd)
++{
++ IOHandler *handler = data;
++ guint dbus_condition = 0;
++ DBusConnection *connection;
++
++ connection = handler->dbus_source->connection;
++
++ if (connection)
++ dbus_connection_ref (connection);
++
++ if (condition & G_IO_IN)
++ dbus_condition |= DBUS_WATCH_READABLE;
++ if (condition & G_IO_OUT)
++ dbus_condition |= DBUS_WATCH_WRITABLE;
++ if (condition & G_IO_ERR)
++ dbus_condition |= DBUS_WATCH_ERROR;
++ if (condition & G_IO_HUP)
++ dbus_condition |= DBUS_WATCH_HANGUP;
++
++ /* Note that we don't touch the handler after this, because
++ * dbus may have disabled the watch and thus killed the
++ * handler.
++ */
++ dbus_watch_handle (handler->watch, dbus_condition);
++ handler = NULL;
++
++ if (connection)
++ dbus_connection_unref (connection);
++
++ return TRUE;
++}
++
++static void
++io_handler_free (IOHandler *handler)
++{
++ DBusSource *dbus_source;
++
++ dbus_source = handler->dbus_source;
++ dbus_source->ios = g_slist_remove (dbus_source->ios, handler);
++
++ g_source_destroy (handler->source);
++ g_source_unref (handler->source);
++ g_free (handler);
++}
++
++static void
++dbus_source_add_watch (DBusSource *dbus_source,
++ DBusWatch *watch)
++{
++ guint flags;
++ GIOCondition condition;
++ IOHandler *handler;
++ int fd;
++
++ if (!dbus_watch_get_enabled (watch))
++ return;
++
++ g_assert (dbus_watch_get_data (watch) == NULL);
++
++ flags = dbus_watch_get_flags (watch);
++
++ condition = G_IO_ERR | G_IO_HUP;
++ if (flags & DBUS_WATCH_READABLE)
++ condition |= G_IO_IN;
++ if (flags & DBUS_WATCH_WRITABLE)
++ condition |= G_IO_OUT;
++
++ handler = g_new0 (IOHandler, 1);
++ handler->dbus_source = dbus_source;
++ handler->watch = watch;
++
++#if (DBUS_MAJOR_VERSION == 1 && DBUS_MINOR_VERSION == 1 && DBUS_MICRO_VERSION >= 1) || (DBUS_MAJOR_VERSION == 1 && DBUS_MINOR_VERSION > 1) || (DBUS_MAJOR_VERSION > 1)
++ fd = dbus_watch_get_unix_fd (watch);
++#else
++ fd = dbus_watch_get_fd (watch);
++#endif
++
++ handler->source = __g_fd_source_new (fd, condition, NULL);
++ g_source_set_callback (handler->source,
++ (GSourceFunc) io_handler_dispatch, handler,
++ NULL);
++ g_source_attach (handler->source, NULL);
++
++ dbus_source->ios = g_slist_prepend (dbus_source->ios, handler);
++ dbus_watch_set_data (watch, handler,
++ (DBusFreeFunction)io_handler_free);
++}
++
++static void
++dbus_source_remove_watch (DBusSource *dbus_source,
++ DBusWatch *watch)
++{
++ dbus_watch_set_data (watch, NULL, NULL);
++}
++
++static void
++timeout_handler_free (TimeoutHandler *handler)
++{
++ DBusSource *dbus_source;
++
++ dbus_source = handler->dbus_source;
++ dbus_source->timeouts = g_slist_remove (dbus_source->timeouts, handler);
++
++ g_source_destroy (handler->source);
++ g_source_unref (handler->source);
++ g_free (handler);
++}
++
++static gboolean
++timeout_handler_dispatch (gpointer data)
++{
++ TimeoutHandler *handler = data;
++
++ dbus_timeout_handle (handler->timeout);
++
++ return TRUE;
++}
++
++static void
++dbus_source_add_timeout (DBusSource *dbus_source,
++ DBusTimeout *timeout)
++{
++ TimeoutHandler *handler;
++
++ if (!dbus_timeout_get_enabled (timeout))
++ return;
++
++ g_assert (dbus_timeout_get_data (timeout) == NULL);
++
++ handler = g_new0 (TimeoutHandler, 1);
++ handler->dbus_source = dbus_source;
++ handler->timeout = timeout;
++
++ handler->source = g_timeout_source_new (dbus_timeout_get_interval (timeout));
++ g_source_set_callback (handler->source,
++ timeout_handler_dispatch, handler,
++ NULL);
++ g_source_attach (handler->source, NULL);
++
++ /* handler->source is owned by the context here */
++ dbus_source->timeouts = g_slist_prepend (dbus_source->timeouts, handler);
++
++ dbus_timeout_set_data (timeout, handler,
++ (DBusFreeFunction)timeout_handler_free);
++}
++
++static void
++dbus_source_remove_timeout (DBusSource *source,
++ DBusTimeout *timeout)
++{
++ dbus_timeout_set_data (timeout, NULL, NULL);
++}
++
++static dbus_bool_t
++add_watch (DBusWatch *watch,
++ gpointer data)
++{
++ DBusSource *dbus_source = data;
++
++ dbus_source_add_watch (dbus_source, watch);
++
++ return TRUE;
++}
++
++static void
++remove_watch (DBusWatch *watch,
++ gpointer data)
++{
++ DBusSource *dbus_source = data;
++
++ dbus_source_remove_watch (dbus_source, watch);
++}
++
++static void
++watch_toggled (DBusWatch *watch,
++ void *data)
++{
++ /* Because we just exit on OOM, enable/disable is
++ * no different from add/remove */
++ if (dbus_watch_get_enabled (watch))
++ add_watch (watch, data);
++ else
++ remove_watch (watch, data);
++}
++
++static dbus_bool_t
++add_timeout (DBusTimeout *timeout,
++ void *data)
++{
++ DBusSource *source = data;
++
++ if (!dbus_timeout_get_enabled (timeout))
++ return TRUE;
++
++ dbus_source_add_timeout (source, timeout);
++
++ return TRUE;
++}
++
++static void
++remove_timeout (DBusTimeout *timeout,
++ void *data)
++{
++ DBusSource *source = data;
++
++ dbus_source_remove_timeout (source, timeout);
++}
++
++static void
++timeout_toggled (DBusTimeout *timeout,
++ void *data)
++{
++ /* Because we just exit on OOM, enable/disable is
++ * no different from add/remove
++ */
++ if (dbus_timeout_get_enabled (timeout))
++ add_timeout (timeout, data);
++ else
++ remove_timeout (timeout, data);
++}
++
++static void
++wakeup_main (void *data)
++{
++ g_main_context_wakeup (NULL);
++}
++
++static const GSourceFuncs dbus_source_funcs = {
++ dbus_source_prepare,
++ dbus_source_check,
++ dbus_source_dispatch
++};
++
++/* Called when the connection dies or when we're unintegrating from mainloop */
++static void
++dbus_source_free (DBusSource *dbus_source)
++{
++ while (dbus_source->ios)
++ {
++ IOHandler *handler = dbus_source->ios->data;
++
++ dbus_watch_set_data (handler->watch, NULL, NULL);
++ }
++
++ while (dbus_source->timeouts)
++ {
++ TimeoutHandler *handler = dbus_source->timeouts->data;
++
++ dbus_timeout_set_data (handler->timeout, NULL, NULL);
++ }
++
++ /* Remove from mainloop */
++ g_source_destroy ((GSource *)dbus_source);
++
++ g_source_unref ((GSource *)dbus_source);
++}
++
++void
++_g_dbus_connection_integrate_with_main (DBusConnection *connection)
++{
++ DBusSource *dbus_source;
++
++ g_once (&once_init_main_integration, main_integration_init, NULL);
++
++ g_assert (connection != NULL);
++
++ _g_dbus_connection_remove_from_main (connection);
++
++ dbus_source = (DBusSource *)
++ g_source_new ((GSourceFuncs*)&dbus_source_funcs,
++ sizeof (DBusSource));
++
++ dbus_source->connection = connection;
++
++ if (!dbus_connection_set_watch_functions (connection,
++ add_watch,
++ remove_watch,
++ watch_toggled,
++ dbus_source, NULL))
++ _g_dbus_oom ();
++
++ if (!dbus_connection_set_timeout_functions (connection,
++ add_timeout,
++ remove_timeout,
++ timeout_toggled,
++ dbus_source, NULL))
++ _g_dbus_oom ();
++
++ dbus_connection_set_wakeup_main_function (connection,
++ wakeup_main,
++ dbus_source, NULL);
++
++ /* Owned by both connection and mainloop (until destroy) */
++ g_source_attach ((GSource *)dbus_source, NULL);
++
++ if (!dbus_connection_set_data (connection,
++ main_integration_data_slot,
++ dbus_source, (DBusFreeFunction)dbus_source_free))
++ _g_dbus_oom ();
++}
++
++void
++_g_dbus_connection_remove_from_main (DBusConnection *connection)
++{
++ g_once (&once_init_main_integration, main_integration_init, NULL);
++
++ if (!dbus_connection_set_data (connection,
++ main_integration_data_slot,
++ NULL, NULL))
++ _g_dbus_oom ();
++}