Index: src/libchcore/TLocalFilesystem.cpp =================================================================== diff -u -rcdc76e1a95383dff63a5254aeb8d37035028512c -r9ebcc7abf1e0e70f0db2d08b2691351a26ef259b --- src/libchcore/TLocalFilesystem.cpp (.../TLocalFilesystem.cpp) (revision cdc76e1a95383dff63a5254aeb8d37035028512c) +++ src/libchcore/TLocalFilesystem.cpp (.../TLocalFilesystem.cpp) (revision 9ebcc7abf1e0e70f0db2d08b2691351a26ef259b) @@ -41,12 +41,20 @@ #include "RoundingFunctions.h" #include #include "TBufferSizes.h" +#include "TLocalFilesystemFile.h" +#include +#include "TLocalFilesystemFind.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"); +TLocalFilesystem::TLocalFilesystem() +{ +} +TLocalFilesystem::~TLocalFilesystem() +{ +} + UINT TLocalFilesystem::GetDriveData(const TSmartPath& spPath) { UINT uiDrvType = DRIVE_UNKNOWN; @@ -68,7 +76,7 @@ return uiDrvType; } -bool TLocalFilesystem::PathExist(TSmartPath pathToCheck) +bool TLocalFilesystem::PathExist(const TSmartPath& pathToCheck) { WIN32_FIND_DATA fd; @@ -82,9 +90,10 @@ // another try (add '\\' if needed and '*' for marking that we look for ie. c:\* // instead of c:\, which would never be found prev. way) - pathToCheck.AppendIfNotExists(_T("*"), false); + TSmartPath findPath = pathToCheck; + findPath.AppendIfNotExists(_T("*"), false); - hFind = FindFirstFile(PrependPathExtensionIfNeeded(pathToCheck).ToString(), &fd); + hFind = FindFirstFile(PrependPathExtensionIfNeeded(findPath).ToString(), &fd); if(hFind != INVALID_HANDLE_VALUE) { ::FindClose(hFind); @@ -189,14 +198,14 @@ return ::MoveFile(PrependPathExtensionIfNeeded(pathSource).ToString(), PrependPathExtensionIfNeeded(pathDestination).ToString()) != FALSE; } -TLocalFilesystemFind TLocalFilesystem::CreateFinderObject(const TSmartPath& pathDir, const TSmartPath& pathMask) +IFilesystemFindPtr TLocalFilesystem::CreateFinderObject(const TSmartPath& pathDir, const TSmartPath& pathMask) { - return TLocalFilesystemFind(pathDir, pathMask); + return std::shared_ptr(new TLocalFilesystemFind(pathDir, pathMask)); } -TLocalFilesystemFile TLocalFilesystem::CreateFileObject() +IFilesystemFilePtr TLocalFilesystem::CreateFileObject() { - return TLocalFilesystemFile(); + return std::shared_ptr(new TLocalFilesystemFile()); } TSmartPath TLocalFilesystem::PrependPathExtensionIfNeeded(const TSmartPath& pathInput) @@ -320,251 +329,4 @@ ///////////////////////////////////////////////////////////////////////////////////// // class TLocalFilesystemFind -TLocalFilesystemFind::TLocalFilesystemFind(const TSmartPath& pathDir, const TSmartPath& pathMask) : - m_pathDir(pathDir), - m_pathMask(pathMask), - m_hFind(INVALID_HANDLE_VALUE) -{ -} - -TLocalFilesystemFind::~TLocalFilesystemFind() -{ - Close(); -} - -bool TLocalFilesystemFind::FindNext(TFileInfoPtr& rspFileInfo) -{ - WIN32_FIND_DATA wfd; - TSmartPath pathCurrent = m_pathDir + m_pathMask; - - // Iterate through dirs & files - bool bContinue = true; - if(m_hFind != INVALID_HANDLE_VALUE) - bContinue = (FindNextFile(m_hFind, &wfd) != FALSE); - else - { - m_hFind = FindFirstFile(TLocalFilesystem::PrependPathExtensionIfNeeded(pathCurrent).ToString(), &wfd); // in this case we always continue - bContinue = (m_hFind != INVALID_HANDLE_VALUE); - } - if(bContinue) - { - do - { - if(!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) - { - rspFileInfo->Init(m_pathDir + PathFromString(wfd.cFileName), wfd.dwFileAttributes, (((ULONGLONG) wfd.nFileSizeHigh) << 32) + wfd.nFileSizeLow, wfd.ftCreationTime, - wfd.ftLastAccessTime, wfd.ftLastWriteTime, 0); - return true; - } - else if(wfd.cFileName[0] != _T('.') || (wfd.cFileName[1] != _T('\0') && (wfd.cFileName[1] != _T('.') || wfd.cFileName[2] != _T('\0')))) - { - // Add directory itself - rspFileInfo->Init(m_pathDir + PathFromString(wfd.cFileName), - wfd.dwFileAttributes, (((ULONGLONG) wfd.nFileSizeHigh) << 32) + wfd.nFileSizeLow, wfd.ftCreationTime, - wfd.ftLastAccessTime, wfd.ftLastWriteTime, 0); - return true; - } - } - while(m_hFind != INVALID_HANDLE_VALUE && ::FindNextFile(m_hFind, &wfd)); // checking m_hFind in case other thread changed it (it shouldn't happen though) - - Close(); - } - - return false; -} - -void TLocalFilesystemFind::Close() -{ - if(m_hFind != INVALID_HANDLE_VALUE) - FindClose(m_hFind); - m_hFind = INVALID_HANDLE_VALUE; -} - -TLocalFilesystemFile::TLocalFilesystemFile() : - m_hFile(INVALID_HANDLE_VALUE), - m_pathFile(), - m_bNoBuffering(false) -{ -} - -TLocalFilesystemFile::~TLocalFilesystemFile() -{ - 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); -} - -bool TLocalFilesystemFile::OpenExistingForReading(const TSmartPath& pathFile, bool bNoBuffering) -{ - Close(); - - 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; - - m_bNoBuffering = bNoBuffering; - return true; -} - -bool TLocalFilesystemFile::CreateNewForWriting(const TSmartPath& pathFile, bool bNoBuffering) -{ - Close(); - - 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; - - m_bNoBuffering = bNoBuffering; - return true; -} - -bool TLocalFilesystemFile::OpenExistingForWriting(const TSmartPath& pathFile, bool bNoBuffering) -{ - Close(); - - 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; - - m_bNoBuffering = bNoBuffering; - return true; -} - -bool TLocalFilesystemFile::SetFilePointer(long long llNewPos, DWORD dwMoveMethod) -{ - if(!IsOpen()) - return false; - - LARGE_INTEGER li = { 0, 0 }; - LARGE_INTEGER liNew = { 0, 0 }; - - li.QuadPart = llNewPos; - - return SetFilePointerEx(m_hFile, li, &liNew, dwMoveMethod) != FALSE; -} - -bool TLocalFilesystemFile::SetEndOfFile() -{ - if(!IsOpen()) - return 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)) - { - DWORD dwLastError = GetLastError(); - switch(dwLastError) - { - case ERROR_IO_PENDING: - return true; - - case ERROR_HANDLE_EOF: - { - rBuffer.SetBytesTransferred(0); - rBuffer.SetStatusCode(0); - rBuffer.SetErrorCode(ERROR_SUCCESS); - rBuffer.SetLastPart(true); - - rBuffer.RequeueAsFull(); // basically the same as OverlappedReadCompleted - - return true; - } - } - - return false; - } - return true; -} - -bool TLocalFilesystemFile::WriteFile(TOverlappedDataBuffer& rBuffer) -{ - if (!IsOpen()) - THROW_CORE_EXCEPTION(eErr_InternalProblem); - - DWORD dwToWrite = boost::numeric_cast(rBuffer.GetRealDataSize()); - - 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; - } - - return true; -} - -bool TLocalFilesystemFile::FinalizeFile(TOverlappedDataBuffer& rBuffer) -{ - if (!IsOpen()) - THROW_CORE_EXCEPTION(eErr_InternalProblem); - - if (m_bNoBuffering && rBuffer.IsLastPart()) - { - DWORD dwToWrite = boost::numeric_cast(rBuffer.GetRealDataSize()); - DWORD dwReallyWritten = RoundUp(dwToWrite, MaxSectorSize); - - ATLTRACE(_T("Finalize file - size diff: written: %I64u, required: %I64u\n"), dwReallyWritten, dwToWrite); - - if (dwToWrite != dwReallyWritten) - { - unsigned long long ullNewFileSize = rBuffer.GetFilePosition() + dwToWrite; // new size - - if (!OpenExistingForWriting(m_pathFile, false)) - return false; - - //seek - ATLTRACE(_T("Truncating file to %I64u bytes\n"), ullNewFileSize); - if (!SetFilePointer(ullNewFileSize, FILE_BEGIN)) - return false; - - //set eof - if (!SetEndOfFile()) - return false; - } - } - - return true; -} - -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; - - BY_HANDLE_FILE_INFORMATION bhfi; - - if(!::GetFileInformationByHandle(m_hFile, &bhfi)) - return 0; - - ULARGE_INTEGER uli; - uli.HighPart = bhfi.nFileSizeHigh; - uli.LowPart = bhfi.nFileSizeLow; - - return uli.QuadPart; -} - END_CHCORE_NAMESPACE