From feccf6b859e83bd8f28408ad72c7854ae12b70bb Mon Sep 17 00:00:00 2001 From: eversinc33 Date: Fri, 3 Jan 2025 21:02:06 +0100 Subject: [PATCH] check for windows NTFS compression on database files --- src/blockchain_db/lmdb/db_lmdb.cpp | 64 ++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index d01119249..f85042d61 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -28,11 +28,16 @@ #include "db_lmdb.h" #include +#include #include #include #include // std::unique_ptr #include // memcpy +#ifdef WIN32 +#include +#endif + #include "string_tools.h" #include "file_io_utils.h" #include "common/util.h" @@ -1321,6 +1326,54 @@ BlockchainLMDB::BlockchainLMDB(bool batch_transactions): BlockchainDB() m_hardfork = nullptr; } +#ifdef WIN32 +static bool disable_ntfs_compression(const boost::filesystem::path& filepath) +{ + DWORD file_attributes = ::GetFileAttributesW(filepath.c_str()); + if (file_attributes == INVALID_FILE_ATTRIBUTES) + { + MERROR("Failed to get " << filepath.string() << " file attributes. Error: " << ::GetLastError()); + return false; + } + + if (!(file_attributes & FILE_ATTRIBUTE_COMPRESSED)) + return true; // not compressed + + LOG_PRINT_L1("Disabling NTFS compression for " << filepath.string()); + HANDLE file_handle = ::CreateFileW( + filepath.c_str(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + nullptr, + OPEN_EXISTING, + boost::filesystem::is_directory(filepath) ? FILE_FLAG_BACKUP_SEMANTICS : 0, // Needed to open handles to directories + nullptr + ); + + if (file_handle == INVALID_HANDLE_VALUE) + { + MERROR("Failed to open handle: " << filepath.string() << ". Error: " << ::GetLastError()); + return false; + } + + USHORT compression_state = COMPRESSION_FORMAT_NONE; + DWORD bytes_returned; + BOOL ok = ::DeviceIoControl( + file_handle, + FSCTL_SET_COMPRESSION, + &compression_state, + sizeof(compression_state), + nullptr, + 0, + &bytes_returned, + nullptr + ); + + ::CloseHandle(file_handle); + return ok; +} +#endif + void BlockchainLMDB::open(const std::string& filename, const int db_flags) { int result; @@ -1347,6 +1400,17 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags) throw DB_ERROR("Database could not be opened"); } +#ifdef WIN32 + // ensure NTFS compression is disabled on the directory and database file to avoid corruption of the blockchain + if (!disable_ntfs_compression(filename)) + LOG_PRINT_L0("Failed to disable NTFS compression on folder: " << filename << ". Error: " << ::GetLastError()); + boost::filesystem::path datafile(filename); + datafile /= CRYPTONOTE_BLOCKCHAINDATA_FILENAME; + boost::filesystem::ofstream(datafile).close(); // touch the file to ensure it exists + if (!disable_ntfs_compression(datafile)) + throw DB_ERROR("Database file is NTFS compressend and compression could not be disabled"); +#endif + boost::optional is_hdd_result = tools::is_hdd(filename.c_str()); if (is_hdd_result) {