Only in BUILD.orig: BUILD
diff -ur a/client/gvfsfusedaemon.c b/client/gvfsfusedaemon.c
--- a/client/gvfsfusedaemon.c	2011-09-21 14:00:55.000000000 +0200
+++ b/client/gvfsfusedaemon.c	2011-12-14 17:18:46.000000000 +0100
@@ -1853,6 +1853,13 @@
         {
           g_mutex_lock (fh->mutex);
 
+          if (fh->op == FILE_OP_WRITE)
+            {
+              g_output_stream_close (fh->stream, NULL, NULL);
+              g_object_unref (fh->stream);
+              fh->stream = NULL;
+            }
+
           result = setup_output_stream (file, fh);
 
           if (result == 0)
diff -ur a/daemon/gvfsbackenddav.c b/daemon/gvfsbackenddav.c
--- a/daemon/gvfsbackenddav.c	2011-09-21 14:01:05.000000000 +0200
+++ b/daemon/gvfsbackenddav.c	2011-12-20 20:42:27.000000000 +0100
@@ -889,7 +889,8 @@
   g_file_info_set_name (info, basename);
   g_file_info_set_edit_name (info, basename);
 
-  file_type = G_FILE_TYPE_UNKNOWN;
+  file_type = G_FILE_TYPE_REGULAR;
+  g_file_info_set_file_type (info, file_type);
   mime_type = NULL;
 
   have_display_name = FALSE;
@@ -1922,6 +1923,46 @@
 
 /* *** create () *** */
 static void
+try_create_created_stub (GObject      *source_object,
+                         GAsyncResult *result,
+                         gpointer      user_data)
+{
+  GVfsJob         *job = G_VFS_JOB (user_data);
+  GVfsBackendHttp *op_backend = job->backend_data;
+  GOutputStream   *stream;
+  GError          *error;
+  gboolean         res;
+  SoupURI         *uri;
+  SoupMessage     *put_msg;
+
+  stream = G_OUTPUT_STREAM (source_object);
+  res = g_output_stream_close_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);
+    }
+
+  uri = soup_output_stream_get_uri (stream);
+  put_msg = soup_message_new_from_uri (SOUP_METHOD_PUT, uri);
+
+  /* 
+   * Doesn't work with apache > 2.2.9
+   * soup_message_headers_append (put_msg->request_headers, "If-None-Match", "*");
+   */
+  stream = soup_output_stream_new (op_backend->session, put_msg, -1);
+  g_object_unref (put_msg);
+
+  g_vfs_job_open_for_write_set_handle (G_VFS_JOB_OPEN_FOR_WRITE (job), stream);
+  g_vfs_job_open_for_write_set_can_seek (G_VFS_JOB_OPEN_FOR_WRITE (job), TRUE);
+  g_vfs_job_succeeded (job);
+}
+
+static void
 try_create_tested_existence (SoupSession *session, SoupMessage *msg,
                              gpointer user_data)
 {
@@ -1942,18 +1983,17 @@
   /* TODO: other errors */
 
   uri = soup_message_get_uri (msg);
-  put_msg = soup_message_new_from_uri (SOUP_METHOD_PUT, uri);
 
-  /* 
-   * Doesn't work with apache > 2.2.9
-   * soup_message_headers_append (put_msg->request_headers, "If-None-Match", "*");
-   */
+  put_msg = soup_message_new_from_uri (SOUP_METHOD_PUT, uri);
   stream = soup_output_stream_new (op_backend->session, put_msg, -1);
   g_object_unref (put_msg);
 
-  g_vfs_job_open_for_write_set_handle (G_VFS_JOB_OPEN_FOR_WRITE (job), stream);
-  g_vfs_job_succeeded (job);
-}  
+  g_output_stream_close_async (stream,
+                               G_PRIORITY_DEFAULT,
+                               G_VFS_JOB (job)->cancellable,
+                               try_create_created_stub,
+                               job);
+}
 
 static gboolean
 try_create (GVfsBackend *backend,
@@ -1994,6 +2034,7 @@
   g_object_unref (put_msg);
 
   g_vfs_job_open_for_write_set_handle (G_VFS_JOB_OPEN_FOR_WRITE (job), stream);
+  g_vfs_job_open_for_write_set_can_seek (G_VFS_JOB_OPEN_FOR_WRITE (job), TRUE);
   g_vfs_job_succeeded (job);
 }
 
@@ -2067,6 +2108,57 @@
   return TRUE;
 }
 
+/* *** append () *** */
+static void
+try_append_to_got_data (SoupSession *session, SoupMessage *msg,
+                        gpointer user_data)
+{
+  SoupMessage *put_msg;
+  GOutputStream *stream;
+  GInputStream *input_stream;
+  GVfsJob *job = G_VFS_JOB (user_data);
+  GVfsBackendHttp *op_backend = job->backend_data;
+
+  put_msg = soup_message_new_from_uri (SOUP_METHOD_PUT, soup_message_get_uri (msg));
+
+  stream = soup_output_stream_new (op_backend->session, put_msg, -1);
+  g_object_unref (put_msg);
+
+  g_output_stream_write (stream,
+                         msg->response_body->data,
+                         msg->response_body->length,
+                         G_VFS_JOB (job)->cancellable,
+                         0);
+
+  g_vfs_job_open_for_write_set_handle (G_VFS_JOB_OPEN_FOR_WRITE (job), stream);
+  g_vfs_job_open_for_write_set_can_seek (G_VFS_JOB_OPEN_FOR_WRITE (job), TRUE);
+  g_vfs_job_succeeded (job);
+}
+
+static gboolean
+try_append_to (GVfsBackend *backend,
+              GVfsJobOpenForWrite *job,
+              const char *filename,
+              GFileCreateFlags flags)
+{
+  GVfsBackendHttp *op_backend;
+  SoupURI         *uri;
+
+  op_backend = G_VFS_BACKEND_HTTP (backend);
+
+  uri = http_backend_uri_for_filename (backend, filename, FALSE);
+
+  SoupMessage *msg;
+
+  msg = soup_message_new_from_uri (SOUP_METHOD_GET, uri);
+  soup_uri_free (uri);
+
+  g_vfs_job_set_backend_data (G_VFS_JOB (job), op_backend, NULL);
+  soup_session_queue_message (op_backend->session, msg,
+                              try_append_to_got_data, job);
+  return TRUE;
+}
+
 /* *** write () *** */
 static void
 write_ready (GObject      *source_object,
@@ -2170,6 +2262,31 @@
   return TRUE;
 }
 
+static gboolean
+try_seek_on_write (GVfsBackend *backend,
+                   GVfsJobSeekWrite *job,
+                   GVfsBackendHandle handle,
+                   goffset    offset,
+                   GSeekType  type)
+{
+  GError *error;
+  GOutputStream *stream;
+
+  stream = G_OUTPUT_STREAM (handle);
+
+  error = NULL;
+  if (! g_seekable_seek (G_SEEKABLE (stream), offset, type, G_VFS_JOB (job)->cancellable, &error)) {
+      g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+                        G_IO_ERROR_FAILED,
+                        _("Seek failed"));
+      g_error_free (error);
+      return FALSE;
+  }
+
+  g_vfs_job_succeeded (G_VFS_JOB (job));
+  return TRUE;
+}
+
 static void
 do_make_directory (GVfsBackend          *backend,
                    GVfsJobMakeDirectory *job,
@@ -2342,8 +2459,10 @@
   backend_class->enumerate         = do_enumerate;
   backend_class->try_create        = try_create;
   backend_class->try_replace       = try_replace;
+  backend_class->try_append_to     = try_append_to;
   backend_class->try_write         = try_write;
   backend_class->try_close_write   = try_close_write;
+  backend_class->try_seek_on_write = try_seek_on_write;
   backend_class->make_directory    = do_make_directory;
   backend_class->delete            = do_delete;
   backend_class->set_display_name  = do_set_display_name;
diff -ur a/daemon/soup-output-stream.c b/daemon/soup-output-stream.c
--- a/daemon/soup-output-stream.c	2011-09-21 14:01:05.000000000 +0200
+++ b/daemon/soup-output-stream.c	2011-12-16 20:21:48.000000000 +0100
@@ -23,6 +23,7 @@
 #include <string.h>
 
 #include <glib.h>
+#include <glib/garray.h>
 #include <gio/gio.h>
 
 #include <libsoup/soup.h>
@@ -30,8 +31,6 @@
 #include "soup-output-stream.h"
 #include "soup-input-stream.h"
 
-G_DEFINE_TYPE (SoupOutputStream, soup_output_stream, G_TYPE_OUTPUT_STREAM)
-
 typedef void (*SoupOutputStreamCallback) (GOutputStream *);
 
 typedef struct {
@@ -40,7 +39,7 @@
   SoupMessage *msg;
   gboolean finished;
 
-  goffset size, offset;
+  goffset size, current_size, offset;
   GByteArray *ba;
 
   GCancellable *cancellable;
@@ -78,9 +77,26 @@
 static gboolean soup_output_stream_close_finish (GOutputStream        *stream,
 						 GAsyncResult         *result,
 						 GError              **error);
+static void     soup_output_stream_seekable_iface_init (GSeekableIface  *iface);
+static goffset  soup_output_stream_tell                (GSeekable       *seekable);
+static gboolean soup_output_stream_can_seek            (GSeekable       *seekable);
+static gboolean soup_output_stream_seek                (GSeekable       *seekable,
+                                                        goffset          offset,
+                                                        GSeekType        type,
+                                                        GCancellable    *cancellable,
+                                                        GError         **error);
+static gboolean soup_output_stream_can_truncate        (GSeekable       *seekable);
+static gboolean soup_output_stream_truncate            (GSeekable       *seekable,
+                                                        goffset          offset,
+                                                        GCancellable    *cancellable,
+                                                        GError         **error);
 
 static void soup_output_stream_finished (SoupMessage *msg, gpointer stream);
 
+
+G_DEFINE_TYPE_WITH_CODE (SoupOutputStream, soup_output_stream, G_TYPE_OUTPUT_STREAM,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE, soup_output_stream_seekable_iface_init))
+
 static void
 soup_output_stream_finalize (GObject *object)
 {
@@ -117,6 +133,16 @@
 }
 
 static void
+soup_output_stream_seekable_iface_init (GSeekableIface *iface)
+{
+  iface->tell         = soup_output_stream_tell;
+  iface->can_seek     = soup_output_stream_can_seek;
+  iface->seek         = soup_output_stream_seek;
+  iface->can_truncate = soup_output_stream_can_truncate;
+  iface->truncate_fn  = soup_output_stream_truncate;
+}
+
+static void
 soup_output_stream_init (SoupOutputStream *stream)
 {
   SoupOutputStreamPrivate *priv = SOUP_OUTPUT_STREAM_GET_PRIVATE (stream);
@@ -262,8 +288,17 @@
       return -1;
   }
 
-  g_byte_array_append (priv->ba, buffer, count);
+  if (priv->offset < priv->current_size) {
+    memcpy(priv->ba->data + priv->offset, buffer, MIN(priv->current_size - priv->offset, count));
+  }
+  if (priv->offset + count > priv->current_size) {
+    g_byte_array_append (priv->ba,
+                         buffer + (priv->current_size - priv->offset),
+                         priv->offset + count - priv->current_size);
+  }
+
   priv->offset += count;
+  priv->current_size += count;
   return count;
 }
 
@@ -274,7 +309,7 @@
 {
   SoupOutputStreamPrivate *priv = SOUP_OUTPUT_STREAM_GET_PRIVATE (stream);
 
-  if (priv->size > 0 && priv->offset != priv->size) {
+  if (priv->size > 0 && priv->current_size != priv->size) {
       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE,
 			   "File is incomplete");
       return -1;
@@ -315,8 +350,17 @@
     }
   else
     {
-      g_byte_array_append (priv->ba, buffer, count);
+      if (priv->offset < priv->current_size) {
+        memcpy(priv->ba->data + priv->offset, buffer, MIN(priv->current_size - priv->offset, count));
+      }
+      if (priv->offset + count > priv->current_size) {
+        g_byte_array_append (priv->ba,
+                             buffer + (priv->current_size - priv->offset),
+                             priv->offset + count - priv->current_size);
+      }
+
       priv->offset += count;
+      priv->current_size += count;
       g_simple_async_result_set_op_res_gssize (result, count);
     }
 
@@ -389,7 +433,7 @@
 				      callback, user_data,
 				      soup_output_stream_close_async);
 
-  if (priv->size > 0 && priv->offset != priv->size)
+  if (priv->size > 0 && priv->current_size != priv->size)
     {
       GError *error;
 
@@ -416,3 +460,113 @@
   /* Failures handled in generic close_finish code */
   return TRUE;
 }
+
+static goffset
+soup_output_stream_tell (GSeekable *seekable)
+{
+  SoupOutputStreamPrivate *priv;
+
+  priv = SOUP_OUTPUT_STREAM_GET_PRIVATE (seekable);
+
+  return priv->offset;
+}
+
+static gboolean
+soup_output_stream_can_seek (GSeekable *seekable)
+{
+  return TRUE;
+}
+
+static gboolean
+soup_output_stream_seek (GSeekable    *seekable,
+                         goffset        offset,
+                         GSeekType      type,
+                         GCancellable  *cancellable,
+                         GError       **error)
+{
+  SoupOutputStreamPrivate *priv;
+  goffset absolute;
+
+  priv = SOUP_OUTPUT_STREAM_GET_PRIVATE (seekable);
+
+  switch (type)
+    {
+      case G_SEEK_CUR:
+        absolute = priv->offset + offset;
+        break;
+
+      case G_SEEK_SET:
+        absolute = offset;
+        break;
+
+      case G_SEEK_END:
+        absolute = priv->current_size + offset;
+        break;
+
+      default:
+        g_set_error_literal (error,
+                            G_IO_ERROR,
+                            G_IO_ERROR_INVALID_ARGUMENT,
+                            "Invalid GSeekType supplied");
+
+        return FALSE;
+    }
+
+  if (absolute < 0)
+    {
+      g_set_error_literal (error,
+                            G_IO_ERROR,
+                            G_IO_ERROR_INVALID_ARGUMENT,
+                            "Invalid seek request");
+      return FALSE;
+    }
+
+  if (absolute > priv->current_size)
+    {
+      g_array_set_size (priv->ba, absolute);
+      memset(priv->ba->data+priv->current_size, 0, absolute-priv->current_size);
+      priv->current_size = absolute;
+    }
+
+  priv->offset = absolute;
+
+  return TRUE;
+}
+
+static gboolean
+soup_output_stream_can_truncate (GSeekable *seekable)
+{
+  return TRUE;
+}
+
+static gboolean
+soup_output_stream_truncate (GSeekable     *seekable,
+                             goffset        offset,
+                             GCancellable  *cancellable,
+                             GError       **error)
+{
+  SoupOutputStreamPrivate *priv;
+
+  priv = SOUP_OUTPUT_STREAM_GET_PRIVATE (seekable);
+
+  if (priv->size > 0 && offset > priv->size) {
+      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE,
+                           "Write would exceed caller-defined file size");
+      return FALSE;
+  }
+
+  g_array_set_size (priv->ba, offset);
+
+  priv->current_size = offset;
+  priv->offset = MAX(offset, priv->offset);
+
+  return TRUE;
+}
+
+SoupURI*
+soup_output_stream_get_uri (GOutputStream  *stream)
+{
+  SoupOutputStreamPrivate *priv = SOUP_OUTPUT_STREAM_GET_PRIVATE (stream);
+
+  return soup_message_get_uri(priv->msg);
+}
diff -ur a/daemon/soup-output-stream.h b/daemon/soup-output-stream.h
--- a/daemon/soup-output-stream.h	2011-09-21 14:01:04.000000000 +0200
+++ b/daemon/soup-output-stream.h	2011-12-16 20:21:59.000000000 +0100
@@ -53,6 +53,7 @@
 };
 
 GType soup_output_stream_get_type (void) G_GNUC_CONST;
+SoupURI* soup_output_stream_get_uri (GOutputStream *stream);
 
 GOutputStream *soup_output_stream_new         (SoupSession         *session,
 					       SoupMessage         *msg,
