-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Reimplement Sys.rename under Win32 to be more POSIX #1306
Conversation
Specifically: "Sys.rename src dst" no longer fails if file "dst" exists, but replaces it with file "src", as in POSIX. Test added.
Now that we have this behavior under Win32, let's guarantee it.
You meant "when the destination name exists", right?
I think this is fine. Even under Unix, NFS mounts don't guarantee atomicity for rename. |
My guess and my hope is that it fails in this case, just like POSIX
Quite possibly. There is similar wording for
I don't know. Testing should tell.
I meant that |
I confirmed, it would be worth mentioning that in the doc-comment for the function, as there could be implications in term of security (among others). |
What about dealing with Unix.rename as well? |
|
All versions of Windows we support provide MoveFileEx.
This is what the old implementation (based on MoveFile() and on rename() from the CRT) did.
@fdopen : you're right, the previous implementation of Sys.rename under Win32 would do a copy if old and new names are on different file systems. I wasn't aware of this. I guess it's best to keep this behavior in the new implementation, for backward compatibility. Commit [41f5ed5] does this. @alainfrisch : @alainfrisch : commit [3cd2a99] documents Can I get my formal review now? |
@xavierleroy Do you know why Unix.rename does not release the runtime lock (Sys.rename does it)? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Extra possible tweaks: (i) release the runtime lock in Win32's version of Unix.rename; (ii) bring the documentation of Unix.rename up-to-date with Sys.rename (or refer to it).
The Unix implementation of Unix.rename does release the runtime lock, but not the Win32 implementation. Originally neither implementations would release the runtime lock because |
Bring it in line with that of Sys.rename.
Documentation of |
The Win32 version can copy files so it can also take a long time. Ok, perhaps something for later (or people can use Sys.rename...). |
Just for the records: it seems that even this new implementations doesn't allow renaming A to B if B exists and is currently opened by any process (even with FILE_SHARE_DELETE). If anyone knows a way to make this works, I'm interested! |
Currently, in the MSVC and Mingw ports of OCaml,
Sys.rename src dst
fails if a file nameddst
already exists. This is unlike the other ports, wheredst
is replaced bysrc
in this case. This PR reimplementsSys.rename
on top of theMoveFileEx
Win32 system call so that the destination file, if it exists already, is replaced by the source file.The "replace existing file" behavior is more useful especially in cases where one wants to prepare data in a temporary file with a unique name, then give it its final name, which can match an existing file. See MPR 4991 and MPR 7472 for possible uses within the OCaml compiler itself.
The "replace existing file" behavior is even more useful if it is guaranteed to be atomic. POSIX gives such guarantees for the
rename
function, but MSDN gives no atomicity guarantees forMoveFileEx
nor forReplaceFile
. It is believed thatMoveFileEx
is atomic on a journaling file system such as NTFS and if no copy of contents is requested. Same beliefs forReplaceFile
, except that the latter is not really usable because it expects the destination name to exist already, and fails otherwise. In the end we cannot guarantee atomicity ofSys.rename
but we've made a best effort.