summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@gmail.com>2011-03-23 19:37:52 +0100
committerHans Petter Jansson <hpj@cl.no>2011-03-23 19:37:52 +0100
commit4c052eee07df06e0a5d1d19fb68259c0ccfcbd92 (patch)
tree11056fc1d19e833d41cf84a24bf5da670c3dcf71 /client
parent27a93d034fc07181f870457ba0bfaf4f358f3124 (diff)
downloadgvfs-4c052eee07df06e0a5d1d19fb68259c0ccfcbd92.tar.gz
[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>
Diffstat (limited to 'client')
-rw-r--r--client/gvfsfusedaemon.c69
1 files changed, 32 insertions, 37 deletions
diff --git a/client/gvfsfusedaemon.c b/client/gvfsfusedaemon.c
index bc3090d6..a331dfdc 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
{