userlibandfileserver/fileserver/sfat32/sl_scan32.cpp
branchRCL_3
changeset 44 3e88ff8f41d5
parent 43 c1f20ce4abcf
--- a/userlibandfileserver/fileserver/sfat32/sl_scan32.cpp	Tue Aug 31 16:34:26 2010 +0300
+++ b/userlibandfileserver/fileserver/sfat32/sl_scan32.cpp	Wed Sep 01 12:34:56 2010 +0100
@@ -72,11 +72,10 @@
     ASSERT(aMount);
 
     //--- setting up 
-	iMount			 = aMount;
-	iGenericError	 = ENoErrors;
-	iDirError		 = ENoDirError;
-	iHangingClusters = 0;
-	iMaxClusters	 = iMount->UsableClusters()+KFatFirstSearchCluster; //-- UsableClusters() doesn't count first 2 unused clusers
+    iMount=aMount;
+    iGenericError = ENoErrors;
+    iDirError     = ENoDirError;  
+    iMaxClusters  = iMount->UsableClusters()+KFatFirstSearchCluster; //-- UsableClusters() doesn't count first 2 unused clusers
     //------------------------------
 	
     //-- create bit vectors that will represent FAT on media and reconstructed by ScanDrive. Each bit in the vector represents 1 FAT cluster.
@@ -110,7 +109,7 @@
         const TUint32 nFatEntry = ReadFatL(i);
        
         //-- each '1' bit represents a used cluster 
-        if(nFatEntry != KSpareCluster)
+        if(nFatEntry != KSpareCluster) 
             iMediaFatBits.SetBit(i);
 	    }
     }
@@ -126,7 +125,7 @@
     ASSERT((aBuf.Size() & (sizeof(TFat32Entry)-1)) == 0);
     
     const TInt KNumEntries = aBuf.Size() >> KFat32EntrySzLog2;
-    const TFat32Entry* const pFatEntry = (const TFat32Entry*)(aBuf.Ptr());
+    const TFat32Entry* const pFatEntry = (const TFat32Entry*)(aBuf.Ptr()); 
 
     for(TInt i=0; i<KNumEntries; ++i)
         {
@@ -162,11 +161,11 @@
 
     iMediaFatBits.Fill(0);
 
-    RBuf8 fatParseBuf;
-    CleanupClosePushL(fatParseBuf);
+    RBuf8 buf;
+    CleanupClosePushL(buf);
 
     //-- allocate memory for FAT parse buffer
-    fatParseBuf.CreateMaxL(KFatBufSz);
+    buf.CreateMaxL(KFatBufSz);
 
     //-- read FAT directly from the media into the large buffer and parse it
     TUint32 rem = KFatSize;
@@ -176,10 +175,10 @@
     while(rem)
         {
         const TUint32 bytesToRead=Min(rem, KFatBufSz);
-        TPtrC8 ptrData(fatParseBuf.Ptr(), bytesToRead);
+        TPtrC8 ptrData(buf.Ptr(), bytesToRead);
 
         //-- read portion of the FAT into buffer
-        User::LeaveIfError(iMount->LocalDrive()->Read(mediaPos, bytesToRead, fatParseBuf)); 
+        User::LeaveIfError(iMount->LocalDrive()->Read(mediaPos, bytesToRead, buf)); 
 
         //-- parse the buffer and populate bit vector
         DoParseFat32Buf(ptrData, currFatEntry);
@@ -188,8 +187,8 @@
         rem -= bytesToRead;
         }
 
-    fatParseBuf.Close();
-    CleanupStack::PopAndDestroy(&fatParseBuf); 
+    buf.Close();
+    CleanupStack::PopAndDestroy(&buf); 
     }
 
 
@@ -242,7 +241,7 @@
 }
 
 /**
-    Sets the flag indicating that there are errors in filesystem structure
+    Sets the flag indicating than there are errors in filesystem structure
     See ProblemsDiscovered()
 
     @param  aError a code describing the error
@@ -301,6 +300,7 @@
 
 	PrintErrors();
 
+
     timeEnd.UniversalTime(); //-- take end time
     const TInt elapsedTime = (TInt)( (timeEnd.MicroSecondsFrom(timeStart)).Int64() / K1mSec);
     (void)elapsedTime;
@@ -478,7 +478,7 @@
 	{
 	CheckDirL(iMount->RootIndicator());
 	// Due to recursive nature of CheckDirL when a depth of
-	// KMaxScanDepth is reached, clusters are stored in a list
+	// KMaxScanDepth is reached clusters are stored in a list
 	// and passed into CheckDirL afresh
 
 	for(TUint i=0;i<KMaxArrayDepth && iClusterListArray[i]!=NULL;++i)
@@ -518,7 +518,7 @@
 
 	TEntryPos entryPos(aCluster,0);
 	TInt dirEntries=0;
-	for(;;)
+	FOREVER
 		{
 		TFatDirEntry entry;
 		ReadDirEntryL(entryPos,entry);
@@ -660,11 +660,11 @@
 		{
         if(IsClusterUsedL(aCluster))
 			{//-- this cluster already seems to belong to some other object; crosslinked cluster chain. Can't fix it.
-            __PRINT1(_L("CScanDrive::RecordClusterChainL #1 %d"),aCluster); 
+                __PRINT1(_L("CScanDrive::RecordClusterChainL #1 %d"),aCluster); 
             
             if(CheckDiskMode())
-                {//-- in check disk mode this is an FS error; Indicate error and abort further scanning
-                __PRINT(_L("CScanDrive::RecordClusterChainL #1.1"));
+                {//-- in check disk mode this is a FS error; Indicate error and abort furter scanning
+                __PRINT(_L("CScanDrive::RecordClusterChainL #1.1")); 
                 IndicateErrorsFound(EClusterAlreadyInUse);
                 User::Leave(KErrCorrupt);
                 }
@@ -687,26 +687,16 @@
         if(clusterCount==1)
 			{//-- we have reached the end of the cluster chain
 			if(!iMount->IsEndOfClusterCh(ReadFatL(aCluster)))
-				{
-				// According to the directory entry, we have reached the end of the cluster chain,
-				// whereas in the media FAT, it is not.
-				// This is a rugged FAT artefact; hanging cluster chain:
-				// 	A cluster chain which is longer in the FAT table than is recorded in the corresponding directory entry 
-				// 	or not terminated by an EOC entry in FAT.
-				// This is caused by:
-				//  - File truncation failing.
-				//	- OR file expanding failing during flushing to the media FAT.
+				{//-- seems to be a rugged FAT artefact; File truncation/extension had failed before and now file length is less than
+                 //-- the corresponding cluster chain shall be. It will be truncated to the size recorded in file DOS entry.
+				iTruncationCluster = aCluster;								
                 
                 if(CheckDiskMode())
-                    {//-- in check disk mode this is an FS error; Indicate error and abort further scanning
-                    __PRINT1(_L("CScanDrive::RecordClusterChainL #2 Hanging cluster=%d"),aCluster);
+                    {//-- in check disk mode this is a FS error; Indicate error and abort furter scanning
+                    __PRINT1(_L("CScanDrive::RecordClusterChainL #2 %d"),aCluster); 
                     IndicateErrorsFound(EInvalidEntrySize);
                     User::Leave(KErrCorrupt);
                     }
-				
-				// The chain will be truncated to the size recorded in the file's DOS entry and
-				// the remaining lost cluster chain will be fixed later in CompareAndFixFatsL().
-				FixHangingClusterChainL(aCluster);
                 }
 
             //__PRINT1(_L("#--: %d -> EOC"), aCluster); 
@@ -773,8 +763,8 @@
         if(!IsValidVFatEntry(aEntry,toFollow))
 			return(EFalse);
 		}
-	// A sequence of VFat entries must end with a Dos entry to be valid.
-	return(IsDosEntry(aEntry));
+	
+    return(IsDosEntry(aEntry));
 	}
 
 //----------------------------------------------------------------------------------------------------
@@ -855,7 +845,7 @@
 
 //----------------------------------------------------------------------------------------------------
 /**
-    Scan for differences in the new and old FAT table writing them to media if discovered
+    Scan for differnces in the new and old FAT table writing them to media if discovered
     It is supposed to be called in 'ScanDrive' mode only
 
     @leave System wide error codes
@@ -895,10 +885,9 @@
                     continue;
                     }
          
-                //-- Here we found a lost cluster. Its FAT entry will be replaced with KSpareCluster.
-                //-- In the case of multiple lost clusters FAT table will be flushed on media sector basis.
-                //-- It is much faster than flushing FAT after every write and will guarantee
-                //-- that FAT won't be corrupted if the media driver provides atomic sector write. 
+                //-- here we found a lost cluster. Its FAT entry will be replaced with KSpareCluster. In the case of multiple lost clusters FAT table will
+                //-- be flushed on media sector basis. It is much faster than flushing FAT after every write and will
+                //-- guarantee that FAT won't be corrupted if the media driver provides atomic sector write. 
                 if(nClustersFixed == 0)
                     {//-- this is the first lost cluster entry we found
                     
@@ -913,7 +902,7 @@
                     const TUint32 fatSec = iMount->FAT().PosInBytes(i) >> KSectorSzLog2; 
 
                     if(fatSec != dirtyFatSector)
-                        {//-- we are going to write to a different media sector
+                        {//-- we are going to write to a differrent media sector
                         iMount->FAT().FlushL();
                         iMount->FAT().WriteL(i, KSpareCluster); //-- fix lost cluster
                         dirtyFatSector = fatSec;
@@ -939,11 +928,18 @@
     
     //------
 
-	
-	// Add the number of hanging clusters fixed by ScanDrive
-	nClustersFixed += iHangingClusters;
+    if(iTruncationCluster != 0)
+        {
+	    iMount->FAT().WriteFatEntryEofL(iTruncationCluster); 
+		iMount->FAT().FlushL();
+		
+        //-- indicate that there are some problems in FAT. and we probably wrote something there.
+        IndicateErrorsFound(EScanDriveDirError); //-- indicate that we have found errors
+
+        ++nClustersFixed;
+        }
     
-    __PRINT3(_L("CScanDrive::WriteNewFatsL() fixed clusters=%d,hanging clusters=%d,bad clusters=%d"),nClustersFixed,iHangingClusters,nBadClusters);
+    __PRINT2(_L("CScanDrive::WriteNewFatsL() fixed:%d, bad:%d"), nClustersFixed, nBadClusters);
     }
 
 //----------------------------------------------------------------------------------------------------
@@ -1019,28 +1015,6 @@
 
 //----------------------------------------------------------------------------------------------------
 /**
-	Fix a hanging cluster chain.
-	Writes EOF to the corresponding FAT entry, making this cluster chain length correspond to the 
-	real file size recorded in the directory entry.
-	The remainder of the chain will be cleaned up later in CompareAndFixFatsL().
-	
-	@leave	System wide error code
-*/
-void CScanDrive::FixHangingClusterChainL(TUint32 aFatEofIndex)
-	{
-	__PRINT1(_L("CScanDrive::FixHangingClusterL() Hanging cluster=%d"), aFatEofIndex);
-	
-	iMount->FAT().WriteFatEntryEofL(aFatEofIndex);
-	iMount->FAT().FlushL();
-	iHangingClusters++;
-	
-	// Indicate that we have found an error
-	IndicateErrorsFound(EScanDriveDirError);
-	}
-
-
-//----------------------------------------------------------------------------------------------------
-/**
     Move past specified number of entries
 
     @param aEntryPos Start position to move from, updated as move takes place
@@ -1113,26 +1087,35 @@
 		if(BoolXOR(bRealFatEntry, bNewFatEntry))
 		    {//-- mismatch between FAT on the media and the FAT bitmap restored by walking directory structure
 
-			if(bRealFatEntry)
-				{//-- FAT[i] on the media is marked as occupied, but restored FAT bitmap shows that it is free
-				if(iMount->IsBadCluster(ReadFatL(i)))
-					continue; //-- this is a BAD cluster it can't be occupied by the FS object, OK.
+			    if(bRealFatEntry)
+                {//-- FAT[i] on the media is marked as occupied, but retored FAT bitmap shows that it is free
+                    if(iMount->IsBadCluster(ReadFatL(i)))
+                        continue; //-- this is a BAD cluster it can't be occupied by the FS object, OK.
 
-				__PRINT2(_L("FAT[%d] = %d\n"), i, ReadFatL(i));
-				
-				//-- this is a Rugged FAT artefact; a lost cluster
-				__PRINT1(_L("Lost cluster=%d\n"),i);
-				
-				IndicateErrorsFound(EBadClusterValue);
-				}
-			else
-				{//-- FAT[i] on the media is marked as free, but restored FAT bitmap shows that it is occupied by some object
-				IndicateErrorsFound(EClusterAlreadyInUse);
-				__PRINT1(_L("Unflushed cluster = %d\n"),i);
-				}
+                    __PRINT2(_L("FAT[%d] = %d\n"), i, ReadFatL(i));        
+                    __PRINT1(_L("iTruncationCluster = %d\n"), iTruncationCluster);        
+                    
+                    //-- this is a lost cluster
+                    if(!IsEofF(ReadFatL(i)) && (i==iTruncationCluster))
+                        {//-- seems to be a Rugged FAT ertefact
+                        __PRINT1(_L("Hanging cluster = %d\n"),i);        
+                        }
+                    else
+                        {
+                        __PRINT1(_L("Lost cluster=%d\n"),i);
+                        }
+                    
+                    
+                    IndicateErrorsFound(EBadClusterValue);
+                }
+                else
+                {//-- FAT[i] on the media is marked as free, but retored FAT bitmap shows that it is occupied by some object
+                    IndicateErrorsFound(EClusterAlreadyInUse);
+                    __PRINT1(_L("Unflushed cluster = %d\n"),i);
+                }
 
-		 if(aStopOnFirstErrorFound)
-			 break; //-- not asked to check for errors further
+             if(aStopOnFirstErrorFound)
+                 break; //-- not asked to check for errors further
 
             }
 		
@@ -1204,13 +1187,13 @@
 	}	
 
 /**
-    Read a cluster from the Media Fat if scan run in a separate thread read from scan Fat table
+    Read a cluster from the Media Fat if scan run in a seperate thread read from scan fat table
     otherwise read from mount owned Fat table
 
     @param aClusterNum Cluster to read
     @return Value of cluster read from Fat
 */
-TUint32 CScanDrive::ReadFatL(TUint aClusterNum)
+TUint32 CScanDrive::ReadFatL(TUint aClusterNum) 
 	{
 	if(aClusterNum < KFatFirstSearchCluster || aClusterNum >= MaxClusters())
         {