Finder.app doesn't respond to EXDEV properly, breaking some NFS use cases

Originator:song
Number:rdar://30408641 Date Originated:2/7/2017
Status:Open Resolved:No
Product:macOS+SDK/Finder.app Product Version:10.12.3
Classification: Reproducible:Always
 
Summary:
In Finder, user can drag&drop files or folders to move them from one location to another, when both source and destination are within the same volume, or mount point. When they are in different mount points, moving by drag&drop is also possible, with Cmd being held. This is great and has been internalized by the majority of Mac users.

Internally on a unix system, moving is typically done by the rename() system call. The rename() call can only handle the move within the same filesystem. If source and destination locations are on different volumes, rename() would fail. The unix standard (http://pubs.opengroup.org/onlinepubs/009695399/functions/rename.html) defines an error code, EXDEV, specifically for this case. The error code allows userspace program to tell "moving across device" from other errors, thus handle differently. The "mv" command, for example, would copy the file or directory over to destination, and remove the old one, in case of an EXDEV from rename().

Finder, however, doesn't seem to respect this error code. Instead of doing a copy-then-remove, Finder just shows an error (incorrectly) saying the file can't be read or written. This normally is not an issue since Finder "sees" different volumes, and knows which locations are on different mounts, which allows it to use different approaches for move. However, on a network drive, this can become an issue and prevent the user from moving stuff using drag&drop. More specifically, if the the network drive's mount has a subdirectory that is a mount point by itself, moving files into or out of that subdirectory using rename() can cause file server to return an EXDEV error. Finder then thinks the file is not readable/writable.

FWIW, the FileManager.moveItem() method in Foundation framework (https://developer.apple.com/reference/foundation/filemanager/1413529-moveitem) works fine in the scenario described above.

We ran into this issue on a product we are working on here at Keybase. But we also managed to reproduce it using NFS, which is a supported feature in Finder. Having mount point(s) inside NFS might seem like an edge case, but considering that NFS is commonly used for storing large amount of data, it's not uncommon for file servers to have to have multiple disks mounted to support one NFS root export. This suggests the bug described here is very likely to happen for NFS users.

Steps to reproduce are listed below, using a Linux NFS server and Finder's "Connect to Server".

Steps to Reproduce:
0. Find out your own UID on macOS (with "id" command in CLI). I, being first user created on my mac, have 501. This is needed because by making the UID same on files served by NFS, it's easier to manage permissions. The script below needs the UID.
1. Spin up a fresh Ubuntu 16.04 Linux instance. The ubuntu/xenial64 box from Vagrant (https://www.vagrantup.com/) works. Make sure macOS is able to access the Linux instance. If you use Vagrant, uncomment the line `config.vm.network "public_network"` makes it on a bridged network.
2. On Linux, install nfs server: sudo apt-get update && sudo apt-get install -y nfs-kernel-server
3. Reboot Linux, so that kernel module is loaded.
4. In Linux, download and run this script (https://gist.github.com/songgao/cb3de68571367b13934a3cd0c48d37de) to configure the NFS server with root: wget https://gist.githubusercontent.com/songgao/cb3de68571367b13934a3cd0c48d37de/raw/027217b33cfd51fe95fb5420f161cdfc57d2ecce/nfs.sh -O nfs.sh && chmod a+x nfs.sh && sudo ./nfs.sh
5. If command in 4 finishes successfully, in macOS try mounting it in Finder using "Connect to Server", and use this address: nfs://<Linux instance IP address>/var/nfs/general/
6. In macOS, in Finder's NFS mount, you'd see a directory called submnt. Create a new folder outside it (i.e. in the mount root), and try dragging it into "submnt" directory. Finder would show the error attached now.

Expected Results:
Moving by drag&drop in Finder within same NFS mount works seamlessly.

Actual Results:
It errors; please see screenshot.

Version:
macOS version 10.12.3 (16D32)
Finder version 10.12.3

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!