GNOME Bugzilla – Bug 734568
fuse: issues with 'mv' and directories inside gvfs-fuse directories for backends without native move operation
Last modified: 2014-08-09 22:18:38 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
Thanks, that looks sensible. I also removed the explicit mapping from EISDIR to EXDEV since that seems incorrect.