userlibandfileserver/fileserver/sfat/sl_file.cpp
changeset 9 96e5fb8b040d
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // f32\sfat\sl_file.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 
       
    19 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       
    20 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       
    21 //!!
       
    22 //!! WARNING!! DO NOT edit this file !! '\sfat' component is obsolete and is not being used. '\sfat32'replaces it
       
    23 //!!
       
    24 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       
    25 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       
    26 
       
    27 
       
    28 #include "sl_std.h"
       
    29 #include "sl_cache.h"
       
    30 #include <e32math.h>
       
    31 
       
    32 const TInt KSeekIndexSize=128; // Cache 128 clusters
       
    33 const TInt KSeekIndexSizeLog2=7;
       
    34 const TInt KFirstClusterNum=2;
       
    35 
       
    36 CFatFileCB::CFatFileCB()
       
    37     {
       
    38 
       
    39     __PRINT1(_L("CFatFileCB created 0x%x"),this);
       
    40     }
       
    41 
       
    42 CFatFileCB::~CFatFileCB()
       
    43     {
       
    44     __PRINT1(_L("CFatFileCB deleted 0x%x"),this);
       
    45 
       
    46     //-- a nasty trick to find out if the CFatFileCB is in consistent state on the moment of destruction.
       
    47     //-- Because of OOM conditions CFatFileCB might not be fully constructed and to be deleted, while FlushAll()
       
    48     //-- implies valid iMount.
       
    49     const CMountCB* pMount  = &Mount();
       
    50     if(pMount)
       
    51         {//-- do some finalisation work if CMountCB is valid
       
    52         if (iAtt&KEntryAttModified)
       
    53             TRAP_IGNORE(FlushAllL());
       
    54         }
       
    55 
       
    56     delete[] iSeekIndex;
       
    57     }
       
    58 
       
    59 
       
    60 void CFatFileCB::CreateSeekIndex()
       
    61 //
       
    62 // Create a seek index
       
    63 //
       
    64     {
       
    65 
       
    66     iSeekIndex = new TUint32[KSeekIndexSize];
       
    67     if (iSeekIndex == NULL)
       
    68         return;
       
    69 
       
    70     Mem::FillZ(iSeekIndex, sizeof(TUint32) * KSeekIndexSize);
       
    71 
       
    72     iSeekIndexSize=CalcSeekIndexSize(Size());
       
    73     }
       
    74 
       
    75 TInt CFatFileCB::SeekToPosition(TInt aNewRelCluster,TInt aClusterOffset)
       
    76 //
       
    77 // Use the seek index to set iCurrentPos.iCluster as close as possible to aNewRelCluster
       
    78 // Return aNewRelCluster-aCurrentPos.iCluster
       
    79 //
       
    80     {
       
    81     TInt clusterOffset=aClusterOffset;
       
    82     TInt seekPos=(aNewRelCluster>>iSeekIndexSize)-1;
       
    83     __ASSERT_DEBUG(seekPos<KSeekIndexSize,Fault(EFatFileSeekIndexTooSmall));
       
    84 
       
    85     while(seekPos>=0 && iSeekIndex[seekPos]==0 && clusterOffset!=0)
       
    86         {
       
    87         seekPos--;
       
    88         clusterOffset--;
       
    89         }
       
    90     if (clusterOffset==0) // Counted back to the current cluster
       
    91         return(aClusterOffset);
       
    92     if (seekPos<0)
       
    93         {
       
    94         iCurrentPos.iCluster=iStartCluster;
       
    95         return(aNewRelCluster);
       
    96         }
       
    97 
       
    98     iCurrentPos.iCluster=iSeekIndex[seekPos];
       
    99     return(aNewRelCluster-((seekPos+1)<<iSeekIndexSize));
       
   100     }
       
   101 
       
   102 void CFatFileCB::SetSeekIndexValueL(TInt aRelCluster,TInt aStoredCluster)
       
   103 //
       
   104 // Sets a value in the seekindex
       
   105 //
       
   106     {
       
   107 
       
   108     TInt seekPos=(aRelCluster>>iSeekIndexSize)-1;
       
   109     __ASSERT_DEBUG(seekPos<KSeekIndexSize,Fault(EFatFileSeekIndexTooSmall));
       
   110     __ASSERT_DEBUG(seekPos>=0,Fault(EFatFileSeekIndexTooSmall2));
       
   111     iSeekIndex[seekPos] = aStoredCluster;
       
   112     }
       
   113 
       
   114 TBool CFatFileCB::IsSeekBackwards(TUint aPos)
       
   115 //
       
   116 // Return true if aPos<currentPos
       
   117 //
       
   118     {
       
   119     
       
   120     TUint cluster=iCurrentPos.iCluster<<ClusterSizeLog2();
       
   121     TInt offset=ClusterRelativePos(iCurrentPos.iPos);
       
   122     TUint currentPos=cluster+offset;
       
   123     return(aPos<currentPos);
       
   124     }
       
   125 
       
   126 void CFatFileCB::CheckPosL(TUint aPos)
       
   127 //
       
   128 // Check that the file is positioned correctly.
       
   129 // If aPos<currentPos attempt to guess the new position.
       
   130 //
       
   131     {
       
   132     __PRINT1(_L("CFatFileCB::CheckPosL(%d)"), aPos);
       
   133     if (aPos==iCurrentPos.iPos)
       
   134         return;
       
   135     __ASSERT_DEBUG(aPos <= (TUint)Size(), Fault(EFatFilePosBeyondEnd));
       
   136 
       
   137     if (iFileSizeModified && IsSeekBackwards(aPos))
       
   138         FlushDataL(); 
       
   139     
       
   140     TUint newRelCluster=aPos>>ClusterSizeLog2();
       
   141     if ( aPos && (aPos==(newRelCluster<<ClusterSizeLog2())) )
       
   142         newRelCluster--;
       
   143     TUint oldRelCluster=iCurrentPos.iPos>>ClusterSizeLog2();
       
   144     if ( iCurrentPos.iPos && (iCurrentPos.iPos==(oldRelCluster<<ClusterSizeLog2())) )
       
   145         oldRelCluster--;    
       
   146     TInt clusterOffset=newRelCluster-oldRelCluster;
       
   147     TInt oldCluster=iCurrentPos.iCluster;
       
   148     iCurrentPos.iPos=aPos;
       
   149     if (clusterOffset==0)
       
   150         return;
       
   151     TInt seekOffset=clusterOffset;
       
   152     if (iSeekIndex!=NULL)
       
   153         { // Can alter iCurrentPos.iCluster
       
   154         seekOffset=SeekToPosition(newRelCluster,seekOffset);
       
   155         if (seekOffset==0)
       
   156             return;
       
   157         }
       
   158     if (clusterOffset==-1 && seekOffset!=1)
       
   159         { // Check previous cluster
       
   160         TInt cluster=oldCluster-1;
       
   161         if (FAT().GetNextClusterL(cluster) && cluster==oldCluster)
       
   162             {
       
   163             iCurrentPos.iCluster=oldCluster-1;
       
   164             return;
       
   165             }
       
   166         }
       
   167     if (seekOffset<0)
       
   168         {
       
   169         seekOffset=newRelCluster;
       
   170         iCurrentPos.iCluster=iStartCluster;
       
   171         }
       
   172     while (seekOffset--)
       
   173         {
       
   174         if (!FAT().GetNextClusterL(iCurrentPos.iCluster))
       
   175             {
       
   176             __PRINT(_L("CFatFileCB::CheckPosL() corrupt#1"));
       
   177             User::Leave(KErrCorrupt);
       
   178             }
       
   179         TInt cluster=newRelCluster-seekOffset;
       
   180         if (iSeekIndex!=NULL && cluster && (cluster>>iSeekIndexSize)<<iSeekIndexSize==cluster)
       
   181             SetSeekIndexValueL(cluster,iCurrentPos.iCluster);
       
   182         }
       
   183     }
       
   184 
       
   185 void CFatFileCB::SetL(const TFatDirEntry& aFatDirEntry,TShare aShare,const TEntryPos& aPos)
       
   186 //
       
   187 // Initialize FileCB from entry data
       
   188 //
       
   189     {
       
   190 
       
   191     __PRINT(_L("CFatFileCB::SetL"));
       
   192     SetSize(aFatDirEntry.Size()); 
       
   193     iCurrentPos.iCluster= FatMount().StartCluster(aFatDirEntry);
       
   194     iStartCluster=iCurrentPos.iCluster;
       
   195     iCurrentPos.iPos=0;
       
   196     iAtt=aFatDirEntry.Attributes();
       
   197     iModified= aFatDirEntry.Time(FatMount().TimeOffset());
       
   198     iShare=aShare;
       
   199     iFileDirPos=aPos;
       
   200 
       
   201     SetMaxSupportedSize(KMaxSupportedFatFileSize);
       
   202     }
       
   203 
       
   204 //-----------------------------------------------------------------------------
       
   205 // from CFileCB::MExtendedFileInterface
       
   206 void CFatFileCB::ReadL(TInt64 aPos,TInt& aLength, TDes8* aDes, const RMessagePtr2& aMessage, TInt aOffset)
       
   207     {
       
   208     __PRINT2(_L("CFatFileCB::ReadL aFilePos=%LU aLength=%d"),aPos,aLength);
       
   209     
       
   210     if((TUint64)aPos > KMaxSupportedFatFileSize-1)
       
   211         User::Leave(KErrNotSupported);  //-- max. position in the file is 0xFFFFFFFE
       
   212 
       
   213     FatMount().CheckStateConsistentL();
       
   214     
       
   215     CheckPosL(I64LOW(aPos));
       
   216     
       
   217     const TUint startPos = iCurrentPos.iPos;
       
   218     const TUint curSize  = (TUint)Size();
       
   219     const TUint length   = (TUint)aLength;
       
   220     
       
   221     if((startPos + length > curSize) || (startPos > startPos + length) )
       
   222         aLength=curSize-startPos;
       
   223     
       
   224     FatMount().ReadFromClusterListL(iCurrentPos,aLength,aDes,aMessage,aOffset);
       
   225     aLength=iCurrentPos.iPos-startPos;
       
   226     }
       
   227 
       
   228 
       
   229 void CFatFileCB::ReadL(TInt aFilePos,TInt& aLength,const TAny* aTrg,const RMessagePtr2& aMessage)
       
   230     {
       
   231     ReadL(TInt64(aFilePos),aLength,(TDes8*) aTrg,aMessage, 0);
       
   232     }
       
   233 
       
   234 //-----------------------------------------------------------------------------
       
   235 // from CFileCB::MExtendedFileInterface
       
   236 void CFatFileCB::WriteL(TInt64 aPos,TInt& aLength,const TDesC8* aSrc,const RMessagePtr2& aMessage, TInt aOffset)
       
   237     {
       
   238     __PRINT2(_L("CFatFileCB::WriteL aFilePos=%LU aLength=%d"),aPos,aLength);
       
   239     // FAT supports 32 bits only for file size
       
   240     TUint64 endPos = aPos + aLength;
       
   241     if(endPos > KMaxSupportedFatFileSize)
       
   242         User::Leave(KErrNotSupported);
       
   243     
       
   244     FatMount().CheckStateConsistentL();
       
   245     FatMount().CheckWritableL();
       
   246     const TUint pos = I64LOW(aPos);
       
   247     CheckPosL(pos);
       
   248     
       
   249     const TUint startCluster = (TUint)iStartCluster;
       
   250     const TUint length       = (TUint)aLength;
       
   251     
       
   252     endPos = iCurrentPos.iPos + length; 
       
   253     if ((endPos           > (TUint)Size()) ||
       
   254         (iCurrentPos.iPos > endPos)         ) // Overflow condition 
       
   255         DoSetSizeL(iCurrentPos.iPos+length,EFalse);
       
   256     
       
   257     TUint startPos=iCurrentPos.iPos;
       
   258     TInt badcluster=0;
       
   259     TInt goodcluster=0;
       
   260     
       
   261     TRAPD(ret, FatMount().WriteToClusterListL(iCurrentPos,aLength,aSrc,aMessage,aOffset,badcluster, goodcluster));
       
   262     
       
   263     if (ret == KErrCorrupt || ret == KErrDied)
       
   264         {
       
   265         if(startCluster == 0)
       
   266             { //Empty File, revert all the clusters allocated.
       
   267             TInt cluster = iStartCluster;
       
   268             iStartCluster = 0;
       
   269             SetSize(0);
       
   270             FlushAllL();
       
   271 
       
   272             iCurrentPos.iCluster = 0;
       
   273             iCurrentPos.iPos = 0;
       
   274 
       
   275             FAT().FreeClusterListL(cluster);
       
   276             FAT().FlushL();
       
   277             }
       
   278         else
       
   279             { //Calculate the clusters required based on file size, revert extra clusters if allocated.
       
   280             const TUint curSize = (TUint)Size();
       
   281             TUint ClustersNeeded = curSize >> ClusterSizeLog2();
       
   282             if(curSize > (ClustersNeeded << ClusterSizeLog2()))
       
   283                 {
       
   284                 ClustersNeeded++;
       
   285                 }
       
   286 
       
   287             TInt cluster = iStartCluster;
       
   288             while(--ClustersNeeded)
       
   289                 {
       
   290                 FAT().GetNextClusterL(cluster);
       
   291                 }
       
   292                 
       
   293             iCurrentPos.iCluster = cluster;
       
   294 
       
   295             if (FAT().GetNextClusterL(cluster))
       
   296                 {
       
   297                 FAT().FreeClusterListL(cluster);
       
   298                 }
       
   299 
       
   300             FAT().WriteFatEntryEofL(iCurrentPos.iCluster);
       
   301             FAT().FlushL();
       
   302             }
       
   303         }
       
   304 
       
   305     User::LeaveIfError(ret);
       
   306 
       
   307     if(badcluster != 0)
       
   308         {
       
   309         if(iStartCluster == badcluster)
       
   310             {
       
   311             iStartCluster = goodcluster;
       
   312             FlushStartClusterL();
       
   313             }
       
   314         else
       
   315             {
       
   316             TInt aCluster = iStartCluster;
       
   317             do
       
   318                 {
       
   319                 if((TUint)badcluster == FAT().ReadL(aCluster))
       
   320                     {
       
   321                     FAT().WriteL(aCluster, goodcluster);
       
   322                     FAT().FlushL();
       
   323                     break;
       
   324                     }
       
   325                 }
       
   326             while(FAT().GetNextClusterL(aCluster));
       
   327             }
       
   328         }
       
   329     aLength=iCurrentPos.iPos-startPos;
       
   330 
       
   331     if(FatMount().IsRuggedFSys() && pos+(TUint)aLength>(TUint)Size())
       
   332         {
       
   333         WriteFileSizeL(pos+aLength);
       
   334         }
       
   335 
       
   336     }
       
   337 
       
   338 
       
   339 void CFatFileCB::WriteL(TInt aFilePos,TInt& aLength,const TAny* aSrc,const RMessagePtr2& aMessage)
       
   340     {
       
   341     WriteL(TInt64(aFilePos),aLength,(TDesC8*) aSrc,aMessage, 0);
       
   342     }
       
   343 
       
   344 
       
   345 
       
   346 //-----------------------------------------------------------------------------
       
   347 
       
   348 void CFatFileCB::ResizeIndex(TInt aNewMult,TUint aNewSize)
       
   349 //
       
   350 // Resize the seek index to accomodate a larger or smaller filesize
       
   351 // Assumes KSeekIndexSize is a power of 2.
       
   352 //
       
   353     {
       
   354 
       
   355     TInt maxNewIndex=aNewSize>>(ClusterSizeLog2()+aNewMult);
       
   356 
       
   357 
       
   358     TInt    index=0;
       
   359     TInt    indexEnd=KSeekIndexSize;
       
   360     TInt    newValEnd=maxNewIndex;
       
   361 
       
   362     if (iSeekIndexSize<aNewMult)
       
   363         {
       
   364         TInt newVal=index;
       
   365         TInt step=1<<(aNewMult-iSeekIndexSize);
       
   366         index+=step-1;
       
   367         while(index<indexEnd && newVal<newValEnd)
       
   368             {
       
   369             iSeekIndex[newVal] =  iSeekIndex[index];
       
   370             newVal++;
       
   371             index+=step;
       
   372             }
       
   373         while(newVal<indexEnd)
       
   374             iSeekIndex[newVal++] =  0;
       
   375         }
       
   376     else
       
   377         {
       
   378         TInt diffSize = iSeekIndexSize-aNewMult;
       
   379         TInt oldVal=(KSeekIndexSize>>diffSize) - 1;
       
   380         TInt newVal=indexEnd-1;
       
   381         TInt skip=(1<<diffSize)-1;
       
   382 
       
   383         if ((iSeekIndexSize - aNewMult) > KSeekIndexSizeLog2)
       
   384             {
       
   385             ClearIndex(0); //-- Invalidate every entry.
       
   386             }
       
   387         else
       
   388             {
       
   389             while(newVal>=index)
       
   390                 {
       
   391 
       
   392                 iSeekIndex[newVal--] =  iSeekIndex[oldVal--];
       
   393 
       
   394 
       
   395                 for(TInt i=skip;i>0;i--)
       
   396                     {   
       
   397                     iSeekIndex[newVal--] = 0;
       
   398 
       
   399                     }
       
   400                 }
       
   401             }
       
   402         }
       
   403     iSeekIndexSize=aNewMult;
       
   404     }
       
   405 
       
   406 
       
   407 /**
       
   408     Zero freed clusters in the index
       
   409 
       
   410     @param  aNewSize new size of the file that the index corresponds to.
       
   411             if = 0  all existing index will be zero filled
       
   412 */ 
       
   413 void CFatFileCB::ClearIndex(TUint aNewSize)
       
   414     {
       
   415 
       
   416     if (!iSeekIndex)
       
   417         return;
       
   418 
       
   419     if(aNewSize==0)
       
   420         {
       
   421         //-- zero fill all the array
       
   422         Mem::FillZ(iSeekIndex, KSeekIndexSize*sizeof(TUint32));
       
   423         return;
       
   424         }
       
   425 
       
   426     // Files that fill up a cluster exactly do not have a trailing empty
       
   427     // cluster. So the entry for that position must also be invalidated
       
   428     aNewSize--;
       
   429     TInt firstInvalidIndex=aNewSize>>(iSeekIndexSize+ClusterSizeLog2());
       
   430         
       
   431     TInt indexLen=KSeekIndexSize-firstInvalidIndex;
       
   432 
       
   433     Mem::FillZ(iSeekIndex+firstInvalidIndex, indexLen * sizeof(TUint32));
       
   434     }
       
   435 
       
   436 TInt CFatFileCB::CalcSeekIndexSize(TUint aSize)
       
   437 //
       
   438 // Find the nearest power of 2 > aSize
       
   439 //
       
   440     {
       
   441     TInt count = 0;
       
   442     const TUint indexSize=KSeekIndexSize<<ClusterSizeLog2();//KSeekIndexSize=128
       
   443     if (aSize<=indexSize)
       
   444       return(count);
       
   445     
       
   446     while((aSize>>=1)>0)
       
   447         {
       
   448         count++;
       
   449         }
       
   450     return (count - (KSeekIndexSizeLog2 + ClusterSizeLog2()) + 1);
       
   451     }
       
   452 
       
   453 //-----------------------------------------------------------------------------
       
   454 
       
   455 void CFatFileCB::SetSizeL(TInt64 aSize)
       
   456     {
       
   457     __PRINT(_L("CFatFileCB::SetSizeL"));
       
   458     
       
   459     // FAT supports 32 bits only for file size
       
   460     if (I64HIGH(aSize))
       
   461         User::Leave(KErrNotSupported);
       
   462 
       
   463     if(FatMount().IsRuggedFSys())
       
   464         DoSetSizeL(I64LOW(aSize),ETrue);
       
   465     else
       
   466         DoSetSizeL(I64LOW(aSize),EFalse);
       
   467     }
       
   468 
       
   469 
       
   470 void CFatFileCB::SetSizeL(TInt aSize)
       
   471 //
       
   472 // Envelope function around DoSetSizeL to enable aSize to
       
   473 // be written to disk for rugged fat file system
       
   474 //
       
   475     {
       
   476     SetSizeL(TInt64(aSize));
       
   477     }
       
   478 
       
   479 void CFatFileCB::DoSetSizeL(TUint aSize,TBool aIsSizeWrite)
       
   480 //
       
   481 // Extend or truncate the file.
       
   482 // Expects the modified attribute and iSize are set afterwards.
       
   483 // Does not alter iCurrentPos, the current file position.
       
   484 // Writes size of file to disk if aIsSizeWrite set
       
   485 //
       
   486     {
       
   487     __PRINT2(_L("CFatFileCB::DoSetSizeL sz:%d, fileWrite=%d"),aSize ,aIsSizeWrite);
       
   488 
       
   489     FatMount().CheckStateConsistentL();
       
   490     FatMount().CheckWritableL();
       
   491 
       
   492     
       
   493     // Can not change the file size if it is clamped
       
   494     if(Mount().IsFileClamped(MAKE_TINT64(0,iStartCluster)) > 0)
       
   495         User::Leave(KErrInUse);
       
   496     
       
   497     iFileSizeModified=ETrue;
       
   498 
       
   499     TInt newIndexMult=CalcSeekIndexSize(aSize);
       
   500     if (iSeekIndex!=NULL && newIndexMult!=iSeekIndexSize)
       
   501         ResizeIndex(newIndexMult,aSize);
       
   502     if (aSize == 0)
       
   503         {
       
   504         if (Size() != 0)
       
   505             {
       
   506             ClearIndex(0); //-- clear seek index array
       
   507             TInt cluster=iStartCluster;
       
   508             iStartCluster = 0;
       
   509             SetSize(0);
       
   510             FlushAllL();
       
   511             CheckPosL(0);
       
   512             FAT().FreeClusterListL(cluster);
       
   513             FAT().FlushL();
       
   514             }
       
   515         return;
       
   516         }
       
   517     if (aSize<(TUint)Size())
       
   518         {
       
   519         if(aIsSizeWrite)        // write file size if decreasing
       
   520                 WriteFileSizeL(aSize);
       
   521         CheckPosL(aSize);
       
   522         TInt cluster=iCurrentPos.iCluster;
       
   523         if (FAT().GetNextClusterL(cluster))
       
   524             {
       
   525             FAT().WriteFatEntryEofL(iCurrentPos.iCluster);
       
   526             FAT().FreeClusterListL(cluster);
       
   527             }
       
   528         ClearIndex(aSize);
       
   529         FAT().FlushL();
       
   530         return;
       
   531         }
       
   532     
       
   533     TUint newSize=aSize>>ClusterSizeLog2(); //  Number of clusters we now need
       
   534     if (aSize > (newSize<<ClusterSizeLog2()))
       
   535         newSize++;  //  File size is not an exact multiple of cluster size
       
   536                     //  Increment the number of clusters required to accomodate tail
       
   537     
       
   538     if (iStartCluster==0)
       
   539         {
       
   540         //-- FAT().FreeClusterHint() will give us a hint of the last free cluster
       
   541         ClearIndex(0); //-- clear seek index array
       
   542         TInt tempStartCluster=FAT().AllocateClusterListL(newSize, FAT().FreeClusterHint());
       
   543         FAT().FlushL();
       
   544         iCurrentPos.iCluster=tempStartCluster;
       
   545         iStartCluster=tempStartCluster;
       
   546         SetSize(aSize);
       
   547         FlushAllL();
       
   548         }
       
   549     else
       
   550         {
       
   551         const TUint curSize = (TUint)Size(); 
       
   552         TUint oldSize=curSize>>ClusterSizeLog2();   //  Number of clusters we had previously
       
   553         if (curSize>(oldSize<<ClusterSizeLog2()))
       
   554             oldSize++;
       
   555     
       
   556         TInt newClusters=newSize-oldSize;   //  Number of clusters we need to prepare
       
   557         if (newClusters)
       
   558             {
       
   559             TEntryPos currentPos=iCurrentPos;
       
   560             CheckPosL(Size());
       
   561             FAT().ExtendClusterListL(newClusters,iCurrentPos.iCluster);
       
   562             iCurrentPos=currentPos;
       
   563             }
       
   564         FAT().FlushL();
       
   565         if(aIsSizeWrite)            // write file size if increasing
       
   566             WriteFileSizeL(aSize);
       
   567         }
       
   568     }
       
   569 
       
   570 //-----------------------------------------------------------------------------
       
   571 /**
       
   572     Set the entry's attributes and modified time.
       
   573 */
       
   574 void CFatFileCB::SetEntryL(const TTime& aTime,TUint aSetAttMask,TUint aClearAttMask)
       
   575     {
       
   576     __PRINT(_L("CFatFileCB::SetEntryL"));
       
   577     
       
   578     FatMount().CheckStateConsistentL();
       
   579     FatMount().CheckWritableL();
       
   580 
       
   581     TUint setAttMask=aSetAttMask&KEntryAttMaskSupported;
       
   582     if (setAttMask|aClearAttMask)
       
   583         {
       
   584         iAtt|=setAttMask;
       
   585         iAtt&=(~aClearAttMask);
       
   586         }
       
   587     if (aSetAttMask&KEntryAttModified)
       
   588         iModified=aTime;
       
   589     iAtt|=KEntryAttModified;
       
   590     }
       
   591 
       
   592 /**
       
   593     This is a RuggedFAT - specific method. Writes file size to the corresponding field of this
       
   594     file direcrory entry.
       
   595 */
       
   596 void CFatFileCB::WriteFileSizeL(TUint aSize)
       
   597     {
       
   598     __PRINT(_L("CFatFileCB::WriteFileSizeL"));
       
   599     TEntryPos entryPos=iFileDirPos;
       
   600     entryPos.iPos+=_FOFF(SFatDirEntry,iSize);
       
   601     TPtrC8 size((TUint8*)&aSize,sizeof(TUint));
       
   602     
       
   603     //-- use directory cache when dealing with directories
       
   604     FatMount().DirWriteL(entryPos,size);
       
   605     iFileSizeModified=EFalse;
       
   606     }
       
   607 
       
   608 //-----------------------------------------------------------------------------
       
   609 /** 
       
   610     Flush file size, attributes, time etc. to the media.
       
   611     It doesn't matter if whole directory entry is being written of only part of it. Anyway, a single DOS
       
   612     dir. entry always fits into 1 sector.
       
   613 */
       
   614 void CFatFileCB::FlushDataL()
       
   615     {
       
   616     __PRINT(_L("CFatFileCB::FlushDataL"));
       
   617     FlushAllL();
       
   618     }
       
   619 
       
   620 //-----------------------------------------------------------------------------
       
   621 /** 
       
   622     Flush the fide directory entry data: files size, attributes, time etc. 
       
   623 */
       
   624 void CFatFileCB::FlushAllL()
       
   625     {
       
   626     __PRINT(_L("CFatFileCB::FlushAllL()"));
       
   627 
       
   628     if (Mount().IsCurrentMount()==EFalse)
       
   629         User::Leave(KErrDisMounted);
       
   630 
       
   631     FatMount().CheckStateConsistentL();
       
   632     FatMount().CheckWritableL();
       
   633 
       
   634     TFatDirEntry entry;
       
   635     FatMount().ReadDirEntryL(iFileDirPos,entry);
       
   636     __ASSERT_ALWAYS(entry.IsEndOfDirectory()==EFalse,User::Leave(KErrCorrupt));
       
   637     entry.SetAttributes(iAtt&KEntryAttMaskSupported);
       
   638     entry.SetSize(Size());
       
   639     entry.SetTime(iModified, FatMount().TimeOffset());
       
   640     entry.SetStartCluster(iStartCluster);
       
   641 
       
   642     TBool setNotify = FatMount().GetNotifyUser();
       
   643     if(setNotify)
       
   644         {
       
   645         FatMount().SetNotifyOff();  // do not launch a notifier
       
   646         }
       
   647 
       
   648     TRAPD(ret, FatMount().WriteDirEntryL(iFileDirPos,entry));
       
   649     
       
   650     if(setNotify)
       
   651         {
       
   652         FatMount().SetNotifyOn();
       
   653         }
       
   654 
       
   655     User::LeaveIfError(ret);
       
   656     iAtt&=(~KEntryAttModified);
       
   657     iFileSizeModified=EFalse;
       
   658     }
       
   659 
       
   660 //-----------------------------------------------------------------------------
       
   661 
       
   662 /**
       
   663     Rename already opened file.
       
   664     @param  aNewName new file name; all trailing dots from the name will be removed
       
   665 */
       
   666 void CFatFileCB::RenameL(const TDesC& aNewName)
       
   667     {
       
   668     __PRINT2(_L("CFatFileCB::RenameL[0x%x], name:%S"),this, &aNewName);
       
   669 
       
   670     FatMount().CheckStateConsistentL();
       
   671     FatMount().CheckWritableL();
       
   672 
       
   673     const TPtrC fileName = RemoveTrailingDots(aNewName); //-- remove trailing dots from the name
       
   674 
       
   675 
       
   676     FatMount().DoRenameOrReplaceL(*iFileName, fileName, CFatMountCB::EModeRename,iFileDirPos);
       
   677     
       
   678     AllocBufferL(iFileName, fileName);
       
   679     
       
   680     if(!FatMount().IsRuggedFSys())
       
   681         FAT().FlushL();
       
   682     }
       
   683 
       
   684 
       
   685 //***********************************************************
       
   686 //* BlockMap interface
       
   687 //***********************************************************
       
   688     
       
   689 TInt CFatFileCB::BlockMap(SBlockMapInfo& aInfo, TInt64& aStartPos, TInt64 aEndPos)
       
   690 //
       
   691 // Retrieves the block map of a given section of the file, in the FAT file system.
       
   692 //  
       
   693     {
       
   694     __PRINT2(_L("CFatFileCB::BlockMap aStartPos=%ld aEndPos=%ld"), aStartPos, aEndPos);
       
   695     
       
   696     if ( I64HIGH(aStartPos) || I64HIGH(aEndPos) )
       
   697         return KErrNotSupported;
       
   698 
       
   699     TUint startPos = I64LOW(aStartPos);
       
   700     TUint endPos = I64LOW(aEndPos);
       
   701 
       
   702     // aEndPos will always be >=0 at this point
       
   703     const TUint length = endPos - startPos;
       
   704     
       
   705     // Store the position of cluster zero in aInfo
       
   706     CFatMountCB& fatMount = FatMount();
       
   707 
       
   708     TInt drvNo=-1;
       
   709     TBusLocalDrive* locDrv;
       
   710     if((fatMount.LocalDrive()->GetLocalDrive(locDrv)==KErrNone) && ((drvNo=GetLocalDriveNumber(locDrv))>=0) && (drvNo<KMaxLocalDrives))
       
   711         aInfo.iLocalDriveNumber=drvNo;
       
   712     else
       
   713         return KErrNotSupported;
       
   714 
       
   715     // Fetch the address of cluster 0
       
   716     aInfo.iStartBlockAddress = fatMount.FAT().DataPositionInBytes(KFirstClusterNum);
       
   717 
       
   718     TRAPD(r, CheckPosL(startPos));
       
   719     if (r != KErrNone)
       
   720         return r;
       
   721 
       
   722     aInfo.iBlockStartOffset = fatMount.ClusterRelativePos(iCurrentPos.iPos);
       
   723     aInfo.iBlockGranularity = 1 << FatMount().ClusterSizeLog2();
       
   724     const TUint myStartPos = iCurrentPos.iPos;
       
   725     if ( myStartPos + length > (TUint)Size())
       
   726         return KErrArgument;
       
   727 
       
   728     TRAP(r, FatMount().BlockMapReadFromClusterListL(iCurrentPos, length, aInfo));
       
   729     if (r != KErrNone)
       
   730         return r;
       
   731 
       
   732     aStartPos = iCurrentPos.iPos;
       
   733     if ((I64LOW(aStartPos) == (TUint)Size()) || ( I64LOW(aStartPos) == (myStartPos + length)))
       
   734         return KErrCompletion;
       
   735     else
       
   736         return KErrNone;
       
   737     }
       
   738 
       
   739 
       
   740 
       
   741 TInt CFatFileCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput)
       
   742     {
       
   743     switch(aInterfaceId)
       
   744         {
       
   745         case EExtendedFileInterface:
       
   746             ((CFileCB::MExtendedFileInterface*&) aInterface) = this;
       
   747             return KErrNone;
       
   748 
       
   749         case EBlockMapInterface:
       
   750             aInterface = (CFileCB::MBlockMapInterface*) this;
       
   751             return KErrNone;
       
   752 
       
   753         case EGetLocalDrive:
       
   754             return FatMount().LocalDrive()->GetLocalDrive((TBusLocalDrive*&) aInterface);
       
   755 
       
   756         default:
       
   757             return CFileCB::GetInterface(aInterfaceId,aInterface,aInput);
       
   758         }
       
   759     }
       
   760 
       
   761 
       
   762 
       
   763 
       
   764 /**
       
   765     Overwrites file's start cluster (iStartCluster) in its directory entry.
       
   766 */
       
   767 void CFatFileCB::FlushStartClusterL()
       
   768     {
       
   769     __PRINT(_L("CFatFileCB::FlushStartClusterL"));
       
   770 
       
   771     CFatMountCB& mount = FatMount();
       
   772     TFatDirEntry dirEntry;
       
   773     
       
   774     mount.ReadDirEntryL(iFileDirPos, dirEntry);      //-- read this file's dir. entry
       
   775     dirEntry.SetStartCluster(iStartCluster);         //-- set new start cluster
       
   776     mount.WriteDirEntryL(iFileDirPos, dirEntry);//-- write the entry back
       
   777     }
       
   778 
       
   779 
       
   780 
       
   781 
       
   782