Fix detection of backup file restored back problem

Fix #10839, close #10843
This commit is contained in:
Don Ho 2021-11-26 23:26:08 +01:00
parent e7bf582ffd
commit bab3573be7
3 changed files with 27 additions and 50 deletions

View File

@ -22,10 +22,7 @@ Win32_IO_File::Win32_IO_File(const char *fname, Mode fmode) : _hMode(fmode)
{
if (fname)
{
DWORD access, share, disp, attrib;
fillCreateParams(access, share, disp, attrib);
_hFile = ::CreateFileA(fname, access, share, NULL, disp, attrib, NULL);
_hFile = ::CreateFileA(fname, _accessParam, _shareParam, NULL, _dispParam, _attribParam, NULL);
}
if ((_hFile != INVALID_HANDLE_VALUE) && (_hMode == Mode::APPEND))
@ -42,10 +39,7 @@ Win32_IO_File::Win32_IO_File(const wchar_t *fname, Mode fmode) : _hMode(fmode)
{
if (fname)
{
DWORD access, share, disp, attrib;
fillCreateParams(access, share, disp, attrib);
_hFile = ::CreateFileW(fname, access, share, NULL, disp, attrib, NULL);
_hFile = ::CreateFileW(fname, _accessParam, _shareParam, NULL, _dispParam, _attribParam, NULL);
}
if ((_hFile != INVALID_HANDLE_VALUE) && (_hMode == Mode::APPEND))
@ -74,7 +68,7 @@ void Win32_IO_File::close()
}
}
/*
int_fast64_t Win32_IO_File::getSize()
{
LARGE_INTEGER r;
@ -85,7 +79,7 @@ int_fast64_t Win32_IO_File::getSize()
return static_cast<int_fast64_t>(r.QuadPart);
}
*/
unsigned long Win32_IO_File::read(void *rbuf, unsigned long buf_size)
{
@ -102,7 +96,7 @@ unsigned long Win32_IO_File::read(void *rbuf, unsigned long buf_size)
bool Win32_IO_File::write(const void *wbuf, unsigned long buf_size)
{
if (!isOpened() || (wbuf == nullptr) || ((_hMode != Mode::WRITE) && (_hMode != Mode::APPEND)))
if (!isOpened() || (wbuf == nullptr))
return false;
DWORD bytes_written = 0;
@ -116,25 +110,3 @@ bool Win32_IO_File::write(const void *wbuf, unsigned long buf_size)
return (bytes_written == buf_size);
}
// Helper function to auto-fill CreateFile params optimized for Notepad++ usage.
void Win32_IO_File::fillCreateParams(DWORD &access, DWORD &share, DWORD &disp, DWORD &attrib)
{
access = GENERIC_READ;
share = FILE_SHARE_READ;
attrib = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_POSIX_SEMANTICS; // Distinguish between upper/lower case in name
if (_hMode == Mode::READ)
{
disp = OPEN_EXISTING; // Open only if file exists and is not locked by other process
attrib |= FILE_FLAG_SEQUENTIAL_SCAN; // Optimize caching for sequential read
}
else
{
disp = OPEN_ALWAYS; // Open existing file for writing without destroying it or create new
share |= FILE_SHARE_WRITE;
access |= GENERIC_WRITE;
attrib |= FILE_FLAG_WRITE_THROUGH; // Write cached data directly to disk (no lazy writer)
}
}

View File

@ -27,13 +27,12 @@ class Win32_IO_File final
{
public:
enum class Mode {
READ,
WRITE,
APPEND
};
Win32_IO_File(const char *fname, Mode fmode = Mode::READ);
Win32_IO_File(const wchar_t *fname, Mode fmode = Mode::READ);
Win32_IO_File(const char *fname, Mode fmode);
Win32_IO_File(const wchar_t *fname, Mode fmode);
Win32_IO_File() = delete;
Win32_IO_File(const Win32_IO_File&) = delete;
@ -48,7 +47,7 @@ public:
};
void close();
int_fast64_t getSize();
//int_fast64_t getSize();
unsigned long read(void *rbuf, unsigned long buf_size);
bool write(const void *wbuf, unsigned long buf_size);
@ -58,8 +57,11 @@ public:
private:
HANDLE _hFile {INVALID_HANDLE_VALUE};
Mode _hMode {Mode::READ};
Mode _hMode {Mode::WRITE};
bool _written {false};
void fillCreateParams(DWORD& access, DWORD& share, DWORD& disp, DWORD& attrib);
const DWORD _accessParam { GENERIC_READ | GENERIC_WRITE };
const DWORD _shareParam { FILE_SHARE_READ | FILE_SHARE_WRITE };
const DWORD _dispParam { OPEN_ALWAYS }; // Open existing file for writing without destroying it or create new
const DWORD _attribParam { FILE_ATTRIBUTE_NORMAL | FILE_FLAG_POSIX_SEMANTICS | FILE_FLAG_WRITE_THROUGH }; // FILE_FLAG_POSIX_SEMANTICS: distinguish between upper/lower case in name
};

View File

@ -140,16 +140,17 @@ void Buffer::updateTimeStamp()
}
LONG res = CompareFileTime(&_timeStamp, &timeStampLive);
if (res == -1) // timeStampLive is later, it means the file has been modified outside of Notepad++
if (res == -1 || res == 1)
// (res == -1) => timeStampLive is later, it means the file has been modified outside of Notepad++ - usual case
//
// (res == 1) => timeStampLive (get directly from the file on disk) is earlier than buffer's timestamp - unusual case
// It can happen when user copies a backup of editing file somewhere-else firstly, then modifies the editing file in Notepad++ and saves it.
// Now user copies the backup back to erase the modified editing file outside Notepad++ (via Explorer).
{
_timeStamp = timeStampLive;
doNotify(BufferChangeTimestamp);
}
else if (res == 1) // timeStampLive (get directly from the file on disk) is earlier than buffer's timestamp - abnormal case
{
// This absurd case can be ignored
}
// else res == 0 => nothing to change
// else (res == 0) => nothing to change
}
@ -271,17 +272,19 @@ bool Buffer::checkFileState() // returns true if the status has been changed (it
}
LONG res = CompareFileTime(&_timeStamp, &attributes.ftLastWriteTime);
if (res == -1) // // attributes.ftLastWriteTime is later, it means the file has been modified outside of Notepad++
if (res == -1 || res == 1)
// (res == -1) => attributes.ftLastWriteTime is later, it means the file has been modified outside of Notepad++ - usual case
//
// (res == 1) => The timestamp get directly from the file on disk is earlier than buffer's timestamp - unusual case
// It can happen when user copies a backup of editing file somewhere-else firstly, then modifies the editing file in Notepad++ and saves it.
// Now user copies the backup back to erase the modified editing file outside Notepad++ (via Explorer).
{
_timeStamp = attributes.ftLastWriteTime;
mask |= BufferChangeTimestamp;
_currentStatus = DOC_MODIFIED;
mask |= BufferChangeStatus; //status always 'changes', even if from modified to modified
}
else if (res == 1) // The timestamp get directly from the file on disk is earlier than buffer's timestamp - abnormal case
{
// This absurd case can be ignored
}
// else res == 0 => nothing to change
if (mask != 0)