diff --git a/framework/global/io/ifilesystem.h b/framework/global/io/ifilesystem.h index 7698613872..d5edce6f55 100644 --- a/framework/global/io/ifilesystem.h +++ b/framework/global/io/ifilesystem.h @@ -65,7 +65,7 @@ class IFileSystem : MODULE_GLOBAL_INTERFACE virtual RetVal readFile(const io::path_t& filePath) const = 0; virtual Ret readFile(const io::path_t& filePath, ByteArray& data) const = 0; - virtual Ret writeFile(const io::path_t& filePath, const ByteArray& data) = 0; + virtual Ret writeFile(const io::path_t& filePath, const ByteArray& data, bool syncToDisk = false) = 0; //! Streaming write virtual RetVal openStream(const io::path_t& filePath, OpenMode mode) = 0; diff --git a/framework/global/io/internal/filesystem.cpp b/framework/global/io/internal/filesystem.cpp index 9625b82bbc..da042b622e 100644 --- a/framework/global/io/internal/filesystem.cpp +++ b/framework/global/io/internal/filesystem.cpp @@ -21,6 +21,9 @@ */ #include "filesystem.h" +#include +#include + #include #include #include @@ -29,11 +32,21 @@ #ifdef Q_OS_WIN #include +#include +#else +#include #endif #include "../ioretcodes.h" #include "log.h" +#ifdef Q_OS_WIN +//Use _commit instead of FlushFileBuffers since it takes a file descriptor like fsync. + #define OS_SYNC_FILE(handle) _commit((handle)) +#else + #define OS_SYNC_FILE(handle) fsync((handle)) +#endif + using namespace muse; using namespace muse::io; @@ -198,7 +211,7 @@ Ret FileSystem::readFile(const io::path_t& filePath, ByteArray& data) const return ret; } -Ret FileSystem::writeFile(const io::path_t& filePath, const ByteArray& data) +Ret FileSystem::writeFile(const io::path_t& filePath, const ByteArray& data, bool syncToDisk) { Ret ret = muse::make_ok(); @@ -223,6 +236,21 @@ Ret FileSystem::writeFile(const io::path_t& filePath, const ByteArray& data) return ret; } + if (syncToDisk) { + // Flush user-space buffer (Qt/fflush), not a disk sync. + // Must be called before OS_SYNC_FILE. + file.flush(); + + // Ask the OS to push data to disk. + // If it fails, we log a warning and proceed — + // a failed sync does not necessarily mean the data wasn't written. + // At least we tried. + if (OS_SYNC_FILE(file.handle()) == -1) { + const int errorCode = errno; + LOGW() << "Failed to sync file to disk:" << std::strerror(errorCode); + } + } + file.close(); return ret; diff --git a/framework/global/io/internal/filesystem.h b/framework/global/io/internal/filesystem.h index 05a5778336..6879965023 100644 --- a/framework/global/io/internal/filesystem.h +++ b/framework/global/io/internal/filesystem.h @@ -55,7 +55,7 @@ class FileSystem : public IFileSystem RetVal readFile(const io::path_t& filePath) const override; Ret readFile(const io::path_t& filePath, ByteArray& data) const override; - Ret writeFile(const io::path_t& filePath, const ByteArray& data) override; + Ret writeFile(const io::path_t& filePath, const ByteArray& data, bool syncToDisk = false) override; RetVal openStream(const io::path_t& filePath, OpenMode mode) override; Ret writeToStream(StreamId fileId, const ByteArray& data, uint64_t offset = STREAM_POS_CURRENT) override;