Merge "Fix bug in WriteStringToFileAtomic"
diff --git a/fs_mgr/libsnapshot/utility.cpp b/fs_mgr/libsnapshot/utility.cpp
index 0a1be0d..cadd24d 100644
--- a/fs_mgr/libsnapshot/utility.cpp
+++ b/fs_mgr/libsnapshot/utility.cpp
@@ -153,9 +153,23 @@
 }
 
 bool WriteStringToFileAtomic(const std::string& content, const std::string& path) {
-    std::string tmp_path = path + ".tmp";
-    if (!android::base::WriteStringToFile(content, tmp_path)) {
-        return false;
+    const std::string tmp_path = path + ".tmp";
+    {
+        const int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_BINARY;
+        android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(tmp_path.c_str(), flags, 0666)));
+        if (fd == -1) {
+            PLOG(ERROR) << "Failed to open " << path;
+            return false;
+        }
+        if (!android::base::WriteStringToFd(content, fd)) {
+            PLOG(ERROR) << "Failed to write to fd " << fd;
+            return false;
+        }
+        // rename() without fsync() is not safe. Data could still be living on page cache. To ensure
+        // atomiticity, call fsync()
+        if (fsync(fd) != 0) {
+            PLOG(ERROR) << "Failed to fsync " << tmp_path;
+        }
     }
     if (rename(tmp_path.c_str(), path.c_str()) == -1) {
         PLOG(ERROR) << "rename failed from " << tmp_path << " to " << path;