os/kernelhwsrv/userlibandfileserver/fileserver/sfat32/sl_file.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // f32\sfat\sl_file.cpp
    15 // 
    16 //
    17 
    18 #include "sl_std.h"
    19 #include "sl_cache.h"
    20 #include <e32math.h>
    21 
    22 const TInt KSeekIndexSize=128; // Cache 128 clusters
    23 const TInt KSeekIndexSizeLog2=7;
    24 const TInt KFirstClusterNum=2;
    25 
    26 CFatFileCB::CFatFileCB()
    27 	{
    28 
    29 	__PRINT1(_L("CFatFileCB created 0x%x"),this);
    30 	}
    31 
    32 CFatFileCB::~CFatFileCB()
    33 	{
    34 	__PRINT1(_L("CFatFileCB deleted 0x%x"),this);
    35 
    36     //-- a nasty trick to find out if the CFatFileCB is in consistent state on the moment of destruction.
    37     //-- Because of OOM conditions CFatFileCB might not be fully constructed and to be deleted, while FlushAll()
    38     //-- implies valid iMount.
    39     const CMountCB* pMount  = &Mount();
    40     if(pMount)
    41         {//-- do some finalisation work if CMountCB is valid
    42         if (iAtt&KEntryAttModified)
    43             TRAP_IGNORE(FlushAllL());
    44         }
    45 
    46     delete[] iSeekIndex;
    47 	}
    48 
    49 
    50 void CFatFileCB::CreateSeekIndex()
    51 //
    52 // Create a seek index
    53 //
    54 	{
    55 
    56 	iSeekIndex = new TUint32[KSeekIndexSize];
    57 	if (iSeekIndex == NULL)
    58 		return;
    59 
    60 	Mem::FillZ(iSeekIndex, sizeof(TUint32) * KSeekIndexSize);
    61 
    62 	iSeekIndexSize=CalcSeekIndexSize(Size());
    63 	}
    64 
    65 TInt CFatFileCB::SeekToPosition(TInt aNewRelCluster,TInt aClusterOffset)
    66 //
    67 // Use the seek index to set iCurrentPos.iCluster as close as possible to aNewRelCluster
    68 // Return aNewRelCluster-aCurrentPos.iCluster
    69 //
    70 	{
    71 	TInt clusterOffset=aClusterOffset;
    72 	TInt seekPos=(aNewRelCluster>>iSeekIndexSize)-1;
    73 	__ASSERT_DEBUG(seekPos<KSeekIndexSize,Fault(EFatFileSeekIndexTooSmall));
    74 
    75 	while(seekPos>=0 && iSeekIndex[seekPos]==0 && clusterOffset!=0)
    76 		{
    77 		seekPos--;
    78 		clusterOffset--;
    79 		}
    80 	if (clusterOffset==0) // Counted back to the current cluster
    81 		return(aClusterOffset);
    82 	if (seekPos<0)
    83 		{
    84 		iCurrentPos.iCluster=iStartCluster;
    85 		return(aNewRelCluster);
    86 		}
    87 
    88 	iCurrentPos.iCluster=iSeekIndex[seekPos];
    89 	return(aNewRelCluster-((seekPos+1)<<iSeekIndexSize));
    90 	}
    91 
    92 void CFatFileCB::SetSeekIndexValueL(TInt aRelCluster,TInt aStoredCluster)
    93 //
    94 // Sets a value in the seekindex
    95 //
    96 	{
    97 
    98 	TInt seekPos=(aRelCluster>>iSeekIndexSize)-1;
    99 	__ASSERT_DEBUG(seekPos<KSeekIndexSize,Fault(EFatFileSeekIndexTooSmall));
   100 	__ASSERT_DEBUG(seekPos>=0,Fault(EFatFileSeekIndexTooSmall2));
   101 	iSeekIndex[seekPos] = aStoredCluster;
   102 	}
   103 
   104 TBool CFatFileCB::IsSeekBackwards(TUint aPos)
   105 //
   106 // Return true if aPos<currentPos
   107 //
   108 	{
   109 	
   110 	TUint cluster=iCurrentPos.iCluster<<ClusterSizeLog2();
   111 	TInt offset=ClusterRelativePos(iCurrentPos.iPos);
   112 	TUint currentPos=cluster+offset;
   113 	return(aPos<currentPos);
   114 	}
   115 
   116 void CFatFileCB::CheckPosL(TUint aPos)
   117 //
   118 // Check that the file is positioned correctly.
   119 // If aPos<currentPos attempt to guess the new position.
   120 //
   121 	{
   122 	__PRINT1(_L("CFatFileCB::CheckPosL(%d)"), aPos);
   123 	if (aPos==iCurrentPos.iPos)
   124 		return;
   125     __ASSERT_DEBUG(aPos <= (TUint)Size(), Fault(EFatFilePosBeyondEnd));
   126 
   127 	if (iFileSizeModified && IsSeekBackwards(aPos))
   128 		FlushDataL(); 
   129 	
   130 	TUint newRelCluster=aPos>>ClusterSizeLog2();
   131 	if ( aPos && (aPos==(newRelCluster<<ClusterSizeLog2())) )
   132 		newRelCluster--;
   133 	TUint oldRelCluster=iCurrentPos.iPos>>ClusterSizeLog2();
   134 	if ( iCurrentPos.iPos && (iCurrentPos.iPos==(oldRelCluster<<ClusterSizeLog2())) )
   135 		oldRelCluster--;	
   136 	TInt clusterOffset=newRelCluster-oldRelCluster;
   137 	TInt oldCluster=iCurrentPos.iCluster;
   138 	iCurrentPos.iPos=aPos;
   139 	if (clusterOffset==0)
   140 		return;
   141 	TInt seekOffset=clusterOffset;
   142 	if (iSeekIndex!=NULL)
   143 		{ // Can alter iCurrentPos.iCluster
   144 		seekOffset=SeekToPosition(newRelCluster,seekOffset);
   145 		if (seekOffset==0)
   146 			return;
   147 		}
   148 	if (clusterOffset==-1 && seekOffset!=1)
   149 		{ // Check previous cluster
   150 		TInt cluster=oldCluster-1;
   151 		if (FAT().GetNextClusterL(cluster) && cluster==oldCluster)
   152 			{
   153             iCurrentPos.iCluster=oldCluster-1;
   154 			return;
   155 			}
   156 		}
   157 	if (seekOffset<0)
   158 		{
   159 		seekOffset=newRelCluster;
   160 		iCurrentPos.iCluster=iStartCluster;
   161 		}
   162 	while (seekOffset--)
   163 		{
   164         if (!FAT().GetNextClusterL(iCurrentPos.iCluster))
   165             {
   166             __PRINT(_L("CFatFileCB::CheckPosL() corrupt#1"));
   167             User::Leave(KErrCorrupt);
   168             }
   169         TInt cluster=newRelCluster-seekOffset;
   170 		if (iSeekIndex!=NULL && cluster && (cluster>>iSeekIndexSize)<<iSeekIndexSize==cluster)
   171 			SetSeekIndexValueL(cluster,iCurrentPos.iCluster);
   172 		}
   173 	}
   174 
   175 void CFatFileCB::SetL(const TFatDirEntry& aFatDirEntry,TShare aShare,const TEntryPos& aPos)
   176 //
   177 // Initialize FileCB from entry data
   178 //
   179 	{
   180 
   181 	__PRINT(_L("CFatFileCB::SetL"));
   182 	SetSize(aFatDirEntry.Size()); 
   183 	iCurrentPos.iCluster= FatMount().StartCluster(aFatDirEntry);
   184 	iStartCluster=iCurrentPos.iCluster;
   185 	iCurrentPos.iPos=0;
   186 	iAtt=aFatDirEntry.Attributes();
   187 	iModified= aFatDirEntry.Time(FatMount().TimeOffset());
   188 	iShare=aShare;
   189 	iFileDirPos=aPos;
   190 
   191     SetMaxSupportedSize(KMaxSupportedFatFileSize);
   192 	}
   193 
   194 //-----------------------------------------------------------------------------
   195 // from CFileCB::MExtendedFileInterface
   196 void CFatFileCB::ReadL(TInt64 aPos,TInt& aLength, TDes8* aDes, const RMessagePtr2& aMessage, TInt aOffset)
   197 	{
   198 	__PRINT2(_L("CFatFileCB::ReadL aFilePos=%LU aLength=%d"),aPos,aLength);
   199 	
   200     if((TUint64)aPos > KMaxSupportedFatFileSize-1)
   201         User::Leave(KErrNotSupported);  //-- max. position in the file is 0xFFFFFFFE
   202 
   203     FatMount().CheckStateConsistentL();
   204     
   205 	CheckPosL(I64LOW(aPos));
   206 	
   207 	const TUint startPos = iCurrentPos.iPos;
   208 	const TUint curSize  = (TUint)Size();
   209 	const TUint length   = (TUint)aLength;
   210 	
   211 	if((startPos + length > curSize) || (startPos > startPos + length) )
   212 		aLength=curSize-startPos;
   213 	
   214     FatMount().ReadFromClusterListL(iCurrentPos,aLength,aDes,aMessage,aOffset);
   215 	aLength=iCurrentPos.iPos-startPos;
   216 	}
   217 
   218 
   219 void CFatFileCB::ReadL(TInt aFilePos,TInt& aLength,const TAny* aTrg,const RMessagePtr2& aMessage)
   220 	{
   221 	ReadL(TInt64(aFilePos),aLength,(TDes8*) aTrg,aMessage, 0);
   222 	}
   223 
   224 //-----------------------------------------------------------------------------
   225 // from CFileCB::MExtendedFileInterface
   226 void CFatFileCB::WriteL(TInt64 aPos,TInt& aLength,const TDesC8* aSrc,const RMessagePtr2& aMessage, TInt aOffset)
   227 	{
   228 	__PRINT2(_L("CFatFileCB::WriteL aFilePos=%LU aLength=%d"),aPos,aLength);
   229 	// FAT supports 32 bits only for file size
   230    	TUint64 endPos = aPos + aLength;
   231    	if(endPos > KMaxSupportedFatFileSize)
   232    		User::Leave(KErrNotSupported);
   233    	
   234     FatMount().CheckStateConsistentL();
   235     FatMount().CheckWritableL();
   236     const TUint pos = I64LOW(aPos);
   237   	CheckPosL(pos);
   238   	
   239 	const TUint startCluster = (TUint)iStartCluster;
   240 	const TUint length       = (TUint)aLength;
   241 	
   242 	endPos = iCurrentPos.iPos + length; 
   243 	if ((endPos           > (TUint)Size()) ||
   244 	    (iCurrentPos.iPos > endPos)         ) // Overflow condition 
   245 		DoSetSizeL(iCurrentPos.iPos+length,EFalse);
   246    	
   247 	TUint startPos=iCurrentPos.iPos;
   248 	TInt badcluster=0;
   249 	TInt goodcluster=0;
   250    	
   251 	TRAPD(ret, FatMount().WriteToClusterListL(iCurrentPos,aLength,aSrc,aMessage,aOffset,badcluster, goodcluster));
   252    	
   253 	if (ret == KErrCorrupt || ret == KErrDied)
   254 		{
   255         if(startCluster == 0)
   256 			{ //Empty File, revert all the clusters allocated.
   257 			TInt cluster = iStartCluster;
   258 			iStartCluster = 0;
   259 			SetSize(0);
   260 			FlushAllL();
   261 
   262 			iCurrentPos.iCluster = 0;
   263 			iCurrentPos.iPos = 0;
   264 
   265 			FAT().FreeClusterListL(cluster);
   266 			FAT().FlushL();
   267 			}
   268 		else
   269 			{ //Calculate the clusters required based on file size, revert extra clusters if allocated.
   270 			const TUint curSize = (TUint)Size();
   271 			TUint ClustersNeeded = curSize >> ClusterSizeLog2();
   272 			if(curSize > (ClustersNeeded << ClusterSizeLog2()))
   273 				{
   274 				ClustersNeeded++;
   275 				}
   276 
   277 			TInt cluster = iStartCluster;
   278 			while(--ClustersNeeded)
   279 				{
   280 				FAT().GetNextClusterL(cluster);
   281 				}
   282                 
   283 			iCurrentPos.iCluster = cluster;
   284 
   285 			if (FAT().GetNextClusterL(cluster))
   286 				{
   287 				FAT().FreeClusterListL(cluster);
   288 				}
   289 
   290 			FAT().WriteFatEntryEofL(iCurrentPos.iCluster);
   291 			FAT().FlushL();
   292 			}
   293 		}
   294 
   295 	User::LeaveIfError(ret);
   296 
   297 	if(badcluster != 0)
   298 		{
   299 		if(iStartCluster == badcluster)
   300 			{
   301 			iStartCluster = goodcluster;
   302 			FlushStartClusterL();
   303 			}
   304 		else
   305 			{
   306 			TInt aCluster = iStartCluster;
   307 			do
   308 				{
   309                 if((TUint)badcluster == FAT().ReadL(aCluster))
   310 					{
   311 					FAT().WriteL(aCluster, goodcluster);
   312 					FAT().FlushL();
   313 					break;
   314 					}
   315 				}
   316 			while(FAT().GetNextClusterL(aCluster));
   317 			}
   318 		}
   319 	aLength=iCurrentPos.iPos-startPos;
   320 
   321 	if(FatMount().IsRuggedFSys() && pos+(TUint)aLength>(TUint)Size())
   322 		{
   323 		WriteFileSizeL(pos+aLength);
   324 		}
   325 
   326 	}
   327 
   328 
   329 void CFatFileCB::WriteL(TInt aFilePos,TInt& aLength,const TAny* aSrc,const RMessagePtr2& aMessage)
   330 	{
   331 	WriteL(TInt64(aFilePos),aLength,(TDesC8*) aSrc,aMessage, 0);
   332 	}
   333 
   334 
   335 
   336 //-----------------------------------------------------------------------------
   337 
   338 void CFatFileCB::ResizeIndex(TInt aNewMult,TUint aNewSize)
   339 //
   340 // Resize the seek index to accomodate a larger or smaller filesize
   341 // Assumes KSeekIndexSize is a power of 2.
   342 //
   343 	{
   344 
   345 	TInt maxNewIndex=aNewSize>>(ClusterSizeLog2()+aNewMult);
   346 
   347 
   348 	TInt    index=0;
   349 	TInt	indexEnd=KSeekIndexSize;
   350 	TInt	newValEnd=maxNewIndex;
   351 
   352 	if (iSeekIndexSize<aNewMult)
   353 		{
   354 		TInt newVal=index;
   355 		TInt step=1<<(aNewMult-iSeekIndexSize);
   356 		index+=step-1;
   357 		while(index<indexEnd && newVal<newValEnd)
   358 			{
   359 			iSeekIndex[newVal] =  iSeekIndex[index];
   360 			newVal++;
   361 			index+=step;
   362 			}
   363 		while(newVal<indexEnd)
   364 			iSeekIndex[newVal++] =  0;
   365 		}
   366 	else
   367 		{
   368 		TInt diffSize = iSeekIndexSize-aNewMult;
   369 		TInt oldVal=(KSeekIndexSize>>diffSize) - 1;
   370 		TInt newVal=indexEnd-1;
   371 		TInt skip=(1<<diffSize)-1;
   372 
   373 		if ((iSeekIndexSize - aNewMult) > KSeekIndexSizeLog2)
   374 			{
   375             ClearIndex(0); //-- Invalidate every entry.
   376 			}
   377 		else
   378 			{
   379 			while(newVal>=index)
   380 				{
   381 
   382 				iSeekIndex[newVal--] =  iSeekIndex[oldVal--];
   383 
   384 
   385 				for(TInt i=skip;i>0;i--)
   386 					{	
   387 					iSeekIndex[newVal--] = 0;
   388 
   389 					}
   390 				}
   391 			}
   392 		}
   393 	iSeekIndexSize=aNewMult;
   394 	}
   395 
   396 
   397 /**
   398     Zero freed clusters in the index
   399 
   400     @param  aNewSize new size of the file that the index corresponds to.
   401             if = 0  all existing index will be zero filled
   402 */ 
   403 void CFatFileCB::ClearIndex(TUint aNewSize)
   404 	{
   405 
   406 	if (!iSeekIndex)
   407 	    return;
   408 
   409     if(aNewSize==0)
   410     	{
   411     	//-- zero fill all the array
   412         Mem::FillZ(iSeekIndex, KSeekIndexSize*sizeof(TUint32));
   413 		return;
   414     	}
   415 
   416 	// Files that fill up a cluster exactly do not have a trailing empty
   417 	// cluster. So the entry for that position must also be invalidated
   418 	aNewSize--;
   419 	TInt firstInvalidIndex=aNewSize>>(iSeekIndexSize+ClusterSizeLog2());
   420 		
   421 	TInt indexLen=KSeekIndexSize-firstInvalidIndex;
   422 
   423 	Mem::FillZ(iSeekIndex+firstInvalidIndex, indexLen * sizeof(TUint32));
   424 	}
   425 
   426 TInt CFatFileCB::CalcSeekIndexSize(TUint aSize)
   427 //
   428 // Find the nearest power of 2 > aSize
   429 //
   430 	{
   431 	TInt count = 0;
   432 	const TUint indexSize=KSeekIndexSize<<ClusterSizeLog2();//KSeekIndexSize=128
   433 	if (aSize<=indexSize)
   434 	  return(count);
   435 	
   436 	while((aSize>>=1)>0)
   437 		{
   438 		count++;
   439 		}
   440 	return (count - (KSeekIndexSizeLog2 + ClusterSizeLog2()) + 1);
   441 	}
   442 
   443 //-----------------------------------------------------------------------------
   444 
   445 void CFatFileCB::SetSizeL(TInt64 aSize)
   446 	{
   447 	__PRINT(_L("CFatFileCB::SetSizeL"));
   448 	
   449 	// FAT supports 32 bits only for file size
   450 	if (I64HIGH(aSize))
   451 		User::Leave(KErrNotSupported);
   452 
   453 	if(FatMount().IsRuggedFSys())
   454 		DoSetSizeL(I64LOW(aSize),ETrue);
   455 	else
   456 		DoSetSizeL(I64LOW(aSize),EFalse);
   457 	}
   458 
   459 
   460 void CFatFileCB::SetSizeL(TInt aSize)
   461 //
   462 // Envelope function around DoSetSizeL to enable aSize to
   463 // be written to disk for rugged fat file system
   464 //
   465 	{
   466 	SetSizeL(TInt64(aSize));
   467 	}
   468 
   469 void CFatFileCB::DoSetSizeL(TUint aSize,TBool aIsSizeWrite)
   470 //
   471 // Extend or truncate the file.
   472 // Expects the modified attribute and iSize are set afterwards.
   473 // Does not alter iCurrentPos, the current file position.
   474 // Writes size of file to disk if aIsSizeWrite set
   475 //
   476 	{
   477 	__PRINT2(_L("CFatFileCB::DoSetSizeL sz:%d, fileWrite=%d"),aSize ,aIsSizeWrite);
   478 
   479     FatMount().CheckStateConsistentL();
   480     FatMount().CheckWritableL();
   481 
   482 	
   483 	// Can not change the file size if it is clamped
   484 	if(Mount().IsFileClamped(MAKE_TINT64(0,iStartCluster)) > 0)
   485 		User::Leave(KErrInUse);
   486 	
   487 	iFileSizeModified=ETrue;
   488 
   489 	TInt newIndexMult=CalcSeekIndexSize(aSize);
   490 	if (iSeekIndex!=NULL && newIndexMult!=iSeekIndexSize)
   491 		ResizeIndex(newIndexMult,aSize);
   492 	if (aSize == 0)
   493 		{
   494 		if (Size() != 0)
   495 			{
   496             ClearIndex(0); //-- clear seek index array
   497 			TInt cluster=iStartCluster;
   498 			iStartCluster = 0;
   499 			SetSize(0);
   500 			FlushAllL();
   501 			CheckPosL(0);
   502 			FAT().FreeClusterListL(cluster);
   503 			FAT().FlushL();
   504 			}
   505 		return;
   506 		}
   507 	if (aSize<(TUint)Size())
   508 		{
   509 		if(aIsSizeWrite)		// write file size if decreasing
   510 				WriteFileSizeL(aSize);
   511 		CheckPosL(aSize);
   512 		TInt cluster=iCurrentPos.iCluster;
   513 		if (FAT().GetNextClusterL(cluster))
   514 			{
   515 			FAT().WriteFatEntryEofL(iCurrentPos.iCluster);
   516 			FAT().FreeClusterListL(cluster);
   517 			}
   518 		ClearIndex(aSize);
   519 		FAT().FlushL();
   520 		return;
   521 		}
   522 	
   523 	TUint newSize=aSize>>ClusterSizeLog2();	//	Number of clusters we now need
   524 	if (aSize > (newSize<<ClusterSizeLog2()))
   525 		newSize++;	//	File size is not an exact multiple of cluster size
   526 					//	Increment the number of clusters required to accomodate tail
   527 	
   528 	if (iStartCluster==0)
   529 		{
   530         //-- FAT().FreeClusterHint() will give us a hint of the last free cluster
   531         ClearIndex(0); //-- clear seek index array
   532         TInt tempStartCluster=FAT().AllocateClusterListL(newSize, FAT().FreeClusterHint());
   533 		FAT().FlushL();
   534 		iCurrentPos.iCluster=tempStartCluster;
   535 		iStartCluster=tempStartCluster;
   536 		SetSize(aSize);
   537 		FlushAllL();
   538 		}
   539 	else
   540 		{
   541 		const TUint curSize = (TUint)Size(); 
   542 		TUint oldSize=curSize>>ClusterSizeLog2();	//	Number of clusters we had previously
   543 		if (curSize>(oldSize<<ClusterSizeLog2()))
   544 			oldSize++;
   545 	
   546 		TInt newClusters=newSize-oldSize;	//	Number of clusters we need to prepare
   547 		if (newClusters)
   548 			{
   549 			TEntryPos currentPos=iCurrentPos;
   550 			CheckPosL(Size());
   551 			FAT().ExtendClusterListL(newClusters,iCurrentPos.iCluster);
   552 			iCurrentPos=currentPos;
   553 			}
   554 		FAT().FlushL();
   555 		if(aIsSizeWrite)			// write file size if increasing
   556 			WriteFileSizeL(aSize);
   557 		}
   558 	}
   559 
   560 //-----------------------------------------------------------------------------
   561 /**
   562     Set the entry's attributes and modified time.
   563 */
   564 void CFatFileCB::SetEntryL(const TTime& aTime,TUint aSetAttMask,TUint aClearAttMask)
   565 	{
   566 	__PRINT(_L("CFatFileCB::SetEntryL"));
   567     
   568     FatMount().CheckStateConsistentL();
   569     FatMount().CheckWritableL();
   570 
   571 	TUint setAttMask=aSetAttMask&KEntryAttMaskSupported;
   572 	if (setAttMask|aClearAttMask)
   573 		{
   574 		iAtt|=setAttMask;
   575 		iAtt&=(~aClearAttMask);
   576 		}
   577 	if (aSetAttMask&KEntryAttModified)
   578 		iModified=aTime;
   579 	iAtt|=KEntryAttModified;
   580 	}
   581 
   582 /**
   583     This is a RuggedFAT - specific method. Writes file size to the corresponding field of this
   584     file direcrory entry.
   585 */
   586 void CFatFileCB::WriteFileSizeL(TUint aSize)
   587 	{
   588 	__PRINT(_L("CFatFileCB::WriteFileSizeL"));
   589 	TEntryPos entryPos=iFileDirPos;
   590 	entryPos.iPos+=_FOFF(SFatDirEntry,iSize);
   591 	TPtrC8 size((TUint8*)&aSize,sizeof(TUint));
   592 	
   593     //-- use directory cache when dealing with directories
   594     FatMount().DirWriteL(entryPos,size);
   595 	iFileSizeModified=EFalse;
   596     }
   597 
   598 //-----------------------------------------------------------------------------
   599 /** 
   600     Flush file size, attributes, time etc. to the media.
   601     It doesn't matter if whole directory entry is being written of only part of it. Anyway, a single DOS
   602     dir. entry always fits into 1 sector.
   603 */
   604 void CFatFileCB::FlushDataL()
   605 	{
   606 	__PRINT(_L("CFatFileCB::FlushDataL"));
   607     FlushAllL();
   608 	}
   609 
   610 //-----------------------------------------------------------------------------
   611 /** 
   612     Flush the fide directory entry data: files size, attributes, time etc. 
   613 */
   614 void CFatFileCB::FlushAllL()
   615 	{
   616 	__PRINT(_L("CFatFileCB::FlushAllL()"));
   617 
   618     if (Mount().IsCurrentMount()==EFalse)
   619 		User::Leave(KErrDisMounted);
   620 
   621     FatMount().CheckStateConsistentL();
   622     FatMount().CheckWritableL();
   623 
   624 	TFatDirEntry entry;
   625 	FatMount().ReadDirEntryL(iFileDirPos,entry);
   626 	__ASSERT_ALWAYS(entry.IsEndOfDirectory()==EFalse,User::Leave(KErrCorrupt));
   627 	entry.SetAttributes(iAtt&KEntryAttMaskSupported);
   628 	entry.SetSize(Size());
   629 	entry.SetTime(iModified, FatMount().TimeOffset());
   630 	entry.SetStartCluster(iStartCluster);
   631 
   632 	TBool setNotify = FatMount().GetNotifyUser();
   633 	if(setNotify)
   634 		{
   635 		FatMount().SetNotifyOff();	// do not launch a notifier
   636 		}
   637 
   638 	TRAPD(ret, FatMount().WriteDirEntryL(iFileDirPos,entry));
   639 	
   640 	if(setNotify)
   641 		{
   642 		FatMount().SetNotifyOn();
   643 		}
   644 
   645 	User::LeaveIfError(ret);
   646 	iAtt&=(~KEntryAttModified);
   647 	iFileSizeModified=EFalse;
   648 	}
   649 
   650 //-----------------------------------------------------------------------------
   651 
   652 /**
   653     Rename already opened file.
   654     @param  aNewName new file name; all trailing dots from the name will be removed
   655 */
   656 void CFatFileCB::RenameL(const TDesC& aNewName)
   657 	{
   658     __PRINT2(_L("CFatFileCB::RenameL[0x%x], name:%S"),this, &aNewName);
   659 
   660     FatMount().CheckStateConsistentL();
   661     FatMount().CheckWritableL();
   662 
   663     const TPtrC fileName = RemoveTrailingDots(aNewName); //-- remove trailing dots from the name
   664 
   665 
   666 	FatMount().DoRenameOrReplaceL(*iFileName, fileName, CFatMountCB::EModeRename,iFileDirPos);
   667 	
   668     AllocBufferL(iFileName, fileName);
   669 	
   670 	if(!FatMount().IsRuggedFSys())
   671 		FAT().FlushL();
   672 	}
   673 
   674 
   675 //***********************************************************
   676 //* BlockMap interface
   677 //***********************************************************
   678 	
   679 TInt CFatFileCB::BlockMap(SBlockMapInfo& aInfo, TInt64& aStartPos, TInt64 aEndPos)
   680 //
   681 // Retrieves the block map of a given section of the file, in the FAT file system.
   682 //	
   683 	{
   684 	__PRINT2(_L("CFatFileCB::BlockMap aStartPos=%ld aEndPos=%ld"), aStartPos, aEndPos);
   685 	
   686 	if ( I64HIGH(aStartPos) || I64HIGH(aEndPos) )
   687 		return KErrNotSupported;
   688 
   689     TUint startPos = I64LOW(aStartPos);
   690 	TUint endPos = I64LOW(aEndPos);
   691 
   692 	// aEndPos will always be >=0 at this point
   693 	const TUint length = endPos - startPos;
   694 	
   695 	// Store the position of cluster zero in aInfo
   696 	CFatMountCB& fatMount = FatMount();
   697 
   698 	TInt drvNo=-1;
   699 	TBusLocalDrive* locDrv;
   700 	if((fatMount.LocalDrive()->GetLocalDrive(locDrv)==KErrNone) && ((drvNo=GetLocalDriveNumber(locDrv))>=0) && (drvNo<KMaxLocalDrives))
   701 		aInfo.iLocalDriveNumber=drvNo;
   702 	else
   703 		return KErrNotSupported;
   704 
   705 	// Fetch the address of cluster 0
   706 	aInfo.iStartBlockAddress = fatMount.FAT().DataPositionInBytes(KFirstClusterNum);
   707 
   708 	TRAPD(r, CheckPosL(startPos));
   709 	if (r != KErrNone)
   710 		return r;
   711 
   712 	aInfo.iBlockStartOffset = fatMount.ClusterRelativePos(iCurrentPos.iPos);
   713 	aInfo.iBlockGranularity = 1 << FatMount().ClusterSizeLog2();
   714 	const TUint myStartPos = iCurrentPos.iPos;
   715 	if ( myStartPos + length > (TUint)Size())
   716 		return KErrArgument;
   717 
   718 	TRAP(r, FatMount().BlockMapReadFromClusterListL(iCurrentPos, length, aInfo));
   719 	if (r != KErrNone)
   720 		return r;
   721 
   722 	aStartPos = iCurrentPos.iPos;
   723 	if ((I64LOW(aStartPos) == (TUint)Size()) || ( I64LOW(aStartPos) == (myStartPos + length)))
   724 		return KErrCompletion;
   725 	else
   726 		return KErrNone;
   727 	}
   728 
   729 
   730 
   731 TInt CFatFileCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput)
   732 	{
   733 	switch(aInterfaceId)
   734 		{
   735 		case EExtendedFileInterface:
   736 			((CFileCB::MExtendedFileInterface*&) aInterface) = this;
   737 			return KErrNone;
   738 
   739 		case EBlockMapInterface:
   740 			aInterface = (CFileCB::MBlockMapInterface*) this;
   741 			return KErrNone;
   742 
   743 		case EGetLocalDrive:
   744 			return FatMount().LocalDrive()->GetLocalDrive((TBusLocalDrive*&) aInterface);
   745 
   746 		default:
   747 			return CFileCB::GetInterface(aInterfaceId,aInterface,aInput);
   748 		}
   749 	}
   750 
   751 
   752 
   753 
   754 /**
   755     Overwrites file's start cluster (iStartCluster) in its directory entry.
   756 */
   757 void CFatFileCB::FlushStartClusterL()
   758 	{
   759 	__PRINT(_L("CFatFileCB::FlushStartClusterL"));
   760 
   761     CFatMountCB& mount = FatMount();
   762     TFatDirEntry dirEntry;
   763     
   764     mount.ReadDirEntryL(iFileDirPos, dirEntry);      //-- read this file's dir. entry
   765     dirEntry.SetStartCluster(iStartCluster);         //-- set new start cluster
   766     mount.WriteDirEntryL(iFileDirPos, dirEntry);//-- write the entry back
   767 	}
   768 
   769 
   770 
   771 
   772