userlibandfileserver/fileserver/sfat/sl_scan.cpp
changeset 15 4122176ea935
parent 0 a41df078684a
equal deleted inserted replaced
0:a41df078684a 15:4122176ea935
    19 /**
    19 /**
    20  @file
    20  @file
    21  @internalTechnology
    21  @internalTechnology
    22 */
    22 */
    23 
    23 
       
    24 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       
    25 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       
    26 //!!
       
    27 //!! WARNING!! DO NOT edit this file !! '\sfat' component is obsolete and is not being used. '\sfat32'replaces it
       
    28 //!!
       
    29 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       
    30 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       
    31 
    24 
    32 
    25 //#define DEBUG_SCANDRIVE
    33 //#define DEBUG_SCANDRIVE
    26 
    34 
    27 #include "sl_std.h"
    35 #include "sl_std.h"
    28 #include "sl_scandrv.h"
    36 #include "sl_scandrv.h"
    29 
    37 
    30 const TInt KEndOfDirectory			= 0xFFFF;   ///< End of directory marker
    38 const TInt KEndOfDirectory          = 0xFFFF;   ///< End of directory marker
    31 const TInt KMaxScanDepth			= 20;       ///< Maximum scan depth of to avoid stack over flow 
    39 const TInt KMaxScanDepth            = 20;       ///< Maximum scan depth of to avoid stack over flow 
    32 const TInt KClusterListGranularity	= 8;        ///< Granularity of cluster list used for storage of clusters when KMaxScanDepth is reached
    40 const TInt KClusterListGranularity  = 8;        ///< Granularity of cluster list used for storage of clusters when KMaxScanDepth is reached
    33 
    41 
    34 /**
    42 /**
    35 Creates a CScanDrive
    43 Creates a CScanDrive
    36 
    44 
    37 @param aMount The owning mount
    45 @param aMount The owning mount
    38 */
    46 */
    39 CScanDrive* CScanDrive::NewL(CFatMountCB* aMount)
    47 CScanDrive* CScanDrive::NewL(CFatMountCB* aMount)
    40 	{
    48     {
    41 	if(aMount==NULL)
    49     if(aMount==NULL)
    42 		User::Leave(KErrArgument);
    50         User::Leave(KErrArgument);
    43 	CScanDrive* self=new (ELeave) CScanDrive();
    51     CScanDrive* self=new (ELeave) CScanDrive();
    44 	CleanupStack::PushL(self);
    52     CleanupStack::PushL(self);
    45 	self->ConstructL(aMount);
    53     self->ConstructL(aMount);
    46 	CleanupStack::Pop();
    54     CleanupStack::Pop();
    47 	return self;
    55     return self;
    48 	}
    56     }
    49 
    57 
    50 
    58 
    51 CScanDrive::CScanDrive()
    59 CScanDrive::CScanDrive()
    52 //
    60 //
    53 // Constructor
    61 // Constructor
    54 //
    62 //
    55 	{
    63     {
    56 	}
    64     }
    57 
    65 
    58 
    66 
    59 CScanDrive::~CScanDrive()
    67 CScanDrive::~CScanDrive()
    60 //
    68 //
    61 // Destructor
    69 // Destructor
    62 //
    70 //
    63 	{
    71     {
    64 	delete iNewFat;
    72     delete iNewFat;
    65 	for(TInt i=0;i<KMaxArrayDepth && iClusterListArray[i]!=NULL;++i)
    73     for(TInt i=0;i<KMaxArrayDepth && iClusterListArray[i]!=NULL;++i)
    66 		{
    74         {
    67 		iClusterListArray[i]->Close();
    75         iClusterListArray[i]->Close();
    68 		delete iClusterListArray[i];
    76         delete iClusterListArray[i];
    69 		}
    77         }
    70 	}
    78     }
    71 
    79 
    72 
    80 
    73 void CScanDrive::ConstructL(CFatMountCB* aMount)
    81 void CScanDrive::ConstructL(CFatMountCB* aMount)
    74 //
    82 //
    75 // Create the new fat and initalise
    83 // Create the new fat and initalise
    76 //
    84 //
    77 	{
    85     {
    78 	iMount=aMount;
    86     iMount=aMount;
    79 	iNewFat=CCheckFatTable::NewL(aMount);
    87     iNewFat=CCheckFatTable::NewL(aMount);
    80 	iNewFat->InitializeL();
    88     iNewFat->InitializeL();
    81 	}
    89     }
    82 
    90 
    83 
    91 
    84 TBool CScanDrive::AlreadyExistsL(TInt aCluster)const
    92 TBool CScanDrive::AlreadyExistsL(TInt aCluster)const
    85 //
    93 //
    86 //	Return ETrue if aCluster in the new fat contains a non-zero entry
    94 //  Return ETrue if aCluster in the new fat contains a non-zero entry
    87 //
    95 //
    88 	{
    96     {
    89 	return(iNewFat->ReadL(aCluster)!=0);
    97     return(iNewFat->ReadL(aCluster)!=0);
    90 	}
    98     }
    91 
    99 
    92 
   100 
    93 TBool CScanDrive::IsEndOfRootDir(const TEntryPos& aPos)const
   101 TBool CScanDrive::IsEndOfRootDir(const TEntryPos& aPos)const
    94 //
   102 //
    95 // Return ETrue if aPos is the last entry in the root directory
   103 // Return ETrue if aPos is the last entry in the root directory
    96 //
   104 //
    97 	{
   105     {
    98 	return(iMount->IsRootDir(aPos)&&(iMount->StartOfRootDirInBytes()+aPos.iPos==(iMount->RootDirEnd()-KSizeOfFatDirEntry)));
   106     return(iMount->IsRootDir(aPos)&&(iMount->StartOfRootDirInBytes()+aPos.iPos==(iMount->RootDirEnd()-KSizeOfFatDirEntry)));
    99 	}
   107     }
   100 
   108 
   101 /**
   109 /**
   102 @param aVal Value of the cluster to be tested
   110 @param aVal Value of the cluster to be tested
   103 @return ETrue if aVal is the end of cluster marker
   111 @return ETrue if aVal is the end of cluster marker
   104 */
   112 */
   105 TBool CScanDrive::IsEofF(TInt aVal)const 
   113 TBool CScanDrive::IsEofF(TInt aVal)const 
   106 	{
   114     {
   107     return iMount->IsEndOfClusterCh(aVal);
   115     return iMount->IsEndOfClusterCh(aVal);
   108 	}
   116     }
   109 
   117 
   110 /**
   118 /**
   111 @return True if a directory error has been found
   119 @return True if a directory error has been found
   112 */
   120 */
   113 TBool CScanDrive::IsDirError()const
   121 TBool CScanDrive::IsDirError()const
   114 	{
   122     {
   115 	return(iDirError!=0);
   123     return(iDirError!=0);
   116 	}
   124     }
   117 
   125 
   118 
   126 
   119 
   127 
   120 /**
   128 /**
   121     After StartL() and finishing allows us to know if there were any problems at all.
   129     After StartL() and finishing allows us to know if there were any problems at all.
   144 
   152 
   145 @return The result of the scan
   153 @return The result of the scan
   146 @leave 
   154 @leave 
   147 */
   155 */
   148 TInt CScanDrive::StartL()
   156 TInt CScanDrive::StartL()
   149 	{
   157     {
   150 	__PRINT(_L("CScanDrive::StartL"));
   158     __PRINT(_L("CScanDrive::StartL"));
   151 	// check directory structure
   159     // check directory structure
   152 	CheckDirStructureL();
   160     CheckDirStructureL();
   153 #if defined(DEBUG_SCANDRIVE)
   161 #if defined(DEBUG_SCANDRIVE)
   154 	CompareFatsL();
   162     CompareFatsL();
   155 #endif
   163 #endif
   156 	// fix error in directory structure
   164     // fix error in directory structure
   157 	if(IsDirError())
   165     if(IsDirError())
   158 		FixupDirErrorL();
   166         FixupDirErrorL();
   159 	// flush new fat
   167     // flush new fat
   160 	WriteNewFatsL();
   168     WriteNewFatsL();
   161 #if defined(DEBUG_SCANDRIVE)
   169 #if defined(DEBUG_SCANDRIVE)
   162 	PrintErrors();
   170     PrintErrors();
   163 #endif
   171 #endif
   164 	return KErrNone;
   172     return KErrNone;
   165 	}
   173     }
   166 
   174 
   167 /**
   175 /**
   168 Fix errors detected by the drive scan
   176 Fix errors detected by the drive scan
   169 
   177 
   170 @leave System wide error code
   178 @leave System wide error code
   171 */
   179 */
   172 void CScanDrive::FixupDirErrorL()
   180 void CScanDrive::FixupDirErrorL()
   173 	{
   181     {
   174 	if(!IsDirError())
   182     if(!IsDirError())
   175 		return;
   183         return;
   176 	if(iDirError==EScanMatchingEntry)
   184     if(iDirError==EScanMatchingEntry)
   177 		{
   185         {
   178 		FindSameStartClusterL();
   186         FindSameStartClusterL();
   179 		FixMatchingEntryL();
   187         FixMatchingEntryL();
   180 		}
   188         }
   181 	else
   189     else
   182 		{
   190         {
   183         FixPartEntryL();
   191         FixPartEntryL();
   184         }
   192         }
   185 
   193 
   186     IndicateErrorsFound(); //-- indicate that we have found errors
   194     IndicateErrorsFound(); //-- indicate that we have found errors
   187 	}
   195     }
   188 
   196 
   189 /**
   197 /**
   190 Find positions of entries with same start cluster for error correction, searches
   198 Find positions of entries with same start cluster for error correction, searches
   191 the whole volume. Starts at the root directory. 
   199 the whole volume. Starts at the root directory. 
   192 
   200 
   193 @leave System wide error code
   201 @leave System wide error code
   194 */
   202 */
   195 void CScanDrive::FindSameStartClusterL()
   203 void CScanDrive::FindSameStartClusterL()
   196 	{
   204     {
   197 	TInt err=FindStartClusterL(0);
   205     TInt err=FindStartClusterL(0);
   198 	if(err==KErrNone)
   206     if(err==KErrNone)
   199 		return;
   207         return;
   200 	for(TInt i=0;i<KMaxArrayDepth && iClusterListArray[i]!=NULL;++i)
   208     for(TInt i=0;i<KMaxArrayDepth && iClusterListArray[i]!=NULL;++i)
   201 		{
   209         {
   202 		RArray<TInt>* clusterList=iClusterListArray[i];
   210         RArray<TInt>* clusterList=iClusterListArray[i];
   203 		for(TInt j=0;j<clusterList->Count();++j)
   211         for(TInt j=0;j<clusterList->Count();++j)
   204 			{
   212             {
   205 			iRecursiveDepth=0;
   213             iRecursiveDepth=0;
   206 			err=FindStartClusterL((*clusterList)[j]);
   214             err=FindStartClusterL((*clusterList)[j]);
   207 			if(err==KErrNone)
   215             if(err==KErrNone)
   208 				return;
   216                 return;
   209 			}
   217             }
   210 		}
   218         }
   211 	__ASSERT_ALWAYS(err==KErrNone,User::Leave(KErrNotFound));
   219     __ASSERT_ALWAYS(err==KErrNone,User::Leave(KErrNotFound));
   212 	}
   220     }
   213 /**
   221 /**
   214 Scan through directory structure looking for start cluster found in iMatching
   222 Scan through directory structure looking for start cluster found in iMatching
   215 
   223 
   216 @param aDirCluster Start cluster for scan to start
   224 @param aDirCluster Start cluster for scan to start
   217 @return System wide error value
   225 @return System wide error value
   218 @leave 
   226 @leave 
   219 */
   227 */
   220 TInt CScanDrive::FindStartClusterL(TInt aDirCluster)
   228 TInt CScanDrive::FindStartClusterL(TInt aDirCluster)
   221 	{
   229     {
   222 	__PRINT1(_L("CScanDrive::FindStartCluster dirCluster=%d"),aDirCluster);
   230     __PRINT1(_L("CScanDrive::FindStartCluster dirCluster=%d"),aDirCluster);
   223 	__ASSERT_ALWAYS(aDirCluster>=0,User::Leave(KErrCorrupt));
   231     __ASSERT_ALWAYS(aDirCluster>=0,User::Leave(KErrCorrupt));
   224 	if(++iRecursiveDepth==KMaxScanDepth)
   232     if(++iRecursiveDepth==KMaxScanDepth)
   225 		{
   233         {
   226 		--iRecursiveDepth;
   234         --iRecursiveDepth;
   227 		return(KErrNotFound);
   235         return(KErrNotFound);
   228 		}
   236         }
   229 	TEntryPos entryPos(aDirCluster,0);
   237     TEntryPos entryPos(aDirCluster,0);
   230 	TInt dirEntries=0;
   238     TInt dirEntries=0;
   231 	FOREVER
   239     FOREVER
   232 		{
   240         {
   233 		TFatDirEntry entry;
   241         TFatDirEntry entry;
   234 		iMount->ReadDirEntryL(entryPos,entry);
   242         iMount->ReadDirEntryL(entryPos,entry);
   235 		if(entry.IsParentDirectory()||entry.IsCurrentDirectory()||entry.IsErased())
   243         if(entry.IsParentDirectory()||entry.IsCurrentDirectory()||entry.IsErased())
   236 			{
   244             {
   237 			if(IsEndOfRootDir(entryPos))
   245             if(IsEndOfRootDir(entryPos))
   238 				break;
   246                 break;
   239 			iMount->MoveToNextEntryL(entryPos);
   247             iMount->MoveToNextEntryL(entryPos);
   240 			continue;
   248             continue;
   241 			}
   249             }
   242 		if(entry.IsEndOfDirectory())
   250         if(entry.IsEndOfDirectory())
   243 			break;
   251             break;
   244 		TBool isComplete;
   252         TBool isComplete;
   245 		TEntryPos vfatPos=entryPos;
   253         TEntryPos vfatPos=entryPos;
   246 		isComplete=MoveToVFatEndL(entryPos,entry,dirEntries);
   254         isComplete=MoveToVFatEndL(entryPos,entry,dirEntries);
   247 		__ASSERT_ALWAYS(isComplete,User::Leave(KErrBadName));
   255         __ASSERT_ALWAYS(isComplete,User::Leave(KErrBadName));
   248 		TInt err=CheckEntryClusterL(entry,vfatPos);
   256         TInt err=CheckEntryClusterL(entry,vfatPos);
   249 		if(err==KErrNone)
   257         if(err==KErrNone)
   250 			{
   258             {
   251 			--iRecursiveDepth;
   259             --iRecursiveDepth;
   252 			return(err);
   260             return(err);
   253 			}
   261             }
   254 		if(IsEndOfRootDir(entryPos))
   262         if(IsEndOfRootDir(entryPos))
   255 			break;
   263             break;
   256 		iMount->MoveToNextEntryL(entryPos);
   264         iMount->MoveToNextEntryL(entryPos);
   257 		}
   265         }
   258 	--iRecursiveDepth;
   266     --iRecursiveDepth;
   259 	return(KErrNotFound);
   267     return(KErrNotFound);
   260 	}
   268     }
   261 
   269 
   262 /**
   270 /**
   263 Procces aEntry to find matching start cluster
   271 Procces aEntry to find matching start cluster
   264 
   272 
   265 @param aEntry Directory entry to check
   273 @param aEntry Directory entry to check
   266 @param aEntryPos Position of directory to check
   274 @param aEntryPos Position of directory to check
   267 @return System wide error value
   275 @return System wide error value
   268 @leave 
   276 @leave 
   269 */
   277 */
   270 TInt CScanDrive::CheckEntryClusterL(const TFatDirEntry& aEntry, const TEntryPos& aEntryPos)
   278 TInt CScanDrive::CheckEntryClusterL(const TFatDirEntry& aEntry, const TEntryPos& aEntryPos)
   271 	{
   279     {
   272 	__PRINT(_L("CScanDrive::CheckEntryClusterL"));
   280     __PRINT(_L("CScanDrive::CheckEntryClusterL"));
   273 	if(iMount->StartCluster(aEntry)==iMatching.iStartCluster)
   281     if(iMount->StartCluster(aEntry)==iMatching.iStartCluster)
   274 		{
   282         {
   275 		TBool complete=AddMatchingEntryL(aEntryPos);
   283         TBool complete=AddMatchingEntryL(aEntryPos);
   276 		if(complete)
   284         if(complete)
   277 			return(KErrNone);
   285             return(KErrNone);
   278 		}
   286         }
   279 	else if(aEntry.Attributes()&KEntryAttDir)
   287     else if(aEntry.Attributes()&KEntryAttDir)
   280 		return(FindStartClusterL(iMount->StartCluster(aEntry)));
   288         return(FindStartClusterL(iMount->StartCluster(aEntry)));
   281 	return(KErrNotFound);
   289     return(KErrNotFound);
   282 	}
   290     }
   283 
   291 
   284 /**
   292 /**
   285 Checks directory strucutre for errors, can be considered the start point of the scan.  
   293 Checks directory strucutre for errors, can be considered the start point of the scan.  
   286 Handles recursion depth to avoid stack overflow.
   294 Handles recursion depth to avoid stack overflow.
   287 
   295 
   288 @leave System wide error code
   296 @leave System wide error code
   289 */
   297 */
   290 void CScanDrive::CheckDirStructureL()
   298 void CScanDrive::CheckDirStructureL()
   291 	{
   299     {
   292 	CheckDirL(iMount->RootIndicator());
   300     CheckDirL(iMount->RootIndicator());
   293 	// Due to recursive nature of CheckDirL when a depth of
   301     // Due to recursive nature of CheckDirL when a depth of
   294 	// KMaxScanDepth is reached clusters are stored in a list
   302     // KMaxScanDepth is reached clusters are stored in a list
   295 	// and passed into CheckDirL afresh
   303     // and passed into CheckDirL afresh
   296 	for(TInt i=0;i<KMaxArrayDepth && iClusterListArray[i]!=NULL;++i)
   304     for(TInt i=0;i<KMaxArrayDepth && iClusterListArray[i]!=NULL;++i)
   297 		{
   305         {
   298 		RArray<TInt>* clusterList=iClusterListArray[i];
   306         RArray<TInt>* clusterList=iClusterListArray[i];
   299 		++iListArrayIndex;
   307         ++iListArrayIndex;
   300 		for(TInt j=0;j<clusterList->Count();++j)
   308         for(TInt j=0;j<clusterList->Count();++j)
   301 			{
   309             {
   302 			iRecursiveDepth=0;
   310             iRecursiveDepth=0;
   303 			CheckDirL((*clusterList)[j]);
   311             CheckDirL((*clusterList)[j]);
   304 			}
   312             }
   305 		}
   313         }
   306 	}
   314     }
   307 /**
   315 /**
   308 Function is called recursively with Process entry untill the whole volume has been scanned.
   316 Function is called recursively with Process entry untill the whole volume has been scanned.
   309 Each directory entry is scanned for errors, these are recorded for later fixing. 
   317 Each directory entry is scanned for errors, these are recorded for later fixing. 
   310 
   318 
   311 @param aCluster Directory cluster to start checking
   319 @param aCluster Directory cluster to start checking
   312 @leave System wide error codes
   320 @leave System wide error codes
   313 */
   321 */
   314 void CScanDrive::CheckDirL(TInt aCluster)
   322 void CScanDrive::CheckDirL(TInt aCluster)
   315 	{
   323     {
   316 	__PRINT1(_L("CScanDrive::CheckDirL aCluster=%d"),aCluster);
   324     __PRINT1(_L("CScanDrive::CheckDirL aCluster=%d"),aCluster);
   317 	__ASSERT_ALWAYS(aCluster>=0,User::Leave(KErrCorrupt));
   325     __ASSERT_ALWAYS(aCluster>=0,User::Leave(KErrCorrupt));
   318 	// check depth of recursion
   326     // check depth of recursion
   319 	if(++iRecursiveDepth==KMaxScanDepth)
   327     if(++iRecursiveDepth==KMaxScanDepth)
   320 		{
   328         {
   321 		AddToClusterListL(aCluster);
   329         AddToClusterListL(aCluster);
   322 		--iRecursiveDepth;
   330         --iRecursiveDepth;
   323 		return;
   331         return;
   324 		}
   332         }
   325 #if defined(DEBUG_SCANDRIVE)
   333 #if defined(DEBUG_SCANDRIVE)
   326 	++iDirsChecked;
   334     ++iDirsChecked;
   327 #endif
   335 #endif
   328 	TEntryPos entryPos(aCluster,0);
   336     TEntryPos entryPos(aCluster,0);
   329 	TInt dirEntries=0;
   337     TInt dirEntries=0;
   330 	FOREVER
   338     FOREVER
   331 		{
   339         {
   332 		TFatDirEntry entry;
   340         TFatDirEntry entry;
   333 		iMount->ReadDirEntryL(entryPos,entry);
   341         iMount->ReadDirEntryL(entryPos,entry);
   334 		if(!iMount->IsEndOfClusterCh(entryPos.iCluster))
   342         if(!iMount->IsEndOfClusterCh(entryPos.iCluster))
   335 			++dirEntries;
   343             ++dirEntries;
   336 		if(entry.IsParentDirectory()||entry.IsCurrentDirectory()||entry.IsErased())
   344         if(entry.IsParentDirectory()||entry.IsCurrentDirectory()||entry.IsErased())
   337 			{
   345             {
   338 			if(IsEndOfRootDir(entryPos))
   346             if(IsEndOfRootDir(entryPos))
   339 				break;
   347                 break;
   340 			iMount->MoveToNextEntryL(entryPos);
   348             iMount->MoveToNextEntryL(entryPos);
   341 			continue;
   349             continue;
   342 			}
   350             }
   343 		if(entry.IsEndOfDirectory())
   351         if(entry.IsEndOfDirectory())
   344 			{
   352             {
   345 			if(aCluster)	
   353             if(aCluster)    
   346 				WriteClusterChainL(aCluster,dirEntries<<KSizeOfFatDirEntryLog2);
   354                 WriteClusterChainL(aCluster,dirEntries<<KSizeOfFatDirEntryLog2);
   347 			break;
   355             break;
   348 			}
   356             }
   349 		TEntryPos origPos=entryPos;
   357         TEntryPos origPos=entryPos;
   350 		TFatDirEntry origEntry=entry;
   358         TFatDirEntry origEntry=entry;
   351 		TInt origDirEntries=dirEntries;
   359         TInt origDirEntries=dirEntries;
   352 		TBool isComplete;
   360         TBool isComplete;
   353 		isComplete=MoveToVFatEndL(entryPos,entry,dirEntries);
   361         isComplete=MoveToVFatEndL(entryPos,entry,dirEntries);
   354 		// Only assume that this is a corrupted VFAT entry if the VFAT attributes are set; 
   362         // Only assume that this is a corrupted VFAT entry if the VFAT attributes are set; 
   355 		// assuming a non-VFAT corrupted entry is a VFAT entry is dangerous as we then assume that the 
   363         // assuming a non-VFAT corrupted entry is a VFAT entry is dangerous as we then assume that the 
   356 		// first byte is a count of entries to skip, thus completely invalidating the next <n> directories.
   364         // first byte is a count of entries to skip, thus completely invalidating the next <n> directories.
   357 		if (!isComplete && origEntry.IsVFatEntry())
   365         if (!isComplete && origEntry.IsVFatEntry())
   358 			{
   366             {
   359 			AddPartialVFatL(origPos,origEntry);
   367             AddPartialVFatL(origPos,origEntry);
   360 			if(entryPos.iCluster!=KEndOfDirectory)
   368             if(entryPos.iCluster!=KEndOfDirectory)
   361 				{
   369                 {
   362 				TInt toMove=origEntry.NumFollowing()-(dirEntries-origDirEntries);
   370                 TInt toMove=origEntry.NumFollowing()-(dirEntries-origDirEntries);
   363 				if(toMove)
   371                 if(toMove)
   364 					MovePastEntriesL(entryPos,entry,toMove,dirEntries);
   372                     MovePastEntriesL(entryPos,entry,toMove,dirEntries);
   365 				}
   373                 }
   366 			else
   374             else
   367 				{
   375                 {
   368 				// we fell off the end of the directory file, so just strip this
   376                 // we fell off the end of the directory file, so just strip this
   369 				// incomplete long file name entry
   377                 // incomplete long file name entry
   370 				dirEntries = origDirEntries;
   378                 dirEntries = origDirEntries;
   371 				}
   379                 }
   372 			}
   380             }
   373 		else
   381         else
   374 			ProcessEntryL(entry);
   382             ProcessEntryL(entry);
   375 		if(IsEndOfRootDir(entryPos))
   383         if(IsEndOfRootDir(entryPos))
   376 			break;
   384             break;
   377 		iMount->MoveToNextEntryL(entryPos);
   385         iMount->MoveToNextEntryL(entryPos);
   378 		}
   386         }
   379 	--iRecursiveDepth;
   387     --iRecursiveDepth;
   380 	}
   388     }
   381 
   389 
   382 /**
   390 /**
   383 Process non trivial entries, such as files, if they are correct by filling out their 
   391 Process non trivial entries, such as files, if they are correct by filling out their 
   384 cluster allocation in the bit packed Fat table. If it comes accross a directory 
   392 cluster allocation in the bit packed Fat table. If it comes accross a directory 
   385 CheckDirL will be called.
   393 CheckDirL will be called.
   386 
   394 
   387 @param aEntry Directory entry to check
   395 @param aEntry Directory entry to check
   388 @leave System wide error code
   396 @leave System wide error code
   389 */
   397 */
   390 void CScanDrive::ProcessEntryL(const TFatDirEntry& aEntry)
   398 void CScanDrive::ProcessEntryL(const TFatDirEntry& aEntry)
   391 	{
   399     {
   392 	__PRINT(_L("CScanDrive::ProcessEntryL"));
   400     __PRINT(_L("CScanDrive::ProcessEntryL"));
   393 	TInt entryAtt=aEntry.Attributes();
   401     TInt entryAtt=aEntry.Attributes();
   394 	__ASSERT_ALWAYS(!(entryAtt&~KEntryAttMaskSupported)&&!aEntry.IsErased(),User::Leave(KErrCorrupt));
   402     __ASSERT_ALWAYS(!(entryAtt&~KEntryAttMaskSupported)&&!aEntry.IsErased(),User::Leave(KErrCorrupt));
   395 	if(!(entryAtt&(KEntryAttDir|KEntryAttVolume)) && iMount->StartCluster(aEntry)>0)
   403     if(!(entryAtt&(KEntryAttDir|KEntryAttVolume)) && iMount->StartCluster(aEntry)>0)
   396 		WriteClusterChainL(iMount->StartCluster(aEntry),aEntry.Size());
   404         WriteClusterChainL(iMount->StartCluster(aEntry),aEntry.Size());
   397 	else if(entryAtt&KEntryAttDir)
   405     else if(entryAtt&KEntryAttDir)
   398 		CheckDirL(iMount->StartCluster(aEntry));
   406         CheckDirL(iMount->StartCluster(aEntry));
   399 	}
   407     }
   400 
   408 
   401 /**
   409 /**
   402 Writes out the cluster chain for a correct file or directory, checks that the cluster 
   410 Writes out the cluster chain for a correct file or directory, checks that the cluster 
   403 has not already been used and that the correct number of clusters are allocated for the 
   411 has not already been used and that the correct number of clusters are allocated for the 
   404 size of file. Registers cluster as used if correct
   412 size of file. Registers cluster as used if correct
   409 */
   417 */
   410 void CScanDrive::WriteClusterChainL(TInt aCluster,TInt aSizeInBytes)
   418 void CScanDrive::WriteClusterChainL(TInt aCluster,TInt aSizeInBytes)
   411 //
   419 //
   412 // Mark off in the new fat the clusters used by entry with start cluster of aCluster
   420 // Mark off in the new fat the clusters used by entry with start cluster of aCluster
   413 //
   421 //
   414 	{
   422     {
   415 
   423 
   416     IndicateErrorsFound(); //-- indicate that we have found errors
   424     IndicateErrorsFound(); //-- indicate that we have found errors
   417 
   425 
   418 	__PRINT1(_L("CScanDrive::WriteClusterChainL starting at %d"),aCluster);
   426     __PRINT1(_L("CScanDrive::WriteClusterChainL starting at %d"),aCluster);
   419 	__ASSERT_ALWAYS(aCluster>0 && aSizeInBytes>=0,User::Leave(KErrCorrupt));
   427     __ASSERT_ALWAYS(aCluster>0 && aSizeInBytes>=0,User::Leave(KErrCorrupt));
   420 	TInt clusterCount;
   428     TInt clusterCount;
   421 	if(aSizeInBytes==0)
   429     if(aSizeInBytes==0)
   422 		clusterCount=1;
   430         clusterCount=1;
   423 	else
   431     else
   424 		clusterCount=(aSizeInBytes+(1<<iMount->ClusterSizeLog2())-1)>>iMount->ClusterSizeLog2();
   432         clusterCount=(aSizeInBytes+(1<<iMount->ClusterSizeLog2())-1)>>iMount->ClusterSizeLog2();
   425 	TInt startCluster=aCluster;
   433     TInt startCluster=aCluster;
   426 	while(clusterCount)
   434     while(clusterCount)
   427 		{
   435         {
   428 		if(AlreadyExistsL(aCluster))
   436         if(AlreadyExistsL(aCluster))
   429 			{
   437             {
   430 			__ASSERT_ALWAYS(!IsDirError()&&iMatching.iStartCluster==0&&aCluster==startCluster,User::Leave(KErrCorrupt));
   438             __ASSERT_ALWAYS(!IsDirError()&&iMatching.iStartCluster==0&&aCluster==startCluster,User::Leave(KErrCorrupt));
   431 			iMatching.iStartCluster=aCluster;
   439             iMatching.iStartCluster=aCluster;
   432 			iDirError=EScanMatchingEntry;
   440             iDirError=EScanMatchingEntry;
   433 			return;
   441             return;
   434 			}
   442             }
   435 		if(clusterCount==1)
   443         if(clusterCount==1)
   436 			{
   444             {
   437 			iNewFat->WriteFatEntryEofFL(aCluster);
   445             iNewFat->WriteFatEntryEofFL(aCluster);
   438 			return;
   446             return;
   439 			}
   447             }
   440 		else
   448         else
   441 			{
   449             {
   442 			TInt clusterVal;
   450             TInt clusterVal;
   443 			clusterVal=iMount->FAT().ReadL(aCluster);
   451             clusterVal=iMount->FAT().ReadL(aCluster);
   444 			__ASSERT_ALWAYS(!IsEofF(clusterVal) && clusterVal!=0,User::Leave(KErrCorrupt));
   452             __ASSERT_ALWAYS(!IsEofF(clusterVal) && clusterVal!=0,User::Leave(KErrCorrupt));
   445 			iNewFat->WriteL(aCluster,clusterVal);
   453             iNewFat->WriteL(aCluster,clusterVal);
   446 			aCluster=clusterVal;
   454             aCluster=clusterVal;
   447 			--clusterCount;
   455             --clusterCount;
   448 			}
   456             }
   449 		}
   457         }
   450 	}
   458     }
   451 
   459 
   452 /**
   460 /**
   453 Move to dos entry, checking all vfat entry ID numbers are in sequence.
   461 Move to dos entry, checking all vfat entry ID numbers are in sequence.
   454 Assumes aEntry is not erased
   462 Assumes aEntry is not erased
   455 
   463 
   458 @param aDirLength Running total of the length of the directory in entries
   466 @param aDirLength Running total of the length of the directory in entries
   459 @leave System wide error codes
   467 @leave System wide error codes
   460 @return EFalse if not valid vfat entries or dos entry, else returns ETrue
   468 @return EFalse if not valid vfat entries or dos entry, else returns ETrue
   461 */
   469 */
   462 TBool CScanDrive::MoveToVFatEndL(TEntryPos& aPos,TFatDirEntry& aEntry,TInt& aDirLength)
   470 TBool CScanDrive::MoveToVFatEndL(TEntryPos& aPos,TFatDirEntry& aEntry,TInt& aDirLength)
   463 	{
   471     {
   464 	__PRINT2(_L("CScanDrive::MoveToVFatEndL cluster=%d,pos=%d"),aPos.iCluster,aPos.iPos);
   472     __PRINT2(_L("CScanDrive::MoveToVFatEndL cluster=%d,pos=%d"),aPos.iCluster,aPos.iPos);
   465 	if(!aEntry.IsVFatEntry())
   473     if(!aEntry.IsVFatEntry())
   466 		return IsDosEntry(aEntry);
   474         return IsDosEntry(aEntry);
   467 	TInt toFollow=aEntry.NumFollowing();
   475     TInt toFollow=aEntry.NumFollowing();
   468 	__ASSERT_ALWAYS(toFollow>0&&!aEntry.IsErased(),User::Leave(KErrCorrupt));
   476     __ASSERT_ALWAYS(toFollow>0&&!aEntry.IsErased(),User::Leave(KErrCorrupt));
   469 	FOREVER
   477     FOREVER
   470 		{
   478         {
   471 		iMount->MoveToNextEntryL(aPos);
   479         iMount->MoveToNextEntryL(aPos);
   472 		iMount->ReadDirEntryL(aPos,aEntry);
   480         iMount->ReadDirEntryL(aPos,aEntry);
   473 		++aDirLength;
   481         ++aDirLength;
   474 		--toFollow;
   482         --toFollow;
   475 		if(!toFollow)
   483         if(!toFollow)
   476 			break;
   484             break;
   477 		if(!IsValidVFatEntry(aEntry,toFollow))
   485         if(!IsValidVFatEntry(aEntry,toFollow))
   478 			return(EFalse);
   486             return(EFalse);
   479 		}
   487         }
   480 	return(IsDosEntry(aEntry));
   488     return(IsDosEntry(aEntry));
   481 	}
   489     }
   482 
   490 
   483 /**
   491 /**
   484 Check if an entry is valid VFat
   492 Check if an entry is valid VFat
   485 
   493 
   486 @param aEntry Entry to check
   494 @param aEntry Entry to check
   487 @param aPrevNum Number into VFat entries for a dos entry to ensure in correct position
   495 @param aPrevNum Number into VFat entries for a dos entry to ensure in correct position
   488 @return ETrue if aEntry is a valid vfat entry
   496 @return ETrue if aEntry is a valid vfat entry
   489 */
   497 */
   490 TBool CScanDrive::IsValidVFatEntry(const TFatDirEntry& aEntry, TInt aPrevNum)const
   498 TBool CScanDrive::IsValidVFatEntry(const TFatDirEntry& aEntry, TInt aPrevNum)const
   491 	{
   499     {
   492 	if(aEntry.IsErased()||!aEntry.IsVFatEntry())
   500     if(aEntry.IsErased()||!aEntry.IsVFatEntry())
   493 		return(EFalse);
   501         return(EFalse);
   494 	return(aEntry.NumFollowing()==aPrevNum);
   502     return(aEntry.NumFollowing()==aPrevNum);
   495 	}
   503     }
   496 
   504 
   497 /**
   505 /**
   498 Check if an entry is a Dos entry
   506 Check if an entry is a Dos entry
   499 
   507 
   500 @param aEntry Entry to check
   508 @param aEntry Entry to check
   501 @return ETrue if aEntry is a dos entry
   509 @return ETrue if aEntry is a dos entry
   502 */
   510 */
   503 TBool CScanDrive::IsDosEntry(const TFatDirEntry& aEntry)const
   511 TBool CScanDrive::IsDosEntry(const TFatDirEntry& aEntry)const
   504 	{
   512     {
   505 	TBool res = !(aEntry.Attributes()&~KEntryAttMaskSupported) && !aEntry.IsErased() && !aEntry.IsVFatEntry() && !aEntry.IsEndOfDirectory();
   513     TBool res = !(aEntry.Attributes()&~KEntryAttMaskSupported) && !aEntry.IsErased() && !aEntry.IsVFatEntry() && !aEntry.IsEndOfDirectory();
   506 	return res;
   514     return res;
   507 	} 
   515     } 
   508 
   516 
   509 /**
   517 /**
   510 Add partial entry to iPartEntry under the error condition of not all Vfat entries 
   518 Add partial entry to iPartEntry under the error condition of not all Vfat entries 
   511 being present
   519 being present
   512 
   520 
   513 @param aStartPos Position of the Dos entry associated with the VFat entries
   521 @param aStartPos Position of the Dos entry associated with the VFat entries
   514 @param aEntry Directory Entry of the Dos entry associated with the VFat entries
   522 @param aEntry Directory Entry of the Dos entry associated with the VFat entries
   515 @leave KErrCorrupt Occurs if the entry is not valid
   523 @leave KErrCorrupt Occurs if the entry is not valid
   516 */
   524 */
   517 void CScanDrive::AddPartialVFatL(const TEntryPos& aStartPos, const TFatDirEntry& aEntry)
   525 void CScanDrive::AddPartialVFatL(const TEntryPos& aStartPos, const TFatDirEntry& aEntry)
   518 	{
   526     {
   519 	__PRINT2(_L("CScanDrive::AddPartialVFatL cluster=%d pos=%d"),aStartPos.iCluster,aStartPos.iPos);
   527     __PRINT2(_L("CScanDrive::AddPartialVFatL cluster=%d pos=%d"),aStartPos.iCluster,aStartPos.iPos);
   520 	__ASSERT_ALWAYS(!IsDirError(),User::Leave(KErrCorrupt));
   528     __ASSERT_ALWAYS(!IsDirError(),User::Leave(KErrCorrupt));
   521 	iPartEntry.iEntryPos=aStartPos;
   529     iPartEntry.iEntryPos=aStartPos;
   522 	iPartEntry.iEntry=aEntry;
   530     iPartEntry.iEntry=aEntry;
   523 	iDirError=EScanPartEntry;
   531     iDirError=EScanPartEntry;
   524 	}
   532     }
   525 
   533 
   526 /**
   534 /**
   527 Add entry position to iMatching
   535 Add entry position to iMatching
   528 
   536 
   529 @param aEntryPos Position of the entry with the matching entry
   537 @param aEntryPos Position of the entry with the matching entry
   530 @leave KErrCorrupt if the start cluster is 0 or more that two matching entries occurs
   538 @leave KErrCorrupt if the start cluster is 0 or more that two matching entries occurs
   531 @return 
   539 @return 
   532 */
   540 */
   533 TBool CScanDrive::AddMatchingEntryL(const TEntryPos& aEntryPos)
   541 TBool CScanDrive::AddMatchingEntryL(const TEntryPos& aEntryPos)
   534 	{
   542     {
   535 	__PRINT2(_L("CScanDrive::AddMatchingEntryL cluster=%d pos=%d"),aEntryPos.iCluster,aEntryPos.iPos);
   543     __PRINT2(_L("CScanDrive::AddMatchingEntryL cluster=%d pos=%d"),aEntryPos.iCluster,aEntryPos.iPos);
   536 	__ASSERT_ALWAYS(iMatching.iStartCluster>0 && iMatching.iCount<KMaxMatchingEntries,User::Leave(KErrCorrupt));
   544     __ASSERT_ALWAYS(iMatching.iStartCluster>0 && iMatching.iCount<KMaxMatchingEntries,User::Leave(KErrCorrupt));
   537 	iMatching.iEntries[iMatching.iCount++]=aEntryPos;
   545     iMatching.iEntries[iMatching.iCount++]=aEntryPos;
   538 	return iMatching.iCount==KMaxMatchingEntries;
   546     return iMatching.iCount==KMaxMatchingEntries;
   539 	}
   547     }
   540 
   548 
   541 
   549 
   542 /**
   550 /**
   543 Scan for differnces in the new and old FAT table writing them to media if discovered
   551 Scan for differnces in the new and old FAT table writing them to media if discovered
   544 
   552 
   546 */
   554 */
   547 void CScanDrive::WriteNewFatsL()
   555 void CScanDrive::WriteNewFatsL()
   548 //
   556 //
   549 // Write the new fat table to disk
   557 // Write the new fat table to disk
   550 //
   558 //
   551 	{
   559     {
   552 	if(iNewFat->FlushL())
   560     if(iNewFat->FlushL())
   553         IndicateErrorsFound(); //-- indicate that we have found errors       
   561         IndicateErrorsFound(); //-- indicate that we have found errors       
   554 	}
   562     }
   555 
   563 
   556 TInt CScanDrive::GetReservedidL(TEntryPos aVFatPos)
   564 TInt CScanDrive::GetReservedidL(TEntryPos aVFatPos)
   557 //
   565 //
   558 // Return the id found in reserved2 field of dos entry
   566 // Return the id found in reserved2 field of dos entry
   559 //
   567 //
   560 	{
   568     {
   561 	__PRINT(_L("CScanDrive::GetReservedidL"));
   569     __PRINT(_L("CScanDrive::GetReservedidL"));
   562 	TFatDirEntry entry;
   570     TFatDirEntry entry;
   563 	iMount->ReadDirEntryL(aVFatPos,entry);
   571     iMount->ReadDirEntryL(aVFatPos,entry);
   564 	if(!IsDosEntry(entry))
   572     if(!IsDosEntry(entry))
   565 		{
   573         {
   566 		TInt toMove=entry.NumFollowing();
   574         TInt toMove=entry.NumFollowing();
   567 		while(toMove--)
   575         while(toMove--)
   568 			iMount->MoveToNextEntryL(aVFatPos);
   576             iMount->MoveToNextEntryL(aVFatPos);
   569 		iMount->ReadDirEntryL(aVFatPos,entry);
   577         iMount->ReadDirEntryL(aVFatPos,entry);
   570 		}
   578         }
   571 	return(entry.RuggedFatEntryId());
   579     return(entry.RuggedFatEntryId());
   572 	}
   580     }
   573 
   581 
   574 /**
   582 /**
   575 Erase part entry found in iPartEntry
   583 Erase part entry found in iPartEntry
   576 
   584 
   577 @leave System wide error code
   585 @leave System wide error code
   578 */
   586 */
   579 void CScanDrive::FixPartEntryL()
   587 void CScanDrive::FixPartEntryL()
   580 	{
   588     {
   581 	__PRINT2(_L("CScanDrive::FixPartEntryL cluster=%d,pos=%d"),iPartEntry.iEntryPos.iCluster,iPartEntry.iEntryPos.iPos);
   589     __PRINT2(_L("CScanDrive::FixPartEntryL cluster=%d,pos=%d"),iPartEntry.iEntryPos.iCluster,iPartEntry.iEntryPos.iPos);
   582 	iMount->EraseDirEntryL(iPartEntry.iEntryPos,iPartEntry.iEntry);
   590     iMount->EraseDirEntryL(iPartEntry.iEntryPos,iPartEntry.iEntry);
   583     IndicateErrorsFound(); //-- indicate that we have found errors
   591     IndicateErrorsFound(); //-- indicate that we have found errors
   584 	}
   592     }
   585 	
   593     
   586 /**
   594 /**
   587 Delete entry with largest value in the reserved2 section(bytes 20 and 21) of dos entry
   595 Delete entry with largest value in the reserved2 section(bytes 20 and 21) of dos entry
   588 	
   596     
   589 @leave System wide error code
   597 @leave System wide error code
   590 */
   598 */
   591 void CScanDrive::FixMatchingEntryL()
   599 void CScanDrive::FixMatchingEntryL()
   592 	{
   600     {
   593 	__PRINT1(_L("CScanDrive::FixMatchingEntryL() start cluster=%d"),iMatching.iStartCluster);
   601     __PRINT1(_L("CScanDrive::FixMatchingEntryL() start cluster=%d"),iMatching.iStartCluster);
   594 	__ASSERT_ALWAYS(iMatching.iCount==KMaxMatchingEntries,User::Leave(KErrCorrupt));
   602     __ASSERT_ALWAYS(iMatching.iCount==KMaxMatchingEntries,User::Leave(KErrCorrupt));
   595 	TInt idOne=GetReservedidL(iMatching.iEntries[0]);
   603     TInt idOne=GetReservedidL(iMatching.iEntries[0]);
   596 	TInt idTwo=GetReservedidL(iMatching.iEntries[1]);
   604     TInt idTwo=GetReservedidL(iMatching.iEntries[1]);
   597 	TFatDirEntry entry;
   605     TFatDirEntry entry;
   598 	TInt num=idOne>idTwo?0:1;
   606     TInt num=idOne>idTwo?0:1;
   599 	iMount->ReadDirEntryL(iMatching.iEntries[num],entry);
   607     iMount->ReadDirEntryL(iMatching.iEntries[num],entry);
   600 	iMount->EraseDirEntryL(iMatching.iEntries[num],entry);
   608     iMount->EraseDirEntryL(iMatching.iEntries[num],entry);
   601 	IndicateErrorsFound(); //-- indicate that we have found errors
   609     IndicateErrorsFound(); //-- indicate that we have found errors
   602     }
   610     }
   603 /**
   611 /**
   604 Move past specified number of entries
   612 Move past specified number of entries
   605 
   613 
   606 @param aEntryPos Start position to move from, updated as move takes place
   614 @param aEntryPos Start position to move from, updated as move takes place
   608 @param aToMove Number of entries to move through
   616 @param aToMove Number of entries to move through
   609 @param aDirEntries Number of entries moved, updated as move takes place
   617 @param aDirEntries Number of entries moved, updated as move takes place
   610 @leave System wide error code
   618 @leave System wide error code
   611 */
   619 */
   612 void CScanDrive::MovePastEntriesL(TEntryPos& aEntryPos,TFatDirEntry& aEntry,TInt aToMove,TInt& aDirEntries)
   620 void CScanDrive::MovePastEntriesL(TEntryPos& aEntryPos,TFatDirEntry& aEntry,TInt aToMove,TInt& aDirEntries)
   613 	{
   621     {
   614 	while(aToMove-- && aEntryPos.iCluster!=KEndOfDirectory)
   622     while(aToMove-- && aEntryPos.iCluster!=KEndOfDirectory)
   615 		{
   623         {
   616 		iMount->MoveToNextEntryL(aEntryPos);
   624         iMount->MoveToNextEntryL(aEntryPos);
   617 		++aDirEntries;
   625         ++aDirEntries;
   618 		}
   626         }
   619 	iMount->ReadDirEntryL(aEntryPos,aEntry);
   627     iMount->ReadDirEntryL(aEntryPos,aEntry);
   620 	}
   628     }
   621 
   629 
   622 /**
   630 /**
   623 Adds aCluster to cluster list array so that it may be revisited later, avoids stack 
   631 Adds aCluster to cluster list array so that it may be revisited later, avoids stack 
   624 over flow
   632 over flow
   625 
   633 
   626 @param aCluster Directory cluster number to add to the list
   634 @param aCluster Directory cluster number to add to the list
   627 @leave KErrNoMemory If allocation fails
   635 @leave KErrNoMemory If allocation fails
   628 */
   636 */
   629 void CScanDrive::AddToClusterListL(TInt aCluster)
   637 void CScanDrive::AddToClusterListL(TInt aCluster)
   630 	{
   638     {
   631 	if(iListArrayIndex>=KMaxArrayDepth)
   639     if(iListArrayIndex>=KMaxArrayDepth)
   632 		return;
   640         return;
   633 	if(iClusterListArray[iListArrayIndex]==NULL)
   641     if(iClusterListArray[iListArrayIndex]==NULL)
   634 		iClusterListArray[iListArrayIndex]=new(ELeave) RArray<TInt>(KClusterListGranularity);
   642         iClusterListArray[iListArrayIndex]=new(ELeave) RArray<TInt>(KClusterListGranularity);
   635 	iClusterListArray[iListArrayIndex]->Append(aCluster);
   643     iClusterListArray[iListArrayIndex]->Append(aCluster);
   636 	}
   644     }
   637 
   645 
   638 
   646 
   639 #if defined(DEBUG_SCANDRIVE)
   647 #if defined(DEBUG_SCANDRIVE)
   640 void CScanDrive::CompareFatsL()
   648 void CScanDrive::CompareFatsL()
   641 //
   649 //
   642 // Compare new fat and first fat table
   650 // Compare new fat and first fat table
   643 //	
   651 //  
   644 	{
   652     {
   645 	__PRINT(_L("CScanDrive::CompareFatsL()"));
   653     __PRINT(_L("CScanDrive::CompareFatsL()"));
   646 	TInt maxClusters;
   654     TInt maxClusters;
   647 	maxClusters=iMount->UsableClusters();
   655     maxClusters=iMount->UsableClusters();
   648 	for(TInt i=KFatFirstSearchCluster; i<maxClusters; ++i)
   656     for(TInt i=KFatFirstSearchCluster; i<maxClusters; ++i)
   649 		{
   657         {
   650 		TInt realFat=iMount->FAT().ReadL(i);
   658         TInt realFat=iMount->FAT().ReadL(i);
   651 		TInt newFat=iNewFat->ReadL(i);
   659         TInt newFat=iNewFat->ReadL(i);
   652 		if(realFat!=newFat)
   660         if(realFat!=newFat)
   653 			{
   661             {
   654 			if(realFat!=0 && newFat==0)
   662             if(realFat!=0 && newFat==0)
   655 				__PRINT1(_L("Lost cluster=%d\n"),i)
   663                 __PRINT1(_L("Lost cluster=%d\n"),i)
   656 			else if((realFat>0 && !IsEofF(realFat)) && IsEofF(newFat))
   664             else if((realFat>0 && !IsEofF(realFat)) && IsEofF(newFat))
   657 				__PRINT1(_L("Hanging cluster = %d\n"),i)
   665                 __PRINT1(_L("Hanging cluster = %d\n"),i)
   658 			else if(realFat==0 && newFat>0)
   666             else if(realFat==0 && newFat>0)
   659 				__PRINT1(_L("Unflushed cluster = %d\n"),i)
   667                 __PRINT1(_L("Unflushed cluster = %d\n"),i)
   660 			else
   668             else
   661 				User::Leave(KErrCorrupt);
   669                 User::Leave(KErrCorrupt);
   662 			}
   670             }
   663 		}
   671         }
   664 	}	
   672     }   
   665 
   673 
   666 
   674 
   667 /** 
   675 /** 
   668 For debug purposes, print errors found as debug output 
   676 For debug purposes, print errors found as debug output 
   669  
   677  
   670 */ 
   678 */ 
   671 void CScanDrive::PrintErrors()
   679 void CScanDrive::PrintErrors()
   672 	{
   680     {
   673 	__PRINT1(_L("Directories visisted = %d\n"),iDirsChecked);
   681     __PRINT1(_L("Directories visisted = %d\n"),iDirsChecked);
   674 	if(iDirError==EScanPartEntry)
   682     if(iDirError==EScanPartEntry)
   675 		__PRINT2(_L("Part entry-dir cluster=%d,dir pos=%d,\n"),iPartEntry.iEntryPos.iCluster,iPartEntry.iEntryPos.iPos)
   683         __PRINT2(_L("Part entry-dir cluster=%d,dir pos=%d,\n"),iPartEntry.iEntryPos.iCluster,iPartEntry.iEntryPos.iPos)
   676 	else if(iDirError==EScanMatchingEntry)
   684     else if(iDirError==EScanMatchingEntry)
   677 		{
   685         {
   678 		__PRINT1(_L("Matching cluster - cluster no=%d\n"),iMatching.iStartCluster);
   686         __PRINT1(_L("Matching cluster - cluster no=%d\n"),iMatching.iStartCluster);
   679 		__PRINT2(_L("\tcluster 1 - dir cluster=%d,dir pos=%d\n"),iMatching.iEntries[0].iCluster,iMatching.iEntries[0].iPos);
   687         __PRINT2(_L("\tcluster 1 - dir cluster=%d,dir pos=%d\n"),iMatching.iEntries[0].iCluster,iMatching.iEntries[0].iPos);
   680 		__PRINT2(_L("\tcluster 2 - dir cluster=%d,dir pos=%d\n"),iMatching.iEntries[1].iCluster,iMatching.iEntries[1].iPos);
   688         __PRINT2(_L("\tcluster 2 - dir cluster=%d,dir pos=%d\n"),iMatching.iEntries[1].iCluster,iMatching.iEntries[1].iPos);
   681 		}
   689         }
   682 	}
   690     }
   683 	
   691     
   684 #endif
   692 #endif
   685 
   693 
   686 
   694 
   687 
   695 
   688 
   696