filesys: safeWriteToFile(): Remove the target file before rename only on Windows
authorPerttu Ahola <celeron55@gmail.com>
Fri, 1 Jan 2016 16:14:30 +0000 (18:14 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Fri, 1 Jan 2016 16:21:18 +0000 (18:21 +0200)
Removing the target file on other platforms was enabled likely unintentionally
by commit 5f1f1151d3a9c113902630adc16cc3f4845da7ba.

This may be the reason why there has been corruption of files on Linux on hard
shutdowns.

Previously I described the problem and this fix in issue #3084.

src/filesys.cpp

index 5fdc976349acf547559a8aecc041cc8d7e5f2b1e..501f9ad6ca53f721f4d117b2a199bb6b2e251af9 100644 (file)
@@ -693,13 +693,22 @@ bool safeWriteToFile(const std::string &path, const std::string &content)
        os.flush();
        os.close();
        if (os.fail()) {
+               // Remove the temporary file because writing it failed and it's useless.
                remove(tmp_file.c_str());
                return false;
        }
 
-       // Copy file
+       // Move the finished temporary file over the real file
+#ifdef _WIN32
+       // On POSIX compliant systems rename() is specified to be able to swap the
+       // file in place of the destination file, making this a truly error-proof
+       // transaction.
+       // However, on Windows, the target file has to be removed first.
        remove(path.c_str());
+#endif
        if(rename(tmp_file.c_str(), path.c_str())) {
+               // Remove the temporary file because moving it over the target file
+               // failed.
                remove(tmp_file.c_str());
                return false;
        } else {