JDK-4017593 : java.io.File.renameTo has different semantics on Solaris and Win32
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.io
  • Affected Version: 1.0.2,1.1,1.2.0
  • Priority: P3
  • Status: Closed
  • Resolution: Won't Fix
  • OS: generic,solaris_2.5
  • CPU: generic,sparc
  • Submitted: 1996-12-04
  • Updated: 1998-08-18
  • Resolved: 1998-08-18
Related Reports
Relates :  
Relates :  
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.

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

SUGGESTED FIX 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.

PUBLIC COMMENTS 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.

EVALUATION 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