diff -r f497542af8e4 -r 538db54a451d userlibandfileserver/fileserver/sfat32/sl_mnt.cpp --- a/userlibandfileserver/fileserver/sfat32/sl_mnt.cpp Tue Jan 19 13:48:03 2010 +0000 +++ b/userlibandfileserver/fileserver/sfat32/sl_mnt.cpp Mon Jan 18 21:31:10 2010 +0200 @@ -29,9 +29,6 @@ TShortName DoGenerateShortNameL(const TDesC& aLongName,TInt& aNum,TBool aUseTildeSelectively); -static void MarkClusterVisited(RBitVector& aFatBitVec, TUint32 aCluster); -static TBool IsClusterVisited(const RBitVector& aFatBitVec, TUint32 aCluster); -static TInt NextUnvisitedCluster(const RBitVector& aFatBitVec, TUint32 aCluster); //----------------------------------------------------------------------------------------- @@ -2507,7 +2504,8 @@ //-- while directory cache pages are. For FAT32 it doesn't matter, because root dir is a usual file. //-- the "rummage dir. cache" can be swithed off. This is not affecting the functionality, only the performance. - #if 1 + #ifdef USE_DIR_CACHE_RUMMAGE + if(iRawDisk->DirCacheInterface() && trgNameFullySpecified && !IsRootDir(aDosEntryPos) && !aFileCreationHelper) {//-- aName is fully specified, i.e doesn't contain wildcards @@ -4122,10 +4120,12 @@ TRAPD(err,GetDosEntryFromNameL(aName,dosEntryPos,dosEntry)); if(err!=KErrNone) return err; + TInt startCluster=StartCluster(dosEntry); // Empty files will return a cluster of zero if(startCluster==0) return KErrEof; + aUniqueId=MAKE_TINT64(0,startCluster); return KErrNone; } @@ -4149,154 +4149,10 @@ //----------------------------------------------------------------------------------------- -//-- maximal level of recursion for the CheckDisk. i.e. the max. number of folded directories to check. -const TInt KCheckDskMaxRecursionLevel = 50; - -// -// Walks a directory cluster list then checks all the entries. -// -void CFatMountCB::ChkDirL(RBitVector& aFatBitVec, TInt aDirCluster) - { - //__PRINT1(_L("### CFatMountCB::ChkDirL() level:%d"),iChkDiscRecLevel); - - //-- check if we have reached the recursion limit. on hardware the stack is very limited - //-- and its overflow will lead to crash. - if(iChkDiscRecLevel++ >= KCheckDskMaxRecursionLevel) - { - __PRINT1(_L("CFatMountCB::ChkDirL() max recursion level(%d) reached. Leaving!"),iChkDiscRecLevel); - User::Leave(KErrTooBig); - } - - if(/*Is32BitFat() &&*/aDirCluster != 0 && (aDirCluster == RootIndicator()))//the bit in comments maybe required - WalkClusterListL(aFatBitVec, RootIndicator()); - - TEntryPos entryPos(aDirCluster,0); - FOREVER - { - TFatDirEntry entry; - ReadDirEntryL(entryPos,entry); - MoveToDosEntryL(entryPos,entry); - if (entry.IsEndOfDirectory()) - break; - if (IsRootDir(entryPos)&&(StartOfRootDirInBytes()+entryPos.iPos==(RootDirEnd()-KSizeOfFatDirEntry))) - { - if(!entry.IsErased()) - ChkEntryL(aFatBitVec, entry); - break; // Allows maximum number of entries in root directory - } - MoveToNextEntryL(entryPos); - if (entry.IsParentDirectory() || entry.IsCurrentDirectory() || entry.IsErased()) - continue; - ChkEntryL(aFatBitVec, entry); - } - - iChkDiscRecLevel--; - } - -//----------------------------------------------------------------------------------------- - -// -// Check FAT is valid for anEntry -// -void CFatMountCB::ChkEntryL(RBitVector& aFatBitVec, const TFatDirEntry& anEntry) - { - TInt listLength=0; - - if ((anEntry.Attributes()&(KEntryAttDir)) || anEntry.Size()) - listLength=WalkClusterListL(aFatBitVec, StartCluster(anEntry)); - else if (anEntry.StartCluster() != 0) // zero length file - User::Leave(EFatChkDskInvalidEntrySize); // shouldn't have clusters - - if (anEntry.Attributes()&KEntryAttDir) - ChkDirL(aFatBitVec, StartCluster(anEntry)); - - // Check that the correct number of clusters have been allocated for the size of the file. - - else if ((anEntry.Attributes()&KEntryAttVolume)==0) - { - TInt clustersForFileSize; - TInt clusterSize=1<> ClusterSizeLog2() ); - - if (listLength!=clustersForFileSize) - User::Leave(EFatChkDskInvalidEntrySize); - } - } - -//----------------------------------------------------------------------------------------- - -// -// Walks cluster list from aCluster to EOF -// Reports an error if an invalid cluster is found before EOF or -// a cluster has been visited before. -// -TInt CFatMountCB::WalkClusterListL(RBitVector& aFatBitVec, TInt aCluster) - { - - TInt i=0; - do { - i++; - if (!ValidClusterNumber(aCluster)) - { - __PRINT1(_L("Bad Cluster number %d"),aCluster); - User::Leave(EFatChkDskIllegalClusterNumber); - } - - if (IsClusterVisited(aFatBitVec, aCluster)) - { - __PRINT1(_L("Cluster already in use %d"),aCluster); - User::Leave(EFatChkDskClusterAlreadyInUse); - } - - MarkClusterVisited(aFatBitVec, aCluster); - - } while (FAT().GetNextClusterL(aCluster)); - - return(i); - } - -//----------------------------------------------------------------------------------------- - -// -// Checks that all unvisited clusters are marked as free in the FAT -// -void CFatMountCB::CheckUnvisitedClustersL(const RBitVector& aFatBitVec) const - { - - TInt cluster=2; - TInt maxCluster=cluster + UsableClusters(); - while (cluster= maxCluster) - break; - - TInt clusterVal=FAT().ReadL(cluster); - if (clusterVal!=0 && IsEndOfClusterCh(clusterVal)==EFalse && !IsBadCluster(clusterVal)) - { - __PRINT1(_L("\n*****Bad cluster Num = %d"),cluster); - User::Leave(EFatChkDskBadCluster); - } - } - } - -//----------------------------------------------------------------------------------------- - -/** -@param aCluster cluster number to check for validity -@returns ETrue if aCluster is a valid cluster number +/** + Check file system for errors. + @return KErrNone if no errors found, otherwise a error code hopefully describing the problem found. */ -TBool CFatMountCB::ValidClusterNumber(TUint32 aCluster) const - { - return (aCluster>=KFatFirstSearchCluster && aCluster<=MaxClusterNumber()); - } - -//----------------------------------------------------------------------------------------- - -// -// Walk the FAT, returns error if find an unterminated list or -// lists that merge. -// TInt CFatMountCB::CheckDisk() { @@ -4307,10 +4163,6 @@ //-- create a bit representation of the FAT const TUint32 MaxClusters = UsableClusters()+KFatFirstSearchCluster; //-- UsableClusters() doesn't count first 2 unused clusers - - - // cluster count may be zero if boot sector failed to be read (e.g. if the media is locked) - // or if TDrive::MountMedia(ETrue) has been called (in which case the boot sector may if (MaxClusters == 0) return KErrCorrupt; @@ -4319,115 +4171,42 @@ TTime timeEnd; timeStart.UniversalTime(); //-- take start time - - RBitVector bitVec; //-- each bit in this vector represents a FAT cluster - - TInt nRes = bitVec.Create(MaxClusters); + TInt nRes; + + CScanDrive* pScnDrv = NULL; + TRAP(nRes, pScnDrv=CScanDrive::NewL(this)); if(nRes != KErrNone) - { - ASSERT(nRes == KErrNoMemory); //-- the only one possible reason. - return KErrNoMemory; - } - - iChkDiscRecLevel = 0; //-- reset CheckDisk recursion counter - TRAPD(r,ChkDirL(bitVec, RootIndicator())); // Check from root directory - if (r==KErrNone) - { - TRAP(r,CheckUnvisitedClustersL(bitVec)); - } - - - bitVec.Close(); - + return nRes; + + //-- start ScanDrive in "checkdisk" mode + TRAPD(nScnDrvRes, pScnDrv->StartL(CScanDrive::ECheckDisk)); + timeEnd.UniversalTime(); //-- take end time const TInt msScanTime = (TInt)( (timeEnd.MicroSecondsFrom(timeStart)).Int64() / K1mSec); (void)msScanTime; - __PRINT1(_L("#@@@ CheckDisk() time taken:%d ms"), msScanTime); - - - switch(r) + + CScanDrive::TGenericError chkDskRes = pScnDrv->ProblemsDiscovered(); + const TBool bProblemsFound = (nScnDrvRes!=KErrNone) || pScnDrv->ProblemsDiscovered(); + + if(bProblemsFound && chkDskRes == CScanDrive::ENoErrors) + {//-- ScanDrive in this mode can leave unexpectedly without setting an error code that is returned by ProblemsDiscovered(); + //-- leave itself means a problem + chkDskRes = CScanDrive::EUnknownError; + } + + delete pScnDrv; + + if(chkDskRes != KErrNone) { - - case KErrNone: - return KErrNone; - - case EFatChkDskIllegalClusterNumber: - return(1); - - case EFatChkDskClusterAlreadyInUse: - return(2); - - case EFatChkDskBadCluster: - return(3); - - case EFatChkDskInvalidEntrySize: - return(4); - - default: - break; + __PRINT2(_L("CFatMountCB::CheckDisk() drv:%d, result:%d"), DriveNumber(), chkDskRes); } - - return(r); + + return chkDskRes; + } -//----------------------------------------------------------------------------------------- -// Helper functions for Check Disk functionality -//----------------------------------------------------------------------------------------- - -/** - Find the next unvisited cluster number in the bit array. - - @param aBitList bit array, where '0' bits represent unvisited clusters. - @param aCluster cluster number to start search with. - - @return positive integer indicating next unvisited cluster number - KErrNotFound (-1) if there are no unvisited clusters - -*/ -static TInt NextUnvisitedCluster(const RBitVector& aFatBitVec, TUint32 aCluster) -{ - __ASSERT_DEBUG(aCluster >= KFatFirstSearchCluster, Fault(EFatChkDskIllegalClusterNumber)); //-- 1st 2 FAT entries are reserved - - TUint32 searchPos = aCluster; //-- bit number to start search with - - //-- look for the unvisited cluster (bit '0') in the bit array from the searchPos to the right - if(aFatBitVec.Find(searchPos, 0, RBitVector::ERight)) - return searchPos; - - return KErrNotFound; -} - - -/** - Check if we have visited cluster aCluster - - @param aFatBitVec bit array, where '0' bits represent unvisited clusters. - @param aCluster cluster number to check - @return ETrue if aCluster has been visited. -*/ -static TBool IsClusterVisited(const RBitVector& aFatBitVec, TUint32 aCluster) -{ - __ASSERT_DEBUG(aCluster >= KFatFirstSearchCluster, Fault(EFatChkDskIllegalClusterNumber)); //-- 1st 2 FAT entries are reserved - - return aFatBitVec[aCluster]; -} - -/** - Mark aCluster as visited - @param aFatBitVec bit array, where '0' bits represent unvisited clusters. - @param aCluster cluster number to mark -*/ -static void MarkClusterVisited(RBitVector& aFatBitVec, TUint32 aCluster) -{ - __ASSERT_DEBUG(aCluster >= KFatFirstSearchCluster, Fault(EFatChkDskIllegalClusterNumber)); //-- 1st 2 FAT entries are reserved - - aFatBitVec.SetBit(aCluster); //-- '1' bit in a bit array means that the corresponding cluster is visited -} - - - //------------------------------------------------------------------------------------------------------------------- /** @@ -4442,7 +4221,7 @@ if(nRes != KErrNone) return nRes; - TRAPD(nScnDrvRes, pScnDrv->StartL()); + TRAPD(nScnDrvRes, pScnDrv->StartL(CScanDrive::EScanAndFix)); const TBool bNeedFatRemount = (nScnDrvRes!=KErrNone) || pScnDrv->ProblemsDiscovered(); delete pScnDrv; @@ -4459,7 +4238,7 @@ return nScnDrvRes; - //-- if ScanDrive hasn't found anything wrong or has fixed recoverable erros, mark the volume clean + //-- if ScanDrive hasn't found anything wrong or has fixed recoverable errors, mark the volume clean if(VolCleanFlagSupported()) { //-- if there is a background FAT scanning thread, we need to wait until it finishes its work.