Index: src/libchcore/EFileError.h =================================================================== diff -u -re96806b7f8ff7ca7e9f4afbea603e6351a3dc3e3 -rd468098a278a0d16c5b700236ea276b9c9677c9f --- src/libchcore/EFileError.h (.../EFileError.h) (revision e96806b7f8ff7ca7e9f4afbea603e6351a3dc3e3) +++ src/libchcore/EFileError.h (.../EFileError.h) (revision d468098a278a0d16c5b700236ea276b9c9677c9f) @@ -32,7 +32,8 @@ eWriteError, ///< Problem occurred when tried to write data to a file eFinalizeError, ///< Problem occurred when tried to finalize file eFastMoveError, ///< Problem occurred when tried to perform fast move operation (that does not involve copying contents) - eCreateError ///< Problem occurred when tried to create the fs object + eCreateError, ///< Problem occurred when tried to create the fs object + eCheckForFreeSpace ///< Problem occurred when tried to create the fs object }; } Index: src/libchcore/ErrorCodes.h =================================================================== diff -u -r27a43e40952cf2f3e0bb0e608a8f3142042ceb46 -rd468098a278a0d16c5b700236ea276b9c9677c9f --- src/libchcore/ErrorCodes.h (.../ErrorCodes.h) (revision 27a43e40952cf2f3e0bb0e608a8f3142042ceb46) +++ src/libchcore/ErrorCodes.h (.../ErrorCodes.h) (revision d468098a278a0d16c5b700236ea276b9c9677c9f) @@ -83,6 +83,12 @@ eErr_FileNotOpen = 3007, eErr_SeekFailed = 3008, eErr_CannotTruncate = 3009, + eErr_CannotSetFileTimes = 3010, + eErr_CannotSetFileAttributes = 3011, + eErr_CannotCreateDirectory = 3012, + eErr_CannotRemoveDirectory = 3013, + eErr_CannotFastMove = 3014, + eErr_CannotGetFreeSpace = 3015, // Task handling errors (4000+) eErr_MissingTaskSerializationPath = 4000, Index: src/libchcore/IFilesystem.h =================================================================== diff -u -r479ad4e8f81a68cbf6d1623cd9b1f3342d8cfdcc -rd468098a278a0d16c5b700236ea276b9c9677c9f --- src/libchcore/IFilesystem.h (.../IFilesystem.h) (revision 479ad4e8f81a68cbf6d1623cd9b1f3342d8cfdcc) +++ src/libchcore/IFilesystem.h (.../IFilesystem.h) (revision d468098a278a0d16c5b700236ea276b9c9677c9f) @@ -46,22 +46,22 @@ virtual bool PathExist(const TSmartPath& strPath) = 0; - virtual bool SetFileDirectoryTime(const TSmartPath& pathFileDir, const TFileTime& ftCreationTime, const TFileTime& ftLastAccessTime, const TFileTime& ftLastWriteTime) = 0; - virtual bool SetAttributes(const TSmartPath& pathFileDir, DWORD dwAttributes) = 0; + virtual void SetFileDirectoryTime(const TSmartPath& pathFileDir, const TFileTime& ftCreationTime, const TFileTime& ftLastAccessTime, const TFileTime& ftLastWriteTime) = 0; + virtual void SetAttributes(const TSmartPath& pathFileDir, DWORD dwAttributes) = 0; - virtual bool CreateDirectory(const TSmartPath& pathDirectory, bool bCreateFullPath) = 0; - virtual bool RemoveDirectory(const TSmartPath& pathFile) = 0; - virtual bool DeleteFile(const TSmartPath& pathFile) = 0; + virtual void CreateDirectory(const TSmartPath& pathDirectory, bool bCreateFullPath) = 0; + virtual void RemoveDirectory(const TSmartPath& pathFile) = 0; + virtual void DeleteFile(const TSmartPath& pathFile) = 0; - virtual bool GetFileInfo(const TSmartPath& pathFile, TFileInfoPtr& rFileInfo, const TBasePathDataPtr& spBasePathData = TBasePathDataPtr()) = 0; - virtual bool FastMove(const TSmartPath& pathSource, const TSmartPath& pathDestination) = 0; + virtual void GetFileInfo(const TSmartPath& pathFile, TFileInfoPtr& rFileInfo, const TBasePathDataPtr& spBasePathData = TBasePathDataPtr()) = 0; + virtual void FastMove(const TSmartPath& pathSource, const TSmartPath& pathDestination) = 0; virtual IFilesystemFindPtr CreateFinderObject(const TSmartPath& pathDir, const TSmartPath& pathMask) = 0; virtual IFilesystemFilePtr CreateFileObject(const TSmartPath& pathFile, bool bNoBuffering) = 0; virtual EPathsRelation GetPathsRelation(const TSmartPath& pathFirst, const TSmartPath& pathSecond) = 0; - virtual bool GetDynamicFreeSpace(const TSmartPath& path, unsigned long long& rullFree) = 0; + virtual void GetDynamicFreeSpace(const TSmartPath& path, unsigned long long& rullFree) = 0; }; typedef std::shared_ptr IFilesystemPtr; Index: src/libchcore/TFakeFilesystem.cpp =================================================================== diff -u -r479ad4e8f81a68cbf6d1623cd9b1f3342d8cfdcc -rd468098a278a0d16c5b700236ea276b9c9677c9f --- src/libchcore/TFakeFilesystem.cpp (.../TFakeFilesystem.cpp) (revision 479ad4e8f81a68cbf6d1623cd9b1f3342d8cfdcc) +++ src/libchcore/TFakeFilesystem.cpp (.../TFakeFilesystem.cpp) (revision d468098a278a0d16c5b700236ea276b9c9677c9f) @@ -24,6 +24,7 @@ #include "TFakeFilesystemFile.h" #include "TFakeFilesystemFind.h" #include "TPathContainer.h" +#include "TFileException.h" namespace chcore { @@ -46,7 +47,7 @@ return false; } - bool TFakeFilesystem::GetDynamicFreeSpace(const TSmartPath& path, unsigned long long& rullFree) + void TFakeFilesystem::GetDynamicFreeSpace(const TSmartPath& path, unsigned long long& rullFree) { // get total size of volume file_size_t fsSize = std::numeric_limits::max(); @@ -60,12 +61,15 @@ { file_size_t fsFileSize(RoundUp(spDesc->GetFileInfo().GetLength64(), (file_size_t)IFilesystemFile::MaxSectorSize)); if (fsFileSize > fsSize) - return false; + { + rullFree = 0; + return; + } + fsSize -= RoundUp(spDesc->GetFileInfo().GetLength64(), (file_size_t)IFilesystemFile::MaxSectorSize); } rullFree = fsSize; - return false; } IFilesystem::EPathsRelation TFakeFilesystem::GetPathsRelation(const TSmartPath& pathFirst, const TSmartPath& pathSecond) @@ -143,34 +147,29 @@ return spFind; } - bool TFakeFilesystem::FastMove(const TSmartPath& pathSource, const TSmartPath& pathDestination) + void TFakeFilesystem::FastMove(const TSmartPath& pathSource, const TSmartPath& pathDestination) { TFakeFileDescriptionPtr spFileDesc = FindFileByLocation(pathSource); if (!spFileDesc) - return false; + THROW_FILE_EXCEPTION(eErr_CannotFastMove, ERROR_FILE_INVALID, pathSource, L"Cannot fast move non-existent file"); // check parent of pathDestination TSmartPath pathParent = pathDestination.GetParent(); if (pathParent.IsEmpty()) - return false; + THROW_FILE_EXCEPTION(eErr_CannotFastMove, ERROR_FILE_INVALID, pathSource, L"Cannot get path of the parent"); TFakeFileDescriptionPtr spParentDesc = FindFileByLocation(pathParent); if (!spParentDesc) - return false; + THROW_FILE_EXCEPTION(eErr_CannotFastMove, ERROR_FILE_INVALID, pathSource, L"Cannot get parent object"); spFileDesc->GetFileInfo().SetFilePath(pathDestination); - return true; } - bool TFakeFilesystem::GetFileInfo(const TSmartPath& pathFile, TFileInfoPtr& rFileInfo, const TBasePathDataPtr& spBasePathData) + void TFakeFilesystem::GetFileInfo(const TSmartPath& pathFile, TFileInfoPtr& rFileInfo, const TBasePathDataPtr& spBasePathData) { TFakeFileDescriptionPtr spFileDesc = FindFileByLocation(pathFile); if (!spFileDesc) - { - FILETIME fi = { 0, 0 }; - rFileInfo->Init(TSmartPath(), (DWORD)-1, 0, fi, fi, fi, 0); - return false; - } + THROW_FILE_EXCEPTION(eErr_CannotGetFileInfo, ERROR_FILE_INVALID, pathFile, L"Cannot get file info from non-existent file"); // copy data from W32_F_D rFileInfo->Init(spBasePathData, pathFile, spFileDesc->GetFileInfo().GetAttributes(), @@ -179,20 +178,18 @@ spFileDesc->GetFileInfo().GetLastAccessTime().GetAsFiletime(), spFileDesc->GetFileInfo().GetLastWriteTime().GetAsFiletime(), 0); - - return true; } - bool TFakeFilesystem::DeleteFile(const TSmartPath& pathFile) + void TFakeFilesystem::DeleteFile(const TSmartPath& pathFile) { // check parent of pathDestination TSmartPath pathParent = pathFile.GetParent(); if (pathParent.IsEmpty()) - return false; + THROW_FILE_EXCEPTION(eErr_CannotDeleteFile, ERROR_FILE_INVALID, pathFile, L"Cannot get parent directory"); TFakeFileDescriptionPtr spParentDesc = FindFileByLocation(pathParent); if (!spParentDesc) - return false; + THROW_FILE_EXCEPTION(eErr_CannotDeleteFile, ERROR_FILE_INVALID, pathFile, L"Cannot delete file from non-existent directory"); // similar to FindFileByLocation(), but operating on iterators for (auto iterList = m_listFilesystemContent.begin(); iterList != m_listFilesystemContent.end(); ++iterList) @@ -201,91 +198,87 @@ if (spDesc->GetFileInfo().GetFullFilePath() == pathFile) { if (spDesc->GetFileInfo().IsDirectory()) - return false; + THROW_FILE_EXCEPTION(eErr_CannotRemoveDirectory, ERROR_FILE_INVALID, pathFile, L"Cannot remove directory by trying to delete a file"); m_listFilesystemContent.erase(iterList); - return true; + return; } } - return false; + THROW_FILE_EXCEPTION(eErr_CannotDeleteFile, ERROR_FILE_INVALID, pathFile, L"Cannot delete non-existent file"); } - bool TFakeFilesystem::RemoveDirectory(const TSmartPath& pathFile) + void TFakeFilesystem::RemoveDirectory(const TSmartPath& pathFile) { // check parent of pathDestination TSmartPath pathParent = pathFile.GetParent(); if (pathParent.IsEmpty()) - return false; + THROW_FILE_EXCEPTION(eErr_CannotRemoveDirectory, ERROR_FILE_INVALID, pathFile, L"Cannot get parent directory"); TFakeFileDescriptionPtr spParentDesc = FindFileByLocation(pathParent); if (!spParentDesc) - return false; + THROW_FILE_EXCEPTION(eErr_CannotRemoveDirectory, ERROR_FILE_INVALID, pathFile, L"Cannot delete directory from non-existent parent"); for (auto iterList = m_listFilesystemContent.begin(); iterList != m_listFilesystemContent.end(); ++iterList) { TFakeFileDescriptionPtr spDesc = (*iterList); if (spDesc->GetFileInfo().GetFullFilePath() == pathFile) { if (!spDesc->GetFileInfo().IsDirectory()) - return false; + THROW_FILE_EXCEPTION(eErr_CannotDeleteFile, ERROR_FILE_INVALID, pathFile, L"Cannot remove file by trying to delete a directory"); m_listFilesystemContent.erase(iterList); - return true; + return; } } - return false; + THROW_FILE_EXCEPTION(eErr_CannotRemoveDirectory, ERROR_FILE_INVALID, pathFile, L"Cannot delete non-existent directory"); } - bool TFakeFilesystem::CreateDirectory(const TSmartPath& pathDirectory, bool bCreateFullPath) + void TFakeFilesystem::CreateDirectory(const TSmartPath& pathDirectory, bool bCreateFullPath) { // check parent of pathDestination TFakeFileDescriptionPtr spDesc = FindFileByLocation(pathDirectory); if (spDesc) - return true; + THROW_FILE_EXCEPTION(eErr_CannotCreateDirectory, ERROR_ALREADY_EXISTS, pathDirectory, L"Cannot create directory - it already exists"); if(!bCreateFullPath) { TSmartPath pathParent = pathDirectory.GetParent(); if (pathParent.IsEmpty()) - return false; + THROW_FILE_EXCEPTION(eErr_CannotCreateDirectory, ERROR_FILE_INVALID, pathDirectory, L"Cannot retrieve parent"); TFakeFileDescriptionPtr spParentDesc = FindFileByLocation(pathParent); if (!spParentDesc) - return false; + THROW_FILE_EXCEPTION(eErr_CannotCreateDirectory, ERROR_FILE_INVALID, pathDirectory, L"Cannot retrieve parent"); CreateFakeDirectory(pathDirectory); } else CreateFSObjectByLocation(pathDirectory); - - return true; } - bool TFakeFilesystem::SetAttributes(const TSmartPath& pathFileDir, DWORD dwAttributes) + void TFakeFilesystem::SetAttributes(const TSmartPath& pathFileDir, DWORD dwAttributes) { TFakeFileDescriptionPtr spFileDesc = FindFileByLocation(pathFileDir); if (!spFileDesc) - return false; + THROW_FILE_EXCEPTION(eErr_CannotSetFileAttributes, ERROR_FILE_INVALID, pathFileDir, L"Cannot locate file"); if (spFileDesc->GetFileInfo().IsDirectory() && !(dwAttributes & FILE_ATTRIBUTE_DIRECTORY)) - return false; + THROW_FILE_EXCEPTION(eErr_CannotSetFileAttributes, ERROR_FILE_INVALID, pathFileDir, L"Cannot set invalid attribute"); if (!spFileDesc->GetFileInfo().IsDirectory() && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY)) - return false; + THROW_FILE_EXCEPTION(eErr_CannotSetFileAttributes, ERROR_FILE_INVALID, pathFileDir, L"Cannot set invalid attribute"); spFileDesc->GetFileInfo().SetAttributes(dwAttributes); - return true; } - bool TFakeFilesystem::SetFileDirectoryTime(const TSmartPath& pathFileDir, const TFileTime& ftCreationTime, const TFileTime& ftLastAccessTime, const TFileTime& ftLastWriteTime) + void TFakeFilesystem::SetFileDirectoryTime(const TSmartPath& pathFileDir, const TFileTime& ftCreationTime, const TFileTime& ftLastAccessTime, const TFileTime& ftLastWriteTime) { TFakeFileDescriptionPtr spFileDesc = FindFileByLocation(pathFileDir); if (!spFileDesc) - return false; + THROW_FILE_EXCEPTION(eErr_CannotSetFileTimes, ERROR_FILE_INVALID, pathFileDir, L"Cannot locate file"); spFileDesc->GetFileInfo().SetFileTimes(ftCreationTime, ftLastAccessTime, ftLastWriteTime); - return true; } void TFakeFilesystem::SetVolumeInfo(wchar_t wchVolumeLetter, file_size_t fsSize, UINT uiDriveType, DWORD dwPhysicalDiskNumber) Index: src/libchcore/TFakeFilesystem.h =================================================================== diff -u -r479ad4e8f81a68cbf6d1623cd9b1f3342d8cfdcc -rd468098a278a0d16c5b700236ea276b9c9677c9f --- src/libchcore/TFakeFilesystem.h (.../TFakeFilesystem.h) (revision 479ad4e8f81a68cbf6d1623cd9b1f3342d8cfdcc) +++ src/libchcore/TFakeFilesystem.h (.../TFakeFilesystem.h) (revision d468098a278a0d16c5b700236ea276b9c9677c9f) @@ -34,17 +34,17 @@ // interface implementation virtual bool PathExist(const TSmartPath& strPath) override; - virtual bool SetFileDirectoryTime(const TSmartPath& pathFileDir, const TFileTime& ftCreationTime, const TFileTime& ftLastAccessTime, const TFileTime& ftLastWriteTime) override; - virtual bool SetAttributes(const TSmartPath& pathFileDir, DWORD dwAttributes) override; - virtual bool CreateDirectory(const TSmartPath& pathDirectory, bool bCreateFullPath) override; - virtual bool RemoveDirectory(const TSmartPath& pathFile) override; - virtual bool DeleteFile(const TSmartPath& pathFile) override; - virtual bool GetFileInfo(const TSmartPath& pathFile, TFileInfoPtr& rFileInfo, const TBasePathDataPtr& spBasePathData = TBasePathDataPtr()) override; - virtual bool FastMove(const TSmartPath& pathSource, const TSmartPath& pathDestination) override; + virtual void SetFileDirectoryTime(const TSmartPath& pathFileDir, const TFileTime& ftCreationTime, const TFileTime& ftLastAccessTime, const TFileTime& ftLastWriteTime) override; + virtual void SetAttributes(const TSmartPath& pathFileDir, DWORD dwAttributes) override; + virtual void CreateDirectory(const TSmartPath& pathDirectory, bool bCreateFullPath) override; + virtual void RemoveDirectory(const TSmartPath& pathFile) override; + virtual void DeleteFile(const TSmartPath& pathFile) override; + virtual void GetFileInfo(const TSmartPath& pathFile, TFileInfoPtr& rFileInfo, const TBasePathDataPtr& spBasePathData = TBasePathDataPtr()) override; + virtual void FastMove(const TSmartPath& pathSource, const TSmartPath& pathDestination) override; virtual IFilesystemFindPtr CreateFinderObject(const TSmartPath& pathDir, const TSmartPath& pathMask) override; virtual IFilesystemFilePtr CreateFileObject(const TSmartPath& spFilename, bool bNoBuffering) override; virtual EPathsRelation GetPathsRelation(const TSmartPath& pathFirst, const TSmartPath& pathSecond) override; - virtual bool GetDynamicFreeSpace(const TSmartPath& path, unsigned long long& rullFree) override; + virtual void GetDynamicFreeSpace(const TSmartPath& path, unsigned long long& rullFree) override; // fake handling api void SetVolumeInfo(wchar_t wchVolumeLetter, file_size_t fsSize, UINT uiDriveType, DWORD dwPhysicalDiskNumber); Index: src/libchcore/TLocalFilesystem.cpp =================================================================== diff -u -r479ad4e8f81a68cbf6d1623cd9b1f3342d8cfdcc -rd468098a278a0d16c5b700236ea276b9c9677c9f --- src/libchcore/TLocalFilesystem.cpp (.../TLocalFilesystem.cpp) (revision 479ad4e8f81a68cbf6d1623cd9b1f3342d8cfdcc) +++ src/libchcore/TLocalFilesystem.cpp (.../TLocalFilesystem.cpp) (revision d468098a278a0d16c5b700236ea276b9c9677c9f) @@ -44,6 +44,7 @@ #include "TLocalFilesystemFile.h" #include #include "TLocalFilesystemFind.h" +#include "TFileException.h" namespace chcore { @@ -103,29 +104,41 @@ return false; } - bool TLocalFilesystem::SetFileDirectoryTime(const TSmartPath& pathFileDir, const TFileTime& ftCreationTime, const TFileTime& ftLastAccessTime, const TFileTime& ftLastWriteTime) + void TLocalFilesystem::SetFileDirectoryTime(const TSmartPath& pathFileDir, const TFileTime& ftCreationTime, const TFileTime& ftLastAccessTime, const TFileTime& ftLastWriteTime) { TAutoFileHandle hFile = CreateFile(PrependPathExtensionIfNeeded(pathFileDir).ToString(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL); if (hFile == INVALID_HANDLE_VALUE) - return false; + { + DWORD dwLastError = GetLastError(); + THROW_FILE_EXCEPTION(eErr_CannotOpenFile, dwLastError, pathFileDir, L"Cannot open file for setting file/directory times"); + } - BOOL bResult = SetFileTime(hFile, &ftCreationTime.GetAsFiletime(), &ftLastAccessTime.GetAsFiletime(), &ftLastWriteTime.GetAsFiletime()); - - if (!hFile.Close()) - return false; - - return bResult != FALSE; + if (!SetFileTime(hFile, &ftCreationTime.GetAsFiletime(), &ftLastAccessTime.GetAsFiletime(), &ftLastWriteTime.GetAsFiletime())) + { + DWORD dwLastError = GetLastError(); + THROW_FILE_EXCEPTION(eErr_CannotSetFileTimes, dwLastError, pathFileDir, L"Cannot set file/directory times"); + } } - bool TLocalFilesystem::SetAttributes(const TSmartPath& pathFileDir, DWORD dwAttributes) + void TLocalFilesystem::SetAttributes(const TSmartPath& pathFileDir, DWORD dwAttributes) { - return ::SetFileAttributes(PrependPathExtensionIfNeeded(pathFileDir).ToString(), dwAttributes) != FALSE; + if (!::SetFileAttributes(PrependPathExtensionIfNeeded(pathFileDir).ToString(), dwAttributes)) + { + DWORD dwLastError = GetLastError(); + THROW_FILE_EXCEPTION(eErr_CannotSetFileAttributes, dwLastError, pathFileDir, L"Cannot set file/directory attributes"); + } } - bool TLocalFilesystem::CreateDirectory(const TSmartPath& pathDirectory, bool bCreateFullPath) + void TLocalFilesystem::CreateDirectory(const TSmartPath& pathDirectory, bool bCreateFullPath) { if (!bCreateFullPath) - return ::CreateDirectory(PrependPathExtensionIfNeeded(pathDirectory).ToString(), NULL) != FALSE; + { + if (!::CreateDirectory(PrependPathExtensionIfNeeded(pathDirectory).ToString(), NULL)) + { + DWORD dwLastError = GetLastError(); + THROW_FILE_EXCEPTION(eErr_CannotCreateDirectory, dwLastError, pathDirectory, L"Cannot create directory"); + } + } else { TPathContainer vComponents; @@ -142,60 +155,72 @@ { // try to create the specified path BOOL bRes = ::CreateDirectory(PrependPathExtensionIfNeeded(pathToTest).ToString(), NULL); - if (!bRes && GetLastError() != ERROR_ALREADY_EXISTS) - return false; + if (!bRes) + { + DWORD dwLastError = GetLastError(); + if (dwLastError != ERROR_ALREADY_EXISTS) + THROW_FILE_EXCEPTION(eErr_CannotCreateDirectory, dwLastError, pathToTest, L"Cannot create directory"); + } } } } - - return true; } - bool TLocalFilesystem::RemoveDirectory(const TSmartPath& pathFile) + void TLocalFilesystem::RemoveDirectory(const TSmartPath& pathDirectory) { - return ::RemoveDirectory(PrependPathExtensionIfNeeded(pathFile).ToString()) != FALSE; + if (!::RemoveDirectory(PrependPathExtensionIfNeeded(pathDirectory).ToString())) + { + DWORD dwLastError = GetLastError(); + THROW_FILE_EXCEPTION(eErr_CannotRemoveDirectory, dwLastError, pathDirectory, L"Cannot delete directory"); + } } - bool TLocalFilesystem::DeleteFile(const TSmartPath& pathFile) + void TLocalFilesystem::DeleteFile(const TSmartPath& pathFile) { - return ::DeleteFile(PrependPathExtensionIfNeeded(pathFile).ToString()) != FALSE; + if (!::DeleteFile(PrependPathExtensionIfNeeded(pathFile).ToString())) + { + DWORD dwLastError = GetLastError(); + THROW_FILE_EXCEPTION(eErr_CannotDeleteFile, dwLastError, pathFile, L"Cannot delete file"); + } } - bool TLocalFilesystem::GetFileInfo(const TSmartPath& pathFile, TFileInfoPtr& rFileInfo, const TBasePathDataPtr& spBasePathData) + void TLocalFilesystem::GetFileInfo(const TSmartPath& pathFile, TFileInfoPtr& spFileInfo, const TBasePathDataPtr& spBasePathData) { - if (!rFileInfo) + if (!spFileInfo) THROW_CORE_EXCEPTION(eErr_InvalidArgument); WIN32_FIND_DATA wfd; HANDLE hFind = FindFirstFile(PrependPathExtensionIfNeeded(pathFile).ToString(), &wfd); - if (hFind != INVALID_HANDLE_VALUE) { FindClose(hFind); - // new instance of path to accomodate the corrected path (i.e. input path might have lower case names, but we'd like to - // preserve the original case contained in the filesystem) + // new instance of path to accommodate the corrected path (i.e. input path might have lower case names, but we'd like to + // preserve the original case contained in the file system) TSmartPath pathNew(pathFile); pathNew.DeleteFileName(); // copy data from W32_F_D - rFileInfo->Init(spBasePathData, pathNew + PathFromString(wfd.cFileName), + spFileInfo->Init(spBasePathData, pathNew + PathFromString(wfd.cFileName), wfd.dwFileAttributes, (((ULONGLONG)wfd.nFileSizeHigh) << 32) + wfd.nFileSizeLow, wfd.ftCreationTime, wfd.ftLastAccessTime, wfd.ftLastWriteTime, 0); - - return true; } else { - FILETIME fi = { 0, 0 }; - rFileInfo->Init(TSmartPath(), (DWORD)-1, 0, fi, fi, fi, 0); - return false; + DWORD dwLastError = GetLastError(); + THROW_FILE_EXCEPTION(eErr_CannotGetFileInfo, dwLastError, pathFile, L"Cannot retrieve file information"); } } - bool TLocalFilesystem::FastMove(const TSmartPath& pathSource, const TSmartPath& pathDestination) + void TLocalFilesystem::FastMove(const TSmartPath& pathSource, const TSmartPath& pathDestination) { - return ::MoveFile(PrependPathExtensionIfNeeded(pathSource).ToString(), PrependPathExtensionIfNeeded(pathDestination).ToString()) != FALSE; + if (!::MoveFile(PrependPathExtensionIfNeeded(pathSource).ToString(), PrependPathExtensionIfNeeded(pathDestination).ToString())) + { + DWORD dwLastError = GetLastError(); + // there is also the destination path that is important; tracking that would require adding a new exception class + // complicating the solution. For now it's not necessary to have that information in the exception. + THROW_FILE_EXCEPTION(eErr_CannotFastMove, dwLastError, pathSource, L"Cannot fast move file/directory"); + } } IFilesystemFindPtr TLocalFilesystem::CreateFinderObject(const TSmartPath& pathDir, const TSmartPath& pathMask) @@ -312,17 +337,17 @@ return pDiskExtent->DiskNumber; } - bool TLocalFilesystem::GetDynamicFreeSpace(const TSmartPath& path, unsigned long long& rullFree) + void TLocalFilesystem::GetDynamicFreeSpace(const TSmartPath& path, unsigned long long& rullFree) { rullFree = 0; ULARGE_INTEGER ui64Available, ui64Total; if (GetDiskFreeSpaceEx(path.ToString(), &ui64Available, &ui64Total, NULL)) - { rullFree = ui64Available.QuadPart; - return true; - } else - return false; + { + DWORD dwLastError = GetLastError(); + THROW_FILE_EXCEPTION(eErr_CannotGetFreeSpace, dwLastError, path, L"Failed to retrieve free space information"); + } } } Index: src/libchcore/TLocalFilesystem.h =================================================================== diff -u -r479ad4e8f81a68cbf6d1623cd9b1f3342d8cfdcc -rd468098a278a0d16c5b700236ea276b9c9677c9f --- src/libchcore/TLocalFilesystem.h (.../TLocalFilesystem.h) (revision 479ad4e8f81a68cbf6d1623cd9b1f3342d8cfdcc) +++ src/libchcore/TLocalFilesystem.h (.../TLocalFilesystem.h) (revision d468098a278a0d16c5b700236ea276b9c9677c9f) @@ -46,22 +46,22 @@ virtual bool PathExist(const TSmartPath& strPath) override; // check for file or folder existence - virtual bool SetFileDirectoryTime(const TSmartPath& pathFileDir, const TFileTime& ftCreationTime, const TFileTime& ftLastAccessTime, const TFileTime& ftLastWriteTime) override; - virtual bool SetAttributes(const TSmartPath& pathFileDir, DWORD dwAttributes) override; + virtual void SetFileDirectoryTime(const TSmartPath& pathFileDir, const TFileTime& ftCreationTime, const TFileTime& ftLastAccessTime, const TFileTime& ftLastWriteTime) override; + virtual void SetAttributes(const TSmartPath& pathFileDir, DWORD dwAttributes) override; - virtual bool CreateDirectory(const TSmartPath& pathDirectory, bool bCreateFullPath) override; - virtual bool RemoveDirectory(const TSmartPath& pathFile) override; - virtual bool DeleteFile(const TSmartPath& pathFile) override; + virtual void CreateDirectory(const TSmartPath& pathDirectory, bool bCreateFullPath) override; + virtual void RemoveDirectory(const TSmartPath& pathFile) override; + virtual void DeleteFile(const TSmartPath& pathFile) override; - virtual bool GetFileInfo(const TSmartPath& pathFile, TFileInfoPtr& rFileInfo, const TBasePathDataPtr& spBasePathData = TBasePathDataPtr()) override; - virtual bool FastMove(const TSmartPath& pathSource, const TSmartPath& pathDestination) override; + virtual void GetFileInfo(const TSmartPath& pathFile, TFileInfoPtr& rFileInfo, const TBasePathDataPtr& spBasePathData = TBasePathDataPtr()) override; + virtual void FastMove(const TSmartPath& pathSource, const TSmartPath& pathDestination) override; virtual IFilesystemFindPtr CreateFinderObject(const TSmartPath& pathDir, const TSmartPath& pathMask) override; virtual IFilesystemFilePtr CreateFileObject(const TSmartPath& pathFile, bool bNoBuffering) override; virtual EPathsRelation GetPathsRelation(const TSmartPath& pathFirst, const TSmartPath& pathSecond) override; - virtual bool GetDynamicFreeSpace(const TSmartPath& path, unsigned long long& rullFree) override; + virtual void GetDynamicFreeSpace(const TSmartPath& path, unsigned long long& rullFree) override; private: static TSmartPath PrependPathExtensionIfNeeded(const TSmartPath& pathInput); Index: src/libchcore/TLocalFilesystemFile.cpp =================================================================== diff -u -r27a43e40952cf2f3e0bb0e608a8f3142042ceb46 -rd468098a278a0d16c5b700236ea276b9c9677c9f --- src/libchcore/TLocalFilesystemFile.cpp (.../TLocalFilesystemFile.cpp) (revision 27a43e40952cf2f3e0bb0e608a8f3142042ceb46) +++ src/libchcore/TLocalFilesystemFile.cpp (.../TLocalFilesystemFile.cpp) (revision d468098a278a0d16c5b700236ea276b9c9677c9f) @@ -169,6 +169,7 @@ rBuffer.SetLastPart(true); rBuffer.RequeueAsFull(); // basically the same as OverlappedReadCompleted + break; } default: @@ -246,5 +247,4 @@ { return m_pathFile; } - } Index: src/libchcore/TSubTaskCopyMove.cpp =================================================================== diff -u -r27a43e40952cf2f3e0bb0e608a8f3142042ceb46 -rd468098a278a0d16c5b700236ea276b9c9677c9f --- src/libchcore/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision 27a43e40952cf2f3e0bb0e608a8f3142042ceb46) +++ src/libchcore/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision d468098a278a0d16c5b700236ea276b9c9677c9f) @@ -803,10 +803,8 @@ // by using spDstFileInfo->Create() (which uses FindFirstFile()) or by // reading parameters using opened handle; need to be tested in the future TFileInfoPtr spDstFileInfo(boost::make_shared()); + spFilesystem->GetFileInfo(fileDst->GetFilePath(), spDstFileInfo); - if(!spFilesystem->GetFileInfo(fileDst->GetFilePath(), spDstFileInfo)) - THROW_CORE_EXCEPTION_WIN32(eErr_CannotGetFileInfo, GetLastError()); - // src and dst files are the same EFeedbackResult frResult = spFeedbackHandler->FileAlreadyExists(spSrcFileInfo, spDstFileInfo); switch(frResult) @@ -1165,33 +1163,33 @@ bSkip = false; - // log - TString strFormat = _T("Error %errno while trying to write %count bytes to destination file %path (CustomCopyFileFB)"); - strFormat.Replace(_t("%errno"), boost::lexical_cast(rBuffer.GetErrorCode()).c_str()); - strFormat.Replace(_t("%count"), boost::lexical_cast(rBuffer.GetBytesTransferred()).c_str()); - strFormat.Replace(_t("%path"), pathFile.ToString()); - rLog.loge(strFormat.c_str()); +// log +TString strFormat = _T("Error %errno while trying to write %count bytes to destination file %path (CustomCopyFileFB)"); +strFormat.Replace(_t("%errno"), boost::lexical_cast(rBuffer.GetErrorCode()).c_str()); +strFormat.Replace(_t("%count"), boost::lexical_cast(rBuffer.GetBytesTransferred()).c_str()); +strFormat.Replace(_t("%path"), pathFile.ToString()); +rLog.loge(strFormat.c_str()); - EFeedbackResult frResult = spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eWriteError, dwLastError); - switch(frResult) - { - case EFeedbackResult::eResult_Cancel: - return TSubTaskBase::eSubResult_CancelRequest; +EFeedbackResult frResult = spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eWriteError, dwLastError); +switch (frResult) +{ +case EFeedbackResult::eResult_Cancel: + return TSubTaskBase::eSubResult_CancelRequest; - case EFeedbackResult::eResult_Retry: - return TSubTaskBase::eSubResult_Retry; +case EFeedbackResult::eResult_Retry: + return TSubTaskBase::eSubResult_Retry; - case EFeedbackResult::eResult_Pause: - return TSubTaskBase::eSubResult_PauseRequest; +case EFeedbackResult::eResult_Pause: + return TSubTaskBase::eSubResult_PauseRequest; - case EFeedbackResult::eResult_Skip: - bSkip = true; - return TSubTaskBase::eSubResult_Continue; +case EFeedbackResult::eResult_Skip: + bSkip = true; + return TSubTaskBase::eSubResult_Continue; - default: - BOOST_ASSERT(FALSE); // unknown result - THROW_CORE_EXCEPTION(eErr_UnhandledCase); - } +default: + BOOST_ASSERT(FALSE); // unknown result + THROW_CORE_EXCEPTION(eErr_UnhandledCase); +} } TSubTaskBase::ESubOperationResult TSubTaskCopyMove::FinalizeFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& spFile, @@ -1244,8 +1242,7 @@ BOOST_ASSERT(FALSE); // unknown result THROW_CORE_EXCEPTION(eErr_UnhandledCase); } - } - while (bRetry); + } while (bRetry); return TSubTaskBase::eSubResult_Continue; } @@ -1255,10 +1252,25 @@ icpf::log_file& rLog = GetContext().GetLog(); IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem(); - bool bRetry = true; - DWORD dwLastError = ERROR_SUCCESS; - while(bRetry && !spFilesystem->CreateDirectory(pathDirectory, false) && (dwLastError = GetLastError()) != ERROR_ALREADY_EXISTS) + bool bRetry = false; + do { + bRetry = false; + + DWORD dwLastError = ERROR_SUCCESS; + try + { + spFilesystem->CreateDirectory(pathDirectory, false); + return TSubTaskBase::eSubResult_Continue; + } + catch (const TFileException& e) + { + dwLastError = e.GetNativeError(); + } + + if (dwLastError == ERROR_ALREADY_EXISTS) + return TSubTaskBase::eSubResult_Continue; + // log TString strFormat; strFormat = _T("Error %errno while calling CreateDirectory %path (ProcessFiles)"); @@ -1273,21 +1285,21 @@ return TSubTaskBase::eSubResult_CancelRequest; case EFeedbackResult::eResult_Retry: - bRetry = false; + bRetry = true; break; case EFeedbackResult::eResult_Pause: return TSubTaskBase::eSubResult_PauseRequest; case EFeedbackResult::eResult_Skip: - bRetry = false; break; // just do nothing default: BOOST_ASSERT(FALSE); // unknown result THROW_CORE_EXCEPTION(eErr_UnhandledCase); } } + while (bRetry); return TSubTaskBase::eSubResult_Continue; } @@ -1313,9 +1325,50 @@ ullNeededSize = rFilesCache.CalculateTotalSize() - rFilesCache.CalculatePartialSize(m_tSubTaskStats.GetCurrentIndex()); // get free space - bool bResult = spFilesystem->GetDynamicFreeSpace(pathDestination, ullAvailableSize); - if(bResult && ullNeededSize > ullAvailableSize) + DWORD dwLastError = ERROR_SUCCESS; + bool bCheckFailed = false; + try { + spFilesystem->GetDynamicFreeSpace(pathDestination, ullAvailableSize); + } + catch (const TFileException& e) + { + dwLastError = e.GetNativeError(); + bCheckFailed = true; + } + + if(bCheckFailed) + { + TString strFormat; + strFormat = _T("Error %errno while checking free space at %path"); + strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); + strFormat.Replace(_T("%path"), pathDestination.ToString()); + rLog.loge(strFormat.c_str()); + + EFeedbackResult frResult = spFeedbackHandler->FileError(pathDestination.ToWString(), TString(), EFileError::eCheckForFreeSpace, dwLastError); + switch (frResult) + { + case EFeedbackResult::eResult_Cancel: + return TSubTaskBase::eSubResult_CancelRequest; + + case EFeedbackResult::eResult_Retry: + bRetry = true; + continue; + + case EFeedbackResult::eResult_Pause: + return TSubTaskBase::eSubResult_PauseRequest; + + case EFeedbackResult::eResult_Skip: + return TSubTaskBase::eSubResult_Continue; + + default: + BOOST_ASSERT(FALSE); // unknown result + THROW_CORE_EXCEPTION(eErr_UnhandledCase); + } + } + + if(ullNeededSize > ullAvailableSize) + { TString strFormat = _T("Not enough free space on disk - needed %needsize bytes for data, available: %availablesize bytes."); strFormat.Replace(_t("%needsize"), boost::lexical_cast(ullNeededSize).c_str()); strFormat.Replace(_t("%availablesize"), boost::lexical_cast(ullAvailableSize).c_str()); Index: src/libchcore/TSubTaskDelete.cpp =================================================================== diff -u -re96806b7f8ff7ca7e9f4afbea603e6351a3dc3e3 -rd468098a278a0d16c5b700236ea276b9c9677c9f --- src/libchcore/TSubTaskDelete.cpp (.../TSubTaskDelete.cpp) (revision e96806b7f8ff7ca7e9f4afbea603e6351a3dc3e3) +++ src/libchcore/TSubTaskDelete.cpp (.../TSubTaskDelete.cpp) (revision d468098a278a0d16c5b700236ea276b9c9677c9f) @@ -38,6 +38,7 @@ #include "TFeedbackHandlerWrapper.h" #include #include "TBufferSizes.h" +#include "TFileException.h" namespace chcore { @@ -64,7 +65,6 @@ icpf::log_file& rLog = GetContext().GetLog(); TFileInfoArray& rFilesCache = GetContext().GetFilesCache(); TWorkerThreadController& rThreadController = GetContext().GetThreadController(); - const TConfig& rConfig = GetContext().GetConfig(); IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem(); // log @@ -79,7 +79,6 @@ m_tSubTaskStats.SetCurrentPath(TString()); // current processed path - BOOL bSuccess; TFileInfoPtr spFileInfo; TString strFormat; @@ -110,63 +109,161 @@ continue; } + ESubOperationResult eResult = TSubTaskBase::eSubResult_Continue; // delete data if (spFileInfo->IsDirectory()) + eResult = RemoveDirectoryFB(spFeedbackHandler, spFileInfo); + else + eResult = DeleteFileFB(spFeedbackHandler, spFileInfo); + + ++fcIndex; + } + + m_tSubTaskStats.SetCurrentIndex(fcIndex); + m_tSubTaskStats.SetProcessedCount(fcIndex); + m_tSubTaskStats.SetCurrentPath(TString()); + + // log + rLog.logi(_T("Deleting files finished")); + + return TSubTaskBase::eSubResult_Continue; + } + + TSubTaskBase::ESubOperationResult TSubTaskDelete::RemoveDirectoryFB(const IFeedbackHandlerPtr& spFeedbackHandler, const TFileInfoPtr& spFileInfo) + { + const TConfig& rConfig = GetContext().GetConfig(); + IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem(); + icpf::log_file& rLog = GetContext().GetLog(); + + bool bRetry = false; + do + { + bRetry = false; + + // #bug - changing read-only attribute should only be done when user explicitly requests it (via feedback response) + // for now it is ignored + try { if (!GetTaskPropValue(rConfig)) spFilesystem->SetAttributes(spFileInfo->GetFullFilePath(), FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY); - bSuccess = spFilesystem->RemoveDirectory(spFileInfo->GetFullFilePath()); } - else + catch (const TFileException&) { - // set files attributes to normal - it'd slow processing a bit, but it's better. - if (!GetTaskPropValue(rConfig)) - spFilesystem->SetAttributes(spFileInfo->GetFullFilePath(), FILE_ATTRIBUTE_NORMAL); - bSuccess = spFilesystem->DeleteFile(spFileInfo->GetFullFilePath()); } - // operation failed - DWORD dwLastError = GetLastError(); - if (!bSuccess && dwLastError != ERROR_PATH_NOT_FOUND && dwLastError != ERROR_FILE_NOT_FOUND) + DWORD dwLastError = ERROR_SUCCESS; + try { - // log - strFormat = _T("Error #%errno while deleting file/folder %path"); - strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); - strFormat.Replace(_T("%path"), spFileInfo->GetFullFilePath().ToString()); - rLog.loge(strFormat.c_str()); + spFilesystem->RemoveDirectory(spFileInfo->GetFullFilePath()); + return TSubTaskBase::eSubResult_Continue; + } + catch (const TFileException& e) + { + dwLastError = e.GetNativeError(); + } - EFeedbackResult frResult = spFeedbackHandler->FileError(spFileInfo->GetFullFilePath().ToWString(), TString(), EFileError::eDeleteError, dwLastError); - switch (frResult) - { - case EFeedbackResult::eResult_Cancel: - rLog.logi(_T("Cancel request while deleting file.")); - return TSubTaskBase::eSubResult_CancelRequest; + if (dwLastError == ERROR_PATH_NOT_FOUND || dwLastError == ERROR_FILE_NOT_FOUND) + return TSubTaskBase::eSubResult_Continue; - case EFeedbackResult::eResult_Retry: - continue; // no fcIndex bump, since we are trying again + // log + TString strFormat = _T("Error #%errno while deleting file/folder %path"); + strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); + strFormat.Replace(_T("%path"), spFileInfo->GetFullFilePath().ToString()); + rLog.loge(strFormat.c_str()); - case EFeedbackResult::eResult_Pause: - return TSubTaskBase::eSubResult_PauseRequest; + EFeedbackResult frResult = spFeedbackHandler->FileError(spFileInfo->GetFullFilePath().ToWString(), TString(), EFileError::eDeleteError, dwLastError); + switch (frResult) + { + case EFeedbackResult::eResult_Cancel: + rLog.logi(_T("Cancel request while deleting file.")); + return TSubTaskBase::eSubResult_CancelRequest; - case EFeedbackResult::eResult_Skip: - break; // just do nothing + case EFeedbackResult::eResult_Retry: + bRetry = true; + continue; // no fcIndex bump, since we are trying again - default: - BOOST_ASSERT(FALSE); // unknown result - THROW_CORE_EXCEPTION(eErr_UnhandledCase); - } + case EFeedbackResult::eResult_Pause: + return TSubTaskBase::eSubResult_PauseRequest; + + case EFeedbackResult::eResult_Skip: + break; // just do nothing + + default: + BOOST_ASSERT(FALSE); // unknown result + THROW_CORE_EXCEPTION(eErr_UnhandledCase); } + } + while (bRetry); - ++fcIndex; - }//while + return TSubTaskBase::eSubResult_Continue; + } - m_tSubTaskStats.SetCurrentIndex(fcIndex); - m_tSubTaskStats.SetProcessedCount(fcIndex); - m_tSubTaskStats.SetCurrentPath(TString()); + TSubTaskBase::ESubOperationResult TSubTaskDelete::DeleteFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const TFileInfoPtr& spFileInfo) + { + const TConfig& rConfig = GetContext().GetConfig(); + IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem(); + icpf::log_file& rLog = GetContext().GetLog(); - // log - rLog.logi(_T("Deleting files finished")); + bool bRetry = false; + do + { + bRetry = false; + // #bug - changing read-only attribute should only be done when user explicitly requests it (via feedback response) + // for now it is ignored + try + { + if (!GetTaskPropValue(rConfig)) + spFilesystem->SetAttributes(spFileInfo->GetFullFilePath(), FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY); + } + catch (const TFileException&) + { + } + + DWORD dwLastError = ERROR_SUCCESS; + try + { + spFilesystem->DeleteFile(spFileInfo->GetFullFilePath()); + return TSubTaskBase::eSubResult_Continue; + } + catch (const TFileException& e) + { + dwLastError = e.GetNativeError(); + } + + if (dwLastError == ERROR_PATH_NOT_FOUND || dwLastError == ERROR_FILE_NOT_FOUND) + return TSubTaskBase::eSubResult_Continue; + + // log + TString strFormat = _T("Error #%errno while deleting file/folder %path"); + strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); + strFormat.Replace(_T("%path"), spFileInfo->GetFullFilePath().ToString()); + rLog.loge(strFormat.c_str()); + + EFeedbackResult frResult = spFeedbackHandler->FileError(spFileInfo->GetFullFilePath().ToWString(), TString(), EFileError::eDeleteError, dwLastError); + switch (frResult) + { + case EFeedbackResult::eResult_Cancel: + rLog.logi(_T("Cancel request while deleting file.")); + return TSubTaskBase::eSubResult_CancelRequest; + + case EFeedbackResult::eResult_Retry: + bRetry = true; + continue; // no fcIndex bump, since we are trying again + + case EFeedbackResult::eResult_Pause: + return TSubTaskBase::eSubResult_PauseRequest; + + case EFeedbackResult::eResult_Skip: + break; // just do nothing + + default: + BOOST_ASSERT(FALSE); // unknown result + THROW_CORE_EXCEPTION(eErr_UnhandledCase); + } + } + while (bRetry); + return TSubTaskBase::eSubResult_Continue; } Index: src/libchcore/TSubTaskDelete.h =================================================================== diff -u -re96806b7f8ff7ca7e9f4afbea603e6351a3dc3e3 -rd468098a278a0d16c5b700236ea276b9c9677c9f --- src/libchcore/TSubTaskDelete.h (.../TSubTaskDelete.h) (revision e96806b7f8ff7ca7e9f4afbea603e6351a3dc3e3) +++ src/libchcore/TSubTaskDelete.h (.../TSubTaskDelete.h) (revision d468098a278a0d16c5b700236ea276b9c9677c9f) @@ -49,6 +49,10 @@ virtual void GetStatsSnapshot(TSubTaskStatsSnapshotPtr& spStats) const; private: + TSubTaskBase::ESubOperationResult RemoveDirectoryFB(const IFeedbackHandlerPtr& spFeedbackHandler, const TFileInfoPtr& spFileInfo); + TSubTaskBase::ESubOperationResult DeleteFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const TFileInfoPtr& spFileInfo); + + private: #pragma warning(push) #pragma warning(disable: 4251) TSubTaskStatsInfo m_tSubTaskStats; Index: src/libchcore/TSubTaskFastMove.cpp =================================================================== diff -u -re96806b7f8ff7ca7e9f4afbea603e6351a3dc3e3 -rd468098a278a0d16c5b700236ea276b9c9677c9f --- src/libchcore/TSubTaskFastMove.cpp (.../TSubTaskFastMove.cpp) (revision e96806b7f8ff7ca7e9f4afbea603e6351a3dc3e3) +++ src/libchcore/TSubTaskFastMove.cpp (.../TSubTaskFastMove.cpp) (revision d468098a278a0d16c5b700236ea276b9c9677c9f) @@ -39,6 +39,7 @@ #include "TScopedRunningTimeTracker.h" #include "TFeedbackHandlerWrapper.h" #include "TBufferSizes.h" +#include "TFileException.h" namespace chcore { @@ -91,8 +92,6 @@ // add everything TString strFormat; - bool bRetry = true; - bool bSkipInputPath = false; file_count_t fcSize = spBasePaths->GetCount(); file_count_t fcIndex = m_tSubTaskStats.GetCurrentIndex(); @@ -114,42 +113,12 @@ continue; TFileInfoPtr spFileInfo(boost::make_shared()); - bSkipInputPath = false; - // try to get some info about the input path; let user know if the path does not exist. - do - { - bRetry = false; - // read attributes of src file/folder - bool bExists = spFilesystem->GetFileInfo(pathCurrent, spFileInfo, spBasePath); - if (!bExists) - { - EFeedbackResult frResult = spFeedbackHandler->FileError(pathCurrent.ToWString(), TString(), EFileError::eFastMoveError, ERROR_FILE_NOT_FOUND); - switch (frResult) - { - case EFeedbackResult::eResult_Cancel: - return eSubResult_CancelRequest; - - case EFeedbackResult::eResult_Retry: - bRetry = true; - break; - - case EFeedbackResult::eResult_Pause: - return eSubResult_PauseRequest; - - case EFeedbackResult::eResult_Skip: - bSkipInputPath = true; - break; // just do nothing - - default: - BOOST_ASSERT(FALSE); // unknown result - THROW_CORE_EXCEPTION(eErr_UnhandledCase); - } - } - } while (bRetry); - - // if we have chosen to skip the input path then there's nothing to do - if (bSkipInputPath) + bool bSkip = false; + ESubOperationResult eResult = GetFileInfoFB(spFeedbackHandler, pathCurrent, spFileInfo, spBasePath, bSkip); + if (eResult != TSubTaskBase::eSubResult_Continue) + return eResult; + else if (bSkip) continue; // does it match the input filter? @@ -160,64 +129,17 @@ } // try to fast move - bRetry = true; - bool bResult = true; - do - { - TSmartPath pathDestinationPath = CalculateDestinationPath(spFileInfo, pathDestination, 0); - TSmartPath pathSrc = spBasePath->GetSrcPath(); - bResult = spFilesystem->FastMove(pathSrc, pathDestinationPath); - if (!bResult) - { - DWORD dwLastError = GetLastError(); + eResult = FastMoveFB(spFeedbackHandler, spFileInfo, pathDestination, spBasePath, bSkip); + if (eResult != TSubTaskBase::eSubResult_Continue) + return eResult; + //else if (bSkip) + // continue; - // check if this is one of the errors, that will just cause fast move to skip - if (dwLastError == ERROR_ACCESS_DENIED || dwLastError == ERROR_ALREADY_EXISTS) - { - bRetry = false; - bResult = true; - } - else - { - //log - strFormat = _T("Error %errno while calling fast move %srcpath -> %dstpath (TSubTaskFastMove)"); - strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); - strFormat.Replace(_T("%srcpath"), spFileInfo->GetFullFilePath().ToString()); - strFormat.Replace(_T("%dstpath"), pathDestination.ToString()); - rLog.loge(strFormat.c_str()); - - EFeedbackResult frResult = spFeedbackHandler->FileError(pathSrc.ToWString(), pathDestinationPath.ToWString(), EFileError::eFastMoveError, dwLastError); - switch (frResult) - { - case EFeedbackResult::eResult_Cancel: - return TSubTaskBase::eSubResult_CancelRequest; - - case EFeedbackResult::eResult_Retry: - continue; - - case EFeedbackResult::eResult_Pause: - return TSubTaskBase::eSubResult_PauseRequest; - - case EFeedbackResult::eResult_Skip: - //bSkipInputPath = true; // not needed, since we will break the loop anyway and there is no other processing for this path either - bRetry = false; - break; // just do nothing - - default: - BOOST_ASSERT(FALSE); // unknown result - THROW_CORE_EXCEPTION(eErr_UnhandledCase); - } - } - } - else - spBasePath->SetSkipFurtherProcessing(true); // mark that this path should not be processed any further - } while (!bResult && bRetry); - // check for kill need if (rThreadController.KillRequested()) { // log - rLog.logi(_T("Kill request while adding data to files array (RecurseDirectories)")); + rLog.logi(_T("Kill request while fast moving items")); return eSubResult_KillRequest; } } @@ -232,6 +154,124 @@ return eSubResult_Continue; } + TSubTaskBase::ESubOperationResult TSubTaskFastMove::FastMoveFB(const IFeedbackHandlerPtr& spFeedbackHandler, const TFileInfoPtr& spFileInfo, const TSmartPath& pathDestination, + const TBasePathDataPtr& spBasePath, bool& bSkip) + { + IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem(); + icpf::log_file& rLog = GetContext().GetLog(); + + bool bRetry = false; + do + { + bRetry = false; + + TSmartPath pathDestinationPath = CalculateDestinationPath(spFileInfo, pathDestination, 0); + TSmartPath pathSrc = spBasePath->GetSrcPath(); + + DWORD dwLastError = ERROR_SUCCESS; + try + { + spFilesystem->FastMove(pathSrc, pathDestinationPath); + spBasePath->SetSkipFurtherProcessing(true); // mark that this path should not be processed any further + return eSubResult_Continue; + } + catch (const TFileException& e) + { + dwLastError = e.GetNativeError(); + } + + // check if this is one of the errors, that will just cause fast move to skip + if (dwLastError == ERROR_ACCESS_DENIED || dwLastError == ERROR_ALREADY_EXISTS) + { + bSkip = true; + break; + } + else + { + //log + TString strFormat = _T("Error %errno while calling fast move %srcpath -> %dstpath (TSubTaskFastMove)"); + strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); + strFormat.Replace(_T("%srcpath"), spFileInfo->GetFullFilePath().ToString()); + strFormat.Replace(_T("%dstpath"), pathDestination.ToString()); + rLog.loge(strFormat.c_str()); + + EFeedbackResult frResult = spFeedbackHandler->FileError(pathSrc.ToWString(), pathDestinationPath.ToWString(), EFileError::eFastMoveError, dwLastError); + switch (frResult) + { + case EFeedbackResult::eResult_Cancel: + return TSubTaskBase::eSubResult_CancelRequest; + + case EFeedbackResult::eResult_Retry: + bRetry = true; + break; + + case EFeedbackResult::eResult_Pause: + return TSubTaskBase::eSubResult_PauseRequest; + + case EFeedbackResult::eResult_Skip: + bSkip = true; + break; // just do nothing + + default: + BOOST_ASSERT(FALSE); // unknown result + THROW_CORE_EXCEPTION(eErr_UnhandledCase); + } + } + } + while (bRetry); + + return eSubResult_Continue; + } + + TSubTaskBase::ESubOperationResult TSubTaskFastMove::GetFileInfoFB(const IFeedbackHandlerPtr& spFeedbackHandler, const TSmartPath& pathCurrent, + TFileInfoPtr& spFileInfo, const TBasePathDataPtr& spBasePath, bool& bSkip) + { + const IFilesystemPtr& spFilesystem = GetContext().GetLocalFilesystem(); + + bool bRetry = false; + do + { + bRetry = false; + + // read attributes of src file/folder + DWORD dwLastError = ERROR_SUCCESS; + try + { + spFilesystem->GetFileInfo(pathCurrent, spFileInfo, spBasePath); + return eSubResult_Continue; + } + catch (const TFileException& e) + { + dwLastError = e.GetNativeError(); + } + + EFeedbackResult frResult = spFeedbackHandler->FileError(pathCurrent.ToWString(), TString(), EFileError::eFastMoveError, dwLastError); + switch (frResult) + { + case EFeedbackResult::eResult_Cancel: + return eSubResult_CancelRequest; + + case EFeedbackResult::eResult_Retry: + bRetry = true; + break; + + case EFeedbackResult::eResult_Pause: + return eSubResult_PauseRequest; + + case EFeedbackResult::eResult_Skip: + bSkip = true; + break; // just do nothing + + default: + BOOST_ASSERT(FALSE); // unknown result + THROW_CORE_EXCEPTION(eErr_UnhandledCase); + } + } + while (bRetry); + + return eSubResult_Continue; + } + void TSubTaskFastMove::GetStatsSnapshot(TSubTaskStatsSnapshotPtr& spStats) const { m_tSubTaskStats.GetSnapshot(spStats); Index: src/libchcore/TSubTaskFastMove.h =================================================================== diff -u -re96806b7f8ff7ca7e9f4afbea603e6351a3dc3e3 -rd468098a278a0d16c5b700236ea276b9c9677c9f --- src/libchcore/TSubTaskFastMove.h (.../TSubTaskFastMove.h) (revision e96806b7f8ff7ca7e9f4afbea603e6351a3dc3e3) +++ src/libchcore/TSubTaskFastMove.h (.../TSubTaskFastMove.h) (revision d468098a278a0d16c5b700236ea276b9c9677c9f) @@ -55,6 +55,8 @@ private: int ScanDirectory(TSmartPath pathDirName, size_t stSrcIndex, bool bRecurse, bool bIncludeDirs, TFileFiltersArray& afFilters); + TSubTaskBase::ESubOperationResult GetFileInfoFB(const IFeedbackHandlerPtr& spFeedbackHandler, const TSmartPath& pathCurrent, TFileInfoPtr& spFileInfo, const TBasePathDataPtr& spBasePath, bool& bSkip); + TSubTaskBase::ESubOperationResult FastMoveFB(const IFeedbackHandlerPtr& spFeedbackHandler, const TFileInfoPtr& spFileInfo, const TSmartPath& pathDestination, const TBasePathDataPtr& spBasePath, bool& bSkip); private: #pragma warning(push) Index: src/libchcore/TSubTaskScanDirectory.cpp =================================================================== diff -u -re96806b7f8ff7ca7e9f4afbea603e6351a3dc3e3 -rd468098a278a0d16c5b700236ea276b9c9677c9f --- src/libchcore/TSubTaskScanDirectory.cpp (.../TSubTaskScanDirectory.cpp) (revision e96806b7f8ff7ca7e9f4afbea603e6351a3dc3e3) +++ src/libchcore/TSubTaskScanDirectory.cpp (.../TSubTaskScanDirectory.cpp) (revision d468098a278a0d16c5b700236ea276b9c9677c9f) @@ -38,6 +38,7 @@ #include "TScopedRunningTimeTracker.h" #include "TFeedbackHandlerWrapper.h" #include "TBufferSizes.h" +#include "TFileException.h" namespace chcore { @@ -70,7 +71,6 @@ TBasePathDataContainerPtr spBasePaths = GetContext().GetBasePaths(); const TConfig& rConfig = GetContext().GetConfig(); const TFileFiltersArray& rafFilters = GetContext().GetFilters(); - const IFilesystemPtr& spFilesystem = GetContext().GetLocalFilesystem(); rLog.logi(_T("Searching for files...")); @@ -93,8 +93,6 @@ // add everything TString strFormat; - bool bRetry = true; - bool bSkipInputPath = false; file_count_t fcSize = spBasePaths->GetCount(); // NOTE: in theory, we should resume the scanning, but in practice we are always restarting scanning if interrupted. @@ -110,50 +108,18 @@ m_tSubTaskStats.SetProcessedCount(fcIndex); m_tSubTaskStats.SetCurrentPath(pathCurrent.ToString()); - bSkipInputPath = false; TFileInfoPtr spFileInfo(boost::make_shared()); // check if we want to process this path at all (might be already fast moved) if (spBasePath->GetSkipFurtherProcessing()) continue; // try to get some info about the input path; let user know if the path does not exist. - do - { - bRetry = false; - - // read attributes of src file/folder - bool bExists = spFilesystem->GetFileInfo(pathCurrent, spFileInfo, spBasePath); - if (!bExists) - { - EFeedbackResult frResult = spFeedbackHandler->FileError(pathCurrent.ToWString(), TString(), EFileError::eFastMoveError, ERROR_FILE_NOT_FOUND); - switch (frResult) - { - case EFeedbackResult::eResult_Cancel: - rFilesCache.Clear(); - return eSubResult_CancelRequest; - - case EFeedbackResult::eResult_Retry: - bRetry = true; - break; - - case EFeedbackResult::eResult_Pause: - rFilesCache.Clear(); - return eSubResult_PauseRequest; - - case EFeedbackResult::eResult_Skip: - bSkipInputPath = true; - break; // just do nothing - - default: - BOOST_ASSERT(FALSE); // unknown result - THROW_CORE_EXCEPTION(eErr_UnhandledCase); - } - } - } while (bRetry); - - // if we have chosen to skip the input path then there's nothing to do - if (bSkipInputPath) + bool bSkip = false; + ESubOperationResult eResult = GetFileInfoFB(spFeedbackHandler, pathCurrent, spFileInfo, spBasePath, bSkip); + if (eResult != TSubTaskBase::eSubResult_Continue) + return eResult; + else if (bSkip) continue; // log @@ -219,6 +185,57 @@ return eSubResult_Continue; } + TSubTaskBase::ESubOperationResult TSubTaskScanDirectories::GetFileInfoFB(const IFeedbackHandlerPtr& spFeedbackHandler, const TSmartPath& pathCurrent, TFileInfoPtr& spFileInfo, const TBasePathDataPtr& spBasePath, bool& bSkip) + { + TFileInfoArray& rFilesCache = GetContext().GetFilesCache(); + const IFilesystemPtr& spFilesystem = GetContext().GetLocalFilesystem(); + + bool bRetry = false; + do + { + bRetry = false; + + // read attributes of src file/folder + DWORD dwLastError = ERROR_SUCCESS; + try + { + spFilesystem->GetFileInfo(pathCurrent, spFileInfo, spBasePath); + return eSubResult_Continue; + } + catch (const TFileException& e) + { + dwLastError = e.GetNativeError(); + } + + EFeedbackResult frResult = spFeedbackHandler->FileError(pathCurrent.ToWString(), TString(), EFileError::eFastMoveError, dwLastError); + switch (frResult) + { + case EFeedbackResult::eResult_Cancel: + rFilesCache.Clear(); + return eSubResult_CancelRequest; + + case EFeedbackResult::eResult_Retry: + bRetry = true; + break; + + case EFeedbackResult::eResult_Pause: + rFilesCache.Clear(); + return eSubResult_PauseRequest; + + case EFeedbackResult::eResult_Skip: + bSkip = true; + break; // just do nothing + + default: + BOOST_ASSERT(FALSE); // unknown result + THROW_CORE_EXCEPTION(eErr_UnhandledCase); + } + } + while (bRetry); + + return eSubResult_Continue; + } + void TSubTaskScanDirectories::GetStatsSnapshot(TSubTaskStatsSnapshotPtr& spStats) const { m_tSubTaskStats.GetSnapshot(spStats); Index: src/libchcore/TSubTaskScanDirectory.h =================================================================== diff -u -re96806b7f8ff7ca7e9f4afbea603e6351a3dc3e3 -rd468098a278a0d16c5b700236ea276b9c9677c9f --- src/libchcore/TSubTaskScanDirectory.h (.../TSubTaskScanDirectory.h) (revision e96806b7f8ff7ca7e9f4afbea603e6351a3dc3e3) +++ src/libchcore/TSubTaskScanDirectory.h (.../TSubTaskScanDirectory.h) (revision d468098a278a0d16c5b700236ea276b9c9677c9f) @@ -56,6 +56,8 @@ int ScanDirectory(TSmartPath pathDirName, const TBasePathDataPtr& spBasePathData, bool bRecurse, bool bIncludeDirs, const TFileFiltersArray& afFilters); + ESubOperationResult GetFileInfoFB(const IFeedbackHandlerPtr& spFeedbackHandler, const TSmartPath& pathCurrent, TFileInfoPtr& spFileInfo, const TBasePathDataPtr& spBasePath, bool& bSkip); + private: #pragma warning(push) #pragma warning(disable: 4251)