userlibandfileserver/fileserver/sfat32/sl_scan32.cpp
branchRCL_3
changeset 87 2f92ad2dc5db
parent 36 538db54a451d
child 256 c1f20ce4abcf
--- a/userlibandfileserver/fileserver/sfat32/sl_scan32.cpp	Mon Mar 15 12:45:50 2010 +0200
+++ b/userlibandfileserver/fileserver/sfat32/sl_scan32.cpp	Wed Mar 31 23:38:45 2010 +0300
@@ -94,7 +94,7 @@
 //----------------------------------------------------------------------------------------------------
 /**
     FAT type-agnostic parser. Reads whole FAT and sets up a bit vector.
-    for FAT12/16 it's OK, because the FAT12/16 is fully cached.
+    For FAT12/16 it's OK, because the FAT12/16 is fully cached.
 */
 void CScanDrive::DoParseFatL()
     {
@@ -255,8 +255,9 @@
 
 //----------------------------------------------------------------------------------------------------
 /**
-    Start the scanner. The this calss description about what it actually does.
-    @param  aMode specifies the operational mode.
+    Starts the scanner.
+    
+    @param	aMode	Specifies the operational mode.
 */
 void CScanDrive::StartL(TScanDriveMode aMode)
 	{
@@ -277,7 +278,7 @@
 
 	CheckDirStructureL();
 
-    //-- uncomments a line below if you need to compare real and restored FAT tables and print out all differences
+    //-- uncomment a line below if you need to compare real and restored FAT tables and print out all differences
     //CompareFatsL(EFalse);
 
         //timeEnd.UniversalTime(); //-- take end time
@@ -363,7 +364,11 @@
 			}
 		}
 
-	__ASSERT_ALWAYS(err==KErrNone,User::Leave(KErrNotFound));
+    if(err != KErrNone)
+        {
+        __PRINT1(_L("CScanDrive::FindSameStartClusterL() #1 %d"), err);
+        User::Leave(KErrNotFound);
+        }
 	}
 
 //----------------------------------------------------------------------------------------------------
@@ -374,21 +379,32 @@
     @return System wide error value
     @leave 
 */
-TInt CScanDrive::FindStartClusterL(TInt aDirCluster)
+TInt CScanDrive::FindStartClusterL(TUint32 aDirCluster)
 	{
 	__PRINT1(_L("CScanDrive::FindStartCluster dirCluster=%d"),aDirCluster);
-	__ASSERT_ALWAYS(aDirCluster>=iMount->RootIndicator(),User::Leave(KErrCorrupt));
+	
+	if(aDirCluster < (TUint)iMount->RootIndicator() || aDirCluster >= MaxClusters())
+        {
+        __PRINT(_L("CScanDrive::FindStartCluster() #!\n"));
+        IndicateErrorsFound(EBadClusterNumber);
+        User::Leave(KErrCorrupt);
+        }
+
+
 	if(++iRecursiveDepth==KMaxScanDepth)
 		{
 		--iRecursiveDepth;
 		return(KErrNotFound);
 		}
+
 	TEntryPos entryPos(aDirCluster,0);
 	TInt dirEntries=0;
-	FOREVER
+
+	for(;;)
 		{
 		TFatDirEntry entry;
 		ReadDirEntryL(entryPos,entry);
+
 		if(entry.IsParentDirectory()||entry.IsCurrentDirectory()||entry.IsErased())
 			{
 			if(IsEndOfRootDir(entryPos))
@@ -396,12 +412,20 @@
 			MoveToNextEntryL(entryPos);
 			continue;
 			}
+
 		if(entry.IsEndOfDirectory())
 			break;
-		TBool isComplete;
+		
 		TEntryPos vfatPos=entryPos;
-		isComplete=MoveToVFatEndL(entryPos,entry,dirEntries);
-		__ASSERT_ALWAYS(isComplete,User::Leave(KErrBadName));
+		const TBool isComplete = MoveToVFatEndL(entryPos,entry,dirEntries);
+		
+        if(!isComplete)
+            {
+            __PRINT(_L("CScanDrive::FindStartCluster() #2\n"));
+            IndicateErrorsFound(EEntrySetIncomplete);
+            User::Leave(KErrBadName);
+            }
+
 
 		TInt err=CheckEntryClusterL(entry,vfatPos);
 		if(err==KErrNone)
@@ -440,7 +464,7 @@
 	else if(aEntry.Attributes()&KEntryAttDir)
 		return(FindStartClusterL(iMount->StartCluster(aEntry)));
 
-	return(KErrNotFound);
+	return KErrNotFound;
 	}
 
 //----------------------------------------------------------------------------------------------------
@@ -526,6 +550,7 @@
         
         if(!isComplete && CheckDiskMode())
             {//-- broken VFAT entryset; in CheckDisk mode this is the FS error, abort further activity
+                __PRINT(_L("CScanDrive::CheckDirL() #1"));
                 IndicateErrorsFound(EInvalidEntrySize);
                 User::Leave(KErrCorrupt);
             }
@@ -577,13 +602,18 @@
 void CScanDrive::ProcessEntryL(const TFatDirEntry& aEntry)
 	{
 	__PRINT(_L("CScanDrive::ProcessEntryL"));
-	TInt entryAtt=aEntry.Attributes();
+	const TUint entryAtt=aEntry.Attributes();
 
-	__ASSERT_ALWAYS(!(entryAtt&~KEntryAttMaskSupported)&&!aEntry.IsErased(),User::Leave(KErrCorrupt));
+    if((entryAtt & ~KEntryAttMaskSupported) || aEntry.IsErased())
+        {
+        __PRINT1(_L("CScanDrive::ProcessEntryL() wrong entry att: 0x%x"), entryAtt);
+        IndicateErrorsFound(EEntryBadAtt);
+        User::Leave(KErrCorrupt);
+        }
 	
     if(!(entryAtt&(KEntryAttDir|KEntryAttVolume)) && iMount->StartCluster(aEntry)>0)
 		{//-- this is a file with length >0. Check that its cluster chain corresponds to its size
-        RecordClusterChainL(iMount->StartCluster(aEntry),(TUint) aEntry.Size());
+        RecordClusterChainL(iMount->StartCluster(aEntry), aEntry.Size());
         }
 	else if(entryAtt&KEntryAttDir)
 		{//-- this is the directory, walk into it
@@ -601,34 +631,52 @@
     @param aSizeInBytes Size of the file or directory in bytes
     @leave System wide error values
 */
-void CScanDrive::RecordClusterChainL(TInt aCluster, TUint aSizeInBytes)
+void CScanDrive::RecordClusterChainL(TUint32 aCluster, TUint aSizeInBytes)
 	{
 	__PRINT2(_L("CScanDrive::RecordClusterChainL() cl:%d, sz:%d") ,aCluster, aSizeInBytes);
-	__ASSERT_ALWAYS(aCluster>0, User::Leave(KErrCorrupt));
+
+    if(aCluster < KFatFirstSearchCluster || aCluster >= MaxClusters())
+	    {
+        __PRINT(_L("CScanDrive::RecordClusterChainL() #0"));
+        IndicateErrorsFound(EBadClusterNumber);
+        User::Leave(KErrCorrupt);
+        }
 	
     TUint clusterCount;
 	
     if(aSizeInBytes==0)
+		{
 		clusterCount=1;
+        }
 	else
 		{
         const TUint64 tmp = aSizeInBytes + Pow2_64(iMount->ClusterSizeLog2()) - 1;
         clusterCount = (TUint) (tmp >> iMount->ClusterSizeLog2());
         }
 
-	TInt startCluster=aCluster;
+	TUint startCluster=aCluster;
+	
 	while(clusterCount)
 		{
         if(IsClusterUsedL(aCluster))
 			{//-- this cluster already seems to belong to some other object; crosslinked cluster chain. Can't fix it.
-			if(CheckDiskMode())
+                __PRINT1(_L("CScanDrive::RecordClusterChainL #1 %d"),aCluster); 
+            
+            if(CheckDiskMode())
                 {//-- in check disk mode this is a FS error; Indicate error and abort furter scanning
-                __PRINT1(_L("CScanDrive::RecordClusterChainL #1 %d"),aCluster); 
+                __PRINT(_L("CScanDrive::RecordClusterChainL #1.1")); 
                 IndicateErrorsFound(EClusterAlreadyInUse);
                 User::Leave(KErrCorrupt);
                 }
             
-            __ASSERT_ALWAYS(!IsDirError() && iMatching.iStartCluster==0 && aCluster==startCluster,User::Leave(KErrCorrupt));
+            
+            if(IsDirError() || iMatching.iStartCluster > 0 || aCluster != startCluster)
+                {//-- secondary entry into this state
+                __PRINT(_L("CScanDrive::RecordClusterChainL #1.2")); 
+                IndicateErrorsFound(EClusterAlreadyInUse);
+                User::Leave(KErrCorrupt);
+                }
+
 			iMatching.iStartCluster=aCluster;
 			iDirError=EScanMatchingEntry;		//ERROR POINT
             IndicateErrorsFound(EScanDriveDirError); //-- indicate that we have found errors
@@ -637,10 +685,10 @@
 
 		
         if(clusterCount==1)
-			{
+			{//-- we have reached the end of the cluster chain
 			if(!iMount->IsEndOfClusterCh(ReadFatL(aCluster)))
-				{//-- seems to be a rugged FAT artefact; File truncation had failed before and now file length is less than
-                 //-- the corresponding cluster chain shall be. It will be truncated.
+				{//-- 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())
@@ -660,8 +708,14 @@
 			const TUint clusterVal=ReadFatL(aCluster);
 
             //__PRINT2(_L("#--: %d -> %d"), aCluster, clusterVal); 
-			
-            __ASSERT_ALWAYS(!IsEofF(clusterVal) && clusterVal !=KSpareCluster, User::Leave(KErrCorrupt));
+            if(IsEofF(clusterVal) || clusterVal == KSpareCluster )
+                {//-- unexpected end of the cluster chain (it is shorter than recorded in file dir. entry)
+                __PRINT1(_L("CScanDrive::RecordClusterChainL #3 %d"),clusterVal); 
+                IndicateErrorsFound(EBadClusterValue);
+                User::Leave(KErrCorrupt);
+                }
+
+
 			MarkClusterUsedL(aCluster);
 			aCluster=clusterVal;
 			--clusterCount;
@@ -688,9 +742,16 @@
 		return IsDosEntry(aEntry);
 
 	TInt toFollow=aEntry.NumFollowing();
-	__ASSERT_ALWAYS(toFollow>0 && !aEntry.IsErased(), User::Leave(KErrCorrupt));
 
-	FOREVER
+    if(toFollow <=0 || aEntry.IsErased())
+        {
+        __PRINT1(_L("CScanDrive::MoveToVFatEndL #1 %d"),toFollow);
+        IndicateErrorsFound(EEntrySetIncomplete);
+        User::Leave(KErrCorrupt);
+        }
+
+
+	for(;;)
 		{
 		MoveToNextEntryL(aPos);
 		ReadDirEntryL(aPos,aEntry);
@@ -731,7 +792,7 @@
 */
 TBool CScanDrive::IsDosEntry(const TFatDirEntry& aEntry)const
 	{
-	TBool res = !(aEntry.Attributes()&~KEntryAttMaskSupported) && !aEntry.IsErased() && !aEntry.IsVFatEntry() && !aEntry.IsEndOfDirectory();
+	const TBool res = !(aEntry.Attributes()&~KEntryAttMaskSupported) && !aEntry.IsErased() && !aEntry.IsVFatEntry() && !aEntry.IsEndOfDirectory();
 	return res;
 	} 
 
@@ -746,7 +807,13 @@
 void CScanDrive::AddPartialVFatL(const TEntryPos& aStartPos, const TFatDirEntry& aEntry)
 	{
 	__PRINT2(_L("CScanDrive::AddPartialVFatL cluster=%d pos=%d"),aStartPos.iCluster,aStartPos.iPos);
-	__ASSERT_ALWAYS(!IsDirError(),User::Leave(KErrCorrupt));
+
+    if(IsDirError())
+        {
+        __PRINT(_L("CScanDrive::AddPartialVFatL #1"));
+        User::Leave(KErrCorrupt);
+        }
+
 	iPartEntry.iEntryPos=aStartPos;
 	iPartEntry.iEntry=aEntry;
 	iDirError=EScanPartEntry;
@@ -763,7 +830,14 @@
 TBool CScanDrive::AddMatchingEntryL(const TEntryPos& aEntryPos)
 	{
 	__PRINT2(_L("CScanDrive::AddMatchingEntryL cluster=%d pos=%d"),aEntryPos.iCluster,aEntryPos.iPos);
-	__ASSERT_ALWAYS(iMatching.iStartCluster>0 && iMatching.iCount<KMaxMatchingEntries,User::Leave(KErrCorrupt));
+	
+    if(iMatching.iStartCluster <= 0 || iMatching.iCount >= KMaxMatchingEntries)
+        {
+        __PRINT(_L("CScanDrive::AddMatchingEntryL #1"));
+        User::Leave(KErrCorrupt);
+        }
+
+
 	iMatching.iEntries[iMatching.iCount++]=aEntryPos;
 	return iMatching.iCount==KMaxMatchingEntries;
 	}
@@ -873,7 +947,6 @@
     Read the "Rugged FAT" ID, stored in reserved2 in the Dos entry or associated with the Dos entry of the 
     Entry at the position passed in. This is used to find which version of two matching entries should be kept.
 
-
     @param aVFatPos Position of an entry to read ID from
     @leave System wide error codes
     @return The ID found in reserved2 field of dos entry 
@@ -886,10 +959,13 @@
 	if(!IsDosEntry(entry))
 		{
 		TInt toMove=entry.NumFollowing();
+		
 		while(toMove--)
 			MoveToNextEntryL(aVFatPos);
+		
 		ReadDirEntryL(aVFatPos,entry);
 		}
+	
 	return(entry.RuggedFatEntryId());
 	}
 
@@ -916,15 +992,24 @@
 	{
 	
     __PRINT1(_L("CScanDrive::FixMatchingEntryL() start cluster=%d"),iMatching.iStartCluster);
-	__ASSERT_ALWAYS(iMatching.iCount==KMaxMatchingEntries,User::Leave(KErrCorrupt));
+	
+    if(iMatching.iCount != KMaxMatchingEntries)
+        {
+        __PRINT1(_L("CScanDrive::FixMatchingEntryL() #1 %d"), iMatching.iCount);            
+        User::Leave(KErrCorrupt);
+        }
+
 	ASSERT(!CheckDiskMode());
 
-    TInt idOne=GetReservedidL(iMatching.iEntries[0]);
-	TInt idTwo=GetReservedidL(iMatching.iEntries[1]);
+    const TInt idOne=GetReservedidL(iMatching.iEntries[0]);
+	const TInt idTwo=GetReservedidL(iMatching.iEntries[1]);
 	TFatDirEntry entry;
-	TInt num=idOne>idTwo?0:1;
+	
+    const TInt num = idOne>idTwo ? 0:1;
 	ReadDirEntryL(iMatching.iEntries[num],entry);
+
 	iMount->EraseDirEntryL(iMatching.iEntries[num],entry);
+    
     IndicateErrorsFound(EScanDriveDirError); //-- indicate that we have found errors
 	}
 
@@ -964,6 +1049,7 @@
 
 	if(iClusterListArray[iListArrayIndex]==NULL)
 		iClusterListArray[iListArrayIndex]=new(ELeave) RArray<TInt>(KClusterListGranularity);
+
 	iClusterListArray[iListArrayIndex]->Append(aCluster);
 	}
 
@@ -1111,6 +1197,7 @@
 	{
 	if(aClusterNum < KFatFirstSearchCluster || aClusterNum >= MaxClusters())
         {
+        __PRINT1(_L("CScanDrive::ReadFatL() bad cluster:%d\n"),aClusterNum);
         IndicateErrorsFound(EBadClusterNumber);
         User::Leave(KErrCorrupt);
         }
@@ -1129,6 +1216,7 @@
 	{
 	if(aClusterNum < KFatFirstSearchCluster || aClusterNum >= MaxClusters())
         {
+        __PRINT1(_L("CScanDrive::MarkClusterUsedL() bad cluster:%d\n"),aClusterNum);
         IndicateErrorsFound(EBadClusterNumber);
         User::Leave(KErrCorrupt);
         }
@@ -1145,6 +1233,7 @@
 	{
 	if(aClusterNum < KFatFirstSearchCluster || aClusterNum >= MaxClusters())
         {
+        __PRINT1(_L("CScanDrive::IsClusterUsedL() bad cluster:%d\n"),aClusterNum);
         IndicateErrorsFound(EBadClusterNumber);
         User::Leave(KErrCorrupt);
         }