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