mirror of
https://github.com/veracrypt/VeraCrypt
synced 2024-11-24 12:03:28 +01:00
Windows: Avoid unnecessary write operations when copying/modifying EFI bootloader files in order to avoid leaking modification timestamp
This commit is contained in:
parent
31a87c2e5f
commit
9b394ddc49
@ -2829,14 +2829,120 @@ namespace VeraCrypt
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EfiBoot::CompareFiles (const wchar_t* fileName1, const wchar_t* fileName2)
|
||||||
|
{
|
||||||
|
bool bRet = false;
|
||||||
|
File f1 (fileName1, true);
|
||||||
|
File f2 (fileName2, true);
|
||||||
|
|
||||||
|
if (f1.IsOpened() && f2.IsOpened())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DWORD size1, size2;
|
||||||
|
f1.GetFileSize (size1);
|
||||||
|
f2.GetFileSize (size2);
|
||||||
|
|
||||||
|
if (size1 == size2)
|
||||||
|
{
|
||||||
|
// same size, so now we compare content
|
||||||
|
std::vector<byte> file1Buf (8096);
|
||||||
|
std::vector<byte> file2Buf (8096);
|
||||||
|
DWORD remainingBytes = size1, dataToRead;
|
||||||
|
|
||||||
|
while (remainingBytes)
|
||||||
|
{
|
||||||
|
dataToRead = VC_MIN (remainingBytes, (DWORD) file1Buf.size());
|
||||||
|
DWORD f1Bytes = f1.Read (file1Buf.data(), dataToRead);
|
||||||
|
DWORD f2Bytes = f2.Read (file2Buf.data(), dataToRead);
|
||||||
|
|
||||||
|
if ((f1Bytes != f2Bytes) || memcmp (file1Buf.data(), file2Buf.data(), (size_t) f1Bytes))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
remainingBytes -= f1Bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == remainingBytes)
|
||||||
|
{
|
||||||
|
// content is the same
|
||||||
|
bRet = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
f1.Close();
|
||||||
|
f2.Close();
|
||||||
|
|
||||||
|
return bRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EfiBoot::CompareFileData (const wchar_t* fileName, const byte* data, DWORD size)
|
||||||
|
{
|
||||||
|
bool bRet = false;
|
||||||
|
|
||||||
|
File f(fileName, true);
|
||||||
|
if (f.IsOpened ())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// check if the file has the same content
|
||||||
|
// if yes, don't perform any write operation to avoid changing its timestamp
|
||||||
|
DWORD existingSize = 0;
|
||||||
|
|
||||||
|
f.GetFileSize(existingSize);
|
||||||
|
|
||||||
|
if (existingSize == size)
|
||||||
|
{
|
||||||
|
std::vector<byte> fileBuf (8096);
|
||||||
|
DWORD remainingBytes = size, dataOffset = 0, dataToRead;
|
||||||
|
|
||||||
|
while (remainingBytes)
|
||||||
|
{
|
||||||
|
dataToRead = VC_MIN (remainingBytes, (DWORD) fileBuf.size());
|
||||||
|
dataToRead = f.Read (fileBuf.data(), dataToRead);
|
||||||
|
|
||||||
|
if (memcmp (data + dataOffset, fileBuf.data(), (size_t) dataToRead))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dataOffset += dataToRead;
|
||||||
|
remainingBytes -= dataToRead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == remainingBytes)
|
||||||
|
{
|
||||||
|
// content is the same
|
||||||
|
bRet = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...){}
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Close();
|
||||||
|
|
||||||
|
return bRet;
|
||||||
|
}
|
||||||
|
|
||||||
void EfiBoot::SaveFile(const wchar_t* name, byte* data, DWORD size) {
|
void EfiBoot::SaveFile(const wchar_t* name, byte* data, DWORD size) {
|
||||||
wstring path = EfiBootPartPath;
|
wstring path = EfiBootPartPath;
|
||||||
path += name;
|
path += name;
|
||||||
|
|
||||||
|
if (!CompareFileData (path.c_str(), data, size))
|
||||||
|
{
|
||||||
File f(path, false, true);
|
File f(path, false, true);
|
||||||
f.Write(data, size);
|
f.Write(data, size);
|
||||||
f.Close();
|
f.Close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EfiBoot::FileExists(const wchar_t* name) {
|
bool EfiBoot::FileExists(const wchar_t* name) {
|
||||||
@ -2875,6 +2981,9 @@ namespace VeraCrypt
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
targetPath = targetName;
|
targetPath = targetName;
|
||||||
|
|
||||||
|
// if both files are the same, we don't perform copy operation
|
||||||
|
if (!CompareFiles (path.c_str(), targetPath.c_str()))
|
||||||
throw_sys_if (!::CopyFileW (path.c_str(), targetPath.c_str(), FALSE));
|
throw_sys_if (!::CopyFileW (path.c_str(), targetPath.c_str(), FALSE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2883,7 +2992,16 @@ namespace VeraCrypt
|
|||||||
path += name;
|
path += name;
|
||||||
wstring pathNew = EfiBootPartPath;
|
wstring pathNew = EfiBootPartPath;
|
||||||
pathNew += nameNew;
|
pathNew += nameNew;
|
||||||
return MoveFileExW(path.c_str(), pathNew.c_str(), bForce? MOVEFILE_REPLACE_EXISTING : 0);
|
|
||||||
|
BOOL bRet;
|
||||||
|
if (CompareFiles (path.c_str(), pathNew.c_str()))
|
||||||
|
{
|
||||||
|
// files identical. Delete source file only
|
||||||
|
bRet = DeleteFile (path.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
bRet = MoveFileExW(path.c_str(), pathNew.c_str(), bForce? MOVEFILE_REPLACE_EXISTING : 0);
|
||||||
|
return bRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL EfiBoot::DelFile(const wchar_t* name) {
|
BOOL EfiBoot::DelFile(const wchar_t* name) {
|
||||||
|
@ -211,6 +211,8 @@ namespace VeraCrypt
|
|||||||
void ReadFile(const wchar_t* name, byte* data, DWORD size);
|
void ReadFile(const wchar_t* name, byte* data, DWORD size);
|
||||||
void CopyFile(const wchar_t* name, const wchar_t* targetName);
|
void CopyFile(const wchar_t* name, const wchar_t* targetName);
|
||||||
bool FileExists(const wchar_t* name);
|
bool FileExists(const wchar_t* name);
|
||||||
|
static bool CompareFiles (const wchar_t* fileName1, const wchar_t* fileName2);
|
||||||
|
static bool CompareFileData (const wchar_t* fileName, const byte* data, DWORD size);
|
||||||
|
|
||||||
BOOL RenameFile(const wchar_t* name, const wchar_t* nameNew, BOOL bForce);
|
BOOL RenameFile(const wchar_t* name, const wchar_t* nameNew, BOOL bForce);
|
||||||
BOOL DelFile(const wchar_t* name);
|
BOOL DelFile(const wchar_t* name);
|
||||||
|
Loading…
Reference in New Issue
Block a user