After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 734568 - fuse: issues with 'mv' and directories inside gvfs-fuse directories for backends without native move operation
fuse: issues with 'mv' and directories inside gvfs-fuse directories for backe...
Status: RESOLVED FIXED
Product: gvfs
Classification: Core
Component: fuse
git master
Other Linux
: Normal normal
: ---
Assigned To: gvfs-maint
gvfs-maint
Depends on:
Blocks:
 
 
Reported: 2014-08-09 20:42 UTC by Rok Mandeljc
Modified: 2014-08-09 22:18 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Add GError to errno mappings for G_IO_ERROR_WOULD_RECURSE and G_IO_ERROR_WOULD_MERGE (1.64 KB, patch)
2014-08-09 20:42 UTC, Rok Mandeljc
committed Details | Review

Description Rok Mandeljc 2014-08-09 20:42:45 UTC
Created attachment 283022 [details] [review]
Add GError to errno mappings for G_IO_ERROR_WOULD_RECURSE and G_IO_ERROR_WOULD_MERGE

There appears to be an issue with using 'mv' on gvfs-fuse directories for backends that do not support native move operation (and thus use the open-copy-delete fallback), such as MTP.

In the example below, an existing directory 'dir1' is supposed to be moved/renamed to (non-existing) 'dir2':

[rok@alpha SD card (20001)]$ pwd
/var/run/user/1000/gvfs/mtp:host=%5Busb%3A001%2C005%5D/SD card (20001)
[rok@alpha SD card (20001)]$ mv dir1 dir2
mv: cannot move ‘dir1’ to ‘dir2’: Input/output error

The corresponding debug messages from gvfsd-fuse:
------------------------------------------------------------------------
unique: 187, opcode: LOOKUP (1), nodeid: 3, insize: 45, pid: 27278
LOOKUP /mtp:host=%5Busb%3A001%2C005%5D/SD card (20001)/dir2
getattr /mtp:host=%5Busb%3A001%2C005%5D/SD card (20001)/dir2
   unique: 187, error: -2 (No such file or directory), outsize: 16
unique: 188, opcode: LOOKUP (1), nodeid: 3, insize: 45, pid: 27278
LOOKUP /mtp:host=%5Busb%3A001%2C005%5D/SD card (20001)/dir1
getattr /mtp:host=%5Busb%3A001%2C005%5D/SD card (20001)/dir1
   NODEID: 12
   unique: 188, success, outsize: 144
unique: 189, opcode: LOOKUP (1), nodeid: 3, insize: 45, pid: 27278
LOOKUP /mtp:host=%5Busb%3A001%2C005%5D/SD card (20001)/dir2
getattr /mtp:host=%5Busb%3A001%2C005%5D/SD card (20001)/dir2
   unique: 189, error: -2 (No such file or directory), outsize: 16
unique: 190, opcode: LOOKUP (1), nodeid: 3, insize: 45, pid: 27278
LOOKUP /mtp:host=%5Busb%3A001%2C005%5D/SD card (20001)/dir2
getattr /mtp:host=%5Busb%3A001%2C005%5D/SD card (20001)/dir2
   unique: 190, error: -2 (No such file or directory), outsize: 16
unique: 191, opcode: RENAME (12), nodeid: 3, insize: 58, pid: 27278
rename /mtp:host=%5Busb%3A001%2C005%5D/SD card (20001)/dir1 /mtp:host=%5Busb%3A001%2C005%5D/SD card (20001)/dir2
   unique: 191, error: -5 (Input/output error), outsize: 16
------------------------------------------------------------------------

The problem is that g_file_move() in vfs_rename() returns G_IO_ERROR_WOULD_RECURSE (a documented behavior for cases when native move operation is not available [1]). Since no mapping is defined in errno_from_error(), it ends up being mapped to -EIO, whereas 'mv' requires -EXDEV to fall back to recursive copy & delete.

Note that code in vfs_rename() explicitly checks and remaps an -EISDIR (mapped from G_IO_ERROR_IS_DIRECTORY) to -EXDEV; however, G_IO_ERROR_IS_DIRECTORY is supposed to be returned when trying to overwrite a file over directory and is not applicable here.

[1] https://developer.gnome.org/gio/stable/GFile.html#g-file-move


There is a similar issue when trying to overwrite (merge) two non-empty directories:

[rok@alpha ~]$ mkdir dir1
[rok@alpha ~]$ touch dir1/fileA
[rok@alpha ~]$ mkdir dir2
[rok@alpha ~]$ mkdir dir2/dir1
[rok@alpha ~]$ touch dir2/dir1/fileB
[rok@alpha ~]$ mv dir1 dir2
mv: cannot move ‘dir1’ to ‘dir2/dir1’: Directory not empty

whereas the same operation on the MTP volume produces:

[rok@alpha SD card (20001)]$ mv dir1 dir2
mv: cannot move ‘dir1’ to ‘dir2/dir1’: Input/output error

In this case, G_IO_ERROR_WOULD_MERGE is returned, but again, no mapping is defined, so it ends up being mapped to -EIO and results in incorrect error message.


The attached patch adds the following error mappings:
G_IO_ERROR_WOULD_RECURSE -> EXDEV
G_IO_ERROR_WOULD_MERGE -> ENOTEMPTY
Comment 1 Ross Lagerwall 2014-08-09 22:18:38 UTC
Thanks, that looks sensible.  I also removed the explicit mapping from EISDIR to EXDEV since that seems incorrect.