GNOME Bugzilla – Bug 777152
Can't perform write operations without O_TRUNC, nor O_APPEND
Last modified: 2018-05-14 11:01:29 UTC
Hi I've recently stumbled upon a strange issue with gvfs in combination with nfs (via libnfs). On another computer in my local network, I set up an NFS share. This is a simple run-of-the-mill NFS share that has the following options set: rw, all_squash, sync, anonuid, anongid Everything seems to work correctly: I can read, create and update files. Well... most files that is; for some unknown reason I can't seem to perform some write actions. For example, opening up an application such as easytag to update music file tags causes a write error. The description of this error is sometimes "Could not write to file" and sometimes something like "Could not create temporary file". Trying to do the same with nfs-utils (Arch Linux) and mount: # mount localserver:/mnt/bulk/music -t nfs /mnt/testmount -o rw ... works fine however (i.e. I can update the tags). This somewhat reassured me that my NFS server is working correctly. Mounting it with gvfs gives me the same error as before. I thought this was related to libnfs at first and went looking at its issue list and stumbled onto a relaetd ticket [1], which is very much what I'm experiencing. I also tried the suggestions from this ticket to run an strace, a wireshark sniff, and also enabling gvfs logging, but none of these seem to report any kind of error. If there is anything I can try to help debug this, I'll be happy to help. I can get by with a manual mount for the moment, but gvfs in nautilus is just so terribly convenient that it'd be nicer if this worked :-). [1] https://github.com/sahlberg/libnfs/issues/161
Thanks for your bug report. Can you please write the error strings precisely (can be in another language), or provide screenshot? I think that you see another bug than the one which is described on github. Do you also see "Operation not supported" as it is written there? I suppose this is probably partially Bug 768281...
Thanks for your quick response. I've disabled my locale to get the English description of the error in easytag, which is literally: Cannot write tag in file 'Test.flac' Operation not supported So it appears that I'm indeed also getting the "Operation not supported" error. For some reason, when I have my locale enabled again, the message becomes what translates to something like "Could not create temporary file". I've examined the linked issues and they do seem similar. The only difference I can spot is that I'm not using a symlink (at least not directly); I'm running easytag from the /run/user/<uid>/gvfs/<host-uri>/<path> folder directly. Looking back at the GitHub issue, I also tried the mentioned application exfalso, to attempt to rule out easytag doing some hocus pocus. Unfortunately, it produces a similar error.
Thanks for the reply. I see the following debug output from fuse daemon for both applications (easytag, exfalso): open_common: flags=100002 vfs_open: -> Operation not supported It means that the applications don't use GIO API, but they access the files using POSIX API over FUSE mount point... Unfortunately, both applications open the file with O_RDWR without O_APPEND, nor O_TRUNC, which is currently unsupported, see Bug 632296.
Created attachment 344774 [details] [review] Patch to support all open() modes
Is there a reason why "GIO API isn't fully compatible with POSIX API" (as mentioned in bug 768281)? I don't know enough about GIO to comment. Nonetheless, I wrote a patch to gvfs fuse daemon to support O_RDWR and O_WRONLY with all combinations of other flags (none, O_APPEND, O_TRUNC), using what I learned today reading the GIO API docs. Would this work? Something that troubles me is that the existing fuse daemon, if asked to read a write-only file or vice-versa, will close the input/outputstream and open the file again in order to obey the request, rather than error "no, this is a read-only/write-only file". Why does it do this?
Review of attachment 344774 [details] [review]: Thanks for your patch, however... ::: gvfsfusedaemon.c.orig-1.28.2 @@ +1058,3 @@ + { + /* Best option for O_WRONLY is open for appending and seek to start. + * If seeking is not possible, this mode is not supported */ As far as I know this is exactly what doesn't work generally... We use O_APPEND where possible in that case, see what "man 2 open" says for O_APPEND: The file is opened in append mode. Before each write(2), the file offset is positioned at the end of the file, as if with lseek(2). As far as I know seeking might be possible, but the offset is changed to the end immediately before write, so it is useless...
Created attachment 345100 [details] gio append example See the attached example and its output: $ gcc -Wall -g write.c `pkg-config --cflags --libs glib-2.0 gio-2.0` -o write && ./write g_file_set_contents: /tmp/test abcdef g_file_append_to: /tmp/test g_seekable_can_seek: 1 g_seekable_seek: 0 g_seekable_tell: 0 g_output_stream_write: 012345 g_seekable_tell: 12 g_output_stream_close: /tmp/test g_file_get_contents: /tmp/test abcdef012345 Seek is possible, you can seek to the beginning, but the stream is written to the end of file anyway...
I am afraid of that only possible solution is a usage of g_file_create with a temporary file in such case, and copying data from the original file in case of seek/close if needed... but this might be pretty ineffective for big files... and fragile, but truly, it is already a bit fragile as you have also noted: (In reply to Stuart Caie from comment #5) > ... > > Something that troubles me is that the existing fuse daemon, if asked to > read a write-only file or vice-versa, will close the input/outputstream and > open the file again in order to obey the request, rather than error "no, > this is a read-only/write-only file". Why does it do this? I suppose it is because of O_RDWR support, because backends don't support g_file_open_readwrite...
Just a note that I was probably wrong when I told that GIO API isn't fully compatible with POSIX. GIO API is compatible with POSIX, however, GVfs is missing an implementation of GFileIOStream... This is definitely not possible for various backends, however, it should be possible to implement it for SMB, NFS and others... and use caching as suggested in Comment 8 for others.
Many id3-Tag-Programs for mp3 do: fp = fopen("filename1", "r+"); and this does not work. Using g_file_open_readwrite() will work?
Isn't this a dup of the long standing bug 748106 ( https://bugzilla.gnome.org/show_bug.cgi?id=748106 ) ?
LibreOffice also throws an error while opening a file via SFTP backend. It works via DAV backend, though.
(In reply to Martin Stolle from comment #11) > Isn't this a dup of the long standing bug 748106 ( > https://bugzilla.gnome.org/show_bug.cgi?id=748106 ) ? It is. (In reply to ernst from comment #12) > LibreOffice also throws an error while opening a file via SFTP backend. It > works via DAV backend, though. If I am not mistaken, LibreOffice uses its own implementation for DAV... *** This bug has been marked as a duplicate of bug 748106 ***