userlibandfileserver/fileserver/sfat32/sl_scan32.cpp
changeset 189 a5496987b1da
parent 90 947f0dc9f7a8
child 291 206a6eaaeb71
equal deleted inserted replaced
177:a232af6b0b1f 189:a5496987b1da
    70 void CScanDrive::ConstructL(CFatMountCB* aMount)
    70 void CScanDrive::ConstructL(CFatMountCB* aMount)
    71     {
    71     {
    72     ASSERT(aMount);
    72     ASSERT(aMount);
    73 
    73 
    74     //--- setting up 
    74     //--- setting up 
    75     iMount=aMount;
    75 	iMount			 = aMount;
    76     iGenericError = ENoErrors;
    76 	iGenericError	 = ENoErrors;
    77     iDirError     = ENoDirError;  
    77 	iDirError		 = ENoDirError;
    78     iMaxClusters  = iMount->UsableClusters()+KFatFirstSearchCluster; //-- UsableClusters() doesn't count first 2 unused clusers
    78 	iHangingClusters = 0;
       
    79 	iMaxClusters	 = iMount->UsableClusters()+KFatFirstSearchCluster; //-- UsableClusters() doesn't count first 2 unused clusers
    79     //------------------------------
    80     //------------------------------
    80 	
    81 	
    81     //-- create bit vectors that will represent FAT on media and reconstructed by ScanDrive. Each bit in the vector represents 1 FAT cluster.
    82     //-- create bit vectors that will represent FAT on media and reconstructed by ScanDrive. Each bit in the vector represents 1 FAT cluster.
    82     const TUint32 KClustersNum = MaxClusters();
    83     const TUint32 KClustersNum = MaxClusters();
    83 
    84 
    92     }
    93     }
    93 
    94 
    94 //----------------------------------------------------------------------------------------------------
    95 //----------------------------------------------------------------------------------------------------
    95 /**
    96 /**
    96     FAT type-agnostic parser. Reads whole FAT and sets up a bit vector.
    97     FAT type-agnostic parser. Reads whole FAT and sets up a bit vector.
    97     for FAT12/16 it's OK, because the FAT12/16 is fully cached.
    98     For FAT12/16 it's OK, because the FAT12/16 is fully cached.
    98 */
    99 */
    99 void CScanDrive::DoParseFatL()
   100 void CScanDrive::DoParseFatL()
   100     {
   101     {
   101     const TInt KMaxClusters = MaxClusters();
   102     const TInt KMaxClusters = MaxClusters();
   102 
   103 
   107     for(TInt i=KFatFirstSearchCluster; i<KMaxClusters; ++i)
   108     for(TInt i=KFatFirstSearchCluster; i<KMaxClusters; ++i)
   108 	    {
   109 	    {
   109         const TUint32 nFatEntry = ReadFatL(i);
   110         const TUint32 nFatEntry = ReadFatL(i);
   110        
   111        
   111         //-- each '1' bit represents a used cluster 
   112         //-- each '1' bit represents a used cluster 
   112         if(nFatEntry != KSpareCluster) 
   113         if(nFatEntry != KSpareCluster)
   113             iMediaFatBits.SetBit(i);
   114             iMediaFatBits.SetBit(i);
   114 	    }
   115 	    }
   115     }
   116     }
   116 
   117 
   117 //----------------------------------------------------------------------------------------------------
   118 //----------------------------------------------------------------------------------------------------
   123 void CScanDrive::DoParseFat32Buf(const TPtrC8& aBuf, TUint32& aCurrFatEntry)
   124 void CScanDrive::DoParseFat32Buf(const TPtrC8& aBuf, TUint32& aCurrFatEntry)
   124     {
   125     {
   125     ASSERT((aBuf.Size() & (sizeof(TFat32Entry)-1)) == 0);
   126     ASSERT((aBuf.Size() & (sizeof(TFat32Entry)-1)) == 0);
   126     
   127     
   127     const TInt KNumEntries = aBuf.Size() >> KFat32EntrySzLog2;
   128     const TInt KNumEntries = aBuf.Size() >> KFat32EntrySzLog2;
   128     const TFat32Entry* const pFatEntry = (const TFat32Entry*)(aBuf.Ptr()); 
   129     const TFat32Entry* const pFatEntry = (const TFat32Entry*)(aBuf.Ptr());
   129 
   130 
   130     for(TInt i=0; i<KNumEntries; ++i)
   131     for(TInt i=0; i<KNumEntries; ++i)
   131         {
   132         {
   132         if(aCurrFatEntry >= KFatFirstSearchCluster)
   133         if(aCurrFatEntry >= KFatFirstSearchCluster)
   133             {
   134             {
   159 
   160 
   160     const TUint32 KFatBufSz = 32*K1KiloByte; //-- buffer size for FAT reading. 32K seems to be optimal size
   161     const TUint32 KFatBufSz = 32*K1KiloByte; //-- buffer size for FAT reading. 32K seems to be optimal size
   161 
   162 
   162     iMediaFatBits.Fill(0);
   163     iMediaFatBits.Fill(0);
   163 
   164 
   164     RBuf8 buf;
   165     RBuf8 fatParseBuf;
   165     CleanupClosePushL(buf);
   166     CleanupClosePushL(fatParseBuf);
   166 
   167 
   167     //-- allocate memory for FAT parse buffer
   168     //-- allocate memory for FAT parse buffer
   168     buf.CreateMaxL(KFatBufSz);
   169     fatParseBuf.CreateMaxL(KFatBufSz);
   169 
   170 
   170     //-- read FAT directly from the media into the large buffer and parse it
   171     //-- read FAT directly from the media into the large buffer and parse it
   171     TUint32 rem = KFatSize;
   172     TUint32 rem = KFatSize;
   172     TUint32 mediaPos = KFat1StartPos;   
   173     TUint32 mediaPos = KFat1StartPos;   
   173     TUint32 currFatEntry = 0;
   174     TUint32 currFatEntry = 0;
   174 
   175 
   175     while(rem)
   176     while(rem)
   176         {
   177         {
   177         const TUint32 bytesToRead=Min(rem, KFatBufSz);
   178         const TUint32 bytesToRead=Min(rem, KFatBufSz);
   178         TPtrC8 ptrData(buf.Ptr(), bytesToRead);
   179         TPtrC8 ptrData(fatParseBuf.Ptr(), bytesToRead);
   179 
   180 
   180         //-- read portion of the FAT into buffer
   181         //-- read portion of the FAT into buffer
   181         User::LeaveIfError(iMount->LocalDrive()->Read(mediaPos, bytesToRead, buf)); 
   182         User::LeaveIfError(iMount->LocalDrive()->Read(mediaPos, bytesToRead, fatParseBuf)); 
   182 
   183 
   183         //-- parse the buffer and populate bit vector
   184         //-- parse the buffer and populate bit vector
   184         DoParseFat32Buf(ptrData, currFatEntry);
   185         DoParseFat32Buf(ptrData, currFatEntry);
   185         
   186         
   186         mediaPos += bytesToRead;
   187         mediaPos += bytesToRead;
   187         rem -= bytesToRead;
   188         rem -= bytesToRead;
   188         }
   189         }
   189 
   190 
   190     buf.Close();
   191     fatParseBuf.Close();
   191     CleanupStack::PopAndDestroy(&buf); 
   192     CleanupStack::PopAndDestroy(&fatParseBuf); 
   192     }
   193     }
   193 
   194 
   194 
   195 
   195 
   196 
   196 //----------------------------------------------------------------------------------------------------
   197 //----------------------------------------------------------------------------------------------------
   239     else
   240     else
   240         return iGenericError;
   241         return iGenericError;
   241 }
   242 }
   242 
   243 
   243 /**
   244 /**
   244     Sets the flag indicating than there are errors in filesystem structure
   245     Sets the flag indicating that there are errors in filesystem structure
   245     See ProblemsDiscovered()
   246     See ProblemsDiscovered()
   246 
   247 
   247     @param  aError a code describing the error
   248     @param  aError a code describing the error
   248 */
   249 */
   249 void CScanDrive::IndicateErrorsFound(TGenericError aError)
   250 void CScanDrive::IndicateErrorsFound(TGenericError aError)
   253 }
   254 }
   254 
   255 
   255 
   256 
   256 //----------------------------------------------------------------------------------------------------
   257 //----------------------------------------------------------------------------------------------------
   257 /**
   258 /**
   258     Start the scanner. The this calss description about what it actually does.
   259     Starts the scanner.
   259     @param  aMode specifies the operational mode.
   260     
       
   261     @param	aMode	Specifies the operational mode.
   260 */
   262 */
   261 void CScanDrive::StartL(TScanDriveMode aMode)
   263 void CScanDrive::StartL(TScanDriveMode aMode)
   262 	{
   264 	{
   263 	__PRINT2(_L("CScanDrive::StartL(%d), drive:%d"), aMode, iMount->DriveNumber());
   265 	__PRINT2(_L("CScanDrive::StartL(%d), drive:%d"), aMode, iMount->DriveNumber());
   264     iScanDriveMode = aMode;
   266     iScanDriveMode = aMode;
   296 
   298 
   297 	    CompareAndFixFatsL();
   299 	    CompareAndFixFatsL();
   298         }
   300         }
   299 
   301 
   300 	PrintErrors();
   302 	PrintErrors();
   301 
       
   302 
   303 
   303     timeEnd.UniversalTime(); //-- take end time
   304     timeEnd.UniversalTime(); //-- take end time
   304     const TInt elapsedTime = (TInt)( (timeEnd.MicroSecondsFrom(timeStart)).Int64() / K1mSec);
   305     const TInt elapsedTime = (TInt)( (timeEnd.MicroSecondsFrom(timeStart)).Int64() / K1mSec);
   305     (void)elapsedTime;
   306     (void)elapsedTime;
   306 
   307 
   475 */
   476 */
   476 void CScanDrive::CheckDirStructureL()
   477 void CScanDrive::CheckDirStructureL()
   477 	{
   478 	{
   478 	CheckDirL(iMount->RootIndicator());
   479 	CheckDirL(iMount->RootIndicator());
   479 	// Due to recursive nature of CheckDirL when a depth of
   480 	// Due to recursive nature of CheckDirL when a depth of
   480 	// KMaxScanDepth is reached clusters are stored in a list
   481 	// KMaxScanDepth is reached, clusters are stored in a list
   481 	// and passed into CheckDirL afresh
   482 	// and passed into CheckDirL afresh
   482 
   483 
   483 	for(TUint i=0;i<KMaxArrayDepth && iClusterListArray[i]!=NULL;++i)
   484 	for(TUint i=0;i<KMaxArrayDepth && iClusterListArray[i]!=NULL;++i)
   484 		{
   485 		{
   485 		RArray<TInt>* clusterList=iClusterListArray[i];
   486 		RArray<TInt>* clusterList=iClusterListArray[i];
   515 
   516 
   516 	++iDirsChecked;
   517 	++iDirsChecked;
   517 
   518 
   518 	TEntryPos entryPos(aCluster,0);
   519 	TEntryPos entryPos(aCluster,0);
   519 	TInt dirEntries=0;
   520 	TInt dirEntries=0;
   520 	FOREVER
   521 	for(;;)
   521 		{
   522 		{
   522 		TFatDirEntry entry;
   523 		TFatDirEntry entry;
   523 		ReadDirEntryL(entryPos,entry);
   524 		ReadDirEntryL(entryPos,entry);
   524 		if(!iMount->IsEndOfClusterCh(entryPos.iCluster))
   525 		if(!iMount->IsEndOfClusterCh(entryPos.iCluster))
   525 			++dirEntries;
   526 			++dirEntries;
   657 	
   658 	
   658 	while(clusterCount)
   659 	while(clusterCount)
   659 		{
   660 		{
   660         if(IsClusterUsedL(aCluster))
   661         if(IsClusterUsedL(aCluster))
   661 			{//-- this cluster already seems to belong to some other object; crosslinked cluster chain. Can't fix it.
   662 			{//-- this cluster already seems to belong to some other object; crosslinked cluster chain. Can't fix it.
   662                 __PRINT1(_L("CScanDrive::RecordClusterChainL #1 %d"),aCluster); 
   663             __PRINT1(_L("CScanDrive::RecordClusterChainL #1 %d"),aCluster); 
   663             
   664             
   664             if(CheckDiskMode())
   665             if(CheckDiskMode())
   665                 {//-- in check disk mode this is a FS error; Indicate error and abort furter scanning
   666                 {//-- in check disk mode this is an FS error; Indicate error and abort further scanning
   666                 __PRINT(_L("CScanDrive::RecordClusterChainL #1.1")); 
   667                 __PRINT(_L("CScanDrive::RecordClusterChainL #1.1"));
   667                 IndicateErrorsFound(EClusterAlreadyInUse);
   668                 IndicateErrorsFound(EClusterAlreadyInUse);
   668                 User::Leave(KErrCorrupt);
   669                 User::Leave(KErrCorrupt);
   669                 }
   670                 }
   670             
   671             
   671             
   672             
   684 
   685 
   685 		
   686 		
   686         if(clusterCount==1)
   687         if(clusterCount==1)
   687 			{//-- we have reached the end of the cluster chain
   688 			{//-- we have reached the end of the cluster chain
   688 			if(!iMount->IsEndOfClusterCh(ReadFatL(aCluster)))
   689 			if(!iMount->IsEndOfClusterCh(ReadFatL(aCluster)))
   689 				{//-- seems to be a rugged FAT artefact; File truncation/extension had failed before and now file length is less than
   690 				{
   690                  //-- the corresponding cluster chain shall be. It will be truncated to the size recorded in file DOS entry.
   691 				// According to the directory entry, we have reached the end of the cluster chain,
   691 				iTruncationCluster = aCluster;								
   692 				// whereas in the media FAT, it is not.
       
   693 				// This is a rugged FAT artefact; hanging cluster chain:
       
   694 				// 	A cluster chain which is longer in the FAT table than is recorded in the corresponding directory entry 
       
   695 				// 	or not terminated by an EOC entry in FAT.
       
   696 				// This is caused by:
       
   697 				//  - File truncation failing.
       
   698 				//	- OR file expanding failing during flushing to the media FAT.
   692                 
   699                 
   693                 if(CheckDiskMode())
   700                 if(CheckDiskMode())
   694                     {//-- in check disk mode this is a FS error; Indicate error and abort furter scanning
   701                     {//-- in check disk mode this is an FS error; Indicate error and abort further scanning
   695                     __PRINT1(_L("CScanDrive::RecordClusterChainL #2 %d"),aCluster); 
   702                     __PRINT1(_L("CScanDrive::RecordClusterChainL #2 Hanging cluster=%d"),aCluster);
   696                     IndicateErrorsFound(EInvalidEntrySize);
   703                     IndicateErrorsFound(EInvalidEntrySize);
   697                     User::Leave(KErrCorrupt);
   704                     User::Leave(KErrCorrupt);
   698                     }
   705                     }
       
   706 				
       
   707 				// The chain will be truncated to the size recorded in the file's DOS entry and
       
   708 				// the remaining lost cluster chain will be fixed later in CompareAndFixFatsL().
       
   709 				FixHangingClusterChainL(aCluster);
   699                 }
   710                 }
   700 
   711 
   701             //__PRINT1(_L("#--: %d -> EOC"), aCluster); 
   712             //__PRINT1(_L("#--: %d -> EOC"), aCluster); 
   702             MarkClusterUsedL(aCluster);
   713             MarkClusterUsedL(aCluster);
   703 			return;
   714 			return;
   760 			break;
   771 			break;
   761 		
   772 		
   762         if(!IsValidVFatEntry(aEntry,toFollow))
   773         if(!IsValidVFatEntry(aEntry,toFollow))
   763 			return(EFalse);
   774 			return(EFalse);
   764 		}
   775 		}
   765 	
   776 	// A sequence of VFat entries must end with a Dos entry to be valid.
   766     return(IsDosEntry(aEntry));
   777 	return(IsDosEntry(aEntry));
   767 	}
   778 	}
   768 
   779 
   769 //----------------------------------------------------------------------------------------------------
   780 //----------------------------------------------------------------------------------------------------
   770 /**
   781 /**
   771     Check if an entry is valid VFat
   782     Check if an entry is valid VFat
   842 	}
   853 	}
   843 
   854 
   844 
   855 
   845 //----------------------------------------------------------------------------------------------------
   856 //----------------------------------------------------------------------------------------------------
   846 /**
   857 /**
   847     Scan for differnces in the new and old FAT table writing them to media if discovered
   858     Scan for differences in the new and old FAT table writing them to media if discovered
   848     It is supposed to be called in 'ScanDrive' mode only
   859     It is supposed to be called in 'ScanDrive' mode only
   849 
   860 
   850     @leave System wide error codes
   861     @leave System wide error codes
   851 */
   862 */
   852 void CScanDrive::CompareAndFixFatsL()
   863 void CScanDrive::CompareAndFixFatsL()
   882                     {
   893                     {
   883                     ++nBadClusters;
   894                     ++nBadClusters;
   884                     continue;
   895                     continue;
   885                     }
   896                     }
   886          
   897          
   887                 //-- here we found a lost cluster. Its FAT entry will be replaced with KSpareCluster. In the case of multiple lost clusters FAT table will
   898                 //-- Here we found a lost cluster. Its FAT entry will be replaced with KSpareCluster.
   888                 //-- be flushed on media sector basis. It is much faster than flushing FAT after every write and will
   899                 //-- In the case of multiple lost clusters FAT table will be flushed on media sector basis.
   889                 //-- guarantee that FAT won't be corrupted if the media driver provides atomic sector write. 
   900                 //-- It is much faster than flushing FAT after every write and will guarantee
       
   901                 //-- that FAT won't be corrupted if the media driver provides atomic sector write. 
   890                 if(nClustersFixed == 0)
   902                 if(nClustersFixed == 0)
   891                     {//-- this is the first lost cluster entry we found
   903                     {//-- this is the first lost cluster entry we found
   892                     
   904                     
   893                     //-- relative FAT media sector for the 'i' entry. The real value doesn't matter, 
   905                     //-- relative FAT media sector for the 'i' entry. The real value doesn't matter, 
   894                     //-- we will just be flushing FAT before writing to the different FAT media sector.
   906                     //-- we will just be flushing FAT before writing to the different FAT media sector.
   899                 else
   911                 else
   900                     {
   912                     {
   901                     const TUint32 fatSec = iMount->FAT().PosInBytes(i) >> KSectorSzLog2; 
   913                     const TUint32 fatSec = iMount->FAT().PosInBytes(i) >> KSectorSzLog2; 
   902 
   914 
   903                     if(fatSec != dirtyFatSector)
   915                     if(fatSec != dirtyFatSector)
   904                         {//-- we are going to write to a differrent media sector
   916                         {//-- we are going to write to a different media sector
   905                         iMount->FAT().FlushL();
   917                         iMount->FAT().FlushL();
   906                         iMount->FAT().WriteL(i, KSpareCluster); //-- fix lost cluster
   918                         iMount->FAT().WriteL(i, KSpareCluster); //-- fix lost cluster
   907                         dirtyFatSector = fatSec;
   919                         dirtyFatSector = fatSec;
   908                         }
   920                         }
   909                     else
   921                     else
   925     if(nClustersFixed)
   937     if(nClustersFixed)
   926         iMount->FAT().FlushL();
   938         iMount->FAT().FlushL();
   927     
   939     
   928     //------
   940     //------
   929 
   941 
   930     if(iTruncationCluster != 0)
   942 	
   931         {
   943 	// Add the number of hanging clusters fixed by ScanDrive
   932 	    iMount->FAT().WriteFatEntryEofL(iTruncationCluster); 
   944 	nClustersFixed += iHangingClusters;
   933 		iMount->FAT().FlushL();
   945     
   934 		
   946     __PRINT3(_L("CScanDrive::WriteNewFatsL() fixed clusters=%d,hanging clusters=%d,bad clusters=%d"),nClustersFixed,iHangingClusters,nBadClusters);
   935         //-- indicate that there are some problems in FAT. and we probably wrote something there.
       
   936         IndicateErrorsFound(EScanDriveDirError); //-- indicate that we have found errors
       
   937 
       
   938         ++nClustersFixed;
       
   939         }
       
   940     
       
   941     __PRINT2(_L("CScanDrive::WriteNewFatsL() fixed:%d, bad:%d"), nClustersFixed, nBadClusters);
       
   942     }
   947     }
   943 
   948 
   944 //----------------------------------------------------------------------------------------------------
   949 //----------------------------------------------------------------------------------------------------
   945 /**
   950 /**
   946     Read the "Rugged FAT" ID, stored in reserved2 in the Dos entry or associated with the Dos entry of the 
   951     Read the "Rugged FAT" ID, stored in reserved2 in the Dos entry or associated with the Dos entry of the 
   947     Entry at the position passed in. This is used to find which version of two matching entries should be kept.
   952     Entry at the position passed in. This is used to find which version of two matching entries should be kept.
   948 
       
   949 
   953 
   950     @param aVFatPos Position of an entry to read ID from
   954     @param aVFatPos Position of an entry to read ID from
   951     @leave System wide error codes
   955     @leave System wide error codes
   952     @return The ID found in reserved2 field of dos entry 
   956     @return The ID found in reserved2 field of dos entry 
   953 */
   957 */
  1010 
  1014 
  1011 	iMount->EraseDirEntryL(iMatching.iEntries[num],entry);
  1015 	iMount->EraseDirEntryL(iMatching.iEntries[num],entry);
  1012     
  1016     
  1013     IndicateErrorsFound(EScanDriveDirError); //-- indicate that we have found errors
  1017     IndicateErrorsFound(EScanDriveDirError); //-- indicate that we have found errors
  1014 	}
  1018 	}
       
  1019 
       
  1020 //----------------------------------------------------------------------------------------------------
       
  1021 /**
       
  1022 	Fix a hanging cluster chain.
       
  1023 	Writes EOF to the corresponding FAT entry, making this cluster chain length correspond to the 
       
  1024 	real file size recorded in the directory entry.
       
  1025 	The remainder of the chain will be cleaned up later in CompareAndFixFatsL().
       
  1026 	
       
  1027 	@leave	System wide error code
       
  1028 */
       
  1029 void CScanDrive::FixHangingClusterChainL(TUint32 aFatEofIndex)
       
  1030 	{
       
  1031 	__PRINT1(_L("CScanDrive::FixHangingClusterL() Hanging cluster=%d"), aFatEofIndex);
       
  1032 	
       
  1033 	iMount->FAT().WriteFatEntryEofL(aFatEofIndex);
       
  1034 	iMount->FAT().FlushL();
       
  1035 	iHangingClusters++;
       
  1036 	
       
  1037 	// Indicate that we have found an error
       
  1038 	IndicateErrorsFound(EScanDriveDirError);
       
  1039 	}
       
  1040 
  1015 
  1041 
  1016 //----------------------------------------------------------------------------------------------------
  1042 //----------------------------------------------------------------------------------------------------
  1017 /**
  1043 /**
  1018     Move past specified number of entries
  1044     Move past specified number of entries
  1019 
  1045 
  1085         const TBool bNewFatEntry  = iScanFatBits[i];
  1111         const TBool bNewFatEntry  = iScanFatBits[i];
  1086 
  1112 
  1087 		if(BoolXOR(bRealFatEntry, bNewFatEntry))
  1113 		if(BoolXOR(bRealFatEntry, bNewFatEntry))
  1088 		    {//-- mismatch between FAT on the media and the FAT bitmap restored by walking directory structure
  1114 		    {//-- mismatch between FAT on the media and the FAT bitmap restored by walking directory structure
  1089 
  1115 
  1090 			    if(bRealFatEntry)
  1116 			if(bRealFatEntry)
  1091                 {//-- FAT[i] on the media is marked as occupied, but retored FAT bitmap shows that it is free
  1117 				{//-- FAT[i] on the media is marked as occupied, but restored FAT bitmap shows that it is free
  1092                     if(iMount->IsBadCluster(ReadFatL(i)))
  1118 				if(iMount->IsBadCluster(ReadFatL(i)))
  1093                         continue; //-- this is a BAD cluster it can't be occupied by the FS object, OK.
  1119 					continue; //-- this is a BAD cluster it can't be occupied by the FS object, OK.
  1094 
  1120 
  1095                     __PRINT2(_L("FAT[%d] = %d\n"), i, ReadFatL(i));        
  1121 				__PRINT2(_L("FAT[%d] = %d\n"), i, ReadFatL(i));
  1096                     __PRINT1(_L("iTruncationCluster = %d\n"), iTruncationCluster);        
  1122 				
  1097                     
  1123 				//-- this is a Rugged FAT artefact; a lost cluster
  1098                     //-- this is a lost cluster
  1124 				__PRINT1(_L("Lost cluster=%d\n"),i);
  1099                     if(!IsEofF(ReadFatL(i)) && (i==iTruncationCluster))
  1125 				
  1100                         {//-- seems to be a Rugged FAT ertefact
  1126 				IndicateErrorsFound(EBadClusterValue);
  1101                         __PRINT1(_L("Hanging cluster = %d\n"),i);        
  1127 				}
  1102                         }
  1128 			else
  1103                     else
  1129 				{//-- FAT[i] on the media is marked as free, but restored FAT bitmap shows that it is occupied by some object
  1104                         {
  1130 				IndicateErrorsFound(EClusterAlreadyInUse);
  1105                         __PRINT1(_L("Lost cluster=%d\n"),i);
  1131 				__PRINT1(_L("Unflushed cluster = %d\n"),i);
  1106                         }
  1132 				}
  1107                     
  1133 
  1108                     
  1134 		 if(aStopOnFirstErrorFound)
  1109                     IndicateErrorsFound(EBadClusterValue);
  1135 			 break; //-- not asked to check for errors further
  1110                 }
       
  1111                 else
       
  1112                 {//-- FAT[i] on the media is marked as free, but retored FAT bitmap shows that it is occupied by some object
       
  1113                     IndicateErrorsFound(EClusterAlreadyInUse);
       
  1114                     __PRINT1(_L("Unflushed cluster = %d\n"),i);
       
  1115                 }
       
  1116 
       
  1117              if(aStopOnFirstErrorFound)
       
  1118                  break; //-- not asked to check for errors further
       
  1119 
  1136 
  1120             }
  1137             }
  1121 		
  1138 		
  1122         if(bRealFatEntry)
  1139         if(bRealFatEntry)
  1123 			mediausedcnt++;
  1140 			mediausedcnt++;
  1185 	//__PRINT(_L("CScanDrive::MoveToNextEntryL"));
  1202 	//__PRINT(_L("CScanDrive::MoveToNextEntryL"));
  1186 	iMount->MoveToNextEntryL(aPos);
  1203 	iMount->MoveToNextEntryL(aPos);
  1187 	}	
  1204 	}	
  1188 
  1205 
  1189 /**
  1206 /**
  1190     Read a cluster from the Media Fat if scan run in a seperate thread read from scan fat table
  1207     Read a cluster from the Media Fat if scan run in a separate thread read from scan Fat table
  1191     otherwise read from mount owned Fat table
  1208     otherwise read from mount owned Fat table
  1192 
  1209 
  1193     @param aClusterNum Cluster to read
  1210     @param aClusterNum Cluster to read
  1194     @return Value of cluster read from Fat
  1211     @return Value of cluster read from Fat
  1195 */
  1212 */
  1196 TUint32 CScanDrive::ReadFatL(TUint aClusterNum) 
  1213 TUint32 CScanDrive::ReadFatL(TUint aClusterNum)
  1197 	{
  1214 	{
  1198 	if(aClusterNum < KFatFirstSearchCluster || aClusterNum >= MaxClusters())
  1215 	if(aClusterNum < KFatFirstSearchCluster || aClusterNum >= MaxClusters())
  1199         {
  1216         {
  1200         __PRINT1(_L("CScanDrive::ReadFatL() bad cluster:%d\n"),aClusterNum);
  1217         __PRINT1(_L("CScanDrive::ReadFatL() bad cluster:%d\n"),aClusterNum);
  1201         IndicateErrorsFound(EBadClusterNumber);
  1218         IndicateErrorsFound(EBadClusterNumber);