userlibandfileserver/fileserver/sfat32/sl_file.cpp
changeset 176 af6ec97d9189
parent 148 31ea0f8e3c99
child 231 75252ea6123b
equal deleted inserted replaced
175:5af6c74cd793 176:af6ec97d9189
    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 	
   241     
   242 	const TUint startPos = iCurrentPos.iPos;
   242     const TUint startPos = iCurrentPos.iPos;
   243 	const TUint curSize  = FCB_FileSize();
   243     const TUint curSize  = FCB_FileSize();
   244 	const TUint length   = (TUint)aLength;
   244     const TUint length   = (TUint)aLength;
   245 	
   245     
   246 	if((startPos + length > curSize) || (startPos > startPos + length) )
   246     if((startPos + length > curSize) || (startPos > startPos + length) )
   247 		aLength=curSize-startPos;
   247         aLength=curSize-startPos;
   248 		
   248 		
   249 	TUint flag = DirectIOMode(aMessage) ? RLocalDrive::ELocDrvDirectIO : 0;
   249 	TUint flag = DirectIOMode(aMessage) ? RLocalDrive::ELocDrvDirectIO : 0;
   250 	
   250 	
   251     FatMount().ReadFromClusterListL(iCurrentPos,aLength,aDes,aMessage,aOffset, flag);
   251     FatMount().ReadFromClusterListL(iCurrentPos,aLength,aDes,aMessage,aOffset, flag);
   252 	aLength=iCurrentPos.iPos-startPos;
   252 	aLength=iCurrentPos.iPos-startPos;
   253 	}
   253 	}
   254 
   254 
   255 
   255 
   256 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)
   257 	{
   257     {
   258 	ReadL(TInt64(aFilePos),aLength,(TDes8*) aTrg,aMessage, 0);
   258     ReadL(TInt64(aFilePos),aLength,(TDes8*) aTrg,aMessage, 0);
   259 	}
   259     }
   260 
   260 
   261 //-----------------------------------------------------------------------------
   261 //-----------------------------------------------------------------------------
   262 /**
   262 /**
   263     Write data to the file.
   263     Write data to the file.
   264     
   264     
   270 
   270 
   271     @leave on media read error
   271     @leave on media read error
   272 
   272 
   273 */
   273 */
   274 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)
   275 	{
   275     {
   276 	__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);
   277 
   277 
   278 	// FAT supports 32 bits only for file size
   278     // FAT supports 32 bits only for file size
   279    	TUint64 endPos = aPos + aLength;
   279     TUint64 endPos = aPos + aLength;
   280    	if(endPos > KMaxSupportedFatFileSize)
   280     if(endPos > KMaxSupportedFatFileSize)
   281    		User::Leave(KErrNotSupported);
   281         User::Leave(KErrNotSupported);
   282    	
   282     
   283     FatMount().CheckStateConsistentL();
   283     FatMount().CheckStateConsistentL();
   284     FatMount().CheckWritableL();
   284     FatMount().CheckWritableL();
   285     const TUint pos = I64LOW(aPos);
   285     const TUint pos = I64LOW(aPos);
   286   	CheckPosL(pos);
   286     CheckPosL(pos);
   287   	
   287     
   288 	const TUint startCluster = FCB_StartCluster();
   288     const TUint startCluster = FCB_StartCluster();
   289 	const TUint length       = (TUint)aLength;
   289     const TUint length       = (TUint)aLength;
   290 	
   290     
   291 	endPos = iCurrentPos.iPos + length; 
   291     endPos = iCurrentPos.iPos + length; 
   292 	if ((endPos           > FCB_FileSize()) ||
   292     if ((endPos           > FCB_FileSize()) ||
   293 	    (iCurrentPos.iPos > endPos)         ) // Overflow condition 
   293         (iCurrentPos.iPos > endPos)         ) // Overflow condition 
   294 		DoSetSizeL(iCurrentPos.iPos+length,EFalse);
   294         DoSetSizeL(iCurrentPos.iPos+length,EFalse);
   295    	
   295     
   296 	TUint startPos=iCurrentPos.iPos;
   296     TUint startPos=iCurrentPos.iPos;
   297 	TUint badcluster=0;
   297     TUint badcluster=0;
   298 	TUint goodcluster=0;
   298     TUint goodcluster=0;
   299    	
   299    	
   300 	TUint flag = DirectIOMode(aMessage) ? RLocalDrive::ELocDrvDirectIO : 0;
   300 	TUint flag = DirectIOMode(aMessage) ? RLocalDrive::ELocDrvDirectIO : 0;
   301 	
   301 	
   302 	TRAPD(ret, FatMount().WriteToClusterListL(iCurrentPos,aLength,aSrc,aMessage,aOffset,badcluster, goodcluster, flag));
   302 	TRAPD(ret, FatMount().WriteToClusterListL(iCurrentPos,aLength,aSrc,aMessage,aOffset,badcluster, goodcluster, flag));
   303    	
   303    	
   304 	if (ret == KErrCorrupt || ret == KErrDied)
   304     if (ret == KErrCorrupt || ret == KErrDied)
   305 		{
   305         {
   306         if(startCluster == 0)
   306         if(startCluster == 0)
   307 			{ //Empty File, revert all the clusters allocated.
   307             { //Empty File, revert all the clusters allocated.
   308 			const TUint32 cluster = FCB_StartCluster();
   308             const TUint32 cluster = FCB_StartCluster();
   309 			FCB_SetStartCluster(0);
   309             FCB_SetStartCluster(0);
   310 			FCB_SetFileSize(0);
   310             FCB_SetFileSize(0);
   311 			IndicateFileSizeModified(ETrue);
   311             IndicateFileSizeModified(ETrue);
   312             
   312             
   313 			FlushAllL();
   313             FlushAllL();
   314 
   314 
   315 			iCurrentPos.iCluster = 0;
   315             iCurrentPos.iCluster = 0;
   316 			iCurrentPos.iPos = 0;
   316             iCurrentPos.iPos = 0;
   317 
   317 
   318 			FAT().FreeClusterListL(cluster);
   318             FAT().FreeClusterListL(cluster);
   319 			FAT().FlushL();
   319             FAT().FlushL();
   320 			}
   320             }
   321 		else
   321         else
   322 			{ //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.
   323 			const TUint curSize = FCB_FileSize();
   323             const TUint curSize = FCB_FileSize();
   324 			TUint ClustersNeeded = curSize >> ClusterSizeLog2();
   324             TUint ClustersNeeded = curSize >> ClusterSizeLog2();
   325 			if(curSize > (ClustersNeeded << ClusterSizeLog2()))
   325             if(curSize > (ClustersNeeded << ClusterSizeLog2()))
   326 				{
   326                 {
   327 				ClustersNeeded++;
   327                 ClustersNeeded++;
   328 				}
   328                 }
   329 
   329 
   330 			TUint32 cluster = FCB_StartCluster();
   330             TUint32 cluster = FCB_StartCluster();
   331 			while(--ClustersNeeded)
   331             while(--ClustersNeeded)
   332 				{
   332                 {
   333 				FAT().GetNextClusterL(cluster);
   333                 FAT().GetNextClusterL(cluster);
   334 				}
   334                 }
   335                 
   335                 
   336 			iCurrentPos.iCluster = cluster;
   336             iCurrentPos.iCluster = cluster;
   337 
   337 
   338 			if (FAT().GetNextClusterL(cluster))
   338             if (FAT().GetNextClusterL(cluster))
   339 				{
   339                 {
   340 				FAT().FreeClusterListL(cluster);
   340                 FAT().FreeClusterListL(cluster);
   341 				}
   341                 }
   342 
   342 
   343 			FAT().WriteFatEntryEofL(iCurrentPos.iCluster);
   343             FAT().WriteFatEntryEofL(iCurrentPos.iCluster);
   344 			FAT().FlushL();
   344             FAT().FlushL();
   345 			}
   345             }
   346 		}
   346         }
   347 
   347 
   348 	User::LeaveIfError(ret);
   348     User::LeaveIfError(ret);
   349 
   349 
   350 	if(badcluster != 0)
   350     if(badcluster != 0)
   351 		{
   351         {
   352 		if(FCB_StartCluster() == badcluster)
   352         if(FCB_StartCluster() == badcluster)
   353 			{
   353             {
   354             FCB_SetStartCluster(goodcluster);
   354             FCB_SetStartCluster(goodcluster);
   355 			FlushStartClusterL();
   355             FlushStartClusterL();
   356 			}
   356             }
   357 		else
   357         else
   358 			{
   358             {
   359 			TUint32 aCluster = FCB_StartCluster();
   359             TUint32 aCluster = FCB_StartCluster();
   360 			do
   360             do
   361 				{
   361                 {
   362                 if((TUint)badcluster == FAT().ReadL(aCluster))
   362                 if((TUint)badcluster == FAT().ReadL(aCluster))
   363 					{
   363                     {
   364 					FAT().WriteL(aCluster, goodcluster);
   364                     FAT().WriteL(aCluster, goodcluster);
   365 					FAT().FlushL();
   365                     FAT().FlushL();
   366 					break;
   366                     break;
   367 					}
   367                     }
   368 				}
   368                 }
   369 			while(FAT().GetNextClusterL(aCluster));
   369             while(FAT().GetNextClusterL(aCluster));
   370 			}
   370             }
   371 		}
   371         }
   372 	aLength=iCurrentPos.iPos-startPos;
   372     aLength=iCurrentPos.iPos-startPos;
   373 
   373 
   374 	if(!IsSequentialMode() && FatMount().IsRuggedFSys() && pos+(TUint)aLength > FCB_FileSize())
   374     if(!IsSequentialMode() && FatMount().IsRuggedFSys() && pos+(TUint)aLength > FCB_FileSize())
   375 		{
   375         {
   376 		WriteFileSizeL(pos+aLength);
   376         WriteFileSizeL(pos+aLength);
   377 		}
   377         }
   378 
   378 
   379 	}
   379     }
   380 
   380 
   381 
   381 
   382 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)
   383 	{
   383     {
   384 	WriteL(TInt64(aFilePos),aLength,(TDesC8*) aSrc,aMessage, 0);
   384     WriteL(TInt64(aFilePos),aLength,(TDesC8*) aSrc,aMessage, 0);
   385 	}
   385     }
   386 
   386 
   387 
   387 
   388 //-----------------------------------------------------------------------------
   388 //-----------------------------------------------------------------------------
   389 
   389 
   390 void CFatFileCB::ResizeIndex(TInt aNewMult,TUint aNewSize)
   390 void CFatFileCB::ResizeIndex(TInt aNewMult,TUint aNewSize)
   391 //
   391 //
   392 // Resize the seek index to accomodate a larger or smaller filesize
   392 // Resize the seek index to accomodate a larger or smaller filesize
   393 // Assumes KSeekIndexSize is a power of 2.
   393 // Assumes KSeekIndexSize is a power of 2.
   394 //
   394 //
   395 	{
   395     {
   396 
   396 
   397 	TInt maxNewIndex=aNewSize>>(ClusterSizeLog2()+aNewMult);
   397     TInt maxNewIndex=aNewSize>>(ClusterSizeLog2()+aNewMult);
   398 
   398 
   399 
   399 
   400 	TInt    index=0;
   400     TInt    index=0;
   401 	TInt	indexEnd=KSeekIndexSize;
   401     TInt    indexEnd=KSeekIndexSize;
   402 	TInt	newValEnd=maxNewIndex;
   402     TInt    newValEnd=maxNewIndex;
   403 
   403 
   404 	if (iSeekIndexSize<aNewMult)
   404     if (iSeekIndexSize<aNewMult)
   405 		{
   405         {
   406 		TInt newVal=index;
   406         TInt newVal=index;
   407 		TInt step=1<<(aNewMult-iSeekIndexSize);
   407         TInt step=1<<(aNewMult-iSeekIndexSize);
   408 		index+=step-1;
   408         index+=step-1;
   409 		while(index<indexEnd && newVal<newValEnd)
   409         while(index<indexEnd && newVal<newValEnd)
   410 			{
   410             {
   411 			iSeekIndex[newVal] =  iSeekIndex[index];
   411             iSeekIndex[newVal] =  iSeekIndex[index];
   412 			newVal++;
   412             newVal++;
   413 			index+=step;
   413             index+=step;
   414 			}
   414             }
   415 		while(newVal<indexEnd)
   415         while(newVal<indexEnd)
   416 			iSeekIndex[newVal++] =  0;
   416             iSeekIndex[newVal++] =  0;
   417 		}
   417         }
   418 	else
   418     else
   419 		{
   419         {
   420 		TInt diffSize = iSeekIndexSize-aNewMult;
   420         TInt diffSize = iSeekIndexSize-aNewMult;
   421 		TInt oldVal=(KSeekIndexSize>>diffSize) - 1;
   421         TInt oldVal=(KSeekIndexSize>>diffSize) - 1;
   422 		TInt newVal=indexEnd-1;
   422         TInt newVal=indexEnd-1;
   423 		TInt skip=(1<<diffSize)-1;
   423         TInt skip=(1<<diffSize)-1;
   424 
   424 
   425 		if ((iSeekIndexSize - aNewMult) > KSeekIndexSizeLog2)
   425         if ((iSeekIndexSize - aNewMult) > KSeekIndexSizeLog2)
   426 			{
   426             {
   427             ClearIndex(0); //-- Invalidate every entry.
   427             ClearIndex(0); //-- Invalidate every entry.
   428 			}
   428             }
   429 		else
   429         else
   430 			{
   430             {
   431 			while(newVal>=index)
   431             while(newVal>=index)
   432 				{
   432                 {
   433 
   433 
   434 				iSeekIndex[newVal--] =  iSeekIndex[oldVal--];
   434                 iSeekIndex[newVal--] =  iSeekIndex[oldVal--];
   435 
   435 
   436 
   436 
   437 				for(TInt i=skip;i>0;i--)
   437                 for(TInt i=skip;i>0;i--)
   438 					{	
   438                     {   
   439 					iSeekIndex[newVal--] = 0;
   439                     iSeekIndex[newVal--] = 0;
   440 
   440 
   441 					}
   441                     }
   442 				}
   442                 }
   443 			}
   443             }
   444 		}
   444         }
   445 	iSeekIndexSize=aNewMult;
   445     iSeekIndexSize=aNewMult;
   446 	}
   446     }
   447 
   447 
   448 
   448 
   449 /**
   449 /**
   450     Zero freed clusters in the index
   450     Zero freed clusters in the index
   451 
   451 
   452     @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.
   453             if = 0  all existing index will be zero filled
   453             if = 0  all existing index will be zero filled
   454 */ 
   454 */ 
   455 void CFatFileCB::ClearIndex(TUint aNewSize)
   455 void CFatFileCB::ClearIndex(TUint aNewSize)
   456 	{
   456     {
   457 
   457 
   458 	if (!iSeekIndex)
   458     if (!iSeekIndex)
   459 	    return;
   459         return;
   460 
   460 
   461     if(aNewSize==0)
   461     if(aNewSize==0)
   462     	{
   462         {
   463     	//-- zero fill all the array
   463         //-- zero fill all the array
   464         Mem::FillZ(iSeekIndex, KSeekIndexSize*sizeof(TUint32));
   464         Mem::FillZ(iSeekIndex, KSeekIndexSize*sizeof(TUint32));
   465 		return;
   465         return;
   466     	}
   466         }
   467 
   467 
   468 	// 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
   469 	// cluster. So the entry for that position must also be invalidated
   469     // cluster. So the entry for that position must also be invalidated
   470 	aNewSize--;
   470     aNewSize--;
   471 	TInt firstInvalidIndex=aNewSize>>(iSeekIndexSize+ClusterSizeLog2());
   471     TInt firstInvalidIndex=aNewSize>>(iSeekIndexSize+ClusterSizeLog2());
   472 		
   472         
   473 	TInt indexLen=KSeekIndexSize-firstInvalidIndex;
   473     TInt indexLen=KSeekIndexSize-firstInvalidIndex;
   474 
   474 
   475 	Mem::FillZ(iSeekIndex+firstInvalidIndex, indexLen * sizeof(TUint32));
   475     Mem::FillZ(iSeekIndex+firstInvalidIndex, indexLen * sizeof(TUint32));
   476 	}
   476     }
   477 
   477 
   478 TInt CFatFileCB::CalcSeekIndexSize(TUint aSize)
   478 TInt CFatFileCB::CalcSeekIndexSize(TUint aSize)
   479 //
   479 //
   480 // Find the nearest power of 2 > aSize
   480 // Find the nearest power of 2 > aSize
   481 //
   481 //
   482 	{
   482     {
   483 	TInt count = 0;
   483     TInt count = 0;
   484 	const TUint indexSize=KSeekIndexSize<<ClusterSizeLog2();//KSeekIndexSize=128
   484     const TUint indexSize=KSeekIndexSize<<ClusterSizeLog2();//KSeekIndexSize=128
   485 	if (aSize<=indexSize)
   485     if (aSize<=indexSize)
   486 	  return(count);
   486       return(count);
   487 	
   487     
   488 	while((aSize>>=1)>0)
   488     while((aSize>>=1)>0)
   489 		{
   489         {
   490 		count++;
   490         count++;
   491 		}
   491         }
   492 	return (count - (KSeekIndexSizeLog2 + ClusterSizeLog2()) + 1);
   492     return (count - (KSeekIndexSizeLog2 + ClusterSizeLog2()) + 1);
   493 	}
   493     }
   494 
   494 
   495 //-----------------------------------------------------------------------------
   495 //-----------------------------------------------------------------------------
   496 /**
   496 /**
   497     Set file size.
   497     Set file size.
   498     @param aSize new file size.
   498     @param aSize new file size.
   499 */
   499 */
   500 void CFatFileCB::SetSizeL(TInt64 aSize)
   500 void CFatFileCB::SetSizeL(TInt64 aSize)
   501 	{
   501     {
   502 	__PRINT2(_L("CFatFileCB::SetSizeL[0x%x] sz=%LU"), this, aSize);
   502     __PRINT2(_L("CFatFileCB::SetSizeL[0x%x] sz=%LU"), this, aSize);
   503 	
   503     
   504 	//-- max. file size for FAT is 4GB-1
   504     //-- max. file size for FAT is 4GB-1
   505 	if (I64HIGH(aSize))
   505     if (I64HIGH(aSize))
   506 		User::Leave(KErrNotSupported);
   506         User::Leave(KErrNotSupported);
   507 
   507 
   508 	DoSetSizeL(I64LOW(aSize), FatMount().IsRuggedFSys());
   508     DoSetSizeL(I64LOW(aSize), FatMount().IsRuggedFSys());
   509 	}
   509     }
   510 
   510 
   511 
   511 
   512 void CFatFileCB::SetSizeL(TInt aSize)
   512 void CFatFileCB::SetSizeL(TInt aSize)
   513 	{
   513     {
   514 	SetSizeL(TInt64(aSize));
   514     SetSizeL(TInt64(aSize));
   515 	}
   515     }
   516 
   516 
   517 //-----------------------------------------------------------------------------
   517 //-----------------------------------------------------------------------------
   518 /**
   518 /**
   519     Shrink file to zero size.
   519     Shrink file to zero size.
   520 */
   520 */
   521 void CFatFileCB::DoShrinkFileToZeroSizeL()
   521 void CFatFileCB::DoShrinkFileToZeroSizeL()
   522     {
   522     {
   523 	    ASSERT(FCB_FileSize());
   523         ASSERT(FCB_FileSize());
   524         ASSERT(FileSizeModified());
   524         ASSERT(FileSizeModified());
   525         
   525         
   526         ClearIndex(0); // Clear seek index array
   526         ClearIndex(0); // Clear seek index array
   527 		
   527         
   528         //-- update file dir. entry
   528         //-- update file dir. entry
   529         const TUint32 cluster = FCB_StartCluster();
   529         const TUint32 cluster = FCB_StartCluster();
   530 		FCB_SetStartCluster(0);
   530         FCB_SetStartCluster(0);
   531 		FCB_SetFileSize(0);
   531         FCB_SetFileSize(0);
   532 			FlushAllL();
   532             FlushAllL();
   533 		
   533         
   534         //-- free cluster list. 
   534         //-- free cluster list. 
   535 			CheckPosL(0);
   535             CheckPosL(0);
   536 			FAT().FreeClusterListL(cluster);
   536             FAT().FreeClusterListL(cluster);
   537 			FAT().FlushL();
   537             FAT().FlushL();
   538 			}
   538             }
   539 
   539 
   540 //-----------------------------------------------------------------------------
   540 //-----------------------------------------------------------------------------
   541 /*
   541 /*
   542     Shrink file to smaller size, but > 0
   542     Shrink file to smaller size, but > 0
   543 
   543 
   544     @param aNewSize new file size
   544     @param aNewSize new file size
   545     @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed 
   545     @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed 
   546 */
   546 */
   547 void CFatFileCB::DoShrinkFileL(TUint32 aNewSize, TBool aForceCachesFlush)
   547 void CFatFileCB::DoShrinkFileL(TUint32 aNewSize, TBool aForceCachesFlush)
   548 		{
   548     {
   549     ASSERT(FileSizeModified());
   549     ASSERT(FileSizeModified());
   550     ASSERT(FCB_FileSize() > aNewSize && aNewSize);
   550     ASSERT(FCB_FileSize() > aNewSize && aNewSize);
   551 	
   551     
   552     if(aForceCachesFlush)		
   552     if(aForceCachesFlush)       
   553         WriteFileSizeL(aNewSize); //-- write file size directly to its dir. entry
   553         WriteFileSizeL(aNewSize); //-- write file size directly to its dir. entry
   554 
   554 
   555 	CheckPosL(aNewSize);
   555     CheckPosL(aNewSize);
   556 	
   556 
   557     TUint32 cluster=iCurrentPos.iCluster;
   557     TUint32 cluster=iCurrentPos.iCluster;
   558 		if (FAT().GetNextClusterL(cluster))
   558     
   559 	    {//-- truncate the cluster chain
   559     if (FAT().GetNextClusterL(cluster))
   560 			FAT().WriteFatEntryEofL(iCurrentPos.iCluster);
   560         {//-- truncate the cluster chain
   561 			FAT().FreeClusterListL(cluster);
   561         FAT().WriteFatEntryEofL(iCurrentPos.iCluster);
   562 			}
   562         FAT().FreeClusterListL(cluster);
   563 		
   563         }
       
   564         
   564     ClearIndex(aNewSize);
   565     ClearIndex(aNewSize);
   565 		FAT().FlushL();
   566     FAT().FlushL();
   566 		}
   567     }
   567 	
   568     
   568 //-----------------------------------------------------------------------------
   569 //-----------------------------------------------------------------------------
   569 /**
   570 /**
   570     Expand a file.
   571     Expand a file.
   571 	
   572     
   572     @param aNewSize new file size.
   573     @param aNewSize new file size.
   573     @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed
   574     @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed
   574 */
   575 */
   575 void CFatFileCB::DoExpandFileL(TUint32 aNewSize, TBool aForceCachesFlush)
   576 void CFatFileCB::DoExpandFileL(TUint32 aNewSize, TBool aForceCachesFlush)
   576 		{
   577     {
   577     ASSERT(FCB_FileSize() < aNewSize);
   578     ASSERT(FCB_FileSize() < aNewSize);
   578     ASSERT(FileSizeModified());
   579     ASSERT(FileSizeModified());
   579 
   580 
   580     const TUint32 KClusterSzLog2  = ClusterSizeLog2();
   581     const TUint32 KClusterSzLog2  = ClusterSizeLog2();
   581     const TUint32 newSizeClusters = (TUint32)(((TUint64)aNewSize + Pow2(KClusterSzLog2) - 1) >> KClusterSzLog2);
   582     const TUint32 newSizeClusters = (TUint32)(((TUint64)aNewSize + Pow2(KClusterSzLog2) - 1) >> KClusterSzLog2);
   582 
   583 
   583 
   584 
   584 	//-- expanding a file
   585     //-- expanding a file
   585 	if (FCB_StartCluster() == 0)
   586     if (FCB_StartCluster() == 0)
   586 		{//-- the initial file size is 0 (no cluster chain)
   587         {//-- the initial file size is 0 (no cluster chain)
   587          
   588          
   588         ClearIndex(0); //-- clear seek index array
   589         ClearIndex(0); //-- clear seek index array
   589         //-- 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
   590         const TUint32 tempStartCluster=FAT().AllocateClusterListL(newSizeClusters, FAT().FreeClusterHint()); 
   591         const TUint32 tempStartCluster=FAT().AllocateClusterListL(newSizeClusters, FAT().FreeClusterHint()); 
   591 		FAT().FlushL();
   592         FAT().FlushL();
   592 
   593 
   593 		iCurrentPos.iCluster=tempStartCluster;
   594         iCurrentPos.iCluster=tempStartCluster;
   594 		FCB_SetStartCluster(tempStartCluster);
   595         FCB_SetStartCluster(tempStartCluster);
   595 		FCB_SetFileSize(aNewSize);
   596         FCB_SetFileSize(aNewSize);
   596 		FlushAllL();
   597         FlushAllL();
   597 		}
   598         }
   598 	else
   599     else
   599 		{
   600         {
   600 		const TUint curSize = FCB_FileSize(); 
   601         const TUint curSize = FCB_FileSize(); 
   601 	    const TUint32 oldSizeClusters = ((curSize + Pow2(KClusterSzLog2) - 1) >> KClusterSzLog2);
   602         const TUint32 oldSizeClusters = ((curSize + Pow2(KClusterSzLog2) - 1) >> KClusterSzLog2);
   602         ASSERT(newSizeClusters >= oldSizeClusters);
   603         ASSERT(newSizeClusters >= oldSizeClusters);
   603 		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
   604 		if (newClusters)
   605         if (newClusters)
   605 			{
   606             {
   606 			TEntryPos currentPos=iCurrentPos;
   607             TEntryPos currentPos=iCurrentPos;
   607 			CheckPosL(FCB_FileSize());
   608             CheckPosL(FCB_FileSize());
   608 			FAT().ExtendClusterListL(newClusters,iCurrentPos.iCluster);
   609             FAT().ExtendClusterListL(newClusters,iCurrentPos.iCluster);
   609 			iCurrentPos=currentPos;
   610             iCurrentPos=currentPos;
   610 			}
   611             }
   611 	
   612     
   612 		FAT().FlushL();
   613         FAT().FlushL();
   613 		
   614         
   614         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
   615 			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
   616 		}
   617         }
   617 
   618 
   618 	}
   619     }
   619 
   620 
   620 //-----------------------------------------------------------------------------
   621 //-----------------------------------------------------------------------------
   621 /**
   622 /**
   622     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.
   623     @param  aSize               new file size
   624     @param  aSize               new file size
   624     @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. 
   625                                 it is used in Rugged FAT mode.
   626                                 it is used in Rugged FAT mode.
   626 */
   627 */
   627 void CFatFileCB::DoSetSizeL(TUint aSize, TBool aForceCachesFlush)
   628 void CFatFileCB::DoSetSizeL(TUint aSize, TBool aForceCachesFlush)
   628 	{
   629     {
   629 	__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);
   630 
   631 
   631     FatMount().CheckStateConsistentL();
   632     FatMount().CheckStateConsistentL();
   632     FatMount().CheckWritableL();
   633     FatMount().CheckWritableL();
   633 
   634 
   634 	
   635     
   635 	// Can not change the file size if it is clamped
   636     // Can not change the file size if it is clamped
   636 	if(Mount().IsFileClamped(MAKE_TINT64(0,FCB_StartCluster())) > 0)
   637     if(Mount().IsFileClamped(MAKE_TINT64(0,FCB_StartCluster())) > 0)
   637 		User::Leave(KErrInUse);
   638         User::Leave(KErrInUse);
   638 	
   639     
   639 	if(aSize == FCB_FileSize())
   640     if(aSize == FCB_FileSize())
   640         return;
   641         return;
   641 
   642 
   642     IndicateFileSizeModified(ETrue);
   643     IndicateFileSizeModified(ETrue);
       
   644 	IndicateFileAttModified(ETrue);		// ensure file size is flushed
   643 
   645 
   644 	TInt newIndexMult=CalcSeekIndexSize(aSize);
   646 	TInt newIndexMult=CalcSeekIndexSize(aSize);
   645 	if (iSeekIndex!=NULL && newIndexMult!=iSeekIndexSize)
   647 	if (iSeekIndex!=NULL && newIndexMult!=iSeekIndexSize)
   646 		ResizeIndex(newIndexMult,aSize);
   648 		ResizeIndex(newIndexMult,aSize);
   647 
   649 
   652         DoShrinkFileToZeroSizeL();
   654         DoShrinkFileToZeroSizeL();
   653         return;
   655         return;
   654         }
   656         }
   655 
   657 
   656     //-------------------------------------------
   658     //-------------------------------------------
   657 	//-- shrinking file to non-zero size
   659     //-- shrinking file to non-zero size
   658     if (aSize < FCB_FileSize())
   660     if (aSize < FCB_FileSize())
   659 		{
   661         {
   660         DoShrinkFileL(aSize, aForceCachesFlush);
   662         DoShrinkFileL(aSize, aForceCachesFlush);
   661         return;
   663         return;
   662         }
   664         }
   663     
   665     
   664     //-------------------------------------------
   666     //-------------------------------------------
   665 	//-- expanding a file
   667     //-- expanding a file
   666     DoExpandFileL(aSize, aForceCachesFlush);
   668     DoExpandFileL(aSize, aForceCachesFlush);
   667 
   669 
   668 	}
   670     }
   669 
   671 
   670 //-----------------------------------------------------------------------------
   672 //-----------------------------------------------------------------------------
   671 /**
   673 /**
   672     Set file entry details, like file attributes and modified time
   674     Set file entry details, like file attributes and modified time
   673     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 
   677     @param  aSetAttMask     file attributes OR mask
   679     @param  aSetAttMask     file attributes OR mask
   678     @param  aClearAttMask   file attributes AND mask
   680     @param  aClearAttMask   file attributes AND mask
   679 
   681 
   680 */
   682 */
   681 void CFatFileCB::SetEntryL(const TTime& aTime,TUint aSetAttMask,TUint aClearAttMask)
   683 void CFatFileCB::SetEntryL(const TTime& aTime,TUint aSetAttMask,TUint aClearAttMask)
   682 	{
   684     {
   683 	__PRINT1(_L("CFatFileCB::SetEntryL[0x%x]"), this);
   685     __PRINT1(_L("CFatFileCB::SetEntryL[0x%x]"), this);
   684     
   686     
   685     FatMount().CheckStateConsistentL();
   687     FatMount().CheckStateConsistentL();
   686     FatMount().CheckWritableL();
   688     FatMount().CheckWritableL();
   687 
   689 
   688     //-- change file attributes
   690     //-- change file attributes
   689     const TUint setAttMask = (aSetAttMask & KEntryAttMaskSupported); //-- supported attributes to set
   691     const TUint setAttMask = (aSetAttMask & KEntryAttMaskSupported); //-- supported attributes to set
   690     TUint newAtt = Att();
   692 	TUint oldAtt = Att();
       
   693 	TUint newAtt = oldAtt;
   691 
   694 
   692 	if (setAttMask|aClearAttMask)
   695 	if (setAttMask|aClearAttMask)
   693 		{
   696 		{
   694         newAtt |= setAttMask;
   697         newAtt |= setAttMask;
   695         newAtt &= ~aClearAttMask;
   698         newAtt &= ~aClearAttMask;
   696         SetAtt(newAtt);
   699 		if (newAtt != oldAtt)
   697         IndicateFileAttModified(ETrue); //-- indicate that file attributes have changed
   700 			{
       
   701 	        SetAtt(newAtt);
       
   702 		    IndicateFileAttModified(ETrue); //-- indicate that file attributes have changed
       
   703 			}
   698 		}
   704 		}
   699     
   705     
   700     //-- set file entry modification time if required
   706     //-- set file entry modification time if required
   701 	if (aSetAttMask&KEntryAttModified)
   707 	if (aSetAttMask&KEntryAttModified)
   702 	{
   708 		{
   703         SetModified(aTime);        //-- set file modified time
   709         SetModified(aTime);        //-- set file modified time
   704         IndicateFileAttModified(ETrue); //-- indicate that file attributes have changed
   710         IndicateFileAttModified(ETrue); //-- indicate that file attributes have changed
   705         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
   706         }
   712         }
   707 
   713 
   708 	}
   714     }
   709 
   715 
   710 
   716 
   711 //-----------------------------------------------------------------------------
   717 //-----------------------------------------------------------------------------
   712 /** 
   718 /** 
   713     The same as FlushAllL(). This method is called from RFile::Flush()
   719     The same as FlushAllL(). This method is called from RFile::Flush()
   714 */
   720 */
   715 void CFatFileCB::FlushDataL()
   721 void CFatFileCB::FlushDataL()
   716 	{
   722     {
   717 	__PRINT1(_L("CFatFileCB::FlushDataL[0x%x]"), this);
   723     __PRINT1(_L("CFatFileCB::FlushDataL[0x%x]"), this);
   718     FlushAllL();
   724     FlushAllL();
   719 	}
   725     }
   720 
   726 
   721 //-----------------------------------------------------------------------------
   727 //-----------------------------------------------------------------------------
   722 /** 
   728 /** 
   723     Flush the fide directory entry data: files size, attributes, time etc. 
   729     Flush the fide directory entry data: files size, attributes, time etc. 
   724 */
   730 */
   725 void CFatFileCB::FlushAllL()
   731 void CFatFileCB::FlushAllL()
   726 	{
   732     {
   727 
   733 
   728     //-- 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.
   729     //-- 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.
   730     //-- file size, start cluster, attributes and modification timestamp
   736     //-- file size, start cluster, attributes and modification timestamp
   731     #define ALWAYS_UPDATE_ENTRY_ON_FLUSH
   737     #define ALWAYS_UPDATE_ENTRY_ON_FLUSH
   732 
   738 
   733 	__PRINT1(_L("CFatFileCB::FlushAllL[0x%x]"), this);
   739     __PRINT1(_L("CFatFileCB::FlushAllL[0x%x]"), this);
   734 
   740 
   735     if (Mount().IsCurrentMount()==EFalse)
   741     if (Mount().IsCurrentMount()==EFalse)
   736 		User::Leave(KErrDisMounted);
   742         User::Leave(KErrDisMounted);
   737 
   743 
   738     FatMount().CheckStateConsistentL();
   744     FatMount().CheckStateConsistentL();
   739     FatMount().CheckWritableL();
   745     FatMount().CheckWritableL();
   740 
   746 
   741 	if(!FileSizeModified() && !FileAttModified() && !FileTimeModified())
   747     if(!FileSizeModified() && !FileAttModified() && !FileTimeModified())
   742         return; //-- nothing has changed in the file entry at all
   748         return; //-- nothing has changed in the file entry at all
   743 
   749 
   744 
   750 
   745     //-- read file dir. entry
   751     //-- read file dir. entry
   746 	TFatDirEntry entry;
   752     TFatDirEntry entry;
   747 	FatMount().ReadDirEntryL(iFileDosEntryPos,entry);
   753     FatMount().ReadDirEntryL(iFileDosEntryPos,entry);
   748 	__ASSERT_ALWAYS(entry.IsEndOfDirectory()==EFalse,User::Leave(KErrCorrupt));
   754     __ASSERT_ALWAYS(entry.IsEndOfDirectory()==EFalse,User::Leave(KErrCorrupt));
   749 
   755 
   750     //-- 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 
   751     //-- 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
   752     //-- 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
   753     
   759     
   774 
   780 
   775 #endif //#ifndef ALWAYS_UPDATE_ENTRY_TS_ON_FLUSH
   781 #endif //#ifndef ALWAYS_UPDATE_ENTRY_TS_ON_FLUSH
   776 
   782 
   777     if(bUpdateDirEntry)
   783     if(bUpdateDirEntry)
   778         {//-- write entry to the media
   784         {//-- write entry to the media
   779 	    __PRINT(_L("  CFatFileCB::FlushAllL #1"));
   785         __PRINT(_L("  CFatFileCB::FlushAllL #1"));
   780         entry.SetAttributes(Att() & KEntryAttMaskSupported);
   786         entry.SetAttributes(Att() & KEntryAttMaskSupported);
   781 	    entry.SetSize(FCB_FileSize());
   787         entry.SetSize(FCB_FileSize());
   782 	    entry.SetTime(iModified, timeOffset);
   788         entry.SetTime(iModified, timeOffset);
   783 	    
   789         
   784         entry.SetStartCluster(FCB_StartCluster());
   790         entry.SetStartCluster(FCB_StartCluster());
   785 
   791 
   786 	    const TBool setNotify = FatMount().GetNotifyUser();
   792 	    const TBool setNotify = FatMount().GetNotifyUser();
   787 	if(setNotify)
   793 		if(setNotify)
   788 		{
   794 			{
   789 		FatMount().SetNotifyOff();	// do not launch a notifier
   795 			FatMount().SetNotifyOff();	// do not launch a notifier
   790 		}
   796 			}
   791 
   797 
   792 	    TRAPD(ret, FatMount().WriteDirEntryL(iFileDosEntryPos,entry));
   798 			TRAPD(ret, FatMount().WriteDirEntryL(iFileDosEntryPos,entry));
   793 	
   799 		
   794 	if(setNotify)
   800 		if(setNotify)
   795 		{
   801 			{
   796 		FatMount().SetNotifyOn();
   802 			FatMount().SetNotifyOn();
   797 		}
   803 			}
   798 
   804 
   799 	User::LeaveIfError(ret);
   805 		User::LeaveIfError(ret);
   800 
   806 
   801         IndicateFileSizeModified(EFalse);
   807 		IndicateFileSizeModified(EFalse);
   802         IndicateFileTimeModified(EFalse);
   808 		IndicateFileTimeModified(EFalse);
   803 	    }
   809 	    }
   804 
   810 
   805 
   811 
   806         //-- KEntryAttModified must be reset anyway
   812     //-- KEntryAttModified must be reset anyway
   807         IndicateFileAttModified(EFalse); 
   813     IndicateFileAttModified(EFalse); 
   808 	}
   814 	}
   809 
   815 
   810 //-----------------------------------------------------------------------------
   816 //-----------------------------------------------------------------------------
   811 
   817 
   812 /**
   818 /**
   813     Rename already opened file.
   819     Rename already opened file.
   814     @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
   815 */
   821 */
   816 void CFatFileCB::RenameL(const TDesC& aNewName)
   822 void CFatFileCB::RenameL(const TDesC& aNewName)
   817 	{
   823     {
   818     __PRINT2(_L("CFatFileCB::RenameL[0x%x], name:%S"),this, &aNewName);
   824     __PRINT2(_L("CFatFileCB::RenameL[0x%x], name:%S"),this, &aNewName);
   819 
   825 
   820     FatMount().CheckStateConsistentL();
   826     FatMount().CheckStateConsistentL();
   821     FatMount().CheckWritableL();
   827     FatMount().CheckWritableL();
   822 
   828 
   823     const TPtrC fileName = RemoveTrailingDots(aNewName); //-- remove trailing dots from the name
   829     const TPtrC fileName = RemoveTrailingDots(aNewName); //-- remove trailing dots from the name
   824 
   830 
   825 
   831 
   826 	FatMount().DoRenameOrReplaceL(*iFileName, fileName, CFatMountCB::EModeRename, iFileDosEntryPos);
   832     FatMount().DoRenameOrReplaceL(*iFileName, fileName, CFatMountCB::EModeRename, iFileDosEntryPos);
   827 	
   833     
   828     AllocBufferL(iFileName, fileName);
   834     AllocBufferL(iFileName, fileName);
   829 	
   835     
   830 	if(!FatMount().IsRuggedFSys())
   836     if(!FatMount().IsRuggedFSys())
   831 		FAT().FlushL();
   837         FAT().FlushL();
   832 	}
   838     }
   833 
   839 
   834 
   840 
   835 //***********************************************************
   841 //***********************************************************
   836 //* BlockMap interface
   842 //* BlockMap interface
   837 //***********************************************************
   843 //***********************************************************
   838 	
   844     
   839 TInt CFatFileCB::BlockMap(SBlockMapInfo& aInfo, TInt64& aStartPos, TInt64 aEndPos)
   845 TInt CFatFileCB::BlockMap(SBlockMapInfo& aInfo, TInt64& aStartPos, TInt64 aEndPos)
   840 //
   846 //
   841 // 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.
   842 //	
   848 //  
   843 	{
   849     {
   844 	__PRINT2(_L("CFatFileCB::BlockMap aStartPos=%ld aEndPos=%ld"), aStartPos, aEndPos);
   850     __PRINT2(_L("CFatFileCB::BlockMap aStartPos=%ld aEndPos=%ld"), aStartPos, aEndPos);
   845 	
   851     
   846 	if ( I64HIGH(aStartPos) || I64HIGH(aEndPos) )
   852     if ( I64HIGH(aStartPos) || I64HIGH(aEndPos) )
   847 		return KErrNotSupported;
   853         return KErrNotSupported;
   848 
   854 
   849     TUint startPos = I64LOW(aStartPos);
   855     TUint startPos = I64LOW(aStartPos);
   850 	TUint endPos = I64LOW(aEndPos);
   856     TUint endPos = I64LOW(aEndPos);
   851 
   857 
   852 	// aEndPos will always be >=0 at this point
   858     // aEndPos will always be >=0 at this point
   853 	const TUint length = endPos - startPos;
   859     const TUint length = endPos - startPos;
   854 	
   860     
   855 	// Store the position of cluster zero in aInfo
   861     // Store the position of cluster zero in aInfo
   856 	CFatMountCB& fatMount = FatMount();
   862     CFatMountCB& fatMount = FatMount();
   857 
   863 
   858 	TInt drvNo=-1;
   864     TInt drvNo=-1;
   859 	TBusLocalDrive* locDrv;
   865     TBusLocalDrive* locDrv;
   860 	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))
   861 		aInfo.iLocalDriveNumber=drvNo;
   867         aInfo.iLocalDriveNumber=drvNo;
   862 	else
   868     else
   863 		return KErrNotSupported;
   869         return KErrNotSupported;
   864 
   870 
   865 	// Fetch the address of cluster 0
   871     // Fetch the address of cluster 0
   866 	aInfo.iStartBlockAddress = fatMount.FAT().DataPositionInBytes(KFirstClusterNum);
   872     aInfo.iStartBlockAddress = fatMount.FAT().DataPositionInBytes(KFirstClusterNum);
   867 
   873 
   868 	TRAPD(r, CheckPosL(startPos));
   874     TRAPD(r, CheckPosL(startPos));
   869 	if (r != KErrNone)
   875     if (r != KErrNone)
   870 		return r;
   876         return r;
   871 
   877 
   872 	aInfo.iBlockStartOffset = fatMount.ClusterRelativePos(iCurrentPos.iPos);
   878     aInfo.iBlockStartOffset = fatMount.ClusterRelativePos(iCurrentPos.iPos);
   873 	aInfo.iBlockGranularity = 1 << FatMount().ClusterSizeLog2();
   879     aInfo.iBlockGranularity = 1 << FatMount().ClusterSizeLog2();
   874 	const TUint myStartPos = iCurrentPos.iPos;
   880     const TUint myStartPos = iCurrentPos.iPos;
   875 	if ( myStartPos + length > FCB_FileSize())
   881     if ( myStartPos + length > FCB_FileSize())
   876 		return KErrArgument;
   882         return KErrArgument;
   877 
   883 
   878 	TRAP(r, FatMount().BlockMapReadFromClusterListL(iCurrentPos, length, aInfo));
   884     TRAP(r, FatMount().BlockMapReadFromClusterListL(iCurrentPos, length, aInfo));
   879 	if (r != KErrNone)
   885     if (r != KErrNone)
   880 		return r;
   886         return r;
   881 
   887 
   882 	aStartPos = iCurrentPos.iPos;
   888     aStartPos = iCurrentPos.iPos;
   883 	if ((I64LOW(aStartPos) == FCB_FileSize()) || ( I64LOW(aStartPos) == (myStartPos + length)))
   889     if ((I64LOW(aStartPos) == FCB_FileSize()) || ( I64LOW(aStartPos) == (myStartPos + length)))
   884 		return KErrCompletion;
   890         return KErrCompletion;
   885 	else
   891     else
   886 		return KErrNone;
   892         return KErrNone;
   887 	}
   893     }
   888 
   894 
   889 
   895 
   890 TInt CFatFileCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput)
   896 TInt CFatFileCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput)
   891 	{
   897     {
   892 	switch(aInterfaceId)
   898     switch(aInterfaceId)
   893 		{
   899         {
   894 		case EExtendedFileInterface:
   900         case EExtendedFileInterface:
   895 			((CFileCB::MExtendedFileInterface*&) aInterface) = this;
   901             ((CFileCB::MExtendedFileInterface*&) aInterface) = this;
   896 			return KErrNone;
   902             return KErrNone;
   897 
   903 
   898 		case EBlockMapInterface:
   904         case EBlockMapInterface:
   899 			aInterface = (CFileCB::MBlockMapInterface*) this;
   905             aInterface = (CFileCB::MBlockMapInterface*) this;
   900 			return KErrNone;
   906             return KErrNone;
   901 
   907 
   902 		case EGetLocalDrive:
   908         case EGetLocalDrive:
   903 			return FatMount().LocalDrive()->GetLocalDrive((TBusLocalDrive*&) aInterface);
   909             return FatMount().LocalDrive()->GetLocalDrive((TBusLocalDrive*&) aInterface);
   904 
   910 
   905 		default:
   911         default:
   906 			return CFileCB::GetInterface(aInterfaceId,aInterface,aInput);
   912             return CFileCB::GetInterface(aInterfaceId,aInterface,aInput);
   907 		}
   913         }
   908 	}
   914     }
   909 
   915 
   910 
   916 
   911 /**
   917 /**
   912     Overwrites file's start cluster (iStartCluster) in its directory entry.
   918     Overwrites file's start cluster (iStartCluster) in its directory entry.
   913 */
   919 */
   914 void CFatFileCB::FlushStartClusterL()
   920 void CFatFileCB::FlushStartClusterL()
   915 	{
   921     {
   916 	__PRINT1(_L("CFatFileCB::FlushStartClusterL[0x%x]"), this);
   922     __PRINT1(_L("CFatFileCB::FlushStartClusterL[0x%x]"), this);
   917 
   923 
   918     CFatMountCB& mount = FatMount();
   924     CFatMountCB& mount = FatMount();
   919     TFatDirEntry dirEntry;
   925     TFatDirEntry dirEntry;
   920     
   926     
   921     mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry
   927     mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry
   922     dirEntry.SetStartCluster(FCB_StartCluster());    //-- set new start cluster
   928     dirEntry.SetStartCluster(FCB_StartCluster());    //-- set new start cluster
   923     mount.WriteDirEntryL(iFileDosEntryPos, dirEntry);//-- write the entry back
   929     mount.WriteDirEntryL(iFileDosEntryPos, dirEntry);//-- write the entry back
   924 	}
   930     }
   925 
   931 
   926 
   932 
   927 /**
   933 /**
   928     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.
   929 */
   935 */
   930 void CFatFileCB::WriteFileSizeL(TUint aSize)
   936 void CFatFileCB::WriteFileSizeL(TUint aSize)
   931 	{
   937     {
   932 	__PRINT2(_L("CFatFileCB::WriteFileSizeL[0x%x], sz:%d"), this, aSize);
   938     __PRINT2(_L("CFatFileCB::WriteFileSizeL[0x%x], sz:%d"), this, aSize);
   933 
   939 
   934     CFatMountCB& mount = FatMount();
   940     CFatMountCB& mount = FatMount();
   935     TFatDirEntry dirEntry;
   941     TFatDirEntry dirEntry;
   936 
   942 
   937     mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry
   943     mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry
   938     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 
   939     mount.WriteDirEntryL(iFileDosEntryPos, dirEntry);//-- write the entry back
   960     mount.WriteDirEntryL(iFileDosEntryPos, dirEntry);//-- write the entry back
   940 
   961 
   941     IndicateFileSizeModified(EFalse);
   962     IndicateFileSizeModified(EFalse);
   942     }
   963     }
   943 
   964