userlibandfileserver/fileserver/sfat32/sl_file.cpp
branchRCL_3
changeset 43 c1f20ce4abcf
parent 42 a179b74831c9
child 44 3e88ff8f41d5
equal deleted inserted replaced
42:a179b74831c9 43:c1f20ce4abcf
     9 // Nokia Corporation - initial contribution.
     9 // Nokia Corporation - initial contribution.
    10 //
    10 //
    11 // Contributors:
    11 // Contributors:
    12 //
    12 //
    13 // Description:
    13 // Description:
    14 // f32\sfat\sl_file.cpp
    14 // f32\sfat32\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(FatMount().IsRuggedFSys() && pos+(TUint)aLength > FCB_FileSize())
   359     if(!IsSequentialMode() && 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 
       
   372 
   371 
   373 
   372 
   374 //-----------------------------------------------------------------------------
   373 //-----------------------------------------------------------------------------
   375 
   374 
   376 void CFatFileCB::ResizeIndex(TInt aNewMult,TUint aNewSize)
   375 void CFatFileCB::ResizeIndex(TInt aNewMult,TUint aNewSize)
   377 //
   376 //
   378 // Resize the seek index to accomodate a larger or smaller filesize
   377 // Resize the seek index to accomodate a larger or smaller filesize
   379 // Assumes KSeekIndexSize is a power of 2.
   378 // Assumes KSeekIndexSize is a power of 2.
   380 //
   379 //
   381 	{
   380     {
   382 
   381 
   383 	TInt maxNewIndex=aNewSize>>(ClusterSizeLog2()+aNewMult);
   382     TInt maxNewIndex=aNewSize>>(ClusterSizeLog2()+aNewMult);
   384 
   383 
   385 
   384 
   386 	TInt    index=0;
   385     TInt    index=0;
   387 	TInt	indexEnd=KSeekIndexSize;
   386     TInt    indexEnd=KSeekIndexSize;
   388 	TInt	newValEnd=maxNewIndex;
   387     TInt    newValEnd=maxNewIndex;
   389 
   388 
   390 	if (iSeekIndexSize<aNewMult)
   389     if (iSeekIndexSize<aNewMult)
   391 		{
   390         {
   392 		TInt newVal=index;
   391         TInt newVal=index;
   393 		TInt step=1<<(aNewMult-iSeekIndexSize);
   392         TInt step=1<<(aNewMult-iSeekIndexSize);
   394 		index+=step-1;
   393         index+=step-1;
   395 		while(index<indexEnd && newVal<newValEnd)
   394         while(index<indexEnd && newVal<newValEnd)
   396 			{
   395             {
   397 			iSeekIndex[newVal] =  iSeekIndex[index];
   396             iSeekIndex[newVal] =  iSeekIndex[index];
   398 			newVal++;
   397             newVal++;
   399 			index+=step;
   398             index+=step;
   400 			}
   399             }
   401 		while(newVal<indexEnd)
   400         while(newVal<indexEnd)
   402 			iSeekIndex[newVal++] =  0;
   401             iSeekIndex[newVal++] =  0;
   403 		}
   402         }
   404 	else
   403     else
   405 		{
   404         {
   406 		TInt diffSize = iSeekIndexSize-aNewMult;
   405         TInt diffSize = iSeekIndexSize-aNewMult;
   407 		TInt oldVal=(KSeekIndexSize>>diffSize) - 1;
   406         TInt oldVal=(KSeekIndexSize>>diffSize) - 1;
   408 		TInt newVal=indexEnd-1;
   407         TInt newVal=indexEnd-1;
   409 		TInt skip=(1<<diffSize)-1;
   408         TInt skip=(1<<diffSize)-1;
   410 
   409 
   411 		if ((iSeekIndexSize - aNewMult) > KSeekIndexSizeLog2)
   410         if ((iSeekIndexSize - aNewMult) > KSeekIndexSizeLog2)
   412 			{
   411             {
   413             ClearIndex(0); //-- Invalidate every entry.
   412             ClearIndex(0); //-- Invalidate every entry.
   414 			}
   413             }
   415 		else
   414         else
   416 			{
   415             {
   417 			while(newVal>=index)
   416             while(newVal>=index)
   418 				{
   417                 {
   419 
   418 
   420 				iSeekIndex[newVal--] =  iSeekIndex[oldVal--];
   419                 iSeekIndex[newVal--] =  iSeekIndex[oldVal--];
   421 
   420 
   422 
   421 
   423 				for(TInt i=skip;i>0;i--)
   422                 for(TInt i=skip;i>0;i--)
   424 					{	
   423                     {   
   425 					iSeekIndex[newVal--] = 0;
   424                     iSeekIndex[newVal--] = 0;
   426 
   425 
   427 					}
   426                     }
   428 				}
   427                 }
   429 			}
   428             }
   430 		}
   429         }
   431 	iSeekIndexSize=aNewMult;
   430     iSeekIndexSize=aNewMult;
   432 	}
   431     }
   433 
   432 
   434 
   433 
   435 /**
   434 /**
   436     Zero freed clusters in the index
   435     Zero freed clusters in the index
   437 
   436 
   438     @param  aNewSize new size of the file that the index corresponds to.
   437     @param  aNewSize new size of the file that the index corresponds to.
   439             if = 0  all existing index will be zero filled
   438             if = 0  all existing index will be zero filled
   440 */ 
   439 */ 
   441 void CFatFileCB::ClearIndex(TUint aNewSize)
   440 void CFatFileCB::ClearIndex(TUint aNewSize)
   442 	{
   441     {
   443 
   442 
   444 	if (!iSeekIndex)
   443     if (!iSeekIndex)
   445 	    return;
   444         return;
   446 
   445 
   447     if(aNewSize==0)
   446     if(aNewSize==0)
   448     	{
   447         {
   449     	//-- zero fill all the array
   448         //-- zero fill all the array
   450         Mem::FillZ(iSeekIndex, KSeekIndexSize*sizeof(TUint32));
   449         Mem::FillZ(iSeekIndex, KSeekIndexSize*sizeof(TUint32));
   451 		return;
   450         return;
   452     	}
   451         }
   453 
   452 
   454 	// Files that fill up a cluster exactly do not have a trailing empty
   453     // Files that fill up a cluster exactly do not have a trailing empty
   455 	// cluster. So the entry for that position must also be invalidated
   454     // cluster. So the entry for that position must also be invalidated
   456 	aNewSize--;
   455     aNewSize--;
   457 	TInt firstInvalidIndex=aNewSize>>(iSeekIndexSize+ClusterSizeLog2());
   456     TInt firstInvalidIndex=aNewSize>>(iSeekIndexSize+ClusterSizeLog2());
   458 		
   457         
   459 	TInt indexLen=KSeekIndexSize-firstInvalidIndex;
   458     TInt indexLen=KSeekIndexSize-firstInvalidIndex;
   460 
   459 
   461 	Mem::FillZ(iSeekIndex+firstInvalidIndex, indexLen * sizeof(TUint32));
   460     Mem::FillZ(iSeekIndex+firstInvalidIndex, indexLen * sizeof(TUint32));
   462 	}
   461     }
   463 
   462 
   464 TInt CFatFileCB::CalcSeekIndexSize(TUint aSize)
   463 TInt CFatFileCB::CalcSeekIndexSize(TUint aSize)
   465 //
   464 //
   466 // Find the nearest power of 2 > aSize
   465 // Find the nearest power of 2 > aSize
   467 //
   466 //
   468 	{
   467     {
   469 	TInt count = 0;
   468     TInt count = 0;
   470 	const TUint indexSize=KSeekIndexSize<<ClusterSizeLog2();//KSeekIndexSize=128
   469     const TUint indexSize=KSeekIndexSize<<ClusterSizeLog2();//KSeekIndexSize=128
   471 	if (aSize<=indexSize)
   470     if (aSize<=indexSize)
   472 	  return(count);
   471       return(count);
   473 	
   472     
   474 	while((aSize>>=1)>0)
   473     while((aSize>>=1)>0)
   475 		{
   474         {
   476 		count++;
   475         count++;
   477 		}
   476         }
   478 	return (count - (KSeekIndexSizeLog2 + ClusterSizeLog2()) + 1);
   477     return (count - (KSeekIndexSizeLog2 + ClusterSizeLog2()) + 1);
   479 	}
   478     }
   480 
   479 
   481 //-----------------------------------------------------------------------------
   480 //-----------------------------------------------------------------------------
   482 /**
   481 /**
   483     Set file size.
   482     Set file size.
   484     @param aSize new file size.
   483     @param aSize new file size.
   485 */
   484 */
   486 void CFatFileCB::SetSizeL(TInt64 aSize)
   485 void CFatFileCB::SetSizeL(TInt64 aSize)
   487 	{
   486     {
   488 	__PRINT2(_L("CFatFileCB::SetSizeL[0x%x] sz=%LU"), this, aSize);
   487     __PRINT2(_L("CFatFileCB::SetSizeL[0x%x] sz=%LU"), this, aSize);
   489 	
   488     
   490 	//-- max. file size for FAT is 4GB-1
   489     //-- max. file size for FAT is 4GB-1
   491 	if (I64HIGH(aSize))
   490     if (I64HIGH(aSize))
   492 		User::Leave(KErrNotSupported);
   491         User::Leave(KErrNotSupported);
   493 
   492 
   494     DoSetSizeL(I64LOW(aSize), FatMount().IsRuggedFSys());
   493     DoSetSizeL(I64LOW(aSize), FatMount().IsRuggedFSys());
   495 	}
   494     }
   496 
   495 
   497 
   496 
   498 void CFatFileCB::SetSizeL(TInt aSize)
   497 void CFatFileCB::SetSizeL(TInt aSize)
   499 	{
   498     {
   500 	SetSizeL(TInt64(aSize));
   499     SetSizeL(TInt64(aSize));
   501 	}
   500     }
   502 
   501 
   503 //-----------------------------------------------------------------------------
   502 //-----------------------------------------------------------------------------
   504 /**
   503 /**
   505     Shrink file to zero size.
   504     Shrink file to zero size.
   506 */
   505 */
   507 void CFatFileCB::DoShrinkFileToZeroSizeL()
   506 void CFatFileCB::DoShrinkFileToZeroSizeL()
   508     {
   507     {
   509 	    ASSERT(FCB_FileSize());
   508         ASSERT(FCB_FileSize());
   510         ASSERT(FileSizeModified());
   509         ASSERT(FileSizeModified());
   511         
   510         
   512             ClearIndex(0); //-- clear seek index array
   511         ClearIndex(0); // Clear seek index array
   513 		
   512         
   514         //-- update file dir. entry
   513         //-- update file dir. entry
   515         const TUint32 cluster = FCB_StartCluster();
   514         const TUint32 cluster = FCB_StartCluster();
   516 		FCB_SetStartCluster(0);
   515         FCB_SetStartCluster(0);
   517 		FCB_SetFileSize(0);
   516         FCB_SetFileSize(0);
   518 			FlushAllL();
   517             FlushAllL();
   519 		
   518         
   520         //-- free cluster list. 
   519         //-- free cluster list. 
   521 			CheckPosL(0);
   520             CheckPosL(0);
   522 			FAT().FreeClusterListL(cluster);
   521             FAT().FreeClusterListL(cluster);
   523 			FAT().FlushL();
   522             FAT().FlushL();
   524 			}
   523             }
   525 
   524 
   526 //-----------------------------------------------------------------------------
   525 //-----------------------------------------------------------------------------
   527 /*
   526 /*
   528     Shrink file to smaller size, but > 0
   527     Shrink file to smaller size, but > 0
   529 
   528 
   530     @param aNewSize new file size
   529     @param aNewSize new file size
   531     @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed 
   530     @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed 
   532 */
   531 */
   533 void CFatFileCB::DoShrinkFileL(TUint32 aNewSize, TBool aForceCachesFlush)
   532 void CFatFileCB::DoShrinkFileL(TUint32 aNewSize, TBool aForceCachesFlush)
   534 		{
   533     {
   535     ASSERT(FileSizeModified());
   534     ASSERT(FileSizeModified());
   536     ASSERT(FCB_FileSize() > aNewSize && aNewSize);
   535     ASSERT(FCB_FileSize() > aNewSize && aNewSize);
   537 	
   536     
   538     if(aForceCachesFlush)		
   537     if(aForceCachesFlush)       
   539         WriteFileSizeL(aNewSize); //-- write file size directly to its dir. entry
   538         WriteFileSizeL(aNewSize); //-- write file size directly to its dir. entry
   540 
   539 
   541 	CheckPosL(aNewSize);
   540     CheckPosL(aNewSize);
   542 	
   541 
   543     TUint32 cluster=iCurrentPos.iCluster;
   542     TUint32 cluster=iCurrentPos.iCluster;
   544 		if (FAT().GetNextClusterL(cluster))
   543     
   545 	    {//-- truncate the cluster chain
   544     if (FAT().GetNextClusterL(cluster))
   546 			FAT().WriteFatEntryEofL(iCurrentPos.iCluster);
   545         {//-- truncate the cluster chain
   547 			FAT().FreeClusterListL(cluster);
   546         FAT().WriteFatEntryEofL(iCurrentPos.iCluster);
   548 			}
   547         FAT().FreeClusterListL(cluster);
   549 		
   548         }
       
   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(aForceCachesFlush)			// write file size if increasing
   600         if(!IsSequentialMode() && aForceCachesFlush)    // Write file size directly to its dir. entry if a cache flush
   601 			WriteFileSizeL(aNewSize);
   601             WriteFileSizeL(aNewSize);               // is needed and rugged FAT is not ignored by client
   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 	
       
   858     // Fetch the address of cluster 0
   856     // Fetch the address of cluster 0
   859 	TRAP(r, aInfo.iStartBlockAddress = fatMount.FAT().DataPositionInBytesL(KFirstClusterNum));
   857     aInfo.iStartBlockAddress = fatMount.FAT().DataPositionInBytes(KFirstClusterNum);
   860 	if (r != KErrNone)
   858 
   861 		return r;
   859     TRAPD(r, CheckPosL(startPos));
   862 
   860     if (r != KErrNone)
   863 
   861         return r;
   864 	TRAP(r, CheckPosL(startPos));
   862 
   865 	if (r != KErrNone)
   863     aInfo.iBlockStartOffset = fatMount.ClusterRelativePos(iCurrentPos.iPos);
   866 		return r;
   864     aInfo.iBlockGranularity = 1 << FatMount().ClusterSizeLog2();
   867 
   865     const TUint myStartPos = iCurrentPos.iPos;
   868 	aInfo.iBlockStartOffset = fatMount.ClusterRelativePos(iCurrentPos.iPos);
   866     if ( myStartPos + length > FCB_FileSize())
   869 	aInfo.iBlockGranularity = 1 << FatMount().ClusterSizeLog2();
   867         return KErrArgument;
   870 	const TUint myStartPos = iCurrentPos.iPos;
   868 
   871 	if ( myStartPos + length > FCB_FileSize())
   869     TRAP(r, FatMount().BlockMapReadFromClusterListL(iCurrentPos, length, aInfo));
   872 		return KErrArgument;
   870     if (r != KErrNone)
   873 
   871         return r;
   874 	TRAP(r, FatMount().BlockMapReadFromClusterListL(iCurrentPos, length, aInfo));
   872 
   875 	if (r != KErrNone)
   873     aStartPos = iCurrentPos.iPos;
   876 		return r;
   874     if ((I64LOW(aStartPos) == FCB_FileSize()) || ( I64LOW(aStartPos) == (myStartPos + length)))
   877 
   875         return KErrCompletion;
   878 	aStartPos = iCurrentPos.iPos;
   876     else
   879 	if ((I64LOW(aStartPos) == FCB_FileSize()) || ( I64LOW(aStartPos) == (myStartPos + length)))
   877         return KErrNone;
   880 		return KErrCompletion;
   878     }
   881 	else
       
   882 		return KErrNone;
       
   883 	}
       
   884 
       
   885 
   879 
   886 
   880 
   887 TInt CFatFileCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput)
   881 TInt CFatFileCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput)
   888 	{
   882     {
   889 	switch(aInterfaceId)
   883     switch(aInterfaceId)
   890 		{
   884         {
   891 		case EExtendedFileInterface:
   885         case EExtendedFileInterface:
   892 			((CFileCB::MExtendedFileInterface*&) aInterface) = this;
   886             ((CFileCB::MExtendedFileInterface*&) aInterface) = this;
   893 			return KErrNone;
   887             return KErrNone;
   894 
   888 
   895 		case EBlockMapInterface:
   889         case EBlockMapInterface:
   896 			aInterface = (CFileCB::MBlockMapInterface*) this;
   890             aInterface = (CFileCB::MBlockMapInterface*) this;
   897 			return KErrNone;
   891             return KErrNone;
   898 
   892 
   899 		case EGetLocalDrive:
   893         case EGetLocalDrive:
   900 			return FatMount().LocalDrive()->GetLocalDrive((TBusLocalDrive*&) aInterface);
   894             return FatMount().LocalDrive()->GetLocalDrive((TBusLocalDrive*&) aInterface);
   901 
   895 
   902 		default:
   896         default:
   903 			return CFileCB::GetInterface(aInterfaceId,aInterface,aInput);
   897             return CFileCB::GetInterface(aInterfaceId,aInterface,aInput);
   904 		}
   898         }
   905 	}
   899     }
   906 
       
   907 
       
   908 
   900 
   909 
   901 
   910 /**
   902 /**
   911     Overwrites file's start cluster (iStartCluster) in its directory entry.
   903     Overwrites file's start cluster (iStartCluster) in its directory entry.
   912 */
   904 */
   913 void CFatFileCB::FlushStartClusterL()
   905 void CFatFileCB::FlushStartClusterL()
   914 	{
   906     {
   915 	__PRINT1(_L("CFatFileCB::FlushStartClusterL[0x%x]"), this);
   907     __PRINT1(_L("CFatFileCB::FlushStartClusterL[0x%x]"), this);
   916 
   908 
   917     CFatMountCB& mount = FatMount();
   909     CFatMountCB& mount = FatMount();
   918     TFatDirEntry dirEntry;
   910     TFatDirEntry dirEntry;
   919     
   911     
   920     mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry
   912     mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry
   921     dirEntry.SetStartCluster(FCB_StartCluster());    //-- set new start cluster
   913     dirEntry.SetStartCluster(FCB_StartCluster());    //-- set new start cluster
   922     mount.WriteDirEntryL(iFileDosEntryPos, dirEntry);//-- write the entry back
   914     mount.WriteDirEntryL(iFileDosEntryPos, dirEntry);//-- write the entry back
   923 	}
   915     }
   924 
   916 
   925 
   917 
   926 /**
   918 /**
   927     This is a RuggedFAT - specific method. Writes file size to the corresponding field of its file directory entry.
   919     This is a RuggedFAT - specific method. Writes file size to the corresponding field of its file directory entry.
   928 */
   920 */
   929 void CFatFileCB::WriteFileSizeL(TUint aSize)
   921 void CFatFileCB::WriteFileSizeL(TUint aSize)
   930 	{
   922     {
   931 	__PRINT2(_L("CFatFileCB::WriteFileSizeL[0x%x], sz:%d"), this, aSize);
   923     __PRINT2(_L("CFatFileCB::WriteFileSizeL[0x%x], sz:%d"), this, aSize);
   932 
   924 
   933     CFatMountCB& mount = FatMount();
   925     CFatMountCB& mount = FatMount();
   934     TFatDirEntry dirEntry;
   926     TFatDirEntry dirEntry;
   935 
   927 
   936     mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry
   928     mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry