United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-4017593 : java.io.File.renameTo has different semantics on Solaris and Win32

Submit Date:
Updated Date:
Project Name:
Resolved Date:
Won't Fix
Affected Versions:
Fixed Versions:

Related Reports

Sub Tasks

File.renameTo() has different semantics on Solaris and Win32.
This routine is a thin veneer over the rename() call in the C library.
On Win32, rename() is defined such that it is an error if the destination
file exists.  On Solaris, the destination file can exist and rename()
has the affect of unlinking it.

We wrote code to update a file, where we write to a temporary file first and
then rename that file over the original.  This is a pretty standard technique
to avoid losing the original data in the file.  We use renameTo() as the final
step and this code fails on a Win32 platform.



Do a File.delete() before doing the renameTo().

The semantics of renameTo should be platform independent.  Decide
which semantics you want and implement those on all platforms.
It doesn't really matter which way you decide.  What matters is that
behaviour is consistent across platforms.

The renameTo() method of java.io.File behaves differently under Solaris and
Win32 when a file with the target name already exists.  Under Solaris the file
is removed and the rename operation completes as expected; under Win32 the
rename operation silently fails.  To work around this bug, delete any file that
will be the target of a rename before doing the rename.

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
target exists.

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,
identical specifications.

-- mr@eng 8/18/1998

Hardware and Software, Engineered to Work Together