Index: src/ch/FileInfo.cpp =================================================================== diff -u -N -re30c2b40bd1b533d8740edc88d80b2fb340f3466 -r1456ff2ae4a98c83f18d20dc253a24f26ddf521d --- src/ch/FileInfo.cpp (.../FileInfo.cpp) (revision e30c2b40bd1b533d8740edc88d80b2fb340f3466) +++ src/ch/FileInfo.cpp (.../FileInfo.cpp) (revision 1456ff2ae4a98c83f18d20dc253a24f26ddf521d) @@ -82,10 +82,37 @@ m_ftLastWrite = ftLastWrite; m_uiFlags = uiFlags; - if(m_pBasePaths && stSrcIndex != std::numeric_limits::max()) - m_pathFile.MakeRelativePath(m_pBasePaths->GetAt(stSrcIndex)); // cut path from clipboard + if(m_pBasePaths && m_stSrcIndex != std::numeric_limits::max()) + m_pathFile.MakeRelativePath(m_pBasePaths->GetAt(m_stSrcIndex)); // cut path from clipboard } +void CFileInfo::Init(const chcore::TSmartPath& rpathFile, DWORD dwAttributes, ULONGLONG uhFileSize, FILETIME ftCreation, FILETIME ftLastAccess, FILETIME ftLastWrite, + uint_t uiFlags) +{ + m_pathFile = rpathFile; + m_stSrcIndex = std::numeric_limits::max(); + m_pBasePaths = NULL; + m_dwAttributes = dwAttributes; + m_uhFileSize = uhFileSize; + m_ftCreation = ftCreation; + m_ftLastAccess = ftLastAccess; + m_ftLastWrite = ftLastWrite; + m_uiFlags = uiFlags; +} + +void CFileInfo::SetParentObject(size_t stIndex, const chcore::TPathContainer* pBasePaths) +{ + // cannot set parent object if there is already one specified + if(m_pBasePaths && m_stSrcIndex != std::numeric_limits::max()) + THROW(_T("Invalid argument"), 0, 0, 0); + + m_stSrcIndex = stIndex; + m_pBasePaths = pBasePaths; + + if(m_pBasePaths && m_stSrcIndex != std::numeric_limits::max()) + m_pathFile.MakeRelativePath(m_pBasePaths->GetAt(m_stSrcIndex)); +} + bool CFileInfo::operator==(const CFileInfo& rInfo) { return (rInfo.m_dwAttributes == m_dwAttributes && rInfo.m_ftCreation.dwHighDateTime == m_ftCreation.dwHighDateTime && rInfo.m_ftCreation.dwLowDateTime == m_ftCreation.dwLowDateTime Index: src/ch/FileInfo.h =================================================================== diff -u -N -re30c2b40bd1b533d8740edc88d80b2fb340f3466 -r1456ff2ae4a98c83f18d20dc253a24f26ddf521d --- src/ch/FileInfo.h (.../FileInfo.h) (revision e30c2b40bd1b533d8740edc88d80b2fb340f3466) +++ src/ch/FileInfo.h (.../FileInfo.h) (revision 1456ff2ae4a98c83f18d20dc253a24f26ddf521d) @@ -46,6 +46,9 @@ void Init(const chcore::TSmartPath& rpathFile, DWORD dwAttributes, ULONGLONG uhFileSize, FILETIME ftCreation, FILETIME ftLastAccess, FILETIME ftLastWrite, uint_t uiFlags); + // setting parent object + void SetParentObject(size_t stIndex, const chcore::TPathContainer* pBasePaths); + ULONGLONG GetLength64() const { return m_uhFileSize; } void SetLength64(ULONGLONG uhSize) { m_uhFileSize=uhSize; } Index: src/ch/TLocalFilesystem.cpp =================================================================== diff -u -N -re30c2b40bd1b533d8740edc88d80b2fb340f3466 -r1456ff2ae4a98c83f18d20dc253a24f26ddf521d --- src/ch/TLocalFilesystem.cpp (.../TLocalFilesystem.cpp) (revision e30c2b40bd1b533d8740edc88d80b2fb340f3466) +++ src/ch/TLocalFilesystem.cpp (.../TLocalFilesystem.cpp) (revision 1456ff2ae4a98c83f18d20dc253a24f26ddf521d) @@ -70,7 +70,7 @@ WIN32_FIND_DATA fd; // search by exact name - HANDLE hFind = FindFirstFile(pathToCheck.ToString(), &fd); + HANDLE hFind = FindFirstFile(PrependPathExtensionIfNeeded(pathToCheck).ToString(), &fd); if(hFind != INVALID_HANDLE_VALUE) { FindClose(hFind); @@ -81,7 +81,7 @@ // instead of c:\, which would never be found prev. way) pathToCheck.AppendIfNotExists(_T("*"), false); - hFind = FindFirstFile(pathToCheck.ToString(), &fd); + hFind = FindFirstFile(PrependPathExtensionIfNeeded(pathToCheck).ToString(), &fd); if(hFind != INVALID_HANDLE_VALUE) { ::FindClose(hFind); @@ -91,29 +91,23 @@ return false; } -bool TLocalFilesystem::SetFileDirectoryTime(LPCTSTR lpszName, const FILETIME& ftCreationTime, const FILETIME& ftLastAccessTime, const FILETIME& ftLastWriteTime) +bool TLocalFilesystem::SetFileDirectoryTime(const chcore::TSmartPath& pathFileDir, const FILETIME& ftCreationTime, const FILETIME& ftLastAccessTime, const FILETIME& ftLastWriteTime) { - TAutoFileHandle hFile = CreateFile(lpszName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL); + 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; - BOOL bResult = (!SetFileTime(hFile, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime)); + BOOL bResult = SetFileTime(hFile, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime); if(!hFile.Close()) return false; - return bResult != 0; + return bResult != FALSE; } bool TLocalFilesystem::CreateDirectory(const chcore::TSmartPath& pathDirectory) { - if(pathDirectory.GetLength() > _MAX_PATH - 1) - { - std::wstring wstrPath = _T("\\\\?\\") + pathDirectory.ToWString(); - return ::CreateDirectory(wstrPath.c_str(), NULL) != FALSE; - } - else - return ::CreateDirectory(pathDirectory.ToString(), NULL) != FALSE; + return ::CreateDirectory(PrependPathExtensionIfNeeded(pathDirectory).ToString(), NULL) != FALSE; } bool TLocalFilesystem::GetFileInfo(const chcore::TSmartPath& pathFile, CFileInfoPtr& rFileInfo, size_t stSrcIndex, const chcore::TPathContainer* pBasePaths) @@ -122,21 +116,14 @@ THROW(_T("Invalid argument"), 0, 0, 0); WIN32_FIND_DATA wfd; - HANDLE hFind = INVALID_HANDLE_VALUE; + HANDLE hFind = FindFirstFile(PrependPathExtensionIfNeeded(pathFile).ToString(), &wfd); - if(pathFile.GetLength() > _MAX_PATH - 1) - { - std::wstring wstrPath = _T("\\\\?\\") + pathFile.ToWString(); - hFind = FindFirstFile(wstrPath.c_str(), &wfd); - } - else - hFind = FindFirstFile(pathFile.ToString(), &wfd); - if(hFind != INVALID_HANDLE_VALUE) { FindClose(hFind); - // add data to members + // 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) chcore::TSmartPath pathNew(pathFile); pathNew.DeleteFileName(); @@ -154,3 +141,78 @@ return false; } } + +bool TLocalFilesystem::FastMove(const chcore::TSmartPath& pathSource, const chcore::TSmartPath& pathDestination) +{ + return ::MoveFile(PrependPathExtensionIfNeeded(pathSource).ToString(), PrependPathExtensionIfNeeded(pathDestination).ToString()) != FALSE; +} + +TLocalFilesystemFind TLocalFilesystem::CreateFinder(const chcore::TSmartPath& pathDir, const chcore::TSmartPath& pathMask) +{ + return TLocalFilesystemFind(pathDir, pathMask); +} + +chcore::TSmartPath TLocalFilesystem::PrependPathExtensionIfNeeded(const chcore::TSmartPath& pathInput) +{ + if(pathInput.GetLength() > _MAX_PATH - 1) + return chcore::PathFromString(_T("\\\\?\\")) + pathInput; + else + return pathInput; +} + +TLocalFilesystemFind::TLocalFilesystemFind(const chcore::TSmartPath& pathDir, const chcore::TSmartPath& pathMask) : + m_pathDir(pathDir), + m_pathMask(pathMask), + m_hFind(INVALID_HANDLE_VALUE) +{ +} + +TLocalFilesystemFind::~TLocalFilesystemFind() +{ + Close(); +} + +bool TLocalFilesystemFind::FindNext(CFileInfoPtr& rspFileInfo) +{ + WIN32_FIND_DATA wfd; + chcore::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 + if(bContinue) + { + do + { + if(!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + rspFileInfo->Init(m_pathDir + chcore::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 + chcore::PathFromString(wfd.cFileName), + wfd.dwFileAttributes, (((ULONGLONG) wfd.nFileSizeHigh) << 32) + wfd.nFileSizeLow, wfd.ftCreationTime, + wfd.ftLastAccessTime, wfd.ftLastWriteTime, 0); + return true; + } + } + while(::FindNextFile(m_hFind, &wfd)); + + Close(); + } + + return false; +} + +void TLocalFilesystemFind::Close() +{ + if(m_hFind != INVALID_HANDLE_VALUE) + FindClose(m_hFind); + m_hFind = INVALID_HANDLE_VALUE; +} Index: src/ch/TLocalFilesystem.h =================================================================== diff -u -N -re30c2b40bd1b533d8740edc88d80b2fb340f3466 -r1456ff2ae4a98c83f18d20dc253a24f26ddf521d --- src/ch/TLocalFilesystem.h (.../TLocalFilesystem.h) (revision e30c2b40bd1b533d8740edc88d80b2fb340f3466) +++ src/ch/TLocalFilesystem.h (.../TLocalFilesystem.h) (revision 1456ff2ae4a98c83f18d20dc253a24f26ddf521d) @@ -28,16 +28,44 @@ class CFileInfo; typedef boost::shared_ptr CFileInfoPtr; +class TLocalFilesystemFind; + class TLocalFilesystem { public: static void GetDriveData(const chcore::TSmartPath& spPath, int *piDrvNum, UINT *puiDrvType); static bool PathExist(chcore::TSmartPath strPath); // check for file or folder existence - static bool SetFileDirectoryTime(LPCTSTR lpszName, const FILETIME& ftCreationTime, const FILETIME& ftLastAccessTime, const FILETIME& ftLastWriteTime); + static bool SetFileDirectoryTime(const chcore::TSmartPath& pathFileDir, const FILETIME& ftCreationTime, const FILETIME& ftLastAccessTime, const FILETIME& ftLastWriteTime); static bool CreateDirectory(const chcore::TSmartPath& pathDirectory); static bool GetFileInfo(const chcore::TSmartPath& pathFile, CFileInfoPtr& rFileInfo, size_t stSrcIndex = std::numeric_limits::max(), const chcore::TPathContainer* pBasePaths = NULL); + static bool FastMove(const chcore::TSmartPath& pathSource, const chcore::TSmartPath& pathDestination); + + static TLocalFilesystemFind CreateFinder(const chcore::TSmartPath& pathDir, const chcore::TSmartPath& pathMask); + +private: + static chcore::TSmartPath PrependPathExtensionIfNeeded(const chcore::TSmartPath& pathInput); + + friend class TLocalFilesystemFind; }; +class TLocalFilesystemFind +{ +public: + ~TLocalFilesystemFind(); + + bool FindNext(CFileInfoPtr& rspFileInfo); + void Close(); + +private: + TLocalFilesystemFind(const chcore::TSmartPath& pathDir, const chcore::TSmartPath& pathMask); + +private: + const chcore::TSmartPath m_pathDir; + const chcore::TSmartPath m_pathMask; + HANDLE m_hFind; + + friend class TLocalFilesystem; +}; #endif Index: src/ch/TSubTaskCopyMove.cpp =================================================================== diff -u -N -re30c2b40bd1b533d8740edc88d80b2fb340f3466 -r1456ff2ae4a98c83f18d20dc253a24f26ddf521d --- src/ch/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision e30c2b40bd1b533d8740edc88d80b2fb340f3466) +++ src/ch/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision 1456ff2ae4a98c83f18d20dc253a24f26ddf521d) @@ -138,7 +138,7 @@ if(bMove && iDstDriveNumber != -1 && iDstDriveNumber == GetDriveNumber(spFileInfo) && GetMove(spFileInfo)) { bool bRetry = true; - if(bRetry && !MoveFile(spFileInfo->GetFullFilePath().ToString(), ccp.pathDstFile.ToString())) + if(bRetry && !TLocalFilesystem::FastMove(spFileInfo->GetFullFilePath(), ccp.pathDstFile)) { dwLastError=GetLastError(); //log @@ -236,7 +236,7 @@ // set a time if(GetTaskPropValue(rTaskDefinition.GetConfiguration())) - TLocalFilesystem::SetFileDirectoryTime(ccp.pathDstFile.ToString(), spFileInfo->GetCreationTime(), spFileInfo->GetLastAccessTime(), spFileInfo->GetLastWriteTime()); // no error checking (but most probably it should be checked) + TLocalFilesystem::SetFileDirectoryTime(ccp.pathDstFile, spFileInfo->GetCreationTime(), spFileInfo->GetLastAccessTime(), spFileInfo->GetLastWriteTime()); // no error checking (but most probably it should be checked) // attributes if(GetTaskPropValue(rTaskDefinition.GetConfiguration())) Index: src/ch/TSubTaskScanDirectory.cpp =================================================================== diff -u -N -re30c2b40bd1b533d8740edc88d80b2fb340f3466 -r1456ff2ae4a98c83f18d20dc253a24f26ddf521d --- src/ch/TSubTaskScanDirectory.cpp (.../TSubTaskScanDirectory.cpp) (revision e30c2b40bd1b533d8740edc88d80b2fb340f3466) +++ src/ch/TSubTaskScanDirectory.cpp (.../TSubTaskScanDirectory.cpp) (revision 1456ff2ae4a98c83f18d20dc253a24f26ddf521d) @@ -218,55 +218,37 @@ TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition(); TWorkerThreadController& rThreadController = GetContext().GetThreadController(); - WIN32_FIND_DATA wfd; - chcore::TSmartPath pathCurrent; +// pathCurrent = pathDirName + chcore::PathFromString(_T("*")); + TLocalFilesystemFind finder = TLocalFilesystem::CreateFinder(pathDirName, chcore::PathFromString(_T("*"))); + CFileInfoPtr spFileInfo(boost::make_shared()); - pathCurrent = pathDirName + chcore::PathFromString(_T("*")); - - // Iterate through dirs & files - HANDLE hFind = FindFirstFile(pathCurrent.ToString(), &wfd); - if(hFind != INVALID_HANDLE_VALUE) + while(finder.FindNext(spFileInfo)) { - do + if(!spFileInfo->IsDirectory()) { - if(!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + if(afFilters.Match(spFileInfo)) { - CFileInfoPtr spFileInfo(boost::make_shared()); - - spFileInfo->Init(pathDirName + chcore::PathFromString(wfd.cFileName), stSrcIndex, &rTaskDefinition.GetSourcePaths(), - wfd.dwFileAttributes, (((ULONGLONG) wfd.nFileSizeHigh) << 32) + wfd.nFileSizeLow, wfd.ftCreationTime, - wfd.ftLastAccessTime, wfd.ftLastWriteTime, 0); - - if(afFilters.Match(spFileInfo)) - rFilesCache.AddFileInfo(spFileInfo); + spFileInfo->SetParentObject(stSrcIndex, &rTaskDefinition.GetSourcePaths()); + rFilesCache.AddFileInfo(spFileInfo); + spFileInfo = boost::make_shared(); } - else if(wfd.cFileName[0] != _T('.') || (wfd.cFileName[1] != _T('\0') && (wfd.cFileName[1] != _T('.') || wfd.cFileName[2] != _T('\0')))) + } + else + { + chcore::TSmartPath pathCurrent = spFileInfo->GetFullFilePath(); + if(bIncludeDirs) { - if(bIncludeDirs) - { - CFileInfoPtr spFileInfo(boost::make_shared()); - - // Add directory itself - spFileInfo->Init(pathDirName + chcore::PathFromString(wfd.cFileName), stSrcIndex, &rTaskDefinition.GetSourcePaths(), - wfd.dwFileAttributes, (((ULONGLONG) wfd.nFileSizeHigh) << 32) + wfd.nFileSizeLow, wfd.ftCreationTime, - wfd.ftLastAccessTime, wfd.ftLastWriteTime, 0); - - rFilesCache.AddFileInfo(spFileInfo); - } - if(bRecurse) - { - pathCurrent = pathDirName + chcore::PathFromString(wfd.cFileName) + chcore::PathFromString(_T("\\")); - // Recurse Dirs - ScanDirectory(pathCurrent, stSrcIndex, bRecurse, bIncludeDirs, afFilters); - } + spFileInfo->SetParentObject(stSrcIndex, &rTaskDefinition.GetSourcePaths()); + rFilesCache.AddFileInfo(spFileInfo); + spFileInfo = boost::make_shared(); } - if(rThreadController.KillRequested()) - break; + if(bRecurse) + ScanDirectory(pathCurrent, stSrcIndex, bRecurse, bIncludeDirs, afFilters); } - while(FindNextFile(hFind, &wfd)); - FindClose(hFind); + if(rThreadController.KillRequested()) + break; } return 0;