userlibandfileserver/fileserver/sfat32/sl_scan32.cpp
branchRCL_3
changeset 87 2f92ad2dc5db
parent 36 538db54a451d
child 256 c1f20ce4abcf
equal deleted inserted replaced
81:e7d2d738d3c2 87:2f92ad2dc5db
    92     }
    92     }
    93 
    93 
    94 //----------------------------------------------------------------------------------------------------
    94 //----------------------------------------------------------------------------------------------------
    95 /**
    95 /**
    96     FAT type-agnostic parser. Reads whole FAT and sets up a bit vector.
    96     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.
    97     For FAT12/16 it's OK, because the FAT12/16 is fully cached.
    98 */
    98 */
    99 void CScanDrive::DoParseFatL()
    99 void CScanDrive::DoParseFatL()
   100     {
   100     {
   101     const TInt KMaxClusters = MaxClusters();
   101     const TInt KMaxClusters = MaxClusters();
   102 
   102 
   253 }
   253 }
   254 
   254 
   255 
   255 
   256 //----------------------------------------------------------------------------------------------------
   256 //----------------------------------------------------------------------------------------------------
   257 /**
   257 /**
   258     Start the scanner. The this calss description about what it actually does.
   258     Starts the scanner.
   259     @param  aMode specifies the operational mode.
   259     
       
   260     @param	aMode	Specifies the operational mode.
   260 */
   261 */
   261 void CScanDrive::StartL(TScanDriveMode aMode)
   262 void CScanDrive::StartL(TScanDriveMode aMode)
   262 	{
   263 	{
   263 	__PRINT2(_L("CScanDrive::StartL(%d), drive:%d"), aMode, iMount->DriveNumber());
   264 	__PRINT2(_L("CScanDrive::StartL(%d), drive:%d"), aMode, iMount->DriveNumber());
   264     iScanDriveMode = aMode;
   265     iScanDriveMode = aMode;
   275         //elapsedTime = (TInt)( (timeEnd.MicroSecondsFrom(timeStart)).Int64() / K1mSec);
   276         //elapsedTime = (TInt)( (timeEnd.MicroSecondsFrom(timeStart)).Int64() / K1mSec);
   276         //__PRINT1(_L("#@@@ CScanDrive #1:%d ms "), elapsedTime);
   277         //__PRINT1(_L("#@@@ CScanDrive #1:%d ms "), elapsedTime);
   277 
   278 
   278 	CheckDirStructureL();
   279 	CheckDirStructureL();
   279 
   280 
   280     //-- uncomments a line below if you need to compare real and restored FAT tables and print out all differences
   281     //-- uncomment a line below if you need to compare real and restored FAT tables and print out all differences
   281     //CompareFatsL(EFalse);
   282     //CompareFatsL(EFalse);
   282 
   283 
   283         //timeEnd.UniversalTime(); //-- take end time
   284         //timeEnd.UniversalTime(); //-- take end time
   284         //elapsedTime = (TInt)( (timeEnd.MicroSecondsFrom(timeStart)).Int64() / K1mSec);
   285         //elapsedTime = (TInt)( (timeEnd.MicroSecondsFrom(timeStart)).Int64() / K1mSec);
   285         //__PRINT1(_L("#@@@ CScanDrive #2:%d ms "), elapsedTime);
   286         //__PRINT1(_L("#@@@ CScanDrive #2:%d ms "), elapsedTime);
   361 			if(err==KErrNone)
   362 			if(err==KErrNone)
   362 				return;
   363 				return;
   363 			}
   364 			}
   364 		}
   365 		}
   365 
   366 
   366 	__ASSERT_ALWAYS(err==KErrNone,User::Leave(KErrNotFound));
   367     if(err != KErrNone)
       
   368         {
       
   369         __PRINT1(_L("CScanDrive::FindSameStartClusterL() #1 %d"), err);
       
   370         User::Leave(KErrNotFound);
       
   371         }
   367 	}
   372 	}
   368 
   373 
   369 //----------------------------------------------------------------------------------------------------
   374 //----------------------------------------------------------------------------------------------------
   370 /**
   375 /**
   371     Scan through directory structure looking for start cluster found in iMatching
   376     Scan through directory structure looking for start cluster found in iMatching
   372 
   377 
   373     @param aDirCluster Start cluster for scan to start
   378     @param aDirCluster Start cluster for scan to start
   374     @return System wide error value
   379     @return System wide error value
   375     @leave 
   380     @leave 
   376 */
   381 */
   377 TInt CScanDrive::FindStartClusterL(TInt aDirCluster)
   382 TInt CScanDrive::FindStartClusterL(TUint32 aDirCluster)
   378 	{
   383 	{
   379 	__PRINT1(_L("CScanDrive::FindStartCluster dirCluster=%d"),aDirCluster);
   384 	__PRINT1(_L("CScanDrive::FindStartCluster dirCluster=%d"),aDirCluster);
   380 	__ASSERT_ALWAYS(aDirCluster>=iMount->RootIndicator(),User::Leave(KErrCorrupt));
   385 	
       
   386 	if(aDirCluster < (TUint)iMount->RootIndicator() || aDirCluster >= MaxClusters())
       
   387         {
       
   388         __PRINT(_L("CScanDrive::FindStartCluster() #!\n"));
       
   389         IndicateErrorsFound(EBadClusterNumber);
       
   390         User::Leave(KErrCorrupt);
       
   391         }
       
   392 
       
   393 
   381 	if(++iRecursiveDepth==KMaxScanDepth)
   394 	if(++iRecursiveDepth==KMaxScanDepth)
   382 		{
   395 		{
   383 		--iRecursiveDepth;
   396 		--iRecursiveDepth;
   384 		return(KErrNotFound);
   397 		return(KErrNotFound);
   385 		}
   398 		}
       
   399 
   386 	TEntryPos entryPos(aDirCluster,0);
   400 	TEntryPos entryPos(aDirCluster,0);
   387 	TInt dirEntries=0;
   401 	TInt dirEntries=0;
   388 	FOREVER
   402 
       
   403 	for(;;)
   389 		{
   404 		{
   390 		TFatDirEntry entry;
   405 		TFatDirEntry entry;
   391 		ReadDirEntryL(entryPos,entry);
   406 		ReadDirEntryL(entryPos,entry);
       
   407 
   392 		if(entry.IsParentDirectory()||entry.IsCurrentDirectory()||entry.IsErased())
   408 		if(entry.IsParentDirectory()||entry.IsCurrentDirectory()||entry.IsErased())
   393 			{
   409 			{
   394 			if(IsEndOfRootDir(entryPos))
   410 			if(IsEndOfRootDir(entryPos))
   395 				break;
   411 				break;
   396 			MoveToNextEntryL(entryPos);
   412 			MoveToNextEntryL(entryPos);
   397 			continue;
   413 			continue;
   398 			}
   414 			}
       
   415 
   399 		if(entry.IsEndOfDirectory())
   416 		if(entry.IsEndOfDirectory())
   400 			break;
   417 			break;
   401 		TBool isComplete;
   418 		
   402 		TEntryPos vfatPos=entryPos;
   419 		TEntryPos vfatPos=entryPos;
   403 		isComplete=MoveToVFatEndL(entryPos,entry,dirEntries);
   420 		const TBool isComplete = MoveToVFatEndL(entryPos,entry,dirEntries);
   404 		__ASSERT_ALWAYS(isComplete,User::Leave(KErrBadName));
   421 		
       
   422         if(!isComplete)
       
   423             {
       
   424             __PRINT(_L("CScanDrive::FindStartCluster() #2\n"));
       
   425             IndicateErrorsFound(EEntrySetIncomplete);
       
   426             User::Leave(KErrBadName);
       
   427             }
       
   428 
   405 
   429 
   406 		TInt err=CheckEntryClusterL(entry,vfatPos);
   430 		TInt err=CheckEntryClusterL(entry,vfatPos);
   407 		if(err==KErrNone)
   431 		if(err==KErrNone)
   408 			{
   432 			{
   409 			--iRecursiveDepth;
   433 			--iRecursiveDepth;
   438 			return(KErrNone);
   462 			return(KErrNone);
   439 		}
   463 		}
   440 	else if(aEntry.Attributes()&KEntryAttDir)
   464 	else if(aEntry.Attributes()&KEntryAttDir)
   441 		return(FindStartClusterL(iMount->StartCluster(aEntry)));
   465 		return(FindStartClusterL(iMount->StartCluster(aEntry)));
   442 
   466 
   443 	return(KErrNotFound);
   467 	return KErrNotFound;
   444 	}
   468 	}
   445 
   469 
   446 //----------------------------------------------------------------------------------------------------
   470 //----------------------------------------------------------------------------------------------------
   447 /**
   471 /**
   448     Checks directory structure for errors, can be considered the start point of the scan.  
   472     Checks directory structure for errors, can be considered the start point of the scan.  
   524 		
   548 		
   525 		const TBool isComplete = MoveToVFatEndL(entryPos,entry,dirEntries);
   549 		const TBool isComplete = MoveToVFatEndL(entryPos,entry,dirEntries);
   526         
   550         
   527         if(!isComplete && CheckDiskMode())
   551         if(!isComplete && CheckDiskMode())
   528             {//-- broken VFAT entryset; in CheckDisk mode this is the FS error, abort further activity
   552             {//-- broken VFAT entryset; in CheckDisk mode this is the FS error, abort further activity
       
   553                 __PRINT(_L("CScanDrive::CheckDirL() #1"));
   529                 IndicateErrorsFound(EInvalidEntrySize);
   554                 IndicateErrorsFound(EInvalidEntrySize);
   530                 User::Leave(KErrCorrupt);
   555                 User::Leave(KErrCorrupt);
   531             }
   556             }
   532 
   557 
   533         // Only assume that this is a corrupted VFAT entry if the VFAT attributes are set; 
   558         // Only assume that this is a corrupted VFAT entry if the VFAT attributes are set; 
   575     @leave System wide error code
   600     @leave System wide error code
   576 */
   601 */
   577 void CScanDrive::ProcessEntryL(const TFatDirEntry& aEntry)
   602 void CScanDrive::ProcessEntryL(const TFatDirEntry& aEntry)
   578 	{
   603 	{
   579 	__PRINT(_L("CScanDrive::ProcessEntryL"));
   604 	__PRINT(_L("CScanDrive::ProcessEntryL"));
   580 	TInt entryAtt=aEntry.Attributes();
   605 	const TUint entryAtt=aEntry.Attributes();
   581 
   606 
   582 	__ASSERT_ALWAYS(!(entryAtt&~KEntryAttMaskSupported)&&!aEntry.IsErased(),User::Leave(KErrCorrupt));
   607     if((entryAtt & ~KEntryAttMaskSupported) || aEntry.IsErased())
       
   608         {
       
   609         __PRINT1(_L("CScanDrive::ProcessEntryL() wrong entry att: 0x%x"), entryAtt);
       
   610         IndicateErrorsFound(EEntryBadAtt);
       
   611         User::Leave(KErrCorrupt);
       
   612         }
   583 	
   613 	
   584     if(!(entryAtt&(KEntryAttDir|KEntryAttVolume)) && iMount->StartCluster(aEntry)>0)
   614     if(!(entryAtt&(KEntryAttDir|KEntryAttVolume)) && iMount->StartCluster(aEntry)>0)
   585 		{//-- this is a file with length >0. Check that its cluster chain corresponds to its size
   615 		{//-- this is a file with length >0. Check that its cluster chain corresponds to its size
   586         RecordClusterChainL(iMount->StartCluster(aEntry),(TUint) aEntry.Size());
   616         RecordClusterChainL(iMount->StartCluster(aEntry), aEntry.Size());
   587         }
   617         }
   588 	else if(entryAtt&KEntryAttDir)
   618 	else if(entryAtt&KEntryAttDir)
   589 		{//-- this is the directory, walk into it
   619 		{//-- this is the directory, walk into it
   590         CheckDirL(iMount->StartCluster(aEntry));
   620         CheckDirL(iMount->StartCluster(aEntry));
   591         }
   621         }
   599 
   629 
   600     @param aCluster Cluster chain start point
   630     @param aCluster Cluster chain start point
   601     @param aSizeInBytes Size of the file or directory in bytes
   631     @param aSizeInBytes Size of the file or directory in bytes
   602     @leave System wide error values
   632     @leave System wide error values
   603 */
   633 */
   604 void CScanDrive::RecordClusterChainL(TInt aCluster, TUint aSizeInBytes)
   634 void CScanDrive::RecordClusterChainL(TUint32 aCluster, TUint aSizeInBytes)
   605 	{
   635 	{
   606 	__PRINT2(_L("CScanDrive::RecordClusterChainL() cl:%d, sz:%d") ,aCluster, aSizeInBytes);
   636 	__PRINT2(_L("CScanDrive::RecordClusterChainL() cl:%d, sz:%d") ,aCluster, aSizeInBytes);
   607 	__ASSERT_ALWAYS(aCluster>0, User::Leave(KErrCorrupt));
   637 
       
   638     if(aCluster < KFatFirstSearchCluster || aCluster >= MaxClusters())
       
   639 	    {
       
   640         __PRINT(_L("CScanDrive::RecordClusterChainL() #0"));
       
   641         IndicateErrorsFound(EBadClusterNumber);
       
   642         User::Leave(KErrCorrupt);
       
   643         }
   608 	
   644 	
   609     TUint clusterCount;
   645     TUint clusterCount;
   610 	
   646 	
   611     if(aSizeInBytes==0)
   647     if(aSizeInBytes==0)
       
   648 		{
   612 		clusterCount=1;
   649 		clusterCount=1;
       
   650         }
   613 	else
   651 	else
   614 		{
   652 		{
   615         const TUint64 tmp = aSizeInBytes + Pow2_64(iMount->ClusterSizeLog2()) - 1;
   653         const TUint64 tmp = aSizeInBytes + Pow2_64(iMount->ClusterSizeLog2()) - 1;
   616         clusterCount = (TUint) (tmp >> iMount->ClusterSizeLog2());
   654         clusterCount = (TUint) (tmp >> iMount->ClusterSizeLog2());
   617         }
   655         }
   618 
   656 
   619 	TInt startCluster=aCluster;
   657 	TUint startCluster=aCluster;
       
   658 	
   620 	while(clusterCount)
   659 	while(clusterCount)
   621 		{
   660 		{
   622         if(IsClusterUsedL(aCluster))
   661         if(IsClusterUsedL(aCluster))
   623 			{//-- 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.
   624 			if(CheckDiskMode())
   663                 __PRINT1(_L("CScanDrive::RecordClusterChainL #1 %d"),aCluster); 
       
   664             
       
   665             if(CheckDiskMode())
   625                 {//-- in check disk mode this is a FS error; Indicate error and abort furter scanning
   666                 {//-- in check disk mode this is a FS error; Indicate error and abort furter scanning
   626                 __PRINT1(_L("CScanDrive::RecordClusterChainL #1 %d"),aCluster); 
   667                 __PRINT(_L("CScanDrive::RecordClusterChainL #1.1")); 
   627                 IndicateErrorsFound(EClusterAlreadyInUse);
   668                 IndicateErrorsFound(EClusterAlreadyInUse);
   628                 User::Leave(KErrCorrupt);
   669                 User::Leave(KErrCorrupt);
   629                 }
   670                 }
   630             
   671             
   631             __ASSERT_ALWAYS(!IsDirError() && iMatching.iStartCluster==0 && aCluster==startCluster,User::Leave(KErrCorrupt));
   672             
       
   673             if(IsDirError() || iMatching.iStartCluster > 0 || aCluster != startCluster)
       
   674                 {//-- secondary entry into this state
       
   675                 __PRINT(_L("CScanDrive::RecordClusterChainL #1.2")); 
       
   676                 IndicateErrorsFound(EClusterAlreadyInUse);
       
   677                 User::Leave(KErrCorrupt);
       
   678                 }
       
   679 
   632 			iMatching.iStartCluster=aCluster;
   680 			iMatching.iStartCluster=aCluster;
   633 			iDirError=EScanMatchingEntry;		//ERROR POINT
   681 			iDirError=EScanMatchingEntry;		//ERROR POINT
   634             IndicateErrorsFound(EScanDriveDirError); //-- indicate that we have found errors
   682             IndicateErrorsFound(EScanDriveDirError); //-- indicate that we have found errors
   635 			return;
   683 			return;
   636 			}
   684 			}
   637 
   685 
   638 		
   686 		
   639         if(clusterCount==1)
   687         if(clusterCount==1)
   640 			{
   688 			{//-- we have reached the end of the cluster chain
   641 			if(!iMount->IsEndOfClusterCh(ReadFatL(aCluster)))
   689 			if(!iMount->IsEndOfClusterCh(ReadFatL(aCluster)))
   642 				{//-- seems to be a rugged FAT artefact; File truncation had failed before and now file length is less than
   690 				{//-- seems to be a rugged FAT artefact; File truncation/extension had failed before and now file length is less than
   643                  //-- the corresponding cluster chain shall be. It will be truncated.
   691                  //-- the corresponding cluster chain shall be. It will be truncated to the size recorded in file DOS entry.
   644 				iTruncationCluster = aCluster;								
   692 				iTruncationCluster = aCluster;								
   645                 
   693                 
   646                 if(CheckDiskMode())
   694                 if(CheckDiskMode())
   647                     {//-- in check disk mode this is a FS error; Indicate error and abort furter scanning
   695                     {//-- in check disk mode this is a FS error; Indicate error and abort furter scanning
   648                     __PRINT1(_L("CScanDrive::RecordClusterChainL #2 %d"),aCluster); 
   696                     __PRINT1(_L("CScanDrive::RecordClusterChainL #2 %d"),aCluster); 
   658 		else
   706 		else
   659 			{
   707 			{
   660 			const TUint clusterVal=ReadFatL(aCluster);
   708 			const TUint clusterVal=ReadFatL(aCluster);
   661 
   709 
   662             //__PRINT2(_L("#--: %d -> %d"), aCluster, clusterVal); 
   710             //__PRINT2(_L("#--: %d -> %d"), aCluster, clusterVal); 
   663 			
   711             if(IsEofF(clusterVal) || clusterVal == KSpareCluster )
   664             __ASSERT_ALWAYS(!IsEofF(clusterVal) && clusterVal !=KSpareCluster, User::Leave(KErrCorrupt));
   712                 {//-- unexpected end of the cluster chain (it is shorter than recorded in file dir. entry)
       
   713                 __PRINT1(_L("CScanDrive::RecordClusterChainL #3 %d"),clusterVal); 
       
   714                 IndicateErrorsFound(EBadClusterValue);
       
   715                 User::Leave(KErrCorrupt);
       
   716                 }
       
   717 
       
   718 
   665 			MarkClusterUsedL(aCluster);
   719 			MarkClusterUsedL(aCluster);
   666 			aCluster=clusterVal;
   720 			aCluster=clusterVal;
   667 			--clusterCount;
   721 			--clusterCount;
   668 			}
   722 			}
   669 		
   723 		
   686 	__PRINT2(_L("CScanDrive::MoveToVFatEndL cluster=%d,pos=%d"),aPos.iCluster,aPos.iPos);
   740 	__PRINT2(_L("CScanDrive::MoveToVFatEndL cluster=%d,pos=%d"),aPos.iCluster,aPos.iPos);
   687 	if(!aEntry.IsVFatEntry())
   741 	if(!aEntry.IsVFatEntry())
   688 		return IsDosEntry(aEntry);
   742 		return IsDosEntry(aEntry);
   689 
   743 
   690 	TInt toFollow=aEntry.NumFollowing();
   744 	TInt toFollow=aEntry.NumFollowing();
   691 	__ASSERT_ALWAYS(toFollow>0 && !aEntry.IsErased(), User::Leave(KErrCorrupt));
   745 
   692 
   746     if(toFollow <=0 || aEntry.IsErased())
   693 	FOREVER
   747         {
       
   748         __PRINT1(_L("CScanDrive::MoveToVFatEndL #1 %d"),toFollow);
       
   749         IndicateErrorsFound(EEntrySetIncomplete);
       
   750         User::Leave(KErrCorrupt);
       
   751         }
       
   752 
       
   753 
       
   754 	for(;;)
   694 		{
   755 		{
   695 		MoveToNextEntryL(aPos);
   756 		MoveToNextEntryL(aPos);
   696 		ReadDirEntryL(aPos,aEntry);
   757 		ReadDirEntryL(aPos,aEntry);
   697 		++aDirLength;
   758 		++aDirLength;
   698 		--toFollow;
   759 		--toFollow;
   729     @param aEntry Entry to check
   790     @param aEntry Entry to check
   730     @return ETrue if aEntry is a dos entry
   791     @return ETrue if aEntry is a dos entry
   731 */
   792 */
   732 TBool CScanDrive::IsDosEntry(const TFatDirEntry& aEntry)const
   793 TBool CScanDrive::IsDosEntry(const TFatDirEntry& aEntry)const
   733 	{
   794 	{
   734 	TBool res = !(aEntry.Attributes()&~KEntryAttMaskSupported) && !aEntry.IsErased() && !aEntry.IsVFatEntry() && !aEntry.IsEndOfDirectory();
   795 	const TBool res = !(aEntry.Attributes()&~KEntryAttMaskSupported) && !aEntry.IsErased() && !aEntry.IsVFatEntry() && !aEntry.IsEndOfDirectory();
   735 	return res;
   796 	return res;
   736 	} 
   797 	} 
   737 
   798 
   738 //----------------------------------------------------------------------------------------------------
   799 //----------------------------------------------------------------------------------------------------
   739 /**
   800 /**
   744     @leave KErrCorrupt Occurs if the entry is not valid
   805     @leave KErrCorrupt Occurs if the entry is not valid
   745 */
   806 */
   746 void CScanDrive::AddPartialVFatL(const TEntryPos& aStartPos, const TFatDirEntry& aEntry)
   807 void CScanDrive::AddPartialVFatL(const TEntryPos& aStartPos, const TFatDirEntry& aEntry)
   747 	{
   808 	{
   748 	__PRINT2(_L("CScanDrive::AddPartialVFatL cluster=%d pos=%d"),aStartPos.iCluster,aStartPos.iPos);
   809 	__PRINT2(_L("CScanDrive::AddPartialVFatL cluster=%d pos=%d"),aStartPos.iCluster,aStartPos.iPos);
   749 	__ASSERT_ALWAYS(!IsDirError(),User::Leave(KErrCorrupt));
   810 
       
   811     if(IsDirError())
       
   812         {
       
   813         __PRINT(_L("CScanDrive::AddPartialVFatL #1"));
       
   814         User::Leave(KErrCorrupt);
       
   815         }
       
   816 
   750 	iPartEntry.iEntryPos=aStartPos;
   817 	iPartEntry.iEntryPos=aStartPos;
   751 	iPartEntry.iEntry=aEntry;
   818 	iPartEntry.iEntry=aEntry;
   752 	iDirError=EScanPartEntry;
   819 	iDirError=EScanPartEntry;
   753 	}
   820 	}
   754 
   821 
   761     @return 
   828     @return 
   762 */
   829 */
   763 TBool CScanDrive::AddMatchingEntryL(const TEntryPos& aEntryPos)
   830 TBool CScanDrive::AddMatchingEntryL(const TEntryPos& aEntryPos)
   764 	{
   831 	{
   765 	__PRINT2(_L("CScanDrive::AddMatchingEntryL cluster=%d pos=%d"),aEntryPos.iCluster,aEntryPos.iPos);
   832 	__PRINT2(_L("CScanDrive::AddMatchingEntryL cluster=%d pos=%d"),aEntryPos.iCluster,aEntryPos.iPos);
   766 	__ASSERT_ALWAYS(iMatching.iStartCluster>0 && iMatching.iCount<KMaxMatchingEntries,User::Leave(KErrCorrupt));
   833 	
       
   834     if(iMatching.iStartCluster <= 0 || iMatching.iCount >= KMaxMatchingEntries)
       
   835         {
       
   836         __PRINT(_L("CScanDrive::AddMatchingEntryL #1"));
       
   837         User::Leave(KErrCorrupt);
       
   838         }
       
   839 
       
   840 
   767 	iMatching.iEntries[iMatching.iCount++]=aEntryPos;
   841 	iMatching.iEntries[iMatching.iCount++]=aEntryPos;
   768 	return iMatching.iCount==KMaxMatchingEntries;
   842 	return iMatching.iCount==KMaxMatchingEntries;
   769 	}
   843 	}
   770 
   844 
   771 
   845 
   871 //----------------------------------------------------------------------------------------------------
   945 //----------------------------------------------------------------------------------------------------
   872 /**
   946 /**
   873     Read the "Rugged FAT" ID, stored in reserved2 in the Dos entry or associated with the Dos entry of the 
   947     Read the "Rugged FAT" ID, stored in reserved2 in the Dos entry or associated with the Dos entry of the 
   874     Entry at the position passed in. This is used to find which version of two matching entries should be kept.
   948     Entry at the position passed in. This is used to find which version of two matching entries should be kept.
   875 
   949 
   876 
       
   877     @param aVFatPos Position of an entry to read ID from
   950     @param aVFatPos Position of an entry to read ID from
   878     @leave System wide error codes
   951     @leave System wide error codes
   879     @return The ID found in reserved2 field of dos entry 
   952     @return The ID found in reserved2 field of dos entry 
   880 */
   953 */
   881 TInt CScanDrive::GetReservedidL(TEntryPos aVFatPos)
   954 TInt CScanDrive::GetReservedidL(TEntryPos aVFatPos)
   884 	TFatDirEntry entry;
   957 	TFatDirEntry entry;
   885 	ReadDirEntryL(aVFatPos,entry);
   958 	ReadDirEntryL(aVFatPos,entry);
   886 	if(!IsDosEntry(entry))
   959 	if(!IsDosEntry(entry))
   887 		{
   960 		{
   888 		TInt toMove=entry.NumFollowing();
   961 		TInt toMove=entry.NumFollowing();
       
   962 		
   889 		while(toMove--)
   963 		while(toMove--)
   890 			MoveToNextEntryL(aVFatPos);
   964 			MoveToNextEntryL(aVFatPos);
       
   965 		
   891 		ReadDirEntryL(aVFatPos,entry);
   966 		ReadDirEntryL(aVFatPos,entry);
   892 		}
   967 		}
       
   968 	
   893 	return(entry.RuggedFatEntryId());
   969 	return(entry.RuggedFatEntryId());
   894 	}
   970 	}
   895 
   971 
   896 //----------------------------------------------------------------------------------------------------
   972 //----------------------------------------------------------------------------------------------------
   897 /**
   973 /**
   914 */
   990 */
   915 void CScanDrive::FixMatchingEntryL()
   991 void CScanDrive::FixMatchingEntryL()
   916 	{
   992 	{
   917 	
   993 	
   918     __PRINT1(_L("CScanDrive::FixMatchingEntryL() start cluster=%d"),iMatching.iStartCluster);
   994     __PRINT1(_L("CScanDrive::FixMatchingEntryL() start cluster=%d"),iMatching.iStartCluster);
   919 	__ASSERT_ALWAYS(iMatching.iCount==KMaxMatchingEntries,User::Leave(KErrCorrupt));
   995 	
       
   996     if(iMatching.iCount != KMaxMatchingEntries)
       
   997         {
       
   998         __PRINT1(_L("CScanDrive::FixMatchingEntryL() #1 %d"), iMatching.iCount);            
       
   999         User::Leave(KErrCorrupt);
       
  1000         }
       
  1001 
   920 	ASSERT(!CheckDiskMode());
  1002 	ASSERT(!CheckDiskMode());
   921 
  1003 
   922     TInt idOne=GetReservedidL(iMatching.iEntries[0]);
  1004     const TInt idOne=GetReservedidL(iMatching.iEntries[0]);
   923 	TInt idTwo=GetReservedidL(iMatching.iEntries[1]);
  1005 	const TInt idTwo=GetReservedidL(iMatching.iEntries[1]);
   924 	TFatDirEntry entry;
  1006 	TFatDirEntry entry;
   925 	TInt num=idOne>idTwo?0:1;
  1007 	
       
  1008     const TInt num = idOne>idTwo ? 0:1;
   926 	ReadDirEntryL(iMatching.iEntries[num],entry);
  1009 	ReadDirEntryL(iMatching.iEntries[num],entry);
       
  1010 
   927 	iMount->EraseDirEntryL(iMatching.iEntries[num],entry);
  1011 	iMount->EraseDirEntryL(iMatching.iEntries[num],entry);
       
  1012     
   928     IndicateErrorsFound(EScanDriveDirError); //-- indicate that we have found errors
  1013     IndicateErrorsFound(EScanDriveDirError); //-- indicate that we have found errors
   929 	}
  1014 	}
   930 
  1015 
   931 //----------------------------------------------------------------------------------------------------
  1016 //----------------------------------------------------------------------------------------------------
   932 /**
  1017 /**
   962 	if(iListArrayIndex>=KMaxArrayDepth)
  1047 	if(iListArrayIndex>=KMaxArrayDepth)
   963 		return;
  1048 		return;
   964 
  1049 
   965 	if(iClusterListArray[iListArrayIndex]==NULL)
  1050 	if(iClusterListArray[iListArrayIndex]==NULL)
   966 		iClusterListArray[iListArrayIndex]=new(ELeave) RArray<TInt>(KClusterListGranularity);
  1051 		iClusterListArray[iListArrayIndex]=new(ELeave) RArray<TInt>(KClusterListGranularity);
       
  1052 
   967 	iClusterListArray[iListArrayIndex]->Append(aCluster);
  1053 	iClusterListArray[iListArrayIndex]->Append(aCluster);
   968 	}
  1054 	}
   969 
  1055 
   970 
  1056 
   971 //----------------------------------------------------------------------------------------------------
  1057 //----------------------------------------------------------------------------------------------------
  1109 */
  1195 */
  1110 TUint32 CScanDrive::ReadFatL(TUint aClusterNum) 
  1196 TUint32 CScanDrive::ReadFatL(TUint aClusterNum) 
  1111 	{
  1197 	{
  1112 	if(aClusterNum < KFatFirstSearchCluster || aClusterNum >= MaxClusters())
  1198 	if(aClusterNum < KFatFirstSearchCluster || aClusterNum >= MaxClusters())
  1113         {
  1199         {
       
  1200         __PRINT1(_L("CScanDrive::ReadFatL() bad cluster:%d\n"),aClusterNum);
  1114         IndicateErrorsFound(EBadClusterNumber);
  1201         IndicateErrorsFound(EBadClusterNumber);
  1115         User::Leave(KErrCorrupt);
  1202         User::Leave(KErrCorrupt);
  1116         }
  1203         }
  1117 
  1204 
  1118     //-- actually, ReadL() can leave with some error code, that won't be reflected in IndicateErrorsFound().
  1205     //-- actually, ReadL() can leave with some error code, that won't be reflected in IndicateErrorsFound().
  1127 */
  1214 */
  1128 void CScanDrive::MarkClusterUsedL(TUint aClusterNum)
  1215 void CScanDrive::MarkClusterUsedL(TUint aClusterNum)
  1129 	{
  1216 	{
  1130 	if(aClusterNum < KFatFirstSearchCluster || aClusterNum >= MaxClusters())
  1217 	if(aClusterNum < KFatFirstSearchCluster || aClusterNum >= MaxClusters())
  1131         {
  1218         {
       
  1219         __PRINT1(_L("CScanDrive::MarkClusterUsedL() bad cluster:%d\n"),aClusterNum);
  1132         IndicateErrorsFound(EBadClusterNumber);
  1220         IndicateErrorsFound(EBadClusterNumber);
  1133         User::Leave(KErrCorrupt);
  1221         User::Leave(KErrCorrupt);
  1134         }
  1222         }
  1135 
  1223 
  1136     iScanFatBits.SetBit(aClusterNum);
  1224     iScanFatBits.SetBit(aClusterNum);
  1143 */
  1231 */
  1144 TBool CScanDrive::IsClusterUsedL(TUint aClusterNum) 
  1232 TBool CScanDrive::IsClusterUsedL(TUint aClusterNum) 
  1145 	{
  1233 	{
  1146 	if(aClusterNum < KFatFirstSearchCluster || aClusterNum >= MaxClusters())
  1234 	if(aClusterNum < KFatFirstSearchCluster || aClusterNum >= MaxClusters())
  1147         {
  1235         {
       
  1236         __PRINT1(_L("CScanDrive::IsClusterUsedL() bad cluster:%d\n"),aClusterNum);
  1148         IndicateErrorsFound(EBadClusterNumber);
  1237         IndicateErrorsFound(EBadClusterNumber);
  1149         User::Leave(KErrCorrupt);
  1238         User::Leave(KErrCorrupt);
  1150         }
  1239         }
  1151 
  1240 
  1152     return iScanFatBits[aClusterNum];
  1241     return iScanFatBits[aClusterNum];