userlibandfileserver/fileserver/sfat32/ram_fat_table32.cpp
changeset 0 a41df078684a
child 36 538db54a451d
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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\sfat32\ram_fat_table32.cpp
       
    15 // FAT16/32 File Allocation Table classes implementation for the RAM media
       
    16 // 
       
    17 //
       
    18 
       
    19 /**
       
    20  @file
       
    21  @internalTechnology
       
    22 */
       
    23 
       
    24 
       
    25 
       
    26 #include "sl_std.h"
       
    27 #include "sl_fatcache32.h"
       
    28 #include "fat_table32.h"
       
    29 
       
    30 
       
    31 //---------------------------------------------------------------------------------------------------------------------------------------
       
    32 
       
    33 //#######################################################################################################################################
       
    34 //#     CRamFatTable class implementation 
       
    35 //#######################################################################################################################################
       
    36 
       
    37 /**
       
    38     Constructor, the RamFatTable allows disk compression by redirecting the FAT
       
    39 
       
    40     @param aOwner Owning mount.
       
    41 */
       
    42 CRamFatTable::CRamFatTable(CFatMountCB& aOwner)
       
    43              :CFatTable(aOwner)
       
    44 {
       
    45     iFatTablePos=aOwner.FirstFatSector()<<aOwner.SectorSizeLog2();
       
    46     iIndirectionTablePos=iFatTablePos+aOwner.FatSizeInBytes();
       
    47 }
       
    48 
       
    49 /** factory method */
       
    50 CRamFatTable* CRamFatTable::NewL(CFatMountCB& aOwner)
       
    51 {
       
    52     __PRINT1(_L("CRamFatTable::NewL() drv:%d"),aOwner.DriveNumber());
       
    53 
       
    54     CRamFatTable* pSelf = new (ELeave) CRamFatTable(aOwner);
       
    55 
       
    56     CleanupStack::PushL(pSelf);
       
    57     pSelf->InitializeL();
       
    58     CleanupStack::Pop();
       
    59 
       
    60     return pSelf;
       
    61 }
       
    62 
       
    63 
       
    64 void CRamFatTable::InitializeL()
       
    65 {
       
    66     CFatTable::InitializeL();
       
    67 
       
    68     ASSERT(iMediaAtt & KMediaAttVariableSize);
       
    69     ASSERT(FatType() == EFat16 || FatType()== EFat32);
       
    70 
       
    71     iFatTablePos=iOwner->FirstFatSector()<<iOwner->SectorSizeLog2();
       
    72     iIndirectionTablePos=iFatTablePos+iOwner->FatSizeInBytes();
       
    73 
       
    74     //-- set RAM disk base
       
    75     TLocalDriveCapsV2 caps;
       
    76     TPckg<TLocalDriveCapsV2> capsPckg(caps);
       
    77     User::LeaveIfError(iOwner->LocalDrive()->Caps(capsPckg));
       
    78   
       
    79     iRamDiskBase = caps.iBaseAddress; 
       
    80 }
       
    81 
       
    82 /**
       
    83     Just Count free clusters in the FAT
       
    84 */
       
    85 void CRamFatTable::MountL(const TMountParams& /*aMountParam*/)
       
    86 {
       
    87     CountFreeClustersL();
       
    88 }
       
    89 
       
    90 
       
    91 /**
       
    92     Return the start address of the Ram Drive
       
    93     @return start address of the Ram Drive 
       
    94 */
       
    95 TUint8 *CRamFatTable::RamDiskBase() const
       
    96     {
       
    97     return(iRamDiskBase);
       
    98     }
       
    99 
       
   100 
       
   101 /**
       
   102     Allocate a new cluster number
       
   103 
       
   104     @return New cluster number
       
   105 */
       
   106 TInt CRamFatTable::AllocateClusterNumber()
       
   107     {
       
   108     return(iOwner->MaxClusterNumber()-NumberOfFreeClusters());
       
   109     }
       
   110 
       
   111 /**
       
   112     Write a value to the FAT (indirection table) 
       
   113 
       
   114     @param aFatIndex Cluster to write to
       
   115     @param aValue value to write to Fat
       
   116 */
       
   117 void CRamFatTable::WriteL(TUint32 aFatIndex, TUint32 aValue)
       
   118     {
       
   119     //__PRINT(_L("CRamFatTable::WriteL"));
       
   120 
       
   121 //  __ASSERT_ALWAYS(aFatIndex>=2 && (aValue>=2 || aValue==0) && aValue<=0xFFFF,User::Leave(KErrCorrupt));
       
   122     TUint32 indirectCluster=aFatIndex;
       
   123     TUint32 indirectClusterNewVal=0;
       
   124     ReadIndirectionTable(indirectCluster);
       
   125 //  If value in indirection table!=0 we assume we have already written to the indirection table
       
   126 //  So just update the FAT table
       
   127     if (indirectCluster!=0 && aValue!=0)
       
   128         {
       
   129         WriteFatTable(aFatIndex,aValue);
       
   130         return;
       
   131         }
       
   132 //  If value in indirection table is 0, we haven't written to it yet, though the memory has
       
   133 //  already been allocated by the EnlargeL() function
       
   134     if (indirectCluster==0 && aValue!=0) // Assumes memory has already been allocated
       
   135         indirectClusterNewVal=AllocateClusterNumber();
       
   136 //  Write aValue into aFaxIndex and indirectClusterNewVal into the corresponding position
       
   137 //  in the indirection table    
       
   138     WriteFatTable(aFatIndex,aValue,indirectClusterNewVal);
       
   139     }   
       
   140 
       
   141 /**
       
   142     Read the value of a cluster in the Fat
       
   143 
       
   144     @param aFatIndex A cluster to read
       
   145     @return The cluster value read
       
   146 */
       
   147 TUint32 CRamFatTable::ReadL(TUint32 aFatIndex) const
       
   148     {
       
   149     __ASSERT_ALWAYS(aFatIndex>=KFatFirstSearchCluster,User::Leave(KErrCorrupt));
       
   150 
       
   151     TUint32 clusterVal;
       
   152 
       
   153     switch(FatType())
       
   154         {
       
   155         case EFat16:
       
   156             clusterVal=*(TUint16*)(RamDiskBase()+PosInBytes(aFatIndex)+iFatTablePos);
       
   157         break;
       
   158 
       
   159         case EFat32:
       
   160             clusterVal=*(TUint32*)(RamDiskBase()+PosInBytes(aFatIndex)+iFatTablePos);
       
   161         break;
       
   162     
       
   163         default:
       
   164             ASSERT(0);
       
   165         return 0;
       
   166         }
       
   167     
       
   168     return clusterVal;
       
   169     }
       
   170 
       
   171 /**
       
   172     Write a value to the FAT and indirection table
       
   173 
       
   174     @param aFatIndex Cluster number to write to
       
   175     @param aFatValue Cluster value for Fat
       
   176     @param anIndirectionValue Value for indirection table
       
   177 */
       
   178 void CRamFatTable::WriteFatTable(TInt aFatIndex,TInt aFatValue,TInt anIndirectionValue)
       
   179     {
       
   180     const TUint8* pos=RamDiskBase()+PosInBytes(aFatIndex);
       
   181 
       
   182     switch(FatType())
       
   183         {
       
   184         case EFat16:
       
   185             *(TUint16*)(pos+iFatTablePos)=(TUint16)aFatValue;
       
   186             *(TUint16*)(pos+iIndirectionTablePos)=(TUint16)anIndirectionValue;
       
   187         break;
       
   188 
       
   189         case EFat32:
       
   190             *(TUint32*)(pos+iFatTablePos)=(TUint32)aFatValue;
       
   191             *(TUint32*)(pos+iIndirectionTablePos)=(TUint32)anIndirectionValue;
       
   192         break;
       
   193     
       
   194         default:
       
   195             ASSERT(0);
       
   196         return;
       
   197         }
       
   198     
       
   199     }
       
   200 
       
   201 /**
       
   202     Write to just the fat table
       
   203 
       
   204     @param aFatIndex Cluster number to write to
       
   205     @param aFatValue Cluster value for Fat
       
   206 */
       
   207 void CRamFatTable::WriteFatTable(TInt aFatIndex,TInt aFatValue)
       
   208     {
       
   209 
       
   210     switch(FatType())
       
   211         {
       
   212         case EFat16:
       
   213             *(TUint16*)(RamDiskBase()+PosInBytes(aFatIndex)+iFatTablePos)=(TUint16)aFatValue;
       
   214         break;
       
   215 
       
   216         case EFat32:
       
   217             *(TUint32*)(RamDiskBase()+PosInBytes(aFatIndex)+iFatTablePos)=(TUint32)aFatValue;
       
   218         break;
       
   219     
       
   220         default:
       
   221             ASSERT(0);
       
   222         return;
       
   223         }
       
   224 
       
   225     }
       
   226 
       
   227 /**
       
   228     Write to just the fat table
       
   229 
       
   230     @param aFatIndex Cluster number to write to
       
   231     @param aFatValue Value for indirection table
       
   232 */
       
   233 void CRamFatTable::WriteIndirectionTable(TInt aFatIndex,TInt aFatValue)
       
   234     {
       
   235     switch(FatType())
       
   236         {
       
   237         case EFat16:
       
   238             *(TUint16*)(RamDiskBase()+PosInBytes(aFatIndex)+iIndirectionTablePos)=(TUint16)aFatValue;
       
   239         break;
       
   240 
       
   241         case EFat32:
       
   242             *(TUint32*)(RamDiskBase()+PosInBytes(aFatIndex)+iIndirectionTablePos)=(TUint32)aFatValue;
       
   243         break;
       
   244     
       
   245         default:
       
   246             ASSERT(0);
       
   247         return;
       
   248         }
       
   249     }
       
   250 
       
   251 /**
       
   252     Find the real location of aCluster
       
   253     @param aCluster Cluster to read, contians cluster value upon return
       
   254 */
       
   255 void CRamFatTable::ReadIndirectionTable(TUint32& aCluster) const
       
   256     {
       
   257     switch(FatType())
       
   258         {
       
   259         case EFat16:
       
   260             aCluster=*(TUint16*)(RamDiskBase()+PosInBytes(aCluster)+iIndirectionTablePos);    
       
   261         break;
       
   262 
       
   263         case EFat32:
       
   264             aCluster=*(TUint32*)(RamDiskBase()+PosInBytes(aCluster)+iIndirectionTablePos);
       
   265         break;
       
   266     
       
   267         default:
       
   268             ASSERT(0);
       
   269         return;
       
   270         }
       
   271     
       
   272     }
       
   273 
       
   274 /**
       
   275     Copy memory in RAM drive area, unlocking required
       
   276 
       
   277     @param aTrg Pointer to destination location
       
   278     @param aSrc Pointer to source location
       
   279     @param aLength Length of data to copy
       
   280     @return Pointer to end of data copied
       
   281 */
       
   282 TUint8* CRamFatTable::MemCopy(TAny* aTrg,const TAny* aSrc,TInt aLength)
       
   283     {
       
   284     TUint8* p=Mem::Copy(aTrg,aSrc,aLength);
       
   285     return(p);
       
   286     }
       
   287 
       
   288 /**
       
   289     Copy memory with filling the source buffer with zeroes. Target and source buffers can overlap.
       
   290     Used on RAMDrive srinking in order to wipe data from the file that is being deleted.
       
   291     
       
   292     @param   aTrg       pointer to the target address
       
   293     @param   aSrc       pointer to the destination address
       
   294     @param   aLength    how many bytes to copy
       
   295     @return  A pointer to a location aLength bytes beyond aTrg (i.e. the location aTrg+aLength).
       
   296 */
       
   297 TUint8* CRamFatTable::MemCopyFillZ(TAny* aTrg, TAny* aSrc,TInt aLength)
       
   298 {
       
   299     //-- just copy src to the trg, the memory areas can overlap.
       
   300     TUint8* p=Mem::Copy(aTrg, aSrc, aLength);
       
   301     
       
   302     //-- now zero-fill the source memory area taking into account possible overlap.
       
   303     TUint8* pSrc = static_cast<TUint8*>(aSrc);
       
   304     TUint8* pTrg = static_cast<TUint8*>(aTrg);
       
   305     
       
   306     TUint8* pZFill = NULL; //-- pointer to the beginning of zerofilled area
       
   307     TInt    zFillLen = 0;  //-- a number of bytes to zero-fill
       
   308     
       
   309     if(aTrg < aSrc)
       
   310     {
       
   311         if(pTrg+aLength < pSrc)
       
   312         {//-- target and source areas do not overlap
       
   313          pZFill = pSrc;
       
   314          zFillLen = aLength;
       
   315         }
       
   316         else
       
   317         {//-- target and source areas overlap, try not to corrupt the target area
       
   318          zFillLen = pSrc-pTrg;
       
   319          pZFill = pTrg+aLength;
       
   320         }
       
   321     }
       
   322     else
       
   323     {
       
   324         if(pSrc+aLength < pTrg)
       
   325         {//-- target and source areas do not overlap
       
   326          pZFill = pSrc;
       
   327          zFillLen = aLength;
       
   328         }
       
   329         else
       
   330         {//-- target and source areas overlap, try not to corrupt the target area
       
   331          zFillLen = pSrc+aLength-pTrg;
       
   332          pZFill = pSrc;
       
   333         }
       
   334     }
       
   335 
       
   336     Mem::FillZ(pZFill, zFillLen);
       
   337 
       
   338     return(p);
       
   339 }
       
   340 
       
   341 
       
   342 /**
       
   343     Zero fill RAM area corresponding to the cluster number aCluster
       
   344     @param  aCluster a cluster number to be zero-filled
       
   345 */
       
   346 void CRamFatTable::ZeroFillCluster(TInt aCluster)
       
   347     {
       
   348     TLinAddr clusterPos= I64LOW(DataPositionInBytes(aCluster));
       
   349     Mem::FillZ(iRamDiskBase+clusterPos, 1<< iOwner->ClusterSizeLog2());     
       
   350     }
       
   351 
       
   352 
       
   353 /**
       
   354 Return the location of a Cluster in the data section of the media
       
   355 
       
   356 @param aCluster to find location of
       
   357 @return Byte offset of the cluster data 
       
   358 */
       
   359 TInt64 CRamFatTable::DataPositionInBytes(TUint32 aCluster) const
       
   360     {
       
   361     //__PRINT(_L("CRamFatTable::DataPositionInBytes"));
       
   362     ReadIndirectionTable(aCluster);
       
   363     return(aCluster<<iOwner->ClusterSizeLog2());
       
   364     }
       
   365 
       
   366 /**
       
   367 Allocate and mark as EOF a single cluster as close as possible to aNearestCluster,
       
   368 calls base class implementation but must Enlarge the RAM drive first. Allocated cluster RAM area will be zero-filled.
       
   369 
       
   370 @param aNearestCluster Cluster the new cluster should be nearest to
       
   371 @leave System wide error codes
       
   372 @return The cluster number allocated
       
   373 */
       
   374 TUint32 CRamFatTable::AllocateSingleClusterL(TUint32 aNearestCluster)
       
   375     {
       
   376     __PRINT(_L("CRamFatTable::AllocateSingleClusterL"));
       
   377     iOwner->EnlargeL(1<<iOwner->ClusterSizeLog2()); //  First enlarge the RAM drive
       
   378     TInt fileAllocated=CFatTable::AllocateSingleClusterL(aNearestCluster); //   Now update the free cluster and fat/fit
       
   379     ZeroFillCluster(fileAllocated);  //-- zero-fill allocated cluster 
       
   380     return(fileAllocated);
       
   381     }   
       
   382 
       
   383 
       
   384 /**
       
   385     Extend a file or directory cluster chain, enlarging RAM drive first. Allocated clusters are zero-filled.
       
   386     Leaves if there are no free clusters (the disk is full).
       
   387     Note that method now doesn't call CFatTable::ExtendClusterListL() from its base class, be careful making changes there.
       
   388 
       
   389     @param aNumber      number of clusters to allocate
       
   390     @param aCluster     starting cluster number / ending cluster number after
       
   391     @leave KErrDiskFull + system wide error codes
       
   392 */
       
   393 void CRamFatTable::ExtendClusterListL(TUint32 aNumber, TInt& aCluster)
       
   394     {
       
   395     __PRINT(_L("CRamFatTable::ExtendClusterListL"));
       
   396     __ASSERT_DEBUG(aNumber>0,Fault(EFatBadParameter));
       
   397 
       
   398     iOwner->EnlargeL(aNumber<<iOwner->ClusterSizeLog2());
       
   399 
       
   400     while(aNumber && GetNextClusterL(aCluster))
       
   401         aNumber--;
       
   402 
       
   403     if(!aNumber)
       
   404         return;
       
   405 
       
   406     if (NumberOfFreeClusters() < aNumber)
       
   407         {
       
   408         __PRINT(_L("CRamFatTable::ExtendClusterListL - leaving KErrDirFull"));
       
   409         User::Leave(KErrDiskFull);
       
   410         }
       
   411 
       
   412     while(aNumber--)
       
   413         {
       
   414         const TInt freeCluster=FindClosestFreeClusterL(aCluster);
       
   415 
       
   416         WriteFatEntryEofL(freeCluster); //  Must write EOF for FindClosestFreeCluster to work again
       
   417         DecrementFreeClusterCount(1);
       
   418         WriteL(aCluster,freeCluster);
       
   419         aCluster=freeCluster;
       
   420         ZeroFillCluster(freeCluster); //-- zero fill just allocated cluster (RAM area)
       
   421         }
       
   422 
       
   423     SetFreeClusterHint(aCluster); 
       
   424   
       
   425     }
       
   426 
       
   427 /**
       
   428 Mark a chain of clusters as free in the FAT. Shrinks the RAM drive once the
       
   429 clusters are free 
       
   430 
       
   431 @param aCluster Start cluster of cluster chain to free
       
   432 @leave System wide error codes
       
   433 */
       
   434 void CRamFatTable::FreeClusterListL(TUint32 aCluster)
       
   435     {
       
   436     __PRINT1(_L("CRamFatTable::FreeClusterListL aCluster=%d"),aCluster);
       
   437     if (aCluster==0)
       
   438         return; // File has no cluster allocated
       
   439 
       
   440     const TInt clusterShift=iOwner->ClusterSizeLog2();
       
   441     TInt startCluster=aCluster;
       
   442     TInt endCluster=0;
       
   443     TInt totalFreed=0;
       
   444     TLinAddr srcEnd=0;
       
   445 
       
   446     if(IsFat32())
       
   447         {
       
   448         while(endCluster!=EOF_32Bit)
       
   449             {
       
   450             TInt num=CountContiguousClustersL(startCluster,endCluster,KMaxTInt);
       
   451             if (GetNextClusterL(endCluster)==EFalse || endCluster==0)
       
   452                 endCluster=EOF_32Bit;   // endCluster==0 -> file contained FAT loop
       
   453 
       
   454         //  Real position in bytes of the start cluster in the data area
       
   455             TLinAddr startClusterPos=I64LOW(DataPositionInBytes(startCluster));
       
   456         //  Sliding value when more than one block is freed
       
   457             TLinAddr trg=startClusterPos-(totalFreed<<clusterShift);
       
   458             __PRINT1(_L("trg=0x%x"),trg);
       
   459 
       
   460         //  Beginning of data area to move
       
   461             TLinAddr srcStart=startClusterPos+(num<<clusterShift);
       
   462             __PRINT1(_L("srcStart=0x%x"),srcStart);
       
   463         //  Position of next part of cluster chain or position of end of ram drive
       
   464             if (endCluster==EOF_32Bit)  //  Last cluster is the end of the chain
       
   465                 {
       
   466             
       
   467         
       
   468             //  Fixed to use the genuine RAM drive size rather than the number
       
   469             //  of free clusters - though they *should* be the same
       
   470             //  It avoids the problem of iFreeClusters getting out of sync with 
       
   471             //  the RAM drive size but doesn't solve the issue of why it can happen...
       
   472                 
       
   473                 srcEnd=I64LOW(iOwner->Size());
       
   474                 __PRINT1(_L("srcEnd=0x%x"),srcEnd);
       
   475                 }
       
   476             else                        //  Just move up to the next part of the chain
       
   477                 srcEnd=I64LOW(DataPositionInBytes(endCluster));
       
   478 
       
   479         //-- Copy (srcEnd-srcStart) bytes from iRamDiskBase+srcStart onto iRamDiskBase+trg
       
   480         //-- zero-filling free space to avoid leaving something important there
       
   481         ASSERT(srcEnd >= srcStart);
       
   482         if(srcEnd-srcStart > 0)
       
   483             { 
       
   484             MemCopyFillZ(iRamDiskBase+trg,iRamDiskBase+srcStart,srcEnd-srcStart);
       
   485             }
       
   486         else
       
   487             {//-- we are freeing the cluster chain at the end of the RAM drive; Nothing to copy to the drive space that has become free,
       
   488              //-- but nevertheless zero fill this space.
       
   489             Mem::FillZ(iRamDiskBase+trg, num<<clusterShift);
       
   490             }
       
   491 
       
   492 
       
   493             totalFreed+=num;
       
   494             startCluster=endCluster;
       
   495             UpdateIndirectionTable(srcStart>>clusterShift,srcEnd>>clusterShift,totalFreed);
       
   496             }
       
   497         }
       
   498     else
       
   499         {
       
   500         while(endCluster!=EOF_16Bit)
       
   501             {
       
   502             TInt num=CountContiguousClustersL(startCluster,endCluster,KMaxTInt);
       
   503             if (GetNextClusterL(endCluster)==EFalse || endCluster==0)
       
   504                 endCluster=EOF_16Bit;   // endCluster==0 -> file contained FAT loop
       
   505 
       
   506         //  Real position in bytes of the start cluster in the data area
       
   507             TLinAddr startClusterPos=I64LOW(DataPositionInBytes(startCluster));
       
   508         //  Sliding value when more than one block is freed
       
   509             TLinAddr trg=startClusterPos-(totalFreed<<clusterShift);
       
   510             __PRINT1(_L("trg=0x%x"),trg);
       
   511 
       
   512         //  Beginning of data area to move
       
   513             TLinAddr srcStart=startClusterPos+(num<<clusterShift);
       
   514             __PRINT1(_L("srcStart=0x%x"),srcStart);
       
   515         //  Position of next part of cluster chain or position of end of ram drive
       
   516             if (endCluster==EOF_16Bit)  //  Last cluster is the end of the chain
       
   517                 {
       
   518             
       
   519         
       
   520             //  Fixed to use the genuine RAM drive size rather than the number
       
   521             //  of free clusters - though they *should* be the same
       
   522             //  It avoids the problem of iFreeClusters getting out of sync with 
       
   523             //  the RAM drive size but doesn't solve the issue of why it can happen...
       
   524                 
       
   525                 srcEnd=I64LOW(iOwner->Size());
       
   526                 __PRINT1(_L("srcEnd=0x%x"),srcEnd);
       
   527                 }
       
   528             else                        //  Just move up to the next part of the chain
       
   529                 srcEnd=I64LOW(DataPositionInBytes(endCluster));
       
   530 
       
   531         //-- Copy (srcEnd-srcStart) bytes from iRamDiskBase+srcStart onto iRamDiskBase+trg
       
   532         //-- zero-filling free space to avoid leaving something important there
       
   533         ASSERT(srcEnd >= srcStart);
       
   534         if(srcEnd-srcStart > 0)
       
   535             { 
       
   536             MemCopyFillZ(iRamDiskBase+trg,iRamDiskBase+srcStart,srcEnd-srcStart);
       
   537             }    
       
   538         else
       
   539             {//-- we are freeing the cluster chain at the end of the RAMdrive; Nothing to copy to the drive space that has become free,
       
   540              //-- but nevertheless zero fill this space.
       
   541             Mem::FillZ(iRamDiskBase+trg, num<<clusterShift);
       
   542             }    
       
   543         
       
   544             totalFreed+=num;
       
   545             startCluster=endCluster;
       
   546             UpdateIndirectionTable(srcStart>>clusterShift,srcEnd>>clusterShift,totalFreed);
       
   547             }
       
   548         }
       
   549     TInt bytesFreed=totalFreed<<clusterShift;
       
   550     
       
   551 //  First free the cluster list
       
   552     CFatTable::FreeClusterListL(aCluster);
       
   553 //  Now reduce the size of the RAM drive
       
   554     iOwner->ReduceSizeL(srcEnd-bytesFreed,bytesFreed);
       
   555     }
       
   556 
       
   557 /**
       
   558 Shift any clusters between aStart and anEnd backwards by aClusterShift
       
   559 
       
   560 @param aStart Start of shift region
       
   561 @param anEnd End of shift region
       
   562 @param aClusterShift amount to shift cluster by
       
   563 */
       
   564 void CRamFatTable::UpdateIndirectionTable(TUint32 aStart,TUint32 anEnd,TInt aClusterShift)
       
   565     {
       
   566     __PRINT(_L("CRamFatTable::UpdateIndirectionTable"));
       
   567 #if defined(__WINS__)
       
   568     TUint32 count=iOwner->MaxClusterNumber();
       
   569     while (count--)
       
   570         {
       
   571         TUint32 cluster=count;
       
   572         ReadIndirectionTable(cluster);
       
   573         if (cluster>=aStart && cluster<anEnd)
       
   574             WriteIndirectionTable(count,cluster-aClusterShift);
       
   575         }
       
   576 #else
       
   577     TUint16* table=(TUint16*)(RamDiskBase()+iIndirectionTablePos);
       
   578     TUint16* entry=table+iOwner->MaxClusterNumber();
       
   579     while (entry>table)
       
   580         {
       
   581         TUint32 cluster=*--entry;
       
   582         if (cluster<aStart)
       
   583             continue;
       
   584         if (cluster<anEnd)
       
   585             *entry=TUint16(cluster-aClusterShift);
       
   586         }
       
   587 #endif
       
   588     }
       
   589 
       
   590 
       
   591