check for windows NTFS compression on database files

This commit is contained in:
eversinc33 2025-01-03 21:02:06 +01:00
parent 941ecefab2
commit feccf6b859

View file

@ -28,11 +28,16 @@
#include "db_lmdb.h"
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/format.hpp>
#include <boost/circular_buffer.hpp>
#include <memory> // std::unique_ptr
#include <cstring> // memcpy
#ifdef WIN32
#include <winioctl.h>
#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<bool> is_hdd_result = tools::is_hdd(filename.c_str());
if (is_hdd_result)
{