-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
os: Case-only renames not possible on case insensitive filesystems #35222
Comments
Your suggested solution sounds reasonable, with a test case. |
The same check also prevents renaming over an empty directory which the actual system call would allow. Given the wording of the os.Rename docs, this could be intentional. Not sure it's a good thing, as this issue clearly demonstrates. Piling on yet more racy checks to work around the unintended side effects seems contraproductive. What about removing the newpath existence check in os and just letting the OS handle it? |
See #19647 for some background. |
May I add that there's currently behaviour inconsistency: the same rename on a case-insensitive filesystem in Windows will work flawlessly and produce no error. |
Change https://golang.org/cl/204601 mentions this issue: |
What version of Go are you using (
go version
)?tip
Does this issue reproduce with the latest release?
yes
What operating system and processor architecture are you using (
go env
)?darwin/amd64 but affects whole of unix with case insensitive filesystems
What did you do?
Case-only directory renames on case-insensitive filesystems on unix are not possible, due to destination existence check as per:
go/src/os/file_unix.go
Lines 23 to 36 in 59a6847
Please note, it seems this only affects directories.
The two different stat calls for differently cased directories will return stat information about the same object in the filesystem, which as a result fails that check, yet the move syscall would not be destructive in this case.
Sadly you cannot compare the names returned by the Stat calls, as the name in the returned struct is set to match what the caller provided.
A possible solution to this would be to check that the names are not the same, and if they are not, verify that the rename would not be a destructive action using os.SameFile.
If that returns true, proceed with the syscall.
If you think this is an acceptable solution, I am happy to submit a CL.
What did you expect to see?
Successful rename (same way like mv command succeeds)
What did you see instead?
syscall.EEXIST error
The text was updated successfully, but these errors were encountered: