userlibandfileserver/fileserver/sfat32/sl_file.cpp
changeset 15 4122176ea935
child 87 2f92ad2dc5db
equal deleted inserted replaced
0:a41df078684a 15:4122176ea935
       
     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