userlibandfileserver/fileserver/sfat32/sl_mnt.cpp
changeset 36 538db54a451d
parent 33 0173bcd7697c
child 62 4a8fed1c0ef6
child 90 947f0dc9f7a8
--- 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();
-        clustersForFileSize = (TInt) ( (TInt64(anEntry.Size()) + TInt64(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)
-        {
-        cluster=NextUnvisitedCluster(aFatBitVec, cluster); //-- move to the next unvisited cluster
-        if(cluster < 0 || 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.