Index: src/libchcore/TLocalFilesystemFile.cpp =================================================================== diff -u -N -r9ebcc7abf1e0e70f0db2d08b2691351a26ef259b -r27c262eb9cae55720e10f4886af6b5a82cb94fe9 --- src/libchcore/TLocalFilesystemFile.cpp (.../TLocalFilesystemFile.cpp) (revision 9ebcc7abf1e0e70f0db2d08b2691351a26ef259b) +++ src/libchcore/TLocalFilesystemFile.cpp (.../TLocalFilesystemFile.cpp) (revision 27c262eb9cae55720e10f4886af6b5a82cb94fe9) @@ -26,196 +26,191 @@ #include "RoundingFunctions.h" #include "TLocalFilesystem.h" -BEGIN_CHCORE_NAMESPACE - -// compile-time check - ensure the buffer granularity used for transfers are bigger than expected sector size -static_assert(TLocalFilesystemFile::MaxSectorSize <= TBufferSizes::BufferGranularity, "Buffer granularity must be equal to or bigger than the max sector size"); - -TLocalFilesystemFile::TLocalFilesystemFile() : - m_hFile(INVALID_HANDLE_VALUE), - m_pathFile(), - m_bNoBuffering(false) +namespace chcore { -} + // compile-time check - ensure the buffer granularity used for transfers are bigger than expected sector size + static_assert(TLocalFilesystemFile::MaxSectorSize <= TBufferSizes::BufferGranularity, "Buffer granularity must be equal to or bigger than the max sector size"); -TLocalFilesystemFile::~TLocalFilesystemFile() -{ - Close(); -} + TLocalFilesystemFile::TLocalFilesystemFile(const TSmartPath& pathFile) : + m_pathFile(TLocalFilesystem::PrependPathExtensionIfNeeded(pathFile)), + m_hFile(INVALID_HANDLE_VALUE), + m_bNoBuffering(false) + { + if (pathFile.IsEmpty()) + THROW_CORE_EXCEPTION(eErr_InvalidArgument); + } -DWORD TLocalFilesystemFile::GetFlagsAndAttributes(bool bNoBuffering) const -{ - return FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_SEQUENTIAL_SCAN | (bNoBuffering ? FILE_FLAG_NO_BUFFERING /*| FILE_FLAG_WRITE_THROUGH*/ : 0); -} + TLocalFilesystemFile::~TLocalFilesystemFile() + { + Close(); + } -bool TLocalFilesystemFile::OpenExistingForReading(const TSmartPath& pathFile, bool bNoBuffering) -{ - Close(); + DWORD TLocalFilesystemFile::GetFlagsAndAttributes(bool bNoBuffering) const + { + return FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_SEQUENTIAL_SCAN | (bNoBuffering ? FILE_FLAG_NO_BUFFERING /*| FILE_FLAG_WRITE_THROUGH*/ : 0); + } - m_pathFile = TLocalFilesystem::PrependPathExtensionIfNeeded(pathFile); - m_hFile = ::CreateFile(m_pathFile.ToString(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, GetFlagsAndAttributes(bNoBuffering), NULL); - if (m_hFile == INVALID_HANDLE_VALUE) - return false; + bool TLocalFilesystemFile::OpenExistingForReading(bool bNoBuffering) + { + Close(); - m_bNoBuffering = bNoBuffering; - return true; -} + m_hFile = ::CreateFile(m_pathFile.ToString(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, GetFlagsAndAttributes(bNoBuffering), NULL); + if (m_hFile == INVALID_HANDLE_VALUE) + return false; -bool TLocalFilesystemFile::CreateNewForWriting(const TSmartPath& pathFile, bool bNoBuffering) -{ - Close(); + m_bNoBuffering = bNoBuffering; + return true; + } - m_pathFile = TLocalFilesystem::PrependPathExtensionIfNeeded(pathFile); - m_hFile = ::CreateFile(m_pathFile.ToString(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, GetFlagsAndAttributes(bNoBuffering), NULL); - if (m_hFile == INVALID_HANDLE_VALUE) - return false; + bool TLocalFilesystemFile::CreateNewForWriting(bool bNoBuffering) + { + Close(); - m_bNoBuffering = bNoBuffering; - return true; -} + m_hFile = ::CreateFile(m_pathFile.ToString(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, GetFlagsAndAttributes(bNoBuffering), NULL); + if (m_hFile == INVALID_HANDLE_VALUE) + return false; -bool TLocalFilesystemFile::OpenExistingForWriting(const TSmartPath& pathFile, bool bNoBuffering) -{ - Close(); + m_bNoBuffering = bNoBuffering; + return true; + } - m_pathFile = TLocalFilesystem::PrependPathExtensionIfNeeded(pathFile); - m_hFile = CreateFile(m_pathFile.ToString(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, GetFlagsAndAttributes(bNoBuffering), NULL); - if (m_hFile == INVALID_HANDLE_VALUE) - return false; + bool TLocalFilesystemFile::OpenExistingForWriting(bool bNoBuffering) + { + Close(); - m_bNoBuffering = bNoBuffering; - return true; -} + m_hFile = CreateFile(m_pathFile.ToString(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, GetFlagsAndAttributes(bNoBuffering), NULL); + if (m_hFile == INVALID_HANDLE_VALUE) + return false; -bool TLocalFilesystemFile::SetFilePointer(long long llNewPos, DWORD dwMoveMethod) -{ - if (!IsOpen()) - return false; + m_bNoBuffering = bNoBuffering; + return true; + } - LARGE_INTEGER li = { 0, 0 }; - LARGE_INTEGER liNew = { 0, 0 }; + bool TLocalFilesystemFile::Truncate(long long llNewSize) + { + if (!IsOpen()) + return false; - li.QuadPart = llNewPos; + LARGE_INTEGER li = { 0, 0 }; + LARGE_INTEGER liNew = { 0, 0 }; - return SetFilePointerEx(m_hFile, li, &liNew, dwMoveMethod) != FALSE; -} + li.QuadPart = llNewSize; -bool TLocalFilesystemFile::SetEndOfFile() -{ - if (!IsOpen()) - return false; + if (!SetFilePointerEx(m_hFile, li, &liNew, FILE_BEGIN)) + return false; - return ::SetEndOfFile(m_hFile) != FALSE; -} + return ::SetEndOfFile(m_hFile) != FALSE; + } -bool TLocalFilesystemFile::ReadFile(TOverlappedDataBuffer& rBuffer) -{ - if (!IsOpen()) - THROW_CORE_EXCEPTION(eErr_InternalProblem); - - ATLTRACE(_T("Reading %lu bytes\n"), rBuffer.GetRequestedDataSize()); - if (!::ReadFileEx(m_hFile, rBuffer.GetBufferPtr(), rBuffer.GetRequestedDataSize(), &rBuffer, OverlappedReadCompleted)) + bool TLocalFilesystemFile::ReadFile(TOverlappedDataBuffer& rBuffer) { - DWORD dwLastError = GetLastError(); - switch (dwLastError) - { - case ERROR_IO_PENDING: - return true; + if (!IsOpen()) + THROW_CORE_EXCEPTION(eErr_InternalProblem); - case ERROR_HANDLE_EOF: + ATLTRACE(_T("Reading %lu bytes\n"), rBuffer.GetRequestedDataSize()); + if (!::ReadFileEx(m_hFile, rBuffer.GetBufferPtr(), rBuffer.GetRequestedDataSize(), &rBuffer, OverlappedReadCompleted)) { - rBuffer.SetBytesTransferred(0); - rBuffer.SetStatusCode(0); - rBuffer.SetErrorCode(ERROR_SUCCESS); - rBuffer.SetLastPart(true); + DWORD dwLastError = GetLastError(); + switch (dwLastError) + { + case ERROR_IO_PENDING: + return true; - rBuffer.RequeueAsFull(); // basically the same as OverlappedReadCompleted + case ERROR_HANDLE_EOF: + { + rBuffer.SetBytesTransferred(0); + rBuffer.SetStatusCode(0); + rBuffer.SetErrorCode(ERROR_SUCCESS); + rBuffer.SetLastPart(true); - return true; - } - } + rBuffer.RequeueAsFull(); // basically the same as OverlappedReadCompleted - return false; + return true; + } + } + + return false; + } + return true; } - return true; -} -bool TLocalFilesystemFile::WriteFile(TOverlappedDataBuffer& rBuffer) -{ - if (!IsOpen()) - THROW_CORE_EXCEPTION(eErr_InternalProblem); + bool TLocalFilesystemFile::WriteFile(TOverlappedDataBuffer& rBuffer) + { + if (!IsOpen()) + THROW_CORE_EXCEPTION(eErr_InternalProblem); - DWORD dwToWrite = boost::numeric_cast(rBuffer.GetRealDataSize()); + DWORD dwToWrite = boost::numeric_cast(rBuffer.GetRealDataSize()); - if (m_bNoBuffering && rBuffer.IsLastPart()) - dwToWrite = RoundUp(dwToWrite, MaxSectorSize); + if (m_bNoBuffering && rBuffer.IsLastPart()) + dwToWrite = RoundUp(dwToWrite, MaxSectorSize); - ATLTRACE(_T("Writing %lu bytes\n"), dwToWrite); - if (!::WriteFileEx(m_hFile, rBuffer.GetBufferPtr(), dwToWrite, &rBuffer, OverlappedWriteCompleted)) - { - if (GetLastError() == ERROR_IO_PENDING) - return true; - return false; + ATLTRACE(_T("Writing %lu bytes\n"), dwToWrite); + if (!::WriteFileEx(m_hFile, rBuffer.GetBufferPtr(), dwToWrite, &rBuffer, OverlappedWriteCompleted)) + { + if (GetLastError() == ERROR_IO_PENDING) + return true; + return false; + } + + return true; } - return true; -} - -bool TLocalFilesystemFile::FinalizeFile(TOverlappedDataBuffer& rBuffer) -{ - if (!IsOpen()) - THROW_CORE_EXCEPTION(eErr_InternalProblem); - - if (m_bNoBuffering && rBuffer.IsLastPart()) + bool TLocalFilesystemFile::FinalizeFile(TOverlappedDataBuffer& rBuffer) { - DWORD dwToWrite = boost::numeric_cast(rBuffer.GetRealDataSize()); - DWORD dwReallyWritten = RoundUp(dwToWrite, MaxSectorSize); + if (!IsOpen()) + THROW_CORE_EXCEPTION(eErr_InternalProblem); - ATLTRACE(_T("Finalize file - size diff: written: %I64u, required: %I64u\n"), dwReallyWritten, dwToWrite); - - if (dwToWrite != dwReallyWritten) + if (m_bNoBuffering && rBuffer.IsLastPart()) { - unsigned long long ullNewFileSize = rBuffer.GetFilePosition() + dwToWrite; // new size + DWORD dwToWrite = boost::numeric_cast(rBuffer.GetRealDataSize()); + DWORD dwReallyWritten = RoundUp(dwToWrite, MaxSectorSize); - if (!OpenExistingForWriting(m_pathFile, false)) - return false; + ATLTRACE(_T("Finalize file - size diff: written: %I64u, required: %I64u\n"), dwReallyWritten, dwToWrite); - //seek - ATLTRACE(_T("Truncating file to %I64u bytes\n"), ullNewFileSize); - if (!SetFilePointer(ullNewFileSize, FILE_BEGIN)) - return false; + if (dwToWrite != dwReallyWritten) + { + unsigned long long ullNewFileSize = rBuffer.GetFilePosition() + dwToWrite; // new size - //set eof - if (!SetEndOfFile()) - return false; + if (!OpenExistingForWriting(false)) + return false; + + //seek + ATLTRACE(_T("Truncating file to %I64u bytes\n"), ullNewFileSize); + if (!Truncate(ullNewFileSize)) + return false; + } } + + return true; } - return true; -} + void TLocalFilesystemFile::Close() + { + if (m_hFile != INVALID_HANDLE_VALUE) + ::CloseHandle(m_hFile); + m_hFile = INVALID_HANDLE_VALUE; + } -void TLocalFilesystemFile::Close() -{ - if (m_hFile != INVALID_HANDLE_VALUE) - ::CloseHandle(m_hFile); - m_hFile = INVALID_HANDLE_VALUE; -} + unsigned long long TLocalFilesystemFile::GetFileSize() const + { + if (!IsOpen()) + return 0; -unsigned long long TLocalFilesystemFile::GetFileSize() const -{ - if (!IsOpen()) - return 0; + BY_HANDLE_FILE_INFORMATION bhfi; - BY_HANDLE_FILE_INFORMATION bhfi; + if (!::GetFileInformationByHandle(m_hFile, &bhfi)) + return 0; - if (!::GetFileInformationByHandle(m_hFile, &bhfi)) - return 0; + ULARGE_INTEGER uli; + uli.HighPart = bhfi.nFileSizeHigh; + uli.LowPart = bhfi.nFileSizeLow; - ULARGE_INTEGER uli; - uli.HighPart = bhfi.nFileSizeHigh; - uli.LowPart = bhfi.nFileSizeLow; + return uli.QuadPart; + } - return uli.QuadPart; -} + TSmartPath TLocalFilesystemFile::GetFilePath() const + { + return m_pathFile; + } -END_CHCORE_NAMESPACE +}