diff --git a/gvfs-1.6.6.tar.bz2 b/gvfs-1.6.6.tar.bz2 deleted file mode 100644 index f050482..0000000 --- a/gvfs-1.6.6.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:902890deb6a670f642180ea958406ebb02af1d5867a464c87e493d56f1dde7bd -size 1387796 diff --git a/gvfs-1.9.0.tar.bz2 b/gvfs-1.9.0.tar.bz2 new file mode 100644 index 0000000..044f583 --- /dev/null +++ b/gvfs-1.9.0.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:323406de7ba912942e7edbebec5e78c214b6d0af46834b48b7bc2dfb755a06dc +size 1415866 diff --git a/gvfs-dav-recursive-directory-ops.patch b/gvfs-dav-recursive-directory-ops.patch deleted file mode 100644 index a332ea4..0000000 --- a/gvfs-dav-recursive-directory-ops.patch +++ /dev/null @@ -1,2231 +0,0 @@ -commit 25cb6b442cc37b8e6056cc837233523d7572736b -Author: Hans Petter Jansson -Date: Thu Jan 13 18:04:58 2011 +0100 - - Patch 8: gvfs-dav-recursive-directory-ops.patch - -diff --git a/daemon/Makefile.am b/daemon/Makefile.am -index 39369b4..767eeb6 100644 ---- a/daemon/Makefile.am -+++ b/daemon/Makefile.am -@@ -430,6 +430,7 @@ gvfsd_gphoto2_LDADD = $(libraries) $(GPHOTO2_LIBS) $(HAL_LIBS) - endif - - gvfsd_http_SOURCES = \ -+ gmempipe.c gmempipe.h \ - soup-input-stream.c soup-input-stream.h \ - soup-output-stream.c soup-output-stream.h \ - gvfsbackendhttp.c gvfsbackendhttp.h \ -@@ -474,6 +475,7 @@ gvfsd_nvvfs_LDADD = $(libraries) - - - gvfsd_dav_SOURCES = \ -+ gmempipe.c gmempipe.h \ - soup-input-stream.c soup-input-stream.h \ - soup-output-stream.c soup-output-stream.h \ - gvfsbackendhttp.c gvfsbackendhttp.h \ -diff --git a/daemon/gmempipe.c b/daemon/gmempipe.c -new file mode 100644 -index 0000000..3ceebd9 ---- /dev/null -+++ b/daemon/gmempipe.c -@@ -0,0 +1,716 @@ -+/* GIO - GLib Input, Output and Streaming Library -+ * -+ * Copyright (C) Christian Kellner -+ * -+ * 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: Christian Kellner -+ */ -+ -+#include "gmempipe.h" -+ -+#include -+ -+ -+ -+G_DEFINE_TYPE (GMemPipe, g_mem_pipe, G_TYPE_OBJECT) -+ -+/* TODO: Real P_() */ -+#define P_(_x) (_x) -+ -+static void g_mem_pipe_get_property (GObject *object, -+ guint prop_id, -+ GValue *value, -+ GParamSpec *pspec); -+ -+static void g_mem_pipe_set_property (GObject *object, -+ guint prop_id, -+ const GValue *value, -+ GParamSpec *pspec); -+ -+typedef enum { -+ -+ GPD_NONE = 0x00, -+ GPD_READ = 0x01, /* reading from the pipe */ -+ GPD_WRITE = 0x02 /* writing to the pipe */ -+ -+} GPipeDirection; -+ -+enum -+{ -+ PROP_0, -+ PROP_BUFFER_SIZE -+}; -+ -+struct _GMemPipePrivate -+{ -+ -+ struct { -+ gsize size; -+ gsize dlen; -+ -+ char *data; -+ -+ } buffer; -+ -+ GMutex *lock; -+ GCond *cond; -+ -+ GPipeDirection closed; -+ GInputStream *input_stream; -+ GOutputStream *output_stream; -+}; -+ -+/* streaming classes declarations */ -+typedef struct _GMemPipeInputStream GMemPipeInputStream; -+typedef struct _GMemPipeOutputStream GMemPipeOutputStream; -+ -+static GOutputStream *g_mem_pipe_output_stream_new (GMemPipe *mem_pipe); -+static GInputStream *g_mem_pipe_input_stream_new (GMemPipe *mem_pipe); -+ -+/* GMemPipe imlementation starts here*/ -+static void -+g_mem_pipe_finalize (GObject *object) -+{ -+ GMemPipe *mem_pipe; -+ GMemPipePrivate *priv; -+ -+ mem_pipe = G_MEM_PIPE (object); -+ -+ priv = mem_pipe->priv; -+ -+ g_mutex_free (priv->lock); -+ g_cond_free (priv->cond); -+ -+ if (priv->buffer.size) -+ g_free (priv->buffer.data); -+ -+ /* FIXME: move those to dispose? */ -+ g_object_unref (priv->input_stream); -+ g_object_unref (priv->output_stream); -+ -+ if (G_OBJECT_CLASS (g_mem_pipe_parent_class)->finalize) -+ (*G_OBJECT_CLASS (g_mem_pipe_parent_class)->finalize) (object); -+} -+ -+static void -+g_mem_pipe_class_init (GMemPipeClass *klass) -+{ -+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass); -+ -+ g_type_class_add_private (klass, sizeof (GMemPipePrivate)); -+ -+ gobject_class->finalize = g_mem_pipe_finalize; -+ gobject_class->set_property = g_mem_pipe_set_property; -+ gobject_class->get_property = g_mem_pipe_get_property; -+ -+ g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE, -+ g_param_spec_uint ("buffer-size", -+ P_("Buffer size"), -+ P_("The size of the internal buffer"), -+ 0, -+ G_MAXUINT, -+ 0, -+ G_PARAM_CONSTRUCT_ONLY | -+ G_PARAM_READWRITE | -+ G_PARAM_STATIC_STRINGS)); -+ -+} -+ -+static void -+g_mem_pipe_init (GMemPipe *mem_pipe) -+{ -+ GMemPipePrivate *priv; -+ mem_pipe->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (mem_pipe, -+ G_TYPE_MEM_PIPE, -+ GMemPipePrivate); -+ -+ priv->cond = g_cond_new (); -+ priv->lock = g_mutex_new (); -+ priv->input_stream = g_mem_pipe_input_stream_new (mem_pipe); -+ priv->output_stream = g_mem_pipe_output_stream_new (mem_pipe); -+} -+ -+static void -+g_mem_pipe_get_property (GObject *object, -+ guint prop_id, -+ GValue *value, -+ GParamSpec *pspec) -+{ -+ GMemPipe *mem_pipe = G_MEM_PIPE (object); -+ -+ switch (prop_id) -+ { -+ case PROP_BUFFER_SIZE: -+ g_warn_if_fail (mem_pipe->priv->buffer.dlen == 0); -+ g_value_set_uint (value, mem_pipe->priv->buffer.size); -+ break; -+ -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -+ } -+} -+ -+static void -+g_mem_pipe_set_property (GObject *object, -+ guint prop_id, -+ const GValue *value, -+ GParamSpec *pspec) -+{ -+ GMemPipe *mem_pipe = G_MEM_PIPE (object); -+ -+ switch (prop_id) -+ { -+ case PROP_BUFFER_SIZE: -+ mem_pipe->priv->buffer.size = g_value_get_uint (value); -+ mem_pipe->priv->buffer.data = g_realloc (mem_pipe->priv->buffer.data, -+ mem_pipe->priv->buffer.size); -+ break; -+ -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -+ } -+} -+ -+static void -+signal_cancellation (GCancellable *cancellable, -+ gpointer user_data) -+{ -+ GMemPipe *mem_pipe; -+ GMemPipePrivate *priv; -+ -+ mem_pipe = G_MEM_PIPE (user_data); -+ priv = mem_pipe->priv; -+ -+ g_mutex_lock (priv->lock); -+ g_cond_signal (priv->cond); -+ g_mutex_unlock (priv->lock); -+} -+ -+static guint -+_g_mem_pipe_cancellable_connect (GMemPipe *mem_pipe, -+ GCancellable *cancellable) -+{ -+ guint handler_id; -+ -+ if (cancellable == NULL) -+ return 0; -+ -+ handler_id = g_cancellable_connect (cancellable, -+ G_CALLBACK (signal_cancellation), -+ mem_pipe, -+ NULL); -+ -+ return handler_id; -+} -+ -+/* half open means write-end closed and read-end still open; -+ * NB there is no need to special case the inverse of it -+ * since writing to a pipe where the read is already closed -+ * makes no sense at all (this is a SIGPIPE in unix land) -+ */ -+#define _g_mem_pipe_is_half_open(_pipe) _pipe->priv->closed & GPD_WRITE && \ -+ ~_pipe->priv->closed & GPD_READ -+static gboolean -+_g_mem_pipe_check_is_open (GMemPipe *mem_pipe, -+ GPipeDirection direction, -+ GError **error) -+{ -+ gboolean res; -+ GMemPipePrivate *priv = mem_pipe->priv; -+ -+ res = priv->closed == 0; -+ -+ if (res == FALSE && direction & GPD_READ) -+ res = _g_mem_pipe_is_half_open (mem_pipe); -+ -+ if (res == FALSE) -+ g_set_error_literal (error, -+ G_IO_ERROR, -+ G_IO_ERROR_CLOSED, -+ "Pipe closed"); -+ return res; -+} -+ -+/* LOCKED: Must be called with the LOCK held! -+ * -+ * Checks if the pipe is ready for IO. Will wait -+ * if not. -+ * -+ * NB: Can only check for GPD_WIRTE *or* GPD_READ! -+ * -+ * Returns: The number of data one can read/write -+ * to the pipe; -1 in case of an error and 0 iff -+ * the pipe write end got closed and there is no -+ * data left in the pipe to read from. -+ */ -+static gssize -+_g_mem_pipe_poll (GMemPipe *mem_pipe, -+ GPipeDirection direction, -+ GCancellable *cancellable, -+ GError **error) -+{ -+ GMemPipePrivate *priv = mem_pipe->priv; -+ gssize res = -1; -+ -+ while (! g_cancellable_set_error_if_cancelled (cancellable, error)) -+ { -+ if (! _g_mem_pipe_check_is_open (mem_pipe, direction, error)) -+ break; -+ -+ /* First check if we have to wait at all */ -+ if (direction & GPD_WRITE) -+ { -+ res = priv->buffer.size - priv->buffer.dlen; -+ g_assert (res >= 0); -+ } -+ else /* ergo: direction & GPD_READ */ -+ { -+ res = priv->buffer.dlen; -+ -+ /* if the pipe is half open we must -+ never wait even in the case that -+ res == 0; so we directly return */ -+ if (_g_mem_pipe_is_half_open (mem_pipe)) -+ return res; -+ } -+ /* if we got some data (or error) there is no need to wait! */ -+ if (res != 0) -+ break; -+ -+ g_cond_wait (priv->cond, priv->lock); -+ -+ res = -1; /* reset */ -+ } -+ -+ return res; -+} -+ -+gssize -+g_mem_pipe_read (GMemPipe *mem_pipe, -+ void *buffer, -+ gsize count, -+ GCancellable *cancellable, -+ GError **error) -+{ -+ GMemPipePrivate *priv; -+ gssize n; -+ gssize nread; -+ gboolean is_buffered; -+ gulong handler_id; -+ -+ g_return_val_if_fail (G_IS_MEM_PIPE (mem_pipe), -1); -+ priv = mem_pipe->priv; -+ -+ if (count == 0) -+ return 0; -+ -+ handler_id = _g_mem_pipe_cancellable_connect (mem_pipe, cancellable); -+ g_mutex_lock (priv->lock); -+ -+ is_buffered = (priv->buffer.size != 0); -+ if (is_buffered == FALSE) -+ { -+ priv->buffer.data = buffer; -+ priv->buffer.size = count; -+ -+ /* if the writer thread is waiting for -+ a place to write to, signal him that -+ now there is this very place */ -+ g_cond_signal (priv->cond); -+ } -+ -+ n = _g_mem_pipe_poll (mem_pipe, GPD_READ, cancellable, error); -+ -+ if (n > 0) -+ { -+ nread = MIN (count, n); -+ -+ if (is_buffered) -+ { -+ memcpy (buffer, priv->buffer.data, nread); -+ g_memmove (priv->buffer.data, priv->buffer.data + nread, nread); -+ priv->buffer.dlen -= nread; -+ -+ /* There should be room now in the buffer, -+ maybe get more data right now */ -+ g_cond_signal (priv->cond); -+ } -+ else -+ priv->buffer.dlen = priv->buffer.size = 0; -+ } -+ else -+ nread = n; -+ -+ g_mutex_unlock (priv->lock); -+ g_cancellable_disconnect (cancellable, handler_id); -+ -+ return nread; -+} -+ -+gssize -+g_mem_pipe_write (GMemPipe *mem_pipe, -+ const void *buffer, -+ gsize count, -+ GCancellable *cancellable, -+ GError **error) -+{ -+ GMemPipePrivate *priv; -+ gssize n; -+ gssize nwritten; -+ gulong handler_id; -+ -+ g_return_val_if_fail (G_IS_MEM_PIPE (mem_pipe), -1); -+ -+ if (count == 0) -+ return 0; -+ -+ priv = mem_pipe->priv; -+ handler_id = _g_mem_pipe_cancellable_connect (mem_pipe, cancellable); -+ -+ g_mutex_lock (priv->lock); -+ -+ n = _g_mem_pipe_poll (mem_pipe, GPD_WRITE, cancellable, error); -+ -+ if (n > 0) -+ { -+ nwritten = MIN (count, n); -+ memcpy (priv->buffer.data + priv->buffer.dlen, buffer, nwritten); -+ priv->buffer.dlen += nwritten; -+ -+ /* data is now available, wake up any sleeping thread */ -+ g_cond_signal (priv->cond); -+ } -+ else -+ nwritten = n; -+ -+ g_mutex_unlock (priv->lock); -+ g_cancellable_disconnect (cancellable, handler_id); -+ -+ return nwritten; -+} -+ -+gboolean -+g_mem_pipe_write_all (GMemPipe *mem_pipe, -+ const void *buffer, -+ gsize count, -+ gsize *bytes_written, -+ GCancellable *cancellable, -+ GError **error) -+{ -+ gssize n; -+ gsize nwritten; -+ gboolean res; -+ -+ g_return_val_if_fail (G_IS_MEM_PIPE (mem_pipe), FALSE); -+ -+ nwritten = 0; -+ res = TRUE; -+ -+ do -+ { -+ n = g_mem_pipe_write (mem_pipe, -+ buffer + nwritten, -+ count - nwritten, -+ cancellable, -+ error); -+ -+ if (n < 0) -+ break; -+ -+ nwritten += n; -+ -+ } -+ while (nwritten != count); -+ -+ if (bytes_written != NULL) -+ *bytes_written = nwritten; -+ -+ return nwritten == count; -+} -+ -+gboolean -+g_mem_pipe_close_write (GMemPipe *mem_pipe, -+ GCancellable *cancellable, -+ GError **error) -+{ -+ GMemPipePrivate *priv; -+ -+ g_return_val_if_fail (G_IS_MEM_PIPE (mem_pipe), FALSE); -+ -+ priv = mem_pipe->priv; -+ g_mutex_lock (priv->lock); -+ priv->closed |= GPD_WRITE; -+ g_cond_signal (priv->cond); -+ g_mutex_unlock (priv->lock); -+ -+ return TRUE; -+} -+ -+gboolean -+g_mem_pipe_close_read (GMemPipe *mem_pipe, -+ GCancellable *cancellable, -+ GError **error) -+{ -+ GMemPipePrivate *priv; -+ -+ g_return_val_if_fail (G_IS_MEM_PIPE (mem_pipe), FALSE); -+ -+ priv = mem_pipe->priv; -+ -+ g_mutex_lock (priv->lock); -+ priv->closed |= GPD_READ; -+ g_cond_signal (priv->cond); -+ g_mutex_unlock (priv->lock); -+ -+ return TRUE; -+} -+ -+GMemPipe * -+g_mem_pipe_new () -+{ -+ GMemPipe *mem_pipe; -+ -+ mem_pipe = g_object_new (G_TYPE_MEM_PIPE, NULL); -+ -+ return mem_pipe; -+} -+ -+GMemPipe * -+g_mem_pipe_buffered_new (gsize buffer_size) -+{ -+ GMemPipe *mem_pipe; -+ -+ mem_pipe = g_object_new (G_TYPE_MEM_PIPE, -+ "buffer-size", buffer_size, -+ NULL); -+ return mem_pipe; -+} -+ -+GInputStream * -+g_mem_pipe_get_input_stream (GMemPipe *mem_pipe) -+{ -+ GMemPipePrivate *priv; -+ -+ g_return_val_if_fail (G_IS_MEM_PIPE (mem_pipe), FALSE); -+ -+ priv = mem_pipe->priv; -+ return g_object_ref (priv->input_stream); -+} -+ -+GOutputStream * -+g_mem_pipe_get_output_stream (GMemPipe *mem_pipe) -+{ -+ GMemPipePrivate *priv; -+ -+ g_return_val_if_fail (G_IS_MEM_PIPE (mem_pipe), FALSE); -+ -+ priv = mem_pipe->priv; -+ return g_object_ref (priv->output_stream); -+} -+ -+ -+/* *********************************************************************** */ -+/* streams */ -+ -+/* ********************************* */ -+/* input stream */ -+typedef GInputStreamClass GMemPipeInputStreamClass; -+struct _GMemPipeInputStream -+{ -+ GInputStream parent_instance; -+ GMemPipe *mem_pipe; -+}; -+ -+#define G_TYPE_MEM_PIPE_INPUT_STREAM (g_mem_pipe_input_stream_get_type ()) -+#define G_MEM_PIPE_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), \ -+ G_TYPE_MEM_PIPE_INPUT_STREAM, \ -+ GMemPipeInputStream)) -+#define G_IS_MEM_PIPE_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), \ -+ G_TYPE_MEM_PIPE_INPUT_STREAM)) -+ -+GType g_mem_pipe_input_stream_get_type (void) G_GNUC_CONST; -+ -+G_DEFINE_TYPE (GMemPipeInputStream, -+ g_mem_pipe_input_stream, -+ G_TYPE_INPUT_STREAM) -+ -+static GInputStream * -+g_mem_pipe_input_stream_new (GMemPipe *mem_pipe) -+{ -+ GMemPipeInputStream *istream; -+ istream = g_object_new (G_TYPE_MEM_PIPE_INPUT_STREAM, NULL); -+ -+ istream->mem_pipe = g_object_ref (mem_pipe); -+ return G_INPUT_STREAM (istream); -+} -+ -+static gssize -+g_mem_pipe_input_stream_read (GInputStream *stream, -+ void *buffer, -+ gsize length, -+ GCancellable *cancellable, -+ GError **error) -+{ -+ GMemPipeInputStream *istream = (GMemPipeInputStream *) stream; -+ -+ return g_mem_pipe_read (istream->mem_pipe, -+ buffer, -+ length, -+ cancellable, -+ error); -+} -+ -+static gboolean -+g_mem_pipe_input_stream_close (GInputStream *stream, -+ GCancellable *cancellable, -+ GError **error) -+{ -+ GMemPipeInputStream *istream = (GMemPipeInputStream *) stream; -+ -+ return g_mem_pipe_close_read (istream->mem_pipe, -+ cancellable, -+ error); -+} -+ -+static void -+g_mem_pipe_input_stream_init (GMemPipeInputStream *self) -+{ -+ -+} -+ -+static void -+g_mem_pipe_input_stream_dispose (GObject *object) -+{ -+ GMemPipeInputStream *istream; -+ -+ istream = G_MEM_PIPE_INPUT_STREAM (object); -+ -+ if (istream->mem_pipe != NULL) -+ { -+ g_object_unref (istream->mem_pipe); -+ istream->mem_pipe = NULL; -+ } -+ -+ G_OBJECT_CLASS (g_mem_pipe_input_stream_parent_class)->dispose (object); -+} -+ -+static void -+g_mem_pipe_input_stream_class_init (GMemPipeInputStreamClass *klass) -+{ -+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass); -+ GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass); -+ -+ gobject_class->dispose = g_mem_pipe_input_stream_dispose; -+ stream_class->read_fn = g_mem_pipe_input_stream_read; -+ stream_class->close_fn = g_mem_pipe_input_stream_close; -+} -+ -+ -+/* ********************************* */ -+/* output stream */ -+typedef GOutputStreamClass GMemPipeOutputStreamClass; -+struct _GMemPipeOutputStream -+{ -+ GOutputStream parent_instance; -+ GMemPipe *mem_pipe; -+}; -+ -+#define G_TYPE_MEM_PIPE_OUTPUT_STREAM (g_mem_pipe_output_stream_get_type ()) -+#define G_MEM_PIPE_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), \ -+ G_TYPE_MEM_PIPE_OUTPUT_STREAM, \ -+ GMemPipeOutputStream)) -+#define G_IS_MEM_PIPE_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), \ -+ G_TYPE_MEM_PIPE_OUTPUT_STREAM)) -+ -+GType g_mem_pipe_output_stream_get_type (void) G_GNUC_CONST; -+ -+G_DEFINE_TYPE (GMemPipeOutputStream, -+ g_mem_pipe_output_stream, -+ G_TYPE_OUTPUT_STREAM) -+ -+static GOutputStream * -+g_mem_pipe_output_stream_new (GMemPipe *mem_pipe) -+{ -+ GMemPipeOutputStream *ostream; -+ ostream = g_object_new (G_TYPE_MEM_PIPE_OUTPUT_STREAM, NULL); -+ -+ ostream->mem_pipe = g_object_ref (mem_pipe); -+ return G_OUTPUT_STREAM (ostream); -+} -+ -+static gssize -+g_mem_pipe_output_stream_write (GOutputStream *stream, -+ const void *buffer, -+ gsize count, -+ GCancellable *cancellable, -+ GError **error) -+{ -+ GMemPipeOutputStream *ostream = (GMemPipeOutputStream *) stream; -+ -+ return g_mem_pipe_write (ostream->mem_pipe, -+ buffer, -+ count, -+ cancellable, -+ error); -+} -+ -+static gboolean -+g_mem_pipe_output_stream_close (GOutputStream *stream, -+ GCancellable *cancellable, -+ GError **error) -+{ -+ GMemPipeOutputStream *ostream = (GMemPipeOutputStream *) stream; -+ -+ g_return_val_if_fail (G_IS_MEMORY_OUTPUT_STREAM (stream), FALSE); -+ -+ return g_mem_pipe_close_write (ostream->mem_pipe, -+ cancellable, -+ error); -+} -+ -+static void -+g_mem_pipe_output_stream_init (GMemPipeOutputStream *self) -+{ -+ -+} -+ -+static void -+g_mem_pipe_output_stream_dispose (GObject *object) -+{ -+ GMemPipeOutputStream *ostream; -+ -+ ostream = G_MEM_PIPE_OUTPUT_STREAM (object); -+ -+ if (ostream->mem_pipe != NULL) -+ { -+ g_object_unref (ostream->mem_pipe); -+ ostream->mem_pipe = NULL; -+ } -+ -+ G_OBJECT_CLASS (g_mem_pipe_output_stream_parent_class)->dispose (object); -+} -+ -+static void -+g_mem_pipe_output_stream_class_init (GMemPipeOutputStreamClass *klass) -+{ -+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass); -+ GOutputStreamClass *stream_class = G_OUTPUT_STREAM_CLASS (klass); -+ -+ gobject_class->dispose = g_mem_pipe_output_stream_dispose; -+ stream_class->write_fn = g_mem_pipe_output_stream_write; -+ stream_class->close_fn = g_mem_pipe_output_stream_close; -+} -diff --git a/daemon/gmempipe.h b/daemon/gmempipe.h -new file mode 100644 -index 0000000..c9b1cd3 ---- /dev/null -+++ b/daemon/gmempipe.h -@@ -0,0 +1,86 @@ -+/* GIO - GLib Input, Output and Streaming Library -+ * -+ * Copyright (C) Christian Kellner -+ * -+ * 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: Christian Kellner -+ */ -+ -+#ifndef __G_MEM_PIPE_H__ -+#define __G_MEM_PIPE_H__ -+ -+#include -+#include -+ -+G_BEGIN_DECLS -+ -+#define G_TYPE_MEM_PIPE (g_mem_pipe_get_type ()) -+#define G_MEM_PIPE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_MEM_PIPE, GMemPipe)) -+#define G_MEM_PIPE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_MEM_PIPE, GMemPipeClass)) -+#define G_IS_MEM_PIPE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_MEM_PIPE)) -+#define G_IS_MEM_PIPE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TPE_MEM_PIPE)) -+#define G_MEM_PIPE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_MEM_PIPE, GMemPipeClass)) -+ -+typedef struct _GMemPipe GMemPipe; -+typedef struct _GMemPipePrivate GMemPipePrivate; -+typedef struct _GMemPipeClass GMemPipeClass; -+ -+struct _GMemPipe -+{ -+ GObject parent_instance; -+ -+ GMemPipePrivate *priv; -+}; -+ -+struct _GMemPipeClass -+{ -+ GObjectClass parent_class; -+ -+}; -+ -+GType g_mem_pipe_get_type (void) G_GNUC_CONST; -+GMemPipe * g_mem_pipe_new (void); -+GMemPipe * g_mem_pipe_buffered_new (gsize buffer_size); -+gssize g_mem_pipe_write (GMemPipe *mem_pipe, -+ const void *buffer, -+ gsize count, -+ GCancellable *cancellable, -+ GError **error); -+gboolean g_mem_pipe_write_all (GMemPipe *mem_pipe, -+ const void *buffer, -+ gsize count, -+ gsize *bytes_written, -+ GCancellable *cancellable, -+ GError **error); -+gssize g_mem_pipe_read (GMemPipe *mem_pipe, -+ void *buffer, -+ gsize count, -+ GCancellable *cancellable, -+ GError **error); -+gboolean g_mem_pipe_close_write (GMemPipe *mem_pipe, -+ GCancellable *cancellable, -+ GError **error); -+gboolean g_mem_pipe_close_read (GMemPipe *mem_pipe, -+ GCancellable *cancellable, -+ GError **error); -+GInputStream *g_mem_pipe_get_input_stream (GMemPipe *mem_pipe); -+GOutputStream *g_mem_pipe_get_output_stream (GMemPipe *mem_pipe); -+ -+ -+G_END_DECLS -+ -+#endif /* __G_MEM_PIPE_H__ */ -diff --git a/daemon/gvfsbackenddav.c b/daemon/gvfsbackenddav.c -index 95dc428..0862249 100644 ---- a/daemon/gvfsbackenddav.c -+++ b/daemon/gvfsbackenddav.c -@@ -2313,6 +2313,47 @@ try_unmount (GVfsBackend *backend, - _exit (0); - } - -+ -+/* *** overwrite http backend method *** */ -+static void -+do_open_for_read (GVfsBackend *backend, -+ GVfsJobOpenForRead *job, -+ const char *filename) -+{ -+ SoupURI *uri; -+ GFileType file_type; -+ gboolean res; -+ guint num_children; -+ GError *error; -+ -+ error = NULL; -+ -+ uri = http_backend_uri_for_filename (backend, filename, FALSE); -+ res = stat_location (backend, uri, &file_type, &num_children, &error); -+ soup_uri_free (uri); -+ -+ if (res == FALSE) -+ { -+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error); -+ g_error_free (error); -+ return; -+ } -+ -+ if (file_type == G_FILE_TYPE_DIRECTORY) -+ { -+ g_vfs_job_failed (G_VFS_JOB (job), -+ G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY, -+ _("Directory not empty")); -+ return; -+ } -+ -+ /* the real work happens in the parent class */ -+ G_VFS_BACKEND_CLASS (g_vfs_backend_dav_parent_class)->open_for_read (backend, -+ job, -+ filename); -+} -+ -+ - /* ************************************************************************* */ - /* */ - static void -@@ -2326,6 +2367,8 @@ g_vfs_backend_dav_class_init (GVfsBackendDavClass *klass) - - backend_class = G_VFS_BACKEND_CLASS (klass); - -+ backend_class->open_for_read = do_open_for_read; -+ - backend_class->try_mount = NULL; - backend_class->mount = do_mount; - backend_class->try_query_info = NULL; -diff --git a/daemon/gvfsbackendhttp.c b/daemon/gvfsbackendhttp.c -index 976e0ed..8534d83 100644 ---- a/daemon/gvfsbackendhttp.c -+++ b/daemon/gvfsbackendhttp.c -@@ -239,7 +239,6 @@ http_error_code_from_status (guint status) - return G_IO_ERROR_FAILED; - } - -- - static void - g_vfs_job_failed_from_http_status (GVfsJob *job, guint status_code, const char *message) - { -@@ -262,6 +261,16 @@ g_vfs_job_failed_from_http_status (GVfsJob *job, guint status_code, const char * - } - } - -+static void -+g_vfs_job_failed_from_soup_error (GVfsJob *job, GError *error) -+{ -+ if (error->domain == SOUP_HTTP_ERROR) -+ g_vfs_job_failed_from_http_status (job, error->code, error->message); -+ else -+ g_vfs_job_failed_literal (job, error->domain, error->code, error->message); -+} -+ -+ - guint - http_backend_send_message (GVfsBackend *backend, - SoupMessage *msg) -@@ -335,53 +344,17 @@ try_mount (GVfsBackend *backend, - return TRUE; - } - --/* *** open_read () *** */ --static void --open_for_read_ready (GObject *source_object, -- GAsyncResult *result, -- gpointer user_data) --{ -- GInputStream *stream; -- GVfsJob *job; -- gboolean res; -- gboolean can_seek; -- GError *error; -- -- stream = G_INPUT_STREAM (source_object); -- error = NULL; -- job = G_VFS_JOB (user_data); -- -- res = soup_input_stream_send_finish (stream, -- result, -- &error); -- if (res == FALSE) -- { -- g_vfs_job_failed_literal (G_VFS_JOB (job), -- error->domain, -- error->code, -- error->message); -- -- g_error_free (error); -- g_object_unref (stream); -- return; -- } -- -- can_seek = G_IS_SEEKABLE (stream) && g_seekable_can_seek (G_SEEKABLE (stream)); -- -- g_vfs_job_open_for_read_set_can_seek (G_VFS_JOB_OPEN_FOR_READ (job), can_seek); -- g_vfs_job_open_for_read_set_handle (G_VFS_JOB_OPEN_FOR_READ (job), stream); -- g_vfs_job_succeeded (job); --} -- --static gboolean --try_open_for_read (GVfsBackend *backend, -- GVfsJobOpenForRead *job, -- const char *filename) -+static void -+do_open_for_read (GVfsBackend *backend, -+ GVfsJobOpenForRead *job, -+ const char *filename) - { - GVfsBackendHttp *op_backend; - GInputStream *stream; - SoupMessage *msg; - SoupURI *uri; -+ GError *error; -+ gboolean res; - - op_backend = G_VFS_BACKEND_HTTP (backend); - uri = http_backend_uri_for_filename (backend, filename, FALSE); -@@ -390,125 +363,119 @@ try_open_for_read (GVfsBackend *backend, - - soup_message_body_set_accumulate (msg->response_body, FALSE); - -- stream = soup_input_stream_new (op_backend->session_async, msg); -+ stream = soup_input_stream_new (op_backend->session, msg); - g_object_unref (msg); - -- soup_input_stream_send_async (stream, -- G_PRIORITY_DEFAULT, -- G_VFS_JOB (job)->cancellable, -- open_for_read_ready, -- job); -- return TRUE; -+ error = NULL; -+ res = soup_input_stream_send (stream, -+ G_VFS_JOB (job)->cancellable, -+ &error); -+ -+ if (res == FALSE) -+ { -+ g_vfs_job_failed_from_soup_error (G_VFS_JOB (job), error); -+ g_error_free (error); -+ g_object_unref (stream); -+ } -+ else -+ { -+ gboolean can_seek; -+ can_seek = G_IS_SEEKABLE (stream) && g_seekable_can_seek (G_SEEKABLE (stream)); -+ -+ g_vfs_job_open_for_read_set_can_seek (G_VFS_JOB_OPEN_FOR_READ (job), can_seek); -+ g_vfs_job_open_for_read_set_handle (G_VFS_JOB_OPEN_FOR_READ (job), stream); -+ -+ g_vfs_job_succeeded (G_VFS_JOB (job)); -+ } - } - --/* *** read () *** */ - static void --read_ready (GObject *source_object, -- GAsyncResult *result, -- gpointer user_data) -+do_read (GVfsBackend * backend, -+ GVfsJobRead * job, -+ GVfsBackendHandle handle, -+ char * buffer, -+ gsize bytes_requested) - { - GInputStream *stream; -- GVfsJob *job; - GError *error; -- gssize nread; -- -- stream = G_INPUT_STREAM (source_object); -- error = NULL; -- job = G_VFS_JOB (user_data); -- -- nread = g_input_stream_read_finish (stream, result, &error); -- -- if (nread < 0) -- { -- g_vfs_job_failed_literal (G_VFS_JOB (job), -- error->domain, -- error->code, -- error->message); -+ gssize n_bytes; - -- g_error_free (error); -- return; -- } -+ stream = G_INPUT_STREAM (handle); - -- g_vfs_job_read_set_size (G_VFS_JOB_READ (job), nread); -- g_vfs_job_succeeded (job); -+ error = NULL; -+ n_bytes = g_input_stream_read (stream, -+ buffer, -+ bytes_requested, -+ G_VFS_JOB (job)->cancellable, -+ &error); - -+ if (n_bytes >= 0) -+ { -+ g_vfs_job_read_set_size (job, n_bytes); -+ g_vfs_job_succeeded (G_VFS_JOB (job)); -+ } -+ else -+ { -+ g_vfs_job_failed_from_soup_error (G_VFS_JOB (job), error); -+ g_error_free (error); -+ } - } - --static gboolean --try_read (GVfsBackend *backend, -- GVfsJobRead *job, -- GVfsBackendHandle handle, -- char *buffer, -- gsize bytes_requested) --{ -- GInputStream *stream; - -- stream = G_INPUT_STREAM (handle); -- -- g_input_stream_read_async (stream, -- buffer, -- bytes_requested, -- G_PRIORITY_DEFAULT, -- G_VFS_JOB (job)->cancellable, -- read_ready, -- job); -- return TRUE; --} -- --static gboolean --try_seek_on_read (GVfsBackend *backend, -- GVfsJobSeekRead *job, -- GVfsBackendHandle handle, -- goffset offset, -- GSeekType type) -+static void -+do_seek_on_read (GVfsBackend *backend, -+ GVfsJobSeekRead *job, -+ GVfsBackendHandle handle, -+ goffset offset, -+ GSeekType type) - { -- GInputStream *stream; -- GError *error = NULL; -+ GInputStream *stream; -+ GError *error = NULL; -+ gboolean res; - - stream = G_INPUT_STREAM (handle); - -- if (!g_seekable_seek (G_SEEKABLE (stream), offset, type, -- G_VFS_JOB (job)->cancellable, &error)) -+ -+ res = g_seekable_seek (G_SEEKABLE (stream), -+ offset, -+ type, -+ G_VFS_JOB (job)->cancellable, -+ &error); -+ -+ if (res == FALSE) - { -- g_vfs_job_failed_literal (G_VFS_JOB (job), -- error->domain, -- error->code, -- error->message); -+ g_vfs_job_failed_from_soup_error (G_VFS_JOB (job), error); - g_error_free (error); -- return FALSE; - } - else - { - g_vfs_job_seek_read_set_offset (job, g_seekable_tell (G_SEEKABLE (stream))); - g_vfs_job_succeeded (G_VFS_JOB (job)); - } -- -- return TRUE; - } - - /* *** read_close () *** */ - static void --close_read_ready (GObject *source_object, -- GAsyncResult *result, -- gpointer user_data) -+do_close_read (GVfsBackend *backend, -+ GVfsJobCloseRead *read_job, -+ GVfsBackendHandle handle) - { - GInputStream *stream; - GVfsJob *job; - GError *error; - gboolean res; - -- job = G_VFS_JOB (user_data); -- stream = G_INPUT_STREAM (source_object); -- res = g_input_stream_close_finish (stream, -- result, -- &error); -+ error = NULL; -+ job = G_VFS_JOB (read_job); -+ stream = G_INPUT_STREAM (handle); -+ -+ -+ res = g_input_stream_close (stream, -+ job->cancellable, -+ &error); - if (res == FALSE) - { -- g_vfs_job_failed_literal (G_VFS_JOB (job), -- error->domain, -- error->code, -- error->message); -- -+ g_vfs_job_failed_from_soup_error (G_VFS_JOB (job), error); - g_error_free (error); - } - else -@@ -517,24 +484,6 @@ close_read_ready (GObject *source_object, - g_object_unref (stream); - } - --static gboolean --try_close_read (GVfsBackend *backend, -- GVfsJobCloseRead *job, -- GVfsBackendHandle handle) --{ -- GInputStream *stream; -- -- stream = G_INPUT_STREAM (handle); -- -- g_input_stream_close_async (stream, -- G_PRIORITY_DEFAULT, -- G_VFS_JOB (job)->cancellable, -- close_read_ready, -- job); -- return TRUE; --} -- -- - /* *** query_info () *** */ - - static void -@@ -688,10 +637,12 @@ g_vfs_backend_http_class_init (GVfsBackendHttpClass *klass) - backend_class = G_VFS_BACKEND_CLASS (klass); - - backend_class->try_mount = try_mount; -- backend_class->try_open_for_read = try_open_for_read; -- backend_class->try_read = try_read; -- backend_class->try_seek_on_read = try_seek_on_read; -- backend_class->try_close_read = try_close_read; -+ -+ backend_class->open_for_read = do_open_for_read; -+ backend_class->close_read = do_close_read; -+ backend_class->read = do_read; -+ backend_class->seek_on_read = do_seek_on_read; -+ - backend_class->try_query_info = try_query_info; - backend_class->try_query_info_on_read = try_query_info_on_read; - } -diff --git a/daemon/soup-input-stream.c b/daemon/soup-input-stream.c -index e1928af..10af4dd 100644 ---- a/daemon/soup-input-stream.c -+++ b/daemon/soup-input-stream.c -@@ -18,7 +18,7 @@ - * Boston, MA 02111-1307, USA. - */ - --#include -+//#include - - #include - -@@ -28,6 +28,7 @@ - #include - - #include "soup-input-stream.h" -+#include "gmempipe.h" - - static void soup_input_stream_seekable_iface_init (GSeekableIface *seekable_iface); - -@@ -37,29 +38,23 @@ G_DEFINE_TYPE_WITH_CODE (SoupInputStream, soup_input_stream, G_TYPE_INPUT_STREAM - - typedef void (*SoupInputStreamCallback) (GInputStream *); - --typedef struct { -+struct SoupInputStreamPrivate { - SoupSession *session; -- GMainContext *async_context; - SoupMessage *msg; -+ - gboolean got_headers, finished; - goffset offset; - -- GCancellable *cancellable; -- GSource *cancel_watch; -- SoupInputStreamCallback got_headers_cb; -- SoupInputStreamCallback got_chunk_cb; -- SoupInputStreamCallback finished_cb; -- SoupInputStreamCallback cancelled_cb; -+ GMutex *lock; -+ GCond *cond; -+ -+ GMemPipe *mem_pipe; - -- guchar *leftover_buffer; -- gsize leftover_bufsize, leftover_offset; -+ GInputStream *in; -+ GOutputStream *out; - -- guchar *caller_buffer; -- gsize caller_bufsize, caller_nread; -- GAsyncReadyCallback outstanding_callback; -- GSimpleAsyncResult *result; -+}; - --} SoupInputStreamPrivate; - #define SOUP_INPUT_STREAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_INPUT_STREAM, SoupInputStreamPrivate)) - - -@@ -71,24 +66,6 @@ static gssize soup_input_stream_read (GInputStream *stream, - static gboolean soup_input_stream_close (GInputStream *stream, - GCancellable *cancellable, - GError **error); --static void soup_input_stream_read_async (GInputStream *stream, -- void *buffer, -- gsize count, -- int io_priority, -- GCancellable *cancellable, -- GAsyncReadyCallback callback, -- gpointer data); --static gssize soup_input_stream_read_finish (GInputStream *stream, -- GAsyncResult *result, -- GError **error); --static void soup_input_stream_close_async (GInputStream *stream, -- int io_priority, -- GCancellable *cancellable, -- GAsyncReadyCallback callback, -- gpointer data); --static gboolean soup_input_stream_close_finish (GInputStream *stream, -- GAsyncResult *result, -- GError **error); - - static goffset soup_input_stream_tell (GSeekable *seekable); - -@@ -115,13 +92,25 @@ soup_input_stream_finalize (GObject *object) - SoupInputStream *stream = SOUP_INPUT_STREAM (object); - SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream); - -- g_object_unref (priv->session); -+ g_print ("Finalize\n"); - -- g_signal_handlers_disconnect_by_func (priv->msg, G_CALLBACK (soup_input_stream_got_headers), stream); -- g_signal_handlers_disconnect_by_func (priv->msg, G_CALLBACK (soup_input_stream_got_chunk), stream); -- g_signal_handlers_disconnect_by_func (priv->msg, G_CALLBACK (soup_input_stream_finished), stream); -- g_object_unref (priv->msg); -- g_free (priv->leftover_buffer); -+ if (priv->session) -+ g_object_unref (priv->session); -+ -+ if (priv->msg) -+ g_object_unref (priv->msg); -+ -+ if (priv->mem_pipe) -+ { -+ g_object_unref (priv->mem_pipe); -+ g_object_unref (priv->in); -+ g_object_unref (priv->out); -+ } -+ -+ g_mutex_free (priv->lock); -+ g_cond_free (priv->cond); -+ -+ g_print ("Done!\n"); - - if (G_OBJECT_CLASS (soup_input_stream_parent_class)->finalize) - (*G_OBJECT_CLASS (soup_input_stream_parent_class)->finalize) (object); -@@ -136,41 +125,77 @@ soup_input_stream_class_init (SoupInputStreamClass *klass) - g_type_class_add_private (klass, sizeof (SoupInputStreamPrivate)); - - gobject_class->finalize = soup_input_stream_finalize; -- -- stream_class->read_fn = soup_input_stream_read; -+ stream_class->read_fn = soup_input_stream_read; - stream_class->close_fn = soup_input_stream_close; -- stream_class->read_async = soup_input_stream_read_async; -- stream_class->read_finish = soup_input_stream_read_finish; -- stream_class->close_async = soup_input_stream_close_async; -- stream_class->close_finish = soup_input_stream_close_finish; - } - - static void - soup_input_stream_seekable_iface_init (GSeekableIface *seekable_iface) - { -- seekable_iface->tell = soup_input_stream_tell; -- seekable_iface->can_seek = soup_input_stream_can_seek; -- seekable_iface->seek = soup_input_stream_seek; -+ seekable_iface->tell = soup_input_stream_tell; -+ seekable_iface->can_seek = soup_input_stream_can_seek; -+ seekable_iface->seek = soup_input_stream_seek; - seekable_iface->can_truncate = soup_input_stream_can_truncate; -- seekable_iface->truncate_fn = soup_input_stream_truncate; -+ seekable_iface->truncate_fn = soup_input_stream_truncate; - } - - static void - soup_input_stream_init (SoupInputStream *stream) - { -- ; -+ SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream); -+ stream->priv = priv; -+ -+ priv->lock = g_mutex_new (); -+ priv->cond = g_cond_new (); - } - - static void --soup_input_stream_queue_message (SoupInputStream *stream) -+_soup_input_stream_queue_msg_and_wait (SoupInputStream *stream) - { -- SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream); -+ SoupInputStreamPrivate *priv = stream->priv; -+ -+ g_mutex_lock (priv->lock); -+ -+ if (priv->mem_pipe) -+ { -+ g_object_unref (priv->mem_pipe); -+ g_object_unref (priv->in); -+ g_object_unref (priv->out); -+ } -+ -+ priv->mem_pipe = g_mem_pipe_new (); -+ priv->in = g_mem_pipe_get_input_stream (priv->mem_pipe); -+ priv->out = g_mem_pipe_get_output_stream (priv->mem_pipe); - - priv->got_headers = priv->finished = FALSE; - - /* Add an extra ref since soup_session_queue_message steals one */ - g_object_ref (priv->msg); - soup_session_queue_message (priv->session, priv->msg, NULL, NULL); -+ -+ /* wait until we got the headers (or fail?) */ -+ while (!priv->got_headers && !priv->finished) -+ g_cond_wait (priv->cond, priv->lock); -+ -+ g_mutex_unlock (priv->lock); -+} -+ -+extern void soup_message_io_cleanup (SoupMessage *msg); -+ -+static void -+_soup_input_stream_cancel_msg_and_wait (SoupInputStream *stream) -+{ -+ SoupInputStreamPrivate *priv = stream->priv; -+ -+ g_mutex_lock (priv->lock); -+ soup_session_cancel_message (priv->session, priv->msg, SOUP_STATUS_CANCELLED); -+ soup_message_io_cleanup (priv->msg); -+ -+ /* FIXME: is this at all necessary? */ -+ while (!priv->got_headers && !priv->finished) -+ g_cond_wait (priv->cond, priv->lock); -+ -+ g_mutex_unlock (priv->lock); - } - - /** -@@ -181,21 +206,8 @@ soup_input_stream_queue_message (SoupInputStream *stream) - * Prepares to send @msg over @session, and returns a #GInputStream - * that can be used to read the response. - * -- * @msg may not be sent until the first read call; if you need to look -- * at the status code or response headers before reading the body, you -- * can use soup_input_stream_send() or soup_input_stream_send_async() -- * to force the message to be sent and the response headers read. -+ * FIXME - * -- * If @msg gets a non-2xx result, the first read (or send) will return -- * an error with type %SOUP_INPUT_STREAM_HTTP_ERROR. -- * -- * Internally, #SoupInputStream is implemented using asynchronous I/O, -- * so if you are using the synchronous API (eg, -- * g_input_stream_read()), you should create a new #GMainContext and -- * set it as the %SOUP_SESSION_ASYNC_CONTEXT property on @session. (If -- * you don't, then synchronous #GInputStream calls will cause the main -- * loop to be run recursively.) The async #GInputStream API works fine -- * with %SOUP_SESSION_ASYNC_CONTEXT either set or unset. - * - * Returns: a new #GInputStream. - **/ -@@ -211,17 +223,15 @@ soup_input_stream_new (SoupSession *session, SoupMessage *msg) - priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream); - - priv->session = g_object_ref (session); -- priv->async_context = soup_session_get_async_context (session); - priv->msg = g_object_ref (msg); -- -+ - g_signal_connect (msg, "got_headers", -- G_CALLBACK (soup_input_stream_got_headers), stream); -+ G_CALLBACK (soup_input_stream_got_headers), stream); - g_signal_connect (msg, "got_chunk", -- G_CALLBACK (soup_input_stream_got_chunk), stream); -+ G_CALLBACK (soup_input_stream_got_chunk), stream); - g_signal_connect (msg, "finished", -- G_CALLBACK (soup_input_stream_finished), stream); -+ G_CALLBACK (soup_input_stream_finished), stream); - -- soup_input_stream_queue_message (stream); - return G_INPUT_STREAM (stream); - } - -@@ -230,6 +240,8 @@ soup_input_stream_got_headers (SoupMessage *msg, gpointer stream) - { - SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream); - -+ g_mutex_lock (priv->lock); -+ - /* If the status is unsuccessful, we just ignore the signal and let - * libsoup keep going (eventually either it will requeue the request - * (after handling authentication/redirection), or else the -@@ -239,19 +251,14 @@ soup_input_stream_got_headers (SoupMessage *msg, gpointer stream) - return; - - priv->got_headers = TRUE; -- if (!priv->caller_buffer) -- { -- /* Not ready to read the body yet */ -- soup_session_pause_message (priv->session, msg); -- } -- -- if (priv->got_headers_cb) -- priv->got_headers_cb (stream); -+ g_cond_signal (priv->cond); -+ g_mutex_unlock (priv->lock); - } - - static void --soup_input_stream_got_chunk (SoupMessage *msg, SoupBuffer *chunk_buffer, -- gpointer stream) -+soup_input_stream_got_chunk (SoupMessage *msg, -+ SoupBuffer *chunk_buffer, -+ gpointer stream) - { - SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream); - const gchar *chunk = chunk_buffer->data; -@@ -263,46 +270,14 @@ soup_input_stream_got_chunk (SoupMessage *msg, SoupBuffer *chunk_buffer, - if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) - return; - -- /* Sanity check */ -- if (priv->caller_bufsize == 0 || priv->leftover_bufsize != 0) -- g_warning ("soup_input_stream_got_chunk called again before previous chunk was processed"); -- -- /* Copy what we can into priv->caller_buffer */ -- if (priv->caller_bufsize - priv->caller_nread > 0) -- { -- gsize nread = MIN (chunk_size, priv->caller_bufsize - priv->caller_nread); -- -- memcpy (priv->caller_buffer + priv->caller_nread, chunk, nread); -- priv->caller_nread += nread; -- priv->offset += nread; -- chunk += nread; -- chunk_size -= nread; -- } -- -- if (chunk_size > 0) -- { -- /* Copy the rest into priv->leftover_buffer. If there's already -- * some data there, realloc and append. Otherwise just copy. -- */ -- if (priv->leftover_bufsize) -- { -- priv->leftover_buffer = g_realloc (priv->leftover_buffer, -- priv->leftover_bufsize + chunk_size); -- memcpy (priv->leftover_buffer + priv->leftover_bufsize, -- chunk, chunk_size); -- priv->leftover_bufsize += chunk_size; -- } -- else -- { -- priv->leftover_bufsize = chunk_size; -- priv->leftover_buffer = g_memdup (chunk, chunk_size); -- priv->leftover_offset = 0; -- } -- } -+ g_output_stream_write_all (priv->out, -+ chunk, -+ chunk_size, -+ NULL, -+ NULL, -+ NULL); - -- soup_session_pause_message (priv->session, msg); -- if (priv->got_chunk_cb) -- priv->got_chunk_cb (stream); -+ /* FIXME: handle errors */ - } - - static void -@@ -310,71 +285,12 @@ soup_input_stream_finished (SoupMessage *msg, gpointer stream) - { - SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream); - -+ g_mutex_lock (priv->lock); - priv->finished = TRUE; -- -- if (priv->finished_cb) -- priv->finished_cb (stream); --} -- --static gboolean --soup_input_stream_cancelled (GIOChannel *chan, GIOCondition condition, -- gpointer stream) --{ -- SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream); -- -- priv->cancel_watch = NULL; -- -- soup_session_pause_message (priv->session, priv->msg); -- if (priv->cancelled_cb) -- priv->cancelled_cb (stream); -- -- return FALSE; --} -- --static void --soup_input_stream_prepare_for_io (GInputStream *stream, -- GCancellable *cancellable, -- guchar *buffer, -- gsize count) --{ -- SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream); -- int cancel_fd; -- -- priv->cancellable = cancellable; -- cancel_fd = g_cancellable_get_fd (cancellable); -- if (cancel_fd != -1) -- { -- GIOChannel *chan = g_io_channel_unix_new (cancel_fd); -- priv->cancel_watch = soup_add_io_watch (priv->async_context, chan, -- G_IO_IN | G_IO_ERR | G_IO_HUP, -- soup_input_stream_cancelled, -- stream); -- g_io_channel_unref (chan); -- } -- -- priv->caller_buffer = buffer; -- priv->caller_bufsize = count; -- priv->caller_nread = 0; -- -- if (priv->got_headers) -- soup_session_unpause_message (priv->session, priv->msg); --} -- --static void --soup_input_stream_done_io (GInputStream *stream) --{ -- SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream); -- -- if (priv->cancel_watch) -- { -- g_source_destroy (priv->cancel_watch); -- priv->cancel_watch = NULL; -- g_cancellable_release_fd (priv->cancellable); -- } -- priv->cancellable = NULL; -- -- priv->caller_buffer = NULL; -- priv->caller_bufsize = 0; -+ //g_print ("Finished!\n"); -+ g_mem_pipe_close_write (priv->mem_pipe, NULL, NULL); -+ g_cond_signal (priv->cond); -+ g_mutex_unlock (priv->lock); - } - - static gboolean -@@ -386,58 +302,10 @@ set_error_if_http_failed (SoupMessage *msg, GError **error) - msg->status_code, msg->reason_phrase); - return TRUE; - } -+ - return FALSE; - } - --static gsize --read_from_leftover (SoupInputStreamPrivate *priv, -- gpointer buffer, gsize bufsize) --{ -- gsize nread; -- -- if (priv->leftover_bufsize - priv->leftover_offset <= bufsize) -- { -- nread = priv->leftover_bufsize - priv->leftover_offset; -- memcpy (buffer, priv->leftover_buffer + priv->leftover_offset, nread); -- -- g_free (priv->leftover_buffer); -- priv->leftover_buffer = NULL; -- priv->leftover_bufsize = priv->leftover_offset = 0; -- } -- else -- { -- nread = bufsize; -- memcpy (buffer, priv->leftover_buffer + priv->leftover_offset, nread); -- priv->leftover_offset += nread; -- } -- -- priv->offset += nread; -- return nread; --} -- --/* This does the work of soup_input_stream_send(), assuming that the -- * GInputStream pending flag has already been set. It is also used by -- * soup_input_stream_send_async() in some circumstances. -- */ --static gboolean --soup_input_stream_send_internal (GInputStream *stream, -- GCancellable *cancellable, -- GError **error) --{ -- SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream); -- -- soup_input_stream_prepare_for_io (stream, cancellable, NULL, 0); -- while (!priv->finished && !priv->got_headers && -- !g_cancellable_is_cancelled (cancellable)) -- g_main_context_iteration (priv->async_context, TRUE); -- soup_input_stream_done_io (stream); -- -- if (g_cancellable_set_error_if_cancelled (cancellable, error)) -- return FALSE; -- else if (set_error_if_http_failed (priv->msg, error)) -- return FALSE; -- return TRUE; --} - - /** - * soup_input_stream_send: -@@ -454,54 +322,59 @@ soup_input_stream_send_internal (GInputStream *stream, - * not. - **/ - gboolean --soup_input_stream_send (GInputStream *stream, -- GCancellable *cancellable, -- GError **error) -+soup_input_stream_send (GInputStream *input_stream, -+ GCancellable *cancellable, -+ GError **error) - { -+ SoupInputStream *stream; -+ SoupInputStreamPrivate *priv; - gboolean result; - -- g_return_val_if_fail (SOUP_IS_INPUT_STREAM (stream), FALSE); -+ g_return_val_if_fail (SOUP_IS_INPUT_STREAM (input_stream), FALSE); -+ -+ stream = SOUP_INPUT_STREAM (input_stream); -+ priv = stream->priv; - -- if (!g_input_stream_set_pending (stream, error)) -+ if (!g_input_stream_set_pending (input_stream, error)) - return FALSE; -- result = soup_input_stream_send_internal (stream, cancellable, error); -- g_input_stream_clear_pending (stream); -+ -+ _soup_input_stream_queue_msg_and_wait (stream); -+ -+ g_input_stream_clear_pending (input_stream); -+ -+ if (g_cancellable_set_error_if_cancelled (cancellable, error)) -+ return FALSE; -+ -+ result = ! set_error_if_http_failed (priv->msg, error); - - return result; - } - - static gssize --soup_input_stream_read (GInputStream *stream, -- void *buffer, -- gsize count, -- GCancellable *cancellable, -- GError **error) -+soup_input_stream_read (GInputStream *stream, -+ void *buffer, -+ gsize count, -+ GCancellable *cancellable, -+ GError **error) - { -- SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream); -- -- if (priv->finished) -- return 0; -+ SoupInputStream *istream; -+ SoupInputStreamPrivate *priv; -+ gssize nread; - -- /* If there is data leftover from a previous read, return it. */ -- if (priv->leftover_bufsize) -- return read_from_leftover (priv, buffer, count); -+ g_return_val_if_fail (SOUP_IS_INPUT_STREAM (stream), -1); -+ -+ istream = SOUP_INPUT_STREAM (stream); -+ priv = istream->priv; - -- /* No leftover data, accept one chunk from the network */ -- soup_input_stream_prepare_for_io (stream, cancellable, buffer, count); -- while (!priv->finished && priv->caller_nread == 0 && -- !g_cancellable_is_cancelled (cancellable)) -- g_main_context_iteration (priv->async_context, TRUE); -- soup_input_stream_done_io (stream); -+ nread = g_input_stream_read (priv->in, -+ buffer, -+ count, -+ cancellable, -+ error); - -- if (priv->caller_nread > 0) -- return priv->caller_nread; -+ priv->offset += nread; - -- if (g_cancellable_set_error_if_cancelled (cancellable, error)) -- return -1; -- else if (set_error_if_http_failed (priv->msg, error)) -- return -1; -- else -- return 0; -+ return nread; - } - - static gboolean -@@ -509,314 +382,25 @@ soup_input_stream_close (GInputStream *stream, - GCancellable *cancellable, - GError **error) - { -- SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream); -- -- if (!priv->finished) -- soup_session_cancel_message (priv->session, priv->msg, SOUP_STATUS_CANCELLED); -- -- return TRUE; --} -- --static void --wrapper_callback (GObject *source_object, GAsyncResult *res, -- gpointer user_data) --{ -- GInputStream *stream = G_INPUT_STREAM (source_object); -- SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream); -- -- g_input_stream_clear_pending (stream); -- if (priv->outstanding_callback) -- (*priv->outstanding_callback) (source_object, res, user_data); -- priv->outstanding_callback = NULL; -- g_object_unref (stream); --} -- --static void --send_async_thread (GSimpleAsyncResult *res, -- GObject *object, -- GCancellable *cancellable) --{ -- GError *error = NULL; -- gboolean success; -- -- success = soup_input_stream_send_internal (G_INPUT_STREAM (object), -- cancellable, &error); -- g_simple_async_result_set_op_res_gboolean (res, success); -- if (error) -- { -- g_simple_async_result_set_from_error (res, error); -- g_error_free (error); -- } --} -- --static void --soup_input_stream_send_async_in_thread (GInputStream *stream, -- int io_priority, -- GCancellable *cancellable, -- GAsyncReadyCallback callback, -- gpointer user_data) --{ -- GSimpleAsyncResult *res; -- -- res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, -- soup_input_stream_send_async_in_thread); -- g_simple_async_result_run_in_thread (res, send_async_thread, -- io_priority, cancellable); -- g_object_unref (res); --} -- --static void --send_async_finished (GInputStream *stream) --{ -- SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream); -- GSimpleAsyncResult *result; -- GError *error = NULL; -- -- if (!g_cancellable_set_error_if_cancelled (priv->cancellable, &error)) -- set_error_if_http_failed (priv->msg, &error); -- -- priv->got_headers_cb = NULL; -- priv->finished_cb = NULL; -- soup_input_stream_done_io (stream); -- -- result = priv->result; -- priv->result = NULL; -- -- g_simple_async_result_set_op_res_gboolean (result, error == NULL); -- if (error) -- { -- g_simple_async_result_set_from_error (result, error); -- g_error_free (error); -- } -- g_simple_async_result_complete (result); --} -- --static void --soup_input_stream_send_async_internal (GInputStream *stream, -- int io_priority, -- GCancellable *cancellable, -- GAsyncReadyCallback callback, -- gpointer user_data) --{ -- SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream); -- -- g_object_ref (stream); -- priv->outstanding_callback = callback; -- -- /* If the session uses the default GMainContext, then we can do -- * async I/O directly. But if it has its own main context, it's -- * easier to just run it in another thread. -- */ -- if (soup_session_get_async_context (priv->session)) -- { -- soup_input_stream_send_async_in_thread (stream, io_priority, cancellable, -- wrapper_callback, user_data); -- return; -- } -- -- priv->got_headers_cb = send_async_finished; -- priv->finished_cb = send_async_finished; -- -- soup_input_stream_prepare_for_io (stream, cancellable, NULL, 0); -- priv->result = g_simple_async_result_new (G_OBJECT (stream), -- wrapper_callback, user_data, -- soup_input_stream_send_async); --} -- --/** -- * soup_input_stream_send_async: -- * @stream: a #SoupInputStream -- * @io_priority: the io priority of the request. -- * @cancellable: optional #GCancellable object, %NULL to ignore. -- * @callback: callback to call when the request is satisfied -- * @user_data: the data to pass to callback function -- * -- * Asynchronously sends the HTTP request associated with @stream, and -- * reads the response headers. Call this after soup_input_stream_new() -- * and before the first g_input_stream_read_async() if you want to -- * check the HTTP status code before you start reading. -- **/ --void --soup_input_stream_send_async (GInputStream *stream, -- int io_priority, -- GCancellable *cancellable, -- GAsyncReadyCallback callback, -- gpointer user_data) --{ -- GError *error = NULL; -- -- g_return_if_fail (SOUP_IS_INPUT_STREAM (stream)); -- -- if (!g_input_stream_set_pending (stream, &error)) -- { -- g_simple_async_report_gerror_in_idle (G_OBJECT (stream), -- callback, -- user_data, -- error); -- g_error_free (error); -- return; -- } -- soup_input_stream_send_async_internal (stream, io_priority, cancellable, -- callback, user_data); --} -- --/** -- * soup_input_stream_send_finish: -- * @stream: a #SoupInputStream -- * @result: a #GAsyncResult. -- * @error: a #GError location to store the error occuring, or %NULL to -- * ignore. -- * -- * Finishes a soup_input_stream_send_async() operation. -- * -- * Return value: %TRUE if the message was sent successfully and -- * received a successful status code, %FALSE if not. -- **/ --gboolean --soup_input_stream_send_finish (GInputStream *stream, -- GAsyncResult *result, -- GError **error) --{ -- GSimpleAsyncResult *simple; -- -- g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE); -- simple = G_SIMPLE_ASYNC_RESULT (result); -- -- g_return_val_if_fail (g_simple_async_result_get_source_tag (simple) == soup_input_stream_send_async, FALSE); -- -- if (g_simple_async_result_propagate_error (simple, error)) -- return FALSE; -- -- return g_simple_async_result_get_op_res_gboolean (simple); --} -- --static void --read_async_done (GInputStream *stream) --{ -- SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream); -- GSimpleAsyncResult *result; -- GError *error = NULL; -- -- result = priv->result; -- priv->result = NULL; -- -- if (g_cancellable_set_error_if_cancelled (priv->cancellable, &error) || -- set_error_if_http_failed (priv->msg, &error)) -- { -- g_simple_async_result_set_from_error (result, error); -- g_error_free (error); -- } -- else -- g_simple_async_result_set_op_res_gssize (result, priv->caller_nread); -- -- priv->got_chunk_cb = NULL; -- priv->finished_cb = NULL; -- priv->cancelled_cb = NULL; -- soup_input_stream_done_io (stream); -- -- g_simple_async_result_complete (result); -- g_object_unref (result); --} -- --static void --soup_input_stream_read_async (GInputStream *stream, -- void *buffer, -- gsize count, -- int io_priority, -- GCancellable *cancellable, -- GAsyncReadyCallback callback, -- gpointer user_data) --{ -- SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream); -- GSimpleAsyncResult *result; -- -- /* If the session uses the default GMainContext, then we can do -- * async I/O directly. But if it has its own main context, we fall -- * back to the async-via-sync-in-another-thread implementation. -- */ -- if (soup_session_get_async_context (priv->session)) -- { -- G_INPUT_STREAM_CLASS (soup_input_stream_parent_class)-> -- read_async (stream, buffer, count, io_priority, -- cancellable, callback, user_data); -- return; -- } -- -- result = g_simple_async_result_new (G_OBJECT (stream), -- callback, user_data, -- soup_input_stream_read_async); -- -- if (priv->finished) -- { -- g_simple_async_result_set_op_res_gssize (result, 0); -- g_simple_async_result_complete_in_idle (result); -- g_object_unref (result); -- return; -- } -- -- if (priv->leftover_bufsize) -- { -- gsize nread = read_from_leftover (priv, buffer, count); -- g_simple_async_result_set_op_res_gssize (result, nread); -- g_simple_async_result_complete_in_idle (result); -- g_object_unref (result); -- return; -- } -- -- priv->result = result; -- -- priv->got_chunk_cb = read_async_done; -- priv->finished_cb = read_async_done; -- priv->cancelled_cb = read_async_done; -- soup_input_stream_prepare_for_io (stream, cancellable, buffer, count); --} -- --static gssize --soup_input_stream_read_finish (GInputStream *stream, -- GAsyncResult *result, -- GError **error) --{ -- GSimpleAsyncResult *simple; -+ SoupInputStream *istream; -+ SoupInputStreamPrivate *priv; - -- g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), -1); -- simple = G_SIMPLE_ASYNC_RESULT (result); -- g_return_val_if_fail (g_simple_async_result_get_source_tag (simple) == soup_input_stream_read_async, -1); -+ g_return_val_if_fail (SOUP_IS_INPUT_STREAM (stream), -1); - -- return g_simple_async_result_get_op_res_gssize (simple); --} -+ istream = SOUP_INPUT_STREAM (stream); -+ priv = istream->priv; - --static void --soup_input_stream_close_async (GInputStream *stream, -- int io_priority, -- GCancellable *cancellable, -- GAsyncReadyCallback callback, -- gpointer user_data) --{ -- GSimpleAsyncResult *result; -- gboolean success; -- GError *error = NULL; -- -- result = g_simple_async_result_new (G_OBJECT (stream), -- callback, user_data, -- soup_input_stream_close_async); -- success = soup_input_stream_close (stream, cancellable, &error); -- g_simple_async_result_set_op_res_gboolean (result, success); -- if (error) -+ g_mutex_lock (priv->lock); -+ if (!priv->finished) - { -- g_simple_async_result_set_from_error (result, error); -- g_error_free (error); -+ soup_session_cancel_message (priv->session, -+ priv->msg, -+ SOUP_STATUS_CANCELLED); -+ g_print ("Cancelling message\n"); - } - -- g_simple_async_result_complete_in_idle (result); -- g_object_unref (result); --} -- --static gboolean --soup_input_stream_close_finish (GInputStream *stream, -- GAsyncResult *result, -- GError **error) --{ -- /* Failures handled in generic close_finish code */ -+ g_mem_pipe_close_read (priv->mem_pipe, cancellable, error); -+ g_mutex_unlock (priv->lock); - return TRUE; - } - -@@ -834,17 +418,17 @@ soup_input_stream_can_seek (GSeekable *seekable) - return TRUE; - } - --extern void soup_message_io_cleanup (SoupMessage *msg); - - static gboolean - soup_input_stream_seek (GSeekable *seekable, -- goffset offset, -- GSeekType type, -- GCancellable *cancellable, -- GError **error) -+ goffset offset, -+ GSeekType type, -+ GCancellable *cancellable, -+ GError **error) - { - GInputStream *stream = G_INPUT_STREAM (seekable); -- SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (seekable); -+ SoupInputStream *istream = SOUP_INPUT_STREAM (stream); -+ SoupInputStreamPrivate *priv = istream->priv; - char *range; - - if (type == G_SEEK_END) -@@ -862,8 +446,7 @@ soup_input_stream_seek (GSeekable *seekable, - if (!g_input_stream_set_pending (stream, error)) - return FALSE; - -- soup_session_cancel_message (priv->session, priv->msg, SOUP_STATUS_CANCELLED); -- soup_message_io_cleanup (priv->msg); -+ _soup_input_stream_cancel_msg_and_wait (istream); - - switch (type) - { -@@ -889,7 +472,7 @@ soup_input_stream_seek (GSeekable *seekable, - soup_message_headers_append (priv->msg->request_headers, "Range", range); - g_free (range); - -- soup_input_stream_queue_message (SOUP_INPUT_STREAM (stream)); -+ _soup_input_stream_queue_msg_and_wait (istream); - - g_input_stream_clear_pending (stream); - return TRUE; -@@ -922,8 +505,8 @@ soup_input_stream_get_message (GInputStream *stream) - GQuark - soup_http_error_quark (void) - { -- static GQuark error; -- if (!error) -- error = g_quark_from_static_string ("soup_http_error_quark"); -- return error; -+ static GQuark error; -+ if (!error) -+ error = g_quark_from_static_string ("soup_http_error_quark"); -+ return error; - } -diff --git a/daemon/soup-input-stream.h b/daemon/soup-input-stream.h -index f425291..2d47c7c 100644 ---- a/daemon/soup-input-stream.h -+++ b/daemon/soup-input-stream.h -@@ -33,17 +33,22 @@ G_BEGIN_DECLS - - typedef struct SoupInputStream SoupInputStream; - typedef struct SoupInputStreamClass SoupInputStreamClass; -+typedef struct SoupInputStreamPrivate SoupInputStreamPrivate; - - struct SoupInputStream - { - GInputStream parent; - -+ SoupInputStreamPrivate *priv; -+ - }; - - struct SoupInputStreamClass - { - GInputStreamClass parent_class; - -+ -+ - /* Padding for future expansion */ - void (*_g_reserved1) (void); - void (*_g_reserved2) (void); -@@ -61,15 +66,6 @@ gboolean soup_input_stream_send (GInputStream *stream, - GCancellable *cancellable, - GError **error); - --void soup_input_stream_send_async (GInputStream *stream, -- int io_priority, -- GCancellable *cancellable, -- GAsyncReadyCallback callback, -- gpointer user_data); --gboolean soup_input_stream_send_finish (GInputStream *stream, -- GAsyncResult *result, -- GError **error); -- - SoupMessage *soup_input_stream_get_message (GInputStream *stream); - - #define SOUP_HTTP_ERROR soup_http_error_quark() diff --git a/gvfs-dice-backend.patch b/gvfs-dice-backend.patch index 4d1ec7e..830bfc4 100644 --- a/gvfs-dice-backend.patch +++ b/gvfs-dice-backend.patch @@ -2092,19 +2092,19 @@ Index: gvfs-1.5.5/daemon/Makefile.am - $(GLIB_LIBS) $(DBUS_LIBS) $(KEYRING_LIBS) + $(GLIB_LIBS) $(DBUS_LIBS) $(DBUS_GLIB_LIBS) $(KEYRING_LIBS) - # D-BUS service file - %.service: %.service.in ../config.log + gvfs_gschemas = + gvfs_gschemas_convert = @@ -37,10 +38,10 @@ service_DATA = gvfs-daemon.service %.mount: %.mount.in ../config.log $(AM_V_GEN) $(SED) -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ --libexec_PROGRAMS=gvfsd gvfsd-sftp gvfsd-trash gvfsd-computer gvfsd-burn gvfsd-localtest gvfsd-ftp -+libexec_PROGRAMS=gvfsd gvfsd-sftp gvfsd-trash gvfsd-computer gvfsd-burn gvfsd-localtest gvfsd-ftp gvfsd-dice +-libexec_PROGRAMS=gvfsd gvfsd-sftp gvfsd-trash gvfsd-computer gvfsd-burn gvfsd-localtest gvfsd-ftp gvfsd-network ++libexec_PROGRAMS=gvfsd gvfsd-sftp gvfsd-trash gvfsd-computer gvfsd-burn gvfsd-localtest gvfsd-ftp gvfsd-network gvfsd-dice --mount_in_files = sftp.mount.in trash.mount.in computer.mount.in burn.mount.in localtest.mount.in --mount_DATA = sftp.mount trash.mount computer.mount burn.mount localtest.mount -+mount_in_files = sftp.mount.in trash.mount.in computer.mount.in burn.mount.in localtest.mount.in dice.mount.in -+mount_DATA = sftp.mount trash.mount computer.mount burn.mount localtest.mount dice.mount +-mount_in_files = sftp.mount.in trash.mount.in computer.mount.in burn.mount.in localtest.mount.in network.mount.in +-mount_DATA = sftp.mount trash.mount computer.mount burn.mount localtest.mount network.mount ++mount_in_files = sftp.mount.in trash.mount.in computer.mount.in burn.mount.in localtest.mount.in network.mount.in dice.mount.in ++mount_DATA = sftp.mount trash.mount computer.mount burn.mount localtest.mount network.mount dice.mount mount_in_files += http.mount.in dav.mount.in dav+sd.mount.in ftp.mount.in if HAVE_HTTP diff --git a/gvfs-glib-2.27.patch b/gvfs-glib-2.27.patch deleted file mode 100644 index 160eb52..0000000 --- a/gvfs-glib-2.27.patch +++ /dev/null @@ -1,50 +0,0 @@ -commit 6115bf7549fc2a9171d7cd5eaec6bc1a58dfb8b2 -Author: Vincent Untz -Date: Fri Nov 19 10:00:36 2010 +0100 - - Do not build app lookup extension if we have glib >= 2.27.1 - - https://bugzilla.gnome.org/show_bug.cgi?id=635252 - -diff --git a/configure.ac b/configure.ac -index ed70e54..5f05f57 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -213,6 +213,14 @@ fi - - AM_CONDITIONAL(USE_GCONF, [test "$msg_gconf" = "yes"]) - -+dnl ************************************************************* -+dnl *** Check if we can build gconf-based gio extension point *** -+dnl ************************************************************* -+ -+msg_gconf_gio=no -+PKG_CHECK_EXISTS(gio-2.0 <= 2.27.1, msg_gconf_gio=yes) -+AM_CONDITIONAL(USE_GCONF_GIO, [test "$msg_gconf_gio" = "yes"]) -+ - dnl ******************************************** - dnl *** Check for expat (for obexftp and gdu *** - dnl ******************************************** -@@ -726,6 +734,7 @@ echo " - archive support: $msg_archive - AFC support: $msg_afc - GConf support: $msg_gconf -+ GConf-based GIO extension: $msg_gconf_gio - DNS-SD support: $msg_avahi - Build HAL volume monitor: $msg_hal (with fast init path: $have_hal_fast_init) - Build GDU volume monitor: $msg_gdu -diff --git a/gconf/Makefile.am b/gconf/Makefile.am -index 85d4d8d..af1433e 100644 ---- a/gconf/Makefile.am -+++ b/gconf/Makefile.am -@@ -4,8 +4,10 @@ NULL = - module_flags = -export_dynamic -avoid-version -module -no-undefined -export-symbols-regex '^g_io_module_(load|unload|query)' - - if USE_GCONF -+if USE_GCONF_GIO - giomodules_LTLIBRARIES = libgiogconf.la - endif -+endif - - libgiogconf_la_SOURCES = \ - gapplookupgconf.c gapplookupgconf.h \ diff --git a/gvfs-nds.patch b/gvfs-nds.patch index 4e6ca20..4d2bd9a 100644 --- a/gvfs-nds.patch +++ b/gvfs-nds.patch @@ -1,7 +1,7 @@ -Index: gvfs-1.5.4/daemon/gvfsbackendnds.c +Index: gvfs-1.9.0/daemon/gvfsbackendnds.c =================================================================== --- /dev/null -+++ gvfs-1.5.4/daemon/gvfsbackendnds.c ++++ gvfs-1.9.0/daemon/gvfsbackendnds.c @@ -0,0 +1,753 @@ +/* GIO - GLib Input, Output and Streaming Library + * @@ -756,10 +756,10 @@ Index: gvfs-1.5.4/daemon/gvfsbackendnds.c +{ + g_set_application_name (_("Displaying Embedded Objects")); +} -Index: gvfs-1.5.4/daemon/gvfsbackendnds.h +Index: gvfs-1.9.0/daemon/gvfsbackendnds.h =================================================================== --- /dev/null -+++ gvfs-1.5.4/daemon/gvfsbackendnds.h ++++ gvfs-1.9.0/daemon/gvfsbackendnds.h @@ -0,0 +1,53 @@ +/* GIO - GLib Input, Output and Streaming Library + * @@ -814,11 +814,11 @@ Index: gvfs-1.5.4/daemon/gvfsbackendnds.h +G_END_DECLS + +#endif /* __G_VFS_BACKEND_NDS_H__ */ -Index: gvfs-1.5.4/daemon/Makefile.am +Index: gvfs-1.9.0/daemon/Makefile.am =================================================================== ---- gvfs-1.5.4.orig/daemon/Makefile.am -+++ gvfs-1.5.4/daemon/Makefile.am -@@ -112,6 +112,10 @@ mount_in_files += nvvfs.mount.in +--- gvfs-1.9.0.orig/daemon/Makefile.am ++++ gvfs-1.9.0/daemon/Makefile.am +@@ -113,6 +113,10 @@ mount_in_files += nvvfs.mount.in mount_DATA += nvvfs.mount libexec_PROGRAMS += gvfsd-nvvfs @@ -826,10 +826,10 @@ Index: gvfs-1.5.4/daemon/Makefile.am +mount_DATA += nds.mount +libexec_PROGRAMS += gvfsd-nds + - EXTRA_DIST = gvfs-daemon.service.in $(mount_in_files) obexftp-marshal.list - - DISTCLEANFILES = gvfs-daemon.service $(mount_DATA) -@@ -442,6 +446,19 @@ gvfsd_http_CPPFLAGS = \ + EXTRA_DIST = \ + gvfs-daemon.service.in \ + $(mount_in_files) \ +@@ -449,6 +453,19 @@ gvfsd_http_CPPFLAGS = \ gvfsd_http_LDADD = $(libraries) $(HTTP_LIBS) @@ -849,10 +849,10 @@ Index: gvfs-1.5.4/daemon/Makefile.am gvfsd_nvvfs_SOURCES = \ gvfsbackendnvvfs.c gvfsbackendnvvfs.h \ daemon-main.c daemon-main.h \ -Index: gvfs-1.5.4/daemon/nds.mount.in +Index: gvfs-1.9.0/daemon/nds.mount.in =================================================================== --- /dev/null -+++ gvfs-1.5.4/daemon/nds.mount.in ++++ gvfs-1.9.0/daemon/nds.mount.in @@ -0,0 +1,5 @@ +[Mount] +Type=nds diff --git a/gvfs-nvvfs.patch b/gvfs-nvvfs.patch index 101ad75..bcd971f 100644 --- a/gvfs-nvvfs.patch +++ b/gvfs-nvvfs.patch @@ -661,9 +661,9 @@ Index: gvfs-1.5.1/daemon/Makefile.am +mount_DATA += nvvfs.mount +libexec_PROGRAMS += gvfsd-nvvfs + - EXTRA_DIST = gvfs-daemon.service.in $(mount_in_files) obexftp-marshal.list - - DISTCLEANFILES = gvfs-daemon.service $(mount_DATA) + EXTRA_DIST = \ + gvfs-daemon.service.in \ + $(mount_in_files) \ @@ -438,6 +442,20 @@ gvfsd_http_CPPFLAGS = \ gvfsd_http_LDADD = $(libraries) $(HTTP_LIBS) diff --git a/gvfs.changes b/gvfs.changes index 5e3bf82..6fc2265 100644 --- a/gvfs.changes +++ b/gvfs.changes @@ -1,9 +1,125 @@ +------------------------------------------------------------------- +Mon Jun 6 10:05:48 UTC 2011 - dimstar@opensuse.org + +- Use 0%%{suse_version} instead of %%{suse_version} only to make + sure we have a value, even when suse_version is not defined. + +------------------------------------------------------------------- +Wed May 18 03:40:29 CEST 2011 - dimstar@opensuse.org + +- Update to version 1.9.0: + + afc: + - Fix renaming files moving them to the root dir + - Use a better display name for jailbroken device access + + common: Use libbluray to get Blu-Ray metadata + + daemon: + - Fix threadsafety of closing channels + - Don't leak dbus messages + + fuse: + - Make created files visible immediately on WebDAV + - Pretend created file exists even if backend didn't create it + + gdu volume monitor: + - Fix setting the BDMV name + - Fix check for symlinks in /dev + - Automount flash card readers + + gphoto2: + - Recognize cameras which don't implement get storageinfo + + dav: + - Fix copying of remote folders to disk + - Correctly handle usernames supplied in the url + + http/dav: Send Accept-Language header + + http: Use Content-Disposition filename if available + + Updated translations. +- Drop gvfs-dav-recursive-directory-ops.patch: fixed upstream. + +------------------------------------------------------------------- +Tue Apr 26 15:16:06 UTC 2011 - fcrozat@novell.com + +- Update to version 1.8.1: + + Fix threadsafety of closing channels. + + Don't leak dbus messages. + + gdu: + - Fix setting the BDMV name. + - Fix check for symlinks in /dev, was reversed. + + Updated translations. +- Version libimobiledevice-devel BuildRequires with >= 1.1.0, to + make sure we don't even try to build if we don't have the right + version. New libimobiledevice will reach Factory soon. + +------------------------------------------------------------------- +Tue Apr 5 11:55:02 UTC 2011 - fcrozat@novell.com + +- Update to version 1.8.0: + + afc: Fix renaming files moving them to the root dir + + Updated translations. + +------------------------------------------------------------------- +Mon Mar 21 16:49:05 UTC 2011 - fcrozat@novell.com + +- Update to version 1.7.3! + + client: Fix wrong assignment before dbus_connection_unref() + + archive: + - Prevent assertion failure on duplicate mount + - Skip leading "./" from pathnames if present + - Propagate entry index as inode no. for files + + smb: Add support for default location + + Build fixes. + + Updated translations. +- Rebase gvfs-dav-recursive-directory-ops.patch. + +------------------------------------------------------------------- +Thu Mar 10 11:09:26 CET 2011 - vuntz@opensuse.org + +- Move gvfsd-metadata daemon to the main gvfs package, and ship + dbus .service files with their appropriate daemons, to avoid + declaring a dbus service if the binary is not installed. + +------------------------------------------------------------------- +Mon Feb 28 11:11:32 UTC 2011 - fcrozat@novell.com + +- Update to version 1.7.2: + + ftp: Parse mode, user and group for unix listings + + ftp: Implement chmod + + sftp: Catch invalid argument type for chmod command + + smb: Catch invalid argument type when setting mtime + + Updated translations. +- Changes from version 1.7.1: + + ftp: Fix refcounting of addresses when connecting + + ftp: Detect TLS and SSL support + + afc: Add ability to mount the house-arrest service + + afc: Add support for House Arrest protocol to access + the Documents/ folder within applications + + Fix gvfs client code on ARM platform + + Various build issues fixed + + Updated translations. + ------------------------------------------------------------------- Thu Jan 13 18:31:47 CET 2011 - hpj@novell.com - Add gvfs-dav-recursive-directory-ops.patch (bnc#395225). This makes copying directories over WebDAV work. +------------------------------------------------------------------- +Thu Dec 16 17:40:53 CET 2010 - vuntz@opensuse.org + +- Update to version 1.7.0: + + sftp: Close pty master in child process to prevent SELinux + denial + + fuse: Add proper truncate support for open() + + Port to GSettings + + gdu: Treat mounts as hidden if they have a path element + that starts with a dot + + Updated translations. +- Drop gvfs-glib-2.27.patch: this is not needed anymore. +- Rebase gvfs-dice-backend.patch, gvfs-nds.patch and + gvfs-nvvfs.patch. +- Remove gconf2-devel BuildRequires. +- Remove check for openSUSE 11.1 and earlier: we won't support 11.1 + anymore. +- Handle gsettings schemas: add %glib2_gsettings_schema_requires + for gvfs-backends, and %glib2_gsettings_schema_post(un) in the + gvfs-backends scriptlets. + ------------------------------------------------------------------- Mon Dec 6 16:10:56 CET 2010 - vuntz@opensuse.org diff --git a/gvfs.spec b/gvfs.spec index aaf8701..31924cf 100644 --- a/gvfs.spec +++ b/gvfs.spec @@ -18,8 +18,9 @@ Name: gvfs -Version: 1.6.6 -Release: 3 +Version: 1.9.0 +Release: 1 +# FIXME: add libbluray BuildRequires once available (fate#312440) License: LGPLv2.0+ Summary: VFS functionality for GLib Url: http://www.gnome.org @@ -32,33 +33,26 @@ Patch1: gvfs-dice-backend.patch Patch5: gvfs-nvvfs.patch # PATCH-FEATURE-OPENSUSE gvfs-nds.patch ksamrat@novell.com -- Provides NDS browsing for nautilus Patch6: gvfs-nds.patch -# PATCH-FIX-UPSTREAM gvfs-glib-2.27.patch bgo#635252 vuntz@opensuse.org -- Fix build with recent glib -Patch7: gvfs-glib-2.27.patch -# PATCH-FIX-UPSTREAM gvfs-dav-recursive-directory-ops.patch bnc#395225 bgo#551339 hpj@novell.com -- Make DAV recursive copy/move work, taken from http://gitorious.org/lanedo/gvfs/commits/dav_sync_io -Patch8: gvfs-dav-recursive-directory-ops.patch BuildRequires: bluez-devel BuildRequires: dbus-1-glib-devel BuildRequires: fuse-devel -BuildRequires: gconf2-devel BuildRequires: glib2-devel BuildRequires: intltool BuildRequires: libarchive-devel BuildRequires: libavahi-glib-devel BuildRequires: libcdio-devel BuildRequires: libexpat-devel +BuildRequires: libgdu-devel BuildRequires: libgnome-keyring-devel BuildRequires: libgphoto2-devel -BuildRequires: libimobiledevice-devel +BuildRequires: libgudev-1_0-devel +BuildRequires: libimobiledevice-devel >= 1.1.0 BuildRequires: libsmbclient-devel BuildRequires: libsoup-devel BuildRequires: pkg-config BuildRequires: translation-update-upstream -%if %suse_version > 1110 -BuildRequires: libgdu-devel -BuildRequires: libgudev-1_0-devel -%endif -Recommends: %{name}-lang Requires: libgvfscommon0 = %{version} +Recommends: %{name}-lang Recommends: gvfs-backends Recommends: gvfs-common Recommends: gvfs-fuse @@ -93,6 +87,7 @@ Group: Development/Libraries/C and C++ Requires: %{name} = %{version} Recommends: gvfs-backend-afc Recommends: obex-data-server +%glib2_gsettings_schema_requires %description backends VFS functionality for GLib. @@ -123,12 +118,10 @@ translation-update-upstream %patch1 -p1 %patch5 -p1 %patch6 -p1 -%patch7 -p1 -%patch8 -p1 - -%build autoreconf -f libtoolize -c -f + +%build %configure \ --libexecdir=%{_libexecdir}/%{name} \ --disable-static @@ -151,6 +144,12 @@ chmod -x %{buildroot}%{_sysconfdir}/profile.d/* %postun %glib2_gio_module_postun +%post backends +%glib2_gsettings_schema_post + +%postun backends +%glib2_gsettings_schema_postun + %post -n libgvfscommon0 -p /sbin/ldconfig %postun -n libgvfscommon0 -p /sbin/ldconfig @@ -162,13 +161,15 @@ rm -rf %{buildroot} %defattr(-, root, root) %doc AUTHORS NEWS README TODO %{_bindir}/* -%{_datadir}/dbus-1/services/*.service %dir %{_datadir}/%{name} %dir %{_datadir}/%{name}/mounts %dir %{_datadir}/%{name}/remote-volume-monitors %{_libdir}/gio/modules/*.so %dir %{_libexecdir}/%{name} %{_libexecdir}/%{name}/gvfsd +%{_datadir}/dbus-1/services/gvfs-daemon.service +%{_libexecdir}/%{name}/gvfsd-metadata +%{_datadir}/dbus-1/services/gvfs-metadata.service %{_sysconfdir}/profile.d/* %files fuse @@ -178,17 +179,20 @@ rm -rf %{buildroot} %files backend-afc %defattr(-, root, root) %{_libexecdir}/%{name}/gvfs-afc-volume-monitor +%{_datadir}/dbus-1/services/org.gtk.Private.AfcVolumeMonitor.service %{_datadir}/%{name}/remote-volume-monitors/afc.monitor %{_libexecdir}/%{name}/gvfsd-afc %{_datadir}/%{name}/mounts/afc.mount %files backends %defattr(-, root, root) -%if %suse_version > 1110 +%if 0%{suse_version} > 1110 %{_libexecdir}/%{name}/gvfs-gdu-volume-monitor +%{_datadir}/dbus-1/services/org.gtk.Private.GduVolumeMonitor.service %{_datadir}/%{name}/remote-volume-monitors/gdu.monitor %endif %{_libexecdir}/%{name}/gvfs-gphoto2-volume-monitor +%{_datadir}/dbus-1/services/org.gtk.Private.GPhoto2VolumeMonitor.service %{_datadir}/%{name}/remote-volume-monitors/gphoto2.monitor %{_libexecdir}/%{name}/gvfsd-archive %{_datadir}/%{name}/mounts/archive.mount @@ -213,7 +217,6 @@ rm -rf %{buildroot} %{_datadir}/%{name}/mounts/http.mount %{_libexecdir}/%{name}/gvfsd-localtest %{_datadir}/%{name}/mounts/localtest.mount -%{_libexecdir}/%{name}/gvfsd-metadata %{_libexecdir}/%{name}/gvfsd-nds %{_datadir}/%{name}/mounts/nds.mount %{_libexecdir}/%{name}/gvfsd-network @@ -231,6 +234,15 @@ rm -rf %{buildroot} # gvfsd-trash is GPLv3 because of trashlib. %{_libexecdir}/%{name}/gvfsd-trash %{_datadir}/%{name}/mounts/trash.mount +# GSettings schemas & conversion data +# Those schemas are used by gvfsd-network & gvfsd-smb +%{_datadir}/glib-2.0/schemas/org.gnome.system.dns_sd.gschema.xml +%{_datadir}/glib-2.0/schemas/org.gnome.system.gvfs.enums.xml +%{_datadir}/glib-2.0/schemas/org.gnome.system.smb.gschema.xml +%dir %{_datadir}/GConf +%dir %{_datadir}/GConf/gsettings +%{_datadir}/GConf/gsettings/gvfs-dns-sd.convert +%{_datadir}/GConf/gsettings/gvfs-smb.convert %files -n libgvfscommon0 %defattr(-, root, root)