diff -r e7d2d738d3c2 -r 2f92ad2dc5db userlibandfileserver/fileserver/sfat32/sl_file.cpp --- a/userlibandfileserver/fileserver/sfat32/sl_file.cpp Mon Mar 15 12:45:50 2010 +0200 +++ b/userlibandfileserver/fileserver/sfat32/sl_file.cpp Wed Mar 31 23:38:45 2010 +0300 @@ -25,13 +25,12 @@ CFatFileCB::CFatFileCB() { - __PRINT1(_L("CFatFileCB created 0x%x"),this); } CFatFileCB::~CFatFileCB() { - __PRINT1(_L("CFatFileCB deleted 0x%x"),this); + __PRINT1(_L("~CFatFileCB deleted 0x%x"),this); //-- a nasty trick to find out if the CFatFileCB is in consistent state on the moment of destruction. //-- Because of OOM conditions CFatFileCB might not be fully constructed and to be deleted, while FlushAll() @@ -39,9 +38,12 @@ const CMountCB* pMount = &Mount(); if(pMount) {//-- do some finalisation work if CMountCB is valid - if (iAtt&KEntryAttModified) + if(FileAttModified()) + { + IndicateFileTimeModified(ETrue); //-- this will force writing file modification time to the media on Flush TRAP_IGNORE(FlushAllL()); } + } delete[] iSeekIndex; } @@ -59,10 +61,10 @@ Mem::FillZ(iSeekIndex, sizeof(TUint32) * KSeekIndexSize); - iSeekIndexSize=CalcSeekIndexSize(Size()); + iSeekIndexSize=CalcSeekIndexSize(FCB_FileSize()); } -TInt CFatFileCB::SeekToPosition(TInt aNewRelCluster,TInt aClusterOffset) +TInt CFatFileCB::SeekToPosition(TUint aNewRelCluster, TUint aClusterOffset) // // Use the seek index to set iCurrentPos.iCluster as close as possible to aNewRelCluster // Return aNewRelCluster-aCurrentPos.iCluster @@ -81,7 +83,7 @@ return(aClusterOffset); if (seekPos<0) { - iCurrentPos.iCluster=iStartCluster; + iCurrentPos.iCluster=FCB_StartCluster(); return(aNewRelCluster); } @@ -89,7 +91,7 @@ return(aNewRelCluster-((seekPos+1)<>ClusterSizeLog2(); if ( aPos && (aPos==(newRelCluster<>ClusterSizeLog2(); + if ( iCurrentPos.iPos && (iCurrentPos.iPos==(oldRelCluster< KMaxSupportedFatFileSize-1) User::Leave(KErrNotSupported); //-- max. position in the file is 0xFFFFFFFE @@ -205,7 +240,7 @@ CheckPosL(I64LOW(aPos)); const TUint startPos = iCurrentPos.iPos; - const TUint curSize = (TUint)Size(); + const TUint curSize = FCB_FileSize(); const TUint length = (TUint)aLength; if((startPos + length > curSize) || (startPos > startPos + length) ) @@ -222,10 +257,22 @@ } //----------------------------------------------------------------------------- -// from CFileCB::MExtendedFileInterface +/** + Write data to the file. + + @param aFilePos start write position within a file + @param aLength how many bytes to write; on return contain amount of data actually written + @param aDes local buffer desctriptor + @param aMessage from file server, used to write data to the media from different address space. + @param aDesOffset offset within data descriptor + + @leave on media read error + +*/ void CFatFileCB::WriteL(TInt64 aPos,TInt& aLength,const TDesC8* aSrc,const RMessagePtr2& aMessage, TInt aOffset) { - __PRINT2(_L("CFatFileCB::WriteL aFilePos=%LU aLength=%d"),aPos,aLength); + __PRINT3(_L("CFatFileCB::WriteL[0x%x] pos=%LU len=%d"), this, aPos, aLength); + // FAT supports 32 bits only for file size TUint64 endPos = aPos + aLength; if(endPos > KMaxSupportedFatFileSize) @@ -236,17 +283,17 @@ const TUint pos = I64LOW(aPos); CheckPosL(pos); - const TUint startCluster = (TUint)iStartCluster; + const TUint startCluster = FCB_StartCluster(); const TUint length = (TUint)aLength; endPos = iCurrentPos.iPos + length; - if ((endPos > (TUint)Size()) || + if ((endPos > FCB_FileSize()) || (iCurrentPos.iPos > endPos) ) // Overflow condition DoSetSizeL(iCurrentPos.iPos+length,EFalse); TUint startPos=iCurrentPos.iPos; - TInt badcluster=0; - TInt goodcluster=0; + TUint badcluster=0; + TUint goodcluster=0; TRAPD(ret, FatMount().WriteToClusterListL(iCurrentPos,aLength,aSrc,aMessage,aOffset,badcluster, goodcluster)); @@ -254,9 +301,11 @@ { if(startCluster == 0) { //Empty File, revert all the clusters allocated. - TInt cluster = iStartCluster; - iStartCluster = 0; - SetSize(0); + const TUint32 cluster = FCB_StartCluster(); + FCB_SetStartCluster(0); + FCB_SetFileSize(0); + IndicateFileSizeModified(ETrue); + FlushAllL(); iCurrentPos.iCluster = 0; @@ -267,14 +316,14 @@ } else { //Calculate the clusters required based on file size, revert extra clusters if allocated. - const TUint curSize = (TUint)Size(); + const TUint curSize = FCB_FileSize(); TUint ClustersNeeded = curSize >> ClusterSizeLog2(); if(curSize > (ClustersNeeded << ClusterSizeLog2())) { ClustersNeeded++; } - TInt cluster = iStartCluster; + TUint32 cluster = FCB_StartCluster(); while(--ClustersNeeded) { FAT().GetNextClusterL(cluster); @@ -296,14 +345,14 @@ if(badcluster != 0) { - if(iStartCluster == badcluster) + if(FCB_StartCluster() == badcluster) { - iStartCluster = goodcluster; + FCB_SetStartCluster(goodcluster); FlushStartClusterL(); } else { - TInt aCluster = iStartCluster; + TUint32 aCluster = FCB_StartCluster(); do { if((TUint)badcluster == FAT().ReadL(aCluster)) @@ -318,7 +367,7 @@ } aLength=iCurrentPos.iPos-startPos; - if(FatMount().IsRuggedFSys() && pos+(TUint)aLength>(TUint)Size()) + if(FatMount().IsRuggedFSys() && pos+(TUint)aLength > FCB_FileSize()) { WriteFileSizeL(pos+aLength); } @@ -441,169 +490,228 @@ } //----------------------------------------------------------------------------- - +/** + Set file size. + @param aSize new file size. +*/ void CFatFileCB::SetSizeL(TInt64 aSize) { - __PRINT(_L("CFatFileCB::SetSizeL")); + __PRINT2(_L("CFatFileCB::SetSizeL[0x%x] sz=%LU"), this, aSize); - // FAT supports 32 bits only for file size + //-- max. file size for FAT is 4GB-1 if (I64HIGH(aSize)) User::Leave(KErrNotSupported); - if(FatMount().IsRuggedFSys()) - DoSetSizeL(I64LOW(aSize),ETrue); - else - DoSetSizeL(I64LOW(aSize),EFalse); + DoSetSizeL(I64LOW(aSize), FatMount().IsRuggedFSys()); } void CFatFileCB::SetSizeL(TInt aSize) -// -// Envelope function around DoSetSizeL to enable aSize to -// be written to disk for rugged fat file system -// { SetSizeL(TInt64(aSize)); } -void CFatFileCB::DoSetSizeL(TUint aSize,TBool aIsSizeWrite) -// -// Extend or truncate the file. -// Expects the modified attribute and iSize are set afterwards. -// Does not alter iCurrentPos, the current file position. -// Writes size of file to disk if aIsSizeWrite set -// +//----------------------------------------------------------------------------- +/** + Shrink file to zero size. +*/ +void CFatFileCB::DoShrinkFileToZeroSizeL() + { + ASSERT(FCB_FileSize()); + ASSERT(FileSizeModified()); + + ClearIndex(0); //-- clear seek index array + + //-- update file dir. entry + const TUint32 cluster = FCB_StartCluster(); + FCB_SetStartCluster(0); + FCB_SetFileSize(0); + FlushAllL(); + + //-- free cluster list. + CheckPosL(0); + FAT().FreeClusterListL(cluster); + FAT().FlushL(); + } + +//----------------------------------------------------------------------------- +/* + Shrink file to smaller size, but > 0 + + @param aNewSize new file size + @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed +*/ +void CFatFileCB::DoShrinkFileL(TUint32 aNewSize, TBool aForceCachesFlush) + { + ASSERT(FileSizeModified()); + ASSERT(FCB_FileSize() > aNewSize && aNewSize); + + if(aForceCachesFlush) + WriteFileSizeL(aNewSize); //-- write file size directly to its dir. entry + + CheckPosL(aNewSize); + + TUint32 cluster=iCurrentPos.iCluster; + if (FAT().GetNextClusterL(cluster)) + {//-- truncate the cluster chain + FAT().WriteFatEntryEofL(iCurrentPos.iCluster); + FAT().FreeClusterListL(cluster); + } + + ClearIndex(aNewSize); + FAT().FlushL(); + } + +//----------------------------------------------------------------------------- +/** + Expand a file. + + @param aNewSize new file size. + @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed +*/ +void CFatFileCB::DoExpandFileL(TUint32 aNewSize, TBool aForceCachesFlush) + { + ASSERT(FCB_FileSize() < aNewSize); + ASSERT(FileSizeModified()); + + const TUint32 KClusterSzLog2 = ClusterSizeLog2(); + const TUint32 newSizeClusters = (TUint32)(((TUint64)aNewSize + Pow2(KClusterSzLog2) - 1) >> KClusterSzLog2); + + + //-- expanding a file + if (FCB_StartCluster() == 0) + {//-- the initial file size is 0 (no cluster chain) + + ClearIndex(0); //-- clear seek index array + //-- FAT().FreeClusterHint() will give us a hint of the last free cluster + const TUint32 tempStartCluster=FAT().AllocateClusterListL(newSizeClusters, FAT().FreeClusterHint()); + FAT().FlushL(); + + iCurrentPos.iCluster=tempStartCluster; + FCB_SetStartCluster(tempStartCluster); + FCB_SetFileSize(aNewSize); + FlushAllL(); + } + else + { + const TUint curSize = FCB_FileSize(); + const TUint32 oldSizeClusters = ((curSize + Pow2(KClusterSzLog2) - 1) >> KClusterSzLog2); + ASSERT(newSizeClusters >= oldSizeClusters); + const TUint newClusters = newSizeClusters-oldSizeClusters; //-- Number of clusters we need to append to the existing cluster chain + if (newClusters) + { + TEntryPos currentPos=iCurrentPos; + CheckPosL(FCB_FileSize()); + FAT().ExtendClusterListL(newClusters,iCurrentPos.iCluster); + iCurrentPos=currentPos; + } + + FAT().FlushL(); + + if(aForceCachesFlush) // write file size if increasing + WriteFileSizeL(aNewSize); + } + + } + +//----------------------------------------------------------------------------- +/** + Set file size. This can involve extending/truncating file's cluster chain. + @param aSize new file size + @param aForceCachesFlush if ETrue, all changes in metadata will go to the media immediately. + it is used in Rugged FAT mode. +*/ +void CFatFileCB::DoSetSizeL(TUint aSize, TBool aForceCachesFlush) { - __PRINT2(_L("CFatFileCB::DoSetSizeL sz:%d, fileWrite=%d"),aSize ,aIsSizeWrite); + __PRINT4(_L("CFatFileCB::DoSetSizeL[0x%x] sz:%d, oldSz:%d, flush:%d"), this, aSize, FCB_FileSize(), aForceCachesFlush); FatMount().CheckStateConsistentL(); FatMount().CheckWritableL(); // Can not change the file size if it is clamped - if(Mount().IsFileClamped(MAKE_TINT64(0,iStartCluster)) > 0) + if(Mount().IsFileClamped(MAKE_TINT64(0,FCB_StartCluster())) > 0) User::Leave(KErrInUse); - iFileSizeModified=ETrue; + if(aSize == FCB_FileSize()) + return; + + IndicateFileSizeModified(ETrue); TInt newIndexMult=CalcSeekIndexSize(aSize); if (iSeekIndex!=NULL && newIndexMult!=iSeekIndexSize) ResizeIndex(newIndexMult,aSize); - if (aSize == 0) - { - if (Size() != 0) - { - ClearIndex(0); //-- clear seek index array - TInt cluster=iStartCluster; - iStartCluster = 0; - SetSize(0); - FlushAllL(); - CheckPosL(0); - FAT().FreeClusterListL(cluster); - FAT().FlushL(); - } - return; - } - if (aSize<(TUint)Size()) + + //------------------------------------------- + //-- shrinking file to 0 size + if(aSize == 0) + { + DoShrinkFileToZeroSizeL(); + return; + } + + //------------------------------------------- + //-- shrinking file to non-zero size + if (aSize < FCB_FileSize()) { - if(aIsSizeWrite) // write file size if decreasing - WriteFileSizeL(aSize); - CheckPosL(aSize); - TInt cluster=iCurrentPos.iCluster; - if (FAT().GetNextClusterL(cluster)) - { - FAT().WriteFatEntryEofL(iCurrentPos.iCluster); - FAT().FreeClusterListL(cluster); - } - ClearIndex(aSize); - FAT().FlushL(); - return; - } - - TUint newSize=aSize>>ClusterSizeLog2(); // Number of clusters we now need - if (aSize > (newSize<>ClusterSizeLog2(); // Number of clusters we had previously - if (curSize>(oldSize< (TUint)Size()) + if ( myStartPos + length > FCB_FileSize()) return KErrArgument; TRAP(r, FatMount().BlockMapReadFromClusterListL(iCurrentPos, length, aInfo)); @@ -720,7 +877,7 @@ return r; aStartPos = iCurrentPos.iPos; - if ((I64LOW(aStartPos) == (TUint)Size()) || ( I64LOW(aStartPos) == (myStartPos + length))) + if ((I64LOW(aStartPos) == FCB_FileSize()) || ( I64LOW(aStartPos) == (myStartPos + length))) return KErrCompletion; else return KErrNone; @@ -756,17 +913,37 @@ */ void CFatFileCB::FlushStartClusterL() { - __PRINT(_L("CFatFileCB::FlushStartClusterL")); + __PRINT1(_L("CFatFileCB::FlushStartClusterL[0x%x]"), this); CFatMountCB& mount = FatMount(); TFatDirEntry dirEntry; - mount.ReadDirEntryL(iFileDirPos, dirEntry); //-- read this file's dir. entry - dirEntry.SetStartCluster(iStartCluster); //-- set new start cluster - mount.WriteDirEntryL(iFileDirPos, dirEntry);//-- write the entry back + mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry + dirEntry.SetStartCluster(FCB_StartCluster()); //-- set new start cluster + mount.WriteDirEntryL(iFileDosEntryPos, dirEntry);//-- write the entry back } +/** + This is a RuggedFAT - specific method. Writes file size to the corresponding field of its file directory entry. +*/ +void CFatFileCB::WriteFileSizeL(TUint aSize) + { + __PRINT2(_L("CFatFileCB::WriteFileSizeL[0x%x], sz:%d"), this, aSize); + + CFatMountCB& mount = FatMount(); + TFatDirEntry dirEntry; + + mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry + dirEntry.SetSize(aSize); //-- set new size + mount.WriteDirEntryL(iFileDosEntryPos, dirEntry);//-- write the entry back + + IndicateFileSizeModified(EFalse); + } + + + +