From e653e8305891535e898511e78a3e5187f4893385 Mon Sep 17 00:00:00 2001 From: Brian Cox Date: Tue, 11 Apr 2017 21:23:25 -0700 Subject: [PATCH] Expanded exception handling for file operations during a check, plus some refactoring & cleanup --- src/fs/fsdatasourceiter.cpp | 67 ++++--- src/fs/fsdatasourceiter.h | 9 +- src/fs/fserrors.cpp | 2 +- src/fs/fspropcalc.cpp | 363 ++++++++++++++++++++---------------- src/fs/fspropcalc.h | 16 +- 5 files changed, 271 insertions(+), 186 deletions(-) diff --git a/src/fs/fsdatasourceiter.cpp b/src/fs/fsdatasourceiter.cpp index 7308621..c63cc91 100644 --- a/src/fs/fsdatasourceiter.cpp +++ b/src/fs/fsdatasourceiter.cpp @@ -42,7 +42,6 @@ #include "fsdatasourceiter.h" #include "fco/fcodatasourceiter.h" #include "fsobject.h" -#include "core/fsservices.h" #include "core/errorbucket.h" #include "core/corestrings.h" #include "core/usernotify.h" @@ -99,6 +98,12 @@ static bool gCrossFileSystems = false; gCrossFileSystems = crossFS; } +void cFSDataSourceIter::AddIterationError(const eError& e) +{ + if(mpErrorBucket) + mpErrorBucket->AddError(e); +} + /////////////////////////////////////////////////////////////////////////////// // CreateCopy /////////////////////////////////////////////////////////////////////////////// @@ -151,15 +156,42 @@ void cFSDataSourceIter::GetChildrenNames( const TSTRING& strParentName, std::vec } catch( eError& e ) { - cDebug d("cFSDataSourceIter::GeneratePeers"); - d.TraceError("**** ReadDir failed for %s\n", strParentName.c_str() ); - - if( mpErrorBucket ) - { - eFSDataSourceIterReadDir eReadDir(e.GetMsg(), eError::NON_FATAL); - mpErrorBucket->AddError( eReadDir ); - } + AddIterationError( eFSDataSourceIterReadDir( strParentName, e.GetMsg(), eError::NON_FATAL) ); } + catch( std::exception& e ) + { + AddIterationError( eFSDataSourceIterReadDir( strParentName, e.what(), eError::NON_FATAL) ); + } + catch(...) + { + AddIterationError( eFSDataSourceIterReadDir( strParentName, "unknown", eError::NON_FATAL) ); + } +} + +bool cFSDataSourceIter::DoStat( const TSTRING& name, cFSStatArgs& statArgs ) +{ + try + { + iFSServices::GetInstance()->Stat( name, statArgs); + } + catch(eError& e) + { + e.SetFatality(false); + AddIterationError(e); + return false; + } + catch(std::exception& e) + { + AddIterationError( eFSDataSourceIter( name, e.what(), eError::NON_FATAL) ); + return false; + } + catch(...) + { + AddIterationError( eFSDataSourceIter( name, "unknown", eError::NON_FATAL) ); + return false; + } + + return true; } /////////////////////////////////////////////////////////////////////////////// @@ -173,30 +205,15 @@ bool cFSDataSourceIter::InitializeTypeInfo(iFCO* pFCO) if( pObj->GetFSPropSet().GetValidVector().ContainsItem( cFSPropSet::PROP_FILETYPE) ) return true; - // // assume invalid by default... // cFSPropSet& propSet = pObj->GetFSPropSet(); propSet.SetFileType(cFSPropSet::FT_INVALID); cFSStatArgs statArgs; - try - { - iFSServices::GetInstance()->Stat( pTrans->ToStringAPI( pObj->GetName() ), statArgs); - } - catch(eError& e) - { - cDebug d("CreateObject"); - d.TraceError( "*** Stat of %s failed!!!\n", pObj->GetName().AsString().c_str() ); - if( mpErrorBucket ) - { - e.SetFatality( false ); - mpErrorBucket->AddError( e ); - } + if( !DoStat( pObj->GetName().AsString(), statArgs )) return false; - } - // // don't create the object if it is on a different file system... // if( gCrossFileSystems == false && (mDev != 0) && (statArgs.dev != mDev) ) diff --git a/src/fs/fsdatasourceiter.h b/src/fs/fsdatasourceiter.h index b4f0eee..e97bc58 100644 --- a/src/fs/fsdatasourceiter.h +++ b/src/fs/fsdatasourceiter.h @@ -39,9 +39,11 @@ // INCLUDES //========================================================================= #include "fco/fcodatasourceiterimpl.h" +#include "core/fileerror.h" +#include "core/fsservices.h" -TSS_EXCEPTION( eFSDataSourceIter, eError ) -TSS_EXCEPTION( eFSDataSourceIterReadDir, eFSDataSourceIter ) +TSS_FILE_EXCEPTION( eFSDataSourceIter, eFileError ) +TSS_FILE_EXCEPTION( eFSDataSourceIterReadDir, eFSDataSourceIter ) //========================================================================= @@ -83,6 +85,9 @@ private: virtual iFCO* CreateObject(const cFCOName& name, bool bCreatingPeers ); virtual bool InitializeTypeInfo(iFCO* pFCO) ; + + void AddIterationError(const eError& e); + bool DoStat(const TSTRING& name, cFSStatArgs& statArgs); }; #endif //__FSDATASOURCEITER_H diff --git a/src/fs/fserrors.cpp b/src/fs/fserrors.cpp index e494057..d5c2e2a 100644 --- a/src/fs/fserrors.cpp +++ b/src/fs/fserrors.cpp @@ -43,7 +43,7 @@ TSS_BEGIN_ERROR_REGISTRATION( fs ) -TSS_REGISTER_ERROR( eFSPropCalc(), _T("NTFS property calculation error.") ) +TSS_REGISTER_ERROR( eFSPropCalc(), _T("Property calculation error.") ) //TSS_REGISTER_ERROR( eFSPropCalcResetAccessTime(), _T("Could not reset access time for file.") ) TSS_REGISTER_ERROR( eFSDataSourceIter(), _T("Data source iterator error.") ) TSS_REGISTER_ERROR( eFSDataSourceIterReadDir(), _T("Could not access directory contents.") ) diff --git a/src/fs/fspropcalc.cpp b/src/fs/fspropcalc.cpp index f575bfd..ad4063a 100644 --- a/src/fs/fspropcalc.cpp +++ b/src/fs/fspropcalc.cpp @@ -35,13 +35,10 @@ #include "stdfs.h" #include "core/debug.h" #include "core/errorbucket.h" -#include "core/fsservices.h" #include "core/errorbucket.h" #include "fco/fconame.h" #include "fco/fconametranslator.h" #include "fco/twfactory.h" -#include "core/archive.h" - #include "fspropcalc.h" #include "fsobject.h" @@ -88,17 +85,15 @@ static bool NeedsStat(const cFCOPropVector& v) /////////////////////////////////////////////////////////////////////////////// -static bool GetSymLinkStr(const cFCOName& fileName, cArchive& arch) +static bool GetSymLinkStr(const TSTRING& strName, cArchive& arch) { - char buf[1024]; + char buf[1024]; // TODO: is this big enough? #if defined(O_PATH) - int fd = open(iTWFactory::GetInstance()->GetNameTranslator()->ToStringAPI( fileName ).c_str(), - (O_PATH | O_NOFOLLOW | O_NOATIME)); + int fd = open(strName.c_str(), (O_PATH | O_NOFOLLOW | O_NOATIME)); int rtn = readlinkat(fd, 0, buf, 1024); close(fd); #else - int rtn = readlink( iTWFactory::GetInstance()->GetNameTranslator()->ToStringAPI( fileName ).c_str(), - buf, 1024 ); + int rtn = readlink( strName.c_str(), buf, 1024 ); #endif if(rtn == -1) @@ -110,127 +105,154 @@ static bool GetSymLinkStr(const cFCOName& fileName, cArchive& arch) return true; } - -/////////////////////////////////////////////////////////////////////////////// -// VisitFSObject -- this is the workhorse method that actually fills out the -// passed in FSObject' properties -/////////////////////////////////////////////////////////////////////////////// -void cFSPropCalc::VisitFSObject(cFSObject& obj) +void cFSPropCalc::AddPropCalcError(const eError& e) { - cDebug d("cFSPropCalc::VisitFSObject"); - d.TraceDetail(_T("Visiting %s\n"), obj.GetName().AsString().c_str()); + if(mpErrorBucket) + mpErrorBucket->AddError(e); +} - // if we are not in overwrite mode, we need to alter the - // properties we are calculating... - cFCOPropVector propsToCheck(mPropVector); - if(mCollAction == iFCOPropCalc::PROP_LEAVE) - { - cFCOPropVector inBoth = propsToCheck; - inBoth &= obj.GetPropSet()->GetValidVector(); - propsToCheck ^= inBoth; - } - -#ifdef _DEBUG - d.TraceDetail("----->Collision Action = %s\n", mCollAction == iFCOPropCalc::PROP_LEAVE ? "Leave" : "Replace"); - d.TraceDetail("----->Object's valid properties (a):\n"); - obj.GetPropSet()->GetValidVector().TraceContents(cDebug::D_DETAIL); - d.TraceDetail("----->Properties to calculate: (b)\n"); - mPropVector.TraceContents(cDebug::D_DETAIL); - d.TraceDetail("----->Properties to change in object ((a&b)^b for Leave or b for Replace):\n"); - propsToCheck.TraceContents(cDebug::D_DETAIL); -#endif //_DEBUG - - // only do the stat() if it is necessary - iFSServices* pFSServices = iFSServices::GetInstance(); - cFSStatArgs ss; - bool bDidStat = false; - TSTRING strName = iTWFactory::GetInstance()->GetNameTranslator()->ToStringAPI( obj.GetName() ); - - // get a reference to the fco's property set - cFSPropSet& propSet = obj.GetFSPropSet(); +bool cFSPropCalc::DoStat( const TSTRING& strName, cFSStatArgs& statArgs ) +{ + cDebug d("cFSPropCalc::DoStat"); - // - // just return if this object is invalid - // - if( propSet.GetFileType() == cFSPropSet::FT_INVALID ) - return; - try { - if( NeedsStat(propsToCheck) ) - { - d.TraceDetail("---Performing Stat()\n"); - pFSServices->Stat(strName, ss); - bDidStat = true; - } + d.TraceDetail("---Performing Stat()\n"); + iFSServices::GetInstance()->Stat(strName, statArgs); } catch(eError& e) { d.TraceError("Error getting stat info for %s : %s\n", strName.c_str(), e.GetMsg().c_str()); - - // add this fco to the error set... - // it is assumed that the file name that the error is associated with is in the exception's - // GetMsg() - e.SetFatality( false ); - if(mpErrorBucket) - mpErrorBucket->AddError( e ); - return; + e.SetFatality(false); + AddPropCalcError(e); + return false; + } + catch(std::exception& e) + { + d.TraceError("Error getting stat info for %s : %s\n", strName.c_str(), e.what()); + AddPropCalcError( eFSPropCalc( strName, e.what(), eError::NON_FATAL ) ); + return false; + } + catch(...) + { + d.TraceError("Unknown error getting stat info for %s\n", strName.c_str()); + AddPropCalcError( eFSPropCalc( strName, "unknown", eError::NON_FATAL ) ); + return false; } - // for now, I will only fill out the stat info indicated in the property vector, - // but in reality, there is no reason not to fill out everything, since we have the - // extra information for free! - if(bDidStat) + return true; +} + +bool cFSPropCalc::DoOpen( const TSTRING& strName, cFileArchive& arch ) +{ + try { - if(propsToCheck.ContainsItem(cFSPropSet::PROP_DEV)) - propSet.SetDev(ss.dev); - - if(propsToCheck.ContainsItem(cFSPropSet::PROP_RDEV)) - propSet.SetRDev(ss.rdev); + arch.OpenRead(strName.c_str(), ((mCalcFlags & iFCOPropCalc::DIRECT_IO) ? + cFileArchive::FA_SCANNING | cFileArchive::FA_DIRECT : + cFileArchive::FA_SCANNING) ); + } + catch (eError&) + { + AddPropCalcError( eArchiveOpen( strName, iFSServices::GetInstance()->GetErrString(), eError::NON_FATAL)); + return false; + } + catch (std::exception& e) + { + AddPropCalcError( eArchiveOpen( strName, e.what(), eError::NON_FATAL ) ); + return false; + } + catch (...) + { + AddPropCalcError( eArchiveOpen( strName, "unknown", eError::NON_FATAL ) ); + return false; + } - if(propsToCheck.ContainsItem(cFSPropSet::PROP_INODE)) - propSet.SetInode(ss.ino); - - if(propsToCheck.ContainsItem(cFSPropSet::PROP_MODE)) - propSet.SetMode(ss.mode); - - if(propsToCheck.ContainsItem(cFSPropSet::PROP_NLINK)) - propSet.SetNLink(ss.nlink); - - if(propsToCheck.ContainsItem(cFSPropSet::PROP_UID)) - propSet.SetUID(ss.uid); - - if(propsToCheck.ContainsItem(cFSPropSet::PROP_GID)) - propSet.SetGID(ss.gid); - - if(propsToCheck.ContainsItem(cFSPropSet::PROP_SIZE)) - propSet.SetSize(ss.size); - - if(propsToCheck.ContainsItem(cFSPropSet::PROP_ATIME)) - propSet.SetAccessTime(ss.atime); - - if(propsToCheck.ContainsItem(cFSPropSet::PROP_MTIME)) - propSet.SetModifyTime(ss.mtime); - - if(propsToCheck.ContainsItem(cFSPropSet::PROP_CTIME)) - propSet.SetCreateTime(ss.ctime); + return true; +} - if(propsToCheck.ContainsItem(cFSPropSet::PROP_BLOCK_SIZE)) - propSet.SetBlockSize(ss.blksize); - - if(propsToCheck.ContainsItem(cFSPropSet::PROP_BLOCKS)) - propSet.SetBlocks(ss.blocks); +bool cFSPropCalc::DoHash( const TSTRING& strName, cBidirArchive* pTheArch, cArchiveSigGen& asg, cFileArchive& arch ) +{ + cDebug d("cFSPropCalc::DoHash"); + try + { + pTheArch->Seek( 0, cBidirArchive::BEGINNING ); + asg.CalculateSignatures( *pTheArch ); + arch.Close(); + } + catch (eError& e) + { + d.TraceError("Error generating hashes for %s : %s\n", strName.c_str(), e.GetMsg().c_str()); + e.SetFatality(false); + AddPropCalcError(e); + return false; + } + catch (std::exception& e) + { + d.TraceError("Error generating hashes for %s : %s\n", strName.c_str(), e.what()); + AddPropCalcError( eArchiveRead( strName, e.what(), eError::NON_FATAL ) ); + return false; + } + catch (...) + { + d.TraceError("Unknown error generating hashes for %s\n", strName.c_str()); + AddPropCalcError( eArchiveRead( strName, "unknown", eError::NON_FATAL ) ); + return false; + } + + return true; +} - if(propsToCheck.ContainsItem(cFSPropSet::PROP_GROWING_FILE)) - propSet.SetGrowingFile(ss.size); +void cFSPropCalc::HandleStatProperties( const cFCOPropVector& propsToCheck, const cFSStatArgs& ss, cFSPropSet& propSet) +{ + if(propsToCheck.ContainsItem(cFSPropSet::PROP_DEV)) + propSet.SetDev(ss.dev); - if(propsToCheck.ContainsItem(cFSPropSet::PROP_FILETYPE)) + if(propsToCheck.ContainsItem(cFSPropSet::PROP_RDEV)) + propSet.SetRDev(ss.rdev); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_INODE)) + propSet.SetInode(ss.ino); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_MODE)) + propSet.SetMode(ss.mode); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_NLINK)) + propSet.SetNLink(ss.nlink); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_UID)) + propSet.SetUID(ss.uid); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_GID)) + propSet.SetGID(ss.gid); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_SIZE)) + propSet.SetSize(ss.size); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_ATIME)) + propSet.SetAccessTime(ss.atime); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_MTIME)) + propSet.SetModifyTime(ss.mtime); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_CTIME)) + propSet.SetCreateTime(ss.ctime); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_BLOCK_SIZE)) + propSet.SetBlockSize(ss.blksize); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_BLOCKS)) + propSet.SetBlocks(ss.blocks); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_GROWING_FILE)) + propSet.SetGrowingFile(ss.size); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_FILETYPE)) + { + // TODO -- It _really_ bites duplicating code here and in fsdatasource.cpp + // *** This _has_ to be remedied somehow! + // set the file type + switch(ss.mFileType) { - // TODO -- It _really_ bites duplicating code here and in fsdatasource.cpp - // *** This _has_ to be remedied somehow! - // set the file type - switch(ss.mFileType) - { case cFSStatArgs::TY_FILE: propSet.SetFileType(cFSPropSet::FT_FILE); break; @@ -261,10 +283,12 @@ void cFSPropCalc::VisitFSObject(cFSObject& obj) default: // set it to invalid propSet.SetFileType(cFSPropSet::FT_INVALID); - } - } + } } +} +void cFSPropCalc::HandleHashes( const cFCOPropVector& propsToCheck, const TSTRING& strName, cFSPropSet& propSet) +{ bool hash_success = false; // if the file type is not a regular file, we will @@ -273,45 +297,31 @@ void cFSPropCalc::VisitFSObject(cFSObject& obj) if( propSet.GetFileType() == cFSPropSet::FT_FILE || propSet.GetFileType() == cFSPropSet::FT_SYMLINK ) { if( // if we need to open the file - propsToCheck.ContainsItem(cFSPropSet::PROP_CRC32) || - propsToCheck.ContainsItem(cFSPropSet::PROP_MD5) || - propsToCheck.ContainsItem(cFSPropSet::PROP_SHA) || - propsToCheck.ContainsItem(cFSPropSet::PROP_HAVAL) - ) + propsToCheck.ContainsItem(cFSPropSet::PROP_CRC32) || + propsToCheck.ContainsItem(cFSPropSet::PROP_MD5) || + propsToCheck.ContainsItem(cFSPropSet::PROP_SHA) || + propsToCheck.ContainsItem(cFSPropSet::PROP_HAVAL) + ) { cFileArchive arch; cMemoryArchive memArch; - cBidirArchive* pTheArch; + cBidirArchive* pTheArch; hash_success = true; if(propSet.GetFileType() == cFSPropSet::FT_SYMLINK) { pTheArch = &memArch; - if(! GetSymLinkStr(obj.GetName(), memArch)) + if(! GetSymLinkStr(strName, memArch)) { // add it to the bucket... - if(mpErrorBucket) - mpErrorBucket->AddError( eArchiveOpen( strName, iFSServices::GetInstance()->GetErrString(), eError::NON_FATAL ) ); + AddPropCalcError( eArchiveOpen( strName, iFSServices::GetInstance()->GetErrString(), eError::NON_FATAL ) ); hash_success = false; } - } else { pTheArch = &arch; - try - { - arch.OpenRead(strName.c_str(), ((mCalcFlags & iFCOPropCalc::DIRECT_IO) ? - cFileArchive::FA_SCANNING | cFileArchive::FA_DIRECT : - cFileArchive::FA_SCANNING) ); - } - catch (eError&) - { - // add it to the bucket... - if(mpErrorBucket) - mpErrorBucket->AddError( eArchiveOpen( strName, iFSServices::GetInstance()->GetErrString(), eError::NON_FATAL ) ); - hash_success = false; - } + hash_success = DoOpen(strName, arch); } // @@ -326,43 +336,29 @@ void cFSPropCalc::VisitFSObject(cFSObject& obj) propSet.SetDefinedCRC32(true); asg.AddSig( propSet.GetCRC32() ); } - + if(propsToCheck.ContainsItem(cFSPropSet::PROP_MD5)) { propSet.SetDefinedMD5(true); asg.AddSig( propSet.GetMD5() ); } - + if(propsToCheck.ContainsItem(cFSPropSet::PROP_SHA)) { propSet.SetDefinedSHA(true); asg.AddSig( propSet.GetSHA() ); } - + if(propsToCheck.ContainsItem(cFSPropSet::PROP_HAVAL)) { propSet.SetDefinedHAVAL(true); asg.AddSig( propSet.GetHAVAL() ); } - + // // calculate the signatures // - try - { - pTheArch->Seek( 0, cBidirArchive::BEGINNING ); - asg.CalculateSignatures( *pTheArch ); - arch.Close(); - } - catch (eError& e) - { - d.TraceError("Error generating hashes for %s : %s\n", strName.c_str(), e.GetMsg().c_str()); - - e.SetFatality(false); - if(mpErrorBucket) - mpErrorBucket->AddError(e); - hash_success = false; - } + hash_success = DoHash(strName, pTheArch, asg, arch); } } } @@ -384,6 +380,59 @@ void cFSPropCalc::VisitFSObject(cFSObject& obj) } } +/////////////////////////////////////////////////////////////////////////////// +// VisitFSObject -- this is the workhorse method that actually fills out the +// passed in FSObject' properties +/////////////////////////////////////////////////////////////////////////////// +void cFSPropCalc::VisitFSObject(cFSObject& obj) +{ + cDebug d("cFSPropCalc::VisitFSObject"); + d.TraceDetail(_T("Visiting %s\n"), obj.GetName().AsString().c_str()); + + // if we are not in overwrite mode, we need to alter the + // properties we are calculating... + cFCOPropVector propsToCheck(mPropVector); + if(mCollAction == iFCOPropCalc::PROP_LEAVE) + { + cFCOPropVector inBoth = propsToCheck; + inBoth &= obj.GetPropSet()->GetValidVector(); + propsToCheck ^= inBoth; + } + +#ifdef _DEBUG + d.TraceDetail("----->Collision Action = %s\n", mCollAction == iFCOPropCalc::PROP_LEAVE ? "Leave" : "Replace"); + d.TraceDetail("----->Object's valid properties (a):\n"); + obj.GetPropSet()->GetValidVector().TraceContents(cDebug::D_DETAIL); + d.TraceDetail("----->Properties to calculate: (b)\n"); + mPropVector.TraceContents(cDebug::D_DETAIL); + d.TraceDetail("----->Properties to change in object ((a&b)^b for Leave or b for Replace):\n"); + propsToCheck.TraceContents(cDebug::D_DETAIL); +#endif //_DEBUG + + // only do the stat() if it is necessary + cFSStatArgs ss; + TSTRING strName = iTWFactory::GetInstance()->GetNameTranslator()->ToStringAPI( obj.GetName() ); + + // get a reference to the fco's property set + cFSPropSet& propSet = obj.GetFSPropSet(); + + // + // just return if this object is invalid + // + if( propSet.GetFileType() == cFSPropSet::FT_INVALID ) + return; + + if( NeedsStat(propsToCheck) ) + { + if (!DoStat(strName, ss)) + return; + + HandleStatProperties(propsToCheck, ss, propSet); + } + + HandleHashes(propsToCheck, strName, propSet); +} + void cFSPropCalc::SetPropVector(const cFCOPropVector& pv) { mPropVector = pv; diff --git a/src/fs/fspropcalc.h b/src/fs/fspropcalc.h index 53a1eae..85afa41 100644 --- a/src/fs/fspropcalc.h +++ b/src/fs/fspropcalc.h @@ -47,7 +47,13 @@ #include "fco/fcopropvector.h" #endif -TSS_EXCEPTION( eFSPropCalc, eError ) +#include "fco/signature.h" +#include "core/fileerror.h" +#include "core/fsservices.h" +#include "core/archive.h" +#include "fspropset.h" + +TSS_FILE_EXCEPTION( eFSPropCalc, eFileError ) //TSS_EXCEPTION( eFSPropCalcResetAccessTime, eFSPropCalc ) // this was never used class cFSPropCalc : public iFCOPropCalc, public iFSVisitor @@ -78,6 +84,14 @@ private: cFSPropCalc( const cFSPropCalc& ); void operator =( const cFSPropCalc& ); + void AddPropCalcError(const eError& e); + + bool DoStat(const TSTRING& name, cFSStatArgs& statArgs); + bool DoOpen(const TSTRING& name, cFileArchive& arch); + bool DoHash( const TSTRING& name, cBidirArchive* pTheArch, cArchiveSigGen& asg, cFileArchive& arch ); + void HandleStatProperties( const cFCOPropVector& propsToCheck, const cFSStatArgs& ss, cFSPropSet& propSet); + void HandleHashes( const cFCOPropVector& propsToCheck, const TSTRING& strName, cFSPropSet& propSet); + cFCOPropVector mPropVector; iFCOPropCalc::CollisionAction mCollAction; int mCalcFlags;