[gvfs] [Fuse] Make created files visible immediately on WebDAV



commit 4c052eee07df06e0a5d1d19fb68259c0ccfcbd92
Author: Stefan Hajnoczi <stefanha gmail com>
Date:   Wed Mar 23 19:37:52 2011 +0100

    [Fuse] Make created files visible immediately on WebDAV
    
    This patch changes .vfs_create() to force file creation and then opens
    the file again for replacement.  This ensures that the created file is
    visible before its file handle is released.
    
    Simple programs like touch(1) and cp(1) encounter ENOENT from creat(2)
    on a WebDAV volume.  FUSE calls .vfs_create() followed by .vfs_getattr()
    on the file as part of creat(2).  The .vfs_getattr() call after
    .vfs_create() fails with ENOENT since the file handle is still open and
    the file has not yet been created on the server side.  The WebDAV server
    fails the PROPFIND request to the non-existent file.
    
    Solve this problem by creating a file first and then reusing .vfs_open()
    code to open the file writeable with O_TRUNC.
    
    Signed-off-by: Hans Petter Jansson <hpj cl no>

 client/gvfsfusedaemon.c |   69 +++++++++++++++++++++-------------------------
 1 files changed, 32 insertions(+), 37 deletions(-)
---
diff --git a/client/gvfsfusedaemon.c b/client/gvfsfusedaemon.c
index bc3090d..a331dfd 100644
--- a/client/gvfsfusedaemon.c
+++ b/client/gvfsfusedaemon.c
@@ -991,6 +991,34 @@ setup_output_stream (GFile *file, FileHandle *fh, int flags)
 }
 
 static gint
+open_common (const gchar *path, struct fuse_file_info *fi, GFile *file, int output_flags)
+{
+  gint        result;
+  FileHandle *fh = get_or_create_file_handle_for_path (path);
+
+  g_mutex_lock (fh->mutex);
+
+  /* File exists */
+
+  SET_FILE_HANDLE (fi, fh);
+
+  debug_print ("open_common: flags=%o\n", fi->flags);
+
+  /* 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)
+    result = setup_output_stream (file, fh, fi->flags | output_flags);
+  else
+    result = setup_input_stream (file, fh);
+
+  g_mutex_unlock (fh->mutex);
+
+  /* The added reference to the file handle is released in vfs_release() */
+  return result;
+}
+
+static gint
 vfs_open (const gchar *path, struct fuse_file_info *fi)
 {
   GFile *file;
@@ -1013,27 +1041,7 @@ vfs_open (const gchar *path, struct fuse_file_info *fi)
 
           if (file_type == G_FILE_TYPE_REGULAR)
             {
-              FileHandle *fh = get_or_create_file_handle_for_path (path);
-
-              g_mutex_lock (fh->mutex);
-
-              /* File exists */
-
-              SET_FILE_HANDLE (fi, fh);
-
-              debug_print ("vfs_open: flags=%o\n", fi->flags);
-
-              /* 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)
-                result = setup_output_stream (file, fh, fi->flags);
-              else
-                result = setup_input_stream (file, fh);
-
-              g_mutex_unlock (fh->mutex);
-
-              /* The added reference to the file handle is released in vfs_release() */
+              result = open_common (path, fi, file, 0);
             }
           else if (file_type == G_FILE_TYPE_DIRECTORY)
             {
@@ -1108,24 +1116,11 @@ vfs_create (const gchar *path, mode_t mode, struct fuse_file_info *fi)
             }
 
           file_output_stream = g_file_create (file, 0, NULL, &error);
-          set_pid_for_file (file);
           if (file_output_stream)
             {
-              FileHandle *fh = get_or_create_file_handle_for_path (path);
-
-              /* Success */
-
-              g_mutex_lock (fh->mutex);
-
-              SET_FILE_HANDLE (fi, fh);
-
-              file_handle_close_stream (fh);
-              fh->stream = file_output_stream;
-              fh->op = FILE_OP_WRITE;
-
-              g_mutex_unlock (fh->mutex);
-
-              /* The added reference to the file handle is released in vfs_release() */
+              g_output_stream_close (G_OUTPUT_STREAM (file_output_stream), NULL, NULL);
+              g_object_unref (file_output_stream);
+              result = open_common (path, fi, file, O_TRUNC);
             }
           else
             {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]