--- gvfsfusedaemon.c.orig-1.28.2	2017-02-02 10:39:52.763983714 +0000
+++ gvfsfusedaemon.c	2017-02-02 13:21:55.215463076 +0000
@@ -60,7 +60,8 @@
 typedef enum {
   FILE_OP_NONE,
   FILE_OP_READ,
-  FILE_OP_WRITE
+  FILE_OP_WRITE,
+  FILE_OP_READWRITE
 } FileOp;
 
 typedef struct {
@@ -270,6 +271,10 @@
           g_output_stream_close (file_handle->stream, NULL, NULL);
           break;
           
+        case FILE_OP_READWRITE:
+          g_io_stream_close (file_handle->stream, NULL, NULL);
+          break;
+          
         default:
           g_assert_not_reached ();
         }
@@ -834,6 +839,11 @@
                                                   query_attributes,
                                                   NULL, &error);
       break;
+    case FILE_OP_READWRITE:
+      file_info = g_file_io_stream_query_info (G_FILE_IO_STREAM (fh->stream),
+                                                  query_attributes,
+                                                  NULL, &error);
+      break;
     default:
       return -ENOTSUP;
     }
@@ -978,7 +988,7 @@
     {
       debug_print ("setup_input_stream: have stream\n");
 
-      if (fh->op == FILE_OP_READ)
+      if (fh->op == FILE_OP_READ || fh->op == FILE_OP_READWRITE)
         {
           debug_print ("setup_input_stream: doing read\n");
         }
@@ -998,12 +1008,12 @@
       debug_print ("setup_input_stream: no stream\n");
       fh->stream = g_file_read (file, NULL, &error);
       fh->pos = 0;
-    }
 
-  if (fh->stream)
-    fh->op = FILE_OP_READ;
-  else
-    fh->op = FILE_OP_NONE;
+      if (fh->stream)
+        fh->op = FILE_OP_READ;
+      else
+        fh->op = FILE_OP_NONE;
+    }
 
   if (error)
     {
@@ -1023,7 +1033,7 @@
 
   if (fh->stream)
     {
-      if (fh->op == FILE_OP_WRITE)
+      if (fh->op == FILE_OP_WRITE || fh->op == FILE_OP_READWRITE)
         {
         }
       else
@@ -1036,6 +1046,7 @@
 
   if (!fh->stream)
     {
+      fh->op = FILE_OP_NONE;
       if (flags & O_TRUNC)
         {
           fh->stream = g_file_replace (file, NULL, FALSE, 0, NULL, &error);
@@ -1044,15 +1055,106 @@
       else if (flags & O_APPEND)
         fh->stream = g_file_append_to (file, 0, NULL, &error);
       else
-        result = -ENOTSUP;
+        {
+          /* Best option for O_WRONLY is open for appending and seek to start.
+           * If seeking is not possible, this mode is not supported */
+          fh->stream = g_file_append_to (file, 0, NULL, &error);
+          if (fh->stream)
+            {
+              if (!g_seekable_can_seek (G_SEEKABLE (fh->stream)) ||
+                  !g_seekable_seek (G_SEEKABLE (fh->stream), 0, G_SEEK_SET, NULL, &error))
+                {
+                  g_output_stream_close (fh->stream, NULL, NULL);
+                  g_object_unref (fh->stream);
+                  fh->stream = NULL;
+                  if (error)
+                    g_error_free (error);
+                  error = NULL;
+                  result = -ENOTSUP;
+                }
+            }
+        }
+
       if (fh->stream)
-        fh->pos = g_seekable_tell (G_SEEKABLE (fh->stream));
+        fh->op = FILE_OP_WRITE;
+    }      
+
+  if (fh->stream)
+    fh->pos = g_seekable_tell (G_SEEKABLE (fh->stream));
+
+  if (error)
+    {
+      result = -errno_from_error (error);
+      g_error_free (error);
     }
 
+  return result;
+}
+
+static gint
+setup_io_stream (GFile *file, FileHandle *fh, int flags)
+{
+  GError *error  = NULL;
+  gint    result = 0;
+
   if (fh->stream)
-    fh->op = FILE_OP_WRITE;
-  else
-    fh->op = FILE_OP_NONE;
+    {
+      if (fh->op == FILE_OP_READWRITE)
+        {
+        }
+      else if (fh->op == FILE_OP_WRITE)
+        {
+          g_output_stream_close (fh->stream, NULL, NULL);
+          g_object_unref (fh->stream);
+          fh->stream = NULL;
+        }
+      else if (fh->op == FILE_OP_READ)
+        {
+          g_input_stream_close (fh->stream, NULL, NULL);
+          g_object_unref (fh->stream);
+          fh->stream = NULL;
+        }
+    }
+
+  if (!fh->stream)
+    {
+      fh->op = FILE_OP_NONE;
+      if (flags & O_TRUNC)
+        {
+          fh->stream = g_file_replace_readwrite (file, NULL, FALSE, 0, NULL, &error);
+          fh->size = 0;
+        }
+      else if (flags & O_APPEND)
+        {
+          /* Best option for O_RDWR|O_APPEND is open for read-write and seek to end.
+           * If seeking is not possible, this mode is not supported */
+          fh->stream = g_file_open_readwrite (file, NULL, &error);
+          if (fh->stream)
+            {
+              if (!g_seekable_can_seek (G_SEEKABLE (fh->stream)) ||
+                  !g_seekable_seek (G_SEEKABLE (fh->stream), 0, G_SEEK_END, NULL, &error))
+                {
+                  g_io_stream_close (fh->stream, NULL, NULL);
+                  g_object_unref (fh->stream);
+                  fh->stream = NULL;
+                      
+                  if (error)
+                    g_error_free (error);
+                  error = NULL;
+                      
+                  result = -ENOTSUP;
+                }
+            }
+        }
+      else
+        fh->stream = g_file_open_readwrite (file, NULL, &error);
+      
+      if (fh->stream)
+          fh->op = FILE_OP_READWRITE;
+    }
+
+  if (fh->stream)
+    fh->pos = g_seekable_tell (G_SEEKABLE (fh->stream));
 
   if (error)
     {
@@ -1078,7 +1180,9 @@
   /* Set up a stream here, so we can check for errors */
   set_pid_for_file (file);
 
-  if (fi->flags & O_WRONLY || fi->flags & O_RDWR)
+  if (fi->flags & O_RDWR)
+    result = setup_io_stream (file, fh, fi->flags | output_flags);
+  else if (fi->flags & O_WRONLY)
     result = setup_output_stream (file, fh, fi->flags | output_flags);
   else
     result = setup_input_stream (file, fh);
@@ -1260,7 +1364,10 @@
   gint          result          = 0;
   GError       *error           = NULL;
 
-  input_stream = fh->stream;
+  if (fh->op == FILE_OP_READWRITE)
+    input_stream = g_io_stream_get_input_stream (G_IO_STREAM (fh->stream));
+  else
+    input_stream = fh->stream;
 
   if (offset != fh->pos)
     {
@@ -1417,7 +1524,10 @@
 
   debug_print ("write_stream: %d bytes at offset %d.\n", input_buf_size, offset);
 
-  output_stream = fh->stream;
+  if (fh->op == FILE_OP_READWRITE)
+    output_stream = g_io_stream_get_output_stream (G_IO_STREAM (fh->stream));
+  else
+    output_stream = fh->stream;
 
   if (!is_append && offset != fh->pos)
     {
@@ -1876,6 +1986,11 @@
 					    G_FILE_ATTRIBUTE_STANDARD_SIZE,
 					    NULL, NULL);
 
+  else if (fh->op == FILE_OP_READWRITE)
+    info = g_file_io_stream_query_info (fh->stream,
+					G_FILE_ATTRIBUTE_STANDARD_SIZE,
+					NULL, NULL);
+
   res = FALSE;
   if (info)
     {
