userlibandfileserver/fileserver/sfat32/sl_file.cpp
branchRCL_3
changeset 257 3e88ff8f41d5
parent 256 c1f20ce4abcf
child 294 039a3e647356
equal deleted inserted replaced
256:c1f20ce4abcf 257:3e88ff8f41d5
     9 // Nokia Corporation - initial contribution.
     9 // Nokia Corporation - initial contribution.
    10 //
    10 //
    11 // Contributors:
    11 // Contributors:
    12 //
    12 //
    13 // Description:
    13 // Description:
    14 // f32\sfat32\sl_file.cpp
    14 // f32\sfat\sl_file.cpp
    15 // 
    15 // 
    16 //
    16 //
    17 
    17 
    18 #include "sl_std.h"
    18 #include "sl_std.h"
    19 #include "sl_cache.h"
    19 #include "sl_cache.h"
    22 const TInt KSeekIndexSize=128; // Cache 128 clusters
    22 const TInt KSeekIndexSize=128; // Cache 128 clusters
    23 const TInt KSeekIndexSizeLog2=7;
    23 const TInt KSeekIndexSizeLog2=7;
    24 const TInt KFirstClusterNum=2;
    24 const TInt KFirstClusterNum=2;
    25 
    25 
    26 CFatFileCB::CFatFileCB()
    26 CFatFileCB::CFatFileCB()
    27     {
    27 	{
    28     __PRINT1(_L("CFatFileCB created 0x%x"),this);
    28 	__PRINT1(_L("CFatFileCB created 0x%x"),this);
    29     }
    29 	}
    30 
    30 
    31 CFatFileCB::~CFatFileCB()
    31 CFatFileCB::~CFatFileCB()
    32     {
    32 	{
    33     __PRINT1(_L("~CFatFileCB deleted 0x%x"),this);
    33 	__PRINT1(_L("~CFatFileCB deleted 0x%x"),this);
    34 
    34 
    35     //-- a nasty trick to find out if the CFatFileCB is in consistent state on the moment of destruction.
    35     //-- a nasty trick to find out if the CFatFileCB is in consistent state on the moment of destruction.
    36     //-- Because of OOM conditions CFatFileCB might not be fully constructed and to be deleted, while FlushAll()
    36     //-- Because of OOM conditions CFatFileCB might not be fully constructed and to be deleted, while FlushAll()
    37     //-- implies valid iMount.
    37     //-- implies valid iMount.
    38     const CMountCB* pMount  = &Mount();
    38     const CMountCB* pMount  = &Mount();
    40         {//-- do some finalisation work if CMountCB is valid
    40         {//-- do some finalisation work if CMountCB is valid
    41         if(FileAttModified())
    41         if(FileAttModified())
    42             {
    42             {
    43             IndicateFileTimeModified(ETrue); //-- this will force writing file modification time to the media on Flush
    43             IndicateFileTimeModified(ETrue); //-- this will force writing file modification time to the media on Flush
    44             TRAP_IGNORE(FlushAllL());
    44             TRAP_IGNORE(FlushAllL());
    45             }
    45 	        }
    46         }
    46         }
    47 
    47 
    48     delete[] iSeekIndex;
    48     delete[] iSeekIndex;
    49     }
    49 	}
    50 
    50 
    51 
    51 
    52 void CFatFileCB::CreateSeekIndex()
    52 void CFatFileCB::CreateSeekIndex()
    53 //
    53 //
    54 // Create a seek index
    54 // Create a seek index
    55 //
    55 //
    56     {
    56 	{
    57 
    57 
    58     iSeekIndex = new TUint32[KSeekIndexSize];
    58 	iSeekIndex = new TUint32[KSeekIndexSize];
    59     if (iSeekIndex == NULL)
    59 	if (iSeekIndex == NULL)
    60         return;
    60 		return;
    61 
    61 
    62     Mem::FillZ(iSeekIndex, sizeof(TUint32) * KSeekIndexSize);
    62 	Mem::FillZ(iSeekIndex, sizeof(TUint32) * KSeekIndexSize);
    63 
    63 
    64     iSeekIndexSize=CalcSeekIndexSize(FCB_FileSize());
    64 	iSeekIndexSize=CalcSeekIndexSize(FCB_FileSize());
    65     }
    65 	}
    66 
    66 
    67 TInt CFatFileCB::SeekToPosition(TUint aNewRelCluster, TUint aClusterOffset)
    67 TInt CFatFileCB::SeekToPosition(TUint aNewRelCluster, TUint aClusterOffset)
    68 //
    68 //
    69 // Use the seek index to set iCurrentPos.iCluster as close as possible to aNewRelCluster
    69 // Use the seek index to set iCurrentPos.iCluster as close as possible to aNewRelCluster
    70 // Return aNewRelCluster-aCurrentPos.iCluster
    70 // Return aNewRelCluster-aCurrentPos.iCluster
    71 //
    71 //
    72     {
    72 	{
    73     TInt clusterOffset=aClusterOffset;
    73 	TInt clusterOffset=aClusterOffset;
    74     TInt seekPos=(aNewRelCluster>>iSeekIndexSize)-1;
    74 	TInt seekPos=(aNewRelCluster>>iSeekIndexSize)-1;
    75     __ASSERT_DEBUG(seekPos<KSeekIndexSize,Fault(EFatFileSeekIndexTooSmall));
    75 	__ASSERT_DEBUG(seekPos<KSeekIndexSize,Fault(EFatFileSeekIndexTooSmall));
    76 
    76 
    77     while(seekPos>=0 && iSeekIndex[seekPos]==0 && clusterOffset!=0)
    77 	while(seekPos>=0 && iSeekIndex[seekPos]==0 && clusterOffset!=0)
    78         {
    78 		{
    79         seekPos--;
    79 		seekPos--;
    80         clusterOffset--;
    80 		clusterOffset--;
    81         }
    81 		}
    82     if (clusterOffset==0) // Counted back to the current cluster
    82 	if (clusterOffset==0) // Counted back to the current cluster
    83         return(aClusterOffset);
    83 		return(aClusterOffset);
    84     if (seekPos<0)
    84 	if (seekPos<0)
    85         {
    85 		{
    86         iCurrentPos.iCluster=FCB_StartCluster();
    86 		iCurrentPos.iCluster=FCB_StartCluster();
    87         return(aNewRelCluster);
    87 		return(aNewRelCluster);
    88         }
    88 		}
    89 
    89 
    90     iCurrentPos.iCluster=iSeekIndex[seekPos];
    90 	iCurrentPos.iCluster=iSeekIndex[seekPos];
    91     return(aNewRelCluster-((seekPos+1)<<iSeekIndexSize));
    91 	return(aNewRelCluster-((seekPos+1)<<iSeekIndexSize));
    92     }
    92 	}
    93 
    93 
    94 void CFatFileCB::SetSeekIndexValueL(TUint aRelCluster, TUint aStoredCluster)
    94 void CFatFileCB::SetSeekIndexValueL(TUint aRelCluster, TUint aStoredCluster)
    95 //
    95 //
    96 // Sets a value in the seekindex
    96 // Sets a value in the seekindex
    97 //
    97 //
    98     {
    98 	{
    99 
    99 
   100     TInt seekPos=(aRelCluster>>iSeekIndexSize)-1;
   100 	TInt seekPos=(aRelCluster>>iSeekIndexSize)-1;
   101     __ASSERT_DEBUG(seekPos<KSeekIndexSize,Fault(EFatFileSeekIndexTooSmall));
   101 	__ASSERT_DEBUG(seekPos<KSeekIndexSize,Fault(EFatFileSeekIndexTooSmall));
   102     __ASSERT_DEBUG(seekPos>=0,Fault(EFatFileSeekIndexTooSmall2));
   102 	__ASSERT_DEBUG(seekPos>=0,Fault(EFatFileSeekIndexTooSmall2));
   103     iSeekIndex[seekPos] = aStoredCluster;
   103 	iSeekIndex[seekPos] = aStoredCluster;
   104     }
   104 	}
   105 
   105 
   106 void CFatFileCB::CheckPosL(TUint aPos)
   106 void CFatFileCB::CheckPosL(TUint aPos)
   107 //
   107 //
   108 // Check that the file is positioned correctly.
   108 // Check that the file is positioned correctly.
   109 // If aPos<currentPos attempt to guess the new position.
   109 // If aPos<currentPos attempt to guess the new position.
   110 //
   110 //
   111     {
   111 	{
   112     __PRINT1(_L("CFatFileCB::CheckPosL(%d)"), aPos);
   112 	__PRINT1(_L("CFatFileCB::CheckPosL(%d)"), aPos);
   113     if (aPos==iCurrentPos.iPos)
   113 	if (aPos==iCurrentPos.iPos)
   114         return;
   114 		return;
   115     __ASSERT_DEBUG(aPos <= FCB_FileSize(), Fault(EFatFilePosBeyondEnd));
   115     __ASSERT_DEBUG(aPos <= FCB_FileSize(), Fault(EFatFilePosBeyondEnd));
   116 
   116 
   117     TUint newRelCluster=aPos>>ClusterSizeLog2();
   117 	TUint newRelCluster=aPos>>ClusterSizeLog2();
   118     if ( aPos && (aPos==(newRelCluster<<ClusterSizeLog2())) )
   118 	if ( aPos && (aPos==(newRelCluster<<ClusterSizeLog2())) )
   119         newRelCluster--;
   119 		newRelCluster--;
   120     TUint oldRelCluster=iCurrentPos.iPos>>ClusterSizeLog2();
   120 	TUint oldRelCluster=iCurrentPos.iPos>>ClusterSizeLog2();
   121     
   121 	
   122     if ( iCurrentPos.iPos && (iCurrentPos.iPos==(oldRelCluster<<ClusterSizeLog2())) )
   122 	if ( iCurrentPos.iPos && (iCurrentPos.iPos==(oldRelCluster<<ClusterSizeLog2())) )
   123         oldRelCluster--;    
   123 		oldRelCluster--;	
   124     
   124 	
   125     TInt clusterOffset=newRelCluster-oldRelCluster;
   125 	TInt clusterOffset=newRelCluster-oldRelCluster;
   126     TUint32 oldCluster=iCurrentPos.iCluster;
   126 	TUint32 oldCluster=iCurrentPos.iCluster;
   127 
   127 
   128     iCurrentPos.iPos=aPos;
   128 	iCurrentPos.iPos=aPos;
   129     if (clusterOffset==0)
   129 	if (clusterOffset==0)
   130         return;
   130 		return;
   131     TInt seekOffset=clusterOffset;
   131 	TInt seekOffset=clusterOffset;
   132     if (iSeekIndex!=NULL)
   132 	if (iSeekIndex!=NULL)
   133         { // Can alter iCurrentPos.iCluster
   133 		{ // Can alter iCurrentPos.iCluster
   134         seekOffset=SeekToPosition(newRelCluster,seekOffset);
   134 		seekOffset=SeekToPosition(newRelCluster,seekOffset);
   135         if (seekOffset==0)
   135 		if (seekOffset==0)
   136             return;
   136 			return;
   137         }
   137 		}
   138     if (clusterOffset==-1 && seekOffset!=1)
   138 	if (clusterOffset==-1 && seekOffset!=1)
   139         { // Check previous cluster
   139 		{ // Check previous cluster
   140         TUint32 cluster=oldCluster-1;
   140 		TUint32 cluster=oldCluster-1;
   141         if (FAT().GetNextClusterL(cluster) && cluster==oldCluster)
   141 		if (FAT().GetNextClusterL(cluster) && cluster==oldCluster)
   142             {
   142 			{
   143             iCurrentPos.iCluster=oldCluster-1;
   143             iCurrentPos.iCluster=oldCluster-1;
   144             return;
   144 			return;
   145             }
   145 			}
   146         }
   146 		}
   147     if (seekOffset<0)
   147 	if (seekOffset<0)
   148         {
   148 		{
   149         seekOffset=newRelCluster;
   149 		seekOffset=newRelCluster;
   150         iCurrentPos.iCluster=FCB_StartCluster();
   150 		iCurrentPos.iCluster=FCB_StartCluster();
   151         }
   151 		}
   152     while (seekOffset--)
   152 	while (seekOffset--)
   153         {
   153 		{
   154         if (!FAT().GetNextClusterL(iCurrentPos.iCluster))
   154         if (!FAT().GetNextClusterL(iCurrentPos.iCluster))
   155             {
   155             {
   156             __PRINT(_L("CFatFileCB::CheckPosL() corrupt#1"));
   156             __PRINT(_L("CFatFileCB::CheckPosL() corrupt#1"));
   157             User::Leave(KErrCorrupt);
   157             User::Leave(KErrCorrupt);
   158             }
   158             }
   159         TInt cluster=newRelCluster-seekOffset;
   159         TInt cluster=newRelCluster-seekOffset;
   160         if (iSeekIndex!=NULL && cluster && (cluster>>iSeekIndexSize)<<iSeekIndexSize==cluster)
   160 		if (iSeekIndex!=NULL && cluster && (cluster>>iSeekIndexSize)<<iSeekIndexSize==cluster)
   161             SetSeekIndexValueL(cluster,iCurrentPos.iCluster);
   161 			SetSeekIndexValueL(cluster,iCurrentPos.iCluster);
   162         }
   162 		}
   163     }
   163 	}
   164 
   164 
   165 //-----------------------------------------------------------------------------
   165 //-----------------------------------------------------------------------------
   166 /** 
   166 /** 
   167     Initialize FileCB from file's entry data.
   167     Initialize FileCB from file's entry data.
   168     
   168     
   169     @param  aFatDirEntry        this file DOS dir entry.
   169     @param  aFatDirEntry        this file DOS dir entry.
   170     @param  aFileDosEntryPos    this file DOS entry dir. iterator in the parent directory.
   170     @param  aFileDosEntryPos    this file DOS entry dir. iterator in the parent directory.
   171 */
   171 */
   172 void CFatFileCB::SetupL(const TFatDirEntry& aFatDirEntry, const TEntryPos& aFileDosEntryPos)
   172 void CFatFileCB::SetupL(const TFatDirEntry& aFatDirEntry, const TEntryPos& aFileDosEntryPos)
   173     {
   173 	{
   174     __PRINT1(_L("CFatFileCB::SetupL[0x%x]"), this);
   174 	__PRINT1(_L("CFatFileCB::SetupL[0x%x]"), this);
   175     
   175 	
   176 
   176 
   177     //-- set up a file control block
   177     //-- set up a file control block
   178     iCurrentPos.iCluster= FatMount().StartCluster(aFatDirEntry);
   178 	iCurrentPos.iCluster= FatMount().StartCluster(aFatDirEntry);
   179     iCurrentPos.iPos=0;
   179 	iCurrentPos.iPos=0;
   180     
   180 	
   181     SetAtt(aFatDirEntry.Attributes());
   181     SetAtt(aFatDirEntry.Attributes());
   182     SetModified(aFatDirEntry.Time(FatMount().TimeOffset()));
   182 	SetModified(aFatDirEntry.Time(FatMount().TimeOffset()));
   183     
   183     
   184     FCB_SetStartCluster(iCurrentPos.iCluster);
   184     FCB_SetStartCluster(iCurrentPos.iCluster);
   185     FCB_SetFileSize(aFatDirEntry.Size()); 
   185     FCB_SetFileSize(aFatDirEntry.Size()); 
   186 
   186 
   187     iFileDosEntryPos = aFileDosEntryPos;
   187 	iFileDosEntryPos = aFileDosEntryPos;
   188 
   188 
   189     SetMaxSupportedSize(KMaxSupportedFatFileSize);
   189     SetMaxSupportedSize(KMaxSupportedFatFileSize);
   190 
   190 
   191     //-- create seek index
   191     //-- create seek index
   192     ASSERT(!iSeekIndex);
   192     ASSERT(!iSeekIndex);
   196 
   196 
   197     
   197     
   198     IndicateFileAttModified(EFalse);
   198     IndicateFileAttModified(EFalse);
   199     IndicateFileSizeModified(EFalse);
   199     IndicateFileSizeModified(EFalse);
   200     IndicateFileTimeModified(EFalse);
   200     IndicateFileTimeModified(EFalse);
   201     }
   201 	}
   202 
   202 
   203 //-----------------------------------------------------------------------------
   203 //-----------------------------------------------------------------------------
   204 /**
   204 /**
   205     Read data from the file.
   205     Read data from the file.
   206     
   206     
   212 
   212 
   213     @leave on media read error
   213     @leave on media read error
   214 
   214 
   215 */
   215 */
   216 void CFatFileCB::ReadL(TInt64 aPos,TInt& aLength, TDes8* aDes, const RMessagePtr2& aMessage, TInt aOffset)
   216 void CFatFileCB::ReadL(TInt64 aPos,TInt& aLength, TDes8* aDes, const RMessagePtr2& aMessage, TInt aOffset)
   217     {
   217 	{
   218     __PRINT3(_L("CFatFileCB::ReadL[0x%x] pos=%LU len=%d"), this, aPos, aLength);
   218 	__PRINT3(_L("CFatFileCB::ReadL[0x%x] pos=%LU len=%d"), this, aPos, aLength);
   219     
   219 	
   220     if((TUint64)aPos > KMaxSupportedFatFileSize-1)
   220     if((TUint64)aPos > KMaxSupportedFatFileSize-1)
   221         User::Leave(KErrNotSupported);  //-- max. position in the file is 0xFFFFFFFE
   221         User::Leave(KErrNotSupported);  //-- max. position in the file is 0xFFFFFFFE
   222 
   222 
   223     FatMount().CheckStateConsistentL();
   223     FatMount().CheckStateConsistentL();
   224     
   224     
   225     CheckPosL(I64LOW(aPos));
   225 	CheckPosL(I64LOW(aPos));
   226     
   226 	
   227     const TUint startPos = iCurrentPos.iPos;
   227 	const TUint startPos = iCurrentPos.iPos;
   228     const TUint curSize  = FCB_FileSize();
   228 	const TUint curSize  = FCB_FileSize();
   229     const TUint length   = (TUint)aLength;
   229 	const TUint length   = (TUint)aLength;
   230     
   230 	
   231     if((startPos + length > curSize) || (startPos > startPos + length) )
   231 	if((startPos + length > curSize) || (startPos > startPos + length) )
   232         aLength=curSize-startPos;
   232 		aLength=curSize-startPos;
   233 		
   233 		
   234 	TUint flag = DirectIOMode(aMessage) ? RLocalDrive::ELocDrvDirectIO : 0;
   234 	TUint flag = DirectIOMode(aMessage) ? RLocalDrive::ELocDrvDirectIO : 0;
   235 	
   235 	
   236     FatMount().ReadFromClusterListL(iCurrentPos,aLength,aDes,aMessage,aOffset, flag);
   236     FatMount().ReadFromClusterListL(iCurrentPos,aLength,aDes,aMessage,aOffset, flag);
   237 	aLength=iCurrentPos.iPos-startPos;
   237 	aLength=iCurrentPos.iPos-startPos;
   238 	}
   238 	}
   239 
   239 
   240 
   240 
   241 void CFatFileCB::ReadL(TInt aFilePos,TInt& aLength,const TAny* aTrg,const RMessagePtr2& aMessage)
   241 void CFatFileCB::ReadL(TInt aFilePos,TInt& aLength,const TAny* aTrg,const RMessagePtr2& aMessage)
   242     {
   242 	{
   243     ReadL(TInt64(aFilePos),aLength,(TDes8*) aTrg,aMessage, 0);
   243 	ReadL(TInt64(aFilePos),aLength,(TDes8*) aTrg,aMessage, 0);
   244     }
   244 	}
   245 
   245 
   246 //-----------------------------------------------------------------------------
   246 //-----------------------------------------------------------------------------
   247 /**
   247 /**
   248     Write data to the file.
   248     Write data to the file.
   249     
   249     
   255 
   255 
   256     @leave on media read error
   256     @leave on media read error
   257 
   257 
   258 */
   258 */
   259 void CFatFileCB::WriteL(TInt64 aPos,TInt& aLength,const TDesC8* aSrc,const RMessagePtr2& aMessage, TInt aOffset)
   259 void CFatFileCB::WriteL(TInt64 aPos,TInt& aLength,const TDesC8* aSrc,const RMessagePtr2& aMessage, TInt aOffset)
   260     {
   260 	{
   261     __PRINT3(_L("CFatFileCB::WriteL[0x%x] pos=%LU len=%d"), this, aPos, aLength);
   261 	__PRINT3(_L("CFatFileCB::WriteL[0x%x] pos=%LU len=%d"), this, aPos, aLength);
   262 
   262 
   263     // FAT supports 32 bits only for file size
   263 	// FAT supports 32 bits only for file size
   264     TUint64 endPos = aPos + aLength;
   264    	TUint64 endPos = aPos + aLength;
   265     if(endPos > KMaxSupportedFatFileSize)
   265    	if(endPos > KMaxSupportedFatFileSize)
   266         User::Leave(KErrNotSupported);
   266    		User::Leave(KErrNotSupported);
   267     
   267    	
   268     FatMount().CheckStateConsistentL();
   268     FatMount().CheckStateConsistentL();
   269     FatMount().CheckWritableL();
   269     FatMount().CheckWritableL();
   270     const TUint pos = I64LOW(aPos);
   270     const TUint pos = I64LOW(aPos);
   271     CheckPosL(pos);
   271   	CheckPosL(pos);
   272     
   272   	
   273     const TUint startCluster = FCB_StartCluster();
   273 	const TUint startCluster = FCB_StartCluster();
   274     const TUint length       = (TUint)aLength;
   274 	const TUint length       = (TUint)aLength;
   275     
   275 	
   276     endPos = iCurrentPos.iPos + length; 
   276 	endPos = iCurrentPos.iPos + length; 
   277     if ((endPos           > FCB_FileSize()) ||
   277 	if ((endPos           > FCB_FileSize()) ||
   278         (iCurrentPos.iPos > endPos)         ) // Overflow condition 
   278 	    (iCurrentPos.iPos > endPos)         ) // Overflow condition 
   279         DoSetSizeL(iCurrentPos.iPos+length,EFalse);
   279 		DoSetSizeL(iCurrentPos.iPos+length,EFalse);
   280     
   280    	
   281     TUint startPos=iCurrentPos.iPos;
   281 	TUint startPos=iCurrentPos.iPos;
   282     TUint badcluster=0;
   282 	TUint badcluster=0;
   283     TUint goodcluster=0;
   283 	TUint goodcluster=0;
   284    	
   284    	
   285 	TUint flag = DirectIOMode(aMessage) ? RLocalDrive::ELocDrvDirectIO : 0;
   285 	TUint flag = DirectIOMode(aMessage) ? RLocalDrive::ELocDrvDirectIO : 0;
   286 	
   286 	
   287 	TRAPD(ret, FatMount().WriteToClusterListL(iCurrentPos,aLength,aSrc,aMessage,aOffset,badcluster, goodcluster, flag));
   287 	TRAPD(ret, FatMount().WriteToClusterListL(iCurrentPos,aLength,aSrc,aMessage,aOffset,badcluster, goodcluster, flag));
   288    	
   288    	
   289     if (ret == KErrCorrupt || ret == KErrDied)
   289 	if (ret == KErrCorrupt || ret == KErrDied)
   290         {
   290 		{
   291         if(startCluster == 0)
   291         if(startCluster == 0)
   292             { //Empty File, revert all the clusters allocated.
   292 			{ //Empty File, revert all the clusters allocated.
   293             const TUint32 cluster = FCB_StartCluster();
   293 			const TUint32 cluster = FCB_StartCluster();
   294             FCB_SetStartCluster(0);
   294 			FCB_SetStartCluster(0);
   295             FCB_SetFileSize(0);
   295 			FCB_SetFileSize(0);
   296             IndicateFileSizeModified(ETrue);
   296 			IndicateFileSizeModified(ETrue);
   297             
   297             
   298             FlushAllL();
   298 			FlushAllL();
   299 
   299 
   300             iCurrentPos.iCluster = 0;
   300 			iCurrentPos.iCluster = 0;
   301             iCurrentPos.iPos = 0;
   301 			iCurrentPos.iPos = 0;
   302 
   302 
   303             FAT().FreeClusterListL(cluster);
   303 			FAT().FreeClusterListL(cluster);
   304             FAT().FlushL();
   304 			FAT().FlushL();
   305             }
   305 			}
   306         else
   306 		else
   307             { //Calculate the clusters required based on file size, revert extra clusters if allocated.
   307 			{ //Calculate the clusters required based on file size, revert extra clusters if allocated.
   308             const TUint curSize = FCB_FileSize();
   308 			const TUint curSize = FCB_FileSize();
   309             TUint ClustersNeeded = curSize >> ClusterSizeLog2();
   309 			TUint ClustersNeeded = curSize >> ClusterSizeLog2();
   310             if(curSize > (ClustersNeeded << ClusterSizeLog2()))
   310 			if(curSize > (ClustersNeeded << ClusterSizeLog2()))
   311                 {
   311 				{
   312                 ClustersNeeded++;
   312 				ClustersNeeded++;
   313                 }
   313 				}
   314 
   314 
   315             TUint32 cluster = FCB_StartCluster();
   315 			TUint32 cluster = FCB_StartCluster();
   316             while(--ClustersNeeded)
   316 			while(--ClustersNeeded)
   317                 {
   317 				{
   318                 FAT().GetNextClusterL(cluster);
   318 				FAT().GetNextClusterL(cluster);
   319                 }
   319 				}
   320                 
   320                 
   321             iCurrentPos.iCluster = cluster;
   321 			iCurrentPos.iCluster = cluster;
   322 
   322 
   323             if (FAT().GetNextClusterL(cluster))
   323 			if (FAT().GetNextClusterL(cluster))
   324                 {
   324 				{
   325                 FAT().FreeClusterListL(cluster);
   325 				FAT().FreeClusterListL(cluster);
   326                 }
   326 				}
   327 
   327 
   328             FAT().WriteFatEntryEofL(iCurrentPos.iCluster);
   328 			FAT().WriteFatEntryEofL(iCurrentPos.iCluster);
   329             FAT().FlushL();
   329 			FAT().FlushL();
   330             }
   330 			}
   331         }
   331 		}
   332 
   332 
   333     User::LeaveIfError(ret);
   333 	User::LeaveIfError(ret);
   334 
   334 
   335     if(badcluster != 0)
   335 	if(badcluster != 0)
   336         {
   336 		{
   337         if(FCB_StartCluster() == badcluster)
   337 		if(FCB_StartCluster() == badcluster)
   338             {
   338 			{
   339             FCB_SetStartCluster(goodcluster);
   339             FCB_SetStartCluster(goodcluster);
   340             FlushStartClusterL();
   340 			FlushStartClusterL();
   341             }
   341 			}
   342         else
   342 		else
   343             {
   343 			{
   344             TUint32 aCluster = FCB_StartCluster();
   344 			TUint32 aCluster = FCB_StartCluster();
   345             do
   345 			do
   346                 {
   346 				{
   347                 if((TUint)badcluster == FAT().ReadL(aCluster))
   347                 if((TUint)badcluster == FAT().ReadL(aCluster))
   348                     {
   348 					{
   349                     FAT().WriteL(aCluster, goodcluster);
   349 					FAT().WriteL(aCluster, goodcluster);
   350                     FAT().FlushL();
   350 					FAT().FlushL();
   351                     break;
   351 					break;
   352                     }
   352 					}
   353                 }
   353 				}
   354             while(FAT().GetNextClusterL(aCluster));
   354 			while(FAT().GetNextClusterL(aCluster));
   355             }
   355 			}
   356         }
   356 		}
   357     aLength=iCurrentPos.iPos-startPos;
   357 	aLength=iCurrentPos.iPos-startPos;
   358 
   358 
   359     if(!IsSequentialMode() && FatMount().IsRuggedFSys() && pos+(TUint)aLength > FCB_FileSize())
   359 	if(FatMount().IsRuggedFSys() && pos+(TUint)aLength > FCB_FileSize())
   360         {
   360 		{
   361         WriteFileSizeL(pos+aLength);
   361 		WriteFileSizeL(pos+aLength);
   362         }
   362 		}
   363 
   363 
   364     }
   364 	}
   365 
   365 
   366 
   366 
   367 void CFatFileCB::WriteL(TInt aFilePos,TInt& aLength,const TAny* aSrc,const RMessagePtr2& aMessage)
   367 void CFatFileCB::WriteL(TInt aFilePos,TInt& aLength,const TAny* aSrc,const RMessagePtr2& aMessage)
   368     {
   368 	{
   369     WriteL(TInt64(aFilePos),aLength,(TDesC8*) aSrc,aMessage, 0);
   369 	WriteL(TInt64(aFilePos),aLength,(TDesC8*) aSrc,aMessage, 0);
   370     }
   370 	}
       
   371 
   371 
   372 
   372 
   373 
   373 //-----------------------------------------------------------------------------
   374 //-----------------------------------------------------------------------------
   374 
   375 
   375 void CFatFileCB::ResizeIndex(TInt aNewMult,TUint aNewSize)
   376 void CFatFileCB::ResizeIndex(TInt aNewMult,TUint aNewSize)
   376 //
   377 //
   377 // Resize the seek index to accomodate a larger or smaller filesize
   378 // Resize the seek index to accomodate a larger or smaller filesize
   378 // Assumes KSeekIndexSize is a power of 2.
   379 // Assumes KSeekIndexSize is a power of 2.
   379 //
   380 //
   380     {
   381 	{
   381 
   382 
   382     TInt maxNewIndex=aNewSize>>(ClusterSizeLog2()+aNewMult);
   383 	TInt maxNewIndex=aNewSize>>(ClusterSizeLog2()+aNewMult);
   383 
   384 
   384 
   385 
   385     TInt    index=0;
   386 	TInt    index=0;
   386     TInt    indexEnd=KSeekIndexSize;
   387 	TInt	indexEnd=KSeekIndexSize;
   387     TInt    newValEnd=maxNewIndex;
   388 	TInt	newValEnd=maxNewIndex;
   388 
   389 
   389     if (iSeekIndexSize<aNewMult)
   390 	if (iSeekIndexSize<aNewMult)
   390         {
   391 		{
   391         TInt newVal=index;
   392 		TInt newVal=index;
   392         TInt step=1<<(aNewMult-iSeekIndexSize);
   393 		TInt step=1<<(aNewMult-iSeekIndexSize);
   393         index+=step-1;
   394 		index+=step-1;
   394         while(index<indexEnd && newVal<newValEnd)
   395 		while(index<indexEnd && newVal<newValEnd)
   395             {
   396 			{
   396             iSeekIndex[newVal] =  iSeekIndex[index];
   397 			iSeekIndex[newVal] =  iSeekIndex[index];
   397             newVal++;
   398 			newVal++;
   398             index+=step;
   399 			index+=step;
   399             }
   400 			}
   400         while(newVal<indexEnd)
   401 		while(newVal<indexEnd)
   401             iSeekIndex[newVal++] =  0;
   402 			iSeekIndex[newVal++] =  0;
   402         }
   403 		}
   403     else
   404 	else
   404         {
   405 		{
   405         TInt diffSize = iSeekIndexSize-aNewMult;
   406 		TInt diffSize = iSeekIndexSize-aNewMult;
   406         TInt oldVal=(KSeekIndexSize>>diffSize) - 1;
   407 		TInt oldVal=(KSeekIndexSize>>diffSize) - 1;
   407         TInt newVal=indexEnd-1;
   408 		TInt newVal=indexEnd-1;
   408         TInt skip=(1<<diffSize)-1;
   409 		TInt skip=(1<<diffSize)-1;
   409 
   410 
   410         if ((iSeekIndexSize - aNewMult) > KSeekIndexSizeLog2)
   411 		if ((iSeekIndexSize - aNewMult) > KSeekIndexSizeLog2)
   411             {
   412 			{
   412             ClearIndex(0); //-- Invalidate every entry.
   413             ClearIndex(0); //-- Invalidate every entry.
   413             }
   414 			}
   414         else
   415 		else
   415             {
   416 			{
   416             while(newVal>=index)
   417 			while(newVal>=index)
   417                 {
   418 				{
   418 
   419 
   419                 iSeekIndex[newVal--] =  iSeekIndex[oldVal--];
   420 				iSeekIndex[newVal--] =  iSeekIndex[oldVal--];
   420 
   421 
   421 
   422 
   422                 for(TInt i=skip;i>0;i--)
   423 				for(TInt i=skip;i>0;i--)
   423                     {   
   424 					{	
   424                     iSeekIndex[newVal--] = 0;
   425 					iSeekIndex[newVal--] = 0;
   425 
   426 
   426                     }
   427 					}
   427                 }
   428 				}
   428             }
   429 			}
   429         }
   430 		}
   430     iSeekIndexSize=aNewMult;
   431 	iSeekIndexSize=aNewMult;
   431     }
   432 	}
   432 
   433 
   433 
   434 
   434 /**
   435 /**
   435     Zero freed clusters in the index
   436     Zero freed clusters in the index
   436 
   437 
   437     @param  aNewSize new size of the file that the index corresponds to.
   438     @param  aNewSize new size of the file that the index corresponds to.
   438             if = 0  all existing index will be zero filled
   439             if = 0  all existing index will be zero filled
   439 */ 
   440 */ 
   440 void CFatFileCB::ClearIndex(TUint aNewSize)
   441 void CFatFileCB::ClearIndex(TUint aNewSize)
   441     {
   442 	{
   442 
   443 
   443     if (!iSeekIndex)
   444 	if (!iSeekIndex)
   444         return;
   445 	    return;
   445 
   446 
   446     if(aNewSize==0)
   447     if(aNewSize==0)
   447         {
   448     	{
   448         //-- zero fill all the array
   449     	//-- zero fill all the array
   449         Mem::FillZ(iSeekIndex, KSeekIndexSize*sizeof(TUint32));
   450         Mem::FillZ(iSeekIndex, KSeekIndexSize*sizeof(TUint32));
   450         return;
   451 		return;
   451         }
   452     	}
   452 
   453 
   453     // Files that fill up a cluster exactly do not have a trailing empty
   454 	// Files that fill up a cluster exactly do not have a trailing empty
   454     // cluster. So the entry for that position must also be invalidated
   455 	// cluster. So the entry for that position must also be invalidated
   455     aNewSize--;
   456 	aNewSize--;
   456     TInt firstInvalidIndex=aNewSize>>(iSeekIndexSize+ClusterSizeLog2());
   457 	TInt firstInvalidIndex=aNewSize>>(iSeekIndexSize+ClusterSizeLog2());
   457         
   458 		
   458     TInt indexLen=KSeekIndexSize-firstInvalidIndex;
   459 	TInt indexLen=KSeekIndexSize-firstInvalidIndex;
   459 
   460 
   460     Mem::FillZ(iSeekIndex+firstInvalidIndex, indexLen * sizeof(TUint32));
   461 	Mem::FillZ(iSeekIndex+firstInvalidIndex, indexLen * sizeof(TUint32));
   461     }
   462 	}
   462 
   463 
   463 TInt CFatFileCB::CalcSeekIndexSize(TUint aSize)
   464 TInt CFatFileCB::CalcSeekIndexSize(TUint aSize)
   464 //
   465 //
   465 // Find the nearest power of 2 > aSize
   466 // Find the nearest power of 2 > aSize
   466 //
   467 //
   467     {
   468 	{
   468     TInt count = 0;
   469 	TInt count = 0;
   469     const TUint indexSize=KSeekIndexSize<<ClusterSizeLog2();//KSeekIndexSize=128
   470 	const TUint indexSize=KSeekIndexSize<<ClusterSizeLog2();//KSeekIndexSize=128
   470     if (aSize<=indexSize)
   471 	if (aSize<=indexSize)
   471       return(count);
   472 	  return(count);
   472     
   473 	
   473     while((aSize>>=1)>0)
   474 	while((aSize>>=1)>0)
   474         {
   475 		{
   475         count++;
   476 		count++;
   476         }
   477 		}
   477     return (count - (KSeekIndexSizeLog2 + ClusterSizeLog2()) + 1);
   478 	return (count - (KSeekIndexSizeLog2 + ClusterSizeLog2()) + 1);
   478     }
   479 	}
   479 
   480 
   480 //-----------------------------------------------------------------------------
   481 //-----------------------------------------------------------------------------
   481 /**
   482 /**
   482     Set file size.
   483     Set file size.
   483     @param aSize new file size.
   484     @param aSize new file size.
   484 */
   485 */
   485 void CFatFileCB::SetSizeL(TInt64 aSize)
   486 void CFatFileCB::SetSizeL(TInt64 aSize)
   486     {
   487 	{
   487     __PRINT2(_L("CFatFileCB::SetSizeL[0x%x] sz=%LU"), this, aSize);
   488 	__PRINT2(_L("CFatFileCB::SetSizeL[0x%x] sz=%LU"), this, aSize);
   488     
   489 	
   489     //-- max. file size for FAT is 4GB-1
   490 	//-- max. file size for FAT is 4GB-1
   490     if (I64HIGH(aSize))
   491 	if (I64HIGH(aSize))
   491         User::Leave(KErrNotSupported);
   492 		User::Leave(KErrNotSupported);
   492 
   493 
   493     DoSetSizeL(I64LOW(aSize), FatMount().IsRuggedFSys());
   494     DoSetSizeL(I64LOW(aSize), FatMount().IsRuggedFSys());
   494     }
   495 	}
   495 
   496 
   496 
   497 
   497 void CFatFileCB::SetSizeL(TInt aSize)
   498 void CFatFileCB::SetSizeL(TInt aSize)
   498     {
   499 	{
   499     SetSizeL(TInt64(aSize));
   500 	SetSizeL(TInt64(aSize));
   500     }
   501 	}
   501 
   502 
   502 //-----------------------------------------------------------------------------
   503 //-----------------------------------------------------------------------------
   503 /**
   504 /**
   504     Shrink file to zero size.
   505     Shrink file to zero size.
   505 */
   506 */
   506 void CFatFileCB::DoShrinkFileToZeroSizeL()
   507 void CFatFileCB::DoShrinkFileToZeroSizeL()
   507     {
   508     {
   508         ASSERT(FCB_FileSize());
   509 	    ASSERT(FCB_FileSize());
   509         ASSERT(FileSizeModified());
   510         ASSERT(FileSizeModified());
   510         
   511         
   511         ClearIndex(0); // Clear seek index array
   512             ClearIndex(0); //-- clear seek index array
   512         
   513 		
   513         //-- update file dir. entry
   514         //-- update file dir. entry
   514         const TUint32 cluster = FCB_StartCluster();
   515         const TUint32 cluster = FCB_StartCluster();
   515         FCB_SetStartCluster(0);
   516 		FCB_SetStartCluster(0);
   516         FCB_SetFileSize(0);
   517 		FCB_SetFileSize(0);
   517             FlushAllL();
   518 			FlushAllL();
   518         
   519 		
   519         //-- free cluster list. 
   520         //-- free cluster list. 
   520             CheckPosL(0);
   521 			CheckPosL(0);
   521             FAT().FreeClusterListL(cluster);
   522 			FAT().FreeClusterListL(cluster);
   522             FAT().FlushL();
   523 			FAT().FlushL();
   523             }
   524 			}
   524 
   525 
   525 //-----------------------------------------------------------------------------
   526 //-----------------------------------------------------------------------------
   526 /*
   527 /*
   527     Shrink file to smaller size, but > 0
   528     Shrink file to smaller size, but > 0
   528 
   529 
   529     @param aNewSize new file size
   530     @param aNewSize new file size
   530     @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed 
   531     @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed 
   531 */
   532 */
   532 void CFatFileCB::DoShrinkFileL(TUint32 aNewSize, TBool aForceCachesFlush)
   533 void CFatFileCB::DoShrinkFileL(TUint32 aNewSize, TBool aForceCachesFlush)
   533     {
   534 		{
   534     ASSERT(FileSizeModified());
   535     ASSERT(FileSizeModified());
   535     ASSERT(FCB_FileSize() > aNewSize && aNewSize);
   536     ASSERT(FCB_FileSize() > aNewSize && aNewSize);
   536     
   537 	
   537     if(aForceCachesFlush)       
   538     if(aForceCachesFlush)		
   538         WriteFileSizeL(aNewSize); //-- write file size directly to its dir. entry
   539         WriteFileSizeL(aNewSize); //-- write file size directly to its dir. entry
   539 
   540 
   540     CheckPosL(aNewSize);
   541 	CheckPosL(aNewSize);
   541 
   542 	
   542     TUint32 cluster=iCurrentPos.iCluster;
   543     TUint32 cluster=iCurrentPos.iCluster;
   543     
   544 		if (FAT().GetNextClusterL(cluster))
   544     if (FAT().GetNextClusterL(cluster))
   545 	    {//-- truncate the cluster chain
   545         {//-- truncate the cluster chain
   546 			FAT().WriteFatEntryEofL(iCurrentPos.iCluster);
   546         FAT().WriteFatEntryEofL(iCurrentPos.iCluster);
   547 			FAT().FreeClusterListL(cluster);
   547         FAT().FreeClusterListL(cluster);
   548 			}
   548         }
   549 		
   549         
       
   550     ClearIndex(aNewSize);
   550     ClearIndex(aNewSize);
   551     FAT().FlushL();
   551 		FAT().FlushL();
   552     }
   552 		}
   553     
   553 	
   554 //-----------------------------------------------------------------------------
   554 //-----------------------------------------------------------------------------
   555 /**
   555 /**
   556     Expand a file.
   556     Expand a file.
   557     
   557 	
   558     @param aNewSize new file size.
   558     @param aNewSize new file size.
   559     @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed
   559     @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed
   560 */
   560 */
   561 void CFatFileCB::DoExpandFileL(TUint32 aNewSize, TBool aForceCachesFlush)
   561 void CFatFileCB::DoExpandFileL(TUint32 aNewSize, TBool aForceCachesFlush)
   562     {
   562 		{
   563     ASSERT(FCB_FileSize() < aNewSize);
   563     ASSERT(FCB_FileSize() < aNewSize);
   564     ASSERT(FileSizeModified());
   564     ASSERT(FileSizeModified());
   565 
   565 
   566     const TUint32 KClusterSzLog2  = ClusterSizeLog2();
   566     const TUint32 KClusterSzLog2  = ClusterSizeLog2();
   567     const TUint32 newSizeClusters = (TUint32)(((TUint64)aNewSize + Pow2(KClusterSzLog2) - 1) >> KClusterSzLog2);
   567     const TUint32 newSizeClusters = (TUint32)(((TUint64)aNewSize + Pow2(KClusterSzLog2) - 1) >> KClusterSzLog2);
   568 
   568 
   569 
   569 
   570     //-- expanding a file
   570 	//-- expanding a file
   571     if (FCB_StartCluster() == 0)
   571 	if (FCB_StartCluster() == 0)
   572         {//-- the initial file size is 0 (no cluster chain)
   572 		{//-- the initial file size is 0 (no cluster chain)
   573          
   573          
   574         ClearIndex(0); //-- clear seek index array
   574         ClearIndex(0); //-- clear seek index array
   575         //-- FAT().FreeClusterHint() will give us a hint of the last free cluster
   575         //-- FAT().FreeClusterHint() will give us a hint of the last free cluster
   576         const TUint32 tempStartCluster=FAT().AllocateClusterListL(newSizeClusters, FAT().FreeClusterHint()); 
   576         const TUint32 tempStartCluster=FAT().AllocateClusterListL(newSizeClusters, FAT().FreeClusterHint()); 
   577         FAT().FlushL();
   577 		FAT().FlushL();
   578 
   578 
   579         iCurrentPos.iCluster=tempStartCluster;
   579 		iCurrentPos.iCluster=tempStartCluster;
   580         FCB_SetStartCluster(tempStartCluster);
   580 		FCB_SetStartCluster(tempStartCluster);
   581         FCB_SetFileSize(aNewSize);
   581 		FCB_SetFileSize(aNewSize);
   582         FlushAllL();
   582 		FlushAllL();
   583         }
   583 		}
   584     else
   584 	else
   585         {
   585 		{
   586         const TUint curSize = FCB_FileSize(); 
   586 		const TUint curSize = FCB_FileSize(); 
   587         const TUint32 oldSizeClusters = ((curSize + Pow2(KClusterSzLog2) - 1) >> KClusterSzLog2);
   587 	    const TUint32 oldSizeClusters = ((curSize + Pow2(KClusterSzLog2) - 1) >> KClusterSzLog2);
   588         ASSERT(newSizeClusters >= oldSizeClusters);
   588         ASSERT(newSizeClusters >= oldSizeClusters);
   589         const TUint newClusters = newSizeClusters-oldSizeClusters;  //-- Number of clusters we need to append to the existing cluster chain
   589 		const TUint newClusters = newSizeClusters-oldSizeClusters;	//-- Number of clusters we need to append to the existing cluster chain
   590         if (newClusters)
   590 		if (newClusters)
   591             {
   591 			{
   592             TEntryPos currentPos=iCurrentPos;
   592 			TEntryPos currentPos=iCurrentPos;
   593             CheckPosL(FCB_FileSize());
   593 			CheckPosL(FCB_FileSize());
   594             FAT().ExtendClusterListL(newClusters,iCurrentPos.iCluster);
   594 			FAT().ExtendClusterListL(newClusters,iCurrentPos.iCluster);
   595             iCurrentPos=currentPos;
   595 			iCurrentPos=currentPos;
   596             }
   596 			}
   597     
   597 	
   598         FAT().FlushL();
   598 		FAT().FlushL();
   599         
   599 		
   600         if(!IsSequentialMode() && aForceCachesFlush)    // Write file size directly to its dir. entry if a cache flush
   600         if(aForceCachesFlush)			// write file size if increasing
   601             WriteFileSizeL(aNewSize);               // is needed and rugged FAT is not ignored by client
   601 			WriteFileSizeL(aNewSize);
   602         }
   602 		}
   603 
   603 
   604     }
   604 	}
   605 
   605 
   606 //-----------------------------------------------------------------------------
   606 //-----------------------------------------------------------------------------
   607 /**
   607 /**
   608     Set file size. This can involve extending/truncating file's cluster chain.
   608     Set file size. This can involve extending/truncating file's cluster chain.
   609     @param  aSize               new file size
   609     @param  aSize               new file size
   610     @param  aForceCachesFlush   if ETrue, all changes in metadata will go to the media immediately. 
   610     @param  aForceCachesFlush   if ETrue, all changes in metadata will go to the media immediately. 
   611                                 it is used in Rugged FAT mode.
   611                                 it is used in Rugged FAT mode.
   612 */
   612 */
   613 void CFatFileCB::DoSetSizeL(TUint aSize, TBool aForceCachesFlush)
   613 void CFatFileCB::DoSetSizeL(TUint aSize, TBool aForceCachesFlush)
   614     {
   614 	{
   615     __PRINT4(_L("CFatFileCB::DoSetSizeL[0x%x] sz:%d, oldSz:%d, flush:%d"), this, aSize, FCB_FileSize(), aForceCachesFlush);
   615 	__PRINT4(_L("CFatFileCB::DoSetSizeL[0x%x] sz:%d, oldSz:%d, flush:%d"), this, aSize, FCB_FileSize(), aForceCachesFlush);
   616 
   616 
   617     FatMount().CheckStateConsistentL();
   617     FatMount().CheckStateConsistentL();
   618     FatMount().CheckWritableL();
   618     FatMount().CheckWritableL();
   619 
   619 
   620     
   620 	
   621     // Can not change the file size if it is clamped
   621 	// Can not change the file size if it is clamped
   622     if(Mount().IsFileClamped(MAKE_TINT64(0,FCB_StartCluster())) > 0)
   622 	if(Mount().IsFileClamped(MAKE_TINT64(0,FCB_StartCluster())) > 0)
   623         User::Leave(KErrInUse);
   623 		User::Leave(KErrInUse);
   624     
   624 	
   625     if(aSize == FCB_FileSize())
   625 	if(aSize == FCB_FileSize())
   626         return;
   626         return;
   627 
   627 
   628     IndicateFileSizeModified(ETrue);
   628     IndicateFileSizeModified(ETrue);
   629 	IndicateFileAttModified(ETrue);		// ensure file size is flushed
   629 	IndicateFileAttModified(ETrue);		// ensure file size is flushed
   630 
   630 
   639         DoShrinkFileToZeroSizeL();
   639         DoShrinkFileToZeroSizeL();
   640         return;
   640         return;
   641         }
   641         }
   642 
   642 
   643     //-------------------------------------------
   643     //-------------------------------------------
   644     //-- shrinking file to non-zero size
   644 	//-- shrinking file to non-zero size
   645     if (aSize < FCB_FileSize())
   645     if (aSize < FCB_FileSize())
   646         {
   646 		{
   647         DoShrinkFileL(aSize, aForceCachesFlush);
   647         DoShrinkFileL(aSize, aForceCachesFlush);
   648         return;
   648         return;
   649         }
   649         }
   650     
   650     
   651     //-------------------------------------------
   651     //-------------------------------------------
   652     //-- expanding a file
   652 	//-- expanding a file
   653     DoExpandFileL(aSize, aForceCachesFlush);
   653     DoExpandFileL(aSize, aForceCachesFlush);
   654 
   654 
   655     }
   655 	}
   656 
   656 
   657 //-----------------------------------------------------------------------------
   657 //-----------------------------------------------------------------------------
   658 /**
   658 /**
   659     Set file entry details, like file attributes and modified time
   659     Set file entry details, like file attributes and modified time
   660     This method doesn't write data to the media immediately, instead, all modified data are cached and can be flushed later 
   660     This method doesn't write data to the media immediately, instead, all modified data are cached and can be flushed later 
   664     @param  aSetAttMask     file attributes OR mask
   664     @param  aSetAttMask     file attributes OR mask
   665     @param  aClearAttMask   file attributes AND mask
   665     @param  aClearAttMask   file attributes AND mask
   666 
   666 
   667 */
   667 */
   668 void CFatFileCB::SetEntryL(const TTime& aTime,TUint aSetAttMask,TUint aClearAttMask)
   668 void CFatFileCB::SetEntryL(const TTime& aTime,TUint aSetAttMask,TUint aClearAttMask)
   669     {
   669 	{
   670     __PRINT1(_L("CFatFileCB::SetEntryL[0x%x]"), this);
   670 	__PRINT1(_L("CFatFileCB::SetEntryL[0x%x]"), this);
   671     
   671     
   672     FatMount().CheckStateConsistentL();
   672     FatMount().CheckStateConsistentL();
   673     FatMount().CheckWritableL();
   673     FatMount().CheckWritableL();
   674 
   674 
   675     //-- change file attributes
   675     //-- change file attributes
   694         SetModified(aTime);        //-- set file modified time
   694         SetModified(aTime);        //-- set file modified time
   695         IndicateFileAttModified(ETrue); //-- indicate that file attributes have changed
   695         IndicateFileAttModified(ETrue); //-- indicate that file attributes have changed
   696         IndicateFileTimeModified(ETrue); //-- this will force writing file mod. time to the media on Flush
   696         IndicateFileTimeModified(ETrue); //-- this will force writing file mod. time to the media on Flush
   697         }
   697         }
   698 
   698 
   699     }
   699 	}
   700 
   700 
   701 
   701 
   702 //-----------------------------------------------------------------------------
   702 //-----------------------------------------------------------------------------
   703 /** 
   703 /** 
   704     The same as FlushAllL(). This method is called from RFile::Flush()
   704     The same as FlushAllL(). This method is called from RFile::Flush()
   705 */
   705 */
   706 void CFatFileCB::FlushDataL()
   706 void CFatFileCB::FlushDataL()
   707     {
   707 	{
   708     __PRINT1(_L("CFatFileCB::FlushDataL[0x%x]"), this);
   708 	__PRINT1(_L("CFatFileCB::FlushDataL[0x%x]"), this);
   709     FlushAllL();
   709     FlushAllL();
   710     }
   710 	}
   711 
   711 
   712 //-----------------------------------------------------------------------------
   712 //-----------------------------------------------------------------------------
   713 /** 
   713 /** 
   714     Flush the fide directory entry data: files size, attributes, time etc. 
   714     Flush the fide directory entry data: files size, attributes, time etc. 
   715 */
   715 */
   716 void CFatFileCB::FlushAllL()
   716 void CFatFileCB::FlushAllL()
   717     {
   717 	{
   718 
   718 
   719     //-- define this symbol in order to enable legacy behaviour, i.e. compulsory updating file dir. entry on flush.
   719     //-- define this symbol in order to enable legacy behaviour, i.e. compulsory updating file dir. entry on flush.
   720     //-- otherwise the FlushAllL() will update the file dir. entry only if it differs from what is on the media, i.e.
   720     //-- otherwise the FlushAllL() will update the file dir. entry only if it differs from what is on the media, i.e.
   721     //-- file size, start cluster, attributes and modification timestamp
   721     //-- file size, start cluster, attributes and modification timestamp
   722     #define ALWAYS_UPDATE_ENTRY_ON_FLUSH
   722     #define ALWAYS_UPDATE_ENTRY_ON_FLUSH
   723 
   723 
   724     __PRINT1(_L("CFatFileCB::FlushAllL[0x%x]"), this);
   724 	__PRINT1(_L("CFatFileCB::FlushAllL[0x%x]"), this);
   725 
   725 
   726     if (Mount().IsCurrentMount()==EFalse)
   726     if (Mount().IsCurrentMount()==EFalse)
   727         User::Leave(KErrDisMounted);
   727 		User::Leave(KErrDisMounted);
   728 
   728 
   729     FatMount().CheckStateConsistentL();
   729     FatMount().CheckStateConsistentL();
   730     FatMount().CheckWritableL();
   730     FatMount().CheckWritableL();
   731 
   731 
   732     if(!FileSizeModified() && !FileAttModified() && !FileTimeModified())
   732 	if(!FileSizeModified() && !FileAttModified() && !FileTimeModified())
   733         return; //-- nothing has changed in the file entry at all
   733         return; //-- nothing has changed in the file entry at all
   734 
   734 
   735 
   735 
   736     //-- read file dir. entry
   736     //-- read file dir. entry
   737     TFatDirEntry entry;
   737 	TFatDirEntry entry;
   738     FatMount().ReadDirEntryL(iFileDosEntryPos,entry);
   738 	FatMount().ReadDirEntryL(iFileDosEntryPos,entry);
   739     __ASSERT_ALWAYS(entry.IsEndOfDirectory()==EFalse,User::Leave(KErrCorrupt));
   739 	__ASSERT_ALWAYS(entry.IsEndOfDirectory()==EFalse,User::Leave(KErrCorrupt));
   740 
   740 
   741     //-- the problem with KEntryAttModified here is that the file server uses this flag to 
   741     //-- the problem with KEntryAttModified here is that the file server uses this flag to 
   742     //-- deal with dirty file data. This means that this flag can be set even if there were no changes
   742     //-- deal with dirty file data. This means that this flag can be set even if there were no changes
   743     //-- in file time and attributes. Just check if any of the entry field has changed at all
   743     //-- in file time and attributes. Just check if any of the entry field has changed at all
   744     
   744     
   765 
   765 
   766 #endif //#ifndef ALWAYS_UPDATE_ENTRY_TS_ON_FLUSH
   766 #endif //#ifndef ALWAYS_UPDATE_ENTRY_TS_ON_FLUSH
   767 
   767 
   768     if(bUpdateDirEntry)
   768     if(bUpdateDirEntry)
   769         {//-- write entry to the media
   769         {//-- write entry to the media
   770         __PRINT(_L("  CFatFileCB::FlushAllL #1"));
   770 	    __PRINT(_L("  CFatFileCB::FlushAllL #1"));
   771         entry.SetAttributes(Att() & KEntryAttMaskSupported);
   771         entry.SetAttributes(Att() & KEntryAttMaskSupported);
   772         entry.SetSize(FCB_FileSize());
   772 	    entry.SetSize(FCB_FileSize());
   773         entry.SetTime(iModified, timeOffset);
   773 	    entry.SetTime(iModified, timeOffset);
   774         
   774 	    
   775         entry.SetStartCluster(FCB_StartCluster());
   775         entry.SetStartCluster(FCB_StartCluster());
   776 
   776 
   777 	    const TBool setNotify = FatMount().GetNotifyUser();
   777 	    const TBool setNotify = FatMount().GetNotifyUser();
   778 		if(setNotify)
   778 	if(setNotify)
   779 			{
   779 		{
   780 			FatMount().SetNotifyOff();	// do not launch a notifier
   780 		FatMount().SetNotifyOff();	// do not launch a notifier
   781 			}
   781 		}
   782 
   782 
   783 			TRAPD(ret, FatMount().WriteDirEntryL(iFileDosEntryPos,entry));
   783 	    TRAPD(ret, FatMount().WriteDirEntryL(iFileDosEntryPos,entry));
   784 		
   784 	
   785 		if(setNotify)
   785 	if(setNotify)
   786 			{
   786 		{
   787 			FatMount().SetNotifyOn();
   787 		FatMount().SetNotifyOn();
   788 			}
   788 		}
   789 
   789 
   790 		User::LeaveIfError(ret);
   790 	User::LeaveIfError(ret);
   791 
   791 
   792 		IndicateFileSizeModified(EFalse);
   792         IndicateFileSizeModified(EFalse);
   793 		IndicateFileTimeModified(EFalse);
   793         IndicateFileTimeModified(EFalse);
   794 	    }
   794 	    }
   795 
   795 
   796 
   796 
   797     //-- KEntryAttModified must be reset anyway
   797         //-- KEntryAttModified must be reset anyway
   798     IndicateFileAttModified(EFalse); 
   798         IndicateFileAttModified(EFalse); 
   799 	}
   799 	}
   800 
   800 
   801 //-----------------------------------------------------------------------------
   801 //-----------------------------------------------------------------------------
   802 
   802 
   803 /**
   803 /**
   804     Rename already opened file.
   804     Rename already opened file.
   805     @param  aNewName new file name; all trailing dots from the name will be removed
   805     @param  aNewName new file name; all trailing dots from the name will be removed
   806 */
   806 */
   807 void CFatFileCB::RenameL(const TDesC& aNewName)
   807 void CFatFileCB::RenameL(const TDesC& aNewName)
   808     {
   808 	{
   809     __PRINT2(_L("CFatFileCB::RenameL[0x%x], name:%S"),this, &aNewName);
   809     __PRINT2(_L("CFatFileCB::RenameL[0x%x], name:%S"),this, &aNewName);
   810 
   810 
   811     FatMount().CheckStateConsistentL();
   811     FatMount().CheckStateConsistentL();
   812     FatMount().CheckWritableL();
   812     FatMount().CheckWritableL();
   813 
   813 
   814     const TPtrC fileName = RemoveTrailingDots(aNewName); //-- remove trailing dots from the name
   814     const TPtrC fileName = RemoveTrailingDots(aNewName); //-- remove trailing dots from the name
   815 
   815 
   816 
   816 
   817     FatMount().DoRenameOrReplaceL(*iFileName, fileName, CFatMountCB::EModeRename, iFileDosEntryPos);
   817 	FatMount().DoRenameOrReplaceL(*iFileName, fileName, CFatMountCB::EModeRename, iFileDosEntryPos);
   818     
   818 	
   819     AllocBufferL(iFileName, fileName);
   819     AllocBufferL(iFileName, fileName);
   820     
   820 	
   821     if(!FatMount().IsRuggedFSys())
   821 	if(!FatMount().IsRuggedFSys())
   822         FAT().FlushL();
   822 		FAT().FlushL();
   823     }
   823 	}
   824 
   824 
   825 
   825 
   826 //***********************************************************
   826 //***********************************************************
   827 //* BlockMap interface
   827 //* BlockMap interface
   828 //***********************************************************
   828 //***********************************************************
   829     
   829 	
   830 TInt CFatFileCB::BlockMap(SBlockMapInfo& aInfo, TInt64& aStartPos, TInt64 aEndPos)
   830 TInt CFatFileCB::BlockMap(SBlockMapInfo& aInfo, TInt64& aStartPos, TInt64 aEndPos)
   831 //
   831 //
   832 // Retrieves the block map of a given section of the file, in the FAT file system.
   832 // Retrieves the block map of a given section of the file, in the FAT file system.
   833 //  
   833 //	
   834     {
   834 	{
   835     __PRINT2(_L("CFatFileCB::BlockMap aStartPos=%ld aEndPos=%ld"), aStartPos, aEndPos);
   835 	__PRINT2(_L("CFatFileCB::BlockMap aStartPos=%ld aEndPos=%ld"), aStartPos, aEndPos);
   836     
   836 	
   837     if ( I64HIGH(aStartPos) || I64HIGH(aEndPos) )
   837 	if ( I64HIGH(aStartPos) || I64HIGH(aEndPos) )
   838         return KErrNotSupported;
   838 		return KErrNotSupported;
   839 
   839 
   840     TUint startPos = I64LOW(aStartPos);
   840     TUint startPos = I64LOW(aStartPos);
   841     TUint endPos = I64LOW(aEndPos);
   841 	TUint endPos = I64LOW(aEndPos);
   842 
   842 
   843     // aEndPos will always be >=0 at this point
   843 	// aEndPos will always be >=0 at this point
   844     const TUint length = endPos - startPos;
   844 	const TUint length = endPos - startPos;
   845     
   845 	
   846     // Store the position of cluster zero in aInfo
   846 	// Store the position of cluster zero in aInfo
   847     CFatMountCB& fatMount = FatMount();
   847 	CFatMountCB& fatMount = FatMount();
   848 
   848 
   849     TInt drvNo=-1;
   849 	TInt drvNo=-1;
   850     TBusLocalDrive* locDrv;
   850 	TBusLocalDrive* locDrv;
   851     if((fatMount.LocalDrive()->GetLocalDrive(locDrv)==KErrNone) && ((drvNo=GetLocalDriveNumber(locDrv))>=0) && (drvNo<KMaxLocalDrives))
   851 	if((fatMount.LocalDrive()->GetLocalDrive(locDrv)==KErrNone) && ((drvNo=GetLocalDriveNumber(locDrv))>=0) && (drvNo<KMaxLocalDrives))
   852         aInfo.iLocalDriveNumber=drvNo;
   852 		aInfo.iLocalDriveNumber=drvNo;
   853     else
   853 	else
   854         return KErrNotSupported;
   854 		return KErrNotSupported;
   855 
   855 
       
   856     TInt r;
       
   857 	
   856     // Fetch the address of cluster 0
   858     // Fetch the address of cluster 0
   857     aInfo.iStartBlockAddress = fatMount.FAT().DataPositionInBytes(KFirstClusterNum);
   859 	TRAP(r, aInfo.iStartBlockAddress = fatMount.FAT().DataPositionInBytesL(KFirstClusterNum));
   858 
   860 	if (r != KErrNone)
   859     TRAPD(r, CheckPosL(startPos));
   861 		return r;
   860     if (r != KErrNone)
   862 
   861         return r;
   863 
   862 
   864 	TRAP(r, CheckPosL(startPos));
   863     aInfo.iBlockStartOffset = fatMount.ClusterRelativePos(iCurrentPos.iPos);
   865 	if (r != KErrNone)
   864     aInfo.iBlockGranularity = 1 << FatMount().ClusterSizeLog2();
   866 		return r;
   865     const TUint myStartPos = iCurrentPos.iPos;
   867 
   866     if ( myStartPos + length > FCB_FileSize())
   868 	aInfo.iBlockStartOffset = fatMount.ClusterRelativePos(iCurrentPos.iPos);
   867         return KErrArgument;
   869 	aInfo.iBlockGranularity = 1 << FatMount().ClusterSizeLog2();
   868 
   870 	const TUint myStartPos = iCurrentPos.iPos;
   869     TRAP(r, FatMount().BlockMapReadFromClusterListL(iCurrentPos, length, aInfo));
   871 	if ( myStartPos + length > FCB_FileSize())
   870     if (r != KErrNone)
   872 		return KErrArgument;
   871         return r;
   873 
   872 
   874 	TRAP(r, FatMount().BlockMapReadFromClusterListL(iCurrentPos, length, aInfo));
   873     aStartPos = iCurrentPos.iPos;
   875 	if (r != KErrNone)
   874     if ((I64LOW(aStartPos) == FCB_FileSize()) || ( I64LOW(aStartPos) == (myStartPos + length)))
   876 		return r;
   875         return KErrCompletion;
   877 
   876     else
   878 	aStartPos = iCurrentPos.iPos;
   877         return KErrNone;
   879 	if ((I64LOW(aStartPos) == FCB_FileSize()) || ( I64LOW(aStartPos) == (myStartPos + length)))
   878     }
   880 		return KErrCompletion;
       
   881 	else
       
   882 		return KErrNone;
       
   883 	}
       
   884 
   879 
   885 
   880 
   886 
   881 TInt CFatFileCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput)
   887 TInt CFatFileCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput)
   882     {
   888 	{
   883     switch(aInterfaceId)
   889 	switch(aInterfaceId)
   884         {
   890 		{
   885         case EExtendedFileInterface:
   891 		case EExtendedFileInterface:
   886             ((CFileCB::MExtendedFileInterface*&) aInterface) = this;
   892 			((CFileCB::MExtendedFileInterface*&) aInterface) = this;
   887             return KErrNone;
   893 			return KErrNone;
   888 
   894 
   889         case EBlockMapInterface:
   895 		case EBlockMapInterface:
   890             aInterface = (CFileCB::MBlockMapInterface*) this;
   896 			aInterface = (CFileCB::MBlockMapInterface*) this;
   891             return KErrNone;
   897 			return KErrNone;
   892 
   898 
   893         case EGetLocalDrive:
   899 		case EGetLocalDrive:
   894             return FatMount().LocalDrive()->GetLocalDrive((TBusLocalDrive*&) aInterface);
   900 			return FatMount().LocalDrive()->GetLocalDrive((TBusLocalDrive*&) aInterface);
   895 
   901 
   896         default:
   902 		default:
   897             return CFileCB::GetInterface(aInterfaceId,aInterface,aInput);
   903 			return CFileCB::GetInterface(aInterfaceId,aInterface,aInput);
   898         }
   904 		}
   899     }
   905 	}
       
   906 
       
   907 
   900 
   908 
   901 
   909 
   902 /**
   910 /**
   903     Overwrites file's start cluster (iStartCluster) in its directory entry.
   911     Overwrites file's start cluster (iStartCluster) in its directory entry.
   904 */
   912 */
   905 void CFatFileCB::FlushStartClusterL()
   913 void CFatFileCB::FlushStartClusterL()
   906     {
   914 	{
   907     __PRINT1(_L("CFatFileCB::FlushStartClusterL[0x%x]"), this);
   915 	__PRINT1(_L("CFatFileCB::FlushStartClusterL[0x%x]"), this);
   908 
   916 
   909     CFatMountCB& mount = FatMount();
   917     CFatMountCB& mount = FatMount();
   910     TFatDirEntry dirEntry;
   918     TFatDirEntry dirEntry;
   911     
   919     
   912     mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry
   920     mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry
   913     dirEntry.SetStartCluster(FCB_StartCluster());    //-- set new start cluster
   921     dirEntry.SetStartCluster(FCB_StartCluster());    //-- set new start cluster
   914     mount.WriteDirEntryL(iFileDosEntryPos, dirEntry);//-- write the entry back
   922     mount.WriteDirEntryL(iFileDosEntryPos, dirEntry);//-- write the entry back
   915     }
   923 	}
   916 
   924 
   917 
   925 
   918 /**
   926 /**
   919     This is a RuggedFAT - specific method. Writes file size to the corresponding field of its file directory entry.
   927     This is a RuggedFAT - specific method. Writes file size to the corresponding field of its file directory entry.
   920 */
   928 */
   921 void CFatFileCB::WriteFileSizeL(TUint aSize)
   929 void CFatFileCB::WriteFileSizeL(TUint aSize)
   922     {
   930 	{
   923     __PRINT2(_L("CFatFileCB::WriteFileSizeL[0x%x], sz:%d"), this, aSize);
   931 	__PRINT2(_L("CFatFileCB::WriteFileSizeL[0x%x], sz:%d"), this, aSize);
   924 
   932 
   925     CFatMountCB& mount = FatMount();
   933     CFatMountCB& mount = FatMount();
   926     TFatDirEntry dirEntry;
   934     TFatDirEntry dirEntry;
   927 
   935 
   928     mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry
   936     mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry