There are two ways to resolve this inconsistency across platforms:
Option 1: Make renameTo always fail when the target file exists.
Option 2: Make renameTo always work when the target file exists.
Option 1 is compatible with the JDK's current behavior on Win32, while option 2
is compatible with the current behavior on Unix systems. The problem with both
options is that, as rws@east observed, neither can be implemented on all
platforms without leaving a window of vulnerability.
Option 1 has a window of vulnerability on Unix because two separate operations
must be performed. First you must test whether a file exists under the target
name. Then, if no such file exists, you go ahead and rename the source file to
the target name. Between these two operations a new file might be created
under the target name, and because the rename() system call is atomic and will
destroy the target this new file will be obliterated. This possibility, while
arguably rare, would violate the claim that renameTo will always fail when the
Option 2, of course, has a window of vulnerability on Win32 because if a file
exists under the target name it must be deleted, perhaps repeatedly, before the
actual rename operation can succeed. If your program or machine crashes before
the rename completes then you may be left with inconsistent state. The Win32
API does not, unfortunately, provide a true atomic rename facility, though it
may be possible to do this with NT-specific kernel calls.
Option 2 also suffers from the fact that it would be a significant behavioral
change for the vast majority of Java developers and end users.
After much anguish I've decided to close this bug as "will not fix." In this
case compatibility with the current behavior seems the best choice, as neither
of the above choices are obviously preferable and both would be a change from
the current behavior on some platforms. I'll clarify the specification of the
renameTo method to say that its operation is inherently system-dependent and
that, in particular, it may or may not be atomic and it may or may not succeed
if a file or directory already exists under the target name.
For those who think that atomic rename is incredibly useful -- and I'm one of
them -- I suggest we consider adding a method in JDK.next, for example
java.io.File.renameToAtomically, that throws an UnsupportedOperationException
or some such if it cannot perform the requested rename operation atomically.
For those who view closing this bug as "will not fix" as a violation of the
WORA principle, I respectfully disagree. WORA never promised identical
behaviors on both platforms, merely identical allowed behaviors, that is,
-- mr@eng 8/18/1998