GNOME Bugzilla – Bug 749314
Cannot restore a just-trashed file
Last modified: 2015-10-14 17:08:38 UTC
Created attachment 303308 [details] reproducer GLib 2.45.1, not reproducible with 2.44 1. In nautilus, trash a local file (by hitting delete) 2. Visit the trash 3. Select the file and hit "Restore" I get a message "Could not determine original location of “sintel-1024-surround.mp4” The item cannot be restored from the Rubbish Bin" instead of having the item restored. I think this is because gvfs doesn't know the original path (gvfs-info trash:///foo confirms this). If I restart gvfsd-trash then it this field is populated and the file can be restored. Attached is a reproducer which fails with glib master but passes with 2.44.0. It prints whether the trashed item has "trash::orig-path" or not.
the regression is in 2.46 now
*** Bug 755335 has been marked as a duplicate of this bug. ***
My analysis from the other bug (which on further research appears to be true): This is related to the file monitor changes. The biggest effect of those changes is that events are now reported immediately instead of waiting for 1 second. It may be that the info file is not yet (fully) on disk at the point that the event is noticed. The old code added a 1-second delay to everything, giving more time for the info file to make it to disk. On the "trashing" side we look for a unique filename in the trash folder by creating an empty info file with that name and then moving the file to the trash and then writing out the contents of the info file. It's pretty clear that gvfs-trash is now picking up the empty info file. This is pretty insane -- I think the correct fix here is to write the full contents of the info file before moving the file into the trash. That's a fix in g_local_file_trash()
Created attachment 312363 [details] [review] g_local_file_trash: write info file first Recent changes to file monitors removed the delay before events were reported. Among other things, this caused the trash backend of gvfs to notice trashed files sooner than before. On noticing trashed files, the backend tries to read the info file to discover (among other things) the original location of the file. Unfortunately, g_local_file_trash() does a strange dance when trashing a file. It does a loop of open(O_EXCL) in order to file an empty filename in the trash to write an info file to, trashes the file, and only then writes the contents of the info file. This means that at the time the file is moved to the trash, the info file is an empty stub. Change the order so that we write out the actual content of the info file first. If the actual trash files then we will unlink the info file anyway.
btw, trash spec has this to say: """ When trashing a file or directory, the implementation MUST create the corresponding file in $trash/info first. """ So the old code is definitely buggy.
Review of attachment 312363 [details] [review]: Looks good to me, module a typo in the commit message "trash files" was meant to be "trash fails", I guess
Review of attachment 312363 [details] [review]: I just tested this on Rawhide, and it fixes the bug for me.
Might it fix the related bug #749317 too? Could you comment/check please?
Attachment 312363 [details] pushed as 8ece2de - g_local_file_trash: write info file first